AudioService.java revision eb1d88ddf9a0888455c82b83f19da124e5ca6f16
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; 28f0cff0456258478ba768097f73d4367ab67fd7a3Jean-Michel Triviimport android.app.PendingIntent; 2982aa7f017daaaeb96c13e6e3491d5037ab471085Jaikumar Ganeshimport android.bluetooth.BluetoothA2dp; 3082aa7f017daaaeb96c13e6e3491d5037ab471085Jaikumar Ganeshimport android.bluetooth.BluetoothAdapter; 3182aa7f017daaaeb96c13e6e3491d5037ab471085Jaikumar Ganeshimport android.bluetooth.BluetoothClass; 3282aa7f017daaaeb96c13e6e3491d5037ab471085Jaikumar Ganeshimport android.bluetooth.BluetoothDevice; 3382aa7f017daaaeb96c13e6e3491d5037ab471085Jaikumar Ganeshimport android.bluetooth.BluetoothHeadset; 3482aa7f017daaaeb96c13e6e3491d5037ab471085Jaikumar Ganeshimport android.bluetooth.BluetoothProfile; 35bd022f423a33f0794bb53e5b0720da2d67e4631cNick Pellyimport android.content.BroadcastReceiver; 36d327f21626217aa3c9c0cdb7a84a742c531e59a3Jean-Michel Triviimport android.content.ComponentName; 379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.content.ContentResolver; 389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.content.Context; 399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.content.Intent; 40a553c25b33c99b345cf1c8688f8df0ed8df14e5aEric Laurentimport android.content.IntentFilter; 419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.content.pm.PackageManager; 42f26f01784e1c733c53cad3ed31918e73448ce369Jean-Michel Triviimport android.content.res.Configuration; 43e78fced559d879b2e37b610d0d9a89daf08f0f2bEric Laurentimport android.content.res.Resources; 44e78fced559d879b2e37b610d0d9a89daf08f0f2bEric Laurentimport android.content.res.XmlResourceParser; 45b109615ebebd6f3b9ae789412279f576c3ace46bJason Parekhimport android.database.ContentObserver; 4641d974631c5f525da49c88d34cecedd5a4cfeda8Jungshik Jangimport android.hardware.hdmi.HdmiControlManager; 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; 51a8b6bd88cfb010c9e9aa1339e504fd593919e1e0Jean-Michel Triviimport android.media.audiopolicy.AudioPolicyConfig; 528a2cfc309ab9126e90022916967c65a793c034f0RoboErikimport android.media.session.MediaSessionLegacyHelper; 539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.os.Binder; 54c18c9138cee0f0859bcab636a004ce92ca4a9ab5Eric Laurentimport android.os.Build; 559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.os.Environment; 569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.os.Handler; 579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.os.IBinder; 589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.os.Looper; 599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.os.Message; 60c68022258ebd3dd97a5079ba99f4f3cd12b223b0Jean-Michel Triviimport android.os.PowerManager; 61632ca417f0a33e3fa9ccece531afa2db3f0d4a30Dianne Hackbornimport android.os.RemoteCallbackList; 629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.os.RemoteException; 639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.os.ServiceManager; 6433f4e04e32fac42f158733d6a731e50490fa9951John Spurlockimport android.os.SystemClock; 6582aa7f017daaaeb96c13e6e3491d5037ab471085Jaikumar Ganeshimport android.os.SystemProperties; 665ac72a29593ab9a20337a2225df52bdf4754be02Dianne Hackbornimport android.os.UserHandle; 67bffc3d1bd33eb2d8e00a9f8b6261d815db503311Eric Laurentimport android.os.Vibrator; 689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.provider.Settings; 699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.provider.Settings.System; 709eb45934c582a0bf5060125690de8bce4f10ca76Santos Cordonimport android.telecomm.TelecommManager; 71632ca417f0a33e3fa9ccece531afa2db3f0d4a30Dianne Hackbornimport android.text.TextUtils; 729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.util.Log; 73a8b6bd88cfb010c9e9aa1339e504fd593919e1e0Jean-Michel Triviimport android.util.Slog; 74d327f21626217aa3c9c0cdb7a84a742c531e59a3Jean-Michel Triviimport android.view.KeyEvent; 75bb6f8711a7f804d39c45218db2d6339940cc5d35Jean-Michel Triviimport android.view.Surface; 76bb6f8711a7f804d39c45218db2d6339940cc5d35Jean-Michel Triviimport android.view.WindowManager; 779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport com.android.internal.telephony.ITelephony; 79e78fced559d879b2e37b610d0d9a89daf08f0f2bEric Laurentimport com.android.internal.util.XmlUtils; 80e78fced559d879b2e37b610d0d9a89daf08f0f2bEric Laurent 81e78fced559d879b2e37b610d0d9a89daf08f0f2bEric Laurentimport org.xmlpull.v1.XmlPullParserException; 829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 83d5176cfe6eae954e9cef1e2ec17859a5089e1330Jean-Michel Triviimport java.io.FileDescriptor; 849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport java.io.IOException; 85d5176cfe6eae954e9cef1e2ec17859a5089e1330Jean-Michel Triviimport java.io.PrintWriter; 86e78fced559d879b2e37b610d0d9a89daf08f0f2bEric Laurentimport java.lang.reflect.Field; 879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport java.util.ArrayList; 883172d5e3e7520a745fa37b71fc1c7bf244b57085Eric Laurentimport java.util.concurrent.ConcurrentHashMap; 896f34f5ab8ab1b1db7887e5405d8b0031e105ab05Jungshik Jangimport java.util.Arrays; 90c42ac9d4d03f62c3a1ba197a28a81fda44bd8b7fEric Laurentimport java.util.HashMap; 91c42ac9d4d03f62c3a1ba197a28a81fda44bd8b7fEric Laurentimport java.util.Iterator; 925a1e4cf83f5be1b5d79e2643fa791aa269b6a4bcJaikumar Ganeshimport java.util.List; 93c42ac9d4d03f62c3a1ba197a28a81fda44bd8b7fEric Laurentimport java.util.Map; 9482aa7f017daaaeb96c13e6e3491d5037ab471085Jaikumar Ganeshimport java.util.NoSuchElementException; 95d09bd0c6eb8318e0122b14d7eb5324e481706e41RoboErikimport java.util.Objects; 96c42ac9d4d03f62c3a1ba197a28a81fda44bd8b7fEric Laurentimport java.util.Set; 979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/** 999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * The implementation of the volume manager service. 1009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * <p> 1019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * This implementation focuses on delivering a responsive UI. Most methods are 1029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * asynchronous to external calls. For example, the task of setting a volume 1039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * will update our internal state, but in a separate thread will set the system 1049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * volume and later persist to the database. Similarly, setting the ringer mode 1059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * will update the state and broadcast a change and in a separate thread later 1069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * persist the ringer mode. 1079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 1089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @hide 1099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 110fa9a69805b001034aa04c3b33989a7ac21522371Jean-Michel Trivipublic class AudioService extends IAudioService.Stub { 1119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private static final String TAG = "AudioService"; 1139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 11418e7bce52318f00b5023f33933a571c477f2b61cJean-Michel Trivi /** Debug remote control client/display feature */ 115ae641c9ccd3f81214cee54a5f13804f1765187adJohn Spurlock protected static final boolean DEBUG_RC = Log.isLoggable(TAG + ".RC", Log.DEBUG); 1163114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi /** Debug volumes */ 117ae641c9ccd3f81214cee54a5f13804f1765187adJohn Spurlock protected static final boolean DEBUG_VOL = Log.isLoggable(TAG + ".VOL", Log.DEBUG); 11818e7bce52318f00b5023f33933a571c477f2b61cJean-Michel Trivi 119430fc48865e5a371b08f180390946b96d73848feRoboErik /** debug calls to media session apis */ 120ae641c9ccd3f81214cee54a5f13804f1765187adJohn Spurlock private static final boolean DEBUG_SESSIONS = Log.isLoggable(TAG + ".SESSIONS", Log.DEBUG); 1218a2cfc309ab9126e90022916967c65a793c034f0RoboErik 1228600534df66c2ff5846ed230b50c56229322d48aJohn Spurlock /** Allow volume changes to set ringer mode to silent? */ 1238600534df66c2ff5846ed230b50c56229322d48aJohn Spurlock private static final boolean VOLUME_SETS_RINGER_MODE_SILENT = false; 1248600534df66c2ff5846ed230b50c56229322d48aJohn Spurlock 125a11b4affcad3d255aa723a89b768ea222506f2e8John Spurlock /** In silent mode, are volume adjustments (raises) prevented? */ 126a11b4affcad3d255aa723a89b768ea222506f2e8John Spurlock private static final boolean PREVENT_VOLUME_ADJUSTMENT_IF_SILENT = true; 127a11b4affcad3d255aa723a89b768ea222506f2e8John Spurlock 1289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** How long to delay before persisting a change in volume/ringer mode. */ 12945edba1b8b0377dfe70a4f2b0afb0f04dd8e1ee9RoboErik private static final int PERSIST_DELAY = 500; 1309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1313346a802087f621c6441bc512dfcc17b07143fc6John Spurlock /** 1323346a802087f621c6441bc512dfcc17b07143fc6John Spurlock * The delay before playing a sound. This small period exists so the user 1333346a802087f621c6441bc512dfcc17b07143fc6John Spurlock * can press another key (non-volume keys, too) to have it NOT be audible. 1343346a802087f621c6441bc512dfcc17b07143fc6John Spurlock * <p> 1353346a802087f621c6441bc512dfcc17b07143fc6John Spurlock * PhoneWindow will implement this part. 1363346a802087f621c6441bc512dfcc17b07143fc6John Spurlock */ 1373346a802087f621c6441bc512dfcc17b07143fc6John Spurlock public static final int PLAY_SOUND_DELAY = 300; 1383346a802087f621c6441bc512dfcc17b07143fc6John Spurlock 139a11b4affcad3d255aa723a89b768ea222506f2e8John Spurlock /** 140a11b4affcad3d255aa723a89b768ea222506f2e8John Spurlock * Only used in the result from {@link #checkForRingerModeChange(int, int, int)} 141a11b4affcad3d255aa723a89b768ea222506f2e8John Spurlock */ 142a11b4affcad3d255aa723a89b768ea222506f2e8John Spurlock private static final int FLAG_ADJUST_VOLUME = 1; 143a11b4affcad3d255aa723a89b768ea222506f2e8John Spurlock 144ba50b97cff80e73620a0e3d13cae169e095974a7Dianne Hackborn private final Context mContext; 145ba50b97cff80e73620a0e3d13cae169e095974a7Dianne Hackborn private final ContentResolver mContentResolver; 146ba50b97cff80e73620a0e3d13cae169e095974a7Dianne Hackborn private final AppOpsManager mAppOps; 147ba50b97cff80e73620a0e3d13cae169e095974a7Dianne Hackborn private final boolean mVoiceCapable; 148d5176cfe6eae954e9cef1e2ec17859a5089e1330Jean-Michel Trivi 1493346a802087f621c6441bc512dfcc17b07143fc6John Spurlock /** The controller for the volume UI. */ 1503346a802087f621c6441bc512dfcc17b07143fc6John Spurlock private final VolumeController mVolumeController = new VolumeController(); 1519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // sendMsg() flags 1539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** If the msg is already queued, replace it with this one. */ 1549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private static final int SENDMSG_REPLACE = 0; 1559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** If the msg is already queued, ignore this one and leave the old. */ 1569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private static final int SENDMSG_NOOP = 1; 1579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** If the msg is already queued, queue this one and leave the old. */ 1589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private static final int SENDMSG_QUEUE = 2; 1599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1603114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi // AudioHandler messages 1619bc8358ddaa01c3490f9709991989633a6a3dd42Eric Laurent private static final int MSG_SET_DEVICE_VOLUME = 0; 1629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private static final int MSG_PERSIST_VOLUME = 1; 1635c55a051ad7d86a464fb91426f1ea3c0250e38b3Mike Lockwood private static final int MSG_PERSIST_MASTER_VOLUME = 2; 1649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private static final int MSG_PERSIST_RINGER_MODE = 3; 165bffc3d1bd33eb2d8e00a9f8b6261d815db503311Eric Laurent private static final int MSG_MEDIA_SERVER_DIED = 4; 166dfb881f96af7898151940a4bbc52e45e6043d38bEric Laurent private static final int MSG_PLAY_SOUND_EFFECT = 5; 167dfb881f96af7898151940a4bbc52e45e6043d38bEric Laurent private static final int MSG_BTA2DP_DOCK_TIMEOUT = 6; 168dfb881f96af7898151940a4bbc52e45e6043d38bEric Laurent private static final int MSG_LOAD_SOUND_EFFECTS = 7; 169dfb881f96af7898151940a4bbc52e45e6043d38bEric Laurent private static final int MSG_SET_FORCE_USE = 8; 170dfb881f96af7898151940a4bbc52e45e6043d38bEric Laurent private static final int MSG_BT_HEADSET_CNCT_FAILED = 9; 171dfb881f96af7898151940a4bbc52e45e6043d38bEric Laurent private static final int MSG_SET_ALL_VOLUMES = 10; 172dfb881f96af7898151940a4bbc52e45e6043d38bEric Laurent private static final int MSG_PERSIST_MASTER_VOLUME_MUTE = 11; 173dfb881f96af7898151940a4bbc52e45e6043d38bEric Laurent private static final int MSG_REPORT_NEW_ROUTES = 12; 174dfb881f96af7898151940a4bbc52e45e6043d38bEric Laurent private static final int MSG_SET_FORCE_BT_A2DP_USE = 13; 175dfb881f96af7898151940a4bbc52e45e6043d38bEric Laurent private static final int MSG_CHECK_MUSIC_ACTIVE = 14; 176dfb881f96af7898151940a4bbc52e45e6043d38bEric Laurent private static final int MSG_BROADCAST_AUDIO_BECOMING_NOISY = 15; 177dfb881f96af7898151940a4bbc52e45e6043d38bEric Laurent private static final int MSG_CONFIGURE_SAFE_MEDIA_VOLUME = 16; 178dfb881f96af7898151940a4bbc52e45e6043d38bEric Laurent private static final int MSG_CONFIGURE_SAFE_MEDIA_VOLUME_FORCED = 17; 179dfb881f96af7898151940a4bbc52e45e6043d38bEric Laurent private static final int MSG_PERSIST_SAFE_VOLUME_STATE = 18; 180dfb881f96af7898151940a4bbc52e45e6043d38bEric Laurent private static final int MSG_BROADCAST_BT_CONNECTION_STATE = 19; 181dfb881f96af7898151940a4bbc52e45e6043d38bEric Laurent private static final int MSG_UNLOAD_SOUND_EFFECTS = 20; 1824a5eeb9c727d77bb57fef87a70c8c9cc23dbfee3Eric Laurent private static final int MSG_SYSTEM_READY = 21; 1833114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi // start of messages handled under wakelock 1843114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi // these messages can only be queued, i.e. sent with queueMsgUnderWakeLock(), 185e12c39bb9cedb8b363658979872694eb55b1386eJean-Michel Trivi // and not with sendMsg(..., ..., SENDMSG_QUEUE, ...) 186fa9a69805b001034aa04c3b33989a7ac21522371Jean-Michel Trivi private static final int MSG_SET_WIRED_DEVICE_CONNECTION_STATE = 100; 1870a40ec2192e4836b2fcb6ba51a7688aa6bd4ee98Mike Lockwood private static final int MSG_SET_A2DP_SRC_CONNECTION_STATE = 101; 1880a40ec2192e4836b2fcb6ba51a7688aa6bd4ee98Mike Lockwood private static final int MSG_SET_A2DP_SINK_CONNECTION_STATE = 102; 1893114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi // end of messages handled under wakelock 190afbb047c3945e9c2b7e9bc6b25098d5fb80bba4eEric Laurent 1914c637b9e34f4c8db69a64ad21a4e2bcfa7485b5fJean-Michel Trivi private static final int BTA2DP_DOCK_TIMEOUT_MILLIS = 8000; 192dc03c61fe3cd8d0805480e48a974986439977a60Eric Laurent // Timeout for connection to bluetooth headset service 193dc03c61fe3cd8d0805480e48a974986439977a60Eric Laurent private static final int BT_HEADSET_CNCT_TIMEOUT_MS = 3000; 194dc03c61fe3cd8d0805480e48a974986439977a60Eric Laurent 1959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** @see AudioSystemThread */ 1969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private AudioSystemThread mAudioSystemThread; 1979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** @see AudioHandler */ 1989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private AudioHandler mAudioHandler; 1999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** @see VolumeStreamState */ 2009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private VolumeStreamState[] mStreamStates; 201b109615ebebd6f3b9ae789412279f576c3ace46bJason Parekh private SettingsObserver mSettingsObserver; 202a553c25b33c99b345cf1c8688f8df0ed8df14e5aEric Laurent 203fa9a69805b001034aa04c3b33989a7ac21522371Jean-Michel Trivi private int mMode = AudioSystem.MODE_NORMAL; 204ba195ebc76f23b6679443724ab58c9dc9f2df884Glenn Kasten // protects mRingerMode 205ba195ebc76f23b6679443724ab58c9dc9f2df884Glenn Kasten private final Object mSettingsLock = new Object(); 20645c90cefd13a03b852bb4b8da4be218876cbbb32Eric Laurent 2079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private SoundPool mSoundPool; 20830c918ce7fbe171944b28fc91b3f22b3d631872dGlenn Kasten private final Object mSoundEffectsLock = new Object(); 2099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private static final int NUM_SOUNDPOOL_CHANNELS = 4; 2109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2114767690f09ea3447b8c5c32fb28d27650aa18e00Mike Lockwood // Internally master volume is a float in the 0.0 - 1.0 range, 2124767690f09ea3447b8c5c32fb28d27650aa18e00Mike Lockwood // but to support integer based AudioManager API we translate it to 0 - 100 2134767690f09ea3447b8c5c32fb28d27650aa18e00Mike Lockwood private static final int MAX_MASTER_VOLUME = 100; 2144767690f09ea3447b8c5c32fb28d27650aa18e00Mike Lockwood 2156c798970ccb8759d1e613b57111daa8da0ab44c7Lei Zhang // Maximum volume adjust steps allowed in a single batch call. 2166c798970ccb8759d1e613b57111daa8da0ab44c7Lei Zhang private static final int MAX_BATCH_VOLUME_ADJUST_STEPS = 4; 2176c798970ccb8759d1e613b57111daa8da0ab44c7Lei Zhang 2189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /* Sound effect file names */ 2199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private static final String SOUND_EFFECTS_PATH = "/media/audio/ui/"; 220e78fced559d879b2e37b610d0d9a89daf08f0f2bEric Laurent private static final List<String> SOUND_EFFECT_FILES = new ArrayList<String>(); 2219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /* Sound effect file name mapping sound effect id (AudioManager.FX_xxx) to 2239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * file index in SOUND_EFFECT_FILES[] (first column) and indicating if effect 2249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * uses soundpool (second column) */ 225e78fced559d879b2e37b610d0d9a89daf08f0f2bEric Laurent private final int[][] SOUND_EFFECT_FILES_MAP = new int[AudioManager.NUM_SOUND_EFFECTS][2]; 2269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2275982013cfc8274ff0bafaba83c676b3a8890cba9Jared Suttles /** @hide Maximum volume index values for audio streams */ 228fa9a69805b001034aa04c3b33989a7ac21522371Jean-Michel Trivi private static final int[] MAX_STREAM_VOLUME = new int[] { 2296ee9952bc20be72b9419cb653c9e2e833889a3d3Eric Laurent 5, // STREAM_VOICE_CALL 2306ee9952bc20be72b9419cb653c9e2e833889a3d3Eric Laurent 7, // STREAM_SYSTEM 2316ee9952bc20be72b9419cb653c9e2e833889a3d3Eric Laurent 7, // STREAM_RING 2326ee9952bc20be72b9419cb653c9e2e833889a3d3Eric Laurent 15, // STREAM_MUSIC 2336ee9952bc20be72b9419cb653c9e2e833889a3d3Eric Laurent 7, // STREAM_ALARM 2346ee9952bc20be72b9419cb653c9e2e833889a3d3Eric Laurent 7, // STREAM_NOTIFICATION 2356ee9952bc20be72b9419cb653c9e2e833889a3d3Eric Laurent 15, // STREAM_BLUETOOTH_SCO 2366ee9952bc20be72b9419cb653c9e2e833889a3d3Eric Laurent 7, // STREAM_SYSTEM_ENFORCED 2376ee9952bc20be72b9419cb653c9e2e833889a3d3Eric Laurent 15, // STREAM_DTMF 2386ee9952bc20be72b9419cb653c9e2e833889a3d3Eric Laurent 15 // STREAM_TTS 2395982013cfc8274ff0bafaba83c676b3a8890cba9Jared Suttles }; 2406d5176638c2189595cede38fb92c3e7e8700e221Eric Laurent /* mStreamVolumeAlias[] indicates for each stream if it uses the volume settings 241a553c25b33c99b345cf1c8688f8df0ed8df14e5aEric Laurent * of another stream: This avoids multiplying the volume settings for hidden 242a553c25b33c99b345cf1c8688f8df0ed8df14e5aEric Laurent * stream types that follow other stream behavior for volume settings 2436d5176638c2189595cede38fb92c3e7e8700e221Eric Laurent * NOTE: do not create loops in aliases! 2446d5176638c2189595cede38fb92c3e7e8700e221Eric Laurent * Some streams alias to different streams according to device category (phone or tablet) or 24524e0d9b6c40712a297e4c287435a3b0fdd30e9daEric Laurent * use case (in call vs off call...). See updateStreamVolumeAlias() for more details. 2466d5176638c2189595cede38fb92c3e7e8700e221Eric Laurent * mStreamVolumeAlias contains the default aliases for a voice capable device (phone) and 2476d5176638c2189595cede38fb92c3e7e8700e221Eric Laurent * STREAM_VOLUME_ALIAS_NON_VOICE for a non voice capable device (tablet).*/ 24830c918ce7fbe171944b28fc91b3f22b3d631872dGlenn Kasten private final int[] STREAM_VOLUME_ALIAS = new int[] { 2496d5176638c2189595cede38fb92c3e7e8700e221Eric Laurent AudioSystem.STREAM_VOICE_CALL, // STREAM_VOICE_CALL 2506d5176638c2189595cede38fb92c3e7e8700e221Eric Laurent AudioSystem.STREAM_RING, // STREAM_SYSTEM 2516d5176638c2189595cede38fb92c3e7e8700e221Eric Laurent AudioSystem.STREAM_RING, // STREAM_RING 2526d5176638c2189595cede38fb92c3e7e8700e221Eric Laurent AudioSystem.STREAM_MUSIC, // STREAM_MUSIC 2536d5176638c2189595cede38fb92c3e7e8700e221Eric Laurent AudioSystem.STREAM_ALARM, // STREAM_ALARM 2546d5176638c2189595cede38fb92c3e7e8700e221Eric Laurent AudioSystem.STREAM_RING, // STREAM_NOTIFICATION 2556d5176638c2189595cede38fb92c3e7e8700e221Eric Laurent AudioSystem.STREAM_BLUETOOTH_SCO, // STREAM_BLUETOOTH_SCO 2566d5176638c2189595cede38fb92c3e7e8700e221Eric Laurent AudioSystem.STREAM_RING, // STREAM_SYSTEM_ENFORCED 2576d5176638c2189595cede38fb92c3e7e8700e221Eric Laurent AudioSystem.STREAM_RING, // STREAM_DTMF 2586d5176638c2189595cede38fb92c3e7e8700e221Eric Laurent AudioSystem.STREAM_MUSIC // STREAM_TTS 259a553c25b33c99b345cf1c8688f8df0ed8df14e5aEric Laurent }; 2606d5176638c2189595cede38fb92c3e7e8700e221Eric Laurent private final int[] STREAM_VOLUME_ALIAS_NON_VOICE = new int[] { 2616d5176638c2189595cede38fb92c3e7e8700e221Eric Laurent AudioSystem.STREAM_VOICE_CALL, // STREAM_VOICE_CALL 2626d5176638c2189595cede38fb92c3e7e8700e221Eric Laurent AudioSystem.STREAM_MUSIC, // STREAM_SYSTEM 2636d5176638c2189595cede38fb92c3e7e8700e221Eric Laurent AudioSystem.STREAM_RING, // STREAM_RING 2646d5176638c2189595cede38fb92c3e7e8700e221Eric Laurent AudioSystem.STREAM_MUSIC, // STREAM_MUSIC 2656d5176638c2189595cede38fb92c3e7e8700e221Eric Laurent AudioSystem.STREAM_ALARM, // STREAM_ALARM 2666d5176638c2189595cede38fb92c3e7e8700e221Eric Laurent AudioSystem.STREAM_RING, // STREAM_NOTIFICATION 2676d5176638c2189595cede38fb92c3e7e8700e221Eric Laurent AudioSystem.STREAM_BLUETOOTH_SCO, // STREAM_BLUETOOTH_SCO 2686d5176638c2189595cede38fb92c3e7e8700e221Eric Laurent AudioSystem.STREAM_MUSIC, // STREAM_SYSTEM_ENFORCED 2696d5176638c2189595cede38fb92c3e7e8700e221Eric Laurent AudioSystem.STREAM_MUSIC, // STREAM_DTMF 2706d5176638c2189595cede38fb92c3e7e8700e221Eric Laurent AudioSystem.STREAM_MUSIC // STREAM_TTS 2716d5176638c2189595cede38fb92c3e7e8700e221Eric Laurent }; 2726d5176638c2189595cede38fb92c3e7e8700e221Eric Laurent private int[] mStreamVolumeAlias; 273a553c25b33c99b345cf1c8688f8df0ed8df14e5aEric Laurent 274ba50b97cff80e73620a0e3d13cae169e095974a7Dianne Hackborn /** 275ba50b97cff80e73620a0e3d13cae169e095974a7Dianne Hackborn * Map AudioSystem.STREAM_* constants to app ops. This should be used 276ba50b97cff80e73620a0e3d13cae169e095974a7Dianne Hackborn * after mapping through mStreamVolumeAlias. 277ba50b97cff80e73620a0e3d13cae169e095974a7Dianne Hackborn */ 278ba50b97cff80e73620a0e3d13cae169e095974a7Dianne Hackborn private static final int[] STEAM_VOLUME_OPS = new int[] { 279ba50b97cff80e73620a0e3d13cae169e095974a7Dianne Hackborn AppOpsManager.OP_AUDIO_VOICE_VOLUME, // STREAM_VOICE_CALL 280ba50b97cff80e73620a0e3d13cae169e095974a7Dianne Hackborn AppOpsManager.OP_AUDIO_MEDIA_VOLUME, // STREAM_SYSTEM 281ba50b97cff80e73620a0e3d13cae169e095974a7Dianne Hackborn AppOpsManager.OP_AUDIO_RING_VOLUME, // STREAM_RING 282ba50b97cff80e73620a0e3d13cae169e095974a7Dianne Hackborn AppOpsManager.OP_AUDIO_MEDIA_VOLUME, // STREAM_MUSIC 283ba50b97cff80e73620a0e3d13cae169e095974a7Dianne Hackborn AppOpsManager.OP_AUDIO_ALARM_VOLUME, // STREAM_ALARM 284ba50b97cff80e73620a0e3d13cae169e095974a7Dianne Hackborn AppOpsManager.OP_AUDIO_NOTIFICATION_VOLUME, // STREAM_NOTIFICATION 285ba50b97cff80e73620a0e3d13cae169e095974a7Dianne Hackborn AppOpsManager.OP_AUDIO_BLUETOOTH_VOLUME, // STREAM_BLUETOOTH_SCO 286ba50b97cff80e73620a0e3d13cae169e095974a7Dianne Hackborn AppOpsManager.OP_AUDIO_MEDIA_VOLUME, // STREAM_SYSTEM_ENFORCED 287ba50b97cff80e73620a0e3d13cae169e095974a7Dianne Hackborn AppOpsManager.OP_AUDIO_MEDIA_VOLUME, // STREAM_DTMF 288ba50b97cff80e73620a0e3d13cae169e095974a7Dianne Hackborn AppOpsManager.OP_AUDIO_MEDIA_VOLUME, // STREAM_TTS 289ba50b97cff80e73620a0e3d13cae169e095974a7Dianne Hackborn }; 290ba50b97cff80e73620a0e3d13cae169e095974a7Dianne Hackborn 29183a017b6b7c099d1a0293e5839be6477325aef06Eric Laurent private final boolean mUseFixedVolume; 29283a017b6b7c099d1a0293e5839be6477325aef06Eric Laurent 293bffc3d1bd33eb2d8e00a9f8b6261d815db503311Eric Laurent // stream names used by dumpStreamStates() 2941af30c7ac480e5d335f267a3ac3b2e6c748ce240John Spurlock private static final String[] STREAM_NAMES = new String[] { 295bffc3d1bd33eb2d8e00a9f8b6261d815db503311Eric Laurent "STREAM_VOICE_CALL", 296bffc3d1bd33eb2d8e00a9f8b6261d815db503311Eric Laurent "STREAM_SYSTEM", 297bffc3d1bd33eb2d8e00a9f8b6261d815db503311Eric Laurent "STREAM_RING", 298bffc3d1bd33eb2d8e00a9f8b6261d815db503311Eric Laurent "STREAM_MUSIC", 299bffc3d1bd33eb2d8e00a9f8b6261d815db503311Eric Laurent "STREAM_ALARM", 300bffc3d1bd33eb2d8e00a9f8b6261d815db503311Eric Laurent "STREAM_NOTIFICATION", 301bffc3d1bd33eb2d8e00a9f8b6261d815db503311Eric Laurent "STREAM_BLUETOOTH_SCO", 302bffc3d1bd33eb2d8e00a9f8b6261d815db503311Eric Laurent "STREAM_SYSTEM_ENFORCED", 303bffc3d1bd33eb2d8e00a9f8b6261d815db503311Eric Laurent "STREAM_DTMF", 304bffc3d1bd33eb2d8e00a9f8b6261d815db503311Eric Laurent "STREAM_TTS" 305bffc3d1bd33eb2d8e00a9f8b6261d815db503311Eric Laurent }; 306bffc3d1bd33eb2d8e00a9f8b6261d815db503311Eric Laurent 30730c918ce7fbe171944b28fc91b3f22b3d631872dGlenn Kasten private final AudioSystem.ErrorCallback mAudioSystemCallback = new AudioSystem.ErrorCallback() { 3089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public void onError(int error) { 3099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project switch (error) { 3109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project case AudioSystem.AUDIO_STATUS_SERVER_DIED: 311dfb881f96af7898151940a4bbc52e45e6043d38bEric Laurent sendMsg(mAudioHandler, MSG_MEDIA_SERVER_DIED, 312dfb881f96af7898151940a4bbc52e45e6043d38bEric Laurent SENDMSG_NOOP, 0, 0, null, 0); 3139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project break; 3149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project default: 3159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project break; 3169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 317dfb881f96af7898151940a4bbc52e45e6043d38bEric Laurent } 3189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project }; 3199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 3219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Current ringer mode from one of {@link AudioManager#RINGER_MODE_NORMAL}, 3229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * {@link AudioManager#RINGER_MODE_SILENT}, or 3239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * {@link AudioManager#RINGER_MODE_VIBRATE}. 3249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 325ba195ebc76f23b6679443724ab58c9dc9f2df884Glenn Kasten // protected by mSettingsLock 3269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private int mRingerMode; 3279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3289bcf401d13d47416043a704430388abd59aef7cdEric Laurent /** @see System#MODE_RINGER_STREAMS_AFFECTED */ 32924e0d9b6c40712a297e4c287435a3b0fdd30e9daEric Laurent private int mRingerModeAffectedStreams = 0; 3309bcf401d13d47416043a704430388abd59aef7cdEric Laurent 3315b4e654d0c7de8e4d58d73e73b0d5220f19b68f7Eric Laurent // Streams currently muted by ringer mode 3325b4e654d0c7de8e4d58d73e73b0d5220f19b68f7Eric Laurent private int mRingerModeMutedStreams; 3335b4e654d0c7de8e4d58d73e73b0d5220f19b68f7Eric Laurent 3349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** @see System#MUTE_STREAMS_AFFECTED */ 3359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private int mMuteAffectedStreams; 3369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 338bffc3d1bd33eb2d8e00a9f8b6261d815db503311Eric Laurent * NOTE: setVibrateSetting(), getVibrateSetting(), shouldVibrate() are deprecated. 339bffc3d1bd33eb2d8e00a9f8b6261d815db503311Eric Laurent * mVibrateSetting is just maintained during deprecation period but vibration policy is 340bffc3d1bd33eb2d8e00a9f8b6261d815db503311Eric Laurent * now only controlled by mHasVibrator and mRingerMode 3419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 3429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private int mVibrateSetting; 3439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 344bffc3d1bd33eb2d8e00a9f8b6261d815db503311Eric Laurent // Is there a vibrator 345bffc3d1bd33eb2d8e00a9f8b6261d815db503311Eric Laurent private final boolean mHasVibrator; 346bffc3d1bd33eb2d8e00a9f8b6261d815db503311Eric Laurent 347a553c25b33c99b345cf1c8688f8df0ed8df14e5aEric Laurent // Broadcast receiver for device connections intent broadcasts 348a553c25b33c99b345cf1c8688f8df0ed8df14e5aEric Laurent private final BroadcastReceiver mReceiver = new AudioServiceBroadcastReceiver(); 349a553c25b33c99b345cf1c8688f8df0ed8df14e5aEric Laurent 350c42ac9d4d03f62c3a1ba197a28a81fda44bd8b7fEric Laurent // Devices currently connected 35130c918ce7fbe171944b28fc91b3f22b3d631872dGlenn Kasten private final HashMap <Integer, String> mConnectedDevices = new HashMap <Integer, String>(); 352c42ac9d4d03f62c3a1ba197a28a81fda44bd8b7fEric Laurent 353c42ac9d4d03f62c3a1ba197a28a81fda44bd8b7fEric Laurent // Forced device usage for communications 354c42ac9d4d03f62c3a1ba197a28a81fda44bd8b7fEric Laurent private int mForcedUseForComm; 355c42ac9d4d03f62c3a1ba197a28a81fda44bd8b7fEric Laurent 3560dc37cce9d564ae43883c8dc8672b9266b881e63Mike Lockwood // True if we have master volume support 3570dc37cce9d564ae43883c8dc8672b9266b881e63Mike Lockwood private final boolean mUseMasterVolume; 3580dc37cce9d564ae43883c8dc8672b9266b881e63Mike Lockwood 3599760647dd0ee67e7c20f3e9d661d2006b1df0b54Mike Lockwood private final int[] mMasterVolumeRamp; 3609760647dd0ee67e7c20f3e9d661d2006b1df0b54Mike Lockwood 3619272b4b4a44fe1f33e3030810618194f817caaecEric Laurent // List of binder death handlers for setMode() client processes. 3629272b4b4a44fe1f33e3030810618194f817caaecEric Laurent // The last process to have called setMode() is at the top of the list. 36330c918ce7fbe171944b28fc91b3f22b3d631872dGlenn Kasten private final ArrayList <SetModeDeathHandler> mSetModeDeathHandlers = new ArrayList <SetModeDeathHandler>(); 364eb14a783be073b5fd6e8c8c9bc87d2d1919f2c9eEric Laurent 3653def1eec2baed0b8845ec32c871e249dc533a9d9Eric Laurent // List of clients having issued a SCO start request 36630c918ce7fbe171944b28fc91b3f22b3d631872dGlenn Kasten private final ArrayList <ScoClient> mScoClients = new ArrayList <ScoClient>(); 3673def1eec2baed0b8845ec32c871e249dc533a9d9Eric Laurent 3683def1eec2baed0b8845ec32c871e249dc533a9d9Eric Laurent // BluetoothHeadset API to control SCO connection 3693def1eec2baed0b8845ec32c871e249dc533a9d9Eric Laurent private BluetoothHeadset mBluetoothHeadset; 3703def1eec2baed0b8845ec32c871e249dc533a9d9Eric Laurent 37182aa7f017daaaeb96c13e6e3491d5037ab471085Jaikumar Ganesh // Bluetooth headset device 37282aa7f017daaaeb96c13e6e3491d5037ab471085Jaikumar Ganesh private BluetoothDevice mBluetoothHeadsetDevice; 3733def1eec2baed0b8845ec32c871e249dc533a9d9Eric Laurent 37462ef767b15a712bab31cc0d5508a330906f535c2Eric Laurent // Indicate if SCO audio connection is currently active and if the initiator is 37562ef767b15a712bab31cc0d5508a330906f535c2Eric Laurent // audio service (internal) or bluetooth headset (external) 37662ef767b15a712bab31cc0d5508a330906f535c2Eric Laurent private int mScoAudioState; 37762ef767b15a712bab31cc0d5508a330906f535c2Eric Laurent // SCO audio state is not active 37862ef767b15a712bab31cc0d5508a330906f535c2Eric Laurent private static final int SCO_STATE_INACTIVE = 0; 379dc03c61fe3cd8d0805480e48a974986439977a60Eric Laurent // SCO audio activation request waiting for headset service to connect 380dc03c61fe3cd8d0805480e48a974986439977a60Eric Laurent private static final int SCO_STATE_ACTIVATE_REQ = 1; 38125fc29b3691a1d2a84164988dc74b2e7d301868eEric Laurent // SCO audio state is active or starting due to a request from AudioManager API 382dc03c61fe3cd8d0805480e48a974986439977a60Eric Laurent private static final int SCO_STATE_ACTIVE_INTERNAL = 3; 383dc03c61fe3cd8d0805480e48a974986439977a60Eric Laurent // SCO audio deactivation request waiting for headset service to connect 384dc03c61fe3cd8d0805480e48a974986439977a60Eric Laurent private static final int SCO_STATE_DEACTIVATE_REQ = 5; 385dc03c61fe3cd8d0805480e48a974986439977a60Eric Laurent 38662ef767b15a712bab31cc0d5508a330906f535c2Eric Laurent // SCO audio state is active due to an action in BT handsfree (either voice recognition or 38762ef767b15a712bab31cc0d5508a330906f535c2Eric Laurent // in call audio) 38862ef767b15a712bab31cc0d5508a330906f535c2Eric Laurent private static final int SCO_STATE_ACTIVE_EXTERNAL = 2; 389dc03c61fe3cd8d0805480e48a974986439977a60Eric Laurent // Deactivation request for all SCO connections (initiated by audio mode change) 390dc03c61fe3cd8d0805480e48a974986439977a60Eric Laurent // waiting for headset service to connect 391dc03c61fe3cd8d0805480e48a974986439977a60Eric Laurent private static final int SCO_STATE_DEACTIVATE_EXT_REQ = 4; 392dc03c61fe3cd8d0805480e48a974986439977a60Eric Laurent 393c18c9138cee0f0859bcab636a004ce92ca4a9ab5Eric Laurent // Indicates the mode used for SCO audio connection. The mode is virtual call if the request 394c18c9138cee0f0859bcab636a004ce92ca4a9ab5Eric Laurent // originated from an app targeting an API version before JB MR2 and raw audio after that. 395c18c9138cee0f0859bcab636a004ce92ca4a9ab5Eric Laurent private int mScoAudioMode; 396f4e51d82d2e34e6832903f01eaecc15ded6c3241Liejun Tao // SCO audio mode is undefined 397f4e51d82d2e34e6832903f01eaecc15ded6c3241Liejun Tao private static final int SCO_MODE_UNDEFINED = -1; 398c18c9138cee0f0859bcab636a004ce92ca4a9ab5Eric Laurent // SCO audio mode is virtual voice call (BluetoothHeadset.startScoUsingVirtualVoiceCall()) 399c18c9138cee0f0859bcab636a004ce92ca4a9ab5Eric Laurent private static final int SCO_MODE_VIRTUAL_CALL = 0; 400c18c9138cee0f0859bcab636a004ce92ca4a9ab5Eric Laurent // SCO audio mode is raw audio (BluetoothHeadset.connectAudio()) 401c18c9138cee0f0859bcab636a004ce92ca4a9ab5Eric Laurent private static final int SCO_MODE_RAW = 1; 402f4e51d82d2e34e6832903f01eaecc15ded6c3241Liejun Tao // SCO audio mode is Voice Recognition (BluetoothHeadset.startVoiceRecognition()) 403f4e51d82d2e34e6832903f01eaecc15ded6c3241Liejun Tao private static final int SCO_MODE_VR = 2; 404f4e51d82d2e34e6832903f01eaecc15ded6c3241Liejun Tao 405f4e51d82d2e34e6832903f01eaecc15ded6c3241Liejun Tao private static final int SCO_MODE_MAX = 2; 406c18c9138cee0f0859bcab636a004ce92ca4a9ab5Eric Laurent 407dc03c61fe3cd8d0805480e48a974986439977a60Eric Laurent // Current connection state indicated by bluetooth headset 408dc03c61fe3cd8d0805480e48a974986439977a60Eric Laurent private int mScoConnectionState; 40962ef767b15a712bab31cc0d5508a330906f535c2Eric Laurent 410a60e212d0dda7d2a748180ce77405f2463c9cf53Eric Laurent // true if boot sequence has been completed 4114a5eeb9c727d77bb57fef87a70c8c9cc23dbfee3Eric Laurent private boolean mSystemReady; 412a60e212d0dda7d2a748180ce77405f2463c9cf53Eric Laurent // listener for SoundPool sample load completion indication 413a60e212d0dda7d2a748180ce77405f2463c9cf53Eric Laurent private SoundPoolCallback mSoundPoolCallBack; 414a60e212d0dda7d2a748180ce77405f2463c9cf53Eric Laurent // thread for SoundPool listener 415a60e212d0dda7d2a748180ce77405f2463c9cf53Eric Laurent private SoundPoolListenerThread mSoundPoolListenerThread; 416a60e212d0dda7d2a748180ce77405f2463c9cf53Eric Laurent // message looper for SoundPool listener 417a60e212d0dda7d2a748180ce77405f2463c9cf53Eric Laurent private Looper mSoundPoolLooper = null; 418c55b393efd462490cd5e27fc373bceafdd25662eJean-Michel Trivi // volume applied to sound played with playSoundEffect() 419f2b0c11f4e797e183131261724d8de310dac5431Jean-Michel Trivi private static int sSoundEffectVolumeDb; 4209903e2638a6c502d96413680d3ebae4fb77fc412Eric Laurent // getActiveStreamType() will return: 4219903e2638a6c502d96413680d3ebae4fb77fc412Eric Laurent // - STREAM_NOTIFICATION on tablets during this period after a notification stopped 4229903e2638a6c502d96413680d3ebae4fb77fc412Eric Laurent // - STREAM_MUSIC on phones during this period after music or talkback/voice search prompt 42325101b0b9a84571ead15b26e9f4cd9c4298d7823Eric Laurent // stopped 4249903e2638a6c502d96413680d3ebae4fb77fc412Eric Laurent private static final int DEFAULT_STREAM_TYPE_OVERRIDE_DELAY_MS = 5000; 42525101b0b9a84571ead15b26e9f4cd9c4298d7823Eric Laurent // previous volume adjustment direction received by checkForRingerModeChange() 42625101b0b9a84571ead15b26e9f4cd9c4298d7823Eric Laurent private int mPrevVolDirection = AudioManager.ADJUST_SAME; 4276243edd818b84adfbe712d5d233d6414b33653acAmith Yamasani // Keyguard manager proxy 4286243edd818b84adfbe712d5d233d6414b33653acAmith Yamasani private KeyguardManager mKeyguardManager; 42945c90cefd13a03b852bb4b8da4be218876cbbb32Eric Laurent // mVolumeControlStream is set by VolumePanel to temporarily force the stream type which volume 43045c90cefd13a03b852bb4b8da4be218876cbbb32Eric Laurent // is controlled by Vol keys. 43145c90cefd13a03b852bb4b8da4be218876cbbb32Eric Laurent private int mVolumeControlStream = -1; 43245c90cefd13a03b852bb4b8da4be218876cbbb32Eric Laurent private final Object mForceControlStreamLock = new Object(); 43345c90cefd13a03b852bb4b8da4be218876cbbb32Eric Laurent // VolumePanel is currently the only client of forceVolumeControlStream() and runs in system 43445c90cefd13a03b852bb4b8da4be218876cbbb32Eric Laurent // server process so in theory it is not necessary to monitor the client death. 43545c90cefd13a03b852bb4b8da4be218876cbbb32Eric Laurent // However it is good to be ready for future evolutions. 43645c90cefd13a03b852bb4b8da4be218876cbbb32Eric Laurent private ForceControlStreamClient mForceControlStreamClient = null; 437098d580cc2bb6c0891c756a4e5230c6c6b0d2376Jeff Sharkey // Used to play ringtones outside system_server 438098d580cc2bb6c0891c756a4e5230c6c6b0d2376Jeff Sharkey private volatile IRingtonePlayer mRingtonePlayer; 4399bc8358ddaa01c3490f9709991989633a6a3dd42Eric Laurent 440f26f01784e1c733c53cad3ed31918e73448ce369Jean-Michel Trivi private int mDeviceOrientation = Configuration.ORIENTATION_UNDEFINED; 441bb6f8711a7f804d39c45218db2d6339940cc5d35Jean-Michel Trivi private int mDeviceRotation = Surface.ROTATION_0; 442f26f01784e1c733c53cad3ed31918e73448ce369Jean-Michel Trivi 4437847211fb4699bf6018e29d214a918ed6657319bEric Laurent // Request to override default use of A2DP for media. 4447847211fb4699bf6018e29d214a918ed6657319bEric Laurent private boolean mBluetoothA2dpEnabled; 4457847211fb4699bf6018e29d214a918ed6657319bEric Laurent private final Object mBluetoothA2dpEnabledLock = new Object(); 4467847211fb4699bf6018e29d214a918ed6657319bEric Laurent 447632ca417f0a33e3fa9ccece531afa2db3f0d4a30Dianne Hackborn // Monitoring of audio routes. Protected by mCurAudioRoutes. 448632ca417f0a33e3fa9ccece531afa2db3f0d4a30Dianne Hackborn final AudioRoutesInfo mCurAudioRoutes = new AudioRoutesInfo(); 449632ca417f0a33e3fa9ccece531afa2db3f0d4a30Dianne Hackborn final RemoteCallbackList<IAudioRoutesObserver> mRoutesObservers 450632ca417f0a33e3fa9ccece531afa2db3f0d4a30Dianne Hackborn = new RemoteCallbackList<IAudioRoutesObserver>(); 451632ca417f0a33e3fa9ccece531afa2db3f0d4a30Dianne Hackborn 4523114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi /** 4533114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi * A fake stream type to match the notion of remote media playback 4543114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi */ 4553114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi public final static int STREAM_REMOTE_MUSIC = -200; 4563114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi 4574bbcc6549738f3d69831b2bd9eb4accec3e9920eEric Laurent // Devices for which the volume is fixed and VolumePanel slider should be disabled 458948d32748caaac5be06c991ebf00f74265a7849fEric Laurent final int mFixedVolumeDevices = AudioSystem.DEVICE_OUT_HDMI | 4594bbcc6549738f3d69831b2bd9eb4accec3e9920eEric Laurent AudioSystem.DEVICE_OUT_DGTL_DOCK_HEADSET | 460fb917e019f04d60f4924114fe2684c0d67981af6Paul McLean AudioSystem.DEVICE_OUT_ANLG_DOCK_HEADSET; 4614bbcc6549738f3d69831b2bd9eb4accec3e9920eEric Laurent 462bb6f8711a7f804d39c45218db2d6339940cc5d35Jean-Michel Trivi // TODO merge orientation and rotation 463d640bd325c3be9a350058c835b880a7e0b40dc60Eric Laurent private final boolean mMonitorOrientation; 464bb6f8711a7f804d39c45218db2d6339940cc5d35Jean-Michel Trivi private final boolean mMonitorRotation; 465d640bd325c3be9a350058c835b880a7e0b40dc60Eric Laurent 4667ee1e4ff7346a278a6722108fbc1869240b3e866Eric Laurent private boolean mDockAudioMediaEnabled = true; 4677ee1e4ff7346a278a6722108fbc1869240b3e866Eric Laurent 46808ed1b9d2099ec8231b21353b33b901492ea9885Eric Laurent private int mDockState = Intent.EXTRA_DOCK_STATE_UNDOCKED; 46908ed1b9d2099ec8231b21353b33b901492ea9885Eric Laurent 470fde16d5879ea88a971004c984093409468b6139cEric Laurent // Used when safe volume warning message display is requested by setStreamVolume(). In this 471fde16d5879ea88a971004c984093409468b6139cEric Laurent // case, the new requested volume, stream type and device are stored in mPendingVolumeCommand 472fde16d5879ea88a971004c984093409468b6139cEric Laurent // and used later when/if disableSafeMediaVolume() is called. 473fde16d5879ea88a971004c984093409468b6139cEric Laurent private StreamVolumeCommand mPendingVolumeCommand; 474fde16d5879ea88a971004c984093409468b6139cEric Laurent 475fa9a69805b001034aa04c3b33989a7ac21522371Jean-Michel Trivi private PowerManager.WakeLock mAudioEventWakeLock; 476fa9a69805b001034aa04c3b33989a7ac21522371Jean-Michel Trivi 477fa9a69805b001034aa04c3b33989a7ac21522371Jean-Michel Trivi private final MediaFocusControl mMediaFocusControl; 478fa9a69805b001034aa04c3b33989a7ac21522371Jean-Michel Trivi 4795a0cf7a27f3953a1266af48543ccd9024f4cd89fJohn Du // Reference to BluetoothA2dp to query for AbsoluteVolume. 4805a0cf7a27f3953a1266af48543ccd9024f4cd89fJohn Du private BluetoothA2dp mA2dp; 4815a0cf7a27f3953a1266af48543ccd9024f4cd89fJohn Du private final Object mA2dpAvrcpLock = new Object(); 4825a0cf7a27f3953a1266af48543ccd9024f4cd89fJohn Du // If absolute volume is supported in AVRCP device 4835a0cf7a27f3953a1266af48543ccd9024f4cd89fJohn Du private boolean mAvrcpAbsVolSupported = false; 4845a0cf7a27f3953a1266af48543ccd9024f4cd89fJohn Du 4859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /////////////////////////////////////////////////////////////////////////// 4869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Construction 4879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /////////////////////////////////////////////////////////////////////////// 4889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 4899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** @hide */ 4909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public AudioService(Context context) { 4919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mContext = context; 4929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mContentResolver = context.getContentResolver(); 493ba50b97cff80e73620a0e3d13cae169e095974a7Dianne Hackborn mAppOps = (AppOpsManager)context.getSystemService(Context.APP_OPS_SERVICE); 494c7fcba4b7bd3d78e7cfe975a3f8e4dde2f6738b7Joe Onorato mVoiceCapable = mContext.getResources().getBoolean( 495c7fcba4b7bd3d78e7cfe975a3f8e4dde2f6738b7Joe Onorato com.android.internal.R.bool.config_voice_capable); 4965982013cfc8274ff0bafaba83c676b3a8890cba9Jared Suttles 497c68022258ebd3dd97a5079ba99f4f3cd12b223b0Jean-Michel Trivi PowerManager pm = (PowerManager)context.getSystemService(Context.POWER_SERVICE); 498fa9a69805b001034aa04c3b33989a7ac21522371Jean-Michel Trivi mAudioEventWakeLock = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "handleAudioEvent"); 499c68022258ebd3dd97a5079ba99f4f3cd12b223b0Jean-Michel Trivi 500bffc3d1bd33eb2d8e00a9f8b6261d815db503311Eric Laurent Vibrator vibrator = (Vibrator) context.getSystemService(Context.VIBRATOR_SERVICE); 501bffc3d1bd33eb2d8e00a9f8b6261d815db503311Eric Laurent mHasVibrator = vibrator == null ? false : vibrator.hasVibrator(); 502bffc3d1bd33eb2d8e00a9f8b6261d815db503311Eric Laurent 5035982013cfc8274ff0bafaba83c676b3a8890cba9Jared Suttles // Intialized volume 5045982013cfc8274ff0bafaba83c676b3a8890cba9Jared Suttles MAX_STREAM_VOLUME[AudioSystem.STREAM_VOICE_CALL] = SystemProperties.getInt( 5055982013cfc8274ff0bafaba83c676b3a8890cba9Jared Suttles "ro.config.vc_call_vol_steps", 5065982013cfc8274ff0bafaba83c676b3a8890cba9Jared Suttles MAX_STREAM_VOLUME[AudioSystem.STREAM_VOICE_CALL]); 5075982013cfc8274ff0bafaba83c676b3a8890cba9Jared Suttles 508f2b0c11f4e797e183131261724d8de310dac5431Jean-Michel Trivi sSoundEffectVolumeDb = context.getResources().getInteger( 509c55b393efd462490cd5e27fc373bceafdd25662eJean-Michel Trivi com.android.internal.R.integer.config_soundEffectVolumeDb); 51025101b0b9a84571ead15b26e9f4cd9c4298d7823Eric Laurent 511c42ac9d4d03f62c3a1ba197a28a81fda44bd8b7fEric Laurent mForcedUseForComm = AudioSystem.FORCE_NONE; 512dd45d01128423a82652a3c9d77fa393631d95229Eric Laurent 5139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project createAudioSystemThread(); 514dd45d01128423a82652a3c9d77fa393631d95229Eric Laurent 515fa9a69805b001034aa04c3b33989a7ac21522371Jean-Michel Trivi mMediaFocusControl = new MediaFocusControl(mAudioHandler.getLooper(), 5163346a802087f621c6441bc512dfcc17b07143fc6John Spurlock mContext, mVolumeController, this); 517fa9a69805b001034aa04c3b33989a7ac21522371Jean-Michel Trivi 518dfb881f96af7898151940a4bbc52e45e6043d38bEric Laurent AudioSystem.setErrorCallback(mAudioSystemCallback); 519dfb881f96af7898151940a4bbc52e45e6043d38bEric Laurent 520dd45d01128423a82652a3c9d77fa393631d95229Eric Laurent boolean cameraSoundForced = mContext.getResources().getBoolean( 521dd45d01128423a82652a3c9d77fa393631d95229Eric Laurent com.android.internal.R.bool.config_camera_sound_forced); 522dd45d01128423a82652a3c9d77fa393631d95229Eric Laurent mCameraSoundForced = new Boolean(cameraSoundForced); 523dd45d01128423a82652a3c9d77fa393631d95229Eric Laurent sendMsg(mAudioHandler, 524dd45d01128423a82652a3c9d77fa393631d95229Eric Laurent MSG_SET_FORCE_USE, 525dd45d01128423a82652a3c9d77fa393631d95229Eric Laurent SENDMSG_QUEUE, 526dd45d01128423a82652a3c9d77fa393631d95229Eric Laurent AudioSystem.FOR_SYSTEM, 527dd45d01128423a82652a3c9d77fa393631d95229Eric Laurent cameraSoundForced ? 528dd45d01128423a82652a3c9d77fa393631d95229Eric Laurent AudioSystem.FORCE_SYSTEM_ENFORCED : AudioSystem.FORCE_NONE, 529dd45d01128423a82652a3c9d77fa393631d95229Eric Laurent null, 530dd45d01128423a82652a3c9d77fa393631d95229Eric Laurent 0); 531dd45d01128423a82652a3c9d77fa393631d95229Eric Laurent 53205274f348e12983eb8613cc6eb9ae561e8197e28Eric Laurent mSafeMediaVolumeState = new Integer(Settings.Global.getInt(mContentResolver, 53305274f348e12983eb8613cc6eb9ae561e8197e28Eric Laurent Settings.Global.AUDIO_SAFE_VOLUME_STATE, 53405274f348e12983eb8613cc6eb9ae561e8197e28Eric Laurent SAFE_MEDIA_VOLUME_NOT_CONFIGURED)); 53505274f348e12983eb8613cc6eb9ae561e8197e28Eric Laurent // The default safe volume index read here will be replaced by the actual value when 53605274f348e12983eb8613cc6eb9ae561e8197e28Eric Laurent // the mcc is read by onConfigureSafeVolume() 53705274f348e12983eb8613cc6eb9ae561e8197e28Eric Laurent mSafeMediaVolumeIndex = mContext.getResources().getInteger( 53805274f348e12983eb8613cc6eb9ae561e8197e28Eric Laurent com.android.internal.R.integer.config_safe_media_volume_index) * 10; 53905274f348e12983eb8613cc6eb9ae561e8197e28Eric Laurent 54083a017b6b7c099d1a0293e5839be6477325aef06Eric Laurent mUseFixedVolume = mContext.getResources().getBoolean( 54183a017b6b7c099d1a0293e5839be6477325aef06Eric Laurent com.android.internal.R.bool.config_useFixedVolume); 54283a017b6b7c099d1a0293e5839be6477325aef06Eric Laurent 54324e0d9b6c40712a297e4c287435a3b0fdd30e9daEric Laurent // must be called before readPersistedSettings() which needs a valid mStreamVolumeAlias[] 54424e0d9b6c40712a297e4c287435a3b0fdd30e9daEric Laurent // array initialized by updateStreamVolumeAlias() 54524e0d9b6c40712a297e4c287435a3b0fdd30e9daEric Laurent updateStreamVolumeAlias(false /*updateVolumes*/); 5469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project readPersistedSettings(); 547c1d4166289ce016965d1147f7e8d37862ee347ecEric Laurent mSettingsObserver = new SettingsObserver(); 548a553c25b33c99b345cf1c8688f8df0ed8df14e5aEric Laurent createStreamStates(); 5499f103de83f2d5d472960dcf1401e95b2ab57a477Eric Laurent 550fd116ad1ab02f6060a0b2201f018317fa32e28b4Glenn Kasten readAndSetLowRamDevice(); 5513891c4cc918e8062abb97c542a8625d556dccc59Eric Laurent 5523891c4cc918e8062abb97c542a8625d556dccc59Eric Laurent // Call setRingerModeInt() to apply correct mute 5533891c4cc918e8062abb97c542a8625d556dccc59Eric Laurent // state on streams affected by ringer mode. 5543891c4cc918e8062abb97c542a8625d556dccc59Eric Laurent mRingerModeMutedStreams = 0; 5553891c4cc918e8062abb97c542a8625d556dccc59Eric Laurent setRingerModeInt(getRingerMode(), false); 5563891c4cc918e8062abb97c542a8625d556dccc59Eric Laurent 557a553c25b33c99b345cf1c8688f8df0ed8df14e5aEric Laurent // Register for device connection intent broadcasts. 558a553c25b33c99b345cf1c8688f8df0ed8df14e5aEric Laurent IntentFilter intentFilter = 559b1fbaaccb656ef09a8770c28df15e3e91a452e64Eric Laurent new IntentFilter(BluetoothHeadset.ACTION_AUDIO_STATE_CHANGED); 56082aa7f017daaaeb96c13e6e3491d5037ab471085Jaikumar Ganesh intentFilter.addAction(BluetoothHeadset.ACTION_CONNECTION_STATE_CHANGED); 56182aa7f017daaaeb96c13e6e3491d5037ab471085Jaikumar Ganesh intentFilter.addAction(Intent.ACTION_DOCK_EVENT); 56259f482764e346a5c5ac118ee1f7b24da645c2559Eric Laurent intentFilter.addAction(Intent.ACTION_USB_AUDIO_ACCESSORY_PLUG); 56359f482764e346a5c5ac118ee1f7b24da645c2559Eric Laurent intentFilter.addAction(Intent.ACTION_USB_AUDIO_DEVICE_PLUG); 564950e8cb40a6d826af4cc2eef9d3908c1b70486e6Eric Laurent intentFilter.addAction(Intent.ACTION_SCREEN_ON); 565950e8cb40a6d826af4cc2eef9d3908c1b70486e6Eric Laurent intentFilter.addAction(Intent.ACTION_SCREEN_OFF); 566bc0fab1fc2db832ef86d8a33466ec4d68b103ca0Eric Laurent intentFilter.addAction(Intent.ACTION_USER_SWITCHED); 567c837a451946b64d70ed7c642fbde03c182c28b6fPaul McLean intentFilter.addAction(UsbManager.ACTION_USB_DEVICE_ATTACHED); 568f26f01784e1c733c53cad3ed31918e73448ce369Jean-Michel Trivi 569d640bd325c3be9a350058c835b880a7e0b40dc60Eric Laurent intentFilter.addAction(Intent.ACTION_CONFIGURATION_CHANGED); 570bb6f8711a7f804d39c45218db2d6339940cc5d35Jean-Michel Trivi // TODO merge orientation and rotation 571d640bd325c3be9a350058c835b880a7e0b40dc60Eric Laurent mMonitorOrientation = SystemProperties.getBoolean("ro.audio.monitorOrientation", false); 572d640bd325c3be9a350058c835b880a7e0b40dc60Eric Laurent if (mMonitorOrientation) { 573f26f01784e1c733c53cad3ed31918e73448ce369Jean-Michel Trivi Log.v(TAG, "monitoring device orientation"); 574f26f01784e1c733c53cad3ed31918e73448ce369Jean-Michel Trivi // initialize orientation in AudioSystem 575f26f01784e1c733c53cad3ed31918e73448ce369Jean-Michel Trivi setOrientationForAudioSystem(); 576f26f01784e1c733c53cad3ed31918e73448ce369Jean-Michel Trivi } 577bb6f8711a7f804d39c45218db2d6339940cc5d35Jean-Michel Trivi mMonitorRotation = SystemProperties.getBoolean("ro.audio.monitorRotation", false); 578bb6f8711a7f804d39c45218db2d6339940cc5d35Jean-Michel Trivi if (mMonitorRotation) { 579bb6f8711a7f804d39c45218db2d6339940cc5d35Jean-Michel Trivi mDeviceRotation = ((WindowManager) mContext.getSystemService(Context.WINDOW_SERVICE)) 580bb6f8711a7f804d39c45218db2d6339940cc5d35Jean-Michel Trivi .getDefaultDisplay().getRotation(); 581bb6f8711a7f804d39c45218db2d6339940cc5d35Jean-Michel Trivi Log.v(TAG, "monitoring device rotation, initial=" + mDeviceRotation); 582bb6f8711a7f804d39c45218db2d6339940cc5d35Jean-Michel Trivi // initialize rotation in AudioSystem 583bb6f8711a7f804d39c45218db2d6339940cc5d35Jean-Michel Trivi setRotationForAudioSystem(); 584bb6f8711a7f804d39c45218db2d6339940cc5d35Jean-Michel Trivi } 585f26f01784e1c733c53cad3ed31918e73448ce369Jean-Michel Trivi 58641d974631c5f525da49c88d34cecedd5a4cfeda8Jungshik Jang HdmiControlManager hdmiManager = 58741d974631c5f525da49c88d34cecedd5a4cfeda8Jungshik Jang (HdmiControlManager) mContext.getSystemService(Context.HDMI_CONTROL_SERVICE); 58841d974631c5f525da49c88d34cecedd5a4cfeda8Jungshik Jang // Null if device is not Tv. 58941d974631c5f525da49c88d34cecedd5a4cfeda8Jungshik Jang mHdmiTvClient = hdmiManager.getTvClient(); 59041d974631c5f525da49c88d34cecedd5a4cfeda8Jungshik Jang 591a553c25b33c99b345cf1c8688f8df0ed8df14e5aEric Laurent context.registerReceiver(mReceiver, intentFilter); 5925982013cfc8274ff0bafaba83c676b3a8890cba9Jared Suttles 5930dc37cce9d564ae43883c8dc8672b9266b881e63Mike Lockwood mUseMasterVolume = context.getResources().getBoolean( 5940dc37cce9d564ae43883c8dc8672b9266b881e63Mike Lockwood com.android.internal.R.bool.config_useMasterVolume); 5959063154a793b0ab38b3c5992cbaed046427b4a82Mike Lockwood restoreMasterVolume(); 5969760647dd0ee67e7c20f3e9d661d2006b1df0b54Mike Lockwood 5979760647dd0ee67e7c20f3e9d661d2006b1df0b54Mike Lockwood mMasterVolumeRamp = context.getResources().getIntArray( 5989760647dd0ee67e7c20f3e9d661d2006b1df0b54Mike Lockwood com.android.internal.R.array.config_masterVolumeRamp); 5997847211fb4699bf6018e29d214a918ed6657319bEric Laurent 6009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 6019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 6024a5eeb9c727d77bb57fef87a70c8c9cc23dbfee3Eric Laurent public void systemReady() { 6034a5eeb9c727d77bb57fef87a70c8c9cc23dbfee3Eric Laurent sendMsg(mAudioHandler, MSG_SYSTEM_READY, SENDMSG_QUEUE, 6044a5eeb9c727d77bb57fef87a70c8c9cc23dbfee3Eric Laurent 0, 0, null, 0); 6054a5eeb9c727d77bb57fef87a70c8c9cc23dbfee3Eric Laurent } 6064a5eeb9c727d77bb57fef87a70c8c9cc23dbfee3Eric Laurent 6074a5eeb9c727d77bb57fef87a70c8c9cc23dbfee3Eric Laurent public void onSystemReady() { 6084a5eeb9c727d77bb57fef87a70c8c9cc23dbfee3Eric Laurent mSystemReady = true; 6094a5eeb9c727d77bb57fef87a70c8c9cc23dbfee3Eric Laurent sendMsg(mAudioHandler, MSG_LOAD_SOUND_EFFECTS, SENDMSG_QUEUE, 6104a5eeb9c727d77bb57fef87a70c8c9cc23dbfee3Eric Laurent 0, 0, null, 0); 6114a5eeb9c727d77bb57fef87a70c8c9cc23dbfee3Eric Laurent 6124a5eeb9c727d77bb57fef87a70c8c9cc23dbfee3Eric Laurent mKeyguardManager = 6134a5eeb9c727d77bb57fef87a70c8c9cc23dbfee3Eric Laurent (KeyguardManager) mContext.getSystemService(Context.KEYGUARD_SERVICE); 6144a5eeb9c727d77bb57fef87a70c8c9cc23dbfee3Eric Laurent mScoConnectionState = AudioManager.SCO_AUDIO_STATE_ERROR; 6154a5eeb9c727d77bb57fef87a70c8c9cc23dbfee3Eric Laurent resetBluetoothSco(); 6164a5eeb9c727d77bb57fef87a70c8c9cc23dbfee3Eric Laurent getBluetoothHeadset(); 6174a5eeb9c727d77bb57fef87a70c8c9cc23dbfee3Eric Laurent //FIXME: this is to maintain compatibility with deprecated intent 6184a5eeb9c727d77bb57fef87a70c8c9cc23dbfee3Eric Laurent // AudioManager.ACTION_SCO_AUDIO_STATE_CHANGED. Remove when appropriate. 6194a5eeb9c727d77bb57fef87a70c8c9cc23dbfee3Eric Laurent Intent newIntent = new Intent(AudioManager.ACTION_SCO_AUDIO_STATE_CHANGED); 6204a5eeb9c727d77bb57fef87a70c8c9cc23dbfee3Eric Laurent newIntent.putExtra(AudioManager.EXTRA_SCO_AUDIO_STATE, 6214a5eeb9c727d77bb57fef87a70c8c9cc23dbfee3Eric Laurent AudioManager.SCO_AUDIO_STATE_DISCONNECTED); 6224a5eeb9c727d77bb57fef87a70c8c9cc23dbfee3Eric Laurent sendStickyBroadcastToAll(newIntent); 6234a5eeb9c727d77bb57fef87a70c8c9cc23dbfee3Eric Laurent 6244a5eeb9c727d77bb57fef87a70c8c9cc23dbfee3Eric Laurent BluetoothAdapter adapter = BluetoothAdapter.getDefaultAdapter(); 6254a5eeb9c727d77bb57fef87a70c8c9cc23dbfee3Eric Laurent if (adapter != null) { 6264a5eeb9c727d77bb57fef87a70c8c9cc23dbfee3Eric Laurent adapter.getProfileProxy(mContext, mBluetoothProfileServiceListener, 6274a5eeb9c727d77bb57fef87a70c8c9cc23dbfee3Eric Laurent BluetoothProfile.A2DP); 6284a5eeb9c727d77bb57fef87a70c8c9cc23dbfee3Eric Laurent } 6294a5eeb9c727d77bb57fef87a70c8c9cc23dbfee3Eric Laurent 6304a5eeb9c727d77bb57fef87a70c8c9cc23dbfee3Eric Laurent sendMsg(mAudioHandler, 6314a5eeb9c727d77bb57fef87a70c8c9cc23dbfee3Eric Laurent MSG_CONFIGURE_SAFE_MEDIA_VOLUME_FORCED, 6324a5eeb9c727d77bb57fef87a70c8c9cc23dbfee3Eric Laurent SENDMSG_REPLACE, 6334a5eeb9c727d77bb57fef87a70c8c9cc23dbfee3Eric Laurent 0, 6344a5eeb9c727d77bb57fef87a70c8c9cc23dbfee3Eric Laurent 0, 6354a5eeb9c727d77bb57fef87a70c8c9cc23dbfee3Eric Laurent null, 6364a5eeb9c727d77bb57fef87a70c8c9cc23dbfee3Eric Laurent SAFE_VOLUME_CONFIGURE_TIMEOUT_MS); 6374a5eeb9c727d77bb57fef87a70c8c9cc23dbfee3Eric Laurent } 6384a5eeb9c727d77bb57fef87a70c8c9cc23dbfee3Eric Laurent 6399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private void createAudioSystemThread() { 6409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mAudioSystemThread = new AudioSystemThread(); 6419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mAudioSystemThread.start(); 6429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project waitForAudioHandlerCreation(); 6439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 6449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 6459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** Waits for the volume handler to be created by the other thread. */ 6469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private void waitForAudioHandlerCreation() { 6479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project synchronized(this) { 6489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project while (mAudioHandler == null) { 6499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project try { 6509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Wait for mAudioHandler to be set by the other thread 6519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project wait(); 6529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } catch (InterruptedException e) { 6539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Log.e(TAG, "Interrupted while waiting on volume handler."); 6549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 6559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 6569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 6579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 6589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 659244820185269991186d07068b92985624cede4a5Eric Laurent private void checkAllAliasStreamVolumes() { 660244820185269991186d07068b92985624cede4a5Eric Laurent int numStreamTypes = AudioSystem.getNumStreamTypes(); 661244820185269991186d07068b92985624cede4a5Eric Laurent for (int streamType = 0; streamType < numStreamTypes; streamType++) { 662244820185269991186d07068b92985624cede4a5Eric Laurent if (streamType != mStreamVolumeAlias[streamType]) { 663244820185269991186d07068b92985624cede4a5Eric Laurent mStreamStates[streamType]. 66442b041ed4f184e3af7f788eb07307f556a2a6616Eric Laurent setAllIndexes(mStreamStates[mStreamVolumeAlias[streamType]]); 665244820185269991186d07068b92985624cede4a5Eric Laurent } 666244820185269991186d07068b92985624cede4a5Eric Laurent // apply stream volume 66742b041ed4f184e3af7f788eb07307f556a2a6616Eric Laurent if (!mStreamStates[streamType].isMuted()) { 668244820185269991186d07068b92985624cede4a5Eric Laurent mStreamStates[streamType].applyAllVolumes(); 669244820185269991186d07068b92985624cede4a5Eric Laurent } 670244820185269991186d07068b92985624cede4a5Eric Laurent } 671244820185269991186d07068b92985624cede4a5Eric Laurent } 672244820185269991186d07068b92985624cede4a5Eric Laurent 6739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private void createStreamStates() { 6749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int numStreamTypes = AudioSystem.getNumStreamTypes(); 6759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project VolumeStreamState[] streams = mStreamStates = new VolumeStreamState[numStreamTypes]; 6769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 6779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project for (int i = 0; i < numStreamTypes; i++) { 6786d5176638c2189595cede38fb92c3e7e8700e221Eric Laurent streams[i] = new VolumeStreamState(System.VOLUME_SETTINGS[mStreamVolumeAlias[i]], i); 6799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 6809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 681244820185269991186d07068b92985624cede4a5Eric Laurent checkAllAliasStreamVolumes(); 6829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 6839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 684bffc3d1bd33eb2d8e00a9f8b6261d815db503311Eric Laurent private void dumpStreamStates(PrintWriter pw) { 685bffc3d1bd33eb2d8e00a9f8b6261d815db503311Eric Laurent pw.println("\nStream volumes (device: index)"); 686bffc3d1bd33eb2d8e00a9f8b6261d815db503311Eric Laurent int numStreamTypes = AudioSystem.getNumStreamTypes(); 687bffc3d1bd33eb2d8e00a9f8b6261d815db503311Eric Laurent for (int i = 0; i < numStreamTypes; i++) { 688bffc3d1bd33eb2d8e00a9f8b6261d815db503311Eric Laurent pw.println("- "+STREAM_NAMES[i]+":"); 689bffc3d1bd33eb2d8e00a9f8b6261d815db503311Eric Laurent mStreamStates[i].dump(pw); 690bffc3d1bd33eb2d8e00a9f8b6261d815db503311Eric Laurent pw.println(""); 691bffc3d1bd33eb2d8e00a9f8b6261d815db503311Eric Laurent } 692dd45d01128423a82652a3c9d77fa393631d95229Eric Laurent pw.print("\n- mute affected streams = 0x"); 693dd45d01128423a82652a3c9d77fa393631d95229Eric Laurent pw.println(Integer.toHexString(mMuteAffectedStreams)); 694bffc3d1bd33eb2d8e00a9f8b6261d815db503311Eric Laurent } 695bffc3d1bd33eb2d8e00a9f8b6261d815db503311Eric Laurent 6961af30c7ac480e5d335f267a3ac3b2e6c748ce240John Spurlock /** @hide */ 6971af30c7ac480e5d335f267a3ac3b2e6c748ce240John Spurlock public static String streamToString(int stream) { 6981af30c7ac480e5d335f267a3ac3b2e6c748ce240John Spurlock if (stream >= 0 && stream < STREAM_NAMES.length) return STREAM_NAMES[stream]; 6991af30c7ac480e5d335f267a3ac3b2e6c748ce240John Spurlock if (stream == AudioManager.USE_DEFAULT_STREAM_TYPE) return "USE_DEFAULT_STREAM_TYPE"; 7001af30c7ac480e5d335f267a3ac3b2e6c748ce240John Spurlock return "UNKNOWN_STREAM_" + stream; 7011af30c7ac480e5d335f267a3ac3b2e6c748ce240John Spurlock } 7026d5176638c2189595cede38fb92c3e7e8700e221Eric Laurent 7036d5176638c2189595cede38fb92c3e7e8700e221Eric Laurent private void updateStreamVolumeAlias(boolean updateVolumes) { 7046d5176638c2189595cede38fb92c3e7e8700e221Eric Laurent int dtmfStreamAlias; 7056d5176638c2189595cede38fb92c3e7e8700e221Eric Laurent if (mVoiceCapable) { 7066d5176638c2189595cede38fb92c3e7e8700e221Eric Laurent mStreamVolumeAlias = STREAM_VOLUME_ALIAS; 7076d5176638c2189595cede38fb92c3e7e8700e221Eric Laurent dtmfStreamAlias = AudioSystem.STREAM_RING; 7086d5176638c2189595cede38fb92c3e7e8700e221Eric Laurent } else { 7096d5176638c2189595cede38fb92c3e7e8700e221Eric Laurent mStreamVolumeAlias = STREAM_VOLUME_ALIAS_NON_VOICE; 7106d5176638c2189595cede38fb92c3e7e8700e221Eric Laurent dtmfStreamAlias = AudioSystem.STREAM_MUSIC; 7116d5176638c2189595cede38fb92c3e7e8700e221Eric Laurent } 7126d5176638c2189595cede38fb92c3e7e8700e221Eric Laurent if (isInCommunication()) { 7136d5176638c2189595cede38fb92c3e7e8700e221Eric Laurent dtmfStreamAlias = AudioSystem.STREAM_VOICE_CALL; 71424e0d9b6c40712a297e4c287435a3b0fdd30e9daEric Laurent mRingerModeAffectedStreams &= ~(1 << AudioSystem.STREAM_DTMF); 71524e0d9b6c40712a297e4c287435a3b0fdd30e9daEric Laurent } else { 71624e0d9b6c40712a297e4c287435a3b0fdd30e9daEric Laurent mRingerModeAffectedStreams |= (1 << AudioSystem.STREAM_DTMF); 7176d5176638c2189595cede38fb92c3e7e8700e221Eric Laurent } 7186d5176638c2189595cede38fb92c3e7e8700e221Eric Laurent mStreamVolumeAlias[AudioSystem.STREAM_DTMF] = dtmfStreamAlias; 7196d5176638c2189595cede38fb92c3e7e8700e221Eric Laurent if (updateVolumes) { 72042b041ed4f184e3af7f788eb07307f556a2a6616Eric Laurent mStreamStates[AudioSystem.STREAM_DTMF].setAllIndexes(mStreamStates[dtmfStreamAlias]); 72124e0d9b6c40712a297e4c287435a3b0fdd30e9daEric Laurent // apply stream mute states according to new value of mRingerModeAffectedStreams 72224e0d9b6c40712a297e4c287435a3b0fdd30e9daEric Laurent setRingerModeInt(getRingerMode(), false); 7236d5176638c2189595cede38fb92c3e7e8700e221Eric Laurent sendMsg(mAudioHandler, 7246d5176638c2189595cede38fb92c3e7e8700e221Eric Laurent MSG_SET_ALL_VOLUMES, 7256d5176638c2189595cede38fb92c3e7e8700e221Eric Laurent SENDMSG_QUEUE, 7266d5176638c2189595cede38fb92c3e7e8700e221Eric Laurent 0, 7276d5176638c2189595cede38fb92c3e7e8700e221Eric Laurent 0, 7286d5176638c2189595cede38fb92c3e7e8700e221Eric Laurent mStreamStates[AudioSystem.STREAM_DTMF], 0); 7296d5176638c2189595cede38fb92c3e7e8700e221Eric Laurent } 7306d5176638c2189595cede38fb92c3e7e8700e221Eric Laurent } 7316d5176638c2189595cede38fb92c3e7e8700e221Eric Laurent 7327ee1e4ff7346a278a6722108fbc1869240b3e866Eric Laurent private void readDockAudioSettings(ContentResolver cr) 7337ee1e4ff7346a278a6722108fbc1869240b3e866Eric Laurent { 7347ee1e4ff7346a278a6722108fbc1869240b3e866Eric Laurent mDockAudioMediaEnabled = Settings.Global.getInt( 7355ba0ffa0237a5c300545e4c72591613c6e5b2ed9Eric Laurent cr, Settings.Global.DOCK_AUDIO_MEDIA_ENABLED, 0) == 1; 7367ee1e4ff7346a278a6722108fbc1869240b3e866Eric Laurent 7377ee1e4ff7346a278a6722108fbc1869240b3e866Eric Laurent if (mDockAudioMediaEnabled) { 7387ee1e4ff7346a278a6722108fbc1869240b3e866Eric Laurent mBecomingNoisyIntentDevices |= AudioSystem.DEVICE_OUT_ANLG_DOCK_HEADSET; 7397ee1e4ff7346a278a6722108fbc1869240b3e866Eric Laurent } else { 7407ee1e4ff7346a278a6722108fbc1869240b3e866Eric Laurent mBecomingNoisyIntentDevices &= ~AudioSystem.DEVICE_OUT_ANLG_DOCK_HEADSET; 7417ee1e4ff7346a278a6722108fbc1869240b3e866Eric Laurent } 7427ee1e4ff7346a278a6722108fbc1869240b3e866Eric Laurent 7437ee1e4ff7346a278a6722108fbc1869240b3e866Eric Laurent sendMsg(mAudioHandler, 7447ee1e4ff7346a278a6722108fbc1869240b3e866Eric Laurent MSG_SET_FORCE_USE, 7457ee1e4ff7346a278a6722108fbc1869240b3e866Eric Laurent SENDMSG_QUEUE, 7467ee1e4ff7346a278a6722108fbc1869240b3e866Eric Laurent AudioSystem.FOR_DOCK, 7477ee1e4ff7346a278a6722108fbc1869240b3e866Eric Laurent mDockAudioMediaEnabled ? 7487ee1e4ff7346a278a6722108fbc1869240b3e866Eric Laurent AudioSystem.FORCE_ANALOG_DOCK : AudioSystem.FORCE_NONE, 7497ee1e4ff7346a278a6722108fbc1869240b3e866Eric Laurent null, 7507ee1e4ff7346a278a6722108fbc1869240b3e866Eric Laurent 0); 7517ee1e4ff7346a278a6722108fbc1869240b3e866Eric Laurent } 7527ee1e4ff7346a278a6722108fbc1869240b3e866Eric Laurent 7539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private void readPersistedSettings() { 7549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project final ContentResolver cr = mContentResolver; 7559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 756bffc3d1bd33eb2d8e00a9f8b6261d815db503311Eric Laurent int ringerModeFromSettings = 7578d9a1f66d9d3dbbd45a56d441a746ec11dba7645Jeff Sharkey Settings.Global.getInt( 7588d9a1f66d9d3dbbd45a56d441a746ec11dba7645Jeff Sharkey cr, Settings.Global.MODE_RINGER, AudioManager.RINGER_MODE_NORMAL); 759bffc3d1bd33eb2d8e00a9f8b6261d815db503311Eric Laurent int ringerMode = ringerModeFromSettings; 76072668b2c040b581b298b069f3b5af5ed7f212d89Eric Laurent // sanity check in case the settings are restored from a device with incompatible 76172668b2c040b581b298b069f3b5af5ed7f212d89Eric Laurent // ringer modes 762ba195ebc76f23b6679443724ab58c9dc9f2df884Glenn Kasten if (!AudioManager.isValidRingerMode(ringerMode)) { 763ba195ebc76f23b6679443724ab58c9dc9f2df884Glenn Kasten ringerMode = AudioManager.RINGER_MODE_NORMAL; 764bffc3d1bd33eb2d8e00a9f8b6261d815db503311Eric Laurent } 765bffc3d1bd33eb2d8e00a9f8b6261d815db503311Eric Laurent if ((ringerMode == AudioManager.RINGER_MODE_VIBRATE) && !mHasVibrator) { 766bffc3d1bd33eb2d8e00a9f8b6261d815db503311Eric Laurent ringerMode = AudioManager.RINGER_MODE_SILENT; 767bffc3d1bd33eb2d8e00a9f8b6261d815db503311Eric Laurent } 768bffc3d1bd33eb2d8e00a9f8b6261d815db503311Eric Laurent if (ringerMode != ringerModeFromSettings) { 7698d9a1f66d9d3dbbd45a56d441a746ec11dba7645Jeff Sharkey Settings.Global.putInt(cr, Settings.Global.MODE_RINGER, ringerMode); 770ba195ebc76f23b6679443724ab58c9dc9f2df884Glenn Kasten } 77183a017b6b7c099d1a0293e5839be6477325aef06Eric Laurent if (mUseFixedVolume) { 77283a017b6b7c099d1a0293e5839be6477325aef06Eric Laurent ringerMode = AudioManager.RINGER_MODE_NORMAL; 77383a017b6b7c099d1a0293e5839be6477325aef06Eric Laurent } 774ba195ebc76f23b6679443724ab58c9dc9f2df884Glenn Kasten synchronized(mSettingsLock) { 775ba195ebc76f23b6679443724ab58c9dc9f2df884Glenn Kasten mRingerMode = ringerMode; 7769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 777dd45d01128423a82652a3c9d77fa393631d95229Eric Laurent // System.VIBRATE_ON is not used any more but defaults for mVibrateSetting 778dd45d01128423a82652a3c9d77fa393631d95229Eric Laurent // are still needed while setVibrateSetting() and getVibrateSetting() are being 779dd45d01128423a82652a3c9d77fa393631d95229Eric Laurent // deprecated. 780dd45d01128423a82652a3c9d77fa393631d95229Eric Laurent mVibrateSetting = getValueForVibrateSetting(0, 781dd45d01128423a82652a3c9d77fa393631d95229Eric Laurent AudioManager.VIBRATE_TYPE_NOTIFICATION, 782dd45d01128423a82652a3c9d77fa393631d95229Eric Laurent mHasVibrator ? AudioManager.VIBRATE_SETTING_ONLY_SILENT 783dd45d01128423a82652a3c9d77fa393631d95229Eric Laurent : AudioManager.VIBRATE_SETTING_OFF); 784dd45d01128423a82652a3c9d77fa393631d95229Eric Laurent mVibrateSetting = getValueForVibrateSetting(mVibrateSetting, 785dd45d01128423a82652a3c9d77fa393631d95229Eric Laurent AudioManager.VIBRATE_TYPE_RINGER, 786dd45d01128423a82652a3c9d77fa393631d95229Eric Laurent mHasVibrator ? AudioManager.VIBRATE_SETTING_ONLY_SILENT 787dd45d01128423a82652a3c9d77fa393631d95229Eric Laurent : AudioManager.VIBRATE_SETTING_OFF); 788dd45d01128423a82652a3c9d77fa393631d95229Eric Laurent 78924e0d9b6c40712a297e4c287435a3b0fdd30e9daEric Laurent updateRingerModeAffectedStreams(); 7907ee1e4ff7346a278a6722108fbc1869240b3e866Eric Laurent readDockAudioSettings(cr); 791402f7f29634a9f68e7929be828a927a3e2f5efe9Eric Laurent } 792c1d4166289ce016965d1147f7e8d37862ee347ecEric Laurent 793bc0fab1fc2db832ef86d8a33466ec4d68b103ca0Eric Laurent mMuteAffectedStreams = System.getIntForUser(cr, 7949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project System.MUTE_STREAMS_AFFECTED, 795bc0fab1fc2db832ef86d8a33466ec4d68b103ca0Eric Laurent ((1 << AudioSystem.STREAM_MUSIC)| 796bc0fab1fc2db832ef86d8a33466ec4d68b103ca0Eric Laurent (1 << AudioSystem.STREAM_RING)| 797bc0fab1fc2db832ef86d8a33466ec4d68b103ca0Eric Laurent (1 << AudioSystem.STREAM_SYSTEM)), 798bc0fab1fc2db832ef86d8a33466ec4d68b103ca0Eric Laurent UserHandle.USER_CURRENT); 7999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 800bc0fab1fc2db832ef86d8a33466ec4d68b103ca0Eric Laurent boolean masterMute = System.getIntForUser(cr, System.VOLUME_MASTER_MUTE, 801bc0fab1fc2db832ef86d8a33466ec4d68b103ca0Eric Laurent 0, UserHandle.USER_CURRENT) == 1; 80283a017b6b7c099d1a0293e5839be6477325aef06Eric Laurent if (mUseFixedVolume) { 80383a017b6b7c099d1a0293e5839be6477325aef06Eric Laurent masterMute = false; 80483a017b6b7c099d1a0293e5839be6477325aef06Eric Laurent AudioSystem.setMasterVolume(1.0f); 80583a017b6b7c099d1a0293e5839be6477325aef06Eric Laurent } 80657978ed86286a33d5b1a0fd000ca3406ba9d87b3Justin Koh AudioSystem.setMasterMute(masterMute); 80757978ed86286a33d5b1a0fd000ca3406ba9d87b3Justin Koh broadcastMasterMuteStatus(masterMute); 80857978ed86286a33d5b1a0fd000ca3406ba9d87b3Justin Koh 8099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Each stream will read its own persisted settings 8109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 8119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Broadcast the sticky intent 812ba195ebc76f23b6679443724ab58c9dc9f2df884Glenn Kasten broadcastRingerMode(ringerMode); 8139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 8149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Broadcast vibrate settings 8159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project broadcastVibrateSetting(AudioManager.VIBRATE_TYPE_RINGER); 8169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project broadcastVibrateSetting(AudioManager.VIBRATE_TYPE_NOTIFICATION); 817d589fea865e90859324f00d21765fa7d7759e465Jean-Michel Trivi 818d589fea865e90859324f00d21765fa7d7759e465Jean-Michel Trivi // Restore the default media button receiver from the system settings 819fa9a69805b001034aa04c3b33989a7ac21522371Jean-Michel Trivi mMediaFocusControl.restoreMediaButtonReceiver(); 82033f4e04e32fac42f158733d6a731e50490fa9951John Spurlock 82133f4e04e32fac42f158733d6a731e50490fa9951John Spurlock // Load settings for the volume controller 82233f4e04e32fac42f158733d6a731e50490fa9951John Spurlock mVolumeController.loadSettings(cr); 8239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 8249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 825a553c25b33c99b345cf1c8688f8df0ed8df14e5aEric Laurent private int rescaleIndex(int index, int srcStream, int dstStream) { 826a553c25b33c99b345cf1c8688f8df0ed8df14e5aEric Laurent return (index * mStreamStates[dstStream].getMaxIndex() + mStreamStates[srcStream].getMaxIndex() / 2) / mStreamStates[srcStream].getMaxIndex(); 827a553c25b33c99b345cf1c8688f8df0ed8df14e5aEric Laurent } 8289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 8299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /////////////////////////////////////////////////////////////////////////// 8309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // IPC methods 8319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /////////////////////////////////////////////////////////////////////////// 832fca1e603236b8d1681f784e77e3719d1d59c1428Jean-Michel Trivi /** @see AudioManager#isLocalOrRemoteMusicActive() */ 833fca1e603236b8d1681f784e77e3719d1d59c1428Jean-Michel Trivi public boolean isLocalOrRemoteMusicActive() { 834fca1e603236b8d1681f784e77e3719d1d59c1428Jean-Michel Trivi if (AudioSystem.isStreamActive(AudioSystem.STREAM_MUSIC, 0)) { 835fca1e603236b8d1681f784e77e3719d1d59c1428Jean-Michel Trivi // local / wired / BT playback active 836fca1e603236b8d1681f784e77e3719d1d59c1428Jean-Michel Trivi if (DEBUG_VOL) Log.d(TAG, "isLocalOrRemoteMusicActive(): local"); 837fca1e603236b8d1681f784e77e3719d1d59c1428Jean-Michel Trivi return true; 838fca1e603236b8d1681f784e77e3719d1d59c1428Jean-Michel Trivi } 839fca1e603236b8d1681f784e77e3719d1d59c1428Jean-Michel Trivi if (mMediaFocusControl.checkUpdateRemoteStateIfActive(AudioSystem.STREAM_MUSIC)) { 840fca1e603236b8d1681f784e77e3719d1d59c1428Jean-Michel Trivi // remote "cast-like" playback active 841fca1e603236b8d1681f784e77e3719d1d59c1428Jean-Michel Trivi if (DEBUG_VOL) Log.d(TAG, "isLocalOrRemoteMusicActive(): has PLAYBACK_TYPE_REMOTE"); 842fca1e603236b8d1681f784e77e3719d1d59c1428Jean-Michel Trivi return true; 843fca1e603236b8d1681f784e77e3719d1d59c1428Jean-Michel Trivi } 844fca1e603236b8d1681f784e77e3719d1d59c1428Jean-Michel Trivi if (AudioSystem.isStreamActiveRemotely(AudioSystem.STREAM_MUSIC, 0)) { 845fca1e603236b8d1681f784e77e3719d1d59c1428Jean-Michel Trivi // remote submix playback active 846fca1e603236b8d1681f784e77e3719d1d59c1428Jean-Michel Trivi if (DEBUG_VOL) Log.d(TAG, "isLocalOrRemoteMusicActive(): remote submix"); 847fca1e603236b8d1681f784e77e3719d1d59c1428Jean-Michel Trivi return true; 848fca1e603236b8d1681f784e77e3719d1d59c1428Jean-Michel Trivi } 849fca1e603236b8d1681f784e77e3719d1d59c1428Jean-Michel Trivi if (DEBUG_VOL) Log.d(TAG, "isLocalOrRemoteMusicActive(): no"); 850fca1e603236b8d1681f784e77e3719d1d59c1428Jean-Michel Trivi return false; 851fca1e603236b8d1681f784e77e3719d1d59c1428Jean-Michel Trivi } 8529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 8539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** @see AudioManager#adjustVolume(int, int) */ 854ba50b97cff80e73620a0e3d13cae169e095974a7Dianne Hackborn public void adjustSuggestedStreamVolume(int direction, int suggestedStreamType, int flags, 855ba50b97cff80e73620a0e3d13cae169e095974a7Dianne Hackborn String callingPackage) { 856ae641c9ccd3f81214cee54a5f13804f1765187adJohn Spurlock if (DEBUG_VOL) Log.d(TAG, "adjustSuggestedStreamVolume() stream="+suggestedStreamType 857ae641c9ccd3f81214cee54a5f13804f1765187adJohn Spurlock + ", flags=" + flags); 858402f7f29634a9f68e7929be828a927a3e2f5efe9Eric Laurent int streamType; 85945c90cefd13a03b852bb4b8da4be218876cbbb32Eric Laurent if (mVolumeControlStream != -1) { 86045c90cefd13a03b852bb4b8da4be218876cbbb32Eric Laurent streamType = mVolumeControlStream; 861402f7f29634a9f68e7929be828a927a3e2f5efe9Eric Laurent } else { 862402f7f29634a9f68e7929be828a927a3e2f5efe9Eric Laurent streamType = getActiveStreamType(suggestedStreamType); 863402f7f29634a9f68e7929be828a927a3e2f5efe9Eric Laurent } 86433f4e04e32fac42f158733d6a731e50490fa9951John Spurlock final int resolvedStream = mStreamVolumeAlias[streamType]; 8659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 8666bd096c8d608197535a6a6a26663fd1e717246deJohn Spurlock // Play sounds on STREAM_RING and STREAM_REMOTE_MUSIC only. 8673114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi if ((streamType != STREAM_REMOTE_MUSIC) && 8683114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi (flags & AudioManager.FLAG_PLAY_SOUND) != 0 && 86933f4e04e32fac42f158733d6a731e50490fa9951John Spurlock resolvedStream != AudioSystem.STREAM_RING) { 87033f4e04e32fac42f158733d6a731e50490fa9951John Spurlock flags &= ~AudioManager.FLAG_PLAY_SOUND; 87133f4e04e32fac42f158733d6a731e50490fa9951John Spurlock } 87233f4e04e32fac42f158733d6a731e50490fa9951John Spurlock 87333f4e04e32fac42f158733d6a731e50490fa9951John Spurlock // For notifications/ring, show the ui before making any adjustments 87433f4e04e32fac42f158733d6a731e50490fa9951John Spurlock if (mVolumeController.suppressAdjustment(resolvedStream, flags)) { 87533f4e04e32fac42f158733d6a731e50490fa9951John Spurlock direction = 0; 8769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project flags &= ~AudioManager.FLAG_PLAY_SOUND; 87733f4e04e32fac42f158733d6a731e50490fa9951John Spurlock flags &= ~AudioManager.FLAG_VIBRATE; 87833f4e04e32fac42f158733d6a731e50490fa9951John Spurlock if (DEBUG_VOL) Log.d(TAG, "Volume controller suppressed adjustment"); 8799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 8809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 8813114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi if (streamType == STREAM_REMOTE_MUSIC) { 88219c9518f6a817d53d5234de0020313cab6950b2fRoboErik // TODO bounce it to MediaSessionService to find an appropriate 88319c9518f6a817d53d5234de0020313cab6950b2fRoboErik // session 8843114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi } else { 885ba50b97cff80e73620a0e3d13cae169e095974a7Dianne Hackborn adjustStreamVolume(streamType, direction, flags, callingPackage); 8863114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi } 8879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 8889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 8899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** @see AudioManager#adjustStreamVolume(int, int, int) */ 890ba50b97cff80e73620a0e3d13cae169e095974a7Dianne Hackborn public void adjustStreamVolume(int streamType, int direction, int flags, 891ba50b97cff80e73620a0e3d13cae169e095974a7Dianne Hackborn String callingPackage) { 89283a017b6b7c099d1a0293e5839be6477325aef06Eric Laurent if (mUseFixedVolume) { 89383a017b6b7c099d1a0293e5839be6477325aef06Eric Laurent return; 89483a017b6b7c099d1a0293e5839be6477325aef06Eric Laurent } 895ae641c9ccd3f81214cee54a5f13804f1765187adJohn Spurlock if (DEBUG_VOL) Log.d(TAG, "adjustStreamVolume() stream="+streamType+", dir="+direction 896ae641c9ccd3f81214cee54a5f13804f1765187adJohn Spurlock + ", flags="+flags); 8973114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi 8989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project ensureValidDirection(direction); 8999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project ensureValidStreamType(streamType); 9009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 90196a33d1caad2fab0bc28891cfbf553f4b050bf0bEric Laurent // use stream type alias here so that streams with same alias have the same behavior, 90296a33d1caad2fab0bc28891cfbf553f4b050bf0bEric Laurent // including with regard to silent mode control (e.g the use of STREAM_RING below and in 90396a33d1caad2fab0bc28891cfbf553f4b050bf0bEric Laurent // checkForRingerModeChange() in place of STREAM_RING or STREAM_NOTIFICATION) 9046d5176638c2189595cede38fb92c3e7e8700e221Eric Laurent int streamTypeAlias = mStreamVolumeAlias[streamType]; 905b024c30a80684ac08daef3137b7ba0d347fe3ce5Eric Laurent VolumeStreamState streamState = mStreamStates[streamTypeAlias]; 9069bc8358ddaa01c3490f9709991989633a6a3dd42Eric Laurent 9079bc8358ddaa01c3490f9709991989633a6a3dd42Eric Laurent final int device = getDeviceForStream(streamTypeAlias); 9083ef7549876a159dae1568429edcb57e4e7d08459Eric Laurent 90942b041ed4f184e3af7f788eb07307f556a2a6616Eric Laurent int aliasIndex = streamState.getIndex(device); 9109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project boolean adjustVolume = true; 9113ef7549876a159dae1568429edcb57e4e7d08459Eric Laurent int step; 912244820185269991186d07068b92985624cede4a5Eric Laurent 913c9d1d5f35091226e96fcfa91817480f589eb36e2Matthew Xie // skip a2dp absolute volume control request when the device 914c9d1d5f35091226e96fcfa91817480f589eb36e2Matthew Xie // is not an a2dp device 915c9d1d5f35091226e96fcfa91817480f589eb36e2Matthew Xie if ((device & AudioSystem.DEVICE_OUT_ALL_A2DP) == 0 && 916c9d1d5f35091226e96fcfa91817480f589eb36e2Matthew Xie (flags & AudioManager.FLAG_BLUETOOTH_ABS_VOLUME) != 0) { 917c9d1d5f35091226e96fcfa91817480f589eb36e2Matthew Xie return; 918c9d1d5f35091226e96fcfa91817480f589eb36e2Matthew Xie } 919c9d1d5f35091226e96fcfa91817480f589eb36e2Matthew Xie 920ba50b97cff80e73620a0e3d13cae169e095974a7Dianne Hackborn if (mAppOps.noteOp(STEAM_VOLUME_OPS[streamTypeAlias], Binder.getCallingUid(), 921ba50b97cff80e73620a0e3d13cae169e095974a7Dianne Hackborn callingPackage) != AppOpsManager.MODE_ALLOWED) { 922ba50b97cff80e73620a0e3d13cae169e095974a7Dianne Hackborn return; 923ba50b97cff80e73620a0e3d13cae169e095974a7Dianne Hackborn } 924ba50b97cff80e73620a0e3d13cae169e095974a7Dianne Hackborn 925fde16d5879ea88a971004c984093409468b6139cEric Laurent // reset any pending volume command 926fde16d5879ea88a971004c984093409468b6139cEric Laurent synchronized (mSafeMediaVolumeState) { 927fde16d5879ea88a971004c984093409468b6139cEric Laurent mPendingVolumeCommand = null; 928fde16d5879ea88a971004c984093409468b6139cEric Laurent } 929fde16d5879ea88a971004c984093409468b6139cEric Laurent 9303ef7549876a159dae1568429edcb57e4e7d08459Eric Laurent flags &= ~AudioManager.FLAG_FIXED_VOLUME; 9313ef7549876a159dae1568429edcb57e4e7d08459Eric Laurent if ((streamTypeAlias == AudioSystem.STREAM_MUSIC) && 9323ef7549876a159dae1568429edcb57e4e7d08459Eric Laurent ((device & mFixedVolumeDevices) != 0)) { 9333ef7549876a159dae1568429edcb57e4e7d08459Eric Laurent flags |= AudioManager.FLAG_FIXED_VOLUME; 9343ef7549876a159dae1568429edcb57e4e7d08459Eric Laurent 9353ef7549876a159dae1568429edcb57e4e7d08459Eric Laurent // Always toggle between max safe volume and 0 for fixed volume devices where safe 9363ef7549876a159dae1568429edcb57e4e7d08459Eric Laurent // volume is enforced, and max and 0 for the others. 9373ef7549876a159dae1568429edcb57e4e7d08459Eric Laurent // This is simulated by stepping by the full allowed volume range 9383ef7549876a159dae1568429edcb57e4e7d08459Eric Laurent if (mSafeMediaVolumeState == SAFE_MEDIA_VOLUME_ACTIVE && 9393ef7549876a159dae1568429edcb57e4e7d08459Eric Laurent (device & mSafeMediaVolumeDevices) != 0) { 9403ef7549876a159dae1568429edcb57e4e7d08459Eric Laurent step = mSafeMediaVolumeIndex; 9413ef7549876a159dae1568429edcb57e4e7d08459Eric Laurent } else { 9423ef7549876a159dae1568429edcb57e4e7d08459Eric Laurent step = streamState.getMaxIndex(); 9433ef7549876a159dae1568429edcb57e4e7d08459Eric Laurent } 9443ef7549876a159dae1568429edcb57e4e7d08459Eric Laurent if (aliasIndex != 0) { 9453ef7549876a159dae1568429edcb57e4e7d08459Eric Laurent aliasIndex = step; 9463ef7549876a159dae1568429edcb57e4e7d08459Eric Laurent } 9473ef7549876a159dae1568429edcb57e4e7d08459Eric Laurent } else { 9483ef7549876a159dae1568429edcb57e4e7d08459Eric Laurent // convert one UI step (+/-1) into a number of internal units on the stream alias 9493ef7549876a159dae1568429edcb57e4e7d08459Eric Laurent step = rescaleIndex(10, streamType, streamTypeAlias); 9503ef7549876a159dae1568429edcb57e4e7d08459Eric Laurent } 9513ef7549876a159dae1568429edcb57e4e7d08459Eric Laurent 95242b041ed4f184e3af7f788eb07307f556a2a6616Eric Laurent // If either the client forces allowing ringer modes for this adjustment, 95342b041ed4f184e3af7f788eb07307f556a2a6616Eric Laurent // or the stream type is one that is affected by ringer modes 95442b041ed4f184e3af7f788eb07307f556a2a6616Eric Laurent if (((flags & AudioManager.FLAG_ALLOW_RINGER_MODES) != 0) || 95542b041ed4f184e3af7f788eb07307f556a2a6616Eric Laurent (streamTypeAlias == getMasterStreamType())) { 95642b041ed4f184e3af7f788eb07307f556a2a6616Eric Laurent int ringerMode = getRingerMode(); 95742b041ed4f184e3af7f788eb07307f556a2a6616Eric Laurent // do not vibrate if already in vibrate mode 95842b041ed4f184e3af7f788eb07307f556a2a6616Eric Laurent if (ringerMode == AudioManager.RINGER_MODE_VIBRATE) { 95942b041ed4f184e3af7f788eb07307f556a2a6616Eric Laurent flags &= ~AudioManager.FLAG_VIBRATE; 96042b041ed4f184e3af7f788eb07307f556a2a6616Eric Laurent } 96142b041ed4f184e3af7f788eb07307f556a2a6616Eric Laurent // Check if the ringer mode changes with this volume adjustment. If 96242b041ed4f184e3af7f788eb07307f556a2a6616Eric Laurent // it does, it will handle adjusting the volume, so we won't below 963a11b4affcad3d255aa723a89b768ea222506f2e8John Spurlock final int result = checkForRingerModeChange(aliasIndex, direction, step); 964a11b4affcad3d255aa723a89b768ea222506f2e8John Spurlock adjustVolume = (result & FLAG_ADJUST_VOLUME) != 0; 965a11b4affcad3d255aa723a89b768ea222506f2e8John Spurlock // If suppressing a volume adjustment in silent mode, display the UI hint 966a11b4affcad3d255aa723a89b768ea222506f2e8John Spurlock if ((result & AudioManager.FLAG_SHOW_SILENT_HINT) != 0) { 967a11b4affcad3d255aa723a89b768ea222506f2e8John Spurlock flags |= AudioManager.FLAG_SHOW_SILENT_HINT; 968a11b4affcad3d255aa723a89b768ea222506f2e8John Spurlock } 96942b041ed4f184e3af7f788eb07307f556a2a6616Eric Laurent } 97042b041ed4f184e3af7f788eb07307f556a2a6616Eric Laurent 97142b041ed4f184e3af7f788eb07307f556a2a6616Eric Laurent int oldIndex = mStreamStates[streamType].getIndex(device); 97242b041ed4f184e3af7f788eb07307f556a2a6616Eric Laurent 97342b041ed4f184e3af7f788eb07307f556a2a6616Eric Laurent if (adjustVolume && (direction != AudioManager.ADJUST_SAME)) { 974c9d1d5f35091226e96fcfa91817480f589eb36e2Matthew Xie 9755a0cf7a27f3953a1266af48543ccd9024f4cd89fJohn Du // Check if volume update should be send to AVRCP 976c9d1d5f35091226e96fcfa91817480f589eb36e2Matthew Xie if (streamTypeAlias == AudioSystem.STREAM_MUSIC && 977c9d1d5f35091226e96fcfa91817480f589eb36e2Matthew Xie (device & AudioSystem.DEVICE_OUT_ALL_A2DP) != 0 && 978c9d1d5f35091226e96fcfa91817480f589eb36e2Matthew Xie (flags & AudioManager.FLAG_BLUETOOTH_ABS_VOLUME) == 0) { 979c9d1d5f35091226e96fcfa91817480f589eb36e2Matthew Xie synchronized (mA2dpAvrcpLock) { 980c9d1d5f35091226e96fcfa91817480f589eb36e2Matthew Xie if (mA2dp != null && mAvrcpAbsVolSupported) { 981c9d1d5f35091226e96fcfa91817480f589eb36e2Matthew Xie mA2dp.adjustAvrcpAbsoluteVolume(direction); 982c9d1d5f35091226e96fcfa91817480f589eb36e2Matthew Xie } 9835a0cf7a27f3953a1266af48543ccd9024f4cd89fJohn Du } 9845a0cf7a27f3953a1266af48543ccd9024f4cd89fJohn Du } 985c9d1d5f35091226e96fcfa91817480f589eb36e2Matthew Xie 98642b041ed4f184e3af7f788eb07307f556a2a6616Eric Laurent if ((direction == AudioManager.ADJUST_RAISE) && 98742b041ed4f184e3af7f788eb07307f556a2a6616Eric Laurent !checkSafeMediaVolume(streamTypeAlias, aliasIndex + step, device)) { 98842b041ed4f184e3af7f788eb07307f556a2a6616Eric Laurent Log.e(TAG, "adjustStreamVolume() safe volume index = "+oldIndex); 9893346a802087f621c6441bc512dfcc17b07143fc6John Spurlock mVolumeController.postDisplaySafeVolumeWarning(flags); 99042b041ed4f184e3af7f788eb07307f556a2a6616Eric Laurent } else if (streamState.adjustIndex(direction * step, device)) { 99142b041ed4f184e3af7f788eb07307f556a2a6616Eric Laurent // Post message to set system volume (it in turn will post a message 99242b041ed4f184e3af7f788eb07307f556a2a6616Eric Laurent // to persist). Do not change volume if stream is muted. 99342b041ed4f184e3af7f788eb07307f556a2a6616Eric Laurent sendMsg(mAudioHandler, 99442b041ed4f184e3af7f788eb07307f556a2a6616Eric Laurent MSG_SET_DEVICE_VOLUME, 99542b041ed4f184e3af7f788eb07307f556a2a6616Eric Laurent SENDMSG_QUEUE, 99642b041ed4f184e3af7f788eb07307f556a2a6616Eric Laurent device, 99742b041ed4f184e3af7f788eb07307f556a2a6616Eric Laurent 0, 99842b041ed4f184e3af7f788eb07307f556a2a6616Eric Laurent streamState, 99942b041ed4f184e3af7f788eb07307f556a2a6616Eric Laurent 0); 10004bbcc6549738f3d69831b2bd9eb4accec3e9920eEric Laurent } 100141d974631c5f525da49c88d34cecedd5a4cfeda8Jungshik Jang 100241d974631c5f525da49c88d34cecedd5a4cfeda8Jungshik Jang // Check if volume update should be send to Hdmi system audio. 100341d974631c5f525da49c88d34cecedd5a4cfeda8Jungshik Jang int newIndex = mStreamStates[streamType].getIndex(device); 100441d974631c5f525da49c88d34cecedd5a4cfeda8Jungshik Jang if (mHdmiTvClient != null && 100541d974631c5f525da49c88d34cecedd5a4cfeda8Jungshik Jang streamTypeAlias == AudioSystem.STREAM_MUSIC && 100641d974631c5f525da49c88d34cecedd5a4cfeda8Jungshik Jang (flags & AudioManager.FLAG_HDMI_SYSTEM_AUDIO_VOLUME) == 0 && 100741d974631c5f525da49c88d34cecedd5a4cfeda8Jungshik Jang oldIndex != newIndex) { 100841d974631c5f525da49c88d34cecedd5a4cfeda8Jungshik Jang int maxIndex = getStreamMaxVolume(streamType); 100941d974631c5f525da49c88d34cecedd5a4cfeda8Jungshik Jang synchronized (mHdmiTvClient) { 101041d974631c5f525da49c88d34cecedd5a4cfeda8Jungshik Jang if (mHdmiSystemAudioSupported) { 101141d974631c5f525da49c88d34cecedd5a4cfeda8Jungshik Jang mHdmiTvClient.setSystemAudioVolume( 101241d974631c5f525da49c88d34cecedd5a4cfeda8Jungshik Jang (oldIndex + 5) / 10, (newIndex + 5) / 10, maxIndex); 101341d974631c5f525da49c88d34cecedd5a4cfeda8Jungshik Jang } 101441d974631c5f525da49c88d34cecedd5a4cfeda8Jungshik Jang } 101541d974631c5f525da49c88d34cecedd5a4cfeda8Jungshik Jang } 10164bbcc6549738f3d69831b2bd9eb4accec3e9920eEric Laurent } 101742b041ed4f184e3af7f788eb07307f556a2a6616Eric Laurent int index = mStreamStates[streamType].getIndex(device); 101825101b0b9a84571ead15b26e9f4cd9c4298d7823Eric Laurent sendVolumeUpdate(streamType, oldIndex, index, flags); 10199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 10209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1021961cae92540763226648813d111c5b5c3b0f1597Dianne Hackborn /** @see AudioManager#adjustMasterVolume(int, int) */ 1022ba50b97cff80e73620a0e3d13cae169e095974a7Dianne Hackborn public void adjustMasterVolume(int steps, int flags, String callingPackage) { 102383a017b6b7c099d1a0293e5839be6477325aef06Eric Laurent if (mUseFixedVolume) { 102483a017b6b7c099d1a0293e5839be6477325aef06Eric Laurent return; 102583a017b6b7c099d1a0293e5839be6477325aef06Eric Laurent } 10266c798970ccb8759d1e613b57111daa8da0ab44c7Lei Zhang ensureValidSteps(steps); 10279760647dd0ee67e7c20f3e9d661d2006b1df0b54Mike Lockwood int volume = Math.round(AudioSystem.getMasterVolume() * MAX_MASTER_VOLUME); 10289760647dd0ee67e7c20f3e9d661d2006b1df0b54Mike Lockwood int delta = 0; 10296c798970ccb8759d1e613b57111daa8da0ab44c7Lei Zhang int numSteps = Math.abs(steps); 10306c798970ccb8759d1e613b57111daa8da0ab44c7Lei Zhang int direction = steps > 0 ? AudioManager.ADJUST_RAISE : AudioManager.ADJUST_LOWER; 10316c798970ccb8759d1e613b57111daa8da0ab44c7Lei Zhang for (int i = 0; i < numSteps; ++i) { 10326c798970ccb8759d1e613b57111daa8da0ab44c7Lei Zhang delta = findVolumeDelta(direction, volume); 10336c798970ccb8759d1e613b57111daa8da0ab44c7Lei Zhang volume += delta; 1034cbdb49dc5e1b993a0bc5c68dbfb9486bfa0cd762Mike Lockwood } 103524b082f87e96c00d5c17d60c735423900be40e70RoboErik 10366c798970ccb8759d1e613b57111daa8da0ab44c7Lei Zhang //Log.d(TAG, "adjustMasterVolume volume: " + volume + " steps: " + steps); 1037ba50b97cff80e73620a0e3d13cae169e095974a7Dianne Hackborn setMasterVolume(volume, flags, callingPackage); 1038cbdb49dc5e1b993a0bc5c68dbfb9486bfa0cd762Mike Lockwood } 1039cbdb49dc5e1b993a0bc5c68dbfb9486bfa0cd762Mike Lockwood 1040fde16d5879ea88a971004c984093409468b6139cEric Laurent // StreamVolumeCommand contains the information needed to defer the process of 1041fde16d5879ea88a971004c984093409468b6139cEric Laurent // setStreamVolume() in case the user has to acknowledge the safe volume warning message. 1042fde16d5879ea88a971004c984093409468b6139cEric Laurent class StreamVolumeCommand { 1043fde16d5879ea88a971004c984093409468b6139cEric Laurent public final int mStreamType; 1044fde16d5879ea88a971004c984093409468b6139cEric Laurent public final int mIndex; 1045fde16d5879ea88a971004c984093409468b6139cEric Laurent public final int mFlags; 1046fde16d5879ea88a971004c984093409468b6139cEric Laurent public final int mDevice; 10473ef7549876a159dae1568429edcb57e4e7d08459Eric Laurent 1048fde16d5879ea88a971004c984093409468b6139cEric Laurent StreamVolumeCommand(int streamType, int index, int flags, int device) { 1049fde16d5879ea88a971004c984093409468b6139cEric Laurent mStreamType = streamType; 1050fde16d5879ea88a971004c984093409468b6139cEric Laurent mIndex = index; 1051fde16d5879ea88a971004c984093409468b6139cEric Laurent mFlags = flags; 1052fde16d5879ea88a971004c984093409468b6139cEric Laurent mDevice = device; 10534bbcc6549738f3d69831b2bd9eb4accec3e9920eEric Laurent } 1054fde16d5879ea88a971004c984093409468b6139cEric Laurent }; 10553ef7549876a159dae1568429edcb57e4e7d08459Eric Laurent 1056fde16d5879ea88a971004c984093409468b6139cEric Laurent private void onSetStreamVolume(int streamType, int index, int flags, int device) { 105742b041ed4f184e3af7f788eb07307f556a2a6616Eric Laurent setStreamVolumeInt(mStreamVolumeAlias[streamType], index, device, false); 10583ef7549876a159dae1568429edcb57e4e7d08459Eric Laurent // setting volume on master stream type also controls silent mode 10593ef7549876a159dae1568429edcb57e4e7d08459Eric Laurent if (((flags & AudioManager.FLAG_ALLOW_RINGER_MODES) != 0) || 10603ef7549876a159dae1568429edcb57e4e7d08459Eric Laurent (mStreamVolumeAlias[streamType] == getMasterStreamType())) { 10613ef7549876a159dae1568429edcb57e4e7d08459Eric Laurent int newRingerMode; 10623ef7549876a159dae1568429edcb57e4e7d08459Eric Laurent if (index == 0) { 10633ef7549876a159dae1568429edcb57e4e7d08459Eric Laurent newRingerMode = mHasVibrator ? AudioManager.RINGER_MODE_VIBRATE 10648600534df66c2ff5846ed230b50c56229322d48aJohn Spurlock : VOLUME_SETS_RINGER_MODE_SILENT ? AudioManager.RINGER_MODE_SILENT 10658600534df66c2ff5846ed230b50c56229322d48aJohn Spurlock : AudioManager.RINGER_MODE_NORMAL; 10663ef7549876a159dae1568429edcb57e4e7d08459Eric Laurent } else { 10673ef7549876a159dae1568429edcb57e4e7d08459Eric Laurent newRingerMode = AudioManager.RINGER_MODE_NORMAL; 10683ef7549876a159dae1568429edcb57e4e7d08459Eric Laurent } 10693ef7549876a159dae1568429edcb57e4e7d08459Eric Laurent setRingerMode(newRingerMode); 10703ef7549876a159dae1568429edcb57e4e7d08459Eric Laurent } 1071fde16d5879ea88a971004c984093409468b6139cEric Laurent } 1072fde16d5879ea88a971004c984093409468b6139cEric Laurent 1073fde16d5879ea88a971004c984093409468b6139cEric Laurent /** @see AudioManager#setStreamVolume(int, int, int) */ 1074ba50b97cff80e73620a0e3d13cae169e095974a7Dianne Hackborn public void setStreamVolume(int streamType, int index, int flags, String callingPackage) { 107583a017b6b7c099d1a0293e5839be6477325aef06Eric Laurent if (mUseFixedVolume) { 107683a017b6b7c099d1a0293e5839be6477325aef06Eric Laurent return; 107783a017b6b7c099d1a0293e5839be6477325aef06Eric Laurent } 107883a017b6b7c099d1a0293e5839be6477325aef06Eric Laurent 1079fde16d5879ea88a971004c984093409468b6139cEric Laurent ensureValidStreamType(streamType); 1080ba50b97cff80e73620a0e3d13cae169e095974a7Dianne Hackborn int streamTypeAlias = mStreamVolumeAlias[streamType]; 1081ba50b97cff80e73620a0e3d13cae169e095974a7Dianne Hackborn VolumeStreamState streamState = mStreamStates[streamTypeAlias]; 1082fde16d5879ea88a971004c984093409468b6139cEric Laurent 1083fde16d5879ea88a971004c984093409468b6139cEric Laurent final int device = getDeviceForStream(streamType); 1084fde16d5879ea88a971004c984093409468b6139cEric Laurent int oldIndex; 1085fde16d5879ea88a971004c984093409468b6139cEric Laurent 1086c9d1d5f35091226e96fcfa91817480f589eb36e2Matthew Xie // skip a2dp absolute volume control request when the device 1087c9d1d5f35091226e96fcfa91817480f589eb36e2Matthew Xie // is not an a2dp device 1088c9d1d5f35091226e96fcfa91817480f589eb36e2Matthew Xie if ((device & AudioSystem.DEVICE_OUT_ALL_A2DP) == 0 && 1089c9d1d5f35091226e96fcfa91817480f589eb36e2Matthew Xie (flags & AudioManager.FLAG_BLUETOOTH_ABS_VOLUME) != 0) { 1090c9d1d5f35091226e96fcfa91817480f589eb36e2Matthew Xie return; 1091c9d1d5f35091226e96fcfa91817480f589eb36e2Matthew Xie } 1092c9d1d5f35091226e96fcfa91817480f589eb36e2Matthew Xie 1093ba50b97cff80e73620a0e3d13cae169e095974a7Dianne Hackborn if (mAppOps.noteOp(STEAM_VOLUME_OPS[streamTypeAlias], Binder.getCallingUid(), 1094ba50b97cff80e73620a0e3d13cae169e095974a7Dianne Hackborn callingPackage) != AppOpsManager.MODE_ALLOWED) { 1095ba50b97cff80e73620a0e3d13cae169e095974a7Dianne Hackborn return; 1096ba50b97cff80e73620a0e3d13cae169e095974a7Dianne Hackborn } 1097ba50b97cff80e73620a0e3d13cae169e095974a7Dianne Hackborn 1098fde16d5879ea88a971004c984093409468b6139cEric Laurent synchronized (mSafeMediaVolumeState) { 1099fde16d5879ea88a971004c984093409468b6139cEric Laurent // reset any pending volume command 1100fde16d5879ea88a971004c984093409468b6139cEric Laurent mPendingVolumeCommand = null; 1101fde16d5879ea88a971004c984093409468b6139cEric Laurent 110242b041ed4f184e3af7f788eb07307f556a2a6616Eric Laurent oldIndex = streamState.getIndex(device); 1103fde16d5879ea88a971004c984093409468b6139cEric Laurent 1104ba50b97cff80e73620a0e3d13cae169e095974a7Dianne Hackborn index = rescaleIndex(index * 10, streamType, streamTypeAlias); 1105fde16d5879ea88a971004c984093409468b6139cEric Laurent 1106c9d1d5f35091226e96fcfa91817480f589eb36e2Matthew Xie if (streamTypeAlias == AudioSystem.STREAM_MUSIC && 1107c9d1d5f35091226e96fcfa91817480f589eb36e2Matthew Xie (device & AudioSystem.DEVICE_OUT_ALL_A2DP) != 0 && 1108c9d1d5f35091226e96fcfa91817480f589eb36e2Matthew Xie (flags & AudioManager.FLAG_BLUETOOTH_ABS_VOLUME) == 0) { 1109c9d1d5f35091226e96fcfa91817480f589eb36e2Matthew Xie synchronized (mA2dpAvrcpLock) { 1110c9d1d5f35091226e96fcfa91817480f589eb36e2Matthew Xie if (mA2dp != null && mAvrcpAbsVolSupported) { 11112f4a2b139b4c1dde7be1d14333ad02553734c528Zhihai Xu mA2dp.setAvrcpAbsoluteVolume(index / 10); 1112c9d1d5f35091226e96fcfa91817480f589eb36e2Matthew Xie } 11135a0cf7a27f3953a1266af48543ccd9024f4cd89fJohn Du } 11145a0cf7a27f3953a1266af48543ccd9024f4cd89fJohn Du } 11155a0cf7a27f3953a1266af48543ccd9024f4cd89fJohn Du 111641d974631c5f525da49c88d34cecedd5a4cfeda8Jungshik Jang if (mHdmiTvClient != null && 111741d974631c5f525da49c88d34cecedd5a4cfeda8Jungshik Jang streamTypeAlias == AudioSystem.STREAM_MUSIC && 111841d974631c5f525da49c88d34cecedd5a4cfeda8Jungshik Jang (flags & AudioManager.FLAG_HDMI_SYSTEM_AUDIO_VOLUME) == 0 && 111941d974631c5f525da49c88d34cecedd5a4cfeda8Jungshik Jang oldIndex != index) { 112041d974631c5f525da49c88d34cecedd5a4cfeda8Jungshik Jang int maxIndex = getStreamMaxVolume(streamType); 112141d974631c5f525da49c88d34cecedd5a4cfeda8Jungshik Jang synchronized (mHdmiTvClient) { 112241d974631c5f525da49c88d34cecedd5a4cfeda8Jungshik Jang if (mHdmiSystemAudioSupported) { 112341d974631c5f525da49c88d34cecedd5a4cfeda8Jungshik Jang mHdmiTvClient.setSystemAudioVolume( 112441d974631c5f525da49c88d34cecedd5a4cfeda8Jungshik Jang (oldIndex + 5) / 10, (index + 5) / 10, maxIndex); 112541d974631c5f525da49c88d34cecedd5a4cfeda8Jungshik Jang } 112641d974631c5f525da49c88d34cecedd5a4cfeda8Jungshik Jang } 112741d974631c5f525da49c88d34cecedd5a4cfeda8Jungshik Jang } 112841d974631c5f525da49c88d34cecedd5a4cfeda8Jungshik Jang 1129fde16d5879ea88a971004c984093409468b6139cEric Laurent flags &= ~AudioManager.FLAG_FIXED_VOLUME; 1130ba50b97cff80e73620a0e3d13cae169e095974a7Dianne Hackborn if ((streamTypeAlias == AudioSystem.STREAM_MUSIC) && 1131fde16d5879ea88a971004c984093409468b6139cEric Laurent ((device & mFixedVolumeDevices) != 0)) { 1132fde16d5879ea88a971004c984093409468b6139cEric Laurent flags |= AudioManager.FLAG_FIXED_VOLUME; 1133fde16d5879ea88a971004c984093409468b6139cEric Laurent 1134fde16d5879ea88a971004c984093409468b6139cEric Laurent // volume is either 0 or max allowed for fixed volume devices 1135fde16d5879ea88a971004c984093409468b6139cEric Laurent if (index != 0) { 1136fde16d5879ea88a971004c984093409468b6139cEric Laurent if (mSafeMediaVolumeState == SAFE_MEDIA_VOLUME_ACTIVE && 1137fde16d5879ea88a971004c984093409468b6139cEric Laurent (device & mSafeMediaVolumeDevices) != 0) { 1138fde16d5879ea88a971004c984093409468b6139cEric Laurent index = mSafeMediaVolumeIndex; 1139fde16d5879ea88a971004c984093409468b6139cEric Laurent } else { 1140fde16d5879ea88a971004c984093409468b6139cEric Laurent index = streamState.getMaxIndex(); 1141fde16d5879ea88a971004c984093409468b6139cEric Laurent } 1142fde16d5879ea88a971004c984093409468b6139cEric Laurent } 1143fde16d5879ea88a971004c984093409468b6139cEric Laurent } 1144fde16d5879ea88a971004c984093409468b6139cEric Laurent 1145ba50b97cff80e73620a0e3d13cae169e095974a7Dianne Hackborn if (!checkSafeMediaVolume(streamTypeAlias, index, device)) { 11463346a802087f621c6441bc512dfcc17b07143fc6John Spurlock mVolumeController.postDisplaySafeVolumeWarning(flags); 1147fde16d5879ea88a971004c984093409468b6139cEric Laurent mPendingVolumeCommand = new StreamVolumeCommand( 1148fde16d5879ea88a971004c984093409468b6139cEric Laurent streamType, index, flags, device); 1149fde16d5879ea88a971004c984093409468b6139cEric Laurent } else { 1150fde16d5879ea88a971004c984093409468b6139cEric Laurent onSetStreamVolume(streamType, index, flags, device); 115142b041ed4f184e3af7f788eb07307f556a2a6616Eric Laurent index = mStreamStates[streamType].getIndex(device); 1152fde16d5879ea88a971004c984093409468b6139cEric Laurent } 1153fde16d5879ea88a971004c984093409468b6139cEric Laurent } 115425101b0b9a84571ead15b26e9f4cd9c4298d7823Eric Laurent sendVolumeUpdate(streamType, oldIndex, index, flags); 11559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 11569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 115745c90cefd13a03b852bb4b8da4be218876cbbb32Eric Laurent /** @see AudioManager#forceVolumeControlStream(int) */ 115845c90cefd13a03b852bb4b8da4be218876cbbb32Eric Laurent public void forceVolumeControlStream(int streamType, IBinder cb) { 115945c90cefd13a03b852bb4b8da4be218876cbbb32Eric Laurent synchronized(mForceControlStreamLock) { 116045c90cefd13a03b852bb4b8da4be218876cbbb32Eric Laurent mVolumeControlStream = streamType; 116145c90cefd13a03b852bb4b8da4be218876cbbb32Eric Laurent if (mVolumeControlStream == -1) { 116245c90cefd13a03b852bb4b8da4be218876cbbb32Eric Laurent if (mForceControlStreamClient != null) { 116345c90cefd13a03b852bb4b8da4be218876cbbb32Eric Laurent mForceControlStreamClient.release(); 116445c90cefd13a03b852bb4b8da4be218876cbbb32Eric Laurent mForceControlStreamClient = null; 116545c90cefd13a03b852bb4b8da4be218876cbbb32Eric Laurent } 116645c90cefd13a03b852bb4b8da4be218876cbbb32Eric Laurent } else { 116745c90cefd13a03b852bb4b8da4be218876cbbb32Eric Laurent mForceControlStreamClient = new ForceControlStreamClient(cb); 116845c90cefd13a03b852bb4b8da4be218876cbbb32Eric Laurent } 116945c90cefd13a03b852bb4b8da4be218876cbbb32Eric Laurent } 117045c90cefd13a03b852bb4b8da4be218876cbbb32Eric Laurent } 117145c90cefd13a03b852bb4b8da4be218876cbbb32Eric Laurent 117245c90cefd13a03b852bb4b8da4be218876cbbb32Eric Laurent private class ForceControlStreamClient implements IBinder.DeathRecipient { 117345c90cefd13a03b852bb4b8da4be218876cbbb32Eric Laurent private IBinder mCb; // To be notified of client's death 117445c90cefd13a03b852bb4b8da4be218876cbbb32Eric Laurent 117545c90cefd13a03b852bb4b8da4be218876cbbb32Eric Laurent ForceControlStreamClient(IBinder cb) { 117645c90cefd13a03b852bb4b8da4be218876cbbb32Eric Laurent if (cb != null) { 117745c90cefd13a03b852bb4b8da4be218876cbbb32Eric Laurent try { 117845c90cefd13a03b852bb4b8da4be218876cbbb32Eric Laurent cb.linkToDeath(this, 0); 117945c90cefd13a03b852bb4b8da4be218876cbbb32Eric Laurent } catch (RemoteException e) { 118045c90cefd13a03b852bb4b8da4be218876cbbb32Eric Laurent // Client has died! 118145c90cefd13a03b852bb4b8da4be218876cbbb32Eric Laurent Log.w(TAG, "ForceControlStreamClient() could not link to "+cb+" binder death"); 118245c90cefd13a03b852bb4b8da4be218876cbbb32Eric Laurent cb = null; 118345c90cefd13a03b852bb4b8da4be218876cbbb32Eric Laurent } 118445c90cefd13a03b852bb4b8da4be218876cbbb32Eric Laurent } 118545c90cefd13a03b852bb4b8da4be218876cbbb32Eric Laurent mCb = cb; 118645c90cefd13a03b852bb4b8da4be218876cbbb32Eric Laurent } 118745c90cefd13a03b852bb4b8da4be218876cbbb32Eric Laurent 118845c90cefd13a03b852bb4b8da4be218876cbbb32Eric Laurent public void binderDied() { 118945c90cefd13a03b852bb4b8da4be218876cbbb32Eric Laurent synchronized(mForceControlStreamLock) { 119045c90cefd13a03b852bb4b8da4be218876cbbb32Eric Laurent Log.w(TAG, "SCO client died"); 119145c90cefd13a03b852bb4b8da4be218876cbbb32Eric Laurent if (mForceControlStreamClient != this) { 119245c90cefd13a03b852bb4b8da4be218876cbbb32Eric Laurent Log.w(TAG, "unregistered control stream client died"); 119345c90cefd13a03b852bb4b8da4be218876cbbb32Eric Laurent } else { 119445c90cefd13a03b852bb4b8da4be218876cbbb32Eric Laurent mForceControlStreamClient = null; 119545c90cefd13a03b852bb4b8da4be218876cbbb32Eric Laurent mVolumeControlStream = -1; 119645c90cefd13a03b852bb4b8da4be218876cbbb32Eric Laurent } 119745c90cefd13a03b852bb4b8da4be218876cbbb32Eric Laurent } 119845c90cefd13a03b852bb4b8da4be218876cbbb32Eric Laurent } 119945c90cefd13a03b852bb4b8da4be218876cbbb32Eric Laurent 120045c90cefd13a03b852bb4b8da4be218876cbbb32Eric Laurent public void release() { 120145c90cefd13a03b852bb4b8da4be218876cbbb32Eric Laurent if (mCb != null) { 120245c90cefd13a03b852bb4b8da4be218876cbbb32Eric Laurent mCb.unlinkToDeath(this, 0); 120345c90cefd13a03b852bb4b8da4be218876cbbb32Eric Laurent mCb = null; 120445c90cefd13a03b852bb4b8da4be218876cbbb32Eric Laurent } 120545c90cefd13a03b852bb4b8da4be218876cbbb32Eric Laurent } 120645c90cefd13a03b852bb4b8da4be218876cbbb32Eric Laurent } 120745c90cefd13a03b852bb4b8da4be218876cbbb32Eric Laurent 12086c798970ccb8759d1e613b57111daa8da0ab44c7Lei Zhang private int findVolumeDelta(int direction, int volume) { 12096c798970ccb8759d1e613b57111daa8da0ab44c7Lei Zhang int delta = 0; 12106c798970ccb8759d1e613b57111daa8da0ab44c7Lei Zhang if (direction == AudioManager.ADJUST_RAISE) { 12116c798970ccb8759d1e613b57111daa8da0ab44c7Lei Zhang if (volume == MAX_MASTER_VOLUME) { 12126c798970ccb8759d1e613b57111daa8da0ab44c7Lei Zhang return 0; 12136c798970ccb8759d1e613b57111daa8da0ab44c7Lei Zhang } 12146c798970ccb8759d1e613b57111daa8da0ab44c7Lei Zhang // This is the default value if we make it to the end 12156c798970ccb8759d1e613b57111daa8da0ab44c7Lei Zhang delta = mMasterVolumeRamp[1]; 12166c798970ccb8759d1e613b57111daa8da0ab44c7Lei Zhang // If we're raising the volume move down the ramp array until we 12176c798970ccb8759d1e613b57111daa8da0ab44c7Lei Zhang // find the volume we're above and use that groups delta. 12186c798970ccb8759d1e613b57111daa8da0ab44c7Lei Zhang for (int i = mMasterVolumeRamp.length - 1; i > 1; i -= 2) { 12196c798970ccb8759d1e613b57111daa8da0ab44c7Lei Zhang if (volume >= mMasterVolumeRamp[i - 1]) { 12206c798970ccb8759d1e613b57111daa8da0ab44c7Lei Zhang delta = mMasterVolumeRamp[i]; 12216c798970ccb8759d1e613b57111daa8da0ab44c7Lei Zhang break; 12226c798970ccb8759d1e613b57111daa8da0ab44c7Lei Zhang } 12236c798970ccb8759d1e613b57111daa8da0ab44c7Lei Zhang } 12246c798970ccb8759d1e613b57111daa8da0ab44c7Lei Zhang } else if (direction == AudioManager.ADJUST_LOWER){ 12256c798970ccb8759d1e613b57111daa8da0ab44c7Lei Zhang if (volume == 0) { 12266c798970ccb8759d1e613b57111daa8da0ab44c7Lei Zhang return 0; 12276c798970ccb8759d1e613b57111daa8da0ab44c7Lei Zhang } 12286c798970ccb8759d1e613b57111daa8da0ab44c7Lei Zhang int length = mMasterVolumeRamp.length; 12296c798970ccb8759d1e613b57111daa8da0ab44c7Lei Zhang // This is the default value if we make it to the end 12306c798970ccb8759d1e613b57111daa8da0ab44c7Lei Zhang delta = -mMasterVolumeRamp[length - 1]; 12316c798970ccb8759d1e613b57111daa8da0ab44c7Lei Zhang // If we're lowering the volume move up the ramp array until we 12326c798970ccb8759d1e613b57111daa8da0ab44c7Lei Zhang // find the volume we're below and use the group below it's delta 12336c798970ccb8759d1e613b57111daa8da0ab44c7Lei Zhang for (int i = 2; i < length; i += 2) { 12346c798970ccb8759d1e613b57111daa8da0ab44c7Lei Zhang if (volume <= mMasterVolumeRamp[i]) { 12356c798970ccb8759d1e613b57111daa8da0ab44c7Lei Zhang delta = -mMasterVolumeRamp[i - 1]; 12366c798970ccb8759d1e613b57111daa8da0ab44c7Lei Zhang break; 12376c798970ccb8759d1e613b57111daa8da0ab44c7Lei Zhang } 12386c798970ccb8759d1e613b57111daa8da0ab44c7Lei Zhang } 12396c798970ccb8759d1e613b57111daa8da0ab44c7Lei Zhang } 12406c798970ccb8759d1e613b57111daa8da0ab44c7Lei Zhang return delta; 12416c798970ccb8759d1e613b57111daa8da0ab44c7Lei Zhang } 12426c798970ccb8759d1e613b57111daa8da0ab44c7Lei Zhang 12435ac72a29593ab9a20337a2225df52bdf4754be02Dianne Hackborn private void sendBroadcastToAll(Intent intent) { 12445ac72a29593ab9a20337a2225df52bdf4754be02Dianne Hackborn final long ident = Binder.clearCallingIdentity(); 12455ac72a29593ab9a20337a2225df52bdf4754be02Dianne Hackborn try { 12465ac72a29593ab9a20337a2225df52bdf4754be02Dianne Hackborn mContext.sendBroadcastAsUser(intent, UserHandle.ALL); 12475ac72a29593ab9a20337a2225df52bdf4754be02Dianne Hackborn } finally { 12485ac72a29593ab9a20337a2225df52bdf4754be02Dianne Hackborn Binder.restoreCallingIdentity(ident); 12495ac72a29593ab9a20337a2225df52bdf4754be02Dianne Hackborn } 12505ac72a29593ab9a20337a2225df52bdf4754be02Dianne Hackborn } 12515ac72a29593ab9a20337a2225df52bdf4754be02Dianne Hackborn 12525ac72a29593ab9a20337a2225df52bdf4754be02Dianne Hackborn private void sendStickyBroadcastToAll(Intent intent) { 12535ac72a29593ab9a20337a2225df52bdf4754be02Dianne Hackborn final long ident = Binder.clearCallingIdentity(); 12545ac72a29593ab9a20337a2225df52bdf4754be02Dianne Hackborn try { 12555ac72a29593ab9a20337a2225df52bdf4754be02Dianne Hackborn mContext.sendStickyBroadcastAsUser(intent, UserHandle.ALL); 12565ac72a29593ab9a20337a2225df52bdf4754be02Dianne Hackborn } finally { 12575ac72a29593ab9a20337a2225df52bdf4754be02Dianne Hackborn Binder.restoreCallingIdentity(ident); 12585ac72a29593ab9a20337a2225df52bdf4754be02Dianne Hackborn } 12595ac72a29593ab9a20337a2225df52bdf4754be02Dianne Hackborn } 12605ac72a29593ab9a20337a2225df52bdf4754be02Dianne Hackborn 126125101b0b9a84571ead15b26e9f4cd9c4298d7823Eric Laurent // UI update and Broadcast Intent 126225101b0b9a84571ead15b26e9f4cd9c4298d7823Eric Laurent private void sendVolumeUpdate(int streamType, int oldIndex, int index, int flags) { 126325101b0b9a84571ead15b26e9f4cd9c4298d7823Eric Laurent if (!mVoiceCapable && (streamType == AudioSystem.STREAM_RING)) { 126425101b0b9a84571ead15b26e9f4cd9c4298d7823Eric Laurent streamType = AudioSystem.STREAM_NOTIFICATION; 126525101b0b9a84571ead15b26e9f4cd9c4298d7823Eric Laurent } 126625101b0b9a84571ead15b26e9f4cd9c4298d7823Eric Laurent 12673346a802087f621c6441bc512dfcc17b07143fc6John Spurlock mVolumeController.postVolumeChanged(streamType, flags); 126825101b0b9a84571ead15b26e9f4cd9c4298d7823Eric Laurent 12694bbcc6549738f3d69831b2bd9eb4accec3e9920eEric Laurent if ((flags & AudioManager.FLAG_FIXED_VOLUME) == 0) { 12704bbcc6549738f3d69831b2bd9eb4accec3e9920eEric Laurent oldIndex = (oldIndex + 5) / 10; 12714bbcc6549738f3d69831b2bd9eb4accec3e9920eEric Laurent index = (index + 5) / 10; 12724bbcc6549738f3d69831b2bd9eb4accec3e9920eEric Laurent Intent intent = new Intent(AudioManager.VOLUME_CHANGED_ACTION); 12734bbcc6549738f3d69831b2bd9eb4accec3e9920eEric Laurent intent.putExtra(AudioManager.EXTRA_VOLUME_STREAM_TYPE, streamType); 12744bbcc6549738f3d69831b2bd9eb4accec3e9920eEric Laurent intent.putExtra(AudioManager.EXTRA_VOLUME_STREAM_VALUE, index); 12754bbcc6549738f3d69831b2bd9eb4accec3e9920eEric Laurent intent.putExtra(AudioManager.EXTRA_PREV_VOLUME_STREAM_VALUE, oldIndex); 12764bbcc6549738f3d69831b2bd9eb4accec3e9920eEric Laurent sendBroadcastToAll(intent); 12774bbcc6549738f3d69831b2bd9eb4accec3e9920eEric Laurent } 12789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 12799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 12800dc37cce9d564ae43883c8dc8672b9266b881e63Mike Lockwood // UI update and Broadcast Intent 12810dc37cce9d564ae43883c8dc8672b9266b881e63Mike Lockwood private void sendMasterVolumeUpdate(int flags, int oldVolume, int newVolume) { 12823346a802087f621c6441bc512dfcc17b07143fc6John Spurlock mVolumeController.postMasterVolumeChanged(flags); 12830dc37cce9d564ae43883c8dc8672b9266b881e63Mike Lockwood 12840dc37cce9d564ae43883c8dc8672b9266b881e63Mike Lockwood Intent intent = new Intent(AudioManager.MASTER_VOLUME_CHANGED_ACTION); 12850dc37cce9d564ae43883c8dc8672b9266b881e63Mike Lockwood intent.putExtra(AudioManager.EXTRA_PREV_MASTER_VOLUME_VALUE, oldVolume); 12860dc37cce9d564ae43883c8dc8672b9266b881e63Mike Lockwood intent.putExtra(AudioManager.EXTRA_MASTER_VOLUME_VALUE, newVolume); 12875ac72a29593ab9a20337a2225df52bdf4754be02Dianne Hackborn sendBroadcastToAll(intent); 12880dc37cce9d564ae43883c8dc8672b9266b881e63Mike Lockwood } 12890dc37cce9d564ae43883c8dc8672b9266b881e63Mike Lockwood 12900dc37cce9d564ae43883c8dc8672b9266b881e63Mike Lockwood // UI update and Broadcast Intent 12910dc37cce9d564ae43883c8dc8672b9266b881e63Mike Lockwood private void sendMasterMuteUpdate(boolean muted, int flags) { 12923346a802087f621c6441bc512dfcc17b07143fc6John Spurlock mVolumeController.postMasterMuteChanged(flags); 129357978ed86286a33d5b1a0fd000ca3406ba9d87b3Justin Koh broadcastMasterMuteStatus(muted); 129457978ed86286a33d5b1a0fd000ca3406ba9d87b3Justin Koh } 12950dc37cce9d564ae43883c8dc8672b9266b881e63Mike Lockwood 129657978ed86286a33d5b1a0fd000ca3406ba9d87b3Justin Koh private void broadcastMasterMuteStatus(boolean muted) { 12970dc37cce9d564ae43883c8dc8672b9266b881e63Mike Lockwood Intent intent = new Intent(AudioManager.MASTER_MUTE_CHANGED_ACTION); 12980dc37cce9d564ae43883c8dc8672b9266b881e63Mike Lockwood intent.putExtra(AudioManager.EXTRA_MASTER_VOLUME_MUTED, muted); 129957978ed86286a33d5b1a0fd000ca3406ba9d87b3Justin Koh intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT 130057978ed86286a33d5b1a0fd000ca3406ba9d87b3Justin Koh | Intent.FLAG_RECEIVER_REPLACE_PENDING); 13015ac72a29593ab9a20337a2225df52bdf4754be02Dianne Hackborn sendStickyBroadcastToAll(intent); 13020dc37cce9d564ae43883c8dc8672b9266b881e63Mike Lockwood } 13030dc37cce9d564ae43883c8dc8672b9266b881e63Mike Lockwood 13049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 13059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Sets the stream state's index, and posts a message to set system volume. 13069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * This will not call out to the UI. Assumes a valid stream type. 13079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 13089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param streamType Type of the stream 13099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param index Desired volume index of the stream 13109bc8358ddaa01c3490f9709991989633a6a3dd42Eric Laurent * @param device the device whose volume must be changed 13119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param force If true, set the volume even if the desired volume is same 13129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * as the current volume. 13139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 13149bc8358ddaa01c3490f9709991989633a6a3dd42Eric Laurent private void setStreamVolumeInt(int streamType, 13159bc8358ddaa01c3490f9709991989633a6a3dd42Eric Laurent int index, 13169bc8358ddaa01c3490f9709991989633a6a3dd42Eric Laurent int device, 131742b041ed4f184e3af7f788eb07307f556a2a6616Eric Laurent boolean force) { 13189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project VolumeStreamState streamState = mStreamStates[streamType]; 13195b4e654d0c7de8e4d58d73e73b0d5220f19b68f7Eric Laurent 132042b041ed4f184e3af7f788eb07307f556a2a6616Eric Laurent if (streamState.setIndex(index, device) || force) { 132142b041ed4f184e3af7f788eb07307f556a2a6616Eric Laurent // Post message to set system volume (it in turn will post a message 132242b041ed4f184e3af7f788eb07307f556a2a6616Eric Laurent // to persist). 132342b041ed4f184e3af7f788eb07307f556a2a6616Eric Laurent sendMsg(mAudioHandler, 132442b041ed4f184e3af7f788eb07307f556a2a6616Eric Laurent MSG_SET_DEVICE_VOLUME, 132542b041ed4f184e3af7f788eb07307f556a2a6616Eric Laurent SENDMSG_QUEUE, 132642b041ed4f184e3af7f788eb07307f556a2a6616Eric Laurent device, 132742b041ed4f184e3af7f788eb07307f556a2a6616Eric Laurent 0, 132842b041ed4f184e3af7f788eb07307f556a2a6616Eric Laurent streamState, 132942b041ed4f184e3af7f788eb07307f556a2a6616Eric Laurent 0); 13309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 13319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 13329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 13339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** @see AudioManager#setStreamSolo(int, boolean) */ 13349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public void setStreamSolo(int streamType, boolean state, IBinder cb) { 133583a017b6b7c099d1a0293e5839be6477325aef06Eric Laurent if (mUseFixedVolume) { 133683a017b6b7c099d1a0293e5839be6477325aef06Eric Laurent return; 133783a017b6b7c099d1a0293e5839be6477325aef06Eric Laurent } 133883a017b6b7c099d1a0293e5839be6477325aef06Eric Laurent 13399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project for (int stream = 0; stream < mStreamStates.length; stream++) { 13409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (!isStreamAffectedByMute(stream) || stream == streamType) continue; 13419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mStreamStates[stream].mute(cb, state); 13429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 13439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 13449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 13459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** @see AudioManager#setStreamMute(int, boolean) */ 13469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public void setStreamMute(int streamType, boolean state, IBinder cb) { 134783a017b6b7c099d1a0293e5839be6477325aef06Eric Laurent if (mUseFixedVolume) { 134883a017b6b7c099d1a0293e5839be6477325aef06Eric Laurent return; 134983a017b6b7c099d1a0293e5839be6477325aef06Eric Laurent } 135083a017b6b7c099d1a0293e5839be6477325aef06Eric Laurent 13519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (isStreamAffectedByMute(streamType)) { 135241d974631c5f525da49c88d34cecedd5a4cfeda8Jungshik Jang if (streamType == AudioSystem.STREAM_MUSIC && mHdmiTvClient != null) { 135341d974631c5f525da49c88d34cecedd5a4cfeda8Jungshik Jang synchronized (mHdmiTvClient) { 135441d974631c5f525da49c88d34cecedd5a4cfeda8Jungshik Jang if (mHdmiSystemAudioSupported) { 135541d974631c5f525da49c88d34cecedd5a4cfeda8Jungshik Jang mHdmiTvClient.setSystemAudioMute(state); 135641d974631c5f525da49c88d34cecedd5a4cfeda8Jungshik Jang } 135741d974631c5f525da49c88d34cecedd5a4cfeda8Jungshik Jang } 135841d974631c5f525da49c88d34cecedd5a4cfeda8Jungshik Jang } 13599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mStreamStates[streamType].mute(cb, state); 13609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 13619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 13629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 136325101b0b9a84571ead15b26e9f4cd9c4298d7823Eric Laurent /** get stream mute state. */ 136425101b0b9a84571ead15b26e9f4cd9c4298d7823Eric Laurent public boolean isStreamMute(int streamType) { 136542b041ed4f184e3af7f788eb07307f556a2a6616Eric Laurent return mStreamStates[streamType].isMuted(); 136625101b0b9a84571ead15b26e9f4cd9c4298d7823Eric Laurent } 136725101b0b9a84571ead15b26e9f4cd9c4298d7823Eric Laurent 1368961cae92540763226648813d111c5b5c3b0f1597Dianne Hackborn /** @see AudioManager#setMasterMute(boolean, int) */ 13694a21b25fad62e4f19d13ba814263841c931f56efJulia Reynolds public void setMasterMute(boolean state, int flags, String callingPackage, IBinder cb) { 137083a017b6b7c099d1a0293e5839be6477325aef06Eric Laurent if (mUseFixedVolume) { 137183a017b6b7c099d1a0293e5839be6477325aef06Eric Laurent return; 137283a017b6b7c099d1a0293e5839be6477325aef06Eric Laurent } 137383a017b6b7c099d1a0293e5839be6477325aef06Eric Laurent 13744a21b25fad62e4f19d13ba814263841c931f56efJulia Reynolds if (mAppOps.noteOp(AppOpsManager.OP_AUDIO_MASTER_VOLUME, Binder.getCallingUid(), 13754a21b25fad62e4f19d13ba814263841c931f56efJulia Reynolds callingPackage) != AppOpsManager.MODE_ALLOWED) { 13764a21b25fad62e4f19d13ba814263841c931f56efJulia Reynolds return; 13774a21b25fad62e4f19d13ba814263841c931f56efJulia Reynolds } 13784a21b25fad62e4f19d13ba814263841c931f56efJulia Reynolds 13791ce5b26d707e0086e09af3cd0428f1b441145261Jason Simmons if (state != AudioSystem.getMasterMute()) { 13801ce5b26d707e0086e09af3cd0428f1b441145261Jason Simmons AudioSystem.setMasterMute(state); 138157978ed86286a33d5b1a0fd000ca3406ba9d87b3Justin Koh // Post a persist master volume msg 138275cf9e19a575c28c200c02c0ab6f83bb79f5c50dJustin Koh sendMsg(mAudioHandler, MSG_PERSIST_MASTER_VOLUME_MUTE, SENDMSG_REPLACE, state ? 1 138357978ed86286a33d5b1a0fd000ca3406ba9d87b3Justin Koh : 0, 0, null, PERSIST_DELAY); 13840273af55cf68d54d26d154b44d105d40fed79701Justin Koh sendMasterMuteUpdate(state, flags); 13851ce5b26d707e0086e09af3cd0428f1b441145261Jason Simmons } 1386ce952c8e13c535bedde77bcdb94dfcc7508475aaMike Lockwood } 1387ce952c8e13c535bedde77bcdb94dfcc7508475aaMike Lockwood 1388ce952c8e13c535bedde77bcdb94dfcc7508475aaMike Lockwood /** get master mute state. */ 1389ce952c8e13c535bedde77bcdb94dfcc7508475aaMike Lockwood public boolean isMasterMute() { 13903194ea94348bce8e7ee9f803698d877f46f8279aMike Lockwood return AudioSystem.getMasterMute(); 1391ce952c8e13c535bedde77bcdb94dfcc7508475aaMike Lockwood } 1392ce952c8e13c535bedde77bcdb94dfcc7508475aaMike Lockwood 1393fa9a69805b001034aa04c3b33989a7ac21522371Jean-Michel Trivi protected static int getMaxStreamVolume(int streamType) { 1394fa9a69805b001034aa04c3b33989a7ac21522371Jean-Michel Trivi return MAX_STREAM_VOLUME[streamType]; 1395fa9a69805b001034aa04c3b33989a7ac21522371Jean-Michel Trivi } 1396fa9a69805b001034aa04c3b33989a7ac21522371Jean-Michel Trivi 13979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** @see AudioManager#getStreamVolume(int) */ 13989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public int getStreamVolume(int streamType) { 13999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project ensureValidStreamType(streamType); 14009bc8358ddaa01c3490f9709991989633a6a3dd42Eric Laurent int device = getDeviceForStream(streamType); 140142b041ed4f184e3af7f788eb07307f556a2a6616Eric Laurent int index = mStreamStates[streamType].getIndex(device); 14024bbcc6549738f3d69831b2bd9eb4accec3e9920eEric Laurent 140342b041ed4f184e3af7f788eb07307f556a2a6616Eric Laurent // by convention getStreamVolume() returns 0 when a stream is muted. 140442b041ed4f184e3af7f788eb07307f556a2a6616Eric Laurent if (mStreamStates[streamType].isMuted()) { 140542b041ed4f184e3af7f788eb07307f556a2a6616Eric Laurent index = 0; 140642b041ed4f184e3af7f788eb07307f556a2a6616Eric Laurent } 14073ef7549876a159dae1568429edcb57e4e7d08459Eric Laurent if (index != 0 && (mStreamVolumeAlias[streamType] == AudioSystem.STREAM_MUSIC) && 14084bbcc6549738f3d69831b2bd9eb4accec3e9920eEric Laurent (device & mFixedVolumeDevices) != 0) { 14094bbcc6549738f3d69831b2bd9eb4accec3e9920eEric Laurent index = mStreamStates[streamType].getMaxIndex(); 14104bbcc6549738f3d69831b2bd9eb4accec3e9920eEric Laurent } 14114bbcc6549738f3d69831b2bd9eb4accec3e9920eEric Laurent return (index + 5) / 10; 14129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 14139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 14144767690f09ea3447b8c5c32fb28d27650aa18e00Mike Lockwood public int getMasterVolume() { 1415ce952c8e13c535bedde77bcdb94dfcc7508475aaMike Lockwood if (isMasterMute()) return 0; 1416ce952c8e13c535bedde77bcdb94dfcc7508475aaMike Lockwood return getLastAudibleMasterVolume(); 14178dc1dabd254249b7ddb8743e88fdb96580ffc585Mike Lockwood } 14188dc1dabd254249b7ddb8743e88fdb96580ffc585Mike Lockwood 1419ba50b97cff80e73620a0e3d13cae169e095974a7Dianne Hackborn public void setMasterVolume(int volume, int flags, String callingPackage) { 142083a017b6b7c099d1a0293e5839be6477325aef06Eric Laurent if (mUseFixedVolume) { 142183a017b6b7c099d1a0293e5839be6477325aef06Eric Laurent return; 142283a017b6b7c099d1a0293e5839be6477325aef06Eric Laurent } 142383a017b6b7c099d1a0293e5839be6477325aef06Eric Laurent 1424ba50b97cff80e73620a0e3d13cae169e095974a7Dianne Hackborn if (mAppOps.noteOp(AppOpsManager.OP_AUDIO_MASTER_VOLUME, Binder.getCallingUid(), 1425ba50b97cff80e73620a0e3d13cae169e095974a7Dianne Hackborn callingPackage) != AppOpsManager.MODE_ALLOWED) { 1426ba50b97cff80e73620a0e3d13cae169e095974a7Dianne Hackborn return; 1427ba50b97cff80e73620a0e3d13cae169e095974a7Dianne Hackborn } 1428ba50b97cff80e73620a0e3d13cae169e095974a7Dianne Hackborn 14299760647dd0ee67e7c20f3e9d661d2006b1df0b54Mike Lockwood if (volume < 0) { 14309760647dd0ee67e7c20f3e9d661d2006b1df0b54Mike Lockwood volume = 0; 14319760647dd0ee67e7c20f3e9d661d2006b1df0b54Mike Lockwood } else if (volume > MAX_MASTER_VOLUME) { 14329760647dd0ee67e7c20f3e9d661d2006b1df0b54Mike Lockwood volume = MAX_MASTER_VOLUME; 14339760647dd0ee67e7c20f3e9d661d2006b1df0b54Mike Lockwood } 14345c55a051ad7d86a464fb91426f1ea3c0250e38b3Mike Lockwood doSetMasterVolume((float)volume / MAX_MASTER_VOLUME, flags); 14355c55a051ad7d86a464fb91426f1ea3c0250e38b3Mike Lockwood } 14365c55a051ad7d86a464fb91426f1ea3c0250e38b3Mike Lockwood 14375c55a051ad7d86a464fb91426f1ea3c0250e38b3Mike Lockwood private void doSetMasterVolume(float volume, int flags) { 14385c55a051ad7d86a464fb91426f1ea3c0250e38b3Mike Lockwood // don't allow changing master volume when muted 14395c55a051ad7d86a464fb91426f1ea3c0250e38b3Mike Lockwood if (!AudioSystem.getMasterMute()) { 14405c55a051ad7d86a464fb91426f1ea3c0250e38b3Mike Lockwood int oldVolume = getMasterVolume(); 14415c55a051ad7d86a464fb91426f1ea3c0250e38b3Mike Lockwood AudioSystem.setMasterVolume(volume); 14425c55a051ad7d86a464fb91426f1ea3c0250e38b3Mike Lockwood 14435c55a051ad7d86a464fb91426f1ea3c0250e38b3Mike Lockwood int newVolume = getMasterVolume(); 14445c55a051ad7d86a464fb91426f1ea3c0250e38b3Mike Lockwood if (newVolume != oldVolume) { 14455c55a051ad7d86a464fb91426f1ea3c0250e38b3Mike Lockwood // Post a persist master volume msg 14465c55a051ad7d86a464fb91426f1ea3c0250e38b3Mike Lockwood sendMsg(mAudioHandler, MSG_PERSIST_MASTER_VOLUME, SENDMSG_REPLACE, 14475c55a051ad7d86a464fb91426f1ea3c0250e38b3Mike Lockwood Math.round(volume * (float)1000.0), 0, null, PERSIST_DELAY); 14485c55a051ad7d86a464fb91426f1ea3c0250e38b3Mike Lockwood } 14493caba517253d1703fc29b50740c4567b932279fbJustin Koh // Send the volume update regardless whether there was a change. 14503caba517253d1703fc29b50740c4567b932279fbJustin Koh sendMasterVolumeUpdate(flags, oldVolume, newVolume); 14515c55a051ad7d86a464fb91426f1ea3c0250e38b3Mike Lockwood } 14528dc1dabd254249b7ddb8743e88fdb96580ffc585Mike Lockwood } 14538dc1dabd254249b7ddb8743e88fdb96580ffc585Mike Lockwood 14549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** @see AudioManager#getStreamMaxVolume(int) */ 14559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public int getStreamMaxVolume(int streamType) { 14569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project ensureValidStreamType(streamType); 1457a553c25b33c99b345cf1c8688f8df0ed8df14e5aEric Laurent return (mStreamStates[streamType].getMaxIndex() + 5) / 10; 14589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 14599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 14604767690f09ea3447b8c5c32fb28d27650aa18e00Mike Lockwood public int getMasterMaxVolume() { 14614767690f09ea3447b8c5c32fb28d27650aa18e00Mike Lockwood return MAX_MASTER_VOLUME; 14624767690f09ea3447b8c5c32fb28d27650aa18e00Mike Lockwood } 146325101b0b9a84571ead15b26e9f4cd9c4298d7823Eric Laurent 146425101b0b9a84571ead15b26e9f4cd9c4298d7823Eric Laurent /** Get last audible volume before stream was muted. */ 146525101b0b9a84571ead15b26e9f4cd9c4298d7823Eric Laurent public int getLastAudibleStreamVolume(int streamType) { 146625101b0b9a84571ead15b26e9f4cd9c4298d7823Eric Laurent ensureValidStreamType(streamType); 14679bc8358ddaa01c3490f9709991989633a6a3dd42Eric Laurent int device = getDeviceForStream(streamType); 146842b041ed4f184e3af7f788eb07307f556a2a6616Eric Laurent return (mStreamStates[streamType].getIndex(device) + 5) / 10; 146925101b0b9a84571ead15b26e9f4cd9c4298d7823Eric Laurent } 147025101b0b9a84571ead15b26e9f4cd9c4298d7823Eric Laurent 1471ce952c8e13c535bedde77bcdb94dfcc7508475aaMike Lockwood /** Get last audible master volume before it was muted. */ 1472ce952c8e13c535bedde77bcdb94dfcc7508475aaMike Lockwood public int getLastAudibleMasterVolume() { 1473ce952c8e13c535bedde77bcdb94dfcc7508475aaMike Lockwood return Math.round(AudioSystem.getMasterVolume() * MAX_MASTER_VOLUME); 1474ce952c8e13c535bedde77bcdb94dfcc7508475aaMike Lockwood } 1475ce952c8e13c535bedde77bcdb94dfcc7508475aaMike Lockwood 1476961cae92540763226648813d111c5b5c3b0f1597Dianne Hackborn /** @see AudioManager#getMasterStreamType() */ 14776d5176638c2189595cede38fb92c3e7e8700e221Eric Laurent public int getMasterStreamType() { 14786d5176638c2189595cede38fb92c3e7e8700e221Eric Laurent if (mVoiceCapable) { 14796d5176638c2189595cede38fb92c3e7e8700e221Eric Laurent return AudioSystem.STREAM_RING; 14806d5176638c2189595cede38fb92c3e7e8700e221Eric Laurent } else { 14816d5176638c2189595cede38fb92c3e7e8700e221Eric Laurent return AudioSystem.STREAM_MUSIC; 14826d5176638c2189595cede38fb92c3e7e8700e221Eric Laurent } 14836d5176638c2189595cede38fb92c3e7e8700e221Eric Laurent } 14846d5176638c2189595cede38fb92c3e7e8700e221Eric Laurent 148522c921a910d236abf3a1705a02541a49fdaf3a14Emily Bernier /** @see AudioManager#setMicrophoneMute(boolean) */ 148622c921a910d236abf3a1705a02541a49fdaf3a14Emily Bernier public void setMicrophoneMute(boolean on, String callingPackage) { 148722c921a910d236abf3a1705a02541a49fdaf3a14Emily Bernier if (mAppOps.noteOp(AppOpsManager.OP_MUTE_MICROPHONE, Binder.getCallingUid(), 148822c921a910d236abf3a1705a02541a49fdaf3a14Emily Bernier callingPackage) != AppOpsManager.MODE_ALLOWED) { 148922c921a910d236abf3a1705a02541a49fdaf3a14Emily Bernier return; 149022c921a910d236abf3a1705a02541a49fdaf3a14Emily Bernier } 149122c921a910d236abf3a1705a02541a49fdaf3a14Emily Bernier 149222c921a910d236abf3a1705a02541a49fdaf3a14Emily Bernier AudioSystem.muteMicrophone(on); 149322c921a910d236abf3a1705a02541a49fdaf3a14Emily Bernier } 149422c921a910d236abf3a1705a02541a49fdaf3a14Emily Bernier 14959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** @see AudioManager#getRingerMode() */ 14969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public int getRingerMode() { 1497ba195ebc76f23b6679443724ab58c9dc9f2df884Glenn Kasten synchronized(mSettingsLock) { 1498ba195ebc76f23b6679443724ab58c9dc9f2df884Glenn Kasten return mRingerMode; 1499ba195ebc76f23b6679443724ab58c9dc9f2df884Glenn Kasten } 1500ba195ebc76f23b6679443724ab58c9dc9f2df884Glenn Kasten } 1501ba195ebc76f23b6679443724ab58c9dc9f2df884Glenn Kasten 1502ba195ebc76f23b6679443724ab58c9dc9f2df884Glenn Kasten private void ensureValidRingerMode(int ringerMode) { 1503ba195ebc76f23b6679443724ab58c9dc9f2df884Glenn Kasten if (!AudioManager.isValidRingerMode(ringerMode)) { 1504ba195ebc76f23b6679443724ab58c9dc9f2df884Glenn Kasten throw new IllegalArgumentException("Bad ringer mode " + ringerMode); 1505ba195ebc76f23b6679443724ab58c9dc9f2df884Glenn Kasten } 15069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 15079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 15089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** @see AudioManager#setRingerMode(int) */ 15099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public void setRingerMode(int ringerMode) { 151083a017b6b7c099d1a0293e5839be6477325aef06Eric Laurent if (mUseFixedVolume) { 151183a017b6b7c099d1a0293e5839be6477325aef06Eric Laurent return; 151283a017b6b7c099d1a0293e5839be6477325aef06Eric Laurent } 151383a017b6b7c099d1a0293e5839be6477325aef06Eric Laurent 1514244820185269991186d07068b92985624cede4a5Eric Laurent if ((ringerMode == AudioManager.RINGER_MODE_VIBRATE) && !mHasVibrator) { 1515244820185269991186d07068b92985624cede4a5Eric Laurent ringerMode = AudioManager.RINGER_MODE_SILENT; 1516244820185269991186d07068b92985624cede4a5Eric Laurent } 1517ba195ebc76f23b6679443724ab58c9dc9f2df884Glenn Kasten if (ringerMode != getRingerMode()) { 1518ba195ebc76f23b6679443724ab58c9dc9f2df884Glenn Kasten setRingerModeInt(ringerMode, true); 1519ba195ebc76f23b6679443724ab58c9dc9f2df884Glenn Kasten // Send sticky broadcast 1520ba195ebc76f23b6679443724ab58c9dc9f2df884Glenn Kasten broadcastRingerMode(ringerMode); 1521b109615ebebd6f3b9ae789412279f576c3ace46bJason Parekh } 1522b109615ebebd6f3b9ae789412279f576c3ace46bJason Parekh } 15239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 15244050c93601b3c3609b21cc1e18a29b64747e7fa9Eric Laurent private void setRingerModeInt(int ringerMode, boolean persist) { 1525ba195ebc76f23b6679443724ab58c9dc9f2df884Glenn Kasten synchronized(mSettingsLock) { 1526ba195ebc76f23b6679443724ab58c9dc9f2df884Glenn Kasten mRingerMode = ringerMode; 1527ba195ebc76f23b6679443724ab58c9dc9f2df884Glenn Kasten } 1528b109615ebebd6f3b9ae789412279f576c3ace46bJason Parekh 15295b4e654d0c7de8e4d58d73e73b0d5220f19b68f7Eric Laurent // Mute stream if not previously muted by ringer mode and ringer mode 15305b4e654d0c7de8e4d58d73e73b0d5220f19b68f7Eric Laurent // is not RINGER_MODE_NORMAL and stream is affected by ringer mode. 15315b4e654d0c7de8e4d58d73e73b0d5220f19b68f7Eric Laurent // Unmute stream if previously muted by ringer mode and ringer mode 15325b4e654d0c7de8e4d58d73e73b0d5220f19b68f7Eric Laurent // is RINGER_MODE_NORMAL or stream is not affected by ringer mode. 1533b109615ebebd6f3b9ae789412279f576c3ace46bJason Parekh int numStreamTypes = AudioSystem.getNumStreamTypes(); 15345b4e654d0c7de8e4d58d73e73b0d5220f19b68f7Eric Laurent for (int streamType = numStreamTypes - 1; streamType >= 0; streamType--) { 15355b4e654d0c7de8e4d58d73e73b0d5220f19b68f7Eric Laurent if (isStreamMutedByRingerMode(streamType)) { 15365b4e654d0c7de8e4d58d73e73b0d5220f19b68f7Eric Laurent if (!isStreamAffectedByRingerMode(streamType) || 1537ba195ebc76f23b6679443724ab58c9dc9f2df884Glenn Kasten ringerMode == AudioManager.RINGER_MODE_NORMAL) { 1538b024c30a80684ac08daef3137b7ba0d347fe3ce5Eric Laurent // ring and notifications volume should never be 0 when not silenced 1539b024c30a80684ac08daef3137b7ba0d347fe3ce5Eric Laurent // on voice capable devices 1540b024c30a80684ac08daef3137b7ba0d347fe3ce5Eric Laurent if (mVoiceCapable && 15416d5176638c2189595cede38fb92c3e7e8700e221Eric Laurent mStreamVolumeAlias[streamType] == AudioSystem.STREAM_RING) { 15423172d5e3e7520a745fa37b71fc1c7bf244b57085Eric Laurent synchronized (mStreamStates[streamType]) { 154342b041ed4f184e3af7f788eb07307f556a2a6616Eric Laurent Set set = mStreamStates[streamType].mIndex.entrySet(); 15443172d5e3e7520a745fa37b71fc1c7bf244b57085Eric Laurent Iterator i = set.iterator(); 15453172d5e3e7520a745fa37b71fc1c7bf244b57085Eric Laurent while (i.hasNext()) { 15463172d5e3e7520a745fa37b71fc1c7bf244b57085Eric Laurent Map.Entry entry = (Map.Entry)i.next(); 15473172d5e3e7520a745fa37b71fc1c7bf244b57085Eric Laurent if ((Integer)entry.getValue() == 0) { 15483172d5e3e7520a745fa37b71fc1c7bf244b57085Eric Laurent entry.setValue(10); 15493172d5e3e7520a745fa37b71fc1c7bf244b57085Eric Laurent } 15509bc8358ddaa01c3490f9709991989633a6a3dd42Eric Laurent } 15519bc8358ddaa01c3490f9709991989633a6a3dd42Eric Laurent } 1552b024c30a80684ac08daef3137b7ba0d347fe3ce5Eric Laurent } 15535b4e654d0c7de8e4d58d73e73b0d5220f19b68f7Eric Laurent mStreamStates[streamType].mute(null, false); 15545b4e654d0c7de8e4d58d73e73b0d5220f19b68f7Eric Laurent mRingerModeMutedStreams &= ~(1 << streamType); 15559bcf401d13d47416043a704430388abd59aef7cdEric Laurent } 15565b4e654d0c7de8e4d58d73e73b0d5220f19b68f7Eric Laurent } else { 15575b4e654d0c7de8e4d58d73e73b0d5220f19b68f7Eric Laurent if (isStreamAffectedByRingerMode(streamType) && 1558ba195ebc76f23b6679443724ab58c9dc9f2df884Glenn Kasten ringerMode != AudioManager.RINGER_MODE_NORMAL) { 15595b4e654d0c7de8e4d58d73e73b0d5220f19b68f7Eric Laurent mStreamStates[streamType].mute(null, true); 15605b4e654d0c7de8e4d58d73e73b0d5220f19b68f7Eric Laurent mRingerModeMutedStreams |= (1 << streamType); 15615b4e654d0c7de8e4d58d73e73b0d5220f19b68f7Eric Laurent } 1562b109615ebebd6f3b9ae789412279f576c3ace46bJason Parekh } 15639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1564a553c25b33c99b345cf1c8688f8df0ed8df14e5aEric Laurent 1565b109615ebebd6f3b9ae789412279f576c3ace46bJason Parekh // Post a persist ringer mode msg 15664050c93601b3c3609b21cc1e18a29b64747e7fa9Eric Laurent if (persist) { 1567afbb047c3945e9c2b7e9bc6b25098d5fb80bba4eEric Laurent sendMsg(mAudioHandler, MSG_PERSIST_RINGER_MODE, 15684050c93601b3c3609b21cc1e18a29b64747e7fa9Eric Laurent SENDMSG_REPLACE, 0, 0, null, PERSIST_DELAY); 15694050c93601b3c3609b21cc1e18a29b64747e7fa9Eric Laurent } 15709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 15719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 15729063154a793b0ab38b3c5992cbaed046427b4a82Mike Lockwood private void restoreMasterVolume() { 157383a017b6b7c099d1a0293e5839be6477325aef06Eric Laurent if (mUseFixedVolume) { 157483a017b6b7c099d1a0293e5839be6477325aef06Eric Laurent AudioSystem.setMasterVolume(1.0f); 157583a017b6b7c099d1a0293e5839be6477325aef06Eric Laurent return; 157683a017b6b7c099d1a0293e5839be6477325aef06Eric Laurent } 15779063154a793b0ab38b3c5992cbaed046427b4a82Mike Lockwood if (mUseMasterVolume) { 1578bc0fab1fc2db832ef86d8a33466ec4d68b103ca0Eric Laurent float volume = Settings.System.getFloatForUser(mContentResolver, 1579bc0fab1fc2db832ef86d8a33466ec4d68b103ca0Eric Laurent Settings.System.VOLUME_MASTER, -1.0f, UserHandle.USER_CURRENT); 15809063154a793b0ab38b3c5992cbaed046427b4a82Mike Lockwood if (volume >= 0.0f) { 15819063154a793b0ab38b3c5992cbaed046427b4a82Mike Lockwood AudioSystem.setMasterVolume(volume); 15829063154a793b0ab38b3c5992cbaed046427b4a82Mike Lockwood } 15839063154a793b0ab38b3c5992cbaed046427b4a82Mike Lockwood } 15849063154a793b0ab38b3c5992cbaed046427b4a82Mike Lockwood } 15859063154a793b0ab38b3c5992cbaed046427b4a82Mike Lockwood 15869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** @see AudioManager#shouldVibrate(int) */ 15879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public boolean shouldVibrate(int vibrateType) { 1588bffc3d1bd33eb2d8e00a9f8b6261d815db503311Eric Laurent if (!mHasVibrator) return false; 15899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 15909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project switch (getVibrateSetting(vibrateType)) { 15919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 15929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project case AudioManager.VIBRATE_SETTING_ON: 1593ba195ebc76f23b6679443724ab58c9dc9f2df884Glenn Kasten return getRingerMode() != AudioManager.RINGER_MODE_SILENT; 15949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 15959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project case AudioManager.VIBRATE_SETTING_ONLY_SILENT: 1596ba195ebc76f23b6679443724ab58c9dc9f2df884Glenn Kasten return getRingerMode() == AudioManager.RINGER_MODE_VIBRATE; 15979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 15989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project case AudioManager.VIBRATE_SETTING_OFF: 1599bcac496076ef6f439147e7a2be71e8a2b76ddedeDaniel Sandler // return false, even for incoming calls 1600bcac496076ef6f439147e7a2be71e8a2b76ddedeDaniel Sandler return false; 16019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 16029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project default: 16039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return false; 16049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 16059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 16069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 16079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** @see AudioManager#getVibrateSetting(int) */ 16089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public int getVibrateSetting(int vibrateType) { 1609bffc3d1bd33eb2d8e00a9f8b6261d815db503311Eric Laurent if (!mHasVibrator) return AudioManager.VIBRATE_SETTING_OFF; 16109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return (mVibrateSetting >> (vibrateType * 2)) & 3; 16119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 16129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 16139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** @see AudioManager#setVibrateSetting(int, int) */ 16149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public void setVibrateSetting(int vibrateType, int vibrateSetting) { 16159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1616bffc3d1bd33eb2d8e00a9f8b6261d815db503311Eric Laurent if (!mHasVibrator) return; 1617bffc3d1bd33eb2d8e00a9f8b6261d815db503311Eric Laurent 16189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mVibrateSetting = getValueForVibrateSetting(mVibrateSetting, vibrateType, vibrateSetting); 16199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 16209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Broadcast change 16219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project broadcastVibrateSetting(vibrateType); 16229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 16239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 16249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 16259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 16269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @see #setVibrateSetting(int, int) 16279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 16289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public static int getValueForVibrateSetting(int existingValue, int vibrateType, 16299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int vibrateSetting) { 16309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 16319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // First clear the existing setting. Each vibrate type has two bits in 16329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // the value. Note '3' is '11' in binary. 16339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project existingValue &= ~(3 << (vibrateType * 2)); 16349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 16359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Set into the old value 16369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project existingValue |= (vibrateSetting & 3) << (vibrateType * 2); 16379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 16389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return existingValue; 16399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 16409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 16419272b4b4a44fe1f33e3030810618194f817caaecEric Laurent private class SetModeDeathHandler implements IBinder.DeathRecipient { 16429272b4b4a44fe1f33e3030810618194f817caaecEric Laurent private IBinder mCb; // To be notified of client's death 1643f1ddd51f9cd2f92b922bc636c307210a8d587c25Marco Nelissen private int mPid; 16449272b4b4a44fe1f33e3030810618194f817caaecEric Laurent private int mMode = AudioSystem.MODE_NORMAL; // Current mode set by this client 16459272b4b4a44fe1f33e3030810618194f817caaecEric Laurent 16469f103de83f2d5d472960dcf1401e95b2ab57a477Eric Laurent SetModeDeathHandler(IBinder cb, int pid) { 16479272b4b4a44fe1f33e3030810618194f817caaecEric Laurent mCb = cb; 16489f103de83f2d5d472960dcf1401e95b2ab57a477Eric Laurent mPid = pid; 16499272b4b4a44fe1f33e3030810618194f817caaecEric Laurent } 16509272b4b4a44fe1f33e3030810618194f817caaecEric Laurent 16519272b4b4a44fe1f33e3030810618194f817caaecEric Laurent public void binderDied() { 1652d7454be47f4111c0478a502353e11dea401378bdEric Laurent int newModeOwnerPid = 0; 16539272b4b4a44fe1f33e3030810618194f817caaecEric Laurent synchronized(mSetModeDeathHandlers) { 16549272b4b4a44fe1f33e3030810618194f817caaecEric Laurent Log.w(TAG, "setMode() client died"); 16559272b4b4a44fe1f33e3030810618194f817caaecEric Laurent int index = mSetModeDeathHandlers.indexOf(this); 16569272b4b4a44fe1f33e3030810618194f817caaecEric Laurent if (index < 0) { 16579272b4b4a44fe1f33e3030810618194f817caaecEric Laurent Log.w(TAG, "unregistered setMode() client died"); 16589272b4b4a44fe1f33e3030810618194f817caaecEric Laurent } else { 1659d7454be47f4111c0478a502353e11dea401378bdEric Laurent newModeOwnerPid = setModeInt(AudioSystem.MODE_NORMAL, mCb, mPid); 16609272b4b4a44fe1f33e3030810618194f817caaecEric Laurent } 16619272b4b4a44fe1f33e3030810618194f817caaecEric Laurent } 16629f103de83f2d5d472960dcf1401e95b2ab57a477Eric Laurent // when entering RINGTONE, IN_CALL or IN_COMMUNICATION mode, clear all 16639f103de83f2d5d472960dcf1401e95b2ab57a477Eric Laurent // SCO connections not started by the application changing the mode 1664d7454be47f4111c0478a502353e11dea401378bdEric Laurent if (newModeOwnerPid != 0) { 16656b5e22d52c69cb6d80ff09bd32395b0034ada343Eric Laurent final long ident = Binder.clearCallingIdentity(); 16666b5e22d52c69cb6d80ff09bd32395b0034ada343Eric Laurent disconnectBluetoothSco(newModeOwnerPid); 16676b5e22d52c69cb6d80ff09bd32395b0034ada343Eric Laurent Binder.restoreCallingIdentity(ident); 16689f103de83f2d5d472960dcf1401e95b2ab57a477Eric Laurent } 16699272b4b4a44fe1f33e3030810618194f817caaecEric Laurent } 16709272b4b4a44fe1f33e3030810618194f817caaecEric Laurent 1671f1ddd51f9cd2f92b922bc636c307210a8d587c25Marco Nelissen public int getPid() { 1672f1ddd51f9cd2f92b922bc636c307210a8d587c25Marco Nelissen return mPid; 1673f1ddd51f9cd2f92b922bc636c307210a8d587c25Marco Nelissen } 1674f1ddd51f9cd2f92b922bc636c307210a8d587c25Marco Nelissen 16759272b4b4a44fe1f33e3030810618194f817caaecEric Laurent public void setMode(int mode) { 16769272b4b4a44fe1f33e3030810618194f817caaecEric Laurent mMode = mode; 16779272b4b4a44fe1f33e3030810618194f817caaecEric Laurent } 16789272b4b4a44fe1f33e3030810618194f817caaecEric Laurent 16799272b4b4a44fe1f33e3030810618194f817caaecEric Laurent public int getMode() { 16809272b4b4a44fe1f33e3030810618194f817caaecEric Laurent return mMode; 16819272b4b4a44fe1f33e3030810618194f817caaecEric Laurent } 16829272b4b4a44fe1f33e3030810618194f817caaecEric Laurent 16839272b4b4a44fe1f33e3030810618194f817caaecEric Laurent public IBinder getBinder() { 16849272b4b4a44fe1f33e3030810618194f817caaecEric Laurent return mCb; 16859272b4b4a44fe1f33e3030810618194f817caaecEric Laurent } 16869272b4b4a44fe1f33e3030810618194f817caaecEric Laurent } 16879272b4b4a44fe1f33e3030810618194f817caaecEric Laurent 16889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** @see AudioManager#setMode(int) */ 16899272b4b4a44fe1f33e3030810618194f817caaecEric Laurent public void setMode(int mode, IBinder cb) { 16909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (!checkAudioSettingsPermission("setMode()")) { 16919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return; 16929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1693a553c25b33c99b345cf1c8688f8df0ed8df14e5aEric Laurent 16948f677d66d9c3ba34c97e69b2bb9e161f129af0eeJean-Michel Trivi if (mode < AudioSystem.MODE_CURRENT || mode >= AudioSystem.NUM_MODES) { 1695a553c25b33c99b345cf1c8688f8df0ed8df14e5aEric Laurent return; 1696a553c25b33c99b345cf1c8688f8df0ed8df14e5aEric Laurent } 1697a553c25b33c99b345cf1c8688f8df0ed8df14e5aEric Laurent 1698d7454be47f4111c0478a502353e11dea401378bdEric Laurent int newModeOwnerPid = 0; 16999f103de83f2d5d472960dcf1401e95b2ab57a477Eric Laurent synchronized(mSetModeDeathHandlers) { 1700a553c25b33c99b345cf1c8688f8df0ed8df14e5aEric Laurent if (mode == AudioSystem.MODE_CURRENT) { 1701a553c25b33c99b345cf1c8688f8df0ed8df14e5aEric Laurent mode = mMode; 1702a553c25b33c99b345cf1c8688f8df0ed8df14e5aEric Laurent } 1703d7454be47f4111c0478a502353e11dea401378bdEric Laurent newModeOwnerPid = setModeInt(mode, cb, Binder.getCallingPid()); 17049f103de83f2d5d472960dcf1401e95b2ab57a477Eric Laurent } 17059f103de83f2d5d472960dcf1401e95b2ab57a477Eric Laurent // when entering RINGTONE, IN_CALL or IN_COMMUNICATION mode, clear all 17069f103de83f2d5d472960dcf1401e95b2ab57a477Eric Laurent // SCO connections not started by the application changing the mode 1707d7454be47f4111c0478a502353e11dea401378bdEric Laurent if (newModeOwnerPid != 0) { 1708d7454be47f4111c0478a502353e11dea401378bdEric Laurent disconnectBluetoothSco(newModeOwnerPid); 17099f103de83f2d5d472960dcf1401e95b2ab57a477Eric Laurent } 17109f103de83f2d5d472960dcf1401e95b2ab57a477Eric Laurent } 17112ade576148fe33c5ff6098d30ccfbcf28df70e8eJean-Michel Trivi 17129f103de83f2d5d472960dcf1401e95b2ab57a477Eric Laurent // must be called synchronized on mSetModeDeathHandlers 1713d7454be47f4111c0478a502353e11dea401378bdEric Laurent // setModeInt() returns a valid PID if the audio mode was successfully set to 17149f103de83f2d5d472960dcf1401e95b2ab57a477Eric Laurent // any mode other than NORMAL. 1715d7454be47f4111c0478a502353e11dea401378bdEric Laurent int setModeInt(int mode, IBinder cb, int pid) { 1716d7454be47f4111c0478a502353e11dea401378bdEric Laurent int newModeOwnerPid = 0; 17179f103de83f2d5d472960dcf1401e95b2ab57a477Eric Laurent if (cb == null) { 17189f103de83f2d5d472960dcf1401e95b2ab57a477Eric Laurent Log.e(TAG, "setModeInt() called with null binder"); 1719d7454be47f4111c0478a502353e11dea401378bdEric Laurent return newModeOwnerPid; 17209f103de83f2d5d472960dcf1401e95b2ab57a477Eric Laurent } 17212ade576148fe33c5ff6098d30ccfbcf28df70e8eJean-Michel Trivi 17229f103de83f2d5d472960dcf1401e95b2ab57a477Eric Laurent SetModeDeathHandler hdlr = null; 17239f103de83f2d5d472960dcf1401e95b2ab57a477Eric Laurent Iterator iter = mSetModeDeathHandlers.iterator(); 17249f103de83f2d5d472960dcf1401e95b2ab57a477Eric Laurent while (iter.hasNext()) { 17259f103de83f2d5d472960dcf1401e95b2ab57a477Eric Laurent SetModeDeathHandler h = (SetModeDeathHandler)iter.next(); 17269f103de83f2d5d472960dcf1401e95b2ab57a477Eric Laurent if (h.getPid() == pid) { 17279f103de83f2d5d472960dcf1401e95b2ab57a477Eric Laurent hdlr = h; 17289f103de83f2d5d472960dcf1401e95b2ab57a477Eric Laurent // Remove from client list so that it is re-inserted at top of list 17299f103de83f2d5d472960dcf1401e95b2ab57a477Eric Laurent iter.remove(); 17309f103de83f2d5d472960dcf1401e95b2ab57a477Eric Laurent hdlr.getBinder().unlinkToDeath(hdlr, 0); 17319f103de83f2d5d472960dcf1401e95b2ab57a477Eric Laurent break; 17329f103de83f2d5d472960dcf1401e95b2ab57a477Eric Laurent } 17339f103de83f2d5d472960dcf1401e95b2ab57a477Eric Laurent } 17349f103de83f2d5d472960dcf1401e95b2ab57a477Eric Laurent int status = AudioSystem.AUDIO_STATUS_OK; 17359f103de83f2d5d472960dcf1401e95b2ab57a477Eric Laurent do { 17369f103de83f2d5d472960dcf1401e95b2ab57a477Eric Laurent if (mode == AudioSystem.MODE_NORMAL) { 17379f103de83f2d5d472960dcf1401e95b2ab57a477Eric Laurent // get new mode from client at top the list if any 17389f103de83f2d5d472960dcf1401e95b2ab57a477Eric Laurent if (!mSetModeDeathHandlers.isEmpty()) { 17399f103de83f2d5d472960dcf1401e95b2ab57a477Eric Laurent hdlr = mSetModeDeathHandlers.get(0); 17409f103de83f2d5d472960dcf1401e95b2ab57a477Eric Laurent cb = hdlr.getBinder(); 17419f103de83f2d5d472960dcf1401e95b2ab57a477Eric Laurent mode = hdlr.getMode(); 17429f103de83f2d5d472960dcf1401e95b2ab57a477Eric Laurent } 17439f103de83f2d5d472960dcf1401e95b2ab57a477Eric Laurent } else { 17449f103de83f2d5d472960dcf1401e95b2ab57a477Eric Laurent if (hdlr == null) { 17459f103de83f2d5d472960dcf1401e95b2ab57a477Eric Laurent hdlr = new SetModeDeathHandler(cb, pid); 17469f103de83f2d5d472960dcf1401e95b2ab57a477Eric Laurent } 17479f103de83f2d5d472960dcf1401e95b2ab57a477Eric Laurent // Register for client death notification 17489f103de83f2d5d472960dcf1401e95b2ab57a477Eric Laurent try { 17499f103de83f2d5d472960dcf1401e95b2ab57a477Eric Laurent cb.linkToDeath(hdlr, 0); 17509f103de83f2d5d472960dcf1401e95b2ab57a477Eric Laurent } catch (RemoteException e) { 17519f103de83f2d5d472960dcf1401e95b2ab57a477Eric Laurent // Client has died! 17529f103de83f2d5d472960dcf1401e95b2ab57a477Eric Laurent Log.w(TAG, "setMode() could not link to "+cb+" binder death"); 17539f103de83f2d5d472960dcf1401e95b2ab57a477Eric Laurent } 17549272b4b4a44fe1f33e3030810618194f817caaecEric Laurent 17559f103de83f2d5d472960dcf1401e95b2ab57a477Eric Laurent // Last client to call setMode() is always at top of client list 17569f103de83f2d5d472960dcf1401e95b2ab57a477Eric Laurent // as required by SetModeDeathHandler.binderDied() 17579f103de83f2d5d472960dcf1401e95b2ab57a477Eric Laurent mSetModeDeathHandlers.add(0, hdlr); 17589f103de83f2d5d472960dcf1401e95b2ab57a477Eric Laurent hdlr.setMode(mode); 17599f103de83f2d5d472960dcf1401e95b2ab57a477Eric Laurent } 17603def1eec2baed0b8845ec32c871e249dc533a9d9Eric Laurent 17619f103de83f2d5d472960dcf1401e95b2ab57a477Eric Laurent if (mode != mMode) { 17629f103de83f2d5d472960dcf1401e95b2ab57a477Eric Laurent status = AudioSystem.setPhoneState(mode); 17639f103de83f2d5d472960dcf1401e95b2ab57a477Eric Laurent if (status == AudioSystem.AUDIO_STATUS_OK) { 17649f103de83f2d5d472960dcf1401e95b2ab57a477Eric Laurent mMode = mode; 17659f103de83f2d5d472960dcf1401e95b2ab57a477Eric Laurent } else { 17669f103de83f2d5d472960dcf1401e95b2ab57a477Eric Laurent if (hdlr != null) { 17679f103de83f2d5d472960dcf1401e95b2ab57a477Eric Laurent mSetModeDeathHandlers.remove(hdlr); 17689f103de83f2d5d472960dcf1401e95b2ab57a477Eric Laurent cb.unlinkToDeath(hdlr, 0); 17693def1eec2baed0b8845ec32c871e249dc533a9d9Eric Laurent } 17709f103de83f2d5d472960dcf1401e95b2ab57a477Eric Laurent // force reading new top of mSetModeDeathHandlers stack 17719f103de83f2d5d472960dcf1401e95b2ab57a477Eric Laurent mode = AudioSystem.MODE_NORMAL; 1772b9c9d260f21b321527c4622a123af9767630d94dEric Laurent } 17739f103de83f2d5d472960dcf1401e95b2ab57a477Eric Laurent } else { 17749f103de83f2d5d472960dcf1401e95b2ab57a477Eric Laurent status = AudioSystem.AUDIO_STATUS_OK; 17759f103de83f2d5d472960dcf1401e95b2ab57a477Eric Laurent } 17769f103de83f2d5d472960dcf1401e95b2ab57a477Eric Laurent } while (status != AudioSystem.AUDIO_STATUS_OK && !mSetModeDeathHandlers.isEmpty()); 17779f103de83f2d5d472960dcf1401e95b2ab57a477Eric Laurent 17789f103de83f2d5d472960dcf1401e95b2ab57a477Eric Laurent if (status == AudioSystem.AUDIO_STATUS_OK) { 17799f103de83f2d5d472960dcf1401e95b2ab57a477Eric Laurent if (mode != AudioSystem.MODE_NORMAL) { 1780d7454be47f4111c0478a502353e11dea401378bdEric Laurent if (mSetModeDeathHandlers.isEmpty()) { 1781d7454be47f4111c0478a502353e11dea401378bdEric Laurent Log.e(TAG, "setMode() different from MODE_NORMAL with empty mode client stack"); 1782d7454be47f4111c0478a502353e11dea401378bdEric Laurent } else { 1783d7454be47f4111c0478a502353e11dea401378bdEric Laurent newModeOwnerPid = mSetModeDeathHandlers.get(0).getPid(); 1784d7454be47f4111c0478a502353e11dea401378bdEric Laurent } 17859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 17869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int streamType = getActiveStreamType(AudioManager.USE_DEFAULT_STREAM_TYPE); 17873114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi if (streamType == STREAM_REMOTE_MUSIC) { 17883114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi // here handle remote media playback the same way as local playback 17893114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi streamType = AudioManager.STREAM_MUSIC; 17903114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi } 17919bc8358ddaa01c3490f9709991989633a6a3dd42Eric Laurent int device = getDeviceForStream(streamType); 179242b041ed4f184e3af7f788eb07307f556a2a6616Eric Laurent int index = mStreamStates[mStreamVolumeAlias[streamType]].getIndex(device); 179342b041ed4f184e3af7f788eb07307f556a2a6616Eric Laurent setStreamVolumeInt(mStreamVolumeAlias[streamType], index, device, true); 17946d5176638c2189595cede38fb92c3e7e8700e221Eric Laurent 17956d5176638c2189595cede38fb92c3e7e8700e221Eric Laurent updateStreamVolumeAlias(true /*updateVolumes*/); 17969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1797d7454be47f4111c0478a502353e11dea401378bdEric Laurent return newModeOwnerPid; 17989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 17999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 18009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** @see AudioManager#getMode() */ 18019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public int getMode() { 18029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return mMode; 18039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 18049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1805e78fced559d879b2e37b610d0d9a89daf08f0f2bEric Laurent //========================================================================================== 1806e78fced559d879b2e37b610d0d9a89daf08f0f2bEric Laurent // Sound Effects 1807e78fced559d879b2e37b610d0d9a89daf08f0f2bEric Laurent //========================================================================================== 1808e78fced559d879b2e37b610d0d9a89daf08f0f2bEric Laurent 1809e78fced559d879b2e37b610d0d9a89daf08f0f2bEric Laurent private static final String TAG_AUDIO_ASSETS = "audio_assets"; 1810e78fced559d879b2e37b610d0d9a89daf08f0f2bEric Laurent private static final String ATTR_VERSION = "version"; 1811e78fced559d879b2e37b610d0d9a89daf08f0f2bEric Laurent private static final String TAG_GROUP = "group"; 1812e78fced559d879b2e37b610d0d9a89daf08f0f2bEric Laurent private static final String ATTR_GROUP_NAME = "name"; 1813e78fced559d879b2e37b610d0d9a89daf08f0f2bEric Laurent private static final String TAG_ASSET = "asset"; 1814e78fced559d879b2e37b610d0d9a89daf08f0f2bEric Laurent private static final String ATTR_ASSET_ID = "id"; 1815e78fced559d879b2e37b610d0d9a89daf08f0f2bEric Laurent private static final String ATTR_ASSET_FILE = "file"; 1816e78fced559d879b2e37b610d0d9a89daf08f0f2bEric Laurent 1817e78fced559d879b2e37b610d0d9a89daf08f0f2bEric Laurent private static final String ASSET_FILE_VERSION = "1.0"; 1818e78fced559d879b2e37b610d0d9a89daf08f0f2bEric Laurent private static final String GROUP_TOUCH_SOUNDS = "touch_sounds"; 1819e78fced559d879b2e37b610d0d9a89daf08f0f2bEric Laurent 1820167d1a27713ab64cd3c0aa70de96434083ef0400Glenn Kasten private static final int SOUND_EFFECTS_LOAD_TIMEOUT_MS = 5000; 18215d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent 18225d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent class LoadSoundEffectReply { 18235d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent public int mStatus = 1; 18245d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent }; 18255d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent 1826e78fced559d879b2e37b610d0d9a89daf08f0f2bEric Laurent private void loadTouchSoundAssetDefaults() { 1827e78fced559d879b2e37b610d0d9a89daf08f0f2bEric Laurent SOUND_EFFECT_FILES.add("Effect_Tick.ogg"); 1828e78fced559d879b2e37b610d0d9a89daf08f0f2bEric Laurent for (int i = 0; i < AudioManager.NUM_SOUND_EFFECTS; i++) { 1829e78fced559d879b2e37b610d0d9a89daf08f0f2bEric Laurent SOUND_EFFECT_FILES_MAP[i][0] = 0; 1830e78fced559d879b2e37b610d0d9a89daf08f0f2bEric Laurent SOUND_EFFECT_FILES_MAP[i][1] = -1; 1831e78fced559d879b2e37b610d0d9a89daf08f0f2bEric Laurent } 1832e78fced559d879b2e37b610d0d9a89daf08f0f2bEric Laurent } 1833e78fced559d879b2e37b610d0d9a89daf08f0f2bEric Laurent 1834e78fced559d879b2e37b610d0d9a89daf08f0f2bEric Laurent private void loadTouchSoundAssets() { 1835e78fced559d879b2e37b610d0d9a89daf08f0f2bEric Laurent XmlResourceParser parser = null; 1836e78fced559d879b2e37b610d0d9a89daf08f0f2bEric Laurent 18375d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent // only load assets once. 18385d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent if (!SOUND_EFFECT_FILES.isEmpty()) { 18395d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent return; 18405d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent } 18415d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent 1842e78fced559d879b2e37b610d0d9a89daf08f0f2bEric Laurent loadTouchSoundAssetDefaults(); 1843e78fced559d879b2e37b610d0d9a89daf08f0f2bEric Laurent 1844e78fced559d879b2e37b610d0d9a89daf08f0f2bEric Laurent try { 1845e78fced559d879b2e37b610d0d9a89daf08f0f2bEric Laurent parser = mContext.getResources().getXml(com.android.internal.R.xml.audio_assets); 1846e78fced559d879b2e37b610d0d9a89daf08f0f2bEric Laurent 1847e78fced559d879b2e37b610d0d9a89daf08f0f2bEric Laurent XmlUtils.beginDocument(parser, TAG_AUDIO_ASSETS); 1848e78fced559d879b2e37b610d0d9a89daf08f0f2bEric Laurent String version = parser.getAttributeValue(null, ATTR_VERSION); 1849e78fced559d879b2e37b610d0d9a89daf08f0f2bEric Laurent boolean inTouchSoundsGroup = false; 1850e78fced559d879b2e37b610d0d9a89daf08f0f2bEric Laurent 1851e78fced559d879b2e37b610d0d9a89daf08f0f2bEric Laurent if (ASSET_FILE_VERSION.equals(version)) { 1852e78fced559d879b2e37b610d0d9a89daf08f0f2bEric Laurent while (true) { 1853e78fced559d879b2e37b610d0d9a89daf08f0f2bEric Laurent XmlUtils.nextElement(parser); 1854e78fced559d879b2e37b610d0d9a89daf08f0f2bEric Laurent String element = parser.getName(); 1855e78fced559d879b2e37b610d0d9a89daf08f0f2bEric Laurent if (element == null) { 1856e78fced559d879b2e37b610d0d9a89daf08f0f2bEric Laurent break; 1857e78fced559d879b2e37b610d0d9a89daf08f0f2bEric Laurent } 1858e78fced559d879b2e37b610d0d9a89daf08f0f2bEric Laurent if (element.equals(TAG_GROUP)) { 1859e78fced559d879b2e37b610d0d9a89daf08f0f2bEric Laurent String name = parser.getAttributeValue(null, ATTR_GROUP_NAME); 1860e78fced559d879b2e37b610d0d9a89daf08f0f2bEric Laurent if (GROUP_TOUCH_SOUNDS.equals(name)) { 1861e78fced559d879b2e37b610d0d9a89daf08f0f2bEric Laurent inTouchSoundsGroup = true; 1862e78fced559d879b2e37b610d0d9a89daf08f0f2bEric Laurent break; 1863e78fced559d879b2e37b610d0d9a89daf08f0f2bEric Laurent } 1864e78fced559d879b2e37b610d0d9a89daf08f0f2bEric Laurent } 1865e78fced559d879b2e37b610d0d9a89daf08f0f2bEric Laurent } 1866e78fced559d879b2e37b610d0d9a89daf08f0f2bEric Laurent while (inTouchSoundsGroup) { 1867e78fced559d879b2e37b610d0d9a89daf08f0f2bEric Laurent XmlUtils.nextElement(parser); 1868e78fced559d879b2e37b610d0d9a89daf08f0f2bEric Laurent String element = parser.getName(); 1869e78fced559d879b2e37b610d0d9a89daf08f0f2bEric Laurent if (element == null) { 1870e78fced559d879b2e37b610d0d9a89daf08f0f2bEric Laurent break; 1871e78fced559d879b2e37b610d0d9a89daf08f0f2bEric Laurent } 1872e78fced559d879b2e37b610d0d9a89daf08f0f2bEric Laurent if (element.equals(TAG_ASSET)) { 1873e78fced559d879b2e37b610d0d9a89daf08f0f2bEric Laurent String id = parser.getAttributeValue(null, ATTR_ASSET_ID); 1874e78fced559d879b2e37b610d0d9a89daf08f0f2bEric Laurent String file = parser.getAttributeValue(null, ATTR_ASSET_FILE); 1875e78fced559d879b2e37b610d0d9a89daf08f0f2bEric Laurent int fx; 1876e78fced559d879b2e37b610d0d9a89daf08f0f2bEric Laurent 1877e78fced559d879b2e37b610d0d9a89daf08f0f2bEric Laurent try { 1878e78fced559d879b2e37b610d0d9a89daf08f0f2bEric Laurent Field field = AudioManager.class.getField(id); 1879e78fced559d879b2e37b610d0d9a89daf08f0f2bEric Laurent fx = field.getInt(null); 1880e78fced559d879b2e37b610d0d9a89daf08f0f2bEric Laurent } catch (Exception e) { 1881e78fced559d879b2e37b610d0d9a89daf08f0f2bEric Laurent Log.w(TAG, "Invalid touch sound ID: "+id); 1882e78fced559d879b2e37b610d0d9a89daf08f0f2bEric Laurent continue; 1883e78fced559d879b2e37b610d0d9a89daf08f0f2bEric Laurent } 1884e78fced559d879b2e37b610d0d9a89daf08f0f2bEric Laurent 1885e78fced559d879b2e37b610d0d9a89daf08f0f2bEric Laurent int i = SOUND_EFFECT_FILES.indexOf(file); 1886e78fced559d879b2e37b610d0d9a89daf08f0f2bEric Laurent if (i == -1) { 1887e78fced559d879b2e37b610d0d9a89daf08f0f2bEric Laurent i = SOUND_EFFECT_FILES.size(); 1888e78fced559d879b2e37b610d0d9a89daf08f0f2bEric Laurent SOUND_EFFECT_FILES.add(file); 1889e78fced559d879b2e37b610d0d9a89daf08f0f2bEric Laurent } 1890e78fced559d879b2e37b610d0d9a89daf08f0f2bEric Laurent SOUND_EFFECT_FILES_MAP[fx][0] = i; 1891e78fced559d879b2e37b610d0d9a89daf08f0f2bEric Laurent } else { 1892e78fced559d879b2e37b610d0d9a89daf08f0f2bEric Laurent break; 1893e78fced559d879b2e37b610d0d9a89daf08f0f2bEric Laurent } 1894e78fced559d879b2e37b610d0d9a89daf08f0f2bEric Laurent } 1895e78fced559d879b2e37b610d0d9a89daf08f0f2bEric Laurent } 1896e78fced559d879b2e37b610d0d9a89daf08f0f2bEric Laurent } catch (Resources.NotFoundException e) { 1897e78fced559d879b2e37b610d0d9a89daf08f0f2bEric Laurent Log.w(TAG, "audio assets file not found", e); 1898e78fced559d879b2e37b610d0d9a89daf08f0f2bEric Laurent } catch (XmlPullParserException e) { 1899e78fced559d879b2e37b610d0d9a89daf08f0f2bEric Laurent Log.w(TAG, "XML parser exception reading touch sound assets", e); 1900e78fced559d879b2e37b610d0d9a89daf08f0f2bEric Laurent } catch (IOException e) { 1901e78fced559d879b2e37b610d0d9a89daf08f0f2bEric Laurent Log.w(TAG, "I/O exception reading touch sound assets", e); 1902e78fced559d879b2e37b610d0d9a89daf08f0f2bEric Laurent } finally { 1903e78fced559d879b2e37b610d0d9a89daf08f0f2bEric Laurent if (parser != null) { 1904e78fced559d879b2e37b610d0d9a89daf08f0f2bEric Laurent parser.close(); 1905e78fced559d879b2e37b610d0d9a89daf08f0f2bEric Laurent } 1906e78fced559d879b2e37b610d0d9a89daf08f0f2bEric Laurent } 1907e78fced559d879b2e37b610d0d9a89daf08f0f2bEric Laurent } 1908e78fced559d879b2e37b610d0d9a89daf08f0f2bEric Laurent 19099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** @see AudioManager#playSoundEffect(int) */ 19109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public void playSoundEffect(int effectType) { 19115d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent playSoundEffectVolume(effectType, -1.0f); 19129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 19139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 19149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** @see AudioManager#playSoundEffect(int, float) */ 19159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public void playSoundEffectVolume(int effectType, float volume) { 1916559c76dbc37ff25b204ed1f060d3ec2fa43d718cNatalie Silvanovich if (effectType >= AudioManager.NUM_SOUND_EFFECTS || effectType < 0) { 1917559c76dbc37ff25b204ed1f060d3ec2fa43d718cNatalie Silvanovich Log.w(TAG, "AudioService effectType value " + effectType + " out of range"); 1918559c76dbc37ff25b204ed1f060d3ec2fa43d718cNatalie Silvanovich return; 1919559c76dbc37ff25b204ed1f060d3ec2fa43d718cNatalie Silvanovich } 1920559c76dbc37ff25b204ed1f060d3ec2fa43d718cNatalie Silvanovich 19215d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent sendMsg(mAudioHandler, MSG_PLAY_SOUND_EFFECT, SENDMSG_QUEUE, 19229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project effectType, (int) (volume * 1000), null, 0); 19239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 19249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 19259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 19269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Loads samples into the soundpool. 19275c17a820f9e46e0756c11795b3e6f89105f2f539Glenn Kasten * This method must be called at first when sound effects are enabled 19289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 19299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public boolean loadSoundEffects() { 19305d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent int attempts = 3; 19315d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent LoadSoundEffectReply reply = new LoadSoundEffectReply(); 1932117b7bb5b5a4457711f59bde3dcc83d8f111c524Eric Laurent 19335d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent synchronized (reply) { 19345d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent sendMsg(mAudioHandler, MSG_LOAD_SOUND_EFFECTS, SENDMSG_QUEUE, 0, 0, reply, 0); 19355d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent while ((reply.mStatus == 1) && (attempts-- > 0)) { 1936117b7bb5b5a4457711f59bde3dcc83d8f111c524Eric Laurent try { 1937167d1a27713ab64cd3c0aa70de96434083ef0400Glenn Kasten reply.wait(SOUND_EFFECTS_LOAD_TIMEOUT_MS); 19385d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent } catch (InterruptedException e) { 19395d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent Log.w(TAG, "loadSoundEffects Interrupted while waiting sound pool loaded."); 1940117b7bb5b5a4457711f59bde3dcc83d8f111c524Eric Laurent } 1941a60e212d0dda7d2a748180ce77405f2463c9cf53Eric Laurent } 19429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 19435d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent return (reply.mStatus == 0); 19449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 19459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 19469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 19479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Unloads samples from the sound pool. 19489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * This method can be called to free some memory when 19499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * sound effects are disabled. 19509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 19519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public void unloadSoundEffects() { 19525d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent sendMsg(mAudioHandler, MSG_UNLOAD_SOUND_EFFECTS, SENDMSG_QUEUE, 0, 0, null, 0); 19539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 19549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1955a60e212d0dda7d2a748180ce77405f2463c9cf53Eric Laurent class SoundPoolListenerThread extends Thread { 1956a60e212d0dda7d2a748180ce77405f2463c9cf53Eric Laurent public SoundPoolListenerThread() { 1957a60e212d0dda7d2a748180ce77405f2463c9cf53Eric Laurent super("SoundPoolListenerThread"); 1958a60e212d0dda7d2a748180ce77405f2463c9cf53Eric Laurent } 1959a60e212d0dda7d2a748180ce77405f2463c9cf53Eric Laurent 1960a60e212d0dda7d2a748180ce77405f2463c9cf53Eric Laurent @Override 1961a60e212d0dda7d2a748180ce77405f2463c9cf53Eric Laurent public void run() { 1962a60e212d0dda7d2a748180ce77405f2463c9cf53Eric Laurent 1963a60e212d0dda7d2a748180ce77405f2463c9cf53Eric Laurent Looper.prepare(); 1964a60e212d0dda7d2a748180ce77405f2463c9cf53Eric Laurent mSoundPoolLooper = Looper.myLooper(); 1965a60e212d0dda7d2a748180ce77405f2463c9cf53Eric Laurent 1966a60e212d0dda7d2a748180ce77405f2463c9cf53Eric Laurent synchronized (mSoundEffectsLock) { 1967a60e212d0dda7d2a748180ce77405f2463c9cf53Eric Laurent if (mSoundPool != null) { 1968a60e212d0dda7d2a748180ce77405f2463c9cf53Eric Laurent mSoundPoolCallBack = new SoundPoolCallback(); 1969a60e212d0dda7d2a748180ce77405f2463c9cf53Eric Laurent mSoundPool.setOnLoadCompleteListener(mSoundPoolCallBack); 1970a60e212d0dda7d2a748180ce77405f2463c9cf53Eric Laurent } 1971a60e212d0dda7d2a748180ce77405f2463c9cf53Eric Laurent mSoundEffectsLock.notify(); 1972a60e212d0dda7d2a748180ce77405f2463c9cf53Eric Laurent } 1973a60e212d0dda7d2a748180ce77405f2463c9cf53Eric Laurent Looper.loop(); 1974a60e212d0dda7d2a748180ce77405f2463c9cf53Eric Laurent } 1975a60e212d0dda7d2a748180ce77405f2463c9cf53Eric Laurent } 1976a60e212d0dda7d2a748180ce77405f2463c9cf53Eric Laurent 1977a60e212d0dda7d2a748180ce77405f2463c9cf53Eric Laurent private final class SoundPoolCallback implements 1978a60e212d0dda7d2a748180ce77405f2463c9cf53Eric Laurent android.media.SoundPool.OnLoadCompleteListener { 1979a60e212d0dda7d2a748180ce77405f2463c9cf53Eric Laurent 19805d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent int mStatus = 1; // 1 means neither error nor last sample loaded yet 19815d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent List<Integer> mSamples = new ArrayList<Integer>(); 1982a60e212d0dda7d2a748180ce77405f2463c9cf53Eric Laurent 1983a60e212d0dda7d2a748180ce77405f2463c9cf53Eric Laurent public int status() { 1984a60e212d0dda7d2a748180ce77405f2463c9cf53Eric Laurent return mStatus; 1985a60e212d0dda7d2a748180ce77405f2463c9cf53Eric Laurent } 1986a60e212d0dda7d2a748180ce77405f2463c9cf53Eric Laurent 19875d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent public void setSamples(int[] samples) { 19885d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent for (int i = 0; i < samples.length; i++) { 19895d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent // do not wait ack for samples rejected upfront by SoundPool 19905d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent if (samples[i] > 0) { 19915d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent mSamples.add(samples[i]); 19925d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent } 19935d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent } 1994a60e212d0dda7d2a748180ce77405f2463c9cf53Eric Laurent } 1995a60e212d0dda7d2a748180ce77405f2463c9cf53Eric Laurent 1996a60e212d0dda7d2a748180ce77405f2463c9cf53Eric Laurent public void onLoadComplete(SoundPool soundPool, int sampleId, int status) { 1997a60e212d0dda7d2a748180ce77405f2463c9cf53Eric Laurent synchronized (mSoundEffectsLock) { 19985d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent int i = mSamples.indexOf(sampleId); 19995d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent if (i >= 0) { 20005d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent mSamples.remove(i); 2001a60e212d0dda7d2a748180ce77405f2463c9cf53Eric Laurent } 20025d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent if ((status != 0) || mSamples. isEmpty()) { 20035d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent mStatus = status; 2004a60e212d0dda7d2a748180ce77405f2463c9cf53Eric Laurent mSoundEffectsLock.notify(); 2005a60e212d0dda7d2a748180ce77405f2463c9cf53Eric Laurent } 2006a60e212d0dda7d2a748180ce77405f2463c9cf53Eric Laurent } 2007a60e212d0dda7d2a748180ce77405f2463c9cf53Eric Laurent } 2008a60e212d0dda7d2a748180ce77405f2463c9cf53Eric Laurent } 2009a60e212d0dda7d2a748180ce77405f2463c9cf53Eric Laurent 20104050c93601b3c3609b21cc1e18a29b64747e7fa9Eric Laurent /** @see AudioManager#reloadAudioSettings() */ 20114050c93601b3c3609b21cc1e18a29b64747e7fa9Eric Laurent public void reloadAudioSettings() { 2012bc0fab1fc2db832ef86d8a33466ec4d68b103ca0Eric Laurent readAudioSettings(false /*userSwitch*/); 2013bc0fab1fc2db832ef86d8a33466ec4d68b103ca0Eric Laurent } 2014bc0fab1fc2db832ef86d8a33466ec4d68b103ca0Eric Laurent 2015bc0fab1fc2db832ef86d8a33466ec4d68b103ca0Eric Laurent private void readAudioSettings(boolean userSwitch) { 20164050c93601b3c3609b21cc1e18a29b64747e7fa9Eric Laurent // restore ringer mode, ringer mode affected streams, mute affected streams and vibrate settings 20174050c93601b3c3609b21cc1e18a29b64747e7fa9Eric Laurent readPersistedSettings(); 20184050c93601b3c3609b21cc1e18a29b64747e7fa9Eric Laurent 20194050c93601b3c3609b21cc1e18a29b64747e7fa9Eric Laurent // restore volume settings 20204050c93601b3c3609b21cc1e18a29b64747e7fa9Eric Laurent int numStreamTypes = AudioSystem.getNumStreamTypes(); 20214050c93601b3c3609b21cc1e18a29b64747e7fa9Eric Laurent for (int streamType = 0; streamType < numStreamTypes; streamType++) { 20224050c93601b3c3609b21cc1e18a29b64747e7fa9Eric Laurent VolumeStreamState streamState = mStreamStates[streamType]; 20234050c93601b3c3609b21cc1e18a29b64747e7fa9Eric Laurent 2024bc0fab1fc2db832ef86d8a33466ec4d68b103ca0Eric Laurent if (userSwitch && mStreamVolumeAlias[streamType] == AudioSystem.STREAM_MUSIC) { 2025bc0fab1fc2db832ef86d8a33466ec4d68b103ca0Eric Laurent continue; 2026bc0fab1fc2db832ef86d8a33466ec4d68b103ca0Eric Laurent } 2027bc0fab1fc2db832ef86d8a33466ec4d68b103ca0Eric Laurent 20283172d5e3e7520a745fa37b71fc1c7bf244b57085Eric Laurent synchronized (streamState) { 20293172d5e3e7520a745fa37b71fc1c7bf244b57085Eric Laurent streamState.readSettings(); 2030a553c25b33c99b345cf1c8688f8df0ed8df14e5aEric Laurent 20313172d5e3e7520a745fa37b71fc1c7bf244b57085Eric Laurent // unmute stream that was muted but is not affect by mute anymore 203242b041ed4f184e3af7f788eb07307f556a2a6616Eric Laurent if (streamState.isMuted() && ((!isStreamAffectedByMute(streamType) && 203383a017b6b7c099d1a0293e5839be6477325aef06Eric Laurent !isStreamMutedByRingerMode(streamType)) || mUseFixedVolume)) { 20343172d5e3e7520a745fa37b71fc1c7bf244b57085Eric Laurent int size = streamState.mDeathHandlers.size(); 20353172d5e3e7520a745fa37b71fc1c7bf244b57085Eric Laurent for (int i = 0; i < size; i++) { 20363172d5e3e7520a745fa37b71fc1c7bf244b57085Eric Laurent streamState.mDeathHandlers.get(i).mMuteCount = 1; 20373172d5e3e7520a745fa37b71fc1c7bf244b57085Eric Laurent streamState.mDeathHandlers.get(i).mute(false); 20383172d5e3e7520a745fa37b71fc1c7bf244b57085Eric Laurent } 20393172d5e3e7520a745fa37b71fc1c7bf244b57085Eric Laurent } 20404050c93601b3c3609b21cc1e18a29b64747e7fa9Eric Laurent } 20414050c93601b3c3609b21cc1e18a29b64747e7fa9Eric Laurent } 20424050c93601b3c3609b21cc1e18a29b64747e7fa9Eric Laurent 204333902db75011d863009585682bd08560c5b89a75Eric Laurent // apply new ringer mode before checking volume for alias streams so that streams 204433902db75011d863009585682bd08560c5b89a75Eric Laurent // muted by ringer mode have the correct volume 204533902db75011d863009585682bd08560c5b89a75Eric Laurent setRingerModeInt(getRingerMode(), false); 204633902db75011d863009585682bd08560c5b89a75Eric Laurent 2047244820185269991186d07068b92985624cede4a5Eric Laurent checkAllAliasStreamVolumes(); 2048244820185269991186d07068b92985624cede4a5Eric Laurent 2049d640bd325c3be9a350058c835b880a7e0b40dc60Eric Laurent synchronized (mSafeMediaVolumeState) { 2050d640bd325c3be9a350058c835b880a7e0b40dc60Eric Laurent if (mSafeMediaVolumeState == SAFE_MEDIA_VOLUME_ACTIVE) { 2051f1a457d06c53a901ea08d2d3fb6e766bc06c4d4fEric Laurent enforceSafeMediaVolume(); 2052f1a457d06c53a901ea08d2d3fb6e766bc06c4d4fEric Laurent } 2053c34dcc1e1ebf152bb400abbb8bc25f7dc0c3ba97Eric Laurent } 20544050c93601b3c3609b21cc1e18a29b64747e7fa9Eric Laurent } 20554050c93601b3c3609b21cc1e18a29b64747e7fa9Eric Laurent 2056961cae92540763226648813d111c5b5c3b0f1597Dianne Hackborn /** @see AudioManager#setSpeakerphoneOn(boolean) */ 2057c42ac9d4d03f62c3a1ba197a28a81fda44bd8b7fEric Laurent public void setSpeakerphoneOn(boolean on){ 2058dc1d17a1dbfc2ae01c20012133a836b62f5b6930Eric Laurent if (!checkAudioSettingsPermission("setSpeakerphoneOn()")) { 2059dc1d17a1dbfc2ae01c20012133a836b62f5b6930Eric Laurent return; 2060dc1d17a1dbfc2ae01c20012133a836b62f5b6930Eric Laurent } 20617337bee7839238f244fad31112a45389f6ef907cJohan Gustavsson 20627337bee7839238f244fad31112a45389f6ef907cJohan Gustavsson if (on) { 20637337bee7839238f244fad31112a45389f6ef907cJohan Gustavsson if (mForcedUseForComm == AudioSystem.FORCE_BT_SCO) { 20647337bee7839238f244fad31112a45389f6ef907cJohan Gustavsson sendMsg(mAudioHandler, MSG_SET_FORCE_USE, SENDMSG_QUEUE, 20657337bee7839238f244fad31112a45389f6ef907cJohan Gustavsson AudioSystem.FOR_RECORD, AudioSystem.FORCE_NONE, null, 0); 20667337bee7839238f244fad31112a45389f6ef907cJohan Gustavsson } 20677337bee7839238f244fad31112a45389f6ef907cJohan Gustavsson mForcedUseForComm = AudioSystem.FORCE_SPEAKER; 20687337bee7839238f244fad31112a45389f6ef907cJohan Gustavsson } else if (mForcedUseForComm == AudioSystem.FORCE_SPEAKER){ 20697337bee7839238f244fad31112a45389f6ef907cJohan Gustavsson mForcedUseForComm = AudioSystem.FORCE_NONE; 20707337bee7839238f244fad31112a45389f6ef907cJohan Gustavsson } 2071fa640154f1f42121d81242b2f1a10f03e52f0014Eric Laurent 2072afbb047c3945e9c2b7e9bc6b25098d5fb80bba4eEric Laurent sendMsg(mAudioHandler, MSG_SET_FORCE_USE, SENDMSG_QUEUE, 2073fa640154f1f42121d81242b2f1a10f03e52f0014Eric Laurent AudioSystem.FOR_COMMUNICATION, mForcedUseForComm, null, 0); 2074c42ac9d4d03f62c3a1ba197a28a81fda44bd8b7fEric Laurent } 2075c42ac9d4d03f62c3a1ba197a28a81fda44bd8b7fEric Laurent 2076c42ac9d4d03f62c3a1ba197a28a81fda44bd8b7fEric Laurent /** @see AudioManager#isSpeakerphoneOn() */ 2077c42ac9d4d03f62c3a1ba197a28a81fda44bd8b7fEric Laurent public boolean isSpeakerphoneOn() { 2078fa640154f1f42121d81242b2f1a10f03e52f0014Eric Laurent return (mForcedUseForComm == AudioSystem.FORCE_SPEAKER); 2079c42ac9d4d03f62c3a1ba197a28a81fda44bd8b7fEric Laurent } 2080c42ac9d4d03f62c3a1ba197a28a81fda44bd8b7fEric Laurent 2081961cae92540763226648813d111c5b5c3b0f1597Dianne Hackborn /** @see AudioManager#setBluetoothScoOn(boolean) */ 2082c42ac9d4d03f62c3a1ba197a28a81fda44bd8b7fEric Laurent public void setBluetoothScoOn(boolean on){ 2083dc1d17a1dbfc2ae01c20012133a836b62f5b6930Eric Laurent if (!checkAudioSettingsPermission("setBluetoothScoOn()")) { 2084dc1d17a1dbfc2ae01c20012133a836b62f5b6930Eric Laurent return; 2085dc1d17a1dbfc2ae01c20012133a836b62f5b6930Eric Laurent } 20867337bee7839238f244fad31112a45389f6ef907cJohan Gustavsson 20877337bee7839238f244fad31112a45389f6ef907cJohan Gustavsson if (on) { 20887337bee7839238f244fad31112a45389f6ef907cJohan Gustavsson mForcedUseForComm = AudioSystem.FORCE_BT_SCO; 20897337bee7839238f244fad31112a45389f6ef907cJohan Gustavsson } else if (mForcedUseForComm == AudioSystem.FORCE_BT_SCO) { 20907337bee7839238f244fad31112a45389f6ef907cJohan Gustavsson mForcedUseForComm = AudioSystem.FORCE_NONE; 20917337bee7839238f244fad31112a45389f6ef907cJohan Gustavsson } 2092fa640154f1f42121d81242b2f1a10f03e52f0014Eric Laurent 2093afbb047c3945e9c2b7e9bc6b25098d5fb80bba4eEric Laurent sendMsg(mAudioHandler, MSG_SET_FORCE_USE, SENDMSG_QUEUE, 2094fa640154f1f42121d81242b2f1a10f03e52f0014Eric Laurent AudioSystem.FOR_COMMUNICATION, mForcedUseForComm, null, 0); 2095afbb047c3945e9c2b7e9bc6b25098d5fb80bba4eEric Laurent sendMsg(mAudioHandler, MSG_SET_FORCE_USE, SENDMSG_QUEUE, 2096fa640154f1f42121d81242b2f1a10f03e52f0014Eric Laurent AudioSystem.FOR_RECORD, mForcedUseForComm, null, 0); 2097c42ac9d4d03f62c3a1ba197a28a81fda44bd8b7fEric Laurent } 2098c42ac9d4d03f62c3a1ba197a28a81fda44bd8b7fEric Laurent 2099c42ac9d4d03f62c3a1ba197a28a81fda44bd8b7fEric Laurent /** @see AudioManager#isBluetoothScoOn() */ 2100c42ac9d4d03f62c3a1ba197a28a81fda44bd8b7fEric Laurent public boolean isBluetoothScoOn() { 2101fa640154f1f42121d81242b2f1a10f03e52f0014Eric Laurent return (mForcedUseForComm == AudioSystem.FORCE_BT_SCO); 2102c42ac9d4d03f62c3a1ba197a28a81fda44bd8b7fEric Laurent } 2103c42ac9d4d03f62c3a1ba197a28a81fda44bd8b7fEric Laurent 2104961cae92540763226648813d111c5b5c3b0f1597Dianne Hackborn /** @see AudioManager#setBluetoothA2dpOn(boolean) */ 21057847211fb4699bf6018e29d214a918ed6657319bEric Laurent public void setBluetoothA2dpOn(boolean on) { 2106c390bed06b4a572e273ead1254da9a932e04dce3Eric Laurent synchronized (mBluetoothA2dpEnabledLock) { 2107c390bed06b4a572e273ead1254da9a932e04dce3Eric Laurent mBluetoothA2dpEnabled = on; 2108c390bed06b4a572e273ead1254da9a932e04dce3Eric Laurent sendMsg(mAudioHandler, MSG_SET_FORCE_BT_A2DP_USE, SENDMSG_QUEUE, 2109c390bed06b4a572e273ead1254da9a932e04dce3Eric Laurent AudioSystem.FOR_MEDIA, 2110c390bed06b4a572e273ead1254da9a932e04dce3Eric Laurent mBluetoothA2dpEnabled ? AudioSystem.FORCE_NONE : AudioSystem.FORCE_NO_BT_A2DP, 2111c390bed06b4a572e273ead1254da9a932e04dce3Eric Laurent null, 0); 2112c390bed06b4a572e273ead1254da9a932e04dce3Eric Laurent } 21137847211fb4699bf6018e29d214a918ed6657319bEric Laurent } 21147847211fb4699bf6018e29d214a918ed6657319bEric Laurent 21157847211fb4699bf6018e29d214a918ed6657319bEric Laurent /** @see AudioManager#isBluetoothA2dpOn() */ 21167847211fb4699bf6018e29d214a918ed6657319bEric Laurent public boolean isBluetoothA2dpOn() { 21177847211fb4699bf6018e29d214a918ed6657319bEric Laurent synchronized (mBluetoothA2dpEnabledLock) { 21187847211fb4699bf6018e29d214a918ed6657319bEric Laurent return mBluetoothA2dpEnabled; 21197847211fb4699bf6018e29d214a918ed6657319bEric Laurent } 21207847211fb4699bf6018e29d214a918ed6657319bEric Laurent } 21217847211fb4699bf6018e29d214a918ed6657319bEric Laurent 21223def1eec2baed0b8845ec32c871e249dc533a9d9Eric Laurent /** @see AudioManager#startBluetoothSco() */ 212383900754f357616b9e56eaf7fc85f49b8906e987Eric Laurent public void startBluetoothSco(IBinder cb, int targetSdkVersion) { 212483900754f357616b9e56eaf7fc85f49b8906e987Eric Laurent int scoAudioMode = 212583900754f357616b9e56eaf7fc85f49b8906e987Eric Laurent (targetSdkVersion < Build.VERSION_CODES.JELLY_BEAN_MR2) ? 2126f4e51d82d2e34e6832903f01eaecc15ded6c3241Liejun Tao SCO_MODE_VIRTUAL_CALL : SCO_MODE_UNDEFINED; 212783900754f357616b9e56eaf7fc85f49b8906e987Eric Laurent startBluetoothScoInt(cb, scoAudioMode); 212883900754f357616b9e56eaf7fc85f49b8906e987Eric Laurent } 212983900754f357616b9e56eaf7fc85f49b8906e987Eric Laurent 213083900754f357616b9e56eaf7fc85f49b8906e987Eric Laurent /** @see AudioManager#startBluetoothScoVirtualCall() */ 213183900754f357616b9e56eaf7fc85f49b8906e987Eric Laurent public void startBluetoothScoVirtualCall(IBinder cb) { 213283900754f357616b9e56eaf7fc85f49b8906e987Eric Laurent startBluetoothScoInt(cb, SCO_MODE_VIRTUAL_CALL); 213383900754f357616b9e56eaf7fc85f49b8906e987Eric Laurent } 213483900754f357616b9e56eaf7fc85f49b8906e987Eric Laurent 213583900754f357616b9e56eaf7fc85f49b8906e987Eric Laurent void startBluetoothScoInt(IBinder cb, int scoAudioMode){ 2136dc03c61fe3cd8d0805480e48a974986439977a60Eric Laurent if (!checkAudioSettingsPermission("startBluetoothSco()") || 21374a5eeb9c727d77bb57fef87a70c8c9cc23dbfee3Eric Laurent !mSystemReady) { 21383def1eec2baed0b8845ec32c871e249dc533a9d9Eric Laurent return; 21393def1eec2baed0b8845ec32c871e249dc533a9d9Eric Laurent } 2140854938a72d968c1bc0de4e2b0ea87777cfebc045Eric Laurent ScoClient client = getScoClient(cb, true); 2141f5a1fc3c0fd733acd21e1437f153ba27220be8ceEric Laurent // The calling identity must be cleared before calling ScoClient.incCount(). 2142f5a1fc3c0fd733acd21e1437f153ba27220be8ceEric Laurent // inCount() calls requestScoState() which in turn can call BluetoothHeadset APIs 2143f5a1fc3c0fd733acd21e1437f153ba27220be8ceEric Laurent // and this must be done on behalf of system server to make sure permissions are granted. 2144f5a1fc3c0fd733acd21e1437f153ba27220be8ceEric Laurent // The caller identity must be cleared after getScoClient() because it is needed if a new 2145f5a1fc3c0fd733acd21e1437f153ba27220be8ceEric Laurent // client is created. 2146f5a1fc3c0fd733acd21e1437f153ba27220be8ceEric Laurent final long ident = Binder.clearCallingIdentity(); 214783900754f357616b9e56eaf7fc85f49b8906e987Eric Laurent client.incCount(scoAudioMode); 21482a57ca931fefe817b6110101289721acaacfc808Eric Laurent Binder.restoreCallingIdentity(ident); 21493def1eec2baed0b8845ec32c871e249dc533a9d9Eric Laurent } 21503def1eec2baed0b8845ec32c871e249dc533a9d9Eric Laurent 21513def1eec2baed0b8845ec32c871e249dc533a9d9Eric Laurent /** @see AudioManager#stopBluetoothSco() */ 21523def1eec2baed0b8845ec32c871e249dc533a9d9Eric Laurent public void stopBluetoothSco(IBinder cb){ 2153dc03c61fe3cd8d0805480e48a974986439977a60Eric Laurent if (!checkAudioSettingsPermission("stopBluetoothSco()") || 21544a5eeb9c727d77bb57fef87a70c8c9cc23dbfee3Eric Laurent !mSystemReady) { 21553def1eec2baed0b8845ec32c871e249dc533a9d9Eric Laurent return; 21563def1eec2baed0b8845ec32c871e249dc533a9d9Eric Laurent } 2157854938a72d968c1bc0de4e2b0ea87777cfebc045Eric Laurent ScoClient client = getScoClient(cb, false); 2158f5a1fc3c0fd733acd21e1437f153ba27220be8ceEric Laurent // The calling identity must be cleared before calling ScoClient.decCount(). 2159f5a1fc3c0fd733acd21e1437f153ba27220be8ceEric Laurent // decCount() calls requestScoState() which in turn can call BluetoothHeadset APIs 2160f5a1fc3c0fd733acd21e1437f153ba27220be8ceEric Laurent // and this must be done on behalf of system server to make sure permissions are granted. 2161f5a1fc3c0fd733acd21e1437f153ba27220be8ceEric Laurent final long ident = Binder.clearCallingIdentity(); 2162854938a72d968c1bc0de4e2b0ea87777cfebc045Eric Laurent if (client != null) { 2163854938a72d968c1bc0de4e2b0ea87777cfebc045Eric Laurent client.decCount(); 2164854938a72d968c1bc0de4e2b0ea87777cfebc045Eric Laurent } 21652a57ca931fefe817b6110101289721acaacfc808Eric Laurent Binder.restoreCallingIdentity(ident); 21663def1eec2baed0b8845ec32c871e249dc533a9d9Eric Laurent } 21673def1eec2baed0b8845ec32c871e249dc533a9d9Eric Laurent 21687847211fb4699bf6018e29d214a918ed6657319bEric Laurent 21693def1eec2baed0b8845ec32c871e249dc533a9d9Eric Laurent private class ScoClient implements IBinder.DeathRecipient { 21703def1eec2baed0b8845ec32c871e249dc533a9d9Eric Laurent private IBinder mCb; // To be notified of client's death 2171f1ddd51f9cd2f92b922bc636c307210a8d587c25Marco Nelissen private int mCreatorPid; 21723def1eec2baed0b8845ec32c871e249dc533a9d9Eric Laurent private int mStartcount; // number of SCO connections started by this client 21733def1eec2baed0b8845ec32c871e249dc533a9d9Eric Laurent 21743def1eec2baed0b8845ec32c871e249dc533a9d9Eric Laurent ScoClient(IBinder cb) { 21753def1eec2baed0b8845ec32c871e249dc533a9d9Eric Laurent mCb = cb; 2176f1ddd51f9cd2f92b922bc636c307210a8d587c25Marco Nelissen mCreatorPid = Binder.getCallingPid(); 21773def1eec2baed0b8845ec32c871e249dc533a9d9Eric Laurent mStartcount = 0; 21783def1eec2baed0b8845ec32c871e249dc533a9d9Eric Laurent } 21793def1eec2baed0b8845ec32c871e249dc533a9d9Eric Laurent 21803def1eec2baed0b8845ec32c871e249dc533a9d9Eric Laurent public void binderDied() { 21813def1eec2baed0b8845ec32c871e249dc533a9d9Eric Laurent synchronized(mScoClients) { 21823def1eec2baed0b8845ec32c871e249dc533a9d9Eric Laurent Log.w(TAG, "SCO client died"); 21833def1eec2baed0b8845ec32c871e249dc533a9d9Eric Laurent int index = mScoClients.indexOf(this); 21843def1eec2baed0b8845ec32c871e249dc533a9d9Eric Laurent if (index < 0) { 21853def1eec2baed0b8845ec32c871e249dc533a9d9Eric Laurent Log.w(TAG, "unregistered SCO client died"); 21863def1eec2baed0b8845ec32c871e249dc533a9d9Eric Laurent } else { 21873def1eec2baed0b8845ec32c871e249dc533a9d9Eric Laurent clearCount(true); 21883def1eec2baed0b8845ec32c871e249dc533a9d9Eric Laurent mScoClients.remove(this); 21893def1eec2baed0b8845ec32c871e249dc533a9d9Eric Laurent } 21903def1eec2baed0b8845ec32c871e249dc533a9d9Eric Laurent } 21913def1eec2baed0b8845ec32c871e249dc533a9d9Eric Laurent } 21923def1eec2baed0b8845ec32c871e249dc533a9d9Eric Laurent 219383900754f357616b9e56eaf7fc85f49b8906e987Eric Laurent public void incCount(int scoAudioMode) { 21943def1eec2baed0b8845ec32c871e249dc533a9d9Eric Laurent synchronized(mScoClients) { 219583900754f357616b9e56eaf7fc85f49b8906e987Eric Laurent requestScoState(BluetoothHeadset.STATE_AUDIO_CONNECTED, scoAudioMode); 21963def1eec2baed0b8845ec32c871e249dc533a9d9Eric Laurent if (mStartcount == 0) { 21973def1eec2baed0b8845ec32c871e249dc533a9d9Eric Laurent try { 21983def1eec2baed0b8845ec32c871e249dc533a9d9Eric Laurent mCb.linkToDeath(this, 0); 21993def1eec2baed0b8845ec32c871e249dc533a9d9Eric Laurent } catch (RemoteException e) { 22003def1eec2baed0b8845ec32c871e249dc533a9d9Eric Laurent // client has already died! 22013def1eec2baed0b8845ec32c871e249dc533a9d9Eric Laurent Log.w(TAG, "ScoClient incCount() could not link to "+mCb+" binder death"); 22023def1eec2baed0b8845ec32c871e249dc533a9d9Eric Laurent } 22033def1eec2baed0b8845ec32c871e249dc533a9d9Eric Laurent } 22043def1eec2baed0b8845ec32c871e249dc533a9d9Eric Laurent mStartcount++; 22053def1eec2baed0b8845ec32c871e249dc533a9d9Eric Laurent } 22063def1eec2baed0b8845ec32c871e249dc533a9d9Eric Laurent } 22073def1eec2baed0b8845ec32c871e249dc533a9d9Eric Laurent 22083def1eec2baed0b8845ec32c871e249dc533a9d9Eric Laurent public void decCount() { 22093def1eec2baed0b8845ec32c871e249dc533a9d9Eric Laurent synchronized(mScoClients) { 22103def1eec2baed0b8845ec32c871e249dc533a9d9Eric Laurent if (mStartcount == 0) { 22113def1eec2baed0b8845ec32c871e249dc533a9d9Eric Laurent Log.w(TAG, "ScoClient.decCount() already 0"); 22123def1eec2baed0b8845ec32c871e249dc533a9d9Eric Laurent } else { 22133def1eec2baed0b8845ec32c871e249dc533a9d9Eric Laurent mStartcount--; 22143def1eec2baed0b8845ec32c871e249dc533a9d9Eric Laurent if (mStartcount == 0) { 2215e2dd8c4592762414c2c27e4589be7edc91a5ecaeEric Laurent try { 2216e2dd8c4592762414c2c27e4589be7edc91a5ecaeEric Laurent mCb.unlinkToDeath(this, 0); 2217e2dd8c4592762414c2c27e4589be7edc91a5ecaeEric Laurent } catch (NoSuchElementException e) { 2218e2dd8c4592762414c2c27e4589be7edc91a5ecaeEric Laurent Log.w(TAG, "decCount() going to 0 but not registered to binder"); 2219e2dd8c4592762414c2c27e4589be7edc91a5ecaeEric Laurent } 22203def1eec2baed0b8845ec32c871e249dc533a9d9Eric Laurent } 2221c18c9138cee0f0859bcab636a004ce92ca4a9ab5Eric Laurent requestScoState(BluetoothHeadset.STATE_AUDIO_DISCONNECTED, 0); 22223def1eec2baed0b8845ec32c871e249dc533a9d9Eric Laurent } 22233def1eec2baed0b8845ec32c871e249dc533a9d9Eric Laurent } 22243def1eec2baed0b8845ec32c871e249dc533a9d9Eric Laurent } 22253def1eec2baed0b8845ec32c871e249dc533a9d9Eric Laurent 22263def1eec2baed0b8845ec32c871e249dc533a9d9Eric Laurent public void clearCount(boolean stopSco) { 22273def1eec2baed0b8845ec32c871e249dc533a9d9Eric Laurent synchronized(mScoClients) { 2228e2dd8c4592762414c2c27e4589be7edc91a5ecaeEric Laurent if (mStartcount != 0) { 2229e2dd8c4592762414c2c27e4589be7edc91a5ecaeEric Laurent try { 2230e2dd8c4592762414c2c27e4589be7edc91a5ecaeEric Laurent mCb.unlinkToDeath(this, 0); 2231e2dd8c4592762414c2c27e4589be7edc91a5ecaeEric Laurent } catch (NoSuchElementException e) { 2232e2dd8c4592762414c2c27e4589be7edc91a5ecaeEric Laurent Log.w(TAG, "clearCount() mStartcount: "+mStartcount+" != 0 but not registered to binder"); 2233e2dd8c4592762414c2c27e4589be7edc91a5ecaeEric Laurent } 2234e2dd8c4592762414c2c27e4589be7edc91a5ecaeEric Laurent } 22353def1eec2baed0b8845ec32c871e249dc533a9d9Eric Laurent mStartcount = 0; 22363def1eec2baed0b8845ec32c871e249dc533a9d9Eric Laurent if (stopSco) { 2237c18c9138cee0f0859bcab636a004ce92ca4a9ab5Eric Laurent requestScoState(BluetoothHeadset.STATE_AUDIO_DISCONNECTED, 0); 22383def1eec2baed0b8845ec32c871e249dc533a9d9Eric Laurent } 22393def1eec2baed0b8845ec32c871e249dc533a9d9Eric Laurent } 22403def1eec2baed0b8845ec32c871e249dc533a9d9Eric Laurent } 22413def1eec2baed0b8845ec32c871e249dc533a9d9Eric Laurent 22423def1eec2baed0b8845ec32c871e249dc533a9d9Eric Laurent public int getCount() { 22433def1eec2baed0b8845ec32c871e249dc533a9d9Eric Laurent return mStartcount; 22443def1eec2baed0b8845ec32c871e249dc533a9d9Eric Laurent } 22453def1eec2baed0b8845ec32c871e249dc533a9d9Eric Laurent 22463def1eec2baed0b8845ec32c871e249dc533a9d9Eric Laurent public IBinder getBinder() { 22473def1eec2baed0b8845ec32c871e249dc533a9d9Eric Laurent return mCb; 22483def1eec2baed0b8845ec32c871e249dc533a9d9Eric Laurent } 22493def1eec2baed0b8845ec32c871e249dc533a9d9Eric Laurent 2250d7454be47f4111c0478a502353e11dea401378bdEric Laurent public int getPid() { 2251d7454be47f4111c0478a502353e11dea401378bdEric Laurent return mCreatorPid; 2252d7454be47f4111c0478a502353e11dea401378bdEric Laurent } 2253d7454be47f4111c0478a502353e11dea401378bdEric Laurent 22543def1eec2baed0b8845ec32c871e249dc533a9d9Eric Laurent public int totalCount() { 22553def1eec2baed0b8845ec32c871e249dc533a9d9Eric Laurent synchronized(mScoClients) { 22563def1eec2baed0b8845ec32c871e249dc533a9d9Eric Laurent int count = 0; 22573def1eec2baed0b8845ec32c871e249dc533a9d9Eric Laurent int size = mScoClients.size(); 22583def1eec2baed0b8845ec32c871e249dc533a9d9Eric Laurent for (int i = 0; i < size; i++) { 22593def1eec2baed0b8845ec32c871e249dc533a9d9Eric Laurent count += mScoClients.get(i).getCount(); 22603def1eec2baed0b8845ec32c871e249dc533a9d9Eric Laurent } 22613def1eec2baed0b8845ec32c871e249dc533a9d9Eric Laurent return count; 22623def1eec2baed0b8845ec32c871e249dc533a9d9Eric Laurent } 22633def1eec2baed0b8845ec32c871e249dc533a9d9Eric Laurent } 22643def1eec2baed0b8845ec32c871e249dc533a9d9Eric Laurent 226583900754f357616b9e56eaf7fc85f49b8906e987Eric Laurent private void requestScoState(int state, int scoAudioMode) { 226662ef767b15a712bab31cc0d5508a330906f535c2Eric Laurent checkScoAudioState(); 2267dc03c61fe3cd8d0805480e48a974986439977a60Eric Laurent if (totalCount() == 0) { 2268dc03c61fe3cd8d0805480e48a974986439977a60Eric Laurent if (state == BluetoothHeadset.STATE_AUDIO_CONNECTED) { 2269dc03c61fe3cd8d0805480e48a974986439977a60Eric Laurent // Make sure that the state transitions to CONNECTING even if we cannot initiate 2270dc03c61fe3cd8d0805480e48a974986439977a60Eric Laurent // the connection. 2271dc03c61fe3cd8d0805480e48a974986439977a60Eric Laurent broadcastScoConnectionState(AudioManager.SCO_AUDIO_STATE_CONNECTING); 2272dc03c61fe3cd8d0805480e48a974986439977a60Eric Laurent // Accept SCO audio activation only in NORMAL audio mode or if the mode is 2273f1ddd51f9cd2f92b922bc636c307210a8d587c25Marco Nelissen // currently controlled by the same client process. 22749f103de83f2d5d472960dcf1401e95b2ab57a477Eric Laurent synchronized(mSetModeDeathHandlers) { 22759f103de83f2d5d472960dcf1401e95b2ab57a477Eric Laurent if ((mSetModeDeathHandlers.isEmpty() || 22769f103de83f2d5d472960dcf1401e95b2ab57a477Eric Laurent mSetModeDeathHandlers.get(0).getPid() == mCreatorPid) && 22779f103de83f2d5d472960dcf1401e95b2ab57a477Eric Laurent (mScoAudioState == SCO_STATE_INACTIVE || 22789f103de83f2d5d472960dcf1401e95b2ab57a477Eric Laurent mScoAudioState == SCO_STATE_DEACTIVATE_REQ)) { 22799f103de83f2d5d472960dcf1401e95b2ab57a477Eric Laurent if (mScoAudioState == SCO_STATE_INACTIVE) { 228083900754f357616b9e56eaf7fc85f49b8906e987Eric Laurent mScoAudioMode = scoAudioMode; 2281f4e51d82d2e34e6832903f01eaecc15ded6c3241Liejun Tao if (scoAudioMode == SCO_MODE_UNDEFINED) { 2282f4e51d82d2e34e6832903f01eaecc15ded6c3241Liejun Tao mScoAudioMode = new Integer(Settings.Global.getInt( 2283f4e51d82d2e34e6832903f01eaecc15ded6c3241Liejun Tao mContentResolver, 2284f4e51d82d2e34e6832903f01eaecc15ded6c3241Liejun Tao "bluetooth_sco_channel_"+ 2285f4e51d82d2e34e6832903f01eaecc15ded6c3241Liejun Tao mBluetoothHeadsetDevice.getAddress(), 2286f4e51d82d2e34e6832903f01eaecc15ded6c3241Liejun Tao SCO_MODE_VIRTUAL_CALL)); 2287f4e51d82d2e34e6832903f01eaecc15ded6c3241Liejun Tao if (mScoAudioMode > SCO_MODE_MAX || mScoAudioMode < 0) { 2288f4e51d82d2e34e6832903f01eaecc15ded6c3241Liejun Tao mScoAudioMode = SCO_MODE_VIRTUAL_CALL; 2289f4e51d82d2e34e6832903f01eaecc15ded6c3241Liejun Tao } 2290f4e51d82d2e34e6832903f01eaecc15ded6c3241Liejun Tao } 22919f103de83f2d5d472960dcf1401e95b2ab57a477Eric Laurent if (mBluetoothHeadset != null && mBluetoothHeadsetDevice != null) { 2292f4e51d82d2e34e6832903f01eaecc15ded6c3241Liejun Tao boolean status = false; 2293c18c9138cee0f0859bcab636a004ce92ca4a9ab5Eric Laurent if (mScoAudioMode == SCO_MODE_RAW) { 2294c18c9138cee0f0859bcab636a004ce92ca4a9ab5Eric Laurent status = mBluetoothHeadset.connectAudio(); 2295f4e51d82d2e34e6832903f01eaecc15ded6c3241Liejun Tao } else if (mScoAudioMode == SCO_MODE_VIRTUAL_CALL) { 2296c18c9138cee0f0859bcab636a004ce92ca4a9ab5Eric Laurent status = mBluetoothHeadset.startScoUsingVirtualVoiceCall( 2297c18c9138cee0f0859bcab636a004ce92ca4a9ab5Eric Laurent mBluetoothHeadsetDevice); 2298f4e51d82d2e34e6832903f01eaecc15ded6c3241Liejun Tao } else if (mScoAudioMode == SCO_MODE_VR) { 2299f4e51d82d2e34e6832903f01eaecc15ded6c3241Liejun Tao status = mBluetoothHeadset.startVoiceRecognition( 2300f4e51d82d2e34e6832903f01eaecc15ded6c3241Liejun Tao mBluetoothHeadsetDevice); 2301c18c9138cee0f0859bcab636a004ce92ca4a9ab5Eric Laurent } 2302f4e51d82d2e34e6832903f01eaecc15ded6c3241Liejun Tao 2303c18c9138cee0f0859bcab636a004ce92ca4a9ab5Eric Laurent if (status) { 23049f103de83f2d5d472960dcf1401e95b2ab57a477Eric Laurent mScoAudioState = SCO_STATE_ACTIVE_INTERNAL; 23059f103de83f2d5d472960dcf1401e95b2ab57a477Eric Laurent } else { 23069f103de83f2d5d472960dcf1401e95b2ab57a477Eric Laurent broadcastScoConnectionState( 23079f103de83f2d5d472960dcf1401e95b2ab57a477Eric Laurent AudioManager.SCO_AUDIO_STATE_DISCONNECTED); 23089f103de83f2d5d472960dcf1401e95b2ab57a477Eric Laurent } 23099f103de83f2d5d472960dcf1401e95b2ab57a477Eric Laurent } else if (getBluetoothHeadset()) { 23109f103de83f2d5d472960dcf1401e95b2ab57a477Eric Laurent mScoAudioState = SCO_STATE_ACTIVATE_REQ; 2311dc03c61fe3cd8d0805480e48a974986439977a60Eric Laurent } 23129f103de83f2d5d472960dcf1401e95b2ab57a477Eric Laurent } else { 23139f103de83f2d5d472960dcf1401e95b2ab57a477Eric Laurent mScoAudioState = SCO_STATE_ACTIVE_INTERNAL; 23149f103de83f2d5d472960dcf1401e95b2ab57a477Eric Laurent broadcastScoConnectionState(AudioManager.SCO_AUDIO_STATE_CONNECTED); 2315dc03c61fe3cd8d0805480e48a974986439977a60Eric Laurent } 2316dc03c61fe3cd8d0805480e48a974986439977a60Eric Laurent } else { 23179f103de83f2d5d472960dcf1401e95b2ab57a477Eric Laurent broadcastScoConnectionState(AudioManager.SCO_AUDIO_STATE_DISCONNECTED); 2318dc03c61fe3cd8d0805480e48a974986439977a60Eric Laurent } 2319dc03c61fe3cd8d0805480e48a974986439977a60Eric Laurent } 232062ef767b15a712bab31cc0d5508a330906f535c2Eric Laurent } else if (state == BluetoothHeadset.STATE_AUDIO_DISCONNECTED && 2321dc03c61fe3cd8d0805480e48a974986439977a60Eric Laurent (mScoAudioState == SCO_STATE_ACTIVE_INTERNAL || 2322dc03c61fe3cd8d0805480e48a974986439977a60Eric Laurent mScoAudioState == SCO_STATE_ACTIVATE_REQ)) { 2323dc03c61fe3cd8d0805480e48a974986439977a60Eric Laurent if (mScoAudioState == SCO_STATE_ACTIVE_INTERNAL) { 2324671db6f3ba1fdb3c907e0735fe6d0d284f5c34deMarco Nelissen if (mBluetoothHeadset != null && mBluetoothHeadsetDevice != null) { 2325f4e51d82d2e34e6832903f01eaecc15ded6c3241Liejun Tao boolean status = false; 2326c18c9138cee0f0859bcab636a004ce92ca4a9ab5Eric Laurent if (mScoAudioMode == SCO_MODE_RAW) { 2327c18c9138cee0f0859bcab636a004ce92ca4a9ab5Eric Laurent status = mBluetoothHeadset.disconnectAudio(); 2328f4e51d82d2e34e6832903f01eaecc15ded6c3241Liejun Tao } else if (mScoAudioMode == SCO_MODE_VIRTUAL_CALL) { 2329c18c9138cee0f0859bcab636a004ce92ca4a9ab5Eric Laurent status = mBluetoothHeadset.stopScoUsingVirtualVoiceCall( 2330c18c9138cee0f0859bcab636a004ce92ca4a9ab5Eric Laurent mBluetoothHeadsetDevice); 2331f4e51d82d2e34e6832903f01eaecc15ded6c3241Liejun Tao } else if (mScoAudioMode == SCO_MODE_VR) { 2332f4e51d82d2e34e6832903f01eaecc15ded6c3241Liejun Tao status = mBluetoothHeadset.stopVoiceRecognition( 2333f4e51d82d2e34e6832903f01eaecc15ded6c3241Liejun Tao mBluetoothHeadsetDevice); 2334c18c9138cee0f0859bcab636a004ce92ca4a9ab5Eric Laurent } 2335f4e51d82d2e34e6832903f01eaecc15ded6c3241Liejun Tao 2336c18c9138cee0f0859bcab636a004ce92ca4a9ab5Eric Laurent if (!status) { 2337dc03c61fe3cd8d0805480e48a974986439977a60Eric Laurent mScoAudioState = SCO_STATE_INACTIVE; 2338dc03c61fe3cd8d0805480e48a974986439977a60Eric Laurent broadcastScoConnectionState( 2339dc03c61fe3cd8d0805480e48a974986439977a60Eric Laurent AudioManager.SCO_AUDIO_STATE_DISCONNECTED); 2340dc03c61fe3cd8d0805480e48a974986439977a60Eric Laurent } 2341dc03c61fe3cd8d0805480e48a974986439977a60Eric Laurent } else if (getBluetoothHeadset()) { 2342dc03c61fe3cd8d0805480e48a974986439977a60Eric Laurent mScoAudioState = SCO_STATE_DEACTIVATE_REQ; 2343dc03c61fe3cd8d0805480e48a974986439977a60Eric Laurent } 2344dc03c61fe3cd8d0805480e48a974986439977a60Eric Laurent } else { 2345dc03c61fe3cd8d0805480e48a974986439977a60Eric Laurent mScoAudioState = SCO_STATE_INACTIVE; 2346dc03c61fe3cd8d0805480e48a974986439977a60Eric Laurent broadcastScoConnectionState(AudioManager.SCO_AUDIO_STATE_DISCONNECTED); 2347dc03c61fe3cd8d0805480e48a974986439977a60Eric Laurent } 23483def1eec2baed0b8845ec32c871e249dc533a9d9Eric Laurent } 23493def1eec2baed0b8845ec32c871e249dc533a9d9Eric Laurent } 23503def1eec2baed0b8845ec32c871e249dc533a9d9Eric Laurent } 23513def1eec2baed0b8845ec32c871e249dc533a9d9Eric Laurent } 23523def1eec2baed0b8845ec32c871e249dc533a9d9Eric Laurent 235362ef767b15a712bab31cc0d5508a330906f535c2Eric Laurent private void checkScoAudioState() { 235462ef767b15a712bab31cc0d5508a330906f535c2Eric Laurent if (mBluetoothHeadset != null && mBluetoothHeadsetDevice != null && 2355dc03c61fe3cd8d0805480e48a974986439977a60Eric Laurent mScoAudioState == SCO_STATE_INACTIVE && 235662ef767b15a712bab31cc0d5508a330906f535c2Eric Laurent mBluetoothHeadset.getAudioState(mBluetoothHeadsetDevice) 235762ef767b15a712bab31cc0d5508a330906f535c2Eric Laurent != BluetoothHeadset.STATE_AUDIO_DISCONNECTED) { 235862ef767b15a712bab31cc0d5508a330906f535c2Eric Laurent mScoAudioState = SCO_STATE_ACTIVE_EXTERNAL; 235962ef767b15a712bab31cc0d5508a330906f535c2Eric Laurent } 236062ef767b15a712bab31cc0d5508a330906f535c2Eric Laurent } 236162ef767b15a712bab31cc0d5508a330906f535c2Eric Laurent 2362854938a72d968c1bc0de4e2b0ea87777cfebc045Eric Laurent private ScoClient getScoClient(IBinder cb, boolean create) { 23633def1eec2baed0b8845ec32c871e249dc533a9d9Eric Laurent synchronized(mScoClients) { 2364854938a72d968c1bc0de4e2b0ea87777cfebc045Eric Laurent ScoClient client = null; 23653def1eec2baed0b8845ec32c871e249dc533a9d9Eric Laurent int size = mScoClients.size(); 23663def1eec2baed0b8845ec32c871e249dc533a9d9Eric Laurent for (int i = 0; i < size; i++) { 23673def1eec2baed0b8845ec32c871e249dc533a9d9Eric Laurent client = mScoClients.get(i); 23683def1eec2baed0b8845ec32c871e249dc533a9d9Eric Laurent if (client.getBinder() == cb) 23693def1eec2baed0b8845ec32c871e249dc533a9d9Eric Laurent return client; 23703def1eec2baed0b8845ec32c871e249dc533a9d9Eric Laurent } 2371854938a72d968c1bc0de4e2b0ea87777cfebc045Eric Laurent if (create) { 2372854938a72d968c1bc0de4e2b0ea87777cfebc045Eric Laurent client = new ScoClient(cb); 2373854938a72d968c1bc0de4e2b0ea87777cfebc045Eric Laurent mScoClients.add(client); 2374854938a72d968c1bc0de4e2b0ea87777cfebc045Eric Laurent } 23753def1eec2baed0b8845ec32c871e249dc533a9d9Eric Laurent return client; 23763def1eec2baed0b8845ec32c871e249dc533a9d9Eric Laurent } 23773def1eec2baed0b8845ec32c871e249dc533a9d9Eric Laurent } 23783def1eec2baed0b8845ec32c871e249dc533a9d9Eric Laurent 2379d7454be47f4111c0478a502353e11dea401378bdEric Laurent public void clearAllScoClients(int exceptPid, boolean stopSco) { 23803def1eec2baed0b8845ec32c871e249dc533a9d9Eric Laurent synchronized(mScoClients) { 2381854938a72d968c1bc0de4e2b0ea87777cfebc045Eric Laurent ScoClient savedClient = null; 23823def1eec2baed0b8845ec32c871e249dc533a9d9Eric Laurent int size = mScoClients.size(); 23833def1eec2baed0b8845ec32c871e249dc533a9d9Eric Laurent for (int i = 0; i < size; i++) { 2384854938a72d968c1bc0de4e2b0ea87777cfebc045Eric Laurent ScoClient cl = mScoClients.get(i); 2385d7454be47f4111c0478a502353e11dea401378bdEric Laurent if (cl.getPid() != exceptPid) { 2386854938a72d968c1bc0de4e2b0ea87777cfebc045Eric Laurent cl.clearCount(stopSco); 2387854938a72d968c1bc0de4e2b0ea87777cfebc045Eric Laurent } else { 2388854938a72d968c1bc0de4e2b0ea87777cfebc045Eric Laurent savedClient = cl; 2389854938a72d968c1bc0de4e2b0ea87777cfebc045Eric Laurent } 2390854938a72d968c1bc0de4e2b0ea87777cfebc045Eric Laurent } 2391854938a72d968c1bc0de4e2b0ea87777cfebc045Eric Laurent mScoClients.clear(); 2392854938a72d968c1bc0de4e2b0ea87777cfebc045Eric Laurent if (savedClient != null) { 2393854938a72d968c1bc0de4e2b0ea87777cfebc045Eric Laurent mScoClients.add(savedClient); 23943def1eec2baed0b8845ec32c871e249dc533a9d9Eric Laurent } 23953def1eec2baed0b8845ec32c871e249dc533a9d9Eric Laurent } 23963def1eec2baed0b8845ec32c871e249dc533a9d9Eric Laurent } 23973def1eec2baed0b8845ec32c871e249dc533a9d9Eric Laurent 2398dc03c61fe3cd8d0805480e48a974986439977a60Eric Laurent private boolean getBluetoothHeadset() { 2399dc03c61fe3cd8d0805480e48a974986439977a60Eric Laurent boolean result = false; 2400dc03c61fe3cd8d0805480e48a974986439977a60Eric Laurent BluetoothAdapter adapter = BluetoothAdapter.getDefaultAdapter(); 2401dc03c61fe3cd8d0805480e48a974986439977a60Eric Laurent if (adapter != null) { 2402dc03c61fe3cd8d0805480e48a974986439977a60Eric Laurent result = adapter.getProfileProxy(mContext, mBluetoothProfileServiceListener, 2403dc03c61fe3cd8d0805480e48a974986439977a60Eric Laurent BluetoothProfile.HEADSET); 2404dc03c61fe3cd8d0805480e48a974986439977a60Eric Laurent } 2405dc03c61fe3cd8d0805480e48a974986439977a60Eric Laurent // If we could not get a bluetooth headset proxy, send a failure message 2406dc03c61fe3cd8d0805480e48a974986439977a60Eric Laurent // without delay to reset the SCO audio state and clear SCO clients. 2407dc03c61fe3cd8d0805480e48a974986439977a60Eric Laurent // If we could get a proxy, send a delayed failure message that will reset our state 2408dc03c61fe3cd8d0805480e48a974986439977a60Eric Laurent // in case we don't receive onServiceConnected(). 2409afbb047c3945e9c2b7e9bc6b25098d5fb80bba4eEric Laurent sendMsg(mAudioHandler, MSG_BT_HEADSET_CNCT_FAILED, 2410dc03c61fe3cd8d0805480e48a974986439977a60Eric Laurent SENDMSG_REPLACE, 0, 0, null, result ? BT_HEADSET_CNCT_TIMEOUT_MS : 0); 2411dc03c61fe3cd8d0805480e48a974986439977a60Eric Laurent return result; 2412dc03c61fe3cd8d0805480e48a974986439977a60Eric Laurent } 2413dc03c61fe3cd8d0805480e48a974986439977a60Eric Laurent 2414d7454be47f4111c0478a502353e11dea401378bdEric Laurent private void disconnectBluetoothSco(int exceptPid) { 2415dc03c61fe3cd8d0805480e48a974986439977a60Eric Laurent synchronized(mScoClients) { 2416dc03c61fe3cd8d0805480e48a974986439977a60Eric Laurent checkScoAudioState(); 2417dc03c61fe3cd8d0805480e48a974986439977a60Eric Laurent if (mScoAudioState == SCO_STATE_ACTIVE_EXTERNAL || 2418dc03c61fe3cd8d0805480e48a974986439977a60Eric Laurent mScoAudioState == SCO_STATE_DEACTIVATE_EXT_REQ) { 2419dc03c61fe3cd8d0805480e48a974986439977a60Eric Laurent if (mBluetoothHeadsetDevice != null) { 2420dc03c61fe3cd8d0805480e48a974986439977a60Eric Laurent if (mBluetoothHeadset != null) { 2421dc03c61fe3cd8d0805480e48a974986439977a60Eric Laurent if (!mBluetoothHeadset.stopVoiceRecognition( 2422b06ac839dd2d0437fc8314f6deb7233af5af521eEric Laurent mBluetoothHeadsetDevice)) { 2423afbb047c3945e9c2b7e9bc6b25098d5fb80bba4eEric Laurent sendMsg(mAudioHandler, MSG_BT_HEADSET_CNCT_FAILED, 2424dc03c61fe3cd8d0805480e48a974986439977a60Eric Laurent SENDMSG_REPLACE, 0, 0, null, 0); 2425dc03c61fe3cd8d0805480e48a974986439977a60Eric Laurent } 2426dc03c61fe3cd8d0805480e48a974986439977a60Eric Laurent } else if (mScoAudioState == SCO_STATE_ACTIVE_EXTERNAL && 2427dc03c61fe3cd8d0805480e48a974986439977a60Eric Laurent getBluetoothHeadset()) { 2428dc03c61fe3cd8d0805480e48a974986439977a60Eric Laurent mScoAudioState = SCO_STATE_DEACTIVATE_EXT_REQ; 2429dc03c61fe3cd8d0805480e48a974986439977a60Eric Laurent } 2430dc03c61fe3cd8d0805480e48a974986439977a60Eric Laurent } 2431dc03c61fe3cd8d0805480e48a974986439977a60Eric Laurent } else { 2432d7454be47f4111c0478a502353e11dea401378bdEric Laurent clearAllScoClients(exceptPid, true); 2433dc03c61fe3cd8d0805480e48a974986439977a60Eric Laurent } 2434dc03c61fe3cd8d0805480e48a974986439977a60Eric Laurent } 2435dc03c61fe3cd8d0805480e48a974986439977a60Eric Laurent } 2436dc03c61fe3cd8d0805480e48a974986439977a60Eric Laurent 2437dc03c61fe3cd8d0805480e48a974986439977a60Eric Laurent private void resetBluetoothSco() { 2438dc03c61fe3cd8d0805480e48a974986439977a60Eric Laurent synchronized(mScoClients) { 2439d7454be47f4111c0478a502353e11dea401378bdEric Laurent clearAllScoClients(0, false); 2440dc03c61fe3cd8d0805480e48a974986439977a60Eric Laurent mScoAudioState = SCO_STATE_INACTIVE; 2441dc03c61fe3cd8d0805480e48a974986439977a60Eric Laurent broadcastScoConnectionState(AudioManager.SCO_AUDIO_STATE_DISCONNECTED); 2442dc03c61fe3cd8d0805480e48a974986439977a60Eric Laurent } 2443dc03c61fe3cd8d0805480e48a974986439977a60Eric Laurent } 2444dc03c61fe3cd8d0805480e48a974986439977a60Eric Laurent 2445dc03c61fe3cd8d0805480e48a974986439977a60Eric Laurent private void broadcastScoConnectionState(int state) { 24462a57ca931fefe817b6110101289721acaacfc808Eric Laurent sendMsg(mAudioHandler, MSG_BROADCAST_BT_CONNECTION_STATE, 24472a57ca931fefe817b6110101289721acaacfc808Eric Laurent SENDMSG_QUEUE, state, 0, null, 0); 24482a57ca931fefe817b6110101289721acaacfc808Eric Laurent } 24492a57ca931fefe817b6110101289721acaacfc808Eric Laurent 24502a57ca931fefe817b6110101289721acaacfc808Eric Laurent private void onBroadcastScoConnectionState(int state) { 2451dc03c61fe3cd8d0805480e48a974986439977a60Eric Laurent if (state != mScoConnectionState) { 2452dc03c61fe3cd8d0805480e48a974986439977a60Eric Laurent Intent newIntent = new Intent(AudioManager.ACTION_SCO_AUDIO_STATE_UPDATED); 2453dc03c61fe3cd8d0805480e48a974986439977a60Eric Laurent newIntent.putExtra(AudioManager.EXTRA_SCO_AUDIO_STATE, state); 2454dc03c61fe3cd8d0805480e48a974986439977a60Eric Laurent newIntent.putExtra(AudioManager.EXTRA_SCO_AUDIO_PREVIOUS_STATE, 2455dc03c61fe3cd8d0805480e48a974986439977a60Eric Laurent mScoConnectionState); 24565ac72a29593ab9a20337a2225df52bdf4754be02Dianne Hackborn sendStickyBroadcastToAll(newIntent); 2457dc03c61fe3cd8d0805480e48a974986439977a60Eric Laurent mScoConnectionState = state; 2458dc03c61fe3cd8d0805480e48a974986439977a60Eric Laurent } 2459dc03c61fe3cd8d0805480e48a974986439977a60Eric Laurent } 2460dc03c61fe3cd8d0805480e48a974986439977a60Eric Laurent 246182aa7f017daaaeb96c13e6e3491d5037ab471085Jaikumar Ganesh private BluetoothProfile.ServiceListener mBluetoothProfileServiceListener = 246282aa7f017daaaeb96c13e6e3491d5037ab471085Jaikumar Ganesh new BluetoothProfile.ServiceListener() { 246382aa7f017daaaeb96c13e6e3491d5037ab471085Jaikumar Ganesh public void onServiceConnected(int profile, BluetoothProfile proxy) { 24646bc7f2cd30b6bd90806942b0722e22daa2108493Eric Laurent BluetoothDevice btDevice; 24656bc7f2cd30b6bd90806942b0722e22daa2108493Eric Laurent List<BluetoothDevice> deviceList; 24666bc7f2cd30b6bd90806942b0722e22daa2108493Eric Laurent switch(profile) { 24676bc7f2cd30b6bd90806942b0722e22daa2108493Eric Laurent case BluetoothProfile.A2DP: 24685a0cf7a27f3953a1266af48543ccd9024f4cd89fJohn Du synchronized (mA2dpAvrcpLock) { 24695a0cf7a27f3953a1266af48543ccd9024f4cd89fJohn Du mA2dp = (BluetoothA2dp) proxy; 24705a0cf7a27f3953a1266af48543ccd9024f4cd89fJohn Du deviceList = mA2dp.getConnectedDevices(); 24715a0cf7a27f3953a1266af48543ccd9024f4cd89fJohn Du if (deviceList.size() > 0) { 24725a0cf7a27f3953a1266af48543ccd9024f4cd89fJohn Du btDevice = deviceList.get(0); 24735a0cf7a27f3953a1266af48543ccd9024f4cd89fJohn Du synchronized (mConnectedDevices) { 24745a0cf7a27f3953a1266af48543ccd9024f4cd89fJohn Du int state = mA2dp.getConnectionState(btDevice); 24755a0cf7a27f3953a1266af48543ccd9024f4cd89fJohn Du int delay = checkSendBecomingNoisyIntent( 24760a40ec2192e4836b2fcb6ba51a7688aa6bd4ee98Mike Lockwood AudioSystem.DEVICE_OUT_BLUETOOTH_A2DP, 24770a40ec2192e4836b2fcb6ba51a7688aa6bd4ee98Mike Lockwood (state == BluetoothA2dp.STATE_CONNECTED) ? 1 : 0); 24785a0cf7a27f3953a1266af48543ccd9024f4cd89fJohn Du queueMsgUnderWakeLock(mAudioHandler, 24790a40ec2192e4836b2fcb6ba51a7688aa6bd4ee98Mike Lockwood MSG_SET_A2DP_SINK_CONNECTION_STATE, 24805a0cf7a27f3953a1266af48543ccd9024f4cd89fJohn Du state, 24815a0cf7a27f3953a1266af48543ccd9024f4cd89fJohn Du 0, 24825a0cf7a27f3953a1266af48543ccd9024f4cd89fJohn Du btDevice, 24835a0cf7a27f3953a1266af48543ccd9024f4cd89fJohn Du delay); 24845a0cf7a27f3953a1266af48543ccd9024f4cd89fJohn Du } 2485b1fbaaccb656ef09a8770c28df15e3e91a452e64Eric Laurent } 24866bc7f2cd30b6bd90806942b0722e22daa2108493Eric Laurent } 24876bc7f2cd30b6bd90806942b0722e22daa2108493Eric Laurent break; 24886bc7f2cd30b6bd90806942b0722e22daa2108493Eric Laurent 24890a40ec2192e4836b2fcb6ba51a7688aa6bd4ee98Mike Lockwood case BluetoothProfile.A2DP_SINK: 24900a40ec2192e4836b2fcb6ba51a7688aa6bd4ee98Mike Lockwood deviceList = proxy.getConnectedDevices(); 24910a40ec2192e4836b2fcb6ba51a7688aa6bd4ee98Mike Lockwood if (deviceList.size() > 0) { 24920a40ec2192e4836b2fcb6ba51a7688aa6bd4ee98Mike Lockwood btDevice = deviceList.get(0); 24930a40ec2192e4836b2fcb6ba51a7688aa6bd4ee98Mike Lockwood synchronized (mConnectedDevices) { 24940a40ec2192e4836b2fcb6ba51a7688aa6bd4ee98Mike Lockwood int state = proxy.getConnectionState(btDevice); 24950a40ec2192e4836b2fcb6ba51a7688aa6bd4ee98Mike Lockwood queueMsgUnderWakeLock(mAudioHandler, 24960a40ec2192e4836b2fcb6ba51a7688aa6bd4ee98Mike Lockwood MSG_SET_A2DP_SRC_CONNECTION_STATE, 24970a40ec2192e4836b2fcb6ba51a7688aa6bd4ee98Mike Lockwood state, 24980a40ec2192e4836b2fcb6ba51a7688aa6bd4ee98Mike Lockwood 0, 24990a40ec2192e4836b2fcb6ba51a7688aa6bd4ee98Mike Lockwood btDevice, 25000a40ec2192e4836b2fcb6ba51a7688aa6bd4ee98Mike Lockwood 0 /* delay */); 25010a40ec2192e4836b2fcb6ba51a7688aa6bd4ee98Mike Lockwood } 25020a40ec2192e4836b2fcb6ba51a7688aa6bd4ee98Mike Lockwood } 25030a40ec2192e4836b2fcb6ba51a7688aa6bd4ee98Mike Lockwood break; 25040a40ec2192e4836b2fcb6ba51a7688aa6bd4ee98Mike Lockwood 25056bc7f2cd30b6bd90806942b0722e22daa2108493Eric Laurent case BluetoothProfile.HEADSET: 25066bc7f2cd30b6bd90806942b0722e22daa2108493Eric Laurent synchronized (mScoClients) { 25076bc7f2cd30b6bd90806942b0722e22daa2108493Eric Laurent // Discard timeout message 25086bc7f2cd30b6bd90806942b0722e22daa2108493Eric Laurent mAudioHandler.removeMessages(MSG_BT_HEADSET_CNCT_FAILED); 25096bc7f2cd30b6bd90806942b0722e22daa2108493Eric Laurent mBluetoothHeadset = (BluetoothHeadset) proxy; 25106bc7f2cd30b6bd90806942b0722e22daa2108493Eric Laurent deviceList = mBluetoothHeadset.getConnectedDevices(); 25116bc7f2cd30b6bd90806942b0722e22daa2108493Eric Laurent if (deviceList.size() > 0) { 25126bc7f2cd30b6bd90806942b0722e22daa2108493Eric Laurent mBluetoothHeadsetDevice = deviceList.get(0); 25136bc7f2cd30b6bd90806942b0722e22daa2108493Eric Laurent } else { 25146bc7f2cd30b6bd90806942b0722e22daa2108493Eric Laurent mBluetoothHeadsetDevice = null; 2515dc03c61fe3cd8d0805480e48a974986439977a60Eric Laurent } 25166bc7f2cd30b6bd90806942b0722e22daa2108493Eric Laurent // Refresh SCO audio state 25176bc7f2cd30b6bd90806942b0722e22daa2108493Eric Laurent checkScoAudioState(); 25186bc7f2cd30b6bd90806942b0722e22daa2108493Eric Laurent // Continue pending action if any 25196bc7f2cd30b6bd90806942b0722e22daa2108493Eric Laurent if (mScoAudioState == SCO_STATE_ACTIVATE_REQ || 25206bc7f2cd30b6bd90806942b0722e22daa2108493Eric Laurent mScoAudioState == SCO_STATE_DEACTIVATE_REQ || 25216bc7f2cd30b6bd90806942b0722e22daa2108493Eric Laurent mScoAudioState == SCO_STATE_DEACTIVATE_EXT_REQ) { 25226bc7f2cd30b6bd90806942b0722e22daa2108493Eric Laurent boolean status = false; 25236bc7f2cd30b6bd90806942b0722e22daa2108493Eric Laurent if (mBluetoothHeadsetDevice != null) { 25246bc7f2cd30b6bd90806942b0722e22daa2108493Eric Laurent switch (mScoAudioState) { 25256bc7f2cd30b6bd90806942b0722e22daa2108493Eric Laurent case SCO_STATE_ACTIVATE_REQ: 25266bc7f2cd30b6bd90806942b0722e22daa2108493Eric Laurent mScoAudioState = SCO_STATE_ACTIVE_INTERNAL; 2527c18c9138cee0f0859bcab636a004ce92ca4a9ab5Eric Laurent if (mScoAudioMode == SCO_MODE_RAW) { 2528c18c9138cee0f0859bcab636a004ce92ca4a9ab5Eric Laurent status = mBluetoothHeadset.connectAudio(); 2529f4e51d82d2e34e6832903f01eaecc15ded6c3241Liejun Tao } else if (mScoAudioMode == SCO_MODE_VIRTUAL_CALL) { 2530c18c9138cee0f0859bcab636a004ce92ca4a9ab5Eric Laurent status = mBluetoothHeadset.startScoUsingVirtualVoiceCall( 2531c18c9138cee0f0859bcab636a004ce92ca4a9ab5Eric Laurent mBluetoothHeadsetDevice); 2532f4e51d82d2e34e6832903f01eaecc15ded6c3241Liejun Tao } else if (mScoAudioMode == SCO_MODE_VR) { 2533f4e51d82d2e34e6832903f01eaecc15ded6c3241Liejun Tao status = mBluetoothHeadset.startVoiceRecognition( 2534f4e51d82d2e34e6832903f01eaecc15ded6c3241Liejun Tao mBluetoothHeadsetDevice); 2535c18c9138cee0f0859bcab636a004ce92ca4a9ab5Eric Laurent } 25366bc7f2cd30b6bd90806942b0722e22daa2108493Eric Laurent break; 25376bc7f2cd30b6bd90806942b0722e22daa2108493Eric Laurent case SCO_STATE_DEACTIVATE_REQ: 2538c18c9138cee0f0859bcab636a004ce92ca4a9ab5Eric Laurent if (mScoAudioMode == SCO_MODE_RAW) { 2539c18c9138cee0f0859bcab636a004ce92ca4a9ab5Eric Laurent status = mBluetoothHeadset.disconnectAudio(); 2540f4e51d82d2e34e6832903f01eaecc15ded6c3241Liejun Tao } else if (mScoAudioMode == SCO_MODE_VIRTUAL_CALL) { 2541c18c9138cee0f0859bcab636a004ce92ca4a9ab5Eric Laurent status = mBluetoothHeadset.stopScoUsingVirtualVoiceCall( 2542c18c9138cee0f0859bcab636a004ce92ca4a9ab5Eric Laurent mBluetoothHeadsetDevice); 2543f4e51d82d2e34e6832903f01eaecc15ded6c3241Liejun Tao } else if (mScoAudioMode == SCO_MODE_VR) { 2544f4e51d82d2e34e6832903f01eaecc15ded6c3241Liejun Tao status = mBluetoothHeadset.stopVoiceRecognition( 2545f4e51d82d2e34e6832903f01eaecc15ded6c3241Liejun Tao mBluetoothHeadsetDevice); 2546c18c9138cee0f0859bcab636a004ce92ca4a9ab5Eric Laurent } 25476bc7f2cd30b6bd90806942b0722e22daa2108493Eric Laurent break; 25486bc7f2cd30b6bd90806942b0722e22daa2108493Eric Laurent case SCO_STATE_DEACTIVATE_EXT_REQ: 25496bc7f2cd30b6bd90806942b0722e22daa2108493Eric Laurent status = mBluetoothHeadset.stopVoiceRecognition( 25506bc7f2cd30b6bd90806942b0722e22daa2108493Eric Laurent mBluetoothHeadsetDevice); 25516bc7f2cd30b6bd90806942b0722e22daa2108493Eric Laurent } 25526bc7f2cd30b6bd90806942b0722e22daa2108493Eric Laurent } 25536bc7f2cd30b6bd90806942b0722e22daa2108493Eric Laurent if (!status) { 2554afbb047c3945e9c2b7e9bc6b25098d5fb80bba4eEric Laurent sendMsg(mAudioHandler, MSG_BT_HEADSET_CNCT_FAILED, 25556bc7f2cd30b6bd90806942b0722e22daa2108493Eric Laurent SENDMSG_REPLACE, 0, 0, null, 0); 25566bc7f2cd30b6bd90806942b0722e22daa2108493Eric Laurent } 2557dc03c61fe3cd8d0805480e48a974986439977a60Eric Laurent } 2558dc03c61fe3cd8d0805480e48a974986439977a60Eric Laurent } 25596bc7f2cd30b6bd90806942b0722e22daa2108493Eric Laurent break; 25606bc7f2cd30b6bd90806942b0722e22daa2108493Eric Laurent 25616bc7f2cd30b6bd90806942b0722e22daa2108493Eric Laurent default: 25626bc7f2cd30b6bd90806942b0722e22daa2108493Eric Laurent break; 25633def1eec2baed0b8845ec32c871e249dc533a9d9Eric Laurent } 25643def1eec2baed0b8845ec32c871e249dc533a9d9Eric Laurent } 256582aa7f017daaaeb96c13e6e3491d5037ab471085Jaikumar Ganesh public void onServiceDisconnected(int profile) { 25666bc7f2cd30b6bd90806942b0722e22daa2108493Eric Laurent switch(profile) { 25676bc7f2cd30b6bd90806942b0722e22daa2108493Eric Laurent case BluetoothProfile.A2DP: 25685a0cf7a27f3953a1266af48543ccd9024f4cd89fJohn Du synchronized (mA2dpAvrcpLock) { 25695a0cf7a27f3953a1266af48543ccd9024f4cd89fJohn Du mA2dp = null; 25705a0cf7a27f3953a1266af48543ccd9024f4cd89fJohn Du synchronized (mConnectedDevices) { 25715a0cf7a27f3953a1266af48543ccd9024f4cd89fJohn Du if (mConnectedDevices.containsKey(AudioSystem.DEVICE_OUT_BLUETOOTH_A2DP)) { 25725a0cf7a27f3953a1266af48543ccd9024f4cd89fJohn Du makeA2dpDeviceUnavailableNow( 25735a0cf7a27f3953a1266af48543ccd9024f4cd89fJohn Du mConnectedDevices.get(AudioSystem.DEVICE_OUT_BLUETOOTH_A2DP)); 25745a0cf7a27f3953a1266af48543ccd9024f4cd89fJohn Du } 25756bc7f2cd30b6bd90806942b0722e22daa2108493Eric Laurent } 25766bc7f2cd30b6bd90806942b0722e22daa2108493Eric Laurent } 25776bc7f2cd30b6bd90806942b0722e22daa2108493Eric Laurent break; 25786bc7f2cd30b6bd90806942b0722e22daa2108493Eric Laurent 25790a40ec2192e4836b2fcb6ba51a7688aa6bd4ee98Mike Lockwood case BluetoothProfile.A2DP_SINK: 25800a40ec2192e4836b2fcb6ba51a7688aa6bd4ee98Mike Lockwood synchronized (mConnectedDevices) { 25810a40ec2192e4836b2fcb6ba51a7688aa6bd4ee98Mike Lockwood if (mConnectedDevices.containsKey(AudioSystem.DEVICE_IN_BLUETOOTH_A2DP)) { 25820a40ec2192e4836b2fcb6ba51a7688aa6bd4ee98Mike Lockwood makeA2dpSrcUnavailable( 25830a40ec2192e4836b2fcb6ba51a7688aa6bd4ee98Mike Lockwood mConnectedDevices.get(AudioSystem.DEVICE_IN_BLUETOOTH_A2DP)); 25840a40ec2192e4836b2fcb6ba51a7688aa6bd4ee98Mike Lockwood } 25850a40ec2192e4836b2fcb6ba51a7688aa6bd4ee98Mike Lockwood } 25860a40ec2192e4836b2fcb6ba51a7688aa6bd4ee98Mike Lockwood break; 25870a40ec2192e4836b2fcb6ba51a7688aa6bd4ee98Mike Lockwood 25886bc7f2cd30b6bd90806942b0722e22daa2108493Eric Laurent case BluetoothProfile.HEADSET: 25896bc7f2cd30b6bd90806942b0722e22daa2108493Eric Laurent synchronized (mScoClients) { 25906bc7f2cd30b6bd90806942b0722e22daa2108493Eric Laurent mBluetoothHeadset = null; 25916bc7f2cd30b6bd90806942b0722e22daa2108493Eric Laurent } 25926bc7f2cd30b6bd90806942b0722e22daa2108493Eric Laurent break; 25936bc7f2cd30b6bd90806942b0722e22daa2108493Eric Laurent 25946bc7f2cd30b6bd90806942b0722e22daa2108493Eric Laurent default: 25956bc7f2cd30b6bd90806942b0722e22daa2108493Eric Laurent break; 25963def1eec2baed0b8845ec32c871e249dc533a9d9Eric Laurent } 25973def1eec2baed0b8845ec32c871e249dc533a9d9Eric Laurent } 25983def1eec2baed0b8845ec32c871e249dc533a9d9Eric Laurent }; 2599d5176cfe6eae954e9cef1e2ec17859a5089e1330Jean-Michel Trivi 2600c34dcc1e1ebf152bb400abbb8bc25f7dc0c3ba97Eric Laurent private void onCheckMusicActive() { 2601d640bd325c3be9a350058c835b880a7e0b40dc60Eric Laurent synchronized (mSafeMediaVolumeState) { 2602d640bd325c3be9a350058c835b880a7e0b40dc60Eric Laurent if (mSafeMediaVolumeState == SAFE_MEDIA_VOLUME_INACTIVE) { 2603c34dcc1e1ebf152bb400abbb8bc25f7dc0c3ba97Eric Laurent int device = getDeviceForStream(AudioSystem.STREAM_MUSIC); 2604c34dcc1e1ebf152bb400abbb8bc25f7dc0c3ba97Eric Laurent 2605c34dcc1e1ebf152bb400abbb8bc25f7dc0c3ba97Eric Laurent if ((device & mSafeMediaVolumeDevices) != 0) { 2606c34dcc1e1ebf152bb400abbb8bc25f7dc0c3ba97Eric Laurent sendMsg(mAudioHandler, 2607c34dcc1e1ebf152bb400abbb8bc25f7dc0c3ba97Eric Laurent MSG_CHECK_MUSIC_ACTIVE, 2608c34dcc1e1ebf152bb400abbb8bc25f7dc0c3ba97Eric Laurent SENDMSG_REPLACE, 2609f1a457d06c53a901ea08d2d3fb6e766bc06c4d4fEric Laurent 0, 2610c34dcc1e1ebf152bb400abbb8bc25f7dc0c3ba97Eric Laurent 0, 2611c34dcc1e1ebf152bb400abbb8bc25f7dc0c3ba97Eric Laurent null, 2612c34dcc1e1ebf152bb400abbb8bc25f7dc0c3ba97Eric Laurent MUSIC_ACTIVE_POLL_PERIOD_MS); 261342b041ed4f184e3af7f788eb07307f556a2a6616Eric Laurent int index = mStreamStates[AudioSystem.STREAM_MUSIC].getIndex(device); 2614f1a457d06c53a901ea08d2d3fb6e766bc06c4d4fEric Laurent if (AudioSystem.isStreamActive(AudioSystem.STREAM_MUSIC, 0) && 2615f1a457d06c53a901ea08d2d3fb6e766bc06c4d4fEric Laurent (index > mSafeMediaVolumeIndex)) { 2616c34dcc1e1ebf152bb400abbb8bc25f7dc0c3ba97Eric Laurent // Approximate cumulative active music time 2617c34dcc1e1ebf152bb400abbb8bc25f7dc0c3ba97Eric Laurent mMusicActiveMs += MUSIC_ACTIVE_POLL_PERIOD_MS; 2618c34dcc1e1ebf152bb400abbb8bc25f7dc0c3ba97Eric Laurent if (mMusicActiveMs > UNSAFE_VOLUME_MUSIC_ACTIVE_MS_MAX) { 2619c34dcc1e1ebf152bb400abbb8bc25f7dc0c3ba97Eric Laurent setSafeMediaVolumeEnabled(true); 2620c34dcc1e1ebf152bb400abbb8bc25f7dc0c3ba97Eric Laurent mMusicActiveMs = 0; 2621c34dcc1e1ebf152bb400abbb8bc25f7dc0c3ba97Eric Laurent } 2622c34dcc1e1ebf152bb400abbb8bc25f7dc0c3ba97Eric Laurent } 2623c34dcc1e1ebf152bb400abbb8bc25f7dc0c3ba97Eric Laurent } 2624c34dcc1e1ebf152bb400abbb8bc25f7dc0c3ba97Eric Laurent } 2625c34dcc1e1ebf152bb400abbb8bc25f7dc0c3ba97Eric Laurent } 2626c34dcc1e1ebf152bb400abbb8bc25f7dc0c3ba97Eric Laurent } 2627c34dcc1e1ebf152bb400abbb8bc25f7dc0c3ba97Eric Laurent 2628d640bd325c3be9a350058c835b880a7e0b40dc60Eric Laurent private void onConfigureSafeVolume(boolean force) { 2629d640bd325c3be9a350058c835b880a7e0b40dc60Eric Laurent synchronized (mSafeMediaVolumeState) { 2630d640bd325c3be9a350058c835b880a7e0b40dc60Eric Laurent int mcc = mContext.getResources().getConfiguration().mcc; 2631d640bd325c3be9a350058c835b880a7e0b40dc60Eric Laurent if ((mMcc != mcc) || ((mMcc == 0) && force)) { 2632d640bd325c3be9a350058c835b880a7e0b40dc60Eric Laurent mSafeMediaVolumeIndex = mContext.getResources().getInteger( 2633d640bd325c3be9a350058c835b880a7e0b40dc60Eric Laurent com.android.internal.R.integer.config_safe_media_volume_index) * 10; 2634d640bd325c3be9a350058c835b880a7e0b40dc60Eric Laurent boolean safeMediaVolumeEnabled = mContext.getResources().getBoolean( 2635d640bd325c3be9a350058c835b880a7e0b40dc60Eric Laurent com.android.internal.R.bool.config_safe_media_volume_enabled); 263605274f348e12983eb8613cc6eb9ae561e8197e28Eric Laurent 263705274f348e12983eb8613cc6eb9ae561e8197e28Eric Laurent // The persisted state is either "disabled" or "active": this is the state applied 263805274f348e12983eb8613cc6eb9ae561e8197e28Eric Laurent // next time we boot and cannot be "inactive" 263905274f348e12983eb8613cc6eb9ae561e8197e28Eric Laurent int persistedState; 2640d640bd325c3be9a350058c835b880a7e0b40dc60Eric Laurent if (safeMediaVolumeEnabled) { 264105274f348e12983eb8613cc6eb9ae561e8197e28Eric Laurent persistedState = SAFE_MEDIA_VOLUME_ACTIVE; 264205274f348e12983eb8613cc6eb9ae561e8197e28Eric Laurent // The state can already be "inactive" here if the user has forced it before 264305274f348e12983eb8613cc6eb9ae561e8197e28Eric Laurent // the 30 seconds timeout for forced configuration. In this case we don't reset 264405274f348e12983eb8613cc6eb9ae561e8197e28Eric Laurent // it to "active". 264505274f348e12983eb8613cc6eb9ae561e8197e28Eric Laurent if (mSafeMediaVolumeState != SAFE_MEDIA_VOLUME_INACTIVE) { 264605274f348e12983eb8613cc6eb9ae561e8197e28Eric Laurent mSafeMediaVolumeState = SAFE_MEDIA_VOLUME_ACTIVE; 264705274f348e12983eb8613cc6eb9ae561e8197e28Eric Laurent enforceSafeMediaVolume(); 264805274f348e12983eb8613cc6eb9ae561e8197e28Eric Laurent } 2649d640bd325c3be9a350058c835b880a7e0b40dc60Eric Laurent } else { 265005274f348e12983eb8613cc6eb9ae561e8197e28Eric Laurent persistedState = SAFE_MEDIA_VOLUME_DISABLED; 2651d640bd325c3be9a350058c835b880a7e0b40dc60Eric Laurent mSafeMediaVolumeState = SAFE_MEDIA_VOLUME_DISABLED; 2652d640bd325c3be9a350058c835b880a7e0b40dc60Eric Laurent } 2653d640bd325c3be9a350058c835b880a7e0b40dc60Eric Laurent mMcc = mcc; 265405274f348e12983eb8613cc6eb9ae561e8197e28Eric Laurent sendMsg(mAudioHandler, 265505274f348e12983eb8613cc6eb9ae561e8197e28Eric Laurent MSG_PERSIST_SAFE_VOLUME_STATE, 265605274f348e12983eb8613cc6eb9ae561e8197e28Eric Laurent SENDMSG_QUEUE, 265705274f348e12983eb8613cc6eb9ae561e8197e28Eric Laurent persistedState, 265805274f348e12983eb8613cc6eb9ae561e8197e28Eric Laurent 0, 265905274f348e12983eb8613cc6eb9ae561e8197e28Eric Laurent null, 266005274f348e12983eb8613cc6eb9ae561e8197e28Eric Laurent 0); 2661d640bd325c3be9a350058c835b880a7e0b40dc60Eric Laurent } 2662d640bd325c3be9a350058c835b880a7e0b40dc60Eric Laurent } 2663d640bd325c3be9a350058c835b880a7e0b40dc60Eric Laurent } 2664d640bd325c3be9a350058c835b880a7e0b40dc60Eric Laurent 26659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /////////////////////////////////////////////////////////////////////////// 26669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Internal methods 26679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /////////////////////////////////////////////////////////////////////////// 26689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 26699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 26709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Checks if the adjustment should change ringer mode instead of just 26719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * adjusting volume. If so, this will set the proper ringer mode and volume 26729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * indices on the stream states. 26739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 2674a11b4affcad3d255aa723a89b768ea222506f2e8John Spurlock private int checkForRingerModeChange(int oldIndex, int direction, int step) { 2675a11b4affcad3d255aa723a89b768ea222506f2e8John Spurlock int result = FLAG_ADJUST_VOLUME; 2676ba195ebc76f23b6679443724ab58c9dc9f2df884Glenn Kasten int ringerMode = getRingerMode(); 2677bffc3d1bd33eb2d8e00a9f8b6261d815db503311Eric Laurent 2678bffc3d1bd33eb2d8e00a9f8b6261d815db503311Eric Laurent switch (ringerMode) { 2679bffc3d1bd33eb2d8e00a9f8b6261d815db503311Eric Laurent case RINGER_MODE_NORMAL: 2680bffc3d1bd33eb2d8e00a9f8b6261d815db503311Eric Laurent if (direction == AudioManager.ADJUST_LOWER) { 2681bffc3d1bd33eb2d8e00a9f8b6261d815db503311Eric Laurent if (mHasVibrator) { 2682244820185269991186d07068b92985624cede4a5Eric Laurent // "step" is the delta in internal index units corresponding to a 2683244820185269991186d07068b92985624cede4a5Eric Laurent // change of 1 in UI index units. 2684244820185269991186d07068b92985624cede4a5Eric Laurent // Because of rounding when rescaling from one stream index range to its alias 2685244820185269991186d07068b92985624cede4a5Eric Laurent // index range, we cannot simply test oldIndex == step: 2686244820185269991186d07068b92985624cede4a5Eric Laurent // (step <= oldIndex < 2 * step) is equivalent to: (old UI index == 1) 2687244820185269991186d07068b92985624cede4a5Eric Laurent if (step <= oldIndex && oldIndex < 2 * step) { 2688bffc3d1bd33eb2d8e00a9f8b6261d815db503311Eric Laurent ringerMode = RINGER_MODE_VIBRATE; 2689bffc3d1bd33eb2d8e00a9f8b6261d815db503311Eric Laurent } 2690bffc3d1bd33eb2d8e00a9f8b6261d815db503311Eric Laurent } else { 2691244820185269991186d07068b92985624cede4a5Eric Laurent // (oldIndex < step) is equivalent to (old UI index == 0) 26928600534df66c2ff5846ed230b50c56229322d48aJohn Spurlock if ((oldIndex < step) 26938600534df66c2ff5846ed230b50c56229322d48aJohn Spurlock && VOLUME_SETS_RINGER_MODE_SILENT 26948600534df66c2ff5846ed230b50c56229322d48aJohn Spurlock && mPrevVolDirection != AudioManager.ADJUST_LOWER) { 2695bffc3d1bd33eb2d8e00a9f8b6261d815db503311Eric Laurent ringerMode = RINGER_MODE_SILENT; 2696bffc3d1bd33eb2d8e00a9f8b6261d815db503311Eric Laurent } 26973d4c06f90726a85e89dab13c41ddc15b9c912a3fEric Laurent } 26986329bf7b1e2217c6c9477bd57349a1edade18417Daniel Sandler } 2699bffc3d1bd33eb2d8e00a9f8b6261d815db503311Eric Laurent break; 2700bffc3d1bd33eb2d8e00a9f8b6261d815db503311Eric Laurent case RINGER_MODE_VIBRATE: 2701bffc3d1bd33eb2d8e00a9f8b6261d815db503311Eric Laurent if (!mHasVibrator) { 2702bffc3d1bd33eb2d8e00a9f8b6261d815db503311Eric Laurent Log.e(TAG, "checkForRingerModeChange() current ringer mode is vibrate" + 2703bffc3d1bd33eb2d8e00a9f8b6261d815db503311Eric Laurent "but no vibrator is present"); 2704bffc3d1bd33eb2d8e00a9f8b6261d815db503311Eric Laurent break; 2705bffc3d1bd33eb2d8e00a9f8b6261d815db503311Eric Laurent } 2706c696a53d1fe4d61373c5dc64dd057d322da90c8fAmith Yamasani if ((direction == AudioManager.ADJUST_LOWER)) { 27078600534df66c2ff5846ed230b50c56229322d48aJohn Spurlock if (VOLUME_SETS_RINGER_MODE_SILENT 27088600534df66c2ff5846ed230b50c56229322d48aJohn Spurlock && mPrevVolDirection != AudioManager.ADJUST_LOWER) { 2709bffc3d1bd33eb2d8e00a9f8b6261d815db503311Eric Laurent ringerMode = RINGER_MODE_SILENT; 2710c696a53d1fe4d61373c5dc64dd057d322da90c8fAmith Yamasani } 2711c696a53d1fe4d61373c5dc64dd057d322da90c8fAmith Yamasani } else if (direction == AudioManager.ADJUST_RAISE) { 2712bffc3d1bd33eb2d8e00a9f8b6261d815db503311Eric Laurent ringerMode = RINGER_MODE_NORMAL; 2713c696a53d1fe4d61373c5dc64dd057d322da90c8fAmith Yamasani } 2714a11b4affcad3d255aa723a89b768ea222506f2e8John Spurlock result &= ~FLAG_ADJUST_VOLUME; 2715bffc3d1bd33eb2d8e00a9f8b6261d815db503311Eric Laurent break; 2716bffc3d1bd33eb2d8e00a9f8b6261d815db503311Eric Laurent case RINGER_MODE_SILENT: 27179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (direction == AudioManager.ADJUST_RAISE) { 2718a11b4affcad3d255aa723a89b768ea222506f2e8John Spurlock if (PREVENT_VOLUME_ADJUSTMENT_IF_SILENT) { 2719a11b4affcad3d255aa723a89b768ea222506f2e8John Spurlock result |= AudioManager.FLAG_SHOW_SILENT_HINT; 2720bffc3d1bd33eb2d8e00a9f8b6261d815db503311Eric Laurent } else { 2721a11b4affcad3d255aa723a89b768ea222506f2e8John Spurlock if (mHasVibrator) { 2722a11b4affcad3d255aa723a89b768ea222506f2e8John Spurlock ringerMode = RINGER_MODE_VIBRATE; 2723a11b4affcad3d255aa723a89b768ea222506f2e8John Spurlock } else { 2724a11b4affcad3d255aa723a89b768ea222506f2e8John Spurlock ringerMode = RINGER_MODE_NORMAL; 2725a11b4affcad3d255aa723a89b768ea222506f2e8John Spurlock } 2726bffc3d1bd33eb2d8e00a9f8b6261d815db503311Eric Laurent } 27279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2728a11b4affcad3d255aa723a89b768ea222506f2e8John Spurlock result &= ~FLAG_ADJUST_VOLUME; 2729bffc3d1bd33eb2d8e00a9f8b6261d815db503311Eric Laurent break; 2730bffc3d1bd33eb2d8e00a9f8b6261d815db503311Eric Laurent default: 2731bffc3d1bd33eb2d8e00a9f8b6261d815db503311Eric Laurent Log.e(TAG, "checkForRingerModeChange() wrong ringer mode: "+ringerMode); 2732bffc3d1bd33eb2d8e00a9f8b6261d815db503311Eric Laurent break; 27339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 27349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2735bffc3d1bd33eb2d8e00a9f8b6261d815db503311Eric Laurent setRingerMode(ringerMode); 27369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 273725101b0b9a84571ead15b26e9f4cd9c4298d7823Eric Laurent mPrevVolDirection = direction; 273825101b0b9a84571ead15b26e9f4cd9c4298d7823Eric Laurent 2739a11b4affcad3d255aa723a89b768ea222506f2e8John Spurlock return result; 27409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 27419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 27423346a802087f621c6441bc512dfcc17b07143fc6John Spurlock @Override 27439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public boolean isStreamAffectedByRingerMode(int streamType) { 27449bcf401d13d47416043a704430388abd59aef7cdEric Laurent return (mRingerModeAffectedStreams & (1 << streamType)) != 0; 27459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 27469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 27475b4e654d0c7de8e4d58d73e73b0d5220f19b68f7Eric Laurent private boolean isStreamMutedByRingerMode(int streamType) { 27485b4e654d0c7de8e4d58d73e73b0d5220f19b68f7Eric Laurent return (mRingerModeMutedStreams & (1 << streamType)) != 0; 27495b4e654d0c7de8e4d58d73e73b0d5220f19b68f7Eric Laurent } 27505b4e654d0c7de8e4d58d73e73b0d5220f19b68f7Eric Laurent 275124e0d9b6c40712a297e4c287435a3b0fdd30e9daEric Laurent boolean updateRingerModeAffectedStreams() { 275224e0d9b6c40712a297e4c287435a3b0fdd30e9daEric Laurent int ringerModeAffectedStreams; 275324e0d9b6c40712a297e4c287435a3b0fdd30e9daEric Laurent // make sure settings for ringer mode are consistent with device type: non voice capable 275424e0d9b6c40712a297e4c287435a3b0fdd30e9daEric Laurent // devices (tablets) include media stream in silent mode whereas phones don't. 275524e0d9b6c40712a297e4c287435a3b0fdd30e9daEric Laurent ringerModeAffectedStreams = Settings.System.getIntForUser(mContentResolver, 275624e0d9b6c40712a297e4c287435a3b0fdd30e9daEric Laurent Settings.System.MODE_RINGER_STREAMS_AFFECTED, 275724e0d9b6c40712a297e4c287435a3b0fdd30e9daEric Laurent ((1 << AudioSystem.STREAM_RING)|(1 << AudioSystem.STREAM_NOTIFICATION)| 275824e0d9b6c40712a297e4c287435a3b0fdd30e9daEric Laurent (1 << AudioSystem.STREAM_SYSTEM)|(1 << AudioSystem.STREAM_SYSTEM_ENFORCED)), 275924e0d9b6c40712a297e4c287435a3b0fdd30e9daEric Laurent UserHandle.USER_CURRENT); 276024e0d9b6c40712a297e4c287435a3b0fdd30e9daEric Laurent 276124e0d9b6c40712a297e4c287435a3b0fdd30e9daEric Laurent // ringtone, notification and system streams are always affected by ringer mode 276224e0d9b6c40712a297e4c287435a3b0fdd30e9daEric Laurent ringerModeAffectedStreams |= (1 << AudioSystem.STREAM_RING)| 276324e0d9b6c40712a297e4c287435a3b0fdd30e9daEric Laurent (1 << AudioSystem.STREAM_NOTIFICATION)| 276424e0d9b6c40712a297e4c287435a3b0fdd30e9daEric Laurent (1 << AudioSystem.STREAM_SYSTEM); 276524e0d9b6c40712a297e4c287435a3b0fdd30e9daEric Laurent 276624e0d9b6c40712a297e4c287435a3b0fdd30e9daEric Laurent if (mVoiceCapable) { 276724e0d9b6c40712a297e4c287435a3b0fdd30e9daEric Laurent ringerModeAffectedStreams &= ~(1 << AudioSystem.STREAM_MUSIC); 276824e0d9b6c40712a297e4c287435a3b0fdd30e9daEric Laurent } else { 276924e0d9b6c40712a297e4c287435a3b0fdd30e9daEric Laurent ringerModeAffectedStreams |= (1 << AudioSystem.STREAM_MUSIC); 277024e0d9b6c40712a297e4c287435a3b0fdd30e9daEric Laurent } 277124e0d9b6c40712a297e4c287435a3b0fdd30e9daEric Laurent synchronized (mCameraSoundForced) { 277224e0d9b6c40712a297e4c287435a3b0fdd30e9daEric Laurent if (mCameraSoundForced) { 277324e0d9b6c40712a297e4c287435a3b0fdd30e9daEric Laurent ringerModeAffectedStreams &= ~(1 << AudioSystem.STREAM_SYSTEM_ENFORCED); 277424e0d9b6c40712a297e4c287435a3b0fdd30e9daEric Laurent } else { 277524e0d9b6c40712a297e4c287435a3b0fdd30e9daEric Laurent ringerModeAffectedStreams |= (1 << AudioSystem.STREAM_SYSTEM_ENFORCED); 277624e0d9b6c40712a297e4c287435a3b0fdd30e9daEric Laurent } 277724e0d9b6c40712a297e4c287435a3b0fdd30e9daEric Laurent } 277824e0d9b6c40712a297e4c287435a3b0fdd30e9daEric Laurent if (mStreamVolumeAlias[AudioSystem.STREAM_DTMF] == AudioSystem.STREAM_RING) { 277924e0d9b6c40712a297e4c287435a3b0fdd30e9daEric Laurent ringerModeAffectedStreams |= (1 << AudioSystem.STREAM_DTMF); 278024e0d9b6c40712a297e4c287435a3b0fdd30e9daEric Laurent } else { 278124e0d9b6c40712a297e4c287435a3b0fdd30e9daEric Laurent ringerModeAffectedStreams &= ~(1 << AudioSystem.STREAM_DTMF); 278224e0d9b6c40712a297e4c287435a3b0fdd30e9daEric Laurent } 278324e0d9b6c40712a297e4c287435a3b0fdd30e9daEric Laurent 278424e0d9b6c40712a297e4c287435a3b0fdd30e9daEric Laurent if (ringerModeAffectedStreams != mRingerModeAffectedStreams) { 278524e0d9b6c40712a297e4c287435a3b0fdd30e9daEric Laurent Settings.System.putIntForUser(mContentResolver, 278624e0d9b6c40712a297e4c287435a3b0fdd30e9daEric Laurent Settings.System.MODE_RINGER_STREAMS_AFFECTED, 278724e0d9b6c40712a297e4c287435a3b0fdd30e9daEric Laurent ringerModeAffectedStreams, 278824e0d9b6c40712a297e4c287435a3b0fdd30e9daEric Laurent UserHandle.USER_CURRENT); 278924e0d9b6c40712a297e4c287435a3b0fdd30e9daEric Laurent mRingerModeAffectedStreams = ringerModeAffectedStreams; 279024e0d9b6c40712a297e4c287435a3b0fdd30e9daEric Laurent return true; 279124e0d9b6c40712a297e4c287435a3b0fdd30e9daEric Laurent } 279224e0d9b6c40712a297e4c287435a3b0fdd30e9daEric Laurent return false; 279324e0d9b6c40712a297e4c287435a3b0fdd30e9daEric Laurent } 279424e0d9b6c40712a297e4c287435a3b0fdd30e9daEric Laurent 27959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public boolean isStreamAffectedByMute(int streamType) { 27969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return (mMuteAffectedStreams & (1 << streamType)) != 0; 27979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 27989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 27999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private void ensureValidDirection(int direction) { 28009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (direction < AudioManager.ADJUST_LOWER || direction > AudioManager.ADJUST_RAISE) { 28019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project throw new IllegalArgumentException("Bad direction " + direction); 28029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 28039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 28049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 28056c798970ccb8759d1e613b57111daa8da0ab44c7Lei Zhang private void ensureValidSteps(int steps) { 28066c798970ccb8759d1e613b57111daa8da0ab44c7Lei Zhang if (Math.abs(steps) > MAX_BATCH_VOLUME_ADJUST_STEPS) { 28076c798970ccb8759d1e613b57111daa8da0ab44c7Lei Zhang throw new IllegalArgumentException("Bad volume adjust steps " + steps); 28086c798970ccb8759d1e613b57111daa8da0ab44c7Lei Zhang } 28096c798970ccb8759d1e613b57111daa8da0ab44c7Lei Zhang } 28106c798970ccb8759d1e613b57111daa8da0ab44c7Lei Zhang 28119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private void ensureValidStreamType(int streamType) { 28129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (streamType < 0 || streamType >= mStreamStates.length) { 28139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project throw new IllegalArgumentException("Bad stream type " + streamType); 28149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 28159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 28169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 28176d5176638c2189595cede38fb92c3e7e8700e221Eric Laurent private boolean isInCommunication() { 28189eb45934c582a0bf5060125690de8bce4f10ca76Santos Cordon boolean isInAPhoneCall = false; 281925101b0b9a84571ead15b26e9f4cd9c4298d7823Eric Laurent 28209eb45934c582a0bf5060125690de8bce4f10ca76Santos Cordon TelecommManager telecommManager = 28219eb45934c582a0bf5060125690de8bce4f10ca76Santos Cordon (TelecommManager) mContext.getSystemService(Context.TELECOMM_SERVICE); 28229eb45934c582a0bf5060125690de8bce4f10ca76Santos Cordon isInAPhoneCall = telecommManager.isInAPhoneCall(); 28239eb45934c582a0bf5060125690de8bce4f10ca76Santos Cordon 28249eb45934c582a0bf5060125690de8bce4f10ca76Santos Cordon return (isInAPhoneCall || getMode() == AudioManager.MODE_IN_COMMUNICATION); 28256d5176638c2189595cede38fb92c3e7e8700e221Eric Laurent } 282625101b0b9a84571ead15b26e9f4cd9c4298d7823Eric Laurent 2827fca1e603236b8d1681f784e77e3719d1d59c1428Jean-Michel Trivi /** 2828fca1e603236b8d1681f784e77e3719d1d59c1428Jean-Michel Trivi * For code clarity for getActiveStreamType(int) 2829fca1e603236b8d1681f784e77e3719d1d59c1428Jean-Michel Trivi * @param delay_ms max time since last STREAM_MUSIC activity to consider 2830fca1e603236b8d1681f784e77e3719d1d59c1428Jean-Michel Trivi * @return true if STREAM_MUSIC is active in streams handled by AudioFlinger now or 2831fca1e603236b8d1681f784e77e3719d1d59c1428Jean-Michel Trivi * in the last "delay_ms" ms. 2832fca1e603236b8d1681f784e77e3719d1d59c1428Jean-Michel Trivi */ 2833fca1e603236b8d1681f784e77e3719d1d59c1428Jean-Michel Trivi private boolean isAfMusicActiveRecently(int delay_ms) { 2834fca1e603236b8d1681f784e77e3719d1d59c1428Jean-Michel Trivi return AudioSystem.isStreamActive(AudioSystem.STREAM_MUSIC, delay_ms) 2835fca1e603236b8d1681f784e77e3719d1d59c1428Jean-Michel Trivi || AudioSystem.isStreamActiveRemotely(AudioSystem.STREAM_MUSIC, delay_ms); 2836fca1e603236b8d1681f784e77e3719d1d59c1428Jean-Michel Trivi } 2837fca1e603236b8d1681f784e77e3719d1d59c1428Jean-Michel Trivi 28386d5176638c2189595cede38fb92c3e7e8700e221Eric Laurent private int getActiveStreamType(int suggestedStreamType) { 28396d5176638c2189595cede38fb92c3e7e8700e221Eric Laurent if (mVoiceCapable) { 28406d5176638c2189595cede38fb92c3e7e8700e221Eric Laurent if (isInCommunication()) { 284125101b0b9a84571ead15b26e9f4cd9c4298d7823Eric Laurent if (AudioSystem.getForceUse(AudioSystem.FOR_COMMUNICATION) 284225101b0b9a84571ead15b26e9f4cd9c4298d7823Eric Laurent == AudioSystem.FORCE_BT_SCO) { 284325101b0b9a84571ead15b26e9f4cd9c4298d7823Eric Laurent // Log.v(TAG, "getActiveStreamType: Forcing STREAM_BLUETOOTH_SCO..."); 284425101b0b9a84571ead15b26e9f4cd9c4298d7823Eric Laurent return AudioSystem.STREAM_BLUETOOTH_SCO; 284525101b0b9a84571ead15b26e9f4cd9c4298d7823Eric Laurent } else { 284625101b0b9a84571ead15b26e9f4cd9c4298d7823Eric Laurent // Log.v(TAG, "getActiveStreamType: Forcing STREAM_VOICE_CALL..."); 284725101b0b9a84571ead15b26e9f4cd9c4298d7823Eric Laurent return AudioSystem.STREAM_VOICE_CALL; 284825101b0b9a84571ead15b26e9f4cd9c4298d7823Eric Laurent } 28493114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi } else if (suggestedStreamType == AudioManager.USE_DEFAULT_STREAM_TYPE) { 2850fca1e603236b8d1681f784e77e3719d1d59c1428Jean-Michel Trivi if (isAfMusicActiveRecently(DEFAULT_STREAM_TYPE_OVERRIDE_DELAY_MS)) { 28513114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi if (DEBUG_VOL) 28523114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi Log.v(TAG, "getActiveStreamType: Forcing STREAM_MUSIC stream active"); 28533114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi return AudioSystem.STREAM_MUSIC; 2854fca1e603236b8d1681f784e77e3719d1d59c1428Jean-Michel Trivi } else 2855fca1e603236b8d1681f784e77e3719d1d59c1428Jean-Michel Trivi if (mMediaFocusControl.checkUpdateRemoteStateIfActive(AudioSystem.STREAM_MUSIC)) 2856fca1e603236b8d1681f784e77e3719d1d59c1428Jean-Michel Trivi { 2857fca1e603236b8d1681f784e77e3719d1d59c1428Jean-Michel Trivi if (DEBUG_VOL) 2858fca1e603236b8d1681f784e77e3719d1d59c1428Jean-Michel Trivi Log.v(TAG, "getActiveStreamType: Forcing STREAM_REMOTE_MUSIC"); 2859fca1e603236b8d1681f784e77e3719d1d59c1428Jean-Michel Trivi return STREAM_REMOTE_MUSIC; 2860fca1e603236b8d1681f784e77e3719d1d59c1428Jean-Michel Trivi } else { 2861fca1e603236b8d1681f784e77e3719d1d59c1428Jean-Michel Trivi if (DEBUG_VOL) 2862fca1e603236b8d1681f784e77e3719d1d59c1428Jean-Michel Trivi Log.v(TAG, "getActiveStreamType: Forcing STREAM_RING b/c default"); 2863fca1e603236b8d1681f784e77e3719d1d59c1428Jean-Michel Trivi return AudioSystem.STREAM_RING; 28643114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi } 2865fca1e603236b8d1681f784e77e3719d1d59c1428Jean-Michel Trivi } else if (isAfMusicActiveRecently(0)) { 28663114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi if (DEBUG_VOL) 28673114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi Log.v(TAG, "getActiveStreamType: Forcing STREAM_MUSIC stream active"); 286825101b0b9a84571ead15b26e9f4cd9c4298d7823Eric Laurent return AudioSystem.STREAM_MUSIC; 2869c7fcba4b7bd3d78e7cfe975a3f8e4dde2f6738b7Joe Onorato } else { 28703114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi if (DEBUG_VOL) Log.v(TAG, "getActiveStreamType: Returning suggested type " 28713114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi + suggestedStreamType); 287225101b0b9a84571ead15b26e9f4cd9c4298d7823Eric Laurent return suggestedStreamType; 287325101b0b9a84571ead15b26e9f4cd9c4298d7823Eric Laurent } 287425101b0b9a84571ead15b26e9f4cd9c4298d7823Eric Laurent } else { 28756d5176638c2189595cede38fb92c3e7e8700e221Eric Laurent if (isInCommunication()) { 287625101b0b9a84571ead15b26e9f4cd9c4298d7823Eric Laurent if (AudioSystem.getForceUse(AudioSystem.FOR_COMMUNICATION) 287725101b0b9a84571ead15b26e9f4cd9c4298d7823Eric Laurent == AudioSystem.FORCE_BT_SCO) { 28783114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi if (DEBUG_VOL) Log.v(TAG, "getActiveStreamType: Forcing STREAM_BLUETOOTH_SCO"); 287925101b0b9a84571ead15b26e9f4cd9c4298d7823Eric Laurent return AudioSystem.STREAM_BLUETOOTH_SCO; 288025101b0b9a84571ead15b26e9f4cd9c4298d7823Eric Laurent } else { 28813114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi if (DEBUG_VOL) Log.v(TAG, "getActiveStreamType: Forcing STREAM_VOICE_CALL"); 288225101b0b9a84571ead15b26e9f4cd9c4298d7823Eric Laurent return AudioSystem.STREAM_VOICE_CALL; 288325101b0b9a84571ead15b26e9f4cd9c4298d7823Eric Laurent } 288425101b0b9a84571ead15b26e9f4cd9c4298d7823Eric Laurent } else if (AudioSystem.isStreamActive(AudioSystem.STREAM_NOTIFICATION, 28859903e2638a6c502d96413680d3ebae4fb77fc412Eric Laurent DEFAULT_STREAM_TYPE_OVERRIDE_DELAY_MS) || 28863114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi AudioSystem.isStreamActive(AudioSystem.STREAM_RING, 28879903e2638a6c502d96413680d3ebae4fb77fc412Eric Laurent DEFAULT_STREAM_TYPE_OVERRIDE_DELAY_MS)) { 28883114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi if (DEBUG_VOL) Log.v(TAG, "getActiveStreamType: Forcing STREAM_NOTIFICATION"); 288925101b0b9a84571ead15b26e9f4cd9c4298d7823Eric Laurent return AudioSystem.STREAM_NOTIFICATION; 28903114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi } else if (suggestedStreamType == AudioManager.USE_DEFAULT_STREAM_TYPE) { 2891fca1e603236b8d1681f784e77e3719d1d59c1428Jean-Michel Trivi if (isAfMusicActiveRecently(DEFAULT_STREAM_TYPE_OVERRIDE_DELAY_MS)) { 2892fca1e603236b8d1681f784e77e3719d1d59c1428Jean-Michel Trivi if (DEBUG_VOL) Log.v(TAG, "getActiveStreamType: forcing STREAM_MUSIC"); 2893fca1e603236b8d1681f784e77e3719d1d59c1428Jean-Michel Trivi return AudioSystem.STREAM_MUSIC; 2894fca1e603236b8d1681f784e77e3719d1d59c1428Jean-Michel Trivi } else 2895fca1e603236b8d1681f784e77e3719d1d59c1428Jean-Michel Trivi if (mMediaFocusControl.checkUpdateRemoteStateIfActive(AudioSystem.STREAM_MUSIC)) 2896fca1e603236b8d1681f784e77e3719d1d59c1428Jean-Michel Trivi { 2897fca1e603236b8d1681f784e77e3719d1d59c1428Jean-Michel Trivi if (DEBUG_VOL) 2898fca1e603236b8d1681f784e77e3719d1d59c1428Jean-Michel Trivi Log.v(TAG, "getActiveStreamType: Forcing STREAM_REMOTE_MUSIC"); 2899fca1e603236b8d1681f784e77e3719d1d59c1428Jean-Michel Trivi return STREAM_REMOTE_MUSIC; 29003114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi } else { 2901eb1d88ddf9a0888455c82b83f19da124e5ca6f16John Spurlock if (DEBUG_VOL) Log.v(TAG, 2902eb1d88ddf9a0888455c82b83f19da124e5ca6f16John Spurlock "getActiveStreamType: using STREAM_NOTIFICATION as default"); 2903eb1d88ddf9a0888455c82b83f19da124e5ca6f16John Spurlock return AudioSystem.STREAM_NOTIFICATION; 29043114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi } 290525101b0b9a84571ead15b26e9f4cd9c4298d7823Eric Laurent } else { 29063114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi if (DEBUG_VOL) Log.v(TAG, "getActiveStreamType: Returning suggested type " 29073114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi + suggestedStreamType); 290825101b0b9a84571ead15b26e9f4cd9c4298d7823Eric Laurent return suggestedStreamType; 2909c7fcba4b7bd3d78e7cfe975a3f8e4dde2f6738b7Joe Onorato } 29109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 29119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 29129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2913ba195ebc76f23b6679443724ab58c9dc9f2df884Glenn Kasten private void broadcastRingerMode(int ringerMode) { 29149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Send sticky broadcast 29151c633fc89bae9bf0af6fe643ac7ad2e744f27bedDianne Hackborn Intent broadcast = new Intent(AudioManager.RINGER_MODE_CHANGED_ACTION); 2916ba195ebc76f23b6679443724ab58c9dc9f2df884Glenn Kasten broadcast.putExtra(AudioManager.EXTRA_RINGER_MODE, ringerMode); 29171c633fc89bae9bf0af6fe643ac7ad2e744f27bedDianne Hackborn broadcast.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT 29181c633fc89bae9bf0af6fe643ac7ad2e744f27bedDianne Hackborn | Intent.FLAG_RECEIVER_REPLACE_PENDING); 29195ac72a29593ab9a20337a2225df52bdf4754be02Dianne Hackborn sendStickyBroadcastToAll(broadcast); 29209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 29219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 29229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private void broadcastVibrateSetting(int vibrateType) { 29239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Send broadcast 29249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (ActivityManagerNative.isSystemReady()) { 29259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Intent broadcast = new Intent(AudioManager.VIBRATE_SETTING_CHANGED_ACTION); 29269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project broadcast.putExtra(AudioManager.EXTRA_VIBRATE_TYPE, vibrateType); 29279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project broadcast.putExtra(AudioManager.EXTRA_VIBRATE_SETTING, getVibrateSetting(vibrateType)); 29285ac72a29593ab9a20337a2225df52bdf4754be02Dianne Hackborn sendBroadcastToAll(broadcast); 29299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 29309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 29319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 29329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Message helper methods 29332d8dab5a549b25b6f36df4614d7c0166d4d099e2Jean-Michel Trivi /** 29342d8dab5a549b25b6f36df4614d7c0166d4d099e2Jean-Michel Trivi * Queue a message on the given handler's message queue, after acquiring the service wake lock. 29352d8dab5a549b25b6f36df4614d7c0166d4d099e2Jean-Michel Trivi * Note that the wake lock needs to be released after the message has been handled. 29362d8dab5a549b25b6f36df4614d7c0166d4d099e2Jean-Michel Trivi */ 29372d8dab5a549b25b6f36df4614d7c0166d4d099e2Jean-Michel Trivi private void queueMsgUnderWakeLock(Handler handler, int msg, 29382d8dab5a549b25b6f36df4614d7c0166d4d099e2Jean-Michel Trivi int arg1, int arg2, Object obj, int delay) { 2939a4dfbdc54d8898491d3a7d1d9d818c7db3fd773dEric Laurent final long ident = Binder.clearCallingIdentity(); 2940a4dfbdc54d8898491d3a7d1d9d818c7db3fd773dEric Laurent // Always acquire the wake lock as AudioService because it is released by the 2941a4dfbdc54d8898491d3a7d1d9d818c7db3fd773dEric Laurent // message handler. 2942fa9a69805b001034aa04c3b33989a7ac21522371Jean-Michel Trivi mAudioEventWakeLock.acquire(); 2943a4dfbdc54d8898491d3a7d1d9d818c7db3fd773dEric Laurent Binder.restoreCallingIdentity(ident); 29442d8dab5a549b25b6f36df4614d7c0166d4d099e2Jean-Michel Trivi sendMsg(handler, msg, SENDMSG_QUEUE, arg1, arg2, obj, delay); 29452d8dab5a549b25b6f36df4614d7c0166d4d099e2Jean-Michel Trivi } 29469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2947afbb047c3945e9c2b7e9bc6b25098d5fb80bba4eEric Laurent private static void sendMsg(Handler handler, int msg, 29489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int existingMsgPolicy, int arg1, int arg2, Object obj, int delay) { 29499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 29509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (existingMsgPolicy == SENDMSG_REPLACE) { 29519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project handler.removeMessages(msg); 29529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else if (existingMsgPolicy == SENDMSG_NOOP && handler.hasMessages(msg)) { 29539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return; 29549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 29559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2956afbb047c3945e9c2b7e9bc6b25098d5fb80bba4eEric Laurent handler.sendMessageDelayed(handler.obtainMessage(msg, arg1, arg2, obj), delay); 29579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 29589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 29599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project boolean checkAudioSettingsPermission(String method) { 29609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (mContext.checkCallingOrSelfPermission("android.permission.MODIFY_AUDIO_SETTINGS") 29619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project == PackageManager.PERMISSION_GRANTED) { 29629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return true; 29639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 29649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project String msg = "Audio Settings Permission Denial: " + method + " from pid=" 29659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project + Binder.getCallingPid() 29669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project + ", uid=" + Binder.getCallingUid(); 29679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Log.w(TAG, msg); 29689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return false; 29699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 29709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 29719bc8358ddaa01c3490f9709991989633a6a3dd42Eric Laurent private int getDeviceForStream(int stream) { 29729bc8358ddaa01c3490f9709991989633a6a3dd42Eric Laurent int device = AudioSystem.getDevicesForStream(stream); 29739bc8358ddaa01c3490f9709991989633a6a3dd42Eric Laurent if ((device & (device - 1)) != 0) { 29749bc8358ddaa01c3490f9709991989633a6a3dd42Eric Laurent // Multiple device selection is either: 29759bc8358ddaa01c3490f9709991989633a6a3dd42Eric Laurent // - speaker + one other device: give priority to speaker in this case. 29769bc8358ddaa01c3490f9709991989633a6a3dd42Eric Laurent // - one A2DP device + another device: happens with duplicated output. In this case 29779bc8358ddaa01c3490f9709991989633a6a3dd42Eric Laurent // retain the device on the A2DP output as the other must not correspond to an active 29789bc8358ddaa01c3490f9709991989633a6a3dd42Eric Laurent // selection if not the speaker. 29799bc8358ddaa01c3490f9709991989633a6a3dd42Eric Laurent if ((device & AudioSystem.DEVICE_OUT_SPEAKER) != 0) { 29809bc8358ddaa01c3490f9709991989633a6a3dd42Eric Laurent device = AudioSystem.DEVICE_OUT_SPEAKER; 29819bc8358ddaa01c3490f9709991989633a6a3dd42Eric Laurent } else { 29829bc8358ddaa01c3490f9709991989633a6a3dd42Eric Laurent device &= AudioSystem.DEVICE_OUT_ALL_A2DP; 29839bc8358ddaa01c3490f9709991989633a6a3dd42Eric Laurent } 29849bc8358ddaa01c3490f9709991989633a6a3dd42Eric Laurent } 29859bc8358ddaa01c3490f9709991989633a6a3dd42Eric Laurent return device; 29869bc8358ddaa01c3490f9709991989633a6a3dd42Eric Laurent } 29879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2988b1fbaaccb656ef09a8770c28df15e3e91a452e64Eric Laurent public void setWiredDeviceConnectionState(int device, int state, String name) { 2989b1fbaaccb656ef09a8770c28df15e3e91a452e64Eric Laurent synchronized (mConnectedDevices) { 2990b1fbaaccb656ef09a8770c28df15e3e91a452e64Eric Laurent int delay = checkSendBecomingNoisyIntent(device, state); 29912d8dab5a549b25b6f36df4614d7c0166d4d099e2Jean-Michel Trivi queueMsgUnderWakeLock(mAudioHandler, 2992b1fbaaccb656ef09a8770c28df15e3e91a452e64Eric Laurent MSG_SET_WIRED_DEVICE_CONNECTION_STATE, 2993b1fbaaccb656ef09a8770c28df15e3e91a452e64Eric Laurent device, 2994b1fbaaccb656ef09a8770c28df15e3e91a452e64Eric Laurent state, 2995b1fbaaccb656ef09a8770c28df15e3e91a452e64Eric Laurent name, 2996b1fbaaccb656ef09a8770c28df15e3e91a452e64Eric Laurent delay); 2997b1fbaaccb656ef09a8770c28df15e3e91a452e64Eric Laurent } 2998b1fbaaccb656ef09a8770c28df15e3e91a452e64Eric Laurent } 2999b1fbaaccb656ef09a8770c28df15e3e91a452e64Eric Laurent 30000a40ec2192e4836b2fcb6ba51a7688aa6bd4ee98Mike Lockwood public int setBluetoothA2dpDeviceConnectionState(BluetoothDevice device, int state, int profile) 3001b1fbaaccb656ef09a8770c28df15e3e91a452e64Eric Laurent { 3002b1fbaaccb656ef09a8770c28df15e3e91a452e64Eric Laurent int delay; 30030a40ec2192e4836b2fcb6ba51a7688aa6bd4ee98Mike Lockwood if (profile != BluetoothProfile.A2DP && profile != BluetoothProfile.A2DP_SINK) { 30040a40ec2192e4836b2fcb6ba51a7688aa6bd4ee98Mike Lockwood throw new IllegalArgumentException("invalid profile " + profile); 30050a40ec2192e4836b2fcb6ba51a7688aa6bd4ee98Mike Lockwood } 3006b1fbaaccb656ef09a8770c28df15e3e91a452e64Eric Laurent synchronized (mConnectedDevices) { 30070a40ec2192e4836b2fcb6ba51a7688aa6bd4ee98Mike Lockwood if (profile == BluetoothProfile.A2DP) { 30080a40ec2192e4836b2fcb6ba51a7688aa6bd4ee98Mike Lockwood delay = checkSendBecomingNoisyIntent(AudioSystem.DEVICE_OUT_BLUETOOTH_A2DP, 30090a40ec2192e4836b2fcb6ba51a7688aa6bd4ee98Mike Lockwood (state == BluetoothA2dp.STATE_CONNECTED) ? 1 : 0); 30100a40ec2192e4836b2fcb6ba51a7688aa6bd4ee98Mike Lockwood } else { 30110a40ec2192e4836b2fcb6ba51a7688aa6bd4ee98Mike Lockwood delay = 0; 30120a40ec2192e4836b2fcb6ba51a7688aa6bd4ee98Mike Lockwood } 30132d8dab5a549b25b6f36df4614d7c0166d4d099e2Jean-Michel Trivi queueMsgUnderWakeLock(mAudioHandler, 30140a40ec2192e4836b2fcb6ba51a7688aa6bd4ee98Mike Lockwood (profile == BluetoothProfile.A2DP ? 30150a40ec2192e4836b2fcb6ba51a7688aa6bd4ee98Mike Lockwood MSG_SET_A2DP_SINK_CONNECTION_STATE : MSG_SET_A2DP_SRC_CONNECTION_STATE), 3016b1fbaaccb656ef09a8770c28df15e3e91a452e64Eric Laurent state, 3017b1fbaaccb656ef09a8770c28df15e3e91a452e64Eric Laurent 0, 3018b1fbaaccb656ef09a8770c28df15e3e91a452e64Eric Laurent device, 3019b1fbaaccb656ef09a8770c28df15e3e91a452e64Eric Laurent delay); 3020b1fbaaccb656ef09a8770c28df15e3e91a452e64Eric Laurent } 3021b1fbaaccb656ef09a8770c28df15e3e91a452e64Eric Laurent return delay; 3022b1fbaaccb656ef09a8770c28df15e3e91a452e64Eric Laurent } 3023b1fbaaccb656ef09a8770c28df15e3e91a452e64Eric Laurent 30249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /////////////////////////////////////////////////////////////////////////// 30259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Inner classes 30269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /////////////////////////////////////////////////////////////////////////// 30279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 30289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public class VolumeStreamState { 30299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private final int mStreamType; 30309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 303111a74a75653197a3d31fe91590cd8312f5270c44Jean-Michel Trivi private String mVolumeIndexSettingName; 3032a553c25b33c99b345cf1c8688f8df0ed8df14e5aEric Laurent private int mIndexMax; 30333172d5e3e7520a745fa37b71fc1c7bf244b57085Eric Laurent private final ConcurrentHashMap<Integer, Integer> mIndex = 30343172d5e3e7520a745fa37b71fc1c7bf244b57085Eric Laurent new ConcurrentHashMap<Integer, Integer>(8, 0.75f, 4); 30359bc8358ddaa01c3490f9709991989633a6a3dd42Eric Laurent private ArrayList<VolumeDeathHandler> mDeathHandlers; //handles mute/solo clients death 30369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3037a553c25b33c99b345cf1c8688f8df0ed8df14e5aEric Laurent private VolumeStreamState(String settingName, int streamType) { 30389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 30399bc8358ddaa01c3490f9709991989633a6a3dd42Eric Laurent mVolumeIndexSettingName = settingName; 30409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 30419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mStreamType = streamType; 30425982013cfc8274ff0bafaba83c676b3a8890cba9Jared Suttles mIndexMax = MAX_STREAM_VOLUME[streamType]; 3043a553c25b33c99b345cf1c8688f8df0ed8df14e5aEric Laurent AudioSystem.initStreamVolume(streamType, 0, mIndexMax); 3044a553c25b33c99b345cf1c8688f8df0ed8df14e5aEric Laurent mIndexMax *= 10; 30459bc8358ddaa01c3490f9709991989633a6a3dd42Eric Laurent 304633902db75011d863009585682bd08560c5b89a75Eric Laurent // mDeathHandlers must be created before calling readSettings() 30479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mDeathHandlers = new ArrayList<VolumeDeathHandler>(); 304833902db75011d863009585682bd08560c5b89a75Eric Laurent 304933902db75011d863009585682bd08560c5b89a75Eric Laurent readSettings(); 30509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 30519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 305242b041ed4f184e3af7f788eb07307f556a2a6616Eric Laurent public String getSettingNameForDevice(int device) { 305342b041ed4f184e3af7f788eb07307f556a2a6616Eric Laurent String name = mVolumeIndexSettingName; 3054948d32748caaac5be06c991ebf00f74265a7849fEric Laurent String suffix = AudioSystem.getOutputDeviceName(device); 30559bc8358ddaa01c3490f9709991989633a6a3dd42Eric Laurent if (suffix.isEmpty()) { 30569bc8358ddaa01c3490f9709991989633a6a3dd42Eric Laurent return name; 30579bc8358ddaa01c3490f9709991989633a6a3dd42Eric Laurent } 30589bc8358ddaa01c3490f9709991989633a6a3dd42Eric Laurent return name + "_" + suffix; 30599bc8358ddaa01c3490f9709991989633a6a3dd42Eric Laurent } 30609bc8358ddaa01c3490f9709991989633a6a3dd42Eric Laurent 3061fdbee869be504e399efce1127a68281bd9b158c5Eric Laurent public void readSettings() { 3062fdbee869be504e399efce1127a68281bd9b158c5Eric Laurent synchronized (VolumeStreamState.class) { 3063fdbee869be504e399efce1127a68281bd9b158c5Eric Laurent // force maximum volume on all streams if fixed volume property is set 3064fdbee869be504e399efce1127a68281bd9b158c5Eric Laurent if (mUseFixedVolume) { 3065fdbee869be504e399efce1127a68281bd9b158c5Eric Laurent mIndex.put(AudioSystem.DEVICE_OUT_DEFAULT, mIndexMax); 3066fdbee869be504e399efce1127a68281bd9b158c5Eric Laurent return; 3067fdbee869be504e399efce1127a68281bd9b158c5Eric Laurent } 3068fdbee869be504e399efce1127a68281bd9b158c5Eric Laurent // do not read system stream volume from settings: this stream is always aliased 3069fdbee869be504e399efce1127a68281bd9b158c5Eric Laurent // to another stream type and its volume is never persisted. Values in settings can 3070fdbee869be504e399efce1127a68281bd9b158c5Eric Laurent // only be stale values 3071fdbee869be504e399efce1127a68281bd9b158c5Eric Laurent if ((mStreamType == AudioSystem.STREAM_SYSTEM) || 3072fdbee869be504e399efce1127a68281bd9b158c5Eric Laurent (mStreamType == AudioSystem.STREAM_SYSTEM_ENFORCED)) { 3073fdbee869be504e399efce1127a68281bd9b158c5Eric Laurent int index = 10 * AudioManager.DEFAULT_STREAM_VOLUME[mStreamType]; 3074fdbee869be504e399efce1127a68281bd9b158c5Eric Laurent synchronized (mCameraSoundForced) { 3075fdbee869be504e399efce1127a68281bd9b158c5Eric Laurent if (mCameraSoundForced) { 3076fdbee869be504e399efce1127a68281bd9b158c5Eric Laurent index = mIndexMax; 3077fdbee869be504e399efce1127a68281bd9b158c5Eric Laurent } 3078dd45d01128423a82652a3c9d77fa393631d95229Eric Laurent } 3079fdbee869be504e399efce1127a68281bd9b158c5Eric Laurent mIndex.put(AudioSystem.DEVICE_OUT_DEFAULT, index); 3080fdbee869be504e399efce1127a68281bd9b158c5Eric Laurent return; 3081dd45d01128423a82652a3c9d77fa393631d95229Eric Laurent } 3082002e9d382d2daa7ed41636463ecdbddbd4897abaEric Laurent 3083fdbee869be504e399efce1127a68281bd9b158c5Eric Laurent int remainingDevices = AudioSystem.DEVICE_OUT_ALL; 308483a017b6b7c099d1a0293e5839be6477325aef06Eric Laurent 3085fdbee869be504e399efce1127a68281bd9b158c5Eric Laurent for (int i = 0; remainingDevices != 0; i++) { 3086fdbee869be504e399efce1127a68281bd9b158c5Eric Laurent int device = (1 << i); 3087fdbee869be504e399efce1127a68281bd9b158c5Eric Laurent if ((device & remainingDevices) == 0) { 3088fdbee869be504e399efce1127a68281bd9b158c5Eric Laurent continue; 3089fdbee869be504e399efce1127a68281bd9b158c5Eric Laurent } 3090fdbee869be504e399efce1127a68281bd9b158c5Eric Laurent remainingDevices &= ~device; 3091fdbee869be504e399efce1127a68281bd9b158c5Eric Laurent 3092fdbee869be504e399efce1127a68281bd9b158c5Eric Laurent // retrieve current volume for device 3093fdbee869be504e399efce1127a68281bd9b158c5Eric Laurent String name = getSettingNameForDevice(device); 3094fdbee869be504e399efce1127a68281bd9b158c5Eric Laurent // if no volume stored for current stream and device, use default volume if default 3095fdbee869be504e399efce1127a68281bd9b158c5Eric Laurent // device, continue otherwise 3096fdbee869be504e399efce1127a68281bd9b158c5Eric Laurent int defaultIndex = (device == AudioSystem.DEVICE_OUT_DEFAULT) ? 3097fdbee869be504e399efce1127a68281bd9b158c5Eric Laurent AudioManager.DEFAULT_STREAM_VOLUME[mStreamType] : -1; 3098fdbee869be504e399efce1127a68281bd9b158c5Eric Laurent int index = Settings.System.getIntForUser( 3099fdbee869be504e399efce1127a68281bd9b158c5Eric Laurent mContentResolver, name, defaultIndex, UserHandle.USER_CURRENT); 3100fdbee869be504e399efce1127a68281bd9b158c5Eric Laurent if (index == -1) { 3101fdbee869be504e399efce1127a68281bd9b158c5Eric Laurent continue; 3102fdbee869be504e399efce1127a68281bd9b158c5Eric Laurent } 31039bc8358ddaa01c3490f9709991989633a6a3dd42Eric Laurent 3104fdbee869be504e399efce1127a68281bd9b158c5Eric Laurent // ignore settings for fixed volume devices: volume should always be at max or 0 3105fdbee869be504e399efce1127a68281bd9b158c5Eric Laurent if ((mStreamVolumeAlias[mStreamType] == AudioSystem.STREAM_MUSIC) && 3106fdbee869be504e399efce1127a68281bd9b158c5Eric Laurent ((device & mFixedVolumeDevices) != 0)) { 3107fdbee869be504e399efce1127a68281bd9b158c5Eric Laurent mIndex.put(device, (index != 0) ? mIndexMax : 0); 3108fdbee869be504e399efce1127a68281bd9b158c5Eric Laurent } else { 3109fdbee869be504e399efce1127a68281bd9b158c5Eric Laurent mIndex.put(device, getValidIndex(10 * index)); 3110fdbee869be504e399efce1127a68281bd9b158c5Eric Laurent } 3111dd45d01128423a82652a3c9d77fa393631d95229Eric Laurent } 31129bc8358ddaa01c3490f9709991989633a6a3dd42Eric Laurent } 31139bc8358ddaa01c3490f9709991989633a6a3dd42Eric Laurent } 31149bc8358ddaa01c3490f9709991989633a6a3dd42Eric Laurent 31159bc8358ddaa01c3490f9709991989633a6a3dd42Eric Laurent public void applyDeviceVolume(int device) { 311642b041ed4f184e3af7f788eb07307f556a2a6616Eric Laurent int index; 311742b041ed4f184e3af7f788eb07307f556a2a6616Eric Laurent if (isMuted()) { 311842b041ed4f184e3af7f788eb07307f556a2a6616Eric Laurent index = 0; 3119cd772d04345850e160a45613fcf6b86da0dce4cfEric Laurent } else if ((device & AudioSystem.DEVICE_OUT_ALL_A2DP) != 0 && 3120c9d1d5f35091226e96fcfa91817480f589eb36e2Matthew Xie mAvrcpAbsVolSupported) { 3121c9d1d5f35091226e96fcfa91817480f589eb36e2Matthew Xie index = (mIndexMax + 5)/10; 3122cd772d04345850e160a45613fcf6b86da0dce4cfEric Laurent } else { 312342b041ed4f184e3af7f788eb07307f556a2a6616Eric Laurent index = (getIndex(device) + 5)/10; 312442b041ed4f184e3af7f788eb07307f556a2a6616Eric Laurent } 312542b041ed4f184e3af7f788eb07307f556a2a6616Eric Laurent AudioSystem.setStreamVolumeIndex(mStreamType, index, device); 31269bc8358ddaa01c3490f9709991989633a6a3dd42Eric Laurent } 31279bc8358ddaa01c3490f9709991989633a6a3dd42Eric Laurent 3128fdbee869be504e399efce1127a68281bd9b158c5Eric Laurent public void applyAllVolumes() { 3129fdbee869be504e399efce1127a68281bd9b158c5Eric Laurent synchronized (VolumeStreamState.class) { 3130fdbee869be504e399efce1127a68281bd9b158c5Eric Laurent // apply default volume first: by convention this will reset all 3131fdbee869be504e399efce1127a68281bd9b158c5Eric Laurent // devices volumes in audio policy manager to the supplied value 3132fdbee869be504e399efce1127a68281bd9b158c5Eric Laurent int index; 3133fdbee869be504e399efce1127a68281bd9b158c5Eric Laurent if (isMuted()) { 3134fdbee869be504e399efce1127a68281bd9b158c5Eric Laurent index = 0; 3135fdbee869be504e399efce1127a68281bd9b158c5Eric Laurent } else { 3136fdbee869be504e399efce1127a68281bd9b158c5Eric Laurent index = (getIndex(AudioSystem.DEVICE_OUT_DEFAULT) + 5)/10; 3137fdbee869be504e399efce1127a68281bd9b158c5Eric Laurent } 3138fdbee869be504e399efce1127a68281bd9b158c5Eric Laurent AudioSystem.setStreamVolumeIndex(mStreamType, index, AudioSystem.DEVICE_OUT_DEFAULT); 3139fdbee869be504e399efce1127a68281bd9b158c5Eric Laurent // then apply device specific volumes 3140fdbee869be504e399efce1127a68281bd9b158c5Eric Laurent Set set = mIndex.entrySet(); 3141fdbee869be504e399efce1127a68281bd9b158c5Eric Laurent Iterator i = set.iterator(); 3142fdbee869be504e399efce1127a68281bd9b158c5Eric Laurent while (i.hasNext()) { 3143fdbee869be504e399efce1127a68281bd9b158c5Eric Laurent Map.Entry entry = (Map.Entry)i.next(); 3144fdbee869be504e399efce1127a68281bd9b158c5Eric Laurent int device = ((Integer)entry.getKey()).intValue(); 3145fdbee869be504e399efce1127a68281bd9b158c5Eric Laurent if (device != AudioSystem.DEVICE_OUT_DEFAULT) { 3146fdbee869be504e399efce1127a68281bd9b158c5Eric Laurent if (isMuted()) { 3147fdbee869be504e399efce1127a68281bd9b158c5Eric Laurent index = 0; 3148fdbee869be504e399efce1127a68281bd9b158c5Eric Laurent } else if ((device & AudioSystem.DEVICE_OUT_ALL_A2DP) != 0 && 3149fdbee869be504e399efce1127a68281bd9b158c5Eric Laurent mAvrcpAbsVolSupported) { 3150fdbee869be504e399efce1127a68281bd9b158c5Eric Laurent index = (mIndexMax + 5)/10; 3151fdbee869be504e399efce1127a68281bd9b158c5Eric Laurent } else { 3152fdbee869be504e399efce1127a68281bd9b158c5Eric Laurent index = ((Integer)entry.getValue() + 5)/10; 3153fdbee869be504e399efce1127a68281bd9b158c5Eric Laurent } 3154fdbee869be504e399efce1127a68281bd9b158c5Eric Laurent AudioSystem.setStreamVolumeIndex(mStreamType, index, device); 315542b041ed4f184e3af7f788eb07307f556a2a6616Eric Laurent } 31569bc8358ddaa01c3490f9709991989633a6a3dd42Eric Laurent } 31579bc8358ddaa01c3490f9709991989633a6a3dd42Eric Laurent } 315811a74a75653197a3d31fe91590cd8312f5270c44Jean-Michel Trivi } 315911a74a75653197a3d31fe91590cd8312f5270c44Jean-Michel Trivi 31609bc8358ddaa01c3490f9709991989633a6a3dd42Eric Laurent public boolean adjustIndex(int deltaIndex, int device) { 316142b041ed4f184e3af7f788eb07307f556a2a6616Eric Laurent return setIndex(getIndex(device) + deltaIndex, 316242b041ed4f184e3af7f788eb07307f556a2a6616Eric Laurent device); 31639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 31649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3165fdbee869be504e399efce1127a68281bd9b158c5Eric Laurent public boolean setIndex(int index, int device) { 3166fdbee869be504e399efce1127a68281bd9b158c5Eric Laurent synchronized (VolumeStreamState.class) { 3167fdbee869be504e399efce1127a68281bd9b158c5Eric Laurent int oldIndex = getIndex(device); 3168fdbee869be504e399efce1127a68281bd9b158c5Eric Laurent index = getValidIndex(index); 3169fdbee869be504e399efce1127a68281bd9b158c5Eric Laurent synchronized (mCameraSoundForced) { 3170fdbee869be504e399efce1127a68281bd9b158c5Eric Laurent if ((mStreamType == AudioSystem.STREAM_SYSTEM_ENFORCED) && mCameraSoundForced) { 3171fdbee869be504e399efce1127a68281bd9b158c5Eric Laurent index = mIndexMax; 3172fdbee869be504e399efce1127a68281bd9b158c5Eric Laurent } 3173dd45d01128423a82652a3c9d77fa393631d95229Eric Laurent } 3174fdbee869be504e399efce1127a68281bd9b158c5Eric Laurent mIndex.put(device, index); 3175fdbee869be504e399efce1127a68281bd9b158c5Eric Laurent 3176fdbee869be504e399efce1127a68281bd9b158c5Eric Laurent if (oldIndex != index) { 3177fdbee869be504e399efce1127a68281bd9b158c5Eric Laurent // Apply change to all streams using this one as alias 3178fdbee869be504e399efce1127a68281bd9b158c5Eric Laurent // if changing volume of current device, also change volume of current 3179fdbee869be504e399efce1127a68281bd9b158c5Eric Laurent // device on aliased stream 3180fdbee869be504e399efce1127a68281bd9b158c5Eric Laurent boolean currentDevice = (device == getDeviceForStream(mStreamType)); 3181fdbee869be504e399efce1127a68281bd9b158c5Eric Laurent int numStreamTypes = AudioSystem.getNumStreamTypes(); 3182fdbee869be504e399efce1127a68281bd9b158c5Eric Laurent for (int streamType = numStreamTypes - 1; streamType >= 0; streamType--) { 3183fdbee869be504e399efce1127a68281bd9b158c5Eric Laurent if (streamType != mStreamType && 3184fdbee869be504e399efce1127a68281bd9b158c5Eric Laurent mStreamVolumeAlias[streamType] == mStreamType) { 3185fdbee869be504e399efce1127a68281bd9b158c5Eric Laurent int scaledIndex = rescaleIndex(index, mStreamType, streamType); 3186bffc3d1bd33eb2d8e00a9f8b6261d815db503311Eric Laurent mStreamStates[streamType].setIndex(scaledIndex, 3187fdbee869be504e399efce1127a68281bd9b158c5Eric Laurent device); 3188fdbee869be504e399efce1127a68281bd9b158c5Eric Laurent if (currentDevice) { 3189fdbee869be504e399efce1127a68281bd9b158c5Eric Laurent mStreamStates[streamType].setIndex(scaledIndex, 3190fdbee869be504e399efce1127a68281bd9b158c5Eric Laurent getDeviceForStream(streamType)); 3191fdbee869be504e399efce1127a68281bd9b158c5Eric Laurent } 3192bffc3d1bd33eb2d8e00a9f8b6261d815db503311Eric Laurent } 3193a553c25b33c99b345cf1c8688f8df0ed8df14e5aEric Laurent } 3194fdbee869be504e399efce1127a68281bd9b158c5Eric Laurent return true; 3195fdbee869be504e399efce1127a68281bd9b158c5Eric Laurent } else { 3196fdbee869be504e399efce1127a68281bd9b158c5Eric Laurent return false; 3197a553c25b33c99b345cf1c8688f8df0ed8df14e5aEric Laurent } 31989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 31999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 32009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3201fdbee869be504e399efce1127a68281bd9b158c5Eric Laurent public int getIndex(int device) { 3202fdbee869be504e399efce1127a68281bd9b158c5Eric Laurent synchronized (VolumeStreamState.class) { 3203fdbee869be504e399efce1127a68281bd9b158c5Eric Laurent Integer index = mIndex.get(device); 3204fdbee869be504e399efce1127a68281bd9b158c5Eric Laurent if (index == null) { 3205fdbee869be504e399efce1127a68281bd9b158c5Eric Laurent // there is always an entry for AudioSystem.DEVICE_OUT_DEFAULT 3206fdbee869be504e399efce1127a68281bd9b158c5Eric Laurent index = mIndex.get(AudioSystem.DEVICE_OUT_DEFAULT); 3207fdbee869be504e399efce1127a68281bd9b158c5Eric Laurent } 3208fdbee869be504e399efce1127a68281bd9b158c5Eric Laurent return index.intValue(); 32099bc8358ddaa01c3490f9709991989633a6a3dd42Eric Laurent } 32109bc8358ddaa01c3490f9709991989633a6a3dd42Eric Laurent } 32119bc8358ddaa01c3490f9709991989633a6a3dd42Eric Laurent 32129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public int getMaxIndex() { 3213a553c25b33c99b345cf1c8688f8df0ed8df14e5aEric Laurent return mIndexMax; 32149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 32159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3216fdbee869be504e399efce1127a68281bd9b158c5Eric Laurent public void setAllIndexes(VolumeStreamState srcStream) { 3217fdbee869be504e399efce1127a68281bd9b158c5Eric Laurent synchronized (VolumeStreamState.class) { 3218fdbee869be504e399efce1127a68281bd9b158c5Eric Laurent int srcStreamType = srcStream.getStreamType(); 3219fdbee869be504e399efce1127a68281bd9b158c5Eric Laurent // apply default device volume from source stream to all devices first in case 3220fdbee869be504e399efce1127a68281bd9b158c5Eric Laurent // some devices are present in this stream state but not in source stream state 3221fdbee869be504e399efce1127a68281bd9b158c5Eric Laurent int index = srcStream.getIndex(AudioSystem.DEVICE_OUT_DEFAULT); 322224e0d9b6c40712a297e4c287435a3b0fdd30e9daEric Laurent index = rescaleIndex(index, srcStreamType, mStreamType); 3223fdbee869be504e399efce1127a68281bd9b158c5Eric Laurent Set set = mIndex.entrySet(); 3224fdbee869be504e399efce1127a68281bd9b158c5Eric Laurent Iterator i = set.iterator(); 3225fdbee869be504e399efce1127a68281bd9b158c5Eric Laurent while (i.hasNext()) { 3226fdbee869be504e399efce1127a68281bd9b158c5Eric Laurent Map.Entry entry = (Map.Entry)i.next(); 3227fdbee869be504e399efce1127a68281bd9b158c5Eric Laurent entry.setValue(index); 3228fdbee869be504e399efce1127a68281bd9b158c5Eric Laurent } 3229fdbee869be504e399efce1127a68281bd9b158c5Eric Laurent // Now apply actual volume for devices in source stream state 3230fdbee869be504e399efce1127a68281bd9b158c5Eric Laurent set = srcStream.mIndex.entrySet(); 3231fdbee869be504e399efce1127a68281bd9b158c5Eric Laurent i = set.iterator(); 3232fdbee869be504e399efce1127a68281bd9b158c5Eric Laurent while (i.hasNext()) { 3233fdbee869be504e399efce1127a68281bd9b158c5Eric Laurent Map.Entry entry = (Map.Entry)i.next(); 3234fdbee869be504e399efce1127a68281bd9b158c5Eric Laurent int device = ((Integer)entry.getKey()).intValue(); 3235fdbee869be504e399efce1127a68281bd9b158c5Eric Laurent index = ((Integer)entry.getValue()).intValue(); 3236fdbee869be504e399efce1127a68281bd9b158c5Eric Laurent index = rescaleIndex(index, srcStreamType, mStreamType); 3237fdbee869be504e399efce1127a68281bd9b158c5Eric Laurent 3238fdbee869be504e399efce1127a68281bd9b158c5Eric Laurent setIndex(index, device); 3239fdbee869be504e399efce1127a68281bd9b158c5Eric Laurent } 32406d5176638c2189595cede38fb92c3e7e8700e221Eric Laurent } 32416d5176638c2189595cede38fb92c3e7e8700e221Eric Laurent } 32426d5176638c2189595cede38fb92c3e7e8700e221Eric Laurent 3243fdbee869be504e399efce1127a68281bd9b158c5Eric Laurent public void setAllIndexesToMax() { 3244fdbee869be504e399efce1127a68281bd9b158c5Eric Laurent synchronized (VolumeStreamState.class) { 3245fdbee869be504e399efce1127a68281bd9b158c5Eric Laurent Set set = mIndex.entrySet(); 3246fdbee869be504e399efce1127a68281bd9b158c5Eric Laurent Iterator i = set.iterator(); 3247fdbee869be504e399efce1127a68281bd9b158c5Eric Laurent while (i.hasNext()) { 3248fdbee869be504e399efce1127a68281bd9b158c5Eric Laurent Map.Entry entry = (Map.Entry)i.next(); 3249fdbee869be504e399efce1127a68281bd9b158c5Eric Laurent entry.setValue(mIndexMax); 3250fdbee869be504e399efce1127a68281bd9b158c5Eric Laurent } 3251dd45d01128423a82652a3c9d77fa393631d95229Eric Laurent } 3252dd45d01128423a82652a3c9d77fa393631d95229Eric Laurent } 3253dd45d01128423a82652a3c9d77fa393631d95229Eric Laurent 3254fdbee869be504e399efce1127a68281bd9b158c5Eric Laurent public void mute(IBinder cb, boolean state) { 3255fdbee869be504e399efce1127a68281bd9b158c5Eric Laurent synchronized (VolumeStreamState.class) { 3256fdbee869be504e399efce1127a68281bd9b158c5Eric Laurent VolumeDeathHandler handler = getDeathHandler(cb, state); 3257fdbee869be504e399efce1127a68281bd9b158c5Eric Laurent if (handler == null) { 3258fdbee869be504e399efce1127a68281bd9b158c5Eric Laurent Log.e(TAG, "Could not get client death handler for stream: "+mStreamType); 3259fdbee869be504e399efce1127a68281bd9b158c5Eric Laurent return; 3260fdbee869be504e399efce1127a68281bd9b158c5Eric Laurent } 3261fdbee869be504e399efce1127a68281bd9b158c5Eric Laurent handler.mute(state); 32629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 32639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 32649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 32656d5176638c2189595cede38fb92c3e7e8700e221Eric Laurent public int getStreamType() { 32666d5176638c2189595cede38fb92c3e7e8700e221Eric Laurent return mStreamType; 32676d5176638c2189595cede38fb92c3e7e8700e221Eric Laurent } 32686d5176638c2189595cede38fb92c3e7e8700e221Eric Laurent 32699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private int getValidIndex(int index) { 32709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (index < 0) { 32719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return 0; 327283a017b6b7c099d1a0293e5839be6477325aef06Eric Laurent } else if (mUseFixedVolume || index > mIndexMax) { 3273a553c25b33c99b345cf1c8688f8df0ed8df14e5aEric Laurent return mIndexMax; 32749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 32759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 32769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return index; 32779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 32789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 32799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private class VolumeDeathHandler implements IBinder.DeathRecipient { 32809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private IBinder mICallback; // To be notified of client's death 32819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private int mMuteCount; // Number of active mutes for this client 32829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 32839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project VolumeDeathHandler(IBinder cb) { 32849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mICallback = cb; 32859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 32869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 32873172d5e3e7520a745fa37b71fc1c7bf244b57085Eric Laurent // must be called while synchronized on parent VolumeStreamState 32889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public void mute(boolean state) { 328942b041ed4f184e3af7f788eb07307f556a2a6616Eric Laurent boolean updateVolume = false; 32903172d5e3e7520a745fa37b71fc1c7bf244b57085Eric Laurent if (state) { 32913172d5e3e7520a745fa37b71fc1c7bf244b57085Eric Laurent if (mMuteCount == 0) { 32923172d5e3e7520a745fa37b71fc1c7bf244b57085Eric Laurent // Register for client death notification 32933172d5e3e7520a745fa37b71fc1c7bf244b57085Eric Laurent try { 32943172d5e3e7520a745fa37b71fc1c7bf244b57085Eric Laurent // mICallback can be 0 if muted by AudioService 32953172d5e3e7520a745fa37b71fc1c7bf244b57085Eric Laurent if (mICallback != null) { 32963172d5e3e7520a745fa37b71fc1c7bf244b57085Eric Laurent mICallback.linkToDeath(this, 0); 32973172d5e3e7520a745fa37b71fc1c7bf244b57085Eric Laurent } 329842b041ed4f184e3af7f788eb07307f556a2a6616Eric Laurent VolumeStreamState.this.mDeathHandlers.add(this); 32993172d5e3e7520a745fa37b71fc1c7bf244b57085Eric Laurent // If the stream is not yet muted by any client, set level to 0 330042b041ed4f184e3af7f788eb07307f556a2a6616Eric Laurent if (!VolumeStreamState.this.isMuted()) { 330142b041ed4f184e3af7f788eb07307f556a2a6616Eric Laurent updateVolume = true; 33023172d5e3e7520a745fa37b71fc1c7bf244b57085Eric Laurent } 33033172d5e3e7520a745fa37b71fc1c7bf244b57085Eric Laurent } catch (RemoteException e) { 33043172d5e3e7520a745fa37b71fc1c7bf244b57085Eric Laurent // Client has died! 33053172d5e3e7520a745fa37b71fc1c7bf244b57085Eric Laurent binderDied(); 33063172d5e3e7520a745fa37b71fc1c7bf244b57085Eric Laurent return; 33073172d5e3e7520a745fa37b71fc1c7bf244b57085Eric Laurent } 33083172d5e3e7520a745fa37b71fc1c7bf244b57085Eric Laurent } else { 33093172d5e3e7520a745fa37b71fc1c7bf244b57085Eric Laurent Log.w(TAG, "stream: "+mStreamType+" was already muted by this client"); 33103172d5e3e7520a745fa37b71fc1c7bf244b57085Eric Laurent } 33113172d5e3e7520a745fa37b71fc1c7bf244b57085Eric Laurent mMuteCount++; 33123172d5e3e7520a745fa37b71fc1c7bf244b57085Eric Laurent } else { 33133172d5e3e7520a745fa37b71fc1c7bf244b57085Eric Laurent if (mMuteCount == 0) { 33143172d5e3e7520a745fa37b71fc1c7bf244b57085Eric Laurent Log.e(TAG, "unexpected unmute for stream: "+mStreamType); 33153172d5e3e7520a745fa37b71fc1c7bf244b57085Eric Laurent } else { 33163172d5e3e7520a745fa37b71fc1c7bf244b57085Eric Laurent mMuteCount--; 33173172d5e3e7520a745fa37b71fc1c7bf244b57085Eric Laurent if (mMuteCount == 0) { 33183172d5e3e7520a745fa37b71fc1c7bf244b57085Eric Laurent // Unregister from client death notification 331942b041ed4f184e3af7f788eb07307f556a2a6616Eric Laurent VolumeStreamState.this.mDeathHandlers.remove(this); 33203172d5e3e7520a745fa37b71fc1c7bf244b57085Eric Laurent // mICallback can be 0 if muted by AudioService 33213172d5e3e7520a745fa37b71fc1c7bf244b57085Eric Laurent if (mICallback != null) { 33223172d5e3e7520a745fa37b71fc1c7bf244b57085Eric Laurent mICallback.unlinkToDeath(this, 0); 33233172d5e3e7520a745fa37b71fc1c7bf244b57085Eric Laurent } 332442b041ed4f184e3af7f788eb07307f556a2a6616Eric Laurent if (!VolumeStreamState.this.isMuted()) { 332542b041ed4f184e3af7f788eb07307f556a2a6616Eric Laurent updateVolume = true; 33269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 33279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 33289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 33299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 333042b041ed4f184e3af7f788eb07307f556a2a6616Eric Laurent if (updateVolume) { 333142b041ed4f184e3af7f788eb07307f556a2a6616Eric Laurent sendMsg(mAudioHandler, 333242b041ed4f184e3af7f788eb07307f556a2a6616Eric Laurent MSG_SET_ALL_VOLUMES, 333342b041ed4f184e3af7f788eb07307f556a2a6616Eric Laurent SENDMSG_QUEUE, 333442b041ed4f184e3af7f788eb07307f556a2a6616Eric Laurent 0, 333542b041ed4f184e3af7f788eb07307f556a2a6616Eric Laurent 0, 333642b041ed4f184e3af7f788eb07307f556a2a6616Eric Laurent VolumeStreamState.this, 0); 333742b041ed4f184e3af7f788eb07307f556a2a6616Eric Laurent } 33389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 33399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 33409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public void binderDied() { 33419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Log.w(TAG, "Volume service client died for stream: "+mStreamType); 33429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (mMuteCount != 0) { 33439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Reset all active mute requests from this client. 33449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mMuteCount = 1; 33459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mute(false); 33469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 33479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 33489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 33499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 33503172d5e3e7520a745fa37b71fc1c7bf244b57085Eric Laurent private synchronized int muteCount() { 33519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int count = 0; 33529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int size = mDeathHandlers.size(); 33539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project for (int i = 0; i < size; i++) { 33549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project count += mDeathHandlers.get(i).mMuteCount; 33559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 33569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return count; 33579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 33589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 335942b041ed4f184e3af7f788eb07307f556a2a6616Eric Laurent private synchronized boolean isMuted() { 336042b041ed4f184e3af7f788eb07307f556a2a6616Eric Laurent return muteCount() != 0; 336142b041ed4f184e3af7f788eb07307f556a2a6616Eric Laurent } 336242b041ed4f184e3af7f788eb07307f556a2a6616Eric Laurent 33633172d5e3e7520a745fa37b71fc1c7bf244b57085Eric Laurent // only called by mute() which is already synchronized 33649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private VolumeDeathHandler getDeathHandler(IBinder cb, boolean state) { 33653172d5e3e7520a745fa37b71fc1c7bf244b57085Eric Laurent VolumeDeathHandler handler; 33663172d5e3e7520a745fa37b71fc1c7bf244b57085Eric Laurent int size = mDeathHandlers.size(); 33673172d5e3e7520a745fa37b71fc1c7bf244b57085Eric Laurent for (int i = 0; i < size; i++) { 33683172d5e3e7520a745fa37b71fc1c7bf244b57085Eric Laurent handler = mDeathHandlers.get(i); 33693172d5e3e7520a745fa37b71fc1c7bf244b57085Eric Laurent if (cb == handler.mICallback) { 33703172d5e3e7520a745fa37b71fc1c7bf244b57085Eric Laurent return handler; 3371ce952c8e13c535bedde77bcdb94dfcc7508475aaMike Lockwood } 3372ce952c8e13c535bedde77bcdb94dfcc7508475aaMike Lockwood } 33733172d5e3e7520a745fa37b71fc1c7bf244b57085Eric Laurent // If this is the first mute request for this client, create a new 33743172d5e3e7520a745fa37b71fc1c7bf244b57085Eric Laurent // client death handler. Otherwise, it is an out of sequence unmute request. 33753172d5e3e7520a745fa37b71fc1c7bf244b57085Eric Laurent if (state) { 33763172d5e3e7520a745fa37b71fc1c7bf244b57085Eric Laurent handler = new VolumeDeathHandler(cb); 33773172d5e3e7520a745fa37b71fc1c7bf244b57085Eric Laurent } else { 33783172d5e3e7520a745fa37b71fc1c7bf244b57085Eric Laurent Log.w(TAG, "stream was not muted by this client"); 33793172d5e3e7520a745fa37b71fc1c7bf244b57085Eric Laurent handler = null; 33803172d5e3e7520a745fa37b71fc1c7bf244b57085Eric Laurent } 33813172d5e3e7520a745fa37b71fc1c7bf244b57085Eric Laurent return handler; 3382ce952c8e13c535bedde77bcdb94dfcc7508475aaMike Lockwood } 3383bffc3d1bd33eb2d8e00a9f8b6261d815db503311Eric Laurent 3384bffc3d1bd33eb2d8e00a9f8b6261d815db503311Eric Laurent private void dump(PrintWriter pw) { 3385dd45d01128423a82652a3c9d77fa393631d95229Eric Laurent pw.print(" Mute count: "); 3386dd45d01128423a82652a3c9d77fa393631d95229Eric Laurent pw.println(muteCount()); 3387bffc3d1bd33eb2d8e00a9f8b6261d815db503311Eric Laurent pw.print(" Current: "); 3388bffc3d1bd33eb2d8e00a9f8b6261d815db503311Eric Laurent Set set = mIndex.entrySet(); 3389bffc3d1bd33eb2d8e00a9f8b6261d815db503311Eric Laurent Iterator i = set.iterator(); 3390bffc3d1bd33eb2d8e00a9f8b6261d815db503311Eric Laurent while (i.hasNext()) { 3391bffc3d1bd33eb2d8e00a9f8b6261d815db503311Eric Laurent Map.Entry entry = (Map.Entry)i.next(); 3392bffc3d1bd33eb2d8e00a9f8b6261d815db503311Eric Laurent pw.print(Integer.toHexString(((Integer)entry.getKey()).intValue()) 3393bffc3d1bd33eb2d8e00a9f8b6261d815db503311Eric Laurent + ": " + ((((Integer)entry.getValue()).intValue() + 5) / 10)+", "); 3394bffc3d1bd33eb2d8e00a9f8b6261d815db503311Eric Laurent } 3395bffc3d1bd33eb2d8e00a9f8b6261d815db503311Eric Laurent } 3396ce952c8e13c535bedde77bcdb94dfcc7508475aaMike Lockwood } 3397ce952c8e13c535bedde77bcdb94dfcc7508475aaMike Lockwood 33989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** Thread that handles native AudioSystem control. */ 33999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private class AudioSystemThread extends Thread { 34009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project AudioSystemThread() { 34019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project super("AudioService"); 34029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 34039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 34049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project @Override 34059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public void run() { 34069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Set this thread up so the handler will work on it 34079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Looper.prepare(); 34089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 34099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project synchronized(AudioService.this) { 34109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mAudioHandler = new AudioHandler(); 34119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 34129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Notify that the handler has been created 34139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project AudioService.this.notify(); 34149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 34159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 34169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Listen for volume change requests that are set by VolumePanel 34179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Looper.loop(); 34189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 34199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 34209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 34219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** Handles internal volume messages in separate volume thread. */ 34229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private class AudioHandler extends Handler { 34239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 34249bc8358ddaa01c3490f9709991989633a6a3dd42Eric Laurent private void setDeviceVolume(VolumeStreamState streamState, int device) { 34259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 34269bc8358ddaa01c3490f9709991989633a6a3dd42Eric Laurent // Apply volume 34279bc8358ddaa01c3490f9709991989633a6a3dd42Eric Laurent streamState.applyDeviceVolume(device); 3428a553c25b33c99b345cf1c8688f8df0ed8df14e5aEric Laurent 3429a553c25b33c99b345cf1c8688f8df0ed8df14e5aEric Laurent // Apply change to all streams using this one as alias 3430a553c25b33c99b345cf1c8688f8df0ed8df14e5aEric Laurent int numStreamTypes = AudioSystem.getNumStreamTypes(); 3431a553c25b33c99b345cf1c8688f8df0ed8df14e5aEric Laurent for (int streamType = numStreamTypes - 1; streamType >= 0; streamType--) { 3432a553c25b33c99b345cf1c8688f8df0ed8df14e5aEric Laurent if (streamType != streamState.mStreamType && 34336d5176638c2189595cede38fb92c3e7e8700e221Eric Laurent mStreamVolumeAlias[streamType] == streamState.mStreamType) { 3434cd772d04345850e160a45613fcf6b86da0dce4cfEric Laurent // Make sure volume is also maxed out on A2DP device for aliased stream 3435cd772d04345850e160a45613fcf6b86da0dce4cfEric Laurent // that may have a different device selected 3436cd772d04345850e160a45613fcf6b86da0dce4cfEric Laurent int streamDevice = getDeviceForStream(streamType); 3437cd772d04345850e160a45613fcf6b86da0dce4cfEric Laurent if ((device != streamDevice) && mAvrcpAbsVolSupported && 3438cd772d04345850e160a45613fcf6b86da0dce4cfEric Laurent ((device & AudioSystem.DEVICE_OUT_ALL_A2DP) != 0)) { 3439cd772d04345850e160a45613fcf6b86da0dce4cfEric Laurent mStreamStates[streamType].applyDeviceVolume(device); 3440cd772d04345850e160a45613fcf6b86da0dce4cfEric Laurent } 3441cd772d04345850e160a45613fcf6b86da0dce4cfEric Laurent mStreamStates[streamType].applyDeviceVolume(streamDevice); 3442a553c25b33c99b345cf1c8688f8df0ed8df14e5aEric Laurent } 3443a553c25b33c99b345cf1c8688f8df0ed8df14e5aEric Laurent } 34449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 34459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Post a persist volume msg 3446afbb047c3945e9c2b7e9bc6b25098d5fb80bba4eEric Laurent sendMsg(mAudioHandler, 3447afbb047c3945e9c2b7e9bc6b25098d5fb80bba4eEric Laurent MSG_PERSIST_VOLUME, 344898ad9b9d6fd34aad487933170f50b5519313df61Eric Laurent SENDMSG_QUEUE, 34499bc8358ddaa01c3490f9709991989633a6a3dd42Eric Laurent device, 345042b041ed4f184e3af7f788eb07307f556a2a6616Eric Laurent 0, 3451afbb047c3945e9c2b7e9bc6b25098d5fb80bba4eEric Laurent streamState, 3452afbb047c3945e9c2b7e9bc6b25098d5fb80bba4eEric Laurent PERSIST_DELAY); 3453afbb047c3945e9c2b7e9bc6b25098d5fb80bba4eEric Laurent 34549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 34559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 34569bc8358ddaa01c3490f9709991989633a6a3dd42Eric Laurent private void setAllVolumes(VolumeStreamState streamState) { 34579bc8358ddaa01c3490f9709991989633a6a3dd42Eric Laurent 34589bc8358ddaa01c3490f9709991989633a6a3dd42Eric Laurent // Apply volume 34599bc8358ddaa01c3490f9709991989633a6a3dd42Eric Laurent streamState.applyAllVolumes(); 34609bc8358ddaa01c3490f9709991989633a6a3dd42Eric Laurent 34619bc8358ddaa01c3490f9709991989633a6a3dd42Eric Laurent // Apply change to all streams using this one as alias 34629bc8358ddaa01c3490f9709991989633a6a3dd42Eric Laurent int numStreamTypes = AudioSystem.getNumStreamTypes(); 34639bc8358ddaa01c3490f9709991989633a6a3dd42Eric Laurent for (int streamType = numStreamTypes - 1; streamType >= 0; streamType--) { 34649bc8358ddaa01c3490f9709991989633a6a3dd42Eric Laurent if (streamType != streamState.mStreamType && 34656d5176638c2189595cede38fb92c3e7e8700e221Eric Laurent mStreamVolumeAlias[streamType] == streamState.mStreamType) { 34669bc8358ddaa01c3490f9709991989633a6a3dd42Eric Laurent mStreamStates[streamType].applyAllVolumes(); 34679bc8358ddaa01c3490f9709991989633a6a3dd42Eric Laurent } 34689bc8358ddaa01c3490f9709991989633a6a3dd42Eric Laurent } 34699bc8358ddaa01c3490f9709991989633a6a3dd42Eric Laurent } 34709bc8358ddaa01c3490f9709991989633a6a3dd42Eric Laurent 347142b041ed4f184e3af7f788eb07307f556a2a6616Eric Laurent private void persistVolume(VolumeStreamState streamState, int device) { 347283a017b6b7c099d1a0293e5839be6477325aef06Eric Laurent if (mUseFixedVolume) { 347383a017b6b7c099d1a0293e5839be6477325aef06Eric Laurent return; 347483a017b6b7c099d1a0293e5839be6477325aef06Eric Laurent } 347542b041ed4f184e3af7f788eb07307f556a2a6616Eric Laurent System.putIntForUser(mContentResolver, 347642b041ed4f184e3af7f788eb07307f556a2a6616Eric Laurent streamState.getSettingNameForDevice(device), 347742b041ed4f184e3af7f788eb07307f556a2a6616Eric Laurent (streamState.getIndex(device) + 5)/ 10, 347842b041ed4f184e3af7f788eb07307f556a2a6616Eric Laurent UserHandle.USER_CURRENT); 34799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 34809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3481ba195ebc76f23b6679443724ab58c9dc9f2df884Glenn Kasten private void persistRingerMode(int ringerMode) { 348283a017b6b7c099d1a0293e5839be6477325aef06Eric Laurent if (mUseFixedVolume) { 348383a017b6b7c099d1a0293e5839be6477325aef06Eric Laurent return; 348483a017b6b7c099d1a0293e5839be6477325aef06Eric Laurent } 34858d9a1f66d9d3dbbd45a56d441a746ec11dba7645Jeff Sharkey Settings.Global.putInt(mContentResolver, Settings.Global.MODE_RINGER, ringerMode); 34869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 34879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 34885d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent private boolean onLoadSoundEffects() { 34895d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent int status; 34905d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent 34915d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent synchronized (mSoundEffectsLock) { 34924a5eeb9c727d77bb57fef87a70c8c9cc23dbfee3Eric Laurent if (!mSystemReady) { 34935d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent Log.w(TAG, "onLoadSoundEffects() called before boot complete"); 34945d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent return false; 34955d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent } 34965d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent 34975d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent if (mSoundPool != null) { 34985d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent return true; 34995d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent } 35005d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent 35015d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent loadTouchSoundAssets(); 35025d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent 35035d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent mSoundPool = new SoundPool(NUM_SOUNDPOOL_CHANNELS, AudioSystem.STREAM_SYSTEM, 0); 35045d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent mSoundPoolCallBack = null; 35055d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent mSoundPoolListenerThread = new SoundPoolListenerThread(); 35065d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent mSoundPoolListenerThread.start(); 35075d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent int attempts = 3; 35085d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent while ((mSoundPoolCallBack == null) && (attempts-- > 0)) { 35095d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent try { 35105d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent // Wait for mSoundPoolCallBack to be set by the other thread 3511167d1a27713ab64cd3c0aa70de96434083ef0400Glenn Kasten mSoundEffectsLock.wait(SOUND_EFFECTS_LOAD_TIMEOUT_MS); 35125d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent } catch (InterruptedException e) { 35135d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent Log.w(TAG, "Interrupted while waiting sound pool listener thread."); 35145d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent } 35155d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent } 35165d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent 35175d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent if (mSoundPoolCallBack == null) { 35185d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent Log.w(TAG, "onLoadSoundEffects() SoundPool listener or thread creation error"); 35195d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent if (mSoundPoolLooper != null) { 35205d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent mSoundPoolLooper.quit(); 35215d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent mSoundPoolLooper = null; 35225d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent } 35235d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent mSoundPoolListenerThread = null; 35245d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent mSoundPool.release(); 35255d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent mSoundPool = null; 35265d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent return false; 35275d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent } 35285d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent /* 35295d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent * poolId table: The value -1 in this table indicates that corresponding 35305d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent * file (same index in SOUND_EFFECT_FILES[] has not been loaded. 35315d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent * Once loaded, the value in poolId is the sample ID and the same 35325d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent * sample can be reused for another effect using the same file. 35335d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent */ 35345d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent int[] poolId = new int[SOUND_EFFECT_FILES.size()]; 35355d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent for (int fileIdx = 0; fileIdx < SOUND_EFFECT_FILES.size(); fileIdx++) { 35365d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent poolId[fileIdx] = -1; 35375d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent } 35385d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent /* 35395d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent * Effects whose value in SOUND_EFFECT_FILES_MAP[effect][1] is -1 must be loaded. 35405d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent * If load succeeds, value in SOUND_EFFECT_FILES_MAP[effect][1] is > 0: 35415d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent * this indicates we have a valid sample loaded for this effect. 35425d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent */ 35435d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent 35445d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent int numSamples = 0; 35455d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent for (int effect = 0; effect < AudioManager.NUM_SOUND_EFFECTS; effect++) { 35465d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent // Do not load sample if this effect uses the MediaPlayer 35475d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent if (SOUND_EFFECT_FILES_MAP[effect][1] == 0) { 35485d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent continue; 35495d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent } 35505d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent if (poolId[SOUND_EFFECT_FILES_MAP[effect][0]] == -1) { 35515d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent String filePath = Environment.getRootDirectory() 35525d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent + SOUND_EFFECTS_PATH 35535d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent + SOUND_EFFECT_FILES.get(SOUND_EFFECT_FILES_MAP[effect][0]); 35545d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent int sampleId = mSoundPool.load(filePath, 0); 35555d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent if (sampleId <= 0) { 35565d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent Log.w(TAG, "Soundpool could not load file: "+filePath); 35575d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent } else { 35585d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent SOUND_EFFECT_FILES_MAP[effect][1] = sampleId; 35595d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent poolId[SOUND_EFFECT_FILES_MAP[effect][0]] = sampleId; 35605d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent numSamples++; 35615d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent } 35625d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent } else { 35635d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent SOUND_EFFECT_FILES_MAP[effect][1] = 35645d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent poolId[SOUND_EFFECT_FILES_MAP[effect][0]]; 35655d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent } 35665d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent } 35675d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent // wait for all samples to be loaded 35685d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent if (numSamples > 0) { 35695d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent mSoundPoolCallBack.setSamples(poolId); 35705d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent 35715d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent attempts = 3; 35725d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent status = 1; 35735d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent while ((status == 1) && (attempts-- > 0)) { 35745d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent try { 3575167d1a27713ab64cd3c0aa70de96434083ef0400Glenn Kasten mSoundEffectsLock.wait(SOUND_EFFECTS_LOAD_TIMEOUT_MS); 35765d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent status = mSoundPoolCallBack.status(); 35775d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent } catch (InterruptedException e) { 35785d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent Log.w(TAG, "Interrupted while waiting sound pool callback."); 35795d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent } 35805d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent } 35815d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent } else { 35825d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent status = -1; 35835d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent } 35845d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent 35855d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent if (mSoundPoolLooper != null) { 35865d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent mSoundPoolLooper.quit(); 35875d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent mSoundPoolLooper = null; 35885d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent } 35895d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent mSoundPoolListenerThread = null; 35905d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent if (status != 0) { 35915d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent Log.w(TAG, 35925d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent "onLoadSoundEffects(), Error "+status+ " while loading samples"); 35935d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent for (int effect = 0; effect < AudioManager.NUM_SOUND_EFFECTS; effect++) { 35945d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent if (SOUND_EFFECT_FILES_MAP[effect][1] > 0) { 35955d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent SOUND_EFFECT_FILES_MAP[effect][1] = -1; 35965d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent } 35975d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent } 35985d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent 35995d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent mSoundPool.release(); 36005d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent mSoundPool = null; 36015d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent } 36025d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent } 36035d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent return (status == 0); 36045d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent } 36055d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent 36065d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent /** 36075d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent * Unloads samples from the sound pool. 36085d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent * This method can be called to free some memory when 36095d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent * sound effects are disabled. 36105d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent */ 36115d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent private void onUnloadSoundEffects() { 36125d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent synchronized (mSoundEffectsLock) { 36135d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent if (mSoundPool == null) { 36145d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent return; 36155d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent } 36165d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent 36175d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent int[] poolId = new int[SOUND_EFFECT_FILES.size()]; 36185d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent for (int fileIdx = 0; fileIdx < SOUND_EFFECT_FILES.size(); fileIdx++) { 36195d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent poolId[fileIdx] = 0; 36205d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent } 36215d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent 36225d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent for (int effect = 0; effect < AudioManager.NUM_SOUND_EFFECTS; effect++) { 36235d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent if (SOUND_EFFECT_FILES_MAP[effect][1] <= 0) { 36245d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent continue; 36255d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent } 36265d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent if (poolId[SOUND_EFFECT_FILES_MAP[effect][0]] == 0) { 36275d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent mSoundPool.unload(SOUND_EFFECT_FILES_MAP[effect][1]); 36285d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent SOUND_EFFECT_FILES_MAP[effect][1] = -1; 36295d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent poolId[SOUND_EFFECT_FILES_MAP[effect][0]] = -1; 36305d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent } 36315d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent } 36325d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent mSoundPool.release(); 36335d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent mSoundPool = null; 36345d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent } 36355d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent } 36365d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent 36375d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent private void onPlaySoundEffect(int effectType, int volume) { 36389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project synchronized (mSoundEffectsLock) { 36395d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent 36405d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent onLoadSoundEffects(); 36415d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent 36429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (mSoundPool == null) { 36439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return; 36449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3645a2ef57dba9ac77d8eccacd646b2b8a8d99fe9d8bEric Laurent float volFloat; 364625101b0b9a84571ead15b26e9f4cd9c4298d7823Eric Laurent // use default if volume is not specified by caller 3647a2ef57dba9ac77d8eccacd646b2b8a8d99fe9d8bEric Laurent if (volume < 0) { 3648f2b0c11f4e797e183131261724d8de310dac5431Jean-Michel Trivi volFloat = (float)Math.pow(10, (float)sSoundEffectVolumeDb/20); 3649a2ef57dba9ac77d8eccacd646b2b8a8d99fe9d8bEric Laurent } else { 36508a2cfc309ab9126e90022916967c65a793c034f0RoboErik volFloat = volume / 1000.0f; 3651a2ef57dba9ac77d8eccacd646b2b8a8d99fe9d8bEric Laurent } 36529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 36539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (SOUND_EFFECT_FILES_MAP[effectType][1] > 0) { 36545d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent mSoundPool.play(SOUND_EFFECT_FILES_MAP[effectType][1], 36555d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent volFloat, volFloat, 0, 0, 1.0f); 36569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else { 36579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project MediaPlayer mediaPlayer = new MediaPlayer(); 365862b9aec7a0a4e1cf8cfec7e39ea3103ab510d72eGlenn Kasten try { 3659e78fced559d879b2e37b610d0d9a89daf08f0f2bEric Laurent String filePath = Environment.getRootDirectory() + SOUND_EFFECTS_PATH + 3660e78fced559d879b2e37b610d0d9a89daf08f0f2bEric Laurent SOUND_EFFECT_FILES.get(SOUND_EFFECT_FILES_MAP[effectType][0]); 366162b9aec7a0a4e1cf8cfec7e39ea3103ab510d72eGlenn Kasten mediaPlayer.setDataSource(filePath); 366262b9aec7a0a4e1cf8cfec7e39ea3103ab510d72eGlenn Kasten mediaPlayer.setAudioStreamType(AudioSystem.STREAM_SYSTEM); 366362b9aec7a0a4e1cf8cfec7e39ea3103ab510d72eGlenn Kasten mediaPlayer.prepare(); 3664068225de0197df07a0247b2877666ea91c22c992Glenn Kasten mediaPlayer.setVolume(volFloat); 366562b9aec7a0a4e1cf8cfec7e39ea3103ab510d72eGlenn Kasten mediaPlayer.setOnCompletionListener(new OnCompletionListener() { 366662b9aec7a0a4e1cf8cfec7e39ea3103ab510d72eGlenn Kasten public void onCompletion(MediaPlayer mp) { 366762b9aec7a0a4e1cf8cfec7e39ea3103ab510d72eGlenn Kasten cleanupPlayer(mp); 366862b9aec7a0a4e1cf8cfec7e39ea3103ab510d72eGlenn Kasten } 366962b9aec7a0a4e1cf8cfec7e39ea3103ab510d72eGlenn Kasten }); 367062b9aec7a0a4e1cf8cfec7e39ea3103ab510d72eGlenn Kasten mediaPlayer.setOnErrorListener(new OnErrorListener() { 367162b9aec7a0a4e1cf8cfec7e39ea3103ab510d72eGlenn Kasten public boolean onError(MediaPlayer mp, int what, int extra) { 367262b9aec7a0a4e1cf8cfec7e39ea3103ab510d72eGlenn Kasten cleanupPlayer(mp); 367362b9aec7a0a4e1cf8cfec7e39ea3103ab510d72eGlenn Kasten return true; 367462b9aec7a0a4e1cf8cfec7e39ea3103ab510d72eGlenn Kasten } 367562b9aec7a0a4e1cf8cfec7e39ea3103ab510d72eGlenn Kasten }); 367662b9aec7a0a4e1cf8cfec7e39ea3103ab510d72eGlenn Kasten mediaPlayer.start(); 367762b9aec7a0a4e1cf8cfec7e39ea3103ab510d72eGlenn Kasten } catch (IOException ex) { 367862b9aec7a0a4e1cf8cfec7e39ea3103ab510d72eGlenn Kasten Log.w(TAG, "MediaPlayer IOException: "+ex); 367962b9aec7a0a4e1cf8cfec7e39ea3103ab510d72eGlenn Kasten } catch (IllegalArgumentException ex) { 368062b9aec7a0a4e1cf8cfec7e39ea3103ab510d72eGlenn Kasten Log.w(TAG, "MediaPlayer IllegalArgumentException: "+ex); 368162b9aec7a0a4e1cf8cfec7e39ea3103ab510d72eGlenn Kasten } catch (IllegalStateException ex) { 368262b9aec7a0a4e1cf8cfec7e39ea3103ab510d72eGlenn Kasten Log.w(TAG, "MediaPlayer IllegalStateException: "+ex); 36839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 36849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 36859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 36869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 36879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 36889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private void cleanupPlayer(MediaPlayer mp) { 36899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (mp != null) { 36909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project try { 36919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mp.stop(); 36929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mp.release(); 36939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } catch (IllegalStateException ex) { 36949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Log.w(TAG, "MediaPlayer IllegalStateException: "+ex); 36959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 36969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 36979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 36989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3699fa640154f1f42121d81242b2f1a10f03e52f0014Eric Laurent private void setForceUse(int usage, int config) { 3700fa640154f1f42121d81242b2f1a10f03e52f0014Eric Laurent AudioSystem.setForceUse(usage, config); 3701fa640154f1f42121d81242b2f1a10f03e52f0014Eric Laurent } 3702fa640154f1f42121d81242b2f1a10f03e52f0014Eric Laurent 370305274f348e12983eb8613cc6eb9ae561e8197e28Eric Laurent private void onPersistSafeVolumeState(int state) { 370405274f348e12983eb8613cc6eb9ae561e8197e28Eric Laurent Settings.Global.putInt(mContentResolver, 370505274f348e12983eb8613cc6eb9ae561e8197e28Eric Laurent Settings.Global.AUDIO_SAFE_VOLUME_STATE, 370605274f348e12983eb8613cc6eb9ae561e8197e28Eric Laurent state); 370705274f348e12983eb8613cc6eb9ae561e8197e28Eric Laurent } 370805274f348e12983eb8613cc6eb9ae561e8197e28Eric Laurent 37099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project @Override 37109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public void handleMessage(Message msg) { 37119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3712afbb047c3945e9c2b7e9bc6b25098d5fb80bba4eEric Laurent switch (msg.what) { 37139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 37149bc8358ddaa01c3490f9709991989633a6a3dd42Eric Laurent case MSG_SET_DEVICE_VOLUME: 37159bc8358ddaa01c3490f9709991989633a6a3dd42Eric Laurent setDeviceVolume((VolumeStreamState) msg.obj, msg.arg1); 37169bc8358ddaa01c3490f9709991989633a6a3dd42Eric Laurent break; 37179bc8358ddaa01c3490f9709991989633a6a3dd42Eric Laurent 37189bc8358ddaa01c3490f9709991989633a6a3dd42Eric Laurent case MSG_SET_ALL_VOLUMES: 37199bc8358ddaa01c3490f9709991989633a6a3dd42Eric Laurent setAllVolumes((VolumeStreamState) msg.obj); 37209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project break; 37219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 37229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project case MSG_PERSIST_VOLUME: 372342b041ed4f184e3af7f788eb07307f556a2a6616Eric Laurent persistVolume((VolumeStreamState) msg.obj, msg.arg1); 37249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project break; 37259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 37265c55a051ad7d86a464fb91426f1ea3c0250e38b3Mike Lockwood case MSG_PERSIST_MASTER_VOLUME: 372783a017b6b7c099d1a0293e5839be6477325aef06Eric Laurent if (mUseFixedVolume) { 372883a017b6b7c099d1a0293e5839be6477325aef06Eric Laurent return; 372983a017b6b7c099d1a0293e5839be6477325aef06Eric Laurent } 3730bc0fab1fc2db832ef86d8a33466ec4d68b103ca0Eric Laurent Settings.System.putFloatForUser(mContentResolver, 3731bc0fab1fc2db832ef86d8a33466ec4d68b103ca0Eric Laurent Settings.System.VOLUME_MASTER, 37328a2cfc309ab9126e90022916967c65a793c034f0RoboErik msg.arg1 / (float)1000.0, 3733bc0fab1fc2db832ef86d8a33466ec4d68b103ca0Eric Laurent UserHandle.USER_CURRENT); 37345c55a051ad7d86a464fb91426f1ea3c0250e38b3Mike Lockwood break; 37355c55a051ad7d86a464fb91426f1ea3c0250e38b3Mike Lockwood 373657978ed86286a33d5b1a0fd000ca3406ba9d87b3Justin Koh case MSG_PERSIST_MASTER_VOLUME_MUTE: 373783a017b6b7c099d1a0293e5839be6477325aef06Eric Laurent if (mUseFixedVolume) { 373883a017b6b7c099d1a0293e5839be6477325aef06Eric Laurent return; 373983a017b6b7c099d1a0293e5839be6477325aef06Eric Laurent } 3740bc0fab1fc2db832ef86d8a33466ec4d68b103ca0Eric Laurent Settings.System.putIntForUser(mContentResolver, 3741bc0fab1fc2db832ef86d8a33466ec4d68b103ca0Eric Laurent Settings.System.VOLUME_MASTER_MUTE, 3742bc0fab1fc2db832ef86d8a33466ec4d68b103ca0Eric Laurent msg.arg1, 3743bc0fab1fc2db832ef86d8a33466ec4d68b103ca0Eric Laurent UserHandle.USER_CURRENT); 374457978ed86286a33d5b1a0fd000ca3406ba9d87b3Justin Koh break; 374557978ed86286a33d5b1a0fd000ca3406ba9d87b3Justin Koh 37469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project case MSG_PERSIST_RINGER_MODE: 3747ba195ebc76f23b6679443724ab58c9dc9f2df884Glenn Kasten // note that the value persisted is the current ringer mode, not the 3748ba195ebc76f23b6679443724ab58c9dc9f2df884Glenn Kasten // value of ringer mode as of the time the request was made to persist 3749ba195ebc76f23b6679443724ab58c9dc9f2df884Glenn Kasten persistRingerMode(getRingerMode()); 37509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project break; 37519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 37529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project case MSG_MEDIA_SERVER_DIED: 3753dfb881f96af7898151940a4bbc52e45e6043d38bEric Laurent if (AudioSystem.checkAudioFlinger() != AudioSystem.AUDIO_STATUS_OK) { 375489e74ba1419732dd5c7f939e48d4aa7989fd3a51Eric Laurent Log.e(TAG, "Media server died."); 3755afbb047c3945e9c2b7e9bc6b25098d5fb80bba4eEric Laurent sendMsg(mAudioHandler, MSG_MEDIA_SERVER_DIED, SENDMSG_NOOP, 0, 0, 375689e74ba1419732dd5c7f939e48d4aa7989fd3a51Eric Laurent null, 500); 3757dfb881f96af7898151940a4bbc52e45e6043d38bEric Laurent break; 375889e74ba1419732dd5c7f939e48d4aa7989fd3a51Eric Laurent } 37599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Log.e(TAG, "Media server started."); 3760dfb881f96af7898151940a4bbc52e45e6043d38bEric Laurent 37613c652ca5a546e7227a5f4bdbf0f81552b2c91383Eric Laurent // indicate to audio HAL that we start the reconfiguration phase after a media 37623c652ca5a546e7227a5f4bdbf0f81552b2c91383Eric Laurent // server crash 3763dfb881f96af7898151940a4bbc52e45e6043d38bEric Laurent // Note that we only execute this when the media server 37643c652ca5a546e7227a5f4bdbf0f81552b2c91383Eric Laurent // process restarts after a crash, not the first time it is started. 37653c652ca5a546e7227a5f4bdbf0f81552b2c91383Eric Laurent AudioSystem.setParameters("restarting=true"); 37663c652ca5a546e7227a5f4bdbf0f81552b2c91383Eric Laurent 3767fd116ad1ab02f6060a0b2201f018317fa32e28b4Glenn Kasten readAndSetLowRamDevice(); 3768fd116ad1ab02f6060a0b2201f018317fa32e28b4Glenn Kasten 3769c42ac9d4d03f62c3a1ba197a28a81fda44bd8b7fEric Laurent // Restore device connection states 37706bc7f2cd30b6bd90806942b0722e22daa2108493Eric Laurent synchronized (mConnectedDevices) { 37716bc7f2cd30b6bd90806942b0722e22daa2108493Eric Laurent Set set = mConnectedDevices.entrySet(); 37726bc7f2cd30b6bd90806942b0722e22daa2108493Eric Laurent Iterator i = set.iterator(); 37739bc8358ddaa01c3490f9709991989633a6a3dd42Eric Laurent while (i.hasNext()) { 37746bc7f2cd30b6bd90806942b0722e22daa2108493Eric Laurent Map.Entry device = (Map.Entry)i.next(); 37756bc7f2cd30b6bd90806942b0722e22daa2108493Eric Laurent AudioSystem.setDeviceConnectionState( 37766bc7f2cd30b6bd90806942b0722e22daa2108493Eric Laurent ((Integer)device.getKey()).intValue(), 37776bc7f2cd30b6bd90806942b0722e22daa2108493Eric Laurent AudioSystem.DEVICE_STATE_AVAILABLE, 37786bc7f2cd30b6bd90806942b0722e22daa2108493Eric Laurent (String)device.getValue()); 37796bc7f2cd30b6bd90806942b0722e22daa2108493Eric Laurent } 3780c42ac9d4d03f62c3a1ba197a28a81fda44bd8b7fEric Laurent } 3781c42ac9d4d03f62c3a1ba197a28a81fda44bd8b7fEric Laurent // Restore call state 3782c42ac9d4d03f62c3a1ba197a28a81fda44bd8b7fEric Laurent AudioSystem.setPhoneState(mMode); 3783c42ac9d4d03f62c3a1ba197a28a81fda44bd8b7fEric Laurent 3784d5603c126acdd94d9f7400bb1d04188020a425b4Eric Laurent // Restore forced usage for communcations and record 3785c42ac9d4d03f62c3a1ba197a28a81fda44bd8b7fEric Laurent AudioSystem.setForceUse(AudioSystem.FOR_COMMUNICATION, mForcedUseForComm); 3786d5603c126acdd94d9f7400bb1d04188020a425b4Eric Laurent AudioSystem.setForceUse(AudioSystem.FOR_RECORD, mForcedUseForComm); 3787dd45d01128423a82652a3c9d77fa393631d95229Eric Laurent AudioSystem.setForceUse(AudioSystem.FOR_SYSTEM, mCameraSoundForced ? 3788dd45d01128423a82652a3c9d77fa393631d95229Eric Laurent AudioSystem.FORCE_SYSTEM_ENFORCED : AudioSystem.FORCE_NONE); 3789c42ac9d4d03f62c3a1ba197a28a81fda44bd8b7fEric Laurent 3790a553c25b33c99b345cf1c8688f8df0ed8df14e5aEric Laurent // Restore stream volumes 37919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int numStreamTypes = AudioSystem.getNumStreamTypes(); 37929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project for (int streamType = numStreamTypes - 1; streamType >= 0; streamType--) { 37939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project VolumeStreamState streamState = mStreamStates[streamType]; 3794c42ac9d4d03f62c3a1ba197a28a81fda44bd8b7fEric Laurent AudioSystem.initStreamVolume(streamType, 0, (streamState.mIndexMax + 5) / 10); 37959bc8358ddaa01c3490f9709991989633a6a3dd42Eric Laurent 37969bc8358ddaa01c3490f9709991989633a6a3dd42Eric Laurent streamState.applyAllVolumes(); 37979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3798c42ac9d4d03f62c3a1ba197a28a81fda44bd8b7fEric Laurent 3799c42ac9d4d03f62c3a1ba197a28a81fda44bd8b7fEric Laurent // Restore ringer mode 3800c42ac9d4d03f62c3a1ba197a28a81fda44bd8b7fEric Laurent setRingerModeInt(getRingerMode(), false); 38013c652ca5a546e7227a5f4bdbf0f81552b2c91383Eric Laurent 38029063154a793b0ab38b3c5992cbaed046427b4a82Mike Lockwood // Restore master volume 38039063154a793b0ab38b3c5992cbaed046427b4a82Mike Lockwood restoreMasterVolume(); 38049063154a793b0ab38b3c5992cbaed046427b4a82Mike Lockwood 3805f26f01784e1c733c53cad3ed31918e73448ce369Jean-Michel Trivi // Reset device orientation (if monitored for this device) 3806d640bd325c3be9a350058c835b880a7e0b40dc60Eric Laurent if (mMonitorOrientation) { 3807f26f01784e1c733c53cad3ed31918e73448ce369Jean-Michel Trivi setOrientationForAudioSystem(); 3808f26f01784e1c733c53cad3ed31918e73448ce369Jean-Michel Trivi } 3809bb6f8711a7f804d39c45218db2d6339940cc5d35Jean-Michel Trivi if (mMonitorRotation) { 3810bb6f8711a7f804d39c45218db2d6339940cc5d35Jean-Michel Trivi setRotationForAudioSystem(); 3811bb6f8711a7f804d39c45218db2d6339940cc5d35Jean-Michel Trivi } 3812f26f01784e1c733c53cad3ed31918e73448ce369Jean-Michel Trivi 38137847211fb4699bf6018e29d214a918ed6657319bEric Laurent synchronized (mBluetoothA2dpEnabledLock) { 38147847211fb4699bf6018e29d214a918ed6657319bEric Laurent AudioSystem.setForceUse(AudioSystem.FOR_MEDIA, 38157847211fb4699bf6018e29d214a918ed6657319bEric Laurent mBluetoothA2dpEnabled ? 38167847211fb4699bf6018e29d214a918ed6657319bEric Laurent AudioSystem.FORCE_NONE : AudioSystem.FORCE_NO_BT_A2DP); 38177847211fb4699bf6018e29d214a918ed6657319bEric Laurent } 3818bff5ca576ef55bfdd51a0d2ff39f4bac614fa728Eric Laurent 3819bff5ca576ef55bfdd51a0d2ff39f4bac614fa728Eric Laurent synchronized (mSettingsLock) { 3820bff5ca576ef55bfdd51a0d2ff39f4bac614fa728Eric Laurent AudioSystem.setForceUse(AudioSystem.FOR_DOCK, 3821bff5ca576ef55bfdd51a0d2ff39f4bac614fa728Eric Laurent mDockAudioMediaEnabled ? 3822bff5ca576ef55bfdd51a0d2ff39f4bac614fa728Eric Laurent AudioSystem.FORCE_ANALOG_DOCK : AudioSystem.FORCE_NONE); 3823bff5ca576ef55bfdd51a0d2ff39f4bac614fa728Eric Laurent } 3824bff5ca576ef55bfdd51a0d2ff39f4bac614fa728Eric Laurent 38256f34f5ab8ab1b1db7887e5405d8b0031e105ab05Jungshik Jang if (mHdmiTvClient != null) { 382612307ca810e8100981b2b60e3f2c6a7e451b9774Jungshik Jang setHdmiSystemAudioSupported(mHdmiSystemAudioSupported); 38276f34f5ab8ab1b1db7887e5405d8b0031e105ab05Jungshik Jang } 38286f34f5ab8ab1b1db7887e5405d8b0031e105ab05Jungshik Jang 38293c652ca5a546e7227a5f4bdbf0f81552b2c91383Eric Laurent // indicate the end of reconfiguration phase to audio HAL 38303c652ca5a546e7227a5f4bdbf0f81552b2c91383Eric Laurent AudioSystem.setParameters("restarting=false"); 38319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project break; 38329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 38335d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent case MSG_UNLOAD_SOUND_EFFECTS: 38345d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent onUnloadSoundEffects(); 38355d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent break; 38365d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent 3837117b7bb5b5a4457711f59bde3dcc83d8f111c524Eric Laurent case MSG_LOAD_SOUND_EFFECTS: 38385d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent //FIXME: onLoadSoundEffects() should be executed in a separate thread as it 38395d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent // can take several dozens of milliseconds to complete 38405d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent boolean loaded = onLoadSoundEffects(); 38415d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent if (msg.obj != null) { 38425d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent LoadSoundEffectReply reply = (LoadSoundEffectReply)msg.obj; 38435d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent synchronized (reply) { 38445d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent reply.mStatus = loaded ? 0 : -1; 38455d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent reply.notify(); 38465d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent } 38475d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent } 3848117b7bb5b5a4457711f59bde3dcc83d8f111c524Eric Laurent break; 3849117b7bb5b5a4457711f59bde3dcc83d8f111c524Eric Laurent 38509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project case MSG_PLAY_SOUND_EFFECT: 38515d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent onPlaySoundEffect(msg.arg1, msg.arg2); 38529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project break; 38534c637b9e34f4c8db69a64ad21a4e2bcfa7485b5fJean-Michel Trivi 38544c637b9e34f4c8db69a64ad21a4e2bcfa7485b5fJean-Michel Trivi case MSG_BTA2DP_DOCK_TIMEOUT: 38554c637b9e34f4c8db69a64ad21a4e2bcfa7485b5fJean-Michel Trivi // msg.obj == address of BTA2DP device 38566bc7f2cd30b6bd90806942b0722e22daa2108493Eric Laurent synchronized (mConnectedDevices) { 38576bc7f2cd30b6bd90806942b0722e22daa2108493Eric Laurent makeA2dpDeviceUnavailableNow( (String) msg.obj ); 38586bc7f2cd30b6bd90806942b0722e22daa2108493Eric Laurent } 38594c637b9e34f4c8db69a64ad21a4e2bcfa7485b5fJean-Michel Trivi break; 3860fa640154f1f42121d81242b2f1a10f03e52f0014Eric Laurent 3861fa640154f1f42121d81242b2f1a10f03e52f0014Eric Laurent case MSG_SET_FORCE_USE: 3862c390bed06b4a572e273ead1254da9a932e04dce3Eric Laurent case MSG_SET_FORCE_BT_A2DP_USE: 3863fa640154f1f42121d81242b2f1a10f03e52f0014Eric Laurent setForceUse(msg.arg1, msg.arg2); 3864fa640154f1f42121d81242b2f1a10f03e52f0014Eric Laurent break; 3865d589fea865e90859324f00d21765fa7d7759e465Jean-Michel Trivi 3866dc03c61fe3cd8d0805480e48a974986439977a60Eric Laurent case MSG_BT_HEADSET_CNCT_FAILED: 3867dc03c61fe3cd8d0805480e48a974986439977a60Eric Laurent resetBluetoothSco(); 3868dc03c61fe3cd8d0805480e48a974986439977a60Eric Laurent break; 3869b1fbaaccb656ef09a8770c28df15e3e91a452e64Eric Laurent 3870b1fbaaccb656ef09a8770c28df15e3e91a452e64Eric Laurent case MSG_SET_WIRED_DEVICE_CONNECTION_STATE: 3871b1fbaaccb656ef09a8770c28df15e3e91a452e64Eric Laurent onSetWiredDeviceConnectionState(msg.arg1, msg.arg2, (String)msg.obj); 3872fa9a69805b001034aa04c3b33989a7ac21522371Jean-Michel Trivi mAudioEventWakeLock.release(); 3873b1fbaaccb656ef09a8770c28df15e3e91a452e64Eric Laurent break; 3874b1fbaaccb656ef09a8770c28df15e3e91a452e64Eric Laurent 38750a40ec2192e4836b2fcb6ba51a7688aa6bd4ee98Mike Lockwood case MSG_SET_A2DP_SRC_CONNECTION_STATE: 38760a40ec2192e4836b2fcb6ba51a7688aa6bd4ee98Mike Lockwood onSetA2dpSourceConnectionState((BluetoothDevice)msg.obj, msg.arg1); 38770a40ec2192e4836b2fcb6ba51a7688aa6bd4ee98Mike Lockwood mAudioEventWakeLock.release(); 38780a40ec2192e4836b2fcb6ba51a7688aa6bd4ee98Mike Lockwood break; 38790a40ec2192e4836b2fcb6ba51a7688aa6bd4ee98Mike Lockwood 38800a40ec2192e4836b2fcb6ba51a7688aa6bd4ee98Mike Lockwood case MSG_SET_A2DP_SINK_CONNECTION_STATE: 38810a40ec2192e4836b2fcb6ba51a7688aa6bd4ee98Mike Lockwood onSetA2dpSinkConnectionState((BluetoothDevice)msg.obj, msg.arg1); 3882fa9a69805b001034aa04c3b33989a7ac21522371Jean-Michel Trivi mAudioEventWakeLock.release(); 3883b1fbaaccb656ef09a8770c28df15e3e91a452e64Eric Laurent break; 3884632ca417f0a33e3fa9ccece531afa2db3f0d4a30Dianne Hackborn 3885632ca417f0a33e3fa9ccece531afa2db3f0d4a30Dianne Hackborn case MSG_REPORT_NEW_ROUTES: { 3886632ca417f0a33e3fa9ccece531afa2db3f0d4a30Dianne Hackborn int N = mRoutesObservers.beginBroadcast(); 3887632ca417f0a33e3fa9ccece531afa2db3f0d4a30Dianne Hackborn if (N > 0) { 3888632ca417f0a33e3fa9ccece531afa2db3f0d4a30Dianne Hackborn AudioRoutesInfo routes; 3889632ca417f0a33e3fa9ccece531afa2db3f0d4a30Dianne Hackborn synchronized (mCurAudioRoutes) { 3890632ca417f0a33e3fa9ccece531afa2db3f0d4a30Dianne Hackborn routes = new AudioRoutesInfo(mCurAudioRoutes); 3891632ca417f0a33e3fa9ccece531afa2db3f0d4a30Dianne Hackborn } 3892632ca417f0a33e3fa9ccece531afa2db3f0d4a30Dianne Hackborn while (N > 0) { 3893632ca417f0a33e3fa9ccece531afa2db3f0d4a30Dianne Hackborn N--; 3894632ca417f0a33e3fa9ccece531afa2db3f0d4a30Dianne Hackborn IAudioRoutesObserver obs = mRoutesObservers.getBroadcastItem(N); 3895632ca417f0a33e3fa9ccece531afa2db3f0d4a30Dianne Hackborn try { 3896632ca417f0a33e3fa9ccece531afa2db3f0d4a30Dianne Hackborn obs.dispatchAudioRoutesChanged(routes); 3897632ca417f0a33e3fa9ccece531afa2db3f0d4a30Dianne Hackborn } catch (RemoteException e) { 3898632ca417f0a33e3fa9ccece531afa2db3f0d4a30Dianne Hackborn } 3899632ca417f0a33e3fa9ccece531afa2db3f0d4a30Dianne Hackborn } 3900632ca417f0a33e3fa9ccece531afa2db3f0d4a30Dianne Hackborn } 3901632ca417f0a33e3fa9ccece531afa2db3f0d4a30Dianne Hackborn mRoutesObservers.finishBroadcast(); 3902632ca417f0a33e3fa9ccece531afa2db3f0d4a30Dianne Hackborn break; 3903632ca417f0a33e3fa9ccece531afa2db3f0d4a30Dianne Hackborn } 39043114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi 3905c34dcc1e1ebf152bb400abbb8bc25f7dc0c3ba97Eric Laurent case MSG_CHECK_MUSIC_ACTIVE: 3906c34dcc1e1ebf152bb400abbb8bc25f7dc0c3ba97Eric Laurent onCheckMusicActive(); 3907c34dcc1e1ebf152bb400abbb8bc25f7dc0c3ba97Eric Laurent break; 39085bfaeaef3fc348d66f48b86be08655e91dff910aEric Laurent 39095bfaeaef3fc348d66f48b86be08655e91dff910aEric Laurent case MSG_BROADCAST_AUDIO_BECOMING_NOISY: 39105bfaeaef3fc348d66f48b86be08655e91dff910aEric Laurent onSendBecomingNoisyIntent(); 39115bfaeaef3fc348d66f48b86be08655e91dff910aEric Laurent break; 3912d640bd325c3be9a350058c835b880a7e0b40dc60Eric Laurent 3913d640bd325c3be9a350058c835b880a7e0b40dc60Eric Laurent case MSG_CONFIGURE_SAFE_MEDIA_VOLUME_FORCED: 3914d640bd325c3be9a350058c835b880a7e0b40dc60Eric Laurent case MSG_CONFIGURE_SAFE_MEDIA_VOLUME: 3915d640bd325c3be9a350058c835b880a7e0b40dc60Eric Laurent onConfigureSafeVolume((msg.what == MSG_CONFIGURE_SAFE_MEDIA_VOLUME_FORCED)); 3916d640bd325c3be9a350058c835b880a7e0b40dc60Eric Laurent break; 391705274f348e12983eb8613cc6eb9ae561e8197e28Eric Laurent case MSG_PERSIST_SAFE_VOLUME_STATE: 391805274f348e12983eb8613cc6eb9ae561e8197e28Eric Laurent onPersistSafeVolumeState(msg.arg1); 391905274f348e12983eb8613cc6eb9ae561e8197e28Eric Laurent break; 3920a578c48e6c8677bcb54340aadb9470f8a275e56cJean-Michel Trivi 39212a57ca931fefe817b6110101289721acaacfc808Eric Laurent case MSG_BROADCAST_BT_CONNECTION_STATE: 39222a57ca931fefe817b6110101289721acaacfc808Eric Laurent onBroadcastScoConnectionState(msg.arg1); 39232a57ca931fefe817b6110101289721acaacfc808Eric Laurent break; 39244a5eeb9c727d77bb57fef87a70c8c9cc23dbfee3Eric Laurent 39254a5eeb9c727d77bb57fef87a70c8c9cc23dbfee3Eric Laurent case MSG_SYSTEM_READY: 39264a5eeb9c727d77bb57fef87a70c8c9cc23dbfee3Eric Laurent onSystemReady(); 39274a5eeb9c727d77bb57fef87a70c8c9cc23dbfee3Eric Laurent break; 39289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 39299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 39309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 39319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3932b109615ebebd6f3b9ae789412279f576c3ace46bJason Parekh private class SettingsObserver extends ContentObserver { 3933a553c25b33c99b345cf1c8688f8df0ed8df14e5aEric Laurent 3934b109615ebebd6f3b9ae789412279f576c3ace46bJason Parekh SettingsObserver() { 3935b109615ebebd6f3b9ae789412279f576c3ace46bJason Parekh super(new Handler()); 3936b109615ebebd6f3b9ae789412279f576c3ace46bJason Parekh mContentResolver.registerContentObserver(Settings.System.getUriFor( 3937b109615ebebd6f3b9ae789412279f576c3ace46bJason Parekh Settings.System.MODE_RINGER_STREAMS_AFFECTED), false, this); 39387ee1e4ff7346a278a6722108fbc1869240b3e866Eric Laurent mContentResolver.registerContentObserver(Settings.Global.getUriFor( 39397ee1e4ff7346a278a6722108fbc1869240b3e866Eric Laurent Settings.Global.DOCK_AUDIO_MEDIA_ENABLED), false, this); 3940b109615ebebd6f3b9ae789412279f576c3ace46bJason Parekh } 3941b109615ebebd6f3b9ae789412279f576c3ace46bJason Parekh 3942b109615ebebd6f3b9ae789412279f576c3ace46bJason Parekh @Override 3943b109615ebebd6f3b9ae789412279f576c3ace46bJason Parekh public void onChange(boolean selfChange) { 3944b109615ebebd6f3b9ae789412279f576c3ace46bJason Parekh super.onChange(selfChange); 3945ba195ebc76f23b6679443724ab58c9dc9f2df884Glenn Kasten // FIXME This synchronized is not necessary if mSettingsLock only protects mRingerMode. 3946ba195ebc76f23b6679443724ab58c9dc9f2df884Glenn Kasten // However there appear to be some missing locks around mRingerModeMutedStreams 3947ba195ebc76f23b6679443724ab58c9dc9f2df884Glenn Kasten // and mRingerModeAffectedStreams, so will leave this synchronized for now. 3948ba195ebc76f23b6679443724ab58c9dc9f2df884Glenn Kasten // mRingerModeMutedStreams and mMuteAffectedStreams are safe (only accessed once). 3949a553c25b33c99b345cf1c8688f8df0ed8df14e5aEric Laurent synchronized (mSettingsLock) { 395024e0d9b6c40712a297e4c287435a3b0fdd30e9daEric Laurent if (updateRingerModeAffectedStreams()) { 3951a553c25b33c99b345cf1c8688f8df0ed8df14e5aEric Laurent /* 3952a553c25b33c99b345cf1c8688f8df0ed8df14e5aEric Laurent * Ensure all stream types that should be affected by ringer mode 3953a553c25b33c99b345cf1c8688f8df0ed8df14e5aEric Laurent * are in the proper state. 3954a553c25b33c99b345cf1c8688f8df0ed8df14e5aEric Laurent */ 3955a553c25b33c99b345cf1c8688f8df0ed8df14e5aEric Laurent setRingerModeInt(getRingerMode(), false); 3956a553c25b33c99b345cf1c8688f8df0ed8df14e5aEric Laurent } 39577ee1e4ff7346a278a6722108fbc1869240b3e866Eric Laurent readDockAudioSettings(mContentResolver); 3958a553c25b33c99b345cf1c8688f8df0ed8df14e5aEric Laurent } 3959b109615ebebd6f3b9ae789412279f576c3ace46bJason Parekh } 3960b109615ebebd6f3b9ae789412279f576c3ace46bJason Parekh } 3961a553c25b33c99b345cf1c8688f8df0ed8df14e5aEric Laurent 39626bc7f2cd30b6bd90806942b0722e22daa2108493Eric Laurent // must be called synchronized on mConnectedDevices 39634c637b9e34f4c8db69a64ad21a4e2bcfa7485b5fJean-Michel Trivi private void makeA2dpDeviceAvailable(String address) { 39647847211fb4699bf6018e29d214a918ed6657319bEric Laurent // enable A2DP before notifying A2DP connection to avoid unecessary processing in 39657847211fb4699bf6018e29d214a918ed6657319bEric Laurent // audio policy manager 3966c9d1d5f35091226e96fcfa91817480f589eb36e2Matthew Xie VolumeStreamState streamState = mStreamStates[AudioSystem.STREAM_MUSIC]; 3967c9d1d5f35091226e96fcfa91817480f589eb36e2Matthew Xie sendMsg(mAudioHandler, MSG_SET_DEVICE_VOLUME, SENDMSG_QUEUE, 3968c9d1d5f35091226e96fcfa91817480f589eb36e2Matthew Xie AudioSystem.DEVICE_OUT_BLUETOOTH_A2DP, 0, streamState, 0); 39697847211fb4699bf6018e29d214a918ed6657319bEric Laurent setBluetoothA2dpOnInt(true); 39704c637b9e34f4c8db69a64ad21a4e2bcfa7485b5fJean-Michel Trivi AudioSystem.setDeviceConnectionState(AudioSystem.DEVICE_OUT_BLUETOOTH_A2DP, 39714c637b9e34f4c8db69a64ad21a4e2bcfa7485b5fJean-Michel Trivi AudioSystem.DEVICE_STATE_AVAILABLE, 39724c637b9e34f4c8db69a64ad21a4e2bcfa7485b5fJean-Michel Trivi address); 39734c637b9e34f4c8db69a64ad21a4e2bcfa7485b5fJean-Michel Trivi // Reset A2DP suspend state each time a new sink is connected 39744c637b9e34f4c8db69a64ad21a4e2bcfa7485b5fJean-Michel Trivi AudioSystem.setParameters("A2dpSuspended=false"); 39754c637b9e34f4c8db69a64ad21a4e2bcfa7485b5fJean-Michel Trivi mConnectedDevices.put( new Integer(AudioSystem.DEVICE_OUT_BLUETOOTH_A2DP), 39764c637b9e34f4c8db69a64ad21a4e2bcfa7485b5fJean-Michel Trivi address); 39774c637b9e34f4c8db69a64ad21a4e2bcfa7485b5fJean-Michel Trivi } 39784c637b9e34f4c8db69a64ad21a4e2bcfa7485b5fJean-Michel Trivi 39795bfaeaef3fc348d66f48b86be08655e91dff910aEric Laurent private void onSendBecomingNoisyIntent() { 39805ac72a29593ab9a20337a2225df52bdf4754be02Dianne Hackborn sendBroadcastToAll(new Intent(AudioManager.ACTION_AUDIO_BECOMING_NOISY)); 39819841818b9a0280abf59343c9e00a2976dbc084faMike Lockwood } 39829841818b9a0280abf59343c9e00a2976dbc084faMike Lockwood 39836bc7f2cd30b6bd90806942b0722e22daa2108493Eric Laurent // must be called synchronized on mConnectedDevices 39844c637b9e34f4c8db69a64ad21a4e2bcfa7485b5fJean-Michel Trivi private void makeA2dpDeviceUnavailableNow(String address) { 3985c9d1d5f35091226e96fcfa91817480f589eb36e2Matthew Xie synchronized (mA2dpAvrcpLock) { 3986c9d1d5f35091226e96fcfa91817480f589eb36e2Matthew Xie mAvrcpAbsVolSupported = false; 3987c9d1d5f35091226e96fcfa91817480f589eb36e2Matthew Xie } 39884c637b9e34f4c8db69a64ad21a4e2bcfa7485b5fJean-Michel Trivi AudioSystem.setDeviceConnectionState(AudioSystem.DEVICE_OUT_BLUETOOTH_A2DP, 39894c637b9e34f4c8db69a64ad21a4e2bcfa7485b5fJean-Michel Trivi AudioSystem.DEVICE_STATE_UNAVAILABLE, 39904c637b9e34f4c8db69a64ad21a4e2bcfa7485b5fJean-Michel Trivi address); 39914c637b9e34f4c8db69a64ad21a4e2bcfa7485b5fJean-Michel Trivi mConnectedDevices.remove(AudioSystem.DEVICE_OUT_BLUETOOTH_A2DP); 39924c637b9e34f4c8db69a64ad21a4e2bcfa7485b5fJean-Michel Trivi } 39934c637b9e34f4c8db69a64ad21a4e2bcfa7485b5fJean-Michel Trivi 39946bc7f2cd30b6bd90806942b0722e22daa2108493Eric Laurent // must be called synchronized on mConnectedDevices 39954c637b9e34f4c8db69a64ad21a4e2bcfa7485b5fJean-Michel Trivi private void makeA2dpDeviceUnavailableLater(String address) { 39963b5912602bec6ccbe8eef8a576730b1565f0067cEric Laurent // prevent any activity on the A2DP audio output to avoid unwanted 39973b5912602bec6ccbe8eef8a576730b1565f0067cEric Laurent // reconnection of the sink. 39983b5912602bec6ccbe8eef8a576730b1565f0067cEric Laurent AudioSystem.setParameters("A2dpSuspended=true"); 39994c637b9e34f4c8db69a64ad21a4e2bcfa7485b5fJean-Michel Trivi // the device will be made unavailable later, so consider it disconnected right away 40004c637b9e34f4c8db69a64ad21a4e2bcfa7485b5fJean-Michel Trivi mConnectedDevices.remove(AudioSystem.DEVICE_OUT_BLUETOOTH_A2DP); 40014c637b9e34f4c8db69a64ad21a4e2bcfa7485b5fJean-Michel Trivi // send the delayed message to make the device unavailable later 40024c637b9e34f4c8db69a64ad21a4e2bcfa7485b5fJean-Michel Trivi Message msg = mAudioHandler.obtainMessage(MSG_BTA2DP_DOCK_TIMEOUT, address); 40034c637b9e34f4c8db69a64ad21a4e2bcfa7485b5fJean-Michel Trivi mAudioHandler.sendMessageDelayed(msg, BTA2DP_DOCK_TIMEOUT_MILLIS); 40044c637b9e34f4c8db69a64ad21a4e2bcfa7485b5fJean-Michel Trivi 40054c637b9e34f4c8db69a64ad21a4e2bcfa7485b5fJean-Michel Trivi } 40064c637b9e34f4c8db69a64ad21a4e2bcfa7485b5fJean-Michel Trivi 40076bc7f2cd30b6bd90806942b0722e22daa2108493Eric Laurent // must be called synchronized on mConnectedDevices 40080a40ec2192e4836b2fcb6ba51a7688aa6bd4ee98Mike Lockwood private void makeA2dpSrcAvailable(String address) { 40090a40ec2192e4836b2fcb6ba51a7688aa6bd4ee98Mike Lockwood AudioSystem.setDeviceConnectionState(AudioSystem.DEVICE_IN_BLUETOOTH_A2DP, 40100a40ec2192e4836b2fcb6ba51a7688aa6bd4ee98Mike Lockwood AudioSystem.DEVICE_STATE_AVAILABLE, 40110a40ec2192e4836b2fcb6ba51a7688aa6bd4ee98Mike Lockwood address); 40120a40ec2192e4836b2fcb6ba51a7688aa6bd4ee98Mike Lockwood mConnectedDevices.put( new Integer(AudioSystem.DEVICE_IN_BLUETOOTH_A2DP), 40130a40ec2192e4836b2fcb6ba51a7688aa6bd4ee98Mike Lockwood address); 40140a40ec2192e4836b2fcb6ba51a7688aa6bd4ee98Mike Lockwood } 40150a40ec2192e4836b2fcb6ba51a7688aa6bd4ee98Mike Lockwood 40160a40ec2192e4836b2fcb6ba51a7688aa6bd4ee98Mike Lockwood // must be called synchronized on mConnectedDevices 40170a40ec2192e4836b2fcb6ba51a7688aa6bd4ee98Mike Lockwood private void makeA2dpSrcUnavailable(String address) { 40180a40ec2192e4836b2fcb6ba51a7688aa6bd4ee98Mike Lockwood AudioSystem.setDeviceConnectionState(AudioSystem.DEVICE_IN_BLUETOOTH_A2DP, 40190a40ec2192e4836b2fcb6ba51a7688aa6bd4ee98Mike Lockwood AudioSystem.DEVICE_STATE_UNAVAILABLE, 40200a40ec2192e4836b2fcb6ba51a7688aa6bd4ee98Mike Lockwood address); 40210a40ec2192e4836b2fcb6ba51a7688aa6bd4ee98Mike Lockwood mConnectedDevices.remove(AudioSystem.DEVICE_IN_BLUETOOTH_A2DP); 40220a40ec2192e4836b2fcb6ba51a7688aa6bd4ee98Mike Lockwood } 40230a40ec2192e4836b2fcb6ba51a7688aa6bd4ee98Mike Lockwood 40240a40ec2192e4836b2fcb6ba51a7688aa6bd4ee98Mike Lockwood // must be called synchronized on mConnectedDevices 4025a847ba4080675d395de725cfac5dfd9d5a993d4eJean-Michel Trivi private void cancelA2dpDeviceTimeout() { 40264c637b9e34f4c8db69a64ad21a4e2bcfa7485b5fJean-Michel Trivi mAudioHandler.removeMessages(MSG_BTA2DP_DOCK_TIMEOUT); 40274c637b9e34f4c8db69a64ad21a4e2bcfa7485b5fJean-Michel Trivi } 40284c637b9e34f4c8db69a64ad21a4e2bcfa7485b5fJean-Michel Trivi 40296bc7f2cd30b6bd90806942b0722e22daa2108493Eric Laurent // must be called synchronized on mConnectedDevices 4030a847ba4080675d395de725cfac5dfd9d5a993d4eJean-Michel Trivi private boolean hasScheduledA2dpDockTimeout() { 4031a847ba4080675d395de725cfac5dfd9d5a993d4eJean-Michel Trivi return mAudioHandler.hasMessages(MSG_BTA2DP_DOCK_TIMEOUT); 4032a847ba4080675d395de725cfac5dfd9d5a993d4eJean-Michel Trivi } 4033a847ba4080675d395de725cfac5dfd9d5a993d4eJean-Michel Trivi 40340a40ec2192e4836b2fcb6ba51a7688aa6bd4ee98Mike Lockwood private void onSetA2dpSinkConnectionState(BluetoothDevice btDevice, int state) 40356bc7f2cd30b6bd90806942b0722e22daa2108493Eric Laurent { 40360a40ec2192e4836b2fcb6ba51a7688aa6bd4ee98Mike Lockwood if (DEBUG_VOL) { 40370a40ec2192e4836b2fcb6ba51a7688aa6bd4ee98Mike Lockwood Log.d(TAG, "onSetA2dpSinkConnectionState btDevice="+btDevice+"state="+state); 40380a40ec2192e4836b2fcb6ba51a7688aa6bd4ee98Mike Lockwood } 40396bc7f2cd30b6bd90806942b0722e22daa2108493Eric Laurent if (btDevice == null) { 40406bc7f2cd30b6bd90806942b0722e22daa2108493Eric Laurent return; 40416bc7f2cd30b6bd90806942b0722e22daa2108493Eric Laurent } 40426bc7f2cd30b6bd90806942b0722e22daa2108493Eric Laurent String address = btDevice.getAddress(); 40436bc7f2cd30b6bd90806942b0722e22daa2108493Eric Laurent if (!BluetoothAdapter.checkBluetoothAddress(address)) { 40446bc7f2cd30b6bd90806942b0722e22daa2108493Eric Laurent address = ""; 40456bc7f2cd30b6bd90806942b0722e22daa2108493Eric Laurent } 40465a0cf7a27f3953a1266af48543ccd9024f4cd89fJohn Du 40476bc7f2cd30b6bd90806942b0722e22daa2108493Eric Laurent synchronized (mConnectedDevices) { 40486bc7f2cd30b6bd90806942b0722e22daa2108493Eric Laurent boolean isConnected = 40496bc7f2cd30b6bd90806942b0722e22daa2108493Eric Laurent (mConnectedDevices.containsKey(AudioSystem.DEVICE_OUT_BLUETOOTH_A2DP) && 40506bc7f2cd30b6bd90806942b0722e22daa2108493Eric Laurent mConnectedDevices.get(AudioSystem.DEVICE_OUT_BLUETOOTH_A2DP).equals(address)); 40516bc7f2cd30b6bd90806942b0722e22daa2108493Eric Laurent 40526bc7f2cd30b6bd90806942b0722e22daa2108493Eric Laurent if (isConnected && state != BluetoothProfile.STATE_CONNECTED) { 40536bc7f2cd30b6bd90806942b0722e22daa2108493Eric Laurent if (btDevice.isBluetoothDock()) { 40546bc7f2cd30b6bd90806942b0722e22daa2108493Eric Laurent if (state == BluetoothProfile.STATE_DISCONNECTED) { 40556bc7f2cd30b6bd90806942b0722e22daa2108493Eric Laurent // introduction of a delay for transient disconnections of docks when 40566bc7f2cd30b6bd90806942b0722e22daa2108493Eric Laurent // power is rapidly turned off/on, this message will be canceled if 40576bc7f2cd30b6bd90806942b0722e22daa2108493Eric Laurent // we reconnect the dock under a preset delay 40586bc7f2cd30b6bd90806942b0722e22daa2108493Eric Laurent makeA2dpDeviceUnavailableLater(address); 40596bc7f2cd30b6bd90806942b0722e22daa2108493Eric Laurent // the next time isConnected is evaluated, it will be false for the dock 40606bc7f2cd30b6bd90806942b0722e22daa2108493Eric Laurent } 40616bc7f2cd30b6bd90806942b0722e22daa2108493Eric Laurent } else { 40626bc7f2cd30b6bd90806942b0722e22daa2108493Eric Laurent makeA2dpDeviceUnavailableNow(address); 40636bc7f2cd30b6bd90806942b0722e22daa2108493Eric Laurent } 4064632ca417f0a33e3fa9ccece531afa2db3f0d4a30Dianne Hackborn synchronized (mCurAudioRoutes) { 4065632ca417f0a33e3fa9ccece531afa2db3f0d4a30Dianne Hackborn if (mCurAudioRoutes.mBluetoothName != null) { 4066632ca417f0a33e3fa9ccece531afa2db3f0d4a30Dianne Hackborn mCurAudioRoutes.mBluetoothName = null; 4067632ca417f0a33e3fa9ccece531afa2db3f0d4a30Dianne Hackborn sendMsg(mAudioHandler, MSG_REPORT_NEW_ROUTES, 4068632ca417f0a33e3fa9ccece531afa2db3f0d4a30Dianne Hackborn SENDMSG_NOOP, 0, 0, null, 0); 4069632ca417f0a33e3fa9ccece531afa2db3f0d4a30Dianne Hackborn } 4070632ca417f0a33e3fa9ccece531afa2db3f0d4a30Dianne Hackborn } 40716bc7f2cd30b6bd90806942b0722e22daa2108493Eric Laurent } else if (!isConnected && state == BluetoothProfile.STATE_CONNECTED) { 40726bc7f2cd30b6bd90806942b0722e22daa2108493Eric Laurent if (btDevice.isBluetoothDock()) { 40736bc7f2cd30b6bd90806942b0722e22daa2108493Eric Laurent // this could be a reconnection after a transient disconnection 40746bc7f2cd30b6bd90806942b0722e22daa2108493Eric Laurent cancelA2dpDeviceTimeout(); 40756bc7f2cd30b6bd90806942b0722e22daa2108493Eric Laurent mDockAddress = address; 40766bc7f2cd30b6bd90806942b0722e22daa2108493Eric Laurent } else { 40776bc7f2cd30b6bd90806942b0722e22daa2108493Eric Laurent // this could be a connection of another A2DP device before the timeout of 40786bc7f2cd30b6bd90806942b0722e22daa2108493Eric Laurent // a dock: cancel the dock timeout, and make the dock unavailable now 40796bc7f2cd30b6bd90806942b0722e22daa2108493Eric Laurent if(hasScheduledA2dpDockTimeout()) { 40806bc7f2cd30b6bd90806942b0722e22daa2108493Eric Laurent cancelA2dpDeviceTimeout(); 40816bc7f2cd30b6bd90806942b0722e22daa2108493Eric Laurent makeA2dpDeviceUnavailableNow(mDockAddress); 40826bc7f2cd30b6bd90806942b0722e22daa2108493Eric Laurent } 40836bc7f2cd30b6bd90806942b0722e22daa2108493Eric Laurent } 40846bc7f2cd30b6bd90806942b0722e22daa2108493Eric Laurent makeA2dpDeviceAvailable(address); 4085632ca417f0a33e3fa9ccece531afa2db3f0d4a30Dianne Hackborn synchronized (mCurAudioRoutes) { 4086632ca417f0a33e3fa9ccece531afa2db3f0d4a30Dianne Hackborn String name = btDevice.getAliasName(); 4087632ca417f0a33e3fa9ccece531afa2db3f0d4a30Dianne Hackborn if (!TextUtils.equals(mCurAudioRoutes.mBluetoothName, name)) { 4088632ca417f0a33e3fa9ccece531afa2db3f0d4a30Dianne Hackborn mCurAudioRoutes.mBluetoothName = name; 4089632ca417f0a33e3fa9ccece531afa2db3f0d4a30Dianne Hackborn sendMsg(mAudioHandler, MSG_REPORT_NEW_ROUTES, 4090632ca417f0a33e3fa9ccece531afa2db3f0d4a30Dianne Hackborn SENDMSG_NOOP, 0, 0, null, 0); 4091632ca417f0a33e3fa9ccece531afa2db3f0d4a30Dianne Hackborn } 4092632ca417f0a33e3fa9ccece531afa2db3f0d4a30Dianne Hackborn } 40936bc7f2cd30b6bd90806942b0722e22daa2108493Eric Laurent } 40946bc7f2cd30b6bd90806942b0722e22daa2108493Eric Laurent } 40956bc7f2cd30b6bd90806942b0722e22daa2108493Eric Laurent } 40966bc7f2cd30b6bd90806942b0722e22daa2108493Eric Laurent 40970a40ec2192e4836b2fcb6ba51a7688aa6bd4ee98Mike Lockwood private void onSetA2dpSourceConnectionState(BluetoothDevice btDevice, int state) 40980a40ec2192e4836b2fcb6ba51a7688aa6bd4ee98Mike Lockwood { 40990a40ec2192e4836b2fcb6ba51a7688aa6bd4ee98Mike Lockwood if (DEBUG_VOL) { 41000a40ec2192e4836b2fcb6ba51a7688aa6bd4ee98Mike Lockwood Log.d(TAG, "onSetA2dpSourceConnectionState btDevice="+btDevice+" state="+state); 41010a40ec2192e4836b2fcb6ba51a7688aa6bd4ee98Mike Lockwood } 41020a40ec2192e4836b2fcb6ba51a7688aa6bd4ee98Mike Lockwood if (btDevice == null) { 41030a40ec2192e4836b2fcb6ba51a7688aa6bd4ee98Mike Lockwood return; 41040a40ec2192e4836b2fcb6ba51a7688aa6bd4ee98Mike Lockwood } 41050a40ec2192e4836b2fcb6ba51a7688aa6bd4ee98Mike Lockwood String address = btDevice.getAddress(); 41060a40ec2192e4836b2fcb6ba51a7688aa6bd4ee98Mike Lockwood if (!BluetoothAdapter.checkBluetoothAddress(address)) { 41070a40ec2192e4836b2fcb6ba51a7688aa6bd4ee98Mike Lockwood address = ""; 41080a40ec2192e4836b2fcb6ba51a7688aa6bd4ee98Mike Lockwood } 41090a40ec2192e4836b2fcb6ba51a7688aa6bd4ee98Mike Lockwood 41100a40ec2192e4836b2fcb6ba51a7688aa6bd4ee98Mike Lockwood synchronized (mConnectedDevices) { 41110a40ec2192e4836b2fcb6ba51a7688aa6bd4ee98Mike Lockwood boolean isConnected = 41120a40ec2192e4836b2fcb6ba51a7688aa6bd4ee98Mike Lockwood (mConnectedDevices.containsKey(AudioSystem.DEVICE_IN_BLUETOOTH_A2DP) && 41130a40ec2192e4836b2fcb6ba51a7688aa6bd4ee98Mike Lockwood mConnectedDevices.get(AudioSystem.DEVICE_IN_BLUETOOTH_A2DP).equals(address)); 41140a40ec2192e4836b2fcb6ba51a7688aa6bd4ee98Mike Lockwood 41150a40ec2192e4836b2fcb6ba51a7688aa6bd4ee98Mike Lockwood if (isConnected && state != BluetoothProfile.STATE_CONNECTED) { 41160a40ec2192e4836b2fcb6ba51a7688aa6bd4ee98Mike Lockwood makeA2dpSrcUnavailable(address); 41170a40ec2192e4836b2fcb6ba51a7688aa6bd4ee98Mike Lockwood } else if (!isConnected && state == BluetoothProfile.STATE_CONNECTED) { 41180a40ec2192e4836b2fcb6ba51a7688aa6bd4ee98Mike Lockwood makeA2dpSrcAvailable(address); 41190a40ec2192e4836b2fcb6ba51a7688aa6bd4ee98Mike Lockwood } 41200a40ec2192e4836b2fcb6ba51a7688aa6bd4ee98Mike Lockwood } 41210a40ec2192e4836b2fcb6ba51a7688aa6bd4ee98Mike Lockwood } 41220a40ec2192e4836b2fcb6ba51a7688aa6bd4ee98Mike Lockwood 41235a0cf7a27f3953a1266af48543ccd9024f4cd89fJohn Du public void avrcpSupportsAbsoluteVolume(String address, boolean support) { 41245a0cf7a27f3953a1266af48543ccd9024f4cd89fJohn Du // address is not used for now, but may be used when multiple a2dp devices are supported 41255a0cf7a27f3953a1266af48543ccd9024f4cd89fJohn Du synchronized (mA2dpAvrcpLock) { 41265a0cf7a27f3953a1266af48543ccd9024f4cd89fJohn Du mAvrcpAbsVolSupported = support; 4127c9d1d5f35091226e96fcfa91817480f589eb36e2Matthew Xie sendMsg(mAudioHandler, MSG_SET_DEVICE_VOLUME, SENDMSG_QUEUE, 4128cd772d04345850e160a45613fcf6b86da0dce4cfEric Laurent AudioSystem.DEVICE_OUT_BLUETOOTH_A2DP, 0, 4129cd772d04345850e160a45613fcf6b86da0dce4cfEric Laurent mStreamStates[AudioSystem.STREAM_MUSIC], 0); 4130cd772d04345850e160a45613fcf6b86da0dce4cfEric Laurent sendMsg(mAudioHandler, MSG_SET_DEVICE_VOLUME, SENDMSG_QUEUE, 4131cd772d04345850e160a45613fcf6b86da0dce4cfEric Laurent AudioSystem.DEVICE_OUT_BLUETOOTH_A2DP, 0, 4132cd772d04345850e160a45613fcf6b86da0dce4cfEric Laurent mStreamStates[AudioSystem.STREAM_RING], 0); 41335a0cf7a27f3953a1266af48543ccd9024f4cd89fJohn Du } 41345a0cf7a27f3953a1266af48543ccd9024f4cd89fJohn Du } 41355a0cf7a27f3953a1266af48543ccd9024f4cd89fJohn Du 413659f482764e346a5c5ac118ee1f7b24da645c2559Eric Laurent private boolean handleDeviceConnection(boolean connected, int device, String params) { 413759f482764e346a5c5ac118ee1f7b24da645c2559Eric Laurent synchronized (mConnectedDevices) { 413859f482764e346a5c5ac118ee1f7b24da645c2559Eric Laurent boolean isConnected = (mConnectedDevices.containsKey(device) && 41399841818b9a0280abf59343c9e00a2976dbc084faMike Lockwood (params.isEmpty() || mConnectedDevices.get(device).equals(params))); 414059f482764e346a5c5ac118ee1f7b24da645c2559Eric Laurent 414159f482764e346a5c5ac118ee1f7b24da645c2559Eric Laurent if (isConnected && !connected) { 414259f482764e346a5c5ac118ee1f7b24da645c2559Eric Laurent AudioSystem.setDeviceConnectionState(device, 414359f482764e346a5c5ac118ee1f7b24da645c2559Eric Laurent AudioSystem.DEVICE_STATE_UNAVAILABLE, 41449841818b9a0280abf59343c9e00a2976dbc084faMike Lockwood mConnectedDevices.get(device)); 414559f482764e346a5c5ac118ee1f7b24da645c2559Eric Laurent mConnectedDevices.remove(device); 414659f482764e346a5c5ac118ee1f7b24da645c2559Eric Laurent return true; 414759f482764e346a5c5ac118ee1f7b24da645c2559Eric Laurent } else if (!isConnected && connected) { 414859f482764e346a5c5ac118ee1f7b24da645c2559Eric Laurent AudioSystem.setDeviceConnectionState(device, 414959f482764e346a5c5ac118ee1f7b24da645c2559Eric Laurent AudioSystem.DEVICE_STATE_AVAILABLE, 415059f482764e346a5c5ac118ee1f7b24da645c2559Eric Laurent params); 415159f482764e346a5c5ac118ee1f7b24da645c2559Eric Laurent mConnectedDevices.put(new Integer(device), params); 415259f482764e346a5c5ac118ee1f7b24da645c2559Eric Laurent return true; 415359f482764e346a5c5ac118ee1f7b24da645c2559Eric Laurent } 415459f482764e346a5c5ac118ee1f7b24da645c2559Eric Laurent } 415559f482764e346a5c5ac118ee1f7b24da645c2559Eric Laurent return false; 415659f482764e346a5c5ac118ee1f7b24da645c2559Eric Laurent } 415759f482764e346a5c5ac118ee1f7b24da645c2559Eric Laurent 4158b1fbaaccb656ef09a8770c28df15e3e91a452e64Eric Laurent // Devices which removal triggers intent ACTION_AUDIO_BECOMING_NOISY. The intent is only 4159b1fbaaccb656ef09a8770c28df15e3e91a452e64Eric Laurent // sent if none of these devices is connected. 4160b1fbaaccb656ef09a8770c28df15e3e91a452e64Eric Laurent int mBecomingNoisyIntentDevices = 4161b1fbaaccb656ef09a8770c28df15e3e91a452e64Eric Laurent AudioSystem.DEVICE_OUT_WIRED_HEADSET | AudioSystem.DEVICE_OUT_WIRED_HEADPHONE | 4162948d32748caaac5be06c991ebf00f74265a7849fEric Laurent AudioSystem.DEVICE_OUT_ALL_A2DP | AudioSystem.DEVICE_OUT_HDMI | 4163794da7a0543cbecffefb73794aa68d1a93e41adfEric Laurent AudioSystem.DEVICE_OUT_ANLG_DOCK_HEADSET | AudioSystem.DEVICE_OUT_DGTL_DOCK_HEADSET | 4164794da7a0543cbecffefb73794aa68d1a93e41adfEric Laurent AudioSystem.DEVICE_OUT_ALL_USB; 4165b1fbaaccb656ef09a8770c28df15e3e91a452e64Eric Laurent 4166b1fbaaccb656ef09a8770c28df15e3e91a452e64Eric Laurent // must be called before removing the device from mConnectedDevices 4167b1fbaaccb656ef09a8770c28df15e3e91a452e64Eric Laurent private int checkSendBecomingNoisyIntent(int device, int state) { 4168b1fbaaccb656ef09a8770c28df15e3e91a452e64Eric Laurent int delay = 0; 4169b1fbaaccb656ef09a8770c28df15e3e91a452e64Eric Laurent if ((state == 0) && ((device & mBecomingNoisyIntentDevices) != 0)) { 4170b1fbaaccb656ef09a8770c28df15e3e91a452e64Eric Laurent int devices = 0; 4171b1fbaaccb656ef09a8770c28df15e3e91a452e64Eric Laurent for (int dev : mConnectedDevices.keySet()) { 4172b1fbaaccb656ef09a8770c28df15e3e91a452e64Eric Laurent if ((dev & mBecomingNoisyIntentDevices) != 0) { 4173b1fbaaccb656ef09a8770c28df15e3e91a452e64Eric Laurent devices |= dev; 4174b1fbaaccb656ef09a8770c28df15e3e91a452e64Eric Laurent } 4175b1fbaaccb656ef09a8770c28df15e3e91a452e64Eric Laurent } 4176b1fbaaccb656ef09a8770c28df15e3e91a452e64Eric Laurent if (devices == device) { 41775bfaeaef3fc348d66f48b86be08655e91dff910aEric Laurent sendMsg(mAudioHandler, 41785bfaeaef3fc348d66f48b86be08655e91dff910aEric Laurent MSG_BROADCAST_AUDIO_BECOMING_NOISY, 41795bfaeaef3fc348d66f48b86be08655e91dff910aEric Laurent SENDMSG_REPLACE, 41805bfaeaef3fc348d66f48b86be08655e91dff910aEric Laurent 0, 41815bfaeaef3fc348d66f48b86be08655e91dff910aEric Laurent 0, 41825bfaeaef3fc348d66f48b86be08655e91dff910aEric Laurent null, 41835bfaeaef3fc348d66f48b86be08655e91dff910aEric Laurent 0); 4184b1fbaaccb656ef09a8770c28df15e3e91a452e64Eric Laurent delay = 1000; 4185b1fbaaccb656ef09a8770c28df15e3e91a452e64Eric Laurent } 4186b1fbaaccb656ef09a8770c28df15e3e91a452e64Eric Laurent } 4187b1fbaaccb656ef09a8770c28df15e3e91a452e64Eric Laurent 41880a40ec2192e4836b2fcb6ba51a7688aa6bd4ee98Mike Lockwood if (mAudioHandler.hasMessages(MSG_SET_A2DP_SRC_CONNECTION_STATE) || 41890a40ec2192e4836b2fcb6ba51a7688aa6bd4ee98Mike Lockwood mAudioHandler.hasMessages(MSG_SET_A2DP_SINK_CONNECTION_STATE) || 4190b1fbaaccb656ef09a8770c28df15e3e91a452e64Eric Laurent mAudioHandler.hasMessages(MSG_SET_WIRED_DEVICE_CONNECTION_STATE)) { 4191b1fbaaccb656ef09a8770c28df15e3e91a452e64Eric Laurent delay = 1000; 4192b1fbaaccb656ef09a8770c28df15e3e91a452e64Eric Laurent } 4193b1fbaaccb656ef09a8770c28df15e3e91a452e64Eric Laurent return delay; 4194b1fbaaccb656ef09a8770c28df15e3e91a452e64Eric Laurent } 4195b1fbaaccb656ef09a8770c28df15e3e91a452e64Eric Laurent 4196b1fbaaccb656ef09a8770c28df15e3e91a452e64Eric Laurent private void sendDeviceConnectionIntent(int device, int state, String name) 4197b1fbaaccb656ef09a8770c28df15e3e91a452e64Eric Laurent { 4198b1fbaaccb656ef09a8770c28df15e3e91a452e64Eric Laurent Intent intent = new Intent(); 4199b1fbaaccb656ef09a8770c28df15e3e91a452e64Eric Laurent 4200b1fbaaccb656ef09a8770c28df15e3e91a452e64Eric Laurent intent.putExtra("state", state); 4201b1fbaaccb656ef09a8770c28df15e3e91a452e64Eric Laurent intent.putExtra("name", name); 4202b1fbaaccb656ef09a8770c28df15e3e91a452e64Eric Laurent intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY); 4203b1fbaaccb656ef09a8770c28df15e3e91a452e64Eric Laurent 4204632ca417f0a33e3fa9ccece531afa2db3f0d4a30Dianne Hackborn int connType = 0; 4205632ca417f0a33e3fa9ccece531afa2db3f0d4a30Dianne Hackborn 4206b1fbaaccb656ef09a8770c28df15e3e91a452e64Eric Laurent if (device == AudioSystem.DEVICE_OUT_WIRED_HEADSET) { 4207632ca417f0a33e3fa9ccece531afa2db3f0d4a30Dianne Hackborn connType = AudioRoutesInfo.MAIN_HEADSET; 4208b1fbaaccb656ef09a8770c28df15e3e91a452e64Eric Laurent intent.setAction(Intent.ACTION_HEADSET_PLUG); 4209b1fbaaccb656ef09a8770c28df15e3e91a452e64Eric Laurent intent.putExtra("microphone", 1); 4210b1fbaaccb656ef09a8770c28df15e3e91a452e64Eric Laurent } else if (device == AudioSystem.DEVICE_OUT_WIRED_HEADPHONE) { 4211632ca417f0a33e3fa9ccece531afa2db3f0d4a30Dianne Hackborn connType = AudioRoutesInfo.MAIN_HEADPHONES; 4212b1fbaaccb656ef09a8770c28df15e3e91a452e64Eric Laurent intent.setAction(Intent.ACTION_HEADSET_PLUG); 4213b1fbaaccb656ef09a8770c28df15e3e91a452e64Eric Laurent intent.putExtra("microphone", 0); 4214b1fbaaccb656ef09a8770c28df15e3e91a452e64Eric Laurent } else if (device == AudioSystem.DEVICE_OUT_ANLG_DOCK_HEADSET) { 4215632ca417f0a33e3fa9ccece531afa2db3f0d4a30Dianne Hackborn connType = AudioRoutesInfo.MAIN_DOCK_SPEAKERS; 4216b1fbaaccb656ef09a8770c28df15e3e91a452e64Eric Laurent intent.setAction(Intent.ACTION_ANALOG_AUDIO_DOCK_PLUG); 4217b1fbaaccb656ef09a8770c28df15e3e91a452e64Eric Laurent } else if (device == AudioSystem.DEVICE_OUT_DGTL_DOCK_HEADSET) { 4218632ca417f0a33e3fa9ccece531afa2db3f0d4a30Dianne Hackborn connType = AudioRoutesInfo.MAIN_DOCK_SPEAKERS; 4219b1fbaaccb656ef09a8770c28df15e3e91a452e64Eric Laurent intent.setAction(Intent.ACTION_DIGITAL_AUDIO_DOCK_PLUG); 4220948d32748caaac5be06c991ebf00f74265a7849fEric Laurent } else if (device == AudioSystem.DEVICE_OUT_HDMI) { 4221632ca417f0a33e3fa9ccece531afa2db3f0d4a30Dianne Hackborn connType = AudioRoutesInfo.MAIN_HDMI; 4222b1fbaaccb656ef09a8770c28df15e3e91a452e64Eric Laurent intent.setAction(Intent.ACTION_HDMI_AUDIO_PLUG); 4223b1fbaaccb656ef09a8770c28df15e3e91a452e64Eric Laurent } 4224b1fbaaccb656ef09a8770c28df15e3e91a452e64Eric Laurent 4225632ca417f0a33e3fa9ccece531afa2db3f0d4a30Dianne Hackborn synchronized (mCurAudioRoutes) { 4226632ca417f0a33e3fa9ccece531afa2db3f0d4a30Dianne Hackborn if (connType != 0) { 4227632ca417f0a33e3fa9ccece531afa2db3f0d4a30Dianne Hackborn int newConn = mCurAudioRoutes.mMainType; 4228632ca417f0a33e3fa9ccece531afa2db3f0d4a30Dianne Hackborn if (state != 0) { 4229632ca417f0a33e3fa9ccece531afa2db3f0d4a30Dianne Hackborn newConn |= connType; 4230632ca417f0a33e3fa9ccece531afa2db3f0d4a30Dianne Hackborn } else { 4231632ca417f0a33e3fa9ccece531afa2db3f0d4a30Dianne Hackborn newConn &= ~connType; 4232632ca417f0a33e3fa9ccece531afa2db3f0d4a30Dianne Hackborn } 4233632ca417f0a33e3fa9ccece531afa2db3f0d4a30Dianne Hackborn if (newConn != mCurAudioRoutes.mMainType) { 4234632ca417f0a33e3fa9ccece531afa2db3f0d4a30Dianne Hackborn mCurAudioRoutes.mMainType = newConn; 4235632ca417f0a33e3fa9ccece531afa2db3f0d4a30Dianne Hackborn sendMsg(mAudioHandler, MSG_REPORT_NEW_ROUTES, 4236632ca417f0a33e3fa9ccece531afa2db3f0d4a30Dianne Hackborn SENDMSG_NOOP, 0, 0, null, 0); 4237632ca417f0a33e3fa9ccece531afa2db3f0d4a30Dianne Hackborn } 4238632ca417f0a33e3fa9ccece531afa2db3f0d4a30Dianne Hackborn } 4239632ca417f0a33e3fa9ccece531afa2db3f0d4a30Dianne Hackborn } 4240632ca417f0a33e3fa9ccece531afa2db3f0d4a30Dianne Hackborn 42415ac72a29593ab9a20337a2225df52bdf4754be02Dianne Hackborn final long ident = Binder.clearCallingIdentity(); 42425ac72a29593ab9a20337a2225df52bdf4754be02Dianne Hackborn try { 42435ac72a29593ab9a20337a2225df52bdf4754be02Dianne Hackborn ActivityManagerNative.broadcastStickyIntent(intent, null, UserHandle.USER_ALL); 42445ac72a29593ab9a20337a2225df52bdf4754be02Dianne Hackborn } finally { 42455ac72a29593ab9a20337a2225df52bdf4754be02Dianne Hackborn Binder.restoreCallingIdentity(ident); 42465ac72a29593ab9a20337a2225df52bdf4754be02Dianne Hackborn } 4247b1fbaaccb656ef09a8770c28df15e3e91a452e64Eric Laurent } 4248b1fbaaccb656ef09a8770c28df15e3e91a452e64Eric Laurent 4249b1fbaaccb656ef09a8770c28df15e3e91a452e64Eric Laurent private void onSetWiredDeviceConnectionState(int device, int state, String name) 4250b1fbaaccb656ef09a8770c28df15e3e91a452e64Eric Laurent { 4251b1fbaaccb656ef09a8770c28df15e3e91a452e64Eric Laurent synchronized (mConnectedDevices) { 4252b1fbaaccb656ef09a8770c28df15e3e91a452e64Eric Laurent if ((state == 0) && ((device == AudioSystem.DEVICE_OUT_WIRED_HEADSET) || 4253b1fbaaccb656ef09a8770c28df15e3e91a452e64Eric Laurent (device == AudioSystem.DEVICE_OUT_WIRED_HEADPHONE))) { 4254b1fbaaccb656ef09a8770c28df15e3e91a452e64Eric Laurent setBluetoothA2dpOnInt(true); 4255b1fbaaccb656ef09a8770c28df15e3e91a452e64Eric Laurent } 4256ae4506e9b5fc3e0c6d9862fbc05b9af7d6742a6eEric Laurent boolean isUsb = ((device & ~AudioSystem.DEVICE_OUT_ALL_USB) == 0) || 4257ae4506e9b5fc3e0c6d9862fbc05b9af7d6742a6eEric Laurent (((device & AudioSystem.DEVICE_BIT_IN) != 0) && 4258ae4506e9b5fc3e0c6d9862fbc05b9af7d6742a6eEric Laurent ((device & ~AudioSystem.DEVICE_IN_ALL_USB) == 0)); 4259db45484e4b5858d14da93d3a06311b93bf0cf320Mike Lockwood handleDeviceConnection((state == 1), device, (isUsb ? name : "")); 4260f1a457d06c53a901ea08d2d3fb6e766bc06c4d4fEric Laurent if (state != 0) { 4261f1a457d06c53a901ea08d2d3fb6e766bc06c4d4fEric Laurent if ((device == AudioSystem.DEVICE_OUT_WIRED_HEADSET) || 4262f1a457d06c53a901ea08d2d3fb6e766bc06c4d4fEric Laurent (device == AudioSystem.DEVICE_OUT_WIRED_HEADPHONE)) { 4263f1a457d06c53a901ea08d2d3fb6e766bc06c4d4fEric Laurent setBluetoothA2dpOnInt(false); 4264f1a457d06c53a901ea08d2d3fb6e766bc06c4d4fEric Laurent } 4265f1a457d06c53a901ea08d2d3fb6e766bc06c4d4fEric Laurent if ((device & mSafeMediaVolumeDevices) != 0) { 4266f1a457d06c53a901ea08d2d3fb6e766bc06c4d4fEric Laurent sendMsg(mAudioHandler, 4267f1a457d06c53a901ea08d2d3fb6e766bc06c4d4fEric Laurent MSG_CHECK_MUSIC_ACTIVE, 4268f1a457d06c53a901ea08d2d3fb6e766bc06c4d4fEric Laurent SENDMSG_REPLACE, 4269f1a457d06c53a901ea08d2d3fb6e766bc06c4d4fEric Laurent 0, 4270f1a457d06c53a901ea08d2d3fb6e766bc06c4d4fEric Laurent 0, 4271f1a457d06c53a901ea08d2d3fb6e766bc06c4d4fEric Laurent null, 4272f1a457d06c53a901ea08d2d3fb6e766bc06c4d4fEric Laurent MUSIC_ACTIVE_POLL_PERIOD_MS); 4273f1a457d06c53a901ea08d2d3fb6e766bc06c4d4fEric Laurent } 4274b1fbaaccb656ef09a8770c28df15e3e91a452e64Eric Laurent } 4275ae4506e9b5fc3e0c6d9862fbc05b9af7d6742a6eEric Laurent if (!isUsb && (device != AudioSystem.DEVICE_IN_WIRED_HEADSET)) { 4276db45484e4b5858d14da93d3a06311b93bf0cf320Mike Lockwood sendDeviceConnectionIntent(device, state, name); 4277db45484e4b5858d14da93d3a06311b93bf0cf320Mike Lockwood } 4278b1fbaaccb656ef09a8770c28df15e3e91a452e64Eric Laurent } 4279b1fbaaccb656ef09a8770c28df15e3e91a452e64Eric Laurent } 4280b1fbaaccb656ef09a8770c28df15e3e91a452e64Eric Laurent 4281a847ba4080675d395de725cfac5dfd9d5a993d4eJean-Michel Trivi /* cache of the address of the last dock the device was connected to */ 4282a847ba4080675d395de725cfac5dfd9d5a993d4eJean-Michel Trivi private String mDockAddress; 4283a847ba4080675d395de725cfac5dfd9d5a993d4eJean-Michel Trivi 4284a553c25b33c99b345cf1c8688f8df0ed8df14e5aEric Laurent /** 4285a553c25b33c99b345cf1c8688f8df0ed8df14e5aEric Laurent * Receiver for misc intent broadcasts the Phone app cares about. 4286a553c25b33c99b345cf1c8688f8df0ed8df14e5aEric Laurent */ 4287a553c25b33c99b345cf1c8688f8df0ed8df14e5aEric Laurent private class AudioServiceBroadcastReceiver extends BroadcastReceiver { 4288a553c25b33c99b345cf1c8688f8df0ed8df14e5aEric Laurent @Override 4289a553c25b33c99b345cf1c8688f8df0ed8df14e5aEric Laurent public void onReceive(Context context, Intent intent) { 4290a553c25b33c99b345cf1c8688f8df0ed8df14e5aEric Laurent String action = intent.getAction(); 4291ae4506e9b5fc3e0c6d9862fbc05b9af7d6742a6eEric Laurent int outDevice; 4292ae4506e9b5fc3e0c6d9862fbc05b9af7d6742a6eEric Laurent int inDevice; 429359f482764e346a5c5ac118ee1f7b24da645c2559Eric Laurent int state; 4294a553c25b33c99b345cf1c8688f8df0ed8df14e5aEric Laurent 4295758559e6b7e310cf46cc269437f44decd58d68d6Jean-Michel Trivi if (action.equals(Intent.ACTION_DOCK_EVENT)) { 4296758559e6b7e310cf46cc269437f44decd58d68d6Jean-Michel Trivi int dockState = intent.getIntExtra(Intent.EXTRA_DOCK_STATE, 4297758559e6b7e310cf46cc269437f44decd58d68d6Jean-Michel Trivi Intent.EXTRA_DOCK_STATE_UNDOCKED); 4298758559e6b7e310cf46cc269437f44decd58d68d6Jean-Michel Trivi int config; 4299758559e6b7e310cf46cc269437f44decd58d68d6Jean-Michel Trivi switch (dockState) { 4300758559e6b7e310cf46cc269437f44decd58d68d6Jean-Michel Trivi case Intent.EXTRA_DOCK_STATE_DESK: 4301758559e6b7e310cf46cc269437f44decd58d68d6Jean-Michel Trivi config = AudioSystem.FORCE_BT_DESK_DOCK; 4302758559e6b7e310cf46cc269437f44decd58d68d6Jean-Michel Trivi break; 4303758559e6b7e310cf46cc269437f44decd58d68d6Jean-Michel Trivi case Intent.EXTRA_DOCK_STATE_CAR: 4304758559e6b7e310cf46cc269437f44decd58d68d6Jean-Michel Trivi config = AudioSystem.FORCE_BT_CAR_DOCK; 4305758559e6b7e310cf46cc269437f44decd58d68d6Jean-Michel Trivi break; 430621e941bf43362ddc6639a9f2d0828053360f53d7Praveen Bharathi case Intent.EXTRA_DOCK_STATE_LE_DESK: 430708ed1b9d2099ec8231b21353b33b901492ea9885Eric Laurent config = AudioSystem.FORCE_ANALOG_DOCK; 430821e941bf43362ddc6639a9f2d0828053360f53d7Praveen Bharathi break; 430921e941bf43362ddc6639a9f2d0828053360f53d7Praveen Bharathi case Intent.EXTRA_DOCK_STATE_HE_DESK: 431021e941bf43362ddc6639a9f2d0828053360f53d7Praveen Bharathi config = AudioSystem.FORCE_DIGITAL_DOCK; 431121e941bf43362ddc6639a9f2d0828053360f53d7Praveen Bharathi break; 4312758559e6b7e310cf46cc269437f44decd58d68d6Jean-Michel Trivi case Intent.EXTRA_DOCK_STATE_UNDOCKED: 4313758559e6b7e310cf46cc269437f44decd58d68d6Jean-Michel Trivi default: 4314758559e6b7e310cf46cc269437f44decd58d68d6Jean-Michel Trivi config = AudioSystem.FORCE_NONE; 4315758559e6b7e310cf46cc269437f44decd58d68d6Jean-Michel Trivi } 431608ed1b9d2099ec8231b21353b33b901492ea9885Eric Laurent // Low end docks have a menu to enable or disable audio 431708ed1b9d2099ec8231b21353b33b901492ea9885Eric Laurent // (see mDockAudioMediaEnabled) 431808ed1b9d2099ec8231b21353b33b901492ea9885Eric Laurent if (!((dockState == Intent.EXTRA_DOCK_STATE_LE_DESK) || 431908ed1b9d2099ec8231b21353b33b901492ea9885Eric Laurent ((dockState == Intent.EXTRA_DOCK_STATE_UNDOCKED) && 432008ed1b9d2099ec8231b21353b33b901492ea9885Eric Laurent (mDockState == Intent.EXTRA_DOCK_STATE_LE_DESK)))) { 432108ed1b9d2099ec8231b21353b33b901492ea9885Eric Laurent AudioSystem.setForceUse(AudioSystem.FOR_DOCK, config); 432208ed1b9d2099ec8231b21353b33b901492ea9885Eric Laurent } 432308ed1b9d2099ec8231b21353b33b901492ea9885Eric Laurent mDockState = dockState; 432482aa7f017daaaeb96c13e6e3491d5037ab471085Jaikumar Ganesh } else if (action.equals(BluetoothHeadset.ACTION_CONNECTION_STATE_CHANGED)) { 432559f482764e346a5c5ac118ee1f7b24da645c2559Eric Laurent state = intent.getIntExtra(BluetoothProfile.EXTRA_STATE, 432682aa7f017daaaeb96c13e6e3491d5037ab471085Jaikumar Ganesh BluetoothProfile.STATE_DISCONNECTED); 4327ae4506e9b5fc3e0c6d9862fbc05b9af7d6742a6eEric Laurent outDevice = AudioSystem.DEVICE_OUT_BLUETOOTH_SCO; 4328ae4506e9b5fc3e0c6d9862fbc05b9af7d6742a6eEric Laurent inDevice = AudioSystem.DEVICE_IN_BLUETOOTH_SCO_HEADSET; 4329a56d1c72190462aa9e377906583eceb58e0efcddNick Pelly String address = null; 4330dca56b9432e2cc851d1a58920071fed2e1e3d142Eric Laurent 4331dca56b9432e2cc851d1a58920071fed2e1e3d142Eric Laurent BluetoothDevice btDevice = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE); 4332dca56b9432e2cc851d1a58920071fed2e1e3d142Eric Laurent if (btDevice == null) { 4333dca56b9432e2cc851d1a58920071fed2e1e3d142Eric Laurent return; 4334dca56b9432e2cc851d1a58920071fed2e1e3d142Eric Laurent } 4335dca56b9432e2cc851d1a58920071fed2e1e3d142Eric Laurent 4336dca56b9432e2cc851d1a58920071fed2e1e3d142Eric Laurent address = btDevice.getAddress(); 4337dca56b9432e2cc851d1a58920071fed2e1e3d142Eric Laurent BluetoothClass btClass = btDevice.getBluetoothClass(); 4338dca56b9432e2cc851d1a58920071fed2e1e3d142Eric Laurent if (btClass != null) { 4339dca56b9432e2cc851d1a58920071fed2e1e3d142Eric Laurent switch (btClass.getDeviceClass()) { 4340dca56b9432e2cc851d1a58920071fed2e1e3d142Eric Laurent case BluetoothClass.Device.AUDIO_VIDEO_WEARABLE_HEADSET: 4341dca56b9432e2cc851d1a58920071fed2e1e3d142Eric Laurent case BluetoothClass.Device.AUDIO_VIDEO_HANDSFREE: 4342ae4506e9b5fc3e0c6d9862fbc05b9af7d6742a6eEric Laurent outDevice = AudioSystem.DEVICE_OUT_BLUETOOTH_SCO_HEADSET; 4343dca56b9432e2cc851d1a58920071fed2e1e3d142Eric Laurent break; 4344dca56b9432e2cc851d1a58920071fed2e1e3d142Eric Laurent case BluetoothClass.Device.AUDIO_VIDEO_CAR_AUDIO: 4345ae4506e9b5fc3e0c6d9862fbc05b9af7d6742a6eEric Laurent outDevice = AudioSystem.DEVICE_OUT_BLUETOOTH_SCO_CARKIT; 4346dca56b9432e2cc851d1a58920071fed2e1e3d142Eric Laurent break; 4347d5603c126acdd94d9f7400bb1d04188020a425b4Eric Laurent } 4348d5603c126acdd94d9f7400bb1d04188020a425b4Eric Laurent } 4349d5603c126acdd94d9f7400bb1d04188020a425b4Eric Laurent 4350dca56b9432e2cc851d1a58920071fed2e1e3d142Eric Laurent if (!BluetoothAdapter.checkBluetoothAddress(address)) { 4351dca56b9432e2cc851d1a58920071fed2e1e3d142Eric Laurent address = ""; 4352dca56b9432e2cc851d1a58920071fed2e1e3d142Eric Laurent } 4353d5603c126acdd94d9f7400bb1d04188020a425b4Eric Laurent 435459f482764e346a5c5ac118ee1f7b24da645c2559Eric Laurent boolean connected = (state == BluetoothProfile.STATE_CONNECTED); 4355ae4506e9b5fc3e0c6d9862fbc05b9af7d6742a6eEric Laurent boolean success = handleDeviceConnection(connected, outDevice, address) && 4356ae4506e9b5fc3e0c6d9862fbc05b9af7d6742a6eEric Laurent handleDeviceConnection(connected, inDevice, address); 4357ae4506e9b5fc3e0c6d9862fbc05b9af7d6742a6eEric Laurent if (success) { 43586bc7f2cd30b6bd90806942b0722e22daa2108493Eric Laurent synchronized (mScoClients) { 435959f482764e346a5c5ac118ee1f7b24da645c2559Eric Laurent if (connected) { 436059f482764e346a5c5ac118ee1f7b24da645c2559Eric Laurent mBluetoothHeadsetDevice = btDevice; 436159f482764e346a5c5ac118ee1f7b24da645c2559Eric Laurent } else { 43626bc7f2cd30b6bd90806942b0722e22daa2108493Eric Laurent mBluetoothHeadsetDevice = null; 43636bc7f2cd30b6bd90806942b0722e22daa2108493Eric Laurent resetBluetoothSco(); 43646bc7f2cd30b6bd90806942b0722e22daa2108493Eric Laurent } 436562ef767b15a712bab31cc0d5508a330906f535c2Eric Laurent } 4366a553c25b33c99b345cf1c8688f8df0ed8df14e5aEric Laurent } 4367df3614693dd4fe52a116dcd28bd74eae80818a4fPaul McLean } else if (action.equals(Intent.ACTION_USB_AUDIO_ACCESSORY_PLUG)) { 4368df3614693dd4fe52a116dcd28bd74eae80818a4fPaul McLean state = intent.getIntExtra("state", 0); 4369df3614693dd4fe52a116dcd28bd74eae80818a4fPaul McLean 4370df3614693dd4fe52a116dcd28bd74eae80818a4fPaul McLean int alsaCard = intent.getIntExtra("card", -1); 4371df3614693dd4fe52a116dcd28bd74eae80818a4fPaul McLean int alsaDevice = intent.getIntExtra("device", -1); 4372df3614693dd4fe52a116dcd28bd74eae80818a4fPaul McLean 4373df3614693dd4fe52a116dcd28bd74eae80818a4fPaul McLean String params = (alsaCard == -1 && alsaDevice == -1 ? "" 4374df3614693dd4fe52a116dcd28bd74eae80818a4fPaul McLean : "card=" + alsaCard + ";device=" + alsaDevice); 4375df3614693dd4fe52a116dcd28bd74eae80818a4fPaul McLean 4376df3614693dd4fe52a116dcd28bd74eae80818a4fPaul McLean // Playback Device 4377ae4506e9b5fc3e0c6d9862fbc05b9af7d6742a6eEric Laurent outDevice = AudioSystem.DEVICE_OUT_USB_ACCESSORY; 4378ae4506e9b5fc3e0c6d9862fbc05b9af7d6742a6eEric Laurent setWiredDeviceConnectionState(outDevice, state, params); 4379df3614693dd4fe52a116dcd28bd74eae80818a4fPaul McLean } else if (action.equals(Intent.ACTION_USB_AUDIO_DEVICE_PLUG)) { 438059f482764e346a5c5ac118ee1f7b24da645c2559Eric Laurent state = intent.getIntExtra("state", 0); 4381c837a451946b64d70ed7c642fbde03c182c28b6fPaul McLean 438259f482764e346a5c5ac118ee1f7b24da645c2559Eric Laurent int alsaCard = intent.getIntExtra("card", -1); 438359f482764e346a5c5ac118ee1f7b24da645c2559Eric Laurent int alsaDevice = intent.getIntExtra("device", -1); 4384c837a451946b64d70ed7c642fbde03c182c28b6fPaul McLean boolean hasPlayback = intent.getBooleanExtra("hasPlayback", false); 4385c837a451946b64d70ed7c642fbde03c182c28b6fPaul McLean boolean hasCapture = intent.getBooleanExtra("hasCapture", false); 4386c837a451946b64d70ed7c642fbde03c182c28b6fPaul McLean boolean hasMIDI = intent.getBooleanExtra("hasMIDI", false); 4387c837a451946b64d70ed7c642fbde03c182c28b6fPaul McLean 43889841818b9a0280abf59343c9e00a2976dbc084faMike Lockwood String params = (alsaCard == -1 && alsaDevice == -1 ? "" 43899841818b9a0280abf59343c9e00a2976dbc084faMike Lockwood : "card=" + alsaCard + ";device=" + alsaDevice); 4390c837a451946b64d70ed7c642fbde03c182c28b6fPaul McLean 4391c837a451946b64d70ed7c642fbde03c182c28b6fPaul McLean // Playback Device 4392df3614693dd4fe52a116dcd28bd74eae80818a4fPaul McLean if (hasPlayback) { 4393ae4506e9b5fc3e0c6d9862fbc05b9af7d6742a6eEric Laurent outDevice = AudioSystem.DEVICE_OUT_USB_DEVICE; 4394ae4506e9b5fc3e0c6d9862fbc05b9af7d6742a6eEric Laurent setWiredDeviceConnectionState(outDevice, state, params); 4395df3614693dd4fe52a116dcd28bd74eae80818a4fPaul McLean } 4396c837a451946b64d70ed7c642fbde03c182c28b6fPaul McLean 4397c837a451946b64d70ed7c642fbde03c182c28b6fPaul McLean // Capture Device 4398df3614693dd4fe52a116dcd28bd74eae80818a4fPaul McLean if (hasCapture) { 4399ae4506e9b5fc3e0c6d9862fbc05b9af7d6742a6eEric Laurent inDevice = AudioSystem.DEVICE_IN_USB_DEVICE; 4400ae4506e9b5fc3e0c6d9862fbc05b9af7d6742a6eEric Laurent setWiredDeviceConnectionState(inDevice, state, params); 4401df3614693dd4fe52a116dcd28bd74eae80818a4fPaul McLean } 4402df3614693dd4fe52a116dcd28bd74eae80818a4fPaul McLean } else if (action.equals(BluetoothHeadset.ACTION_AUDIO_STATE_CHANGED)) { 440362ef767b15a712bab31cc0d5508a330906f535c2Eric Laurent boolean broadcast = false; 440459f482764e346a5c5ac118ee1f7b24da645c2559Eric Laurent int scoAudioState = AudioManager.SCO_AUDIO_STATE_ERROR; 44053def1eec2baed0b8845ec32c871e249dc533a9d9Eric Laurent synchronized (mScoClients) { 440662ef767b15a712bab31cc0d5508a330906f535c2Eric Laurent int btState = intent.getIntExtra(BluetoothProfile.EXTRA_STATE, -1); 4407dc03c61fe3cd8d0805480e48a974986439977a60Eric Laurent // broadcast intent if the connection was initated by AudioService 4408dc03c61fe3cd8d0805480e48a974986439977a60Eric Laurent if (!mScoClients.isEmpty() && 4409dc03c61fe3cd8d0805480e48a974986439977a60Eric Laurent (mScoAudioState == SCO_STATE_ACTIVE_INTERNAL || 4410dc03c61fe3cd8d0805480e48a974986439977a60Eric Laurent mScoAudioState == SCO_STATE_ACTIVATE_REQ || 4411dc03c61fe3cd8d0805480e48a974986439977a60Eric Laurent mScoAudioState == SCO_STATE_DEACTIVATE_REQ)) { 441262ef767b15a712bab31cc0d5508a330906f535c2Eric Laurent broadcast = true; 441362ef767b15a712bab31cc0d5508a330906f535c2Eric Laurent } 441462ef767b15a712bab31cc0d5508a330906f535c2Eric Laurent switch (btState) { 441562ef767b15a712bab31cc0d5508a330906f535c2Eric Laurent case BluetoothHeadset.STATE_AUDIO_CONNECTED: 441659f482764e346a5c5ac118ee1f7b24da645c2559Eric Laurent scoAudioState = AudioManager.SCO_AUDIO_STATE_CONNECTED; 4417dc03c61fe3cd8d0805480e48a974986439977a60Eric Laurent if (mScoAudioState != SCO_STATE_ACTIVE_INTERNAL && 4418dc03c61fe3cd8d0805480e48a974986439977a60Eric Laurent mScoAudioState != SCO_STATE_DEACTIVATE_REQ && 4419dc03c61fe3cd8d0805480e48a974986439977a60Eric Laurent mScoAudioState != SCO_STATE_DEACTIVATE_EXT_REQ) { 442062ef767b15a712bab31cc0d5508a330906f535c2Eric Laurent mScoAudioState = SCO_STATE_ACTIVE_EXTERNAL; 44213def1eec2baed0b8845ec32c871e249dc533a9d9Eric Laurent } 442262ef767b15a712bab31cc0d5508a330906f535c2Eric Laurent break; 442362ef767b15a712bab31cc0d5508a330906f535c2Eric Laurent case BluetoothHeadset.STATE_AUDIO_DISCONNECTED: 442459f482764e346a5c5ac118ee1f7b24da645c2559Eric Laurent scoAudioState = AudioManager.SCO_AUDIO_STATE_DISCONNECTED; 442562ef767b15a712bab31cc0d5508a330906f535c2Eric Laurent mScoAudioState = SCO_STATE_INACTIVE; 4426d7454be47f4111c0478a502353e11dea401378bdEric Laurent clearAllScoClients(0, false); 442762ef767b15a712bab31cc0d5508a330906f535c2Eric Laurent break; 442862ef767b15a712bab31cc0d5508a330906f535c2Eric Laurent case BluetoothHeadset.STATE_AUDIO_CONNECTING: 4429dc03c61fe3cd8d0805480e48a974986439977a60Eric Laurent if (mScoAudioState != SCO_STATE_ACTIVE_INTERNAL && 4430dc03c61fe3cd8d0805480e48a974986439977a60Eric Laurent mScoAudioState != SCO_STATE_DEACTIVATE_REQ && 4431dc03c61fe3cd8d0805480e48a974986439977a60Eric Laurent mScoAudioState != SCO_STATE_DEACTIVATE_EXT_REQ) { 443262ef767b15a712bab31cc0d5508a330906f535c2Eric Laurent mScoAudioState = SCO_STATE_ACTIVE_EXTERNAL; 44333def1eec2baed0b8845ec32c871e249dc533a9d9Eric Laurent } 443462ef767b15a712bab31cc0d5508a330906f535c2Eric Laurent default: 443562ef767b15a712bab31cc0d5508a330906f535c2Eric Laurent // do not broadcast CONNECTING or invalid state 443662ef767b15a712bab31cc0d5508a330906f535c2Eric Laurent broadcast = false; 443762ef767b15a712bab31cc0d5508a330906f535c2Eric Laurent break; 44383def1eec2baed0b8845ec32c871e249dc533a9d9Eric Laurent } 44393def1eec2baed0b8845ec32c871e249dc533a9d9Eric Laurent } 444062ef767b15a712bab31cc0d5508a330906f535c2Eric Laurent if (broadcast) { 444159f482764e346a5c5ac118ee1f7b24da645c2559Eric Laurent broadcastScoConnectionState(scoAudioState); 4442dc03c61fe3cd8d0805480e48a974986439977a60Eric Laurent //FIXME: this is to maintain compatibility with deprecated intent 4443dc03c61fe3cd8d0805480e48a974986439977a60Eric Laurent // AudioManager.ACTION_SCO_AUDIO_STATE_CHANGED. Remove when appropriate. 444462ef767b15a712bab31cc0d5508a330906f535c2Eric Laurent Intent newIntent = new Intent(AudioManager.ACTION_SCO_AUDIO_STATE_CHANGED); 444559f482764e346a5c5ac118ee1f7b24da645c2559Eric Laurent newIntent.putExtra(AudioManager.EXTRA_SCO_AUDIO_STATE, scoAudioState); 44465ac72a29593ab9a20337a2225df52bdf4754be02Dianne Hackborn sendStickyBroadcastToAll(newIntent); 444762ef767b15a712bab31cc0d5508a330906f535c2Eric Laurent } 4448950e8cb40a6d826af4cc2eef9d3908c1b70486e6Eric Laurent } else if (action.equals(Intent.ACTION_SCREEN_ON)) { 4449950e8cb40a6d826af4cc2eef9d3908c1b70486e6Eric Laurent AudioSystem.setParameters("screen_state=on"); 4450950e8cb40a6d826af4cc2eef9d3908c1b70486e6Eric Laurent } else if (action.equals(Intent.ACTION_SCREEN_OFF)) { 4451950e8cb40a6d826af4cc2eef9d3908c1b70486e6Eric Laurent AudioSystem.setParameters("screen_state=off"); 4452961cae92540763226648813d111c5b5c3b0f1597Dianne Hackborn } else if (action.equals(Intent.ACTION_CONFIGURATION_CHANGED)) { 4453f26f01784e1c733c53cad3ed31918e73448ce369Jean-Michel Trivi handleConfigurationChanged(context); 4454bc0fab1fc2db832ef86d8a33466ec4d68b103ca0Eric Laurent } else if (action.equals(Intent.ACTION_USER_SWITCHED)) { 4455f4a8eb22112c534f436357b50f231778c5c15c25Jean-Michel Trivi // attempt to stop music playback for background user 44565bfaeaef3fc348d66f48b86be08655e91dff910aEric Laurent sendMsg(mAudioHandler, 44575bfaeaef3fc348d66f48b86be08655e91dff910aEric Laurent MSG_BROADCAST_AUDIO_BECOMING_NOISY, 44585bfaeaef3fc348d66f48b86be08655e91dff910aEric Laurent SENDMSG_REPLACE, 44595bfaeaef3fc348d66f48b86be08655e91dff910aEric Laurent 0, 44605bfaeaef3fc348d66f48b86be08655e91dff910aEric Laurent 0, 44615bfaeaef3fc348d66f48b86be08655e91dff910aEric Laurent null, 44625bfaeaef3fc348d66f48b86be08655e91dff910aEric Laurent 0); 4463f4a8eb22112c534f436357b50f231778c5c15c25Jean-Michel Trivi // the current audio focus owner is no longer valid 4464fa9a69805b001034aa04c3b33989a7ac21522371Jean-Michel Trivi mMediaFocusControl.discardAudioFocusOwner(); 4465f4a8eb22112c534f436357b50f231778c5c15c25Jean-Michel Trivi 44665bfaeaef3fc348d66f48b86be08655e91dff910aEric Laurent // load volume settings for new user 4467bc0fab1fc2db832ef86d8a33466ec4d68b103ca0Eric Laurent readAudioSettings(true /*userSwitch*/); 4468bc0fab1fc2db832ef86d8a33466ec4d68b103ca0Eric Laurent // preserve STREAM_MUSIC volume from one user to the next. 4469bc0fab1fc2db832ef86d8a33466ec4d68b103ca0Eric Laurent sendMsg(mAudioHandler, 4470bc0fab1fc2db832ef86d8a33466ec4d68b103ca0Eric Laurent MSG_SET_ALL_VOLUMES, 4471bc0fab1fc2db832ef86d8a33466ec4d68b103ca0Eric Laurent SENDMSG_QUEUE, 4472bc0fab1fc2db832ef86d8a33466ec4d68b103ca0Eric Laurent 0, 4473bc0fab1fc2db832ef86d8a33466ec4d68b103ca0Eric Laurent 0, 4474bc0fab1fc2db832ef86d8a33466ec4d68b103ca0Eric Laurent mStreamStates[AudioSystem.STREAM_MUSIC], 0); 4475a553c25b33c99b345cf1c8688f8df0ed8df14e5aEric Laurent } 4476a553c25b33c99b345cf1c8688f8df0ed8df14e5aEric Laurent } 4477c837a451946b64d70ed7c642fbde03c182c28b6fPaul McLean } // end class AudioServiceBroadcastReceiver 4478d5176cfe6eae954e9cef1e2ec17859a5089e1330Jean-Michel Trivi 4479d5176cfe6eae954e9cef1e2ec17859a5089e1330Jean-Michel Trivi //========================================================================================== 4480fa9a69805b001034aa04c3b33989a7ac21522371Jean-Michel Trivi // RemoteControlDisplay / RemoteControlClient / Remote info 4481d5176cfe6eae954e9cef1e2ec17859a5089e1330Jean-Michel Trivi //========================================================================================== 4482f108cdd9ee5efe354d87edd02a07b323298c116cJean-Michel Trivi public boolean registerRemoteController(IRemoteControlDisplay rcd, int w, int h, 4483f108cdd9ee5efe354d87edd02a07b323298c116cJean-Michel Trivi ComponentName listenerComp) { 4484f108cdd9ee5efe354d87edd02a07b323298c116cJean-Michel Trivi return mMediaFocusControl.registerRemoteController(rcd, w, h, listenerComp); 4485f108cdd9ee5efe354d87edd02a07b323298c116cJean-Michel Trivi } 4486f108cdd9ee5efe354d87edd02a07b323298c116cJean-Michel Trivi 44877ddd226e7c6e759feaf2747a90be1cc06acf37a3Jean-Michel Trivi public boolean registerRemoteControlDisplay(IRemoteControlDisplay rcd, int w, int h) { 4488f108cdd9ee5efe354d87edd02a07b323298c116cJean-Michel Trivi return mMediaFocusControl.registerRemoteControlDisplay(rcd, w, h); 4489e5e1e870fdb35f5291790e6d178bde7126f6fe35Jean-Michel Trivi } 4490e5e1e870fdb35f5291790e6d178bde7126f6fe35Jean-Michel Trivi 4491fa9a69805b001034aa04c3b33989a7ac21522371Jean-Michel Trivi public void unregisterRemoteControlDisplay(IRemoteControlDisplay rcd) { 4492fa9a69805b001034aa04c3b33989a7ac21522371Jean-Michel Trivi mMediaFocusControl.unregisterRemoteControlDisplay(rcd); 4493d5176cfe6eae954e9cef1e2ec17859a5089e1330Jean-Michel Trivi } 4494d5176cfe6eae954e9cef1e2ec17859a5089e1330Jean-Michel Trivi 4495fa9a69805b001034aa04c3b33989a7ac21522371Jean-Michel Trivi public void remoteControlDisplayUsesBitmapSize(IRemoteControlDisplay rcd, int w, int h) { 4496fa9a69805b001034aa04c3b33989a7ac21522371Jean-Michel Trivi mMediaFocusControl.remoteControlDisplayUsesBitmapSize(rcd, w, h); 4497d5176cfe6eae954e9cef1e2ec17859a5089e1330Jean-Michel Trivi } 4498d5176cfe6eae954e9cef1e2ec17859a5089e1330Jean-Michel Trivi 4499fa9a69805b001034aa04c3b33989a7ac21522371Jean-Michel Trivi public void remoteControlDisplayWantsPlaybackPositionSync(IRemoteControlDisplay rcd, 4500fa9a69805b001034aa04c3b33989a7ac21522371Jean-Michel Trivi boolean wantsSync) { 4501fa9a69805b001034aa04c3b33989a7ac21522371Jean-Michel Trivi mMediaFocusControl.remoteControlDisplayWantsPlaybackPositionSync(rcd, wantsSync); 4502d5176cfe6eae954e9cef1e2ec17859a5089e1330Jean-Michel Trivi } 4503d5176cfe6eae954e9cef1e2ec17859a5089e1330Jean-Michel Trivi 45043346a802087f621c6441bc512dfcc17b07143fc6John Spurlock @Override 4505fa9a69805b001034aa04c3b33989a7ac21522371Jean-Michel Trivi public void setRemoteStreamVolume(int index) { 45063346a802087f621c6441bc512dfcc17b07143fc6John Spurlock enforceSelfOrSystemUI("set the remote stream volume"); 4507fa9a69805b001034aa04c3b33989a7ac21522371Jean-Michel Trivi mMediaFocusControl.setRemoteStreamVolume(index); 4508d327f21626217aa3c9c0cdb7a84a742c531e59a3Jean-Michel Trivi } 4509d327f21626217aa3c9c0cdb7a84a742c531e59a3Jean-Michel Trivi 4510fa9a69805b001034aa04c3b33989a7ac21522371Jean-Michel Trivi //========================================================================================== 4511fa9a69805b001034aa04c3b33989a7ac21522371Jean-Michel Trivi // Audio Focus 4512fa9a69805b001034aa04c3b33989a7ac21522371Jean-Michel Trivi //========================================================================================== 4513fa9a69805b001034aa04c3b33989a7ac21522371Jean-Michel Trivi public int requestAudioFocus(int mainStreamType, int durationHint, IBinder cb, 4514fa9a69805b001034aa04c3b33989a7ac21522371Jean-Michel Trivi IAudioFocusDispatcher fd, String clientId, String callingPackageName) { 4515fa9a69805b001034aa04c3b33989a7ac21522371Jean-Michel Trivi return mMediaFocusControl.requestAudioFocus(mainStreamType, durationHint, cb, fd, 4516fa9a69805b001034aa04c3b33989a7ac21522371Jean-Michel Trivi clientId, callingPackageName); 45174294b83927f51e5c115ebaafd2e185ba5de91436Jean-Michel Trivi } 45184294b83927f51e5c115ebaafd2e185ba5de91436Jean-Michel Trivi 4519fa9a69805b001034aa04c3b33989a7ac21522371Jean-Michel Trivi public int abandonAudioFocus(IAudioFocusDispatcher fd, String clientId) { 4520fa9a69805b001034aa04c3b33989a7ac21522371Jean-Michel Trivi return mMediaFocusControl.abandonAudioFocus(fd, clientId); 4521c68022258ebd3dd97a5079ba99f4f3cd12b223b0Jean-Michel Trivi } 4522c68022258ebd3dd97a5079ba99f4f3cd12b223b0Jean-Michel Trivi 4523fa9a69805b001034aa04c3b33989a7ac21522371Jean-Michel Trivi public void unregisterAudioFocusClient(String clientId) { 4524fa9a69805b001034aa04c3b33989a7ac21522371Jean-Michel Trivi mMediaFocusControl.unregisterAudioFocusClient(clientId); 45253114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi } 45263114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi 45272380566debfc57eb1cc07db1306ccee23b84ddd4Jean-Michel Trivi public int getCurrentAudioFocus() { 45282380566debfc57eb1cc07db1306ccee23b84ddd4Jean-Michel Trivi return mMediaFocusControl.getCurrentAudioFocus(); 45292380566debfc57eb1cc07db1306ccee23b84ddd4Jean-Michel Trivi } 45302380566debfc57eb1cc07db1306ccee23b84ddd4Jean-Michel Trivi 4531f26f01784e1c733c53cad3ed31918e73448ce369Jean-Michel Trivi //========================================================================================== 4532f26f01784e1c733c53cad3ed31918e73448ce369Jean-Michel Trivi // Device orientation 4533f26f01784e1c733c53cad3ed31918e73448ce369Jean-Michel Trivi //========================================================================================== 4534f26f01784e1c733c53cad3ed31918e73448ce369Jean-Michel Trivi /** 4535bb6f8711a7f804d39c45218db2d6339940cc5d35Jean-Michel Trivi * Handles device configuration changes that may map to a change in the orientation 4536bb6f8711a7f804d39c45218db2d6339940cc5d35Jean-Michel Trivi * or orientation. 4537bb6f8711a7f804d39c45218db2d6339940cc5d35Jean-Michel Trivi * Monitoring orientation and rotation is optional, and is defined by the definition and value 4538bb6f8711a7f804d39c45218db2d6339940cc5d35Jean-Michel Trivi * of the "ro.audio.monitorOrientation" and "ro.audio.monitorRotation" system properties. 4539f26f01784e1c733c53cad3ed31918e73448ce369Jean-Michel Trivi */ 4540f26f01784e1c733c53cad3ed31918e73448ce369Jean-Michel Trivi private void handleConfigurationChanged(Context context) { 4541f26f01784e1c733c53cad3ed31918e73448ce369Jean-Michel Trivi try { 4542f26f01784e1c733c53cad3ed31918e73448ce369Jean-Michel Trivi // reading new orientation "safely" (i.e. under try catch) in case anything 4543f26f01784e1c733c53cad3ed31918e73448ce369Jean-Michel Trivi // goes wrong when obtaining resources and configuration 4544d640bd325c3be9a350058c835b880a7e0b40dc60Eric Laurent Configuration config = context.getResources().getConfiguration(); 4545bb6f8711a7f804d39c45218db2d6339940cc5d35Jean-Michel Trivi // TODO merge rotation and orientation 4546d640bd325c3be9a350058c835b880a7e0b40dc60Eric Laurent if (mMonitorOrientation) { 4547d640bd325c3be9a350058c835b880a7e0b40dc60Eric Laurent int newOrientation = config.orientation; 4548d640bd325c3be9a350058c835b880a7e0b40dc60Eric Laurent if (newOrientation != mDeviceOrientation) { 4549d640bd325c3be9a350058c835b880a7e0b40dc60Eric Laurent mDeviceOrientation = newOrientation; 4550d640bd325c3be9a350058c835b880a7e0b40dc60Eric Laurent setOrientationForAudioSystem(); 4551d640bd325c3be9a350058c835b880a7e0b40dc60Eric Laurent } 4552f26f01784e1c733c53cad3ed31918e73448ce369Jean-Michel Trivi } 4553bb6f8711a7f804d39c45218db2d6339940cc5d35Jean-Michel Trivi if (mMonitorRotation) { 4554bb6f8711a7f804d39c45218db2d6339940cc5d35Jean-Michel Trivi int newRotation = ((WindowManager) context.getSystemService( 4555bb6f8711a7f804d39c45218db2d6339940cc5d35Jean-Michel Trivi Context.WINDOW_SERVICE)).getDefaultDisplay().getRotation(); 4556bb6f8711a7f804d39c45218db2d6339940cc5d35Jean-Michel Trivi if (newRotation != mDeviceRotation) { 4557bb6f8711a7f804d39c45218db2d6339940cc5d35Jean-Michel Trivi mDeviceRotation = newRotation; 4558bb6f8711a7f804d39c45218db2d6339940cc5d35Jean-Michel Trivi setRotationForAudioSystem(); 4559bb6f8711a7f804d39c45218db2d6339940cc5d35Jean-Michel Trivi } 4560bb6f8711a7f804d39c45218db2d6339940cc5d35Jean-Michel Trivi } 4561d640bd325c3be9a350058c835b880a7e0b40dc60Eric Laurent sendMsg(mAudioHandler, 4562d640bd325c3be9a350058c835b880a7e0b40dc60Eric Laurent MSG_CONFIGURE_SAFE_MEDIA_VOLUME, 4563d640bd325c3be9a350058c835b880a7e0b40dc60Eric Laurent SENDMSG_REPLACE, 4564d640bd325c3be9a350058c835b880a7e0b40dc60Eric Laurent 0, 4565d640bd325c3be9a350058c835b880a7e0b40dc60Eric Laurent 0, 4566d640bd325c3be9a350058c835b880a7e0b40dc60Eric Laurent null, 4567d640bd325c3be9a350058c835b880a7e0b40dc60Eric Laurent 0); 4568dd45d01128423a82652a3c9d77fa393631d95229Eric Laurent 4569dd45d01128423a82652a3c9d77fa393631d95229Eric Laurent boolean cameraSoundForced = mContext.getResources().getBoolean( 4570dd45d01128423a82652a3c9d77fa393631d95229Eric Laurent com.android.internal.R.bool.config_camera_sound_forced); 4571dd45d01128423a82652a3c9d77fa393631d95229Eric Laurent synchronized (mSettingsLock) { 4572dd45d01128423a82652a3c9d77fa393631d95229Eric Laurent synchronized (mCameraSoundForced) { 4573dd45d01128423a82652a3c9d77fa393631d95229Eric Laurent if (cameraSoundForced != mCameraSoundForced) { 4574dd45d01128423a82652a3c9d77fa393631d95229Eric Laurent mCameraSoundForced = cameraSoundForced; 4575dd45d01128423a82652a3c9d77fa393631d95229Eric Laurent 4576dd45d01128423a82652a3c9d77fa393631d95229Eric Laurent VolumeStreamState s = mStreamStates[AudioSystem.STREAM_SYSTEM_ENFORCED]; 4577dd45d01128423a82652a3c9d77fa393631d95229Eric Laurent if (cameraSoundForced) { 4578dd45d01128423a82652a3c9d77fa393631d95229Eric Laurent s.setAllIndexesToMax(); 4579dd45d01128423a82652a3c9d77fa393631d95229Eric Laurent mRingerModeAffectedStreams &= 4580dd45d01128423a82652a3c9d77fa393631d95229Eric Laurent ~(1 << AudioSystem.STREAM_SYSTEM_ENFORCED); 4581dd45d01128423a82652a3c9d77fa393631d95229Eric Laurent } else { 458242b041ed4f184e3af7f788eb07307f556a2a6616Eric Laurent s.setAllIndexes(mStreamStates[AudioSystem.STREAM_SYSTEM]); 4583dd45d01128423a82652a3c9d77fa393631d95229Eric Laurent mRingerModeAffectedStreams |= 4584dd45d01128423a82652a3c9d77fa393631d95229Eric Laurent (1 << AudioSystem.STREAM_SYSTEM_ENFORCED); 4585dd45d01128423a82652a3c9d77fa393631d95229Eric Laurent } 4586dd45d01128423a82652a3c9d77fa393631d95229Eric Laurent // take new state into account for streams muted by ringer mode 4587dd45d01128423a82652a3c9d77fa393631d95229Eric Laurent setRingerModeInt(getRingerMode(), false); 4588dd45d01128423a82652a3c9d77fa393631d95229Eric Laurent 4589dd45d01128423a82652a3c9d77fa393631d95229Eric Laurent sendMsg(mAudioHandler, 4590dd45d01128423a82652a3c9d77fa393631d95229Eric Laurent MSG_SET_FORCE_USE, 4591dd45d01128423a82652a3c9d77fa393631d95229Eric Laurent SENDMSG_QUEUE, 4592dd45d01128423a82652a3c9d77fa393631d95229Eric Laurent AudioSystem.FOR_SYSTEM, 4593dd45d01128423a82652a3c9d77fa393631d95229Eric Laurent cameraSoundForced ? 4594dd45d01128423a82652a3c9d77fa393631d95229Eric Laurent AudioSystem.FORCE_SYSTEM_ENFORCED : AudioSystem.FORCE_NONE, 4595dd45d01128423a82652a3c9d77fa393631d95229Eric Laurent null, 4596dd45d01128423a82652a3c9d77fa393631d95229Eric Laurent 0); 4597dd45d01128423a82652a3c9d77fa393631d95229Eric Laurent 4598dd45d01128423a82652a3c9d77fa393631d95229Eric Laurent sendMsg(mAudioHandler, 4599dd45d01128423a82652a3c9d77fa393631d95229Eric Laurent MSG_SET_ALL_VOLUMES, 4600dd45d01128423a82652a3c9d77fa393631d95229Eric Laurent SENDMSG_QUEUE, 4601dd45d01128423a82652a3c9d77fa393631d95229Eric Laurent 0, 4602dd45d01128423a82652a3c9d77fa393631d95229Eric Laurent 0, 4603dd45d01128423a82652a3c9d77fa393631d95229Eric Laurent mStreamStates[AudioSystem.STREAM_SYSTEM_ENFORCED], 0); 4604dd45d01128423a82652a3c9d77fa393631d95229Eric Laurent } 4605dd45d01128423a82652a3c9d77fa393631d95229Eric Laurent } 4606dd45d01128423a82652a3c9d77fa393631d95229Eric Laurent } 46073346a802087f621c6441bc512dfcc17b07143fc6John Spurlock mVolumeController.setLayoutDirection(config.getLayoutDirection()); 4608f26f01784e1c733c53cad3ed31918e73448ce369Jean-Michel Trivi } catch (Exception e) { 4609bb6f8711a7f804d39c45218db2d6339940cc5d35Jean-Michel Trivi Log.e(TAG, "Error handling configuration change: ", e); 4610f26f01784e1c733c53cad3ed31918e73448ce369Jean-Michel Trivi } 4611f26f01784e1c733c53cad3ed31918e73448ce369Jean-Michel Trivi } 4612f26f01784e1c733c53cad3ed31918e73448ce369Jean-Michel Trivi 4613f26f01784e1c733c53cad3ed31918e73448ce369Jean-Michel Trivi private void setOrientationForAudioSystem() { 4614f26f01784e1c733c53cad3ed31918e73448ce369Jean-Michel Trivi switch (mDeviceOrientation) { 4615f26f01784e1c733c53cad3ed31918e73448ce369Jean-Michel Trivi case Configuration.ORIENTATION_LANDSCAPE: 4616f26f01784e1c733c53cad3ed31918e73448ce369Jean-Michel Trivi //Log.i(TAG, "orientation is landscape"); 4617f26f01784e1c733c53cad3ed31918e73448ce369Jean-Michel Trivi AudioSystem.setParameters("orientation=landscape"); 4618f26f01784e1c733c53cad3ed31918e73448ce369Jean-Michel Trivi break; 4619f26f01784e1c733c53cad3ed31918e73448ce369Jean-Michel Trivi case Configuration.ORIENTATION_PORTRAIT: 4620f26f01784e1c733c53cad3ed31918e73448ce369Jean-Michel Trivi //Log.i(TAG, "orientation is portrait"); 4621f26f01784e1c733c53cad3ed31918e73448ce369Jean-Michel Trivi AudioSystem.setParameters("orientation=portrait"); 4622f26f01784e1c733c53cad3ed31918e73448ce369Jean-Michel Trivi break; 4623f26f01784e1c733c53cad3ed31918e73448ce369Jean-Michel Trivi case Configuration.ORIENTATION_SQUARE: 4624f26f01784e1c733c53cad3ed31918e73448ce369Jean-Michel Trivi //Log.i(TAG, "orientation is square"); 4625f26f01784e1c733c53cad3ed31918e73448ce369Jean-Michel Trivi AudioSystem.setParameters("orientation=square"); 4626f26f01784e1c733c53cad3ed31918e73448ce369Jean-Michel Trivi break; 4627f26f01784e1c733c53cad3ed31918e73448ce369Jean-Michel Trivi case Configuration.ORIENTATION_UNDEFINED: 4628f26f01784e1c733c53cad3ed31918e73448ce369Jean-Michel Trivi //Log.i(TAG, "orientation is undefined"); 4629f26f01784e1c733c53cad3ed31918e73448ce369Jean-Michel Trivi AudioSystem.setParameters("orientation=undefined"); 4630f26f01784e1c733c53cad3ed31918e73448ce369Jean-Michel Trivi break; 4631f26f01784e1c733c53cad3ed31918e73448ce369Jean-Michel Trivi default: 4632f26f01784e1c733c53cad3ed31918e73448ce369Jean-Michel Trivi Log.e(TAG, "Unknown orientation"); 4633f26f01784e1c733c53cad3ed31918e73448ce369Jean-Michel Trivi } 4634f26f01784e1c733c53cad3ed31918e73448ce369Jean-Michel Trivi } 4635f26f01784e1c733c53cad3ed31918e73448ce369Jean-Michel Trivi 4636bb6f8711a7f804d39c45218db2d6339940cc5d35Jean-Michel Trivi private void setRotationForAudioSystem() { 4637bb6f8711a7f804d39c45218db2d6339940cc5d35Jean-Michel Trivi switch (mDeviceRotation) { 4638bb6f8711a7f804d39c45218db2d6339940cc5d35Jean-Michel Trivi case Surface.ROTATION_0: 4639bb6f8711a7f804d39c45218db2d6339940cc5d35Jean-Michel Trivi AudioSystem.setParameters("rotation=0"); 4640bb6f8711a7f804d39c45218db2d6339940cc5d35Jean-Michel Trivi break; 4641bb6f8711a7f804d39c45218db2d6339940cc5d35Jean-Michel Trivi case Surface.ROTATION_90: 4642bb6f8711a7f804d39c45218db2d6339940cc5d35Jean-Michel Trivi AudioSystem.setParameters("rotation=90"); 4643bb6f8711a7f804d39c45218db2d6339940cc5d35Jean-Michel Trivi break; 4644bb6f8711a7f804d39c45218db2d6339940cc5d35Jean-Michel Trivi case Surface.ROTATION_180: 4645bb6f8711a7f804d39c45218db2d6339940cc5d35Jean-Michel Trivi AudioSystem.setParameters("rotation=180"); 4646bb6f8711a7f804d39c45218db2d6339940cc5d35Jean-Michel Trivi break; 4647bb6f8711a7f804d39c45218db2d6339940cc5d35Jean-Michel Trivi case Surface.ROTATION_270: 4648bb6f8711a7f804d39c45218db2d6339940cc5d35Jean-Michel Trivi AudioSystem.setParameters("rotation=270"); 4649bb6f8711a7f804d39c45218db2d6339940cc5d35Jean-Michel Trivi break; 4650bb6f8711a7f804d39c45218db2d6339940cc5d35Jean-Michel Trivi default: 4651bb6f8711a7f804d39c45218db2d6339940cc5d35Jean-Michel Trivi Log.e(TAG, "Unknown device rotation"); 4652bb6f8711a7f804d39c45218db2d6339940cc5d35Jean-Michel Trivi } 4653bb6f8711a7f804d39c45218db2d6339940cc5d35Jean-Michel Trivi } 4654bb6f8711a7f804d39c45218db2d6339940cc5d35Jean-Michel Trivi 4655f26f01784e1c733c53cad3ed31918e73448ce369Jean-Michel Trivi 46567847211fb4699bf6018e29d214a918ed6657319bEric Laurent // Handles request to override default use of A2DP for media. 46577847211fb4699bf6018e29d214a918ed6657319bEric Laurent public void setBluetoothA2dpOnInt(boolean on) { 46587847211fb4699bf6018e29d214a918ed6657319bEric Laurent synchronized (mBluetoothA2dpEnabledLock) { 46597847211fb4699bf6018e29d214a918ed6657319bEric Laurent mBluetoothA2dpEnabled = on; 4660c390bed06b4a572e273ead1254da9a932e04dce3Eric Laurent mAudioHandler.removeMessages(MSG_SET_FORCE_BT_A2DP_USE); 4661c390bed06b4a572e273ead1254da9a932e04dce3Eric Laurent AudioSystem.setForceUse(AudioSystem.FOR_MEDIA, 4662c390bed06b4a572e273ead1254da9a932e04dce3Eric Laurent mBluetoothA2dpEnabled ? AudioSystem.FORCE_NONE : AudioSystem.FORCE_NO_BT_A2DP); 46637847211fb4699bf6018e29d214a918ed6657319bEric Laurent } 46647847211fb4699bf6018e29d214a918ed6657319bEric Laurent } 46657847211fb4699bf6018e29d214a918ed6657319bEric Laurent 4666d5176cfe6eae954e9cef1e2ec17859a5089e1330Jean-Michel Trivi @Override 4667098d580cc2bb6c0891c756a4e5230c6c6b0d2376Jeff Sharkey public void setRingtonePlayer(IRingtonePlayer player) { 4668098d580cc2bb6c0891c756a4e5230c6c6b0d2376Jeff Sharkey mContext.enforceCallingOrSelfPermission(REMOTE_AUDIO_PLAYBACK, null); 4669098d580cc2bb6c0891c756a4e5230c6c6b0d2376Jeff Sharkey mRingtonePlayer = player; 4670098d580cc2bb6c0891c756a4e5230c6c6b0d2376Jeff Sharkey } 4671098d580cc2bb6c0891c756a4e5230c6c6b0d2376Jeff Sharkey 4672098d580cc2bb6c0891c756a4e5230c6c6b0d2376Jeff Sharkey @Override 4673098d580cc2bb6c0891c756a4e5230c6c6b0d2376Jeff Sharkey public IRingtonePlayer getRingtonePlayer() { 4674098d580cc2bb6c0891c756a4e5230c6c6b0d2376Jeff Sharkey return mRingtonePlayer; 4675098d580cc2bb6c0891c756a4e5230c6c6b0d2376Jeff Sharkey } 4676098d580cc2bb6c0891c756a4e5230c6c6b0d2376Jeff Sharkey 4677098d580cc2bb6c0891c756a4e5230c6c6b0d2376Jeff Sharkey @Override 4678632ca417f0a33e3fa9ccece531afa2db3f0d4a30Dianne Hackborn public AudioRoutesInfo startWatchingRoutes(IAudioRoutesObserver observer) { 4679632ca417f0a33e3fa9ccece531afa2db3f0d4a30Dianne Hackborn synchronized (mCurAudioRoutes) { 4680632ca417f0a33e3fa9ccece531afa2db3f0d4a30Dianne Hackborn AudioRoutesInfo routes = new AudioRoutesInfo(mCurAudioRoutes); 4681632ca417f0a33e3fa9ccece531afa2db3f0d4a30Dianne Hackborn mRoutesObservers.register(observer); 4682632ca417f0a33e3fa9ccece531afa2db3f0d4a30Dianne Hackborn return routes; 4683632ca417f0a33e3fa9ccece531afa2db3f0d4a30Dianne Hackborn } 4684632ca417f0a33e3fa9ccece531afa2db3f0d4a30Dianne Hackborn } 4685632ca417f0a33e3fa9ccece531afa2db3f0d4a30Dianne Hackborn 4686c34dcc1e1ebf152bb400abbb8bc25f7dc0c3ba97Eric Laurent 4687c34dcc1e1ebf152bb400abbb8bc25f7dc0c3ba97Eric Laurent //========================================================================================== 4688c34dcc1e1ebf152bb400abbb8bc25f7dc0c3ba97Eric Laurent // Safe media volume management. 4689c34dcc1e1ebf152bb400abbb8bc25f7dc0c3ba97Eric Laurent // MUSIC stream volume level is limited when headphones are connected according to safety 4690c34dcc1e1ebf152bb400abbb8bc25f7dc0c3ba97Eric Laurent // regulation. When the user attempts to raise the volume above the limit, a warning is 4691c34dcc1e1ebf152bb400abbb8bc25f7dc0c3ba97Eric Laurent // displayed and the user has to acknowlegde before the volume is actually changed. 4692c34dcc1e1ebf152bb400abbb8bc25f7dc0c3ba97Eric Laurent // The volume index corresponding to the limit is stored in config_safe_media_volume_index 4693c34dcc1e1ebf152bb400abbb8bc25f7dc0c3ba97Eric Laurent // property. Platforms with a different limit must set this property accordingly in their 4694c34dcc1e1ebf152bb400abbb8bc25f7dc0c3ba97Eric Laurent // overlay. 4695c34dcc1e1ebf152bb400abbb8bc25f7dc0c3ba97Eric Laurent //========================================================================================== 4696c34dcc1e1ebf152bb400abbb8bc25f7dc0c3ba97Eric Laurent 4697d640bd325c3be9a350058c835b880a7e0b40dc60Eric Laurent // mSafeMediaVolumeState indicates whether the media volume is limited over headphones. 4698d640bd325c3be9a350058c835b880a7e0b40dc60Eric Laurent // It is SAFE_MEDIA_VOLUME_NOT_CONFIGURED at boot time until a network service is connected 4699d640bd325c3be9a350058c835b880a7e0b40dc60Eric Laurent // or the configure time is elapsed. It is then set to SAFE_MEDIA_VOLUME_ACTIVE or 4700d640bd325c3be9a350058c835b880a7e0b40dc60Eric Laurent // SAFE_MEDIA_VOLUME_DISABLED according to country option. If not SAFE_MEDIA_VOLUME_DISABLED, it 4701d640bd325c3be9a350058c835b880a7e0b40dc60Eric Laurent // can be set to SAFE_MEDIA_VOLUME_INACTIVE by calling AudioService.disableSafeMediaVolume() 4702d640bd325c3be9a350058c835b880a7e0b40dc60Eric Laurent // (when user opts out). 4703d640bd325c3be9a350058c835b880a7e0b40dc60Eric Laurent private final int SAFE_MEDIA_VOLUME_NOT_CONFIGURED = 0; 4704d640bd325c3be9a350058c835b880a7e0b40dc60Eric Laurent private final int SAFE_MEDIA_VOLUME_DISABLED = 1; 4705d640bd325c3be9a350058c835b880a7e0b40dc60Eric Laurent private final int SAFE_MEDIA_VOLUME_INACTIVE = 2; 4706d640bd325c3be9a350058c835b880a7e0b40dc60Eric Laurent private final int SAFE_MEDIA_VOLUME_ACTIVE = 3; 4707d640bd325c3be9a350058c835b880a7e0b40dc60Eric Laurent private Integer mSafeMediaVolumeState; 4708d640bd325c3be9a350058c835b880a7e0b40dc60Eric Laurent 4709d640bd325c3be9a350058c835b880a7e0b40dc60Eric Laurent private int mMcc = 0; 4710c34dcc1e1ebf152bb400abbb8bc25f7dc0c3ba97Eric Laurent // mSafeMediaVolumeIndex is the cached value of config_safe_media_volume_index property 4711d640bd325c3be9a350058c835b880a7e0b40dc60Eric Laurent private int mSafeMediaVolumeIndex; 4712c34dcc1e1ebf152bb400abbb8bc25f7dc0c3ba97Eric Laurent // mSafeMediaVolumeDevices lists the devices for which safe media volume is enforced, 4713c34dcc1e1ebf152bb400abbb8bc25f7dc0c3ba97Eric Laurent private final int mSafeMediaVolumeDevices = AudioSystem.DEVICE_OUT_WIRED_HEADSET | 4714c34dcc1e1ebf152bb400abbb8bc25f7dc0c3ba97Eric Laurent AudioSystem.DEVICE_OUT_WIRED_HEADPHONE; 4715c34dcc1e1ebf152bb400abbb8bc25f7dc0c3ba97Eric Laurent // mMusicActiveMs is the cumulative time of music activity since safe volume was disabled. 4716c34dcc1e1ebf152bb400abbb8bc25f7dc0c3ba97Eric Laurent // When this time reaches UNSAFE_VOLUME_MUSIC_ACTIVE_MS_MAX, the safe media volume is re-enabled 4717c34dcc1e1ebf152bb400abbb8bc25f7dc0c3ba97Eric Laurent // automatically. mMusicActiveMs is rounded to a multiple of MUSIC_ACTIVE_POLL_PERIOD_MS. 4718c34dcc1e1ebf152bb400abbb8bc25f7dc0c3ba97Eric Laurent private int mMusicActiveMs; 4719c34dcc1e1ebf152bb400abbb8bc25f7dc0c3ba97Eric Laurent private static final int UNSAFE_VOLUME_MUSIC_ACTIVE_MS_MAX = (20 * 3600 * 1000); // 20 hours 4720c34dcc1e1ebf152bb400abbb8bc25f7dc0c3ba97Eric Laurent private static final int MUSIC_ACTIVE_POLL_PERIOD_MS = 60000; // 1 minute polling interval 4721d640bd325c3be9a350058c835b880a7e0b40dc60Eric Laurent private static final int SAFE_VOLUME_CONFIGURE_TIMEOUT_MS = 30000; // 30s after boot completed 4722c34dcc1e1ebf152bb400abbb8bc25f7dc0c3ba97Eric Laurent 4723c34dcc1e1ebf152bb400abbb8bc25f7dc0c3ba97Eric Laurent private void setSafeMediaVolumeEnabled(boolean on) { 4724d640bd325c3be9a350058c835b880a7e0b40dc60Eric Laurent synchronized (mSafeMediaVolumeState) { 4725d640bd325c3be9a350058c835b880a7e0b40dc60Eric Laurent if ((mSafeMediaVolumeState != SAFE_MEDIA_VOLUME_NOT_CONFIGURED) && 4726d640bd325c3be9a350058c835b880a7e0b40dc60Eric Laurent (mSafeMediaVolumeState != SAFE_MEDIA_VOLUME_DISABLED)) { 4727d640bd325c3be9a350058c835b880a7e0b40dc60Eric Laurent if (on && (mSafeMediaVolumeState == SAFE_MEDIA_VOLUME_INACTIVE)) { 4728d640bd325c3be9a350058c835b880a7e0b40dc60Eric Laurent mSafeMediaVolumeState = SAFE_MEDIA_VOLUME_ACTIVE; 4729d640bd325c3be9a350058c835b880a7e0b40dc60Eric Laurent enforceSafeMediaVolume(); 4730d640bd325c3be9a350058c835b880a7e0b40dc60Eric Laurent } else if (!on && (mSafeMediaVolumeState == SAFE_MEDIA_VOLUME_ACTIVE)) { 4731d640bd325c3be9a350058c835b880a7e0b40dc60Eric Laurent mSafeMediaVolumeState = SAFE_MEDIA_VOLUME_INACTIVE; 4732d640bd325c3be9a350058c835b880a7e0b40dc60Eric Laurent mMusicActiveMs = 0; 4733d640bd325c3be9a350058c835b880a7e0b40dc60Eric Laurent sendMsg(mAudioHandler, 4734d640bd325c3be9a350058c835b880a7e0b40dc60Eric Laurent MSG_CHECK_MUSIC_ACTIVE, 4735d640bd325c3be9a350058c835b880a7e0b40dc60Eric Laurent SENDMSG_REPLACE, 4736d640bd325c3be9a350058c835b880a7e0b40dc60Eric Laurent 0, 4737d640bd325c3be9a350058c835b880a7e0b40dc60Eric Laurent 0, 4738d640bd325c3be9a350058c835b880a7e0b40dc60Eric Laurent null, 4739d640bd325c3be9a350058c835b880a7e0b40dc60Eric Laurent MUSIC_ACTIVE_POLL_PERIOD_MS); 4740d640bd325c3be9a350058c835b880a7e0b40dc60Eric Laurent } 4741c34dcc1e1ebf152bb400abbb8bc25f7dc0c3ba97Eric Laurent } 4742c34dcc1e1ebf152bb400abbb8bc25f7dc0c3ba97Eric Laurent } 4743c34dcc1e1ebf152bb400abbb8bc25f7dc0c3ba97Eric Laurent } 4744c34dcc1e1ebf152bb400abbb8bc25f7dc0c3ba97Eric Laurent 4745c34dcc1e1ebf152bb400abbb8bc25f7dc0c3ba97Eric Laurent private void enforceSafeMediaVolume() { 4746c34dcc1e1ebf152bb400abbb8bc25f7dc0c3ba97Eric Laurent VolumeStreamState streamState = mStreamStates[AudioSystem.STREAM_MUSIC]; 4747c34dcc1e1ebf152bb400abbb8bc25f7dc0c3ba97Eric Laurent int devices = mSafeMediaVolumeDevices; 4748c34dcc1e1ebf152bb400abbb8bc25f7dc0c3ba97Eric Laurent int i = 0; 4749c34dcc1e1ebf152bb400abbb8bc25f7dc0c3ba97Eric Laurent 4750c34dcc1e1ebf152bb400abbb8bc25f7dc0c3ba97Eric Laurent while (devices != 0) { 4751c34dcc1e1ebf152bb400abbb8bc25f7dc0c3ba97Eric Laurent int device = 1 << i++; 4752c34dcc1e1ebf152bb400abbb8bc25f7dc0c3ba97Eric Laurent if ((device & devices) == 0) { 4753c34dcc1e1ebf152bb400abbb8bc25f7dc0c3ba97Eric Laurent continue; 4754c34dcc1e1ebf152bb400abbb8bc25f7dc0c3ba97Eric Laurent } 475542b041ed4f184e3af7f788eb07307f556a2a6616Eric Laurent int index = streamState.getIndex(device); 4756c34dcc1e1ebf152bb400abbb8bc25f7dc0c3ba97Eric Laurent if (index > mSafeMediaVolumeIndex) { 475742b041ed4f184e3af7f788eb07307f556a2a6616Eric Laurent streamState.setIndex(mSafeMediaVolumeIndex, device); 475842b041ed4f184e3af7f788eb07307f556a2a6616Eric Laurent sendMsg(mAudioHandler, 475942b041ed4f184e3af7f788eb07307f556a2a6616Eric Laurent MSG_SET_DEVICE_VOLUME, 476042b041ed4f184e3af7f788eb07307f556a2a6616Eric Laurent SENDMSG_QUEUE, 476142b041ed4f184e3af7f788eb07307f556a2a6616Eric Laurent device, 476242b041ed4f184e3af7f788eb07307f556a2a6616Eric Laurent 0, 476342b041ed4f184e3af7f788eb07307f556a2a6616Eric Laurent streamState, 476442b041ed4f184e3af7f788eb07307f556a2a6616Eric Laurent 0); 4765c34dcc1e1ebf152bb400abbb8bc25f7dc0c3ba97Eric Laurent } 4766c34dcc1e1ebf152bb400abbb8bc25f7dc0c3ba97Eric Laurent devices &= ~device; 4767c34dcc1e1ebf152bb400abbb8bc25f7dc0c3ba97Eric Laurent } 4768c34dcc1e1ebf152bb400abbb8bc25f7dc0c3ba97Eric Laurent } 4769c34dcc1e1ebf152bb400abbb8bc25f7dc0c3ba97Eric Laurent 4770c34dcc1e1ebf152bb400abbb8bc25f7dc0c3ba97Eric Laurent private boolean checkSafeMediaVolume(int streamType, int index, int device) { 4771d640bd325c3be9a350058c835b880a7e0b40dc60Eric Laurent synchronized (mSafeMediaVolumeState) { 4772d640bd325c3be9a350058c835b880a7e0b40dc60Eric Laurent if ((mSafeMediaVolumeState == SAFE_MEDIA_VOLUME_ACTIVE) && 4773c34dcc1e1ebf152bb400abbb8bc25f7dc0c3ba97Eric Laurent (mStreamVolumeAlias[streamType] == AudioSystem.STREAM_MUSIC) && 4774c34dcc1e1ebf152bb400abbb8bc25f7dc0c3ba97Eric Laurent ((device & mSafeMediaVolumeDevices) != 0) && 4775c34dcc1e1ebf152bb400abbb8bc25f7dc0c3ba97Eric Laurent (index > mSafeMediaVolumeIndex)) { 4776c34dcc1e1ebf152bb400abbb8bc25f7dc0c3ba97Eric Laurent return false; 4777c34dcc1e1ebf152bb400abbb8bc25f7dc0c3ba97Eric Laurent } 4778c34dcc1e1ebf152bb400abbb8bc25f7dc0c3ba97Eric Laurent return true; 4779c34dcc1e1ebf152bb400abbb8bc25f7dc0c3ba97Eric Laurent } 4780c34dcc1e1ebf152bb400abbb8bc25f7dc0c3ba97Eric Laurent } 4781c34dcc1e1ebf152bb400abbb8bc25f7dc0c3ba97Eric Laurent 47823346a802087f621c6441bc512dfcc17b07143fc6John Spurlock @Override 4783c34dcc1e1ebf152bb400abbb8bc25f7dc0c3ba97Eric Laurent public void disableSafeMediaVolume() { 47843346a802087f621c6441bc512dfcc17b07143fc6John Spurlock enforceSelfOrSystemUI("disable the safe media volume"); 4785d640bd325c3be9a350058c835b880a7e0b40dc60Eric Laurent synchronized (mSafeMediaVolumeState) { 4786c34dcc1e1ebf152bb400abbb8bc25f7dc0c3ba97Eric Laurent setSafeMediaVolumeEnabled(false); 4787fde16d5879ea88a971004c984093409468b6139cEric Laurent if (mPendingVolumeCommand != null) { 4788fde16d5879ea88a971004c984093409468b6139cEric Laurent onSetStreamVolume(mPendingVolumeCommand.mStreamType, 4789fde16d5879ea88a971004c984093409468b6139cEric Laurent mPendingVolumeCommand.mIndex, 4790fde16d5879ea88a971004c984093409468b6139cEric Laurent mPendingVolumeCommand.mFlags, 4791fde16d5879ea88a971004c984093409468b6139cEric Laurent mPendingVolumeCommand.mDevice); 4792fde16d5879ea88a971004c984093409468b6139cEric Laurent mPendingVolumeCommand = null; 4793fde16d5879ea88a971004c984093409468b6139cEric Laurent } 4794c34dcc1e1ebf152bb400abbb8bc25f7dc0c3ba97Eric Laurent } 4795c34dcc1e1ebf152bb400abbb8bc25f7dc0c3ba97Eric Laurent } 4796c34dcc1e1ebf152bb400abbb8bc25f7dc0c3ba97Eric Laurent 479741d974631c5f525da49c88d34cecedd5a4cfeda8Jungshik Jang //========================================================================================== 479841d974631c5f525da49c88d34cecedd5a4cfeda8Jungshik Jang // Hdmi Cec system audio mode. 479941d974631c5f525da49c88d34cecedd5a4cfeda8Jungshik Jang // If Hdmi Cec's system audio mode is on, audio service should notify volume change 480041d974631c5f525da49c88d34cecedd5a4cfeda8Jungshik Jang // to HdmiControlService so that audio recevier can handle volume change. 480141d974631c5f525da49c88d34cecedd5a4cfeda8Jungshik Jang //========================================================================================== 480241d974631c5f525da49c88d34cecedd5a4cfeda8Jungshik Jang 480341d974631c5f525da49c88d34cecedd5a4cfeda8Jungshik Jang // If HDMI-CEC system audio is supported 480441d974631c5f525da49c88d34cecedd5a4cfeda8Jungshik Jang private boolean mHdmiSystemAudioSupported = false; 480541d974631c5f525da49c88d34cecedd5a4cfeda8Jungshik Jang // Set only when device is tv. 480641d974631c5f525da49c88d34cecedd5a4cfeda8Jungshik Jang private HdmiTvClient mHdmiTvClient; 480741d974631c5f525da49c88d34cecedd5a4cfeda8Jungshik Jang 480841d974631c5f525da49c88d34cecedd5a4cfeda8Jungshik Jang @Override 480912307ca810e8100981b2b60e3f2c6a7e451b9774Jungshik Jang public int setHdmiSystemAudioSupported(boolean on) { 481041d974631c5f525da49c88d34cecedd5a4cfeda8Jungshik Jang if (mHdmiTvClient == null) { 481141d974631c5f525da49c88d34cecedd5a4cfeda8Jungshik Jang Log.w(TAG, "Only Hdmi-Cec enabled TV device supports system audio mode."); 48126f34f5ab8ab1b1db7887e5405d8b0031e105ab05Jungshik Jang return AudioSystem.DEVICE_NONE; 481341d974631c5f525da49c88d34cecedd5a4cfeda8Jungshik Jang } 481441d974631c5f525da49c88d34cecedd5a4cfeda8Jungshik Jang 481541d974631c5f525da49c88d34cecedd5a4cfeda8Jungshik Jang synchronized (mHdmiTvClient) { 48166f34f5ab8ab1b1db7887e5405d8b0031e105ab05Jungshik Jang if (mHdmiSystemAudioSupported == on) { 48176f34f5ab8ab1b1db7887e5405d8b0031e105ab05Jungshik Jang return AudioSystem.getDevicesForStream(AudioSystem.STREAM_MUSIC); 48186f34f5ab8ab1b1db7887e5405d8b0031e105ab05Jungshik Jang } 481941d974631c5f525da49c88d34cecedd5a4cfeda8Jungshik Jang mHdmiSystemAudioSupported = on; 482012307ca810e8100981b2b60e3f2c6a7e451b9774Jungshik Jang AudioSystem.setForceUse(AudioSystem.FOR_HDMI_SYSTEM_AUDIO, 482112307ca810e8100981b2b60e3f2c6a7e451b9774Jungshik Jang on ? AudioSystem.FORCE_HDMI_SYSTEM_AUDIO_ENFORCED : AudioSystem.FORCE_NONE); 48226f34f5ab8ab1b1db7887e5405d8b0031e105ab05Jungshik Jang } 48236f34f5ab8ab1b1db7887e5405d8b0031e105ab05Jungshik Jang return AudioSystem.getDevicesForStream(AudioSystem.STREAM_MUSIC); 48246f34f5ab8ab1b1db7887e5405d8b0031e105ab05Jungshik Jang } 48256f34f5ab8ab1b1db7887e5405d8b0031e105ab05Jungshik Jang 4826dd45d01128423a82652a3c9d77fa393631d95229Eric Laurent //========================================================================================== 4827dd45d01128423a82652a3c9d77fa393631d95229Eric Laurent // Camera shutter sound policy. 4828dd45d01128423a82652a3c9d77fa393631d95229Eric Laurent // config_camera_sound_forced configuration option in config.xml defines if the camera shutter 4829dd45d01128423a82652a3c9d77fa393631d95229Eric Laurent // sound is forced (sound even if the device is in silent mode) or not. This option is false by 4830dd45d01128423a82652a3c9d77fa393631d95229Eric Laurent // default and can be overridden by country specific overlay in values-mccXXX/config.xml. 4831dd45d01128423a82652a3c9d77fa393631d95229Eric Laurent //========================================================================================== 4832dd45d01128423a82652a3c9d77fa393631d95229Eric Laurent 4833dd45d01128423a82652a3c9d77fa393631d95229Eric Laurent // cached value of com.android.internal.R.bool.config_camera_sound_forced 4834dd45d01128423a82652a3c9d77fa393631d95229Eric Laurent private Boolean mCameraSoundForced; 4835dd45d01128423a82652a3c9d77fa393631d95229Eric Laurent 4836dd45d01128423a82652a3c9d77fa393631d95229Eric Laurent // called by android.hardware.Camera to populate CameraInfo.canDisableShutterSound 4837dd45d01128423a82652a3c9d77fa393631d95229Eric Laurent public boolean isCameraSoundForced() { 4838dd45d01128423a82652a3c9d77fa393631d95229Eric Laurent synchronized (mCameraSoundForced) { 4839dd45d01128423a82652a3c9d77fa393631d95229Eric Laurent return mCameraSoundForced; 4840dd45d01128423a82652a3c9d77fa393631d95229Eric Laurent } 4841dd45d01128423a82652a3c9d77fa393631d95229Eric Laurent } 4842dd45d01128423a82652a3c9d77fa393631d95229Eric Laurent 4843dd45d01128423a82652a3c9d77fa393631d95229Eric Laurent private static final String[] RINGER_MODE_NAMES = new String[] { 4844dd45d01128423a82652a3c9d77fa393631d95229Eric Laurent "SILENT", 4845dd45d01128423a82652a3c9d77fa393631d95229Eric Laurent "VIBRATE", 4846dd45d01128423a82652a3c9d77fa393631d95229Eric Laurent "NORMAL" 4847dd45d01128423a82652a3c9d77fa393631d95229Eric Laurent }; 4848dd45d01128423a82652a3c9d77fa393631d95229Eric Laurent 4849dd45d01128423a82652a3c9d77fa393631d95229Eric Laurent private void dumpRingerMode(PrintWriter pw) { 4850dd45d01128423a82652a3c9d77fa393631d95229Eric Laurent pw.println("\nRinger mode: "); 4851dd45d01128423a82652a3c9d77fa393631d95229Eric Laurent pw.println("- mode: "+RINGER_MODE_NAMES[mRingerMode]); 4852dd45d01128423a82652a3c9d77fa393631d95229Eric Laurent pw.print("- ringer mode affected streams = 0x"); 4853dd45d01128423a82652a3c9d77fa393631d95229Eric Laurent pw.println(Integer.toHexString(mRingerModeAffectedStreams)); 4854dd45d01128423a82652a3c9d77fa393631d95229Eric Laurent pw.print("- ringer mode muted streams = 0x"); 4855dd45d01128423a82652a3c9d77fa393631d95229Eric Laurent pw.println(Integer.toHexString(mRingerModeMutedStreams)); 4856dd45d01128423a82652a3c9d77fa393631d95229Eric Laurent } 4857dd45d01128423a82652a3c9d77fa393631d95229Eric Laurent 4858632ca417f0a33e3fa9ccece531afa2db3f0d4a30Dianne Hackborn @Override 4859d5176cfe6eae954e9cef1e2ec17859a5089e1330Jean-Michel Trivi protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) { 4860eb4cc492c93ab9635dde78b958a834120412e72aJeff Sharkey mContext.enforceCallingOrSelfPermission(android.Manifest.permission.DUMP, TAG); 4861eb4cc492c93ab9635dde78b958a834120412e72aJeff Sharkey 4862fa9a69805b001034aa04c3b33989a7ac21522371Jean-Michel Trivi mMediaFocusControl.dump(pw); 4863bffc3d1bd33eb2d8e00a9f8b6261d815db503311Eric Laurent dumpStreamStates(pw); 4864dd45d01128423a82652a3c9d77fa393631d95229Eric Laurent dumpRingerMode(pw); 4865632ca417f0a33e3fa9ccece531afa2db3f0d4a30Dianne Hackborn pw.println("\nAudio routes:"); 4866632ca417f0a33e3fa9ccece531afa2db3f0d4a30Dianne Hackborn pw.print(" mMainType=0x"); pw.println(Integer.toHexString(mCurAudioRoutes.mMainType)); 4867632ca417f0a33e3fa9ccece531afa2db3f0d4a30Dianne Hackborn pw.print(" mBluetoothName="); pw.println(mCurAudioRoutes.mBluetoothName); 48683346a802087f621c6441bc512dfcc17b07143fc6John Spurlock pw.print(" mVolumeController="); pw.println(mVolumeController); 4869d5176cfe6eae954e9cef1e2ec17859a5089e1330Jean-Michel Trivi } 4870fd116ad1ab02f6060a0b2201f018317fa32e28b4Glenn Kasten 4871fd116ad1ab02f6060a0b2201f018317fa32e28b4Glenn Kasten // Inform AudioFlinger of our device's low RAM attribute 4872fd116ad1ab02f6060a0b2201f018317fa32e28b4Glenn Kasten private static void readAndSetLowRamDevice() 4873fd116ad1ab02f6060a0b2201f018317fa32e28b4Glenn Kasten { 4874fd116ad1ab02f6060a0b2201f018317fa32e28b4Glenn Kasten int status = AudioSystem.setLowRamDevice(ActivityManager.isLowRamDeviceStatic()); 4875fd116ad1ab02f6060a0b2201f018317fa32e28b4Glenn Kasten if (status != 0) { 4876fd116ad1ab02f6060a0b2201f018317fa32e28b4Glenn Kasten Log.w(TAG, "AudioFlinger informed of device's low RAM attribute; status " + status); 4877fd116ad1ab02f6060a0b2201f018317fa32e28b4Glenn Kasten } 4878fd116ad1ab02f6060a0b2201f018317fa32e28b4Glenn Kasten } 48793346a802087f621c6441bc512dfcc17b07143fc6John Spurlock 48803346a802087f621c6441bc512dfcc17b07143fc6John Spurlock private void enforceSelfOrSystemUI(String action) { 48813346a802087f621c6441bc512dfcc17b07143fc6John Spurlock mContext.enforceCallingOrSelfPermission(android.Manifest.permission.STATUS_BAR_SERVICE, 48823346a802087f621c6441bc512dfcc17b07143fc6John Spurlock "Only SystemUI can " + action); 48833346a802087f621c6441bc512dfcc17b07143fc6John Spurlock } 48843346a802087f621c6441bc512dfcc17b07143fc6John Spurlock 48853346a802087f621c6441bc512dfcc17b07143fc6John Spurlock @Override 48863346a802087f621c6441bc512dfcc17b07143fc6John Spurlock public void setVolumeController(final IVolumeController controller) { 48873346a802087f621c6441bc512dfcc17b07143fc6John Spurlock enforceSelfOrSystemUI("set the volume controller"); 48883346a802087f621c6441bc512dfcc17b07143fc6John Spurlock 48893346a802087f621c6441bc512dfcc17b07143fc6John Spurlock // return early if things are not actually changing 48903346a802087f621c6441bc512dfcc17b07143fc6John Spurlock if (mVolumeController.isSameBinder(controller)) { 48913346a802087f621c6441bc512dfcc17b07143fc6John Spurlock return; 48923346a802087f621c6441bc512dfcc17b07143fc6John Spurlock } 48933346a802087f621c6441bc512dfcc17b07143fc6John Spurlock 48943346a802087f621c6441bc512dfcc17b07143fc6John Spurlock // dismiss the old volume controller 48953346a802087f621c6441bc512dfcc17b07143fc6John Spurlock mVolumeController.postDismiss(); 48963346a802087f621c6441bc512dfcc17b07143fc6John Spurlock if (controller != null) { 48973346a802087f621c6441bc512dfcc17b07143fc6John Spurlock // we are about to register a new controller, listen for its death 48983346a802087f621c6441bc512dfcc17b07143fc6John Spurlock try { 48993346a802087f621c6441bc512dfcc17b07143fc6John Spurlock controller.asBinder().linkToDeath(new DeathRecipient() { 49003346a802087f621c6441bc512dfcc17b07143fc6John Spurlock @Override 49013346a802087f621c6441bc512dfcc17b07143fc6John Spurlock public void binderDied() { 49023346a802087f621c6441bc512dfcc17b07143fc6John Spurlock if (mVolumeController.isSameBinder(controller)) { 49033346a802087f621c6441bc512dfcc17b07143fc6John Spurlock Log.w(TAG, "Current remote volume controller died, unregistering"); 49043346a802087f621c6441bc512dfcc17b07143fc6John Spurlock setVolumeController(null); 49053346a802087f621c6441bc512dfcc17b07143fc6John Spurlock } 49063346a802087f621c6441bc512dfcc17b07143fc6John Spurlock } 49073346a802087f621c6441bc512dfcc17b07143fc6John Spurlock }, 0); 49083346a802087f621c6441bc512dfcc17b07143fc6John Spurlock } catch (RemoteException e) { 49093346a802087f621c6441bc512dfcc17b07143fc6John Spurlock // noop 49103346a802087f621c6441bc512dfcc17b07143fc6John Spurlock } 49113346a802087f621c6441bc512dfcc17b07143fc6John Spurlock } 49123346a802087f621c6441bc512dfcc17b07143fc6John Spurlock mVolumeController.setController(controller); 491333f4e04e32fac42f158733d6a731e50490fa9951John Spurlock if (DEBUG_VOL) Log.d(TAG, "Volume controller: " + mVolumeController); 491433f4e04e32fac42f158733d6a731e50490fa9951John Spurlock } 491533f4e04e32fac42f158733d6a731e50490fa9951John Spurlock 491633f4e04e32fac42f158733d6a731e50490fa9951John Spurlock @Override 491733f4e04e32fac42f158733d6a731e50490fa9951John Spurlock public void notifyVolumeControllerVisible(final IVolumeController controller, boolean visible) { 491833f4e04e32fac42f158733d6a731e50490fa9951John Spurlock enforceSelfOrSystemUI("notify about volume controller visibility"); 491933f4e04e32fac42f158733d6a731e50490fa9951John Spurlock 492033f4e04e32fac42f158733d6a731e50490fa9951John Spurlock // return early if the controller is not current 492133f4e04e32fac42f158733d6a731e50490fa9951John Spurlock if (!mVolumeController.isSameBinder(controller)) { 492233f4e04e32fac42f158733d6a731e50490fa9951John Spurlock return; 492333f4e04e32fac42f158733d6a731e50490fa9951John Spurlock } 492433f4e04e32fac42f158733d6a731e50490fa9951John Spurlock 492533f4e04e32fac42f158733d6a731e50490fa9951John Spurlock mVolumeController.setVisible(visible); 492633f4e04e32fac42f158733d6a731e50490fa9951John Spurlock if (DEBUG_VOL) Log.d(TAG, "Volume controller visible: " + visible); 49273346a802087f621c6441bc512dfcc17b07143fc6John Spurlock } 4928d09bd0c6eb8318e0122b14d7eb5324e481706e41RoboErik 4929d09bd0c6eb8318e0122b14d7eb5324e481706e41RoboErik public static class VolumeController { 4930d09bd0c6eb8318e0122b14d7eb5324e481706e41RoboErik private static final String TAG = "VolumeController"; 4931d09bd0c6eb8318e0122b14d7eb5324e481706e41RoboErik 4932d09bd0c6eb8318e0122b14d7eb5324e481706e41RoboErik private IVolumeController mController; 493333f4e04e32fac42f158733d6a731e50490fa9951John Spurlock private boolean mVisible; 493433f4e04e32fac42f158733d6a731e50490fa9951John Spurlock private long mNextLongPress; 493533f4e04e32fac42f158733d6a731e50490fa9951John Spurlock private int mLongPressTimeout; 4936d09bd0c6eb8318e0122b14d7eb5324e481706e41RoboErik 4937d09bd0c6eb8318e0122b14d7eb5324e481706e41RoboErik public void setController(IVolumeController controller) { 4938d09bd0c6eb8318e0122b14d7eb5324e481706e41RoboErik mController = controller; 493933f4e04e32fac42f158733d6a731e50490fa9951John Spurlock mVisible = false; 494033f4e04e32fac42f158733d6a731e50490fa9951John Spurlock } 494133f4e04e32fac42f158733d6a731e50490fa9951John Spurlock 494233f4e04e32fac42f158733d6a731e50490fa9951John Spurlock public void loadSettings(ContentResolver cr) { 494333f4e04e32fac42f158733d6a731e50490fa9951John Spurlock mLongPressTimeout = Settings.Secure.getIntForUser(cr, 494433f4e04e32fac42f158733d6a731e50490fa9951John Spurlock Settings.Secure.LONG_PRESS_TIMEOUT, 500, UserHandle.USER_CURRENT); 494533f4e04e32fac42f158733d6a731e50490fa9951John Spurlock } 494633f4e04e32fac42f158733d6a731e50490fa9951John Spurlock 494733f4e04e32fac42f158733d6a731e50490fa9951John Spurlock public boolean suppressAdjustment(int resolvedStream, int flags) { 494833f4e04e32fac42f158733d6a731e50490fa9951John Spurlock boolean suppress = false; 494933f4e04e32fac42f158733d6a731e50490fa9951John Spurlock if (resolvedStream == AudioSystem.STREAM_RING && mController != null) { 495033f4e04e32fac42f158733d6a731e50490fa9951John Spurlock final long now = SystemClock.uptimeMillis(); 495133f4e04e32fac42f158733d6a731e50490fa9951John Spurlock if ((flags & AudioManager.FLAG_SHOW_UI) != 0 && !mVisible) { 495233f4e04e32fac42f158733d6a731e50490fa9951John Spurlock // ui will become visible 495333f4e04e32fac42f158733d6a731e50490fa9951John Spurlock if (mNextLongPress < now) { 495433f4e04e32fac42f158733d6a731e50490fa9951John Spurlock mNextLongPress = now + mLongPressTimeout; 495533f4e04e32fac42f158733d6a731e50490fa9951John Spurlock } 495633f4e04e32fac42f158733d6a731e50490fa9951John Spurlock suppress = true; 495733f4e04e32fac42f158733d6a731e50490fa9951John Spurlock } else if (mNextLongPress > 0) { // in a long-press 495833f4e04e32fac42f158733d6a731e50490fa9951John Spurlock if (now > mNextLongPress) { 495933f4e04e32fac42f158733d6a731e50490fa9951John Spurlock // long press triggered, no more suppression 496033f4e04e32fac42f158733d6a731e50490fa9951John Spurlock mNextLongPress = 0; 496133f4e04e32fac42f158733d6a731e50490fa9951John Spurlock } else { 496233f4e04e32fac42f158733d6a731e50490fa9951John Spurlock // keep suppressing until the long press triggers 496333f4e04e32fac42f158733d6a731e50490fa9951John Spurlock suppress = true; 496433f4e04e32fac42f158733d6a731e50490fa9951John Spurlock } 496533f4e04e32fac42f158733d6a731e50490fa9951John Spurlock } 496633f4e04e32fac42f158733d6a731e50490fa9951John Spurlock } 496733f4e04e32fac42f158733d6a731e50490fa9951John Spurlock return suppress; 496833f4e04e32fac42f158733d6a731e50490fa9951John Spurlock } 496933f4e04e32fac42f158733d6a731e50490fa9951John Spurlock 497033f4e04e32fac42f158733d6a731e50490fa9951John Spurlock public void setVisible(boolean visible) { 497133f4e04e32fac42f158733d6a731e50490fa9951John Spurlock mVisible = visible; 4972d09bd0c6eb8318e0122b14d7eb5324e481706e41RoboErik } 4973d09bd0c6eb8318e0122b14d7eb5324e481706e41RoboErik 4974d09bd0c6eb8318e0122b14d7eb5324e481706e41RoboErik public boolean isSameBinder(IVolumeController controller) { 4975d09bd0c6eb8318e0122b14d7eb5324e481706e41RoboErik return Objects.equals(asBinder(), binder(controller)); 4976d09bd0c6eb8318e0122b14d7eb5324e481706e41RoboErik } 4977d09bd0c6eb8318e0122b14d7eb5324e481706e41RoboErik 4978d09bd0c6eb8318e0122b14d7eb5324e481706e41RoboErik public IBinder asBinder() { 4979d09bd0c6eb8318e0122b14d7eb5324e481706e41RoboErik return binder(mController); 4980d09bd0c6eb8318e0122b14d7eb5324e481706e41RoboErik } 4981d09bd0c6eb8318e0122b14d7eb5324e481706e41RoboErik 4982d09bd0c6eb8318e0122b14d7eb5324e481706e41RoboErik private static IBinder binder(IVolumeController controller) { 4983d09bd0c6eb8318e0122b14d7eb5324e481706e41RoboErik return controller == null ? null : controller.asBinder(); 4984d09bd0c6eb8318e0122b14d7eb5324e481706e41RoboErik } 4985d09bd0c6eb8318e0122b14d7eb5324e481706e41RoboErik 4986d09bd0c6eb8318e0122b14d7eb5324e481706e41RoboErik @Override 4987d09bd0c6eb8318e0122b14d7eb5324e481706e41RoboErik public String toString() { 498833f4e04e32fac42f158733d6a731e50490fa9951John Spurlock return "VolumeController(" + asBinder() + ",mVisible=" + mVisible + ")"; 4989d09bd0c6eb8318e0122b14d7eb5324e481706e41RoboErik } 4990d09bd0c6eb8318e0122b14d7eb5324e481706e41RoboErik 4991d09bd0c6eb8318e0122b14d7eb5324e481706e41RoboErik public void postDisplaySafeVolumeWarning(int flags) { 4992d09bd0c6eb8318e0122b14d7eb5324e481706e41RoboErik if (mController == null) 4993d09bd0c6eb8318e0122b14d7eb5324e481706e41RoboErik return; 4994d09bd0c6eb8318e0122b14d7eb5324e481706e41RoboErik try { 4995d09bd0c6eb8318e0122b14d7eb5324e481706e41RoboErik mController.displaySafeVolumeWarning(flags); 4996d09bd0c6eb8318e0122b14d7eb5324e481706e41RoboErik } catch (RemoteException e) { 4997d09bd0c6eb8318e0122b14d7eb5324e481706e41RoboErik Log.w(TAG, "Error calling displaySafeVolumeWarning", e); 4998d09bd0c6eb8318e0122b14d7eb5324e481706e41RoboErik } 4999d09bd0c6eb8318e0122b14d7eb5324e481706e41RoboErik } 5000d09bd0c6eb8318e0122b14d7eb5324e481706e41RoboErik 5001d09bd0c6eb8318e0122b14d7eb5324e481706e41RoboErik public void postVolumeChanged(int streamType, int flags) { 5002d09bd0c6eb8318e0122b14d7eb5324e481706e41RoboErik if (mController == null) 5003d09bd0c6eb8318e0122b14d7eb5324e481706e41RoboErik return; 5004d09bd0c6eb8318e0122b14d7eb5324e481706e41RoboErik try { 5005d09bd0c6eb8318e0122b14d7eb5324e481706e41RoboErik mController.volumeChanged(streamType, flags); 5006d09bd0c6eb8318e0122b14d7eb5324e481706e41RoboErik } catch (RemoteException e) { 5007d09bd0c6eb8318e0122b14d7eb5324e481706e41RoboErik Log.w(TAG, "Error calling volumeChanged", e); 5008d09bd0c6eb8318e0122b14d7eb5324e481706e41RoboErik } 5009d09bd0c6eb8318e0122b14d7eb5324e481706e41RoboErik } 5010d09bd0c6eb8318e0122b14d7eb5324e481706e41RoboErik 5011d09bd0c6eb8318e0122b14d7eb5324e481706e41RoboErik public void postMasterVolumeChanged(int flags) { 5012d09bd0c6eb8318e0122b14d7eb5324e481706e41RoboErik if (mController == null) 5013d09bd0c6eb8318e0122b14d7eb5324e481706e41RoboErik return; 5014d09bd0c6eb8318e0122b14d7eb5324e481706e41RoboErik try { 5015d09bd0c6eb8318e0122b14d7eb5324e481706e41RoboErik mController.masterVolumeChanged(flags); 5016d09bd0c6eb8318e0122b14d7eb5324e481706e41RoboErik } catch (RemoteException e) { 5017d09bd0c6eb8318e0122b14d7eb5324e481706e41RoboErik Log.w(TAG, "Error calling masterVolumeChanged", e); 5018d09bd0c6eb8318e0122b14d7eb5324e481706e41RoboErik } 5019d09bd0c6eb8318e0122b14d7eb5324e481706e41RoboErik } 5020d09bd0c6eb8318e0122b14d7eb5324e481706e41RoboErik 5021d09bd0c6eb8318e0122b14d7eb5324e481706e41RoboErik public void postMasterMuteChanged(int flags) { 5022d09bd0c6eb8318e0122b14d7eb5324e481706e41RoboErik if (mController == null) 5023d09bd0c6eb8318e0122b14d7eb5324e481706e41RoboErik return; 5024d09bd0c6eb8318e0122b14d7eb5324e481706e41RoboErik try { 5025d09bd0c6eb8318e0122b14d7eb5324e481706e41RoboErik mController.masterMuteChanged(flags); 5026d09bd0c6eb8318e0122b14d7eb5324e481706e41RoboErik } catch (RemoteException e) { 5027d09bd0c6eb8318e0122b14d7eb5324e481706e41RoboErik Log.w(TAG, "Error calling masterMuteChanged", e); 5028d09bd0c6eb8318e0122b14d7eb5324e481706e41RoboErik } 5029d09bd0c6eb8318e0122b14d7eb5324e481706e41RoboErik } 5030d09bd0c6eb8318e0122b14d7eb5324e481706e41RoboErik 5031d09bd0c6eb8318e0122b14d7eb5324e481706e41RoboErik public void setLayoutDirection(int layoutDirection) { 5032d09bd0c6eb8318e0122b14d7eb5324e481706e41RoboErik if (mController == null) 5033d09bd0c6eb8318e0122b14d7eb5324e481706e41RoboErik return; 5034d09bd0c6eb8318e0122b14d7eb5324e481706e41RoboErik try { 5035d09bd0c6eb8318e0122b14d7eb5324e481706e41RoboErik mController.setLayoutDirection(layoutDirection); 5036d09bd0c6eb8318e0122b14d7eb5324e481706e41RoboErik } catch (RemoteException e) { 5037d09bd0c6eb8318e0122b14d7eb5324e481706e41RoboErik Log.w(TAG, "Error calling setLayoutDirection", e); 5038d09bd0c6eb8318e0122b14d7eb5324e481706e41RoboErik } 5039d09bd0c6eb8318e0122b14d7eb5324e481706e41RoboErik } 5040d09bd0c6eb8318e0122b14d7eb5324e481706e41RoboErik 5041d09bd0c6eb8318e0122b14d7eb5324e481706e41RoboErik public void postDismiss() { 5042d09bd0c6eb8318e0122b14d7eb5324e481706e41RoboErik if (mController == null) 5043d09bd0c6eb8318e0122b14d7eb5324e481706e41RoboErik return; 5044d09bd0c6eb8318e0122b14d7eb5324e481706e41RoboErik try { 5045d09bd0c6eb8318e0122b14d7eb5324e481706e41RoboErik mController.dismiss(); 5046d09bd0c6eb8318e0122b14d7eb5324e481706e41RoboErik } catch (RemoteException e) { 5047d09bd0c6eb8318e0122b14d7eb5324e481706e41RoboErik Log.w(TAG, "Error calling dismiss", e); 5048d09bd0c6eb8318e0122b14d7eb5324e481706e41RoboErik } 5049d09bd0c6eb8318e0122b14d7eb5324e481706e41RoboErik } 5050d09bd0c6eb8318e0122b14d7eb5324e481706e41RoboErik } 5051a8b6bd88cfb010c9e9aa1339e504fd593919e1e0Jean-Michel Trivi 5052a8b6bd88cfb010c9e9aa1339e504fd593919e1e0Jean-Michel Trivi //========================================================================================== 5053a8b6bd88cfb010c9e9aa1339e504fd593919e1e0Jean-Michel Trivi // Audio policy management 5054a8b6bd88cfb010c9e9aa1339e504fd593919e1e0Jean-Michel Trivi //========================================================================================== 5055a8b6bd88cfb010c9e9aa1339e504fd593919e1e0Jean-Michel Trivi public boolean registerAudioPolicy(AudioPolicyConfig policyConfig, IBinder cb) { 5056a8b6bd88cfb010c9e9aa1339e504fd593919e1e0Jean-Michel Trivi //Log.v(TAG, "registerAudioPolicy for " + cb + " got policy:" + policyConfig); 5057a8b6bd88cfb010c9e9aa1339e504fd593919e1e0Jean-Michel Trivi boolean hasPermissionForPolicy = 5058a8b6bd88cfb010c9e9aa1339e504fd593919e1e0Jean-Michel Trivi (PackageManager.PERMISSION_GRANTED == mContext.checkCallingOrSelfPermission( 5059a8b6bd88cfb010c9e9aa1339e504fd593919e1e0Jean-Michel Trivi android.Manifest.permission.MODIFY_AUDIO_ROUTING)); 5060a8b6bd88cfb010c9e9aa1339e504fd593919e1e0Jean-Michel Trivi if (!hasPermissionForPolicy) { 5061a8b6bd88cfb010c9e9aa1339e504fd593919e1e0Jean-Michel Trivi Slog.w(TAG, "Can't register audio policy for pid " + Binder.getCallingPid() + " / uid " 5062a8b6bd88cfb010c9e9aa1339e504fd593919e1e0Jean-Michel Trivi + Binder.getCallingUid() + ", need MODIFY_AUDIO_ROUTING"); 5063a8b6bd88cfb010c9e9aa1339e504fd593919e1e0Jean-Michel Trivi return false; 5064a8b6bd88cfb010c9e9aa1339e504fd593919e1e0Jean-Michel Trivi } 5065a8b6bd88cfb010c9e9aa1339e504fd593919e1e0Jean-Michel Trivi synchronized (mAudioPolicies) { 5066a8b6bd88cfb010c9e9aa1339e504fd593919e1e0Jean-Michel Trivi AudioPolicyProxy app = new AudioPolicyProxy(policyConfig, cb); 5067a8b6bd88cfb010c9e9aa1339e504fd593919e1e0Jean-Michel Trivi try { 5068a8b6bd88cfb010c9e9aa1339e504fd593919e1e0Jean-Michel Trivi cb.linkToDeath(app, 0/*flags*/); 5069a8b6bd88cfb010c9e9aa1339e504fd593919e1e0Jean-Michel Trivi mAudioPolicies.put(cb, app); 5070a8b6bd88cfb010c9e9aa1339e504fd593919e1e0Jean-Michel Trivi } catch (RemoteException e) { 5071a8b6bd88cfb010c9e9aa1339e504fd593919e1e0Jean-Michel Trivi // audio policy owner has already died! 5072a8b6bd88cfb010c9e9aa1339e504fd593919e1e0Jean-Michel Trivi Slog.w(TAG, "Audio policy registration failed, could not link to " + cb + 5073a8b6bd88cfb010c9e9aa1339e504fd593919e1e0Jean-Michel Trivi " binder death", e); 5074a8b6bd88cfb010c9e9aa1339e504fd593919e1e0Jean-Michel Trivi return false; 5075a8b6bd88cfb010c9e9aa1339e504fd593919e1e0Jean-Michel Trivi } 5076a8b6bd88cfb010c9e9aa1339e504fd593919e1e0Jean-Michel Trivi } 5077a8b6bd88cfb010c9e9aa1339e504fd593919e1e0Jean-Michel Trivi // TODO implement registration with native audio policy (including permission check) 5078a8b6bd88cfb010c9e9aa1339e504fd593919e1e0Jean-Michel Trivi return true; 5079a8b6bd88cfb010c9e9aa1339e504fd593919e1e0Jean-Michel Trivi } 5080a8b6bd88cfb010c9e9aa1339e504fd593919e1e0Jean-Michel Trivi public void unregisterAudioPolicyAsync(IBinder cb) { 5081a8b6bd88cfb010c9e9aa1339e504fd593919e1e0Jean-Michel Trivi synchronized (mAudioPolicies) { 5082a8b6bd88cfb010c9e9aa1339e504fd593919e1e0Jean-Michel Trivi AudioPolicyProxy app = mAudioPolicies.remove(cb); 5083a8b6bd88cfb010c9e9aa1339e504fd593919e1e0Jean-Michel Trivi if (app == null) { 5084a8b6bd88cfb010c9e9aa1339e504fd593919e1e0Jean-Michel Trivi Slog.w(TAG, "Trying to unregister unknown audio policy for pid " 5085a8b6bd88cfb010c9e9aa1339e504fd593919e1e0Jean-Michel Trivi + Binder.getCallingPid() + " / uid " + Binder.getCallingUid()); 5086a8b6bd88cfb010c9e9aa1339e504fd593919e1e0Jean-Michel Trivi } else { 5087a8b6bd88cfb010c9e9aa1339e504fd593919e1e0Jean-Michel Trivi cb.unlinkToDeath(app, 0/*flags*/); 5088a8b6bd88cfb010c9e9aa1339e504fd593919e1e0Jean-Michel Trivi } 5089a8b6bd88cfb010c9e9aa1339e504fd593919e1e0Jean-Michel Trivi } 5090a8b6bd88cfb010c9e9aa1339e504fd593919e1e0Jean-Michel Trivi // TODO implement registration with native audio policy 5091a8b6bd88cfb010c9e9aa1339e504fd593919e1e0Jean-Michel Trivi } 5092a8b6bd88cfb010c9e9aa1339e504fd593919e1e0Jean-Michel Trivi 5093a8b6bd88cfb010c9e9aa1339e504fd593919e1e0Jean-Michel Trivi public class AudioPolicyProxy implements IBinder.DeathRecipient { 5094a8b6bd88cfb010c9e9aa1339e504fd593919e1e0Jean-Michel Trivi private static final String TAG = "AudioPolicyProxy"; 5095a8b6bd88cfb010c9e9aa1339e504fd593919e1e0Jean-Michel Trivi AudioPolicyConfig mConfig; 5096a8b6bd88cfb010c9e9aa1339e504fd593919e1e0Jean-Michel Trivi IBinder mToken; 5097a8b6bd88cfb010c9e9aa1339e504fd593919e1e0Jean-Michel Trivi AudioPolicyProxy(AudioPolicyConfig config, IBinder token) { 5098a8b6bd88cfb010c9e9aa1339e504fd593919e1e0Jean-Michel Trivi mConfig = config; 5099a8b6bd88cfb010c9e9aa1339e504fd593919e1e0Jean-Michel Trivi mToken = token; 5100a8b6bd88cfb010c9e9aa1339e504fd593919e1e0Jean-Michel Trivi } 5101a8b6bd88cfb010c9e9aa1339e504fd593919e1e0Jean-Michel Trivi 5102a8b6bd88cfb010c9e9aa1339e504fd593919e1e0Jean-Michel Trivi public void binderDied() { 5103a8b6bd88cfb010c9e9aa1339e504fd593919e1e0Jean-Michel Trivi synchronized (mAudioPolicies) { 5104a8b6bd88cfb010c9e9aa1339e504fd593919e1e0Jean-Michel Trivi Log.v(TAG, "audio policy " + mToken + " died"); 5105a8b6bd88cfb010c9e9aa1339e504fd593919e1e0Jean-Michel Trivi mAudioPolicies.remove(mToken); 5106a8b6bd88cfb010c9e9aa1339e504fd593919e1e0Jean-Michel Trivi } 5107a8b6bd88cfb010c9e9aa1339e504fd593919e1e0Jean-Michel Trivi } 5108a8b6bd88cfb010c9e9aa1339e504fd593919e1e0Jean-Michel Trivi }; 5109a8b6bd88cfb010c9e9aa1339e504fd593919e1e0Jean-Michel Trivi 5110a8b6bd88cfb010c9e9aa1339e504fd593919e1e0Jean-Michel Trivi private HashMap<IBinder, AudioPolicyProxy> mAudioPolicies = 5111a8b6bd88cfb010c9e9aa1339e504fd593919e1e0Jean-Michel Trivi new HashMap<IBinder, AudioPolicyProxy>(); 51129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} 5113