AudioService.java revision 6fa4245589c93025d91aab7dc6681babdd91ee41
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) { 14035ac72a29593ab9a20337a2225df52bdf4754be02Dianne Hackborn final long ident = Binder.clearCallingIdentity(); 14045ac72a29593ab9a20337a2225df52bdf4754be02Dianne Hackborn try { 14055ac72a29593ab9a20337a2225df52bdf4754be02Dianne Hackborn mContext.sendBroadcastAsUser(intent, UserHandle.ALL); 14065ac72a29593ab9a20337a2225df52bdf4754be02Dianne Hackborn } finally { 14075ac72a29593ab9a20337a2225df52bdf4754be02Dianne Hackborn Binder.restoreCallingIdentity(ident); 14085ac72a29593ab9a20337a2225df52bdf4754be02Dianne Hackborn } 14095ac72a29593ab9a20337a2225df52bdf4754be02Dianne Hackborn } 14105ac72a29593ab9a20337a2225df52bdf4754be02Dianne Hackborn 14115ac72a29593ab9a20337a2225df52bdf4754be02Dianne Hackborn private void sendStickyBroadcastToAll(Intent intent) { 14125ac72a29593ab9a20337a2225df52bdf4754be02Dianne Hackborn final long ident = Binder.clearCallingIdentity(); 14135ac72a29593ab9a20337a2225df52bdf4754be02Dianne Hackborn try { 14145ac72a29593ab9a20337a2225df52bdf4754be02Dianne Hackborn mContext.sendStickyBroadcastAsUser(intent, UserHandle.ALL); 14155ac72a29593ab9a20337a2225df52bdf4754be02Dianne Hackborn } finally { 14165ac72a29593ab9a20337a2225df52bdf4754be02Dianne Hackborn Binder.restoreCallingIdentity(ident); 14175ac72a29593ab9a20337a2225df52bdf4754be02Dianne Hackborn } 14185ac72a29593ab9a20337a2225df52bdf4754be02Dianne Hackborn } 14195ac72a29593ab9a20337a2225df52bdf4754be02Dianne Hackborn 142025101b0b9a84571ead15b26e9f4cd9c4298d7823Eric Laurent // UI update and Broadcast Intent 142125101b0b9a84571ead15b26e9f4cd9c4298d7823Eric Laurent private void sendVolumeUpdate(int streamType, int oldIndex, int index, int flags) { 1422212532b58e3b17d7e9d6e1361946d909d4e372c2Eric Laurent if (!isPlatformVoice() && (streamType == AudioSystem.STREAM_RING)) { 142325101b0b9a84571ead15b26e9f4cd9c4298d7823Eric Laurent streamType = AudioSystem.STREAM_NOTIFICATION; 142425101b0b9a84571ead15b26e9f4cd9c4298d7823Eric Laurent } 142525101b0b9a84571ead15b26e9f4cd9c4298d7823Eric Laurent 1426336cdb488ff0e5ec6709c66f55072d3ad22b82edJinsuk Kim if (streamType == AudioSystem.STREAM_MUSIC) { 1427336cdb488ff0e5ec6709c66f55072d3ad22b82edJinsuk Kim flags = updateFlagsForSystemAudio(flags); 14281a6be6ed3962735f12dbd5ce1bca758120c8fb8dJungshik Jang } 14293346a802087f621c6441bc512dfcc17b07143fc6John Spurlock mVolumeController.postVolumeChanged(streamType, flags); 143025101b0b9a84571ead15b26e9f4cd9c4298d7823Eric Laurent 14314bbcc6549738f3d69831b2bd9eb4accec3e9920eEric Laurent if ((flags & AudioManager.FLAG_FIXED_VOLUME) == 0) { 14324bbcc6549738f3d69831b2bd9eb4accec3e9920eEric Laurent oldIndex = (oldIndex + 5) / 10; 14334bbcc6549738f3d69831b2bd9eb4accec3e9920eEric Laurent index = (index + 5) / 10; 14344bbcc6549738f3d69831b2bd9eb4accec3e9920eEric Laurent Intent intent = new Intent(AudioManager.VOLUME_CHANGED_ACTION); 14354bbcc6549738f3d69831b2bd9eb4accec3e9920eEric Laurent intent.putExtra(AudioManager.EXTRA_VOLUME_STREAM_TYPE, streamType); 14364bbcc6549738f3d69831b2bd9eb4accec3e9920eEric Laurent intent.putExtra(AudioManager.EXTRA_VOLUME_STREAM_VALUE, index); 14374bbcc6549738f3d69831b2bd9eb4accec3e9920eEric Laurent intent.putExtra(AudioManager.EXTRA_PREV_VOLUME_STREAM_VALUE, oldIndex); 14384bbcc6549738f3d69831b2bd9eb4accec3e9920eEric Laurent sendBroadcastToAll(intent); 14394bbcc6549738f3d69831b2bd9eb4accec3e9920eEric Laurent } 14409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 14419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1442336cdb488ff0e5ec6709c66f55072d3ad22b82edJinsuk Kim // If Hdmi-CEC system audio mode is on, we show volume bar only when TV 1443336cdb488ff0e5ec6709c66f55072d3ad22b82edJinsuk Kim // receives volume notification from Audio Receiver. 1444336cdb488ff0e5ec6709c66f55072d3ad22b82edJinsuk Kim private int updateFlagsForSystemAudio(int flags) { 1445336cdb488ff0e5ec6709c66f55072d3ad22b82edJinsuk Kim if (mHdmiTvClient != null) { 1446336cdb488ff0e5ec6709c66f55072d3ad22b82edJinsuk Kim synchronized (mHdmiTvClient) { 1447336cdb488ff0e5ec6709c66f55072d3ad22b82edJinsuk Kim if (mHdmiSystemAudioSupported && 1448336cdb488ff0e5ec6709c66f55072d3ad22b82edJinsuk Kim ((flags & AudioManager.FLAG_HDMI_SYSTEM_AUDIO_VOLUME) == 0)) { 1449336cdb488ff0e5ec6709c66f55072d3ad22b82edJinsuk Kim flags &= ~AudioManager.FLAG_SHOW_UI; 1450336cdb488ff0e5ec6709c66f55072d3ad22b82edJinsuk Kim } 1451336cdb488ff0e5ec6709c66f55072d3ad22b82edJinsuk Kim } 1452336cdb488ff0e5ec6709c66f55072d3ad22b82edJinsuk Kim } 1453336cdb488ff0e5ec6709c66f55072d3ad22b82edJinsuk Kim return flags; 1454336cdb488ff0e5ec6709c66f55072d3ad22b82edJinsuk Kim } 1455336cdb488ff0e5ec6709c66f55072d3ad22b82edJinsuk Kim 14560dc37cce9d564ae43883c8dc8672b9266b881e63Mike Lockwood // UI update and Broadcast Intent 14570dc37cce9d564ae43883c8dc8672b9266b881e63Mike Lockwood private void sendMasterVolumeUpdate(int flags, int oldVolume, int newVolume) { 1458336cdb488ff0e5ec6709c66f55072d3ad22b82edJinsuk Kim mVolumeController.postMasterVolumeChanged(updateFlagsForSystemAudio(flags)); 14590dc37cce9d564ae43883c8dc8672b9266b881e63Mike Lockwood 14600dc37cce9d564ae43883c8dc8672b9266b881e63Mike Lockwood Intent intent = new Intent(AudioManager.MASTER_VOLUME_CHANGED_ACTION); 14610dc37cce9d564ae43883c8dc8672b9266b881e63Mike Lockwood intent.putExtra(AudioManager.EXTRA_PREV_MASTER_VOLUME_VALUE, oldVolume); 14620dc37cce9d564ae43883c8dc8672b9266b881e63Mike Lockwood intent.putExtra(AudioManager.EXTRA_MASTER_VOLUME_VALUE, newVolume); 14635ac72a29593ab9a20337a2225df52bdf4754be02Dianne Hackborn sendBroadcastToAll(intent); 14640dc37cce9d564ae43883c8dc8672b9266b881e63Mike Lockwood } 14650dc37cce9d564ae43883c8dc8672b9266b881e63Mike Lockwood 14660dc37cce9d564ae43883c8dc8672b9266b881e63Mike Lockwood // UI update and Broadcast Intent 14670dc37cce9d564ae43883c8dc8672b9266b881e63Mike Lockwood private void sendMasterMuteUpdate(boolean muted, int flags) { 1468336cdb488ff0e5ec6709c66f55072d3ad22b82edJinsuk Kim mVolumeController.postMasterMuteChanged(updateFlagsForSystemAudio(flags)); 146957978ed86286a33d5b1a0fd000ca3406ba9d87b3Justin Koh broadcastMasterMuteStatus(muted); 147057978ed86286a33d5b1a0fd000ca3406ba9d87b3Justin Koh } 14710dc37cce9d564ae43883c8dc8672b9266b881e63Mike Lockwood 147257978ed86286a33d5b1a0fd000ca3406ba9d87b3Justin Koh private void broadcastMasterMuteStatus(boolean muted) { 14730dc37cce9d564ae43883c8dc8672b9266b881e63Mike Lockwood Intent intent = new Intent(AudioManager.MASTER_MUTE_CHANGED_ACTION); 14740dc37cce9d564ae43883c8dc8672b9266b881e63Mike Lockwood intent.putExtra(AudioManager.EXTRA_MASTER_VOLUME_MUTED, muted); 147557978ed86286a33d5b1a0fd000ca3406ba9d87b3Justin Koh intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT 147657978ed86286a33d5b1a0fd000ca3406ba9d87b3Justin Koh | Intent.FLAG_RECEIVER_REPLACE_PENDING); 14775ac72a29593ab9a20337a2225df52bdf4754be02Dianne Hackborn sendStickyBroadcastToAll(intent); 14780dc37cce9d564ae43883c8dc8672b9266b881e63Mike Lockwood } 14790dc37cce9d564ae43883c8dc8672b9266b881e63Mike Lockwood 14809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 14819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Sets the stream state's index, and posts a message to set system volume. 14829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * This will not call out to the UI. Assumes a valid stream type. 14839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 14849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param streamType Type of the stream 14859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param index Desired volume index of the stream 14869bc8358ddaa01c3490f9709991989633a6a3dd42Eric Laurent * @param device the device whose volume must be changed 14879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param force If true, set the volume even if the desired volume is same 14889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * as the current volume. 14899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 14909bc8358ddaa01c3490f9709991989633a6a3dd42Eric Laurent private void setStreamVolumeInt(int streamType, 14919bc8358ddaa01c3490f9709991989633a6a3dd42Eric Laurent int index, 14929bc8358ddaa01c3490f9709991989633a6a3dd42Eric Laurent int device, 149342b041ed4f184e3af7f788eb07307f556a2a6616Eric Laurent boolean force) { 14949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project VolumeStreamState streamState = mStreamStates[streamType]; 14955b4e654d0c7de8e4d58d73e73b0d5220f19b68f7Eric Laurent 149642b041ed4f184e3af7f788eb07307f556a2a6616Eric Laurent if (streamState.setIndex(index, device) || force) { 149742b041ed4f184e3af7f788eb07307f556a2a6616Eric Laurent // Post message to set system volume (it in turn will post a message 149842b041ed4f184e3af7f788eb07307f556a2a6616Eric Laurent // to persist). 149942b041ed4f184e3af7f788eb07307f556a2a6616Eric Laurent sendMsg(mAudioHandler, 150042b041ed4f184e3af7f788eb07307f556a2a6616Eric Laurent MSG_SET_DEVICE_VOLUME, 150142b041ed4f184e3af7f788eb07307f556a2a6616Eric Laurent SENDMSG_QUEUE, 150242b041ed4f184e3af7f788eb07307f556a2a6616Eric Laurent device, 150342b041ed4f184e3af7f788eb07307f556a2a6616Eric Laurent 0, 150442b041ed4f184e3af7f788eb07307f556a2a6616Eric Laurent streamState, 150542b041ed4f184e3af7f788eb07307f556a2a6616Eric Laurent 0); 15069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 15079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 15089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 15099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** @see AudioManager#setStreamSolo(int, boolean) */ 15109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public void setStreamSolo(int streamType, boolean state, IBinder cb) { 151183a017b6b7c099d1a0293e5839be6477325aef06Eric Laurent if (mUseFixedVolume) { 151283a017b6b7c099d1a0293e5839be6477325aef06Eric Laurent return; 151383a017b6b7c099d1a0293e5839be6477325aef06Eric Laurent } 151483a017b6b7c099d1a0293e5839be6477325aef06Eric Laurent 15159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project for (int stream = 0; stream < mStreamStates.length; stream++) { 15169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (!isStreamAffectedByMute(stream) || stream == streamType) continue; 15179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mStreamStates[stream].mute(cb, state); 15189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 15199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 15209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 15219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** @see AudioManager#setStreamMute(int, boolean) */ 15229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public void setStreamMute(int streamType, boolean state, IBinder cb) { 152383a017b6b7c099d1a0293e5839be6477325aef06Eric Laurent if (mUseFixedVolume) { 152483a017b6b7c099d1a0293e5839be6477325aef06Eric Laurent return; 152583a017b6b7c099d1a0293e5839be6477325aef06Eric Laurent } 15267c82ced4fc5b66c09a19eed9a5499039530142fbRoboErik if (streamType == AudioManager.USE_DEFAULT_STREAM_TYPE) { 15277c82ced4fc5b66c09a19eed9a5499039530142fbRoboErik streamType = getActiveStreamType(streamType); 15287c82ced4fc5b66c09a19eed9a5499039530142fbRoboErik } 152983a017b6b7c099d1a0293e5839be6477325aef06Eric Laurent 15309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (isStreamAffectedByMute(streamType)) { 1531336cdb488ff0e5ec6709c66f55072d3ad22b82edJinsuk Kim if (streamType == AudioSystem.STREAM_MUSIC) { 1532336cdb488ff0e5ec6709c66f55072d3ad22b82edJinsuk Kim setSystemAudioMute(state); 1533336cdb488ff0e5ec6709c66f55072d3ad22b82edJinsuk Kim } 1534336cdb488ff0e5ec6709c66f55072d3ad22b82edJinsuk Kim mStreamStates[streamType].mute(cb, state); 15357c82ced4fc5b66c09a19eed9a5499039530142fbRoboErik 15367c82ced4fc5b66c09a19eed9a5499039530142fbRoboErik Intent intent = new Intent(AudioManager.STREAM_MUTE_CHANGED_ACTION); 15377c82ced4fc5b66c09a19eed9a5499039530142fbRoboErik intent.putExtra(AudioManager.EXTRA_VOLUME_STREAM_TYPE, streamType); 15387c82ced4fc5b66c09a19eed9a5499039530142fbRoboErik intent.putExtra(AudioManager.EXTRA_STREAM_VOLUME_MUTED, state); 15397c82ced4fc5b66c09a19eed9a5499039530142fbRoboErik sendBroadcastToAll(intent); 1540336cdb488ff0e5ec6709c66f55072d3ad22b82edJinsuk Kim } 1541336cdb488ff0e5ec6709c66f55072d3ad22b82edJinsuk Kim } 1542336cdb488ff0e5ec6709c66f55072d3ad22b82edJinsuk Kim 1543336cdb488ff0e5ec6709c66f55072d3ad22b82edJinsuk Kim private void setSystemAudioMute(boolean state) { 1544336cdb488ff0e5ec6709c66f55072d3ad22b82edJinsuk Kim if (mHdmiManager == null || mHdmiTvClient == null) return; 1545336cdb488ff0e5ec6709c66f55072d3ad22b82edJinsuk Kim synchronized (mHdmiManager) { 154648cbf292ba9ad550af7e44d950a441b1812428e2Jinsuk Kim if (!mHdmiSystemAudioSupported) return; 154748cbf292ba9ad550af7e44d950a441b1812428e2Jinsuk Kim synchronized (mHdmiTvClient) { 154848cbf292ba9ad550af7e44d950a441b1812428e2Jinsuk Kim final long token = Binder.clearCallingIdentity(); 154948cbf292ba9ad550af7e44d950a441b1812428e2Jinsuk Kim try { 155048cbf292ba9ad550af7e44d950a441b1812428e2Jinsuk Kim mHdmiTvClient.setSystemAudioMute(state); 155148cbf292ba9ad550af7e44d950a441b1812428e2Jinsuk Kim } finally { 155248cbf292ba9ad550af7e44d950a441b1812428e2Jinsuk Kim Binder.restoreCallingIdentity(token); 155341d974631c5f525da49c88d34cecedd5a4cfeda8Jungshik Jang } 155441d974631c5f525da49c88d34cecedd5a4cfeda8Jungshik Jang } 15559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 15569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 15579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 155825101b0b9a84571ead15b26e9f4cd9c4298d7823Eric Laurent /** get stream mute state. */ 155925101b0b9a84571ead15b26e9f4cd9c4298d7823Eric Laurent public boolean isStreamMute(int streamType) { 15607c82ced4fc5b66c09a19eed9a5499039530142fbRoboErik if (streamType == AudioManager.USE_DEFAULT_STREAM_TYPE) { 15617c82ced4fc5b66c09a19eed9a5499039530142fbRoboErik streamType = getActiveStreamType(streamType); 15627c82ced4fc5b66c09a19eed9a5499039530142fbRoboErik } 15638fa4d6f585f40ff5cf5f9bed316d92c64a306f21Eric Laurent synchronized (VolumeStreamState.class) { 15648fa4d6f585f40ff5cf5f9bed316d92c64a306f21Eric Laurent return mStreamStates[streamType].isMuted_syncVSS(); 15658fa4d6f585f40ff5cf5f9bed316d92c64a306f21Eric Laurent } 156625101b0b9a84571ead15b26e9f4cd9c4298d7823Eric Laurent } 156725101b0b9a84571ead15b26e9f4cd9c4298d7823Eric Laurent 1568ba5270b88798c66fefc17a1b25b27894e4fb7862Jean-Michel Trivi private class RmtSbmxFullVolDeathHandler implements IBinder.DeathRecipient { 1569ba5270b88798c66fefc17a1b25b27894e4fb7862Jean-Michel Trivi private IBinder mICallback; // To be notified of client's death 1570ba5270b88798c66fefc17a1b25b27894e4fb7862Jean-Michel Trivi 1571ba5270b88798c66fefc17a1b25b27894e4fb7862Jean-Michel Trivi RmtSbmxFullVolDeathHandler(IBinder cb) { 1572ba5270b88798c66fefc17a1b25b27894e4fb7862Jean-Michel Trivi mICallback = cb; 1573ba5270b88798c66fefc17a1b25b27894e4fb7862Jean-Michel Trivi try { 1574ba5270b88798c66fefc17a1b25b27894e4fb7862Jean-Michel Trivi cb.linkToDeath(this, 0/*flags*/); 1575ba5270b88798c66fefc17a1b25b27894e4fb7862Jean-Michel Trivi } catch (RemoteException e) { 1576ba5270b88798c66fefc17a1b25b27894e4fb7862Jean-Michel Trivi Log.e(TAG, "can't link to death", e); 1577ba5270b88798c66fefc17a1b25b27894e4fb7862Jean-Michel Trivi } 1578ba5270b88798c66fefc17a1b25b27894e4fb7862Jean-Michel Trivi } 1579ba5270b88798c66fefc17a1b25b27894e4fb7862Jean-Michel Trivi 1580ba5270b88798c66fefc17a1b25b27894e4fb7862Jean-Michel Trivi boolean isHandlerFor(IBinder cb) { 1581ba5270b88798c66fefc17a1b25b27894e4fb7862Jean-Michel Trivi return mICallback.equals(cb); 1582ba5270b88798c66fefc17a1b25b27894e4fb7862Jean-Michel Trivi } 1583ba5270b88798c66fefc17a1b25b27894e4fb7862Jean-Michel Trivi 1584ba5270b88798c66fefc17a1b25b27894e4fb7862Jean-Michel Trivi void forget() { 1585ba5270b88798c66fefc17a1b25b27894e4fb7862Jean-Michel Trivi try { 1586ba5270b88798c66fefc17a1b25b27894e4fb7862Jean-Michel Trivi mICallback.unlinkToDeath(this, 0/*flags*/); 1587ba5270b88798c66fefc17a1b25b27894e4fb7862Jean-Michel Trivi } catch (NoSuchElementException e) { 1588ba5270b88798c66fefc17a1b25b27894e4fb7862Jean-Michel Trivi Log.e(TAG, "error unlinking to death", e); 1589ba5270b88798c66fefc17a1b25b27894e4fb7862Jean-Michel Trivi } 1590ba5270b88798c66fefc17a1b25b27894e4fb7862Jean-Michel Trivi } 1591ba5270b88798c66fefc17a1b25b27894e4fb7862Jean-Michel Trivi 1592ba5270b88798c66fefc17a1b25b27894e4fb7862Jean-Michel Trivi public void binderDied() { 1593ba5270b88798c66fefc17a1b25b27894e4fb7862Jean-Michel Trivi Log.w(TAG, "Recorder with remote submix at full volume died " + mICallback); 1594ba5270b88798c66fefc17a1b25b27894e4fb7862Jean-Michel Trivi forceRemoteSubmixFullVolume(false, mICallback); 1595ba5270b88798c66fefc17a1b25b27894e4fb7862Jean-Michel Trivi } 1596ba5270b88798c66fefc17a1b25b27894e4fb7862Jean-Michel Trivi } 1597ba5270b88798c66fefc17a1b25b27894e4fb7862Jean-Michel Trivi 1598ba5270b88798c66fefc17a1b25b27894e4fb7862Jean-Michel Trivi /** 1599ba5270b88798c66fefc17a1b25b27894e4fb7862Jean-Michel Trivi * call must be synchronized on mRmtSbmxFullVolDeathHandlers 1600ba5270b88798c66fefc17a1b25b27894e4fb7862Jean-Michel Trivi * @return true if there is a registered death handler, false otherwise */ 1601ba5270b88798c66fefc17a1b25b27894e4fb7862Jean-Michel Trivi private boolean discardRmtSbmxFullVolDeathHandlerFor(IBinder cb) { 1602ba5270b88798c66fefc17a1b25b27894e4fb7862Jean-Michel Trivi Iterator<RmtSbmxFullVolDeathHandler> it = mRmtSbmxFullVolDeathHandlers.iterator(); 1603ba5270b88798c66fefc17a1b25b27894e4fb7862Jean-Michel Trivi while (it.hasNext()) { 1604ba5270b88798c66fefc17a1b25b27894e4fb7862Jean-Michel Trivi final RmtSbmxFullVolDeathHandler handler = it.next(); 1605ba5270b88798c66fefc17a1b25b27894e4fb7862Jean-Michel Trivi if (handler.isHandlerFor(cb)) { 1606ba5270b88798c66fefc17a1b25b27894e4fb7862Jean-Michel Trivi handler.forget(); 1607ba5270b88798c66fefc17a1b25b27894e4fb7862Jean-Michel Trivi mRmtSbmxFullVolDeathHandlers.remove(handler); 1608ba5270b88798c66fefc17a1b25b27894e4fb7862Jean-Michel Trivi return true; 1609ba5270b88798c66fefc17a1b25b27894e4fb7862Jean-Michel Trivi } 1610ba5270b88798c66fefc17a1b25b27894e4fb7862Jean-Michel Trivi } 1611ba5270b88798c66fefc17a1b25b27894e4fb7862Jean-Michel Trivi return false; 1612ba5270b88798c66fefc17a1b25b27894e4fb7862Jean-Michel Trivi } 1613ba5270b88798c66fefc17a1b25b27894e4fb7862Jean-Michel Trivi 1614ba5270b88798c66fefc17a1b25b27894e4fb7862Jean-Michel Trivi /** call synchronized on mRmtSbmxFullVolDeathHandlers */ 1615ba5270b88798c66fefc17a1b25b27894e4fb7862Jean-Michel Trivi private boolean hasRmtSbmxFullVolDeathHandlerFor(IBinder cb) { 1616ba5270b88798c66fefc17a1b25b27894e4fb7862Jean-Michel Trivi Iterator<RmtSbmxFullVolDeathHandler> it = mRmtSbmxFullVolDeathHandlers.iterator(); 1617ba5270b88798c66fefc17a1b25b27894e4fb7862Jean-Michel Trivi while (it.hasNext()) { 1618ba5270b88798c66fefc17a1b25b27894e4fb7862Jean-Michel Trivi if (it.next().isHandlerFor(cb)) { 1619ba5270b88798c66fefc17a1b25b27894e4fb7862Jean-Michel Trivi return true; 1620ba5270b88798c66fefc17a1b25b27894e4fb7862Jean-Michel Trivi } 1621ba5270b88798c66fefc17a1b25b27894e4fb7862Jean-Michel Trivi } 1622ba5270b88798c66fefc17a1b25b27894e4fb7862Jean-Michel Trivi return false; 1623ba5270b88798c66fefc17a1b25b27894e4fb7862Jean-Michel Trivi } 1624ba5270b88798c66fefc17a1b25b27894e4fb7862Jean-Michel Trivi 1625ba5270b88798c66fefc17a1b25b27894e4fb7862Jean-Michel Trivi private int mRmtSbmxFullVolRefCount = 0; 1626ba5270b88798c66fefc17a1b25b27894e4fb7862Jean-Michel Trivi private ArrayList<RmtSbmxFullVolDeathHandler> mRmtSbmxFullVolDeathHandlers = 1627ba5270b88798c66fefc17a1b25b27894e4fb7862Jean-Michel Trivi new ArrayList<RmtSbmxFullVolDeathHandler>(); 1628ba5270b88798c66fefc17a1b25b27894e4fb7862Jean-Michel Trivi 1629ba5270b88798c66fefc17a1b25b27894e4fb7862Jean-Michel Trivi public void forceRemoteSubmixFullVolume(boolean startForcing, IBinder cb) { 1630ba5270b88798c66fefc17a1b25b27894e4fb7862Jean-Michel Trivi if (cb == null) { 1631ba5270b88798c66fefc17a1b25b27894e4fb7862Jean-Michel Trivi return; 1632ba5270b88798c66fefc17a1b25b27894e4fb7862Jean-Michel Trivi } 1633ba5270b88798c66fefc17a1b25b27894e4fb7862Jean-Michel Trivi if ((PackageManager.PERMISSION_GRANTED != mContext.checkCallingOrSelfPermission( 1634ba5270b88798c66fefc17a1b25b27894e4fb7862Jean-Michel Trivi android.Manifest.permission.CAPTURE_AUDIO_OUTPUT))) { 1635ba5270b88798c66fefc17a1b25b27894e4fb7862Jean-Michel Trivi Log.w(TAG, "Trying to call forceRemoteSubmixFullVolume() without CAPTURE_AUDIO_OUTPUT"); 1636ba5270b88798c66fefc17a1b25b27894e4fb7862Jean-Michel Trivi return; 1637ba5270b88798c66fefc17a1b25b27894e4fb7862Jean-Michel Trivi } 1638ba5270b88798c66fefc17a1b25b27894e4fb7862Jean-Michel Trivi synchronized(mRmtSbmxFullVolDeathHandlers) { 1639ba5270b88798c66fefc17a1b25b27894e4fb7862Jean-Michel Trivi boolean applyRequired = false; 1640ba5270b88798c66fefc17a1b25b27894e4fb7862Jean-Michel Trivi if (startForcing) { 1641ba5270b88798c66fefc17a1b25b27894e4fb7862Jean-Michel Trivi if (!hasRmtSbmxFullVolDeathHandlerFor(cb)) { 1642ba5270b88798c66fefc17a1b25b27894e4fb7862Jean-Michel Trivi mRmtSbmxFullVolDeathHandlers.add(new RmtSbmxFullVolDeathHandler(cb)); 1643ba5270b88798c66fefc17a1b25b27894e4fb7862Jean-Michel Trivi if (mRmtSbmxFullVolRefCount == 0) { 1644ba5270b88798c66fefc17a1b25b27894e4fb7862Jean-Michel Trivi mFullVolumeDevices |= AudioSystem.DEVICE_OUT_REMOTE_SUBMIX; 1645ba5270b88798c66fefc17a1b25b27894e4fb7862Jean-Michel Trivi mFixedVolumeDevices |= AudioSystem.DEVICE_OUT_REMOTE_SUBMIX; 1646ba5270b88798c66fefc17a1b25b27894e4fb7862Jean-Michel Trivi applyRequired = true; 1647ba5270b88798c66fefc17a1b25b27894e4fb7862Jean-Michel Trivi } 1648ba5270b88798c66fefc17a1b25b27894e4fb7862Jean-Michel Trivi mRmtSbmxFullVolRefCount++; 1649ba5270b88798c66fefc17a1b25b27894e4fb7862Jean-Michel Trivi } 1650ba5270b88798c66fefc17a1b25b27894e4fb7862Jean-Michel Trivi } else { 1651ba5270b88798c66fefc17a1b25b27894e4fb7862Jean-Michel Trivi if (discardRmtSbmxFullVolDeathHandlerFor(cb) && (mRmtSbmxFullVolRefCount > 0)) { 1652ba5270b88798c66fefc17a1b25b27894e4fb7862Jean-Michel Trivi mRmtSbmxFullVolRefCount--; 1653ba5270b88798c66fefc17a1b25b27894e4fb7862Jean-Michel Trivi if (mRmtSbmxFullVolRefCount == 0) { 1654ba5270b88798c66fefc17a1b25b27894e4fb7862Jean-Michel Trivi mFullVolumeDevices &= ~AudioSystem.DEVICE_OUT_REMOTE_SUBMIX; 1655ba5270b88798c66fefc17a1b25b27894e4fb7862Jean-Michel Trivi mFixedVolumeDevices &= ~AudioSystem.DEVICE_OUT_REMOTE_SUBMIX; 1656ba5270b88798c66fefc17a1b25b27894e4fb7862Jean-Michel Trivi applyRequired = true; 1657ba5270b88798c66fefc17a1b25b27894e4fb7862Jean-Michel Trivi } 1658ba5270b88798c66fefc17a1b25b27894e4fb7862Jean-Michel Trivi } 1659ba5270b88798c66fefc17a1b25b27894e4fb7862Jean-Michel Trivi } 1660ba5270b88798c66fefc17a1b25b27894e4fb7862Jean-Michel Trivi if (applyRequired) { 1661ba5270b88798c66fefc17a1b25b27894e4fb7862Jean-Michel Trivi // Assumes only STREAM_MUSIC going through DEVICE_OUT_REMOTE_SUBMIX 1662ba5270b88798c66fefc17a1b25b27894e4fb7862Jean-Michel Trivi checkAllFixedVolumeDevices(AudioSystem.STREAM_MUSIC); 1663ba5270b88798c66fefc17a1b25b27894e4fb7862Jean-Michel Trivi mStreamStates[AudioSystem.STREAM_MUSIC].applyAllVolumes(); 1664ba5270b88798c66fefc17a1b25b27894e4fb7862Jean-Michel Trivi } 1665ba5270b88798c66fefc17a1b25b27894e4fb7862Jean-Michel Trivi } 1666ba5270b88798c66fefc17a1b25b27894e4fb7862Jean-Michel Trivi } 1667ba5270b88798c66fefc17a1b25b27894e4fb7862Jean-Michel Trivi 1668961cae92540763226648813d111c5b5c3b0f1597Dianne Hackborn /** @see AudioManager#setMasterMute(boolean, int) */ 16694a21b25fad62e4f19d13ba814263841c931f56efJulia Reynolds public void setMasterMute(boolean state, int flags, String callingPackage, IBinder cb) { 16707c82ced4fc5b66c09a19eed9a5499039530142fbRoboErik setMasterMuteInternal(state, flags, callingPackage, cb, Binder.getCallingUid()); 16717c82ced4fc5b66c09a19eed9a5499039530142fbRoboErik } 16727c82ced4fc5b66c09a19eed9a5499039530142fbRoboErik 16737c82ced4fc5b66c09a19eed9a5499039530142fbRoboErik private void setMasterMuteInternal(boolean state, int flags, String callingPackage, IBinder cb, 16747c82ced4fc5b66c09a19eed9a5499039530142fbRoboErik int uid) { 167583a017b6b7c099d1a0293e5839be6477325aef06Eric Laurent if (mUseFixedVolume) { 167683a017b6b7c099d1a0293e5839be6477325aef06Eric Laurent return; 167783a017b6b7c099d1a0293e5839be6477325aef06Eric Laurent } 16787c82ced4fc5b66c09a19eed9a5499039530142fbRoboErik if (mAppOps.noteOp(AppOpsManager.OP_AUDIO_MASTER_VOLUME, uid, callingPackage) 16797c82ced4fc5b66c09a19eed9a5499039530142fbRoboErik != AppOpsManager.MODE_ALLOWED) { 16804a21b25fad62e4f19d13ba814263841c931f56efJulia Reynolds return; 16814a21b25fad62e4f19d13ba814263841c931f56efJulia Reynolds } 16821ce5b26d707e0086e09af3cd0428f1b441145261Jason Simmons if (state != AudioSystem.getMasterMute()) { 1683336cdb488ff0e5ec6709c66f55072d3ad22b82edJinsuk Kim setSystemAudioMute(state); 16841ce5b26d707e0086e09af3cd0428f1b441145261Jason Simmons AudioSystem.setMasterMute(state); 168557978ed86286a33d5b1a0fd000ca3406ba9d87b3Justin Koh // Post a persist master volume msg 168675cf9e19a575c28c200c02c0ab6f83bb79f5c50dJustin Koh sendMsg(mAudioHandler, MSG_PERSIST_MASTER_VOLUME_MUTE, SENDMSG_REPLACE, state ? 1 1687b53453fae037d67e421011936c8fdffe7ba43922Julia Reynolds : 0, UserHandle.getCallingUserId(), null, PERSIST_DELAY); 16880273af55cf68d54d26d154b44d105d40fed79701Justin Koh sendMasterMuteUpdate(state, flags); 16897c82ced4fc5b66c09a19eed9a5499039530142fbRoboErik 16907c82ced4fc5b66c09a19eed9a5499039530142fbRoboErik Intent intent = new Intent(AudioManager.MASTER_MUTE_CHANGED_ACTION); 16917c82ced4fc5b66c09a19eed9a5499039530142fbRoboErik intent.putExtra(AudioManager.EXTRA_MASTER_VOLUME_MUTED, state); 16927c82ced4fc5b66c09a19eed9a5499039530142fbRoboErik sendBroadcastToAll(intent); 16931ce5b26d707e0086e09af3cd0428f1b441145261Jason Simmons } 1694ce952c8e13c535bedde77bcdb94dfcc7508475aaMike Lockwood } 1695ce952c8e13c535bedde77bcdb94dfcc7508475aaMike Lockwood 1696ce952c8e13c535bedde77bcdb94dfcc7508475aaMike Lockwood /** get master mute state. */ 1697ce952c8e13c535bedde77bcdb94dfcc7508475aaMike Lockwood public boolean isMasterMute() { 16983194ea94348bce8e7ee9f803698d877f46f8279aMike Lockwood return AudioSystem.getMasterMute(); 1699ce952c8e13c535bedde77bcdb94dfcc7508475aaMike Lockwood } 1700ce952c8e13c535bedde77bcdb94dfcc7508475aaMike Lockwood 1701fa9a69805b001034aa04c3b33989a7ac21522371Jean-Michel Trivi protected static int getMaxStreamVolume(int streamType) { 1702fa9a69805b001034aa04c3b33989a7ac21522371Jean-Michel Trivi return MAX_STREAM_VOLUME[streamType]; 1703fa9a69805b001034aa04c3b33989a7ac21522371Jean-Michel Trivi } 1704fa9a69805b001034aa04c3b33989a7ac21522371Jean-Michel Trivi 170591377de6f23af2b0b08adae22810cae6fc35cb1aEric Laurent public static int getDefaultStreamVolume(int streamType) { 170691377de6f23af2b0b08adae22810cae6fc35cb1aEric Laurent return DEFAULT_STREAM_VOLUME[streamType]; 170791377de6f23af2b0b08adae22810cae6fc35cb1aEric Laurent } 170891377de6f23af2b0b08adae22810cae6fc35cb1aEric Laurent 17099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** @see AudioManager#getStreamVolume(int) */ 17109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public int getStreamVolume(int streamType) { 17119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project ensureValidStreamType(streamType); 17129bc8358ddaa01c3490f9709991989633a6a3dd42Eric Laurent int device = getDeviceForStream(streamType); 17138fa4d6f585f40ff5cf5f9bed316d92c64a306f21Eric Laurent synchronized (VolumeStreamState.class) { 17148fa4d6f585f40ff5cf5f9bed316d92c64a306f21Eric Laurent int index = mStreamStates[streamType].getIndex(device); 17154bbcc6549738f3d69831b2bd9eb4accec3e9920eEric Laurent 17168fa4d6f585f40ff5cf5f9bed316d92c64a306f21Eric Laurent // by convention getStreamVolume() returns 0 when a stream is muted. 17178fa4d6f585f40ff5cf5f9bed316d92c64a306f21Eric Laurent if (mStreamStates[streamType].isMuted_syncVSS()) { 17188fa4d6f585f40ff5cf5f9bed316d92c64a306f21Eric Laurent index = 0; 17198fa4d6f585f40ff5cf5f9bed316d92c64a306f21Eric Laurent } 17208fa4d6f585f40ff5cf5f9bed316d92c64a306f21Eric Laurent if (index != 0 && (mStreamVolumeAlias[streamType] == AudioSystem.STREAM_MUSIC) && 17218fa4d6f585f40ff5cf5f9bed316d92c64a306f21Eric Laurent (device & mFixedVolumeDevices) != 0) { 17228fa4d6f585f40ff5cf5f9bed316d92c64a306f21Eric Laurent index = mStreamStates[streamType].getMaxIndex(); 17238fa4d6f585f40ff5cf5f9bed316d92c64a306f21Eric Laurent } 17248fa4d6f585f40ff5cf5f9bed316d92c64a306f21Eric Laurent return (index + 5) / 10; 17254bbcc6549738f3d69831b2bd9eb4accec3e9920eEric Laurent } 17269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 17279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1728519c7744b522aa07e12bc3244ac3de14aa2a4ad0RoboErik @Override 17294767690f09ea3447b8c5c32fb28d27650aa18e00Mike Lockwood public int getMasterVolume() { 1730ce952c8e13c535bedde77bcdb94dfcc7508475aaMike Lockwood if (isMasterMute()) return 0; 1731ce952c8e13c535bedde77bcdb94dfcc7508475aaMike Lockwood return getLastAudibleMasterVolume(); 17328dc1dabd254249b7ddb8743e88fdb96580ffc585Mike Lockwood } 17338dc1dabd254249b7ddb8743e88fdb96580ffc585Mike Lockwood 1734519c7744b522aa07e12bc3244ac3de14aa2a4ad0RoboErik @Override 1735ba50b97cff80e73620a0e3d13cae169e095974a7Dianne Hackborn public void setMasterVolume(int volume, int flags, String callingPackage) { 1736519c7744b522aa07e12bc3244ac3de14aa2a4ad0RoboErik setMasterVolume(volume, flags, callingPackage, Binder.getCallingUid()); 1737519c7744b522aa07e12bc3244ac3de14aa2a4ad0RoboErik } 1738519c7744b522aa07e12bc3244ac3de14aa2a4ad0RoboErik 1739519c7744b522aa07e12bc3244ac3de14aa2a4ad0RoboErik public void setMasterVolume(int volume, int flags, String callingPackage, int uid) { 174083a017b6b7c099d1a0293e5839be6477325aef06Eric Laurent if (mUseFixedVolume) { 174183a017b6b7c099d1a0293e5839be6477325aef06Eric Laurent return; 174283a017b6b7c099d1a0293e5839be6477325aef06Eric Laurent } 174383a017b6b7c099d1a0293e5839be6477325aef06Eric Laurent 1744519c7744b522aa07e12bc3244ac3de14aa2a4ad0RoboErik if (mAppOps.noteOp(AppOpsManager.OP_AUDIO_MASTER_VOLUME, uid, callingPackage) 1745519c7744b522aa07e12bc3244ac3de14aa2a4ad0RoboErik != AppOpsManager.MODE_ALLOWED) { 1746ba50b97cff80e73620a0e3d13cae169e095974a7Dianne Hackborn return; 1747ba50b97cff80e73620a0e3d13cae169e095974a7Dianne Hackborn } 1748ba50b97cff80e73620a0e3d13cae169e095974a7Dianne Hackborn 17499760647dd0ee67e7c20f3e9d661d2006b1df0b54Mike Lockwood if (volume < 0) { 17509760647dd0ee67e7c20f3e9d661d2006b1df0b54Mike Lockwood volume = 0; 17519760647dd0ee67e7c20f3e9d661d2006b1df0b54Mike Lockwood } else if (volume > MAX_MASTER_VOLUME) { 17529760647dd0ee67e7c20f3e9d661d2006b1df0b54Mike Lockwood volume = MAX_MASTER_VOLUME; 17539760647dd0ee67e7c20f3e9d661d2006b1df0b54Mike Lockwood } 17545c55a051ad7d86a464fb91426f1ea3c0250e38b3Mike Lockwood doSetMasterVolume((float)volume / MAX_MASTER_VOLUME, flags); 17555c55a051ad7d86a464fb91426f1ea3c0250e38b3Mike Lockwood } 17565c55a051ad7d86a464fb91426f1ea3c0250e38b3Mike Lockwood 17575c55a051ad7d86a464fb91426f1ea3c0250e38b3Mike Lockwood private void doSetMasterVolume(float volume, int flags) { 17585c55a051ad7d86a464fb91426f1ea3c0250e38b3Mike Lockwood // don't allow changing master volume when muted 17595c55a051ad7d86a464fb91426f1ea3c0250e38b3Mike Lockwood if (!AudioSystem.getMasterMute()) { 17605c55a051ad7d86a464fb91426f1ea3c0250e38b3Mike Lockwood int oldVolume = getMasterVolume(); 17615c55a051ad7d86a464fb91426f1ea3c0250e38b3Mike Lockwood AudioSystem.setMasterVolume(volume); 17625c55a051ad7d86a464fb91426f1ea3c0250e38b3Mike Lockwood 17635c55a051ad7d86a464fb91426f1ea3c0250e38b3Mike Lockwood int newVolume = getMasterVolume(); 17645c55a051ad7d86a464fb91426f1ea3c0250e38b3Mike Lockwood if (newVolume != oldVolume) { 17655c55a051ad7d86a464fb91426f1ea3c0250e38b3Mike Lockwood // Post a persist master volume msg 17665c55a051ad7d86a464fb91426f1ea3c0250e38b3Mike Lockwood sendMsg(mAudioHandler, MSG_PERSIST_MASTER_VOLUME, SENDMSG_REPLACE, 17675c55a051ad7d86a464fb91426f1ea3c0250e38b3Mike Lockwood Math.round(volume * (float)1000.0), 0, null, PERSIST_DELAY); 1768336cdb488ff0e5ec6709c66f55072d3ad22b82edJinsuk Kim setSystemAudioVolume(oldVolume, newVolume, getMasterMaxVolume(), flags); 17695c55a051ad7d86a464fb91426f1ea3c0250e38b3Mike Lockwood } 17703caba517253d1703fc29b50740c4567b932279fbJustin Koh // Send the volume update regardless whether there was a change. 17713caba517253d1703fc29b50740c4567b932279fbJustin Koh sendMasterVolumeUpdate(flags, oldVolume, newVolume); 17725c55a051ad7d86a464fb91426f1ea3c0250e38b3Mike Lockwood } 17738dc1dabd254249b7ddb8743e88fdb96580ffc585Mike Lockwood } 17748dc1dabd254249b7ddb8743e88fdb96580ffc585Mike Lockwood 17759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** @see AudioManager#getStreamMaxVolume(int) */ 17769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public int getStreamMaxVolume(int streamType) { 17779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project ensureValidStreamType(streamType); 1778a553c25b33c99b345cf1c8688f8df0ed8df14e5aEric Laurent return (mStreamStates[streamType].getMaxIndex() + 5) / 10; 17799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 17809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 17814767690f09ea3447b8c5c32fb28d27650aa18e00Mike Lockwood public int getMasterMaxVolume() { 17824767690f09ea3447b8c5c32fb28d27650aa18e00Mike Lockwood return MAX_MASTER_VOLUME; 17834767690f09ea3447b8c5c32fb28d27650aa18e00Mike Lockwood } 178425101b0b9a84571ead15b26e9f4cd9c4298d7823Eric Laurent 178525101b0b9a84571ead15b26e9f4cd9c4298d7823Eric Laurent /** Get last audible volume before stream was muted. */ 178625101b0b9a84571ead15b26e9f4cd9c4298d7823Eric Laurent public int getLastAudibleStreamVolume(int streamType) { 178725101b0b9a84571ead15b26e9f4cd9c4298d7823Eric Laurent ensureValidStreamType(streamType); 17889bc8358ddaa01c3490f9709991989633a6a3dd42Eric Laurent int device = getDeviceForStream(streamType); 178942b041ed4f184e3af7f788eb07307f556a2a6616Eric Laurent return (mStreamStates[streamType].getIndex(device) + 5) / 10; 179025101b0b9a84571ead15b26e9f4cd9c4298d7823Eric Laurent } 179125101b0b9a84571ead15b26e9f4cd9c4298d7823Eric Laurent 1792ce952c8e13c535bedde77bcdb94dfcc7508475aaMike Lockwood /** Get last audible master volume before it was muted. */ 1793ce952c8e13c535bedde77bcdb94dfcc7508475aaMike Lockwood public int getLastAudibleMasterVolume() { 1794ce952c8e13c535bedde77bcdb94dfcc7508475aaMike Lockwood return Math.round(AudioSystem.getMasterVolume() * MAX_MASTER_VOLUME); 1795ce952c8e13c535bedde77bcdb94dfcc7508475aaMike Lockwood } 1796ce952c8e13c535bedde77bcdb94dfcc7508475aaMike Lockwood 1797961cae92540763226648813d111c5b5c3b0f1597Dianne Hackborn /** @see AudioManager#getMasterStreamType() */ 17986d5176638c2189595cede38fb92c3e7e8700e221Eric Laurent public int getMasterStreamType() { 17994f0f120316cfcee5880191264885772677fff921John Spurlock return mStreamVolumeAlias[AudioSystem.STREAM_SYSTEM]; 18006d5176638c2189595cede38fb92c3e7e8700e221Eric Laurent } 18016d5176638c2189595cede38fb92c3e7e8700e221Eric Laurent 180222c921a910d236abf3a1705a02541a49fdaf3a14Emily Bernier /** @see AudioManager#setMicrophoneMute(boolean) */ 180322c921a910d236abf3a1705a02541a49fdaf3a14Emily Bernier public void setMicrophoneMute(boolean on, String callingPackage) { 180422c921a910d236abf3a1705a02541a49fdaf3a14Emily Bernier if (mAppOps.noteOp(AppOpsManager.OP_MUTE_MICROPHONE, Binder.getCallingUid(), 180522c921a910d236abf3a1705a02541a49fdaf3a14Emily Bernier callingPackage) != AppOpsManager.MODE_ALLOWED) { 180622c921a910d236abf3a1705a02541a49fdaf3a14Emily Bernier return; 180722c921a910d236abf3a1705a02541a49fdaf3a14Emily Bernier } 18084a4fea0752c8edd33d680765e97ee3b538d777a5Jean-Michel Trivi if (!checkAudioSettingsPermission("setMicrophoneMute()")) { 18094a4fea0752c8edd33d680765e97ee3b538d777a5Jean-Michel Trivi return; 18104a4fea0752c8edd33d680765e97ee3b538d777a5Jean-Michel Trivi } 181122c921a910d236abf3a1705a02541a49fdaf3a14Emily Bernier 181222c921a910d236abf3a1705a02541a49fdaf3a14Emily Bernier AudioSystem.muteMicrophone(on); 1813b53453fae037d67e421011936c8fdffe7ba43922Julia Reynolds // Post a persist microphone msg. 1814b53453fae037d67e421011936c8fdffe7ba43922Julia Reynolds sendMsg(mAudioHandler, MSG_PERSIST_MICROPHONE_MUTE, SENDMSG_REPLACE, on ? 1 1815b53453fae037d67e421011936c8fdffe7ba43922Julia Reynolds : 0, UserHandle.getCallingUserId(), null, PERSIST_DELAY); 181622c921a910d236abf3a1705a02541a49fdaf3a14Emily Bernier } 181722c921a910d236abf3a1705a02541a49fdaf3a14Emily Bernier 1818661f2cf45860d2e10924e6b69966a9afe255f28bJohn Spurlock @Override 1819661f2cf45860d2e10924e6b69966a9afe255f28bJohn Spurlock public int getRingerModeExternal() { 1820661f2cf45860d2e10924e6b69966a9afe255f28bJohn Spurlock synchronized(mSettingsLock) { 1821661f2cf45860d2e10924e6b69966a9afe255f28bJohn Spurlock return mRingerModeExternal; 1822661f2cf45860d2e10924e6b69966a9afe255f28bJohn Spurlock } 1823661f2cf45860d2e10924e6b69966a9afe255f28bJohn Spurlock } 1824661f2cf45860d2e10924e6b69966a9afe255f28bJohn Spurlock 1825661f2cf45860d2e10924e6b69966a9afe255f28bJohn Spurlock @Override 1826661f2cf45860d2e10924e6b69966a9afe255f28bJohn Spurlock public int getRingerModeInternal() { 1827ba195ebc76f23b6679443724ab58c9dc9f2df884Glenn Kasten synchronized(mSettingsLock) { 1828ba195ebc76f23b6679443724ab58c9dc9f2df884Glenn Kasten return mRingerMode; 1829ba195ebc76f23b6679443724ab58c9dc9f2df884Glenn Kasten } 1830ba195ebc76f23b6679443724ab58c9dc9f2df884Glenn Kasten } 1831ba195ebc76f23b6679443724ab58c9dc9f2df884Glenn Kasten 1832ba195ebc76f23b6679443724ab58c9dc9f2df884Glenn Kasten private void ensureValidRingerMode(int ringerMode) { 18339755937ed90f06db45ff5fe4510950ae1516f8f9John Spurlock if (!isValidRingerMode(ringerMode)) { 1834ba195ebc76f23b6679443724ab58c9dc9f2df884Glenn Kasten throw new IllegalArgumentException("Bad ringer mode " + ringerMode); 1835ba195ebc76f23b6679443724ab58c9dc9f2df884Glenn Kasten } 18369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 18379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 18389755937ed90f06db45ff5fe4510950ae1516f8f9John Spurlock /** @see AudioManager#isValidRingerMode(int) */ 18399755937ed90f06db45ff5fe4510950ae1516f8f9John Spurlock public boolean isValidRingerMode(int ringerMode) { 18409755937ed90f06db45ff5fe4510950ae1516f8f9John Spurlock return ringerMode >= 0 && ringerMode <= AudioManager.RINGER_MODE_MAX; 18419755937ed90f06db45ff5fe4510950ae1516f8f9John Spurlock } 18429755937ed90f06db45ff5fe4510950ae1516f8f9John Spurlock 1843661f2cf45860d2e10924e6b69966a9afe255f28bJohn Spurlock public void setRingerModeExternal(int ringerMode, String caller) { 1844af88a19165a1de77948d58b2692c9a7e13712a59John Spurlock setRingerMode(ringerMode, caller, true /*external*/); 1845661f2cf45860d2e10924e6b69966a9afe255f28bJohn Spurlock } 1846661f2cf45860d2e10924e6b69966a9afe255f28bJohn Spurlock 1847661f2cf45860d2e10924e6b69966a9afe255f28bJohn Spurlock public void setRingerModeInternal(int ringerMode, String caller) { 1848661f2cf45860d2e10924e6b69966a9afe255f28bJohn Spurlock enforceSelfOrSystemUI("setRingerModeInternal"); 1849af88a19165a1de77948d58b2692c9a7e13712a59John Spurlock setRingerMode(ringerMode, caller, false /*external*/); 1850661f2cf45860d2e10924e6b69966a9afe255f28bJohn Spurlock } 1851661f2cf45860d2e10924e6b69966a9afe255f28bJohn Spurlock 1852661f2cf45860d2e10924e6b69966a9afe255f28bJohn Spurlock private void setRingerMode(int ringerMode, String caller, boolean external) { 1853212532b58e3b17d7e9d6e1361946d909d4e372c2Eric Laurent if (mUseFixedVolume || isPlatformTelevision()) { 185483a017b6b7c099d1a0293e5839be6477325aef06Eric Laurent return; 185583a017b6b7c099d1a0293e5839be6477325aef06Eric Laurent } 1856661f2cf45860d2e10924e6b69966a9afe255f28bJohn Spurlock if (caller == null || caller.length() == 0) { 1857661f2cf45860d2e10924e6b69966a9afe255f28bJohn Spurlock throw new IllegalArgumentException("Bad caller: " + caller); 1858661f2cf45860d2e10924e6b69966a9afe255f28bJohn Spurlock } 18599755937ed90f06db45ff5fe4510950ae1516f8f9John Spurlock ensureValidRingerMode(ringerMode); 1860244820185269991186d07068b92985624cede4a5Eric Laurent if ((ringerMode == AudioManager.RINGER_MODE_VIBRATE) && !mHasVibrator) { 1861244820185269991186d07068b92985624cede4a5Eric Laurent ringerMode = AudioManager.RINGER_MODE_SILENT; 1862244820185269991186d07068b92985624cede4a5Eric Laurent } 1863af88a19165a1de77948d58b2692c9a7e13712a59John Spurlock final long identity = Binder.clearCallingIdentity(); 1864af88a19165a1de77948d58b2692c9a7e13712a59John Spurlock try { 1865af88a19165a1de77948d58b2692c9a7e13712a59John Spurlock synchronized (mSettingsLock) { 1866af88a19165a1de77948d58b2692c9a7e13712a59John Spurlock final int ringerModeInternal = getRingerModeInternal(); 1867af88a19165a1de77948d58b2692c9a7e13712a59John Spurlock final int ringerModeExternal = getRingerModeExternal(); 1868af88a19165a1de77948d58b2692c9a7e13712a59John Spurlock if (external) { 1869af88a19165a1de77948d58b2692c9a7e13712a59John Spurlock setRingerModeExt(ringerMode); 1870af88a19165a1de77948d58b2692c9a7e13712a59John Spurlock if (mRingerModeDelegate != null) { 1871af88a19165a1de77948d58b2692c9a7e13712a59John Spurlock ringerMode = mRingerModeDelegate.onSetRingerModeExternal(ringerModeExternal, 1872af88a19165a1de77948d58b2692c9a7e13712a59John Spurlock ringerMode, caller, ringerModeInternal); 1873af88a19165a1de77948d58b2692c9a7e13712a59John Spurlock } 1874af88a19165a1de77948d58b2692c9a7e13712a59John Spurlock if (ringerMode != ringerModeInternal) { 1875af88a19165a1de77948d58b2692c9a7e13712a59John Spurlock setRingerModeInt(ringerMode, true /*persist*/); 1876af88a19165a1de77948d58b2692c9a7e13712a59John Spurlock } 1877af88a19165a1de77948d58b2692c9a7e13712a59John Spurlock } else /*internal*/ { 1878af88a19165a1de77948d58b2692c9a7e13712a59John Spurlock if (ringerMode != ringerModeInternal) { 1879af88a19165a1de77948d58b2692c9a7e13712a59John Spurlock setRingerModeInt(ringerMode, true /*persist*/); 1880af88a19165a1de77948d58b2692c9a7e13712a59John Spurlock } 1881af88a19165a1de77948d58b2692c9a7e13712a59John Spurlock if (mRingerModeDelegate != null) { 1882af88a19165a1de77948d58b2692c9a7e13712a59John Spurlock ringerMode = mRingerModeDelegate.onSetRingerModeInternal(ringerModeInternal, 1883af88a19165a1de77948d58b2692c9a7e13712a59John Spurlock ringerMode, caller, ringerModeExternal); 1884af88a19165a1de77948d58b2692c9a7e13712a59John Spurlock } 1885af88a19165a1de77948d58b2692c9a7e13712a59John Spurlock setRingerModeExt(ringerMode); 188657627794b682235afd60adfb235fee46d32f54e2John Spurlock } 1887661f2cf45860d2e10924e6b69966a9afe255f28bJohn Spurlock } 1888af88a19165a1de77948d58b2692c9a7e13712a59John Spurlock } finally { 1889af88a19165a1de77948d58b2692c9a7e13712a59John Spurlock Binder.restoreCallingIdentity(identity); 1890b109615ebebd6f3b9ae789412279f576c3ace46bJason Parekh } 1891b109615ebebd6f3b9ae789412279f576c3ace46bJason Parekh } 18929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1893661f2cf45860d2e10924e6b69966a9afe255f28bJohn Spurlock private void setRingerModeExt(int ringerMode) { 1894661f2cf45860d2e10924e6b69966a9afe255f28bJohn Spurlock synchronized(mSettingsLock) { 1895661f2cf45860d2e10924e6b69966a9afe255f28bJohn Spurlock if (ringerMode == mRingerModeExternal) return; 1896661f2cf45860d2e10924e6b69966a9afe255f28bJohn Spurlock mRingerModeExternal = ringerMode; 1897e5b42d97f6fd3eb0220ea84f21e60d530d93fc46John Spurlock } 1898661f2cf45860d2e10924e6b69966a9afe255f28bJohn Spurlock // Send sticky broadcast 1899bcc1087af40a0e1bb35dbe8a39c830ecdea8280bJohn Spurlock broadcastRingerMode(AudioManager.RINGER_MODE_CHANGED_ACTION, ringerMode); 1900e5b42d97f6fd3eb0220ea84f21e60d530d93fc46John Spurlock } 1901e5b42d97f6fd3eb0220ea84f21e60d530d93fc46John Spurlock 19024050c93601b3c3609b21cc1e18a29b64747e7fa9Eric Laurent private void setRingerModeInt(int ringerMode, boolean persist) { 1903bcc1087af40a0e1bb35dbe8a39c830ecdea8280bJohn Spurlock final boolean change; 1904ba195ebc76f23b6679443724ab58c9dc9f2df884Glenn Kasten synchronized(mSettingsLock) { 1905bcc1087af40a0e1bb35dbe8a39c830ecdea8280bJohn Spurlock change = mRingerMode != ringerMode; 1906ba195ebc76f23b6679443724ab58c9dc9f2df884Glenn Kasten mRingerMode = ringerMode; 1907ba195ebc76f23b6679443724ab58c9dc9f2df884Glenn Kasten } 1908b109615ebebd6f3b9ae789412279f576c3ace46bJason Parekh 19095b4e654d0c7de8e4d58d73e73b0d5220f19b68f7Eric Laurent // Mute stream if not previously muted by ringer mode and ringer mode 19105b4e654d0c7de8e4d58d73e73b0d5220f19b68f7Eric Laurent // is not RINGER_MODE_NORMAL and stream is affected by ringer mode. 19115b4e654d0c7de8e4d58d73e73b0d5220f19b68f7Eric Laurent // Unmute stream if previously muted by ringer mode and ringer mode 19125b4e654d0c7de8e4d58d73e73b0d5220f19b68f7Eric Laurent // is RINGER_MODE_NORMAL or stream is not affected by ringer mode. 1913b109615ebebd6f3b9ae789412279f576c3ace46bJason Parekh int numStreamTypes = AudioSystem.getNumStreamTypes(); 1914661f2cf45860d2e10924e6b69966a9afe255f28bJohn Spurlock final boolean ringerModeMute = ringerMode == AudioManager.RINGER_MODE_VIBRATE 1915661f2cf45860d2e10924e6b69966a9afe255f28bJohn Spurlock || ringerMode == AudioManager.RINGER_MODE_SILENT; 19165b4e654d0c7de8e4d58d73e73b0d5220f19b68f7Eric Laurent for (int streamType = numStreamTypes - 1; streamType >= 0; streamType--) { 1917661f2cf45860d2e10924e6b69966a9afe255f28bJohn Spurlock final boolean isMuted = isStreamMutedByRingerMode(streamType); 1918661f2cf45860d2e10924e6b69966a9afe255f28bJohn Spurlock final boolean shouldMute = ringerModeMute && isStreamAffectedByRingerMode(streamType); 1919661f2cf45860d2e10924e6b69966a9afe255f28bJohn Spurlock if (isMuted == shouldMute) continue; 1920661f2cf45860d2e10924e6b69966a9afe255f28bJohn Spurlock if (!shouldMute) { 1921661f2cf45860d2e10924e6b69966a9afe255f28bJohn Spurlock // unmute 1922661f2cf45860d2e10924e6b69966a9afe255f28bJohn Spurlock // ring and notifications volume should never be 0 when not silenced 1923661f2cf45860d2e10924e6b69966a9afe255f28bJohn Spurlock // on voice capable devices or devices that support vibration 1924661f2cf45860d2e10924e6b69966a9afe255f28bJohn Spurlock if ((isPlatformVoice() || mHasVibrator) && 1925661f2cf45860d2e10924e6b69966a9afe255f28bJohn Spurlock mStreamVolumeAlias[streamType] == AudioSystem.STREAM_RING) { 1926661f2cf45860d2e10924e6b69966a9afe255f28bJohn Spurlock synchronized (VolumeStreamState.class) { 1927661f2cf45860d2e10924e6b69966a9afe255f28bJohn Spurlock Set set = mStreamStates[streamType].mIndex.entrySet(); 1928661f2cf45860d2e10924e6b69966a9afe255f28bJohn Spurlock Iterator i = set.iterator(); 1929661f2cf45860d2e10924e6b69966a9afe255f28bJohn Spurlock while (i.hasNext()) { 1930661f2cf45860d2e10924e6b69966a9afe255f28bJohn Spurlock Map.Entry entry = (Map.Entry)i.next(); 1931661f2cf45860d2e10924e6b69966a9afe255f28bJohn Spurlock if ((Integer)entry.getValue() == 0) { 1932661f2cf45860d2e10924e6b69966a9afe255f28bJohn Spurlock entry.setValue(10); 19339bc8358ddaa01c3490f9709991989633a6a3dd42Eric Laurent } 19349bc8358ddaa01c3490f9709991989633a6a3dd42Eric Laurent } 1935b024c30a80684ac08daef3137b7ba0d347fe3ce5Eric Laurent } 19369bcf401d13d47416043a704430388abd59aef7cdEric Laurent } 1937661f2cf45860d2e10924e6b69966a9afe255f28bJohn Spurlock mStreamStates[streamType].mute(null, false); 1938661f2cf45860d2e10924e6b69966a9afe255f28bJohn Spurlock mRingerModeMutedStreams &= ~(1 << streamType); 19395b4e654d0c7de8e4d58d73e73b0d5220f19b68f7Eric Laurent } else { 1940661f2cf45860d2e10924e6b69966a9afe255f28bJohn Spurlock // mute 1941661f2cf45860d2e10924e6b69966a9afe255f28bJohn Spurlock mStreamStates[streamType].mute(null, true); 1942661f2cf45860d2e10924e6b69966a9afe255f28bJohn Spurlock mRingerModeMutedStreams |= (1 << streamType); 1943b109615ebebd6f3b9ae789412279f576c3ace46bJason Parekh } 19449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1945a553c25b33c99b345cf1c8688f8df0ed8df14e5aEric Laurent 1946b109615ebebd6f3b9ae789412279f576c3ace46bJason Parekh // Post a persist ringer mode msg 19474050c93601b3c3609b21cc1e18a29b64747e7fa9Eric Laurent if (persist) { 1948afbb047c3945e9c2b7e9bc6b25098d5fb80bba4eEric Laurent sendMsg(mAudioHandler, MSG_PERSIST_RINGER_MODE, 19494050c93601b3c3609b21cc1e18a29b64747e7fa9Eric Laurent SENDMSG_REPLACE, 0, 0, null, PERSIST_DELAY); 19504050c93601b3c3609b21cc1e18a29b64747e7fa9Eric Laurent } 1951bcc1087af40a0e1bb35dbe8a39c830ecdea8280bJohn Spurlock if (change) { 1952bcc1087af40a0e1bb35dbe8a39c830ecdea8280bJohn Spurlock // Send sticky broadcast 1953bcc1087af40a0e1bb35dbe8a39c830ecdea8280bJohn Spurlock broadcastRingerMode(AudioManager.INTERNAL_RINGER_MODE_CHANGED_ACTION, ringerMode); 1954bcc1087af40a0e1bb35dbe8a39c830ecdea8280bJohn Spurlock } 19559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 19569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 19579063154a793b0ab38b3c5992cbaed046427b4a82Mike Lockwood private void restoreMasterVolume() { 195883a017b6b7c099d1a0293e5839be6477325aef06Eric Laurent if (mUseFixedVolume) { 195983a017b6b7c099d1a0293e5839be6477325aef06Eric Laurent AudioSystem.setMasterVolume(1.0f); 196083a017b6b7c099d1a0293e5839be6477325aef06Eric Laurent return; 196183a017b6b7c099d1a0293e5839be6477325aef06Eric Laurent } 19629063154a793b0ab38b3c5992cbaed046427b4a82Mike Lockwood if (mUseMasterVolume) { 1963bc0fab1fc2db832ef86d8a33466ec4d68b103ca0Eric Laurent float volume = Settings.System.getFloatForUser(mContentResolver, 1964bc0fab1fc2db832ef86d8a33466ec4d68b103ca0Eric Laurent Settings.System.VOLUME_MASTER, -1.0f, UserHandle.USER_CURRENT); 19659063154a793b0ab38b3c5992cbaed046427b4a82Mike Lockwood if (volume >= 0.0f) { 19669063154a793b0ab38b3c5992cbaed046427b4a82Mike Lockwood AudioSystem.setMasterVolume(volume); 19679063154a793b0ab38b3c5992cbaed046427b4a82Mike Lockwood } 19689063154a793b0ab38b3c5992cbaed046427b4a82Mike Lockwood } 19699063154a793b0ab38b3c5992cbaed046427b4a82Mike Lockwood } 19709063154a793b0ab38b3c5992cbaed046427b4a82Mike Lockwood 19719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** @see AudioManager#shouldVibrate(int) */ 19729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public boolean shouldVibrate(int vibrateType) { 1973bffc3d1bd33eb2d8e00a9f8b6261d815db503311Eric Laurent if (!mHasVibrator) return false; 19749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 19759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project switch (getVibrateSetting(vibrateType)) { 19769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 19779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project case AudioManager.VIBRATE_SETTING_ON: 197857627794b682235afd60adfb235fee46d32f54e2John Spurlock return getRingerModeExternal() != AudioManager.RINGER_MODE_SILENT; 19799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 19809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project case AudioManager.VIBRATE_SETTING_ONLY_SILENT: 198157627794b682235afd60adfb235fee46d32f54e2John Spurlock return getRingerModeExternal() == AudioManager.RINGER_MODE_VIBRATE; 19829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 19839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project case AudioManager.VIBRATE_SETTING_OFF: 1984bcac496076ef6f439147e7a2be71e8a2b76ddedeDaniel Sandler // return false, even for incoming calls 1985bcac496076ef6f439147e7a2be71e8a2b76ddedeDaniel Sandler return false; 19869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 19879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project default: 19889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return false; 19899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 19909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 19919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 19929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** @see AudioManager#getVibrateSetting(int) */ 19939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public int getVibrateSetting(int vibrateType) { 1994bffc3d1bd33eb2d8e00a9f8b6261d815db503311Eric Laurent if (!mHasVibrator) return AudioManager.VIBRATE_SETTING_OFF; 19959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return (mVibrateSetting >> (vibrateType * 2)) & 3; 19969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 19979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 19989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** @see AudioManager#setVibrateSetting(int, int) */ 19999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public void setVibrateSetting(int vibrateType, int vibrateSetting) { 20009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2001bffc3d1bd33eb2d8e00a9f8b6261d815db503311Eric Laurent if (!mHasVibrator) return; 2002bffc3d1bd33eb2d8e00a9f8b6261d815db503311Eric Laurent 20039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mVibrateSetting = getValueForVibrateSetting(mVibrateSetting, vibrateType, vibrateSetting); 20049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 20059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Broadcast change 20069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project broadcastVibrateSetting(vibrateType); 20079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 20089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 20099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 20109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 20119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @see #setVibrateSetting(int, int) 20129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 20139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public static int getValueForVibrateSetting(int existingValue, int vibrateType, 20149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int vibrateSetting) { 20159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 20169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // First clear the existing setting. Each vibrate type has two bits in 20179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // the value. Note '3' is '11' in binary. 20189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project existingValue &= ~(3 << (vibrateType * 2)); 20199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 20209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Set into the old value 20219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project existingValue |= (vibrateSetting & 3) << (vibrateType * 2); 20229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 20239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return existingValue; 20249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 20259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 20269272b4b4a44fe1f33e3030810618194f817caaecEric Laurent private class SetModeDeathHandler implements IBinder.DeathRecipient { 20279272b4b4a44fe1f33e3030810618194f817caaecEric Laurent private IBinder mCb; // To be notified of client's death 2028f1ddd51f9cd2f92b922bc636c307210a8d587c25Marco Nelissen private int mPid; 20299272b4b4a44fe1f33e3030810618194f817caaecEric Laurent private int mMode = AudioSystem.MODE_NORMAL; // Current mode set by this client 20309272b4b4a44fe1f33e3030810618194f817caaecEric Laurent 20319f103de83f2d5d472960dcf1401e95b2ab57a477Eric Laurent SetModeDeathHandler(IBinder cb, int pid) { 20329272b4b4a44fe1f33e3030810618194f817caaecEric Laurent mCb = cb; 20339f103de83f2d5d472960dcf1401e95b2ab57a477Eric Laurent mPid = pid; 20349272b4b4a44fe1f33e3030810618194f817caaecEric Laurent } 20359272b4b4a44fe1f33e3030810618194f817caaecEric Laurent 20369272b4b4a44fe1f33e3030810618194f817caaecEric Laurent public void binderDied() { 2037d7454be47f4111c0478a502353e11dea401378bdEric Laurent int newModeOwnerPid = 0; 20389272b4b4a44fe1f33e3030810618194f817caaecEric Laurent synchronized(mSetModeDeathHandlers) { 20399272b4b4a44fe1f33e3030810618194f817caaecEric Laurent Log.w(TAG, "setMode() client died"); 20409272b4b4a44fe1f33e3030810618194f817caaecEric Laurent int index = mSetModeDeathHandlers.indexOf(this); 20419272b4b4a44fe1f33e3030810618194f817caaecEric Laurent if (index < 0) { 20429272b4b4a44fe1f33e3030810618194f817caaecEric Laurent Log.w(TAG, "unregistered setMode() client died"); 20439272b4b4a44fe1f33e3030810618194f817caaecEric Laurent } else { 2044d7454be47f4111c0478a502353e11dea401378bdEric Laurent newModeOwnerPid = setModeInt(AudioSystem.MODE_NORMAL, mCb, mPid); 20459272b4b4a44fe1f33e3030810618194f817caaecEric Laurent } 20469272b4b4a44fe1f33e3030810618194f817caaecEric Laurent } 20479f103de83f2d5d472960dcf1401e95b2ab57a477Eric Laurent // when entering RINGTONE, IN_CALL or IN_COMMUNICATION mode, clear all 20489f103de83f2d5d472960dcf1401e95b2ab57a477Eric Laurent // SCO connections not started by the application changing the mode 2049d7454be47f4111c0478a502353e11dea401378bdEric Laurent if (newModeOwnerPid != 0) { 20506b5e22d52c69cb6d80ff09bd32395b0034ada343Eric Laurent final long ident = Binder.clearCallingIdentity(); 20516b5e22d52c69cb6d80ff09bd32395b0034ada343Eric Laurent disconnectBluetoothSco(newModeOwnerPid); 20526b5e22d52c69cb6d80ff09bd32395b0034ada343Eric Laurent Binder.restoreCallingIdentity(ident); 20539f103de83f2d5d472960dcf1401e95b2ab57a477Eric Laurent } 20549272b4b4a44fe1f33e3030810618194f817caaecEric Laurent } 20559272b4b4a44fe1f33e3030810618194f817caaecEric Laurent 2056f1ddd51f9cd2f92b922bc636c307210a8d587c25Marco Nelissen public int getPid() { 2057f1ddd51f9cd2f92b922bc636c307210a8d587c25Marco Nelissen return mPid; 2058f1ddd51f9cd2f92b922bc636c307210a8d587c25Marco Nelissen } 2059f1ddd51f9cd2f92b922bc636c307210a8d587c25Marco Nelissen 20609272b4b4a44fe1f33e3030810618194f817caaecEric Laurent public void setMode(int mode) { 20619272b4b4a44fe1f33e3030810618194f817caaecEric Laurent mMode = mode; 20629272b4b4a44fe1f33e3030810618194f817caaecEric Laurent } 20639272b4b4a44fe1f33e3030810618194f817caaecEric Laurent 20649272b4b4a44fe1f33e3030810618194f817caaecEric Laurent public int getMode() { 20659272b4b4a44fe1f33e3030810618194f817caaecEric Laurent return mMode; 20669272b4b4a44fe1f33e3030810618194f817caaecEric Laurent } 20679272b4b4a44fe1f33e3030810618194f817caaecEric Laurent 20689272b4b4a44fe1f33e3030810618194f817caaecEric Laurent public IBinder getBinder() { 20699272b4b4a44fe1f33e3030810618194f817caaecEric Laurent return mCb; 20709272b4b4a44fe1f33e3030810618194f817caaecEric Laurent } 20719272b4b4a44fe1f33e3030810618194f817caaecEric Laurent } 20729272b4b4a44fe1f33e3030810618194f817caaecEric Laurent 20739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** @see AudioManager#setMode(int) */ 20749272b4b4a44fe1f33e3030810618194f817caaecEric Laurent public void setMode(int mode, IBinder cb) { 2075339567d5c91a8dc9228913ed1e5deb0ebb8a4a64Jean-Michel Trivi if (DEBUG_MODE) { Log.v(TAG, "setMode(mode=" + mode + ")"); } 20769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (!checkAudioSettingsPermission("setMode()")) { 20779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return; 20789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2079a553c25b33c99b345cf1c8688f8df0ed8df14e5aEric Laurent 2080ccd654e9d4c38da0d652c442e7a2ca3f447e9abeJean-Michel Trivi if ( (mode == AudioSystem.MODE_IN_CALL) && 2081ccd654e9d4c38da0d652c442e7a2ca3f447e9abeJean-Michel Trivi (mContext.checkCallingOrSelfPermission( 2082ccd654e9d4c38da0d652c442e7a2ca3f447e9abeJean-Michel Trivi android.Manifest.permission.MODIFY_PHONE_STATE) 2083ccd654e9d4c38da0d652c442e7a2ca3f447e9abeJean-Michel Trivi != PackageManager.PERMISSION_GRANTED)) { 2084ccd654e9d4c38da0d652c442e7a2ca3f447e9abeJean-Michel Trivi Log.w(TAG, "MODIFY_PHONE_STATE Permission Denial: setMode(MODE_IN_CALL) from pid=" 2085ccd654e9d4c38da0d652c442e7a2ca3f447e9abeJean-Michel Trivi + Binder.getCallingPid() + ", uid=" + Binder.getCallingUid()); 2086ccd654e9d4c38da0d652c442e7a2ca3f447e9abeJean-Michel Trivi return; 2087ccd654e9d4c38da0d652c442e7a2ca3f447e9abeJean-Michel Trivi } 2088ccd654e9d4c38da0d652c442e7a2ca3f447e9abeJean-Michel Trivi 20898f677d66d9c3ba34c97e69b2bb9e161f129af0eeJean-Michel Trivi if (mode < AudioSystem.MODE_CURRENT || mode >= AudioSystem.NUM_MODES) { 2090a553c25b33c99b345cf1c8688f8df0ed8df14e5aEric Laurent return; 2091a553c25b33c99b345cf1c8688f8df0ed8df14e5aEric Laurent } 2092a553c25b33c99b345cf1c8688f8df0ed8df14e5aEric Laurent 2093d7454be47f4111c0478a502353e11dea401378bdEric Laurent int newModeOwnerPid = 0; 20949f103de83f2d5d472960dcf1401e95b2ab57a477Eric Laurent synchronized(mSetModeDeathHandlers) { 2095a553c25b33c99b345cf1c8688f8df0ed8df14e5aEric Laurent if (mode == AudioSystem.MODE_CURRENT) { 2096a553c25b33c99b345cf1c8688f8df0ed8df14e5aEric Laurent mode = mMode; 2097a553c25b33c99b345cf1c8688f8df0ed8df14e5aEric Laurent } 2098d7454be47f4111c0478a502353e11dea401378bdEric Laurent newModeOwnerPid = setModeInt(mode, cb, Binder.getCallingPid()); 20999f103de83f2d5d472960dcf1401e95b2ab57a477Eric Laurent } 21009f103de83f2d5d472960dcf1401e95b2ab57a477Eric Laurent // when entering RINGTONE, IN_CALL or IN_COMMUNICATION mode, clear all 21019f103de83f2d5d472960dcf1401e95b2ab57a477Eric Laurent // SCO connections not started by the application changing the mode 2102d7454be47f4111c0478a502353e11dea401378bdEric Laurent if (newModeOwnerPid != 0) { 2103d7454be47f4111c0478a502353e11dea401378bdEric Laurent disconnectBluetoothSco(newModeOwnerPid); 21049f103de83f2d5d472960dcf1401e95b2ab57a477Eric Laurent } 21059f103de83f2d5d472960dcf1401e95b2ab57a477Eric Laurent } 21062ade576148fe33c5ff6098d30ccfbcf28df70e8eJean-Michel Trivi 21079f103de83f2d5d472960dcf1401e95b2ab57a477Eric Laurent // must be called synchronized on mSetModeDeathHandlers 2108d7454be47f4111c0478a502353e11dea401378bdEric Laurent // setModeInt() returns a valid PID if the audio mode was successfully set to 21099f103de83f2d5d472960dcf1401e95b2ab57a477Eric Laurent // any mode other than NORMAL. 2110ccd654e9d4c38da0d652c442e7a2ca3f447e9abeJean-Michel Trivi private int setModeInt(int mode, IBinder cb, int pid) { 2111339567d5c91a8dc9228913ed1e5deb0ebb8a4a64Jean-Michel Trivi if (DEBUG_MODE) { Log.v(TAG, "setModeInt(mode=" + mode + ", pid=" + pid + ")"); } 2112d7454be47f4111c0478a502353e11dea401378bdEric Laurent int newModeOwnerPid = 0; 21139f103de83f2d5d472960dcf1401e95b2ab57a477Eric Laurent if (cb == null) { 21149f103de83f2d5d472960dcf1401e95b2ab57a477Eric Laurent Log.e(TAG, "setModeInt() called with null binder"); 2115d7454be47f4111c0478a502353e11dea401378bdEric Laurent return newModeOwnerPid; 21169f103de83f2d5d472960dcf1401e95b2ab57a477Eric Laurent } 21172ade576148fe33c5ff6098d30ccfbcf28df70e8eJean-Michel Trivi 21189f103de83f2d5d472960dcf1401e95b2ab57a477Eric Laurent SetModeDeathHandler hdlr = null; 21199f103de83f2d5d472960dcf1401e95b2ab57a477Eric Laurent Iterator iter = mSetModeDeathHandlers.iterator(); 21209f103de83f2d5d472960dcf1401e95b2ab57a477Eric Laurent while (iter.hasNext()) { 21219f103de83f2d5d472960dcf1401e95b2ab57a477Eric Laurent SetModeDeathHandler h = (SetModeDeathHandler)iter.next(); 21229f103de83f2d5d472960dcf1401e95b2ab57a477Eric Laurent if (h.getPid() == pid) { 21239f103de83f2d5d472960dcf1401e95b2ab57a477Eric Laurent hdlr = h; 21249f103de83f2d5d472960dcf1401e95b2ab57a477Eric Laurent // Remove from client list so that it is re-inserted at top of list 21259f103de83f2d5d472960dcf1401e95b2ab57a477Eric Laurent iter.remove(); 21269f103de83f2d5d472960dcf1401e95b2ab57a477Eric Laurent hdlr.getBinder().unlinkToDeath(hdlr, 0); 21279f103de83f2d5d472960dcf1401e95b2ab57a477Eric Laurent break; 21289f103de83f2d5d472960dcf1401e95b2ab57a477Eric Laurent } 21299f103de83f2d5d472960dcf1401e95b2ab57a477Eric Laurent } 21309f103de83f2d5d472960dcf1401e95b2ab57a477Eric Laurent int status = AudioSystem.AUDIO_STATUS_OK; 21319f103de83f2d5d472960dcf1401e95b2ab57a477Eric Laurent do { 21329f103de83f2d5d472960dcf1401e95b2ab57a477Eric Laurent if (mode == AudioSystem.MODE_NORMAL) { 21339f103de83f2d5d472960dcf1401e95b2ab57a477Eric Laurent // get new mode from client at top the list if any 21349f103de83f2d5d472960dcf1401e95b2ab57a477Eric Laurent if (!mSetModeDeathHandlers.isEmpty()) { 21359f103de83f2d5d472960dcf1401e95b2ab57a477Eric Laurent hdlr = mSetModeDeathHandlers.get(0); 21369f103de83f2d5d472960dcf1401e95b2ab57a477Eric Laurent cb = hdlr.getBinder(); 21379f103de83f2d5d472960dcf1401e95b2ab57a477Eric Laurent mode = hdlr.getMode(); 2138339567d5c91a8dc9228913ed1e5deb0ebb8a4a64Jean-Michel Trivi if (DEBUG_MODE) { 2139339567d5c91a8dc9228913ed1e5deb0ebb8a4a64Jean-Michel Trivi Log.w(TAG, " using mode=" + mode + " instead due to death hdlr at pid=" 2140339567d5c91a8dc9228913ed1e5deb0ebb8a4a64Jean-Michel Trivi + hdlr.mPid); 2141339567d5c91a8dc9228913ed1e5deb0ebb8a4a64Jean-Michel Trivi } 21429f103de83f2d5d472960dcf1401e95b2ab57a477Eric Laurent } 21439f103de83f2d5d472960dcf1401e95b2ab57a477Eric Laurent } else { 21449f103de83f2d5d472960dcf1401e95b2ab57a477Eric Laurent if (hdlr == null) { 21459f103de83f2d5d472960dcf1401e95b2ab57a477Eric Laurent hdlr = new SetModeDeathHandler(cb, pid); 21469f103de83f2d5d472960dcf1401e95b2ab57a477Eric Laurent } 21479f103de83f2d5d472960dcf1401e95b2ab57a477Eric Laurent // Register for client death notification 21489f103de83f2d5d472960dcf1401e95b2ab57a477Eric Laurent try { 21499f103de83f2d5d472960dcf1401e95b2ab57a477Eric Laurent cb.linkToDeath(hdlr, 0); 21509f103de83f2d5d472960dcf1401e95b2ab57a477Eric Laurent } catch (RemoteException e) { 21519f103de83f2d5d472960dcf1401e95b2ab57a477Eric Laurent // Client has died! 21529f103de83f2d5d472960dcf1401e95b2ab57a477Eric Laurent Log.w(TAG, "setMode() could not link to "+cb+" binder death"); 21539f103de83f2d5d472960dcf1401e95b2ab57a477Eric Laurent } 21549272b4b4a44fe1f33e3030810618194f817caaecEric Laurent 21559f103de83f2d5d472960dcf1401e95b2ab57a477Eric Laurent // Last client to call setMode() is always at top of client list 21569f103de83f2d5d472960dcf1401e95b2ab57a477Eric Laurent // as required by SetModeDeathHandler.binderDied() 21579f103de83f2d5d472960dcf1401e95b2ab57a477Eric Laurent mSetModeDeathHandlers.add(0, hdlr); 21589f103de83f2d5d472960dcf1401e95b2ab57a477Eric Laurent hdlr.setMode(mode); 21599f103de83f2d5d472960dcf1401e95b2ab57a477Eric Laurent } 21603def1eec2baed0b8845ec32c871e249dc533a9d9Eric Laurent 21619f103de83f2d5d472960dcf1401e95b2ab57a477Eric Laurent if (mode != mMode) { 21629f103de83f2d5d472960dcf1401e95b2ab57a477Eric Laurent status = AudioSystem.setPhoneState(mode); 21639f103de83f2d5d472960dcf1401e95b2ab57a477Eric Laurent if (status == AudioSystem.AUDIO_STATUS_OK) { 2164339567d5c91a8dc9228913ed1e5deb0ebb8a4a64Jean-Michel Trivi if (DEBUG_MODE) { Log.v(TAG, " mode successfully set to " + mode); } 21659f103de83f2d5d472960dcf1401e95b2ab57a477Eric Laurent mMode = mode; 21669f103de83f2d5d472960dcf1401e95b2ab57a477Eric Laurent } else { 21679f103de83f2d5d472960dcf1401e95b2ab57a477Eric Laurent if (hdlr != null) { 21689f103de83f2d5d472960dcf1401e95b2ab57a477Eric Laurent mSetModeDeathHandlers.remove(hdlr); 21699f103de83f2d5d472960dcf1401e95b2ab57a477Eric Laurent cb.unlinkToDeath(hdlr, 0); 21703def1eec2baed0b8845ec32c871e249dc533a9d9Eric Laurent } 21719f103de83f2d5d472960dcf1401e95b2ab57a477Eric Laurent // force reading new top of mSetModeDeathHandlers stack 2172339567d5c91a8dc9228913ed1e5deb0ebb8a4a64Jean-Michel Trivi if (DEBUG_MODE) { Log.w(TAG, " mode set to MODE_NORMAL after phoneState pb"); } 21739f103de83f2d5d472960dcf1401e95b2ab57a477Eric Laurent mode = AudioSystem.MODE_NORMAL; 2174b9c9d260f21b321527c4622a123af9767630d94dEric Laurent } 21759f103de83f2d5d472960dcf1401e95b2ab57a477Eric Laurent } else { 21769f103de83f2d5d472960dcf1401e95b2ab57a477Eric Laurent status = AudioSystem.AUDIO_STATUS_OK; 21779f103de83f2d5d472960dcf1401e95b2ab57a477Eric Laurent } 21789f103de83f2d5d472960dcf1401e95b2ab57a477Eric Laurent } while (status != AudioSystem.AUDIO_STATUS_OK && !mSetModeDeathHandlers.isEmpty()); 21799f103de83f2d5d472960dcf1401e95b2ab57a477Eric Laurent 21809f103de83f2d5d472960dcf1401e95b2ab57a477Eric Laurent if (status == AudioSystem.AUDIO_STATUS_OK) { 21819f103de83f2d5d472960dcf1401e95b2ab57a477Eric Laurent if (mode != AudioSystem.MODE_NORMAL) { 2182d7454be47f4111c0478a502353e11dea401378bdEric Laurent if (mSetModeDeathHandlers.isEmpty()) { 2183d7454be47f4111c0478a502353e11dea401378bdEric Laurent Log.e(TAG, "setMode() different from MODE_NORMAL with empty mode client stack"); 2184d7454be47f4111c0478a502353e11dea401378bdEric Laurent } else { 2185d7454be47f4111c0478a502353e11dea401378bdEric Laurent newModeOwnerPid = mSetModeDeathHandlers.get(0).getPid(); 2186d7454be47f4111c0478a502353e11dea401378bdEric Laurent } 21879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 21889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int streamType = getActiveStreamType(AudioManager.USE_DEFAULT_STREAM_TYPE); 21899bc8358ddaa01c3490f9709991989633a6a3dd42Eric Laurent int device = getDeviceForStream(streamType); 219042b041ed4f184e3af7f788eb07307f556a2a6616Eric Laurent int index = mStreamStates[mStreamVolumeAlias[streamType]].getIndex(device); 219142b041ed4f184e3af7f788eb07307f556a2a6616Eric Laurent setStreamVolumeInt(mStreamVolumeAlias[streamType], index, device, true); 21926d5176638c2189595cede38fb92c3e7e8700e221Eric Laurent 21936d5176638c2189595cede38fb92c3e7e8700e221Eric Laurent updateStreamVolumeAlias(true /*updateVolumes*/); 21949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2195d7454be47f4111c0478a502353e11dea401378bdEric Laurent return newModeOwnerPid; 21969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 21979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 21989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** @see AudioManager#getMode() */ 21999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public int getMode() { 22009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return mMode; 22019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 22029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2203e78fced559d879b2e37b610d0d9a89daf08f0f2bEric Laurent //========================================================================================== 2204e78fced559d879b2e37b610d0d9a89daf08f0f2bEric Laurent // Sound Effects 2205e78fced559d879b2e37b610d0d9a89daf08f0f2bEric Laurent //========================================================================================== 2206e78fced559d879b2e37b610d0d9a89daf08f0f2bEric Laurent 2207e78fced559d879b2e37b610d0d9a89daf08f0f2bEric Laurent private static final String TAG_AUDIO_ASSETS = "audio_assets"; 2208e78fced559d879b2e37b610d0d9a89daf08f0f2bEric Laurent private static final String ATTR_VERSION = "version"; 2209e78fced559d879b2e37b610d0d9a89daf08f0f2bEric Laurent private static final String TAG_GROUP = "group"; 2210e78fced559d879b2e37b610d0d9a89daf08f0f2bEric Laurent private static final String ATTR_GROUP_NAME = "name"; 2211e78fced559d879b2e37b610d0d9a89daf08f0f2bEric Laurent private static final String TAG_ASSET = "asset"; 2212e78fced559d879b2e37b610d0d9a89daf08f0f2bEric Laurent private static final String ATTR_ASSET_ID = "id"; 2213e78fced559d879b2e37b610d0d9a89daf08f0f2bEric Laurent private static final String ATTR_ASSET_FILE = "file"; 2214e78fced559d879b2e37b610d0d9a89daf08f0f2bEric Laurent 2215e78fced559d879b2e37b610d0d9a89daf08f0f2bEric Laurent private static final String ASSET_FILE_VERSION = "1.0"; 2216e78fced559d879b2e37b610d0d9a89daf08f0f2bEric Laurent private static final String GROUP_TOUCH_SOUNDS = "touch_sounds"; 2217e78fced559d879b2e37b610d0d9a89daf08f0f2bEric Laurent 2218167d1a27713ab64cd3c0aa70de96434083ef0400Glenn Kasten private static final int SOUND_EFFECTS_LOAD_TIMEOUT_MS = 5000; 22195d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent 22205d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent class LoadSoundEffectReply { 22215d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent public int mStatus = 1; 22225d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent }; 22235d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent 2224e78fced559d879b2e37b610d0d9a89daf08f0f2bEric Laurent private void loadTouchSoundAssetDefaults() { 2225e78fced559d879b2e37b610d0d9a89daf08f0f2bEric Laurent SOUND_EFFECT_FILES.add("Effect_Tick.ogg"); 2226e78fced559d879b2e37b610d0d9a89daf08f0f2bEric Laurent for (int i = 0; i < AudioManager.NUM_SOUND_EFFECTS; i++) { 2227e78fced559d879b2e37b610d0d9a89daf08f0f2bEric Laurent SOUND_EFFECT_FILES_MAP[i][0] = 0; 2228e78fced559d879b2e37b610d0d9a89daf08f0f2bEric Laurent SOUND_EFFECT_FILES_MAP[i][1] = -1; 2229e78fced559d879b2e37b610d0d9a89daf08f0f2bEric Laurent } 2230e78fced559d879b2e37b610d0d9a89daf08f0f2bEric Laurent } 2231e78fced559d879b2e37b610d0d9a89daf08f0f2bEric Laurent 2232e78fced559d879b2e37b610d0d9a89daf08f0f2bEric Laurent private void loadTouchSoundAssets() { 2233e78fced559d879b2e37b610d0d9a89daf08f0f2bEric Laurent XmlResourceParser parser = null; 2234e78fced559d879b2e37b610d0d9a89daf08f0f2bEric Laurent 22355d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent // only load assets once. 22365d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent if (!SOUND_EFFECT_FILES.isEmpty()) { 22375d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent return; 22385d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent } 22395d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent 2240e78fced559d879b2e37b610d0d9a89daf08f0f2bEric Laurent loadTouchSoundAssetDefaults(); 2241e78fced559d879b2e37b610d0d9a89daf08f0f2bEric Laurent 2242e78fced559d879b2e37b610d0d9a89daf08f0f2bEric Laurent try { 2243e78fced559d879b2e37b610d0d9a89daf08f0f2bEric Laurent parser = mContext.getResources().getXml(com.android.internal.R.xml.audio_assets); 2244e78fced559d879b2e37b610d0d9a89daf08f0f2bEric Laurent 2245e78fced559d879b2e37b610d0d9a89daf08f0f2bEric Laurent XmlUtils.beginDocument(parser, TAG_AUDIO_ASSETS); 2246e78fced559d879b2e37b610d0d9a89daf08f0f2bEric Laurent String version = parser.getAttributeValue(null, ATTR_VERSION); 2247e78fced559d879b2e37b610d0d9a89daf08f0f2bEric Laurent boolean inTouchSoundsGroup = false; 2248e78fced559d879b2e37b610d0d9a89daf08f0f2bEric Laurent 2249e78fced559d879b2e37b610d0d9a89daf08f0f2bEric Laurent if (ASSET_FILE_VERSION.equals(version)) { 2250e78fced559d879b2e37b610d0d9a89daf08f0f2bEric Laurent while (true) { 2251e78fced559d879b2e37b610d0d9a89daf08f0f2bEric Laurent XmlUtils.nextElement(parser); 2252e78fced559d879b2e37b610d0d9a89daf08f0f2bEric Laurent String element = parser.getName(); 2253e78fced559d879b2e37b610d0d9a89daf08f0f2bEric Laurent if (element == null) { 2254e78fced559d879b2e37b610d0d9a89daf08f0f2bEric Laurent break; 2255e78fced559d879b2e37b610d0d9a89daf08f0f2bEric Laurent } 2256e78fced559d879b2e37b610d0d9a89daf08f0f2bEric Laurent if (element.equals(TAG_GROUP)) { 2257e78fced559d879b2e37b610d0d9a89daf08f0f2bEric Laurent String name = parser.getAttributeValue(null, ATTR_GROUP_NAME); 2258e78fced559d879b2e37b610d0d9a89daf08f0f2bEric Laurent if (GROUP_TOUCH_SOUNDS.equals(name)) { 2259e78fced559d879b2e37b610d0d9a89daf08f0f2bEric Laurent inTouchSoundsGroup = true; 2260e78fced559d879b2e37b610d0d9a89daf08f0f2bEric Laurent break; 2261e78fced559d879b2e37b610d0d9a89daf08f0f2bEric Laurent } 2262e78fced559d879b2e37b610d0d9a89daf08f0f2bEric Laurent } 2263e78fced559d879b2e37b610d0d9a89daf08f0f2bEric Laurent } 2264e78fced559d879b2e37b610d0d9a89daf08f0f2bEric Laurent while (inTouchSoundsGroup) { 2265e78fced559d879b2e37b610d0d9a89daf08f0f2bEric Laurent XmlUtils.nextElement(parser); 2266e78fced559d879b2e37b610d0d9a89daf08f0f2bEric Laurent String element = parser.getName(); 2267e78fced559d879b2e37b610d0d9a89daf08f0f2bEric Laurent if (element == null) { 2268e78fced559d879b2e37b610d0d9a89daf08f0f2bEric Laurent break; 2269e78fced559d879b2e37b610d0d9a89daf08f0f2bEric Laurent } 2270e78fced559d879b2e37b610d0d9a89daf08f0f2bEric Laurent if (element.equals(TAG_ASSET)) { 2271e78fced559d879b2e37b610d0d9a89daf08f0f2bEric Laurent String id = parser.getAttributeValue(null, ATTR_ASSET_ID); 2272e78fced559d879b2e37b610d0d9a89daf08f0f2bEric Laurent String file = parser.getAttributeValue(null, ATTR_ASSET_FILE); 2273e78fced559d879b2e37b610d0d9a89daf08f0f2bEric Laurent int fx; 2274e78fced559d879b2e37b610d0d9a89daf08f0f2bEric Laurent 2275e78fced559d879b2e37b610d0d9a89daf08f0f2bEric Laurent try { 2276e78fced559d879b2e37b610d0d9a89daf08f0f2bEric Laurent Field field = AudioManager.class.getField(id); 2277e78fced559d879b2e37b610d0d9a89daf08f0f2bEric Laurent fx = field.getInt(null); 2278e78fced559d879b2e37b610d0d9a89daf08f0f2bEric Laurent } catch (Exception e) { 2279e78fced559d879b2e37b610d0d9a89daf08f0f2bEric Laurent Log.w(TAG, "Invalid touch sound ID: "+id); 2280e78fced559d879b2e37b610d0d9a89daf08f0f2bEric Laurent continue; 2281e78fced559d879b2e37b610d0d9a89daf08f0f2bEric Laurent } 2282e78fced559d879b2e37b610d0d9a89daf08f0f2bEric Laurent 2283e78fced559d879b2e37b610d0d9a89daf08f0f2bEric Laurent int i = SOUND_EFFECT_FILES.indexOf(file); 2284e78fced559d879b2e37b610d0d9a89daf08f0f2bEric Laurent if (i == -1) { 2285e78fced559d879b2e37b610d0d9a89daf08f0f2bEric Laurent i = SOUND_EFFECT_FILES.size(); 2286e78fced559d879b2e37b610d0d9a89daf08f0f2bEric Laurent SOUND_EFFECT_FILES.add(file); 2287e78fced559d879b2e37b610d0d9a89daf08f0f2bEric Laurent } 2288e78fced559d879b2e37b610d0d9a89daf08f0f2bEric Laurent SOUND_EFFECT_FILES_MAP[fx][0] = i; 2289e78fced559d879b2e37b610d0d9a89daf08f0f2bEric Laurent } else { 2290e78fced559d879b2e37b610d0d9a89daf08f0f2bEric Laurent break; 2291e78fced559d879b2e37b610d0d9a89daf08f0f2bEric Laurent } 2292e78fced559d879b2e37b610d0d9a89daf08f0f2bEric Laurent } 2293e78fced559d879b2e37b610d0d9a89daf08f0f2bEric Laurent } 2294e78fced559d879b2e37b610d0d9a89daf08f0f2bEric Laurent } catch (Resources.NotFoundException e) { 2295e78fced559d879b2e37b610d0d9a89daf08f0f2bEric Laurent Log.w(TAG, "audio assets file not found", e); 2296e78fced559d879b2e37b610d0d9a89daf08f0f2bEric Laurent } catch (XmlPullParserException e) { 2297e78fced559d879b2e37b610d0d9a89daf08f0f2bEric Laurent Log.w(TAG, "XML parser exception reading touch sound assets", e); 2298e78fced559d879b2e37b610d0d9a89daf08f0f2bEric Laurent } catch (IOException e) { 2299e78fced559d879b2e37b610d0d9a89daf08f0f2bEric Laurent Log.w(TAG, "I/O exception reading touch sound assets", e); 2300e78fced559d879b2e37b610d0d9a89daf08f0f2bEric Laurent } finally { 2301e78fced559d879b2e37b610d0d9a89daf08f0f2bEric Laurent if (parser != null) { 2302e78fced559d879b2e37b610d0d9a89daf08f0f2bEric Laurent parser.close(); 2303e78fced559d879b2e37b610d0d9a89daf08f0f2bEric Laurent } 2304e78fced559d879b2e37b610d0d9a89daf08f0f2bEric Laurent } 2305e78fced559d879b2e37b610d0d9a89daf08f0f2bEric Laurent } 2306e78fced559d879b2e37b610d0d9a89daf08f0f2bEric Laurent 23079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** @see AudioManager#playSoundEffect(int) */ 23089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public void playSoundEffect(int effectType) { 23095d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent playSoundEffectVolume(effectType, -1.0f); 23109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 23119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 23129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** @see AudioManager#playSoundEffect(int, float) */ 23139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public void playSoundEffectVolume(int effectType, float volume) { 2314559c76dbc37ff25b204ed1f060d3ec2fa43d718cNatalie Silvanovich if (effectType >= AudioManager.NUM_SOUND_EFFECTS || effectType < 0) { 2315559c76dbc37ff25b204ed1f060d3ec2fa43d718cNatalie Silvanovich Log.w(TAG, "AudioService effectType value " + effectType + " out of range"); 2316559c76dbc37ff25b204ed1f060d3ec2fa43d718cNatalie Silvanovich return; 2317559c76dbc37ff25b204ed1f060d3ec2fa43d718cNatalie Silvanovich } 2318559c76dbc37ff25b204ed1f060d3ec2fa43d718cNatalie Silvanovich 23195d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent sendMsg(mAudioHandler, MSG_PLAY_SOUND_EFFECT, SENDMSG_QUEUE, 23209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project effectType, (int) (volume * 1000), null, 0); 23219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 23229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 23239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 23249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Loads samples into the soundpool. 23255c17a820f9e46e0756c11795b3e6f89105f2f539Glenn Kasten * This method must be called at first when sound effects are enabled 23269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 23279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public boolean loadSoundEffects() { 23285d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent int attempts = 3; 23295d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent LoadSoundEffectReply reply = new LoadSoundEffectReply(); 2330117b7bb5b5a4457711f59bde3dcc83d8f111c524Eric Laurent 23315d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent synchronized (reply) { 23325d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent sendMsg(mAudioHandler, MSG_LOAD_SOUND_EFFECTS, SENDMSG_QUEUE, 0, 0, reply, 0); 23335d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent while ((reply.mStatus == 1) && (attempts-- > 0)) { 2334117b7bb5b5a4457711f59bde3dcc83d8f111c524Eric Laurent try { 2335167d1a27713ab64cd3c0aa70de96434083ef0400Glenn Kasten reply.wait(SOUND_EFFECTS_LOAD_TIMEOUT_MS); 23365d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent } catch (InterruptedException e) { 23375d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent Log.w(TAG, "loadSoundEffects Interrupted while waiting sound pool loaded."); 2338117b7bb5b5a4457711f59bde3dcc83d8f111c524Eric Laurent } 2339a60e212d0dda7d2a748180ce77405f2463c9cf53Eric Laurent } 23409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 23415d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent return (reply.mStatus == 0); 23429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 23439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 23449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 23459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Unloads samples from the sound pool. 23469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * This method can be called to free some memory when 23479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * sound effects are disabled. 23489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 23499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public void unloadSoundEffects() { 23505d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent sendMsg(mAudioHandler, MSG_UNLOAD_SOUND_EFFECTS, SENDMSG_QUEUE, 0, 0, null, 0); 23519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 23529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2353a60e212d0dda7d2a748180ce77405f2463c9cf53Eric Laurent class SoundPoolListenerThread extends Thread { 2354a60e212d0dda7d2a748180ce77405f2463c9cf53Eric Laurent public SoundPoolListenerThread() { 2355a60e212d0dda7d2a748180ce77405f2463c9cf53Eric Laurent super("SoundPoolListenerThread"); 2356a60e212d0dda7d2a748180ce77405f2463c9cf53Eric Laurent } 2357a60e212d0dda7d2a748180ce77405f2463c9cf53Eric Laurent 2358a60e212d0dda7d2a748180ce77405f2463c9cf53Eric Laurent @Override 2359a60e212d0dda7d2a748180ce77405f2463c9cf53Eric Laurent public void run() { 2360a60e212d0dda7d2a748180ce77405f2463c9cf53Eric Laurent 2361a60e212d0dda7d2a748180ce77405f2463c9cf53Eric Laurent Looper.prepare(); 2362a60e212d0dda7d2a748180ce77405f2463c9cf53Eric Laurent mSoundPoolLooper = Looper.myLooper(); 2363a60e212d0dda7d2a748180ce77405f2463c9cf53Eric Laurent 2364a60e212d0dda7d2a748180ce77405f2463c9cf53Eric Laurent synchronized (mSoundEffectsLock) { 2365a60e212d0dda7d2a748180ce77405f2463c9cf53Eric Laurent if (mSoundPool != null) { 2366a60e212d0dda7d2a748180ce77405f2463c9cf53Eric Laurent mSoundPoolCallBack = new SoundPoolCallback(); 2367a60e212d0dda7d2a748180ce77405f2463c9cf53Eric Laurent mSoundPool.setOnLoadCompleteListener(mSoundPoolCallBack); 2368a60e212d0dda7d2a748180ce77405f2463c9cf53Eric Laurent } 2369a60e212d0dda7d2a748180ce77405f2463c9cf53Eric Laurent mSoundEffectsLock.notify(); 2370a60e212d0dda7d2a748180ce77405f2463c9cf53Eric Laurent } 2371a60e212d0dda7d2a748180ce77405f2463c9cf53Eric Laurent Looper.loop(); 2372a60e212d0dda7d2a748180ce77405f2463c9cf53Eric Laurent } 2373a60e212d0dda7d2a748180ce77405f2463c9cf53Eric Laurent } 2374a60e212d0dda7d2a748180ce77405f2463c9cf53Eric Laurent 2375a60e212d0dda7d2a748180ce77405f2463c9cf53Eric Laurent private final class SoundPoolCallback implements 2376a60e212d0dda7d2a748180ce77405f2463c9cf53Eric Laurent android.media.SoundPool.OnLoadCompleteListener { 2377a60e212d0dda7d2a748180ce77405f2463c9cf53Eric Laurent 23785d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent int mStatus = 1; // 1 means neither error nor last sample loaded yet 23795d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent List<Integer> mSamples = new ArrayList<Integer>(); 2380a60e212d0dda7d2a748180ce77405f2463c9cf53Eric Laurent 2381a60e212d0dda7d2a748180ce77405f2463c9cf53Eric Laurent public int status() { 2382a60e212d0dda7d2a748180ce77405f2463c9cf53Eric Laurent return mStatus; 2383a60e212d0dda7d2a748180ce77405f2463c9cf53Eric Laurent } 2384a60e212d0dda7d2a748180ce77405f2463c9cf53Eric Laurent 23855d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent public void setSamples(int[] samples) { 23865d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent for (int i = 0; i < samples.length; i++) { 23875d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent // do not wait ack for samples rejected upfront by SoundPool 23885d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent if (samples[i] > 0) { 23895d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent mSamples.add(samples[i]); 23905d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent } 23915d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent } 2392a60e212d0dda7d2a748180ce77405f2463c9cf53Eric Laurent } 2393a60e212d0dda7d2a748180ce77405f2463c9cf53Eric Laurent 2394a60e212d0dda7d2a748180ce77405f2463c9cf53Eric Laurent public void onLoadComplete(SoundPool soundPool, int sampleId, int status) { 2395a60e212d0dda7d2a748180ce77405f2463c9cf53Eric Laurent synchronized (mSoundEffectsLock) { 23965d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent int i = mSamples.indexOf(sampleId); 23975d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent if (i >= 0) { 23985d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent mSamples.remove(i); 2399a60e212d0dda7d2a748180ce77405f2463c9cf53Eric Laurent } 24005d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent if ((status != 0) || mSamples. isEmpty()) { 24015d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent mStatus = status; 2402a60e212d0dda7d2a748180ce77405f2463c9cf53Eric Laurent mSoundEffectsLock.notify(); 2403a60e212d0dda7d2a748180ce77405f2463c9cf53Eric Laurent } 2404a60e212d0dda7d2a748180ce77405f2463c9cf53Eric Laurent } 2405a60e212d0dda7d2a748180ce77405f2463c9cf53Eric Laurent } 2406a60e212d0dda7d2a748180ce77405f2463c9cf53Eric Laurent } 2407a60e212d0dda7d2a748180ce77405f2463c9cf53Eric Laurent 24084050c93601b3c3609b21cc1e18a29b64747e7fa9Eric Laurent /** @see AudioManager#reloadAudioSettings() */ 24094050c93601b3c3609b21cc1e18a29b64747e7fa9Eric Laurent public void reloadAudioSettings() { 2410bc0fab1fc2db832ef86d8a33466ec4d68b103ca0Eric Laurent readAudioSettings(false /*userSwitch*/); 2411bc0fab1fc2db832ef86d8a33466ec4d68b103ca0Eric Laurent } 2412bc0fab1fc2db832ef86d8a33466ec4d68b103ca0Eric Laurent 2413bc0fab1fc2db832ef86d8a33466ec4d68b103ca0Eric Laurent private void readAudioSettings(boolean userSwitch) { 24144050c93601b3c3609b21cc1e18a29b64747e7fa9Eric Laurent // restore ringer mode, ringer mode affected streams, mute affected streams and vibrate settings 24154050c93601b3c3609b21cc1e18a29b64747e7fa9Eric Laurent readPersistedSettings(); 24164050c93601b3c3609b21cc1e18a29b64747e7fa9Eric Laurent 24174050c93601b3c3609b21cc1e18a29b64747e7fa9Eric Laurent // restore volume settings 24184050c93601b3c3609b21cc1e18a29b64747e7fa9Eric Laurent int numStreamTypes = AudioSystem.getNumStreamTypes(); 24194050c93601b3c3609b21cc1e18a29b64747e7fa9Eric Laurent for (int streamType = 0; streamType < numStreamTypes; streamType++) { 24204050c93601b3c3609b21cc1e18a29b64747e7fa9Eric Laurent VolumeStreamState streamState = mStreamStates[streamType]; 24214050c93601b3c3609b21cc1e18a29b64747e7fa9Eric Laurent 2422bc0fab1fc2db832ef86d8a33466ec4d68b103ca0Eric Laurent if (userSwitch && mStreamVolumeAlias[streamType] == AudioSystem.STREAM_MUSIC) { 2423bc0fab1fc2db832ef86d8a33466ec4d68b103ca0Eric Laurent continue; 2424bc0fab1fc2db832ef86d8a33466ec4d68b103ca0Eric Laurent } 2425bc0fab1fc2db832ef86d8a33466ec4d68b103ca0Eric Laurent 24268fa4d6f585f40ff5cf5f9bed316d92c64a306f21Eric Laurent streamState.readSettings(); 24278fa4d6f585f40ff5cf5f9bed316d92c64a306f21Eric Laurent synchronized (VolumeStreamState.class) { 24283172d5e3e7520a745fa37b71fc1c7bf244b57085Eric Laurent // unmute stream that was muted but is not affect by mute anymore 24298fa4d6f585f40ff5cf5f9bed316d92c64a306f21Eric Laurent if (streamState.isMuted_syncVSS() && ((!isStreamAffectedByMute(streamType) && 243083a017b6b7c099d1a0293e5839be6477325aef06Eric Laurent !isStreamMutedByRingerMode(streamType)) || mUseFixedVolume)) { 24313172d5e3e7520a745fa37b71fc1c7bf244b57085Eric Laurent int size = streamState.mDeathHandlers.size(); 24323172d5e3e7520a745fa37b71fc1c7bf244b57085Eric Laurent for (int i = 0; i < size; i++) { 24333172d5e3e7520a745fa37b71fc1c7bf244b57085Eric Laurent streamState.mDeathHandlers.get(i).mMuteCount = 1; 24348fa4d6f585f40ff5cf5f9bed316d92c64a306f21Eric Laurent streamState.mDeathHandlers.get(i).mute_syncVSS(false); 24353172d5e3e7520a745fa37b71fc1c7bf244b57085Eric Laurent } 24363172d5e3e7520a745fa37b71fc1c7bf244b57085Eric Laurent } 24374050c93601b3c3609b21cc1e18a29b64747e7fa9Eric Laurent } 24384050c93601b3c3609b21cc1e18a29b64747e7fa9Eric Laurent } 24394050c93601b3c3609b21cc1e18a29b64747e7fa9Eric Laurent 244033902db75011d863009585682bd08560c5b89a75Eric Laurent // apply new ringer mode before checking volume for alias streams so that streams 244133902db75011d863009585682bd08560c5b89a75Eric Laurent // muted by ringer mode have the correct volume 2442661f2cf45860d2e10924e6b69966a9afe255f28bJohn Spurlock setRingerModeInt(getRingerModeInternal(), false); 244333902db75011d863009585682bd08560c5b89a75Eric Laurent 2444212532b58e3b17d7e9d6e1361946d909d4e372c2Eric Laurent checkAllFixedVolumeDevices(); 2445244820185269991186d07068b92985624cede4a5Eric Laurent checkAllAliasStreamVolumes(); 2446244820185269991186d07068b92985624cede4a5Eric Laurent 2447d640bd325c3be9a350058c835b880a7e0b40dc60Eric Laurent synchronized (mSafeMediaVolumeState) { 2448aa5ee4d65f8788e2a0afcd198367450853fd72acJohn Spurlock mMusicActiveMs = MathUtils.constrain(Settings.Secure.getIntForUser(mContentResolver, 2449aa5ee4d65f8788e2a0afcd198367450853fd72acJohn Spurlock Settings.Secure.UNSAFE_VOLUME_MUSIC_ACTIVE_MS, 0, UserHandle.USER_CURRENT), 2450aa5ee4d65f8788e2a0afcd198367450853fd72acJohn Spurlock 0, UNSAFE_VOLUME_MUSIC_ACTIVE_MS_MAX); 2451d640bd325c3be9a350058c835b880a7e0b40dc60Eric Laurent if (mSafeMediaVolumeState == SAFE_MEDIA_VOLUME_ACTIVE) { 2452f1a457d06c53a901ea08d2d3fb6e766bc06c4d4fEric Laurent enforceSafeMediaVolume(); 2453f1a457d06c53a901ea08d2d3fb6e766bc06c4d4fEric Laurent } 2454c34dcc1e1ebf152bb400abbb8bc25f7dc0c3ba97Eric Laurent } 24554050c93601b3c3609b21cc1e18a29b64747e7fa9Eric Laurent } 24564050c93601b3c3609b21cc1e18a29b64747e7fa9Eric Laurent 2457961cae92540763226648813d111c5b5c3b0f1597Dianne Hackborn /** @see AudioManager#setSpeakerphoneOn(boolean) */ 2458c42ac9d4d03f62c3a1ba197a28a81fda44bd8b7fEric Laurent public void setSpeakerphoneOn(boolean on){ 2459dc1d17a1dbfc2ae01c20012133a836b62f5b6930Eric Laurent if (!checkAudioSettingsPermission("setSpeakerphoneOn()")) { 2460dc1d17a1dbfc2ae01c20012133a836b62f5b6930Eric Laurent return; 2461dc1d17a1dbfc2ae01c20012133a836b62f5b6930Eric Laurent } 24627337bee7839238f244fad31112a45389f6ef907cJohan Gustavsson 24637337bee7839238f244fad31112a45389f6ef907cJohan Gustavsson if (on) { 24647337bee7839238f244fad31112a45389f6ef907cJohan Gustavsson if (mForcedUseForComm == AudioSystem.FORCE_BT_SCO) { 24657337bee7839238f244fad31112a45389f6ef907cJohan Gustavsson sendMsg(mAudioHandler, MSG_SET_FORCE_USE, SENDMSG_QUEUE, 24667337bee7839238f244fad31112a45389f6ef907cJohan Gustavsson AudioSystem.FOR_RECORD, AudioSystem.FORCE_NONE, null, 0); 24677337bee7839238f244fad31112a45389f6ef907cJohan Gustavsson } 24687337bee7839238f244fad31112a45389f6ef907cJohan Gustavsson mForcedUseForComm = AudioSystem.FORCE_SPEAKER; 24697337bee7839238f244fad31112a45389f6ef907cJohan Gustavsson } else if (mForcedUseForComm == AudioSystem.FORCE_SPEAKER){ 24707337bee7839238f244fad31112a45389f6ef907cJohan Gustavsson mForcedUseForComm = AudioSystem.FORCE_NONE; 24717337bee7839238f244fad31112a45389f6ef907cJohan Gustavsson } 2472fa640154f1f42121d81242b2f1a10f03e52f0014Eric Laurent 2473afbb047c3945e9c2b7e9bc6b25098d5fb80bba4eEric Laurent sendMsg(mAudioHandler, MSG_SET_FORCE_USE, SENDMSG_QUEUE, 2474fa640154f1f42121d81242b2f1a10f03e52f0014Eric Laurent AudioSystem.FOR_COMMUNICATION, mForcedUseForComm, null, 0); 2475c42ac9d4d03f62c3a1ba197a28a81fda44bd8b7fEric Laurent } 2476c42ac9d4d03f62c3a1ba197a28a81fda44bd8b7fEric Laurent 2477c42ac9d4d03f62c3a1ba197a28a81fda44bd8b7fEric Laurent /** @see AudioManager#isSpeakerphoneOn() */ 2478c42ac9d4d03f62c3a1ba197a28a81fda44bd8b7fEric Laurent public boolean isSpeakerphoneOn() { 2479fa640154f1f42121d81242b2f1a10f03e52f0014Eric Laurent return (mForcedUseForComm == AudioSystem.FORCE_SPEAKER); 2480c42ac9d4d03f62c3a1ba197a28a81fda44bd8b7fEric Laurent } 2481c42ac9d4d03f62c3a1ba197a28a81fda44bd8b7fEric Laurent 2482961cae92540763226648813d111c5b5c3b0f1597Dianne Hackborn /** @see AudioManager#setBluetoothScoOn(boolean) */ 2483c42ac9d4d03f62c3a1ba197a28a81fda44bd8b7fEric Laurent public void setBluetoothScoOn(boolean on){ 2484dc1d17a1dbfc2ae01c20012133a836b62f5b6930Eric Laurent if (!checkAudioSettingsPermission("setBluetoothScoOn()")) { 2485dc1d17a1dbfc2ae01c20012133a836b62f5b6930Eric Laurent return; 2486dc1d17a1dbfc2ae01c20012133a836b62f5b6930Eric Laurent } 24877337bee7839238f244fad31112a45389f6ef907cJohan Gustavsson 24887337bee7839238f244fad31112a45389f6ef907cJohan Gustavsson if (on) { 24897337bee7839238f244fad31112a45389f6ef907cJohan Gustavsson mForcedUseForComm = AudioSystem.FORCE_BT_SCO; 24907337bee7839238f244fad31112a45389f6ef907cJohan Gustavsson } else if (mForcedUseForComm == AudioSystem.FORCE_BT_SCO) { 24917337bee7839238f244fad31112a45389f6ef907cJohan Gustavsson mForcedUseForComm = AudioSystem.FORCE_NONE; 24927337bee7839238f244fad31112a45389f6ef907cJohan Gustavsson } 2493fa640154f1f42121d81242b2f1a10f03e52f0014Eric Laurent 2494afbb047c3945e9c2b7e9bc6b25098d5fb80bba4eEric Laurent sendMsg(mAudioHandler, MSG_SET_FORCE_USE, SENDMSG_QUEUE, 2495fa640154f1f42121d81242b2f1a10f03e52f0014Eric Laurent AudioSystem.FOR_COMMUNICATION, mForcedUseForComm, null, 0); 2496afbb047c3945e9c2b7e9bc6b25098d5fb80bba4eEric Laurent sendMsg(mAudioHandler, MSG_SET_FORCE_USE, SENDMSG_QUEUE, 2497fa640154f1f42121d81242b2f1a10f03e52f0014Eric Laurent AudioSystem.FOR_RECORD, mForcedUseForComm, null, 0); 2498c42ac9d4d03f62c3a1ba197a28a81fda44bd8b7fEric Laurent } 2499c42ac9d4d03f62c3a1ba197a28a81fda44bd8b7fEric Laurent 2500c42ac9d4d03f62c3a1ba197a28a81fda44bd8b7fEric Laurent /** @see AudioManager#isBluetoothScoOn() */ 2501c42ac9d4d03f62c3a1ba197a28a81fda44bd8b7fEric Laurent public boolean isBluetoothScoOn() { 2502fa640154f1f42121d81242b2f1a10f03e52f0014Eric Laurent return (mForcedUseForComm == AudioSystem.FORCE_BT_SCO); 2503c42ac9d4d03f62c3a1ba197a28a81fda44bd8b7fEric Laurent } 2504c42ac9d4d03f62c3a1ba197a28a81fda44bd8b7fEric Laurent 2505961cae92540763226648813d111c5b5c3b0f1597Dianne Hackborn /** @see AudioManager#setBluetoothA2dpOn(boolean) */ 25067847211fb4699bf6018e29d214a918ed6657319bEric Laurent public void setBluetoothA2dpOn(boolean on) { 2507c390bed06b4a572e273ead1254da9a932e04dce3Eric Laurent synchronized (mBluetoothA2dpEnabledLock) { 2508c390bed06b4a572e273ead1254da9a932e04dce3Eric Laurent mBluetoothA2dpEnabled = on; 2509c390bed06b4a572e273ead1254da9a932e04dce3Eric Laurent sendMsg(mAudioHandler, MSG_SET_FORCE_BT_A2DP_USE, SENDMSG_QUEUE, 2510c390bed06b4a572e273ead1254da9a932e04dce3Eric Laurent AudioSystem.FOR_MEDIA, 2511c390bed06b4a572e273ead1254da9a932e04dce3Eric Laurent mBluetoothA2dpEnabled ? AudioSystem.FORCE_NONE : AudioSystem.FORCE_NO_BT_A2DP, 2512c390bed06b4a572e273ead1254da9a932e04dce3Eric Laurent null, 0); 2513c390bed06b4a572e273ead1254da9a932e04dce3Eric Laurent } 25147847211fb4699bf6018e29d214a918ed6657319bEric Laurent } 25157847211fb4699bf6018e29d214a918ed6657319bEric Laurent 25167847211fb4699bf6018e29d214a918ed6657319bEric Laurent /** @see AudioManager#isBluetoothA2dpOn() */ 25177847211fb4699bf6018e29d214a918ed6657319bEric Laurent public boolean isBluetoothA2dpOn() { 25187847211fb4699bf6018e29d214a918ed6657319bEric Laurent synchronized (mBluetoothA2dpEnabledLock) { 25197847211fb4699bf6018e29d214a918ed6657319bEric Laurent return mBluetoothA2dpEnabled; 25207847211fb4699bf6018e29d214a918ed6657319bEric Laurent } 25217847211fb4699bf6018e29d214a918ed6657319bEric Laurent } 25227847211fb4699bf6018e29d214a918ed6657319bEric Laurent 25233def1eec2baed0b8845ec32c871e249dc533a9d9Eric Laurent /** @see AudioManager#startBluetoothSco() */ 252483900754f357616b9e56eaf7fc85f49b8906e987Eric Laurent public void startBluetoothSco(IBinder cb, int targetSdkVersion) { 252583900754f357616b9e56eaf7fc85f49b8906e987Eric Laurent int scoAudioMode = 252683900754f357616b9e56eaf7fc85f49b8906e987Eric Laurent (targetSdkVersion < Build.VERSION_CODES.JELLY_BEAN_MR2) ? 2527f4e51d82d2e34e6832903f01eaecc15ded6c3241Liejun Tao SCO_MODE_VIRTUAL_CALL : SCO_MODE_UNDEFINED; 252883900754f357616b9e56eaf7fc85f49b8906e987Eric Laurent startBluetoothScoInt(cb, scoAudioMode); 252983900754f357616b9e56eaf7fc85f49b8906e987Eric Laurent } 253083900754f357616b9e56eaf7fc85f49b8906e987Eric Laurent 253183900754f357616b9e56eaf7fc85f49b8906e987Eric Laurent /** @see AudioManager#startBluetoothScoVirtualCall() */ 253283900754f357616b9e56eaf7fc85f49b8906e987Eric Laurent public void startBluetoothScoVirtualCall(IBinder cb) { 253383900754f357616b9e56eaf7fc85f49b8906e987Eric Laurent startBluetoothScoInt(cb, SCO_MODE_VIRTUAL_CALL); 253483900754f357616b9e56eaf7fc85f49b8906e987Eric Laurent } 253583900754f357616b9e56eaf7fc85f49b8906e987Eric Laurent 253683900754f357616b9e56eaf7fc85f49b8906e987Eric Laurent void startBluetoothScoInt(IBinder cb, int scoAudioMode){ 2537dc03c61fe3cd8d0805480e48a974986439977a60Eric Laurent if (!checkAudioSettingsPermission("startBluetoothSco()") || 25384a5eeb9c727d77bb57fef87a70c8c9cc23dbfee3Eric Laurent !mSystemReady) { 25393def1eec2baed0b8845ec32c871e249dc533a9d9Eric Laurent return; 25403def1eec2baed0b8845ec32c871e249dc533a9d9Eric Laurent } 2541854938a72d968c1bc0de4e2b0ea87777cfebc045Eric Laurent ScoClient client = getScoClient(cb, true); 2542f5a1fc3c0fd733acd21e1437f153ba27220be8ceEric Laurent // The calling identity must be cleared before calling ScoClient.incCount(). 2543f5a1fc3c0fd733acd21e1437f153ba27220be8ceEric Laurent // inCount() calls requestScoState() which in turn can call BluetoothHeadset APIs 2544f5a1fc3c0fd733acd21e1437f153ba27220be8ceEric Laurent // and this must be done on behalf of system server to make sure permissions are granted. 2545f5a1fc3c0fd733acd21e1437f153ba27220be8ceEric Laurent // The caller identity must be cleared after getScoClient() because it is needed if a new 2546f5a1fc3c0fd733acd21e1437f153ba27220be8ceEric Laurent // client is created. 2547f5a1fc3c0fd733acd21e1437f153ba27220be8ceEric Laurent final long ident = Binder.clearCallingIdentity(); 254883900754f357616b9e56eaf7fc85f49b8906e987Eric Laurent client.incCount(scoAudioMode); 25492a57ca931fefe817b6110101289721acaacfc808Eric Laurent Binder.restoreCallingIdentity(ident); 25503def1eec2baed0b8845ec32c871e249dc533a9d9Eric Laurent } 25513def1eec2baed0b8845ec32c871e249dc533a9d9Eric Laurent 25523def1eec2baed0b8845ec32c871e249dc533a9d9Eric Laurent /** @see AudioManager#stopBluetoothSco() */ 25533def1eec2baed0b8845ec32c871e249dc533a9d9Eric Laurent public void stopBluetoothSco(IBinder cb){ 2554dc03c61fe3cd8d0805480e48a974986439977a60Eric Laurent if (!checkAudioSettingsPermission("stopBluetoothSco()") || 25554a5eeb9c727d77bb57fef87a70c8c9cc23dbfee3Eric Laurent !mSystemReady) { 25563def1eec2baed0b8845ec32c871e249dc533a9d9Eric Laurent return; 25573def1eec2baed0b8845ec32c871e249dc533a9d9Eric Laurent } 2558854938a72d968c1bc0de4e2b0ea87777cfebc045Eric Laurent ScoClient client = getScoClient(cb, false); 2559f5a1fc3c0fd733acd21e1437f153ba27220be8ceEric Laurent // The calling identity must be cleared before calling ScoClient.decCount(). 2560f5a1fc3c0fd733acd21e1437f153ba27220be8ceEric Laurent // decCount() calls requestScoState() which in turn can call BluetoothHeadset APIs 2561f5a1fc3c0fd733acd21e1437f153ba27220be8ceEric Laurent // and this must be done on behalf of system server to make sure permissions are granted. 2562f5a1fc3c0fd733acd21e1437f153ba27220be8ceEric Laurent final long ident = Binder.clearCallingIdentity(); 2563854938a72d968c1bc0de4e2b0ea87777cfebc045Eric Laurent if (client != null) { 2564854938a72d968c1bc0de4e2b0ea87777cfebc045Eric Laurent client.decCount(); 2565854938a72d968c1bc0de4e2b0ea87777cfebc045Eric Laurent } 25662a57ca931fefe817b6110101289721acaacfc808Eric Laurent Binder.restoreCallingIdentity(ident); 25673def1eec2baed0b8845ec32c871e249dc533a9d9Eric Laurent } 25683def1eec2baed0b8845ec32c871e249dc533a9d9Eric Laurent 25697847211fb4699bf6018e29d214a918ed6657319bEric Laurent 25703def1eec2baed0b8845ec32c871e249dc533a9d9Eric Laurent private class ScoClient implements IBinder.DeathRecipient { 25713def1eec2baed0b8845ec32c871e249dc533a9d9Eric Laurent private IBinder mCb; // To be notified of client's death 2572f1ddd51f9cd2f92b922bc636c307210a8d587c25Marco Nelissen private int mCreatorPid; 25733def1eec2baed0b8845ec32c871e249dc533a9d9Eric Laurent private int mStartcount; // number of SCO connections started by this client 25743def1eec2baed0b8845ec32c871e249dc533a9d9Eric Laurent 25753def1eec2baed0b8845ec32c871e249dc533a9d9Eric Laurent ScoClient(IBinder cb) { 25763def1eec2baed0b8845ec32c871e249dc533a9d9Eric Laurent mCb = cb; 2577f1ddd51f9cd2f92b922bc636c307210a8d587c25Marco Nelissen mCreatorPid = Binder.getCallingPid(); 25783def1eec2baed0b8845ec32c871e249dc533a9d9Eric Laurent mStartcount = 0; 25793def1eec2baed0b8845ec32c871e249dc533a9d9Eric Laurent } 25803def1eec2baed0b8845ec32c871e249dc533a9d9Eric Laurent 25813def1eec2baed0b8845ec32c871e249dc533a9d9Eric Laurent public void binderDied() { 25823def1eec2baed0b8845ec32c871e249dc533a9d9Eric Laurent synchronized(mScoClients) { 25833def1eec2baed0b8845ec32c871e249dc533a9d9Eric Laurent Log.w(TAG, "SCO client died"); 25843def1eec2baed0b8845ec32c871e249dc533a9d9Eric Laurent int index = mScoClients.indexOf(this); 25853def1eec2baed0b8845ec32c871e249dc533a9d9Eric Laurent if (index < 0) { 25863def1eec2baed0b8845ec32c871e249dc533a9d9Eric Laurent Log.w(TAG, "unregistered SCO client died"); 25873def1eec2baed0b8845ec32c871e249dc533a9d9Eric Laurent } else { 25883def1eec2baed0b8845ec32c871e249dc533a9d9Eric Laurent clearCount(true); 25893def1eec2baed0b8845ec32c871e249dc533a9d9Eric Laurent mScoClients.remove(this); 25903def1eec2baed0b8845ec32c871e249dc533a9d9Eric Laurent } 25913def1eec2baed0b8845ec32c871e249dc533a9d9Eric Laurent } 25923def1eec2baed0b8845ec32c871e249dc533a9d9Eric Laurent } 25933def1eec2baed0b8845ec32c871e249dc533a9d9Eric Laurent 259483900754f357616b9e56eaf7fc85f49b8906e987Eric Laurent public void incCount(int scoAudioMode) { 25953def1eec2baed0b8845ec32c871e249dc533a9d9Eric Laurent synchronized(mScoClients) { 259683900754f357616b9e56eaf7fc85f49b8906e987Eric Laurent requestScoState(BluetoothHeadset.STATE_AUDIO_CONNECTED, scoAudioMode); 25973def1eec2baed0b8845ec32c871e249dc533a9d9Eric Laurent if (mStartcount == 0) { 25983def1eec2baed0b8845ec32c871e249dc533a9d9Eric Laurent try { 25993def1eec2baed0b8845ec32c871e249dc533a9d9Eric Laurent mCb.linkToDeath(this, 0); 26003def1eec2baed0b8845ec32c871e249dc533a9d9Eric Laurent } catch (RemoteException e) { 26013def1eec2baed0b8845ec32c871e249dc533a9d9Eric Laurent // client has already died! 26023def1eec2baed0b8845ec32c871e249dc533a9d9Eric Laurent Log.w(TAG, "ScoClient incCount() could not link to "+mCb+" binder death"); 26033def1eec2baed0b8845ec32c871e249dc533a9d9Eric Laurent } 26043def1eec2baed0b8845ec32c871e249dc533a9d9Eric Laurent } 26053def1eec2baed0b8845ec32c871e249dc533a9d9Eric Laurent mStartcount++; 26063def1eec2baed0b8845ec32c871e249dc533a9d9Eric Laurent } 26073def1eec2baed0b8845ec32c871e249dc533a9d9Eric Laurent } 26083def1eec2baed0b8845ec32c871e249dc533a9d9Eric Laurent 26093def1eec2baed0b8845ec32c871e249dc533a9d9Eric Laurent public void decCount() { 26103def1eec2baed0b8845ec32c871e249dc533a9d9Eric Laurent synchronized(mScoClients) { 26113def1eec2baed0b8845ec32c871e249dc533a9d9Eric Laurent if (mStartcount == 0) { 26123def1eec2baed0b8845ec32c871e249dc533a9d9Eric Laurent Log.w(TAG, "ScoClient.decCount() already 0"); 26133def1eec2baed0b8845ec32c871e249dc533a9d9Eric Laurent } else { 26143def1eec2baed0b8845ec32c871e249dc533a9d9Eric Laurent mStartcount--; 26153def1eec2baed0b8845ec32c871e249dc533a9d9Eric Laurent if (mStartcount == 0) { 2616e2dd8c4592762414c2c27e4589be7edc91a5ecaeEric Laurent try { 2617e2dd8c4592762414c2c27e4589be7edc91a5ecaeEric Laurent mCb.unlinkToDeath(this, 0); 2618e2dd8c4592762414c2c27e4589be7edc91a5ecaeEric Laurent } catch (NoSuchElementException e) { 2619e2dd8c4592762414c2c27e4589be7edc91a5ecaeEric Laurent Log.w(TAG, "decCount() going to 0 but not registered to binder"); 2620e2dd8c4592762414c2c27e4589be7edc91a5ecaeEric Laurent } 26213def1eec2baed0b8845ec32c871e249dc533a9d9Eric Laurent } 2622c18c9138cee0f0859bcab636a004ce92ca4a9ab5Eric Laurent requestScoState(BluetoothHeadset.STATE_AUDIO_DISCONNECTED, 0); 26233def1eec2baed0b8845ec32c871e249dc533a9d9Eric Laurent } 26243def1eec2baed0b8845ec32c871e249dc533a9d9Eric Laurent } 26253def1eec2baed0b8845ec32c871e249dc533a9d9Eric Laurent } 26263def1eec2baed0b8845ec32c871e249dc533a9d9Eric Laurent 26273def1eec2baed0b8845ec32c871e249dc533a9d9Eric Laurent public void clearCount(boolean stopSco) { 26283def1eec2baed0b8845ec32c871e249dc533a9d9Eric Laurent synchronized(mScoClients) { 2629e2dd8c4592762414c2c27e4589be7edc91a5ecaeEric Laurent if (mStartcount != 0) { 2630e2dd8c4592762414c2c27e4589be7edc91a5ecaeEric Laurent try { 2631e2dd8c4592762414c2c27e4589be7edc91a5ecaeEric Laurent mCb.unlinkToDeath(this, 0); 2632e2dd8c4592762414c2c27e4589be7edc91a5ecaeEric Laurent } catch (NoSuchElementException e) { 2633e2dd8c4592762414c2c27e4589be7edc91a5ecaeEric Laurent Log.w(TAG, "clearCount() mStartcount: "+mStartcount+" != 0 but not registered to binder"); 2634e2dd8c4592762414c2c27e4589be7edc91a5ecaeEric Laurent } 2635e2dd8c4592762414c2c27e4589be7edc91a5ecaeEric Laurent } 26363def1eec2baed0b8845ec32c871e249dc533a9d9Eric Laurent mStartcount = 0; 26373def1eec2baed0b8845ec32c871e249dc533a9d9Eric Laurent if (stopSco) { 2638c18c9138cee0f0859bcab636a004ce92ca4a9ab5Eric Laurent requestScoState(BluetoothHeadset.STATE_AUDIO_DISCONNECTED, 0); 26393def1eec2baed0b8845ec32c871e249dc533a9d9Eric Laurent } 26403def1eec2baed0b8845ec32c871e249dc533a9d9Eric Laurent } 26413def1eec2baed0b8845ec32c871e249dc533a9d9Eric Laurent } 26423def1eec2baed0b8845ec32c871e249dc533a9d9Eric Laurent 26433def1eec2baed0b8845ec32c871e249dc533a9d9Eric Laurent public int getCount() { 26443def1eec2baed0b8845ec32c871e249dc533a9d9Eric Laurent return mStartcount; 26453def1eec2baed0b8845ec32c871e249dc533a9d9Eric Laurent } 26463def1eec2baed0b8845ec32c871e249dc533a9d9Eric Laurent 26473def1eec2baed0b8845ec32c871e249dc533a9d9Eric Laurent public IBinder getBinder() { 26483def1eec2baed0b8845ec32c871e249dc533a9d9Eric Laurent return mCb; 26493def1eec2baed0b8845ec32c871e249dc533a9d9Eric Laurent } 26503def1eec2baed0b8845ec32c871e249dc533a9d9Eric Laurent 2651d7454be47f4111c0478a502353e11dea401378bdEric Laurent public int getPid() { 2652d7454be47f4111c0478a502353e11dea401378bdEric Laurent return mCreatorPid; 2653d7454be47f4111c0478a502353e11dea401378bdEric Laurent } 2654d7454be47f4111c0478a502353e11dea401378bdEric Laurent 26553def1eec2baed0b8845ec32c871e249dc533a9d9Eric Laurent public int totalCount() { 26563def1eec2baed0b8845ec32c871e249dc533a9d9Eric Laurent synchronized(mScoClients) { 26573def1eec2baed0b8845ec32c871e249dc533a9d9Eric Laurent int count = 0; 26583def1eec2baed0b8845ec32c871e249dc533a9d9Eric Laurent int size = mScoClients.size(); 26593def1eec2baed0b8845ec32c871e249dc533a9d9Eric Laurent for (int i = 0; i < size; i++) { 26603def1eec2baed0b8845ec32c871e249dc533a9d9Eric Laurent count += mScoClients.get(i).getCount(); 26613def1eec2baed0b8845ec32c871e249dc533a9d9Eric Laurent } 26623def1eec2baed0b8845ec32c871e249dc533a9d9Eric Laurent return count; 26633def1eec2baed0b8845ec32c871e249dc533a9d9Eric Laurent } 26643def1eec2baed0b8845ec32c871e249dc533a9d9Eric Laurent } 26653def1eec2baed0b8845ec32c871e249dc533a9d9Eric Laurent 266683900754f357616b9e56eaf7fc85f49b8906e987Eric Laurent private void requestScoState(int state, int scoAudioMode) { 266762ef767b15a712bab31cc0d5508a330906f535c2Eric Laurent checkScoAudioState(); 2668dc03c61fe3cd8d0805480e48a974986439977a60Eric Laurent if (totalCount() == 0) { 2669dc03c61fe3cd8d0805480e48a974986439977a60Eric Laurent if (state == BluetoothHeadset.STATE_AUDIO_CONNECTED) { 2670dc03c61fe3cd8d0805480e48a974986439977a60Eric Laurent // Make sure that the state transitions to CONNECTING even if we cannot initiate 2671dc03c61fe3cd8d0805480e48a974986439977a60Eric Laurent // the connection. 2672dc03c61fe3cd8d0805480e48a974986439977a60Eric Laurent broadcastScoConnectionState(AudioManager.SCO_AUDIO_STATE_CONNECTING); 2673dc03c61fe3cd8d0805480e48a974986439977a60Eric Laurent // Accept SCO audio activation only in NORMAL audio mode or if the mode is 2674f1ddd51f9cd2f92b922bc636c307210a8d587c25Marco Nelissen // currently controlled by the same client process. 26759f103de83f2d5d472960dcf1401e95b2ab57a477Eric Laurent synchronized(mSetModeDeathHandlers) { 26769f103de83f2d5d472960dcf1401e95b2ab57a477Eric Laurent if ((mSetModeDeathHandlers.isEmpty() || 26779f103de83f2d5d472960dcf1401e95b2ab57a477Eric Laurent mSetModeDeathHandlers.get(0).getPid() == mCreatorPid) && 26789f103de83f2d5d472960dcf1401e95b2ab57a477Eric Laurent (mScoAudioState == SCO_STATE_INACTIVE || 26799f103de83f2d5d472960dcf1401e95b2ab57a477Eric Laurent mScoAudioState == SCO_STATE_DEACTIVATE_REQ)) { 26809f103de83f2d5d472960dcf1401e95b2ab57a477Eric Laurent if (mScoAudioState == SCO_STATE_INACTIVE) { 268183900754f357616b9e56eaf7fc85f49b8906e987Eric Laurent mScoAudioMode = scoAudioMode; 2682f4e51d82d2e34e6832903f01eaecc15ded6c3241Liejun Tao if (scoAudioMode == SCO_MODE_UNDEFINED) { 2683570cc5302a2e076f2b6ce810f9ac6f3c53bcd125Andre Eisenbach if (mBluetoothHeadsetDevice != null) { 2684570cc5302a2e076f2b6ce810f9ac6f3c53bcd125Andre Eisenbach mScoAudioMode = new Integer(Settings.Global.getInt( 2685570cc5302a2e076f2b6ce810f9ac6f3c53bcd125Andre Eisenbach mContentResolver, 2686570cc5302a2e076f2b6ce810f9ac6f3c53bcd125Andre Eisenbach "bluetooth_sco_channel_"+ 2687570cc5302a2e076f2b6ce810f9ac6f3c53bcd125Andre Eisenbach mBluetoothHeadsetDevice.getAddress(), 2688570cc5302a2e076f2b6ce810f9ac6f3c53bcd125Andre Eisenbach SCO_MODE_VIRTUAL_CALL)); 2689570cc5302a2e076f2b6ce810f9ac6f3c53bcd125Andre Eisenbach if (mScoAudioMode > SCO_MODE_MAX || mScoAudioMode < 0) { 2690570cc5302a2e076f2b6ce810f9ac6f3c53bcd125Andre Eisenbach mScoAudioMode = SCO_MODE_VIRTUAL_CALL; 2691570cc5302a2e076f2b6ce810f9ac6f3c53bcd125Andre Eisenbach } 2692570cc5302a2e076f2b6ce810f9ac6f3c53bcd125Andre Eisenbach } else { 2693570cc5302a2e076f2b6ce810f9ac6f3c53bcd125Andre Eisenbach mScoAudioMode = SCO_MODE_RAW; 2694f4e51d82d2e34e6832903f01eaecc15ded6c3241Liejun Tao } 2695f4e51d82d2e34e6832903f01eaecc15ded6c3241Liejun Tao } 26969f103de83f2d5d472960dcf1401e95b2ab57a477Eric Laurent if (mBluetoothHeadset != null && mBluetoothHeadsetDevice != null) { 2697f4e51d82d2e34e6832903f01eaecc15ded6c3241Liejun Tao boolean status = false; 2698c18c9138cee0f0859bcab636a004ce92ca4a9ab5Eric Laurent if (mScoAudioMode == SCO_MODE_RAW) { 2699c18c9138cee0f0859bcab636a004ce92ca4a9ab5Eric Laurent status = mBluetoothHeadset.connectAudio(); 2700f4e51d82d2e34e6832903f01eaecc15ded6c3241Liejun Tao } else if (mScoAudioMode == SCO_MODE_VIRTUAL_CALL) { 2701c18c9138cee0f0859bcab636a004ce92ca4a9ab5Eric Laurent status = mBluetoothHeadset.startScoUsingVirtualVoiceCall( 2702c18c9138cee0f0859bcab636a004ce92ca4a9ab5Eric Laurent mBluetoothHeadsetDevice); 2703f4e51d82d2e34e6832903f01eaecc15ded6c3241Liejun Tao } else if (mScoAudioMode == SCO_MODE_VR) { 2704f4e51d82d2e34e6832903f01eaecc15ded6c3241Liejun Tao status = mBluetoothHeadset.startVoiceRecognition( 2705f4e51d82d2e34e6832903f01eaecc15ded6c3241Liejun Tao mBluetoothHeadsetDevice); 2706c18c9138cee0f0859bcab636a004ce92ca4a9ab5Eric Laurent } 2707f4e51d82d2e34e6832903f01eaecc15ded6c3241Liejun Tao 2708c18c9138cee0f0859bcab636a004ce92ca4a9ab5Eric Laurent if (status) { 27099f103de83f2d5d472960dcf1401e95b2ab57a477Eric Laurent mScoAudioState = SCO_STATE_ACTIVE_INTERNAL; 27109f103de83f2d5d472960dcf1401e95b2ab57a477Eric Laurent } else { 27119f103de83f2d5d472960dcf1401e95b2ab57a477Eric Laurent broadcastScoConnectionState( 27129f103de83f2d5d472960dcf1401e95b2ab57a477Eric Laurent AudioManager.SCO_AUDIO_STATE_DISCONNECTED); 27139f103de83f2d5d472960dcf1401e95b2ab57a477Eric Laurent } 27149f103de83f2d5d472960dcf1401e95b2ab57a477Eric Laurent } else if (getBluetoothHeadset()) { 27159f103de83f2d5d472960dcf1401e95b2ab57a477Eric Laurent mScoAudioState = SCO_STATE_ACTIVATE_REQ; 2716dc03c61fe3cd8d0805480e48a974986439977a60Eric Laurent } 27179f103de83f2d5d472960dcf1401e95b2ab57a477Eric Laurent } else { 27189f103de83f2d5d472960dcf1401e95b2ab57a477Eric Laurent mScoAudioState = SCO_STATE_ACTIVE_INTERNAL; 27199f103de83f2d5d472960dcf1401e95b2ab57a477Eric Laurent broadcastScoConnectionState(AudioManager.SCO_AUDIO_STATE_CONNECTED); 2720dc03c61fe3cd8d0805480e48a974986439977a60Eric Laurent } 2721dc03c61fe3cd8d0805480e48a974986439977a60Eric Laurent } else { 27229f103de83f2d5d472960dcf1401e95b2ab57a477Eric Laurent broadcastScoConnectionState(AudioManager.SCO_AUDIO_STATE_DISCONNECTED); 2723dc03c61fe3cd8d0805480e48a974986439977a60Eric Laurent } 2724dc03c61fe3cd8d0805480e48a974986439977a60Eric Laurent } 272562ef767b15a712bab31cc0d5508a330906f535c2Eric Laurent } else if (state == BluetoothHeadset.STATE_AUDIO_DISCONNECTED && 2726dc03c61fe3cd8d0805480e48a974986439977a60Eric Laurent (mScoAudioState == SCO_STATE_ACTIVE_INTERNAL || 2727dc03c61fe3cd8d0805480e48a974986439977a60Eric Laurent mScoAudioState == SCO_STATE_ACTIVATE_REQ)) { 2728dc03c61fe3cd8d0805480e48a974986439977a60Eric Laurent if (mScoAudioState == SCO_STATE_ACTIVE_INTERNAL) { 2729671db6f3ba1fdb3c907e0735fe6d0d284f5c34deMarco Nelissen if (mBluetoothHeadset != null && mBluetoothHeadsetDevice != null) { 2730f4e51d82d2e34e6832903f01eaecc15ded6c3241Liejun Tao boolean status = false; 2731c18c9138cee0f0859bcab636a004ce92ca4a9ab5Eric Laurent if (mScoAudioMode == SCO_MODE_RAW) { 2732c18c9138cee0f0859bcab636a004ce92ca4a9ab5Eric Laurent status = mBluetoothHeadset.disconnectAudio(); 2733f4e51d82d2e34e6832903f01eaecc15ded6c3241Liejun Tao } else if (mScoAudioMode == SCO_MODE_VIRTUAL_CALL) { 2734c18c9138cee0f0859bcab636a004ce92ca4a9ab5Eric Laurent status = mBluetoothHeadset.stopScoUsingVirtualVoiceCall( 2735c18c9138cee0f0859bcab636a004ce92ca4a9ab5Eric Laurent mBluetoothHeadsetDevice); 2736f4e51d82d2e34e6832903f01eaecc15ded6c3241Liejun Tao } else if (mScoAudioMode == SCO_MODE_VR) { 2737f4e51d82d2e34e6832903f01eaecc15ded6c3241Liejun Tao status = mBluetoothHeadset.stopVoiceRecognition( 2738f4e51d82d2e34e6832903f01eaecc15ded6c3241Liejun Tao mBluetoothHeadsetDevice); 2739c18c9138cee0f0859bcab636a004ce92ca4a9ab5Eric Laurent } 2740f4e51d82d2e34e6832903f01eaecc15ded6c3241Liejun Tao 2741c18c9138cee0f0859bcab636a004ce92ca4a9ab5Eric Laurent if (!status) { 2742dc03c61fe3cd8d0805480e48a974986439977a60Eric Laurent mScoAudioState = SCO_STATE_INACTIVE; 2743dc03c61fe3cd8d0805480e48a974986439977a60Eric Laurent broadcastScoConnectionState( 2744dc03c61fe3cd8d0805480e48a974986439977a60Eric Laurent AudioManager.SCO_AUDIO_STATE_DISCONNECTED); 2745dc03c61fe3cd8d0805480e48a974986439977a60Eric Laurent } 2746dc03c61fe3cd8d0805480e48a974986439977a60Eric Laurent } else if (getBluetoothHeadset()) { 2747dc03c61fe3cd8d0805480e48a974986439977a60Eric Laurent mScoAudioState = SCO_STATE_DEACTIVATE_REQ; 2748dc03c61fe3cd8d0805480e48a974986439977a60Eric Laurent } 2749dc03c61fe3cd8d0805480e48a974986439977a60Eric Laurent } else { 2750dc03c61fe3cd8d0805480e48a974986439977a60Eric Laurent mScoAudioState = SCO_STATE_INACTIVE; 2751dc03c61fe3cd8d0805480e48a974986439977a60Eric Laurent broadcastScoConnectionState(AudioManager.SCO_AUDIO_STATE_DISCONNECTED); 2752dc03c61fe3cd8d0805480e48a974986439977a60Eric Laurent } 27533def1eec2baed0b8845ec32c871e249dc533a9d9Eric Laurent } 27543def1eec2baed0b8845ec32c871e249dc533a9d9Eric Laurent } 27553def1eec2baed0b8845ec32c871e249dc533a9d9Eric Laurent } 27563def1eec2baed0b8845ec32c871e249dc533a9d9Eric Laurent } 27573def1eec2baed0b8845ec32c871e249dc533a9d9Eric Laurent 275862ef767b15a712bab31cc0d5508a330906f535c2Eric Laurent private void checkScoAudioState() { 275962ef767b15a712bab31cc0d5508a330906f535c2Eric Laurent if (mBluetoothHeadset != null && mBluetoothHeadsetDevice != null && 2760dc03c61fe3cd8d0805480e48a974986439977a60Eric Laurent mScoAudioState == SCO_STATE_INACTIVE && 276162ef767b15a712bab31cc0d5508a330906f535c2Eric Laurent mBluetoothHeadset.getAudioState(mBluetoothHeadsetDevice) 276262ef767b15a712bab31cc0d5508a330906f535c2Eric Laurent != BluetoothHeadset.STATE_AUDIO_DISCONNECTED) { 276362ef767b15a712bab31cc0d5508a330906f535c2Eric Laurent mScoAudioState = SCO_STATE_ACTIVE_EXTERNAL; 276462ef767b15a712bab31cc0d5508a330906f535c2Eric Laurent } 276562ef767b15a712bab31cc0d5508a330906f535c2Eric Laurent } 276662ef767b15a712bab31cc0d5508a330906f535c2Eric Laurent 2767854938a72d968c1bc0de4e2b0ea87777cfebc045Eric Laurent private ScoClient getScoClient(IBinder cb, boolean create) { 27683def1eec2baed0b8845ec32c871e249dc533a9d9Eric Laurent synchronized(mScoClients) { 2769854938a72d968c1bc0de4e2b0ea87777cfebc045Eric Laurent ScoClient client = null; 27703def1eec2baed0b8845ec32c871e249dc533a9d9Eric Laurent int size = mScoClients.size(); 27713def1eec2baed0b8845ec32c871e249dc533a9d9Eric Laurent for (int i = 0; i < size; i++) { 27723def1eec2baed0b8845ec32c871e249dc533a9d9Eric Laurent client = mScoClients.get(i); 27733def1eec2baed0b8845ec32c871e249dc533a9d9Eric Laurent if (client.getBinder() == cb) 27743def1eec2baed0b8845ec32c871e249dc533a9d9Eric Laurent return client; 27753def1eec2baed0b8845ec32c871e249dc533a9d9Eric Laurent } 2776854938a72d968c1bc0de4e2b0ea87777cfebc045Eric Laurent if (create) { 2777854938a72d968c1bc0de4e2b0ea87777cfebc045Eric Laurent client = new ScoClient(cb); 2778854938a72d968c1bc0de4e2b0ea87777cfebc045Eric Laurent mScoClients.add(client); 2779854938a72d968c1bc0de4e2b0ea87777cfebc045Eric Laurent } 27803def1eec2baed0b8845ec32c871e249dc533a9d9Eric Laurent return client; 27813def1eec2baed0b8845ec32c871e249dc533a9d9Eric Laurent } 27823def1eec2baed0b8845ec32c871e249dc533a9d9Eric Laurent } 27833def1eec2baed0b8845ec32c871e249dc533a9d9Eric Laurent 2784d7454be47f4111c0478a502353e11dea401378bdEric Laurent public void clearAllScoClients(int exceptPid, boolean stopSco) { 27853def1eec2baed0b8845ec32c871e249dc533a9d9Eric Laurent synchronized(mScoClients) { 2786854938a72d968c1bc0de4e2b0ea87777cfebc045Eric Laurent ScoClient savedClient = null; 27873def1eec2baed0b8845ec32c871e249dc533a9d9Eric Laurent int size = mScoClients.size(); 27883def1eec2baed0b8845ec32c871e249dc533a9d9Eric Laurent for (int i = 0; i < size; i++) { 2789854938a72d968c1bc0de4e2b0ea87777cfebc045Eric Laurent ScoClient cl = mScoClients.get(i); 2790d7454be47f4111c0478a502353e11dea401378bdEric Laurent if (cl.getPid() != exceptPid) { 2791854938a72d968c1bc0de4e2b0ea87777cfebc045Eric Laurent cl.clearCount(stopSco); 2792854938a72d968c1bc0de4e2b0ea87777cfebc045Eric Laurent } else { 2793854938a72d968c1bc0de4e2b0ea87777cfebc045Eric Laurent savedClient = cl; 2794854938a72d968c1bc0de4e2b0ea87777cfebc045Eric Laurent } 2795854938a72d968c1bc0de4e2b0ea87777cfebc045Eric Laurent } 2796854938a72d968c1bc0de4e2b0ea87777cfebc045Eric Laurent mScoClients.clear(); 2797854938a72d968c1bc0de4e2b0ea87777cfebc045Eric Laurent if (savedClient != null) { 2798854938a72d968c1bc0de4e2b0ea87777cfebc045Eric Laurent mScoClients.add(savedClient); 27993def1eec2baed0b8845ec32c871e249dc533a9d9Eric Laurent } 28003def1eec2baed0b8845ec32c871e249dc533a9d9Eric Laurent } 28013def1eec2baed0b8845ec32c871e249dc533a9d9Eric Laurent } 28023def1eec2baed0b8845ec32c871e249dc533a9d9Eric Laurent 2803dc03c61fe3cd8d0805480e48a974986439977a60Eric Laurent private boolean getBluetoothHeadset() { 2804dc03c61fe3cd8d0805480e48a974986439977a60Eric Laurent boolean result = false; 2805dc03c61fe3cd8d0805480e48a974986439977a60Eric Laurent BluetoothAdapter adapter = BluetoothAdapter.getDefaultAdapter(); 2806dc03c61fe3cd8d0805480e48a974986439977a60Eric Laurent if (adapter != null) { 2807dc03c61fe3cd8d0805480e48a974986439977a60Eric Laurent result = adapter.getProfileProxy(mContext, mBluetoothProfileServiceListener, 2808dc03c61fe3cd8d0805480e48a974986439977a60Eric Laurent BluetoothProfile.HEADSET); 2809dc03c61fe3cd8d0805480e48a974986439977a60Eric Laurent } 2810dc03c61fe3cd8d0805480e48a974986439977a60Eric Laurent // If we could not get a bluetooth headset proxy, send a failure message 2811dc03c61fe3cd8d0805480e48a974986439977a60Eric Laurent // without delay to reset the SCO audio state and clear SCO clients. 2812dc03c61fe3cd8d0805480e48a974986439977a60Eric Laurent // If we could get a proxy, send a delayed failure message that will reset our state 2813dc03c61fe3cd8d0805480e48a974986439977a60Eric Laurent // in case we don't receive onServiceConnected(). 2814afbb047c3945e9c2b7e9bc6b25098d5fb80bba4eEric Laurent sendMsg(mAudioHandler, MSG_BT_HEADSET_CNCT_FAILED, 2815dc03c61fe3cd8d0805480e48a974986439977a60Eric Laurent SENDMSG_REPLACE, 0, 0, null, result ? BT_HEADSET_CNCT_TIMEOUT_MS : 0); 2816dc03c61fe3cd8d0805480e48a974986439977a60Eric Laurent return result; 2817dc03c61fe3cd8d0805480e48a974986439977a60Eric Laurent } 2818dc03c61fe3cd8d0805480e48a974986439977a60Eric Laurent 2819d7454be47f4111c0478a502353e11dea401378bdEric Laurent private void disconnectBluetoothSco(int exceptPid) { 2820dc03c61fe3cd8d0805480e48a974986439977a60Eric Laurent synchronized(mScoClients) { 2821dc03c61fe3cd8d0805480e48a974986439977a60Eric Laurent checkScoAudioState(); 2822dc03c61fe3cd8d0805480e48a974986439977a60Eric Laurent if (mScoAudioState == SCO_STATE_ACTIVE_EXTERNAL || 2823dc03c61fe3cd8d0805480e48a974986439977a60Eric Laurent mScoAudioState == SCO_STATE_DEACTIVATE_EXT_REQ) { 2824dc03c61fe3cd8d0805480e48a974986439977a60Eric Laurent if (mBluetoothHeadsetDevice != null) { 2825dc03c61fe3cd8d0805480e48a974986439977a60Eric Laurent if (mBluetoothHeadset != null) { 2826dc03c61fe3cd8d0805480e48a974986439977a60Eric Laurent if (!mBluetoothHeadset.stopVoiceRecognition( 2827b06ac839dd2d0437fc8314f6deb7233af5af521eEric Laurent mBluetoothHeadsetDevice)) { 2828afbb047c3945e9c2b7e9bc6b25098d5fb80bba4eEric Laurent sendMsg(mAudioHandler, MSG_BT_HEADSET_CNCT_FAILED, 2829dc03c61fe3cd8d0805480e48a974986439977a60Eric Laurent SENDMSG_REPLACE, 0, 0, null, 0); 2830dc03c61fe3cd8d0805480e48a974986439977a60Eric Laurent } 2831dc03c61fe3cd8d0805480e48a974986439977a60Eric Laurent } else if (mScoAudioState == SCO_STATE_ACTIVE_EXTERNAL && 2832dc03c61fe3cd8d0805480e48a974986439977a60Eric Laurent getBluetoothHeadset()) { 2833dc03c61fe3cd8d0805480e48a974986439977a60Eric Laurent mScoAudioState = SCO_STATE_DEACTIVATE_EXT_REQ; 2834dc03c61fe3cd8d0805480e48a974986439977a60Eric Laurent } 2835dc03c61fe3cd8d0805480e48a974986439977a60Eric Laurent } 2836dc03c61fe3cd8d0805480e48a974986439977a60Eric Laurent } else { 2837d7454be47f4111c0478a502353e11dea401378bdEric Laurent clearAllScoClients(exceptPid, true); 2838dc03c61fe3cd8d0805480e48a974986439977a60Eric Laurent } 2839dc03c61fe3cd8d0805480e48a974986439977a60Eric Laurent } 2840dc03c61fe3cd8d0805480e48a974986439977a60Eric Laurent } 2841dc03c61fe3cd8d0805480e48a974986439977a60Eric Laurent 2842dc03c61fe3cd8d0805480e48a974986439977a60Eric Laurent private void resetBluetoothSco() { 2843dc03c61fe3cd8d0805480e48a974986439977a60Eric Laurent synchronized(mScoClients) { 2844d7454be47f4111c0478a502353e11dea401378bdEric Laurent clearAllScoClients(0, false); 2845dc03c61fe3cd8d0805480e48a974986439977a60Eric Laurent mScoAudioState = SCO_STATE_INACTIVE; 2846dc03c61fe3cd8d0805480e48a974986439977a60Eric Laurent broadcastScoConnectionState(AudioManager.SCO_AUDIO_STATE_DISCONNECTED); 2847dc03c61fe3cd8d0805480e48a974986439977a60Eric Laurent } 2848dc03c61fe3cd8d0805480e48a974986439977a60Eric Laurent } 2849dc03c61fe3cd8d0805480e48a974986439977a60Eric Laurent 2850dc03c61fe3cd8d0805480e48a974986439977a60Eric Laurent private void broadcastScoConnectionState(int state) { 28512a57ca931fefe817b6110101289721acaacfc808Eric Laurent sendMsg(mAudioHandler, MSG_BROADCAST_BT_CONNECTION_STATE, 28522a57ca931fefe817b6110101289721acaacfc808Eric Laurent SENDMSG_QUEUE, state, 0, null, 0); 28532a57ca931fefe817b6110101289721acaacfc808Eric Laurent } 28542a57ca931fefe817b6110101289721acaacfc808Eric Laurent 28552a57ca931fefe817b6110101289721acaacfc808Eric Laurent private void onBroadcastScoConnectionState(int state) { 2856dc03c61fe3cd8d0805480e48a974986439977a60Eric Laurent if (state != mScoConnectionState) { 2857dc03c61fe3cd8d0805480e48a974986439977a60Eric Laurent Intent newIntent = new Intent(AudioManager.ACTION_SCO_AUDIO_STATE_UPDATED); 2858dc03c61fe3cd8d0805480e48a974986439977a60Eric Laurent newIntent.putExtra(AudioManager.EXTRA_SCO_AUDIO_STATE, state); 2859dc03c61fe3cd8d0805480e48a974986439977a60Eric Laurent newIntent.putExtra(AudioManager.EXTRA_SCO_AUDIO_PREVIOUS_STATE, 2860dc03c61fe3cd8d0805480e48a974986439977a60Eric Laurent mScoConnectionState); 28615ac72a29593ab9a20337a2225df52bdf4754be02Dianne Hackborn sendStickyBroadcastToAll(newIntent); 2862dc03c61fe3cd8d0805480e48a974986439977a60Eric Laurent mScoConnectionState = state; 2863dc03c61fe3cd8d0805480e48a974986439977a60Eric Laurent } 2864dc03c61fe3cd8d0805480e48a974986439977a60Eric Laurent } 2865dc03c61fe3cd8d0805480e48a974986439977a60Eric Laurent 286682aa7f017daaaeb96c13e6e3491d5037ab471085Jaikumar Ganesh private BluetoothProfile.ServiceListener mBluetoothProfileServiceListener = 286782aa7f017daaaeb96c13e6e3491d5037ab471085Jaikumar Ganesh new BluetoothProfile.ServiceListener() { 286882aa7f017daaaeb96c13e6e3491d5037ab471085Jaikumar Ganesh public void onServiceConnected(int profile, BluetoothProfile proxy) { 28696bc7f2cd30b6bd90806942b0722e22daa2108493Eric Laurent BluetoothDevice btDevice; 28706bc7f2cd30b6bd90806942b0722e22daa2108493Eric Laurent List<BluetoothDevice> deviceList; 28716bc7f2cd30b6bd90806942b0722e22daa2108493Eric Laurent switch(profile) { 28726bc7f2cd30b6bd90806942b0722e22daa2108493Eric Laurent case BluetoothProfile.A2DP: 28735a0cf7a27f3953a1266af48543ccd9024f4cd89fJohn Du synchronized (mA2dpAvrcpLock) { 28745a0cf7a27f3953a1266af48543ccd9024f4cd89fJohn Du mA2dp = (BluetoothA2dp) proxy; 28755a0cf7a27f3953a1266af48543ccd9024f4cd89fJohn Du deviceList = mA2dp.getConnectedDevices(); 28765a0cf7a27f3953a1266af48543ccd9024f4cd89fJohn Du if (deviceList.size() > 0) { 28775a0cf7a27f3953a1266af48543ccd9024f4cd89fJohn Du btDevice = deviceList.get(0); 28785a0cf7a27f3953a1266af48543ccd9024f4cd89fJohn Du synchronized (mConnectedDevices) { 28795a0cf7a27f3953a1266af48543ccd9024f4cd89fJohn Du int state = mA2dp.getConnectionState(btDevice); 28805a0cf7a27f3953a1266af48543ccd9024f4cd89fJohn Du int delay = checkSendBecomingNoisyIntent( 28810a40ec2192e4836b2fcb6ba51a7688aa6bd4ee98Mike Lockwood AudioSystem.DEVICE_OUT_BLUETOOTH_A2DP, 28820a40ec2192e4836b2fcb6ba51a7688aa6bd4ee98Mike Lockwood (state == BluetoothA2dp.STATE_CONNECTED) ? 1 : 0); 28835a0cf7a27f3953a1266af48543ccd9024f4cd89fJohn Du queueMsgUnderWakeLock(mAudioHandler, 28840a40ec2192e4836b2fcb6ba51a7688aa6bd4ee98Mike Lockwood MSG_SET_A2DP_SINK_CONNECTION_STATE, 28855a0cf7a27f3953a1266af48543ccd9024f4cd89fJohn Du state, 28865a0cf7a27f3953a1266af48543ccd9024f4cd89fJohn Du 0, 28875a0cf7a27f3953a1266af48543ccd9024f4cd89fJohn Du btDevice, 28885a0cf7a27f3953a1266af48543ccd9024f4cd89fJohn Du delay); 28895a0cf7a27f3953a1266af48543ccd9024f4cd89fJohn Du } 2890b1fbaaccb656ef09a8770c28df15e3e91a452e64Eric Laurent } 28916bc7f2cd30b6bd90806942b0722e22daa2108493Eric Laurent } 28926bc7f2cd30b6bd90806942b0722e22daa2108493Eric Laurent break; 28936bc7f2cd30b6bd90806942b0722e22daa2108493Eric Laurent 28940a40ec2192e4836b2fcb6ba51a7688aa6bd4ee98Mike Lockwood case BluetoothProfile.A2DP_SINK: 28950a40ec2192e4836b2fcb6ba51a7688aa6bd4ee98Mike Lockwood deviceList = proxy.getConnectedDevices(); 28960a40ec2192e4836b2fcb6ba51a7688aa6bd4ee98Mike Lockwood if (deviceList.size() > 0) { 28970a40ec2192e4836b2fcb6ba51a7688aa6bd4ee98Mike Lockwood btDevice = deviceList.get(0); 28980a40ec2192e4836b2fcb6ba51a7688aa6bd4ee98Mike Lockwood synchronized (mConnectedDevices) { 28990a40ec2192e4836b2fcb6ba51a7688aa6bd4ee98Mike Lockwood int state = proxy.getConnectionState(btDevice); 29000a40ec2192e4836b2fcb6ba51a7688aa6bd4ee98Mike Lockwood queueMsgUnderWakeLock(mAudioHandler, 29010a40ec2192e4836b2fcb6ba51a7688aa6bd4ee98Mike Lockwood MSG_SET_A2DP_SRC_CONNECTION_STATE, 29020a40ec2192e4836b2fcb6ba51a7688aa6bd4ee98Mike Lockwood state, 29030a40ec2192e4836b2fcb6ba51a7688aa6bd4ee98Mike Lockwood 0, 29040a40ec2192e4836b2fcb6ba51a7688aa6bd4ee98Mike Lockwood btDevice, 29050a40ec2192e4836b2fcb6ba51a7688aa6bd4ee98Mike Lockwood 0 /* delay */); 29060a40ec2192e4836b2fcb6ba51a7688aa6bd4ee98Mike Lockwood } 29070a40ec2192e4836b2fcb6ba51a7688aa6bd4ee98Mike Lockwood } 29080a40ec2192e4836b2fcb6ba51a7688aa6bd4ee98Mike Lockwood break; 29090a40ec2192e4836b2fcb6ba51a7688aa6bd4ee98Mike Lockwood 29106bc7f2cd30b6bd90806942b0722e22daa2108493Eric Laurent case BluetoothProfile.HEADSET: 29116bc7f2cd30b6bd90806942b0722e22daa2108493Eric Laurent synchronized (mScoClients) { 29126bc7f2cd30b6bd90806942b0722e22daa2108493Eric Laurent // Discard timeout message 29136bc7f2cd30b6bd90806942b0722e22daa2108493Eric Laurent mAudioHandler.removeMessages(MSG_BT_HEADSET_CNCT_FAILED); 29146bc7f2cd30b6bd90806942b0722e22daa2108493Eric Laurent mBluetoothHeadset = (BluetoothHeadset) proxy; 29156bc7f2cd30b6bd90806942b0722e22daa2108493Eric Laurent deviceList = mBluetoothHeadset.getConnectedDevices(); 29166bc7f2cd30b6bd90806942b0722e22daa2108493Eric Laurent if (deviceList.size() > 0) { 29176bc7f2cd30b6bd90806942b0722e22daa2108493Eric Laurent mBluetoothHeadsetDevice = deviceList.get(0); 29186bc7f2cd30b6bd90806942b0722e22daa2108493Eric Laurent } else { 29196bc7f2cd30b6bd90806942b0722e22daa2108493Eric Laurent mBluetoothHeadsetDevice = null; 2920dc03c61fe3cd8d0805480e48a974986439977a60Eric Laurent } 29216bc7f2cd30b6bd90806942b0722e22daa2108493Eric Laurent // Refresh SCO audio state 29226bc7f2cd30b6bd90806942b0722e22daa2108493Eric Laurent checkScoAudioState(); 29236bc7f2cd30b6bd90806942b0722e22daa2108493Eric Laurent // Continue pending action if any 29246bc7f2cd30b6bd90806942b0722e22daa2108493Eric Laurent if (mScoAudioState == SCO_STATE_ACTIVATE_REQ || 29256bc7f2cd30b6bd90806942b0722e22daa2108493Eric Laurent mScoAudioState == SCO_STATE_DEACTIVATE_REQ || 29266bc7f2cd30b6bd90806942b0722e22daa2108493Eric Laurent mScoAudioState == SCO_STATE_DEACTIVATE_EXT_REQ) { 29276bc7f2cd30b6bd90806942b0722e22daa2108493Eric Laurent boolean status = false; 29286bc7f2cd30b6bd90806942b0722e22daa2108493Eric Laurent if (mBluetoothHeadsetDevice != null) { 29296bc7f2cd30b6bd90806942b0722e22daa2108493Eric Laurent switch (mScoAudioState) { 29306bc7f2cd30b6bd90806942b0722e22daa2108493Eric Laurent case SCO_STATE_ACTIVATE_REQ: 29316bc7f2cd30b6bd90806942b0722e22daa2108493Eric Laurent mScoAudioState = SCO_STATE_ACTIVE_INTERNAL; 2932c18c9138cee0f0859bcab636a004ce92ca4a9ab5Eric Laurent if (mScoAudioMode == SCO_MODE_RAW) { 2933c18c9138cee0f0859bcab636a004ce92ca4a9ab5Eric Laurent status = mBluetoothHeadset.connectAudio(); 2934f4e51d82d2e34e6832903f01eaecc15ded6c3241Liejun Tao } else if (mScoAudioMode == SCO_MODE_VIRTUAL_CALL) { 2935c18c9138cee0f0859bcab636a004ce92ca4a9ab5Eric Laurent status = mBluetoothHeadset.startScoUsingVirtualVoiceCall( 2936c18c9138cee0f0859bcab636a004ce92ca4a9ab5Eric Laurent mBluetoothHeadsetDevice); 2937f4e51d82d2e34e6832903f01eaecc15ded6c3241Liejun Tao } else if (mScoAudioMode == SCO_MODE_VR) { 2938f4e51d82d2e34e6832903f01eaecc15ded6c3241Liejun Tao status = mBluetoothHeadset.startVoiceRecognition( 2939f4e51d82d2e34e6832903f01eaecc15ded6c3241Liejun Tao mBluetoothHeadsetDevice); 2940c18c9138cee0f0859bcab636a004ce92ca4a9ab5Eric Laurent } 29416bc7f2cd30b6bd90806942b0722e22daa2108493Eric Laurent break; 29426bc7f2cd30b6bd90806942b0722e22daa2108493Eric Laurent case SCO_STATE_DEACTIVATE_REQ: 2943c18c9138cee0f0859bcab636a004ce92ca4a9ab5Eric Laurent if (mScoAudioMode == SCO_MODE_RAW) { 2944c18c9138cee0f0859bcab636a004ce92ca4a9ab5Eric Laurent status = mBluetoothHeadset.disconnectAudio(); 2945f4e51d82d2e34e6832903f01eaecc15ded6c3241Liejun Tao } else if (mScoAudioMode == SCO_MODE_VIRTUAL_CALL) { 2946c18c9138cee0f0859bcab636a004ce92ca4a9ab5Eric Laurent status = mBluetoothHeadset.stopScoUsingVirtualVoiceCall( 2947c18c9138cee0f0859bcab636a004ce92ca4a9ab5Eric Laurent mBluetoothHeadsetDevice); 2948f4e51d82d2e34e6832903f01eaecc15ded6c3241Liejun Tao } else if (mScoAudioMode == SCO_MODE_VR) { 2949f4e51d82d2e34e6832903f01eaecc15ded6c3241Liejun Tao status = mBluetoothHeadset.stopVoiceRecognition( 2950f4e51d82d2e34e6832903f01eaecc15ded6c3241Liejun Tao mBluetoothHeadsetDevice); 2951c18c9138cee0f0859bcab636a004ce92ca4a9ab5Eric Laurent } 29526bc7f2cd30b6bd90806942b0722e22daa2108493Eric Laurent break; 29536bc7f2cd30b6bd90806942b0722e22daa2108493Eric Laurent case SCO_STATE_DEACTIVATE_EXT_REQ: 29546bc7f2cd30b6bd90806942b0722e22daa2108493Eric Laurent status = mBluetoothHeadset.stopVoiceRecognition( 29556bc7f2cd30b6bd90806942b0722e22daa2108493Eric Laurent mBluetoothHeadsetDevice); 29566bc7f2cd30b6bd90806942b0722e22daa2108493Eric Laurent } 29576bc7f2cd30b6bd90806942b0722e22daa2108493Eric Laurent } 29586bc7f2cd30b6bd90806942b0722e22daa2108493Eric Laurent if (!status) { 2959afbb047c3945e9c2b7e9bc6b25098d5fb80bba4eEric Laurent sendMsg(mAudioHandler, MSG_BT_HEADSET_CNCT_FAILED, 29606bc7f2cd30b6bd90806942b0722e22daa2108493Eric Laurent SENDMSG_REPLACE, 0, 0, null, 0); 29616bc7f2cd30b6bd90806942b0722e22daa2108493Eric Laurent } 2962dc03c61fe3cd8d0805480e48a974986439977a60Eric Laurent } 2963dc03c61fe3cd8d0805480e48a974986439977a60Eric Laurent } 29646bc7f2cd30b6bd90806942b0722e22daa2108493Eric Laurent break; 29656bc7f2cd30b6bd90806942b0722e22daa2108493Eric Laurent 29666bc7f2cd30b6bd90806942b0722e22daa2108493Eric Laurent default: 29676bc7f2cd30b6bd90806942b0722e22daa2108493Eric Laurent break; 29683def1eec2baed0b8845ec32c871e249dc533a9d9Eric Laurent } 29693def1eec2baed0b8845ec32c871e249dc533a9d9Eric Laurent } 297082aa7f017daaaeb96c13e6e3491d5037ab471085Jaikumar Ganesh public void onServiceDisconnected(int profile) { 29716bc7f2cd30b6bd90806942b0722e22daa2108493Eric Laurent switch(profile) { 29726bc7f2cd30b6bd90806942b0722e22daa2108493Eric Laurent case BluetoothProfile.A2DP: 29735a0cf7a27f3953a1266af48543ccd9024f4cd89fJohn Du synchronized (mA2dpAvrcpLock) { 29745a0cf7a27f3953a1266af48543ccd9024f4cd89fJohn Du mA2dp = null; 29755a0cf7a27f3953a1266af48543ccd9024f4cd89fJohn Du synchronized (mConnectedDevices) { 29765a0cf7a27f3953a1266af48543ccd9024f4cd89fJohn Du if (mConnectedDevices.containsKey(AudioSystem.DEVICE_OUT_BLUETOOTH_A2DP)) { 29775a0cf7a27f3953a1266af48543ccd9024f4cd89fJohn Du makeA2dpDeviceUnavailableNow( 29785a0cf7a27f3953a1266af48543ccd9024f4cd89fJohn Du mConnectedDevices.get(AudioSystem.DEVICE_OUT_BLUETOOTH_A2DP)); 29795a0cf7a27f3953a1266af48543ccd9024f4cd89fJohn Du } 29806bc7f2cd30b6bd90806942b0722e22daa2108493Eric Laurent } 29816bc7f2cd30b6bd90806942b0722e22daa2108493Eric Laurent } 29826bc7f2cd30b6bd90806942b0722e22daa2108493Eric Laurent break; 29836bc7f2cd30b6bd90806942b0722e22daa2108493Eric Laurent 29840a40ec2192e4836b2fcb6ba51a7688aa6bd4ee98Mike Lockwood case BluetoothProfile.A2DP_SINK: 29850a40ec2192e4836b2fcb6ba51a7688aa6bd4ee98Mike Lockwood synchronized (mConnectedDevices) { 29860a40ec2192e4836b2fcb6ba51a7688aa6bd4ee98Mike Lockwood if (mConnectedDevices.containsKey(AudioSystem.DEVICE_IN_BLUETOOTH_A2DP)) { 29870a40ec2192e4836b2fcb6ba51a7688aa6bd4ee98Mike Lockwood makeA2dpSrcUnavailable( 29880a40ec2192e4836b2fcb6ba51a7688aa6bd4ee98Mike Lockwood mConnectedDevices.get(AudioSystem.DEVICE_IN_BLUETOOTH_A2DP)); 29890a40ec2192e4836b2fcb6ba51a7688aa6bd4ee98Mike Lockwood } 29900a40ec2192e4836b2fcb6ba51a7688aa6bd4ee98Mike Lockwood } 29910a40ec2192e4836b2fcb6ba51a7688aa6bd4ee98Mike Lockwood break; 29920a40ec2192e4836b2fcb6ba51a7688aa6bd4ee98Mike Lockwood 29936bc7f2cd30b6bd90806942b0722e22daa2108493Eric Laurent case BluetoothProfile.HEADSET: 29946bc7f2cd30b6bd90806942b0722e22daa2108493Eric Laurent synchronized (mScoClients) { 29956bc7f2cd30b6bd90806942b0722e22daa2108493Eric Laurent mBluetoothHeadset = null; 29966bc7f2cd30b6bd90806942b0722e22daa2108493Eric Laurent } 29976bc7f2cd30b6bd90806942b0722e22daa2108493Eric Laurent break; 29986bc7f2cd30b6bd90806942b0722e22daa2108493Eric Laurent 29996bc7f2cd30b6bd90806942b0722e22daa2108493Eric Laurent default: 30006bc7f2cd30b6bd90806942b0722e22daa2108493Eric Laurent break; 30013def1eec2baed0b8845ec32c871e249dc533a9d9Eric Laurent } 30023def1eec2baed0b8845ec32c871e249dc533a9d9Eric Laurent } 30033def1eec2baed0b8845ec32c871e249dc533a9d9Eric Laurent }; 3004d5176cfe6eae954e9cef1e2ec17859a5089e1330Jean-Michel Trivi 3005c34dcc1e1ebf152bb400abbb8bc25f7dc0c3ba97Eric Laurent private void onCheckMusicActive() { 3006d640bd325c3be9a350058c835b880a7e0b40dc60Eric Laurent synchronized (mSafeMediaVolumeState) { 3007d640bd325c3be9a350058c835b880a7e0b40dc60Eric Laurent if (mSafeMediaVolumeState == SAFE_MEDIA_VOLUME_INACTIVE) { 3008c34dcc1e1ebf152bb400abbb8bc25f7dc0c3ba97Eric Laurent int device = getDeviceForStream(AudioSystem.STREAM_MUSIC); 3009c34dcc1e1ebf152bb400abbb8bc25f7dc0c3ba97Eric Laurent 3010c34dcc1e1ebf152bb400abbb8bc25f7dc0c3ba97Eric Laurent if ((device & mSafeMediaVolumeDevices) != 0) { 3011c34dcc1e1ebf152bb400abbb8bc25f7dc0c3ba97Eric Laurent sendMsg(mAudioHandler, 3012c34dcc1e1ebf152bb400abbb8bc25f7dc0c3ba97Eric Laurent MSG_CHECK_MUSIC_ACTIVE, 3013c34dcc1e1ebf152bb400abbb8bc25f7dc0c3ba97Eric Laurent SENDMSG_REPLACE, 3014f1a457d06c53a901ea08d2d3fb6e766bc06c4d4fEric Laurent 0, 3015c34dcc1e1ebf152bb400abbb8bc25f7dc0c3ba97Eric Laurent 0, 3016c34dcc1e1ebf152bb400abbb8bc25f7dc0c3ba97Eric Laurent null, 3017c34dcc1e1ebf152bb400abbb8bc25f7dc0c3ba97Eric Laurent MUSIC_ACTIVE_POLL_PERIOD_MS); 301842b041ed4f184e3af7f788eb07307f556a2a6616Eric Laurent int index = mStreamStates[AudioSystem.STREAM_MUSIC].getIndex(device); 3019f1a457d06c53a901ea08d2d3fb6e766bc06c4d4fEric Laurent if (AudioSystem.isStreamActive(AudioSystem.STREAM_MUSIC, 0) && 3020f1a457d06c53a901ea08d2d3fb6e766bc06c4d4fEric Laurent (index > mSafeMediaVolumeIndex)) { 3021c34dcc1e1ebf152bb400abbb8bc25f7dc0c3ba97Eric Laurent // Approximate cumulative active music time 3022c34dcc1e1ebf152bb400abbb8bc25f7dc0c3ba97Eric Laurent mMusicActiveMs += MUSIC_ACTIVE_POLL_PERIOD_MS; 3023c34dcc1e1ebf152bb400abbb8bc25f7dc0c3ba97Eric Laurent if (mMusicActiveMs > UNSAFE_VOLUME_MUSIC_ACTIVE_MS_MAX) { 3024c34dcc1e1ebf152bb400abbb8bc25f7dc0c3ba97Eric Laurent setSafeMediaVolumeEnabled(true); 3025c34dcc1e1ebf152bb400abbb8bc25f7dc0c3ba97Eric Laurent mMusicActiveMs = 0; 3026c34dcc1e1ebf152bb400abbb8bc25f7dc0c3ba97Eric Laurent } 3027aa5ee4d65f8788e2a0afcd198367450853fd72acJohn Spurlock saveMusicActiveMs(); 3028c34dcc1e1ebf152bb400abbb8bc25f7dc0c3ba97Eric Laurent } 3029c34dcc1e1ebf152bb400abbb8bc25f7dc0c3ba97Eric Laurent } 3030c34dcc1e1ebf152bb400abbb8bc25f7dc0c3ba97Eric Laurent } 3031c34dcc1e1ebf152bb400abbb8bc25f7dc0c3ba97Eric Laurent } 3032c34dcc1e1ebf152bb400abbb8bc25f7dc0c3ba97Eric Laurent } 3033c34dcc1e1ebf152bb400abbb8bc25f7dc0c3ba97Eric Laurent 3034aa5ee4d65f8788e2a0afcd198367450853fd72acJohn Spurlock private void saveMusicActiveMs() { 3035aa5ee4d65f8788e2a0afcd198367450853fd72acJohn Spurlock mAudioHandler.obtainMessage(MSG_PERSIST_MUSIC_ACTIVE_MS, mMusicActiveMs, 0).sendToTarget(); 3036aa5ee4d65f8788e2a0afcd198367450853fd72acJohn Spurlock } 3037aa5ee4d65f8788e2a0afcd198367450853fd72acJohn Spurlock 3038d640bd325c3be9a350058c835b880a7e0b40dc60Eric Laurent private void onConfigureSafeVolume(boolean force) { 3039d640bd325c3be9a350058c835b880a7e0b40dc60Eric Laurent synchronized (mSafeMediaVolumeState) { 3040d640bd325c3be9a350058c835b880a7e0b40dc60Eric Laurent int mcc = mContext.getResources().getConfiguration().mcc; 3041d640bd325c3be9a350058c835b880a7e0b40dc60Eric Laurent if ((mMcc != mcc) || ((mMcc == 0) && force)) { 3042d640bd325c3be9a350058c835b880a7e0b40dc60Eric Laurent mSafeMediaVolumeIndex = mContext.getResources().getInteger( 3043d640bd325c3be9a350058c835b880a7e0b40dc60Eric Laurent com.android.internal.R.integer.config_safe_media_volume_index) * 10; 3044351346092acdfbfcc1d9ebf98d539d2a1196c5e8John Spurlock boolean safeMediaVolumeEnabled = 3045351346092acdfbfcc1d9ebf98d539d2a1196c5e8John Spurlock SystemProperties.getBoolean("audio.safemedia.force", false) 3046351346092acdfbfcc1d9ebf98d539d2a1196c5e8John Spurlock || mContext.getResources().getBoolean( 3047351346092acdfbfcc1d9ebf98d539d2a1196c5e8John Spurlock com.android.internal.R.bool.config_safe_media_volume_enabled); 304805274f348e12983eb8613cc6eb9ae561e8197e28Eric Laurent 304905274f348e12983eb8613cc6eb9ae561e8197e28Eric Laurent // The persisted state is either "disabled" or "active": this is the state applied 305005274f348e12983eb8613cc6eb9ae561e8197e28Eric Laurent // next time we boot and cannot be "inactive" 305105274f348e12983eb8613cc6eb9ae561e8197e28Eric Laurent int persistedState; 3052d640bd325c3be9a350058c835b880a7e0b40dc60Eric Laurent if (safeMediaVolumeEnabled) { 305305274f348e12983eb8613cc6eb9ae561e8197e28Eric Laurent persistedState = SAFE_MEDIA_VOLUME_ACTIVE; 305405274f348e12983eb8613cc6eb9ae561e8197e28Eric Laurent // The state can already be "inactive" here if the user has forced it before 305505274f348e12983eb8613cc6eb9ae561e8197e28Eric Laurent // the 30 seconds timeout for forced configuration. In this case we don't reset 305605274f348e12983eb8613cc6eb9ae561e8197e28Eric Laurent // it to "active". 305705274f348e12983eb8613cc6eb9ae561e8197e28Eric Laurent if (mSafeMediaVolumeState != SAFE_MEDIA_VOLUME_INACTIVE) { 3058aa5ee4d65f8788e2a0afcd198367450853fd72acJohn Spurlock if (mMusicActiveMs == 0) { 3059aa5ee4d65f8788e2a0afcd198367450853fd72acJohn Spurlock mSafeMediaVolumeState = SAFE_MEDIA_VOLUME_ACTIVE; 3060aa5ee4d65f8788e2a0afcd198367450853fd72acJohn Spurlock enforceSafeMediaVolume(); 3061aa5ee4d65f8788e2a0afcd198367450853fd72acJohn Spurlock } else { 3062aa5ee4d65f8788e2a0afcd198367450853fd72acJohn Spurlock // We have existing playback time recorded, already confirmed. 3063aa5ee4d65f8788e2a0afcd198367450853fd72acJohn Spurlock mSafeMediaVolumeState = SAFE_MEDIA_VOLUME_INACTIVE; 3064aa5ee4d65f8788e2a0afcd198367450853fd72acJohn Spurlock } 306505274f348e12983eb8613cc6eb9ae561e8197e28Eric Laurent } 3066d640bd325c3be9a350058c835b880a7e0b40dc60Eric Laurent } else { 306705274f348e12983eb8613cc6eb9ae561e8197e28Eric Laurent persistedState = SAFE_MEDIA_VOLUME_DISABLED; 3068d640bd325c3be9a350058c835b880a7e0b40dc60Eric Laurent mSafeMediaVolumeState = SAFE_MEDIA_VOLUME_DISABLED; 3069d640bd325c3be9a350058c835b880a7e0b40dc60Eric Laurent } 3070d640bd325c3be9a350058c835b880a7e0b40dc60Eric Laurent mMcc = mcc; 307105274f348e12983eb8613cc6eb9ae561e8197e28Eric Laurent sendMsg(mAudioHandler, 307205274f348e12983eb8613cc6eb9ae561e8197e28Eric Laurent MSG_PERSIST_SAFE_VOLUME_STATE, 307305274f348e12983eb8613cc6eb9ae561e8197e28Eric Laurent SENDMSG_QUEUE, 307405274f348e12983eb8613cc6eb9ae561e8197e28Eric Laurent persistedState, 307505274f348e12983eb8613cc6eb9ae561e8197e28Eric Laurent 0, 307605274f348e12983eb8613cc6eb9ae561e8197e28Eric Laurent null, 307705274f348e12983eb8613cc6eb9ae561e8197e28Eric Laurent 0); 3078d640bd325c3be9a350058c835b880a7e0b40dc60Eric Laurent } 3079d640bd325c3be9a350058c835b880a7e0b40dc60Eric Laurent } 3080d640bd325c3be9a350058c835b880a7e0b40dc60Eric Laurent } 3081d640bd325c3be9a350058c835b880a7e0b40dc60Eric Laurent 30829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /////////////////////////////////////////////////////////////////////////// 30839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Internal methods 30849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /////////////////////////////////////////////////////////////////////////// 30859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 30869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 30879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Checks if the adjustment should change ringer mode instead of just 30889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * adjusting volume. If so, this will set the proper ringer mode and volume 30899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * indices on the stream states. 30909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 3091a11b4affcad3d255aa723a89b768ea222506f2e8John Spurlock private int checkForRingerModeChange(int oldIndex, int direction, int step) { 3092a11b4affcad3d255aa723a89b768ea222506f2e8John Spurlock int result = FLAG_ADJUST_VOLUME; 3093661f2cf45860d2e10924e6b69966a9afe255f28bJohn Spurlock int ringerMode = getRingerModeInternal(); 3094bffc3d1bd33eb2d8e00a9f8b6261d815db503311Eric Laurent 3095bffc3d1bd33eb2d8e00a9f8b6261d815db503311Eric Laurent switch (ringerMode) { 3096bffc3d1bd33eb2d8e00a9f8b6261d815db503311Eric Laurent case RINGER_MODE_NORMAL: 3097bffc3d1bd33eb2d8e00a9f8b6261d815db503311Eric Laurent if (direction == AudioManager.ADJUST_LOWER) { 3098bffc3d1bd33eb2d8e00a9f8b6261d815db503311Eric Laurent if (mHasVibrator) { 3099244820185269991186d07068b92985624cede4a5Eric Laurent // "step" is the delta in internal index units corresponding to a 3100244820185269991186d07068b92985624cede4a5Eric Laurent // change of 1 in UI index units. 3101244820185269991186d07068b92985624cede4a5Eric Laurent // Because of rounding when rescaling from one stream index range to its alias 3102244820185269991186d07068b92985624cede4a5Eric Laurent // index range, we cannot simply test oldIndex == step: 3103244820185269991186d07068b92985624cede4a5Eric Laurent // (step <= oldIndex < 2 * step) is equivalent to: (old UI index == 1) 3104244820185269991186d07068b92985624cede4a5Eric Laurent if (step <= oldIndex && oldIndex < 2 * step) { 3105bffc3d1bd33eb2d8e00a9f8b6261d815db503311Eric Laurent ringerMode = RINGER_MODE_VIBRATE; 3106bffc3d1bd33eb2d8e00a9f8b6261d815db503311Eric Laurent } 3107bffc3d1bd33eb2d8e00a9f8b6261d815db503311Eric Laurent } else { 3108244820185269991186d07068b92985624cede4a5Eric Laurent // (oldIndex < step) is equivalent to (old UI index == 0) 31098600534df66c2ff5846ed230b50c56229322d48aJohn Spurlock if ((oldIndex < step) 31108600534df66c2ff5846ed230b50c56229322d48aJohn Spurlock && VOLUME_SETS_RINGER_MODE_SILENT 31118600534df66c2ff5846ed230b50c56229322d48aJohn Spurlock && mPrevVolDirection != AudioManager.ADJUST_LOWER) { 3112bffc3d1bd33eb2d8e00a9f8b6261d815db503311Eric Laurent ringerMode = RINGER_MODE_SILENT; 3113bffc3d1bd33eb2d8e00a9f8b6261d815db503311Eric Laurent } 31143d4c06f90726a85e89dab13c41ddc15b9c912a3fEric Laurent } 31156329bf7b1e2217c6c9477bd57349a1edade18417Daniel Sandler } 3116bffc3d1bd33eb2d8e00a9f8b6261d815db503311Eric Laurent break; 3117bffc3d1bd33eb2d8e00a9f8b6261d815db503311Eric Laurent case RINGER_MODE_VIBRATE: 3118bffc3d1bd33eb2d8e00a9f8b6261d815db503311Eric Laurent if (!mHasVibrator) { 3119bffc3d1bd33eb2d8e00a9f8b6261d815db503311Eric Laurent Log.e(TAG, "checkForRingerModeChange() current ringer mode is vibrate" + 3120bffc3d1bd33eb2d8e00a9f8b6261d815db503311Eric Laurent "but no vibrator is present"); 3121bffc3d1bd33eb2d8e00a9f8b6261d815db503311Eric Laurent break; 3122bffc3d1bd33eb2d8e00a9f8b6261d815db503311Eric Laurent } 3123c696a53d1fe4d61373c5dc64dd057d322da90c8fAmith Yamasani if ((direction == AudioManager.ADJUST_LOWER)) { 3124795a51469701b4339eed4d97b6b06560f2d16d3fJohn Spurlock if (mPrevVolDirection != AudioManager.ADJUST_LOWER) { 3125795a51469701b4339eed4d97b6b06560f2d16d3fJohn Spurlock if (VOLUME_SETS_RINGER_MODE_SILENT) { 3126795a51469701b4339eed4d97b6b06560f2d16d3fJohn Spurlock ringerMode = RINGER_MODE_SILENT; 3127795a51469701b4339eed4d97b6b06560f2d16d3fJohn Spurlock } else { 3128795a51469701b4339eed4d97b6b06560f2d16d3fJohn Spurlock result |= AudioManager.FLAG_SHOW_VIBRATE_HINT; 3129795a51469701b4339eed4d97b6b06560f2d16d3fJohn Spurlock } 3130c696a53d1fe4d61373c5dc64dd057d322da90c8fAmith Yamasani } 3131c696a53d1fe4d61373c5dc64dd057d322da90c8fAmith Yamasani } else if (direction == AudioManager.ADJUST_RAISE) { 3132bffc3d1bd33eb2d8e00a9f8b6261d815db503311Eric Laurent ringerMode = RINGER_MODE_NORMAL; 3133c696a53d1fe4d61373c5dc64dd057d322da90c8fAmith Yamasani } 3134a11b4affcad3d255aa723a89b768ea222506f2e8John Spurlock result &= ~FLAG_ADJUST_VOLUME; 3135bffc3d1bd33eb2d8e00a9f8b6261d815db503311Eric Laurent break; 3136bffc3d1bd33eb2d8e00a9f8b6261d815db503311Eric Laurent case RINGER_MODE_SILENT: 31379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (direction == AudioManager.ADJUST_RAISE) { 3138a11b4affcad3d255aa723a89b768ea222506f2e8John Spurlock if (PREVENT_VOLUME_ADJUSTMENT_IF_SILENT) { 3139a11b4affcad3d255aa723a89b768ea222506f2e8John Spurlock result |= AudioManager.FLAG_SHOW_SILENT_HINT; 3140bffc3d1bd33eb2d8e00a9f8b6261d815db503311Eric Laurent } else { 3141a11b4affcad3d255aa723a89b768ea222506f2e8John Spurlock if (mHasVibrator) { 3142a11b4affcad3d255aa723a89b768ea222506f2e8John Spurlock ringerMode = RINGER_MODE_VIBRATE; 3143a11b4affcad3d255aa723a89b768ea222506f2e8John Spurlock } else { 3144a11b4affcad3d255aa723a89b768ea222506f2e8John Spurlock ringerMode = RINGER_MODE_NORMAL; 3145a11b4affcad3d255aa723a89b768ea222506f2e8John Spurlock } 3146bffc3d1bd33eb2d8e00a9f8b6261d815db503311Eric Laurent } 31479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3148a11b4affcad3d255aa723a89b768ea222506f2e8John Spurlock result &= ~FLAG_ADJUST_VOLUME; 3149bffc3d1bd33eb2d8e00a9f8b6261d815db503311Eric Laurent break; 3150bffc3d1bd33eb2d8e00a9f8b6261d815db503311Eric Laurent default: 3151bffc3d1bd33eb2d8e00a9f8b6261d815db503311Eric Laurent Log.e(TAG, "checkForRingerModeChange() wrong ringer mode: "+ringerMode); 3152bffc3d1bd33eb2d8e00a9f8b6261d815db503311Eric Laurent break; 31539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 31549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3155661f2cf45860d2e10924e6b69966a9afe255f28bJohn Spurlock setRingerMode(ringerMode, TAG + ".checkForRingerModeChange", false /*external*/); 31569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 315725101b0b9a84571ead15b26e9f4cd9c4298d7823Eric Laurent mPrevVolDirection = direction; 315825101b0b9a84571ead15b26e9f4cd9c4298d7823Eric Laurent 3159a11b4affcad3d255aa723a89b768ea222506f2e8John Spurlock return result; 31609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 31619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 31623346a802087f621c6441bc512dfcc17b07143fc6John Spurlock @Override 31639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public boolean isStreamAffectedByRingerMode(int streamType) { 31649bcf401d13d47416043a704430388abd59aef7cdEric Laurent return (mRingerModeAffectedStreams & (1 << streamType)) != 0; 31659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 31669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 31675b4e654d0c7de8e4d58d73e73b0d5220f19b68f7Eric Laurent private boolean isStreamMutedByRingerMode(int streamType) { 31685b4e654d0c7de8e4d58d73e73b0d5220f19b68f7Eric Laurent return (mRingerModeMutedStreams & (1 << streamType)) != 0; 31695b4e654d0c7de8e4d58d73e73b0d5220f19b68f7Eric Laurent } 31705b4e654d0c7de8e4d58d73e73b0d5220f19b68f7Eric Laurent 317124e0d9b6c40712a297e4c287435a3b0fdd30e9daEric Laurent boolean updateRingerModeAffectedStreams() { 317224e0d9b6c40712a297e4c287435a3b0fdd30e9daEric Laurent int ringerModeAffectedStreams; 317324e0d9b6c40712a297e4c287435a3b0fdd30e9daEric Laurent // make sure settings for ringer mode are consistent with device type: non voice capable 317424e0d9b6c40712a297e4c287435a3b0fdd30e9daEric Laurent // devices (tablets) include media stream in silent mode whereas phones don't. 317524e0d9b6c40712a297e4c287435a3b0fdd30e9daEric Laurent ringerModeAffectedStreams = Settings.System.getIntForUser(mContentResolver, 317624e0d9b6c40712a297e4c287435a3b0fdd30e9daEric Laurent Settings.System.MODE_RINGER_STREAMS_AFFECTED, 317724e0d9b6c40712a297e4c287435a3b0fdd30e9daEric Laurent ((1 << AudioSystem.STREAM_RING)|(1 << AudioSystem.STREAM_NOTIFICATION)| 317824e0d9b6c40712a297e4c287435a3b0fdd30e9daEric Laurent (1 << AudioSystem.STREAM_SYSTEM)|(1 << AudioSystem.STREAM_SYSTEM_ENFORCED)), 317924e0d9b6c40712a297e4c287435a3b0fdd30e9daEric Laurent UserHandle.USER_CURRENT); 318024e0d9b6c40712a297e4c287435a3b0fdd30e9daEric Laurent 318124e0d9b6c40712a297e4c287435a3b0fdd30e9daEric Laurent // ringtone, notification and system streams are always affected by ringer mode 318224e0d9b6c40712a297e4c287435a3b0fdd30e9daEric Laurent ringerModeAffectedStreams |= (1 << AudioSystem.STREAM_RING)| 318324e0d9b6c40712a297e4c287435a3b0fdd30e9daEric Laurent (1 << AudioSystem.STREAM_NOTIFICATION)| 318424e0d9b6c40712a297e4c287435a3b0fdd30e9daEric Laurent (1 << AudioSystem.STREAM_SYSTEM); 318524e0d9b6c40712a297e4c287435a3b0fdd30e9daEric Laurent 3186212532b58e3b17d7e9d6e1361946d909d4e372c2Eric Laurent switch (mPlatformType) { 3187212532b58e3b17d7e9d6e1361946d909d4e372c2Eric Laurent case PLATFORM_TELEVISION: 3188212532b58e3b17d7e9d6e1361946d909d4e372c2Eric Laurent ringerModeAffectedStreams = 0; 3189212532b58e3b17d7e9d6e1361946d909d4e372c2Eric Laurent break; 3190212532b58e3b17d7e9d6e1361946d909d4e372c2Eric Laurent default: 319177e54d905f8c0c9925f21a8339a893391179d9d7John Spurlock ringerModeAffectedStreams &= ~(1 << AudioSystem.STREAM_MUSIC); 3192212532b58e3b17d7e9d6e1361946d909d4e372c2Eric Laurent break; 319324e0d9b6c40712a297e4c287435a3b0fdd30e9daEric Laurent } 3194212532b58e3b17d7e9d6e1361946d909d4e372c2Eric Laurent 319524e0d9b6c40712a297e4c287435a3b0fdd30e9daEric Laurent synchronized (mCameraSoundForced) { 319624e0d9b6c40712a297e4c287435a3b0fdd30e9daEric Laurent if (mCameraSoundForced) { 319724e0d9b6c40712a297e4c287435a3b0fdd30e9daEric Laurent ringerModeAffectedStreams &= ~(1 << AudioSystem.STREAM_SYSTEM_ENFORCED); 319824e0d9b6c40712a297e4c287435a3b0fdd30e9daEric Laurent } else { 319924e0d9b6c40712a297e4c287435a3b0fdd30e9daEric Laurent ringerModeAffectedStreams |= (1 << AudioSystem.STREAM_SYSTEM_ENFORCED); 320024e0d9b6c40712a297e4c287435a3b0fdd30e9daEric Laurent } 320124e0d9b6c40712a297e4c287435a3b0fdd30e9daEric Laurent } 320224e0d9b6c40712a297e4c287435a3b0fdd30e9daEric Laurent if (mStreamVolumeAlias[AudioSystem.STREAM_DTMF] == AudioSystem.STREAM_RING) { 320324e0d9b6c40712a297e4c287435a3b0fdd30e9daEric Laurent ringerModeAffectedStreams |= (1 << AudioSystem.STREAM_DTMF); 320424e0d9b6c40712a297e4c287435a3b0fdd30e9daEric Laurent } else { 320524e0d9b6c40712a297e4c287435a3b0fdd30e9daEric Laurent ringerModeAffectedStreams &= ~(1 << AudioSystem.STREAM_DTMF); 320624e0d9b6c40712a297e4c287435a3b0fdd30e9daEric Laurent } 320724e0d9b6c40712a297e4c287435a3b0fdd30e9daEric Laurent 320824e0d9b6c40712a297e4c287435a3b0fdd30e9daEric Laurent if (ringerModeAffectedStreams != mRingerModeAffectedStreams) { 320924e0d9b6c40712a297e4c287435a3b0fdd30e9daEric Laurent Settings.System.putIntForUser(mContentResolver, 321024e0d9b6c40712a297e4c287435a3b0fdd30e9daEric Laurent Settings.System.MODE_RINGER_STREAMS_AFFECTED, 321124e0d9b6c40712a297e4c287435a3b0fdd30e9daEric Laurent ringerModeAffectedStreams, 321224e0d9b6c40712a297e4c287435a3b0fdd30e9daEric Laurent UserHandle.USER_CURRENT); 321324e0d9b6c40712a297e4c287435a3b0fdd30e9daEric Laurent mRingerModeAffectedStreams = ringerModeAffectedStreams; 321424e0d9b6c40712a297e4c287435a3b0fdd30e9daEric Laurent return true; 321524e0d9b6c40712a297e4c287435a3b0fdd30e9daEric Laurent } 321624e0d9b6c40712a297e4c287435a3b0fdd30e9daEric Laurent return false; 321724e0d9b6c40712a297e4c287435a3b0fdd30e9daEric Laurent } 321824e0d9b6c40712a297e4c287435a3b0fdd30e9daEric Laurent 32199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public boolean isStreamAffectedByMute(int streamType) { 32209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return (mMuteAffectedStreams & (1 << streamType)) != 0; 32219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 32229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 32239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private void ensureValidDirection(int direction) { 32249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (direction < AudioManager.ADJUST_LOWER || direction > AudioManager.ADJUST_RAISE) { 32259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project throw new IllegalArgumentException("Bad direction " + direction); 32269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 32279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 32289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 32296c798970ccb8759d1e613b57111daa8da0ab44c7Lei Zhang private void ensureValidSteps(int steps) { 32306c798970ccb8759d1e613b57111daa8da0ab44c7Lei Zhang if (Math.abs(steps) > MAX_BATCH_VOLUME_ADJUST_STEPS) { 32316c798970ccb8759d1e613b57111daa8da0ab44c7Lei Zhang throw new IllegalArgumentException("Bad volume adjust steps " + steps); 32326c798970ccb8759d1e613b57111daa8da0ab44c7Lei Zhang } 32336c798970ccb8759d1e613b57111daa8da0ab44c7Lei Zhang } 32346c798970ccb8759d1e613b57111daa8da0ab44c7Lei Zhang 32359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private void ensureValidStreamType(int streamType) { 32369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (streamType < 0 || streamType >= mStreamStates.length) { 32379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project throw new IllegalArgumentException("Bad stream type " + streamType); 32389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 32399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 32409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 32416d5176638c2189595cede38fb92c3e7e8700e221Eric Laurent private boolean isInCommunication() { 32420eb1e402c7e612887e38dc5516f11506b11fd835Nancy Chen boolean IsInCall = false; 324325101b0b9a84571ead15b26e9f4cd9c4298d7823Eric Laurent 3244ef9f6f957d897ea0ed82114185b8fa3fefd4917bTyler Gunn TelecomManager telecomManager = 3245ef9f6f957d897ea0ed82114185b8fa3fefd4917bTyler Gunn (TelecomManager) mContext.getSystemService(Context.TELECOM_SERVICE); 324638edfda9bdd282228db08e3cc449b554b8744625Eric Laurent 324738edfda9bdd282228db08e3cc449b554b8744625Eric Laurent final long ident = Binder.clearCallingIdentity(); 3248ef9f6f957d897ea0ed82114185b8fa3fefd4917bTyler Gunn IsInCall = telecomManager.isInCall(); 324938edfda9bdd282228db08e3cc449b554b8744625Eric Laurent Binder.restoreCallingIdentity(ident); 32509eb45934c582a0bf5060125690de8bce4f10ca76Santos Cordon 32510eb1e402c7e612887e38dc5516f11506b11fd835Nancy Chen return (IsInCall || getMode() == AudioManager.MODE_IN_COMMUNICATION); 32526d5176638c2189595cede38fb92c3e7e8700e221Eric Laurent } 325325101b0b9a84571ead15b26e9f4cd9c4298d7823Eric Laurent 3254fca1e603236b8d1681f784e77e3719d1d59c1428Jean-Michel Trivi /** 3255fca1e603236b8d1681f784e77e3719d1d59c1428Jean-Michel Trivi * For code clarity for getActiveStreamType(int) 3256fca1e603236b8d1681f784e77e3719d1d59c1428Jean-Michel Trivi * @param delay_ms max time since last STREAM_MUSIC activity to consider 3257fca1e603236b8d1681f784e77e3719d1d59c1428Jean-Michel Trivi * @return true if STREAM_MUSIC is active in streams handled by AudioFlinger now or 3258fca1e603236b8d1681f784e77e3719d1d59c1428Jean-Michel Trivi * in the last "delay_ms" ms. 3259fca1e603236b8d1681f784e77e3719d1d59c1428Jean-Michel Trivi */ 3260fca1e603236b8d1681f784e77e3719d1d59c1428Jean-Michel Trivi private boolean isAfMusicActiveRecently(int delay_ms) { 3261fca1e603236b8d1681f784e77e3719d1d59c1428Jean-Michel Trivi return AudioSystem.isStreamActive(AudioSystem.STREAM_MUSIC, delay_ms) 3262fca1e603236b8d1681f784e77e3719d1d59c1428Jean-Michel Trivi || AudioSystem.isStreamActiveRemotely(AudioSystem.STREAM_MUSIC, delay_ms); 3263fca1e603236b8d1681f784e77e3719d1d59c1428Jean-Michel Trivi } 3264fca1e603236b8d1681f784e77e3719d1d59c1428Jean-Michel Trivi 32656d5176638c2189595cede38fb92c3e7e8700e221Eric Laurent private int getActiveStreamType(int suggestedStreamType) { 3266212532b58e3b17d7e9d6e1361946d909d4e372c2Eric Laurent switch (mPlatformType) { 3267212532b58e3b17d7e9d6e1361946d909d4e372c2Eric Laurent case PLATFORM_VOICE: 32686d5176638c2189595cede38fb92c3e7e8700e221Eric Laurent if (isInCommunication()) { 326925101b0b9a84571ead15b26e9f4cd9c4298d7823Eric Laurent if (AudioSystem.getForceUse(AudioSystem.FOR_COMMUNICATION) 327025101b0b9a84571ead15b26e9f4cd9c4298d7823Eric Laurent == AudioSystem.FORCE_BT_SCO) { 327125101b0b9a84571ead15b26e9f4cd9c4298d7823Eric Laurent // Log.v(TAG, "getActiveStreamType: Forcing STREAM_BLUETOOTH_SCO..."); 327225101b0b9a84571ead15b26e9f4cd9c4298d7823Eric Laurent return AudioSystem.STREAM_BLUETOOTH_SCO; 327325101b0b9a84571ead15b26e9f4cd9c4298d7823Eric Laurent } else { 327425101b0b9a84571ead15b26e9f4cd9c4298d7823Eric Laurent // Log.v(TAG, "getActiveStreamType: Forcing STREAM_VOICE_CALL..."); 327525101b0b9a84571ead15b26e9f4cd9c4298d7823Eric Laurent return AudioSystem.STREAM_VOICE_CALL; 327625101b0b9a84571ead15b26e9f4cd9c4298d7823Eric Laurent } 32773114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi } else if (suggestedStreamType == AudioManager.USE_DEFAULT_STREAM_TYPE) { 3278873cc45da2463a11182fe94a2565364d7e1709bbJean-Michel Trivi if (isAfMusicActiveRecently(StreamOverride.sDelayMs)) { 32793114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi if (DEBUG_VOL) 32803114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi Log.v(TAG, "getActiveStreamType: Forcing STREAM_MUSIC stream active"); 32813114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi return AudioSystem.STREAM_MUSIC; 3282fca1e603236b8d1681f784e77e3719d1d59c1428Jean-Michel Trivi } else { 3283fca1e603236b8d1681f784e77e3719d1d59c1428Jean-Michel Trivi if (DEBUG_VOL) 3284fca1e603236b8d1681f784e77e3719d1d59c1428Jean-Michel Trivi Log.v(TAG, "getActiveStreamType: Forcing STREAM_RING b/c default"); 3285fca1e603236b8d1681f784e77e3719d1d59c1428Jean-Michel Trivi return AudioSystem.STREAM_RING; 32863114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi } 3287fca1e603236b8d1681f784e77e3719d1d59c1428Jean-Michel Trivi } else if (isAfMusicActiveRecently(0)) { 32883114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi if (DEBUG_VOL) 32893114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi Log.v(TAG, "getActiveStreamType: Forcing STREAM_MUSIC stream active"); 329025101b0b9a84571ead15b26e9f4cd9c4298d7823Eric Laurent return AudioSystem.STREAM_MUSIC; 329125101b0b9a84571ead15b26e9f4cd9c4298d7823Eric Laurent } 3292212532b58e3b17d7e9d6e1361946d909d4e372c2Eric Laurent break; 3293212532b58e3b17d7e9d6e1361946d909d4e372c2Eric Laurent case PLATFORM_TELEVISION: 3294212532b58e3b17d7e9d6e1361946d909d4e372c2Eric Laurent if (suggestedStreamType == AudioManager.USE_DEFAULT_STREAM_TYPE) { 32952811dd337262934ea82477f9598f3e49092edb5eRoboErik // TV always defaults to STREAM_MUSIC 3296212532b58e3b17d7e9d6e1361946d909d4e372c2Eric Laurent return AudioSystem.STREAM_MUSIC; 3297212532b58e3b17d7e9d6e1361946d909d4e372c2Eric Laurent } 3298212532b58e3b17d7e9d6e1361946d909d4e372c2Eric Laurent break; 3299212532b58e3b17d7e9d6e1361946d909d4e372c2Eric Laurent default: 33006d5176638c2189595cede38fb92c3e7e8700e221Eric Laurent if (isInCommunication()) { 330125101b0b9a84571ead15b26e9f4cd9c4298d7823Eric Laurent if (AudioSystem.getForceUse(AudioSystem.FOR_COMMUNICATION) 330225101b0b9a84571ead15b26e9f4cd9c4298d7823Eric Laurent == AudioSystem.FORCE_BT_SCO) { 33033114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi if (DEBUG_VOL) Log.v(TAG, "getActiveStreamType: Forcing STREAM_BLUETOOTH_SCO"); 330425101b0b9a84571ead15b26e9f4cd9c4298d7823Eric Laurent return AudioSystem.STREAM_BLUETOOTH_SCO; 330525101b0b9a84571ead15b26e9f4cd9c4298d7823Eric Laurent } else { 33063114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi if (DEBUG_VOL) Log.v(TAG, "getActiveStreamType: Forcing STREAM_VOICE_CALL"); 330725101b0b9a84571ead15b26e9f4cd9c4298d7823Eric Laurent return AudioSystem.STREAM_VOICE_CALL; 330825101b0b9a84571ead15b26e9f4cd9c4298d7823Eric Laurent } 330925101b0b9a84571ead15b26e9f4cd9c4298d7823Eric Laurent } else if (AudioSystem.isStreamActive(AudioSystem.STREAM_NOTIFICATION, 3310873cc45da2463a11182fe94a2565364d7e1709bbJean-Michel Trivi StreamOverride.sDelayMs) || 33113114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi AudioSystem.isStreamActive(AudioSystem.STREAM_RING, 3312873cc45da2463a11182fe94a2565364d7e1709bbJean-Michel Trivi StreamOverride.sDelayMs)) { 33133114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi if (DEBUG_VOL) Log.v(TAG, "getActiveStreamType: Forcing STREAM_NOTIFICATION"); 331425101b0b9a84571ead15b26e9f4cd9c4298d7823Eric Laurent return AudioSystem.STREAM_NOTIFICATION; 33153114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi } else if (suggestedStreamType == AudioManager.USE_DEFAULT_STREAM_TYPE) { 3316873cc45da2463a11182fe94a2565364d7e1709bbJean-Michel Trivi if (isAfMusicActiveRecently(StreamOverride.sDelayMs)) { 3317fca1e603236b8d1681f784e77e3719d1d59c1428Jean-Michel Trivi if (DEBUG_VOL) Log.v(TAG, "getActiveStreamType: forcing STREAM_MUSIC"); 3318fca1e603236b8d1681f784e77e3719d1d59c1428Jean-Michel Trivi return AudioSystem.STREAM_MUSIC; 33193114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi } else { 3320eb1d88ddf9a0888455c82b83f19da124e5ca6f16John Spurlock if (DEBUG_VOL) Log.v(TAG, 3321eb1d88ddf9a0888455c82b83f19da124e5ca6f16John Spurlock "getActiveStreamType: using STREAM_NOTIFICATION as default"); 3322eb1d88ddf9a0888455c82b83f19da124e5ca6f16John Spurlock return AudioSystem.STREAM_NOTIFICATION; 33233114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi } 3324c7fcba4b7bd3d78e7cfe975a3f8e4dde2f6738b7Joe Onorato } 3325212532b58e3b17d7e9d6e1361946d909d4e372c2Eric Laurent break; 33269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3327212532b58e3b17d7e9d6e1361946d909d4e372c2Eric Laurent if (DEBUG_VOL) Log.v(TAG, "getActiveStreamType: Returning suggested type " 3328212532b58e3b17d7e9d6e1361946d909d4e372c2Eric Laurent + suggestedStreamType); 3329212532b58e3b17d7e9d6e1361946d909d4e372c2Eric Laurent return suggestedStreamType; 33309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 33319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3332bcc1087af40a0e1bb35dbe8a39c830ecdea8280bJohn Spurlock private void broadcastRingerMode(String action, int ringerMode) { 33339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Send sticky broadcast 3334bcc1087af40a0e1bb35dbe8a39c830ecdea8280bJohn Spurlock Intent broadcast = new Intent(action); 3335ba195ebc76f23b6679443724ab58c9dc9f2df884Glenn Kasten broadcast.putExtra(AudioManager.EXTRA_RINGER_MODE, ringerMode); 33361c633fc89bae9bf0af6fe643ac7ad2e744f27bedDianne Hackborn broadcast.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT 33371c633fc89bae9bf0af6fe643ac7ad2e744f27bedDianne Hackborn | Intent.FLAG_RECEIVER_REPLACE_PENDING); 33385ac72a29593ab9a20337a2225df52bdf4754be02Dianne Hackborn sendStickyBroadcastToAll(broadcast); 33399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 33409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 33419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private void broadcastVibrateSetting(int vibrateType) { 33429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Send broadcast 33439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (ActivityManagerNative.isSystemReady()) { 33449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Intent broadcast = new Intent(AudioManager.VIBRATE_SETTING_CHANGED_ACTION); 33459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project broadcast.putExtra(AudioManager.EXTRA_VIBRATE_TYPE, vibrateType); 33469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project broadcast.putExtra(AudioManager.EXTRA_VIBRATE_SETTING, getVibrateSetting(vibrateType)); 33475ac72a29593ab9a20337a2225df52bdf4754be02Dianne Hackborn sendBroadcastToAll(broadcast); 33489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 33499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 33509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 33519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Message helper methods 33522d8dab5a549b25b6f36df4614d7c0166d4d099e2Jean-Michel Trivi /** 33532d8dab5a549b25b6f36df4614d7c0166d4d099e2Jean-Michel Trivi * Queue a message on the given handler's message queue, after acquiring the service wake lock. 33542d8dab5a549b25b6f36df4614d7c0166d4d099e2Jean-Michel Trivi * Note that the wake lock needs to be released after the message has been handled. 33552d8dab5a549b25b6f36df4614d7c0166d4d099e2Jean-Michel Trivi */ 33562d8dab5a549b25b6f36df4614d7c0166d4d099e2Jean-Michel Trivi private void queueMsgUnderWakeLock(Handler handler, int msg, 33572d8dab5a549b25b6f36df4614d7c0166d4d099e2Jean-Michel Trivi int arg1, int arg2, Object obj, int delay) { 3358a4dfbdc54d8898491d3a7d1d9d818c7db3fd773dEric Laurent final long ident = Binder.clearCallingIdentity(); 3359a4dfbdc54d8898491d3a7d1d9d818c7db3fd773dEric Laurent // Always acquire the wake lock as AudioService because it is released by the 3360a4dfbdc54d8898491d3a7d1d9d818c7db3fd773dEric Laurent // message handler. 3361fa9a69805b001034aa04c3b33989a7ac21522371Jean-Michel Trivi mAudioEventWakeLock.acquire(); 3362a4dfbdc54d8898491d3a7d1d9d818c7db3fd773dEric Laurent Binder.restoreCallingIdentity(ident); 33632d8dab5a549b25b6f36df4614d7c0166d4d099e2Jean-Michel Trivi sendMsg(handler, msg, SENDMSG_QUEUE, arg1, arg2, obj, delay); 33642d8dab5a549b25b6f36df4614d7c0166d4d099e2Jean-Michel Trivi } 33659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3366afbb047c3945e9c2b7e9bc6b25098d5fb80bba4eEric Laurent private static void sendMsg(Handler handler, int msg, 33679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int existingMsgPolicy, int arg1, int arg2, Object obj, int delay) { 33689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 33699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (existingMsgPolicy == SENDMSG_REPLACE) { 33709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project handler.removeMessages(msg); 33719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else if (existingMsgPolicy == SENDMSG_NOOP && handler.hasMessages(msg)) { 33729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return; 33739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3374adbe8bf85f3c8230d16ae5cb3f5d9736e09ed84aEric Laurent synchronized (mLastDeviceConnectMsgTime) { 3375adbe8bf85f3c8230d16ae5cb3f5d9736e09ed84aEric Laurent long time = SystemClock.uptimeMillis() + delay; 3376adbe8bf85f3c8230d16ae5cb3f5d9736e09ed84aEric Laurent handler.sendMessageAtTime(handler.obtainMessage(msg, arg1, arg2, obj), time); 3377adbe8bf85f3c8230d16ae5cb3f5d9736e09ed84aEric Laurent if (msg == MSG_SET_WIRED_DEVICE_CONNECTION_STATE || 3378adbe8bf85f3c8230d16ae5cb3f5d9736e09ed84aEric Laurent msg == MSG_SET_A2DP_SRC_CONNECTION_STATE || 3379adbe8bf85f3c8230d16ae5cb3f5d9736e09ed84aEric Laurent msg == MSG_SET_A2DP_SINK_CONNECTION_STATE) { 3380adbe8bf85f3c8230d16ae5cb3f5d9736e09ed84aEric Laurent mLastDeviceConnectMsgTime = time; 3381adbe8bf85f3c8230d16ae5cb3f5d9736e09ed84aEric Laurent } 3382adbe8bf85f3c8230d16ae5cb3f5d9736e09ed84aEric Laurent } 33839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 33849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 33859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project boolean checkAudioSettingsPermission(String method) { 3386ccd654e9d4c38da0d652c442e7a2ca3f447e9abeJean-Michel Trivi if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.MODIFY_AUDIO_SETTINGS) 33879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project == PackageManager.PERMISSION_GRANTED) { 33889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return true; 33899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 33909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project String msg = "Audio Settings Permission Denial: " + method + " from pid=" 33919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project + Binder.getCallingPid() 33929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project + ", uid=" + Binder.getCallingUid(); 33939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Log.w(TAG, msg); 33949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return false; 33959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 33969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 33979bc8358ddaa01c3490f9709991989633a6a3dd42Eric Laurent private int getDeviceForStream(int stream) { 33989bc8358ddaa01c3490f9709991989633a6a3dd42Eric Laurent int device = AudioSystem.getDevicesForStream(stream); 33999bc8358ddaa01c3490f9709991989633a6a3dd42Eric Laurent if ((device & (device - 1)) != 0) { 34009bc8358ddaa01c3490f9709991989633a6a3dd42Eric Laurent // Multiple device selection is either: 34019bc8358ddaa01c3490f9709991989633a6a3dd42Eric Laurent // - speaker + one other device: give priority to speaker in this case. 34029bc8358ddaa01c3490f9709991989633a6a3dd42Eric Laurent // - one A2DP device + another device: happens with duplicated output. In this case 34039bc8358ddaa01c3490f9709991989633a6a3dd42Eric Laurent // retain the device on the A2DP output as the other must not correspond to an active 34049bc8358ddaa01c3490f9709991989633a6a3dd42Eric Laurent // selection if not the speaker. 3405c9ff968787d4744194f9985ebaf8ce7efdd12256Jungshik Jang // - HDMI-CEC system audio mode only output: give priority to available item in order. 34069bc8358ddaa01c3490f9709991989633a6a3dd42Eric Laurent if ((device & AudioSystem.DEVICE_OUT_SPEAKER) != 0) { 34079bc8358ddaa01c3490f9709991989633a6a3dd42Eric Laurent device = AudioSystem.DEVICE_OUT_SPEAKER; 3408c9ff968787d4744194f9985ebaf8ce7efdd12256Jungshik Jang } else if ((device & AudioSystem.DEVICE_OUT_HDMI_ARC) != 0) { 3409c9ff968787d4744194f9985ebaf8ce7efdd12256Jungshik Jang device = AudioSystem.DEVICE_OUT_HDMI_ARC; 3410c9ff968787d4744194f9985ebaf8ce7efdd12256Jungshik Jang } else if ((device & AudioSystem.DEVICE_OUT_SPDIF) != 0) { 3411c9ff968787d4744194f9985ebaf8ce7efdd12256Jungshik Jang device = AudioSystem.DEVICE_OUT_SPDIF; 3412c9ff968787d4744194f9985ebaf8ce7efdd12256Jungshik Jang } else if ((device & AudioSystem.DEVICE_OUT_AUX_LINE) != 0) { 3413c9ff968787d4744194f9985ebaf8ce7efdd12256Jungshik Jang device = AudioSystem.DEVICE_OUT_AUX_LINE; 34149bc8358ddaa01c3490f9709991989633a6a3dd42Eric Laurent } else { 34159bc8358ddaa01c3490f9709991989633a6a3dd42Eric Laurent device &= AudioSystem.DEVICE_OUT_ALL_A2DP; 34169bc8358ddaa01c3490f9709991989633a6a3dd42Eric Laurent } 34179bc8358ddaa01c3490f9709991989633a6a3dd42Eric Laurent } 34189bc8358ddaa01c3490f9709991989633a6a3dd42Eric Laurent return device; 34199bc8358ddaa01c3490f9709991989633a6a3dd42Eric Laurent } 34209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3421b1fbaaccb656ef09a8770c28df15e3e91a452e64Eric Laurent public void setWiredDeviceConnectionState(int device, int state, String name) { 3422b1fbaaccb656ef09a8770c28df15e3e91a452e64Eric Laurent synchronized (mConnectedDevices) { 3423b1fbaaccb656ef09a8770c28df15e3e91a452e64Eric Laurent int delay = checkSendBecomingNoisyIntent(device, state); 34242d8dab5a549b25b6f36df4614d7c0166d4d099e2Jean-Michel Trivi queueMsgUnderWakeLock(mAudioHandler, 3425b1fbaaccb656ef09a8770c28df15e3e91a452e64Eric Laurent MSG_SET_WIRED_DEVICE_CONNECTION_STATE, 3426b1fbaaccb656ef09a8770c28df15e3e91a452e64Eric Laurent device, 3427b1fbaaccb656ef09a8770c28df15e3e91a452e64Eric Laurent state, 3428b1fbaaccb656ef09a8770c28df15e3e91a452e64Eric Laurent name, 3429b1fbaaccb656ef09a8770c28df15e3e91a452e64Eric Laurent delay); 3430b1fbaaccb656ef09a8770c28df15e3e91a452e64Eric Laurent } 3431b1fbaaccb656ef09a8770c28df15e3e91a452e64Eric Laurent } 3432b1fbaaccb656ef09a8770c28df15e3e91a452e64Eric Laurent 34330a40ec2192e4836b2fcb6ba51a7688aa6bd4ee98Mike Lockwood public int setBluetoothA2dpDeviceConnectionState(BluetoothDevice device, int state, int profile) 3434b1fbaaccb656ef09a8770c28df15e3e91a452e64Eric Laurent { 3435b1fbaaccb656ef09a8770c28df15e3e91a452e64Eric Laurent int delay; 34360a40ec2192e4836b2fcb6ba51a7688aa6bd4ee98Mike Lockwood if (profile != BluetoothProfile.A2DP && profile != BluetoothProfile.A2DP_SINK) { 34370a40ec2192e4836b2fcb6ba51a7688aa6bd4ee98Mike Lockwood throw new IllegalArgumentException("invalid profile " + profile); 34380a40ec2192e4836b2fcb6ba51a7688aa6bd4ee98Mike Lockwood } 3439b1fbaaccb656ef09a8770c28df15e3e91a452e64Eric Laurent synchronized (mConnectedDevices) { 34400a40ec2192e4836b2fcb6ba51a7688aa6bd4ee98Mike Lockwood if (profile == BluetoothProfile.A2DP) { 34410a40ec2192e4836b2fcb6ba51a7688aa6bd4ee98Mike Lockwood delay = checkSendBecomingNoisyIntent(AudioSystem.DEVICE_OUT_BLUETOOTH_A2DP, 34420a40ec2192e4836b2fcb6ba51a7688aa6bd4ee98Mike Lockwood (state == BluetoothA2dp.STATE_CONNECTED) ? 1 : 0); 34430a40ec2192e4836b2fcb6ba51a7688aa6bd4ee98Mike Lockwood } else { 34440a40ec2192e4836b2fcb6ba51a7688aa6bd4ee98Mike Lockwood delay = 0; 34450a40ec2192e4836b2fcb6ba51a7688aa6bd4ee98Mike Lockwood } 34462d8dab5a549b25b6f36df4614d7c0166d4d099e2Jean-Michel Trivi queueMsgUnderWakeLock(mAudioHandler, 34470a40ec2192e4836b2fcb6ba51a7688aa6bd4ee98Mike Lockwood (profile == BluetoothProfile.A2DP ? 34480a40ec2192e4836b2fcb6ba51a7688aa6bd4ee98Mike Lockwood MSG_SET_A2DP_SINK_CONNECTION_STATE : MSG_SET_A2DP_SRC_CONNECTION_STATE), 3449b1fbaaccb656ef09a8770c28df15e3e91a452e64Eric Laurent state, 3450b1fbaaccb656ef09a8770c28df15e3e91a452e64Eric Laurent 0, 3451b1fbaaccb656ef09a8770c28df15e3e91a452e64Eric Laurent device, 3452b1fbaaccb656ef09a8770c28df15e3e91a452e64Eric Laurent delay); 3453b1fbaaccb656ef09a8770c28df15e3e91a452e64Eric Laurent } 3454b1fbaaccb656ef09a8770c28df15e3e91a452e64Eric Laurent return delay; 3455b1fbaaccb656ef09a8770c28df15e3e91a452e64Eric Laurent } 3456b1fbaaccb656ef09a8770c28df15e3e91a452e64Eric Laurent 34579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /////////////////////////////////////////////////////////////////////////// 34589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Inner classes 34599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /////////////////////////////////////////////////////////////////////////// 34609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 34618fa4d6f585f40ff5cf5f9bed316d92c64a306f21Eric Laurent // NOTE: Locking order for synchronized objects related to volume or ringer mode management: 34628fa4d6f585f40ff5cf5f9bed316d92c64a306f21Eric Laurent // 1 mScoclient OR mSafeMediaVolumeState 34638fa4d6f585f40ff5cf5f9bed316d92c64a306f21Eric Laurent // 2 mSetModeDeathHandlers 34648fa4d6f585f40ff5cf5f9bed316d92c64a306f21Eric Laurent // 3 mSettingsLock 34658fa4d6f585f40ff5cf5f9bed316d92c64a306f21Eric Laurent // 4 VolumeStreamState.class 34668fa4d6f585f40ff5cf5f9bed316d92c64a306f21Eric Laurent // 5 mCameraSoundForced 34679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public class VolumeStreamState { 34689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private final int mStreamType; 34699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 347011a74a75653197a3d31fe91590cd8312f5270c44Jean-Michel Trivi private String mVolumeIndexSettingName; 3471a553c25b33c99b345cf1c8688f8df0ed8df14e5aEric Laurent private int mIndexMax; 34723172d5e3e7520a745fa37b71fc1c7bf244b57085Eric Laurent private final ConcurrentHashMap<Integer, Integer> mIndex = 34733172d5e3e7520a745fa37b71fc1c7bf244b57085Eric Laurent new ConcurrentHashMap<Integer, Integer>(8, 0.75f, 4); 34749bc8358ddaa01c3490f9709991989633a6a3dd42Eric Laurent private ArrayList<VolumeDeathHandler> mDeathHandlers; //handles mute/solo clients death 34759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3476a553c25b33c99b345cf1c8688f8df0ed8df14e5aEric Laurent private VolumeStreamState(String settingName, int streamType) { 34779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 34789bc8358ddaa01c3490f9709991989633a6a3dd42Eric Laurent mVolumeIndexSettingName = settingName; 34799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 34809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mStreamType = streamType; 34815982013cfc8274ff0bafaba83c676b3a8890cba9Jared Suttles mIndexMax = MAX_STREAM_VOLUME[streamType]; 3482a553c25b33c99b345cf1c8688f8df0ed8df14e5aEric Laurent AudioSystem.initStreamVolume(streamType, 0, mIndexMax); 3483a553c25b33c99b345cf1c8688f8df0ed8df14e5aEric Laurent mIndexMax *= 10; 34849bc8358ddaa01c3490f9709991989633a6a3dd42Eric Laurent 348533902db75011d863009585682bd08560c5b89a75Eric Laurent // mDeathHandlers must be created before calling readSettings() 34869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mDeathHandlers = new ArrayList<VolumeDeathHandler>(); 348733902db75011d863009585682bd08560c5b89a75Eric Laurent 348833902db75011d863009585682bd08560c5b89a75Eric Laurent readSettings(); 34899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 34909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 349142b041ed4f184e3af7f788eb07307f556a2a6616Eric Laurent public String getSettingNameForDevice(int device) { 349242b041ed4f184e3af7f788eb07307f556a2a6616Eric Laurent String name = mVolumeIndexSettingName; 3493948d32748caaac5be06c991ebf00f74265a7849fEric Laurent String suffix = AudioSystem.getOutputDeviceName(device); 34949bc8358ddaa01c3490f9709991989633a6a3dd42Eric Laurent if (suffix.isEmpty()) { 34959bc8358ddaa01c3490f9709991989633a6a3dd42Eric Laurent return name; 34969bc8358ddaa01c3490f9709991989633a6a3dd42Eric Laurent } 34979bc8358ddaa01c3490f9709991989633a6a3dd42Eric Laurent return name + "_" + suffix; 34989bc8358ddaa01c3490f9709991989633a6a3dd42Eric Laurent } 34999bc8358ddaa01c3490f9709991989633a6a3dd42Eric Laurent 3500fdbee869be504e399efce1127a68281bd9b158c5Eric Laurent public void readSettings() { 3501fdbee869be504e399efce1127a68281bd9b158c5Eric Laurent synchronized (VolumeStreamState.class) { 3502da39290460b30e5080769f039d6dff352b3c7808Wally Yau // force maximum volume on all streams if fixed volume property 3503da39290460b30e5080769f039d6dff352b3c7808Wally Yau // or master volume property is set 3504da39290460b30e5080769f039d6dff352b3c7808Wally Yau if (mUseFixedVolume || mUseMasterVolume) { 3505fdbee869be504e399efce1127a68281bd9b158c5Eric Laurent mIndex.put(AudioSystem.DEVICE_OUT_DEFAULT, mIndexMax); 3506fdbee869be504e399efce1127a68281bd9b158c5Eric Laurent return; 3507fdbee869be504e399efce1127a68281bd9b158c5Eric Laurent } 3508fdbee869be504e399efce1127a68281bd9b158c5Eric Laurent // do not read system stream volume from settings: this stream is always aliased 3509fdbee869be504e399efce1127a68281bd9b158c5Eric Laurent // to another stream type and its volume is never persisted. Values in settings can 3510fdbee869be504e399efce1127a68281bd9b158c5Eric Laurent // only be stale values 3511fdbee869be504e399efce1127a68281bd9b158c5Eric Laurent if ((mStreamType == AudioSystem.STREAM_SYSTEM) || 3512fdbee869be504e399efce1127a68281bd9b158c5Eric Laurent (mStreamType == AudioSystem.STREAM_SYSTEM_ENFORCED)) { 351391377de6f23af2b0b08adae22810cae6fc35cb1aEric Laurent int index = 10 * DEFAULT_STREAM_VOLUME[mStreamType]; 3514fdbee869be504e399efce1127a68281bd9b158c5Eric Laurent synchronized (mCameraSoundForced) { 3515fdbee869be504e399efce1127a68281bd9b158c5Eric Laurent if (mCameraSoundForced) { 3516fdbee869be504e399efce1127a68281bd9b158c5Eric Laurent index = mIndexMax; 3517fdbee869be504e399efce1127a68281bd9b158c5Eric Laurent } 3518dd45d01128423a82652a3c9d77fa393631d95229Eric Laurent } 3519fdbee869be504e399efce1127a68281bd9b158c5Eric Laurent mIndex.put(AudioSystem.DEVICE_OUT_DEFAULT, index); 3520fdbee869be504e399efce1127a68281bd9b158c5Eric Laurent return; 3521dd45d01128423a82652a3c9d77fa393631d95229Eric Laurent } 3522002e9d382d2daa7ed41636463ecdbddbd4897abaEric Laurent 3523fdbee869be504e399efce1127a68281bd9b158c5Eric Laurent int remainingDevices = AudioSystem.DEVICE_OUT_ALL; 352483a017b6b7c099d1a0293e5839be6477325aef06Eric Laurent 3525fdbee869be504e399efce1127a68281bd9b158c5Eric Laurent for (int i = 0; remainingDevices != 0; i++) { 3526fdbee869be504e399efce1127a68281bd9b158c5Eric Laurent int device = (1 << i); 3527fdbee869be504e399efce1127a68281bd9b158c5Eric Laurent if ((device & remainingDevices) == 0) { 3528fdbee869be504e399efce1127a68281bd9b158c5Eric Laurent continue; 3529fdbee869be504e399efce1127a68281bd9b158c5Eric Laurent } 3530fdbee869be504e399efce1127a68281bd9b158c5Eric Laurent remainingDevices &= ~device; 3531fdbee869be504e399efce1127a68281bd9b158c5Eric Laurent 3532fdbee869be504e399efce1127a68281bd9b158c5Eric Laurent // retrieve current volume for device 3533fdbee869be504e399efce1127a68281bd9b158c5Eric Laurent String name = getSettingNameForDevice(device); 3534fdbee869be504e399efce1127a68281bd9b158c5Eric Laurent // if no volume stored for current stream and device, use default volume if default 3535fdbee869be504e399efce1127a68281bd9b158c5Eric Laurent // device, continue otherwise 3536fdbee869be504e399efce1127a68281bd9b158c5Eric Laurent int defaultIndex = (device == AudioSystem.DEVICE_OUT_DEFAULT) ? 353791377de6f23af2b0b08adae22810cae6fc35cb1aEric Laurent DEFAULT_STREAM_VOLUME[mStreamType] : -1; 3538fdbee869be504e399efce1127a68281bd9b158c5Eric Laurent int index = Settings.System.getIntForUser( 3539fdbee869be504e399efce1127a68281bd9b158c5Eric Laurent mContentResolver, name, defaultIndex, UserHandle.USER_CURRENT); 3540fdbee869be504e399efce1127a68281bd9b158c5Eric Laurent if (index == -1) { 3541fdbee869be504e399efce1127a68281bd9b158c5Eric Laurent continue; 3542fdbee869be504e399efce1127a68281bd9b158c5Eric Laurent } 35439bc8358ddaa01c3490f9709991989633a6a3dd42Eric Laurent 3544212532b58e3b17d7e9d6e1361946d909d4e372c2Eric Laurent mIndex.put(device, getValidIndex(10 * index)); 3545dd45d01128423a82652a3c9d77fa393631d95229Eric Laurent } 35469bc8358ddaa01c3490f9709991989633a6a3dd42Eric Laurent } 35479bc8358ddaa01c3490f9709991989633a6a3dd42Eric Laurent } 35489bc8358ddaa01c3490f9709991989633a6a3dd42Eric Laurent 35498fa4d6f585f40ff5cf5f9bed316d92c64a306f21Eric Laurent // must be called while synchronized VolumeStreamState.class 35508fa4d6f585f40ff5cf5f9bed316d92c64a306f21Eric Laurent public void applyDeviceVolume_syncVSS(int device) { 355142b041ed4f184e3af7f788eb07307f556a2a6616Eric Laurent int index; 35528fa4d6f585f40ff5cf5f9bed316d92c64a306f21Eric Laurent if (isMuted_syncVSS()) { 355342b041ed4f184e3af7f788eb07307f556a2a6616Eric Laurent index = 0; 3554ba5270b88798c66fefc17a1b25b27894e4fb7862Jean-Michel Trivi } else if (((device & AudioSystem.DEVICE_OUT_ALL_A2DP) != 0 && mAvrcpAbsVolSupported) 3555ba5270b88798c66fefc17a1b25b27894e4fb7862Jean-Michel Trivi || ((device & mFullVolumeDevices) != 0)) { 3556c9d1d5f35091226e96fcfa91817480f589eb36e2Matthew Xie index = (mIndexMax + 5)/10; 3557cd772d04345850e160a45613fcf6b86da0dce4cfEric Laurent } else { 355842b041ed4f184e3af7f788eb07307f556a2a6616Eric Laurent index = (getIndex(device) + 5)/10; 355942b041ed4f184e3af7f788eb07307f556a2a6616Eric Laurent } 356042b041ed4f184e3af7f788eb07307f556a2a6616Eric Laurent AudioSystem.setStreamVolumeIndex(mStreamType, index, device); 35619bc8358ddaa01c3490f9709991989633a6a3dd42Eric Laurent } 35629bc8358ddaa01c3490f9709991989633a6a3dd42Eric Laurent 3563fdbee869be504e399efce1127a68281bd9b158c5Eric Laurent public void applyAllVolumes() { 3564fdbee869be504e399efce1127a68281bd9b158c5Eric Laurent synchronized (VolumeStreamState.class) { 3565fdbee869be504e399efce1127a68281bd9b158c5Eric Laurent // apply default volume first: by convention this will reset all 3566fdbee869be504e399efce1127a68281bd9b158c5Eric Laurent // devices volumes in audio policy manager to the supplied value 3567fdbee869be504e399efce1127a68281bd9b158c5Eric Laurent int index; 35688fa4d6f585f40ff5cf5f9bed316d92c64a306f21Eric Laurent if (isMuted_syncVSS()) { 3569fdbee869be504e399efce1127a68281bd9b158c5Eric Laurent index = 0; 3570fdbee869be504e399efce1127a68281bd9b158c5Eric Laurent } else { 3571fdbee869be504e399efce1127a68281bd9b158c5Eric Laurent index = (getIndex(AudioSystem.DEVICE_OUT_DEFAULT) + 5)/10; 3572fdbee869be504e399efce1127a68281bd9b158c5Eric Laurent } 3573fdbee869be504e399efce1127a68281bd9b158c5Eric Laurent AudioSystem.setStreamVolumeIndex(mStreamType, index, AudioSystem.DEVICE_OUT_DEFAULT); 3574fdbee869be504e399efce1127a68281bd9b158c5Eric Laurent // then apply device specific volumes 3575fdbee869be504e399efce1127a68281bd9b158c5Eric Laurent Set set = mIndex.entrySet(); 3576fdbee869be504e399efce1127a68281bd9b158c5Eric Laurent Iterator i = set.iterator(); 3577fdbee869be504e399efce1127a68281bd9b158c5Eric Laurent while (i.hasNext()) { 3578fdbee869be504e399efce1127a68281bd9b158c5Eric Laurent Map.Entry entry = (Map.Entry)i.next(); 3579fdbee869be504e399efce1127a68281bd9b158c5Eric Laurent int device = ((Integer)entry.getKey()).intValue(); 3580fdbee869be504e399efce1127a68281bd9b158c5Eric Laurent if (device != AudioSystem.DEVICE_OUT_DEFAULT) { 35818fa4d6f585f40ff5cf5f9bed316d92c64a306f21Eric Laurent if (isMuted_syncVSS()) { 3582fdbee869be504e399efce1127a68281bd9b158c5Eric Laurent index = 0; 3583ba5270b88798c66fefc17a1b25b27894e4fb7862Jean-Michel Trivi } else if (((device & AudioSystem.DEVICE_OUT_ALL_A2DP) != 0 && 3584ba5270b88798c66fefc17a1b25b27894e4fb7862Jean-Michel Trivi mAvrcpAbsVolSupported) 3585ba5270b88798c66fefc17a1b25b27894e4fb7862Jean-Michel Trivi || ((device & mFullVolumeDevices) != 0)) 3586ba5270b88798c66fefc17a1b25b27894e4fb7862Jean-Michel Trivi { 3587fdbee869be504e399efce1127a68281bd9b158c5Eric Laurent index = (mIndexMax + 5)/10; 3588fdbee869be504e399efce1127a68281bd9b158c5Eric Laurent } else { 3589fdbee869be504e399efce1127a68281bd9b158c5Eric Laurent index = ((Integer)entry.getValue() + 5)/10; 3590fdbee869be504e399efce1127a68281bd9b158c5Eric Laurent } 3591fdbee869be504e399efce1127a68281bd9b158c5Eric Laurent AudioSystem.setStreamVolumeIndex(mStreamType, index, device); 359242b041ed4f184e3af7f788eb07307f556a2a6616Eric Laurent } 35939bc8358ddaa01c3490f9709991989633a6a3dd42Eric Laurent } 35949bc8358ddaa01c3490f9709991989633a6a3dd42Eric Laurent } 359511a74a75653197a3d31fe91590cd8312f5270c44Jean-Michel Trivi } 359611a74a75653197a3d31fe91590cd8312f5270c44Jean-Michel Trivi 35979bc8358ddaa01c3490f9709991989633a6a3dd42Eric Laurent public boolean adjustIndex(int deltaIndex, int device) { 359842b041ed4f184e3af7f788eb07307f556a2a6616Eric Laurent return setIndex(getIndex(device) + deltaIndex, 359942b041ed4f184e3af7f788eb07307f556a2a6616Eric Laurent device); 36009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 36019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3602fdbee869be504e399efce1127a68281bd9b158c5Eric Laurent public boolean setIndex(int index, int device) { 3603fdbee869be504e399efce1127a68281bd9b158c5Eric Laurent synchronized (VolumeStreamState.class) { 3604fdbee869be504e399efce1127a68281bd9b158c5Eric Laurent int oldIndex = getIndex(device); 3605fdbee869be504e399efce1127a68281bd9b158c5Eric Laurent index = getValidIndex(index); 3606fdbee869be504e399efce1127a68281bd9b158c5Eric Laurent synchronized (mCameraSoundForced) { 3607fdbee869be504e399efce1127a68281bd9b158c5Eric Laurent if ((mStreamType == AudioSystem.STREAM_SYSTEM_ENFORCED) && mCameraSoundForced) { 3608fdbee869be504e399efce1127a68281bd9b158c5Eric Laurent index = mIndexMax; 3609fdbee869be504e399efce1127a68281bd9b158c5Eric Laurent } 3610dd45d01128423a82652a3c9d77fa393631d95229Eric Laurent } 3611fdbee869be504e399efce1127a68281bd9b158c5Eric Laurent mIndex.put(device, index); 3612fdbee869be504e399efce1127a68281bd9b158c5Eric Laurent 3613fdbee869be504e399efce1127a68281bd9b158c5Eric Laurent if (oldIndex != index) { 3614fdbee869be504e399efce1127a68281bd9b158c5Eric Laurent // Apply change to all streams using this one as alias 3615fdbee869be504e399efce1127a68281bd9b158c5Eric Laurent // if changing volume of current device, also change volume of current 3616fdbee869be504e399efce1127a68281bd9b158c5Eric Laurent // device on aliased stream 3617fdbee869be504e399efce1127a68281bd9b158c5Eric Laurent boolean currentDevice = (device == getDeviceForStream(mStreamType)); 3618fdbee869be504e399efce1127a68281bd9b158c5Eric Laurent int numStreamTypes = AudioSystem.getNumStreamTypes(); 3619fdbee869be504e399efce1127a68281bd9b158c5Eric Laurent for (int streamType = numStreamTypes - 1; streamType >= 0; streamType--) { 3620fdbee869be504e399efce1127a68281bd9b158c5Eric Laurent if (streamType != mStreamType && 3621fdbee869be504e399efce1127a68281bd9b158c5Eric Laurent mStreamVolumeAlias[streamType] == mStreamType) { 3622fdbee869be504e399efce1127a68281bd9b158c5Eric Laurent int scaledIndex = rescaleIndex(index, mStreamType, streamType); 3623bffc3d1bd33eb2d8e00a9f8b6261d815db503311Eric Laurent mStreamStates[streamType].setIndex(scaledIndex, 3624fdbee869be504e399efce1127a68281bd9b158c5Eric Laurent device); 3625fdbee869be504e399efce1127a68281bd9b158c5Eric Laurent if (currentDevice) { 3626fdbee869be504e399efce1127a68281bd9b158c5Eric Laurent mStreamStates[streamType].setIndex(scaledIndex, 3627fdbee869be504e399efce1127a68281bd9b158c5Eric Laurent getDeviceForStream(streamType)); 3628fdbee869be504e399efce1127a68281bd9b158c5Eric Laurent } 3629bffc3d1bd33eb2d8e00a9f8b6261d815db503311Eric Laurent } 3630a553c25b33c99b345cf1c8688f8df0ed8df14e5aEric Laurent } 3631fdbee869be504e399efce1127a68281bd9b158c5Eric Laurent return true; 3632fdbee869be504e399efce1127a68281bd9b158c5Eric Laurent } else { 3633fdbee869be504e399efce1127a68281bd9b158c5Eric Laurent return false; 3634a553c25b33c99b345cf1c8688f8df0ed8df14e5aEric Laurent } 36359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 36369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 36379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3638fdbee869be504e399efce1127a68281bd9b158c5Eric Laurent public int getIndex(int device) { 3639fdbee869be504e399efce1127a68281bd9b158c5Eric Laurent synchronized (VolumeStreamState.class) { 3640fdbee869be504e399efce1127a68281bd9b158c5Eric Laurent Integer index = mIndex.get(device); 3641fdbee869be504e399efce1127a68281bd9b158c5Eric Laurent if (index == null) { 3642fdbee869be504e399efce1127a68281bd9b158c5Eric Laurent // there is always an entry for AudioSystem.DEVICE_OUT_DEFAULT 3643fdbee869be504e399efce1127a68281bd9b158c5Eric Laurent index = mIndex.get(AudioSystem.DEVICE_OUT_DEFAULT); 3644fdbee869be504e399efce1127a68281bd9b158c5Eric Laurent } 3645fdbee869be504e399efce1127a68281bd9b158c5Eric Laurent return index.intValue(); 36469bc8358ddaa01c3490f9709991989633a6a3dd42Eric Laurent } 36479bc8358ddaa01c3490f9709991989633a6a3dd42Eric Laurent } 36489bc8358ddaa01c3490f9709991989633a6a3dd42Eric Laurent 36499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public int getMaxIndex() { 3650a553c25b33c99b345cf1c8688f8df0ed8df14e5aEric Laurent return mIndexMax; 36519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 36529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3653fdbee869be504e399efce1127a68281bd9b158c5Eric Laurent public void setAllIndexes(VolumeStreamState srcStream) { 3654fdbee869be504e399efce1127a68281bd9b158c5Eric Laurent synchronized (VolumeStreamState.class) { 3655fdbee869be504e399efce1127a68281bd9b158c5Eric Laurent int srcStreamType = srcStream.getStreamType(); 3656fdbee869be504e399efce1127a68281bd9b158c5Eric Laurent // apply default device volume from source stream to all devices first in case 3657fdbee869be504e399efce1127a68281bd9b158c5Eric Laurent // some devices are present in this stream state but not in source stream state 3658fdbee869be504e399efce1127a68281bd9b158c5Eric Laurent int index = srcStream.getIndex(AudioSystem.DEVICE_OUT_DEFAULT); 365924e0d9b6c40712a297e4c287435a3b0fdd30e9daEric Laurent index = rescaleIndex(index, srcStreamType, mStreamType); 3660fdbee869be504e399efce1127a68281bd9b158c5Eric Laurent Set set = mIndex.entrySet(); 3661fdbee869be504e399efce1127a68281bd9b158c5Eric Laurent Iterator i = set.iterator(); 3662fdbee869be504e399efce1127a68281bd9b158c5Eric Laurent while (i.hasNext()) { 3663fdbee869be504e399efce1127a68281bd9b158c5Eric Laurent Map.Entry entry = (Map.Entry)i.next(); 3664fdbee869be504e399efce1127a68281bd9b158c5Eric Laurent entry.setValue(index); 3665fdbee869be504e399efce1127a68281bd9b158c5Eric Laurent } 3666fdbee869be504e399efce1127a68281bd9b158c5Eric Laurent // Now apply actual volume for devices in source stream state 3667fdbee869be504e399efce1127a68281bd9b158c5Eric Laurent set = srcStream.mIndex.entrySet(); 3668fdbee869be504e399efce1127a68281bd9b158c5Eric Laurent i = set.iterator(); 3669fdbee869be504e399efce1127a68281bd9b158c5Eric Laurent while (i.hasNext()) { 3670fdbee869be504e399efce1127a68281bd9b158c5Eric Laurent Map.Entry entry = (Map.Entry)i.next(); 3671fdbee869be504e399efce1127a68281bd9b158c5Eric Laurent int device = ((Integer)entry.getKey()).intValue(); 3672fdbee869be504e399efce1127a68281bd9b158c5Eric Laurent index = ((Integer)entry.getValue()).intValue(); 3673fdbee869be504e399efce1127a68281bd9b158c5Eric Laurent index = rescaleIndex(index, srcStreamType, mStreamType); 3674fdbee869be504e399efce1127a68281bd9b158c5Eric Laurent 3675fdbee869be504e399efce1127a68281bd9b158c5Eric Laurent setIndex(index, device); 3676fdbee869be504e399efce1127a68281bd9b158c5Eric Laurent } 36776d5176638c2189595cede38fb92c3e7e8700e221Eric Laurent } 36786d5176638c2189595cede38fb92c3e7e8700e221Eric Laurent } 36796d5176638c2189595cede38fb92c3e7e8700e221Eric Laurent 3680fdbee869be504e399efce1127a68281bd9b158c5Eric Laurent public void setAllIndexesToMax() { 3681fdbee869be504e399efce1127a68281bd9b158c5Eric Laurent synchronized (VolumeStreamState.class) { 3682fdbee869be504e399efce1127a68281bd9b158c5Eric Laurent Set set = mIndex.entrySet(); 3683fdbee869be504e399efce1127a68281bd9b158c5Eric Laurent Iterator i = set.iterator(); 3684fdbee869be504e399efce1127a68281bd9b158c5Eric Laurent while (i.hasNext()) { 3685fdbee869be504e399efce1127a68281bd9b158c5Eric Laurent Map.Entry entry = (Map.Entry)i.next(); 3686fdbee869be504e399efce1127a68281bd9b158c5Eric Laurent entry.setValue(mIndexMax); 3687fdbee869be504e399efce1127a68281bd9b158c5Eric Laurent } 3688dd45d01128423a82652a3c9d77fa393631d95229Eric Laurent } 3689dd45d01128423a82652a3c9d77fa393631d95229Eric Laurent } 3690dd45d01128423a82652a3c9d77fa393631d95229Eric Laurent 3691fdbee869be504e399efce1127a68281bd9b158c5Eric Laurent public void mute(IBinder cb, boolean state) { 3692fdbee869be504e399efce1127a68281bd9b158c5Eric Laurent synchronized (VolumeStreamState.class) { 36938fa4d6f585f40ff5cf5f9bed316d92c64a306f21Eric Laurent VolumeDeathHandler handler = getDeathHandler_syncVSS(cb, state); 3694fdbee869be504e399efce1127a68281bd9b158c5Eric Laurent if (handler == null) { 3695fdbee869be504e399efce1127a68281bd9b158c5Eric Laurent Log.e(TAG, "Could not get client death handler for stream: "+mStreamType); 3696fdbee869be504e399efce1127a68281bd9b158c5Eric Laurent return; 3697fdbee869be504e399efce1127a68281bd9b158c5Eric Laurent } 36988fa4d6f585f40ff5cf5f9bed316d92c64a306f21Eric Laurent handler.mute_syncVSS(state); 36999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 37009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 37019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 37026d5176638c2189595cede38fb92c3e7e8700e221Eric Laurent public int getStreamType() { 37036d5176638c2189595cede38fb92c3e7e8700e221Eric Laurent return mStreamType; 37046d5176638c2189595cede38fb92c3e7e8700e221Eric Laurent } 37056d5176638c2189595cede38fb92c3e7e8700e221Eric Laurent 3706212532b58e3b17d7e9d6e1361946d909d4e372c2Eric Laurent public void checkFixedVolumeDevices() { 3707212532b58e3b17d7e9d6e1361946d909d4e372c2Eric Laurent synchronized (VolumeStreamState.class) { 3708212532b58e3b17d7e9d6e1361946d909d4e372c2Eric Laurent // ignore settings for fixed volume devices: volume should always be at max or 0 3709212532b58e3b17d7e9d6e1361946d909d4e372c2Eric Laurent if (mStreamVolumeAlias[mStreamType] == AudioSystem.STREAM_MUSIC) { 3710212532b58e3b17d7e9d6e1361946d909d4e372c2Eric Laurent Set set = mIndex.entrySet(); 3711212532b58e3b17d7e9d6e1361946d909d4e372c2Eric Laurent Iterator i = set.iterator(); 3712212532b58e3b17d7e9d6e1361946d909d4e372c2Eric Laurent while (i.hasNext()) { 3713212532b58e3b17d7e9d6e1361946d909d4e372c2Eric Laurent Map.Entry entry = (Map.Entry)i.next(); 3714212532b58e3b17d7e9d6e1361946d909d4e372c2Eric Laurent int device = ((Integer)entry.getKey()).intValue(); 3715212532b58e3b17d7e9d6e1361946d909d4e372c2Eric Laurent int index = ((Integer)entry.getValue()).intValue(); 3716ba5270b88798c66fefc17a1b25b27894e4fb7862Jean-Michel Trivi if (((device & mFullVolumeDevices) != 0) 3717ba5270b88798c66fefc17a1b25b27894e4fb7862Jean-Michel Trivi || (((device & mFixedVolumeDevices) != 0) && index != 0)) { 3718212532b58e3b17d7e9d6e1361946d909d4e372c2Eric Laurent entry.setValue(mIndexMax); 3719212532b58e3b17d7e9d6e1361946d909d4e372c2Eric Laurent } 37208fa4d6f585f40ff5cf5f9bed316d92c64a306f21Eric Laurent applyDeviceVolume_syncVSS(device); 3721212532b58e3b17d7e9d6e1361946d909d4e372c2Eric Laurent } 3722212532b58e3b17d7e9d6e1361946d909d4e372c2Eric Laurent } 3723212532b58e3b17d7e9d6e1361946d909d4e372c2Eric Laurent } 3724212532b58e3b17d7e9d6e1361946d909d4e372c2Eric Laurent } 3725212532b58e3b17d7e9d6e1361946d909d4e372c2Eric Laurent 37269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private int getValidIndex(int index) { 37279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (index < 0) { 37289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return 0; 3729da39290460b30e5080769f039d6dff352b3c7808Wally Yau } else if (mUseFixedVolume || mUseMasterVolume || index > mIndexMax) { 3730a553c25b33c99b345cf1c8688f8df0ed8df14e5aEric Laurent return mIndexMax; 37319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 37329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 37339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return index; 37349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 37359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 37369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private class VolumeDeathHandler implements IBinder.DeathRecipient { 37379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private IBinder mICallback; // To be notified of client's death 37389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private int mMuteCount; // Number of active mutes for this client 37399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 37409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project VolumeDeathHandler(IBinder cb) { 37419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mICallback = cb; 37429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 37439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 37448fa4d6f585f40ff5cf5f9bed316d92c64a306f21Eric Laurent // must be called while synchronized VolumeStreamState.class 37458fa4d6f585f40ff5cf5f9bed316d92c64a306f21Eric Laurent public void mute_syncVSS(boolean state) { 374642b041ed4f184e3af7f788eb07307f556a2a6616Eric Laurent boolean updateVolume = false; 37473172d5e3e7520a745fa37b71fc1c7bf244b57085Eric Laurent if (state) { 37483172d5e3e7520a745fa37b71fc1c7bf244b57085Eric Laurent if (mMuteCount == 0) { 37493172d5e3e7520a745fa37b71fc1c7bf244b57085Eric Laurent // Register for client death notification 37503172d5e3e7520a745fa37b71fc1c7bf244b57085Eric Laurent try { 37513172d5e3e7520a745fa37b71fc1c7bf244b57085Eric Laurent // mICallback can be 0 if muted by AudioService 37523172d5e3e7520a745fa37b71fc1c7bf244b57085Eric Laurent if (mICallback != null) { 37533172d5e3e7520a745fa37b71fc1c7bf244b57085Eric Laurent mICallback.linkToDeath(this, 0); 37543172d5e3e7520a745fa37b71fc1c7bf244b57085Eric Laurent } 375542b041ed4f184e3af7f788eb07307f556a2a6616Eric Laurent VolumeStreamState.this.mDeathHandlers.add(this); 37563172d5e3e7520a745fa37b71fc1c7bf244b57085Eric Laurent // If the stream is not yet muted by any client, set level to 0 37578fa4d6f585f40ff5cf5f9bed316d92c64a306f21Eric Laurent if (!VolumeStreamState.this.isMuted_syncVSS()) { 375842b041ed4f184e3af7f788eb07307f556a2a6616Eric Laurent updateVolume = true; 37593172d5e3e7520a745fa37b71fc1c7bf244b57085Eric Laurent } 37603172d5e3e7520a745fa37b71fc1c7bf244b57085Eric Laurent } catch (RemoteException e) { 37613172d5e3e7520a745fa37b71fc1c7bf244b57085Eric Laurent // Client has died! 37623172d5e3e7520a745fa37b71fc1c7bf244b57085Eric Laurent binderDied(); 37633172d5e3e7520a745fa37b71fc1c7bf244b57085Eric Laurent return; 37643172d5e3e7520a745fa37b71fc1c7bf244b57085Eric Laurent } 37653172d5e3e7520a745fa37b71fc1c7bf244b57085Eric Laurent } else { 37663172d5e3e7520a745fa37b71fc1c7bf244b57085Eric Laurent Log.w(TAG, "stream: "+mStreamType+" was already muted by this client"); 37673172d5e3e7520a745fa37b71fc1c7bf244b57085Eric Laurent } 37683172d5e3e7520a745fa37b71fc1c7bf244b57085Eric Laurent mMuteCount++; 37693172d5e3e7520a745fa37b71fc1c7bf244b57085Eric Laurent } else { 37703172d5e3e7520a745fa37b71fc1c7bf244b57085Eric Laurent if (mMuteCount == 0) { 37713172d5e3e7520a745fa37b71fc1c7bf244b57085Eric Laurent Log.e(TAG, "unexpected unmute for stream: "+mStreamType); 37723172d5e3e7520a745fa37b71fc1c7bf244b57085Eric Laurent } else { 37733172d5e3e7520a745fa37b71fc1c7bf244b57085Eric Laurent mMuteCount--; 37743172d5e3e7520a745fa37b71fc1c7bf244b57085Eric Laurent if (mMuteCount == 0) { 37753172d5e3e7520a745fa37b71fc1c7bf244b57085Eric Laurent // Unregister from client death notification 377642b041ed4f184e3af7f788eb07307f556a2a6616Eric Laurent VolumeStreamState.this.mDeathHandlers.remove(this); 37773172d5e3e7520a745fa37b71fc1c7bf244b57085Eric Laurent // mICallback can be 0 if muted by AudioService 37783172d5e3e7520a745fa37b71fc1c7bf244b57085Eric Laurent if (mICallback != null) { 37793172d5e3e7520a745fa37b71fc1c7bf244b57085Eric Laurent mICallback.unlinkToDeath(this, 0); 37803172d5e3e7520a745fa37b71fc1c7bf244b57085Eric Laurent } 37818fa4d6f585f40ff5cf5f9bed316d92c64a306f21Eric Laurent if (!VolumeStreamState.this.isMuted_syncVSS()) { 378242b041ed4f184e3af7f788eb07307f556a2a6616Eric Laurent updateVolume = true; 37839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 37849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 37859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 37869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 378742b041ed4f184e3af7f788eb07307f556a2a6616Eric Laurent if (updateVolume) { 378842b041ed4f184e3af7f788eb07307f556a2a6616Eric Laurent sendMsg(mAudioHandler, 378942b041ed4f184e3af7f788eb07307f556a2a6616Eric Laurent MSG_SET_ALL_VOLUMES, 379042b041ed4f184e3af7f788eb07307f556a2a6616Eric Laurent SENDMSG_QUEUE, 379142b041ed4f184e3af7f788eb07307f556a2a6616Eric Laurent 0, 379242b041ed4f184e3af7f788eb07307f556a2a6616Eric Laurent 0, 379342b041ed4f184e3af7f788eb07307f556a2a6616Eric Laurent VolumeStreamState.this, 0); 379442b041ed4f184e3af7f788eb07307f556a2a6616Eric Laurent } 37959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 37969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 37979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public void binderDied() { 37989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Log.w(TAG, "Volume service client died for stream: "+mStreamType); 37998fa4d6f585f40ff5cf5f9bed316d92c64a306f21Eric Laurent synchronized (VolumeStreamState.class) { 38008fa4d6f585f40ff5cf5f9bed316d92c64a306f21Eric Laurent if (mMuteCount != 0) { 38018fa4d6f585f40ff5cf5f9bed316d92c64a306f21Eric Laurent // Reset all active mute requests from this client. 38028fa4d6f585f40ff5cf5f9bed316d92c64a306f21Eric Laurent mMuteCount = 1; 38038fa4d6f585f40ff5cf5f9bed316d92c64a306f21Eric Laurent mute_syncVSS(false); 38048fa4d6f585f40ff5cf5f9bed316d92c64a306f21Eric Laurent } 38059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 38069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 38079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 38089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 38098fa4d6f585f40ff5cf5f9bed316d92c64a306f21Eric Laurent private int muteCount() { 38109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int count = 0; 38119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int size = mDeathHandlers.size(); 38129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project for (int i = 0; i < size; i++) { 38139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project count += mDeathHandlers.get(i).mMuteCount; 38149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 38159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return count; 38169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 38179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 38188fa4d6f585f40ff5cf5f9bed316d92c64a306f21Eric Laurent // must be called while synchronized VolumeStreamState.class 38198fa4d6f585f40ff5cf5f9bed316d92c64a306f21Eric Laurent private boolean isMuted_syncVSS() { 382042b041ed4f184e3af7f788eb07307f556a2a6616Eric Laurent return muteCount() != 0; 382142b041ed4f184e3af7f788eb07307f556a2a6616Eric Laurent } 382242b041ed4f184e3af7f788eb07307f556a2a6616Eric Laurent 38238fa4d6f585f40ff5cf5f9bed316d92c64a306f21Eric Laurent // must be called while synchronized VolumeStreamState.class 38248fa4d6f585f40ff5cf5f9bed316d92c64a306f21Eric Laurent private VolumeDeathHandler getDeathHandler_syncVSS(IBinder cb, boolean state) { 38253172d5e3e7520a745fa37b71fc1c7bf244b57085Eric Laurent VolumeDeathHandler handler; 38263172d5e3e7520a745fa37b71fc1c7bf244b57085Eric Laurent int size = mDeathHandlers.size(); 38273172d5e3e7520a745fa37b71fc1c7bf244b57085Eric Laurent for (int i = 0; i < size; i++) { 38283172d5e3e7520a745fa37b71fc1c7bf244b57085Eric Laurent handler = mDeathHandlers.get(i); 38293172d5e3e7520a745fa37b71fc1c7bf244b57085Eric Laurent if (cb == handler.mICallback) { 38303172d5e3e7520a745fa37b71fc1c7bf244b57085Eric Laurent return handler; 3831ce952c8e13c535bedde77bcdb94dfcc7508475aaMike Lockwood } 3832ce952c8e13c535bedde77bcdb94dfcc7508475aaMike Lockwood } 38333172d5e3e7520a745fa37b71fc1c7bf244b57085Eric Laurent // If this is the first mute request for this client, create a new 38343172d5e3e7520a745fa37b71fc1c7bf244b57085Eric Laurent // client death handler. Otherwise, it is an out of sequence unmute request. 38353172d5e3e7520a745fa37b71fc1c7bf244b57085Eric Laurent if (state) { 38363172d5e3e7520a745fa37b71fc1c7bf244b57085Eric Laurent handler = new VolumeDeathHandler(cb); 38373172d5e3e7520a745fa37b71fc1c7bf244b57085Eric Laurent } else { 38383172d5e3e7520a745fa37b71fc1c7bf244b57085Eric Laurent Log.w(TAG, "stream was not muted by this client"); 38393172d5e3e7520a745fa37b71fc1c7bf244b57085Eric Laurent handler = null; 38403172d5e3e7520a745fa37b71fc1c7bf244b57085Eric Laurent } 38413172d5e3e7520a745fa37b71fc1c7bf244b57085Eric Laurent return handler; 3842ce952c8e13c535bedde77bcdb94dfcc7508475aaMike Lockwood } 3843bffc3d1bd33eb2d8e00a9f8b6261d815db503311Eric Laurent 3844bffc3d1bd33eb2d8e00a9f8b6261d815db503311Eric Laurent private void dump(PrintWriter pw) { 3845dd45d01128423a82652a3c9d77fa393631d95229Eric Laurent pw.print(" Mute count: "); 3846dd45d01128423a82652a3c9d77fa393631d95229Eric Laurent pw.println(muteCount()); 38472b29bc4c1cef64abdf3a68b60bdcf7207193e980John Spurlock pw.print(" Max: "); 38482b29bc4c1cef64abdf3a68b60bdcf7207193e980John Spurlock pw.println((mIndexMax + 5) / 10); 3849bffc3d1bd33eb2d8e00a9f8b6261d815db503311Eric Laurent pw.print(" Current: "); 3850bffc3d1bd33eb2d8e00a9f8b6261d815db503311Eric Laurent Set set = mIndex.entrySet(); 3851bffc3d1bd33eb2d8e00a9f8b6261d815db503311Eric Laurent Iterator i = set.iterator(); 3852bffc3d1bd33eb2d8e00a9f8b6261d815db503311Eric Laurent while (i.hasNext()) { 3853bffc3d1bd33eb2d8e00a9f8b6261d815db503311Eric Laurent Map.Entry entry = (Map.Entry)i.next(); 38542b29bc4c1cef64abdf3a68b60bdcf7207193e980John Spurlock final int device = (Integer) entry.getKey(); 38552b29bc4c1cef64abdf3a68b60bdcf7207193e980John Spurlock pw.print(Integer.toHexString(device)); 38562b29bc4c1cef64abdf3a68b60bdcf7207193e980John Spurlock final String deviceName = device == AudioSystem.DEVICE_OUT_DEFAULT ? "default" 38572b29bc4c1cef64abdf3a68b60bdcf7207193e980John Spurlock : AudioSystem.getOutputDeviceName(device); 38582b29bc4c1cef64abdf3a68b60bdcf7207193e980John Spurlock if (!deviceName.isEmpty()) { 38592b29bc4c1cef64abdf3a68b60bdcf7207193e980John Spurlock pw.print(" ("); 38602b29bc4c1cef64abdf3a68b60bdcf7207193e980John Spurlock pw.print(deviceName); 38612b29bc4c1cef64abdf3a68b60bdcf7207193e980John Spurlock pw.print(")"); 38622b29bc4c1cef64abdf3a68b60bdcf7207193e980John Spurlock } 38632b29bc4c1cef64abdf3a68b60bdcf7207193e980John Spurlock pw.print(": "); 38642b29bc4c1cef64abdf3a68b60bdcf7207193e980John Spurlock final int index = (((Integer) entry.getValue()) + 5) / 10; 38652b29bc4c1cef64abdf3a68b60bdcf7207193e980John Spurlock pw.print(index); 38662b29bc4c1cef64abdf3a68b60bdcf7207193e980John Spurlock if (i.hasNext()) { 38672b29bc4c1cef64abdf3a68b60bdcf7207193e980John Spurlock pw.print(", "); 38682b29bc4c1cef64abdf3a68b60bdcf7207193e980John Spurlock } 3869bffc3d1bd33eb2d8e00a9f8b6261d815db503311Eric Laurent } 3870bffc3d1bd33eb2d8e00a9f8b6261d815db503311Eric Laurent } 3871ce952c8e13c535bedde77bcdb94dfcc7508475aaMike Lockwood } 3872ce952c8e13c535bedde77bcdb94dfcc7508475aaMike Lockwood 38739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** Thread that handles native AudioSystem control. */ 38749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private class AudioSystemThread extends Thread { 38759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project AudioSystemThread() { 38769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project super("AudioService"); 38779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 38789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 38799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project @Override 38809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public void run() { 38819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Set this thread up so the handler will work on it 38829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Looper.prepare(); 38839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 38849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project synchronized(AudioService.this) { 38859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mAudioHandler = new AudioHandler(); 38869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 38879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Notify that the handler has been created 38889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project AudioService.this.notify(); 38899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 38909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 38919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Listen for volume change requests that are set by VolumePanel 38929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Looper.loop(); 38939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 38949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 38959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 38969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** Handles internal volume messages in separate volume thread. */ 38979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private class AudioHandler extends Handler { 38989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 38999bc8358ddaa01c3490f9709991989633a6a3dd42Eric Laurent private void setDeviceVolume(VolumeStreamState streamState, int device) { 39009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 39018fa4d6f585f40ff5cf5f9bed316d92c64a306f21Eric Laurent synchronized (VolumeStreamState.class) { 39028fa4d6f585f40ff5cf5f9bed316d92c64a306f21Eric Laurent // Apply volume 39038fa4d6f585f40ff5cf5f9bed316d92c64a306f21Eric Laurent streamState.applyDeviceVolume_syncVSS(device); 39048fa4d6f585f40ff5cf5f9bed316d92c64a306f21Eric Laurent 39058fa4d6f585f40ff5cf5f9bed316d92c64a306f21Eric Laurent // Apply change to all streams using this one as alias 39068fa4d6f585f40ff5cf5f9bed316d92c64a306f21Eric Laurent int numStreamTypes = AudioSystem.getNumStreamTypes(); 39078fa4d6f585f40ff5cf5f9bed316d92c64a306f21Eric Laurent for (int streamType = numStreamTypes - 1; streamType >= 0; streamType--) { 39088fa4d6f585f40ff5cf5f9bed316d92c64a306f21Eric Laurent if (streamType != streamState.mStreamType && 39098fa4d6f585f40ff5cf5f9bed316d92c64a306f21Eric Laurent mStreamVolumeAlias[streamType] == streamState.mStreamType) { 39108fa4d6f585f40ff5cf5f9bed316d92c64a306f21Eric Laurent // Make sure volume is also maxed out on A2DP device for aliased stream 39118fa4d6f585f40ff5cf5f9bed316d92c64a306f21Eric Laurent // that may have a different device selected 39128fa4d6f585f40ff5cf5f9bed316d92c64a306f21Eric Laurent int streamDevice = getDeviceForStream(streamType); 39138fa4d6f585f40ff5cf5f9bed316d92c64a306f21Eric Laurent if ((device != streamDevice) && mAvrcpAbsVolSupported && 39148fa4d6f585f40ff5cf5f9bed316d92c64a306f21Eric Laurent ((device & AudioSystem.DEVICE_OUT_ALL_A2DP) != 0)) { 39158fa4d6f585f40ff5cf5f9bed316d92c64a306f21Eric Laurent mStreamStates[streamType].applyDeviceVolume_syncVSS(device); 39168fa4d6f585f40ff5cf5f9bed316d92c64a306f21Eric Laurent } 39178fa4d6f585f40ff5cf5f9bed316d92c64a306f21Eric Laurent mStreamStates[streamType].applyDeviceVolume_syncVSS(streamDevice); 3918cd772d04345850e160a45613fcf6b86da0dce4cfEric Laurent } 3919a553c25b33c99b345cf1c8688f8df0ed8df14e5aEric Laurent } 3920a553c25b33c99b345cf1c8688f8df0ed8df14e5aEric Laurent } 39219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Post a persist volume msg 3922afbb047c3945e9c2b7e9bc6b25098d5fb80bba4eEric Laurent sendMsg(mAudioHandler, 3923afbb047c3945e9c2b7e9bc6b25098d5fb80bba4eEric Laurent MSG_PERSIST_VOLUME, 392498ad9b9d6fd34aad487933170f50b5519313df61Eric Laurent SENDMSG_QUEUE, 39259bc8358ddaa01c3490f9709991989633a6a3dd42Eric Laurent device, 392642b041ed4f184e3af7f788eb07307f556a2a6616Eric Laurent 0, 3927afbb047c3945e9c2b7e9bc6b25098d5fb80bba4eEric Laurent streamState, 3928afbb047c3945e9c2b7e9bc6b25098d5fb80bba4eEric Laurent PERSIST_DELAY); 3929afbb047c3945e9c2b7e9bc6b25098d5fb80bba4eEric Laurent 39309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 39319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 39329bc8358ddaa01c3490f9709991989633a6a3dd42Eric Laurent private void setAllVolumes(VolumeStreamState streamState) { 39339bc8358ddaa01c3490f9709991989633a6a3dd42Eric Laurent 39349bc8358ddaa01c3490f9709991989633a6a3dd42Eric Laurent // Apply volume 39359bc8358ddaa01c3490f9709991989633a6a3dd42Eric Laurent streamState.applyAllVolumes(); 39369bc8358ddaa01c3490f9709991989633a6a3dd42Eric Laurent 39379bc8358ddaa01c3490f9709991989633a6a3dd42Eric Laurent // Apply change to all streams using this one as alias 39389bc8358ddaa01c3490f9709991989633a6a3dd42Eric Laurent int numStreamTypes = AudioSystem.getNumStreamTypes(); 39399bc8358ddaa01c3490f9709991989633a6a3dd42Eric Laurent for (int streamType = numStreamTypes - 1; streamType >= 0; streamType--) { 39409bc8358ddaa01c3490f9709991989633a6a3dd42Eric Laurent if (streamType != streamState.mStreamType && 39416d5176638c2189595cede38fb92c3e7e8700e221Eric Laurent mStreamVolumeAlias[streamType] == streamState.mStreamType) { 39429bc8358ddaa01c3490f9709991989633a6a3dd42Eric Laurent mStreamStates[streamType].applyAllVolumes(); 39439bc8358ddaa01c3490f9709991989633a6a3dd42Eric Laurent } 39449bc8358ddaa01c3490f9709991989633a6a3dd42Eric Laurent } 39459bc8358ddaa01c3490f9709991989633a6a3dd42Eric Laurent } 39469bc8358ddaa01c3490f9709991989633a6a3dd42Eric Laurent 394742b041ed4f184e3af7f788eb07307f556a2a6616Eric Laurent private void persistVolume(VolumeStreamState streamState, int device) { 394883a017b6b7c099d1a0293e5839be6477325aef06Eric Laurent if (mUseFixedVolume) { 394983a017b6b7c099d1a0293e5839be6477325aef06Eric Laurent return; 395083a017b6b7c099d1a0293e5839be6477325aef06Eric Laurent } 3951212532b58e3b17d7e9d6e1361946d909d4e372c2Eric Laurent if (isPlatformTelevision() && (streamState.mStreamType != AudioSystem.STREAM_MUSIC)) { 3952212532b58e3b17d7e9d6e1361946d909d4e372c2Eric Laurent return; 3953212532b58e3b17d7e9d6e1361946d909d4e372c2Eric Laurent } 395442b041ed4f184e3af7f788eb07307f556a2a6616Eric Laurent System.putIntForUser(mContentResolver, 395542b041ed4f184e3af7f788eb07307f556a2a6616Eric Laurent streamState.getSettingNameForDevice(device), 395642b041ed4f184e3af7f788eb07307f556a2a6616Eric Laurent (streamState.getIndex(device) + 5)/ 10, 395742b041ed4f184e3af7f788eb07307f556a2a6616Eric Laurent UserHandle.USER_CURRENT); 39589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 39599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3960ba195ebc76f23b6679443724ab58c9dc9f2df884Glenn Kasten private void persistRingerMode(int ringerMode) { 396183a017b6b7c099d1a0293e5839be6477325aef06Eric Laurent if (mUseFixedVolume) { 396283a017b6b7c099d1a0293e5839be6477325aef06Eric Laurent return; 396383a017b6b7c099d1a0293e5839be6477325aef06Eric Laurent } 39648d9a1f66d9d3dbbd45a56d441a746ec11dba7645Jeff Sharkey Settings.Global.putInt(mContentResolver, Settings.Global.MODE_RINGER, ringerMode); 39659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 39669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 39675d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent private boolean onLoadSoundEffects() { 39685d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent int status; 39695d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent 39705d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent synchronized (mSoundEffectsLock) { 39714a5eeb9c727d77bb57fef87a70c8c9cc23dbfee3Eric Laurent if (!mSystemReady) { 39725d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent Log.w(TAG, "onLoadSoundEffects() called before boot complete"); 39735d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent return false; 39745d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent } 39755d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent 39765d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent if (mSoundPool != null) { 39775d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent return true; 39785d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent } 39795d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent 39805d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent loadTouchSoundAssets(); 39815d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent 398255a30c41b6c47d3afe6b13c25c64e8eec9f45e7cJean-Michel Trivi mSoundPool = new SoundPool.Builder() 398355a30c41b6c47d3afe6b13c25c64e8eec9f45e7cJean-Michel Trivi .setMaxStreams(NUM_SOUNDPOOL_CHANNELS) 398455a30c41b6c47d3afe6b13c25c64e8eec9f45e7cJean-Michel Trivi .setAudioAttributes(new AudioAttributes.Builder() 398555a30c41b6c47d3afe6b13c25c64e8eec9f45e7cJean-Michel Trivi .setUsage(AudioAttributes.USAGE_ASSISTANCE_SONIFICATION) 398655a30c41b6c47d3afe6b13c25c64e8eec9f45e7cJean-Michel Trivi .setContentType(AudioAttributes.CONTENT_TYPE_SONIFICATION) 398755a30c41b6c47d3afe6b13c25c64e8eec9f45e7cJean-Michel Trivi .build()) 398855a30c41b6c47d3afe6b13c25c64e8eec9f45e7cJean-Michel Trivi .build(); 39895d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent mSoundPoolCallBack = null; 39905d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent mSoundPoolListenerThread = new SoundPoolListenerThread(); 39915d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent mSoundPoolListenerThread.start(); 39925d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent int attempts = 3; 39935d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent while ((mSoundPoolCallBack == null) && (attempts-- > 0)) { 39945d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent try { 39955d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent // Wait for mSoundPoolCallBack to be set by the other thread 3996167d1a27713ab64cd3c0aa70de96434083ef0400Glenn Kasten mSoundEffectsLock.wait(SOUND_EFFECTS_LOAD_TIMEOUT_MS); 39975d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent } catch (InterruptedException e) { 39985d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent Log.w(TAG, "Interrupted while waiting sound pool listener thread."); 39995d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent } 40005d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent } 40015d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent 40025d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent if (mSoundPoolCallBack == null) { 40035d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent Log.w(TAG, "onLoadSoundEffects() SoundPool listener or thread creation error"); 40045d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent if (mSoundPoolLooper != null) { 40055d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent mSoundPoolLooper.quit(); 40065d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent mSoundPoolLooper = null; 40075d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent } 40085d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent mSoundPoolListenerThread = null; 40095d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent mSoundPool.release(); 40105d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent mSoundPool = null; 40115d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent return false; 40125d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent } 40135d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent /* 40145d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent * poolId table: The value -1 in this table indicates that corresponding 40155d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent * file (same index in SOUND_EFFECT_FILES[] has not been loaded. 40165d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent * Once loaded, the value in poolId is the sample ID and the same 40175d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent * sample can be reused for another effect using the same file. 40185d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent */ 40195d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent int[] poolId = new int[SOUND_EFFECT_FILES.size()]; 40205d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent for (int fileIdx = 0; fileIdx < SOUND_EFFECT_FILES.size(); fileIdx++) { 40215d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent poolId[fileIdx] = -1; 40225d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent } 40235d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent /* 40245d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent * Effects whose value in SOUND_EFFECT_FILES_MAP[effect][1] is -1 must be loaded. 40255d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent * If load succeeds, value in SOUND_EFFECT_FILES_MAP[effect][1] is > 0: 40265d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent * this indicates we have a valid sample loaded for this effect. 40275d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent */ 40285d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent 40295d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent int numSamples = 0; 40305d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent for (int effect = 0; effect < AudioManager.NUM_SOUND_EFFECTS; effect++) { 40315d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent // Do not load sample if this effect uses the MediaPlayer 40325d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent if (SOUND_EFFECT_FILES_MAP[effect][1] == 0) { 40335d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent continue; 40345d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent } 40355d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent if (poolId[SOUND_EFFECT_FILES_MAP[effect][0]] == -1) { 40365d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent String filePath = Environment.getRootDirectory() 40375d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent + SOUND_EFFECTS_PATH 40385d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent + SOUND_EFFECT_FILES.get(SOUND_EFFECT_FILES_MAP[effect][0]); 40395d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent int sampleId = mSoundPool.load(filePath, 0); 40405d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent if (sampleId <= 0) { 40415d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent Log.w(TAG, "Soundpool could not load file: "+filePath); 40425d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent } else { 40435d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent SOUND_EFFECT_FILES_MAP[effect][1] = sampleId; 40445d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent poolId[SOUND_EFFECT_FILES_MAP[effect][0]] = sampleId; 40455d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent numSamples++; 40465d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent } 40475d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent } else { 40485d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent SOUND_EFFECT_FILES_MAP[effect][1] = 40495d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent poolId[SOUND_EFFECT_FILES_MAP[effect][0]]; 40505d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent } 40515d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent } 40525d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent // wait for all samples to be loaded 40535d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent if (numSamples > 0) { 40545d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent mSoundPoolCallBack.setSamples(poolId); 40555d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent 40565d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent attempts = 3; 40575d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent status = 1; 40585d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent while ((status == 1) && (attempts-- > 0)) { 40595d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent try { 4060167d1a27713ab64cd3c0aa70de96434083ef0400Glenn Kasten mSoundEffectsLock.wait(SOUND_EFFECTS_LOAD_TIMEOUT_MS); 40615d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent status = mSoundPoolCallBack.status(); 40625d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent } catch (InterruptedException e) { 40635d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent Log.w(TAG, "Interrupted while waiting sound pool callback."); 40645d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent } 40655d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent } 40665d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent } else { 40675d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent status = -1; 40685d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent } 40695d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent 40705d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent if (mSoundPoolLooper != null) { 40715d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent mSoundPoolLooper.quit(); 40725d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent mSoundPoolLooper = null; 40735d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent } 40745d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent mSoundPoolListenerThread = null; 40755d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent if (status != 0) { 40765d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent Log.w(TAG, 40775d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent "onLoadSoundEffects(), Error "+status+ " while loading samples"); 40785d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent for (int effect = 0; effect < AudioManager.NUM_SOUND_EFFECTS; effect++) { 40795d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent if (SOUND_EFFECT_FILES_MAP[effect][1] > 0) { 40805d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent SOUND_EFFECT_FILES_MAP[effect][1] = -1; 40815d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent } 40825d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent } 40835d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent 40845d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent mSoundPool.release(); 40855d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent mSoundPool = null; 40865d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent } 40875d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent } 40885d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent return (status == 0); 40895d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent } 40905d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent 40915d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent /** 40925d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent * Unloads samples from the sound pool. 40935d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent * This method can be called to free some memory when 40945d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent * sound effects are disabled. 40955d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent */ 40965d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent private void onUnloadSoundEffects() { 40975d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent synchronized (mSoundEffectsLock) { 40985d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent if (mSoundPool == null) { 40995d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent return; 41005d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent } 41015d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent 41025d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent int[] poolId = new int[SOUND_EFFECT_FILES.size()]; 41035d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent for (int fileIdx = 0; fileIdx < SOUND_EFFECT_FILES.size(); fileIdx++) { 41045d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent poolId[fileIdx] = 0; 41055d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent } 41065d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent 41075d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent for (int effect = 0; effect < AudioManager.NUM_SOUND_EFFECTS; effect++) { 41085d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent if (SOUND_EFFECT_FILES_MAP[effect][1] <= 0) { 41095d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent continue; 41105d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent } 41115d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent if (poolId[SOUND_EFFECT_FILES_MAP[effect][0]] == 0) { 41125d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent mSoundPool.unload(SOUND_EFFECT_FILES_MAP[effect][1]); 41135d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent SOUND_EFFECT_FILES_MAP[effect][1] = -1; 41145d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent poolId[SOUND_EFFECT_FILES_MAP[effect][0]] = -1; 41155d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent } 41165d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent } 41175d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent mSoundPool.release(); 41185d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent mSoundPool = null; 41195d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent } 41205d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent } 41215d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent 41225d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent private void onPlaySoundEffect(int effectType, int volume) { 41239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project synchronized (mSoundEffectsLock) { 41245d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent 41255d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent onLoadSoundEffects(); 41265d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent 41279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (mSoundPool == null) { 41289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return; 41299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4130a2ef57dba9ac77d8eccacd646b2b8a8d99fe9d8bEric Laurent float volFloat; 413125101b0b9a84571ead15b26e9f4cd9c4298d7823Eric Laurent // use default if volume is not specified by caller 4132a2ef57dba9ac77d8eccacd646b2b8a8d99fe9d8bEric Laurent if (volume < 0) { 4133f2b0c11f4e797e183131261724d8de310dac5431Jean-Michel Trivi volFloat = (float)Math.pow(10, (float)sSoundEffectVolumeDb/20); 4134a2ef57dba9ac77d8eccacd646b2b8a8d99fe9d8bEric Laurent } else { 41358a2cfc309ab9126e90022916967c65a793c034f0RoboErik volFloat = volume / 1000.0f; 4136a2ef57dba9ac77d8eccacd646b2b8a8d99fe9d8bEric Laurent } 41379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 41389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (SOUND_EFFECT_FILES_MAP[effectType][1] > 0) { 41395d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent mSoundPool.play(SOUND_EFFECT_FILES_MAP[effectType][1], 41405d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent volFloat, volFloat, 0, 0, 1.0f); 41419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else { 41429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project MediaPlayer mediaPlayer = new MediaPlayer(); 414362b9aec7a0a4e1cf8cfec7e39ea3103ab510d72eGlenn Kasten try { 4144e78fced559d879b2e37b610d0d9a89daf08f0f2bEric Laurent String filePath = Environment.getRootDirectory() + SOUND_EFFECTS_PATH + 4145e78fced559d879b2e37b610d0d9a89daf08f0f2bEric Laurent SOUND_EFFECT_FILES.get(SOUND_EFFECT_FILES_MAP[effectType][0]); 414662b9aec7a0a4e1cf8cfec7e39ea3103ab510d72eGlenn Kasten mediaPlayer.setDataSource(filePath); 414762b9aec7a0a4e1cf8cfec7e39ea3103ab510d72eGlenn Kasten mediaPlayer.setAudioStreamType(AudioSystem.STREAM_SYSTEM); 414862b9aec7a0a4e1cf8cfec7e39ea3103ab510d72eGlenn Kasten mediaPlayer.prepare(); 4149068225de0197df07a0247b2877666ea91c22c992Glenn Kasten mediaPlayer.setVolume(volFloat); 415062b9aec7a0a4e1cf8cfec7e39ea3103ab510d72eGlenn Kasten mediaPlayer.setOnCompletionListener(new OnCompletionListener() { 415162b9aec7a0a4e1cf8cfec7e39ea3103ab510d72eGlenn Kasten public void onCompletion(MediaPlayer mp) { 415262b9aec7a0a4e1cf8cfec7e39ea3103ab510d72eGlenn Kasten cleanupPlayer(mp); 415362b9aec7a0a4e1cf8cfec7e39ea3103ab510d72eGlenn Kasten } 415462b9aec7a0a4e1cf8cfec7e39ea3103ab510d72eGlenn Kasten }); 415562b9aec7a0a4e1cf8cfec7e39ea3103ab510d72eGlenn Kasten mediaPlayer.setOnErrorListener(new OnErrorListener() { 415662b9aec7a0a4e1cf8cfec7e39ea3103ab510d72eGlenn Kasten public boolean onError(MediaPlayer mp, int what, int extra) { 415762b9aec7a0a4e1cf8cfec7e39ea3103ab510d72eGlenn Kasten cleanupPlayer(mp); 415862b9aec7a0a4e1cf8cfec7e39ea3103ab510d72eGlenn Kasten return true; 415962b9aec7a0a4e1cf8cfec7e39ea3103ab510d72eGlenn Kasten } 416062b9aec7a0a4e1cf8cfec7e39ea3103ab510d72eGlenn Kasten }); 416162b9aec7a0a4e1cf8cfec7e39ea3103ab510d72eGlenn Kasten mediaPlayer.start(); 416262b9aec7a0a4e1cf8cfec7e39ea3103ab510d72eGlenn Kasten } catch (IOException ex) { 416362b9aec7a0a4e1cf8cfec7e39ea3103ab510d72eGlenn Kasten Log.w(TAG, "MediaPlayer IOException: "+ex); 416462b9aec7a0a4e1cf8cfec7e39ea3103ab510d72eGlenn Kasten } catch (IllegalArgumentException ex) { 416562b9aec7a0a4e1cf8cfec7e39ea3103ab510d72eGlenn Kasten Log.w(TAG, "MediaPlayer IllegalArgumentException: "+ex); 416662b9aec7a0a4e1cf8cfec7e39ea3103ab510d72eGlenn Kasten } catch (IllegalStateException ex) { 416762b9aec7a0a4e1cf8cfec7e39ea3103ab510d72eGlenn Kasten Log.w(TAG, "MediaPlayer IllegalStateException: "+ex); 41689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 41699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 41709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 41719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 41729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 41739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private void cleanupPlayer(MediaPlayer mp) { 41749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (mp != null) { 41759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project try { 41769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mp.stop(); 41779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mp.release(); 41789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } catch (IllegalStateException ex) { 41799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Log.w(TAG, "MediaPlayer IllegalStateException: "+ex); 41809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 41819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 41829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 41839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 4184fa640154f1f42121d81242b2f1a10f03e52f0014Eric Laurent private void setForceUse(int usage, int config) { 4185fa640154f1f42121d81242b2f1a10f03e52f0014Eric Laurent AudioSystem.setForceUse(usage, config); 4186fa640154f1f42121d81242b2f1a10f03e52f0014Eric Laurent } 4187fa640154f1f42121d81242b2f1a10f03e52f0014Eric Laurent 418805274f348e12983eb8613cc6eb9ae561e8197e28Eric Laurent private void onPersistSafeVolumeState(int state) { 418905274f348e12983eb8613cc6eb9ae561e8197e28Eric Laurent Settings.Global.putInt(mContentResolver, 419005274f348e12983eb8613cc6eb9ae561e8197e28Eric Laurent Settings.Global.AUDIO_SAFE_VOLUME_STATE, 419105274f348e12983eb8613cc6eb9ae561e8197e28Eric Laurent state); 419205274f348e12983eb8613cc6eb9ae561e8197e28Eric Laurent } 419305274f348e12983eb8613cc6eb9ae561e8197e28Eric Laurent 41949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project @Override 41959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public void handleMessage(Message msg) { 4196afbb047c3945e9c2b7e9bc6b25098d5fb80bba4eEric Laurent switch (msg.what) { 41979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 41989bc8358ddaa01c3490f9709991989633a6a3dd42Eric Laurent case MSG_SET_DEVICE_VOLUME: 41999bc8358ddaa01c3490f9709991989633a6a3dd42Eric Laurent setDeviceVolume((VolumeStreamState) msg.obj, msg.arg1); 42009bc8358ddaa01c3490f9709991989633a6a3dd42Eric Laurent break; 42019bc8358ddaa01c3490f9709991989633a6a3dd42Eric Laurent 42029bc8358ddaa01c3490f9709991989633a6a3dd42Eric Laurent case MSG_SET_ALL_VOLUMES: 42039bc8358ddaa01c3490f9709991989633a6a3dd42Eric Laurent setAllVolumes((VolumeStreamState) msg.obj); 42049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project break; 42059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 42069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project case MSG_PERSIST_VOLUME: 420742b041ed4f184e3af7f788eb07307f556a2a6616Eric Laurent persistVolume((VolumeStreamState) msg.obj, msg.arg1); 42089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project break; 42099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 42105c55a051ad7d86a464fb91426f1ea3c0250e38b3Mike Lockwood case MSG_PERSIST_MASTER_VOLUME: 421183a017b6b7c099d1a0293e5839be6477325aef06Eric Laurent if (mUseFixedVolume) { 421283a017b6b7c099d1a0293e5839be6477325aef06Eric Laurent return; 421383a017b6b7c099d1a0293e5839be6477325aef06Eric Laurent } 4214bc0fab1fc2db832ef86d8a33466ec4d68b103ca0Eric Laurent Settings.System.putFloatForUser(mContentResolver, 4215bc0fab1fc2db832ef86d8a33466ec4d68b103ca0Eric Laurent Settings.System.VOLUME_MASTER, 42168a2cfc309ab9126e90022916967c65a793c034f0RoboErik msg.arg1 / (float)1000.0, 4217bc0fab1fc2db832ef86d8a33466ec4d68b103ca0Eric Laurent UserHandle.USER_CURRENT); 42185c55a051ad7d86a464fb91426f1ea3c0250e38b3Mike Lockwood break; 42195c55a051ad7d86a464fb91426f1ea3c0250e38b3Mike Lockwood 422057978ed86286a33d5b1a0fd000ca3406ba9d87b3Justin Koh case MSG_PERSIST_MASTER_VOLUME_MUTE: 422183a017b6b7c099d1a0293e5839be6477325aef06Eric Laurent if (mUseFixedVolume) { 422283a017b6b7c099d1a0293e5839be6477325aef06Eric Laurent return; 422383a017b6b7c099d1a0293e5839be6477325aef06Eric Laurent } 4224bc0fab1fc2db832ef86d8a33466ec4d68b103ca0Eric Laurent Settings.System.putIntForUser(mContentResolver, 4225bc0fab1fc2db832ef86d8a33466ec4d68b103ca0Eric Laurent Settings.System.VOLUME_MASTER_MUTE, 4226bc0fab1fc2db832ef86d8a33466ec4d68b103ca0Eric Laurent msg.arg1, 4227b53453fae037d67e421011936c8fdffe7ba43922Julia Reynolds msg.arg2); 422857978ed86286a33d5b1a0fd000ca3406ba9d87b3Justin Koh break; 422957978ed86286a33d5b1a0fd000ca3406ba9d87b3Justin Koh 42309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project case MSG_PERSIST_RINGER_MODE: 4231ba195ebc76f23b6679443724ab58c9dc9f2df884Glenn Kasten // note that the value persisted is the current ringer mode, not the 4232ba195ebc76f23b6679443724ab58c9dc9f2df884Glenn Kasten // value of ringer mode as of the time the request was made to persist 4233661f2cf45860d2e10924e6b69966a9afe255f28bJohn Spurlock persistRingerMode(getRingerModeInternal()); 42349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project break; 42359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 42369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project case MSG_MEDIA_SERVER_DIED: 4237eb4b8a27e3219726691a868793d2247dc9d2a317Eric Laurent if (!mSystemReady || 4238eb4b8a27e3219726691a868793d2247dc9d2a317Eric Laurent (AudioSystem.checkAudioFlinger() != AudioSystem.AUDIO_STATUS_OK)) { 423989e74ba1419732dd5c7f939e48d4aa7989fd3a51Eric Laurent Log.e(TAG, "Media server died."); 4240afbb047c3945e9c2b7e9bc6b25098d5fb80bba4eEric Laurent sendMsg(mAudioHandler, MSG_MEDIA_SERVER_DIED, SENDMSG_NOOP, 0, 0, 424189e74ba1419732dd5c7f939e48d4aa7989fd3a51Eric Laurent null, 500); 4242dfb881f96af7898151940a4bbc52e45e6043d38bEric Laurent break; 424389e74ba1419732dd5c7f939e48d4aa7989fd3a51Eric Laurent } 42449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Log.e(TAG, "Media server started."); 4245dfb881f96af7898151940a4bbc52e45e6043d38bEric Laurent 42463c652ca5a546e7227a5f4bdbf0f81552b2c91383Eric Laurent // indicate to audio HAL that we start the reconfiguration phase after a media 42473c652ca5a546e7227a5f4bdbf0f81552b2c91383Eric Laurent // server crash 4248dfb881f96af7898151940a4bbc52e45e6043d38bEric Laurent // Note that we only execute this when the media server 42493c652ca5a546e7227a5f4bdbf0f81552b2c91383Eric Laurent // process restarts after a crash, not the first time it is started. 42503c652ca5a546e7227a5f4bdbf0f81552b2c91383Eric Laurent AudioSystem.setParameters("restarting=true"); 42513c652ca5a546e7227a5f4bdbf0f81552b2c91383Eric Laurent 4252fd116ad1ab02f6060a0b2201f018317fa32e28b4Glenn Kasten readAndSetLowRamDevice(); 4253fd116ad1ab02f6060a0b2201f018317fa32e28b4Glenn Kasten 4254c42ac9d4d03f62c3a1ba197a28a81fda44bd8b7fEric Laurent // Restore device connection states 42556bc7f2cd30b6bd90806942b0722e22daa2108493Eric Laurent synchronized (mConnectedDevices) { 42566bc7f2cd30b6bd90806942b0722e22daa2108493Eric Laurent Set set = mConnectedDevices.entrySet(); 42576bc7f2cd30b6bd90806942b0722e22daa2108493Eric Laurent Iterator i = set.iterator(); 42589bc8358ddaa01c3490f9709991989633a6a3dd42Eric Laurent while (i.hasNext()) { 42596bc7f2cd30b6bd90806942b0722e22daa2108493Eric Laurent Map.Entry device = (Map.Entry)i.next(); 42606bc7f2cd30b6bd90806942b0722e22daa2108493Eric Laurent AudioSystem.setDeviceConnectionState( 42616bc7f2cd30b6bd90806942b0722e22daa2108493Eric Laurent ((Integer)device.getKey()).intValue(), 42626bc7f2cd30b6bd90806942b0722e22daa2108493Eric Laurent AudioSystem.DEVICE_STATE_AVAILABLE, 42636bc7f2cd30b6bd90806942b0722e22daa2108493Eric Laurent (String)device.getValue()); 42646bc7f2cd30b6bd90806942b0722e22daa2108493Eric Laurent } 4265c42ac9d4d03f62c3a1ba197a28a81fda44bd8b7fEric Laurent } 4266c42ac9d4d03f62c3a1ba197a28a81fda44bd8b7fEric Laurent // Restore call state 4267c42ac9d4d03f62c3a1ba197a28a81fda44bd8b7fEric Laurent AudioSystem.setPhoneState(mMode); 4268c42ac9d4d03f62c3a1ba197a28a81fda44bd8b7fEric Laurent 4269d5603c126acdd94d9f7400bb1d04188020a425b4Eric Laurent // Restore forced usage for communcations and record 4270c42ac9d4d03f62c3a1ba197a28a81fda44bd8b7fEric Laurent AudioSystem.setForceUse(AudioSystem.FOR_COMMUNICATION, mForcedUseForComm); 4271d5603c126acdd94d9f7400bb1d04188020a425b4Eric Laurent AudioSystem.setForceUse(AudioSystem.FOR_RECORD, mForcedUseForComm); 4272dd45d01128423a82652a3c9d77fa393631d95229Eric Laurent AudioSystem.setForceUse(AudioSystem.FOR_SYSTEM, mCameraSoundForced ? 4273dd45d01128423a82652a3c9d77fa393631d95229Eric Laurent AudioSystem.FORCE_SYSTEM_ENFORCED : AudioSystem.FORCE_NONE); 4274c42ac9d4d03f62c3a1ba197a28a81fda44bd8b7fEric Laurent 4275a553c25b33c99b345cf1c8688f8df0ed8df14e5aEric Laurent // Restore stream volumes 42769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int numStreamTypes = AudioSystem.getNumStreamTypes(); 42779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project for (int streamType = numStreamTypes - 1; streamType >= 0; streamType--) { 42789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project VolumeStreamState streamState = mStreamStates[streamType]; 4279c42ac9d4d03f62c3a1ba197a28a81fda44bd8b7fEric Laurent AudioSystem.initStreamVolume(streamType, 0, (streamState.mIndexMax + 5) / 10); 42809bc8358ddaa01c3490f9709991989633a6a3dd42Eric Laurent 42819bc8358ddaa01c3490f9709991989633a6a3dd42Eric Laurent streamState.applyAllVolumes(); 42829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4283c42ac9d4d03f62c3a1ba197a28a81fda44bd8b7fEric Laurent 4284c42ac9d4d03f62c3a1ba197a28a81fda44bd8b7fEric Laurent // Restore ringer mode 4285661f2cf45860d2e10924e6b69966a9afe255f28bJohn Spurlock setRingerModeInt(getRingerModeInternal(), false); 42863c652ca5a546e7227a5f4bdbf0f81552b2c91383Eric Laurent 42879063154a793b0ab38b3c5992cbaed046427b4a82Mike Lockwood // Restore master volume 42889063154a793b0ab38b3c5992cbaed046427b4a82Mike Lockwood restoreMasterVolume(); 42899063154a793b0ab38b3c5992cbaed046427b4a82Mike Lockwood 4290f26f01784e1c733c53cad3ed31918e73448ce369Jean-Michel Trivi // Reset device orientation (if monitored for this device) 4291d640bd325c3be9a350058c835b880a7e0b40dc60Eric Laurent if (mMonitorOrientation) { 4292f26f01784e1c733c53cad3ed31918e73448ce369Jean-Michel Trivi setOrientationForAudioSystem(); 4293f26f01784e1c733c53cad3ed31918e73448ce369Jean-Michel Trivi } 4294bb6f8711a7f804d39c45218db2d6339940cc5d35Jean-Michel Trivi if (mMonitorRotation) { 4295bb6f8711a7f804d39c45218db2d6339940cc5d35Jean-Michel Trivi setRotationForAudioSystem(); 4296bb6f8711a7f804d39c45218db2d6339940cc5d35Jean-Michel Trivi } 4297f26f01784e1c733c53cad3ed31918e73448ce369Jean-Michel Trivi 42987847211fb4699bf6018e29d214a918ed6657319bEric Laurent synchronized (mBluetoothA2dpEnabledLock) { 42997847211fb4699bf6018e29d214a918ed6657319bEric Laurent AudioSystem.setForceUse(AudioSystem.FOR_MEDIA, 43007847211fb4699bf6018e29d214a918ed6657319bEric Laurent mBluetoothA2dpEnabled ? 43017847211fb4699bf6018e29d214a918ed6657319bEric Laurent AudioSystem.FORCE_NONE : AudioSystem.FORCE_NO_BT_A2DP); 43027847211fb4699bf6018e29d214a918ed6657319bEric Laurent } 4303bff5ca576ef55bfdd51a0d2ff39f4bac614fa728Eric Laurent 4304bff5ca576ef55bfdd51a0d2ff39f4bac614fa728Eric Laurent synchronized (mSettingsLock) { 4305bff5ca576ef55bfdd51a0d2ff39f4bac614fa728Eric Laurent AudioSystem.setForceUse(AudioSystem.FOR_DOCK, 4306bff5ca576ef55bfdd51a0d2ff39f4bac614fa728Eric Laurent mDockAudioMediaEnabled ? 4307bff5ca576ef55bfdd51a0d2ff39f4bac614fa728Eric Laurent AudioSystem.FORCE_ANALOG_DOCK : AudioSystem.FORCE_NONE); 4308bff5ca576ef55bfdd51a0d2ff39f4bac614fa728Eric Laurent } 4309212532b58e3b17d7e9d6e1361946d909d4e372c2Eric Laurent if (mHdmiManager != null) { 4310212532b58e3b17d7e9d6e1361946d909d4e372c2Eric Laurent synchronized (mHdmiManager) { 4311212532b58e3b17d7e9d6e1361946d909d4e372c2Eric Laurent if (mHdmiTvClient != null) { 4312212532b58e3b17d7e9d6e1361946d909d4e372c2Eric Laurent setHdmiSystemAudioSupported(mHdmiSystemAudioSupported); 4313212532b58e3b17d7e9d6e1361946d909d4e372c2Eric Laurent } 4314212532b58e3b17d7e9d6e1361946d909d4e372c2Eric Laurent } 43156f34f5ab8ab1b1db7887e5405d8b0031e105ab05Jungshik Jang } 43167f5eb9fe3c10d8d83ff0e2b0fc60a05c2e6d5b02Eric Laurent 43177f5eb9fe3c10d8d83ff0e2b0fc60a05c2e6d5b02Eric Laurent synchronized (mAudioPolicies) { 43187f5eb9fe3c10d8d83ff0e2b0fc60a05c2e6d5b02Eric Laurent for(AudioPolicyProxy policy : mAudioPolicies.values()) { 43197f5eb9fe3c10d8d83ff0e2b0fc60a05c2e6d5b02Eric Laurent policy.connectMixes(); 43207f5eb9fe3c10d8d83ff0e2b0fc60a05c2e6d5b02Eric Laurent } 43217f5eb9fe3c10d8d83ff0e2b0fc60a05c2e6d5b02Eric Laurent } 43227f5eb9fe3c10d8d83ff0e2b0fc60a05c2e6d5b02Eric Laurent 43233c652ca5a546e7227a5f4bdbf0f81552b2c91383Eric Laurent // indicate the end of reconfiguration phase to audio HAL 43243c652ca5a546e7227a5f4bdbf0f81552b2c91383Eric Laurent AudioSystem.setParameters("restarting=false"); 43259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project break; 43269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 43275d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent case MSG_UNLOAD_SOUND_EFFECTS: 43285d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent onUnloadSoundEffects(); 43295d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent break; 43305d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent 4331117b7bb5b5a4457711f59bde3dcc83d8f111c524Eric Laurent case MSG_LOAD_SOUND_EFFECTS: 43325d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent //FIXME: onLoadSoundEffects() should be executed in a separate thread as it 43335d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent // can take several dozens of milliseconds to complete 43345d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent boolean loaded = onLoadSoundEffects(); 43355d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent if (msg.obj != null) { 43365d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent LoadSoundEffectReply reply = (LoadSoundEffectReply)msg.obj; 43375d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent synchronized (reply) { 43385d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent reply.mStatus = loaded ? 0 : -1; 43395d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent reply.notify(); 43405d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent } 43415d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent } 4342117b7bb5b5a4457711f59bde3dcc83d8f111c524Eric Laurent break; 4343117b7bb5b5a4457711f59bde3dcc83d8f111c524Eric Laurent 43449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project case MSG_PLAY_SOUND_EFFECT: 43455d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent onPlaySoundEffect(msg.arg1, msg.arg2); 43469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project break; 43474c637b9e34f4c8db69a64ad21a4e2bcfa7485b5fJean-Michel Trivi 43484c637b9e34f4c8db69a64ad21a4e2bcfa7485b5fJean-Michel Trivi case MSG_BTA2DP_DOCK_TIMEOUT: 43494c637b9e34f4c8db69a64ad21a4e2bcfa7485b5fJean-Michel Trivi // msg.obj == address of BTA2DP device 43506bc7f2cd30b6bd90806942b0722e22daa2108493Eric Laurent synchronized (mConnectedDevices) { 43516bc7f2cd30b6bd90806942b0722e22daa2108493Eric Laurent makeA2dpDeviceUnavailableNow( (String) msg.obj ); 43526bc7f2cd30b6bd90806942b0722e22daa2108493Eric Laurent } 43534c637b9e34f4c8db69a64ad21a4e2bcfa7485b5fJean-Michel Trivi break; 4354fa640154f1f42121d81242b2f1a10f03e52f0014Eric Laurent 4355fa640154f1f42121d81242b2f1a10f03e52f0014Eric Laurent case MSG_SET_FORCE_USE: 4356c390bed06b4a572e273ead1254da9a932e04dce3Eric Laurent case MSG_SET_FORCE_BT_A2DP_USE: 4357fa640154f1f42121d81242b2f1a10f03e52f0014Eric Laurent setForceUse(msg.arg1, msg.arg2); 4358fa640154f1f42121d81242b2f1a10f03e52f0014Eric Laurent break; 4359d589fea865e90859324f00d21765fa7d7759e465Jean-Michel Trivi 4360dc03c61fe3cd8d0805480e48a974986439977a60Eric Laurent case MSG_BT_HEADSET_CNCT_FAILED: 4361dc03c61fe3cd8d0805480e48a974986439977a60Eric Laurent resetBluetoothSco(); 4362dc03c61fe3cd8d0805480e48a974986439977a60Eric Laurent break; 4363b1fbaaccb656ef09a8770c28df15e3e91a452e64Eric Laurent 4364b1fbaaccb656ef09a8770c28df15e3e91a452e64Eric Laurent case MSG_SET_WIRED_DEVICE_CONNECTION_STATE: 4365b1fbaaccb656ef09a8770c28df15e3e91a452e64Eric Laurent onSetWiredDeviceConnectionState(msg.arg1, msg.arg2, (String)msg.obj); 4366fa9a69805b001034aa04c3b33989a7ac21522371Jean-Michel Trivi mAudioEventWakeLock.release(); 4367b1fbaaccb656ef09a8770c28df15e3e91a452e64Eric Laurent break; 4368b1fbaaccb656ef09a8770c28df15e3e91a452e64Eric Laurent 43690a40ec2192e4836b2fcb6ba51a7688aa6bd4ee98Mike Lockwood case MSG_SET_A2DP_SRC_CONNECTION_STATE: 43700a40ec2192e4836b2fcb6ba51a7688aa6bd4ee98Mike Lockwood onSetA2dpSourceConnectionState((BluetoothDevice)msg.obj, msg.arg1); 43710a40ec2192e4836b2fcb6ba51a7688aa6bd4ee98Mike Lockwood mAudioEventWakeLock.release(); 43720a40ec2192e4836b2fcb6ba51a7688aa6bd4ee98Mike Lockwood break; 43730a40ec2192e4836b2fcb6ba51a7688aa6bd4ee98Mike Lockwood 43740a40ec2192e4836b2fcb6ba51a7688aa6bd4ee98Mike Lockwood case MSG_SET_A2DP_SINK_CONNECTION_STATE: 43750a40ec2192e4836b2fcb6ba51a7688aa6bd4ee98Mike Lockwood onSetA2dpSinkConnectionState((BluetoothDevice)msg.obj, msg.arg1); 4376fa9a69805b001034aa04c3b33989a7ac21522371Jean-Michel Trivi mAudioEventWakeLock.release(); 4377b1fbaaccb656ef09a8770c28df15e3e91a452e64Eric Laurent break; 4378632ca417f0a33e3fa9ccece531afa2db3f0d4a30Dianne Hackborn 4379632ca417f0a33e3fa9ccece531afa2db3f0d4a30Dianne Hackborn case MSG_REPORT_NEW_ROUTES: { 4380632ca417f0a33e3fa9ccece531afa2db3f0d4a30Dianne Hackborn int N = mRoutesObservers.beginBroadcast(); 4381632ca417f0a33e3fa9ccece531afa2db3f0d4a30Dianne Hackborn if (N > 0) { 4382632ca417f0a33e3fa9ccece531afa2db3f0d4a30Dianne Hackborn AudioRoutesInfo routes; 4383632ca417f0a33e3fa9ccece531afa2db3f0d4a30Dianne Hackborn synchronized (mCurAudioRoutes) { 4384632ca417f0a33e3fa9ccece531afa2db3f0d4a30Dianne Hackborn routes = new AudioRoutesInfo(mCurAudioRoutes); 4385632ca417f0a33e3fa9ccece531afa2db3f0d4a30Dianne Hackborn } 4386632ca417f0a33e3fa9ccece531afa2db3f0d4a30Dianne Hackborn while (N > 0) { 4387632ca417f0a33e3fa9ccece531afa2db3f0d4a30Dianne Hackborn N--; 4388632ca417f0a33e3fa9ccece531afa2db3f0d4a30Dianne Hackborn IAudioRoutesObserver obs = mRoutesObservers.getBroadcastItem(N); 4389632ca417f0a33e3fa9ccece531afa2db3f0d4a30Dianne Hackborn try { 4390632ca417f0a33e3fa9ccece531afa2db3f0d4a30Dianne Hackborn obs.dispatchAudioRoutesChanged(routes); 4391632ca417f0a33e3fa9ccece531afa2db3f0d4a30Dianne Hackborn } catch (RemoteException e) { 4392632ca417f0a33e3fa9ccece531afa2db3f0d4a30Dianne Hackborn } 4393632ca417f0a33e3fa9ccece531afa2db3f0d4a30Dianne Hackborn } 4394632ca417f0a33e3fa9ccece531afa2db3f0d4a30Dianne Hackborn } 4395632ca417f0a33e3fa9ccece531afa2db3f0d4a30Dianne Hackborn mRoutesObservers.finishBroadcast(); 4396632ca417f0a33e3fa9ccece531afa2db3f0d4a30Dianne Hackborn break; 4397632ca417f0a33e3fa9ccece531afa2db3f0d4a30Dianne Hackborn } 43983114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi 4399c34dcc1e1ebf152bb400abbb8bc25f7dc0c3ba97Eric Laurent case MSG_CHECK_MUSIC_ACTIVE: 4400c34dcc1e1ebf152bb400abbb8bc25f7dc0c3ba97Eric Laurent onCheckMusicActive(); 4401c34dcc1e1ebf152bb400abbb8bc25f7dc0c3ba97Eric Laurent break; 44025bfaeaef3fc348d66f48b86be08655e91dff910aEric Laurent 44035bfaeaef3fc348d66f48b86be08655e91dff910aEric Laurent case MSG_BROADCAST_AUDIO_BECOMING_NOISY: 44045bfaeaef3fc348d66f48b86be08655e91dff910aEric Laurent onSendBecomingNoisyIntent(); 44055bfaeaef3fc348d66f48b86be08655e91dff910aEric Laurent break; 4406d640bd325c3be9a350058c835b880a7e0b40dc60Eric Laurent 4407d640bd325c3be9a350058c835b880a7e0b40dc60Eric Laurent case MSG_CONFIGURE_SAFE_MEDIA_VOLUME_FORCED: 4408d640bd325c3be9a350058c835b880a7e0b40dc60Eric Laurent case MSG_CONFIGURE_SAFE_MEDIA_VOLUME: 4409d640bd325c3be9a350058c835b880a7e0b40dc60Eric Laurent onConfigureSafeVolume((msg.what == MSG_CONFIGURE_SAFE_MEDIA_VOLUME_FORCED)); 4410d640bd325c3be9a350058c835b880a7e0b40dc60Eric Laurent break; 441105274f348e12983eb8613cc6eb9ae561e8197e28Eric Laurent case MSG_PERSIST_SAFE_VOLUME_STATE: 441205274f348e12983eb8613cc6eb9ae561e8197e28Eric Laurent onPersistSafeVolumeState(msg.arg1); 441305274f348e12983eb8613cc6eb9ae561e8197e28Eric Laurent break; 4414a578c48e6c8677bcb54340aadb9470f8a275e56cJean-Michel Trivi 44152a57ca931fefe817b6110101289721acaacfc808Eric Laurent case MSG_BROADCAST_BT_CONNECTION_STATE: 44162a57ca931fefe817b6110101289721acaacfc808Eric Laurent onBroadcastScoConnectionState(msg.arg1); 44172a57ca931fefe817b6110101289721acaacfc808Eric Laurent break; 44184a5eeb9c727d77bb57fef87a70c8c9cc23dbfee3Eric Laurent 44194a5eeb9c727d77bb57fef87a70c8c9cc23dbfee3Eric Laurent case MSG_SYSTEM_READY: 44204a5eeb9c727d77bb57fef87a70c8c9cc23dbfee3Eric Laurent onSystemReady(); 44214a5eeb9c727d77bb57fef87a70c8c9cc23dbfee3Eric Laurent break; 4422aa5ee4d65f8788e2a0afcd198367450853fd72acJohn Spurlock 4423aa5ee4d65f8788e2a0afcd198367450853fd72acJohn Spurlock case MSG_PERSIST_MUSIC_ACTIVE_MS: 4424aa5ee4d65f8788e2a0afcd198367450853fd72acJohn Spurlock final int musicActiveMs = msg.arg1; 4425aa5ee4d65f8788e2a0afcd198367450853fd72acJohn Spurlock Settings.Secure.putIntForUser(mContentResolver, 4426aa5ee4d65f8788e2a0afcd198367450853fd72acJohn Spurlock Settings.Secure.UNSAFE_VOLUME_MUSIC_ACTIVE_MS, musicActiveMs, 4427aa5ee4d65f8788e2a0afcd198367450853fd72acJohn Spurlock UserHandle.USER_CURRENT); 4428aa5ee4d65f8788e2a0afcd198367450853fd72acJohn Spurlock break; 4429b53453fae037d67e421011936c8fdffe7ba43922Julia Reynolds case MSG_PERSIST_MICROPHONE_MUTE: 4430b53453fae037d67e421011936c8fdffe7ba43922Julia Reynolds Settings.System.putIntForUser(mContentResolver, 4431b53453fae037d67e421011936c8fdffe7ba43922Julia Reynolds Settings.System.MICROPHONE_MUTE, 4432b53453fae037d67e421011936c8fdffe7ba43922Julia Reynolds msg.arg1, 4433b53453fae037d67e421011936c8fdffe7ba43922Julia Reynolds msg.arg2); 4434b53453fae037d67e421011936c8fdffe7ba43922Julia Reynolds break; 44359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 44369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 44379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 44389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 4439b109615ebebd6f3b9ae789412279f576c3ace46bJason Parekh private class SettingsObserver extends ContentObserver { 4440a553c25b33c99b345cf1c8688f8df0ed8df14e5aEric Laurent 4441b109615ebebd6f3b9ae789412279f576c3ace46bJason Parekh SettingsObserver() { 4442b109615ebebd6f3b9ae789412279f576c3ace46bJason Parekh super(new Handler()); 4443b109615ebebd6f3b9ae789412279f576c3ace46bJason Parekh mContentResolver.registerContentObserver(Settings.System.getUriFor( 4444b109615ebebd6f3b9ae789412279f576c3ace46bJason Parekh Settings.System.MODE_RINGER_STREAMS_AFFECTED), false, this); 44457ee1e4ff7346a278a6722108fbc1869240b3e866Eric Laurent mContentResolver.registerContentObserver(Settings.Global.getUriFor( 44467ee1e4ff7346a278a6722108fbc1869240b3e866Eric Laurent Settings.Global.DOCK_AUDIO_MEDIA_ENABLED), false, this); 4447b109615ebebd6f3b9ae789412279f576c3ace46bJason Parekh } 4448b109615ebebd6f3b9ae789412279f576c3ace46bJason Parekh 4449b109615ebebd6f3b9ae789412279f576c3ace46bJason Parekh @Override 4450b109615ebebd6f3b9ae789412279f576c3ace46bJason Parekh public void onChange(boolean selfChange) { 4451b109615ebebd6f3b9ae789412279f576c3ace46bJason Parekh super.onChange(selfChange); 4452ba195ebc76f23b6679443724ab58c9dc9f2df884Glenn Kasten // FIXME This synchronized is not necessary if mSettingsLock only protects mRingerMode. 4453ba195ebc76f23b6679443724ab58c9dc9f2df884Glenn Kasten // However there appear to be some missing locks around mRingerModeMutedStreams 4454ba195ebc76f23b6679443724ab58c9dc9f2df884Glenn Kasten // and mRingerModeAffectedStreams, so will leave this synchronized for now. 4455ba195ebc76f23b6679443724ab58c9dc9f2df884Glenn Kasten // mRingerModeMutedStreams and mMuteAffectedStreams are safe (only accessed once). 4456a553c25b33c99b345cf1c8688f8df0ed8df14e5aEric Laurent synchronized (mSettingsLock) { 445724e0d9b6c40712a297e4c287435a3b0fdd30e9daEric Laurent if (updateRingerModeAffectedStreams()) { 4458a553c25b33c99b345cf1c8688f8df0ed8df14e5aEric Laurent /* 4459a553c25b33c99b345cf1c8688f8df0ed8df14e5aEric Laurent * Ensure all stream types that should be affected by ringer mode 4460a553c25b33c99b345cf1c8688f8df0ed8df14e5aEric Laurent * are in the proper state. 4461a553c25b33c99b345cf1c8688f8df0ed8df14e5aEric Laurent */ 4462661f2cf45860d2e10924e6b69966a9afe255f28bJohn Spurlock setRingerModeInt(getRingerModeInternal(), false); 4463a553c25b33c99b345cf1c8688f8df0ed8df14e5aEric Laurent } 44647ee1e4ff7346a278a6722108fbc1869240b3e866Eric Laurent readDockAudioSettings(mContentResolver); 4465a553c25b33c99b345cf1c8688f8df0ed8df14e5aEric Laurent } 4466b109615ebebd6f3b9ae789412279f576c3ace46bJason Parekh } 4467b109615ebebd6f3b9ae789412279f576c3ace46bJason Parekh } 4468a553c25b33c99b345cf1c8688f8df0ed8df14e5aEric Laurent 44696bc7f2cd30b6bd90806942b0722e22daa2108493Eric Laurent // must be called synchronized on mConnectedDevices 44704c637b9e34f4c8db69a64ad21a4e2bcfa7485b5fJean-Michel Trivi private void makeA2dpDeviceAvailable(String address) { 44717847211fb4699bf6018e29d214a918ed6657319bEric Laurent // enable A2DP before notifying A2DP connection to avoid unecessary processing in 44727847211fb4699bf6018e29d214a918ed6657319bEric Laurent // audio policy manager 4473c9d1d5f35091226e96fcfa91817480f589eb36e2Matthew Xie VolumeStreamState streamState = mStreamStates[AudioSystem.STREAM_MUSIC]; 4474c9d1d5f35091226e96fcfa91817480f589eb36e2Matthew Xie sendMsg(mAudioHandler, MSG_SET_DEVICE_VOLUME, SENDMSG_QUEUE, 4475c9d1d5f35091226e96fcfa91817480f589eb36e2Matthew Xie AudioSystem.DEVICE_OUT_BLUETOOTH_A2DP, 0, streamState, 0); 44767847211fb4699bf6018e29d214a918ed6657319bEric Laurent setBluetoothA2dpOnInt(true); 44774c637b9e34f4c8db69a64ad21a4e2bcfa7485b5fJean-Michel Trivi AudioSystem.setDeviceConnectionState(AudioSystem.DEVICE_OUT_BLUETOOTH_A2DP, 44784c637b9e34f4c8db69a64ad21a4e2bcfa7485b5fJean-Michel Trivi AudioSystem.DEVICE_STATE_AVAILABLE, 44794c637b9e34f4c8db69a64ad21a4e2bcfa7485b5fJean-Michel Trivi address); 44804c637b9e34f4c8db69a64ad21a4e2bcfa7485b5fJean-Michel Trivi // Reset A2DP suspend state each time a new sink is connected 44814c637b9e34f4c8db69a64ad21a4e2bcfa7485b5fJean-Michel Trivi AudioSystem.setParameters("A2dpSuspended=false"); 44824c637b9e34f4c8db69a64ad21a4e2bcfa7485b5fJean-Michel Trivi mConnectedDevices.put( new Integer(AudioSystem.DEVICE_OUT_BLUETOOTH_A2DP), 44834c637b9e34f4c8db69a64ad21a4e2bcfa7485b5fJean-Michel Trivi address); 44844c637b9e34f4c8db69a64ad21a4e2bcfa7485b5fJean-Michel Trivi } 44854c637b9e34f4c8db69a64ad21a4e2bcfa7485b5fJean-Michel Trivi 44865bfaeaef3fc348d66f48b86be08655e91dff910aEric Laurent private void onSendBecomingNoisyIntent() { 44875ac72a29593ab9a20337a2225df52bdf4754be02Dianne Hackborn sendBroadcastToAll(new Intent(AudioManager.ACTION_AUDIO_BECOMING_NOISY)); 44889841818b9a0280abf59343c9e00a2976dbc084faMike Lockwood } 44899841818b9a0280abf59343c9e00a2976dbc084faMike Lockwood 44906bc7f2cd30b6bd90806942b0722e22daa2108493Eric Laurent // must be called synchronized on mConnectedDevices 44914c637b9e34f4c8db69a64ad21a4e2bcfa7485b5fJean-Michel Trivi private void makeA2dpDeviceUnavailableNow(String address) { 4492c9d1d5f35091226e96fcfa91817480f589eb36e2Matthew Xie synchronized (mA2dpAvrcpLock) { 4493c9d1d5f35091226e96fcfa91817480f589eb36e2Matthew Xie mAvrcpAbsVolSupported = false; 4494c9d1d5f35091226e96fcfa91817480f589eb36e2Matthew Xie } 44954c637b9e34f4c8db69a64ad21a4e2bcfa7485b5fJean-Michel Trivi AudioSystem.setDeviceConnectionState(AudioSystem.DEVICE_OUT_BLUETOOTH_A2DP, 44964c637b9e34f4c8db69a64ad21a4e2bcfa7485b5fJean-Michel Trivi AudioSystem.DEVICE_STATE_UNAVAILABLE, 44974c637b9e34f4c8db69a64ad21a4e2bcfa7485b5fJean-Michel Trivi address); 44984c637b9e34f4c8db69a64ad21a4e2bcfa7485b5fJean-Michel Trivi mConnectedDevices.remove(AudioSystem.DEVICE_OUT_BLUETOOTH_A2DP); 44995535ea8ef876be25121a6336ffab5a0bf8dbd031RoboErik synchronized (mCurAudioRoutes) { 45005535ea8ef876be25121a6336ffab5a0bf8dbd031RoboErik // Remove A2DP routes as well 45015535ea8ef876be25121a6336ffab5a0bf8dbd031RoboErik if (mCurAudioRoutes.mBluetoothName != null) { 45025535ea8ef876be25121a6336ffab5a0bf8dbd031RoboErik mCurAudioRoutes.mBluetoothName = null; 45035535ea8ef876be25121a6336ffab5a0bf8dbd031RoboErik sendMsg(mAudioHandler, MSG_REPORT_NEW_ROUTES, 45045535ea8ef876be25121a6336ffab5a0bf8dbd031RoboErik SENDMSG_NOOP, 0, 0, null, 0); 45055535ea8ef876be25121a6336ffab5a0bf8dbd031RoboErik } 45065535ea8ef876be25121a6336ffab5a0bf8dbd031RoboErik } 45074c637b9e34f4c8db69a64ad21a4e2bcfa7485b5fJean-Michel Trivi } 45084c637b9e34f4c8db69a64ad21a4e2bcfa7485b5fJean-Michel Trivi 45096bc7f2cd30b6bd90806942b0722e22daa2108493Eric Laurent // must be called synchronized on mConnectedDevices 45104c637b9e34f4c8db69a64ad21a4e2bcfa7485b5fJean-Michel Trivi private void makeA2dpDeviceUnavailableLater(String address) { 45113b5912602bec6ccbe8eef8a576730b1565f0067cEric Laurent // prevent any activity on the A2DP audio output to avoid unwanted 45123b5912602bec6ccbe8eef8a576730b1565f0067cEric Laurent // reconnection of the sink. 45133b5912602bec6ccbe8eef8a576730b1565f0067cEric Laurent AudioSystem.setParameters("A2dpSuspended=true"); 45144c637b9e34f4c8db69a64ad21a4e2bcfa7485b5fJean-Michel Trivi // the device will be made unavailable later, so consider it disconnected right away 45154c637b9e34f4c8db69a64ad21a4e2bcfa7485b5fJean-Michel Trivi mConnectedDevices.remove(AudioSystem.DEVICE_OUT_BLUETOOTH_A2DP); 45164c637b9e34f4c8db69a64ad21a4e2bcfa7485b5fJean-Michel Trivi // send the delayed message to make the device unavailable later 45174c637b9e34f4c8db69a64ad21a4e2bcfa7485b5fJean-Michel Trivi Message msg = mAudioHandler.obtainMessage(MSG_BTA2DP_DOCK_TIMEOUT, address); 45184c637b9e34f4c8db69a64ad21a4e2bcfa7485b5fJean-Michel Trivi mAudioHandler.sendMessageDelayed(msg, BTA2DP_DOCK_TIMEOUT_MILLIS); 45194c637b9e34f4c8db69a64ad21a4e2bcfa7485b5fJean-Michel Trivi 45204c637b9e34f4c8db69a64ad21a4e2bcfa7485b5fJean-Michel Trivi } 45214c637b9e34f4c8db69a64ad21a4e2bcfa7485b5fJean-Michel Trivi 45226bc7f2cd30b6bd90806942b0722e22daa2108493Eric Laurent // must be called synchronized on mConnectedDevices 45230a40ec2192e4836b2fcb6ba51a7688aa6bd4ee98Mike Lockwood private void makeA2dpSrcAvailable(String address) { 45240a40ec2192e4836b2fcb6ba51a7688aa6bd4ee98Mike Lockwood AudioSystem.setDeviceConnectionState(AudioSystem.DEVICE_IN_BLUETOOTH_A2DP, 45250a40ec2192e4836b2fcb6ba51a7688aa6bd4ee98Mike Lockwood AudioSystem.DEVICE_STATE_AVAILABLE, 45260a40ec2192e4836b2fcb6ba51a7688aa6bd4ee98Mike Lockwood address); 45270a40ec2192e4836b2fcb6ba51a7688aa6bd4ee98Mike Lockwood mConnectedDevices.put( new Integer(AudioSystem.DEVICE_IN_BLUETOOTH_A2DP), 45280a40ec2192e4836b2fcb6ba51a7688aa6bd4ee98Mike Lockwood address); 45290a40ec2192e4836b2fcb6ba51a7688aa6bd4ee98Mike Lockwood } 45300a40ec2192e4836b2fcb6ba51a7688aa6bd4ee98Mike Lockwood 45310a40ec2192e4836b2fcb6ba51a7688aa6bd4ee98Mike Lockwood // must be called synchronized on mConnectedDevices 45320a40ec2192e4836b2fcb6ba51a7688aa6bd4ee98Mike Lockwood private void makeA2dpSrcUnavailable(String address) { 45330a40ec2192e4836b2fcb6ba51a7688aa6bd4ee98Mike Lockwood AudioSystem.setDeviceConnectionState(AudioSystem.DEVICE_IN_BLUETOOTH_A2DP, 45340a40ec2192e4836b2fcb6ba51a7688aa6bd4ee98Mike Lockwood AudioSystem.DEVICE_STATE_UNAVAILABLE, 45350a40ec2192e4836b2fcb6ba51a7688aa6bd4ee98Mike Lockwood address); 45360a40ec2192e4836b2fcb6ba51a7688aa6bd4ee98Mike Lockwood mConnectedDevices.remove(AudioSystem.DEVICE_IN_BLUETOOTH_A2DP); 45370a40ec2192e4836b2fcb6ba51a7688aa6bd4ee98Mike Lockwood } 45380a40ec2192e4836b2fcb6ba51a7688aa6bd4ee98Mike Lockwood 45390a40ec2192e4836b2fcb6ba51a7688aa6bd4ee98Mike Lockwood // must be called synchronized on mConnectedDevices 4540a847ba4080675d395de725cfac5dfd9d5a993d4eJean-Michel Trivi private void cancelA2dpDeviceTimeout() { 45414c637b9e34f4c8db69a64ad21a4e2bcfa7485b5fJean-Michel Trivi mAudioHandler.removeMessages(MSG_BTA2DP_DOCK_TIMEOUT); 45424c637b9e34f4c8db69a64ad21a4e2bcfa7485b5fJean-Michel Trivi } 45434c637b9e34f4c8db69a64ad21a4e2bcfa7485b5fJean-Michel Trivi 45446bc7f2cd30b6bd90806942b0722e22daa2108493Eric Laurent // must be called synchronized on mConnectedDevices 4545a847ba4080675d395de725cfac5dfd9d5a993d4eJean-Michel Trivi private boolean hasScheduledA2dpDockTimeout() { 4546a847ba4080675d395de725cfac5dfd9d5a993d4eJean-Michel Trivi return mAudioHandler.hasMessages(MSG_BTA2DP_DOCK_TIMEOUT); 4547a847ba4080675d395de725cfac5dfd9d5a993d4eJean-Michel Trivi } 4548a847ba4080675d395de725cfac5dfd9d5a993d4eJean-Michel Trivi 45490a40ec2192e4836b2fcb6ba51a7688aa6bd4ee98Mike Lockwood private void onSetA2dpSinkConnectionState(BluetoothDevice btDevice, int state) 45506bc7f2cd30b6bd90806942b0722e22daa2108493Eric Laurent { 45510a40ec2192e4836b2fcb6ba51a7688aa6bd4ee98Mike Lockwood if (DEBUG_VOL) { 45520a40ec2192e4836b2fcb6ba51a7688aa6bd4ee98Mike Lockwood Log.d(TAG, "onSetA2dpSinkConnectionState btDevice="+btDevice+"state="+state); 45530a40ec2192e4836b2fcb6ba51a7688aa6bd4ee98Mike Lockwood } 45546bc7f2cd30b6bd90806942b0722e22daa2108493Eric Laurent if (btDevice == null) { 45556bc7f2cd30b6bd90806942b0722e22daa2108493Eric Laurent return; 45566bc7f2cd30b6bd90806942b0722e22daa2108493Eric Laurent } 45576bc7f2cd30b6bd90806942b0722e22daa2108493Eric Laurent String address = btDevice.getAddress(); 45586bc7f2cd30b6bd90806942b0722e22daa2108493Eric Laurent if (!BluetoothAdapter.checkBluetoothAddress(address)) { 45596bc7f2cd30b6bd90806942b0722e22daa2108493Eric Laurent address = ""; 45606bc7f2cd30b6bd90806942b0722e22daa2108493Eric Laurent } 45615a0cf7a27f3953a1266af48543ccd9024f4cd89fJohn Du 45626bc7f2cd30b6bd90806942b0722e22daa2108493Eric Laurent synchronized (mConnectedDevices) { 45636bc7f2cd30b6bd90806942b0722e22daa2108493Eric Laurent boolean isConnected = 45646bc7f2cd30b6bd90806942b0722e22daa2108493Eric Laurent (mConnectedDevices.containsKey(AudioSystem.DEVICE_OUT_BLUETOOTH_A2DP) && 45656bc7f2cd30b6bd90806942b0722e22daa2108493Eric Laurent mConnectedDevices.get(AudioSystem.DEVICE_OUT_BLUETOOTH_A2DP).equals(address)); 45666bc7f2cd30b6bd90806942b0722e22daa2108493Eric Laurent 45676bc7f2cd30b6bd90806942b0722e22daa2108493Eric Laurent if (isConnected && state != BluetoothProfile.STATE_CONNECTED) { 45686bc7f2cd30b6bd90806942b0722e22daa2108493Eric Laurent if (btDevice.isBluetoothDock()) { 45696bc7f2cd30b6bd90806942b0722e22daa2108493Eric Laurent if (state == BluetoothProfile.STATE_DISCONNECTED) { 45706bc7f2cd30b6bd90806942b0722e22daa2108493Eric Laurent // introduction of a delay for transient disconnections of docks when 45716bc7f2cd30b6bd90806942b0722e22daa2108493Eric Laurent // power is rapidly turned off/on, this message will be canceled if 45726bc7f2cd30b6bd90806942b0722e22daa2108493Eric Laurent // we reconnect the dock under a preset delay 45736bc7f2cd30b6bd90806942b0722e22daa2108493Eric Laurent makeA2dpDeviceUnavailableLater(address); 45746bc7f2cd30b6bd90806942b0722e22daa2108493Eric Laurent // the next time isConnected is evaluated, it will be false for the dock 45756bc7f2cd30b6bd90806942b0722e22daa2108493Eric Laurent } 45766bc7f2cd30b6bd90806942b0722e22daa2108493Eric Laurent } else { 45776bc7f2cd30b6bd90806942b0722e22daa2108493Eric Laurent makeA2dpDeviceUnavailableNow(address); 45786bc7f2cd30b6bd90806942b0722e22daa2108493Eric Laurent } 4579632ca417f0a33e3fa9ccece531afa2db3f0d4a30Dianne Hackborn synchronized (mCurAudioRoutes) { 4580632ca417f0a33e3fa9ccece531afa2db3f0d4a30Dianne Hackborn if (mCurAudioRoutes.mBluetoothName != null) { 4581632ca417f0a33e3fa9ccece531afa2db3f0d4a30Dianne Hackborn mCurAudioRoutes.mBluetoothName = null; 4582632ca417f0a33e3fa9ccece531afa2db3f0d4a30Dianne Hackborn sendMsg(mAudioHandler, MSG_REPORT_NEW_ROUTES, 4583632ca417f0a33e3fa9ccece531afa2db3f0d4a30Dianne Hackborn SENDMSG_NOOP, 0, 0, null, 0); 4584632ca417f0a33e3fa9ccece531afa2db3f0d4a30Dianne Hackborn } 4585632ca417f0a33e3fa9ccece531afa2db3f0d4a30Dianne Hackborn } 45866bc7f2cd30b6bd90806942b0722e22daa2108493Eric Laurent } else if (!isConnected && state == BluetoothProfile.STATE_CONNECTED) { 45876bc7f2cd30b6bd90806942b0722e22daa2108493Eric Laurent if (btDevice.isBluetoothDock()) { 45886bc7f2cd30b6bd90806942b0722e22daa2108493Eric Laurent // this could be a reconnection after a transient disconnection 45896bc7f2cd30b6bd90806942b0722e22daa2108493Eric Laurent cancelA2dpDeviceTimeout(); 45906bc7f2cd30b6bd90806942b0722e22daa2108493Eric Laurent mDockAddress = address; 45916bc7f2cd30b6bd90806942b0722e22daa2108493Eric Laurent } else { 45926bc7f2cd30b6bd90806942b0722e22daa2108493Eric Laurent // this could be a connection of another A2DP device before the timeout of 45936bc7f2cd30b6bd90806942b0722e22daa2108493Eric Laurent // a dock: cancel the dock timeout, and make the dock unavailable now 45946bc7f2cd30b6bd90806942b0722e22daa2108493Eric Laurent if(hasScheduledA2dpDockTimeout()) { 45956bc7f2cd30b6bd90806942b0722e22daa2108493Eric Laurent cancelA2dpDeviceTimeout(); 45966bc7f2cd30b6bd90806942b0722e22daa2108493Eric Laurent makeA2dpDeviceUnavailableNow(mDockAddress); 45976bc7f2cd30b6bd90806942b0722e22daa2108493Eric Laurent } 45986bc7f2cd30b6bd90806942b0722e22daa2108493Eric Laurent } 45996bc7f2cd30b6bd90806942b0722e22daa2108493Eric Laurent makeA2dpDeviceAvailable(address); 4600632ca417f0a33e3fa9ccece531afa2db3f0d4a30Dianne Hackborn synchronized (mCurAudioRoutes) { 4601632ca417f0a33e3fa9ccece531afa2db3f0d4a30Dianne Hackborn String name = btDevice.getAliasName(); 4602632ca417f0a33e3fa9ccece531afa2db3f0d4a30Dianne Hackborn if (!TextUtils.equals(mCurAudioRoutes.mBluetoothName, name)) { 4603632ca417f0a33e3fa9ccece531afa2db3f0d4a30Dianne Hackborn mCurAudioRoutes.mBluetoothName = name; 4604632ca417f0a33e3fa9ccece531afa2db3f0d4a30Dianne Hackborn sendMsg(mAudioHandler, MSG_REPORT_NEW_ROUTES, 4605632ca417f0a33e3fa9ccece531afa2db3f0d4a30Dianne Hackborn SENDMSG_NOOP, 0, 0, null, 0); 4606632ca417f0a33e3fa9ccece531afa2db3f0d4a30Dianne Hackborn } 4607632ca417f0a33e3fa9ccece531afa2db3f0d4a30Dianne Hackborn } 46086bc7f2cd30b6bd90806942b0722e22daa2108493Eric Laurent } 46096bc7f2cd30b6bd90806942b0722e22daa2108493Eric Laurent } 46106bc7f2cd30b6bd90806942b0722e22daa2108493Eric Laurent } 46116bc7f2cd30b6bd90806942b0722e22daa2108493Eric Laurent 46120a40ec2192e4836b2fcb6ba51a7688aa6bd4ee98Mike Lockwood private void onSetA2dpSourceConnectionState(BluetoothDevice btDevice, int state) 46130a40ec2192e4836b2fcb6ba51a7688aa6bd4ee98Mike Lockwood { 46140a40ec2192e4836b2fcb6ba51a7688aa6bd4ee98Mike Lockwood if (DEBUG_VOL) { 46150a40ec2192e4836b2fcb6ba51a7688aa6bd4ee98Mike Lockwood Log.d(TAG, "onSetA2dpSourceConnectionState btDevice="+btDevice+" state="+state); 46160a40ec2192e4836b2fcb6ba51a7688aa6bd4ee98Mike Lockwood } 46170a40ec2192e4836b2fcb6ba51a7688aa6bd4ee98Mike Lockwood if (btDevice == null) { 46180a40ec2192e4836b2fcb6ba51a7688aa6bd4ee98Mike Lockwood return; 46190a40ec2192e4836b2fcb6ba51a7688aa6bd4ee98Mike Lockwood } 46200a40ec2192e4836b2fcb6ba51a7688aa6bd4ee98Mike Lockwood String address = btDevice.getAddress(); 46210a40ec2192e4836b2fcb6ba51a7688aa6bd4ee98Mike Lockwood if (!BluetoothAdapter.checkBluetoothAddress(address)) { 46220a40ec2192e4836b2fcb6ba51a7688aa6bd4ee98Mike Lockwood address = ""; 46230a40ec2192e4836b2fcb6ba51a7688aa6bd4ee98Mike Lockwood } 46240a40ec2192e4836b2fcb6ba51a7688aa6bd4ee98Mike Lockwood 46250a40ec2192e4836b2fcb6ba51a7688aa6bd4ee98Mike Lockwood synchronized (mConnectedDevices) { 46260a40ec2192e4836b2fcb6ba51a7688aa6bd4ee98Mike Lockwood boolean isConnected = 46270a40ec2192e4836b2fcb6ba51a7688aa6bd4ee98Mike Lockwood (mConnectedDevices.containsKey(AudioSystem.DEVICE_IN_BLUETOOTH_A2DP) && 46280a40ec2192e4836b2fcb6ba51a7688aa6bd4ee98Mike Lockwood mConnectedDevices.get(AudioSystem.DEVICE_IN_BLUETOOTH_A2DP).equals(address)); 46290a40ec2192e4836b2fcb6ba51a7688aa6bd4ee98Mike Lockwood 46300a40ec2192e4836b2fcb6ba51a7688aa6bd4ee98Mike Lockwood if (isConnected && state != BluetoothProfile.STATE_CONNECTED) { 46310a40ec2192e4836b2fcb6ba51a7688aa6bd4ee98Mike Lockwood makeA2dpSrcUnavailable(address); 46320a40ec2192e4836b2fcb6ba51a7688aa6bd4ee98Mike Lockwood } else if (!isConnected && state == BluetoothProfile.STATE_CONNECTED) { 46330a40ec2192e4836b2fcb6ba51a7688aa6bd4ee98Mike Lockwood makeA2dpSrcAvailable(address); 46340a40ec2192e4836b2fcb6ba51a7688aa6bd4ee98Mike Lockwood } 46350a40ec2192e4836b2fcb6ba51a7688aa6bd4ee98Mike Lockwood } 46360a40ec2192e4836b2fcb6ba51a7688aa6bd4ee98Mike Lockwood } 46370a40ec2192e4836b2fcb6ba51a7688aa6bd4ee98Mike Lockwood 46385a0cf7a27f3953a1266af48543ccd9024f4cd89fJohn Du public void avrcpSupportsAbsoluteVolume(String address, boolean support) { 46395a0cf7a27f3953a1266af48543ccd9024f4cd89fJohn Du // address is not used for now, but may be used when multiple a2dp devices are supported 46405a0cf7a27f3953a1266af48543ccd9024f4cd89fJohn Du synchronized (mA2dpAvrcpLock) { 46415a0cf7a27f3953a1266af48543ccd9024f4cd89fJohn Du mAvrcpAbsVolSupported = support; 4642c9d1d5f35091226e96fcfa91817480f589eb36e2Matthew Xie sendMsg(mAudioHandler, MSG_SET_DEVICE_VOLUME, SENDMSG_QUEUE, 4643cd772d04345850e160a45613fcf6b86da0dce4cfEric Laurent AudioSystem.DEVICE_OUT_BLUETOOTH_A2DP, 0, 4644cd772d04345850e160a45613fcf6b86da0dce4cfEric Laurent mStreamStates[AudioSystem.STREAM_MUSIC], 0); 4645cd772d04345850e160a45613fcf6b86da0dce4cfEric Laurent sendMsg(mAudioHandler, MSG_SET_DEVICE_VOLUME, SENDMSG_QUEUE, 4646cd772d04345850e160a45613fcf6b86da0dce4cfEric Laurent AudioSystem.DEVICE_OUT_BLUETOOTH_A2DP, 0, 4647cd772d04345850e160a45613fcf6b86da0dce4cfEric Laurent mStreamStates[AudioSystem.STREAM_RING], 0); 46485a0cf7a27f3953a1266af48543ccd9024f4cd89fJohn Du } 46495a0cf7a27f3953a1266af48543ccd9024f4cd89fJohn Du } 46505a0cf7a27f3953a1266af48543ccd9024f4cd89fJohn Du 465159f482764e346a5c5ac118ee1f7b24da645c2559Eric Laurent private boolean handleDeviceConnection(boolean connected, int device, String params) { 465259f482764e346a5c5ac118ee1f7b24da645c2559Eric Laurent synchronized (mConnectedDevices) { 465359f482764e346a5c5ac118ee1f7b24da645c2559Eric Laurent boolean isConnected = (mConnectedDevices.containsKey(device) && 46549841818b9a0280abf59343c9e00a2976dbc084faMike Lockwood (params.isEmpty() || mConnectedDevices.get(device).equals(params))); 465559f482764e346a5c5ac118ee1f7b24da645c2559Eric Laurent 465659f482764e346a5c5ac118ee1f7b24da645c2559Eric Laurent if (isConnected && !connected) { 465759f482764e346a5c5ac118ee1f7b24da645c2559Eric Laurent AudioSystem.setDeviceConnectionState(device, 465859f482764e346a5c5ac118ee1f7b24da645c2559Eric Laurent AudioSystem.DEVICE_STATE_UNAVAILABLE, 46599841818b9a0280abf59343c9e00a2976dbc084faMike Lockwood mConnectedDevices.get(device)); 466059f482764e346a5c5ac118ee1f7b24da645c2559Eric Laurent mConnectedDevices.remove(device); 466159f482764e346a5c5ac118ee1f7b24da645c2559Eric Laurent return true; 466259f482764e346a5c5ac118ee1f7b24da645c2559Eric Laurent } else if (!isConnected && connected) { 466359f482764e346a5c5ac118ee1f7b24da645c2559Eric Laurent AudioSystem.setDeviceConnectionState(device, 466459f482764e346a5c5ac118ee1f7b24da645c2559Eric Laurent AudioSystem.DEVICE_STATE_AVAILABLE, 466559f482764e346a5c5ac118ee1f7b24da645c2559Eric Laurent params); 466659f482764e346a5c5ac118ee1f7b24da645c2559Eric Laurent mConnectedDevices.put(new Integer(device), params); 466759f482764e346a5c5ac118ee1f7b24da645c2559Eric Laurent return true; 466859f482764e346a5c5ac118ee1f7b24da645c2559Eric Laurent } 466959f482764e346a5c5ac118ee1f7b24da645c2559Eric Laurent } 467059f482764e346a5c5ac118ee1f7b24da645c2559Eric Laurent return false; 467159f482764e346a5c5ac118ee1f7b24da645c2559Eric Laurent } 467259f482764e346a5c5ac118ee1f7b24da645c2559Eric Laurent 4673b1fbaaccb656ef09a8770c28df15e3e91a452e64Eric Laurent // Devices which removal triggers intent ACTION_AUDIO_BECOMING_NOISY. The intent is only 4674b1fbaaccb656ef09a8770c28df15e3e91a452e64Eric Laurent // sent if none of these devices is connected. 4675b1fbaaccb656ef09a8770c28df15e3e91a452e64Eric Laurent int mBecomingNoisyIntentDevices = 4676b1fbaaccb656ef09a8770c28df15e3e91a452e64Eric Laurent AudioSystem.DEVICE_OUT_WIRED_HEADSET | AudioSystem.DEVICE_OUT_WIRED_HEADPHONE | 4677948d32748caaac5be06c991ebf00f74265a7849fEric Laurent AudioSystem.DEVICE_OUT_ALL_A2DP | AudioSystem.DEVICE_OUT_HDMI | 4678794da7a0543cbecffefb73794aa68d1a93e41adfEric Laurent AudioSystem.DEVICE_OUT_ANLG_DOCK_HEADSET | AudioSystem.DEVICE_OUT_DGTL_DOCK_HEADSET | 467943cc8bbbbd5e6418cdfa0fa4b26c9f5c3a28c029Jon Eklund AudioSystem.DEVICE_OUT_ALL_USB | AudioSystem.DEVICE_OUT_LINE; 4680b1fbaaccb656ef09a8770c28df15e3e91a452e64Eric Laurent 4681b1fbaaccb656ef09a8770c28df15e3e91a452e64Eric Laurent // must be called before removing the device from mConnectedDevices 4682b1fbaaccb656ef09a8770c28df15e3e91a452e64Eric Laurent private int checkSendBecomingNoisyIntent(int device, int state) { 4683b1fbaaccb656ef09a8770c28df15e3e91a452e64Eric Laurent int delay = 0; 4684b1fbaaccb656ef09a8770c28df15e3e91a452e64Eric Laurent if ((state == 0) && ((device & mBecomingNoisyIntentDevices) != 0)) { 4685b1fbaaccb656ef09a8770c28df15e3e91a452e64Eric Laurent int devices = 0; 4686b1fbaaccb656ef09a8770c28df15e3e91a452e64Eric Laurent for (int dev : mConnectedDevices.keySet()) { 468727c30e4426302581a266c89d0ef880b340d7b061Eric Laurent if (((dev & AudioSystem.DEVICE_BIT_IN) == 0) && 468827c30e4426302581a266c89d0ef880b340d7b061Eric Laurent ((dev & mBecomingNoisyIntentDevices) != 0)) { 4689b1fbaaccb656ef09a8770c28df15e3e91a452e64Eric Laurent devices |= dev; 4690b1fbaaccb656ef09a8770c28df15e3e91a452e64Eric Laurent } 4691b1fbaaccb656ef09a8770c28df15e3e91a452e64Eric Laurent } 4692b1fbaaccb656ef09a8770c28df15e3e91a452e64Eric Laurent if (devices == device) { 46935bfaeaef3fc348d66f48b86be08655e91dff910aEric Laurent sendMsg(mAudioHandler, 46945bfaeaef3fc348d66f48b86be08655e91dff910aEric Laurent MSG_BROADCAST_AUDIO_BECOMING_NOISY, 46955bfaeaef3fc348d66f48b86be08655e91dff910aEric Laurent SENDMSG_REPLACE, 46965bfaeaef3fc348d66f48b86be08655e91dff910aEric Laurent 0, 46975bfaeaef3fc348d66f48b86be08655e91dff910aEric Laurent 0, 46985bfaeaef3fc348d66f48b86be08655e91dff910aEric Laurent null, 46995bfaeaef3fc348d66f48b86be08655e91dff910aEric Laurent 0); 4700b1fbaaccb656ef09a8770c28df15e3e91a452e64Eric Laurent delay = 1000; 4701b1fbaaccb656ef09a8770c28df15e3e91a452e64Eric Laurent } 4702b1fbaaccb656ef09a8770c28df15e3e91a452e64Eric Laurent } 4703b1fbaaccb656ef09a8770c28df15e3e91a452e64Eric Laurent 47040a40ec2192e4836b2fcb6ba51a7688aa6bd4ee98Mike Lockwood if (mAudioHandler.hasMessages(MSG_SET_A2DP_SRC_CONNECTION_STATE) || 47050a40ec2192e4836b2fcb6ba51a7688aa6bd4ee98Mike Lockwood mAudioHandler.hasMessages(MSG_SET_A2DP_SINK_CONNECTION_STATE) || 4706b1fbaaccb656ef09a8770c28df15e3e91a452e64Eric Laurent mAudioHandler.hasMessages(MSG_SET_WIRED_DEVICE_CONNECTION_STATE)) { 4707adbe8bf85f3c8230d16ae5cb3f5d9736e09ed84aEric Laurent synchronized (mLastDeviceConnectMsgTime) { 4708adbe8bf85f3c8230d16ae5cb3f5d9736e09ed84aEric Laurent long time = SystemClock.uptimeMillis(); 4709adbe8bf85f3c8230d16ae5cb3f5d9736e09ed84aEric Laurent if (mLastDeviceConnectMsgTime > time) { 4710adbe8bf85f3c8230d16ae5cb3f5d9736e09ed84aEric Laurent delay = (int)(mLastDeviceConnectMsgTime - time); 4711adbe8bf85f3c8230d16ae5cb3f5d9736e09ed84aEric Laurent } 4712adbe8bf85f3c8230d16ae5cb3f5d9736e09ed84aEric Laurent } 4713b1fbaaccb656ef09a8770c28df15e3e91a452e64Eric Laurent } 4714b1fbaaccb656ef09a8770c28df15e3e91a452e64Eric Laurent return delay; 4715b1fbaaccb656ef09a8770c28df15e3e91a452e64Eric Laurent } 4716b1fbaaccb656ef09a8770c28df15e3e91a452e64Eric Laurent 4717b1fbaaccb656ef09a8770c28df15e3e91a452e64Eric Laurent private void sendDeviceConnectionIntent(int device, int state, String name) 4718b1fbaaccb656ef09a8770c28df15e3e91a452e64Eric Laurent { 4719b1fbaaccb656ef09a8770c28df15e3e91a452e64Eric Laurent Intent intent = new Intent(); 4720b1fbaaccb656ef09a8770c28df15e3e91a452e64Eric Laurent 4721b1fbaaccb656ef09a8770c28df15e3e91a452e64Eric Laurent intent.putExtra("state", state); 4722b1fbaaccb656ef09a8770c28df15e3e91a452e64Eric Laurent intent.putExtra("name", name); 4723b1fbaaccb656ef09a8770c28df15e3e91a452e64Eric Laurent intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY); 4724b1fbaaccb656ef09a8770c28df15e3e91a452e64Eric Laurent 4725632ca417f0a33e3fa9ccece531afa2db3f0d4a30Dianne Hackborn int connType = 0; 4726632ca417f0a33e3fa9ccece531afa2db3f0d4a30Dianne Hackborn 4727b1fbaaccb656ef09a8770c28df15e3e91a452e64Eric Laurent if (device == AudioSystem.DEVICE_OUT_WIRED_HEADSET) { 4728632ca417f0a33e3fa9ccece531afa2db3f0d4a30Dianne Hackborn connType = AudioRoutesInfo.MAIN_HEADSET; 4729b1fbaaccb656ef09a8770c28df15e3e91a452e64Eric Laurent intent.setAction(Intent.ACTION_HEADSET_PLUG); 4730b1fbaaccb656ef09a8770c28df15e3e91a452e64Eric Laurent intent.putExtra("microphone", 1); 473143cc8bbbbd5e6418cdfa0fa4b26c9f5c3a28c029Jon Eklund } else if (device == AudioSystem.DEVICE_OUT_WIRED_HEADPHONE || 473243cc8bbbbd5e6418cdfa0fa4b26c9f5c3a28c029Jon Eklund device == AudioSystem.DEVICE_OUT_LINE) { 473343cc8bbbbd5e6418cdfa0fa4b26c9f5c3a28c029Jon Eklund /*do apps care about line-out vs headphones?*/ 4734632ca417f0a33e3fa9ccece531afa2db3f0d4a30Dianne Hackborn connType = AudioRoutesInfo.MAIN_HEADPHONES; 4735b1fbaaccb656ef09a8770c28df15e3e91a452e64Eric Laurent intent.setAction(Intent.ACTION_HEADSET_PLUG); 4736b1fbaaccb656ef09a8770c28df15e3e91a452e64Eric Laurent intent.putExtra("microphone", 0); 4737b1fbaaccb656ef09a8770c28df15e3e91a452e64Eric Laurent } else if (device == AudioSystem.DEVICE_OUT_ANLG_DOCK_HEADSET) { 4738632ca417f0a33e3fa9ccece531afa2db3f0d4a30Dianne Hackborn connType = AudioRoutesInfo.MAIN_DOCK_SPEAKERS; 4739c5258433dd353769ccfa2e5e769a7379378a3a0bJean-Michel Trivi intent.setAction(AudioManager.ACTION_ANALOG_AUDIO_DOCK_PLUG); 4740b1fbaaccb656ef09a8770c28df15e3e91a452e64Eric Laurent } else if (device == AudioSystem.DEVICE_OUT_DGTL_DOCK_HEADSET) { 4741632ca417f0a33e3fa9ccece531afa2db3f0d4a30Dianne Hackborn connType = AudioRoutesInfo.MAIN_DOCK_SPEAKERS; 4742c5258433dd353769ccfa2e5e769a7379378a3a0bJean-Michel Trivi intent.setAction(AudioManager.ACTION_DIGITAL_AUDIO_DOCK_PLUG); 47436fa4245589c93025d91aab7dc6681babdd91ee41Eric Laurent } else if (device == AudioSystem.DEVICE_OUT_HDMI || 47446fa4245589c93025d91aab7dc6681babdd91ee41Eric Laurent device == AudioSystem.DEVICE_OUT_HDMI_ARC) { 4745632ca417f0a33e3fa9ccece531afa2db3f0d4a30Dianne Hackborn connType = AudioRoutesInfo.MAIN_HDMI; 474637d7804627eecaf04e170793c2f5703d5d6d44e8Jean-Michel Trivi configureHdmiPlugIntent(intent, state); 4747b1fbaaccb656ef09a8770c28df15e3e91a452e64Eric Laurent } 4748b1fbaaccb656ef09a8770c28df15e3e91a452e64Eric Laurent 4749632ca417f0a33e3fa9ccece531afa2db3f0d4a30Dianne Hackborn synchronized (mCurAudioRoutes) { 4750632ca417f0a33e3fa9ccece531afa2db3f0d4a30Dianne Hackborn if (connType != 0) { 4751632ca417f0a33e3fa9ccece531afa2db3f0d4a30Dianne Hackborn int newConn = mCurAudioRoutes.mMainType; 4752632ca417f0a33e3fa9ccece531afa2db3f0d4a30Dianne Hackborn if (state != 0) { 4753632ca417f0a33e3fa9ccece531afa2db3f0d4a30Dianne Hackborn newConn |= connType; 4754632ca417f0a33e3fa9ccece531afa2db3f0d4a30Dianne Hackborn } else { 4755632ca417f0a33e3fa9ccece531afa2db3f0d4a30Dianne Hackborn newConn &= ~connType; 4756632ca417f0a33e3fa9ccece531afa2db3f0d4a30Dianne Hackborn } 4757632ca417f0a33e3fa9ccece531afa2db3f0d4a30Dianne Hackborn if (newConn != mCurAudioRoutes.mMainType) { 4758632ca417f0a33e3fa9ccece531afa2db3f0d4a30Dianne Hackborn mCurAudioRoutes.mMainType = newConn; 4759632ca417f0a33e3fa9ccece531afa2db3f0d4a30Dianne Hackborn sendMsg(mAudioHandler, MSG_REPORT_NEW_ROUTES, 4760632ca417f0a33e3fa9ccece531afa2db3f0d4a30Dianne Hackborn SENDMSG_NOOP, 0, 0, null, 0); 4761632ca417f0a33e3fa9ccece531afa2db3f0d4a30Dianne Hackborn } 4762632ca417f0a33e3fa9ccece531afa2db3f0d4a30Dianne Hackborn } 4763632ca417f0a33e3fa9ccece531afa2db3f0d4a30Dianne Hackborn } 4764632ca417f0a33e3fa9ccece531afa2db3f0d4a30Dianne Hackborn 47655ac72a29593ab9a20337a2225df52bdf4754be02Dianne Hackborn final long ident = Binder.clearCallingIdentity(); 47665ac72a29593ab9a20337a2225df52bdf4754be02Dianne Hackborn try { 47675ac72a29593ab9a20337a2225df52bdf4754be02Dianne Hackborn ActivityManagerNative.broadcastStickyIntent(intent, null, UserHandle.USER_ALL); 47685ac72a29593ab9a20337a2225df52bdf4754be02Dianne Hackborn } finally { 47695ac72a29593ab9a20337a2225df52bdf4754be02Dianne Hackborn Binder.restoreCallingIdentity(ident); 47705ac72a29593ab9a20337a2225df52bdf4754be02Dianne Hackborn } 4771b1fbaaccb656ef09a8770c28df15e3e91a452e64Eric Laurent } 4772b1fbaaccb656ef09a8770c28df15e3e91a452e64Eric Laurent 4773b1fbaaccb656ef09a8770c28df15e3e91a452e64Eric Laurent private void onSetWiredDeviceConnectionState(int device, int state, String name) 4774b1fbaaccb656ef09a8770c28df15e3e91a452e64Eric Laurent { 4775b1fbaaccb656ef09a8770c28df15e3e91a452e64Eric Laurent synchronized (mConnectedDevices) { 4776b1fbaaccb656ef09a8770c28df15e3e91a452e64Eric Laurent if ((state == 0) && ((device == AudioSystem.DEVICE_OUT_WIRED_HEADSET) || 477743cc8bbbbd5e6418cdfa0fa4b26c9f5c3a28c029Jon Eklund (device == AudioSystem.DEVICE_OUT_WIRED_HEADPHONE) || 477843cc8bbbbd5e6418cdfa0fa4b26c9f5c3a28c029Jon Eklund (device == AudioSystem.DEVICE_OUT_LINE))) { 4779b1fbaaccb656ef09a8770c28df15e3e91a452e64Eric Laurent setBluetoothA2dpOnInt(true); 4780b1fbaaccb656ef09a8770c28df15e3e91a452e64Eric Laurent } 4781ae4506e9b5fc3e0c6d9862fbc05b9af7d6742a6eEric Laurent boolean isUsb = ((device & ~AudioSystem.DEVICE_OUT_ALL_USB) == 0) || 4782ae4506e9b5fc3e0c6d9862fbc05b9af7d6742a6eEric Laurent (((device & AudioSystem.DEVICE_BIT_IN) != 0) && 4783ae4506e9b5fc3e0c6d9862fbc05b9af7d6742a6eEric Laurent ((device & ~AudioSystem.DEVICE_IN_ALL_USB) == 0)); 4784db45484e4b5858d14da93d3a06311b93bf0cf320Mike Lockwood handleDeviceConnection((state == 1), device, (isUsb ? name : "")); 4785f1a457d06c53a901ea08d2d3fb6e766bc06c4d4fEric Laurent if (state != 0) { 4786f1a457d06c53a901ea08d2d3fb6e766bc06c4d4fEric Laurent if ((device == AudioSystem.DEVICE_OUT_WIRED_HEADSET) || 478743cc8bbbbd5e6418cdfa0fa4b26c9f5c3a28c029Jon Eklund (device == AudioSystem.DEVICE_OUT_WIRED_HEADPHONE) || 478843cc8bbbbd5e6418cdfa0fa4b26c9f5c3a28c029Jon Eklund (device == AudioSystem.DEVICE_OUT_LINE)) { 4789f1a457d06c53a901ea08d2d3fb6e766bc06c4d4fEric Laurent setBluetoothA2dpOnInt(false); 4790f1a457d06c53a901ea08d2d3fb6e766bc06c4d4fEric Laurent } 4791f1a457d06c53a901ea08d2d3fb6e766bc06c4d4fEric Laurent if ((device & mSafeMediaVolumeDevices) != 0) { 4792f1a457d06c53a901ea08d2d3fb6e766bc06c4d4fEric Laurent sendMsg(mAudioHandler, 4793f1a457d06c53a901ea08d2d3fb6e766bc06c4d4fEric Laurent MSG_CHECK_MUSIC_ACTIVE, 4794f1a457d06c53a901ea08d2d3fb6e766bc06c4d4fEric Laurent SENDMSG_REPLACE, 4795f1a457d06c53a901ea08d2d3fb6e766bc06c4d4fEric Laurent 0, 4796f1a457d06c53a901ea08d2d3fb6e766bc06c4d4fEric Laurent 0, 4797f1a457d06c53a901ea08d2d3fb6e766bc06c4d4fEric Laurent null, 4798f1a457d06c53a901ea08d2d3fb6e766bc06c4d4fEric Laurent MUSIC_ACTIVE_POLL_PERIOD_MS); 4799f1a457d06c53a901ea08d2d3fb6e766bc06c4d4fEric Laurent } 4800212532b58e3b17d7e9d6e1361946d909d4e372c2Eric Laurent // Television devices without CEC service apply software volume on HDMI output 4801212532b58e3b17d7e9d6e1361946d909d4e372c2Eric Laurent if (isPlatformTelevision() && ((device & AudioSystem.DEVICE_OUT_HDMI) != 0)) { 4802212532b58e3b17d7e9d6e1361946d909d4e372c2Eric Laurent mFixedVolumeDevices |= AudioSystem.DEVICE_OUT_HDMI; 4803212532b58e3b17d7e9d6e1361946d909d4e372c2Eric Laurent checkAllFixedVolumeDevices(); 4804212532b58e3b17d7e9d6e1361946d909d4e372c2Eric Laurent if (mHdmiManager != null) { 4805212532b58e3b17d7e9d6e1361946d909d4e372c2Eric Laurent synchronized (mHdmiManager) { 4806212532b58e3b17d7e9d6e1361946d909d4e372c2Eric Laurent if (mHdmiPlaybackClient != null) { 4807212532b58e3b17d7e9d6e1361946d909d4e372c2Eric Laurent mHdmiCecSink = false; 4808212532b58e3b17d7e9d6e1361946d909d4e372c2Eric Laurent mHdmiPlaybackClient.queryDisplayStatus(mHdmiDisplayStatusCallback); 4809212532b58e3b17d7e9d6e1361946d909d4e372c2Eric Laurent } 4810212532b58e3b17d7e9d6e1361946d909d4e372c2Eric Laurent } 4811212532b58e3b17d7e9d6e1361946d909d4e372c2Eric Laurent } 4812212532b58e3b17d7e9d6e1361946d909d4e372c2Eric Laurent } 4813212532b58e3b17d7e9d6e1361946d909d4e372c2Eric Laurent } else { 4814212532b58e3b17d7e9d6e1361946d909d4e372c2Eric Laurent if (isPlatformTelevision() && ((device & AudioSystem.DEVICE_OUT_HDMI) != 0)) { 4815212532b58e3b17d7e9d6e1361946d909d4e372c2Eric Laurent if (mHdmiManager != null) { 4816212532b58e3b17d7e9d6e1361946d909d4e372c2Eric Laurent synchronized (mHdmiManager) { 4817212532b58e3b17d7e9d6e1361946d909d4e372c2Eric Laurent mHdmiCecSink = false; 4818212532b58e3b17d7e9d6e1361946d909d4e372c2Eric Laurent } 4819212532b58e3b17d7e9d6e1361946d909d4e372c2Eric Laurent } 4820212532b58e3b17d7e9d6e1361946d909d4e372c2Eric Laurent } 4821b1fbaaccb656ef09a8770c28df15e3e91a452e64Eric Laurent } 4822ae4506e9b5fc3e0c6d9862fbc05b9af7d6742a6eEric Laurent if (!isUsb && (device != AudioSystem.DEVICE_IN_WIRED_HEADSET)) { 4823db45484e4b5858d14da93d3a06311b93bf0cf320Mike Lockwood sendDeviceConnectionIntent(device, state, name); 4824db45484e4b5858d14da93d3a06311b93bf0cf320Mike Lockwood } 4825b1fbaaccb656ef09a8770c28df15e3e91a452e64Eric Laurent } 4826b1fbaaccb656ef09a8770c28df15e3e91a452e64Eric Laurent } 4827b1fbaaccb656ef09a8770c28df15e3e91a452e64Eric Laurent 482837d7804627eecaf04e170793c2f5703d5d6d44e8Jean-Michel Trivi private void configureHdmiPlugIntent(Intent intent, int state) { 4829c5258433dd353769ccfa2e5e769a7379378a3a0bJean-Michel Trivi intent.setAction(AudioManager.ACTION_HDMI_AUDIO_PLUG); 4830c5258433dd353769ccfa2e5e769a7379378a3a0bJean-Michel Trivi intent.putExtra(AudioManager.EXTRA_AUDIO_PLUG_STATE, state); 483137d7804627eecaf04e170793c2f5703d5d6d44e8Jean-Michel Trivi if (state == 1) { 483237d7804627eecaf04e170793c2f5703d5d6d44e8Jean-Michel Trivi ArrayList<AudioPort> ports = new ArrayList<AudioPort>(); 483337d7804627eecaf04e170793c2f5703d5d6d44e8Jean-Michel Trivi int[] portGeneration = new int[1]; 483437d7804627eecaf04e170793c2f5703d5d6d44e8Jean-Michel Trivi int status = AudioSystem.listAudioPorts(ports, portGeneration); 483537d7804627eecaf04e170793c2f5703d5d6d44e8Jean-Michel Trivi if (status == AudioManager.SUCCESS) { 483637d7804627eecaf04e170793c2f5703d5d6d44e8Jean-Michel Trivi for (AudioPort port : ports) { 483737d7804627eecaf04e170793c2f5703d5d6d44e8Jean-Michel Trivi if (port instanceof AudioDevicePort) { 483837d7804627eecaf04e170793c2f5703d5d6d44e8Jean-Michel Trivi final AudioDevicePort devicePort = (AudioDevicePort) port; 48396fa4245589c93025d91aab7dc6681babdd91ee41Eric Laurent if (devicePort.type() == AudioManager.DEVICE_OUT_HDMI || 48406fa4245589c93025d91aab7dc6681babdd91ee41Eric Laurent devicePort.type() == AudioManager.DEVICE_OUT_HDMI_ARC) { 484137d7804627eecaf04e170793c2f5703d5d6d44e8Jean-Michel Trivi // format the list of supported encodings 484237d7804627eecaf04e170793c2f5703d5d6d44e8Jean-Michel Trivi int[] formats = devicePort.formats(); 484337d7804627eecaf04e170793c2f5703d5d6d44e8Jean-Michel Trivi if (formats.length > 0) { 484437d7804627eecaf04e170793c2f5703d5d6d44e8Jean-Michel Trivi ArrayList<Integer> encodingList = new ArrayList(1); 484537d7804627eecaf04e170793c2f5703d5d6d44e8Jean-Michel Trivi for (int format : formats) { 484637d7804627eecaf04e170793c2f5703d5d6d44e8Jean-Michel Trivi // a format in the list can be 0, skip it 484737d7804627eecaf04e170793c2f5703d5d6d44e8Jean-Michel Trivi if (format != AudioFormat.ENCODING_INVALID) { 484837d7804627eecaf04e170793c2f5703d5d6d44e8Jean-Michel Trivi encodingList.add(format); 484937d7804627eecaf04e170793c2f5703d5d6d44e8Jean-Michel Trivi } 485037d7804627eecaf04e170793c2f5703d5d6d44e8Jean-Michel Trivi } 485137d7804627eecaf04e170793c2f5703d5d6d44e8Jean-Michel Trivi int[] encodingArray = new int[encodingList.size()]; 485237d7804627eecaf04e170793c2f5703d5d6d44e8Jean-Michel Trivi for (int i = 0 ; i < encodingArray.length ; i++) { 485337d7804627eecaf04e170793c2f5703d5d6d44e8Jean-Michel Trivi encodingArray[i] = encodingList.get(i); 485437d7804627eecaf04e170793c2f5703d5d6d44e8Jean-Michel Trivi } 4855c5258433dd353769ccfa2e5e769a7379378a3a0bJean-Michel Trivi intent.putExtra(AudioManager.EXTRA_ENCODINGS, encodingArray); 485637d7804627eecaf04e170793c2f5703d5d6d44e8Jean-Michel Trivi } 485737d7804627eecaf04e170793c2f5703d5d6d44e8Jean-Michel Trivi // find the maximum supported number of channels 485837d7804627eecaf04e170793c2f5703d5d6d44e8Jean-Michel Trivi int maxChannels = 0; 485937d7804627eecaf04e170793c2f5703d5d6d44e8Jean-Michel Trivi for (int mask : devicePort.channelMasks()) { 486037d7804627eecaf04e170793c2f5703d5d6d44e8Jean-Michel Trivi int channelCount = AudioFormat.channelCountFromOutChannelMask(mask); 486137d7804627eecaf04e170793c2f5703d5d6d44e8Jean-Michel Trivi if (channelCount > maxChannels) { 486237d7804627eecaf04e170793c2f5703d5d6d44e8Jean-Michel Trivi maxChannels = channelCount; 486337d7804627eecaf04e170793c2f5703d5d6d44e8Jean-Michel Trivi } 486437d7804627eecaf04e170793c2f5703d5d6d44e8Jean-Michel Trivi } 4865c5258433dd353769ccfa2e5e769a7379378a3a0bJean-Michel Trivi intent.putExtra(AudioManager.EXTRA_MAX_CHANNEL_COUNT, maxChannels); 486637d7804627eecaf04e170793c2f5703d5d6d44e8Jean-Michel Trivi } 486737d7804627eecaf04e170793c2f5703d5d6d44e8Jean-Michel Trivi } 486837d7804627eecaf04e170793c2f5703d5d6d44e8Jean-Michel Trivi } 486937d7804627eecaf04e170793c2f5703d5d6d44e8Jean-Michel Trivi } 487037d7804627eecaf04e170793c2f5703d5d6d44e8Jean-Michel Trivi } 487137d7804627eecaf04e170793c2f5703d5d6d44e8Jean-Michel Trivi } 487237d7804627eecaf04e170793c2f5703d5d6d44e8Jean-Michel Trivi 4873a847ba4080675d395de725cfac5dfd9d5a993d4eJean-Michel Trivi /* cache of the address of the last dock the device was connected to */ 4874a847ba4080675d395de725cfac5dfd9d5a993d4eJean-Michel Trivi private String mDockAddress; 4875a847ba4080675d395de725cfac5dfd9d5a993d4eJean-Michel Trivi 4876a553c25b33c99b345cf1c8688f8df0ed8df14e5aEric Laurent /** 4877a553c25b33c99b345cf1c8688f8df0ed8df14e5aEric Laurent * Receiver for misc intent broadcasts the Phone app cares about. 4878a553c25b33c99b345cf1c8688f8df0ed8df14e5aEric Laurent */ 4879a553c25b33c99b345cf1c8688f8df0ed8df14e5aEric Laurent private class AudioServiceBroadcastReceiver extends BroadcastReceiver { 4880a553c25b33c99b345cf1c8688f8df0ed8df14e5aEric Laurent @Override 4881a553c25b33c99b345cf1c8688f8df0ed8df14e5aEric Laurent public void onReceive(Context context, Intent intent) { 4882a553c25b33c99b345cf1c8688f8df0ed8df14e5aEric Laurent String action = intent.getAction(); 4883ae4506e9b5fc3e0c6d9862fbc05b9af7d6742a6eEric Laurent int outDevice; 4884ae4506e9b5fc3e0c6d9862fbc05b9af7d6742a6eEric Laurent int inDevice; 488559f482764e346a5c5ac118ee1f7b24da645c2559Eric Laurent int state; 4886a553c25b33c99b345cf1c8688f8df0ed8df14e5aEric Laurent 4887758559e6b7e310cf46cc269437f44decd58d68d6Jean-Michel Trivi if (action.equals(Intent.ACTION_DOCK_EVENT)) { 4888758559e6b7e310cf46cc269437f44decd58d68d6Jean-Michel Trivi int dockState = intent.getIntExtra(Intent.EXTRA_DOCK_STATE, 4889758559e6b7e310cf46cc269437f44decd58d68d6Jean-Michel Trivi Intent.EXTRA_DOCK_STATE_UNDOCKED); 4890758559e6b7e310cf46cc269437f44decd58d68d6Jean-Michel Trivi int config; 4891758559e6b7e310cf46cc269437f44decd58d68d6Jean-Michel Trivi switch (dockState) { 4892758559e6b7e310cf46cc269437f44decd58d68d6Jean-Michel Trivi case Intent.EXTRA_DOCK_STATE_DESK: 4893758559e6b7e310cf46cc269437f44decd58d68d6Jean-Michel Trivi config = AudioSystem.FORCE_BT_DESK_DOCK; 4894758559e6b7e310cf46cc269437f44decd58d68d6Jean-Michel Trivi break; 4895758559e6b7e310cf46cc269437f44decd58d68d6Jean-Michel Trivi case Intent.EXTRA_DOCK_STATE_CAR: 4896758559e6b7e310cf46cc269437f44decd58d68d6Jean-Michel Trivi config = AudioSystem.FORCE_BT_CAR_DOCK; 4897758559e6b7e310cf46cc269437f44decd58d68d6Jean-Michel Trivi break; 489821e941bf43362ddc6639a9f2d0828053360f53d7Praveen Bharathi case Intent.EXTRA_DOCK_STATE_LE_DESK: 489908ed1b9d2099ec8231b21353b33b901492ea9885Eric Laurent config = AudioSystem.FORCE_ANALOG_DOCK; 490021e941bf43362ddc6639a9f2d0828053360f53d7Praveen Bharathi break; 490121e941bf43362ddc6639a9f2d0828053360f53d7Praveen Bharathi case Intent.EXTRA_DOCK_STATE_HE_DESK: 490221e941bf43362ddc6639a9f2d0828053360f53d7Praveen Bharathi config = AudioSystem.FORCE_DIGITAL_DOCK; 490321e941bf43362ddc6639a9f2d0828053360f53d7Praveen Bharathi break; 4904758559e6b7e310cf46cc269437f44decd58d68d6Jean-Michel Trivi case Intent.EXTRA_DOCK_STATE_UNDOCKED: 4905758559e6b7e310cf46cc269437f44decd58d68d6Jean-Michel Trivi default: 4906758559e6b7e310cf46cc269437f44decd58d68d6Jean-Michel Trivi config = AudioSystem.FORCE_NONE; 4907758559e6b7e310cf46cc269437f44decd58d68d6Jean-Michel Trivi } 490808ed1b9d2099ec8231b21353b33b901492ea9885Eric Laurent // Low end docks have a menu to enable or disable audio 490908ed1b9d2099ec8231b21353b33b901492ea9885Eric Laurent // (see mDockAudioMediaEnabled) 491008ed1b9d2099ec8231b21353b33b901492ea9885Eric Laurent if (!((dockState == Intent.EXTRA_DOCK_STATE_LE_DESK) || 491108ed1b9d2099ec8231b21353b33b901492ea9885Eric Laurent ((dockState == Intent.EXTRA_DOCK_STATE_UNDOCKED) && 491208ed1b9d2099ec8231b21353b33b901492ea9885Eric Laurent (mDockState == Intent.EXTRA_DOCK_STATE_LE_DESK)))) { 491308ed1b9d2099ec8231b21353b33b901492ea9885Eric Laurent AudioSystem.setForceUse(AudioSystem.FOR_DOCK, config); 491408ed1b9d2099ec8231b21353b33b901492ea9885Eric Laurent } 491508ed1b9d2099ec8231b21353b33b901492ea9885Eric Laurent mDockState = dockState; 491682aa7f017daaaeb96c13e6e3491d5037ab471085Jaikumar Ganesh } else if (action.equals(BluetoothHeadset.ACTION_CONNECTION_STATE_CHANGED)) { 491759f482764e346a5c5ac118ee1f7b24da645c2559Eric Laurent state = intent.getIntExtra(BluetoothProfile.EXTRA_STATE, 491882aa7f017daaaeb96c13e6e3491d5037ab471085Jaikumar Ganesh BluetoothProfile.STATE_DISCONNECTED); 4919ae4506e9b5fc3e0c6d9862fbc05b9af7d6742a6eEric Laurent outDevice = AudioSystem.DEVICE_OUT_BLUETOOTH_SCO; 4920ae4506e9b5fc3e0c6d9862fbc05b9af7d6742a6eEric Laurent inDevice = AudioSystem.DEVICE_IN_BLUETOOTH_SCO_HEADSET; 4921a56d1c72190462aa9e377906583eceb58e0efcddNick Pelly String address = null; 4922dca56b9432e2cc851d1a58920071fed2e1e3d142Eric Laurent 4923dca56b9432e2cc851d1a58920071fed2e1e3d142Eric Laurent BluetoothDevice btDevice = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE); 4924dca56b9432e2cc851d1a58920071fed2e1e3d142Eric Laurent if (btDevice == null) { 4925dca56b9432e2cc851d1a58920071fed2e1e3d142Eric Laurent return; 4926dca56b9432e2cc851d1a58920071fed2e1e3d142Eric Laurent } 4927dca56b9432e2cc851d1a58920071fed2e1e3d142Eric Laurent 4928dca56b9432e2cc851d1a58920071fed2e1e3d142Eric Laurent address = btDevice.getAddress(); 4929dca56b9432e2cc851d1a58920071fed2e1e3d142Eric Laurent BluetoothClass btClass = btDevice.getBluetoothClass(); 4930dca56b9432e2cc851d1a58920071fed2e1e3d142Eric Laurent if (btClass != null) { 4931dca56b9432e2cc851d1a58920071fed2e1e3d142Eric Laurent switch (btClass.getDeviceClass()) { 4932dca56b9432e2cc851d1a58920071fed2e1e3d142Eric Laurent case BluetoothClass.Device.AUDIO_VIDEO_WEARABLE_HEADSET: 4933dca56b9432e2cc851d1a58920071fed2e1e3d142Eric Laurent case BluetoothClass.Device.AUDIO_VIDEO_HANDSFREE: 4934ae4506e9b5fc3e0c6d9862fbc05b9af7d6742a6eEric Laurent outDevice = AudioSystem.DEVICE_OUT_BLUETOOTH_SCO_HEADSET; 4935dca56b9432e2cc851d1a58920071fed2e1e3d142Eric Laurent break; 4936dca56b9432e2cc851d1a58920071fed2e1e3d142Eric Laurent case BluetoothClass.Device.AUDIO_VIDEO_CAR_AUDIO: 4937ae4506e9b5fc3e0c6d9862fbc05b9af7d6742a6eEric Laurent outDevice = AudioSystem.DEVICE_OUT_BLUETOOTH_SCO_CARKIT; 4938dca56b9432e2cc851d1a58920071fed2e1e3d142Eric Laurent break; 4939d5603c126acdd94d9f7400bb1d04188020a425b4Eric Laurent } 4940d5603c126acdd94d9f7400bb1d04188020a425b4Eric Laurent } 4941d5603c126acdd94d9f7400bb1d04188020a425b4Eric Laurent 4942dca56b9432e2cc851d1a58920071fed2e1e3d142Eric Laurent if (!BluetoothAdapter.checkBluetoothAddress(address)) { 4943dca56b9432e2cc851d1a58920071fed2e1e3d142Eric Laurent address = ""; 4944dca56b9432e2cc851d1a58920071fed2e1e3d142Eric Laurent } 4945d5603c126acdd94d9f7400bb1d04188020a425b4Eric Laurent 494659f482764e346a5c5ac118ee1f7b24da645c2559Eric Laurent boolean connected = (state == BluetoothProfile.STATE_CONNECTED); 4947ae4506e9b5fc3e0c6d9862fbc05b9af7d6742a6eEric Laurent boolean success = handleDeviceConnection(connected, outDevice, address) && 4948ae4506e9b5fc3e0c6d9862fbc05b9af7d6742a6eEric Laurent handleDeviceConnection(connected, inDevice, address); 4949ae4506e9b5fc3e0c6d9862fbc05b9af7d6742a6eEric Laurent if (success) { 49506bc7f2cd30b6bd90806942b0722e22daa2108493Eric Laurent synchronized (mScoClients) { 495159f482764e346a5c5ac118ee1f7b24da645c2559Eric Laurent if (connected) { 495259f482764e346a5c5ac118ee1f7b24da645c2559Eric Laurent mBluetoothHeadsetDevice = btDevice; 495359f482764e346a5c5ac118ee1f7b24da645c2559Eric Laurent } else { 49546bc7f2cd30b6bd90806942b0722e22daa2108493Eric Laurent mBluetoothHeadsetDevice = null; 49556bc7f2cd30b6bd90806942b0722e22daa2108493Eric Laurent resetBluetoothSco(); 49566bc7f2cd30b6bd90806942b0722e22daa2108493Eric Laurent } 495762ef767b15a712bab31cc0d5508a330906f535c2Eric Laurent } 4958a553c25b33c99b345cf1c8688f8df0ed8df14e5aEric Laurent } 4959c5258433dd353769ccfa2e5e769a7379378a3a0bJean-Michel Trivi } else if (action.equals(AudioManager.ACTION_USB_AUDIO_ACCESSORY_PLUG)) { 4960df3614693dd4fe52a116dcd28bd74eae80818a4fPaul McLean state = intent.getIntExtra("state", 0); 4961df3614693dd4fe52a116dcd28bd74eae80818a4fPaul McLean 4962df3614693dd4fe52a116dcd28bd74eae80818a4fPaul McLean int alsaCard = intent.getIntExtra("card", -1); 4963df3614693dd4fe52a116dcd28bd74eae80818a4fPaul McLean int alsaDevice = intent.getIntExtra("device", -1); 4964df3614693dd4fe52a116dcd28bd74eae80818a4fPaul McLean 4965df3614693dd4fe52a116dcd28bd74eae80818a4fPaul McLean String params = (alsaCard == -1 && alsaDevice == -1 ? "" 4966df3614693dd4fe52a116dcd28bd74eae80818a4fPaul McLean : "card=" + alsaCard + ";device=" + alsaDevice); 4967df3614693dd4fe52a116dcd28bd74eae80818a4fPaul McLean 4968df3614693dd4fe52a116dcd28bd74eae80818a4fPaul McLean // Playback Device 4969ae4506e9b5fc3e0c6d9862fbc05b9af7d6742a6eEric Laurent outDevice = AudioSystem.DEVICE_OUT_USB_ACCESSORY; 4970ae4506e9b5fc3e0c6d9862fbc05b9af7d6742a6eEric Laurent setWiredDeviceConnectionState(outDevice, state, params); 4971c5258433dd353769ccfa2e5e769a7379378a3a0bJean-Michel Trivi } else if (action.equals(AudioManager.ACTION_USB_AUDIO_DEVICE_PLUG)) { 49725f5163548424ed3a4d7ea259848f82fb74aaf75dGlenn Kasten // FIXME Does not yet handle the case where the setting is changed 49735f5163548424ed3a4d7ea259848f82fb74aaf75dGlenn Kasten // after device connection. Ideally we should handle the settings change 49745f5163548424ed3a4d7ea259848f82fb74aaf75dGlenn Kasten // in SettingsObserver. Here we should log that a USB device is connected 49755f5163548424ed3a4d7ea259848f82fb74aaf75dGlenn Kasten // and disconnected with its address (card , device) and force the 49765f5163548424ed3a4d7ea259848f82fb74aaf75dGlenn Kasten // connection or disconnection when the setting changes. 497734cc4db180c20569e62db5860c0b206be65b5117Glenn Kasten int isDisabled = Settings.Secure.getInt(mContentResolver, 497834cc4db180c20569e62db5860c0b206be65b5117Glenn Kasten Settings.Secure.USB_AUDIO_AUTOMATIC_ROUTING_DISABLED, 0); 49795f5163548424ed3a4d7ea259848f82fb74aaf75dGlenn Kasten if (isDisabled != 0) { 49805f5163548424ed3a4d7ea259848f82fb74aaf75dGlenn Kasten return; 49815f5163548424ed3a4d7ea259848f82fb74aaf75dGlenn Kasten } 49825f5163548424ed3a4d7ea259848f82fb74aaf75dGlenn Kasten 498359f482764e346a5c5ac118ee1f7b24da645c2559Eric Laurent state = intent.getIntExtra("state", 0); 4984c837a451946b64d70ed7c642fbde03c182c28b6fPaul McLean 498559f482764e346a5c5ac118ee1f7b24da645c2559Eric Laurent int alsaCard = intent.getIntExtra("card", -1); 498659f482764e346a5c5ac118ee1f7b24da645c2559Eric Laurent int alsaDevice = intent.getIntExtra("device", -1); 4987c837a451946b64d70ed7c642fbde03c182c28b6fPaul McLean boolean hasPlayback = intent.getBooleanExtra("hasPlayback", false); 4988c837a451946b64d70ed7c642fbde03c182c28b6fPaul McLean boolean hasCapture = intent.getBooleanExtra("hasCapture", false); 4989c837a451946b64d70ed7c642fbde03c182c28b6fPaul McLean boolean hasMIDI = intent.getBooleanExtra("hasMIDI", false); 4990c837a451946b64d70ed7c642fbde03c182c28b6fPaul McLean 49919841818b9a0280abf59343c9e00a2976dbc084faMike Lockwood String params = (alsaCard == -1 && alsaDevice == -1 ? "" 49929841818b9a0280abf59343c9e00a2976dbc084faMike Lockwood : "card=" + alsaCard + ";device=" + alsaDevice); 4993c837a451946b64d70ed7c642fbde03c182c28b6fPaul McLean 4994c837a451946b64d70ed7c642fbde03c182c28b6fPaul McLean // Playback Device 4995df3614693dd4fe52a116dcd28bd74eae80818a4fPaul McLean if (hasPlayback) { 4996ae4506e9b5fc3e0c6d9862fbc05b9af7d6742a6eEric Laurent outDevice = AudioSystem.DEVICE_OUT_USB_DEVICE; 4997ae4506e9b5fc3e0c6d9862fbc05b9af7d6742a6eEric Laurent setWiredDeviceConnectionState(outDevice, state, params); 4998df3614693dd4fe52a116dcd28bd74eae80818a4fPaul McLean } 4999c837a451946b64d70ed7c642fbde03c182c28b6fPaul McLean 5000c837a451946b64d70ed7c642fbde03c182c28b6fPaul McLean // Capture Device 5001df3614693dd4fe52a116dcd28bd74eae80818a4fPaul McLean if (hasCapture) { 5002ae4506e9b5fc3e0c6d9862fbc05b9af7d6742a6eEric Laurent inDevice = AudioSystem.DEVICE_IN_USB_DEVICE; 5003ae4506e9b5fc3e0c6d9862fbc05b9af7d6742a6eEric Laurent setWiredDeviceConnectionState(inDevice, state, params); 5004df3614693dd4fe52a116dcd28bd74eae80818a4fPaul McLean } 5005df3614693dd4fe52a116dcd28bd74eae80818a4fPaul McLean } else if (action.equals(BluetoothHeadset.ACTION_AUDIO_STATE_CHANGED)) { 500662ef767b15a712bab31cc0d5508a330906f535c2Eric Laurent boolean broadcast = false; 500759f482764e346a5c5ac118ee1f7b24da645c2559Eric Laurent int scoAudioState = AudioManager.SCO_AUDIO_STATE_ERROR; 50083def1eec2baed0b8845ec32c871e249dc533a9d9Eric Laurent synchronized (mScoClients) { 500962ef767b15a712bab31cc0d5508a330906f535c2Eric Laurent int btState = intent.getIntExtra(BluetoothProfile.EXTRA_STATE, -1); 5010dc03c61fe3cd8d0805480e48a974986439977a60Eric Laurent // broadcast intent if the connection was initated by AudioService 5011dc03c61fe3cd8d0805480e48a974986439977a60Eric Laurent if (!mScoClients.isEmpty() && 5012dc03c61fe3cd8d0805480e48a974986439977a60Eric Laurent (mScoAudioState == SCO_STATE_ACTIVE_INTERNAL || 5013dc03c61fe3cd8d0805480e48a974986439977a60Eric Laurent mScoAudioState == SCO_STATE_ACTIVATE_REQ || 5014dc03c61fe3cd8d0805480e48a974986439977a60Eric Laurent mScoAudioState == SCO_STATE_DEACTIVATE_REQ)) { 501562ef767b15a712bab31cc0d5508a330906f535c2Eric Laurent broadcast = true; 501662ef767b15a712bab31cc0d5508a330906f535c2Eric Laurent } 501762ef767b15a712bab31cc0d5508a330906f535c2Eric Laurent switch (btState) { 501862ef767b15a712bab31cc0d5508a330906f535c2Eric Laurent case BluetoothHeadset.STATE_AUDIO_CONNECTED: 501959f482764e346a5c5ac118ee1f7b24da645c2559Eric Laurent scoAudioState = AudioManager.SCO_AUDIO_STATE_CONNECTED; 5020dc03c61fe3cd8d0805480e48a974986439977a60Eric Laurent if (mScoAudioState != SCO_STATE_ACTIVE_INTERNAL && 5021dc03c61fe3cd8d0805480e48a974986439977a60Eric Laurent mScoAudioState != SCO_STATE_DEACTIVATE_REQ && 5022dc03c61fe3cd8d0805480e48a974986439977a60Eric Laurent mScoAudioState != SCO_STATE_DEACTIVATE_EXT_REQ) { 502362ef767b15a712bab31cc0d5508a330906f535c2Eric Laurent mScoAudioState = SCO_STATE_ACTIVE_EXTERNAL; 50243def1eec2baed0b8845ec32c871e249dc533a9d9Eric Laurent } 502562ef767b15a712bab31cc0d5508a330906f535c2Eric Laurent break; 502662ef767b15a712bab31cc0d5508a330906f535c2Eric Laurent case BluetoothHeadset.STATE_AUDIO_DISCONNECTED: 502759f482764e346a5c5ac118ee1f7b24da645c2559Eric Laurent scoAudioState = AudioManager.SCO_AUDIO_STATE_DISCONNECTED; 502862ef767b15a712bab31cc0d5508a330906f535c2Eric Laurent mScoAudioState = SCO_STATE_INACTIVE; 5029d7454be47f4111c0478a502353e11dea401378bdEric Laurent clearAllScoClients(0, false); 503062ef767b15a712bab31cc0d5508a330906f535c2Eric Laurent break; 503162ef767b15a712bab31cc0d5508a330906f535c2Eric Laurent case BluetoothHeadset.STATE_AUDIO_CONNECTING: 5032dc03c61fe3cd8d0805480e48a974986439977a60Eric Laurent if (mScoAudioState != SCO_STATE_ACTIVE_INTERNAL && 5033dc03c61fe3cd8d0805480e48a974986439977a60Eric Laurent mScoAudioState != SCO_STATE_DEACTIVATE_REQ && 5034dc03c61fe3cd8d0805480e48a974986439977a60Eric Laurent mScoAudioState != SCO_STATE_DEACTIVATE_EXT_REQ) { 503562ef767b15a712bab31cc0d5508a330906f535c2Eric Laurent mScoAudioState = SCO_STATE_ACTIVE_EXTERNAL; 50363def1eec2baed0b8845ec32c871e249dc533a9d9Eric Laurent } 503762ef767b15a712bab31cc0d5508a330906f535c2Eric Laurent default: 503862ef767b15a712bab31cc0d5508a330906f535c2Eric Laurent // do not broadcast CONNECTING or invalid state 503962ef767b15a712bab31cc0d5508a330906f535c2Eric Laurent broadcast = false; 504062ef767b15a712bab31cc0d5508a330906f535c2Eric Laurent break; 50413def1eec2baed0b8845ec32c871e249dc533a9d9Eric Laurent } 50423def1eec2baed0b8845ec32c871e249dc533a9d9Eric Laurent } 504362ef767b15a712bab31cc0d5508a330906f535c2Eric Laurent if (broadcast) { 504459f482764e346a5c5ac118ee1f7b24da645c2559Eric Laurent broadcastScoConnectionState(scoAudioState); 5045dc03c61fe3cd8d0805480e48a974986439977a60Eric Laurent //FIXME: this is to maintain compatibility with deprecated intent 5046dc03c61fe3cd8d0805480e48a974986439977a60Eric Laurent // AudioManager.ACTION_SCO_AUDIO_STATE_CHANGED. Remove when appropriate. 504762ef767b15a712bab31cc0d5508a330906f535c2Eric Laurent Intent newIntent = new Intent(AudioManager.ACTION_SCO_AUDIO_STATE_CHANGED); 504859f482764e346a5c5ac118ee1f7b24da645c2559Eric Laurent newIntent.putExtra(AudioManager.EXTRA_SCO_AUDIO_STATE, scoAudioState); 50495ac72a29593ab9a20337a2225df52bdf4754be02Dianne Hackborn sendStickyBroadcastToAll(newIntent); 505062ef767b15a712bab31cc0d5508a330906f535c2Eric Laurent } 5051950e8cb40a6d826af4cc2eef9d3908c1b70486e6Eric Laurent } else if (action.equals(Intent.ACTION_SCREEN_ON)) { 5052318f0fe43bdc4b2f6764edd91d6b78d9875ffdebJon Eklund if (mMonitorRotation) { 5053318f0fe43bdc4b2f6764edd91d6b78d9875ffdebJon Eklund mOrientationListener.onOrientationChanged(0); //argument is ignored anyway 5054318f0fe43bdc4b2f6764edd91d6b78d9875ffdebJon Eklund mOrientationListener.enable(); 5055318f0fe43bdc4b2f6764edd91d6b78d9875ffdebJon Eklund } 5056950e8cb40a6d826af4cc2eef9d3908c1b70486e6Eric Laurent AudioSystem.setParameters("screen_state=on"); 5057950e8cb40a6d826af4cc2eef9d3908c1b70486e6Eric Laurent } else if (action.equals(Intent.ACTION_SCREEN_OFF)) { 5058318f0fe43bdc4b2f6764edd91d6b78d9875ffdebJon Eklund if (mMonitorRotation) { 5059318f0fe43bdc4b2f6764edd91d6b78d9875ffdebJon Eklund //reduce wakeups (save current) by only listening when display is on 5060318f0fe43bdc4b2f6764edd91d6b78d9875ffdebJon Eklund mOrientationListener.disable(); 5061318f0fe43bdc4b2f6764edd91d6b78d9875ffdebJon Eklund } 5062950e8cb40a6d826af4cc2eef9d3908c1b70486e6Eric Laurent AudioSystem.setParameters("screen_state=off"); 5063961cae92540763226648813d111c5b5c3b0f1597Dianne Hackborn } else if (action.equals(Intent.ACTION_CONFIGURATION_CHANGED)) { 5064f26f01784e1c733c53cad3ed31918e73448ce369Jean-Michel Trivi handleConfigurationChanged(context); 5065bc0fab1fc2db832ef86d8a33466ec4d68b103ca0Eric Laurent } else if (action.equals(Intent.ACTION_USER_SWITCHED)) { 5066f4a8eb22112c534f436357b50f231778c5c15c25Jean-Michel Trivi // attempt to stop music playback for background user 50675bfaeaef3fc348d66f48b86be08655e91dff910aEric Laurent sendMsg(mAudioHandler, 50685bfaeaef3fc348d66f48b86be08655e91dff910aEric Laurent MSG_BROADCAST_AUDIO_BECOMING_NOISY, 50695bfaeaef3fc348d66f48b86be08655e91dff910aEric Laurent SENDMSG_REPLACE, 50705bfaeaef3fc348d66f48b86be08655e91dff910aEric Laurent 0, 50715bfaeaef3fc348d66f48b86be08655e91dff910aEric Laurent 0, 50725bfaeaef3fc348d66f48b86be08655e91dff910aEric Laurent null, 50735bfaeaef3fc348d66f48b86be08655e91dff910aEric Laurent 0); 5074f4a8eb22112c534f436357b50f231778c5c15c25Jean-Michel Trivi // the current audio focus owner is no longer valid 5075fa9a69805b001034aa04c3b33989a7ac21522371Jean-Michel Trivi mMediaFocusControl.discardAudioFocusOwner(); 5076f4a8eb22112c534f436357b50f231778c5c15c25Jean-Michel Trivi 50775bfaeaef3fc348d66f48b86be08655e91dff910aEric Laurent // load volume settings for new user 5078bc0fab1fc2db832ef86d8a33466ec4d68b103ca0Eric Laurent readAudioSettings(true /*userSwitch*/); 5079bc0fab1fc2db832ef86d8a33466ec4d68b103ca0Eric Laurent // preserve STREAM_MUSIC volume from one user to the next. 5080bc0fab1fc2db832ef86d8a33466ec4d68b103ca0Eric Laurent sendMsg(mAudioHandler, 5081bc0fab1fc2db832ef86d8a33466ec4d68b103ca0Eric Laurent MSG_SET_ALL_VOLUMES, 5082bc0fab1fc2db832ef86d8a33466ec4d68b103ca0Eric Laurent SENDMSG_QUEUE, 5083bc0fab1fc2db832ef86d8a33466ec4d68b103ca0Eric Laurent 0, 5084bc0fab1fc2db832ef86d8a33466ec4d68b103ca0Eric Laurent 0, 5085bc0fab1fc2db832ef86d8a33466ec4d68b103ca0Eric Laurent mStreamStates[AudioSystem.STREAM_MUSIC], 0); 5086a553c25b33c99b345cf1c8688f8df0ed8df14e5aEric Laurent } 5087a553c25b33c99b345cf1c8688f8df0ed8df14e5aEric Laurent } 5088c837a451946b64d70ed7c642fbde03c182c28b6fPaul McLean } // end class AudioServiceBroadcastReceiver 5089d5176cfe6eae954e9cef1e2ec17859a5089e1330Jean-Michel Trivi 5090d5176cfe6eae954e9cef1e2ec17859a5089e1330Jean-Michel Trivi //========================================================================================== 5091fa9a69805b001034aa04c3b33989a7ac21522371Jean-Michel Trivi // RemoteControlDisplay / RemoteControlClient / Remote info 5092d5176cfe6eae954e9cef1e2ec17859a5089e1330Jean-Michel Trivi //========================================================================================== 5093f108cdd9ee5efe354d87edd02a07b323298c116cJean-Michel Trivi public boolean registerRemoteController(IRemoteControlDisplay rcd, int w, int h, 5094f108cdd9ee5efe354d87edd02a07b323298c116cJean-Michel Trivi ComponentName listenerComp) { 5095f108cdd9ee5efe354d87edd02a07b323298c116cJean-Michel Trivi return mMediaFocusControl.registerRemoteController(rcd, w, h, listenerComp); 5096f108cdd9ee5efe354d87edd02a07b323298c116cJean-Michel Trivi } 5097f108cdd9ee5efe354d87edd02a07b323298c116cJean-Michel Trivi 50987ddd226e7c6e759feaf2747a90be1cc06acf37a3Jean-Michel Trivi public boolean registerRemoteControlDisplay(IRemoteControlDisplay rcd, int w, int h) { 5099f108cdd9ee5efe354d87edd02a07b323298c116cJean-Michel Trivi return mMediaFocusControl.registerRemoteControlDisplay(rcd, w, h); 5100e5e1e870fdb35f5291790e6d178bde7126f6fe35Jean-Michel Trivi } 5101e5e1e870fdb35f5291790e6d178bde7126f6fe35Jean-Michel Trivi 5102fa9a69805b001034aa04c3b33989a7ac21522371Jean-Michel Trivi public void unregisterRemoteControlDisplay(IRemoteControlDisplay rcd) { 5103fa9a69805b001034aa04c3b33989a7ac21522371Jean-Michel Trivi mMediaFocusControl.unregisterRemoteControlDisplay(rcd); 5104d5176cfe6eae954e9cef1e2ec17859a5089e1330Jean-Michel Trivi } 5105d5176cfe6eae954e9cef1e2ec17859a5089e1330Jean-Michel Trivi 5106fa9a69805b001034aa04c3b33989a7ac21522371Jean-Michel Trivi public void remoteControlDisplayUsesBitmapSize(IRemoteControlDisplay rcd, int w, int h) { 5107fa9a69805b001034aa04c3b33989a7ac21522371Jean-Michel Trivi mMediaFocusControl.remoteControlDisplayUsesBitmapSize(rcd, w, h); 5108d5176cfe6eae954e9cef1e2ec17859a5089e1330Jean-Michel Trivi } 5109d5176cfe6eae954e9cef1e2ec17859a5089e1330Jean-Michel Trivi 5110fa9a69805b001034aa04c3b33989a7ac21522371Jean-Michel Trivi public void remoteControlDisplayWantsPlaybackPositionSync(IRemoteControlDisplay rcd, 5111fa9a69805b001034aa04c3b33989a7ac21522371Jean-Michel Trivi boolean wantsSync) { 5112fa9a69805b001034aa04c3b33989a7ac21522371Jean-Michel Trivi mMediaFocusControl.remoteControlDisplayWantsPlaybackPositionSync(rcd, wantsSync); 5113d5176cfe6eae954e9cef1e2ec17859a5089e1330Jean-Michel Trivi } 5114d5176cfe6eae954e9cef1e2ec17859a5089e1330Jean-Michel Trivi 51153346a802087f621c6441bc512dfcc17b07143fc6John Spurlock @Override 5116fa9a69805b001034aa04c3b33989a7ac21522371Jean-Michel Trivi public void setRemoteStreamVolume(int index) { 51173346a802087f621c6441bc512dfcc17b07143fc6John Spurlock enforceSelfOrSystemUI("set the remote stream volume"); 5118fa9a69805b001034aa04c3b33989a7ac21522371Jean-Michel Trivi mMediaFocusControl.setRemoteStreamVolume(index); 5119d327f21626217aa3c9c0cdb7a84a742c531e59a3Jean-Michel Trivi } 5120d327f21626217aa3c9c0cdb7a84a742c531e59a3Jean-Michel Trivi 5121fa9a69805b001034aa04c3b33989a7ac21522371Jean-Michel Trivi //========================================================================================== 5122fa9a69805b001034aa04c3b33989a7ac21522371Jean-Michel Trivi // Audio Focus 5123fa9a69805b001034aa04c3b33989a7ac21522371Jean-Michel Trivi //========================================================================================== 5124fd6ad747e6c268753d0edf7a5a59b6815b190854Jean-Michel Trivi public int requestAudioFocus(AudioAttributes aa, int durationHint, IBinder cb, 5125958876fe55ea0fdeb73c72240a2f2bab32833443Jean-Michel Trivi IAudioFocusDispatcher fd, String clientId, String callingPackageName, int flags, 51260212be5150fb9fb3c340f3c7e51f6126372cc6f9Jean-Michel Trivi IAudioPolicyCallback pcb) { 5127958876fe55ea0fdeb73c72240a2f2bab32833443Jean-Michel Trivi // permission checks 5128958876fe55ea0fdeb73c72240a2f2bab32833443Jean-Michel Trivi if ((flags & AudioManager.AUDIOFOCUS_FLAG_LOCK) == AudioManager.AUDIOFOCUS_FLAG_LOCK) { 5129958876fe55ea0fdeb73c72240a2f2bab32833443Jean-Michel Trivi if (mMediaFocusControl.IN_VOICE_COMM_FOCUS_ID.equals(clientId)) { 5130958876fe55ea0fdeb73c72240a2f2bab32833443Jean-Michel Trivi if (PackageManager.PERMISSION_GRANTED != mContext.checkCallingOrSelfPermission( 5131958876fe55ea0fdeb73c72240a2f2bab32833443Jean-Michel Trivi android.Manifest.permission.MODIFY_PHONE_STATE)) { 5132958876fe55ea0fdeb73c72240a2f2bab32833443Jean-Michel Trivi Log.e(TAG, "Invalid permission to (un)lock audio focus", new Exception()); 5133958876fe55ea0fdeb73c72240a2f2bab32833443Jean-Michel Trivi return AudioManager.AUDIOFOCUS_REQUEST_FAILED; 5134958876fe55ea0fdeb73c72240a2f2bab32833443Jean-Michel Trivi } 5135958876fe55ea0fdeb73c72240a2f2bab32833443Jean-Michel Trivi } else { 5136958876fe55ea0fdeb73c72240a2f2bab32833443Jean-Michel Trivi // only a registered audio policy can be used to lock focus 5137958876fe55ea0fdeb73c72240a2f2bab32833443Jean-Michel Trivi synchronized (mAudioPolicies) { 51380212be5150fb9fb3c340f3c7e51f6126372cc6f9Jean-Michel Trivi if (!mAudioPolicies.containsKey(pcb.asBinder())) { 51390212be5150fb9fb3c340f3c7e51f6126372cc6f9Jean-Michel Trivi Log.e(TAG, "Invalid unregistered AudioPolicy to (un)lock audio focus"); 5140958876fe55ea0fdeb73c72240a2f2bab32833443Jean-Michel Trivi return AudioManager.AUDIOFOCUS_REQUEST_FAILED; 5141958876fe55ea0fdeb73c72240a2f2bab32833443Jean-Michel Trivi } 5142958876fe55ea0fdeb73c72240a2f2bab32833443Jean-Michel Trivi } 5143958876fe55ea0fdeb73c72240a2f2bab32833443Jean-Michel Trivi } 5144958876fe55ea0fdeb73c72240a2f2bab32833443Jean-Michel Trivi } 5145958876fe55ea0fdeb73c72240a2f2bab32833443Jean-Michel Trivi 5146fd6ad747e6c268753d0edf7a5a59b6815b190854Jean-Michel Trivi return mMediaFocusControl.requestAudioFocus(aa, durationHint, cb, fd, 5147fd6ad747e6c268753d0edf7a5a59b6815b190854Jean-Michel Trivi clientId, callingPackageName, flags); 51484294b83927f51e5c115ebaafd2e185ba5de91436Jean-Michel Trivi } 51494294b83927f51e5c115ebaafd2e185ba5de91436Jean-Michel Trivi 5150958876fe55ea0fdeb73c72240a2f2bab32833443Jean-Michel Trivi public int abandonAudioFocus(IAudioFocusDispatcher fd, String clientId, AudioAttributes aa) { 5151958876fe55ea0fdeb73c72240a2f2bab32833443Jean-Michel Trivi return mMediaFocusControl.abandonAudioFocus(fd, clientId, aa); 5152c68022258ebd3dd97a5079ba99f4f3cd12b223b0Jean-Michel Trivi } 5153c68022258ebd3dd97a5079ba99f4f3cd12b223b0Jean-Michel Trivi 5154fa9a69805b001034aa04c3b33989a7ac21522371Jean-Michel Trivi public void unregisterAudioFocusClient(String clientId) { 5155fa9a69805b001034aa04c3b33989a7ac21522371Jean-Michel Trivi mMediaFocusControl.unregisterAudioFocusClient(clientId); 51563114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi } 51573114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi 51582380566debfc57eb1cc07db1306ccee23b84ddd4Jean-Michel Trivi public int getCurrentAudioFocus() { 51592380566debfc57eb1cc07db1306ccee23b84ddd4Jean-Michel Trivi return mMediaFocusControl.getCurrentAudioFocus(); 51602380566debfc57eb1cc07db1306ccee23b84ddd4Jean-Michel Trivi } 51612380566debfc57eb1cc07db1306ccee23b84ddd4Jean-Michel Trivi 5162f26f01784e1c733c53cad3ed31918e73448ce369Jean-Michel Trivi //========================================================================================== 5163f26f01784e1c733c53cad3ed31918e73448ce369Jean-Michel Trivi // Device orientation 5164f26f01784e1c733c53cad3ed31918e73448ce369Jean-Michel Trivi //========================================================================================== 5165f26f01784e1c733c53cad3ed31918e73448ce369Jean-Michel Trivi /** 5166bb6f8711a7f804d39c45218db2d6339940cc5d35Jean-Michel Trivi * Handles device configuration changes that may map to a change in the orientation 5167bb6f8711a7f804d39c45218db2d6339940cc5d35Jean-Michel Trivi * or orientation. 5168bb6f8711a7f804d39c45218db2d6339940cc5d35Jean-Michel Trivi * Monitoring orientation and rotation is optional, and is defined by the definition and value 5169bb6f8711a7f804d39c45218db2d6339940cc5d35Jean-Michel Trivi * of the "ro.audio.monitorOrientation" and "ro.audio.monitorRotation" system properties. 5170f26f01784e1c733c53cad3ed31918e73448ce369Jean-Michel Trivi */ 5171f26f01784e1c733c53cad3ed31918e73448ce369Jean-Michel Trivi private void handleConfigurationChanged(Context context) { 5172f26f01784e1c733c53cad3ed31918e73448ce369Jean-Michel Trivi try { 5173f26f01784e1c733c53cad3ed31918e73448ce369Jean-Michel Trivi // reading new orientation "safely" (i.e. under try catch) in case anything 5174f26f01784e1c733c53cad3ed31918e73448ce369Jean-Michel Trivi // goes wrong when obtaining resources and configuration 5175d640bd325c3be9a350058c835b880a7e0b40dc60Eric Laurent Configuration config = context.getResources().getConfiguration(); 5176bb6f8711a7f804d39c45218db2d6339940cc5d35Jean-Michel Trivi // TODO merge rotation and orientation 5177d640bd325c3be9a350058c835b880a7e0b40dc60Eric Laurent if (mMonitorOrientation) { 5178d640bd325c3be9a350058c835b880a7e0b40dc60Eric Laurent int newOrientation = config.orientation; 5179d640bd325c3be9a350058c835b880a7e0b40dc60Eric Laurent if (newOrientation != mDeviceOrientation) { 5180d640bd325c3be9a350058c835b880a7e0b40dc60Eric Laurent mDeviceOrientation = newOrientation; 5181d640bd325c3be9a350058c835b880a7e0b40dc60Eric Laurent setOrientationForAudioSystem(); 5182d640bd325c3be9a350058c835b880a7e0b40dc60Eric Laurent } 5183f26f01784e1c733c53cad3ed31918e73448ce369Jean-Michel Trivi } 5184d640bd325c3be9a350058c835b880a7e0b40dc60Eric Laurent sendMsg(mAudioHandler, 5185d640bd325c3be9a350058c835b880a7e0b40dc60Eric Laurent MSG_CONFIGURE_SAFE_MEDIA_VOLUME, 5186d640bd325c3be9a350058c835b880a7e0b40dc60Eric Laurent SENDMSG_REPLACE, 5187d640bd325c3be9a350058c835b880a7e0b40dc60Eric Laurent 0, 5188d640bd325c3be9a350058c835b880a7e0b40dc60Eric Laurent 0, 5189d640bd325c3be9a350058c835b880a7e0b40dc60Eric Laurent null, 5190d640bd325c3be9a350058c835b880a7e0b40dc60Eric Laurent 0); 5191dd45d01128423a82652a3c9d77fa393631d95229Eric Laurent 5192dd45d01128423a82652a3c9d77fa393631d95229Eric Laurent boolean cameraSoundForced = mContext.getResources().getBoolean( 5193dd45d01128423a82652a3c9d77fa393631d95229Eric Laurent com.android.internal.R.bool.config_camera_sound_forced); 5194dd45d01128423a82652a3c9d77fa393631d95229Eric Laurent synchronized (mSettingsLock) { 51958fa4d6f585f40ff5cf5f9bed316d92c64a306f21Eric Laurent boolean cameraSoundForcedChanged = false; 5196dd45d01128423a82652a3c9d77fa393631d95229Eric Laurent synchronized (mCameraSoundForced) { 5197dd45d01128423a82652a3c9d77fa393631d95229Eric Laurent if (cameraSoundForced != mCameraSoundForced) { 5198dd45d01128423a82652a3c9d77fa393631d95229Eric Laurent mCameraSoundForced = cameraSoundForced; 51998fa4d6f585f40ff5cf5f9bed316d92c64a306f21Eric Laurent cameraSoundForcedChanged = true; 52008fa4d6f585f40ff5cf5f9bed316d92c64a306f21Eric Laurent } 52018fa4d6f585f40ff5cf5f9bed316d92c64a306f21Eric Laurent } 52028fa4d6f585f40ff5cf5f9bed316d92c64a306f21Eric Laurent if (cameraSoundForcedChanged) { 52038fa4d6f585f40ff5cf5f9bed316d92c64a306f21Eric Laurent if (!isPlatformTelevision()) { 52048fa4d6f585f40ff5cf5f9bed316d92c64a306f21Eric Laurent VolumeStreamState s = mStreamStates[AudioSystem.STREAM_SYSTEM_ENFORCED]; 52058fa4d6f585f40ff5cf5f9bed316d92c64a306f21Eric Laurent if (cameraSoundForced) { 52068fa4d6f585f40ff5cf5f9bed316d92c64a306f21Eric Laurent s.setAllIndexesToMax(); 52078fa4d6f585f40ff5cf5f9bed316d92c64a306f21Eric Laurent mRingerModeAffectedStreams &= 52088fa4d6f585f40ff5cf5f9bed316d92c64a306f21Eric Laurent ~(1 << AudioSystem.STREAM_SYSTEM_ENFORCED); 52098fa4d6f585f40ff5cf5f9bed316d92c64a306f21Eric Laurent } else { 52108fa4d6f585f40ff5cf5f9bed316d92c64a306f21Eric Laurent s.setAllIndexes(mStreamStates[AudioSystem.STREAM_SYSTEM]); 52118fa4d6f585f40ff5cf5f9bed316d92c64a306f21Eric Laurent mRingerModeAffectedStreams |= 52128fa4d6f585f40ff5cf5f9bed316d92c64a306f21Eric Laurent (1 << AudioSystem.STREAM_SYSTEM_ENFORCED); 5213dd45d01128423a82652a3c9d77fa393631d95229Eric Laurent } 52148fa4d6f585f40ff5cf5f9bed316d92c64a306f21Eric Laurent // take new state into account for streams muted by ringer mode 5215661f2cf45860d2e10924e6b69966a9afe255f28bJohn Spurlock setRingerModeInt(getRingerModeInternal(), false); 5216dd45d01128423a82652a3c9d77fa393631d95229Eric Laurent } 52178fa4d6f585f40ff5cf5f9bed316d92c64a306f21Eric Laurent 52188fa4d6f585f40ff5cf5f9bed316d92c64a306f21Eric Laurent sendMsg(mAudioHandler, 52198fa4d6f585f40ff5cf5f9bed316d92c64a306f21Eric Laurent MSG_SET_FORCE_USE, 52208fa4d6f585f40ff5cf5f9bed316d92c64a306f21Eric Laurent SENDMSG_QUEUE, 52218fa4d6f585f40ff5cf5f9bed316d92c64a306f21Eric Laurent AudioSystem.FOR_SYSTEM, 52228fa4d6f585f40ff5cf5f9bed316d92c64a306f21Eric Laurent cameraSoundForced ? 52238fa4d6f585f40ff5cf5f9bed316d92c64a306f21Eric Laurent AudioSystem.FORCE_SYSTEM_ENFORCED : AudioSystem.FORCE_NONE, 52248fa4d6f585f40ff5cf5f9bed316d92c64a306f21Eric Laurent null, 52258fa4d6f585f40ff5cf5f9bed316d92c64a306f21Eric Laurent 0); 52268fa4d6f585f40ff5cf5f9bed316d92c64a306f21Eric Laurent 52278fa4d6f585f40ff5cf5f9bed316d92c64a306f21Eric Laurent sendMsg(mAudioHandler, 52288fa4d6f585f40ff5cf5f9bed316d92c64a306f21Eric Laurent MSG_SET_ALL_VOLUMES, 52298fa4d6f585f40ff5cf5f9bed316d92c64a306f21Eric Laurent SENDMSG_QUEUE, 52308fa4d6f585f40ff5cf5f9bed316d92c64a306f21Eric Laurent 0, 52318fa4d6f585f40ff5cf5f9bed316d92c64a306f21Eric Laurent 0, 52328fa4d6f585f40ff5cf5f9bed316d92c64a306f21Eric Laurent mStreamStates[AudioSystem.STREAM_SYSTEM_ENFORCED], 0); 5233dd45d01128423a82652a3c9d77fa393631d95229Eric Laurent } 5234dd45d01128423a82652a3c9d77fa393631d95229Eric Laurent } 52353346a802087f621c6441bc512dfcc17b07143fc6John Spurlock mVolumeController.setLayoutDirection(config.getLayoutDirection()); 5236f26f01784e1c733c53cad3ed31918e73448ce369Jean-Michel Trivi } catch (Exception e) { 5237bb6f8711a7f804d39c45218db2d6339940cc5d35Jean-Michel Trivi Log.e(TAG, "Error handling configuration change: ", e); 5238f26f01784e1c733c53cad3ed31918e73448ce369Jean-Michel Trivi } 5239f26f01784e1c733c53cad3ed31918e73448ce369Jean-Michel Trivi } 5240f26f01784e1c733c53cad3ed31918e73448ce369Jean-Michel Trivi 5241f26f01784e1c733c53cad3ed31918e73448ce369Jean-Michel Trivi private void setOrientationForAudioSystem() { 5242f26f01784e1c733c53cad3ed31918e73448ce369Jean-Michel Trivi switch (mDeviceOrientation) { 5243f26f01784e1c733c53cad3ed31918e73448ce369Jean-Michel Trivi case Configuration.ORIENTATION_LANDSCAPE: 5244f26f01784e1c733c53cad3ed31918e73448ce369Jean-Michel Trivi //Log.i(TAG, "orientation is landscape"); 5245f26f01784e1c733c53cad3ed31918e73448ce369Jean-Michel Trivi AudioSystem.setParameters("orientation=landscape"); 5246f26f01784e1c733c53cad3ed31918e73448ce369Jean-Michel Trivi break; 5247f26f01784e1c733c53cad3ed31918e73448ce369Jean-Michel Trivi case Configuration.ORIENTATION_PORTRAIT: 5248f26f01784e1c733c53cad3ed31918e73448ce369Jean-Michel Trivi //Log.i(TAG, "orientation is portrait"); 5249f26f01784e1c733c53cad3ed31918e73448ce369Jean-Michel Trivi AudioSystem.setParameters("orientation=portrait"); 5250f26f01784e1c733c53cad3ed31918e73448ce369Jean-Michel Trivi break; 5251f26f01784e1c733c53cad3ed31918e73448ce369Jean-Michel Trivi case Configuration.ORIENTATION_SQUARE: 5252f26f01784e1c733c53cad3ed31918e73448ce369Jean-Michel Trivi //Log.i(TAG, "orientation is square"); 5253f26f01784e1c733c53cad3ed31918e73448ce369Jean-Michel Trivi AudioSystem.setParameters("orientation=square"); 5254f26f01784e1c733c53cad3ed31918e73448ce369Jean-Michel Trivi break; 5255f26f01784e1c733c53cad3ed31918e73448ce369Jean-Michel Trivi case Configuration.ORIENTATION_UNDEFINED: 5256f26f01784e1c733c53cad3ed31918e73448ce369Jean-Michel Trivi //Log.i(TAG, "orientation is undefined"); 5257f26f01784e1c733c53cad3ed31918e73448ce369Jean-Michel Trivi AudioSystem.setParameters("orientation=undefined"); 5258f26f01784e1c733c53cad3ed31918e73448ce369Jean-Michel Trivi break; 5259f26f01784e1c733c53cad3ed31918e73448ce369Jean-Michel Trivi default: 5260f26f01784e1c733c53cad3ed31918e73448ce369Jean-Michel Trivi Log.e(TAG, "Unknown orientation"); 5261f26f01784e1c733c53cad3ed31918e73448ce369Jean-Michel Trivi } 5262f26f01784e1c733c53cad3ed31918e73448ce369Jean-Michel Trivi } 5263f26f01784e1c733c53cad3ed31918e73448ce369Jean-Michel Trivi 5264bb6f8711a7f804d39c45218db2d6339940cc5d35Jean-Michel Trivi private void setRotationForAudioSystem() { 5265bb6f8711a7f804d39c45218db2d6339940cc5d35Jean-Michel Trivi switch (mDeviceRotation) { 5266bb6f8711a7f804d39c45218db2d6339940cc5d35Jean-Michel Trivi case Surface.ROTATION_0: 5267bb6f8711a7f804d39c45218db2d6339940cc5d35Jean-Michel Trivi AudioSystem.setParameters("rotation=0"); 5268bb6f8711a7f804d39c45218db2d6339940cc5d35Jean-Michel Trivi break; 5269bb6f8711a7f804d39c45218db2d6339940cc5d35Jean-Michel Trivi case Surface.ROTATION_90: 5270bb6f8711a7f804d39c45218db2d6339940cc5d35Jean-Michel Trivi AudioSystem.setParameters("rotation=90"); 5271bb6f8711a7f804d39c45218db2d6339940cc5d35Jean-Michel Trivi break; 5272bb6f8711a7f804d39c45218db2d6339940cc5d35Jean-Michel Trivi case Surface.ROTATION_180: 5273bb6f8711a7f804d39c45218db2d6339940cc5d35Jean-Michel Trivi AudioSystem.setParameters("rotation=180"); 5274bb6f8711a7f804d39c45218db2d6339940cc5d35Jean-Michel Trivi break; 5275bb6f8711a7f804d39c45218db2d6339940cc5d35Jean-Michel Trivi case Surface.ROTATION_270: 5276bb6f8711a7f804d39c45218db2d6339940cc5d35Jean-Michel Trivi AudioSystem.setParameters("rotation=270"); 5277bb6f8711a7f804d39c45218db2d6339940cc5d35Jean-Michel Trivi break; 5278bb6f8711a7f804d39c45218db2d6339940cc5d35Jean-Michel Trivi default: 5279bb6f8711a7f804d39c45218db2d6339940cc5d35Jean-Michel Trivi Log.e(TAG, "Unknown device rotation"); 5280bb6f8711a7f804d39c45218db2d6339940cc5d35Jean-Michel Trivi } 5281bb6f8711a7f804d39c45218db2d6339940cc5d35Jean-Michel Trivi } 5282bb6f8711a7f804d39c45218db2d6339940cc5d35Jean-Michel Trivi 5283f26f01784e1c733c53cad3ed31918e73448ce369Jean-Michel Trivi 52847847211fb4699bf6018e29d214a918ed6657319bEric Laurent // Handles request to override default use of A2DP for media. 52857847211fb4699bf6018e29d214a918ed6657319bEric Laurent public void setBluetoothA2dpOnInt(boolean on) { 52867847211fb4699bf6018e29d214a918ed6657319bEric Laurent synchronized (mBluetoothA2dpEnabledLock) { 52877847211fb4699bf6018e29d214a918ed6657319bEric Laurent mBluetoothA2dpEnabled = on; 5288c390bed06b4a572e273ead1254da9a932e04dce3Eric Laurent mAudioHandler.removeMessages(MSG_SET_FORCE_BT_A2DP_USE); 5289c390bed06b4a572e273ead1254da9a932e04dce3Eric Laurent AudioSystem.setForceUse(AudioSystem.FOR_MEDIA, 5290c390bed06b4a572e273ead1254da9a932e04dce3Eric Laurent mBluetoothA2dpEnabled ? AudioSystem.FORCE_NONE : AudioSystem.FORCE_NO_BT_A2DP); 52917847211fb4699bf6018e29d214a918ed6657319bEric Laurent } 52927847211fb4699bf6018e29d214a918ed6657319bEric Laurent } 52937847211fb4699bf6018e29d214a918ed6657319bEric Laurent 5294d5176cfe6eae954e9cef1e2ec17859a5089e1330Jean-Michel Trivi @Override 5295098d580cc2bb6c0891c756a4e5230c6c6b0d2376Jeff Sharkey public void setRingtonePlayer(IRingtonePlayer player) { 5296098d580cc2bb6c0891c756a4e5230c6c6b0d2376Jeff Sharkey mContext.enforceCallingOrSelfPermission(REMOTE_AUDIO_PLAYBACK, null); 5297098d580cc2bb6c0891c756a4e5230c6c6b0d2376Jeff Sharkey mRingtonePlayer = player; 5298098d580cc2bb6c0891c756a4e5230c6c6b0d2376Jeff Sharkey } 5299098d580cc2bb6c0891c756a4e5230c6c6b0d2376Jeff Sharkey 5300098d580cc2bb6c0891c756a4e5230c6c6b0d2376Jeff Sharkey @Override 5301098d580cc2bb6c0891c756a4e5230c6c6b0d2376Jeff Sharkey public IRingtonePlayer getRingtonePlayer() { 5302098d580cc2bb6c0891c756a4e5230c6c6b0d2376Jeff Sharkey return mRingtonePlayer; 5303098d580cc2bb6c0891c756a4e5230c6c6b0d2376Jeff Sharkey } 5304098d580cc2bb6c0891c756a4e5230c6c6b0d2376Jeff Sharkey 5305098d580cc2bb6c0891c756a4e5230c6c6b0d2376Jeff Sharkey @Override 5306632ca417f0a33e3fa9ccece531afa2db3f0d4a30Dianne Hackborn public AudioRoutesInfo startWatchingRoutes(IAudioRoutesObserver observer) { 5307632ca417f0a33e3fa9ccece531afa2db3f0d4a30Dianne Hackborn synchronized (mCurAudioRoutes) { 5308632ca417f0a33e3fa9ccece531afa2db3f0d4a30Dianne Hackborn AudioRoutesInfo routes = new AudioRoutesInfo(mCurAudioRoutes); 5309632ca417f0a33e3fa9ccece531afa2db3f0d4a30Dianne Hackborn mRoutesObservers.register(observer); 5310632ca417f0a33e3fa9ccece531afa2db3f0d4a30Dianne Hackborn return routes; 5311632ca417f0a33e3fa9ccece531afa2db3f0d4a30Dianne Hackborn } 5312632ca417f0a33e3fa9ccece531afa2db3f0d4a30Dianne Hackborn } 5313632ca417f0a33e3fa9ccece531afa2db3f0d4a30Dianne Hackborn 5314c34dcc1e1ebf152bb400abbb8bc25f7dc0c3ba97Eric Laurent 5315c34dcc1e1ebf152bb400abbb8bc25f7dc0c3ba97Eric Laurent //========================================================================================== 5316c34dcc1e1ebf152bb400abbb8bc25f7dc0c3ba97Eric Laurent // Safe media volume management. 5317c34dcc1e1ebf152bb400abbb8bc25f7dc0c3ba97Eric Laurent // MUSIC stream volume level is limited when headphones are connected according to safety 5318c34dcc1e1ebf152bb400abbb8bc25f7dc0c3ba97Eric Laurent // regulation. When the user attempts to raise the volume above the limit, a warning is 5319c34dcc1e1ebf152bb400abbb8bc25f7dc0c3ba97Eric Laurent // displayed and the user has to acknowlegde before the volume is actually changed. 5320c34dcc1e1ebf152bb400abbb8bc25f7dc0c3ba97Eric Laurent // The volume index corresponding to the limit is stored in config_safe_media_volume_index 5321c34dcc1e1ebf152bb400abbb8bc25f7dc0c3ba97Eric Laurent // property. Platforms with a different limit must set this property accordingly in their 5322c34dcc1e1ebf152bb400abbb8bc25f7dc0c3ba97Eric Laurent // overlay. 5323c34dcc1e1ebf152bb400abbb8bc25f7dc0c3ba97Eric Laurent //========================================================================================== 5324c34dcc1e1ebf152bb400abbb8bc25f7dc0c3ba97Eric Laurent 5325d640bd325c3be9a350058c835b880a7e0b40dc60Eric Laurent // mSafeMediaVolumeState indicates whether the media volume is limited over headphones. 5326d640bd325c3be9a350058c835b880a7e0b40dc60Eric Laurent // It is SAFE_MEDIA_VOLUME_NOT_CONFIGURED at boot time until a network service is connected 5327d640bd325c3be9a350058c835b880a7e0b40dc60Eric Laurent // or the configure time is elapsed. It is then set to SAFE_MEDIA_VOLUME_ACTIVE or 5328d640bd325c3be9a350058c835b880a7e0b40dc60Eric Laurent // SAFE_MEDIA_VOLUME_DISABLED according to country option. If not SAFE_MEDIA_VOLUME_DISABLED, it 5329d640bd325c3be9a350058c835b880a7e0b40dc60Eric Laurent // can be set to SAFE_MEDIA_VOLUME_INACTIVE by calling AudioService.disableSafeMediaVolume() 5330d640bd325c3be9a350058c835b880a7e0b40dc60Eric Laurent // (when user opts out). 5331351346092acdfbfcc1d9ebf98d539d2a1196c5e8John Spurlock private static final int SAFE_MEDIA_VOLUME_NOT_CONFIGURED = 0; 5332351346092acdfbfcc1d9ebf98d539d2a1196c5e8John Spurlock private static final int SAFE_MEDIA_VOLUME_DISABLED = 1; 5333351346092acdfbfcc1d9ebf98d539d2a1196c5e8John Spurlock private static final int SAFE_MEDIA_VOLUME_INACTIVE = 2; // confirmed 5334351346092acdfbfcc1d9ebf98d539d2a1196c5e8John Spurlock private static final int SAFE_MEDIA_VOLUME_ACTIVE = 3; // unconfirmed 5335d640bd325c3be9a350058c835b880a7e0b40dc60Eric Laurent private Integer mSafeMediaVolumeState; 5336d640bd325c3be9a350058c835b880a7e0b40dc60Eric Laurent 5337d640bd325c3be9a350058c835b880a7e0b40dc60Eric Laurent private int mMcc = 0; 5338c34dcc1e1ebf152bb400abbb8bc25f7dc0c3ba97Eric Laurent // mSafeMediaVolumeIndex is the cached value of config_safe_media_volume_index property 5339d640bd325c3be9a350058c835b880a7e0b40dc60Eric Laurent private int mSafeMediaVolumeIndex; 5340c34dcc1e1ebf152bb400abbb8bc25f7dc0c3ba97Eric Laurent // mSafeMediaVolumeDevices lists the devices for which safe media volume is enforced, 5341c34dcc1e1ebf152bb400abbb8bc25f7dc0c3ba97Eric Laurent private final int mSafeMediaVolumeDevices = AudioSystem.DEVICE_OUT_WIRED_HEADSET | 5342c34dcc1e1ebf152bb400abbb8bc25f7dc0c3ba97Eric Laurent AudioSystem.DEVICE_OUT_WIRED_HEADPHONE; 5343c34dcc1e1ebf152bb400abbb8bc25f7dc0c3ba97Eric Laurent // mMusicActiveMs is the cumulative time of music activity since safe volume was disabled. 5344c34dcc1e1ebf152bb400abbb8bc25f7dc0c3ba97Eric Laurent // When this time reaches UNSAFE_VOLUME_MUSIC_ACTIVE_MS_MAX, the safe media volume is re-enabled 5345c34dcc1e1ebf152bb400abbb8bc25f7dc0c3ba97Eric Laurent // automatically. mMusicActiveMs is rounded to a multiple of MUSIC_ACTIVE_POLL_PERIOD_MS. 5346c34dcc1e1ebf152bb400abbb8bc25f7dc0c3ba97Eric Laurent private int mMusicActiveMs; 5347c34dcc1e1ebf152bb400abbb8bc25f7dc0c3ba97Eric Laurent private static final int UNSAFE_VOLUME_MUSIC_ACTIVE_MS_MAX = (20 * 3600 * 1000); // 20 hours 5348c34dcc1e1ebf152bb400abbb8bc25f7dc0c3ba97Eric Laurent private static final int MUSIC_ACTIVE_POLL_PERIOD_MS = 60000; // 1 minute polling interval 5349d640bd325c3be9a350058c835b880a7e0b40dc60Eric Laurent private static final int SAFE_VOLUME_CONFIGURE_TIMEOUT_MS = 30000; // 30s after boot completed 5350c34dcc1e1ebf152bb400abbb8bc25f7dc0c3ba97Eric Laurent 5351c34dcc1e1ebf152bb400abbb8bc25f7dc0c3ba97Eric Laurent private void setSafeMediaVolumeEnabled(boolean on) { 5352d640bd325c3be9a350058c835b880a7e0b40dc60Eric Laurent synchronized (mSafeMediaVolumeState) { 5353d640bd325c3be9a350058c835b880a7e0b40dc60Eric Laurent if ((mSafeMediaVolumeState != SAFE_MEDIA_VOLUME_NOT_CONFIGURED) && 5354d640bd325c3be9a350058c835b880a7e0b40dc60Eric Laurent (mSafeMediaVolumeState != SAFE_MEDIA_VOLUME_DISABLED)) { 5355d640bd325c3be9a350058c835b880a7e0b40dc60Eric Laurent if (on && (mSafeMediaVolumeState == SAFE_MEDIA_VOLUME_INACTIVE)) { 5356d640bd325c3be9a350058c835b880a7e0b40dc60Eric Laurent mSafeMediaVolumeState = SAFE_MEDIA_VOLUME_ACTIVE; 5357d640bd325c3be9a350058c835b880a7e0b40dc60Eric Laurent enforceSafeMediaVolume(); 5358d640bd325c3be9a350058c835b880a7e0b40dc60Eric Laurent } else if (!on && (mSafeMediaVolumeState == SAFE_MEDIA_VOLUME_ACTIVE)) { 5359d640bd325c3be9a350058c835b880a7e0b40dc60Eric Laurent mSafeMediaVolumeState = SAFE_MEDIA_VOLUME_INACTIVE; 5360aa5ee4d65f8788e2a0afcd198367450853fd72acJohn Spurlock mMusicActiveMs = 1; // nonzero = confirmed 5361aa5ee4d65f8788e2a0afcd198367450853fd72acJohn Spurlock saveMusicActiveMs(); 5362d640bd325c3be9a350058c835b880a7e0b40dc60Eric Laurent sendMsg(mAudioHandler, 5363d640bd325c3be9a350058c835b880a7e0b40dc60Eric Laurent MSG_CHECK_MUSIC_ACTIVE, 5364d640bd325c3be9a350058c835b880a7e0b40dc60Eric Laurent SENDMSG_REPLACE, 5365d640bd325c3be9a350058c835b880a7e0b40dc60Eric Laurent 0, 5366d640bd325c3be9a350058c835b880a7e0b40dc60Eric Laurent 0, 5367d640bd325c3be9a350058c835b880a7e0b40dc60Eric Laurent null, 5368d640bd325c3be9a350058c835b880a7e0b40dc60Eric Laurent MUSIC_ACTIVE_POLL_PERIOD_MS); 5369d640bd325c3be9a350058c835b880a7e0b40dc60Eric Laurent } 5370c34dcc1e1ebf152bb400abbb8bc25f7dc0c3ba97Eric Laurent } 5371c34dcc1e1ebf152bb400abbb8bc25f7dc0c3ba97Eric Laurent } 5372c34dcc1e1ebf152bb400abbb8bc25f7dc0c3ba97Eric Laurent } 5373c34dcc1e1ebf152bb400abbb8bc25f7dc0c3ba97Eric Laurent 5374c34dcc1e1ebf152bb400abbb8bc25f7dc0c3ba97Eric Laurent private void enforceSafeMediaVolume() { 5375c34dcc1e1ebf152bb400abbb8bc25f7dc0c3ba97Eric Laurent VolumeStreamState streamState = mStreamStates[AudioSystem.STREAM_MUSIC]; 5376c34dcc1e1ebf152bb400abbb8bc25f7dc0c3ba97Eric Laurent int devices = mSafeMediaVolumeDevices; 5377c34dcc1e1ebf152bb400abbb8bc25f7dc0c3ba97Eric Laurent int i = 0; 5378c34dcc1e1ebf152bb400abbb8bc25f7dc0c3ba97Eric Laurent 5379c34dcc1e1ebf152bb400abbb8bc25f7dc0c3ba97Eric Laurent while (devices != 0) { 5380c34dcc1e1ebf152bb400abbb8bc25f7dc0c3ba97Eric Laurent int device = 1 << i++; 5381c34dcc1e1ebf152bb400abbb8bc25f7dc0c3ba97Eric Laurent if ((device & devices) == 0) { 5382c34dcc1e1ebf152bb400abbb8bc25f7dc0c3ba97Eric Laurent continue; 5383c34dcc1e1ebf152bb400abbb8bc25f7dc0c3ba97Eric Laurent } 538442b041ed4f184e3af7f788eb07307f556a2a6616Eric Laurent int index = streamState.getIndex(device); 5385c34dcc1e1ebf152bb400abbb8bc25f7dc0c3ba97Eric Laurent if (index > mSafeMediaVolumeIndex) { 538642b041ed4f184e3af7f788eb07307f556a2a6616Eric Laurent streamState.setIndex(mSafeMediaVolumeIndex, device); 538742b041ed4f184e3af7f788eb07307f556a2a6616Eric Laurent sendMsg(mAudioHandler, 538842b041ed4f184e3af7f788eb07307f556a2a6616Eric Laurent MSG_SET_DEVICE_VOLUME, 538942b041ed4f184e3af7f788eb07307f556a2a6616Eric Laurent SENDMSG_QUEUE, 539042b041ed4f184e3af7f788eb07307f556a2a6616Eric Laurent device, 539142b041ed4f184e3af7f788eb07307f556a2a6616Eric Laurent 0, 539242b041ed4f184e3af7f788eb07307f556a2a6616Eric Laurent streamState, 539342b041ed4f184e3af7f788eb07307f556a2a6616Eric Laurent 0); 5394c34dcc1e1ebf152bb400abbb8bc25f7dc0c3ba97Eric Laurent } 5395c34dcc1e1ebf152bb400abbb8bc25f7dc0c3ba97Eric Laurent devices &= ~device; 5396c34dcc1e1ebf152bb400abbb8bc25f7dc0c3ba97Eric Laurent } 5397c34dcc1e1ebf152bb400abbb8bc25f7dc0c3ba97Eric Laurent } 5398c34dcc1e1ebf152bb400abbb8bc25f7dc0c3ba97Eric Laurent 5399c34dcc1e1ebf152bb400abbb8bc25f7dc0c3ba97Eric Laurent private boolean checkSafeMediaVolume(int streamType, int index, int device) { 5400d640bd325c3be9a350058c835b880a7e0b40dc60Eric Laurent synchronized (mSafeMediaVolumeState) { 5401d640bd325c3be9a350058c835b880a7e0b40dc60Eric Laurent if ((mSafeMediaVolumeState == SAFE_MEDIA_VOLUME_ACTIVE) && 5402c34dcc1e1ebf152bb400abbb8bc25f7dc0c3ba97Eric Laurent (mStreamVolumeAlias[streamType] == AudioSystem.STREAM_MUSIC) && 5403c34dcc1e1ebf152bb400abbb8bc25f7dc0c3ba97Eric Laurent ((device & mSafeMediaVolumeDevices) != 0) && 5404c34dcc1e1ebf152bb400abbb8bc25f7dc0c3ba97Eric Laurent (index > mSafeMediaVolumeIndex)) { 5405c34dcc1e1ebf152bb400abbb8bc25f7dc0c3ba97Eric Laurent return false; 5406c34dcc1e1ebf152bb400abbb8bc25f7dc0c3ba97Eric Laurent } 5407c34dcc1e1ebf152bb400abbb8bc25f7dc0c3ba97Eric Laurent return true; 5408c34dcc1e1ebf152bb400abbb8bc25f7dc0c3ba97Eric Laurent } 5409c34dcc1e1ebf152bb400abbb8bc25f7dc0c3ba97Eric Laurent } 5410c34dcc1e1ebf152bb400abbb8bc25f7dc0c3ba97Eric Laurent 54113346a802087f621c6441bc512dfcc17b07143fc6John Spurlock @Override 5412c34dcc1e1ebf152bb400abbb8bc25f7dc0c3ba97Eric Laurent public void disableSafeMediaVolume() { 54133346a802087f621c6441bc512dfcc17b07143fc6John Spurlock enforceSelfOrSystemUI("disable the safe media volume"); 5414d640bd325c3be9a350058c835b880a7e0b40dc60Eric Laurent synchronized (mSafeMediaVolumeState) { 5415c34dcc1e1ebf152bb400abbb8bc25f7dc0c3ba97Eric Laurent setSafeMediaVolumeEnabled(false); 5416fde16d5879ea88a971004c984093409468b6139cEric Laurent if (mPendingVolumeCommand != null) { 5417fde16d5879ea88a971004c984093409468b6139cEric Laurent onSetStreamVolume(mPendingVolumeCommand.mStreamType, 5418fde16d5879ea88a971004c984093409468b6139cEric Laurent mPendingVolumeCommand.mIndex, 5419fde16d5879ea88a971004c984093409468b6139cEric Laurent mPendingVolumeCommand.mFlags, 5420fde16d5879ea88a971004c984093409468b6139cEric Laurent mPendingVolumeCommand.mDevice); 5421fde16d5879ea88a971004c984093409468b6139cEric Laurent mPendingVolumeCommand = null; 5422fde16d5879ea88a971004c984093409468b6139cEric Laurent } 5423c34dcc1e1ebf152bb400abbb8bc25f7dc0c3ba97Eric Laurent } 5424c34dcc1e1ebf152bb400abbb8bc25f7dc0c3ba97Eric Laurent } 5425c34dcc1e1ebf152bb400abbb8bc25f7dc0c3ba97Eric Laurent 542641d974631c5f525da49c88d34cecedd5a4cfeda8Jungshik Jang //========================================================================================== 542741d974631c5f525da49c88d34cecedd5a4cfeda8Jungshik Jang // Hdmi Cec system audio mode. 542841d974631c5f525da49c88d34cecedd5a4cfeda8Jungshik Jang // If Hdmi Cec's system audio mode is on, audio service should notify volume change 542941d974631c5f525da49c88d34cecedd5a4cfeda8Jungshik Jang // to HdmiControlService so that audio recevier can handle volume change. 543041d974631c5f525da49c88d34cecedd5a4cfeda8Jungshik Jang //========================================================================================== 543141d974631c5f525da49c88d34cecedd5a4cfeda8Jungshik Jang 5432212532b58e3b17d7e9d6e1361946d909d4e372c2Eric Laurent private class MyDisplayStatusCallback implements HdmiPlaybackClient.DisplayStatusCallback { 5433212532b58e3b17d7e9d6e1361946d909d4e372c2Eric Laurent public void onComplete(int status) { 5434212532b58e3b17d7e9d6e1361946d909d4e372c2Eric Laurent if (mHdmiManager != null) { 5435212532b58e3b17d7e9d6e1361946d909d4e372c2Eric Laurent synchronized (mHdmiManager) { 5436212532b58e3b17d7e9d6e1361946d909d4e372c2Eric Laurent mHdmiCecSink = (status != HdmiControlManager.POWER_STATUS_UNKNOWN); 5437212532b58e3b17d7e9d6e1361946d909d4e372c2Eric Laurent // Television devices without CEC service apply software volume on HDMI output 5438212532b58e3b17d7e9d6e1361946d909d4e372c2Eric Laurent if (isPlatformTelevision() && !mHdmiCecSink) { 5439212532b58e3b17d7e9d6e1361946d909d4e372c2Eric Laurent mFixedVolumeDevices &= ~AudioSystem.DEVICE_OUT_HDMI; 5440212532b58e3b17d7e9d6e1361946d909d4e372c2Eric Laurent } 5441212532b58e3b17d7e9d6e1361946d909d4e372c2Eric Laurent checkAllFixedVolumeDevices(); 5442212532b58e3b17d7e9d6e1361946d909d4e372c2Eric Laurent } 5443212532b58e3b17d7e9d6e1361946d909d4e372c2Eric Laurent } 5444212532b58e3b17d7e9d6e1361946d909d4e372c2Eric Laurent } 5445212532b58e3b17d7e9d6e1361946d909d4e372c2Eric Laurent }; 5446212532b58e3b17d7e9d6e1361946d909d4e372c2Eric Laurent 544741d974631c5f525da49c88d34cecedd5a4cfeda8Jungshik Jang // If HDMI-CEC system audio is supported 544841d974631c5f525da49c88d34cecedd5a4cfeda8Jungshik Jang private boolean mHdmiSystemAudioSupported = false; 544941d974631c5f525da49c88d34cecedd5a4cfeda8Jungshik Jang // Set only when device is tv. 545041d974631c5f525da49c88d34cecedd5a4cfeda8Jungshik Jang private HdmiTvClient mHdmiTvClient; 54510b03f9909be438f45b32ce2a6a2c2c5208a82cc9Eric Laurent // true if the device has system feature PackageManager.FEATURE_LEANBACK. 5452212532b58e3b17d7e9d6e1361946d909d4e372c2Eric Laurent // cached HdmiControlManager interface 5453212532b58e3b17d7e9d6e1361946d909d4e372c2Eric Laurent private HdmiControlManager mHdmiManager; 5454212532b58e3b17d7e9d6e1361946d909d4e372c2Eric Laurent // Set only when device is a set-top box. 5455212532b58e3b17d7e9d6e1361946d909d4e372c2Eric Laurent private HdmiPlaybackClient mHdmiPlaybackClient; 5456212532b58e3b17d7e9d6e1361946d909d4e372c2Eric Laurent // true if we are a set-top box, an HDMI sink is connected and it supports CEC. 5457212532b58e3b17d7e9d6e1361946d909d4e372c2Eric Laurent private boolean mHdmiCecSink; 5458212532b58e3b17d7e9d6e1361946d909d4e372c2Eric Laurent 5459212532b58e3b17d7e9d6e1361946d909d4e372c2Eric Laurent private MyDisplayStatusCallback mHdmiDisplayStatusCallback = new MyDisplayStatusCallback(); 546041d974631c5f525da49c88d34cecedd5a4cfeda8Jungshik Jang 546141d974631c5f525da49c88d34cecedd5a4cfeda8Jungshik Jang @Override 546212307ca810e8100981b2b60e3f2c6a7e451b9774Jungshik Jang public int setHdmiSystemAudioSupported(boolean on) { 5463212532b58e3b17d7e9d6e1361946d909d4e372c2Eric Laurent int device = AudioSystem.DEVICE_NONE; 5464212532b58e3b17d7e9d6e1361946d909d4e372c2Eric Laurent if (mHdmiManager != null) { 5465212532b58e3b17d7e9d6e1361946d909d4e372c2Eric Laurent synchronized (mHdmiManager) { 5466212532b58e3b17d7e9d6e1361946d909d4e372c2Eric Laurent if (mHdmiTvClient == null) { 5467212532b58e3b17d7e9d6e1361946d909d4e372c2Eric Laurent Log.w(TAG, "Only Hdmi-Cec enabled TV device supports system audio mode."); 5468212532b58e3b17d7e9d6e1361946d909d4e372c2Eric Laurent return device; 5469212532b58e3b17d7e9d6e1361946d909d4e372c2Eric Laurent } 547041d974631c5f525da49c88d34cecedd5a4cfeda8Jungshik Jang 5471212532b58e3b17d7e9d6e1361946d909d4e372c2Eric Laurent synchronized (mHdmiTvClient) { 5472212532b58e3b17d7e9d6e1361946d909d4e372c2Eric Laurent if (mHdmiSystemAudioSupported != on) { 5473212532b58e3b17d7e9d6e1361946d909d4e372c2Eric Laurent mHdmiSystemAudioSupported = on; 5474212532b58e3b17d7e9d6e1361946d909d4e372c2Eric Laurent AudioSystem.setForceUse(AudioSystem.FOR_HDMI_SYSTEM_AUDIO, 5475212532b58e3b17d7e9d6e1361946d909d4e372c2Eric Laurent on ? AudioSystem.FORCE_HDMI_SYSTEM_AUDIO_ENFORCED : 5476212532b58e3b17d7e9d6e1361946d909d4e372c2Eric Laurent AudioSystem.FORCE_NONE); 5477212532b58e3b17d7e9d6e1361946d909d4e372c2Eric Laurent } 5478212532b58e3b17d7e9d6e1361946d909d4e372c2Eric Laurent device = AudioSystem.getDevicesForStream(AudioSystem.STREAM_MUSIC); 5479212532b58e3b17d7e9d6e1361946d909d4e372c2Eric Laurent } 54806f34f5ab8ab1b1db7887e5405d8b0031e105ab05Jungshik Jang } 54816f34f5ab8ab1b1db7887e5405d8b0031e105ab05Jungshik Jang } 5482212532b58e3b17d7e9d6e1361946d909d4e372c2Eric Laurent return device; 54836f34f5ab8ab1b1db7887e5405d8b0031e105ab05Jungshik Jang } 54846f34f5ab8ab1b1db7887e5405d8b0031e105ab05Jungshik Jang 5485e7d6d97f0d95b9e8982b0d4d9f5e8ce688291940Terry Heo @Override 5486e7d6d97f0d95b9e8982b0d4d9f5e8ce688291940Terry Heo public boolean isHdmiSystemAudioSupported() { 5487e7d6d97f0d95b9e8982b0d4d9f5e8ce688291940Terry Heo return mHdmiSystemAudioSupported; 5488e7d6d97f0d95b9e8982b0d4d9f5e8ce688291940Terry Heo } 5489e7d6d97f0d95b9e8982b0d4d9f5e8ce688291940Terry Heo 5490dd45d01128423a82652a3c9d77fa393631d95229Eric Laurent //========================================================================================== 5491873cc45da2463a11182fe94a2565364d7e1709bbJean-Michel Trivi // Accessibility: taking touch exploration into account for selecting the default 5492873cc45da2463a11182fe94a2565364d7e1709bbJean-Michel Trivi // stream override timeout when adjusting volume 5493873cc45da2463a11182fe94a2565364d7e1709bbJean-Michel Trivi //========================================================================================== 5494873cc45da2463a11182fe94a2565364d7e1709bbJean-Michel Trivi private static class StreamOverride 5495873cc45da2463a11182fe94a2565364d7e1709bbJean-Michel Trivi implements AccessibilityManager.TouchExplorationStateChangeListener { 5496873cc45da2463a11182fe94a2565364d7e1709bbJean-Michel Trivi 5497873cc45da2463a11182fe94a2565364d7e1709bbJean-Michel Trivi // AudioService.getActiveStreamType() will return: 5498873cc45da2463a11182fe94a2565364d7e1709bbJean-Michel Trivi // - STREAM_NOTIFICATION on tablets during this period after a notification stopped 5499873cc45da2463a11182fe94a2565364d7e1709bbJean-Michel Trivi // - STREAM_MUSIC on phones during this period after music or talkback/voice search prompt 5500873cc45da2463a11182fe94a2565364d7e1709bbJean-Michel Trivi // stopped 5501873cc45da2463a11182fe94a2565364d7e1709bbJean-Michel Trivi private static final int DEFAULT_STREAM_TYPE_OVERRIDE_DELAY_MS = 5000; 5502873cc45da2463a11182fe94a2565364d7e1709bbJean-Michel Trivi private static final int TOUCH_EXPLORE_STREAM_TYPE_OVERRIDE_DELAY_MS = 1000; 5503873cc45da2463a11182fe94a2565364d7e1709bbJean-Michel Trivi 5504873cc45da2463a11182fe94a2565364d7e1709bbJean-Michel Trivi static int sDelayMs; 5505873cc45da2463a11182fe94a2565364d7e1709bbJean-Michel Trivi 5506873cc45da2463a11182fe94a2565364d7e1709bbJean-Michel Trivi static void init(Context ctxt) { 5507873cc45da2463a11182fe94a2565364d7e1709bbJean-Michel Trivi AccessibilityManager accessibilityManager = 5508873cc45da2463a11182fe94a2565364d7e1709bbJean-Michel Trivi (AccessibilityManager) ctxt.getSystemService(Context.ACCESSIBILITY_SERVICE); 5509873cc45da2463a11182fe94a2565364d7e1709bbJean-Michel Trivi updateDefaultStreamOverrideDelay( 5510873cc45da2463a11182fe94a2565364d7e1709bbJean-Michel Trivi accessibilityManager.isTouchExplorationEnabled()); 5511873cc45da2463a11182fe94a2565364d7e1709bbJean-Michel Trivi accessibilityManager.addTouchExplorationStateChangeListener( 5512873cc45da2463a11182fe94a2565364d7e1709bbJean-Michel Trivi new StreamOverride()); 5513873cc45da2463a11182fe94a2565364d7e1709bbJean-Michel Trivi } 5514873cc45da2463a11182fe94a2565364d7e1709bbJean-Michel Trivi 5515873cc45da2463a11182fe94a2565364d7e1709bbJean-Michel Trivi @Override 5516873cc45da2463a11182fe94a2565364d7e1709bbJean-Michel Trivi public void onTouchExplorationStateChanged(boolean enabled) { 5517873cc45da2463a11182fe94a2565364d7e1709bbJean-Michel Trivi updateDefaultStreamOverrideDelay(enabled); 5518873cc45da2463a11182fe94a2565364d7e1709bbJean-Michel Trivi } 5519873cc45da2463a11182fe94a2565364d7e1709bbJean-Michel Trivi 5520873cc45da2463a11182fe94a2565364d7e1709bbJean-Michel Trivi private static void updateDefaultStreamOverrideDelay(boolean touchExploreEnabled) { 5521873cc45da2463a11182fe94a2565364d7e1709bbJean-Michel Trivi if (touchExploreEnabled) { 5522873cc45da2463a11182fe94a2565364d7e1709bbJean-Michel Trivi sDelayMs = TOUCH_EXPLORE_STREAM_TYPE_OVERRIDE_DELAY_MS; 5523873cc45da2463a11182fe94a2565364d7e1709bbJean-Michel Trivi } else { 5524873cc45da2463a11182fe94a2565364d7e1709bbJean-Michel Trivi sDelayMs = DEFAULT_STREAM_TYPE_OVERRIDE_DELAY_MS; 5525873cc45da2463a11182fe94a2565364d7e1709bbJean-Michel Trivi } 5526873cc45da2463a11182fe94a2565364d7e1709bbJean-Michel Trivi if (DEBUG_VOL) Log.d(TAG, "Touch exploration enabled=" + touchExploreEnabled 5527873cc45da2463a11182fe94a2565364d7e1709bbJean-Michel Trivi + " stream override delay is now " + sDelayMs + " ms"); 5528873cc45da2463a11182fe94a2565364d7e1709bbJean-Michel Trivi } 5529873cc45da2463a11182fe94a2565364d7e1709bbJean-Michel Trivi } 5530873cc45da2463a11182fe94a2565364d7e1709bbJean-Michel Trivi 5531873cc45da2463a11182fe94a2565364d7e1709bbJean-Michel Trivi //========================================================================================== 5532dd45d01128423a82652a3c9d77fa393631d95229Eric Laurent // Camera shutter sound policy. 5533dd45d01128423a82652a3c9d77fa393631d95229Eric Laurent // config_camera_sound_forced configuration option in config.xml defines if the camera shutter 5534dd45d01128423a82652a3c9d77fa393631d95229Eric Laurent // sound is forced (sound even if the device is in silent mode) or not. This option is false by 5535dd45d01128423a82652a3c9d77fa393631d95229Eric Laurent // default and can be overridden by country specific overlay in values-mccXXX/config.xml. 5536dd45d01128423a82652a3c9d77fa393631d95229Eric Laurent //========================================================================================== 5537dd45d01128423a82652a3c9d77fa393631d95229Eric Laurent 5538dd45d01128423a82652a3c9d77fa393631d95229Eric Laurent // cached value of com.android.internal.R.bool.config_camera_sound_forced 5539dd45d01128423a82652a3c9d77fa393631d95229Eric Laurent private Boolean mCameraSoundForced; 5540dd45d01128423a82652a3c9d77fa393631d95229Eric Laurent 5541dd45d01128423a82652a3c9d77fa393631d95229Eric Laurent // called by android.hardware.Camera to populate CameraInfo.canDisableShutterSound 5542dd45d01128423a82652a3c9d77fa393631d95229Eric Laurent public boolean isCameraSoundForced() { 5543dd45d01128423a82652a3c9d77fa393631d95229Eric Laurent synchronized (mCameraSoundForced) { 5544dd45d01128423a82652a3c9d77fa393631d95229Eric Laurent return mCameraSoundForced; 5545dd45d01128423a82652a3c9d77fa393631d95229Eric Laurent } 5546dd45d01128423a82652a3c9d77fa393631d95229Eric Laurent } 5547dd45d01128423a82652a3c9d77fa393631d95229Eric Laurent 5548dd45d01128423a82652a3c9d77fa393631d95229Eric Laurent private static final String[] RINGER_MODE_NAMES = new String[] { 5549dd45d01128423a82652a3c9d77fa393631d95229Eric Laurent "SILENT", 5550dd45d01128423a82652a3c9d77fa393631d95229Eric Laurent "VIBRATE", 5551dd45d01128423a82652a3c9d77fa393631d95229Eric Laurent "NORMAL" 5552dd45d01128423a82652a3c9d77fa393631d95229Eric Laurent }; 5553dd45d01128423a82652a3c9d77fa393631d95229Eric Laurent 5554dd45d01128423a82652a3c9d77fa393631d95229Eric Laurent private void dumpRingerMode(PrintWriter pw) { 5555dd45d01128423a82652a3c9d77fa393631d95229Eric Laurent pw.println("\nRinger mode: "); 5556661f2cf45860d2e10924e6b69966a9afe255f28bJohn Spurlock pw.println("- mode (internal) = " + RINGER_MODE_NAMES[mRingerMode]); 5557661f2cf45860d2e10924e6b69966a9afe255f28bJohn Spurlock pw.println("- mode (external) = " + RINGER_MODE_NAMES[mRingerModeExternal]); 5558dd45d01128423a82652a3c9d77fa393631d95229Eric Laurent pw.print("- ringer mode affected streams = 0x"); 5559dd45d01128423a82652a3c9d77fa393631d95229Eric Laurent pw.println(Integer.toHexString(mRingerModeAffectedStreams)); 5560dd45d01128423a82652a3c9d77fa393631d95229Eric Laurent pw.print("- ringer mode muted streams = 0x"); 5561dd45d01128423a82652a3c9d77fa393631d95229Eric Laurent pw.println(Integer.toHexString(mRingerModeMutedStreams)); 5562661f2cf45860d2e10924e6b69966a9afe255f28bJohn Spurlock pw.print("- delegate = "); pw.println(mRingerModeDelegate); 5563dd45d01128423a82652a3c9d77fa393631d95229Eric Laurent } 5564dd45d01128423a82652a3c9d77fa393631d95229Eric Laurent 5565632ca417f0a33e3fa9ccece531afa2db3f0d4a30Dianne Hackborn @Override 5566d5176cfe6eae954e9cef1e2ec17859a5089e1330Jean-Michel Trivi protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) { 5567eb4cc492c93ab9635dde78b958a834120412e72aJeff Sharkey mContext.enforceCallingOrSelfPermission(android.Manifest.permission.DUMP, TAG); 5568eb4cc492c93ab9635dde78b958a834120412e72aJeff Sharkey 5569fa9a69805b001034aa04c3b33989a7ac21522371Jean-Michel Trivi mMediaFocusControl.dump(pw); 5570bffc3d1bd33eb2d8e00a9f8b6261d815db503311Eric Laurent dumpStreamStates(pw); 5571dd45d01128423a82652a3c9d77fa393631d95229Eric Laurent dumpRingerMode(pw); 5572632ca417f0a33e3fa9ccece531afa2db3f0d4a30Dianne Hackborn pw.println("\nAudio routes:"); 5573632ca417f0a33e3fa9ccece531afa2db3f0d4a30Dianne Hackborn pw.print(" mMainType=0x"); pw.println(Integer.toHexString(mCurAudioRoutes.mMainType)); 5574632ca417f0a33e3fa9ccece531afa2db3f0d4a30Dianne Hackborn pw.print(" mBluetoothName="); pw.println(mCurAudioRoutes.mBluetoothName); 5575351346092acdfbfcc1d9ebf98d539d2a1196c5e8John Spurlock 5576351346092acdfbfcc1d9ebf98d539d2a1196c5e8John Spurlock pw.println("\nOther state:"); 55773346a802087f621c6441bc512dfcc17b07143fc6John Spurlock pw.print(" mVolumeController="); pw.println(mVolumeController); 5578351346092acdfbfcc1d9ebf98d539d2a1196c5e8John Spurlock pw.print(" mSafeMediaVolumeState="); 5579351346092acdfbfcc1d9ebf98d539d2a1196c5e8John Spurlock pw.println(safeMediaVolumeStateToString(mSafeMediaVolumeState)); 5580351346092acdfbfcc1d9ebf98d539d2a1196c5e8John Spurlock pw.print(" mSafeMediaVolumeIndex="); pw.println(mSafeMediaVolumeIndex); 5581351346092acdfbfcc1d9ebf98d539d2a1196c5e8John Spurlock pw.print(" mPendingVolumeCommand="); pw.println(mPendingVolumeCommand); 5582351346092acdfbfcc1d9ebf98d539d2a1196c5e8John Spurlock pw.print(" mMusicActiveMs="); pw.println(mMusicActiveMs); 5583aa5ee4d65f8788e2a0afcd198367450853fd72acJohn Spurlock pw.print(" mMcc="); pw.println(mMcc); 5584661f2cf45860d2e10924e6b69966a9afe255f28bJohn Spurlock pw.print(" mHasVibrator="); pw.println(mHasVibrator); 55851b3541d5eedb332ea01066b4a78a2d06d5304044Jean-Michel Trivi 55861b3541d5eedb332ea01066b4a78a2d06d5304044Jean-Michel Trivi dumpAudioPolicies(pw); 5587351346092acdfbfcc1d9ebf98d539d2a1196c5e8John Spurlock } 5588351346092acdfbfcc1d9ebf98d539d2a1196c5e8John Spurlock 5589351346092acdfbfcc1d9ebf98d539d2a1196c5e8John Spurlock private static String safeMediaVolumeStateToString(Integer state) { 5590351346092acdfbfcc1d9ebf98d539d2a1196c5e8John Spurlock switch(state) { 5591351346092acdfbfcc1d9ebf98d539d2a1196c5e8John Spurlock case SAFE_MEDIA_VOLUME_NOT_CONFIGURED: return "SAFE_MEDIA_VOLUME_NOT_CONFIGURED"; 5592351346092acdfbfcc1d9ebf98d539d2a1196c5e8John Spurlock case SAFE_MEDIA_VOLUME_DISABLED: return "SAFE_MEDIA_VOLUME_DISABLED"; 5593351346092acdfbfcc1d9ebf98d539d2a1196c5e8John Spurlock case SAFE_MEDIA_VOLUME_INACTIVE: return "SAFE_MEDIA_VOLUME_INACTIVE"; 5594351346092acdfbfcc1d9ebf98d539d2a1196c5e8John Spurlock case SAFE_MEDIA_VOLUME_ACTIVE: return "SAFE_MEDIA_VOLUME_ACTIVE"; 5595351346092acdfbfcc1d9ebf98d539d2a1196c5e8John Spurlock } 5596351346092acdfbfcc1d9ebf98d539d2a1196c5e8John Spurlock return null; 5597d5176cfe6eae954e9cef1e2ec17859a5089e1330Jean-Michel Trivi } 5598fd116ad1ab02f6060a0b2201f018317fa32e28b4Glenn Kasten 5599fd116ad1ab02f6060a0b2201f018317fa32e28b4Glenn Kasten // Inform AudioFlinger of our device's low RAM attribute 5600fd116ad1ab02f6060a0b2201f018317fa32e28b4Glenn Kasten private static void readAndSetLowRamDevice() 5601fd116ad1ab02f6060a0b2201f018317fa32e28b4Glenn Kasten { 5602fd116ad1ab02f6060a0b2201f018317fa32e28b4Glenn Kasten int status = AudioSystem.setLowRamDevice(ActivityManager.isLowRamDeviceStatic()); 5603fd116ad1ab02f6060a0b2201f018317fa32e28b4Glenn Kasten if (status != 0) { 5604fd116ad1ab02f6060a0b2201f018317fa32e28b4Glenn Kasten Log.w(TAG, "AudioFlinger informed of device's low RAM attribute; status " + status); 5605fd116ad1ab02f6060a0b2201f018317fa32e28b4Glenn Kasten } 5606fd116ad1ab02f6060a0b2201f018317fa32e28b4Glenn Kasten } 56073346a802087f621c6441bc512dfcc17b07143fc6John Spurlock 56083346a802087f621c6441bc512dfcc17b07143fc6John Spurlock private void enforceSelfOrSystemUI(String action) { 56093346a802087f621c6441bc512dfcc17b07143fc6John Spurlock mContext.enforceCallingOrSelfPermission(android.Manifest.permission.STATUS_BAR_SERVICE, 56103346a802087f621c6441bc512dfcc17b07143fc6John Spurlock "Only SystemUI can " + action); 56113346a802087f621c6441bc512dfcc17b07143fc6John Spurlock } 56123346a802087f621c6441bc512dfcc17b07143fc6John Spurlock 56133346a802087f621c6441bc512dfcc17b07143fc6John Spurlock @Override 56143346a802087f621c6441bc512dfcc17b07143fc6John Spurlock public void setVolumeController(final IVolumeController controller) { 56153346a802087f621c6441bc512dfcc17b07143fc6John Spurlock enforceSelfOrSystemUI("set the volume controller"); 56163346a802087f621c6441bc512dfcc17b07143fc6John Spurlock 56173346a802087f621c6441bc512dfcc17b07143fc6John Spurlock // return early if things are not actually changing 56183346a802087f621c6441bc512dfcc17b07143fc6John Spurlock if (mVolumeController.isSameBinder(controller)) { 56193346a802087f621c6441bc512dfcc17b07143fc6John Spurlock return; 56203346a802087f621c6441bc512dfcc17b07143fc6John Spurlock } 56213346a802087f621c6441bc512dfcc17b07143fc6John Spurlock 56223346a802087f621c6441bc512dfcc17b07143fc6John Spurlock // dismiss the old volume controller 56233346a802087f621c6441bc512dfcc17b07143fc6John Spurlock mVolumeController.postDismiss(); 56243346a802087f621c6441bc512dfcc17b07143fc6John Spurlock if (controller != null) { 56253346a802087f621c6441bc512dfcc17b07143fc6John Spurlock // we are about to register a new controller, listen for its death 56263346a802087f621c6441bc512dfcc17b07143fc6John Spurlock try { 56273346a802087f621c6441bc512dfcc17b07143fc6John Spurlock controller.asBinder().linkToDeath(new DeathRecipient() { 56283346a802087f621c6441bc512dfcc17b07143fc6John Spurlock @Override 56293346a802087f621c6441bc512dfcc17b07143fc6John Spurlock public void binderDied() { 56303346a802087f621c6441bc512dfcc17b07143fc6John Spurlock if (mVolumeController.isSameBinder(controller)) { 56313346a802087f621c6441bc512dfcc17b07143fc6John Spurlock Log.w(TAG, "Current remote volume controller died, unregistering"); 56323346a802087f621c6441bc512dfcc17b07143fc6John Spurlock setVolumeController(null); 56333346a802087f621c6441bc512dfcc17b07143fc6John Spurlock } 56343346a802087f621c6441bc512dfcc17b07143fc6John Spurlock } 56353346a802087f621c6441bc512dfcc17b07143fc6John Spurlock }, 0); 56363346a802087f621c6441bc512dfcc17b07143fc6John Spurlock } catch (RemoteException e) { 56373346a802087f621c6441bc512dfcc17b07143fc6John Spurlock // noop 56383346a802087f621c6441bc512dfcc17b07143fc6John Spurlock } 56393346a802087f621c6441bc512dfcc17b07143fc6John Spurlock } 56403346a802087f621c6441bc512dfcc17b07143fc6John Spurlock mVolumeController.setController(controller); 564133f4e04e32fac42f158733d6a731e50490fa9951John Spurlock if (DEBUG_VOL) Log.d(TAG, "Volume controller: " + mVolumeController); 564233f4e04e32fac42f158733d6a731e50490fa9951John Spurlock } 564333f4e04e32fac42f158733d6a731e50490fa9951John Spurlock 564433f4e04e32fac42f158733d6a731e50490fa9951John Spurlock @Override 564533f4e04e32fac42f158733d6a731e50490fa9951John Spurlock public void notifyVolumeControllerVisible(final IVolumeController controller, boolean visible) { 564633f4e04e32fac42f158733d6a731e50490fa9951John Spurlock enforceSelfOrSystemUI("notify about volume controller visibility"); 564733f4e04e32fac42f158733d6a731e50490fa9951John Spurlock 564833f4e04e32fac42f158733d6a731e50490fa9951John Spurlock // return early if the controller is not current 564933f4e04e32fac42f158733d6a731e50490fa9951John Spurlock if (!mVolumeController.isSameBinder(controller)) { 565033f4e04e32fac42f158733d6a731e50490fa9951John Spurlock return; 565133f4e04e32fac42f158733d6a731e50490fa9951John Spurlock } 565233f4e04e32fac42f158733d6a731e50490fa9951John Spurlock 565333f4e04e32fac42f158733d6a731e50490fa9951John Spurlock mVolumeController.setVisible(visible); 565433f4e04e32fac42f158733d6a731e50490fa9951John Spurlock if (DEBUG_VOL) Log.d(TAG, "Volume controller visible: " + visible); 56553346a802087f621c6441bc512dfcc17b07143fc6John Spurlock } 5656d09bd0c6eb8318e0122b14d7eb5324e481706e41RoboErik 5657d09bd0c6eb8318e0122b14d7eb5324e481706e41RoboErik public static class VolumeController { 5658d09bd0c6eb8318e0122b14d7eb5324e481706e41RoboErik private static final String TAG = "VolumeController"; 5659d09bd0c6eb8318e0122b14d7eb5324e481706e41RoboErik 5660d09bd0c6eb8318e0122b14d7eb5324e481706e41RoboErik private IVolumeController mController; 566133f4e04e32fac42f158733d6a731e50490fa9951John Spurlock private boolean mVisible; 566233f4e04e32fac42f158733d6a731e50490fa9951John Spurlock private long mNextLongPress; 566333f4e04e32fac42f158733d6a731e50490fa9951John Spurlock private int mLongPressTimeout; 5664d09bd0c6eb8318e0122b14d7eb5324e481706e41RoboErik 5665d09bd0c6eb8318e0122b14d7eb5324e481706e41RoboErik public void setController(IVolumeController controller) { 5666d09bd0c6eb8318e0122b14d7eb5324e481706e41RoboErik mController = controller; 566733f4e04e32fac42f158733d6a731e50490fa9951John Spurlock mVisible = false; 566833f4e04e32fac42f158733d6a731e50490fa9951John Spurlock } 566933f4e04e32fac42f158733d6a731e50490fa9951John Spurlock 567033f4e04e32fac42f158733d6a731e50490fa9951John Spurlock public void loadSettings(ContentResolver cr) { 567133f4e04e32fac42f158733d6a731e50490fa9951John Spurlock mLongPressTimeout = Settings.Secure.getIntForUser(cr, 567233f4e04e32fac42f158733d6a731e50490fa9951John Spurlock Settings.Secure.LONG_PRESS_TIMEOUT, 500, UserHandle.USER_CURRENT); 567333f4e04e32fac42f158733d6a731e50490fa9951John Spurlock } 567433f4e04e32fac42f158733d6a731e50490fa9951John Spurlock 567533f4e04e32fac42f158733d6a731e50490fa9951John Spurlock public boolean suppressAdjustment(int resolvedStream, int flags) { 567633f4e04e32fac42f158733d6a731e50490fa9951John Spurlock boolean suppress = false; 567733f4e04e32fac42f158733d6a731e50490fa9951John Spurlock if (resolvedStream == AudioSystem.STREAM_RING && mController != null) { 567833f4e04e32fac42f158733d6a731e50490fa9951John Spurlock final long now = SystemClock.uptimeMillis(); 567933f4e04e32fac42f158733d6a731e50490fa9951John Spurlock if ((flags & AudioManager.FLAG_SHOW_UI) != 0 && !mVisible) { 568033f4e04e32fac42f158733d6a731e50490fa9951John Spurlock // ui will become visible 568133f4e04e32fac42f158733d6a731e50490fa9951John Spurlock if (mNextLongPress < now) { 568233f4e04e32fac42f158733d6a731e50490fa9951John Spurlock mNextLongPress = now + mLongPressTimeout; 568333f4e04e32fac42f158733d6a731e50490fa9951John Spurlock } 568433f4e04e32fac42f158733d6a731e50490fa9951John Spurlock suppress = true; 568533f4e04e32fac42f158733d6a731e50490fa9951John Spurlock } else if (mNextLongPress > 0) { // in a long-press 568633f4e04e32fac42f158733d6a731e50490fa9951John Spurlock if (now > mNextLongPress) { 568733f4e04e32fac42f158733d6a731e50490fa9951John Spurlock // long press triggered, no more suppression 568833f4e04e32fac42f158733d6a731e50490fa9951John Spurlock mNextLongPress = 0; 568933f4e04e32fac42f158733d6a731e50490fa9951John Spurlock } else { 569033f4e04e32fac42f158733d6a731e50490fa9951John Spurlock // keep suppressing until the long press triggers 569133f4e04e32fac42f158733d6a731e50490fa9951John Spurlock suppress = true; 569233f4e04e32fac42f158733d6a731e50490fa9951John Spurlock } 569333f4e04e32fac42f158733d6a731e50490fa9951John Spurlock } 569433f4e04e32fac42f158733d6a731e50490fa9951John Spurlock } 569533f4e04e32fac42f158733d6a731e50490fa9951John Spurlock return suppress; 569633f4e04e32fac42f158733d6a731e50490fa9951John Spurlock } 569733f4e04e32fac42f158733d6a731e50490fa9951John Spurlock 569833f4e04e32fac42f158733d6a731e50490fa9951John Spurlock public void setVisible(boolean visible) { 569933f4e04e32fac42f158733d6a731e50490fa9951John Spurlock mVisible = visible; 5700d09bd0c6eb8318e0122b14d7eb5324e481706e41RoboErik } 5701d09bd0c6eb8318e0122b14d7eb5324e481706e41RoboErik 5702d09bd0c6eb8318e0122b14d7eb5324e481706e41RoboErik public boolean isSameBinder(IVolumeController controller) { 5703d09bd0c6eb8318e0122b14d7eb5324e481706e41RoboErik return Objects.equals(asBinder(), binder(controller)); 5704d09bd0c6eb8318e0122b14d7eb5324e481706e41RoboErik } 5705d09bd0c6eb8318e0122b14d7eb5324e481706e41RoboErik 5706d09bd0c6eb8318e0122b14d7eb5324e481706e41RoboErik public IBinder asBinder() { 5707d09bd0c6eb8318e0122b14d7eb5324e481706e41RoboErik return binder(mController); 5708d09bd0c6eb8318e0122b14d7eb5324e481706e41RoboErik } 5709d09bd0c6eb8318e0122b14d7eb5324e481706e41RoboErik 5710d09bd0c6eb8318e0122b14d7eb5324e481706e41RoboErik private static IBinder binder(IVolumeController controller) { 5711d09bd0c6eb8318e0122b14d7eb5324e481706e41RoboErik return controller == null ? null : controller.asBinder(); 5712d09bd0c6eb8318e0122b14d7eb5324e481706e41RoboErik } 5713d09bd0c6eb8318e0122b14d7eb5324e481706e41RoboErik 5714d09bd0c6eb8318e0122b14d7eb5324e481706e41RoboErik @Override 5715d09bd0c6eb8318e0122b14d7eb5324e481706e41RoboErik public String toString() { 571633f4e04e32fac42f158733d6a731e50490fa9951John Spurlock return "VolumeController(" + asBinder() + ",mVisible=" + mVisible + ")"; 5717d09bd0c6eb8318e0122b14d7eb5324e481706e41RoboErik } 5718d09bd0c6eb8318e0122b14d7eb5324e481706e41RoboErik 5719d09bd0c6eb8318e0122b14d7eb5324e481706e41RoboErik public void postDisplaySafeVolumeWarning(int flags) { 5720d09bd0c6eb8318e0122b14d7eb5324e481706e41RoboErik if (mController == null) 5721d09bd0c6eb8318e0122b14d7eb5324e481706e41RoboErik return; 5722d09bd0c6eb8318e0122b14d7eb5324e481706e41RoboErik try { 5723d09bd0c6eb8318e0122b14d7eb5324e481706e41RoboErik mController.displaySafeVolumeWarning(flags); 5724d09bd0c6eb8318e0122b14d7eb5324e481706e41RoboErik } catch (RemoteException e) { 5725d09bd0c6eb8318e0122b14d7eb5324e481706e41RoboErik Log.w(TAG, "Error calling displaySafeVolumeWarning", e); 5726d09bd0c6eb8318e0122b14d7eb5324e481706e41RoboErik } 5727d09bd0c6eb8318e0122b14d7eb5324e481706e41RoboErik } 5728d09bd0c6eb8318e0122b14d7eb5324e481706e41RoboErik 5729d09bd0c6eb8318e0122b14d7eb5324e481706e41RoboErik public void postVolumeChanged(int streamType, int flags) { 5730d09bd0c6eb8318e0122b14d7eb5324e481706e41RoboErik if (mController == null) 5731d09bd0c6eb8318e0122b14d7eb5324e481706e41RoboErik return; 5732d09bd0c6eb8318e0122b14d7eb5324e481706e41RoboErik try { 5733d09bd0c6eb8318e0122b14d7eb5324e481706e41RoboErik mController.volumeChanged(streamType, flags); 5734d09bd0c6eb8318e0122b14d7eb5324e481706e41RoboErik } catch (RemoteException e) { 5735d09bd0c6eb8318e0122b14d7eb5324e481706e41RoboErik Log.w(TAG, "Error calling volumeChanged", e); 5736d09bd0c6eb8318e0122b14d7eb5324e481706e41RoboErik } 5737d09bd0c6eb8318e0122b14d7eb5324e481706e41RoboErik } 5738d09bd0c6eb8318e0122b14d7eb5324e481706e41RoboErik 5739d09bd0c6eb8318e0122b14d7eb5324e481706e41RoboErik public void postMasterVolumeChanged(int flags) { 5740d09bd0c6eb8318e0122b14d7eb5324e481706e41RoboErik if (mController == null) 5741d09bd0c6eb8318e0122b14d7eb5324e481706e41RoboErik return; 5742d09bd0c6eb8318e0122b14d7eb5324e481706e41RoboErik try { 5743d09bd0c6eb8318e0122b14d7eb5324e481706e41RoboErik mController.masterVolumeChanged(flags); 5744d09bd0c6eb8318e0122b14d7eb5324e481706e41RoboErik } catch (RemoteException e) { 5745d09bd0c6eb8318e0122b14d7eb5324e481706e41RoboErik Log.w(TAG, "Error calling masterVolumeChanged", e); 5746d09bd0c6eb8318e0122b14d7eb5324e481706e41RoboErik } 5747d09bd0c6eb8318e0122b14d7eb5324e481706e41RoboErik } 5748d09bd0c6eb8318e0122b14d7eb5324e481706e41RoboErik 5749d09bd0c6eb8318e0122b14d7eb5324e481706e41RoboErik public void postMasterMuteChanged(int flags) { 5750d09bd0c6eb8318e0122b14d7eb5324e481706e41RoboErik if (mController == null) 5751d09bd0c6eb8318e0122b14d7eb5324e481706e41RoboErik return; 5752d09bd0c6eb8318e0122b14d7eb5324e481706e41RoboErik try { 5753d09bd0c6eb8318e0122b14d7eb5324e481706e41RoboErik mController.masterMuteChanged(flags); 5754d09bd0c6eb8318e0122b14d7eb5324e481706e41RoboErik } catch (RemoteException e) { 5755d09bd0c6eb8318e0122b14d7eb5324e481706e41RoboErik Log.w(TAG, "Error calling masterMuteChanged", e); 5756d09bd0c6eb8318e0122b14d7eb5324e481706e41RoboErik } 5757d09bd0c6eb8318e0122b14d7eb5324e481706e41RoboErik } 5758d09bd0c6eb8318e0122b14d7eb5324e481706e41RoboErik 5759d09bd0c6eb8318e0122b14d7eb5324e481706e41RoboErik public void setLayoutDirection(int layoutDirection) { 5760d09bd0c6eb8318e0122b14d7eb5324e481706e41RoboErik if (mController == null) 5761d09bd0c6eb8318e0122b14d7eb5324e481706e41RoboErik return; 5762d09bd0c6eb8318e0122b14d7eb5324e481706e41RoboErik try { 5763d09bd0c6eb8318e0122b14d7eb5324e481706e41RoboErik mController.setLayoutDirection(layoutDirection); 5764d09bd0c6eb8318e0122b14d7eb5324e481706e41RoboErik } catch (RemoteException e) { 5765d09bd0c6eb8318e0122b14d7eb5324e481706e41RoboErik Log.w(TAG, "Error calling setLayoutDirection", e); 5766d09bd0c6eb8318e0122b14d7eb5324e481706e41RoboErik } 5767d09bd0c6eb8318e0122b14d7eb5324e481706e41RoboErik } 5768d09bd0c6eb8318e0122b14d7eb5324e481706e41RoboErik 5769d09bd0c6eb8318e0122b14d7eb5324e481706e41RoboErik public void postDismiss() { 5770d09bd0c6eb8318e0122b14d7eb5324e481706e41RoboErik if (mController == null) 5771d09bd0c6eb8318e0122b14d7eb5324e481706e41RoboErik return; 5772d09bd0c6eb8318e0122b14d7eb5324e481706e41RoboErik try { 5773d09bd0c6eb8318e0122b14d7eb5324e481706e41RoboErik mController.dismiss(); 5774d09bd0c6eb8318e0122b14d7eb5324e481706e41RoboErik } catch (RemoteException e) { 5775d09bd0c6eb8318e0122b14d7eb5324e481706e41RoboErik Log.w(TAG, "Error calling dismiss", e); 5776d09bd0c6eb8318e0122b14d7eb5324e481706e41RoboErik } 5777661f2cf45860d2e10924e6b69966a9afe255f28bJohn Spurlock } 5778d09bd0c6eb8318e0122b14d7eb5324e481706e41RoboErik } 5779a8b6bd88cfb010c9e9aa1339e504fd593919e1e0Jean-Michel Trivi 57800dac35af2c6aa42bcd181981b041747cfd1afa5fRoboErik /** 57810dac35af2c6aa42bcd181981b041747cfd1afa5fRoboErik * Interface for system components to get some extra functionality through 57820dac35af2c6aa42bcd181981b041747cfd1afa5fRoboErik * LocalServices. 57830dac35af2c6aa42bcd181981b041747cfd1afa5fRoboErik */ 57840dac35af2c6aa42bcd181981b041747cfd1afa5fRoboErik final class AudioServiceInternal extends AudioManagerInternal { 5785661f2cf45860d2e10924e6b69966a9afe255f28bJohn Spurlock @Override 5786661f2cf45860d2e10924e6b69966a9afe255f28bJohn Spurlock public void setRingerModeDelegate(RingerModeDelegate delegate) { 5787661f2cf45860d2e10924e6b69966a9afe255f28bJohn Spurlock mRingerModeDelegate = delegate; 5788661f2cf45860d2e10924e6b69966a9afe255f28bJohn Spurlock if (mRingerModeDelegate != null) { 5789661f2cf45860d2e10924e6b69966a9afe255f28bJohn Spurlock setRingerModeInternal(getRingerModeInternal(), TAG + ".setRingerModeDelegate"); 5790661f2cf45860d2e10924e6b69966a9afe255f28bJohn Spurlock } 5791661f2cf45860d2e10924e6b69966a9afe255f28bJohn Spurlock } 5792272e161c1a200900cb10b5b0cdab8ae1f123cabdRoboErik 5793272e161c1a200900cb10b5b0cdab8ae1f123cabdRoboErik @Override 5794272e161c1a200900cb10b5b0cdab8ae1f123cabdRoboErik public void adjustSuggestedStreamVolumeForUid(int streamType, int direction, int flags, 5795272e161c1a200900cb10b5b0cdab8ae1f123cabdRoboErik String callingPackage, int uid) { 5796272e161c1a200900cb10b5b0cdab8ae1f123cabdRoboErik // direction and stream type swap here because the public 5797272e161c1a200900cb10b5b0cdab8ae1f123cabdRoboErik // adjustSuggested has a different order than the other methods. 5798272e161c1a200900cb10b5b0cdab8ae1f123cabdRoboErik adjustSuggestedStreamVolume(direction, streamType, flags, callingPackage, uid); 5799272e161c1a200900cb10b5b0cdab8ae1f123cabdRoboErik } 5800272e161c1a200900cb10b5b0cdab8ae1f123cabdRoboErik 58010dac35af2c6aa42bcd181981b041747cfd1afa5fRoboErik @Override 58020dac35af2c6aa42bcd181981b041747cfd1afa5fRoboErik public void adjustStreamVolumeForUid(int streamType, int direction, int flags, 58030dac35af2c6aa42bcd181981b041747cfd1afa5fRoboErik String callingPackage, int uid) { 58040dac35af2c6aa42bcd181981b041747cfd1afa5fRoboErik adjustStreamVolume(streamType, direction, flags, callingPackage, uid); 58050dac35af2c6aa42bcd181981b041747cfd1afa5fRoboErik } 58060dac35af2c6aa42bcd181981b041747cfd1afa5fRoboErik 58070dac35af2c6aa42bcd181981b041747cfd1afa5fRoboErik @Override 58080dac35af2c6aa42bcd181981b041747cfd1afa5fRoboErik public void setStreamVolumeForUid(int streamType, int direction, int flags, 58090dac35af2c6aa42bcd181981b041747cfd1afa5fRoboErik String callingPackage, int uid) { 58100dac35af2c6aa42bcd181981b041747cfd1afa5fRoboErik setStreamVolume(streamType, direction, flags, callingPackage, uid); 58110dac35af2c6aa42bcd181981b041747cfd1afa5fRoboErik } 5812519c7744b522aa07e12bc3244ac3de14aa2a4ad0RoboErik 5813519c7744b522aa07e12bc3244ac3de14aa2a4ad0RoboErik @Override 5814519c7744b522aa07e12bc3244ac3de14aa2a4ad0RoboErik public void adjustMasterVolumeForUid(int steps, int flags, String callingPackage, 5815519c7744b522aa07e12bc3244ac3de14aa2a4ad0RoboErik int uid) { 5816519c7744b522aa07e12bc3244ac3de14aa2a4ad0RoboErik adjustMasterVolume(steps, flags, callingPackage, uid); 5817519c7744b522aa07e12bc3244ac3de14aa2a4ad0RoboErik } 5818661f2cf45860d2e10924e6b69966a9afe255f28bJohn Spurlock 5819661f2cf45860d2e10924e6b69966a9afe255f28bJohn Spurlock @Override 5820661f2cf45860d2e10924e6b69966a9afe255f28bJohn Spurlock public int getRingerModeInternal() { 5821661f2cf45860d2e10924e6b69966a9afe255f28bJohn Spurlock return AudioService.this.getRingerModeInternal(); 5822661f2cf45860d2e10924e6b69966a9afe255f28bJohn Spurlock } 5823661f2cf45860d2e10924e6b69966a9afe255f28bJohn Spurlock 5824661f2cf45860d2e10924e6b69966a9afe255f28bJohn Spurlock @Override 5825661f2cf45860d2e10924e6b69966a9afe255f28bJohn Spurlock public void setRingerModeInternal(int ringerMode, String caller) { 5826661f2cf45860d2e10924e6b69966a9afe255f28bJohn Spurlock AudioService.this.setRingerModeInternal(ringerMode, caller); 5827661f2cf45860d2e10924e6b69966a9afe255f28bJohn Spurlock } 58287c82ced4fc5b66c09a19eed9a5499039530142fbRoboErik 58297c82ced4fc5b66c09a19eed9a5499039530142fbRoboErik @Override 58307c82ced4fc5b66c09a19eed9a5499039530142fbRoboErik public void setMasterMuteForUid(boolean state, int flags, String callingPackage, IBinder cb, 58317c82ced4fc5b66c09a19eed9a5499039530142fbRoboErik int uid) { 58327c82ced4fc5b66c09a19eed9a5499039530142fbRoboErik setMasterMuteInternal(state, flags, callingPackage, cb, uid); 58337c82ced4fc5b66c09a19eed9a5499039530142fbRoboErik } 58340dac35af2c6aa42bcd181981b041747cfd1afa5fRoboErik } 58350dac35af2c6aa42bcd181981b041747cfd1afa5fRoboErik 5836a8b6bd88cfb010c9e9aa1339e504fd593919e1e0Jean-Michel Trivi //========================================================================================== 5837a8b6bd88cfb010c9e9aa1339e504fd593919e1e0Jean-Michel Trivi // Audio policy management 5838a8b6bd88cfb010c9e9aa1339e504fd593919e1e0Jean-Michel Trivi //========================================================================================== 58390212be5150fb9fb3c340f3c7e51f6126372cc6f9Jean-Michel Trivi public String registerAudioPolicy(AudioPolicyConfig policyConfig, IAudioPolicyCallback pcb, 58400212be5150fb9fb3c340f3c7e51f6126372cc6f9Jean-Michel Trivi boolean hasFocusListener) { 58410212be5150fb9fb3c340f3c7e51f6126372cc6f9Jean-Michel Trivi if (DEBUG_AP) Log.d(TAG, "registerAudioPolicy for " + pcb.asBinder() 58420212be5150fb9fb3c340f3c7e51f6126372cc6f9Jean-Michel Trivi + " with config:" + policyConfig); 58438fdb0d4defb6ee2ca8057d3442ead36b408b6c17Jean-Michel Trivi String regId = null; 58440212be5150fb9fb3c340f3c7e51f6126372cc6f9Jean-Michel Trivi // error handling 5845a8b6bd88cfb010c9e9aa1339e504fd593919e1e0Jean-Michel Trivi boolean hasPermissionForPolicy = 58460212be5150fb9fb3c340f3c7e51f6126372cc6f9Jean-Michel Trivi (PackageManager.PERMISSION_GRANTED == mContext.checkCallingPermission( 5847a8b6bd88cfb010c9e9aa1339e504fd593919e1e0Jean-Michel Trivi android.Manifest.permission.MODIFY_AUDIO_ROUTING)); 5848a8b6bd88cfb010c9e9aa1339e504fd593919e1e0Jean-Michel Trivi if (!hasPermissionForPolicy) { 5849a8b6bd88cfb010c9e9aa1339e504fd593919e1e0Jean-Michel Trivi Slog.w(TAG, "Can't register audio policy for pid " + Binder.getCallingPid() + " / uid " 5850a8b6bd88cfb010c9e9aa1339e504fd593919e1e0Jean-Michel Trivi + Binder.getCallingUid() + ", need MODIFY_AUDIO_ROUTING"); 58518fdb0d4defb6ee2ca8057d3442ead36b408b6c17Jean-Michel Trivi return null; 5852a8b6bd88cfb010c9e9aa1339e504fd593919e1e0Jean-Michel Trivi } 58530212be5150fb9fb3c340f3c7e51f6126372cc6f9Jean-Michel Trivi 5854a8b6bd88cfb010c9e9aa1339e504fd593919e1e0Jean-Michel Trivi synchronized (mAudioPolicies) { 5855a8b6bd88cfb010c9e9aa1339e504fd593919e1e0Jean-Michel Trivi try { 58560212be5150fb9fb3c340f3c7e51f6126372cc6f9Jean-Michel Trivi if (mAudioPolicies.containsKey(pcb.asBinder())) { 58571b3541d5eedb332ea01066b4a78a2d06d5304044Jean-Michel Trivi Slog.e(TAG, "Cannot re-register policy"); 58581b3541d5eedb332ea01066b4a78a2d06d5304044Jean-Michel Trivi return null; 58591b3541d5eedb332ea01066b4a78a2d06d5304044Jean-Michel Trivi } 58600212be5150fb9fb3c340f3c7e51f6126372cc6f9Jean-Michel Trivi AudioPolicyProxy app = new AudioPolicyProxy(policyConfig, pcb, hasFocusListener); 58610212be5150fb9fb3c340f3c7e51f6126372cc6f9Jean-Michel Trivi pcb.asBinder().linkToDeath(app, 0/*flags*/); 58620212be5150fb9fb3c340f3c7e51f6126372cc6f9Jean-Michel Trivi regId = app.getRegistrationId(); 58630212be5150fb9fb3c340f3c7e51f6126372cc6f9Jean-Michel Trivi mAudioPolicies.put(pcb.asBinder(), app); 5864a8b6bd88cfb010c9e9aa1339e504fd593919e1e0Jean-Michel Trivi } catch (RemoteException e) { 5865a8b6bd88cfb010c9e9aa1339e504fd593919e1e0Jean-Michel Trivi // audio policy owner has already died! 58660212be5150fb9fb3c340f3c7e51f6126372cc6f9Jean-Michel Trivi Slog.w(TAG, "Audio policy registration failed, could not link to " + pcb + 5867a8b6bd88cfb010c9e9aa1339e504fd593919e1e0Jean-Michel Trivi " binder death", e); 58688fdb0d4defb6ee2ca8057d3442ead36b408b6c17Jean-Michel Trivi return null; 5869a8b6bd88cfb010c9e9aa1339e504fd593919e1e0Jean-Michel Trivi } 5870a8b6bd88cfb010c9e9aa1339e504fd593919e1e0Jean-Michel Trivi } 58718fdb0d4defb6ee2ca8057d3442ead36b408b6c17Jean-Michel Trivi return regId; 5872a8b6bd88cfb010c9e9aa1339e504fd593919e1e0Jean-Michel Trivi } 58738fdb0d4defb6ee2ca8057d3442ead36b408b6c17Jean-Michel Trivi 58740212be5150fb9fb3c340f3c7e51f6126372cc6f9Jean-Michel Trivi public void unregisterAudioPolicyAsync(IAudioPolicyCallback pcb) { 58750212be5150fb9fb3c340f3c7e51f6126372cc6f9Jean-Michel Trivi if (DEBUG_AP) Log.d(TAG, "unregisterAudioPolicyAsync for " + pcb.asBinder()); 5876a8b6bd88cfb010c9e9aa1339e504fd593919e1e0Jean-Michel Trivi synchronized (mAudioPolicies) { 58770212be5150fb9fb3c340f3c7e51f6126372cc6f9Jean-Michel Trivi AudioPolicyProxy app = mAudioPolicies.remove(pcb.asBinder()); 5878a8b6bd88cfb010c9e9aa1339e504fd593919e1e0Jean-Michel Trivi if (app == null) { 5879a8b6bd88cfb010c9e9aa1339e504fd593919e1e0Jean-Michel Trivi Slog.w(TAG, "Trying to unregister unknown audio policy for pid " 5880a8b6bd88cfb010c9e9aa1339e504fd593919e1e0Jean-Michel Trivi + Binder.getCallingPid() + " / uid " + Binder.getCallingUid()); 58811b3541d5eedb332ea01066b4a78a2d06d5304044Jean-Michel Trivi return; 5882a8b6bd88cfb010c9e9aa1339e504fd593919e1e0Jean-Michel Trivi } else { 58830212be5150fb9fb3c340f3c7e51f6126372cc6f9Jean-Michel Trivi pcb.asBinder().unlinkToDeath(app, 0/*flags*/); 5884a8b6bd88cfb010c9e9aa1339e504fd593919e1e0Jean-Michel Trivi } 58850212be5150fb9fb3c340f3c7e51f6126372cc6f9Jean-Michel Trivi app.release(); 5886a8b6bd88cfb010c9e9aa1339e504fd593919e1e0Jean-Michel Trivi } 58878fdb0d4defb6ee2ca8057d3442ead36b408b6c17Jean-Michel Trivi // TODO implement clearing mix attribute matching info in native audio policy 5888a8b6bd88cfb010c9e9aa1339e504fd593919e1e0Jean-Michel Trivi } 5889a8b6bd88cfb010c9e9aa1339e504fd593919e1e0Jean-Michel Trivi 58900212be5150fb9fb3c340f3c7e51f6126372cc6f9Jean-Michel Trivi public int setFocusPropertiesForPolicy(int duckingBehavior, IAudioPolicyCallback pcb) { 58910212be5150fb9fb3c340f3c7e51f6126372cc6f9Jean-Michel Trivi if (DEBUG_AP) Log.d(TAG, "setFocusPropertiesForPolicy() duck behavior=" + duckingBehavior 58920212be5150fb9fb3c340f3c7e51f6126372cc6f9Jean-Michel Trivi + " policy " + pcb.asBinder()); 58930212be5150fb9fb3c340f3c7e51f6126372cc6f9Jean-Michel Trivi // error handling 58940212be5150fb9fb3c340f3c7e51f6126372cc6f9Jean-Michel Trivi boolean hasPermissionForPolicy = 58950212be5150fb9fb3c340f3c7e51f6126372cc6f9Jean-Michel Trivi (PackageManager.PERMISSION_GRANTED == mContext.checkCallingPermission( 58960212be5150fb9fb3c340f3c7e51f6126372cc6f9Jean-Michel Trivi android.Manifest.permission.MODIFY_AUDIO_ROUTING)); 58970212be5150fb9fb3c340f3c7e51f6126372cc6f9Jean-Michel Trivi if (!hasPermissionForPolicy) { 58980212be5150fb9fb3c340f3c7e51f6126372cc6f9Jean-Michel Trivi Slog.w(TAG, "Cannot change audio policy ducking handling for pid " + 58990212be5150fb9fb3c340f3c7e51f6126372cc6f9Jean-Michel Trivi + Binder.getCallingPid() + " / uid " 59000212be5150fb9fb3c340f3c7e51f6126372cc6f9Jean-Michel Trivi + Binder.getCallingUid() + ", need MODIFY_AUDIO_ROUTING"); 59010212be5150fb9fb3c340f3c7e51f6126372cc6f9Jean-Michel Trivi return AudioManager.ERROR; 59020212be5150fb9fb3c340f3c7e51f6126372cc6f9Jean-Michel Trivi } 59030212be5150fb9fb3c340f3c7e51f6126372cc6f9Jean-Michel Trivi 59040212be5150fb9fb3c340f3c7e51f6126372cc6f9Jean-Michel Trivi synchronized (mAudioPolicies) { 59050212be5150fb9fb3c340f3c7e51f6126372cc6f9Jean-Michel Trivi if (!mAudioPolicies.containsKey(pcb.asBinder())) { 59060212be5150fb9fb3c340f3c7e51f6126372cc6f9Jean-Michel Trivi Slog.e(TAG, "Cannot change audio policy focus properties, unregistered policy"); 59070212be5150fb9fb3c340f3c7e51f6126372cc6f9Jean-Michel Trivi return AudioManager.ERROR; 59080212be5150fb9fb3c340f3c7e51f6126372cc6f9Jean-Michel Trivi } 59090212be5150fb9fb3c340f3c7e51f6126372cc6f9Jean-Michel Trivi final AudioPolicyProxy app = mAudioPolicies.get(pcb.asBinder()); 59100212be5150fb9fb3c340f3c7e51f6126372cc6f9Jean-Michel Trivi if (duckingBehavior == AudioPolicy.FOCUS_POLICY_DUCKING_IN_POLICY) { 59110212be5150fb9fb3c340f3c7e51f6126372cc6f9Jean-Michel Trivi // is there already one policy managing ducking? 59120212be5150fb9fb3c340f3c7e51f6126372cc6f9Jean-Michel Trivi for(AudioPolicyProxy policy : mAudioPolicies.values()) { 59130212be5150fb9fb3c340f3c7e51f6126372cc6f9Jean-Michel Trivi if (policy.mFocusDuckBehavior == AudioPolicy.FOCUS_POLICY_DUCKING_IN_POLICY) { 59140212be5150fb9fb3c340f3c7e51f6126372cc6f9Jean-Michel Trivi Slog.e(TAG, "Cannot change audio policy ducking behavior, already handled"); 59150212be5150fb9fb3c340f3c7e51f6126372cc6f9Jean-Michel Trivi return AudioManager.ERROR; 59160212be5150fb9fb3c340f3c7e51f6126372cc6f9Jean-Michel Trivi } 59170212be5150fb9fb3c340f3c7e51f6126372cc6f9Jean-Michel Trivi } 59180212be5150fb9fb3c340f3c7e51f6126372cc6f9Jean-Michel Trivi } 59190212be5150fb9fb3c340f3c7e51f6126372cc6f9Jean-Michel Trivi app.mFocusDuckBehavior = duckingBehavior; 59200212be5150fb9fb3c340f3c7e51f6126372cc6f9Jean-Michel Trivi mMediaFocusControl.setDuckingInExtPolicyAvailable( 59210212be5150fb9fb3c340f3c7e51f6126372cc6f9Jean-Michel Trivi duckingBehavior == AudioPolicy.FOCUS_POLICY_DUCKING_IN_POLICY); 59220212be5150fb9fb3c340f3c7e51f6126372cc6f9Jean-Michel Trivi } 59230212be5150fb9fb3c340f3c7e51f6126372cc6f9Jean-Michel Trivi return AudioManager.SUCCESS; 59240212be5150fb9fb3c340f3c7e51f6126372cc6f9Jean-Michel Trivi } 59250212be5150fb9fb3c340f3c7e51f6126372cc6f9Jean-Michel Trivi 59261b3541d5eedb332ea01066b4a78a2d06d5304044Jean-Michel Trivi private void dumpAudioPolicies(PrintWriter pw) { 59271b3541d5eedb332ea01066b4a78a2d06d5304044Jean-Michel Trivi pw.println("\nAudio policies:"); 59281b3541d5eedb332ea01066b4a78a2d06d5304044Jean-Michel Trivi synchronized (mAudioPolicies) { 59291b3541d5eedb332ea01066b4a78a2d06d5304044Jean-Michel Trivi for(AudioPolicyProxy policy : mAudioPolicies.values()) { 59301b3541d5eedb332ea01066b4a78a2d06d5304044Jean-Michel Trivi pw.println(policy.toLogFriendlyString()); 59311b3541d5eedb332ea01066b4a78a2d06d5304044Jean-Michel Trivi } 59321b3541d5eedb332ea01066b4a78a2d06d5304044Jean-Michel Trivi } 59331b3541d5eedb332ea01066b4a78a2d06d5304044Jean-Michel Trivi } 59341b3541d5eedb332ea01066b4a78a2d06d5304044Jean-Michel Trivi 5935958876fe55ea0fdeb73c72240a2f2bab32833443Jean-Michel Trivi //====================== 5936958876fe55ea0fdeb73c72240a2f2bab32833443Jean-Michel Trivi // Audio policy proxy 5937958876fe55ea0fdeb73c72240a2f2bab32833443Jean-Michel Trivi //====================== 59388fdb0d4defb6ee2ca8057d3442ead36b408b6c17Jean-Michel Trivi /** 59391b3541d5eedb332ea01066b4a78a2d06d5304044Jean-Michel Trivi * This internal class inherits from AudioPolicyConfig, each instance contains all the 59401b3541d5eedb332ea01066b4a78a2d06d5304044Jean-Michel Trivi * mixes of an AudioPolicy and their configurations. 59418fdb0d4defb6ee2ca8057d3442ead36b408b6c17Jean-Michel Trivi */ 59428fdb0d4defb6ee2ca8057d3442ead36b408b6c17Jean-Michel Trivi public class AudioPolicyProxy extends AudioPolicyConfig implements IBinder.DeathRecipient { 5943a8b6bd88cfb010c9e9aa1339e504fd593919e1e0Jean-Michel Trivi private static final String TAG = "AudioPolicyProxy"; 5944a8b6bd88cfb010c9e9aa1339e504fd593919e1e0Jean-Michel Trivi AudioPolicyConfig mConfig; 59450212be5150fb9fb3c340f3c7e51f6126372cc6f9Jean-Michel Trivi IAudioPolicyCallback mPolicyToken; 59460212be5150fb9fb3c340f3c7e51f6126372cc6f9Jean-Michel Trivi boolean mHasFocusListener; 59470212be5150fb9fb3c340f3c7e51f6126372cc6f9Jean-Michel Trivi /** 59480212be5150fb9fb3c340f3c7e51f6126372cc6f9Jean-Michel Trivi * Audio focus ducking behavior for an audio policy. 59490212be5150fb9fb3c340f3c7e51f6126372cc6f9Jean-Michel Trivi * This variable reflects the value that was successfully set in 59500212be5150fb9fb3c340f3c7e51f6126372cc6f9Jean-Michel Trivi * {@link AudioService#setFocusPropertiesForPolicy(int, IAudioPolicyCallback)}. This 59510212be5150fb9fb3c340f3c7e51f6126372cc6f9Jean-Michel Trivi * implies that a value of FOCUS_POLICY_DUCKING_IN_POLICY means the corresponding policy 59520212be5150fb9fb3c340f3c7e51f6126372cc6f9Jean-Michel Trivi * is handling ducking for audio focus. 59530212be5150fb9fb3c340f3c7e51f6126372cc6f9Jean-Michel Trivi */ 59540212be5150fb9fb3c340f3c7e51f6126372cc6f9Jean-Michel Trivi int mFocusDuckBehavior = AudioPolicy.FOCUS_POLICY_DUCKING_DEFAULT; 59550212be5150fb9fb3c340f3c7e51f6126372cc6f9Jean-Michel Trivi 59560212be5150fb9fb3c340f3c7e51f6126372cc6f9Jean-Michel Trivi AudioPolicyProxy(AudioPolicyConfig config, IAudioPolicyCallback token, 59570212be5150fb9fb3c340f3c7e51f6126372cc6f9Jean-Michel Trivi boolean hasFocusListener) { 59588fdb0d4defb6ee2ca8057d3442ead36b408b6c17Jean-Michel Trivi super(config); 59591b3541d5eedb332ea01066b4a78a2d06d5304044Jean-Michel Trivi setRegistration(new String(config.hashCode() + ":ap:" + mAudioPolicyCounter++)); 59600212be5150fb9fb3c340f3c7e51f6126372cc6f9Jean-Michel Trivi mPolicyToken = token; 59610212be5150fb9fb3c340f3c7e51f6126372cc6f9Jean-Michel Trivi mHasFocusListener = hasFocusListener; 59620212be5150fb9fb3c340f3c7e51f6126372cc6f9Jean-Michel Trivi if (mHasFocusListener) { 59630212be5150fb9fb3c340f3c7e51f6126372cc6f9Jean-Michel Trivi mMediaFocusControl.addFocusFollower(mPolicyToken); 59640212be5150fb9fb3c340f3c7e51f6126372cc6f9Jean-Michel Trivi } 59657f5eb9fe3c10d8d83ff0e2b0fc60a05c2e6d5b02Eric Laurent connectMixes(); 5966a8b6bd88cfb010c9e9aa1339e504fd593919e1e0Jean-Michel Trivi } 5967a8b6bd88cfb010c9e9aa1339e504fd593919e1e0Jean-Michel Trivi 5968a8b6bd88cfb010c9e9aa1339e504fd593919e1e0Jean-Michel Trivi public void binderDied() { 5969a8b6bd88cfb010c9e9aa1339e504fd593919e1e0Jean-Michel Trivi synchronized (mAudioPolicies) { 59700212be5150fb9fb3c340f3c7e51f6126372cc6f9Jean-Michel Trivi Log.i(TAG, "audio policy " + mPolicyToken + " died"); 59710212be5150fb9fb3c340f3c7e51f6126372cc6f9Jean-Michel Trivi release(); 59720212be5150fb9fb3c340f3c7e51f6126372cc6f9Jean-Michel Trivi mAudioPolicies.remove(mPolicyToken.asBinder()); 59738fdb0d4defb6ee2ca8057d3442ead36b408b6c17Jean-Michel Trivi } 59748fdb0d4defb6ee2ca8057d3442ead36b408b6c17Jean-Michel Trivi } 59758fdb0d4defb6ee2ca8057d3442ead36b408b6c17Jean-Michel Trivi 59760212be5150fb9fb3c340f3c7e51f6126372cc6f9Jean-Michel Trivi String getRegistrationId() { 59771b3541d5eedb332ea01066b4a78a2d06d5304044Jean-Michel Trivi return getRegistration(); 59788fdb0d4defb6ee2ca8057d3442ead36b408b6c17Jean-Michel Trivi } 59798fdb0d4defb6ee2ca8057d3442ead36b408b6c17Jean-Michel Trivi 59800212be5150fb9fb3c340f3c7e51f6126372cc6f9Jean-Michel Trivi void release() { 59810212be5150fb9fb3c340f3c7e51f6126372cc6f9Jean-Michel Trivi if (mFocusDuckBehavior == AudioPolicy.FOCUS_POLICY_DUCKING_IN_POLICY) { 59820212be5150fb9fb3c340f3c7e51f6126372cc6f9Jean-Michel Trivi mMediaFocusControl.setDuckingInExtPolicyAvailable(false); 59830212be5150fb9fb3c340f3c7e51f6126372cc6f9Jean-Michel Trivi } 59840212be5150fb9fb3c340f3c7e51f6126372cc6f9Jean-Michel Trivi if (mHasFocusListener) { 59850212be5150fb9fb3c340f3c7e51f6126372cc6f9Jean-Michel Trivi mMediaFocusControl.removeFocusFollower(mPolicyToken); 59860212be5150fb9fb3c340f3c7e51f6126372cc6f9Jean-Michel Trivi } 59877f5eb9fe3c10d8d83ff0e2b0fc60a05c2e6d5b02Eric Laurent AudioSystem.registerPolicyMixes(mMixes, false); 59888fdb0d4defb6ee2ca8057d3442ead36b408b6c17Jean-Michel Trivi } 59898fdb0d4defb6ee2ca8057d3442ead36b408b6c17Jean-Michel Trivi 59907f5eb9fe3c10d8d83ff0e2b0fc60a05c2e6d5b02Eric Laurent void connectMixes() { 59917f5eb9fe3c10d8d83ff0e2b0fc60a05c2e6d5b02Eric Laurent AudioSystem.registerPolicyMixes(mMixes, true); 5992a8b6bd88cfb010c9e9aa1339e504fd593919e1e0Jean-Michel Trivi } 5993a8b6bd88cfb010c9e9aa1339e504fd593919e1e0Jean-Michel Trivi }; 5994a8b6bd88cfb010c9e9aa1339e504fd593919e1e0Jean-Michel Trivi 5995a8b6bd88cfb010c9e9aa1339e504fd593919e1e0Jean-Michel Trivi private HashMap<IBinder, AudioPolicyProxy> mAudioPolicies = 5996a8b6bd88cfb010c9e9aa1339e504fd593919e1e0Jean-Michel Trivi new HashMap<IBinder, AudioPolicyProxy>(); 59978fdb0d4defb6ee2ca8057d3442ead36b408b6c17Jean-Michel Trivi private int mAudioPolicyCounter = 0; // always accessed synchronized on mAudioPolicies 59989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} 5999