AudioService.java revision fb917e019f04d60f4924114fe2684c0d67981af6
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; 46c837a451946b64d70ed7c642fbde03c182c28b6fPaul McLeanimport android.hardware.usb.UsbManager; 479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.media.MediaPlayer.OnCompletionListener; 489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.media.MediaPlayer.OnErrorListener; 498a2cfc309ab9126e90022916967c65a793c034f0RoboErikimport android.media.session.MediaSessionLegacyHelper; 509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.os.Binder; 51c18c9138cee0f0859bcab636a004ce92ca4a9ab5Eric Laurentimport android.os.Build; 529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.os.Environment; 539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.os.Handler; 549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.os.IBinder; 559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.os.Looper; 569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.os.Message; 57c68022258ebd3dd97a5079ba99f4f3cd12b223b0Jean-Michel Triviimport android.os.PowerManager; 58632ca417f0a33e3fa9ccece531afa2db3f0d4a30Dianne Hackbornimport android.os.RemoteCallbackList; 599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.os.RemoteException; 609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.os.ServiceManager; 6182aa7f017daaaeb96c13e6e3491d5037ab471085Jaikumar Ganeshimport android.os.SystemProperties; 625ac72a29593ab9a20337a2225df52bdf4754be02Dianne Hackbornimport android.os.UserHandle; 63bffc3d1bd33eb2d8e00a9f8b6261d815db503311Eric Laurentimport android.os.Vibrator; 649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.provider.Settings; 659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.provider.Settings.System; 66632ca417f0a33e3fa9ccece531afa2db3f0d4a30Dianne Hackbornimport android.text.TextUtils; 679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.util.Log; 68d327f21626217aa3c9c0cdb7a84a742c531e59a3Jean-Michel Triviimport android.view.KeyEvent; 69bb6f8711a7f804d39c45218db2d6339940cc5d35Jean-Michel Triviimport android.view.Surface; 70bb6f8711a7f804d39c45218db2d6339940cc5d35Jean-Michel Triviimport android.view.WindowManager; 719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport com.android.internal.telephony.ITelephony; 73e78fced559d879b2e37b610d0d9a89daf08f0f2bEric Laurentimport com.android.internal.util.XmlUtils; 74e78fced559d879b2e37b610d0d9a89daf08f0f2bEric Laurent 75e78fced559d879b2e37b610d0d9a89daf08f0f2bEric Laurentimport org.xmlpull.v1.XmlPullParserException; 769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 77d5176cfe6eae954e9cef1e2ec17859a5089e1330Jean-Michel Triviimport java.io.FileDescriptor; 789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport java.io.IOException; 79d5176cfe6eae954e9cef1e2ec17859a5089e1330Jean-Michel Triviimport java.io.PrintWriter; 80e78fced559d879b2e37b610d0d9a89daf08f0f2bEric Laurentimport java.lang.reflect.Field; 819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport java.util.ArrayList; 823172d5e3e7520a745fa37b71fc1c7bf244b57085Eric Laurentimport java.util.concurrent.ConcurrentHashMap; 83c42ac9d4d03f62c3a1ba197a28a81fda44bd8b7fEric Laurentimport java.util.HashMap; 84c42ac9d4d03f62c3a1ba197a28a81fda44bd8b7fEric Laurentimport java.util.Iterator; 855a1e4cf83f5be1b5d79e2643fa791aa269b6a4bcJaikumar Ganeshimport java.util.List; 86c42ac9d4d03f62c3a1ba197a28a81fda44bd8b7fEric Laurentimport java.util.Map; 8782aa7f017daaaeb96c13e6e3491d5037ab471085Jaikumar Ganeshimport java.util.NoSuchElementException; 88d09bd0c6eb8318e0122b14d7eb5324e481706e41RoboErikimport java.util.Objects; 89c42ac9d4d03f62c3a1ba197a28a81fda44bd8b7fEric Laurentimport java.util.Set; 909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/** 929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * The implementation of the volume manager service. 939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * <p> 949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * This implementation focuses on delivering a responsive UI. Most methods are 959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * asynchronous to external calls. For example, the task of setting a volume 969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * will update our internal state, but in a separate thread will set the system 979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * volume and later persist to the database. Similarly, setting the ringer mode 989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * will update the state and broadcast a change and in a separate thread later 999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * persist the ringer mode. 1009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 1019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @hide 1029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 103fa9a69805b001034aa04c3b33989a7ac21522371Jean-Michel Trivipublic class AudioService extends IAudioService.Stub { 1049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private static final String TAG = "AudioService"; 1069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 10718e7bce52318f00b5023f33933a571c477f2b61cJean-Michel Trivi /** Debug remote control client/display feature */ 1087ff866e8cf43afc64111e98863dab549b57447b4Jean-Michel Trivi protected static final boolean DEBUG_RC = false; 1093114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi /** Debug volumes */ 1103114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi protected static final boolean DEBUG_VOL = false; 11118e7bce52318f00b5023f33933a571c477f2b61cJean-Michel Trivi 112430fc48865e5a371b08f180390946b96d73848feRoboErik /** debug calls to media session apis */ 1138a2cfc309ab9126e90022916967c65a793c034f0RoboErik private static final boolean DEBUG_SESSIONS = true; 1148a2cfc309ab9126e90022916967c65a793c034f0RoboErik 1158600534df66c2ff5846ed230b50c56229322d48aJohn Spurlock /** Allow volume changes to set ringer mode to silent? */ 1168600534df66c2ff5846ed230b50c56229322d48aJohn Spurlock private static final boolean VOLUME_SETS_RINGER_MODE_SILENT = false; 1178600534df66c2ff5846ed230b50c56229322d48aJohn Spurlock 118a11b4affcad3d255aa723a89b768ea222506f2e8John Spurlock /** In silent mode, are volume adjustments (raises) prevented? */ 119a11b4affcad3d255aa723a89b768ea222506f2e8John Spurlock private static final boolean PREVENT_VOLUME_ADJUSTMENT_IF_SILENT = true; 120a11b4affcad3d255aa723a89b768ea222506f2e8John Spurlock 1219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** How long to delay before persisting a change in volume/ringer mode. */ 12245edba1b8b0377dfe70a4f2b0afb0f04dd8e1ee9RoboErik private static final int PERSIST_DELAY = 500; 1239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1243346a802087f621c6441bc512dfcc17b07143fc6John Spurlock /** 1253346a802087f621c6441bc512dfcc17b07143fc6John Spurlock * The delay before playing a sound. This small period exists so the user 1263346a802087f621c6441bc512dfcc17b07143fc6John Spurlock * can press another key (non-volume keys, too) to have it NOT be audible. 1273346a802087f621c6441bc512dfcc17b07143fc6John Spurlock * <p> 1283346a802087f621c6441bc512dfcc17b07143fc6John Spurlock * PhoneWindow will implement this part. 1293346a802087f621c6441bc512dfcc17b07143fc6John Spurlock */ 1303346a802087f621c6441bc512dfcc17b07143fc6John Spurlock public static final int PLAY_SOUND_DELAY = 300; 1313346a802087f621c6441bc512dfcc17b07143fc6John Spurlock 132a11b4affcad3d255aa723a89b768ea222506f2e8John Spurlock /** 133a11b4affcad3d255aa723a89b768ea222506f2e8John Spurlock * Only used in the result from {@link #checkForRingerModeChange(int, int, int)} 134a11b4affcad3d255aa723a89b768ea222506f2e8John Spurlock */ 135a11b4affcad3d255aa723a89b768ea222506f2e8John Spurlock private static final int FLAG_ADJUST_VOLUME = 1; 136a11b4affcad3d255aa723a89b768ea222506f2e8John Spurlock 137ba50b97cff80e73620a0e3d13cae169e095974a7Dianne Hackborn private final Context mContext; 138ba50b97cff80e73620a0e3d13cae169e095974a7Dianne Hackborn private final ContentResolver mContentResolver; 139ba50b97cff80e73620a0e3d13cae169e095974a7Dianne Hackborn private final AppOpsManager mAppOps; 140ba50b97cff80e73620a0e3d13cae169e095974a7Dianne Hackborn private final boolean mVoiceCapable; 141d5176cfe6eae954e9cef1e2ec17859a5089e1330Jean-Michel Trivi 1423346a802087f621c6441bc512dfcc17b07143fc6John Spurlock /** The controller for the volume UI. */ 1433346a802087f621c6441bc512dfcc17b07143fc6John Spurlock private final VolumeController mVolumeController = new VolumeController(); 1449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // sendMsg() flags 1469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** If the msg is already queued, replace it with this one. */ 1479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private static final int SENDMSG_REPLACE = 0; 1489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** If the msg is already queued, ignore this one and leave the old. */ 1499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private static final int SENDMSG_NOOP = 1; 1509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** If the msg is already queued, queue this one and leave the old. */ 1519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private static final int SENDMSG_QUEUE = 2; 1529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1533114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi // AudioHandler messages 1549bc8358ddaa01c3490f9709991989633a6a3dd42Eric Laurent private static final int MSG_SET_DEVICE_VOLUME = 0; 1559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private static final int MSG_PERSIST_VOLUME = 1; 1565c55a051ad7d86a464fb91426f1ea3c0250e38b3Mike Lockwood private static final int MSG_PERSIST_MASTER_VOLUME = 2; 1579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private static final int MSG_PERSIST_RINGER_MODE = 3; 158bffc3d1bd33eb2d8e00a9f8b6261d815db503311Eric Laurent private static final int MSG_MEDIA_SERVER_DIED = 4; 159dfb881f96af7898151940a4bbc52e45e6043d38bEric Laurent private static final int MSG_PLAY_SOUND_EFFECT = 5; 160dfb881f96af7898151940a4bbc52e45e6043d38bEric Laurent private static final int MSG_BTA2DP_DOCK_TIMEOUT = 6; 161dfb881f96af7898151940a4bbc52e45e6043d38bEric Laurent private static final int MSG_LOAD_SOUND_EFFECTS = 7; 162dfb881f96af7898151940a4bbc52e45e6043d38bEric Laurent private static final int MSG_SET_FORCE_USE = 8; 163dfb881f96af7898151940a4bbc52e45e6043d38bEric Laurent private static final int MSG_BT_HEADSET_CNCT_FAILED = 9; 164dfb881f96af7898151940a4bbc52e45e6043d38bEric Laurent private static final int MSG_SET_ALL_VOLUMES = 10; 165dfb881f96af7898151940a4bbc52e45e6043d38bEric Laurent private static final int MSG_PERSIST_MASTER_VOLUME_MUTE = 11; 166dfb881f96af7898151940a4bbc52e45e6043d38bEric Laurent private static final int MSG_REPORT_NEW_ROUTES = 12; 167dfb881f96af7898151940a4bbc52e45e6043d38bEric Laurent private static final int MSG_SET_FORCE_BT_A2DP_USE = 13; 168dfb881f96af7898151940a4bbc52e45e6043d38bEric Laurent private static final int MSG_CHECK_MUSIC_ACTIVE = 14; 169dfb881f96af7898151940a4bbc52e45e6043d38bEric Laurent private static final int MSG_BROADCAST_AUDIO_BECOMING_NOISY = 15; 170dfb881f96af7898151940a4bbc52e45e6043d38bEric Laurent private static final int MSG_CONFIGURE_SAFE_MEDIA_VOLUME = 16; 171dfb881f96af7898151940a4bbc52e45e6043d38bEric Laurent private static final int MSG_CONFIGURE_SAFE_MEDIA_VOLUME_FORCED = 17; 172dfb881f96af7898151940a4bbc52e45e6043d38bEric Laurent private static final int MSG_PERSIST_SAFE_VOLUME_STATE = 18; 173dfb881f96af7898151940a4bbc52e45e6043d38bEric Laurent private static final int MSG_BROADCAST_BT_CONNECTION_STATE = 19; 174dfb881f96af7898151940a4bbc52e45e6043d38bEric Laurent private static final int MSG_UNLOAD_SOUND_EFFECTS = 20; 1754a5eeb9c727d77bb57fef87a70c8c9cc23dbfee3Eric Laurent private static final int MSG_SYSTEM_READY = 21; 1763114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi // start of messages handled under wakelock 1773114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi // these messages can only be queued, i.e. sent with queueMsgUnderWakeLock(), 178e12c39bb9cedb8b363658979872694eb55b1386eJean-Michel Trivi // and not with sendMsg(..., ..., SENDMSG_QUEUE, ...) 179fa9a69805b001034aa04c3b33989a7ac21522371Jean-Michel Trivi private static final int MSG_SET_WIRED_DEVICE_CONNECTION_STATE = 100; 1800a40ec2192e4836b2fcb6ba51a7688aa6bd4ee98Mike Lockwood private static final int MSG_SET_A2DP_SRC_CONNECTION_STATE = 101; 1810a40ec2192e4836b2fcb6ba51a7688aa6bd4ee98Mike Lockwood private static final int MSG_SET_A2DP_SINK_CONNECTION_STATE = 102; 1823114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi // end of messages handled under wakelock 183afbb047c3945e9c2b7e9bc6b25098d5fb80bba4eEric Laurent 1844c637b9e34f4c8db69a64ad21a4e2bcfa7485b5fJean-Michel Trivi private static final int BTA2DP_DOCK_TIMEOUT_MILLIS = 8000; 185dc03c61fe3cd8d0805480e48a974986439977a60Eric Laurent // Timeout for connection to bluetooth headset service 186dc03c61fe3cd8d0805480e48a974986439977a60Eric Laurent private static final int BT_HEADSET_CNCT_TIMEOUT_MS = 3000; 187dc03c61fe3cd8d0805480e48a974986439977a60Eric Laurent 1889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** @see AudioSystemThread */ 1899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private AudioSystemThread mAudioSystemThread; 1909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** @see AudioHandler */ 1919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private AudioHandler mAudioHandler; 1929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** @see VolumeStreamState */ 1939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private VolumeStreamState[] mStreamStates; 194b109615ebebd6f3b9ae789412279f576c3ace46bJason Parekh private SettingsObserver mSettingsObserver; 195a553c25b33c99b345cf1c8688f8df0ed8df14e5aEric Laurent 196fa9a69805b001034aa04c3b33989a7ac21522371Jean-Michel Trivi private int mMode = AudioSystem.MODE_NORMAL; 197ba195ebc76f23b6679443724ab58c9dc9f2df884Glenn Kasten // protects mRingerMode 198ba195ebc76f23b6679443724ab58c9dc9f2df884Glenn Kasten private final Object mSettingsLock = new Object(); 19945c90cefd13a03b852bb4b8da4be218876cbbb32Eric Laurent 2009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private SoundPool mSoundPool; 20130c918ce7fbe171944b28fc91b3f22b3d631872dGlenn Kasten private final Object mSoundEffectsLock = new Object(); 2029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private static final int NUM_SOUNDPOOL_CHANNELS = 4; 2039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2044767690f09ea3447b8c5c32fb28d27650aa18e00Mike Lockwood // Internally master volume is a float in the 0.0 - 1.0 range, 2054767690f09ea3447b8c5c32fb28d27650aa18e00Mike Lockwood // but to support integer based AudioManager API we translate it to 0 - 100 2064767690f09ea3447b8c5c32fb28d27650aa18e00Mike Lockwood private static final int MAX_MASTER_VOLUME = 100; 2074767690f09ea3447b8c5c32fb28d27650aa18e00Mike Lockwood 2086c798970ccb8759d1e613b57111daa8da0ab44c7Lei Zhang // Maximum volume adjust steps allowed in a single batch call. 2096c798970ccb8759d1e613b57111daa8da0ab44c7Lei Zhang private static final int MAX_BATCH_VOLUME_ADJUST_STEPS = 4; 2106c798970ccb8759d1e613b57111daa8da0ab44c7Lei Zhang 2119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /* Sound effect file names */ 2129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private static final String SOUND_EFFECTS_PATH = "/media/audio/ui/"; 213e78fced559d879b2e37b610d0d9a89daf08f0f2bEric Laurent private static final List<String> SOUND_EFFECT_FILES = new ArrayList<String>(); 2149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /* Sound effect file name mapping sound effect id (AudioManager.FX_xxx) to 2169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * file index in SOUND_EFFECT_FILES[] (first column) and indicating if effect 2179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * uses soundpool (second column) */ 218e78fced559d879b2e37b610d0d9a89daf08f0f2bEric Laurent private final int[][] SOUND_EFFECT_FILES_MAP = new int[AudioManager.NUM_SOUND_EFFECTS][2]; 2199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2205982013cfc8274ff0bafaba83c676b3a8890cba9Jared Suttles /** @hide Maximum volume index values for audio streams */ 221fa9a69805b001034aa04c3b33989a7ac21522371Jean-Michel Trivi private static final int[] MAX_STREAM_VOLUME = new int[] { 2226ee9952bc20be72b9419cb653c9e2e833889a3d3Eric Laurent 5, // STREAM_VOICE_CALL 2236ee9952bc20be72b9419cb653c9e2e833889a3d3Eric Laurent 7, // STREAM_SYSTEM 2246ee9952bc20be72b9419cb653c9e2e833889a3d3Eric Laurent 7, // STREAM_RING 2256ee9952bc20be72b9419cb653c9e2e833889a3d3Eric Laurent 15, // STREAM_MUSIC 2266ee9952bc20be72b9419cb653c9e2e833889a3d3Eric Laurent 7, // STREAM_ALARM 2276ee9952bc20be72b9419cb653c9e2e833889a3d3Eric Laurent 7, // STREAM_NOTIFICATION 2286ee9952bc20be72b9419cb653c9e2e833889a3d3Eric Laurent 15, // STREAM_BLUETOOTH_SCO 2296ee9952bc20be72b9419cb653c9e2e833889a3d3Eric Laurent 7, // STREAM_SYSTEM_ENFORCED 2306ee9952bc20be72b9419cb653c9e2e833889a3d3Eric Laurent 15, // STREAM_DTMF 2316ee9952bc20be72b9419cb653c9e2e833889a3d3Eric Laurent 15 // STREAM_TTS 2325982013cfc8274ff0bafaba83c676b3a8890cba9Jared Suttles }; 2336d5176638c2189595cede38fb92c3e7e8700e221Eric Laurent /* mStreamVolumeAlias[] indicates for each stream if it uses the volume settings 234a553c25b33c99b345cf1c8688f8df0ed8df14e5aEric Laurent * of another stream: This avoids multiplying the volume settings for hidden 235a553c25b33c99b345cf1c8688f8df0ed8df14e5aEric Laurent * stream types that follow other stream behavior for volume settings 2366d5176638c2189595cede38fb92c3e7e8700e221Eric Laurent * NOTE: do not create loops in aliases! 2376d5176638c2189595cede38fb92c3e7e8700e221Eric Laurent * Some streams alias to different streams according to device category (phone or tablet) or 23824e0d9b6c40712a297e4c287435a3b0fdd30e9daEric Laurent * use case (in call vs off call...). See updateStreamVolumeAlias() for more details. 2396d5176638c2189595cede38fb92c3e7e8700e221Eric Laurent * mStreamVolumeAlias contains the default aliases for a voice capable device (phone) and 2406d5176638c2189595cede38fb92c3e7e8700e221Eric Laurent * STREAM_VOLUME_ALIAS_NON_VOICE for a non voice capable device (tablet).*/ 24130c918ce7fbe171944b28fc91b3f22b3d631872dGlenn Kasten private final int[] STREAM_VOLUME_ALIAS = new int[] { 2426d5176638c2189595cede38fb92c3e7e8700e221Eric Laurent AudioSystem.STREAM_VOICE_CALL, // STREAM_VOICE_CALL 2436d5176638c2189595cede38fb92c3e7e8700e221Eric Laurent AudioSystem.STREAM_RING, // STREAM_SYSTEM 2446d5176638c2189595cede38fb92c3e7e8700e221Eric Laurent AudioSystem.STREAM_RING, // STREAM_RING 2456d5176638c2189595cede38fb92c3e7e8700e221Eric Laurent AudioSystem.STREAM_MUSIC, // STREAM_MUSIC 2466d5176638c2189595cede38fb92c3e7e8700e221Eric Laurent AudioSystem.STREAM_ALARM, // STREAM_ALARM 2476d5176638c2189595cede38fb92c3e7e8700e221Eric Laurent AudioSystem.STREAM_RING, // STREAM_NOTIFICATION 2486d5176638c2189595cede38fb92c3e7e8700e221Eric Laurent AudioSystem.STREAM_BLUETOOTH_SCO, // STREAM_BLUETOOTH_SCO 2496d5176638c2189595cede38fb92c3e7e8700e221Eric Laurent AudioSystem.STREAM_RING, // STREAM_SYSTEM_ENFORCED 2506d5176638c2189595cede38fb92c3e7e8700e221Eric Laurent AudioSystem.STREAM_RING, // STREAM_DTMF 2516d5176638c2189595cede38fb92c3e7e8700e221Eric Laurent AudioSystem.STREAM_MUSIC // STREAM_TTS 252a553c25b33c99b345cf1c8688f8df0ed8df14e5aEric Laurent }; 2536d5176638c2189595cede38fb92c3e7e8700e221Eric Laurent private final int[] STREAM_VOLUME_ALIAS_NON_VOICE = new int[] { 2546d5176638c2189595cede38fb92c3e7e8700e221Eric Laurent AudioSystem.STREAM_VOICE_CALL, // STREAM_VOICE_CALL 2556d5176638c2189595cede38fb92c3e7e8700e221Eric Laurent AudioSystem.STREAM_MUSIC, // STREAM_SYSTEM 2566d5176638c2189595cede38fb92c3e7e8700e221Eric Laurent AudioSystem.STREAM_RING, // STREAM_RING 2576d5176638c2189595cede38fb92c3e7e8700e221Eric Laurent AudioSystem.STREAM_MUSIC, // STREAM_MUSIC 2586d5176638c2189595cede38fb92c3e7e8700e221Eric Laurent AudioSystem.STREAM_ALARM, // STREAM_ALARM 2596d5176638c2189595cede38fb92c3e7e8700e221Eric Laurent AudioSystem.STREAM_RING, // STREAM_NOTIFICATION 2606d5176638c2189595cede38fb92c3e7e8700e221Eric Laurent AudioSystem.STREAM_BLUETOOTH_SCO, // STREAM_BLUETOOTH_SCO 2616d5176638c2189595cede38fb92c3e7e8700e221Eric Laurent AudioSystem.STREAM_MUSIC, // STREAM_SYSTEM_ENFORCED 2626d5176638c2189595cede38fb92c3e7e8700e221Eric Laurent AudioSystem.STREAM_MUSIC, // STREAM_DTMF 2636d5176638c2189595cede38fb92c3e7e8700e221Eric Laurent AudioSystem.STREAM_MUSIC // STREAM_TTS 2646d5176638c2189595cede38fb92c3e7e8700e221Eric Laurent }; 2656d5176638c2189595cede38fb92c3e7e8700e221Eric Laurent private int[] mStreamVolumeAlias; 266a553c25b33c99b345cf1c8688f8df0ed8df14e5aEric Laurent 267ba50b97cff80e73620a0e3d13cae169e095974a7Dianne Hackborn /** 268ba50b97cff80e73620a0e3d13cae169e095974a7Dianne Hackborn * Map AudioSystem.STREAM_* constants to app ops. This should be used 269ba50b97cff80e73620a0e3d13cae169e095974a7Dianne Hackborn * after mapping through mStreamVolumeAlias. 270ba50b97cff80e73620a0e3d13cae169e095974a7Dianne Hackborn */ 271ba50b97cff80e73620a0e3d13cae169e095974a7Dianne Hackborn private static final int[] STEAM_VOLUME_OPS = new int[] { 272ba50b97cff80e73620a0e3d13cae169e095974a7Dianne Hackborn AppOpsManager.OP_AUDIO_VOICE_VOLUME, // STREAM_VOICE_CALL 273ba50b97cff80e73620a0e3d13cae169e095974a7Dianne Hackborn AppOpsManager.OP_AUDIO_MEDIA_VOLUME, // STREAM_SYSTEM 274ba50b97cff80e73620a0e3d13cae169e095974a7Dianne Hackborn AppOpsManager.OP_AUDIO_RING_VOLUME, // STREAM_RING 275ba50b97cff80e73620a0e3d13cae169e095974a7Dianne Hackborn AppOpsManager.OP_AUDIO_MEDIA_VOLUME, // STREAM_MUSIC 276ba50b97cff80e73620a0e3d13cae169e095974a7Dianne Hackborn AppOpsManager.OP_AUDIO_ALARM_VOLUME, // STREAM_ALARM 277ba50b97cff80e73620a0e3d13cae169e095974a7Dianne Hackborn AppOpsManager.OP_AUDIO_NOTIFICATION_VOLUME, // STREAM_NOTIFICATION 278ba50b97cff80e73620a0e3d13cae169e095974a7Dianne Hackborn AppOpsManager.OP_AUDIO_BLUETOOTH_VOLUME, // STREAM_BLUETOOTH_SCO 279ba50b97cff80e73620a0e3d13cae169e095974a7Dianne Hackborn AppOpsManager.OP_AUDIO_MEDIA_VOLUME, // STREAM_SYSTEM_ENFORCED 280ba50b97cff80e73620a0e3d13cae169e095974a7Dianne Hackborn AppOpsManager.OP_AUDIO_MEDIA_VOLUME, // STREAM_DTMF 281ba50b97cff80e73620a0e3d13cae169e095974a7Dianne Hackborn AppOpsManager.OP_AUDIO_MEDIA_VOLUME, // STREAM_TTS 282ba50b97cff80e73620a0e3d13cae169e095974a7Dianne Hackborn }; 283ba50b97cff80e73620a0e3d13cae169e095974a7Dianne Hackborn 28483a017b6b7c099d1a0293e5839be6477325aef06Eric Laurent private final boolean mUseFixedVolume; 28583a017b6b7c099d1a0293e5839be6477325aef06Eric Laurent 286bffc3d1bd33eb2d8e00a9f8b6261d815db503311Eric Laurent // stream names used by dumpStreamStates() 2871af30c7ac480e5d335f267a3ac3b2e6c748ce240John Spurlock private static final String[] STREAM_NAMES = new String[] { 288bffc3d1bd33eb2d8e00a9f8b6261d815db503311Eric Laurent "STREAM_VOICE_CALL", 289bffc3d1bd33eb2d8e00a9f8b6261d815db503311Eric Laurent "STREAM_SYSTEM", 290bffc3d1bd33eb2d8e00a9f8b6261d815db503311Eric Laurent "STREAM_RING", 291bffc3d1bd33eb2d8e00a9f8b6261d815db503311Eric Laurent "STREAM_MUSIC", 292bffc3d1bd33eb2d8e00a9f8b6261d815db503311Eric Laurent "STREAM_ALARM", 293bffc3d1bd33eb2d8e00a9f8b6261d815db503311Eric Laurent "STREAM_NOTIFICATION", 294bffc3d1bd33eb2d8e00a9f8b6261d815db503311Eric Laurent "STREAM_BLUETOOTH_SCO", 295bffc3d1bd33eb2d8e00a9f8b6261d815db503311Eric Laurent "STREAM_SYSTEM_ENFORCED", 296bffc3d1bd33eb2d8e00a9f8b6261d815db503311Eric Laurent "STREAM_DTMF", 297bffc3d1bd33eb2d8e00a9f8b6261d815db503311Eric Laurent "STREAM_TTS" 298bffc3d1bd33eb2d8e00a9f8b6261d815db503311Eric Laurent }; 299bffc3d1bd33eb2d8e00a9f8b6261d815db503311Eric Laurent 30030c918ce7fbe171944b28fc91b3f22b3d631872dGlenn Kasten private final AudioSystem.ErrorCallback mAudioSystemCallback = new AudioSystem.ErrorCallback() { 3019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public void onError(int error) { 3029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project switch (error) { 3039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project case AudioSystem.AUDIO_STATUS_SERVER_DIED: 304dfb881f96af7898151940a4bbc52e45e6043d38bEric Laurent sendMsg(mAudioHandler, MSG_MEDIA_SERVER_DIED, 305dfb881f96af7898151940a4bbc52e45e6043d38bEric Laurent SENDMSG_NOOP, 0, 0, null, 0); 3069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project break; 3079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project default: 3089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project break; 3099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 310dfb881f96af7898151940a4bbc52e45e6043d38bEric Laurent } 3119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project }; 3129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 3149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Current ringer mode from one of {@link AudioManager#RINGER_MODE_NORMAL}, 3159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * {@link AudioManager#RINGER_MODE_SILENT}, or 3169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * {@link AudioManager#RINGER_MODE_VIBRATE}. 3179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 318ba195ebc76f23b6679443724ab58c9dc9f2df884Glenn Kasten // protected by mSettingsLock 3199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private int mRingerMode; 3209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3219bcf401d13d47416043a704430388abd59aef7cdEric Laurent /** @see System#MODE_RINGER_STREAMS_AFFECTED */ 32224e0d9b6c40712a297e4c287435a3b0fdd30e9daEric Laurent private int mRingerModeAffectedStreams = 0; 3239bcf401d13d47416043a704430388abd59aef7cdEric Laurent 3245b4e654d0c7de8e4d58d73e73b0d5220f19b68f7Eric Laurent // Streams currently muted by ringer mode 3255b4e654d0c7de8e4d58d73e73b0d5220f19b68f7Eric Laurent private int mRingerModeMutedStreams; 3265b4e654d0c7de8e4d58d73e73b0d5220f19b68f7Eric Laurent 3279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** @see System#MUTE_STREAMS_AFFECTED */ 3289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private int mMuteAffectedStreams; 3299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 331bffc3d1bd33eb2d8e00a9f8b6261d815db503311Eric Laurent * NOTE: setVibrateSetting(), getVibrateSetting(), shouldVibrate() are deprecated. 332bffc3d1bd33eb2d8e00a9f8b6261d815db503311Eric Laurent * mVibrateSetting is just maintained during deprecation period but vibration policy is 333bffc3d1bd33eb2d8e00a9f8b6261d815db503311Eric Laurent * now only controlled by mHasVibrator and mRingerMode 3349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 3359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private int mVibrateSetting; 3369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 337bffc3d1bd33eb2d8e00a9f8b6261d815db503311Eric Laurent // Is there a vibrator 338bffc3d1bd33eb2d8e00a9f8b6261d815db503311Eric Laurent private final boolean mHasVibrator; 339bffc3d1bd33eb2d8e00a9f8b6261d815db503311Eric Laurent 340a553c25b33c99b345cf1c8688f8df0ed8df14e5aEric Laurent // Broadcast receiver for device connections intent broadcasts 341a553c25b33c99b345cf1c8688f8df0ed8df14e5aEric Laurent private final BroadcastReceiver mReceiver = new AudioServiceBroadcastReceiver(); 342a553c25b33c99b345cf1c8688f8df0ed8df14e5aEric Laurent 343c42ac9d4d03f62c3a1ba197a28a81fda44bd8b7fEric Laurent // Devices currently connected 34430c918ce7fbe171944b28fc91b3f22b3d631872dGlenn Kasten private final HashMap <Integer, String> mConnectedDevices = new HashMap <Integer, String>(); 345c42ac9d4d03f62c3a1ba197a28a81fda44bd8b7fEric Laurent 346c42ac9d4d03f62c3a1ba197a28a81fda44bd8b7fEric Laurent // Forced device usage for communications 347c42ac9d4d03f62c3a1ba197a28a81fda44bd8b7fEric Laurent private int mForcedUseForComm; 348c42ac9d4d03f62c3a1ba197a28a81fda44bd8b7fEric Laurent 3490dc37cce9d564ae43883c8dc8672b9266b881e63Mike Lockwood // True if we have master volume support 3500dc37cce9d564ae43883c8dc8672b9266b881e63Mike Lockwood private final boolean mUseMasterVolume; 3510dc37cce9d564ae43883c8dc8672b9266b881e63Mike Lockwood 3529760647dd0ee67e7c20f3e9d661d2006b1df0b54Mike Lockwood private final int[] mMasterVolumeRamp; 3539760647dd0ee67e7c20f3e9d661d2006b1df0b54Mike Lockwood 3549272b4b4a44fe1f33e3030810618194f817caaecEric Laurent // List of binder death handlers for setMode() client processes. 3559272b4b4a44fe1f33e3030810618194f817caaecEric Laurent // The last process to have called setMode() is at the top of the list. 35630c918ce7fbe171944b28fc91b3f22b3d631872dGlenn Kasten private final ArrayList <SetModeDeathHandler> mSetModeDeathHandlers = new ArrayList <SetModeDeathHandler>(); 357eb14a783be073b5fd6e8c8c9bc87d2d1919f2c9eEric Laurent 3583def1eec2baed0b8845ec32c871e249dc533a9d9Eric Laurent // List of clients having issued a SCO start request 35930c918ce7fbe171944b28fc91b3f22b3d631872dGlenn Kasten private final ArrayList <ScoClient> mScoClients = new ArrayList <ScoClient>(); 3603def1eec2baed0b8845ec32c871e249dc533a9d9Eric Laurent 3613def1eec2baed0b8845ec32c871e249dc533a9d9Eric Laurent // BluetoothHeadset API to control SCO connection 3623def1eec2baed0b8845ec32c871e249dc533a9d9Eric Laurent private BluetoothHeadset mBluetoothHeadset; 3633def1eec2baed0b8845ec32c871e249dc533a9d9Eric Laurent 36482aa7f017daaaeb96c13e6e3491d5037ab471085Jaikumar Ganesh // Bluetooth headset device 36582aa7f017daaaeb96c13e6e3491d5037ab471085Jaikumar Ganesh private BluetoothDevice mBluetoothHeadsetDevice; 3663def1eec2baed0b8845ec32c871e249dc533a9d9Eric Laurent 36762ef767b15a712bab31cc0d5508a330906f535c2Eric Laurent // Indicate if SCO audio connection is currently active and if the initiator is 36862ef767b15a712bab31cc0d5508a330906f535c2Eric Laurent // audio service (internal) or bluetooth headset (external) 36962ef767b15a712bab31cc0d5508a330906f535c2Eric Laurent private int mScoAudioState; 37062ef767b15a712bab31cc0d5508a330906f535c2Eric Laurent // SCO audio state is not active 37162ef767b15a712bab31cc0d5508a330906f535c2Eric Laurent private static final int SCO_STATE_INACTIVE = 0; 372dc03c61fe3cd8d0805480e48a974986439977a60Eric Laurent // SCO audio activation request waiting for headset service to connect 373dc03c61fe3cd8d0805480e48a974986439977a60Eric Laurent private static final int SCO_STATE_ACTIVATE_REQ = 1; 37425fc29b3691a1d2a84164988dc74b2e7d301868eEric Laurent // SCO audio state is active or starting due to a request from AudioManager API 375dc03c61fe3cd8d0805480e48a974986439977a60Eric Laurent private static final int SCO_STATE_ACTIVE_INTERNAL = 3; 376dc03c61fe3cd8d0805480e48a974986439977a60Eric Laurent // SCO audio deactivation request waiting for headset service to connect 377dc03c61fe3cd8d0805480e48a974986439977a60Eric Laurent private static final int SCO_STATE_DEACTIVATE_REQ = 5; 378dc03c61fe3cd8d0805480e48a974986439977a60Eric Laurent 37962ef767b15a712bab31cc0d5508a330906f535c2Eric Laurent // SCO audio state is active due to an action in BT handsfree (either voice recognition or 38062ef767b15a712bab31cc0d5508a330906f535c2Eric Laurent // in call audio) 38162ef767b15a712bab31cc0d5508a330906f535c2Eric Laurent private static final int SCO_STATE_ACTIVE_EXTERNAL = 2; 382dc03c61fe3cd8d0805480e48a974986439977a60Eric Laurent // Deactivation request for all SCO connections (initiated by audio mode change) 383dc03c61fe3cd8d0805480e48a974986439977a60Eric Laurent // waiting for headset service to connect 384dc03c61fe3cd8d0805480e48a974986439977a60Eric Laurent private static final int SCO_STATE_DEACTIVATE_EXT_REQ = 4; 385dc03c61fe3cd8d0805480e48a974986439977a60Eric Laurent 386c18c9138cee0f0859bcab636a004ce92ca4a9ab5Eric Laurent // Indicates the mode used for SCO audio connection. The mode is virtual call if the request 387c18c9138cee0f0859bcab636a004ce92ca4a9ab5Eric Laurent // originated from an app targeting an API version before JB MR2 and raw audio after that. 388c18c9138cee0f0859bcab636a004ce92ca4a9ab5Eric Laurent private int mScoAudioMode; 389c18c9138cee0f0859bcab636a004ce92ca4a9ab5Eric Laurent // SCO audio mode is virtual voice call (BluetoothHeadset.startScoUsingVirtualVoiceCall()) 390c18c9138cee0f0859bcab636a004ce92ca4a9ab5Eric Laurent private static final int SCO_MODE_VIRTUAL_CALL = 0; 391c18c9138cee0f0859bcab636a004ce92ca4a9ab5Eric Laurent // SCO audio mode is raw audio (BluetoothHeadset.connectAudio()) 392c18c9138cee0f0859bcab636a004ce92ca4a9ab5Eric Laurent private static final int SCO_MODE_RAW = 1; 393c18c9138cee0f0859bcab636a004ce92ca4a9ab5Eric Laurent 394dc03c61fe3cd8d0805480e48a974986439977a60Eric Laurent // Current connection state indicated by bluetooth headset 395dc03c61fe3cd8d0805480e48a974986439977a60Eric Laurent private int mScoConnectionState; 39662ef767b15a712bab31cc0d5508a330906f535c2Eric Laurent 397a60e212d0dda7d2a748180ce77405f2463c9cf53Eric Laurent // true if boot sequence has been completed 3984a5eeb9c727d77bb57fef87a70c8c9cc23dbfee3Eric Laurent private boolean mSystemReady; 399a60e212d0dda7d2a748180ce77405f2463c9cf53Eric Laurent // listener for SoundPool sample load completion indication 400a60e212d0dda7d2a748180ce77405f2463c9cf53Eric Laurent private SoundPoolCallback mSoundPoolCallBack; 401a60e212d0dda7d2a748180ce77405f2463c9cf53Eric Laurent // thread for SoundPool listener 402a60e212d0dda7d2a748180ce77405f2463c9cf53Eric Laurent private SoundPoolListenerThread mSoundPoolListenerThread; 403a60e212d0dda7d2a748180ce77405f2463c9cf53Eric Laurent // message looper for SoundPool listener 404a60e212d0dda7d2a748180ce77405f2463c9cf53Eric Laurent private Looper mSoundPoolLooper = null; 405c55b393efd462490cd5e27fc373bceafdd25662eJean-Michel Trivi // volume applied to sound played with playSoundEffect() 406f2b0c11f4e797e183131261724d8de310dac5431Jean-Michel Trivi private static int sSoundEffectVolumeDb; 4079903e2638a6c502d96413680d3ebae4fb77fc412Eric Laurent // getActiveStreamType() will return: 4089903e2638a6c502d96413680d3ebae4fb77fc412Eric Laurent // - STREAM_NOTIFICATION on tablets during this period after a notification stopped 4099903e2638a6c502d96413680d3ebae4fb77fc412Eric Laurent // - STREAM_MUSIC on phones during this period after music or talkback/voice search prompt 41025101b0b9a84571ead15b26e9f4cd9c4298d7823Eric Laurent // stopped 4119903e2638a6c502d96413680d3ebae4fb77fc412Eric Laurent private static final int DEFAULT_STREAM_TYPE_OVERRIDE_DELAY_MS = 5000; 41225101b0b9a84571ead15b26e9f4cd9c4298d7823Eric Laurent // previous volume adjustment direction received by checkForRingerModeChange() 41325101b0b9a84571ead15b26e9f4cd9c4298d7823Eric Laurent private int mPrevVolDirection = AudioManager.ADJUST_SAME; 4146243edd818b84adfbe712d5d233d6414b33653acAmith Yamasani // Keyguard manager proxy 4156243edd818b84adfbe712d5d233d6414b33653acAmith Yamasani private KeyguardManager mKeyguardManager; 41645c90cefd13a03b852bb4b8da4be218876cbbb32Eric Laurent // mVolumeControlStream is set by VolumePanel to temporarily force the stream type which volume 41745c90cefd13a03b852bb4b8da4be218876cbbb32Eric Laurent // is controlled by Vol keys. 41845c90cefd13a03b852bb4b8da4be218876cbbb32Eric Laurent private int mVolumeControlStream = -1; 41945c90cefd13a03b852bb4b8da4be218876cbbb32Eric Laurent private final Object mForceControlStreamLock = new Object(); 42045c90cefd13a03b852bb4b8da4be218876cbbb32Eric Laurent // VolumePanel is currently the only client of forceVolumeControlStream() and runs in system 42145c90cefd13a03b852bb4b8da4be218876cbbb32Eric Laurent // server process so in theory it is not necessary to monitor the client death. 42245c90cefd13a03b852bb4b8da4be218876cbbb32Eric Laurent // However it is good to be ready for future evolutions. 42345c90cefd13a03b852bb4b8da4be218876cbbb32Eric Laurent private ForceControlStreamClient mForceControlStreamClient = null; 424098d580cc2bb6c0891c756a4e5230c6c6b0d2376Jeff Sharkey // Used to play ringtones outside system_server 425098d580cc2bb6c0891c756a4e5230c6c6b0d2376Jeff Sharkey private volatile IRingtonePlayer mRingtonePlayer; 4269bc8358ddaa01c3490f9709991989633a6a3dd42Eric Laurent 427f26f01784e1c733c53cad3ed31918e73448ce369Jean-Michel Trivi private int mDeviceOrientation = Configuration.ORIENTATION_UNDEFINED; 428bb6f8711a7f804d39c45218db2d6339940cc5d35Jean-Michel Trivi private int mDeviceRotation = Surface.ROTATION_0; 429f26f01784e1c733c53cad3ed31918e73448ce369Jean-Michel Trivi 4307847211fb4699bf6018e29d214a918ed6657319bEric Laurent // Request to override default use of A2DP for media. 4317847211fb4699bf6018e29d214a918ed6657319bEric Laurent private boolean mBluetoothA2dpEnabled; 4327847211fb4699bf6018e29d214a918ed6657319bEric Laurent private final Object mBluetoothA2dpEnabledLock = new Object(); 4337847211fb4699bf6018e29d214a918ed6657319bEric Laurent 434632ca417f0a33e3fa9ccece531afa2db3f0d4a30Dianne Hackborn // Monitoring of audio routes. Protected by mCurAudioRoutes. 435632ca417f0a33e3fa9ccece531afa2db3f0d4a30Dianne Hackborn final AudioRoutesInfo mCurAudioRoutes = new AudioRoutesInfo(); 436632ca417f0a33e3fa9ccece531afa2db3f0d4a30Dianne Hackborn final RemoteCallbackList<IAudioRoutesObserver> mRoutesObservers 437632ca417f0a33e3fa9ccece531afa2db3f0d4a30Dianne Hackborn = new RemoteCallbackList<IAudioRoutesObserver>(); 438632ca417f0a33e3fa9ccece531afa2db3f0d4a30Dianne Hackborn 4393114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi /** 4403114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi * A fake stream type to match the notion of remote media playback 4413114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi */ 4423114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi public final static int STREAM_REMOTE_MUSIC = -200; 4433114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi 4444bbcc6549738f3d69831b2bd9eb4accec3e9920eEric Laurent // Devices for which the volume is fixed and VolumePanel slider should be disabled 445948d32748caaac5be06c991ebf00f74265a7849fEric Laurent final int mFixedVolumeDevices = AudioSystem.DEVICE_OUT_HDMI | 4464bbcc6549738f3d69831b2bd9eb4accec3e9920eEric Laurent AudioSystem.DEVICE_OUT_DGTL_DOCK_HEADSET | 447fb917e019f04d60f4924114fe2684c0d67981af6Paul McLean AudioSystem.DEVICE_OUT_ANLG_DOCK_HEADSET; 4484bbcc6549738f3d69831b2bd9eb4accec3e9920eEric Laurent 449bb6f8711a7f804d39c45218db2d6339940cc5d35Jean-Michel Trivi // TODO merge orientation and rotation 450d640bd325c3be9a350058c835b880a7e0b40dc60Eric Laurent private final boolean mMonitorOrientation; 451bb6f8711a7f804d39c45218db2d6339940cc5d35Jean-Michel Trivi private final boolean mMonitorRotation; 452d640bd325c3be9a350058c835b880a7e0b40dc60Eric Laurent 4537ee1e4ff7346a278a6722108fbc1869240b3e866Eric Laurent private boolean mDockAudioMediaEnabled = true; 4547ee1e4ff7346a278a6722108fbc1869240b3e866Eric Laurent 45508ed1b9d2099ec8231b21353b33b901492ea9885Eric Laurent private int mDockState = Intent.EXTRA_DOCK_STATE_UNDOCKED; 45608ed1b9d2099ec8231b21353b33b901492ea9885Eric Laurent 457fde16d5879ea88a971004c984093409468b6139cEric Laurent // Used when safe volume warning message display is requested by setStreamVolume(). In this 458fde16d5879ea88a971004c984093409468b6139cEric Laurent // case, the new requested volume, stream type and device are stored in mPendingVolumeCommand 459fde16d5879ea88a971004c984093409468b6139cEric Laurent // and used later when/if disableSafeMediaVolume() is called. 460fde16d5879ea88a971004c984093409468b6139cEric Laurent private StreamVolumeCommand mPendingVolumeCommand; 461fde16d5879ea88a971004c984093409468b6139cEric Laurent 462fa9a69805b001034aa04c3b33989a7ac21522371Jean-Michel Trivi private PowerManager.WakeLock mAudioEventWakeLock; 463fa9a69805b001034aa04c3b33989a7ac21522371Jean-Michel Trivi 464fa9a69805b001034aa04c3b33989a7ac21522371Jean-Michel Trivi private final MediaFocusControl mMediaFocusControl; 465fa9a69805b001034aa04c3b33989a7ac21522371Jean-Michel Trivi 4665a0cf7a27f3953a1266af48543ccd9024f4cd89fJohn Du // Reference to BluetoothA2dp to query for AbsoluteVolume. 4675a0cf7a27f3953a1266af48543ccd9024f4cd89fJohn Du private BluetoothA2dp mA2dp; 4685a0cf7a27f3953a1266af48543ccd9024f4cd89fJohn Du private final Object mA2dpAvrcpLock = new Object(); 4695a0cf7a27f3953a1266af48543ccd9024f4cd89fJohn Du // If absolute volume is supported in AVRCP device 4705a0cf7a27f3953a1266af48543ccd9024f4cd89fJohn Du private boolean mAvrcpAbsVolSupported = false; 4715a0cf7a27f3953a1266af48543ccd9024f4cd89fJohn Du 4729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /////////////////////////////////////////////////////////////////////////// 4739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Construction 4749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /////////////////////////////////////////////////////////////////////////// 4759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 4769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** @hide */ 4779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public AudioService(Context context) { 4789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mContext = context; 4799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mContentResolver = context.getContentResolver(); 480ba50b97cff80e73620a0e3d13cae169e095974a7Dianne Hackborn mAppOps = (AppOpsManager)context.getSystemService(Context.APP_OPS_SERVICE); 481c7fcba4b7bd3d78e7cfe975a3f8e4dde2f6738b7Joe Onorato mVoiceCapable = mContext.getResources().getBoolean( 482c7fcba4b7bd3d78e7cfe975a3f8e4dde2f6738b7Joe Onorato com.android.internal.R.bool.config_voice_capable); 4835982013cfc8274ff0bafaba83c676b3a8890cba9Jared Suttles 484c68022258ebd3dd97a5079ba99f4f3cd12b223b0Jean-Michel Trivi PowerManager pm = (PowerManager)context.getSystemService(Context.POWER_SERVICE); 485fa9a69805b001034aa04c3b33989a7ac21522371Jean-Michel Trivi mAudioEventWakeLock = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "handleAudioEvent"); 486c68022258ebd3dd97a5079ba99f4f3cd12b223b0Jean-Michel Trivi 487bffc3d1bd33eb2d8e00a9f8b6261d815db503311Eric Laurent Vibrator vibrator = (Vibrator) context.getSystemService(Context.VIBRATOR_SERVICE); 488bffc3d1bd33eb2d8e00a9f8b6261d815db503311Eric Laurent mHasVibrator = vibrator == null ? false : vibrator.hasVibrator(); 489bffc3d1bd33eb2d8e00a9f8b6261d815db503311Eric Laurent 4905982013cfc8274ff0bafaba83c676b3a8890cba9Jared Suttles // Intialized volume 4915982013cfc8274ff0bafaba83c676b3a8890cba9Jared Suttles MAX_STREAM_VOLUME[AudioSystem.STREAM_VOICE_CALL] = SystemProperties.getInt( 4925982013cfc8274ff0bafaba83c676b3a8890cba9Jared Suttles "ro.config.vc_call_vol_steps", 4935982013cfc8274ff0bafaba83c676b3a8890cba9Jared Suttles MAX_STREAM_VOLUME[AudioSystem.STREAM_VOICE_CALL]); 4945982013cfc8274ff0bafaba83c676b3a8890cba9Jared Suttles 495f2b0c11f4e797e183131261724d8de310dac5431Jean-Michel Trivi sSoundEffectVolumeDb = context.getResources().getInteger( 496c55b393efd462490cd5e27fc373bceafdd25662eJean-Michel Trivi com.android.internal.R.integer.config_soundEffectVolumeDb); 49725101b0b9a84571ead15b26e9f4cd9c4298d7823Eric Laurent 498c42ac9d4d03f62c3a1ba197a28a81fda44bd8b7fEric Laurent mForcedUseForComm = AudioSystem.FORCE_NONE; 499dd45d01128423a82652a3c9d77fa393631d95229Eric Laurent 5009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project createAudioSystemThread(); 501dd45d01128423a82652a3c9d77fa393631d95229Eric Laurent 502fa9a69805b001034aa04c3b33989a7ac21522371Jean-Michel Trivi mMediaFocusControl = new MediaFocusControl(mAudioHandler.getLooper(), 5033346a802087f621c6441bc512dfcc17b07143fc6John Spurlock mContext, mVolumeController, this); 504fa9a69805b001034aa04c3b33989a7ac21522371Jean-Michel Trivi 505dfb881f96af7898151940a4bbc52e45e6043d38bEric Laurent AudioSystem.setErrorCallback(mAudioSystemCallback); 506dfb881f96af7898151940a4bbc52e45e6043d38bEric Laurent 507dd45d01128423a82652a3c9d77fa393631d95229Eric Laurent boolean cameraSoundForced = mContext.getResources().getBoolean( 508dd45d01128423a82652a3c9d77fa393631d95229Eric Laurent com.android.internal.R.bool.config_camera_sound_forced); 509dd45d01128423a82652a3c9d77fa393631d95229Eric Laurent mCameraSoundForced = new Boolean(cameraSoundForced); 510dd45d01128423a82652a3c9d77fa393631d95229Eric Laurent sendMsg(mAudioHandler, 511dd45d01128423a82652a3c9d77fa393631d95229Eric Laurent MSG_SET_FORCE_USE, 512dd45d01128423a82652a3c9d77fa393631d95229Eric Laurent SENDMSG_QUEUE, 513dd45d01128423a82652a3c9d77fa393631d95229Eric Laurent AudioSystem.FOR_SYSTEM, 514dd45d01128423a82652a3c9d77fa393631d95229Eric Laurent cameraSoundForced ? 515dd45d01128423a82652a3c9d77fa393631d95229Eric Laurent AudioSystem.FORCE_SYSTEM_ENFORCED : AudioSystem.FORCE_NONE, 516dd45d01128423a82652a3c9d77fa393631d95229Eric Laurent null, 517dd45d01128423a82652a3c9d77fa393631d95229Eric Laurent 0); 518dd45d01128423a82652a3c9d77fa393631d95229Eric Laurent 51905274f348e12983eb8613cc6eb9ae561e8197e28Eric Laurent mSafeMediaVolumeState = new Integer(Settings.Global.getInt(mContentResolver, 52005274f348e12983eb8613cc6eb9ae561e8197e28Eric Laurent Settings.Global.AUDIO_SAFE_VOLUME_STATE, 52105274f348e12983eb8613cc6eb9ae561e8197e28Eric Laurent SAFE_MEDIA_VOLUME_NOT_CONFIGURED)); 52205274f348e12983eb8613cc6eb9ae561e8197e28Eric Laurent // The default safe volume index read here will be replaced by the actual value when 52305274f348e12983eb8613cc6eb9ae561e8197e28Eric Laurent // the mcc is read by onConfigureSafeVolume() 52405274f348e12983eb8613cc6eb9ae561e8197e28Eric Laurent mSafeMediaVolumeIndex = mContext.getResources().getInteger( 52505274f348e12983eb8613cc6eb9ae561e8197e28Eric Laurent com.android.internal.R.integer.config_safe_media_volume_index) * 10; 52605274f348e12983eb8613cc6eb9ae561e8197e28Eric Laurent 52783a017b6b7c099d1a0293e5839be6477325aef06Eric Laurent mUseFixedVolume = mContext.getResources().getBoolean( 52883a017b6b7c099d1a0293e5839be6477325aef06Eric Laurent com.android.internal.R.bool.config_useFixedVolume); 52983a017b6b7c099d1a0293e5839be6477325aef06Eric Laurent 53024e0d9b6c40712a297e4c287435a3b0fdd30e9daEric Laurent // must be called before readPersistedSettings() which needs a valid mStreamVolumeAlias[] 53124e0d9b6c40712a297e4c287435a3b0fdd30e9daEric Laurent // array initialized by updateStreamVolumeAlias() 53224e0d9b6c40712a297e4c287435a3b0fdd30e9daEric Laurent updateStreamVolumeAlias(false /*updateVolumes*/); 5339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project readPersistedSettings(); 534c1d4166289ce016965d1147f7e8d37862ee347ecEric Laurent mSettingsObserver = new SettingsObserver(); 535a553c25b33c99b345cf1c8688f8df0ed8df14e5aEric Laurent createStreamStates(); 5369f103de83f2d5d472960dcf1401e95b2ab57a477Eric Laurent 537fd116ad1ab02f6060a0b2201f018317fa32e28b4Glenn Kasten readAndSetLowRamDevice(); 5383891c4cc918e8062abb97c542a8625d556dccc59Eric Laurent 5393891c4cc918e8062abb97c542a8625d556dccc59Eric Laurent // Call setRingerModeInt() to apply correct mute 5403891c4cc918e8062abb97c542a8625d556dccc59Eric Laurent // state on streams affected by ringer mode. 5413891c4cc918e8062abb97c542a8625d556dccc59Eric Laurent mRingerModeMutedStreams = 0; 5423891c4cc918e8062abb97c542a8625d556dccc59Eric Laurent setRingerModeInt(getRingerMode(), false); 5433891c4cc918e8062abb97c542a8625d556dccc59Eric Laurent 544a553c25b33c99b345cf1c8688f8df0ed8df14e5aEric Laurent // Register for device connection intent broadcasts. 545a553c25b33c99b345cf1c8688f8df0ed8df14e5aEric Laurent IntentFilter intentFilter = 546b1fbaaccb656ef09a8770c28df15e3e91a452e64Eric Laurent new IntentFilter(BluetoothHeadset.ACTION_AUDIO_STATE_CHANGED); 54782aa7f017daaaeb96c13e6e3491d5037ab471085Jaikumar Ganesh intentFilter.addAction(BluetoothHeadset.ACTION_CONNECTION_STATE_CHANGED); 54882aa7f017daaaeb96c13e6e3491d5037ab471085Jaikumar Ganesh intentFilter.addAction(Intent.ACTION_DOCK_EVENT); 54959f482764e346a5c5ac118ee1f7b24da645c2559Eric Laurent intentFilter.addAction(Intent.ACTION_USB_AUDIO_ACCESSORY_PLUG); 55059f482764e346a5c5ac118ee1f7b24da645c2559Eric Laurent intentFilter.addAction(Intent.ACTION_USB_AUDIO_DEVICE_PLUG); 551950e8cb40a6d826af4cc2eef9d3908c1b70486e6Eric Laurent intentFilter.addAction(Intent.ACTION_SCREEN_ON); 552950e8cb40a6d826af4cc2eef9d3908c1b70486e6Eric Laurent intentFilter.addAction(Intent.ACTION_SCREEN_OFF); 553bc0fab1fc2db832ef86d8a33466ec4d68b103ca0Eric Laurent intentFilter.addAction(Intent.ACTION_USER_SWITCHED); 554c837a451946b64d70ed7c642fbde03c182c28b6fPaul McLean intentFilter.addAction(UsbManager.ACTION_USB_DEVICE_ATTACHED); 555f26f01784e1c733c53cad3ed31918e73448ce369Jean-Michel Trivi 556d640bd325c3be9a350058c835b880a7e0b40dc60Eric Laurent intentFilter.addAction(Intent.ACTION_CONFIGURATION_CHANGED); 557bb6f8711a7f804d39c45218db2d6339940cc5d35Jean-Michel Trivi // TODO merge orientation and rotation 558d640bd325c3be9a350058c835b880a7e0b40dc60Eric Laurent mMonitorOrientation = SystemProperties.getBoolean("ro.audio.monitorOrientation", false); 559d640bd325c3be9a350058c835b880a7e0b40dc60Eric Laurent if (mMonitorOrientation) { 560f26f01784e1c733c53cad3ed31918e73448ce369Jean-Michel Trivi Log.v(TAG, "monitoring device orientation"); 561f26f01784e1c733c53cad3ed31918e73448ce369Jean-Michel Trivi // initialize orientation in AudioSystem 562f26f01784e1c733c53cad3ed31918e73448ce369Jean-Michel Trivi setOrientationForAudioSystem(); 563f26f01784e1c733c53cad3ed31918e73448ce369Jean-Michel Trivi } 564bb6f8711a7f804d39c45218db2d6339940cc5d35Jean-Michel Trivi mMonitorRotation = SystemProperties.getBoolean("ro.audio.monitorRotation", false); 565bb6f8711a7f804d39c45218db2d6339940cc5d35Jean-Michel Trivi if (mMonitorRotation) { 566bb6f8711a7f804d39c45218db2d6339940cc5d35Jean-Michel Trivi mDeviceRotation = ((WindowManager) mContext.getSystemService(Context.WINDOW_SERVICE)) 567bb6f8711a7f804d39c45218db2d6339940cc5d35Jean-Michel Trivi .getDefaultDisplay().getRotation(); 568bb6f8711a7f804d39c45218db2d6339940cc5d35Jean-Michel Trivi Log.v(TAG, "monitoring device rotation, initial=" + mDeviceRotation); 569bb6f8711a7f804d39c45218db2d6339940cc5d35Jean-Michel Trivi // initialize rotation in AudioSystem 570bb6f8711a7f804d39c45218db2d6339940cc5d35Jean-Michel Trivi setRotationForAudioSystem(); 571bb6f8711a7f804d39c45218db2d6339940cc5d35Jean-Michel Trivi } 572f26f01784e1c733c53cad3ed31918e73448ce369Jean-Michel Trivi 573a553c25b33c99b345cf1c8688f8df0ed8df14e5aEric Laurent context.registerReceiver(mReceiver, intentFilter); 5745982013cfc8274ff0bafaba83c676b3a8890cba9Jared Suttles 5750dc37cce9d564ae43883c8dc8672b9266b881e63Mike Lockwood mUseMasterVolume = context.getResources().getBoolean( 5760dc37cce9d564ae43883c8dc8672b9266b881e63Mike Lockwood com.android.internal.R.bool.config_useMasterVolume); 5779063154a793b0ab38b3c5992cbaed046427b4a82Mike Lockwood restoreMasterVolume(); 5789760647dd0ee67e7c20f3e9d661d2006b1df0b54Mike Lockwood 5799760647dd0ee67e7c20f3e9d661d2006b1df0b54Mike Lockwood mMasterVolumeRamp = context.getResources().getIntArray( 5809760647dd0ee67e7c20f3e9d661d2006b1df0b54Mike Lockwood com.android.internal.R.array.config_masterVolumeRamp); 5817847211fb4699bf6018e29d214a918ed6657319bEric Laurent 5829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 5839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 5844a5eeb9c727d77bb57fef87a70c8c9cc23dbfee3Eric Laurent public void systemReady() { 5854a5eeb9c727d77bb57fef87a70c8c9cc23dbfee3Eric Laurent sendMsg(mAudioHandler, MSG_SYSTEM_READY, SENDMSG_QUEUE, 5864a5eeb9c727d77bb57fef87a70c8c9cc23dbfee3Eric Laurent 0, 0, null, 0); 5874a5eeb9c727d77bb57fef87a70c8c9cc23dbfee3Eric Laurent } 5884a5eeb9c727d77bb57fef87a70c8c9cc23dbfee3Eric Laurent 5894a5eeb9c727d77bb57fef87a70c8c9cc23dbfee3Eric Laurent public void onSystemReady() { 5904a5eeb9c727d77bb57fef87a70c8c9cc23dbfee3Eric Laurent mSystemReady = true; 5914a5eeb9c727d77bb57fef87a70c8c9cc23dbfee3Eric Laurent sendMsg(mAudioHandler, MSG_LOAD_SOUND_EFFECTS, SENDMSG_QUEUE, 5924a5eeb9c727d77bb57fef87a70c8c9cc23dbfee3Eric Laurent 0, 0, null, 0); 5934a5eeb9c727d77bb57fef87a70c8c9cc23dbfee3Eric Laurent 5944a5eeb9c727d77bb57fef87a70c8c9cc23dbfee3Eric Laurent mKeyguardManager = 5954a5eeb9c727d77bb57fef87a70c8c9cc23dbfee3Eric Laurent (KeyguardManager) mContext.getSystemService(Context.KEYGUARD_SERVICE); 5964a5eeb9c727d77bb57fef87a70c8c9cc23dbfee3Eric Laurent mScoConnectionState = AudioManager.SCO_AUDIO_STATE_ERROR; 5974a5eeb9c727d77bb57fef87a70c8c9cc23dbfee3Eric Laurent resetBluetoothSco(); 5984a5eeb9c727d77bb57fef87a70c8c9cc23dbfee3Eric Laurent getBluetoothHeadset(); 5994a5eeb9c727d77bb57fef87a70c8c9cc23dbfee3Eric Laurent //FIXME: this is to maintain compatibility with deprecated intent 6004a5eeb9c727d77bb57fef87a70c8c9cc23dbfee3Eric Laurent // AudioManager.ACTION_SCO_AUDIO_STATE_CHANGED. Remove when appropriate. 6014a5eeb9c727d77bb57fef87a70c8c9cc23dbfee3Eric Laurent Intent newIntent = new Intent(AudioManager.ACTION_SCO_AUDIO_STATE_CHANGED); 6024a5eeb9c727d77bb57fef87a70c8c9cc23dbfee3Eric Laurent newIntent.putExtra(AudioManager.EXTRA_SCO_AUDIO_STATE, 6034a5eeb9c727d77bb57fef87a70c8c9cc23dbfee3Eric Laurent AudioManager.SCO_AUDIO_STATE_DISCONNECTED); 6044a5eeb9c727d77bb57fef87a70c8c9cc23dbfee3Eric Laurent sendStickyBroadcastToAll(newIntent); 6054a5eeb9c727d77bb57fef87a70c8c9cc23dbfee3Eric Laurent 6064a5eeb9c727d77bb57fef87a70c8c9cc23dbfee3Eric Laurent BluetoothAdapter adapter = BluetoothAdapter.getDefaultAdapter(); 6074a5eeb9c727d77bb57fef87a70c8c9cc23dbfee3Eric Laurent if (adapter != null) { 6084a5eeb9c727d77bb57fef87a70c8c9cc23dbfee3Eric Laurent adapter.getProfileProxy(mContext, mBluetoothProfileServiceListener, 6094a5eeb9c727d77bb57fef87a70c8c9cc23dbfee3Eric Laurent BluetoothProfile.A2DP); 6104a5eeb9c727d77bb57fef87a70c8c9cc23dbfee3Eric Laurent } 6114a5eeb9c727d77bb57fef87a70c8c9cc23dbfee3Eric Laurent 6124a5eeb9c727d77bb57fef87a70c8c9cc23dbfee3Eric Laurent sendMsg(mAudioHandler, 6134a5eeb9c727d77bb57fef87a70c8c9cc23dbfee3Eric Laurent MSG_CONFIGURE_SAFE_MEDIA_VOLUME_FORCED, 6144a5eeb9c727d77bb57fef87a70c8c9cc23dbfee3Eric Laurent SENDMSG_REPLACE, 6154a5eeb9c727d77bb57fef87a70c8c9cc23dbfee3Eric Laurent 0, 6164a5eeb9c727d77bb57fef87a70c8c9cc23dbfee3Eric Laurent 0, 6174a5eeb9c727d77bb57fef87a70c8c9cc23dbfee3Eric Laurent null, 6184a5eeb9c727d77bb57fef87a70c8c9cc23dbfee3Eric Laurent SAFE_VOLUME_CONFIGURE_TIMEOUT_MS); 6194a5eeb9c727d77bb57fef87a70c8c9cc23dbfee3Eric Laurent } 6204a5eeb9c727d77bb57fef87a70c8c9cc23dbfee3Eric Laurent 6219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private void createAudioSystemThread() { 6229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mAudioSystemThread = new AudioSystemThread(); 6239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mAudioSystemThread.start(); 6249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project waitForAudioHandlerCreation(); 6259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 6269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 6279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** Waits for the volume handler to be created by the other thread. */ 6289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private void waitForAudioHandlerCreation() { 6299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project synchronized(this) { 6309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project while (mAudioHandler == null) { 6319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project try { 6329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Wait for mAudioHandler to be set by the other thread 6339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project wait(); 6349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } catch (InterruptedException e) { 6359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Log.e(TAG, "Interrupted while waiting on volume handler."); 6369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 6379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 6389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 6399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 6409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 641244820185269991186d07068b92985624cede4a5Eric Laurent private void checkAllAliasStreamVolumes() { 642244820185269991186d07068b92985624cede4a5Eric Laurent int numStreamTypes = AudioSystem.getNumStreamTypes(); 643244820185269991186d07068b92985624cede4a5Eric Laurent for (int streamType = 0; streamType < numStreamTypes; streamType++) { 644244820185269991186d07068b92985624cede4a5Eric Laurent if (streamType != mStreamVolumeAlias[streamType]) { 645244820185269991186d07068b92985624cede4a5Eric Laurent mStreamStates[streamType]. 64642b041ed4f184e3af7f788eb07307f556a2a6616Eric Laurent setAllIndexes(mStreamStates[mStreamVolumeAlias[streamType]]); 647244820185269991186d07068b92985624cede4a5Eric Laurent } 648244820185269991186d07068b92985624cede4a5Eric Laurent // apply stream volume 64942b041ed4f184e3af7f788eb07307f556a2a6616Eric Laurent if (!mStreamStates[streamType].isMuted()) { 650244820185269991186d07068b92985624cede4a5Eric Laurent mStreamStates[streamType].applyAllVolumes(); 651244820185269991186d07068b92985624cede4a5Eric Laurent } 652244820185269991186d07068b92985624cede4a5Eric Laurent } 653244820185269991186d07068b92985624cede4a5Eric Laurent } 654244820185269991186d07068b92985624cede4a5Eric Laurent 6559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private void createStreamStates() { 6569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int numStreamTypes = AudioSystem.getNumStreamTypes(); 6579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project VolumeStreamState[] streams = mStreamStates = new VolumeStreamState[numStreamTypes]; 6589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 6599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project for (int i = 0; i < numStreamTypes; i++) { 6606d5176638c2189595cede38fb92c3e7e8700e221Eric Laurent streams[i] = new VolumeStreamState(System.VOLUME_SETTINGS[mStreamVolumeAlias[i]], i); 6619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 6629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 663244820185269991186d07068b92985624cede4a5Eric Laurent checkAllAliasStreamVolumes(); 6649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 6659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 666bffc3d1bd33eb2d8e00a9f8b6261d815db503311Eric Laurent private void dumpStreamStates(PrintWriter pw) { 667bffc3d1bd33eb2d8e00a9f8b6261d815db503311Eric Laurent pw.println("\nStream volumes (device: index)"); 668bffc3d1bd33eb2d8e00a9f8b6261d815db503311Eric Laurent int numStreamTypes = AudioSystem.getNumStreamTypes(); 669bffc3d1bd33eb2d8e00a9f8b6261d815db503311Eric Laurent for (int i = 0; i < numStreamTypes; i++) { 670bffc3d1bd33eb2d8e00a9f8b6261d815db503311Eric Laurent pw.println("- "+STREAM_NAMES[i]+":"); 671bffc3d1bd33eb2d8e00a9f8b6261d815db503311Eric Laurent mStreamStates[i].dump(pw); 672bffc3d1bd33eb2d8e00a9f8b6261d815db503311Eric Laurent pw.println(""); 673bffc3d1bd33eb2d8e00a9f8b6261d815db503311Eric Laurent } 674dd45d01128423a82652a3c9d77fa393631d95229Eric Laurent pw.print("\n- mute affected streams = 0x"); 675dd45d01128423a82652a3c9d77fa393631d95229Eric Laurent pw.println(Integer.toHexString(mMuteAffectedStreams)); 676bffc3d1bd33eb2d8e00a9f8b6261d815db503311Eric Laurent } 677bffc3d1bd33eb2d8e00a9f8b6261d815db503311Eric Laurent 6781af30c7ac480e5d335f267a3ac3b2e6c748ce240John Spurlock /** @hide */ 6791af30c7ac480e5d335f267a3ac3b2e6c748ce240John Spurlock public static String streamToString(int stream) { 6801af30c7ac480e5d335f267a3ac3b2e6c748ce240John Spurlock if (stream >= 0 && stream < STREAM_NAMES.length) return STREAM_NAMES[stream]; 6811af30c7ac480e5d335f267a3ac3b2e6c748ce240John Spurlock if (stream == AudioManager.USE_DEFAULT_STREAM_TYPE) return "USE_DEFAULT_STREAM_TYPE"; 6821af30c7ac480e5d335f267a3ac3b2e6c748ce240John Spurlock return "UNKNOWN_STREAM_" + stream; 6831af30c7ac480e5d335f267a3ac3b2e6c748ce240John Spurlock } 6846d5176638c2189595cede38fb92c3e7e8700e221Eric Laurent 6856d5176638c2189595cede38fb92c3e7e8700e221Eric Laurent private void updateStreamVolumeAlias(boolean updateVolumes) { 6866d5176638c2189595cede38fb92c3e7e8700e221Eric Laurent int dtmfStreamAlias; 6876d5176638c2189595cede38fb92c3e7e8700e221Eric Laurent if (mVoiceCapable) { 6886d5176638c2189595cede38fb92c3e7e8700e221Eric Laurent mStreamVolumeAlias = STREAM_VOLUME_ALIAS; 6896d5176638c2189595cede38fb92c3e7e8700e221Eric Laurent dtmfStreamAlias = AudioSystem.STREAM_RING; 6906d5176638c2189595cede38fb92c3e7e8700e221Eric Laurent } else { 6916d5176638c2189595cede38fb92c3e7e8700e221Eric Laurent mStreamVolumeAlias = STREAM_VOLUME_ALIAS_NON_VOICE; 6926d5176638c2189595cede38fb92c3e7e8700e221Eric Laurent dtmfStreamAlias = AudioSystem.STREAM_MUSIC; 6936d5176638c2189595cede38fb92c3e7e8700e221Eric Laurent } 6946d5176638c2189595cede38fb92c3e7e8700e221Eric Laurent if (isInCommunication()) { 6956d5176638c2189595cede38fb92c3e7e8700e221Eric Laurent dtmfStreamAlias = AudioSystem.STREAM_VOICE_CALL; 69624e0d9b6c40712a297e4c287435a3b0fdd30e9daEric Laurent mRingerModeAffectedStreams &= ~(1 << AudioSystem.STREAM_DTMF); 69724e0d9b6c40712a297e4c287435a3b0fdd30e9daEric Laurent } else { 69824e0d9b6c40712a297e4c287435a3b0fdd30e9daEric Laurent mRingerModeAffectedStreams |= (1 << AudioSystem.STREAM_DTMF); 6996d5176638c2189595cede38fb92c3e7e8700e221Eric Laurent } 7006d5176638c2189595cede38fb92c3e7e8700e221Eric Laurent mStreamVolumeAlias[AudioSystem.STREAM_DTMF] = dtmfStreamAlias; 7016d5176638c2189595cede38fb92c3e7e8700e221Eric Laurent if (updateVolumes) { 70242b041ed4f184e3af7f788eb07307f556a2a6616Eric Laurent mStreamStates[AudioSystem.STREAM_DTMF].setAllIndexes(mStreamStates[dtmfStreamAlias]); 70324e0d9b6c40712a297e4c287435a3b0fdd30e9daEric Laurent // apply stream mute states according to new value of mRingerModeAffectedStreams 70424e0d9b6c40712a297e4c287435a3b0fdd30e9daEric Laurent setRingerModeInt(getRingerMode(), false); 7056d5176638c2189595cede38fb92c3e7e8700e221Eric Laurent sendMsg(mAudioHandler, 7066d5176638c2189595cede38fb92c3e7e8700e221Eric Laurent MSG_SET_ALL_VOLUMES, 7076d5176638c2189595cede38fb92c3e7e8700e221Eric Laurent SENDMSG_QUEUE, 7086d5176638c2189595cede38fb92c3e7e8700e221Eric Laurent 0, 7096d5176638c2189595cede38fb92c3e7e8700e221Eric Laurent 0, 7106d5176638c2189595cede38fb92c3e7e8700e221Eric Laurent mStreamStates[AudioSystem.STREAM_DTMF], 0); 7116d5176638c2189595cede38fb92c3e7e8700e221Eric Laurent } 7126d5176638c2189595cede38fb92c3e7e8700e221Eric Laurent } 7136d5176638c2189595cede38fb92c3e7e8700e221Eric Laurent 7147ee1e4ff7346a278a6722108fbc1869240b3e866Eric Laurent private void readDockAudioSettings(ContentResolver cr) 7157ee1e4ff7346a278a6722108fbc1869240b3e866Eric Laurent { 7167ee1e4ff7346a278a6722108fbc1869240b3e866Eric Laurent mDockAudioMediaEnabled = Settings.Global.getInt( 7175ba0ffa0237a5c300545e4c72591613c6e5b2ed9Eric Laurent cr, Settings.Global.DOCK_AUDIO_MEDIA_ENABLED, 0) == 1; 7187ee1e4ff7346a278a6722108fbc1869240b3e866Eric Laurent 7197ee1e4ff7346a278a6722108fbc1869240b3e866Eric Laurent if (mDockAudioMediaEnabled) { 7207ee1e4ff7346a278a6722108fbc1869240b3e866Eric Laurent mBecomingNoisyIntentDevices |= AudioSystem.DEVICE_OUT_ANLG_DOCK_HEADSET; 7217ee1e4ff7346a278a6722108fbc1869240b3e866Eric Laurent } else { 7227ee1e4ff7346a278a6722108fbc1869240b3e866Eric Laurent mBecomingNoisyIntentDevices &= ~AudioSystem.DEVICE_OUT_ANLG_DOCK_HEADSET; 7237ee1e4ff7346a278a6722108fbc1869240b3e866Eric Laurent } 7247ee1e4ff7346a278a6722108fbc1869240b3e866Eric Laurent 7257ee1e4ff7346a278a6722108fbc1869240b3e866Eric Laurent sendMsg(mAudioHandler, 7267ee1e4ff7346a278a6722108fbc1869240b3e866Eric Laurent MSG_SET_FORCE_USE, 7277ee1e4ff7346a278a6722108fbc1869240b3e866Eric Laurent SENDMSG_QUEUE, 7287ee1e4ff7346a278a6722108fbc1869240b3e866Eric Laurent AudioSystem.FOR_DOCK, 7297ee1e4ff7346a278a6722108fbc1869240b3e866Eric Laurent mDockAudioMediaEnabled ? 7307ee1e4ff7346a278a6722108fbc1869240b3e866Eric Laurent AudioSystem.FORCE_ANALOG_DOCK : AudioSystem.FORCE_NONE, 7317ee1e4ff7346a278a6722108fbc1869240b3e866Eric Laurent null, 7327ee1e4ff7346a278a6722108fbc1869240b3e866Eric Laurent 0); 7337ee1e4ff7346a278a6722108fbc1869240b3e866Eric Laurent } 7347ee1e4ff7346a278a6722108fbc1869240b3e866Eric Laurent 7359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private void readPersistedSettings() { 7369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project final ContentResolver cr = mContentResolver; 7379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 738bffc3d1bd33eb2d8e00a9f8b6261d815db503311Eric Laurent int ringerModeFromSettings = 7398d9a1f66d9d3dbbd45a56d441a746ec11dba7645Jeff Sharkey Settings.Global.getInt( 7408d9a1f66d9d3dbbd45a56d441a746ec11dba7645Jeff Sharkey cr, Settings.Global.MODE_RINGER, AudioManager.RINGER_MODE_NORMAL); 741bffc3d1bd33eb2d8e00a9f8b6261d815db503311Eric Laurent int ringerMode = ringerModeFromSettings; 74272668b2c040b581b298b069f3b5af5ed7f212d89Eric Laurent // sanity check in case the settings are restored from a device with incompatible 74372668b2c040b581b298b069f3b5af5ed7f212d89Eric Laurent // ringer modes 744ba195ebc76f23b6679443724ab58c9dc9f2df884Glenn Kasten if (!AudioManager.isValidRingerMode(ringerMode)) { 745ba195ebc76f23b6679443724ab58c9dc9f2df884Glenn Kasten ringerMode = AudioManager.RINGER_MODE_NORMAL; 746bffc3d1bd33eb2d8e00a9f8b6261d815db503311Eric Laurent } 747bffc3d1bd33eb2d8e00a9f8b6261d815db503311Eric Laurent if ((ringerMode == AudioManager.RINGER_MODE_VIBRATE) && !mHasVibrator) { 748bffc3d1bd33eb2d8e00a9f8b6261d815db503311Eric Laurent ringerMode = AudioManager.RINGER_MODE_SILENT; 749bffc3d1bd33eb2d8e00a9f8b6261d815db503311Eric Laurent } 750bffc3d1bd33eb2d8e00a9f8b6261d815db503311Eric Laurent if (ringerMode != ringerModeFromSettings) { 7518d9a1f66d9d3dbbd45a56d441a746ec11dba7645Jeff Sharkey Settings.Global.putInt(cr, Settings.Global.MODE_RINGER, ringerMode); 752ba195ebc76f23b6679443724ab58c9dc9f2df884Glenn Kasten } 75383a017b6b7c099d1a0293e5839be6477325aef06Eric Laurent if (mUseFixedVolume) { 75483a017b6b7c099d1a0293e5839be6477325aef06Eric Laurent ringerMode = AudioManager.RINGER_MODE_NORMAL; 75583a017b6b7c099d1a0293e5839be6477325aef06Eric Laurent } 756ba195ebc76f23b6679443724ab58c9dc9f2df884Glenn Kasten synchronized(mSettingsLock) { 757ba195ebc76f23b6679443724ab58c9dc9f2df884Glenn Kasten mRingerMode = ringerMode; 7589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 759dd45d01128423a82652a3c9d77fa393631d95229Eric Laurent // System.VIBRATE_ON is not used any more but defaults for mVibrateSetting 760dd45d01128423a82652a3c9d77fa393631d95229Eric Laurent // are still needed while setVibrateSetting() and getVibrateSetting() are being 761dd45d01128423a82652a3c9d77fa393631d95229Eric Laurent // deprecated. 762dd45d01128423a82652a3c9d77fa393631d95229Eric Laurent mVibrateSetting = getValueForVibrateSetting(0, 763dd45d01128423a82652a3c9d77fa393631d95229Eric Laurent AudioManager.VIBRATE_TYPE_NOTIFICATION, 764dd45d01128423a82652a3c9d77fa393631d95229Eric Laurent mHasVibrator ? AudioManager.VIBRATE_SETTING_ONLY_SILENT 765dd45d01128423a82652a3c9d77fa393631d95229Eric Laurent : AudioManager.VIBRATE_SETTING_OFF); 766dd45d01128423a82652a3c9d77fa393631d95229Eric Laurent mVibrateSetting = getValueForVibrateSetting(mVibrateSetting, 767dd45d01128423a82652a3c9d77fa393631d95229Eric Laurent AudioManager.VIBRATE_TYPE_RINGER, 768dd45d01128423a82652a3c9d77fa393631d95229Eric Laurent mHasVibrator ? AudioManager.VIBRATE_SETTING_ONLY_SILENT 769dd45d01128423a82652a3c9d77fa393631d95229Eric Laurent : AudioManager.VIBRATE_SETTING_OFF); 770dd45d01128423a82652a3c9d77fa393631d95229Eric Laurent 77124e0d9b6c40712a297e4c287435a3b0fdd30e9daEric Laurent updateRingerModeAffectedStreams(); 7727ee1e4ff7346a278a6722108fbc1869240b3e866Eric Laurent readDockAudioSettings(cr); 773402f7f29634a9f68e7929be828a927a3e2f5efe9Eric Laurent } 774c1d4166289ce016965d1147f7e8d37862ee347ecEric Laurent 775bc0fab1fc2db832ef86d8a33466ec4d68b103ca0Eric Laurent mMuteAffectedStreams = System.getIntForUser(cr, 7769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project System.MUTE_STREAMS_AFFECTED, 777bc0fab1fc2db832ef86d8a33466ec4d68b103ca0Eric Laurent ((1 << AudioSystem.STREAM_MUSIC)| 778bc0fab1fc2db832ef86d8a33466ec4d68b103ca0Eric Laurent (1 << AudioSystem.STREAM_RING)| 779bc0fab1fc2db832ef86d8a33466ec4d68b103ca0Eric Laurent (1 << AudioSystem.STREAM_SYSTEM)), 780bc0fab1fc2db832ef86d8a33466ec4d68b103ca0Eric Laurent UserHandle.USER_CURRENT); 7819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 782bc0fab1fc2db832ef86d8a33466ec4d68b103ca0Eric Laurent boolean masterMute = System.getIntForUser(cr, System.VOLUME_MASTER_MUTE, 783bc0fab1fc2db832ef86d8a33466ec4d68b103ca0Eric Laurent 0, UserHandle.USER_CURRENT) == 1; 78483a017b6b7c099d1a0293e5839be6477325aef06Eric Laurent if (mUseFixedVolume) { 78583a017b6b7c099d1a0293e5839be6477325aef06Eric Laurent masterMute = false; 78683a017b6b7c099d1a0293e5839be6477325aef06Eric Laurent AudioSystem.setMasterVolume(1.0f); 78783a017b6b7c099d1a0293e5839be6477325aef06Eric Laurent } 78857978ed86286a33d5b1a0fd000ca3406ba9d87b3Justin Koh AudioSystem.setMasterMute(masterMute); 78957978ed86286a33d5b1a0fd000ca3406ba9d87b3Justin Koh broadcastMasterMuteStatus(masterMute); 79057978ed86286a33d5b1a0fd000ca3406ba9d87b3Justin Koh 7919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Each stream will read its own persisted settings 7929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 7939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Broadcast the sticky intent 794ba195ebc76f23b6679443724ab58c9dc9f2df884Glenn Kasten broadcastRingerMode(ringerMode); 7959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 7969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Broadcast vibrate settings 7979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project broadcastVibrateSetting(AudioManager.VIBRATE_TYPE_RINGER); 7989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project broadcastVibrateSetting(AudioManager.VIBRATE_TYPE_NOTIFICATION); 799d589fea865e90859324f00d21765fa7d7759e465Jean-Michel Trivi 800d589fea865e90859324f00d21765fa7d7759e465Jean-Michel Trivi // Restore the default media button receiver from the system settings 801fa9a69805b001034aa04c3b33989a7ac21522371Jean-Michel Trivi mMediaFocusControl.restoreMediaButtonReceiver(); 8029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 8039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 804a553c25b33c99b345cf1c8688f8df0ed8df14e5aEric Laurent private int rescaleIndex(int index, int srcStream, int dstStream) { 805a553c25b33c99b345cf1c8688f8df0ed8df14e5aEric Laurent return (index * mStreamStates[dstStream].getMaxIndex() + mStreamStates[srcStream].getMaxIndex() / 2) / mStreamStates[srcStream].getMaxIndex(); 806a553c25b33c99b345cf1c8688f8df0ed8df14e5aEric Laurent } 8079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 8089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /////////////////////////////////////////////////////////////////////////// 8099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // IPC methods 8109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /////////////////////////////////////////////////////////////////////////// 811fca1e603236b8d1681f784e77e3719d1d59c1428Jean-Michel Trivi /** @see AudioManager#isLocalOrRemoteMusicActive() */ 812fca1e603236b8d1681f784e77e3719d1d59c1428Jean-Michel Trivi public boolean isLocalOrRemoteMusicActive() { 813fca1e603236b8d1681f784e77e3719d1d59c1428Jean-Michel Trivi if (AudioSystem.isStreamActive(AudioSystem.STREAM_MUSIC, 0)) { 814fca1e603236b8d1681f784e77e3719d1d59c1428Jean-Michel Trivi // local / wired / BT playback active 815fca1e603236b8d1681f784e77e3719d1d59c1428Jean-Michel Trivi if (DEBUG_VOL) Log.d(TAG, "isLocalOrRemoteMusicActive(): local"); 816fca1e603236b8d1681f784e77e3719d1d59c1428Jean-Michel Trivi return true; 817fca1e603236b8d1681f784e77e3719d1d59c1428Jean-Michel Trivi } 818fca1e603236b8d1681f784e77e3719d1d59c1428Jean-Michel Trivi if (mMediaFocusControl.checkUpdateRemoteStateIfActive(AudioSystem.STREAM_MUSIC)) { 819fca1e603236b8d1681f784e77e3719d1d59c1428Jean-Michel Trivi // remote "cast-like" playback active 820fca1e603236b8d1681f784e77e3719d1d59c1428Jean-Michel Trivi if (DEBUG_VOL) Log.d(TAG, "isLocalOrRemoteMusicActive(): has PLAYBACK_TYPE_REMOTE"); 821fca1e603236b8d1681f784e77e3719d1d59c1428Jean-Michel Trivi return true; 822fca1e603236b8d1681f784e77e3719d1d59c1428Jean-Michel Trivi } 823fca1e603236b8d1681f784e77e3719d1d59c1428Jean-Michel Trivi if (AudioSystem.isStreamActiveRemotely(AudioSystem.STREAM_MUSIC, 0)) { 824fca1e603236b8d1681f784e77e3719d1d59c1428Jean-Michel Trivi // remote submix playback active 825fca1e603236b8d1681f784e77e3719d1d59c1428Jean-Michel Trivi if (DEBUG_VOL) Log.d(TAG, "isLocalOrRemoteMusicActive(): remote submix"); 826fca1e603236b8d1681f784e77e3719d1d59c1428Jean-Michel Trivi return true; 827fca1e603236b8d1681f784e77e3719d1d59c1428Jean-Michel Trivi } 828fca1e603236b8d1681f784e77e3719d1d59c1428Jean-Michel Trivi if (DEBUG_VOL) Log.d(TAG, "isLocalOrRemoteMusicActive(): no"); 829fca1e603236b8d1681f784e77e3719d1d59c1428Jean-Michel Trivi return false; 830fca1e603236b8d1681f784e77e3719d1d59c1428Jean-Michel Trivi } 8319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 8329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** @see AudioManager#adjustVolume(int, int) */ 833ba50b97cff80e73620a0e3d13cae169e095974a7Dianne Hackborn public void adjustSuggestedStreamVolume(int direction, int suggestedStreamType, int flags, 834ba50b97cff80e73620a0e3d13cae169e095974a7Dianne Hackborn String callingPackage) { 8353114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi if (DEBUG_VOL) Log.d(TAG, "adjustSuggestedStreamVolume() stream="+suggestedStreamType); 836402f7f29634a9f68e7929be828a927a3e2f5efe9Eric Laurent int streamType; 83745c90cefd13a03b852bb4b8da4be218876cbbb32Eric Laurent if (mVolumeControlStream != -1) { 83845c90cefd13a03b852bb4b8da4be218876cbbb32Eric Laurent streamType = mVolumeControlStream; 839402f7f29634a9f68e7929be828a927a3e2f5efe9Eric Laurent } else { 840402f7f29634a9f68e7929be828a927a3e2f5efe9Eric Laurent streamType = getActiveStreamType(suggestedStreamType); 841402f7f29634a9f68e7929be828a927a3e2f5efe9Eric Laurent } 8429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 8436243edd818b84adfbe712d5d233d6414b33653acAmith Yamasani // Play sounds on STREAM_RING only and if lock screen is not on. 8443114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi if ((streamType != STREAM_REMOTE_MUSIC) && 8453114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi (flags & AudioManager.FLAG_PLAY_SOUND) != 0 && 8466d5176638c2189595cede38fb92c3e7e8700e221Eric Laurent ((mStreamVolumeAlias[streamType] != AudioSystem.STREAM_RING) 8476243edd818b84adfbe712d5d233d6414b33653acAmith Yamasani || (mKeyguardManager != null && mKeyguardManager.isKeyguardLocked()))) { 8489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project flags &= ~AudioManager.FLAG_PLAY_SOUND; 8499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 8509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 8513114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi if (streamType == STREAM_REMOTE_MUSIC) { 85219c9518f6a817d53d5234de0020313cab6950b2fRoboErik // TODO bounce it to MediaSessionService to find an appropriate 85319c9518f6a817d53d5234de0020313cab6950b2fRoboErik // session 8543114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi } else { 855ba50b97cff80e73620a0e3d13cae169e095974a7Dianne Hackborn adjustStreamVolume(streamType, direction, flags, callingPackage); 8563114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi } 8579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 8589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 8599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** @see AudioManager#adjustStreamVolume(int, int, int) */ 860ba50b97cff80e73620a0e3d13cae169e095974a7Dianne Hackborn public void adjustStreamVolume(int streamType, int direction, int flags, 861ba50b97cff80e73620a0e3d13cae169e095974a7Dianne Hackborn String callingPackage) { 86283a017b6b7c099d1a0293e5839be6477325aef06Eric Laurent if (mUseFixedVolume) { 86383a017b6b7c099d1a0293e5839be6477325aef06Eric Laurent return; 86483a017b6b7c099d1a0293e5839be6477325aef06Eric Laurent } 8653114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi if (DEBUG_VOL) Log.d(TAG, "adjustStreamVolume() stream="+streamType+", dir="+direction); 8663114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi 8679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project ensureValidDirection(direction); 8689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project ensureValidStreamType(streamType); 8699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 87096a33d1caad2fab0bc28891cfbf553f4b050bf0bEric Laurent // use stream type alias here so that streams with same alias have the same behavior, 87196a33d1caad2fab0bc28891cfbf553f4b050bf0bEric Laurent // including with regard to silent mode control (e.g the use of STREAM_RING below and in 87296a33d1caad2fab0bc28891cfbf553f4b050bf0bEric Laurent // checkForRingerModeChange() in place of STREAM_RING or STREAM_NOTIFICATION) 8736d5176638c2189595cede38fb92c3e7e8700e221Eric Laurent int streamTypeAlias = mStreamVolumeAlias[streamType]; 874b024c30a80684ac08daef3137b7ba0d347fe3ce5Eric Laurent VolumeStreamState streamState = mStreamStates[streamTypeAlias]; 8759bc8358ddaa01c3490f9709991989633a6a3dd42Eric Laurent 8769bc8358ddaa01c3490f9709991989633a6a3dd42Eric Laurent final int device = getDeviceForStream(streamTypeAlias); 8773ef7549876a159dae1568429edcb57e4e7d08459Eric Laurent 87842b041ed4f184e3af7f788eb07307f556a2a6616Eric Laurent int aliasIndex = streamState.getIndex(device); 8799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project boolean adjustVolume = true; 8803ef7549876a159dae1568429edcb57e4e7d08459Eric Laurent int step; 881244820185269991186d07068b92985624cede4a5Eric Laurent 882c9d1d5f35091226e96fcfa91817480f589eb36e2Matthew Xie // skip a2dp absolute volume control request when the device 883c9d1d5f35091226e96fcfa91817480f589eb36e2Matthew Xie // is not an a2dp device 884c9d1d5f35091226e96fcfa91817480f589eb36e2Matthew Xie if ((device & AudioSystem.DEVICE_OUT_ALL_A2DP) == 0 && 885c9d1d5f35091226e96fcfa91817480f589eb36e2Matthew Xie (flags & AudioManager.FLAG_BLUETOOTH_ABS_VOLUME) != 0) { 886c9d1d5f35091226e96fcfa91817480f589eb36e2Matthew Xie return; 887c9d1d5f35091226e96fcfa91817480f589eb36e2Matthew Xie } 888c9d1d5f35091226e96fcfa91817480f589eb36e2Matthew Xie 889ba50b97cff80e73620a0e3d13cae169e095974a7Dianne Hackborn if (mAppOps.noteOp(STEAM_VOLUME_OPS[streamTypeAlias], Binder.getCallingUid(), 890ba50b97cff80e73620a0e3d13cae169e095974a7Dianne Hackborn callingPackage) != AppOpsManager.MODE_ALLOWED) { 891ba50b97cff80e73620a0e3d13cae169e095974a7Dianne Hackborn return; 892ba50b97cff80e73620a0e3d13cae169e095974a7Dianne Hackborn } 893ba50b97cff80e73620a0e3d13cae169e095974a7Dianne Hackborn 894fde16d5879ea88a971004c984093409468b6139cEric Laurent // reset any pending volume command 895fde16d5879ea88a971004c984093409468b6139cEric Laurent synchronized (mSafeMediaVolumeState) { 896fde16d5879ea88a971004c984093409468b6139cEric Laurent mPendingVolumeCommand = null; 897fde16d5879ea88a971004c984093409468b6139cEric Laurent } 898fde16d5879ea88a971004c984093409468b6139cEric Laurent 8993ef7549876a159dae1568429edcb57e4e7d08459Eric Laurent flags &= ~AudioManager.FLAG_FIXED_VOLUME; 9003ef7549876a159dae1568429edcb57e4e7d08459Eric Laurent if ((streamTypeAlias == AudioSystem.STREAM_MUSIC) && 9013ef7549876a159dae1568429edcb57e4e7d08459Eric Laurent ((device & mFixedVolumeDevices) != 0)) { 9023ef7549876a159dae1568429edcb57e4e7d08459Eric Laurent flags |= AudioManager.FLAG_FIXED_VOLUME; 9033ef7549876a159dae1568429edcb57e4e7d08459Eric Laurent 9043ef7549876a159dae1568429edcb57e4e7d08459Eric Laurent // Always toggle between max safe volume and 0 for fixed volume devices where safe 9053ef7549876a159dae1568429edcb57e4e7d08459Eric Laurent // volume is enforced, and max and 0 for the others. 9063ef7549876a159dae1568429edcb57e4e7d08459Eric Laurent // This is simulated by stepping by the full allowed volume range 9073ef7549876a159dae1568429edcb57e4e7d08459Eric Laurent if (mSafeMediaVolumeState == SAFE_MEDIA_VOLUME_ACTIVE && 9083ef7549876a159dae1568429edcb57e4e7d08459Eric Laurent (device & mSafeMediaVolumeDevices) != 0) { 9093ef7549876a159dae1568429edcb57e4e7d08459Eric Laurent step = mSafeMediaVolumeIndex; 9103ef7549876a159dae1568429edcb57e4e7d08459Eric Laurent } else { 9113ef7549876a159dae1568429edcb57e4e7d08459Eric Laurent step = streamState.getMaxIndex(); 9123ef7549876a159dae1568429edcb57e4e7d08459Eric Laurent } 9133ef7549876a159dae1568429edcb57e4e7d08459Eric Laurent if (aliasIndex != 0) { 9143ef7549876a159dae1568429edcb57e4e7d08459Eric Laurent aliasIndex = step; 9153ef7549876a159dae1568429edcb57e4e7d08459Eric Laurent } 9163ef7549876a159dae1568429edcb57e4e7d08459Eric Laurent } else { 9173ef7549876a159dae1568429edcb57e4e7d08459Eric Laurent // convert one UI step (+/-1) into a number of internal units on the stream alias 9183ef7549876a159dae1568429edcb57e4e7d08459Eric Laurent step = rescaleIndex(10, streamType, streamTypeAlias); 9193ef7549876a159dae1568429edcb57e4e7d08459Eric Laurent } 9203ef7549876a159dae1568429edcb57e4e7d08459Eric Laurent 92142b041ed4f184e3af7f788eb07307f556a2a6616Eric Laurent // If either the client forces allowing ringer modes for this adjustment, 92242b041ed4f184e3af7f788eb07307f556a2a6616Eric Laurent // or the stream type is one that is affected by ringer modes 92342b041ed4f184e3af7f788eb07307f556a2a6616Eric Laurent if (((flags & AudioManager.FLAG_ALLOW_RINGER_MODES) != 0) || 92442b041ed4f184e3af7f788eb07307f556a2a6616Eric Laurent (streamTypeAlias == getMasterStreamType())) { 92542b041ed4f184e3af7f788eb07307f556a2a6616Eric Laurent int ringerMode = getRingerMode(); 92642b041ed4f184e3af7f788eb07307f556a2a6616Eric Laurent // do not vibrate if already in vibrate mode 92742b041ed4f184e3af7f788eb07307f556a2a6616Eric Laurent if (ringerMode == AudioManager.RINGER_MODE_VIBRATE) { 92842b041ed4f184e3af7f788eb07307f556a2a6616Eric Laurent flags &= ~AudioManager.FLAG_VIBRATE; 92942b041ed4f184e3af7f788eb07307f556a2a6616Eric Laurent } 93042b041ed4f184e3af7f788eb07307f556a2a6616Eric Laurent // Check if the ringer mode changes with this volume adjustment. If 93142b041ed4f184e3af7f788eb07307f556a2a6616Eric Laurent // it does, it will handle adjusting the volume, so we won't below 932a11b4affcad3d255aa723a89b768ea222506f2e8John Spurlock final int result = checkForRingerModeChange(aliasIndex, direction, step); 933a11b4affcad3d255aa723a89b768ea222506f2e8John Spurlock adjustVolume = (result & FLAG_ADJUST_VOLUME) != 0; 934a11b4affcad3d255aa723a89b768ea222506f2e8John Spurlock // If suppressing a volume adjustment in silent mode, display the UI hint 935a11b4affcad3d255aa723a89b768ea222506f2e8John Spurlock if ((result & AudioManager.FLAG_SHOW_SILENT_HINT) != 0) { 936a11b4affcad3d255aa723a89b768ea222506f2e8John Spurlock flags |= AudioManager.FLAG_SHOW_SILENT_HINT; 937a11b4affcad3d255aa723a89b768ea222506f2e8John Spurlock } 93842b041ed4f184e3af7f788eb07307f556a2a6616Eric Laurent } 93942b041ed4f184e3af7f788eb07307f556a2a6616Eric Laurent 94042b041ed4f184e3af7f788eb07307f556a2a6616Eric Laurent int oldIndex = mStreamStates[streamType].getIndex(device); 94142b041ed4f184e3af7f788eb07307f556a2a6616Eric Laurent 94242b041ed4f184e3af7f788eb07307f556a2a6616Eric Laurent if (adjustVolume && (direction != AudioManager.ADJUST_SAME)) { 943c9d1d5f35091226e96fcfa91817480f589eb36e2Matthew Xie 9445a0cf7a27f3953a1266af48543ccd9024f4cd89fJohn Du // Check if volume update should be send to AVRCP 945c9d1d5f35091226e96fcfa91817480f589eb36e2Matthew Xie if (streamTypeAlias == AudioSystem.STREAM_MUSIC && 946c9d1d5f35091226e96fcfa91817480f589eb36e2Matthew Xie (device & AudioSystem.DEVICE_OUT_ALL_A2DP) != 0 && 947c9d1d5f35091226e96fcfa91817480f589eb36e2Matthew Xie (flags & AudioManager.FLAG_BLUETOOTH_ABS_VOLUME) == 0) { 948c9d1d5f35091226e96fcfa91817480f589eb36e2Matthew Xie synchronized (mA2dpAvrcpLock) { 949c9d1d5f35091226e96fcfa91817480f589eb36e2Matthew Xie if (mA2dp != null && mAvrcpAbsVolSupported) { 950c9d1d5f35091226e96fcfa91817480f589eb36e2Matthew Xie mA2dp.adjustAvrcpAbsoluteVolume(direction); 951c9d1d5f35091226e96fcfa91817480f589eb36e2Matthew Xie } 9525a0cf7a27f3953a1266af48543ccd9024f4cd89fJohn Du } 9535a0cf7a27f3953a1266af48543ccd9024f4cd89fJohn Du } 954c9d1d5f35091226e96fcfa91817480f589eb36e2Matthew Xie 95542b041ed4f184e3af7f788eb07307f556a2a6616Eric Laurent if ((direction == AudioManager.ADJUST_RAISE) && 95642b041ed4f184e3af7f788eb07307f556a2a6616Eric Laurent !checkSafeMediaVolume(streamTypeAlias, aliasIndex + step, device)) { 95742b041ed4f184e3af7f788eb07307f556a2a6616Eric Laurent Log.e(TAG, "adjustStreamVolume() safe volume index = "+oldIndex); 9583346a802087f621c6441bc512dfcc17b07143fc6John Spurlock mVolumeController.postDisplaySafeVolumeWarning(flags); 95942b041ed4f184e3af7f788eb07307f556a2a6616Eric Laurent } else if (streamState.adjustIndex(direction * step, device)) { 96042b041ed4f184e3af7f788eb07307f556a2a6616Eric Laurent // Post message to set system volume (it in turn will post a message 96142b041ed4f184e3af7f788eb07307f556a2a6616Eric Laurent // to persist). Do not change volume if stream is muted. 96242b041ed4f184e3af7f788eb07307f556a2a6616Eric Laurent sendMsg(mAudioHandler, 96342b041ed4f184e3af7f788eb07307f556a2a6616Eric Laurent MSG_SET_DEVICE_VOLUME, 96442b041ed4f184e3af7f788eb07307f556a2a6616Eric Laurent SENDMSG_QUEUE, 96542b041ed4f184e3af7f788eb07307f556a2a6616Eric Laurent device, 96642b041ed4f184e3af7f788eb07307f556a2a6616Eric Laurent 0, 96742b041ed4f184e3af7f788eb07307f556a2a6616Eric Laurent streamState, 96842b041ed4f184e3af7f788eb07307f556a2a6616Eric Laurent 0); 9694bbcc6549738f3d69831b2bd9eb4accec3e9920eEric Laurent } 9704bbcc6549738f3d69831b2bd9eb4accec3e9920eEric Laurent } 97142b041ed4f184e3af7f788eb07307f556a2a6616Eric Laurent int index = mStreamStates[streamType].getIndex(device); 97225101b0b9a84571ead15b26e9f4cd9c4298d7823Eric Laurent sendVolumeUpdate(streamType, oldIndex, index, flags); 9739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 9749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 975961cae92540763226648813d111c5b5c3b0f1597Dianne Hackborn /** @see AudioManager#adjustMasterVolume(int, int) */ 976ba50b97cff80e73620a0e3d13cae169e095974a7Dianne Hackborn public void adjustMasterVolume(int steps, int flags, String callingPackage) { 97783a017b6b7c099d1a0293e5839be6477325aef06Eric Laurent if (mUseFixedVolume) { 97883a017b6b7c099d1a0293e5839be6477325aef06Eric Laurent return; 97983a017b6b7c099d1a0293e5839be6477325aef06Eric Laurent } 9806c798970ccb8759d1e613b57111daa8da0ab44c7Lei Zhang ensureValidSteps(steps); 9819760647dd0ee67e7c20f3e9d661d2006b1df0b54Mike Lockwood int volume = Math.round(AudioSystem.getMasterVolume() * MAX_MASTER_VOLUME); 9829760647dd0ee67e7c20f3e9d661d2006b1df0b54Mike Lockwood int delta = 0; 9836c798970ccb8759d1e613b57111daa8da0ab44c7Lei Zhang int numSteps = Math.abs(steps); 9846c798970ccb8759d1e613b57111daa8da0ab44c7Lei Zhang int direction = steps > 0 ? AudioManager.ADJUST_RAISE : AudioManager.ADJUST_LOWER; 9856c798970ccb8759d1e613b57111daa8da0ab44c7Lei Zhang for (int i = 0; i < numSteps; ++i) { 9866c798970ccb8759d1e613b57111daa8da0ab44c7Lei Zhang delta = findVolumeDelta(direction, volume); 9876c798970ccb8759d1e613b57111daa8da0ab44c7Lei Zhang volume += delta; 988cbdb49dc5e1b993a0bc5c68dbfb9486bfa0cd762Mike Lockwood } 98924b082f87e96c00d5c17d60c735423900be40e70RoboErik 9906c798970ccb8759d1e613b57111daa8da0ab44c7Lei Zhang //Log.d(TAG, "adjustMasterVolume volume: " + volume + " steps: " + steps); 991ba50b97cff80e73620a0e3d13cae169e095974a7Dianne Hackborn setMasterVolume(volume, flags, callingPackage); 992cbdb49dc5e1b993a0bc5c68dbfb9486bfa0cd762Mike Lockwood } 993cbdb49dc5e1b993a0bc5c68dbfb9486bfa0cd762Mike Lockwood 994fde16d5879ea88a971004c984093409468b6139cEric Laurent // StreamVolumeCommand contains the information needed to defer the process of 995fde16d5879ea88a971004c984093409468b6139cEric Laurent // setStreamVolume() in case the user has to acknowledge the safe volume warning message. 996fde16d5879ea88a971004c984093409468b6139cEric Laurent class StreamVolumeCommand { 997fde16d5879ea88a971004c984093409468b6139cEric Laurent public final int mStreamType; 998fde16d5879ea88a971004c984093409468b6139cEric Laurent public final int mIndex; 999fde16d5879ea88a971004c984093409468b6139cEric Laurent public final int mFlags; 1000fde16d5879ea88a971004c984093409468b6139cEric Laurent public final int mDevice; 10013ef7549876a159dae1568429edcb57e4e7d08459Eric Laurent 1002fde16d5879ea88a971004c984093409468b6139cEric Laurent StreamVolumeCommand(int streamType, int index, int flags, int device) { 1003fde16d5879ea88a971004c984093409468b6139cEric Laurent mStreamType = streamType; 1004fde16d5879ea88a971004c984093409468b6139cEric Laurent mIndex = index; 1005fde16d5879ea88a971004c984093409468b6139cEric Laurent mFlags = flags; 1006fde16d5879ea88a971004c984093409468b6139cEric Laurent mDevice = device; 10074bbcc6549738f3d69831b2bd9eb4accec3e9920eEric Laurent } 1008fde16d5879ea88a971004c984093409468b6139cEric Laurent }; 10093ef7549876a159dae1568429edcb57e4e7d08459Eric Laurent 1010fde16d5879ea88a971004c984093409468b6139cEric Laurent private void onSetStreamVolume(int streamType, int index, int flags, int device) { 101142b041ed4f184e3af7f788eb07307f556a2a6616Eric Laurent setStreamVolumeInt(mStreamVolumeAlias[streamType], index, device, false); 10123ef7549876a159dae1568429edcb57e4e7d08459Eric Laurent // setting volume on master stream type also controls silent mode 10133ef7549876a159dae1568429edcb57e4e7d08459Eric Laurent if (((flags & AudioManager.FLAG_ALLOW_RINGER_MODES) != 0) || 10143ef7549876a159dae1568429edcb57e4e7d08459Eric Laurent (mStreamVolumeAlias[streamType] == getMasterStreamType())) { 10153ef7549876a159dae1568429edcb57e4e7d08459Eric Laurent int newRingerMode; 10163ef7549876a159dae1568429edcb57e4e7d08459Eric Laurent if (index == 0) { 10173ef7549876a159dae1568429edcb57e4e7d08459Eric Laurent newRingerMode = mHasVibrator ? AudioManager.RINGER_MODE_VIBRATE 10188600534df66c2ff5846ed230b50c56229322d48aJohn Spurlock : VOLUME_SETS_RINGER_MODE_SILENT ? AudioManager.RINGER_MODE_SILENT 10198600534df66c2ff5846ed230b50c56229322d48aJohn Spurlock : AudioManager.RINGER_MODE_NORMAL; 10203ef7549876a159dae1568429edcb57e4e7d08459Eric Laurent } else { 10213ef7549876a159dae1568429edcb57e4e7d08459Eric Laurent newRingerMode = AudioManager.RINGER_MODE_NORMAL; 10223ef7549876a159dae1568429edcb57e4e7d08459Eric Laurent } 10233ef7549876a159dae1568429edcb57e4e7d08459Eric Laurent setRingerMode(newRingerMode); 10243ef7549876a159dae1568429edcb57e4e7d08459Eric Laurent } 1025fde16d5879ea88a971004c984093409468b6139cEric Laurent } 1026fde16d5879ea88a971004c984093409468b6139cEric Laurent 1027fde16d5879ea88a971004c984093409468b6139cEric Laurent /** @see AudioManager#setStreamVolume(int, int, int) */ 1028ba50b97cff80e73620a0e3d13cae169e095974a7Dianne Hackborn public void setStreamVolume(int streamType, int index, int flags, String callingPackage) { 102983a017b6b7c099d1a0293e5839be6477325aef06Eric Laurent if (mUseFixedVolume) { 103083a017b6b7c099d1a0293e5839be6477325aef06Eric Laurent return; 103183a017b6b7c099d1a0293e5839be6477325aef06Eric Laurent } 103283a017b6b7c099d1a0293e5839be6477325aef06Eric Laurent 1033fde16d5879ea88a971004c984093409468b6139cEric Laurent ensureValidStreamType(streamType); 1034ba50b97cff80e73620a0e3d13cae169e095974a7Dianne Hackborn int streamTypeAlias = mStreamVolumeAlias[streamType]; 1035ba50b97cff80e73620a0e3d13cae169e095974a7Dianne Hackborn VolumeStreamState streamState = mStreamStates[streamTypeAlias]; 1036fde16d5879ea88a971004c984093409468b6139cEric Laurent 1037fde16d5879ea88a971004c984093409468b6139cEric Laurent final int device = getDeviceForStream(streamType); 1038fde16d5879ea88a971004c984093409468b6139cEric Laurent int oldIndex; 1039fde16d5879ea88a971004c984093409468b6139cEric Laurent 1040c9d1d5f35091226e96fcfa91817480f589eb36e2Matthew Xie // skip a2dp absolute volume control request when the device 1041c9d1d5f35091226e96fcfa91817480f589eb36e2Matthew Xie // is not an a2dp device 1042c9d1d5f35091226e96fcfa91817480f589eb36e2Matthew Xie if ((device & AudioSystem.DEVICE_OUT_ALL_A2DP) == 0 && 1043c9d1d5f35091226e96fcfa91817480f589eb36e2Matthew Xie (flags & AudioManager.FLAG_BLUETOOTH_ABS_VOLUME) != 0) { 1044c9d1d5f35091226e96fcfa91817480f589eb36e2Matthew Xie return; 1045c9d1d5f35091226e96fcfa91817480f589eb36e2Matthew Xie } 1046c9d1d5f35091226e96fcfa91817480f589eb36e2Matthew Xie 1047ba50b97cff80e73620a0e3d13cae169e095974a7Dianne Hackborn if (mAppOps.noteOp(STEAM_VOLUME_OPS[streamTypeAlias], Binder.getCallingUid(), 1048ba50b97cff80e73620a0e3d13cae169e095974a7Dianne Hackborn callingPackage) != AppOpsManager.MODE_ALLOWED) { 1049ba50b97cff80e73620a0e3d13cae169e095974a7Dianne Hackborn return; 1050ba50b97cff80e73620a0e3d13cae169e095974a7Dianne Hackborn } 1051ba50b97cff80e73620a0e3d13cae169e095974a7Dianne Hackborn 1052fde16d5879ea88a971004c984093409468b6139cEric Laurent synchronized (mSafeMediaVolumeState) { 1053fde16d5879ea88a971004c984093409468b6139cEric Laurent // reset any pending volume command 1054fde16d5879ea88a971004c984093409468b6139cEric Laurent mPendingVolumeCommand = null; 1055fde16d5879ea88a971004c984093409468b6139cEric Laurent 105642b041ed4f184e3af7f788eb07307f556a2a6616Eric Laurent oldIndex = streamState.getIndex(device); 1057fde16d5879ea88a971004c984093409468b6139cEric Laurent 1058ba50b97cff80e73620a0e3d13cae169e095974a7Dianne Hackborn index = rescaleIndex(index * 10, streamType, streamTypeAlias); 1059fde16d5879ea88a971004c984093409468b6139cEric Laurent 1060c9d1d5f35091226e96fcfa91817480f589eb36e2Matthew Xie if (streamTypeAlias == AudioSystem.STREAM_MUSIC && 1061c9d1d5f35091226e96fcfa91817480f589eb36e2Matthew Xie (device & AudioSystem.DEVICE_OUT_ALL_A2DP) != 0 && 1062c9d1d5f35091226e96fcfa91817480f589eb36e2Matthew Xie (flags & AudioManager.FLAG_BLUETOOTH_ABS_VOLUME) == 0) { 1063c9d1d5f35091226e96fcfa91817480f589eb36e2Matthew Xie synchronized (mA2dpAvrcpLock) { 1064c9d1d5f35091226e96fcfa91817480f589eb36e2Matthew Xie if (mA2dp != null && mAvrcpAbsVolSupported) { 10652f4a2b139b4c1dde7be1d14333ad02553734c528Zhihai Xu mA2dp.setAvrcpAbsoluteVolume(index / 10); 1066c9d1d5f35091226e96fcfa91817480f589eb36e2Matthew Xie } 10675a0cf7a27f3953a1266af48543ccd9024f4cd89fJohn Du } 10685a0cf7a27f3953a1266af48543ccd9024f4cd89fJohn Du } 10695a0cf7a27f3953a1266af48543ccd9024f4cd89fJohn Du 1070fde16d5879ea88a971004c984093409468b6139cEric Laurent flags &= ~AudioManager.FLAG_FIXED_VOLUME; 1071ba50b97cff80e73620a0e3d13cae169e095974a7Dianne Hackborn if ((streamTypeAlias == AudioSystem.STREAM_MUSIC) && 1072fde16d5879ea88a971004c984093409468b6139cEric Laurent ((device & mFixedVolumeDevices) != 0)) { 1073fde16d5879ea88a971004c984093409468b6139cEric Laurent flags |= AudioManager.FLAG_FIXED_VOLUME; 1074fde16d5879ea88a971004c984093409468b6139cEric Laurent 1075fde16d5879ea88a971004c984093409468b6139cEric Laurent // volume is either 0 or max allowed for fixed volume devices 1076fde16d5879ea88a971004c984093409468b6139cEric Laurent if (index != 0) { 1077fde16d5879ea88a971004c984093409468b6139cEric Laurent if (mSafeMediaVolumeState == SAFE_MEDIA_VOLUME_ACTIVE && 1078fde16d5879ea88a971004c984093409468b6139cEric Laurent (device & mSafeMediaVolumeDevices) != 0) { 1079fde16d5879ea88a971004c984093409468b6139cEric Laurent index = mSafeMediaVolumeIndex; 1080fde16d5879ea88a971004c984093409468b6139cEric Laurent } else { 1081fde16d5879ea88a971004c984093409468b6139cEric Laurent index = streamState.getMaxIndex(); 1082fde16d5879ea88a971004c984093409468b6139cEric Laurent } 1083fde16d5879ea88a971004c984093409468b6139cEric Laurent } 1084fde16d5879ea88a971004c984093409468b6139cEric Laurent } 1085fde16d5879ea88a971004c984093409468b6139cEric Laurent 1086ba50b97cff80e73620a0e3d13cae169e095974a7Dianne Hackborn if (!checkSafeMediaVolume(streamTypeAlias, index, device)) { 10873346a802087f621c6441bc512dfcc17b07143fc6John Spurlock mVolumeController.postDisplaySafeVolumeWarning(flags); 1088fde16d5879ea88a971004c984093409468b6139cEric Laurent mPendingVolumeCommand = new StreamVolumeCommand( 1089fde16d5879ea88a971004c984093409468b6139cEric Laurent streamType, index, flags, device); 1090fde16d5879ea88a971004c984093409468b6139cEric Laurent } else { 1091fde16d5879ea88a971004c984093409468b6139cEric Laurent onSetStreamVolume(streamType, index, flags, device); 109242b041ed4f184e3af7f788eb07307f556a2a6616Eric Laurent index = mStreamStates[streamType].getIndex(device); 1093fde16d5879ea88a971004c984093409468b6139cEric Laurent } 1094fde16d5879ea88a971004c984093409468b6139cEric Laurent } 109525101b0b9a84571ead15b26e9f4cd9c4298d7823Eric Laurent sendVolumeUpdate(streamType, oldIndex, index, flags); 10969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 10979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 109845c90cefd13a03b852bb4b8da4be218876cbbb32Eric Laurent /** @see AudioManager#forceVolumeControlStream(int) */ 109945c90cefd13a03b852bb4b8da4be218876cbbb32Eric Laurent public void forceVolumeControlStream(int streamType, IBinder cb) { 110045c90cefd13a03b852bb4b8da4be218876cbbb32Eric Laurent synchronized(mForceControlStreamLock) { 110145c90cefd13a03b852bb4b8da4be218876cbbb32Eric Laurent mVolumeControlStream = streamType; 110245c90cefd13a03b852bb4b8da4be218876cbbb32Eric Laurent if (mVolumeControlStream == -1) { 110345c90cefd13a03b852bb4b8da4be218876cbbb32Eric Laurent if (mForceControlStreamClient != null) { 110445c90cefd13a03b852bb4b8da4be218876cbbb32Eric Laurent mForceControlStreamClient.release(); 110545c90cefd13a03b852bb4b8da4be218876cbbb32Eric Laurent mForceControlStreamClient = null; 110645c90cefd13a03b852bb4b8da4be218876cbbb32Eric Laurent } 110745c90cefd13a03b852bb4b8da4be218876cbbb32Eric Laurent } else { 110845c90cefd13a03b852bb4b8da4be218876cbbb32Eric Laurent mForceControlStreamClient = new ForceControlStreamClient(cb); 110945c90cefd13a03b852bb4b8da4be218876cbbb32Eric Laurent } 111045c90cefd13a03b852bb4b8da4be218876cbbb32Eric Laurent } 111145c90cefd13a03b852bb4b8da4be218876cbbb32Eric Laurent } 111245c90cefd13a03b852bb4b8da4be218876cbbb32Eric Laurent 111345c90cefd13a03b852bb4b8da4be218876cbbb32Eric Laurent private class ForceControlStreamClient implements IBinder.DeathRecipient { 111445c90cefd13a03b852bb4b8da4be218876cbbb32Eric Laurent private IBinder mCb; // To be notified of client's death 111545c90cefd13a03b852bb4b8da4be218876cbbb32Eric Laurent 111645c90cefd13a03b852bb4b8da4be218876cbbb32Eric Laurent ForceControlStreamClient(IBinder cb) { 111745c90cefd13a03b852bb4b8da4be218876cbbb32Eric Laurent if (cb != null) { 111845c90cefd13a03b852bb4b8da4be218876cbbb32Eric Laurent try { 111945c90cefd13a03b852bb4b8da4be218876cbbb32Eric Laurent cb.linkToDeath(this, 0); 112045c90cefd13a03b852bb4b8da4be218876cbbb32Eric Laurent } catch (RemoteException e) { 112145c90cefd13a03b852bb4b8da4be218876cbbb32Eric Laurent // Client has died! 112245c90cefd13a03b852bb4b8da4be218876cbbb32Eric Laurent Log.w(TAG, "ForceControlStreamClient() could not link to "+cb+" binder death"); 112345c90cefd13a03b852bb4b8da4be218876cbbb32Eric Laurent cb = null; 112445c90cefd13a03b852bb4b8da4be218876cbbb32Eric Laurent } 112545c90cefd13a03b852bb4b8da4be218876cbbb32Eric Laurent } 112645c90cefd13a03b852bb4b8da4be218876cbbb32Eric Laurent mCb = cb; 112745c90cefd13a03b852bb4b8da4be218876cbbb32Eric Laurent } 112845c90cefd13a03b852bb4b8da4be218876cbbb32Eric Laurent 112945c90cefd13a03b852bb4b8da4be218876cbbb32Eric Laurent public void binderDied() { 113045c90cefd13a03b852bb4b8da4be218876cbbb32Eric Laurent synchronized(mForceControlStreamLock) { 113145c90cefd13a03b852bb4b8da4be218876cbbb32Eric Laurent Log.w(TAG, "SCO client died"); 113245c90cefd13a03b852bb4b8da4be218876cbbb32Eric Laurent if (mForceControlStreamClient != this) { 113345c90cefd13a03b852bb4b8da4be218876cbbb32Eric Laurent Log.w(TAG, "unregistered control stream client died"); 113445c90cefd13a03b852bb4b8da4be218876cbbb32Eric Laurent } else { 113545c90cefd13a03b852bb4b8da4be218876cbbb32Eric Laurent mForceControlStreamClient = null; 113645c90cefd13a03b852bb4b8da4be218876cbbb32Eric Laurent mVolumeControlStream = -1; 113745c90cefd13a03b852bb4b8da4be218876cbbb32Eric Laurent } 113845c90cefd13a03b852bb4b8da4be218876cbbb32Eric Laurent } 113945c90cefd13a03b852bb4b8da4be218876cbbb32Eric Laurent } 114045c90cefd13a03b852bb4b8da4be218876cbbb32Eric Laurent 114145c90cefd13a03b852bb4b8da4be218876cbbb32Eric Laurent public void release() { 114245c90cefd13a03b852bb4b8da4be218876cbbb32Eric Laurent if (mCb != null) { 114345c90cefd13a03b852bb4b8da4be218876cbbb32Eric Laurent mCb.unlinkToDeath(this, 0); 114445c90cefd13a03b852bb4b8da4be218876cbbb32Eric Laurent mCb = null; 114545c90cefd13a03b852bb4b8da4be218876cbbb32Eric Laurent } 114645c90cefd13a03b852bb4b8da4be218876cbbb32Eric Laurent } 114745c90cefd13a03b852bb4b8da4be218876cbbb32Eric Laurent } 114845c90cefd13a03b852bb4b8da4be218876cbbb32Eric Laurent 11496c798970ccb8759d1e613b57111daa8da0ab44c7Lei Zhang private int findVolumeDelta(int direction, int volume) { 11506c798970ccb8759d1e613b57111daa8da0ab44c7Lei Zhang int delta = 0; 11516c798970ccb8759d1e613b57111daa8da0ab44c7Lei Zhang if (direction == AudioManager.ADJUST_RAISE) { 11526c798970ccb8759d1e613b57111daa8da0ab44c7Lei Zhang if (volume == MAX_MASTER_VOLUME) { 11536c798970ccb8759d1e613b57111daa8da0ab44c7Lei Zhang return 0; 11546c798970ccb8759d1e613b57111daa8da0ab44c7Lei Zhang } 11556c798970ccb8759d1e613b57111daa8da0ab44c7Lei Zhang // This is the default value if we make it to the end 11566c798970ccb8759d1e613b57111daa8da0ab44c7Lei Zhang delta = mMasterVolumeRamp[1]; 11576c798970ccb8759d1e613b57111daa8da0ab44c7Lei Zhang // If we're raising the volume move down the ramp array until we 11586c798970ccb8759d1e613b57111daa8da0ab44c7Lei Zhang // find the volume we're above and use that groups delta. 11596c798970ccb8759d1e613b57111daa8da0ab44c7Lei Zhang for (int i = mMasterVolumeRamp.length - 1; i > 1; i -= 2) { 11606c798970ccb8759d1e613b57111daa8da0ab44c7Lei Zhang if (volume >= mMasterVolumeRamp[i - 1]) { 11616c798970ccb8759d1e613b57111daa8da0ab44c7Lei Zhang delta = mMasterVolumeRamp[i]; 11626c798970ccb8759d1e613b57111daa8da0ab44c7Lei Zhang break; 11636c798970ccb8759d1e613b57111daa8da0ab44c7Lei Zhang } 11646c798970ccb8759d1e613b57111daa8da0ab44c7Lei Zhang } 11656c798970ccb8759d1e613b57111daa8da0ab44c7Lei Zhang } else if (direction == AudioManager.ADJUST_LOWER){ 11666c798970ccb8759d1e613b57111daa8da0ab44c7Lei Zhang if (volume == 0) { 11676c798970ccb8759d1e613b57111daa8da0ab44c7Lei Zhang return 0; 11686c798970ccb8759d1e613b57111daa8da0ab44c7Lei Zhang } 11696c798970ccb8759d1e613b57111daa8da0ab44c7Lei Zhang int length = mMasterVolumeRamp.length; 11706c798970ccb8759d1e613b57111daa8da0ab44c7Lei Zhang // This is the default value if we make it to the end 11716c798970ccb8759d1e613b57111daa8da0ab44c7Lei Zhang delta = -mMasterVolumeRamp[length - 1]; 11726c798970ccb8759d1e613b57111daa8da0ab44c7Lei Zhang // If we're lowering the volume move up the ramp array until we 11736c798970ccb8759d1e613b57111daa8da0ab44c7Lei Zhang // find the volume we're below and use the group below it's delta 11746c798970ccb8759d1e613b57111daa8da0ab44c7Lei Zhang for (int i = 2; i < length; i += 2) { 11756c798970ccb8759d1e613b57111daa8da0ab44c7Lei Zhang if (volume <= mMasterVolumeRamp[i]) { 11766c798970ccb8759d1e613b57111daa8da0ab44c7Lei Zhang delta = -mMasterVolumeRamp[i - 1]; 11776c798970ccb8759d1e613b57111daa8da0ab44c7Lei Zhang break; 11786c798970ccb8759d1e613b57111daa8da0ab44c7Lei Zhang } 11796c798970ccb8759d1e613b57111daa8da0ab44c7Lei Zhang } 11806c798970ccb8759d1e613b57111daa8da0ab44c7Lei Zhang } 11816c798970ccb8759d1e613b57111daa8da0ab44c7Lei Zhang return delta; 11826c798970ccb8759d1e613b57111daa8da0ab44c7Lei Zhang } 11836c798970ccb8759d1e613b57111daa8da0ab44c7Lei Zhang 11845ac72a29593ab9a20337a2225df52bdf4754be02Dianne Hackborn private void sendBroadcastToAll(Intent intent) { 11855ac72a29593ab9a20337a2225df52bdf4754be02Dianne Hackborn final long ident = Binder.clearCallingIdentity(); 11865ac72a29593ab9a20337a2225df52bdf4754be02Dianne Hackborn try { 11875ac72a29593ab9a20337a2225df52bdf4754be02Dianne Hackborn mContext.sendBroadcastAsUser(intent, UserHandle.ALL); 11885ac72a29593ab9a20337a2225df52bdf4754be02Dianne Hackborn } finally { 11895ac72a29593ab9a20337a2225df52bdf4754be02Dianne Hackborn Binder.restoreCallingIdentity(ident); 11905ac72a29593ab9a20337a2225df52bdf4754be02Dianne Hackborn } 11915ac72a29593ab9a20337a2225df52bdf4754be02Dianne Hackborn } 11925ac72a29593ab9a20337a2225df52bdf4754be02Dianne Hackborn 11935ac72a29593ab9a20337a2225df52bdf4754be02Dianne Hackborn private void sendStickyBroadcastToAll(Intent intent) { 11945ac72a29593ab9a20337a2225df52bdf4754be02Dianne Hackborn final long ident = Binder.clearCallingIdentity(); 11955ac72a29593ab9a20337a2225df52bdf4754be02Dianne Hackborn try { 11965ac72a29593ab9a20337a2225df52bdf4754be02Dianne Hackborn mContext.sendStickyBroadcastAsUser(intent, UserHandle.ALL); 11975ac72a29593ab9a20337a2225df52bdf4754be02Dianne Hackborn } finally { 11985ac72a29593ab9a20337a2225df52bdf4754be02Dianne Hackborn Binder.restoreCallingIdentity(ident); 11995ac72a29593ab9a20337a2225df52bdf4754be02Dianne Hackborn } 12005ac72a29593ab9a20337a2225df52bdf4754be02Dianne Hackborn } 12015ac72a29593ab9a20337a2225df52bdf4754be02Dianne Hackborn 120225101b0b9a84571ead15b26e9f4cd9c4298d7823Eric Laurent // UI update and Broadcast Intent 120325101b0b9a84571ead15b26e9f4cd9c4298d7823Eric Laurent private void sendVolumeUpdate(int streamType, int oldIndex, int index, int flags) { 120425101b0b9a84571ead15b26e9f4cd9c4298d7823Eric Laurent if (!mVoiceCapable && (streamType == AudioSystem.STREAM_RING)) { 120525101b0b9a84571ead15b26e9f4cd9c4298d7823Eric Laurent streamType = AudioSystem.STREAM_NOTIFICATION; 120625101b0b9a84571ead15b26e9f4cd9c4298d7823Eric Laurent } 120725101b0b9a84571ead15b26e9f4cd9c4298d7823Eric Laurent 12083346a802087f621c6441bc512dfcc17b07143fc6John Spurlock mVolumeController.postVolumeChanged(streamType, flags); 120925101b0b9a84571ead15b26e9f4cd9c4298d7823Eric Laurent 12104bbcc6549738f3d69831b2bd9eb4accec3e9920eEric Laurent if ((flags & AudioManager.FLAG_FIXED_VOLUME) == 0) { 12114bbcc6549738f3d69831b2bd9eb4accec3e9920eEric Laurent oldIndex = (oldIndex + 5) / 10; 12124bbcc6549738f3d69831b2bd9eb4accec3e9920eEric Laurent index = (index + 5) / 10; 12134bbcc6549738f3d69831b2bd9eb4accec3e9920eEric Laurent Intent intent = new Intent(AudioManager.VOLUME_CHANGED_ACTION); 12144bbcc6549738f3d69831b2bd9eb4accec3e9920eEric Laurent intent.putExtra(AudioManager.EXTRA_VOLUME_STREAM_TYPE, streamType); 12154bbcc6549738f3d69831b2bd9eb4accec3e9920eEric Laurent intent.putExtra(AudioManager.EXTRA_VOLUME_STREAM_VALUE, index); 12164bbcc6549738f3d69831b2bd9eb4accec3e9920eEric Laurent intent.putExtra(AudioManager.EXTRA_PREV_VOLUME_STREAM_VALUE, oldIndex); 12174bbcc6549738f3d69831b2bd9eb4accec3e9920eEric Laurent sendBroadcastToAll(intent); 12184bbcc6549738f3d69831b2bd9eb4accec3e9920eEric Laurent } 12199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 12209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 12210dc37cce9d564ae43883c8dc8672b9266b881e63Mike Lockwood // UI update and Broadcast Intent 12220dc37cce9d564ae43883c8dc8672b9266b881e63Mike Lockwood private void sendMasterVolumeUpdate(int flags, int oldVolume, int newVolume) { 12233346a802087f621c6441bc512dfcc17b07143fc6John Spurlock mVolumeController.postMasterVolumeChanged(flags); 12240dc37cce9d564ae43883c8dc8672b9266b881e63Mike Lockwood 12250dc37cce9d564ae43883c8dc8672b9266b881e63Mike Lockwood Intent intent = new Intent(AudioManager.MASTER_VOLUME_CHANGED_ACTION); 12260dc37cce9d564ae43883c8dc8672b9266b881e63Mike Lockwood intent.putExtra(AudioManager.EXTRA_PREV_MASTER_VOLUME_VALUE, oldVolume); 12270dc37cce9d564ae43883c8dc8672b9266b881e63Mike Lockwood intent.putExtra(AudioManager.EXTRA_MASTER_VOLUME_VALUE, newVolume); 12285ac72a29593ab9a20337a2225df52bdf4754be02Dianne Hackborn sendBroadcastToAll(intent); 12290dc37cce9d564ae43883c8dc8672b9266b881e63Mike Lockwood } 12300dc37cce9d564ae43883c8dc8672b9266b881e63Mike Lockwood 12310dc37cce9d564ae43883c8dc8672b9266b881e63Mike Lockwood // UI update and Broadcast Intent 12320dc37cce9d564ae43883c8dc8672b9266b881e63Mike Lockwood private void sendMasterMuteUpdate(boolean muted, int flags) { 12333346a802087f621c6441bc512dfcc17b07143fc6John Spurlock mVolumeController.postMasterMuteChanged(flags); 123457978ed86286a33d5b1a0fd000ca3406ba9d87b3Justin Koh broadcastMasterMuteStatus(muted); 123557978ed86286a33d5b1a0fd000ca3406ba9d87b3Justin Koh } 12360dc37cce9d564ae43883c8dc8672b9266b881e63Mike Lockwood 123757978ed86286a33d5b1a0fd000ca3406ba9d87b3Justin Koh private void broadcastMasterMuteStatus(boolean muted) { 12380dc37cce9d564ae43883c8dc8672b9266b881e63Mike Lockwood Intent intent = new Intent(AudioManager.MASTER_MUTE_CHANGED_ACTION); 12390dc37cce9d564ae43883c8dc8672b9266b881e63Mike Lockwood intent.putExtra(AudioManager.EXTRA_MASTER_VOLUME_MUTED, muted); 124057978ed86286a33d5b1a0fd000ca3406ba9d87b3Justin Koh intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT 124157978ed86286a33d5b1a0fd000ca3406ba9d87b3Justin Koh | Intent.FLAG_RECEIVER_REPLACE_PENDING); 12425ac72a29593ab9a20337a2225df52bdf4754be02Dianne Hackborn sendStickyBroadcastToAll(intent); 12430dc37cce9d564ae43883c8dc8672b9266b881e63Mike Lockwood } 12440dc37cce9d564ae43883c8dc8672b9266b881e63Mike Lockwood 12459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 12469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Sets the stream state's index, and posts a message to set system volume. 12479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * This will not call out to the UI. Assumes a valid stream type. 12489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 12499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param streamType Type of the stream 12509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param index Desired volume index of the stream 12519bc8358ddaa01c3490f9709991989633a6a3dd42Eric Laurent * @param device the device whose volume must be changed 12529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param force If true, set the volume even if the desired volume is same 12539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * as the current volume. 12549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 12559bc8358ddaa01c3490f9709991989633a6a3dd42Eric Laurent private void setStreamVolumeInt(int streamType, 12569bc8358ddaa01c3490f9709991989633a6a3dd42Eric Laurent int index, 12579bc8358ddaa01c3490f9709991989633a6a3dd42Eric Laurent int device, 125842b041ed4f184e3af7f788eb07307f556a2a6616Eric Laurent boolean force) { 12599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project VolumeStreamState streamState = mStreamStates[streamType]; 12605b4e654d0c7de8e4d58d73e73b0d5220f19b68f7Eric Laurent 126142b041ed4f184e3af7f788eb07307f556a2a6616Eric Laurent if (streamState.setIndex(index, device) || force) { 126242b041ed4f184e3af7f788eb07307f556a2a6616Eric Laurent // Post message to set system volume (it in turn will post a message 126342b041ed4f184e3af7f788eb07307f556a2a6616Eric Laurent // to persist). 126442b041ed4f184e3af7f788eb07307f556a2a6616Eric Laurent sendMsg(mAudioHandler, 126542b041ed4f184e3af7f788eb07307f556a2a6616Eric Laurent MSG_SET_DEVICE_VOLUME, 126642b041ed4f184e3af7f788eb07307f556a2a6616Eric Laurent SENDMSG_QUEUE, 126742b041ed4f184e3af7f788eb07307f556a2a6616Eric Laurent device, 126842b041ed4f184e3af7f788eb07307f556a2a6616Eric Laurent 0, 126942b041ed4f184e3af7f788eb07307f556a2a6616Eric Laurent streamState, 127042b041ed4f184e3af7f788eb07307f556a2a6616Eric Laurent 0); 12719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 12729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 12739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 12749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** @see AudioManager#setStreamSolo(int, boolean) */ 12759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public void setStreamSolo(int streamType, boolean state, IBinder cb) { 127683a017b6b7c099d1a0293e5839be6477325aef06Eric Laurent if (mUseFixedVolume) { 127783a017b6b7c099d1a0293e5839be6477325aef06Eric Laurent return; 127883a017b6b7c099d1a0293e5839be6477325aef06Eric Laurent } 127983a017b6b7c099d1a0293e5839be6477325aef06Eric Laurent 12809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project for (int stream = 0; stream < mStreamStates.length; stream++) { 12819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (!isStreamAffectedByMute(stream) || stream == streamType) continue; 12829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mStreamStates[stream].mute(cb, state); 12839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 12849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 12859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 12869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** @see AudioManager#setStreamMute(int, boolean) */ 12879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public void setStreamMute(int streamType, boolean state, IBinder cb) { 128883a017b6b7c099d1a0293e5839be6477325aef06Eric Laurent if (mUseFixedVolume) { 128983a017b6b7c099d1a0293e5839be6477325aef06Eric Laurent return; 129083a017b6b7c099d1a0293e5839be6477325aef06Eric Laurent } 129183a017b6b7c099d1a0293e5839be6477325aef06Eric Laurent 12929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (isStreamAffectedByMute(streamType)) { 12939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mStreamStates[streamType].mute(cb, state); 12949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 12959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 12969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 129725101b0b9a84571ead15b26e9f4cd9c4298d7823Eric Laurent /** get stream mute state. */ 129825101b0b9a84571ead15b26e9f4cd9c4298d7823Eric Laurent public boolean isStreamMute(int streamType) { 129942b041ed4f184e3af7f788eb07307f556a2a6616Eric Laurent return mStreamStates[streamType].isMuted(); 130025101b0b9a84571ead15b26e9f4cd9c4298d7823Eric Laurent } 130125101b0b9a84571ead15b26e9f4cd9c4298d7823Eric Laurent 1302961cae92540763226648813d111c5b5c3b0f1597Dianne Hackborn /** @see AudioManager#setMasterMute(boolean, int) */ 13034a21b25fad62e4f19d13ba814263841c931f56efJulia Reynolds public void setMasterMute(boolean state, int flags, String callingPackage, IBinder cb) { 130483a017b6b7c099d1a0293e5839be6477325aef06Eric Laurent if (mUseFixedVolume) { 130583a017b6b7c099d1a0293e5839be6477325aef06Eric Laurent return; 130683a017b6b7c099d1a0293e5839be6477325aef06Eric Laurent } 130783a017b6b7c099d1a0293e5839be6477325aef06Eric Laurent 13084a21b25fad62e4f19d13ba814263841c931f56efJulia Reynolds if (mAppOps.noteOp(AppOpsManager.OP_AUDIO_MASTER_VOLUME, Binder.getCallingUid(), 13094a21b25fad62e4f19d13ba814263841c931f56efJulia Reynolds callingPackage) != AppOpsManager.MODE_ALLOWED) { 13104a21b25fad62e4f19d13ba814263841c931f56efJulia Reynolds return; 13114a21b25fad62e4f19d13ba814263841c931f56efJulia Reynolds } 13124a21b25fad62e4f19d13ba814263841c931f56efJulia Reynolds 13131ce5b26d707e0086e09af3cd0428f1b441145261Jason Simmons if (state != AudioSystem.getMasterMute()) { 13141ce5b26d707e0086e09af3cd0428f1b441145261Jason Simmons AudioSystem.setMasterMute(state); 131557978ed86286a33d5b1a0fd000ca3406ba9d87b3Justin Koh // Post a persist master volume msg 131675cf9e19a575c28c200c02c0ab6f83bb79f5c50dJustin Koh sendMsg(mAudioHandler, MSG_PERSIST_MASTER_VOLUME_MUTE, SENDMSG_REPLACE, state ? 1 131757978ed86286a33d5b1a0fd000ca3406ba9d87b3Justin Koh : 0, 0, null, PERSIST_DELAY); 13180273af55cf68d54d26d154b44d105d40fed79701Justin Koh sendMasterMuteUpdate(state, flags); 13191ce5b26d707e0086e09af3cd0428f1b441145261Jason Simmons } 1320ce952c8e13c535bedde77bcdb94dfcc7508475aaMike Lockwood } 1321ce952c8e13c535bedde77bcdb94dfcc7508475aaMike Lockwood 1322ce952c8e13c535bedde77bcdb94dfcc7508475aaMike Lockwood /** get master mute state. */ 1323ce952c8e13c535bedde77bcdb94dfcc7508475aaMike Lockwood public boolean isMasterMute() { 13243194ea94348bce8e7ee9f803698d877f46f8279aMike Lockwood return AudioSystem.getMasterMute(); 1325ce952c8e13c535bedde77bcdb94dfcc7508475aaMike Lockwood } 1326ce952c8e13c535bedde77bcdb94dfcc7508475aaMike Lockwood 1327fa9a69805b001034aa04c3b33989a7ac21522371Jean-Michel Trivi protected static int getMaxStreamVolume(int streamType) { 1328fa9a69805b001034aa04c3b33989a7ac21522371Jean-Michel Trivi return MAX_STREAM_VOLUME[streamType]; 1329fa9a69805b001034aa04c3b33989a7ac21522371Jean-Michel Trivi } 1330fa9a69805b001034aa04c3b33989a7ac21522371Jean-Michel Trivi 13319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** @see AudioManager#getStreamVolume(int) */ 13329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public int getStreamVolume(int streamType) { 13339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project ensureValidStreamType(streamType); 13349bc8358ddaa01c3490f9709991989633a6a3dd42Eric Laurent int device = getDeviceForStream(streamType); 133542b041ed4f184e3af7f788eb07307f556a2a6616Eric Laurent int index = mStreamStates[streamType].getIndex(device); 13364bbcc6549738f3d69831b2bd9eb4accec3e9920eEric Laurent 133742b041ed4f184e3af7f788eb07307f556a2a6616Eric Laurent // by convention getStreamVolume() returns 0 when a stream is muted. 133842b041ed4f184e3af7f788eb07307f556a2a6616Eric Laurent if (mStreamStates[streamType].isMuted()) { 133942b041ed4f184e3af7f788eb07307f556a2a6616Eric Laurent index = 0; 134042b041ed4f184e3af7f788eb07307f556a2a6616Eric Laurent } 13413ef7549876a159dae1568429edcb57e4e7d08459Eric Laurent if (index != 0 && (mStreamVolumeAlias[streamType] == AudioSystem.STREAM_MUSIC) && 13424bbcc6549738f3d69831b2bd9eb4accec3e9920eEric Laurent (device & mFixedVolumeDevices) != 0) { 13434bbcc6549738f3d69831b2bd9eb4accec3e9920eEric Laurent index = mStreamStates[streamType].getMaxIndex(); 13444bbcc6549738f3d69831b2bd9eb4accec3e9920eEric Laurent } 13454bbcc6549738f3d69831b2bd9eb4accec3e9920eEric Laurent return (index + 5) / 10; 13469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 13479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 13484767690f09ea3447b8c5c32fb28d27650aa18e00Mike Lockwood public int getMasterVolume() { 1349ce952c8e13c535bedde77bcdb94dfcc7508475aaMike Lockwood if (isMasterMute()) return 0; 1350ce952c8e13c535bedde77bcdb94dfcc7508475aaMike Lockwood return getLastAudibleMasterVolume(); 13518dc1dabd254249b7ddb8743e88fdb96580ffc585Mike Lockwood } 13528dc1dabd254249b7ddb8743e88fdb96580ffc585Mike Lockwood 1353ba50b97cff80e73620a0e3d13cae169e095974a7Dianne Hackborn public void setMasterVolume(int volume, int flags, String callingPackage) { 135483a017b6b7c099d1a0293e5839be6477325aef06Eric Laurent if (mUseFixedVolume) { 135583a017b6b7c099d1a0293e5839be6477325aef06Eric Laurent return; 135683a017b6b7c099d1a0293e5839be6477325aef06Eric Laurent } 135783a017b6b7c099d1a0293e5839be6477325aef06Eric Laurent 1358ba50b97cff80e73620a0e3d13cae169e095974a7Dianne Hackborn if (mAppOps.noteOp(AppOpsManager.OP_AUDIO_MASTER_VOLUME, Binder.getCallingUid(), 1359ba50b97cff80e73620a0e3d13cae169e095974a7Dianne Hackborn callingPackage) != AppOpsManager.MODE_ALLOWED) { 1360ba50b97cff80e73620a0e3d13cae169e095974a7Dianne Hackborn return; 1361ba50b97cff80e73620a0e3d13cae169e095974a7Dianne Hackborn } 1362ba50b97cff80e73620a0e3d13cae169e095974a7Dianne Hackborn 13639760647dd0ee67e7c20f3e9d661d2006b1df0b54Mike Lockwood if (volume < 0) { 13649760647dd0ee67e7c20f3e9d661d2006b1df0b54Mike Lockwood volume = 0; 13659760647dd0ee67e7c20f3e9d661d2006b1df0b54Mike Lockwood } else if (volume > MAX_MASTER_VOLUME) { 13669760647dd0ee67e7c20f3e9d661d2006b1df0b54Mike Lockwood volume = MAX_MASTER_VOLUME; 13679760647dd0ee67e7c20f3e9d661d2006b1df0b54Mike Lockwood } 13685c55a051ad7d86a464fb91426f1ea3c0250e38b3Mike Lockwood doSetMasterVolume((float)volume / MAX_MASTER_VOLUME, flags); 13695c55a051ad7d86a464fb91426f1ea3c0250e38b3Mike Lockwood } 13705c55a051ad7d86a464fb91426f1ea3c0250e38b3Mike Lockwood 13715c55a051ad7d86a464fb91426f1ea3c0250e38b3Mike Lockwood private void doSetMasterVolume(float volume, int flags) { 13725c55a051ad7d86a464fb91426f1ea3c0250e38b3Mike Lockwood // don't allow changing master volume when muted 13735c55a051ad7d86a464fb91426f1ea3c0250e38b3Mike Lockwood if (!AudioSystem.getMasterMute()) { 13745c55a051ad7d86a464fb91426f1ea3c0250e38b3Mike Lockwood int oldVolume = getMasterVolume(); 13755c55a051ad7d86a464fb91426f1ea3c0250e38b3Mike Lockwood AudioSystem.setMasterVolume(volume); 13765c55a051ad7d86a464fb91426f1ea3c0250e38b3Mike Lockwood 13775c55a051ad7d86a464fb91426f1ea3c0250e38b3Mike Lockwood int newVolume = getMasterVolume(); 13785c55a051ad7d86a464fb91426f1ea3c0250e38b3Mike Lockwood if (newVolume != oldVolume) { 13795c55a051ad7d86a464fb91426f1ea3c0250e38b3Mike Lockwood // Post a persist master volume msg 13805c55a051ad7d86a464fb91426f1ea3c0250e38b3Mike Lockwood sendMsg(mAudioHandler, MSG_PERSIST_MASTER_VOLUME, SENDMSG_REPLACE, 13815c55a051ad7d86a464fb91426f1ea3c0250e38b3Mike Lockwood Math.round(volume * (float)1000.0), 0, null, PERSIST_DELAY); 13825c55a051ad7d86a464fb91426f1ea3c0250e38b3Mike Lockwood } 13833caba517253d1703fc29b50740c4567b932279fbJustin Koh // Send the volume update regardless whether there was a change. 13843caba517253d1703fc29b50740c4567b932279fbJustin Koh sendMasterVolumeUpdate(flags, oldVolume, newVolume); 13855c55a051ad7d86a464fb91426f1ea3c0250e38b3Mike Lockwood } 13868dc1dabd254249b7ddb8743e88fdb96580ffc585Mike Lockwood } 13878dc1dabd254249b7ddb8743e88fdb96580ffc585Mike Lockwood 13889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** @see AudioManager#getStreamMaxVolume(int) */ 13899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public int getStreamMaxVolume(int streamType) { 13909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project ensureValidStreamType(streamType); 1391a553c25b33c99b345cf1c8688f8df0ed8df14e5aEric Laurent return (mStreamStates[streamType].getMaxIndex() + 5) / 10; 13929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 13939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 13944767690f09ea3447b8c5c32fb28d27650aa18e00Mike Lockwood public int getMasterMaxVolume() { 13954767690f09ea3447b8c5c32fb28d27650aa18e00Mike Lockwood return MAX_MASTER_VOLUME; 13964767690f09ea3447b8c5c32fb28d27650aa18e00Mike Lockwood } 139725101b0b9a84571ead15b26e9f4cd9c4298d7823Eric Laurent 139825101b0b9a84571ead15b26e9f4cd9c4298d7823Eric Laurent /** Get last audible volume before stream was muted. */ 139925101b0b9a84571ead15b26e9f4cd9c4298d7823Eric Laurent public int getLastAudibleStreamVolume(int streamType) { 140025101b0b9a84571ead15b26e9f4cd9c4298d7823Eric Laurent ensureValidStreamType(streamType); 14019bc8358ddaa01c3490f9709991989633a6a3dd42Eric Laurent int device = getDeviceForStream(streamType); 140242b041ed4f184e3af7f788eb07307f556a2a6616Eric Laurent return (mStreamStates[streamType].getIndex(device) + 5) / 10; 140325101b0b9a84571ead15b26e9f4cd9c4298d7823Eric Laurent } 140425101b0b9a84571ead15b26e9f4cd9c4298d7823Eric Laurent 1405ce952c8e13c535bedde77bcdb94dfcc7508475aaMike Lockwood /** Get last audible master volume before it was muted. */ 1406ce952c8e13c535bedde77bcdb94dfcc7508475aaMike Lockwood public int getLastAudibleMasterVolume() { 1407ce952c8e13c535bedde77bcdb94dfcc7508475aaMike Lockwood return Math.round(AudioSystem.getMasterVolume() * MAX_MASTER_VOLUME); 1408ce952c8e13c535bedde77bcdb94dfcc7508475aaMike Lockwood } 1409ce952c8e13c535bedde77bcdb94dfcc7508475aaMike Lockwood 1410961cae92540763226648813d111c5b5c3b0f1597Dianne Hackborn /** @see AudioManager#getMasterStreamType() */ 14116d5176638c2189595cede38fb92c3e7e8700e221Eric Laurent public int getMasterStreamType() { 14126d5176638c2189595cede38fb92c3e7e8700e221Eric Laurent if (mVoiceCapable) { 14136d5176638c2189595cede38fb92c3e7e8700e221Eric Laurent return AudioSystem.STREAM_RING; 14146d5176638c2189595cede38fb92c3e7e8700e221Eric Laurent } else { 14156d5176638c2189595cede38fb92c3e7e8700e221Eric Laurent return AudioSystem.STREAM_MUSIC; 14166d5176638c2189595cede38fb92c3e7e8700e221Eric Laurent } 14176d5176638c2189595cede38fb92c3e7e8700e221Eric Laurent } 14186d5176638c2189595cede38fb92c3e7e8700e221Eric Laurent 141922c921a910d236abf3a1705a02541a49fdaf3a14Emily Bernier /** @see AudioManager#setMicrophoneMute(boolean) */ 142022c921a910d236abf3a1705a02541a49fdaf3a14Emily Bernier public void setMicrophoneMute(boolean on, String callingPackage) { 142122c921a910d236abf3a1705a02541a49fdaf3a14Emily Bernier if (mAppOps.noteOp(AppOpsManager.OP_MUTE_MICROPHONE, Binder.getCallingUid(), 142222c921a910d236abf3a1705a02541a49fdaf3a14Emily Bernier callingPackage) != AppOpsManager.MODE_ALLOWED) { 142322c921a910d236abf3a1705a02541a49fdaf3a14Emily Bernier return; 142422c921a910d236abf3a1705a02541a49fdaf3a14Emily Bernier } 142522c921a910d236abf3a1705a02541a49fdaf3a14Emily Bernier 142622c921a910d236abf3a1705a02541a49fdaf3a14Emily Bernier AudioSystem.muteMicrophone(on); 142722c921a910d236abf3a1705a02541a49fdaf3a14Emily Bernier } 142822c921a910d236abf3a1705a02541a49fdaf3a14Emily Bernier 14299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** @see AudioManager#getRingerMode() */ 14309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public int getRingerMode() { 1431ba195ebc76f23b6679443724ab58c9dc9f2df884Glenn Kasten synchronized(mSettingsLock) { 1432ba195ebc76f23b6679443724ab58c9dc9f2df884Glenn Kasten return mRingerMode; 1433ba195ebc76f23b6679443724ab58c9dc9f2df884Glenn Kasten } 1434ba195ebc76f23b6679443724ab58c9dc9f2df884Glenn Kasten } 1435ba195ebc76f23b6679443724ab58c9dc9f2df884Glenn Kasten 1436ba195ebc76f23b6679443724ab58c9dc9f2df884Glenn Kasten private void ensureValidRingerMode(int ringerMode) { 1437ba195ebc76f23b6679443724ab58c9dc9f2df884Glenn Kasten if (!AudioManager.isValidRingerMode(ringerMode)) { 1438ba195ebc76f23b6679443724ab58c9dc9f2df884Glenn Kasten throw new IllegalArgumentException("Bad ringer mode " + ringerMode); 1439ba195ebc76f23b6679443724ab58c9dc9f2df884Glenn Kasten } 14409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 14419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 14429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** @see AudioManager#setRingerMode(int) */ 14439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public void setRingerMode(int ringerMode) { 144483a017b6b7c099d1a0293e5839be6477325aef06Eric Laurent if (mUseFixedVolume) { 144583a017b6b7c099d1a0293e5839be6477325aef06Eric Laurent return; 144683a017b6b7c099d1a0293e5839be6477325aef06Eric Laurent } 144783a017b6b7c099d1a0293e5839be6477325aef06Eric Laurent 1448244820185269991186d07068b92985624cede4a5Eric Laurent if ((ringerMode == AudioManager.RINGER_MODE_VIBRATE) && !mHasVibrator) { 1449244820185269991186d07068b92985624cede4a5Eric Laurent ringerMode = AudioManager.RINGER_MODE_SILENT; 1450244820185269991186d07068b92985624cede4a5Eric Laurent } 1451ba195ebc76f23b6679443724ab58c9dc9f2df884Glenn Kasten if (ringerMode != getRingerMode()) { 1452ba195ebc76f23b6679443724ab58c9dc9f2df884Glenn Kasten setRingerModeInt(ringerMode, true); 1453ba195ebc76f23b6679443724ab58c9dc9f2df884Glenn Kasten // Send sticky broadcast 1454ba195ebc76f23b6679443724ab58c9dc9f2df884Glenn Kasten broadcastRingerMode(ringerMode); 1455b109615ebebd6f3b9ae789412279f576c3ace46bJason Parekh } 1456b109615ebebd6f3b9ae789412279f576c3ace46bJason Parekh } 14579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 14584050c93601b3c3609b21cc1e18a29b64747e7fa9Eric Laurent private void setRingerModeInt(int ringerMode, boolean persist) { 1459ba195ebc76f23b6679443724ab58c9dc9f2df884Glenn Kasten synchronized(mSettingsLock) { 1460ba195ebc76f23b6679443724ab58c9dc9f2df884Glenn Kasten mRingerMode = ringerMode; 1461ba195ebc76f23b6679443724ab58c9dc9f2df884Glenn Kasten } 1462b109615ebebd6f3b9ae789412279f576c3ace46bJason Parekh 14635b4e654d0c7de8e4d58d73e73b0d5220f19b68f7Eric Laurent // Mute stream if not previously muted by ringer mode and ringer mode 14645b4e654d0c7de8e4d58d73e73b0d5220f19b68f7Eric Laurent // is not RINGER_MODE_NORMAL and stream is affected by ringer mode. 14655b4e654d0c7de8e4d58d73e73b0d5220f19b68f7Eric Laurent // Unmute stream if previously muted by ringer mode and ringer mode 14665b4e654d0c7de8e4d58d73e73b0d5220f19b68f7Eric Laurent // is RINGER_MODE_NORMAL or stream is not affected by ringer mode. 1467b109615ebebd6f3b9ae789412279f576c3ace46bJason Parekh int numStreamTypes = AudioSystem.getNumStreamTypes(); 14685b4e654d0c7de8e4d58d73e73b0d5220f19b68f7Eric Laurent for (int streamType = numStreamTypes - 1; streamType >= 0; streamType--) { 14695b4e654d0c7de8e4d58d73e73b0d5220f19b68f7Eric Laurent if (isStreamMutedByRingerMode(streamType)) { 14705b4e654d0c7de8e4d58d73e73b0d5220f19b68f7Eric Laurent if (!isStreamAffectedByRingerMode(streamType) || 1471ba195ebc76f23b6679443724ab58c9dc9f2df884Glenn Kasten ringerMode == AudioManager.RINGER_MODE_NORMAL) { 1472b024c30a80684ac08daef3137b7ba0d347fe3ce5Eric Laurent // ring and notifications volume should never be 0 when not silenced 1473b024c30a80684ac08daef3137b7ba0d347fe3ce5Eric Laurent // on voice capable devices 1474b024c30a80684ac08daef3137b7ba0d347fe3ce5Eric Laurent if (mVoiceCapable && 14756d5176638c2189595cede38fb92c3e7e8700e221Eric Laurent mStreamVolumeAlias[streamType] == AudioSystem.STREAM_RING) { 14763172d5e3e7520a745fa37b71fc1c7bf244b57085Eric Laurent synchronized (mStreamStates[streamType]) { 147742b041ed4f184e3af7f788eb07307f556a2a6616Eric Laurent Set set = mStreamStates[streamType].mIndex.entrySet(); 14783172d5e3e7520a745fa37b71fc1c7bf244b57085Eric Laurent Iterator i = set.iterator(); 14793172d5e3e7520a745fa37b71fc1c7bf244b57085Eric Laurent while (i.hasNext()) { 14803172d5e3e7520a745fa37b71fc1c7bf244b57085Eric Laurent Map.Entry entry = (Map.Entry)i.next(); 14813172d5e3e7520a745fa37b71fc1c7bf244b57085Eric Laurent if ((Integer)entry.getValue() == 0) { 14823172d5e3e7520a745fa37b71fc1c7bf244b57085Eric Laurent entry.setValue(10); 14833172d5e3e7520a745fa37b71fc1c7bf244b57085Eric Laurent } 14849bc8358ddaa01c3490f9709991989633a6a3dd42Eric Laurent } 14859bc8358ddaa01c3490f9709991989633a6a3dd42Eric Laurent } 1486b024c30a80684ac08daef3137b7ba0d347fe3ce5Eric Laurent } 14875b4e654d0c7de8e4d58d73e73b0d5220f19b68f7Eric Laurent mStreamStates[streamType].mute(null, false); 14885b4e654d0c7de8e4d58d73e73b0d5220f19b68f7Eric Laurent mRingerModeMutedStreams &= ~(1 << streamType); 14899bcf401d13d47416043a704430388abd59aef7cdEric Laurent } 14905b4e654d0c7de8e4d58d73e73b0d5220f19b68f7Eric Laurent } else { 14915b4e654d0c7de8e4d58d73e73b0d5220f19b68f7Eric Laurent if (isStreamAffectedByRingerMode(streamType) && 1492ba195ebc76f23b6679443724ab58c9dc9f2df884Glenn Kasten ringerMode != AudioManager.RINGER_MODE_NORMAL) { 14935b4e654d0c7de8e4d58d73e73b0d5220f19b68f7Eric Laurent mStreamStates[streamType].mute(null, true); 14945b4e654d0c7de8e4d58d73e73b0d5220f19b68f7Eric Laurent mRingerModeMutedStreams |= (1 << streamType); 14955b4e654d0c7de8e4d58d73e73b0d5220f19b68f7Eric Laurent } 1496b109615ebebd6f3b9ae789412279f576c3ace46bJason Parekh } 14979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1498a553c25b33c99b345cf1c8688f8df0ed8df14e5aEric Laurent 1499b109615ebebd6f3b9ae789412279f576c3ace46bJason Parekh // Post a persist ringer mode msg 15004050c93601b3c3609b21cc1e18a29b64747e7fa9Eric Laurent if (persist) { 1501afbb047c3945e9c2b7e9bc6b25098d5fb80bba4eEric Laurent sendMsg(mAudioHandler, MSG_PERSIST_RINGER_MODE, 15024050c93601b3c3609b21cc1e18a29b64747e7fa9Eric Laurent SENDMSG_REPLACE, 0, 0, null, PERSIST_DELAY); 15034050c93601b3c3609b21cc1e18a29b64747e7fa9Eric Laurent } 15049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 15059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 15069063154a793b0ab38b3c5992cbaed046427b4a82Mike Lockwood private void restoreMasterVolume() { 150783a017b6b7c099d1a0293e5839be6477325aef06Eric Laurent if (mUseFixedVolume) { 150883a017b6b7c099d1a0293e5839be6477325aef06Eric Laurent AudioSystem.setMasterVolume(1.0f); 150983a017b6b7c099d1a0293e5839be6477325aef06Eric Laurent return; 151083a017b6b7c099d1a0293e5839be6477325aef06Eric Laurent } 15119063154a793b0ab38b3c5992cbaed046427b4a82Mike Lockwood if (mUseMasterVolume) { 1512bc0fab1fc2db832ef86d8a33466ec4d68b103ca0Eric Laurent float volume = Settings.System.getFloatForUser(mContentResolver, 1513bc0fab1fc2db832ef86d8a33466ec4d68b103ca0Eric Laurent Settings.System.VOLUME_MASTER, -1.0f, UserHandle.USER_CURRENT); 15149063154a793b0ab38b3c5992cbaed046427b4a82Mike Lockwood if (volume >= 0.0f) { 15159063154a793b0ab38b3c5992cbaed046427b4a82Mike Lockwood AudioSystem.setMasterVolume(volume); 15169063154a793b0ab38b3c5992cbaed046427b4a82Mike Lockwood } 15179063154a793b0ab38b3c5992cbaed046427b4a82Mike Lockwood } 15189063154a793b0ab38b3c5992cbaed046427b4a82Mike Lockwood } 15199063154a793b0ab38b3c5992cbaed046427b4a82Mike Lockwood 15209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** @see AudioManager#shouldVibrate(int) */ 15219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public boolean shouldVibrate(int vibrateType) { 1522bffc3d1bd33eb2d8e00a9f8b6261d815db503311Eric Laurent if (!mHasVibrator) return false; 15239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 15249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project switch (getVibrateSetting(vibrateType)) { 15259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 15269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project case AudioManager.VIBRATE_SETTING_ON: 1527ba195ebc76f23b6679443724ab58c9dc9f2df884Glenn Kasten return getRingerMode() != AudioManager.RINGER_MODE_SILENT; 15289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 15299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project case AudioManager.VIBRATE_SETTING_ONLY_SILENT: 1530ba195ebc76f23b6679443724ab58c9dc9f2df884Glenn Kasten return getRingerMode() == AudioManager.RINGER_MODE_VIBRATE; 15319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 15329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project case AudioManager.VIBRATE_SETTING_OFF: 1533bcac496076ef6f439147e7a2be71e8a2b76ddedeDaniel Sandler // return false, even for incoming calls 1534bcac496076ef6f439147e7a2be71e8a2b76ddedeDaniel Sandler return false; 15359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 15369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project default: 15379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return false; 15389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 15399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 15409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 15419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** @see AudioManager#getVibrateSetting(int) */ 15429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public int getVibrateSetting(int vibrateType) { 1543bffc3d1bd33eb2d8e00a9f8b6261d815db503311Eric Laurent if (!mHasVibrator) return AudioManager.VIBRATE_SETTING_OFF; 15449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return (mVibrateSetting >> (vibrateType * 2)) & 3; 15459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 15469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 15479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** @see AudioManager#setVibrateSetting(int, int) */ 15489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public void setVibrateSetting(int vibrateType, int vibrateSetting) { 15499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1550bffc3d1bd33eb2d8e00a9f8b6261d815db503311Eric Laurent if (!mHasVibrator) return; 1551bffc3d1bd33eb2d8e00a9f8b6261d815db503311Eric Laurent 15529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mVibrateSetting = getValueForVibrateSetting(mVibrateSetting, vibrateType, vibrateSetting); 15539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 15549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Broadcast change 15559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project broadcastVibrateSetting(vibrateType); 15569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 15579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 15589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 15599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 15609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @see #setVibrateSetting(int, int) 15619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 15629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public static int getValueForVibrateSetting(int existingValue, int vibrateType, 15639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int vibrateSetting) { 15649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 15659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // First clear the existing setting. Each vibrate type has two bits in 15669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // the value. Note '3' is '11' in binary. 15679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project existingValue &= ~(3 << (vibrateType * 2)); 15689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 15699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Set into the old value 15709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project existingValue |= (vibrateSetting & 3) << (vibrateType * 2); 15719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 15729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return existingValue; 15739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 15749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 15759272b4b4a44fe1f33e3030810618194f817caaecEric Laurent private class SetModeDeathHandler implements IBinder.DeathRecipient { 15769272b4b4a44fe1f33e3030810618194f817caaecEric Laurent private IBinder mCb; // To be notified of client's death 1577f1ddd51f9cd2f92b922bc636c307210a8d587c25Marco Nelissen private int mPid; 15789272b4b4a44fe1f33e3030810618194f817caaecEric Laurent private int mMode = AudioSystem.MODE_NORMAL; // Current mode set by this client 15799272b4b4a44fe1f33e3030810618194f817caaecEric Laurent 15809f103de83f2d5d472960dcf1401e95b2ab57a477Eric Laurent SetModeDeathHandler(IBinder cb, int pid) { 15819272b4b4a44fe1f33e3030810618194f817caaecEric Laurent mCb = cb; 15829f103de83f2d5d472960dcf1401e95b2ab57a477Eric Laurent mPid = pid; 15839272b4b4a44fe1f33e3030810618194f817caaecEric Laurent } 15849272b4b4a44fe1f33e3030810618194f817caaecEric Laurent 15859272b4b4a44fe1f33e3030810618194f817caaecEric Laurent public void binderDied() { 1586d7454be47f4111c0478a502353e11dea401378bdEric Laurent int newModeOwnerPid = 0; 15879272b4b4a44fe1f33e3030810618194f817caaecEric Laurent synchronized(mSetModeDeathHandlers) { 15889272b4b4a44fe1f33e3030810618194f817caaecEric Laurent Log.w(TAG, "setMode() client died"); 15899272b4b4a44fe1f33e3030810618194f817caaecEric Laurent int index = mSetModeDeathHandlers.indexOf(this); 15909272b4b4a44fe1f33e3030810618194f817caaecEric Laurent if (index < 0) { 15919272b4b4a44fe1f33e3030810618194f817caaecEric Laurent Log.w(TAG, "unregistered setMode() client died"); 15929272b4b4a44fe1f33e3030810618194f817caaecEric Laurent } else { 1593d7454be47f4111c0478a502353e11dea401378bdEric Laurent newModeOwnerPid = setModeInt(AudioSystem.MODE_NORMAL, mCb, mPid); 15949272b4b4a44fe1f33e3030810618194f817caaecEric Laurent } 15959272b4b4a44fe1f33e3030810618194f817caaecEric Laurent } 15969f103de83f2d5d472960dcf1401e95b2ab57a477Eric Laurent // when entering RINGTONE, IN_CALL or IN_COMMUNICATION mode, clear all 15979f103de83f2d5d472960dcf1401e95b2ab57a477Eric Laurent // SCO connections not started by the application changing the mode 1598d7454be47f4111c0478a502353e11dea401378bdEric Laurent if (newModeOwnerPid != 0) { 15996b5e22d52c69cb6d80ff09bd32395b0034ada343Eric Laurent final long ident = Binder.clearCallingIdentity(); 16006b5e22d52c69cb6d80ff09bd32395b0034ada343Eric Laurent disconnectBluetoothSco(newModeOwnerPid); 16016b5e22d52c69cb6d80ff09bd32395b0034ada343Eric Laurent Binder.restoreCallingIdentity(ident); 16029f103de83f2d5d472960dcf1401e95b2ab57a477Eric Laurent } 16039272b4b4a44fe1f33e3030810618194f817caaecEric Laurent } 16049272b4b4a44fe1f33e3030810618194f817caaecEric Laurent 1605f1ddd51f9cd2f92b922bc636c307210a8d587c25Marco Nelissen public int getPid() { 1606f1ddd51f9cd2f92b922bc636c307210a8d587c25Marco Nelissen return mPid; 1607f1ddd51f9cd2f92b922bc636c307210a8d587c25Marco Nelissen } 1608f1ddd51f9cd2f92b922bc636c307210a8d587c25Marco Nelissen 16099272b4b4a44fe1f33e3030810618194f817caaecEric Laurent public void setMode(int mode) { 16109272b4b4a44fe1f33e3030810618194f817caaecEric Laurent mMode = mode; 16119272b4b4a44fe1f33e3030810618194f817caaecEric Laurent } 16129272b4b4a44fe1f33e3030810618194f817caaecEric Laurent 16139272b4b4a44fe1f33e3030810618194f817caaecEric Laurent public int getMode() { 16149272b4b4a44fe1f33e3030810618194f817caaecEric Laurent return mMode; 16159272b4b4a44fe1f33e3030810618194f817caaecEric Laurent } 16169272b4b4a44fe1f33e3030810618194f817caaecEric Laurent 16179272b4b4a44fe1f33e3030810618194f817caaecEric Laurent public IBinder getBinder() { 16189272b4b4a44fe1f33e3030810618194f817caaecEric Laurent return mCb; 16199272b4b4a44fe1f33e3030810618194f817caaecEric Laurent } 16209272b4b4a44fe1f33e3030810618194f817caaecEric Laurent } 16219272b4b4a44fe1f33e3030810618194f817caaecEric Laurent 16229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** @see AudioManager#setMode(int) */ 16239272b4b4a44fe1f33e3030810618194f817caaecEric Laurent public void setMode(int mode, IBinder cb) { 16249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (!checkAudioSettingsPermission("setMode()")) { 16259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return; 16269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1627a553c25b33c99b345cf1c8688f8df0ed8df14e5aEric Laurent 16288f677d66d9c3ba34c97e69b2bb9e161f129af0eeJean-Michel Trivi if (mode < AudioSystem.MODE_CURRENT || mode >= AudioSystem.NUM_MODES) { 1629a553c25b33c99b345cf1c8688f8df0ed8df14e5aEric Laurent return; 1630a553c25b33c99b345cf1c8688f8df0ed8df14e5aEric Laurent } 1631a553c25b33c99b345cf1c8688f8df0ed8df14e5aEric Laurent 1632d7454be47f4111c0478a502353e11dea401378bdEric Laurent int newModeOwnerPid = 0; 16339f103de83f2d5d472960dcf1401e95b2ab57a477Eric Laurent synchronized(mSetModeDeathHandlers) { 1634a553c25b33c99b345cf1c8688f8df0ed8df14e5aEric Laurent if (mode == AudioSystem.MODE_CURRENT) { 1635a553c25b33c99b345cf1c8688f8df0ed8df14e5aEric Laurent mode = mMode; 1636a553c25b33c99b345cf1c8688f8df0ed8df14e5aEric Laurent } 1637d7454be47f4111c0478a502353e11dea401378bdEric Laurent newModeOwnerPid = setModeInt(mode, cb, Binder.getCallingPid()); 16389f103de83f2d5d472960dcf1401e95b2ab57a477Eric Laurent } 16399f103de83f2d5d472960dcf1401e95b2ab57a477Eric Laurent // when entering RINGTONE, IN_CALL or IN_COMMUNICATION mode, clear all 16409f103de83f2d5d472960dcf1401e95b2ab57a477Eric Laurent // SCO connections not started by the application changing the mode 1641d7454be47f4111c0478a502353e11dea401378bdEric Laurent if (newModeOwnerPid != 0) { 1642d7454be47f4111c0478a502353e11dea401378bdEric Laurent disconnectBluetoothSco(newModeOwnerPid); 16439f103de83f2d5d472960dcf1401e95b2ab57a477Eric Laurent } 16449f103de83f2d5d472960dcf1401e95b2ab57a477Eric Laurent } 16452ade576148fe33c5ff6098d30ccfbcf28df70e8eJean-Michel Trivi 16469f103de83f2d5d472960dcf1401e95b2ab57a477Eric Laurent // must be called synchronized on mSetModeDeathHandlers 1647d7454be47f4111c0478a502353e11dea401378bdEric Laurent // setModeInt() returns a valid PID if the audio mode was successfully set to 16489f103de83f2d5d472960dcf1401e95b2ab57a477Eric Laurent // any mode other than NORMAL. 1649d7454be47f4111c0478a502353e11dea401378bdEric Laurent int setModeInt(int mode, IBinder cb, int pid) { 1650d7454be47f4111c0478a502353e11dea401378bdEric Laurent int newModeOwnerPid = 0; 16519f103de83f2d5d472960dcf1401e95b2ab57a477Eric Laurent if (cb == null) { 16529f103de83f2d5d472960dcf1401e95b2ab57a477Eric Laurent Log.e(TAG, "setModeInt() called with null binder"); 1653d7454be47f4111c0478a502353e11dea401378bdEric Laurent return newModeOwnerPid; 16549f103de83f2d5d472960dcf1401e95b2ab57a477Eric Laurent } 16552ade576148fe33c5ff6098d30ccfbcf28df70e8eJean-Michel Trivi 16569f103de83f2d5d472960dcf1401e95b2ab57a477Eric Laurent SetModeDeathHandler hdlr = null; 16579f103de83f2d5d472960dcf1401e95b2ab57a477Eric Laurent Iterator iter = mSetModeDeathHandlers.iterator(); 16589f103de83f2d5d472960dcf1401e95b2ab57a477Eric Laurent while (iter.hasNext()) { 16599f103de83f2d5d472960dcf1401e95b2ab57a477Eric Laurent SetModeDeathHandler h = (SetModeDeathHandler)iter.next(); 16609f103de83f2d5d472960dcf1401e95b2ab57a477Eric Laurent if (h.getPid() == pid) { 16619f103de83f2d5d472960dcf1401e95b2ab57a477Eric Laurent hdlr = h; 16629f103de83f2d5d472960dcf1401e95b2ab57a477Eric Laurent // Remove from client list so that it is re-inserted at top of list 16639f103de83f2d5d472960dcf1401e95b2ab57a477Eric Laurent iter.remove(); 16649f103de83f2d5d472960dcf1401e95b2ab57a477Eric Laurent hdlr.getBinder().unlinkToDeath(hdlr, 0); 16659f103de83f2d5d472960dcf1401e95b2ab57a477Eric Laurent break; 16669f103de83f2d5d472960dcf1401e95b2ab57a477Eric Laurent } 16679f103de83f2d5d472960dcf1401e95b2ab57a477Eric Laurent } 16689f103de83f2d5d472960dcf1401e95b2ab57a477Eric Laurent int status = AudioSystem.AUDIO_STATUS_OK; 16699f103de83f2d5d472960dcf1401e95b2ab57a477Eric Laurent do { 16709f103de83f2d5d472960dcf1401e95b2ab57a477Eric Laurent if (mode == AudioSystem.MODE_NORMAL) { 16719f103de83f2d5d472960dcf1401e95b2ab57a477Eric Laurent // get new mode from client at top the list if any 16729f103de83f2d5d472960dcf1401e95b2ab57a477Eric Laurent if (!mSetModeDeathHandlers.isEmpty()) { 16739f103de83f2d5d472960dcf1401e95b2ab57a477Eric Laurent hdlr = mSetModeDeathHandlers.get(0); 16749f103de83f2d5d472960dcf1401e95b2ab57a477Eric Laurent cb = hdlr.getBinder(); 16759f103de83f2d5d472960dcf1401e95b2ab57a477Eric Laurent mode = hdlr.getMode(); 16769f103de83f2d5d472960dcf1401e95b2ab57a477Eric Laurent } 16779f103de83f2d5d472960dcf1401e95b2ab57a477Eric Laurent } else { 16789f103de83f2d5d472960dcf1401e95b2ab57a477Eric Laurent if (hdlr == null) { 16799f103de83f2d5d472960dcf1401e95b2ab57a477Eric Laurent hdlr = new SetModeDeathHandler(cb, pid); 16809f103de83f2d5d472960dcf1401e95b2ab57a477Eric Laurent } 16819f103de83f2d5d472960dcf1401e95b2ab57a477Eric Laurent // Register for client death notification 16829f103de83f2d5d472960dcf1401e95b2ab57a477Eric Laurent try { 16839f103de83f2d5d472960dcf1401e95b2ab57a477Eric Laurent cb.linkToDeath(hdlr, 0); 16849f103de83f2d5d472960dcf1401e95b2ab57a477Eric Laurent } catch (RemoteException e) { 16859f103de83f2d5d472960dcf1401e95b2ab57a477Eric Laurent // Client has died! 16869f103de83f2d5d472960dcf1401e95b2ab57a477Eric Laurent Log.w(TAG, "setMode() could not link to "+cb+" binder death"); 16879f103de83f2d5d472960dcf1401e95b2ab57a477Eric Laurent } 16889272b4b4a44fe1f33e3030810618194f817caaecEric Laurent 16899f103de83f2d5d472960dcf1401e95b2ab57a477Eric Laurent // Last client to call setMode() is always at top of client list 16909f103de83f2d5d472960dcf1401e95b2ab57a477Eric Laurent // as required by SetModeDeathHandler.binderDied() 16919f103de83f2d5d472960dcf1401e95b2ab57a477Eric Laurent mSetModeDeathHandlers.add(0, hdlr); 16929f103de83f2d5d472960dcf1401e95b2ab57a477Eric Laurent hdlr.setMode(mode); 16939f103de83f2d5d472960dcf1401e95b2ab57a477Eric Laurent } 16943def1eec2baed0b8845ec32c871e249dc533a9d9Eric Laurent 16959f103de83f2d5d472960dcf1401e95b2ab57a477Eric Laurent if (mode != mMode) { 16969f103de83f2d5d472960dcf1401e95b2ab57a477Eric Laurent status = AudioSystem.setPhoneState(mode); 16979f103de83f2d5d472960dcf1401e95b2ab57a477Eric Laurent if (status == AudioSystem.AUDIO_STATUS_OK) { 16989f103de83f2d5d472960dcf1401e95b2ab57a477Eric Laurent mMode = mode; 16999f103de83f2d5d472960dcf1401e95b2ab57a477Eric Laurent } else { 17009f103de83f2d5d472960dcf1401e95b2ab57a477Eric Laurent if (hdlr != null) { 17019f103de83f2d5d472960dcf1401e95b2ab57a477Eric Laurent mSetModeDeathHandlers.remove(hdlr); 17029f103de83f2d5d472960dcf1401e95b2ab57a477Eric Laurent cb.unlinkToDeath(hdlr, 0); 17033def1eec2baed0b8845ec32c871e249dc533a9d9Eric Laurent } 17049f103de83f2d5d472960dcf1401e95b2ab57a477Eric Laurent // force reading new top of mSetModeDeathHandlers stack 17059f103de83f2d5d472960dcf1401e95b2ab57a477Eric Laurent mode = AudioSystem.MODE_NORMAL; 1706b9c9d260f21b321527c4622a123af9767630d94dEric Laurent } 17079f103de83f2d5d472960dcf1401e95b2ab57a477Eric Laurent } else { 17089f103de83f2d5d472960dcf1401e95b2ab57a477Eric Laurent status = AudioSystem.AUDIO_STATUS_OK; 17099f103de83f2d5d472960dcf1401e95b2ab57a477Eric Laurent } 17109f103de83f2d5d472960dcf1401e95b2ab57a477Eric Laurent } while (status != AudioSystem.AUDIO_STATUS_OK && !mSetModeDeathHandlers.isEmpty()); 17119f103de83f2d5d472960dcf1401e95b2ab57a477Eric Laurent 17129f103de83f2d5d472960dcf1401e95b2ab57a477Eric Laurent if (status == AudioSystem.AUDIO_STATUS_OK) { 17139f103de83f2d5d472960dcf1401e95b2ab57a477Eric Laurent if (mode != AudioSystem.MODE_NORMAL) { 1714d7454be47f4111c0478a502353e11dea401378bdEric Laurent if (mSetModeDeathHandlers.isEmpty()) { 1715d7454be47f4111c0478a502353e11dea401378bdEric Laurent Log.e(TAG, "setMode() different from MODE_NORMAL with empty mode client stack"); 1716d7454be47f4111c0478a502353e11dea401378bdEric Laurent } else { 1717d7454be47f4111c0478a502353e11dea401378bdEric Laurent newModeOwnerPid = mSetModeDeathHandlers.get(0).getPid(); 1718d7454be47f4111c0478a502353e11dea401378bdEric Laurent } 17199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 17209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int streamType = getActiveStreamType(AudioManager.USE_DEFAULT_STREAM_TYPE); 17213114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi if (streamType == STREAM_REMOTE_MUSIC) { 17223114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi // here handle remote media playback the same way as local playback 17233114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi streamType = AudioManager.STREAM_MUSIC; 17243114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi } 17259bc8358ddaa01c3490f9709991989633a6a3dd42Eric Laurent int device = getDeviceForStream(streamType); 172642b041ed4f184e3af7f788eb07307f556a2a6616Eric Laurent int index = mStreamStates[mStreamVolumeAlias[streamType]].getIndex(device); 172742b041ed4f184e3af7f788eb07307f556a2a6616Eric Laurent setStreamVolumeInt(mStreamVolumeAlias[streamType], index, device, true); 17286d5176638c2189595cede38fb92c3e7e8700e221Eric Laurent 17296d5176638c2189595cede38fb92c3e7e8700e221Eric Laurent updateStreamVolumeAlias(true /*updateVolumes*/); 17309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1731d7454be47f4111c0478a502353e11dea401378bdEric Laurent return newModeOwnerPid; 17329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 17339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 17349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** @see AudioManager#getMode() */ 17359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public int getMode() { 17369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return mMode; 17379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 17389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1739e78fced559d879b2e37b610d0d9a89daf08f0f2bEric Laurent //========================================================================================== 1740e78fced559d879b2e37b610d0d9a89daf08f0f2bEric Laurent // Sound Effects 1741e78fced559d879b2e37b610d0d9a89daf08f0f2bEric Laurent //========================================================================================== 1742e78fced559d879b2e37b610d0d9a89daf08f0f2bEric Laurent 1743e78fced559d879b2e37b610d0d9a89daf08f0f2bEric Laurent private static final String TAG_AUDIO_ASSETS = "audio_assets"; 1744e78fced559d879b2e37b610d0d9a89daf08f0f2bEric Laurent private static final String ATTR_VERSION = "version"; 1745e78fced559d879b2e37b610d0d9a89daf08f0f2bEric Laurent private static final String TAG_GROUP = "group"; 1746e78fced559d879b2e37b610d0d9a89daf08f0f2bEric Laurent private static final String ATTR_GROUP_NAME = "name"; 1747e78fced559d879b2e37b610d0d9a89daf08f0f2bEric Laurent private static final String TAG_ASSET = "asset"; 1748e78fced559d879b2e37b610d0d9a89daf08f0f2bEric Laurent private static final String ATTR_ASSET_ID = "id"; 1749e78fced559d879b2e37b610d0d9a89daf08f0f2bEric Laurent private static final String ATTR_ASSET_FILE = "file"; 1750e78fced559d879b2e37b610d0d9a89daf08f0f2bEric Laurent 1751e78fced559d879b2e37b610d0d9a89daf08f0f2bEric Laurent private static final String ASSET_FILE_VERSION = "1.0"; 1752e78fced559d879b2e37b610d0d9a89daf08f0f2bEric Laurent private static final String GROUP_TOUCH_SOUNDS = "touch_sounds"; 1753e78fced559d879b2e37b610d0d9a89daf08f0f2bEric Laurent 1754167d1a27713ab64cd3c0aa70de96434083ef0400Glenn Kasten private static final int SOUND_EFFECTS_LOAD_TIMEOUT_MS = 5000; 17555d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent 17565d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent class LoadSoundEffectReply { 17575d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent public int mStatus = 1; 17585d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent }; 17595d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent 1760e78fced559d879b2e37b610d0d9a89daf08f0f2bEric Laurent private void loadTouchSoundAssetDefaults() { 1761e78fced559d879b2e37b610d0d9a89daf08f0f2bEric Laurent SOUND_EFFECT_FILES.add("Effect_Tick.ogg"); 1762e78fced559d879b2e37b610d0d9a89daf08f0f2bEric Laurent for (int i = 0; i < AudioManager.NUM_SOUND_EFFECTS; i++) { 1763e78fced559d879b2e37b610d0d9a89daf08f0f2bEric Laurent SOUND_EFFECT_FILES_MAP[i][0] = 0; 1764e78fced559d879b2e37b610d0d9a89daf08f0f2bEric Laurent SOUND_EFFECT_FILES_MAP[i][1] = -1; 1765e78fced559d879b2e37b610d0d9a89daf08f0f2bEric Laurent } 1766e78fced559d879b2e37b610d0d9a89daf08f0f2bEric Laurent } 1767e78fced559d879b2e37b610d0d9a89daf08f0f2bEric Laurent 1768e78fced559d879b2e37b610d0d9a89daf08f0f2bEric Laurent private void loadTouchSoundAssets() { 1769e78fced559d879b2e37b610d0d9a89daf08f0f2bEric Laurent XmlResourceParser parser = null; 1770e78fced559d879b2e37b610d0d9a89daf08f0f2bEric Laurent 17715d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent // only load assets once. 17725d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent if (!SOUND_EFFECT_FILES.isEmpty()) { 17735d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent return; 17745d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent } 17755d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent 1776e78fced559d879b2e37b610d0d9a89daf08f0f2bEric Laurent loadTouchSoundAssetDefaults(); 1777e78fced559d879b2e37b610d0d9a89daf08f0f2bEric Laurent 1778e78fced559d879b2e37b610d0d9a89daf08f0f2bEric Laurent try { 1779e78fced559d879b2e37b610d0d9a89daf08f0f2bEric Laurent parser = mContext.getResources().getXml(com.android.internal.R.xml.audio_assets); 1780e78fced559d879b2e37b610d0d9a89daf08f0f2bEric Laurent 1781e78fced559d879b2e37b610d0d9a89daf08f0f2bEric Laurent XmlUtils.beginDocument(parser, TAG_AUDIO_ASSETS); 1782e78fced559d879b2e37b610d0d9a89daf08f0f2bEric Laurent String version = parser.getAttributeValue(null, ATTR_VERSION); 1783e78fced559d879b2e37b610d0d9a89daf08f0f2bEric Laurent boolean inTouchSoundsGroup = false; 1784e78fced559d879b2e37b610d0d9a89daf08f0f2bEric Laurent 1785e78fced559d879b2e37b610d0d9a89daf08f0f2bEric Laurent if (ASSET_FILE_VERSION.equals(version)) { 1786e78fced559d879b2e37b610d0d9a89daf08f0f2bEric Laurent while (true) { 1787e78fced559d879b2e37b610d0d9a89daf08f0f2bEric Laurent XmlUtils.nextElement(parser); 1788e78fced559d879b2e37b610d0d9a89daf08f0f2bEric Laurent String element = parser.getName(); 1789e78fced559d879b2e37b610d0d9a89daf08f0f2bEric Laurent if (element == null) { 1790e78fced559d879b2e37b610d0d9a89daf08f0f2bEric Laurent break; 1791e78fced559d879b2e37b610d0d9a89daf08f0f2bEric Laurent } 1792e78fced559d879b2e37b610d0d9a89daf08f0f2bEric Laurent if (element.equals(TAG_GROUP)) { 1793e78fced559d879b2e37b610d0d9a89daf08f0f2bEric Laurent String name = parser.getAttributeValue(null, ATTR_GROUP_NAME); 1794e78fced559d879b2e37b610d0d9a89daf08f0f2bEric Laurent if (GROUP_TOUCH_SOUNDS.equals(name)) { 1795e78fced559d879b2e37b610d0d9a89daf08f0f2bEric Laurent inTouchSoundsGroup = true; 1796e78fced559d879b2e37b610d0d9a89daf08f0f2bEric Laurent break; 1797e78fced559d879b2e37b610d0d9a89daf08f0f2bEric Laurent } 1798e78fced559d879b2e37b610d0d9a89daf08f0f2bEric Laurent } 1799e78fced559d879b2e37b610d0d9a89daf08f0f2bEric Laurent } 1800e78fced559d879b2e37b610d0d9a89daf08f0f2bEric Laurent while (inTouchSoundsGroup) { 1801e78fced559d879b2e37b610d0d9a89daf08f0f2bEric Laurent XmlUtils.nextElement(parser); 1802e78fced559d879b2e37b610d0d9a89daf08f0f2bEric Laurent String element = parser.getName(); 1803e78fced559d879b2e37b610d0d9a89daf08f0f2bEric Laurent if (element == null) { 1804e78fced559d879b2e37b610d0d9a89daf08f0f2bEric Laurent break; 1805e78fced559d879b2e37b610d0d9a89daf08f0f2bEric Laurent } 1806e78fced559d879b2e37b610d0d9a89daf08f0f2bEric Laurent if (element.equals(TAG_ASSET)) { 1807e78fced559d879b2e37b610d0d9a89daf08f0f2bEric Laurent String id = parser.getAttributeValue(null, ATTR_ASSET_ID); 1808e78fced559d879b2e37b610d0d9a89daf08f0f2bEric Laurent String file = parser.getAttributeValue(null, ATTR_ASSET_FILE); 1809e78fced559d879b2e37b610d0d9a89daf08f0f2bEric Laurent int fx; 1810e78fced559d879b2e37b610d0d9a89daf08f0f2bEric Laurent 1811e78fced559d879b2e37b610d0d9a89daf08f0f2bEric Laurent try { 1812e78fced559d879b2e37b610d0d9a89daf08f0f2bEric Laurent Field field = AudioManager.class.getField(id); 1813e78fced559d879b2e37b610d0d9a89daf08f0f2bEric Laurent fx = field.getInt(null); 1814e78fced559d879b2e37b610d0d9a89daf08f0f2bEric Laurent } catch (Exception e) { 1815e78fced559d879b2e37b610d0d9a89daf08f0f2bEric Laurent Log.w(TAG, "Invalid touch sound ID: "+id); 1816e78fced559d879b2e37b610d0d9a89daf08f0f2bEric Laurent continue; 1817e78fced559d879b2e37b610d0d9a89daf08f0f2bEric Laurent } 1818e78fced559d879b2e37b610d0d9a89daf08f0f2bEric Laurent 1819e78fced559d879b2e37b610d0d9a89daf08f0f2bEric Laurent int i = SOUND_EFFECT_FILES.indexOf(file); 1820e78fced559d879b2e37b610d0d9a89daf08f0f2bEric Laurent if (i == -1) { 1821e78fced559d879b2e37b610d0d9a89daf08f0f2bEric Laurent i = SOUND_EFFECT_FILES.size(); 1822e78fced559d879b2e37b610d0d9a89daf08f0f2bEric Laurent SOUND_EFFECT_FILES.add(file); 1823e78fced559d879b2e37b610d0d9a89daf08f0f2bEric Laurent } 1824e78fced559d879b2e37b610d0d9a89daf08f0f2bEric Laurent SOUND_EFFECT_FILES_MAP[fx][0] = i; 1825e78fced559d879b2e37b610d0d9a89daf08f0f2bEric Laurent } else { 1826e78fced559d879b2e37b610d0d9a89daf08f0f2bEric Laurent break; 1827e78fced559d879b2e37b610d0d9a89daf08f0f2bEric Laurent } 1828e78fced559d879b2e37b610d0d9a89daf08f0f2bEric Laurent } 1829e78fced559d879b2e37b610d0d9a89daf08f0f2bEric Laurent } 1830e78fced559d879b2e37b610d0d9a89daf08f0f2bEric Laurent } catch (Resources.NotFoundException e) { 1831e78fced559d879b2e37b610d0d9a89daf08f0f2bEric Laurent Log.w(TAG, "audio assets file not found", e); 1832e78fced559d879b2e37b610d0d9a89daf08f0f2bEric Laurent } catch (XmlPullParserException e) { 1833e78fced559d879b2e37b610d0d9a89daf08f0f2bEric Laurent Log.w(TAG, "XML parser exception reading touch sound assets", e); 1834e78fced559d879b2e37b610d0d9a89daf08f0f2bEric Laurent } catch (IOException e) { 1835e78fced559d879b2e37b610d0d9a89daf08f0f2bEric Laurent Log.w(TAG, "I/O exception reading touch sound assets", e); 1836e78fced559d879b2e37b610d0d9a89daf08f0f2bEric Laurent } finally { 1837e78fced559d879b2e37b610d0d9a89daf08f0f2bEric Laurent if (parser != null) { 1838e78fced559d879b2e37b610d0d9a89daf08f0f2bEric Laurent parser.close(); 1839e78fced559d879b2e37b610d0d9a89daf08f0f2bEric Laurent } 1840e78fced559d879b2e37b610d0d9a89daf08f0f2bEric Laurent } 1841e78fced559d879b2e37b610d0d9a89daf08f0f2bEric Laurent } 1842e78fced559d879b2e37b610d0d9a89daf08f0f2bEric Laurent 18439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** @see AudioManager#playSoundEffect(int) */ 18449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public void playSoundEffect(int effectType) { 18455d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent playSoundEffectVolume(effectType, -1.0f); 18469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 18479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 18489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** @see AudioManager#playSoundEffect(int, float) */ 18499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public void playSoundEffectVolume(int effectType, float volume) { 1850559c76dbc37ff25b204ed1f060d3ec2fa43d718cNatalie Silvanovich if (effectType >= AudioManager.NUM_SOUND_EFFECTS || effectType < 0) { 1851559c76dbc37ff25b204ed1f060d3ec2fa43d718cNatalie Silvanovich Log.w(TAG, "AudioService effectType value " + effectType + " out of range"); 1852559c76dbc37ff25b204ed1f060d3ec2fa43d718cNatalie Silvanovich return; 1853559c76dbc37ff25b204ed1f060d3ec2fa43d718cNatalie Silvanovich } 1854559c76dbc37ff25b204ed1f060d3ec2fa43d718cNatalie Silvanovich 18555d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent sendMsg(mAudioHandler, MSG_PLAY_SOUND_EFFECT, SENDMSG_QUEUE, 18569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project effectType, (int) (volume * 1000), null, 0); 18579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 18589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 18599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 18609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Loads samples into the soundpool. 18615c17a820f9e46e0756c11795b3e6f89105f2f539Glenn Kasten * This method must be called at first when sound effects are enabled 18629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 18639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public boolean loadSoundEffects() { 18645d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent int attempts = 3; 18655d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent LoadSoundEffectReply reply = new LoadSoundEffectReply(); 1866117b7bb5b5a4457711f59bde3dcc83d8f111c524Eric Laurent 18675d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent synchronized (reply) { 18685d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent sendMsg(mAudioHandler, MSG_LOAD_SOUND_EFFECTS, SENDMSG_QUEUE, 0, 0, reply, 0); 18695d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent while ((reply.mStatus == 1) && (attempts-- > 0)) { 1870117b7bb5b5a4457711f59bde3dcc83d8f111c524Eric Laurent try { 1871167d1a27713ab64cd3c0aa70de96434083ef0400Glenn Kasten reply.wait(SOUND_EFFECTS_LOAD_TIMEOUT_MS); 18725d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent } catch (InterruptedException e) { 18735d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent Log.w(TAG, "loadSoundEffects Interrupted while waiting sound pool loaded."); 1874117b7bb5b5a4457711f59bde3dcc83d8f111c524Eric Laurent } 1875a60e212d0dda7d2a748180ce77405f2463c9cf53Eric Laurent } 18769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 18775d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent return (reply.mStatus == 0); 18789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 18799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 18809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 18819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Unloads samples from the sound pool. 18829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * This method can be called to free some memory when 18839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * sound effects are disabled. 18849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 18859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public void unloadSoundEffects() { 18865d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent sendMsg(mAudioHandler, MSG_UNLOAD_SOUND_EFFECTS, SENDMSG_QUEUE, 0, 0, null, 0); 18879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 18889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1889a60e212d0dda7d2a748180ce77405f2463c9cf53Eric Laurent class SoundPoolListenerThread extends Thread { 1890a60e212d0dda7d2a748180ce77405f2463c9cf53Eric Laurent public SoundPoolListenerThread() { 1891a60e212d0dda7d2a748180ce77405f2463c9cf53Eric Laurent super("SoundPoolListenerThread"); 1892a60e212d0dda7d2a748180ce77405f2463c9cf53Eric Laurent } 1893a60e212d0dda7d2a748180ce77405f2463c9cf53Eric Laurent 1894a60e212d0dda7d2a748180ce77405f2463c9cf53Eric Laurent @Override 1895a60e212d0dda7d2a748180ce77405f2463c9cf53Eric Laurent public void run() { 1896a60e212d0dda7d2a748180ce77405f2463c9cf53Eric Laurent 1897a60e212d0dda7d2a748180ce77405f2463c9cf53Eric Laurent Looper.prepare(); 1898a60e212d0dda7d2a748180ce77405f2463c9cf53Eric Laurent mSoundPoolLooper = Looper.myLooper(); 1899a60e212d0dda7d2a748180ce77405f2463c9cf53Eric Laurent 1900a60e212d0dda7d2a748180ce77405f2463c9cf53Eric Laurent synchronized (mSoundEffectsLock) { 1901a60e212d0dda7d2a748180ce77405f2463c9cf53Eric Laurent if (mSoundPool != null) { 1902a60e212d0dda7d2a748180ce77405f2463c9cf53Eric Laurent mSoundPoolCallBack = new SoundPoolCallback(); 1903a60e212d0dda7d2a748180ce77405f2463c9cf53Eric Laurent mSoundPool.setOnLoadCompleteListener(mSoundPoolCallBack); 1904a60e212d0dda7d2a748180ce77405f2463c9cf53Eric Laurent } 1905a60e212d0dda7d2a748180ce77405f2463c9cf53Eric Laurent mSoundEffectsLock.notify(); 1906a60e212d0dda7d2a748180ce77405f2463c9cf53Eric Laurent } 1907a60e212d0dda7d2a748180ce77405f2463c9cf53Eric Laurent Looper.loop(); 1908a60e212d0dda7d2a748180ce77405f2463c9cf53Eric Laurent } 1909a60e212d0dda7d2a748180ce77405f2463c9cf53Eric Laurent } 1910a60e212d0dda7d2a748180ce77405f2463c9cf53Eric Laurent 1911a60e212d0dda7d2a748180ce77405f2463c9cf53Eric Laurent private final class SoundPoolCallback implements 1912a60e212d0dda7d2a748180ce77405f2463c9cf53Eric Laurent android.media.SoundPool.OnLoadCompleteListener { 1913a60e212d0dda7d2a748180ce77405f2463c9cf53Eric Laurent 19145d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent int mStatus = 1; // 1 means neither error nor last sample loaded yet 19155d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent List<Integer> mSamples = new ArrayList<Integer>(); 1916a60e212d0dda7d2a748180ce77405f2463c9cf53Eric Laurent 1917a60e212d0dda7d2a748180ce77405f2463c9cf53Eric Laurent public int status() { 1918a60e212d0dda7d2a748180ce77405f2463c9cf53Eric Laurent return mStatus; 1919a60e212d0dda7d2a748180ce77405f2463c9cf53Eric Laurent } 1920a60e212d0dda7d2a748180ce77405f2463c9cf53Eric Laurent 19215d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent public void setSamples(int[] samples) { 19225d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent for (int i = 0; i < samples.length; i++) { 19235d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent // do not wait ack for samples rejected upfront by SoundPool 19245d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent if (samples[i] > 0) { 19255d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent mSamples.add(samples[i]); 19265d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent } 19275d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent } 1928a60e212d0dda7d2a748180ce77405f2463c9cf53Eric Laurent } 1929a60e212d0dda7d2a748180ce77405f2463c9cf53Eric Laurent 1930a60e212d0dda7d2a748180ce77405f2463c9cf53Eric Laurent public void onLoadComplete(SoundPool soundPool, int sampleId, int status) { 1931a60e212d0dda7d2a748180ce77405f2463c9cf53Eric Laurent synchronized (mSoundEffectsLock) { 19325d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent int i = mSamples.indexOf(sampleId); 19335d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent if (i >= 0) { 19345d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent mSamples.remove(i); 1935a60e212d0dda7d2a748180ce77405f2463c9cf53Eric Laurent } 19365d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent if ((status != 0) || mSamples. isEmpty()) { 19375d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent mStatus = status; 1938a60e212d0dda7d2a748180ce77405f2463c9cf53Eric Laurent mSoundEffectsLock.notify(); 1939a60e212d0dda7d2a748180ce77405f2463c9cf53Eric Laurent } 1940a60e212d0dda7d2a748180ce77405f2463c9cf53Eric Laurent } 1941a60e212d0dda7d2a748180ce77405f2463c9cf53Eric Laurent } 1942a60e212d0dda7d2a748180ce77405f2463c9cf53Eric Laurent } 1943a60e212d0dda7d2a748180ce77405f2463c9cf53Eric Laurent 19444050c93601b3c3609b21cc1e18a29b64747e7fa9Eric Laurent /** @see AudioManager#reloadAudioSettings() */ 19454050c93601b3c3609b21cc1e18a29b64747e7fa9Eric Laurent public void reloadAudioSettings() { 1946bc0fab1fc2db832ef86d8a33466ec4d68b103ca0Eric Laurent readAudioSettings(false /*userSwitch*/); 1947bc0fab1fc2db832ef86d8a33466ec4d68b103ca0Eric Laurent } 1948bc0fab1fc2db832ef86d8a33466ec4d68b103ca0Eric Laurent 1949bc0fab1fc2db832ef86d8a33466ec4d68b103ca0Eric Laurent private void readAudioSettings(boolean userSwitch) { 19504050c93601b3c3609b21cc1e18a29b64747e7fa9Eric Laurent // restore ringer mode, ringer mode affected streams, mute affected streams and vibrate settings 19514050c93601b3c3609b21cc1e18a29b64747e7fa9Eric Laurent readPersistedSettings(); 19524050c93601b3c3609b21cc1e18a29b64747e7fa9Eric Laurent 19534050c93601b3c3609b21cc1e18a29b64747e7fa9Eric Laurent // restore volume settings 19544050c93601b3c3609b21cc1e18a29b64747e7fa9Eric Laurent int numStreamTypes = AudioSystem.getNumStreamTypes(); 19554050c93601b3c3609b21cc1e18a29b64747e7fa9Eric Laurent for (int streamType = 0; streamType < numStreamTypes; streamType++) { 19564050c93601b3c3609b21cc1e18a29b64747e7fa9Eric Laurent VolumeStreamState streamState = mStreamStates[streamType]; 19574050c93601b3c3609b21cc1e18a29b64747e7fa9Eric Laurent 1958bc0fab1fc2db832ef86d8a33466ec4d68b103ca0Eric Laurent if (userSwitch && mStreamVolumeAlias[streamType] == AudioSystem.STREAM_MUSIC) { 1959bc0fab1fc2db832ef86d8a33466ec4d68b103ca0Eric Laurent continue; 1960bc0fab1fc2db832ef86d8a33466ec4d68b103ca0Eric Laurent } 1961bc0fab1fc2db832ef86d8a33466ec4d68b103ca0Eric Laurent 19623172d5e3e7520a745fa37b71fc1c7bf244b57085Eric Laurent synchronized (streamState) { 19633172d5e3e7520a745fa37b71fc1c7bf244b57085Eric Laurent streamState.readSettings(); 1964a553c25b33c99b345cf1c8688f8df0ed8df14e5aEric Laurent 19653172d5e3e7520a745fa37b71fc1c7bf244b57085Eric Laurent // unmute stream that was muted but is not affect by mute anymore 196642b041ed4f184e3af7f788eb07307f556a2a6616Eric Laurent if (streamState.isMuted() && ((!isStreamAffectedByMute(streamType) && 196783a017b6b7c099d1a0293e5839be6477325aef06Eric Laurent !isStreamMutedByRingerMode(streamType)) || mUseFixedVolume)) { 19683172d5e3e7520a745fa37b71fc1c7bf244b57085Eric Laurent int size = streamState.mDeathHandlers.size(); 19693172d5e3e7520a745fa37b71fc1c7bf244b57085Eric Laurent for (int i = 0; i < size; i++) { 19703172d5e3e7520a745fa37b71fc1c7bf244b57085Eric Laurent streamState.mDeathHandlers.get(i).mMuteCount = 1; 19713172d5e3e7520a745fa37b71fc1c7bf244b57085Eric Laurent streamState.mDeathHandlers.get(i).mute(false); 19723172d5e3e7520a745fa37b71fc1c7bf244b57085Eric Laurent } 19733172d5e3e7520a745fa37b71fc1c7bf244b57085Eric Laurent } 19744050c93601b3c3609b21cc1e18a29b64747e7fa9Eric Laurent } 19754050c93601b3c3609b21cc1e18a29b64747e7fa9Eric Laurent } 19764050c93601b3c3609b21cc1e18a29b64747e7fa9Eric Laurent 197733902db75011d863009585682bd08560c5b89a75Eric Laurent // apply new ringer mode before checking volume for alias streams so that streams 197833902db75011d863009585682bd08560c5b89a75Eric Laurent // muted by ringer mode have the correct volume 197933902db75011d863009585682bd08560c5b89a75Eric Laurent setRingerModeInt(getRingerMode(), false); 198033902db75011d863009585682bd08560c5b89a75Eric Laurent 1981244820185269991186d07068b92985624cede4a5Eric Laurent checkAllAliasStreamVolumes(); 1982244820185269991186d07068b92985624cede4a5Eric Laurent 1983d640bd325c3be9a350058c835b880a7e0b40dc60Eric Laurent synchronized (mSafeMediaVolumeState) { 1984d640bd325c3be9a350058c835b880a7e0b40dc60Eric Laurent if (mSafeMediaVolumeState == SAFE_MEDIA_VOLUME_ACTIVE) { 1985f1a457d06c53a901ea08d2d3fb6e766bc06c4d4fEric Laurent enforceSafeMediaVolume(); 1986f1a457d06c53a901ea08d2d3fb6e766bc06c4d4fEric Laurent } 1987c34dcc1e1ebf152bb400abbb8bc25f7dc0c3ba97Eric Laurent } 19884050c93601b3c3609b21cc1e18a29b64747e7fa9Eric Laurent } 19894050c93601b3c3609b21cc1e18a29b64747e7fa9Eric Laurent 1990961cae92540763226648813d111c5b5c3b0f1597Dianne Hackborn /** @see AudioManager#setSpeakerphoneOn(boolean) */ 1991c42ac9d4d03f62c3a1ba197a28a81fda44bd8b7fEric Laurent public void setSpeakerphoneOn(boolean on){ 1992dc1d17a1dbfc2ae01c20012133a836b62f5b6930Eric Laurent if (!checkAudioSettingsPermission("setSpeakerphoneOn()")) { 1993dc1d17a1dbfc2ae01c20012133a836b62f5b6930Eric Laurent return; 1994dc1d17a1dbfc2ae01c20012133a836b62f5b6930Eric Laurent } 19957337bee7839238f244fad31112a45389f6ef907cJohan Gustavsson 19967337bee7839238f244fad31112a45389f6ef907cJohan Gustavsson if (on) { 19977337bee7839238f244fad31112a45389f6ef907cJohan Gustavsson if (mForcedUseForComm == AudioSystem.FORCE_BT_SCO) { 19987337bee7839238f244fad31112a45389f6ef907cJohan Gustavsson sendMsg(mAudioHandler, MSG_SET_FORCE_USE, SENDMSG_QUEUE, 19997337bee7839238f244fad31112a45389f6ef907cJohan Gustavsson AudioSystem.FOR_RECORD, AudioSystem.FORCE_NONE, null, 0); 20007337bee7839238f244fad31112a45389f6ef907cJohan Gustavsson } 20017337bee7839238f244fad31112a45389f6ef907cJohan Gustavsson mForcedUseForComm = AudioSystem.FORCE_SPEAKER; 20027337bee7839238f244fad31112a45389f6ef907cJohan Gustavsson } else if (mForcedUseForComm == AudioSystem.FORCE_SPEAKER){ 20037337bee7839238f244fad31112a45389f6ef907cJohan Gustavsson mForcedUseForComm = AudioSystem.FORCE_NONE; 20047337bee7839238f244fad31112a45389f6ef907cJohan Gustavsson } 2005fa640154f1f42121d81242b2f1a10f03e52f0014Eric Laurent 2006afbb047c3945e9c2b7e9bc6b25098d5fb80bba4eEric Laurent sendMsg(mAudioHandler, MSG_SET_FORCE_USE, SENDMSG_QUEUE, 2007fa640154f1f42121d81242b2f1a10f03e52f0014Eric Laurent AudioSystem.FOR_COMMUNICATION, mForcedUseForComm, null, 0); 2008c42ac9d4d03f62c3a1ba197a28a81fda44bd8b7fEric Laurent } 2009c42ac9d4d03f62c3a1ba197a28a81fda44bd8b7fEric Laurent 2010c42ac9d4d03f62c3a1ba197a28a81fda44bd8b7fEric Laurent /** @see AudioManager#isSpeakerphoneOn() */ 2011c42ac9d4d03f62c3a1ba197a28a81fda44bd8b7fEric Laurent public boolean isSpeakerphoneOn() { 2012fa640154f1f42121d81242b2f1a10f03e52f0014Eric Laurent return (mForcedUseForComm == AudioSystem.FORCE_SPEAKER); 2013c42ac9d4d03f62c3a1ba197a28a81fda44bd8b7fEric Laurent } 2014c42ac9d4d03f62c3a1ba197a28a81fda44bd8b7fEric Laurent 2015961cae92540763226648813d111c5b5c3b0f1597Dianne Hackborn /** @see AudioManager#setBluetoothScoOn(boolean) */ 2016c42ac9d4d03f62c3a1ba197a28a81fda44bd8b7fEric Laurent public void setBluetoothScoOn(boolean on){ 2017dc1d17a1dbfc2ae01c20012133a836b62f5b6930Eric Laurent if (!checkAudioSettingsPermission("setBluetoothScoOn()")) { 2018dc1d17a1dbfc2ae01c20012133a836b62f5b6930Eric Laurent return; 2019dc1d17a1dbfc2ae01c20012133a836b62f5b6930Eric Laurent } 20207337bee7839238f244fad31112a45389f6ef907cJohan Gustavsson 20217337bee7839238f244fad31112a45389f6ef907cJohan Gustavsson if (on) { 20227337bee7839238f244fad31112a45389f6ef907cJohan Gustavsson mForcedUseForComm = AudioSystem.FORCE_BT_SCO; 20237337bee7839238f244fad31112a45389f6ef907cJohan Gustavsson } else if (mForcedUseForComm == AudioSystem.FORCE_BT_SCO) { 20247337bee7839238f244fad31112a45389f6ef907cJohan Gustavsson mForcedUseForComm = AudioSystem.FORCE_NONE; 20257337bee7839238f244fad31112a45389f6ef907cJohan Gustavsson } 2026fa640154f1f42121d81242b2f1a10f03e52f0014Eric Laurent 2027afbb047c3945e9c2b7e9bc6b25098d5fb80bba4eEric Laurent sendMsg(mAudioHandler, MSG_SET_FORCE_USE, SENDMSG_QUEUE, 2028fa640154f1f42121d81242b2f1a10f03e52f0014Eric Laurent AudioSystem.FOR_COMMUNICATION, mForcedUseForComm, null, 0); 2029afbb047c3945e9c2b7e9bc6b25098d5fb80bba4eEric Laurent sendMsg(mAudioHandler, MSG_SET_FORCE_USE, SENDMSG_QUEUE, 2030fa640154f1f42121d81242b2f1a10f03e52f0014Eric Laurent AudioSystem.FOR_RECORD, mForcedUseForComm, null, 0); 2031c42ac9d4d03f62c3a1ba197a28a81fda44bd8b7fEric Laurent } 2032c42ac9d4d03f62c3a1ba197a28a81fda44bd8b7fEric Laurent 2033c42ac9d4d03f62c3a1ba197a28a81fda44bd8b7fEric Laurent /** @see AudioManager#isBluetoothScoOn() */ 2034c42ac9d4d03f62c3a1ba197a28a81fda44bd8b7fEric Laurent public boolean isBluetoothScoOn() { 2035fa640154f1f42121d81242b2f1a10f03e52f0014Eric Laurent return (mForcedUseForComm == AudioSystem.FORCE_BT_SCO); 2036c42ac9d4d03f62c3a1ba197a28a81fda44bd8b7fEric Laurent } 2037c42ac9d4d03f62c3a1ba197a28a81fda44bd8b7fEric Laurent 2038961cae92540763226648813d111c5b5c3b0f1597Dianne Hackborn /** @see AudioManager#setBluetoothA2dpOn(boolean) */ 20397847211fb4699bf6018e29d214a918ed6657319bEric Laurent public void setBluetoothA2dpOn(boolean on) { 2040c390bed06b4a572e273ead1254da9a932e04dce3Eric Laurent synchronized (mBluetoothA2dpEnabledLock) { 2041c390bed06b4a572e273ead1254da9a932e04dce3Eric Laurent mBluetoothA2dpEnabled = on; 2042c390bed06b4a572e273ead1254da9a932e04dce3Eric Laurent sendMsg(mAudioHandler, MSG_SET_FORCE_BT_A2DP_USE, SENDMSG_QUEUE, 2043c390bed06b4a572e273ead1254da9a932e04dce3Eric Laurent AudioSystem.FOR_MEDIA, 2044c390bed06b4a572e273ead1254da9a932e04dce3Eric Laurent mBluetoothA2dpEnabled ? AudioSystem.FORCE_NONE : AudioSystem.FORCE_NO_BT_A2DP, 2045c390bed06b4a572e273ead1254da9a932e04dce3Eric Laurent null, 0); 2046c390bed06b4a572e273ead1254da9a932e04dce3Eric Laurent } 20477847211fb4699bf6018e29d214a918ed6657319bEric Laurent } 20487847211fb4699bf6018e29d214a918ed6657319bEric Laurent 20497847211fb4699bf6018e29d214a918ed6657319bEric Laurent /** @see AudioManager#isBluetoothA2dpOn() */ 20507847211fb4699bf6018e29d214a918ed6657319bEric Laurent public boolean isBluetoothA2dpOn() { 20517847211fb4699bf6018e29d214a918ed6657319bEric Laurent synchronized (mBluetoothA2dpEnabledLock) { 20527847211fb4699bf6018e29d214a918ed6657319bEric Laurent return mBluetoothA2dpEnabled; 20537847211fb4699bf6018e29d214a918ed6657319bEric Laurent } 20547847211fb4699bf6018e29d214a918ed6657319bEric Laurent } 20557847211fb4699bf6018e29d214a918ed6657319bEric Laurent 20563def1eec2baed0b8845ec32c871e249dc533a9d9Eric Laurent /** @see AudioManager#startBluetoothSco() */ 205783900754f357616b9e56eaf7fc85f49b8906e987Eric Laurent public void startBluetoothSco(IBinder cb, int targetSdkVersion) { 205883900754f357616b9e56eaf7fc85f49b8906e987Eric Laurent int scoAudioMode = 205983900754f357616b9e56eaf7fc85f49b8906e987Eric Laurent (targetSdkVersion < Build.VERSION_CODES.JELLY_BEAN_MR2) ? 206083900754f357616b9e56eaf7fc85f49b8906e987Eric Laurent SCO_MODE_VIRTUAL_CALL : SCO_MODE_RAW; 206183900754f357616b9e56eaf7fc85f49b8906e987Eric Laurent startBluetoothScoInt(cb, scoAudioMode); 206283900754f357616b9e56eaf7fc85f49b8906e987Eric Laurent } 206383900754f357616b9e56eaf7fc85f49b8906e987Eric Laurent 206483900754f357616b9e56eaf7fc85f49b8906e987Eric Laurent /** @see AudioManager#startBluetoothScoVirtualCall() */ 206583900754f357616b9e56eaf7fc85f49b8906e987Eric Laurent public void startBluetoothScoVirtualCall(IBinder cb) { 206683900754f357616b9e56eaf7fc85f49b8906e987Eric Laurent startBluetoothScoInt(cb, SCO_MODE_VIRTUAL_CALL); 206783900754f357616b9e56eaf7fc85f49b8906e987Eric Laurent } 206883900754f357616b9e56eaf7fc85f49b8906e987Eric Laurent 206983900754f357616b9e56eaf7fc85f49b8906e987Eric Laurent void startBluetoothScoInt(IBinder cb, int scoAudioMode){ 2070dc03c61fe3cd8d0805480e48a974986439977a60Eric Laurent if (!checkAudioSettingsPermission("startBluetoothSco()") || 20714a5eeb9c727d77bb57fef87a70c8c9cc23dbfee3Eric Laurent !mSystemReady) { 20723def1eec2baed0b8845ec32c871e249dc533a9d9Eric Laurent return; 20733def1eec2baed0b8845ec32c871e249dc533a9d9Eric Laurent } 2074854938a72d968c1bc0de4e2b0ea87777cfebc045Eric Laurent ScoClient client = getScoClient(cb, true); 2075f5a1fc3c0fd733acd21e1437f153ba27220be8ceEric Laurent // The calling identity must be cleared before calling ScoClient.incCount(). 2076f5a1fc3c0fd733acd21e1437f153ba27220be8ceEric Laurent // inCount() calls requestScoState() which in turn can call BluetoothHeadset APIs 2077f5a1fc3c0fd733acd21e1437f153ba27220be8ceEric Laurent // and this must be done on behalf of system server to make sure permissions are granted. 2078f5a1fc3c0fd733acd21e1437f153ba27220be8ceEric Laurent // The caller identity must be cleared after getScoClient() because it is needed if a new 2079f5a1fc3c0fd733acd21e1437f153ba27220be8ceEric Laurent // client is created. 2080f5a1fc3c0fd733acd21e1437f153ba27220be8ceEric Laurent final long ident = Binder.clearCallingIdentity(); 208183900754f357616b9e56eaf7fc85f49b8906e987Eric Laurent client.incCount(scoAudioMode); 20822a57ca931fefe817b6110101289721acaacfc808Eric Laurent Binder.restoreCallingIdentity(ident); 20833def1eec2baed0b8845ec32c871e249dc533a9d9Eric Laurent } 20843def1eec2baed0b8845ec32c871e249dc533a9d9Eric Laurent 20853def1eec2baed0b8845ec32c871e249dc533a9d9Eric Laurent /** @see AudioManager#stopBluetoothSco() */ 20863def1eec2baed0b8845ec32c871e249dc533a9d9Eric Laurent public void stopBluetoothSco(IBinder cb){ 2087dc03c61fe3cd8d0805480e48a974986439977a60Eric Laurent if (!checkAudioSettingsPermission("stopBluetoothSco()") || 20884a5eeb9c727d77bb57fef87a70c8c9cc23dbfee3Eric Laurent !mSystemReady) { 20893def1eec2baed0b8845ec32c871e249dc533a9d9Eric Laurent return; 20903def1eec2baed0b8845ec32c871e249dc533a9d9Eric Laurent } 2091854938a72d968c1bc0de4e2b0ea87777cfebc045Eric Laurent ScoClient client = getScoClient(cb, false); 2092f5a1fc3c0fd733acd21e1437f153ba27220be8ceEric Laurent // The calling identity must be cleared before calling ScoClient.decCount(). 2093f5a1fc3c0fd733acd21e1437f153ba27220be8ceEric Laurent // decCount() calls requestScoState() which in turn can call BluetoothHeadset APIs 2094f5a1fc3c0fd733acd21e1437f153ba27220be8ceEric Laurent // and this must be done on behalf of system server to make sure permissions are granted. 2095f5a1fc3c0fd733acd21e1437f153ba27220be8ceEric Laurent final long ident = Binder.clearCallingIdentity(); 2096854938a72d968c1bc0de4e2b0ea87777cfebc045Eric Laurent if (client != null) { 2097854938a72d968c1bc0de4e2b0ea87777cfebc045Eric Laurent client.decCount(); 2098854938a72d968c1bc0de4e2b0ea87777cfebc045Eric Laurent } 20992a57ca931fefe817b6110101289721acaacfc808Eric Laurent Binder.restoreCallingIdentity(ident); 21003def1eec2baed0b8845ec32c871e249dc533a9d9Eric Laurent } 21013def1eec2baed0b8845ec32c871e249dc533a9d9Eric Laurent 21027847211fb4699bf6018e29d214a918ed6657319bEric Laurent 21033def1eec2baed0b8845ec32c871e249dc533a9d9Eric Laurent private class ScoClient implements IBinder.DeathRecipient { 21043def1eec2baed0b8845ec32c871e249dc533a9d9Eric Laurent private IBinder mCb; // To be notified of client's death 2105f1ddd51f9cd2f92b922bc636c307210a8d587c25Marco Nelissen private int mCreatorPid; 21063def1eec2baed0b8845ec32c871e249dc533a9d9Eric Laurent private int mStartcount; // number of SCO connections started by this client 21073def1eec2baed0b8845ec32c871e249dc533a9d9Eric Laurent 21083def1eec2baed0b8845ec32c871e249dc533a9d9Eric Laurent ScoClient(IBinder cb) { 21093def1eec2baed0b8845ec32c871e249dc533a9d9Eric Laurent mCb = cb; 2110f1ddd51f9cd2f92b922bc636c307210a8d587c25Marco Nelissen mCreatorPid = Binder.getCallingPid(); 21113def1eec2baed0b8845ec32c871e249dc533a9d9Eric Laurent mStartcount = 0; 21123def1eec2baed0b8845ec32c871e249dc533a9d9Eric Laurent } 21133def1eec2baed0b8845ec32c871e249dc533a9d9Eric Laurent 21143def1eec2baed0b8845ec32c871e249dc533a9d9Eric Laurent public void binderDied() { 21153def1eec2baed0b8845ec32c871e249dc533a9d9Eric Laurent synchronized(mScoClients) { 21163def1eec2baed0b8845ec32c871e249dc533a9d9Eric Laurent Log.w(TAG, "SCO client died"); 21173def1eec2baed0b8845ec32c871e249dc533a9d9Eric Laurent int index = mScoClients.indexOf(this); 21183def1eec2baed0b8845ec32c871e249dc533a9d9Eric Laurent if (index < 0) { 21193def1eec2baed0b8845ec32c871e249dc533a9d9Eric Laurent Log.w(TAG, "unregistered SCO client died"); 21203def1eec2baed0b8845ec32c871e249dc533a9d9Eric Laurent } else { 21213def1eec2baed0b8845ec32c871e249dc533a9d9Eric Laurent clearCount(true); 21223def1eec2baed0b8845ec32c871e249dc533a9d9Eric Laurent mScoClients.remove(this); 21233def1eec2baed0b8845ec32c871e249dc533a9d9Eric Laurent } 21243def1eec2baed0b8845ec32c871e249dc533a9d9Eric Laurent } 21253def1eec2baed0b8845ec32c871e249dc533a9d9Eric Laurent } 21263def1eec2baed0b8845ec32c871e249dc533a9d9Eric Laurent 212783900754f357616b9e56eaf7fc85f49b8906e987Eric Laurent public void incCount(int scoAudioMode) { 21283def1eec2baed0b8845ec32c871e249dc533a9d9Eric Laurent synchronized(mScoClients) { 212983900754f357616b9e56eaf7fc85f49b8906e987Eric Laurent requestScoState(BluetoothHeadset.STATE_AUDIO_CONNECTED, scoAudioMode); 21303def1eec2baed0b8845ec32c871e249dc533a9d9Eric Laurent if (mStartcount == 0) { 21313def1eec2baed0b8845ec32c871e249dc533a9d9Eric Laurent try { 21323def1eec2baed0b8845ec32c871e249dc533a9d9Eric Laurent mCb.linkToDeath(this, 0); 21333def1eec2baed0b8845ec32c871e249dc533a9d9Eric Laurent } catch (RemoteException e) { 21343def1eec2baed0b8845ec32c871e249dc533a9d9Eric Laurent // client has already died! 21353def1eec2baed0b8845ec32c871e249dc533a9d9Eric Laurent Log.w(TAG, "ScoClient incCount() could not link to "+mCb+" binder death"); 21363def1eec2baed0b8845ec32c871e249dc533a9d9Eric Laurent } 21373def1eec2baed0b8845ec32c871e249dc533a9d9Eric Laurent } 21383def1eec2baed0b8845ec32c871e249dc533a9d9Eric Laurent mStartcount++; 21393def1eec2baed0b8845ec32c871e249dc533a9d9Eric Laurent } 21403def1eec2baed0b8845ec32c871e249dc533a9d9Eric Laurent } 21413def1eec2baed0b8845ec32c871e249dc533a9d9Eric Laurent 21423def1eec2baed0b8845ec32c871e249dc533a9d9Eric Laurent public void decCount() { 21433def1eec2baed0b8845ec32c871e249dc533a9d9Eric Laurent synchronized(mScoClients) { 21443def1eec2baed0b8845ec32c871e249dc533a9d9Eric Laurent if (mStartcount == 0) { 21453def1eec2baed0b8845ec32c871e249dc533a9d9Eric Laurent Log.w(TAG, "ScoClient.decCount() already 0"); 21463def1eec2baed0b8845ec32c871e249dc533a9d9Eric Laurent } else { 21473def1eec2baed0b8845ec32c871e249dc533a9d9Eric Laurent mStartcount--; 21483def1eec2baed0b8845ec32c871e249dc533a9d9Eric Laurent if (mStartcount == 0) { 2149e2dd8c4592762414c2c27e4589be7edc91a5ecaeEric Laurent try { 2150e2dd8c4592762414c2c27e4589be7edc91a5ecaeEric Laurent mCb.unlinkToDeath(this, 0); 2151e2dd8c4592762414c2c27e4589be7edc91a5ecaeEric Laurent } catch (NoSuchElementException e) { 2152e2dd8c4592762414c2c27e4589be7edc91a5ecaeEric Laurent Log.w(TAG, "decCount() going to 0 but not registered to binder"); 2153e2dd8c4592762414c2c27e4589be7edc91a5ecaeEric Laurent } 21543def1eec2baed0b8845ec32c871e249dc533a9d9Eric Laurent } 2155c18c9138cee0f0859bcab636a004ce92ca4a9ab5Eric Laurent requestScoState(BluetoothHeadset.STATE_AUDIO_DISCONNECTED, 0); 21563def1eec2baed0b8845ec32c871e249dc533a9d9Eric Laurent } 21573def1eec2baed0b8845ec32c871e249dc533a9d9Eric Laurent } 21583def1eec2baed0b8845ec32c871e249dc533a9d9Eric Laurent } 21593def1eec2baed0b8845ec32c871e249dc533a9d9Eric Laurent 21603def1eec2baed0b8845ec32c871e249dc533a9d9Eric Laurent public void clearCount(boolean stopSco) { 21613def1eec2baed0b8845ec32c871e249dc533a9d9Eric Laurent synchronized(mScoClients) { 2162e2dd8c4592762414c2c27e4589be7edc91a5ecaeEric Laurent if (mStartcount != 0) { 2163e2dd8c4592762414c2c27e4589be7edc91a5ecaeEric Laurent try { 2164e2dd8c4592762414c2c27e4589be7edc91a5ecaeEric Laurent mCb.unlinkToDeath(this, 0); 2165e2dd8c4592762414c2c27e4589be7edc91a5ecaeEric Laurent } catch (NoSuchElementException e) { 2166e2dd8c4592762414c2c27e4589be7edc91a5ecaeEric Laurent Log.w(TAG, "clearCount() mStartcount: "+mStartcount+" != 0 but not registered to binder"); 2167e2dd8c4592762414c2c27e4589be7edc91a5ecaeEric Laurent } 2168e2dd8c4592762414c2c27e4589be7edc91a5ecaeEric Laurent } 21693def1eec2baed0b8845ec32c871e249dc533a9d9Eric Laurent mStartcount = 0; 21703def1eec2baed0b8845ec32c871e249dc533a9d9Eric Laurent if (stopSco) { 2171c18c9138cee0f0859bcab636a004ce92ca4a9ab5Eric Laurent requestScoState(BluetoothHeadset.STATE_AUDIO_DISCONNECTED, 0); 21723def1eec2baed0b8845ec32c871e249dc533a9d9Eric Laurent } 21733def1eec2baed0b8845ec32c871e249dc533a9d9Eric Laurent } 21743def1eec2baed0b8845ec32c871e249dc533a9d9Eric Laurent } 21753def1eec2baed0b8845ec32c871e249dc533a9d9Eric Laurent 21763def1eec2baed0b8845ec32c871e249dc533a9d9Eric Laurent public int getCount() { 21773def1eec2baed0b8845ec32c871e249dc533a9d9Eric Laurent return mStartcount; 21783def1eec2baed0b8845ec32c871e249dc533a9d9Eric Laurent } 21793def1eec2baed0b8845ec32c871e249dc533a9d9Eric Laurent 21803def1eec2baed0b8845ec32c871e249dc533a9d9Eric Laurent public IBinder getBinder() { 21813def1eec2baed0b8845ec32c871e249dc533a9d9Eric Laurent return mCb; 21823def1eec2baed0b8845ec32c871e249dc533a9d9Eric Laurent } 21833def1eec2baed0b8845ec32c871e249dc533a9d9Eric Laurent 2184d7454be47f4111c0478a502353e11dea401378bdEric Laurent public int getPid() { 2185d7454be47f4111c0478a502353e11dea401378bdEric Laurent return mCreatorPid; 2186d7454be47f4111c0478a502353e11dea401378bdEric Laurent } 2187d7454be47f4111c0478a502353e11dea401378bdEric Laurent 21883def1eec2baed0b8845ec32c871e249dc533a9d9Eric Laurent public int totalCount() { 21893def1eec2baed0b8845ec32c871e249dc533a9d9Eric Laurent synchronized(mScoClients) { 21903def1eec2baed0b8845ec32c871e249dc533a9d9Eric Laurent int count = 0; 21913def1eec2baed0b8845ec32c871e249dc533a9d9Eric Laurent int size = mScoClients.size(); 21923def1eec2baed0b8845ec32c871e249dc533a9d9Eric Laurent for (int i = 0; i < size; i++) { 21933def1eec2baed0b8845ec32c871e249dc533a9d9Eric Laurent count += mScoClients.get(i).getCount(); 21943def1eec2baed0b8845ec32c871e249dc533a9d9Eric Laurent } 21953def1eec2baed0b8845ec32c871e249dc533a9d9Eric Laurent return count; 21963def1eec2baed0b8845ec32c871e249dc533a9d9Eric Laurent } 21973def1eec2baed0b8845ec32c871e249dc533a9d9Eric Laurent } 21983def1eec2baed0b8845ec32c871e249dc533a9d9Eric Laurent 219983900754f357616b9e56eaf7fc85f49b8906e987Eric Laurent private void requestScoState(int state, int scoAudioMode) { 220062ef767b15a712bab31cc0d5508a330906f535c2Eric Laurent checkScoAudioState(); 2201dc03c61fe3cd8d0805480e48a974986439977a60Eric Laurent if (totalCount() == 0) { 2202dc03c61fe3cd8d0805480e48a974986439977a60Eric Laurent if (state == BluetoothHeadset.STATE_AUDIO_CONNECTED) { 2203dc03c61fe3cd8d0805480e48a974986439977a60Eric Laurent // Make sure that the state transitions to CONNECTING even if we cannot initiate 2204dc03c61fe3cd8d0805480e48a974986439977a60Eric Laurent // the connection. 2205dc03c61fe3cd8d0805480e48a974986439977a60Eric Laurent broadcastScoConnectionState(AudioManager.SCO_AUDIO_STATE_CONNECTING); 2206dc03c61fe3cd8d0805480e48a974986439977a60Eric Laurent // Accept SCO audio activation only in NORMAL audio mode or if the mode is 2207f1ddd51f9cd2f92b922bc636c307210a8d587c25Marco Nelissen // currently controlled by the same client process. 22089f103de83f2d5d472960dcf1401e95b2ab57a477Eric Laurent synchronized(mSetModeDeathHandlers) { 22099f103de83f2d5d472960dcf1401e95b2ab57a477Eric Laurent if ((mSetModeDeathHandlers.isEmpty() || 22109f103de83f2d5d472960dcf1401e95b2ab57a477Eric Laurent mSetModeDeathHandlers.get(0).getPid() == mCreatorPid) && 22119f103de83f2d5d472960dcf1401e95b2ab57a477Eric Laurent (mScoAudioState == SCO_STATE_INACTIVE || 22129f103de83f2d5d472960dcf1401e95b2ab57a477Eric Laurent mScoAudioState == SCO_STATE_DEACTIVATE_REQ)) { 22139f103de83f2d5d472960dcf1401e95b2ab57a477Eric Laurent if (mScoAudioState == SCO_STATE_INACTIVE) { 221483900754f357616b9e56eaf7fc85f49b8906e987Eric Laurent mScoAudioMode = scoAudioMode; 22159f103de83f2d5d472960dcf1401e95b2ab57a477Eric Laurent if (mBluetoothHeadset != null && mBluetoothHeadsetDevice != null) { 2216c18c9138cee0f0859bcab636a004ce92ca4a9ab5Eric Laurent boolean status; 2217c18c9138cee0f0859bcab636a004ce92ca4a9ab5Eric Laurent if (mScoAudioMode == SCO_MODE_RAW) { 2218c18c9138cee0f0859bcab636a004ce92ca4a9ab5Eric Laurent status = mBluetoothHeadset.connectAudio(); 2219c18c9138cee0f0859bcab636a004ce92ca4a9ab5Eric Laurent } else { 2220c18c9138cee0f0859bcab636a004ce92ca4a9ab5Eric Laurent status = mBluetoothHeadset.startScoUsingVirtualVoiceCall( 2221c18c9138cee0f0859bcab636a004ce92ca4a9ab5Eric Laurent mBluetoothHeadsetDevice); 2222c18c9138cee0f0859bcab636a004ce92ca4a9ab5Eric Laurent } 2223c18c9138cee0f0859bcab636a004ce92ca4a9ab5Eric Laurent if (status) { 22249f103de83f2d5d472960dcf1401e95b2ab57a477Eric Laurent mScoAudioState = SCO_STATE_ACTIVE_INTERNAL; 22259f103de83f2d5d472960dcf1401e95b2ab57a477Eric Laurent } else { 22269f103de83f2d5d472960dcf1401e95b2ab57a477Eric Laurent broadcastScoConnectionState( 22279f103de83f2d5d472960dcf1401e95b2ab57a477Eric Laurent AudioManager.SCO_AUDIO_STATE_DISCONNECTED); 22289f103de83f2d5d472960dcf1401e95b2ab57a477Eric Laurent } 22299f103de83f2d5d472960dcf1401e95b2ab57a477Eric Laurent } else if (getBluetoothHeadset()) { 22309f103de83f2d5d472960dcf1401e95b2ab57a477Eric Laurent mScoAudioState = SCO_STATE_ACTIVATE_REQ; 2231dc03c61fe3cd8d0805480e48a974986439977a60Eric Laurent } 22329f103de83f2d5d472960dcf1401e95b2ab57a477Eric Laurent } else { 22339f103de83f2d5d472960dcf1401e95b2ab57a477Eric Laurent mScoAudioState = SCO_STATE_ACTIVE_INTERNAL; 22349f103de83f2d5d472960dcf1401e95b2ab57a477Eric Laurent broadcastScoConnectionState(AudioManager.SCO_AUDIO_STATE_CONNECTED); 2235dc03c61fe3cd8d0805480e48a974986439977a60Eric Laurent } 2236dc03c61fe3cd8d0805480e48a974986439977a60Eric Laurent } else { 22379f103de83f2d5d472960dcf1401e95b2ab57a477Eric Laurent broadcastScoConnectionState(AudioManager.SCO_AUDIO_STATE_DISCONNECTED); 2238dc03c61fe3cd8d0805480e48a974986439977a60Eric Laurent } 2239dc03c61fe3cd8d0805480e48a974986439977a60Eric Laurent } 224062ef767b15a712bab31cc0d5508a330906f535c2Eric Laurent } else if (state == BluetoothHeadset.STATE_AUDIO_DISCONNECTED && 2241dc03c61fe3cd8d0805480e48a974986439977a60Eric Laurent (mScoAudioState == SCO_STATE_ACTIVE_INTERNAL || 2242dc03c61fe3cd8d0805480e48a974986439977a60Eric Laurent mScoAudioState == SCO_STATE_ACTIVATE_REQ)) { 2243dc03c61fe3cd8d0805480e48a974986439977a60Eric Laurent if (mScoAudioState == SCO_STATE_ACTIVE_INTERNAL) { 2244671db6f3ba1fdb3c907e0735fe6d0d284f5c34deMarco Nelissen if (mBluetoothHeadset != null && mBluetoothHeadsetDevice != null) { 2245c18c9138cee0f0859bcab636a004ce92ca4a9ab5Eric Laurent boolean status; 2246c18c9138cee0f0859bcab636a004ce92ca4a9ab5Eric Laurent if (mScoAudioMode == SCO_MODE_RAW) { 2247c18c9138cee0f0859bcab636a004ce92ca4a9ab5Eric Laurent status = mBluetoothHeadset.disconnectAudio(); 2248c18c9138cee0f0859bcab636a004ce92ca4a9ab5Eric Laurent } else { 2249c18c9138cee0f0859bcab636a004ce92ca4a9ab5Eric Laurent status = mBluetoothHeadset.stopScoUsingVirtualVoiceCall( 2250c18c9138cee0f0859bcab636a004ce92ca4a9ab5Eric Laurent mBluetoothHeadsetDevice); 2251c18c9138cee0f0859bcab636a004ce92ca4a9ab5Eric Laurent } 2252c18c9138cee0f0859bcab636a004ce92ca4a9ab5Eric Laurent if (!status) { 2253dc03c61fe3cd8d0805480e48a974986439977a60Eric Laurent mScoAudioState = SCO_STATE_INACTIVE; 2254dc03c61fe3cd8d0805480e48a974986439977a60Eric Laurent broadcastScoConnectionState( 2255dc03c61fe3cd8d0805480e48a974986439977a60Eric Laurent AudioManager.SCO_AUDIO_STATE_DISCONNECTED); 2256dc03c61fe3cd8d0805480e48a974986439977a60Eric Laurent } 2257dc03c61fe3cd8d0805480e48a974986439977a60Eric Laurent } else if (getBluetoothHeadset()) { 2258dc03c61fe3cd8d0805480e48a974986439977a60Eric Laurent mScoAudioState = SCO_STATE_DEACTIVATE_REQ; 2259dc03c61fe3cd8d0805480e48a974986439977a60Eric Laurent } 2260dc03c61fe3cd8d0805480e48a974986439977a60Eric Laurent } else { 2261dc03c61fe3cd8d0805480e48a974986439977a60Eric Laurent mScoAudioState = SCO_STATE_INACTIVE; 2262dc03c61fe3cd8d0805480e48a974986439977a60Eric Laurent broadcastScoConnectionState(AudioManager.SCO_AUDIO_STATE_DISCONNECTED); 2263dc03c61fe3cd8d0805480e48a974986439977a60Eric Laurent } 22643def1eec2baed0b8845ec32c871e249dc533a9d9Eric Laurent } 22653def1eec2baed0b8845ec32c871e249dc533a9d9Eric Laurent } 22663def1eec2baed0b8845ec32c871e249dc533a9d9Eric Laurent } 22673def1eec2baed0b8845ec32c871e249dc533a9d9Eric Laurent } 22683def1eec2baed0b8845ec32c871e249dc533a9d9Eric Laurent 226962ef767b15a712bab31cc0d5508a330906f535c2Eric Laurent private void checkScoAudioState() { 227062ef767b15a712bab31cc0d5508a330906f535c2Eric Laurent if (mBluetoothHeadset != null && mBluetoothHeadsetDevice != null && 2271dc03c61fe3cd8d0805480e48a974986439977a60Eric Laurent mScoAudioState == SCO_STATE_INACTIVE && 227262ef767b15a712bab31cc0d5508a330906f535c2Eric Laurent mBluetoothHeadset.getAudioState(mBluetoothHeadsetDevice) 227362ef767b15a712bab31cc0d5508a330906f535c2Eric Laurent != BluetoothHeadset.STATE_AUDIO_DISCONNECTED) { 227462ef767b15a712bab31cc0d5508a330906f535c2Eric Laurent mScoAudioState = SCO_STATE_ACTIVE_EXTERNAL; 227562ef767b15a712bab31cc0d5508a330906f535c2Eric Laurent } 227662ef767b15a712bab31cc0d5508a330906f535c2Eric Laurent } 227762ef767b15a712bab31cc0d5508a330906f535c2Eric Laurent 2278854938a72d968c1bc0de4e2b0ea87777cfebc045Eric Laurent private ScoClient getScoClient(IBinder cb, boolean create) { 22793def1eec2baed0b8845ec32c871e249dc533a9d9Eric Laurent synchronized(mScoClients) { 2280854938a72d968c1bc0de4e2b0ea87777cfebc045Eric Laurent ScoClient client = null; 22813def1eec2baed0b8845ec32c871e249dc533a9d9Eric Laurent int size = mScoClients.size(); 22823def1eec2baed0b8845ec32c871e249dc533a9d9Eric Laurent for (int i = 0; i < size; i++) { 22833def1eec2baed0b8845ec32c871e249dc533a9d9Eric Laurent client = mScoClients.get(i); 22843def1eec2baed0b8845ec32c871e249dc533a9d9Eric Laurent if (client.getBinder() == cb) 22853def1eec2baed0b8845ec32c871e249dc533a9d9Eric Laurent return client; 22863def1eec2baed0b8845ec32c871e249dc533a9d9Eric Laurent } 2287854938a72d968c1bc0de4e2b0ea87777cfebc045Eric Laurent if (create) { 2288854938a72d968c1bc0de4e2b0ea87777cfebc045Eric Laurent client = new ScoClient(cb); 2289854938a72d968c1bc0de4e2b0ea87777cfebc045Eric Laurent mScoClients.add(client); 2290854938a72d968c1bc0de4e2b0ea87777cfebc045Eric Laurent } 22913def1eec2baed0b8845ec32c871e249dc533a9d9Eric Laurent return client; 22923def1eec2baed0b8845ec32c871e249dc533a9d9Eric Laurent } 22933def1eec2baed0b8845ec32c871e249dc533a9d9Eric Laurent } 22943def1eec2baed0b8845ec32c871e249dc533a9d9Eric Laurent 2295d7454be47f4111c0478a502353e11dea401378bdEric Laurent public void clearAllScoClients(int exceptPid, boolean stopSco) { 22963def1eec2baed0b8845ec32c871e249dc533a9d9Eric Laurent synchronized(mScoClients) { 2297854938a72d968c1bc0de4e2b0ea87777cfebc045Eric Laurent ScoClient savedClient = null; 22983def1eec2baed0b8845ec32c871e249dc533a9d9Eric Laurent int size = mScoClients.size(); 22993def1eec2baed0b8845ec32c871e249dc533a9d9Eric Laurent for (int i = 0; i < size; i++) { 2300854938a72d968c1bc0de4e2b0ea87777cfebc045Eric Laurent ScoClient cl = mScoClients.get(i); 2301d7454be47f4111c0478a502353e11dea401378bdEric Laurent if (cl.getPid() != exceptPid) { 2302854938a72d968c1bc0de4e2b0ea87777cfebc045Eric Laurent cl.clearCount(stopSco); 2303854938a72d968c1bc0de4e2b0ea87777cfebc045Eric Laurent } else { 2304854938a72d968c1bc0de4e2b0ea87777cfebc045Eric Laurent savedClient = cl; 2305854938a72d968c1bc0de4e2b0ea87777cfebc045Eric Laurent } 2306854938a72d968c1bc0de4e2b0ea87777cfebc045Eric Laurent } 2307854938a72d968c1bc0de4e2b0ea87777cfebc045Eric Laurent mScoClients.clear(); 2308854938a72d968c1bc0de4e2b0ea87777cfebc045Eric Laurent if (savedClient != null) { 2309854938a72d968c1bc0de4e2b0ea87777cfebc045Eric Laurent mScoClients.add(savedClient); 23103def1eec2baed0b8845ec32c871e249dc533a9d9Eric Laurent } 23113def1eec2baed0b8845ec32c871e249dc533a9d9Eric Laurent } 23123def1eec2baed0b8845ec32c871e249dc533a9d9Eric Laurent } 23133def1eec2baed0b8845ec32c871e249dc533a9d9Eric Laurent 2314dc03c61fe3cd8d0805480e48a974986439977a60Eric Laurent private boolean getBluetoothHeadset() { 2315dc03c61fe3cd8d0805480e48a974986439977a60Eric Laurent boolean result = false; 2316dc03c61fe3cd8d0805480e48a974986439977a60Eric Laurent BluetoothAdapter adapter = BluetoothAdapter.getDefaultAdapter(); 2317dc03c61fe3cd8d0805480e48a974986439977a60Eric Laurent if (adapter != null) { 2318dc03c61fe3cd8d0805480e48a974986439977a60Eric Laurent result = adapter.getProfileProxy(mContext, mBluetoothProfileServiceListener, 2319dc03c61fe3cd8d0805480e48a974986439977a60Eric Laurent BluetoothProfile.HEADSET); 2320dc03c61fe3cd8d0805480e48a974986439977a60Eric Laurent } 2321dc03c61fe3cd8d0805480e48a974986439977a60Eric Laurent // If we could not get a bluetooth headset proxy, send a failure message 2322dc03c61fe3cd8d0805480e48a974986439977a60Eric Laurent // without delay to reset the SCO audio state and clear SCO clients. 2323dc03c61fe3cd8d0805480e48a974986439977a60Eric Laurent // If we could get a proxy, send a delayed failure message that will reset our state 2324dc03c61fe3cd8d0805480e48a974986439977a60Eric Laurent // in case we don't receive onServiceConnected(). 2325afbb047c3945e9c2b7e9bc6b25098d5fb80bba4eEric Laurent sendMsg(mAudioHandler, MSG_BT_HEADSET_CNCT_FAILED, 2326dc03c61fe3cd8d0805480e48a974986439977a60Eric Laurent SENDMSG_REPLACE, 0, 0, null, result ? BT_HEADSET_CNCT_TIMEOUT_MS : 0); 2327dc03c61fe3cd8d0805480e48a974986439977a60Eric Laurent return result; 2328dc03c61fe3cd8d0805480e48a974986439977a60Eric Laurent } 2329dc03c61fe3cd8d0805480e48a974986439977a60Eric Laurent 2330d7454be47f4111c0478a502353e11dea401378bdEric Laurent private void disconnectBluetoothSco(int exceptPid) { 2331dc03c61fe3cd8d0805480e48a974986439977a60Eric Laurent synchronized(mScoClients) { 2332dc03c61fe3cd8d0805480e48a974986439977a60Eric Laurent checkScoAudioState(); 2333dc03c61fe3cd8d0805480e48a974986439977a60Eric Laurent if (mScoAudioState == SCO_STATE_ACTIVE_EXTERNAL || 2334dc03c61fe3cd8d0805480e48a974986439977a60Eric Laurent mScoAudioState == SCO_STATE_DEACTIVATE_EXT_REQ) { 2335dc03c61fe3cd8d0805480e48a974986439977a60Eric Laurent if (mBluetoothHeadsetDevice != null) { 2336dc03c61fe3cd8d0805480e48a974986439977a60Eric Laurent if (mBluetoothHeadset != null) { 2337dc03c61fe3cd8d0805480e48a974986439977a60Eric Laurent if (!mBluetoothHeadset.stopVoiceRecognition( 2338b06ac839dd2d0437fc8314f6deb7233af5af521eEric Laurent mBluetoothHeadsetDevice)) { 2339afbb047c3945e9c2b7e9bc6b25098d5fb80bba4eEric Laurent sendMsg(mAudioHandler, MSG_BT_HEADSET_CNCT_FAILED, 2340dc03c61fe3cd8d0805480e48a974986439977a60Eric Laurent SENDMSG_REPLACE, 0, 0, null, 0); 2341dc03c61fe3cd8d0805480e48a974986439977a60Eric Laurent } 2342dc03c61fe3cd8d0805480e48a974986439977a60Eric Laurent } else if (mScoAudioState == SCO_STATE_ACTIVE_EXTERNAL && 2343dc03c61fe3cd8d0805480e48a974986439977a60Eric Laurent getBluetoothHeadset()) { 2344dc03c61fe3cd8d0805480e48a974986439977a60Eric Laurent mScoAudioState = SCO_STATE_DEACTIVATE_EXT_REQ; 2345dc03c61fe3cd8d0805480e48a974986439977a60Eric Laurent } 2346dc03c61fe3cd8d0805480e48a974986439977a60Eric Laurent } 2347dc03c61fe3cd8d0805480e48a974986439977a60Eric Laurent } else { 2348d7454be47f4111c0478a502353e11dea401378bdEric Laurent clearAllScoClients(exceptPid, true); 2349dc03c61fe3cd8d0805480e48a974986439977a60Eric Laurent } 2350dc03c61fe3cd8d0805480e48a974986439977a60Eric Laurent } 2351dc03c61fe3cd8d0805480e48a974986439977a60Eric Laurent } 2352dc03c61fe3cd8d0805480e48a974986439977a60Eric Laurent 2353dc03c61fe3cd8d0805480e48a974986439977a60Eric Laurent private void resetBluetoothSco() { 2354dc03c61fe3cd8d0805480e48a974986439977a60Eric Laurent synchronized(mScoClients) { 2355d7454be47f4111c0478a502353e11dea401378bdEric Laurent clearAllScoClients(0, false); 2356dc03c61fe3cd8d0805480e48a974986439977a60Eric Laurent mScoAudioState = SCO_STATE_INACTIVE; 2357dc03c61fe3cd8d0805480e48a974986439977a60Eric Laurent broadcastScoConnectionState(AudioManager.SCO_AUDIO_STATE_DISCONNECTED); 2358dc03c61fe3cd8d0805480e48a974986439977a60Eric Laurent } 2359dc03c61fe3cd8d0805480e48a974986439977a60Eric Laurent } 2360dc03c61fe3cd8d0805480e48a974986439977a60Eric Laurent 2361dc03c61fe3cd8d0805480e48a974986439977a60Eric Laurent private void broadcastScoConnectionState(int state) { 23622a57ca931fefe817b6110101289721acaacfc808Eric Laurent sendMsg(mAudioHandler, MSG_BROADCAST_BT_CONNECTION_STATE, 23632a57ca931fefe817b6110101289721acaacfc808Eric Laurent SENDMSG_QUEUE, state, 0, null, 0); 23642a57ca931fefe817b6110101289721acaacfc808Eric Laurent } 23652a57ca931fefe817b6110101289721acaacfc808Eric Laurent 23662a57ca931fefe817b6110101289721acaacfc808Eric Laurent private void onBroadcastScoConnectionState(int state) { 2367dc03c61fe3cd8d0805480e48a974986439977a60Eric Laurent if (state != mScoConnectionState) { 2368dc03c61fe3cd8d0805480e48a974986439977a60Eric Laurent Intent newIntent = new Intent(AudioManager.ACTION_SCO_AUDIO_STATE_UPDATED); 2369dc03c61fe3cd8d0805480e48a974986439977a60Eric Laurent newIntent.putExtra(AudioManager.EXTRA_SCO_AUDIO_STATE, state); 2370dc03c61fe3cd8d0805480e48a974986439977a60Eric Laurent newIntent.putExtra(AudioManager.EXTRA_SCO_AUDIO_PREVIOUS_STATE, 2371dc03c61fe3cd8d0805480e48a974986439977a60Eric Laurent mScoConnectionState); 23725ac72a29593ab9a20337a2225df52bdf4754be02Dianne Hackborn sendStickyBroadcastToAll(newIntent); 2373dc03c61fe3cd8d0805480e48a974986439977a60Eric Laurent mScoConnectionState = state; 2374dc03c61fe3cd8d0805480e48a974986439977a60Eric Laurent } 2375dc03c61fe3cd8d0805480e48a974986439977a60Eric Laurent } 2376dc03c61fe3cd8d0805480e48a974986439977a60Eric Laurent 237782aa7f017daaaeb96c13e6e3491d5037ab471085Jaikumar Ganesh private BluetoothProfile.ServiceListener mBluetoothProfileServiceListener = 237882aa7f017daaaeb96c13e6e3491d5037ab471085Jaikumar Ganesh new BluetoothProfile.ServiceListener() { 237982aa7f017daaaeb96c13e6e3491d5037ab471085Jaikumar Ganesh public void onServiceConnected(int profile, BluetoothProfile proxy) { 23806bc7f2cd30b6bd90806942b0722e22daa2108493Eric Laurent BluetoothDevice btDevice; 23816bc7f2cd30b6bd90806942b0722e22daa2108493Eric Laurent List<BluetoothDevice> deviceList; 23826bc7f2cd30b6bd90806942b0722e22daa2108493Eric Laurent switch(profile) { 23836bc7f2cd30b6bd90806942b0722e22daa2108493Eric Laurent case BluetoothProfile.A2DP: 23845a0cf7a27f3953a1266af48543ccd9024f4cd89fJohn Du synchronized (mA2dpAvrcpLock) { 23855a0cf7a27f3953a1266af48543ccd9024f4cd89fJohn Du mA2dp = (BluetoothA2dp) proxy; 23865a0cf7a27f3953a1266af48543ccd9024f4cd89fJohn Du deviceList = mA2dp.getConnectedDevices(); 23875a0cf7a27f3953a1266af48543ccd9024f4cd89fJohn Du if (deviceList.size() > 0) { 23885a0cf7a27f3953a1266af48543ccd9024f4cd89fJohn Du btDevice = deviceList.get(0); 23895a0cf7a27f3953a1266af48543ccd9024f4cd89fJohn Du synchronized (mConnectedDevices) { 23905a0cf7a27f3953a1266af48543ccd9024f4cd89fJohn Du int state = mA2dp.getConnectionState(btDevice); 23915a0cf7a27f3953a1266af48543ccd9024f4cd89fJohn Du int delay = checkSendBecomingNoisyIntent( 23920a40ec2192e4836b2fcb6ba51a7688aa6bd4ee98Mike Lockwood AudioSystem.DEVICE_OUT_BLUETOOTH_A2DP, 23930a40ec2192e4836b2fcb6ba51a7688aa6bd4ee98Mike Lockwood (state == BluetoothA2dp.STATE_CONNECTED) ? 1 : 0); 23945a0cf7a27f3953a1266af48543ccd9024f4cd89fJohn Du queueMsgUnderWakeLock(mAudioHandler, 23950a40ec2192e4836b2fcb6ba51a7688aa6bd4ee98Mike Lockwood MSG_SET_A2DP_SINK_CONNECTION_STATE, 23965a0cf7a27f3953a1266af48543ccd9024f4cd89fJohn Du state, 23975a0cf7a27f3953a1266af48543ccd9024f4cd89fJohn Du 0, 23985a0cf7a27f3953a1266af48543ccd9024f4cd89fJohn Du btDevice, 23995a0cf7a27f3953a1266af48543ccd9024f4cd89fJohn Du delay); 24005a0cf7a27f3953a1266af48543ccd9024f4cd89fJohn Du } 2401b1fbaaccb656ef09a8770c28df15e3e91a452e64Eric Laurent } 24026bc7f2cd30b6bd90806942b0722e22daa2108493Eric Laurent } 24036bc7f2cd30b6bd90806942b0722e22daa2108493Eric Laurent break; 24046bc7f2cd30b6bd90806942b0722e22daa2108493Eric Laurent 24050a40ec2192e4836b2fcb6ba51a7688aa6bd4ee98Mike Lockwood case BluetoothProfile.A2DP_SINK: 24060a40ec2192e4836b2fcb6ba51a7688aa6bd4ee98Mike Lockwood deviceList = proxy.getConnectedDevices(); 24070a40ec2192e4836b2fcb6ba51a7688aa6bd4ee98Mike Lockwood if (deviceList.size() > 0) { 24080a40ec2192e4836b2fcb6ba51a7688aa6bd4ee98Mike Lockwood btDevice = deviceList.get(0); 24090a40ec2192e4836b2fcb6ba51a7688aa6bd4ee98Mike Lockwood synchronized (mConnectedDevices) { 24100a40ec2192e4836b2fcb6ba51a7688aa6bd4ee98Mike Lockwood int state = proxy.getConnectionState(btDevice); 24110a40ec2192e4836b2fcb6ba51a7688aa6bd4ee98Mike Lockwood queueMsgUnderWakeLock(mAudioHandler, 24120a40ec2192e4836b2fcb6ba51a7688aa6bd4ee98Mike Lockwood MSG_SET_A2DP_SRC_CONNECTION_STATE, 24130a40ec2192e4836b2fcb6ba51a7688aa6bd4ee98Mike Lockwood state, 24140a40ec2192e4836b2fcb6ba51a7688aa6bd4ee98Mike Lockwood 0, 24150a40ec2192e4836b2fcb6ba51a7688aa6bd4ee98Mike Lockwood btDevice, 24160a40ec2192e4836b2fcb6ba51a7688aa6bd4ee98Mike Lockwood 0 /* delay */); 24170a40ec2192e4836b2fcb6ba51a7688aa6bd4ee98Mike Lockwood } 24180a40ec2192e4836b2fcb6ba51a7688aa6bd4ee98Mike Lockwood } 24190a40ec2192e4836b2fcb6ba51a7688aa6bd4ee98Mike Lockwood break; 24200a40ec2192e4836b2fcb6ba51a7688aa6bd4ee98Mike Lockwood 24216bc7f2cd30b6bd90806942b0722e22daa2108493Eric Laurent case BluetoothProfile.HEADSET: 24226bc7f2cd30b6bd90806942b0722e22daa2108493Eric Laurent synchronized (mScoClients) { 24236bc7f2cd30b6bd90806942b0722e22daa2108493Eric Laurent // Discard timeout message 24246bc7f2cd30b6bd90806942b0722e22daa2108493Eric Laurent mAudioHandler.removeMessages(MSG_BT_HEADSET_CNCT_FAILED); 24256bc7f2cd30b6bd90806942b0722e22daa2108493Eric Laurent mBluetoothHeadset = (BluetoothHeadset) proxy; 24266bc7f2cd30b6bd90806942b0722e22daa2108493Eric Laurent deviceList = mBluetoothHeadset.getConnectedDevices(); 24276bc7f2cd30b6bd90806942b0722e22daa2108493Eric Laurent if (deviceList.size() > 0) { 24286bc7f2cd30b6bd90806942b0722e22daa2108493Eric Laurent mBluetoothHeadsetDevice = deviceList.get(0); 24296bc7f2cd30b6bd90806942b0722e22daa2108493Eric Laurent } else { 24306bc7f2cd30b6bd90806942b0722e22daa2108493Eric Laurent mBluetoothHeadsetDevice = null; 2431dc03c61fe3cd8d0805480e48a974986439977a60Eric Laurent } 24326bc7f2cd30b6bd90806942b0722e22daa2108493Eric Laurent // Refresh SCO audio state 24336bc7f2cd30b6bd90806942b0722e22daa2108493Eric Laurent checkScoAudioState(); 24346bc7f2cd30b6bd90806942b0722e22daa2108493Eric Laurent // Continue pending action if any 24356bc7f2cd30b6bd90806942b0722e22daa2108493Eric Laurent if (mScoAudioState == SCO_STATE_ACTIVATE_REQ || 24366bc7f2cd30b6bd90806942b0722e22daa2108493Eric Laurent mScoAudioState == SCO_STATE_DEACTIVATE_REQ || 24376bc7f2cd30b6bd90806942b0722e22daa2108493Eric Laurent mScoAudioState == SCO_STATE_DEACTIVATE_EXT_REQ) { 24386bc7f2cd30b6bd90806942b0722e22daa2108493Eric Laurent boolean status = false; 24396bc7f2cd30b6bd90806942b0722e22daa2108493Eric Laurent if (mBluetoothHeadsetDevice != null) { 24406bc7f2cd30b6bd90806942b0722e22daa2108493Eric Laurent switch (mScoAudioState) { 24416bc7f2cd30b6bd90806942b0722e22daa2108493Eric Laurent case SCO_STATE_ACTIVATE_REQ: 24426bc7f2cd30b6bd90806942b0722e22daa2108493Eric Laurent mScoAudioState = SCO_STATE_ACTIVE_INTERNAL; 2443c18c9138cee0f0859bcab636a004ce92ca4a9ab5Eric Laurent if (mScoAudioMode == SCO_MODE_RAW) { 2444c18c9138cee0f0859bcab636a004ce92ca4a9ab5Eric Laurent status = mBluetoothHeadset.connectAudio(); 2445c18c9138cee0f0859bcab636a004ce92ca4a9ab5Eric Laurent } else { 2446c18c9138cee0f0859bcab636a004ce92ca4a9ab5Eric Laurent status = mBluetoothHeadset.startScoUsingVirtualVoiceCall( 2447c18c9138cee0f0859bcab636a004ce92ca4a9ab5Eric Laurent mBluetoothHeadsetDevice); 2448c18c9138cee0f0859bcab636a004ce92ca4a9ab5Eric Laurent } 24496bc7f2cd30b6bd90806942b0722e22daa2108493Eric Laurent break; 24506bc7f2cd30b6bd90806942b0722e22daa2108493Eric Laurent case SCO_STATE_DEACTIVATE_REQ: 2451c18c9138cee0f0859bcab636a004ce92ca4a9ab5Eric Laurent if (mScoAudioMode == SCO_MODE_RAW) { 2452c18c9138cee0f0859bcab636a004ce92ca4a9ab5Eric Laurent status = mBluetoothHeadset.disconnectAudio(); 2453c18c9138cee0f0859bcab636a004ce92ca4a9ab5Eric Laurent } else { 2454c18c9138cee0f0859bcab636a004ce92ca4a9ab5Eric Laurent status = mBluetoothHeadset.stopScoUsingVirtualVoiceCall( 2455c18c9138cee0f0859bcab636a004ce92ca4a9ab5Eric Laurent mBluetoothHeadsetDevice); 2456c18c9138cee0f0859bcab636a004ce92ca4a9ab5Eric Laurent } 24576bc7f2cd30b6bd90806942b0722e22daa2108493Eric Laurent break; 24586bc7f2cd30b6bd90806942b0722e22daa2108493Eric Laurent case SCO_STATE_DEACTIVATE_EXT_REQ: 24596bc7f2cd30b6bd90806942b0722e22daa2108493Eric Laurent status = mBluetoothHeadset.stopVoiceRecognition( 24606bc7f2cd30b6bd90806942b0722e22daa2108493Eric Laurent mBluetoothHeadsetDevice); 24616bc7f2cd30b6bd90806942b0722e22daa2108493Eric Laurent } 24626bc7f2cd30b6bd90806942b0722e22daa2108493Eric Laurent } 24636bc7f2cd30b6bd90806942b0722e22daa2108493Eric Laurent if (!status) { 2464afbb047c3945e9c2b7e9bc6b25098d5fb80bba4eEric Laurent sendMsg(mAudioHandler, MSG_BT_HEADSET_CNCT_FAILED, 24656bc7f2cd30b6bd90806942b0722e22daa2108493Eric Laurent SENDMSG_REPLACE, 0, 0, null, 0); 24666bc7f2cd30b6bd90806942b0722e22daa2108493Eric Laurent } 2467dc03c61fe3cd8d0805480e48a974986439977a60Eric Laurent } 2468dc03c61fe3cd8d0805480e48a974986439977a60Eric Laurent } 24696bc7f2cd30b6bd90806942b0722e22daa2108493Eric Laurent break; 24706bc7f2cd30b6bd90806942b0722e22daa2108493Eric Laurent 24716bc7f2cd30b6bd90806942b0722e22daa2108493Eric Laurent default: 24726bc7f2cd30b6bd90806942b0722e22daa2108493Eric Laurent break; 24733def1eec2baed0b8845ec32c871e249dc533a9d9Eric Laurent } 24743def1eec2baed0b8845ec32c871e249dc533a9d9Eric Laurent } 247582aa7f017daaaeb96c13e6e3491d5037ab471085Jaikumar Ganesh public void onServiceDisconnected(int profile) { 24766bc7f2cd30b6bd90806942b0722e22daa2108493Eric Laurent switch(profile) { 24776bc7f2cd30b6bd90806942b0722e22daa2108493Eric Laurent case BluetoothProfile.A2DP: 24785a0cf7a27f3953a1266af48543ccd9024f4cd89fJohn Du synchronized (mA2dpAvrcpLock) { 24795a0cf7a27f3953a1266af48543ccd9024f4cd89fJohn Du mA2dp = null; 24805a0cf7a27f3953a1266af48543ccd9024f4cd89fJohn Du synchronized (mConnectedDevices) { 24815a0cf7a27f3953a1266af48543ccd9024f4cd89fJohn Du if (mConnectedDevices.containsKey(AudioSystem.DEVICE_OUT_BLUETOOTH_A2DP)) { 24825a0cf7a27f3953a1266af48543ccd9024f4cd89fJohn Du makeA2dpDeviceUnavailableNow( 24835a0cf7a27f3953a1266af48543ccd9024f4cd89fJohn Du mConnectedDevices.get(AudioSystem.DEVICE_OUT_BLUETOOTH_A2DP)); 24845a0cf7a27f3953a1266af48543ccd9024f4cd89fJohn Du } 24856bc7f2cd30b6bd90806942b0722e22daa2108493Eric Laurent } 24866bc7f2cd30b6bd90806942b0722e22daa2108493Eric Laurent } 24876bc7f2cd30b6bd90806942b0722e22daa2108493Eric Laurent break; 24886bc7f2cd30b6bd90806942b0722e22daa2108493Eric Laurent 24890a40ec2192e4836b2fcb6ba51a7688aa6bd4ee98Mike Lockwood case BluetoothProfile.A2DP_SINK: 24900a40ec2192e4836b2fcb6ba51a7688aa6bd4ee98Mike Lockwood synchronized (mConnectedDevices) { 24910a40ec2192e4836b2fcb6ba51a7688aa6bd4ee98Mike Lockwood if (mConnectedDevices.containsKey(AudioSystem.DEVICE_IN_BLUETOOTH_A2DP)) { 24920a40ec2192e4836b2fcb6ba51a7688aa6bd4ee98Mike Lockwood makeA2dpSrcUnavailable( 24930a40ec2192e4836b2fcb6ba51a7688aa6bd4ee98Mike Lockwood mConnectedDevices.get(AudioSystem.DEVICE_IN_BLUETOOTH_A2DP)); 24940a40ec2192e4836b2fcb6ba51a7688aa6bd4ee98Mike Lockwood } 24950a40ec2192e4836b2fcb6ba51a7688aa6bd4ee98Mike Lockwood } 24960a40ec2192e4836b2fcb6ba51a7688aa6bd4ee98Mike Lockwood break; 24970a40ec2192e4836b2fcb6ba51a7688aa6bd4ee98Mike Lockwood 24986bc7f2cd30b6bd90806942b0722e22daa2108493Eric Laurent case BluetoothProfile.HEADSET: 24996bc7f2cd30b6bd90806942b0722e22daa2108493Eric Laurent synchronized (mScoClients) { 25006bc7f2cd30b6bd90806942b0722e22daa2108493Eric Laurent mBluetoothHeadset = null; 25016bc7f2cd30b6bd90806942b0722e22daa2108493Eric Laurent } 25026bc7f2cd30b6bd90806942b0722e22daa2108493Eric Laurent break; 25036bc7f2cd30b6bd90806942b0722e22daa2108493Eric Laurent 25046bc7f2cd30b6bd90806942b0722e22daa2108493Eric Laurent default: 25056bc7f2cd30b6bd90806942b0722e22daa2108493Eric Laurent break; 25063def1eec2baed0b8845ec32c871e249dc533a9d9Eric Laurent } 25073def1eec2baed0b8845ec32c871e249dc533a9d9Eric Laurent } 25083def1eec2baed0b8845ec32c871e249dc533a9d9Eric Laurent }; 2509d5176cfe6eae954e9cef1e2ec17859a5089e1330Jean-Michel Trivi 2510c34dcc1e1ebf152bb400abbb8bc25f7dc0c3ba97Eric Laurent private void onCheckMusicActive() { 2511d640bd325c3be9a350058c835b880a7e0b40dc60Eric Laurent synchronized (mSafeMediaVolumeState) { 2512d640bd325c3be9a350058c835b880a7e0b40dc60Eric Laurent if (mSafeMediaVolumeState == SAFE_MEDIA_VOLUME_INACTIVE) { 2513c34dcc1e1ebf152bb400abbb8bc25f7dc0c3ba97Eric Laurent int device = getDeviceForStream(AudioSystem.STREAM_MUSIC); 2514c34dcc1e1ebf152bb400abbb8bc25f7dc0c3ba97Eric Laurent 2515c34dcc1e1ebf152bb400abbb8bc25f7dc0c3ba97Eric Laurent if ((device & mSafeMediaVolumeDevices) != 0) { 2516c34dcc1e1ebf152bb400abbb8bc25f7dc0c3ba97Eric Laurent sendMsg(mAudioHandler, 2517c34dcc1e1ebf152bb400abbb8bc25f7dc0c3ba97Eric Laurent MSG_CHECK_MUSIC_ACTIVE, 2518c34dcc1e1ebf152bb400abbb8bc25f7dc0c3ba97Eric Laurent SENDMSG_REPLACE, 2519f1a457d06c53a901ea08d2d3fb6e766bc06c4d4fEric Laurent 0, 2520c34dcc1e1ebf152bb400abbb8bc25f7dc0c3ba97Eric Laurent 0, 2521c34dcc1e1ebf152bb400abbb8bc25f7dc0c3ba97Eric Laurent null, 2522c34dcc1e1ebf152bb400abbb8bc25f7dc0c3ba97Eric Laurent MUSIC_ACTIVE_POLL_PERIOD_MS); 252342b041ed4f184e3af7f788eb07307f556a2a6616Eric Laurent int index = mStreamStates[AudioSystem.STREAM_MUSIC].getIndex(device); 2524f1a457d06c53a901ea08d2d3fb6e766bc06c4d4fEric Laurent if (AudioSystem.isStreamActive(AudioSystem.STREAM_MUSIC, 0) && 2525f1a457d06c53a901ea08d2d3fb6e766bc06c4d4fEric Laurent (index > mSafeMediaVolumeIndex)) { 2526c34dcc1e1ebf152bb400abbb8bc25f7dc0c3ba97Eric Laurent // Approximate cumulative active music time 2527c34dcc1e1ebf152bb400abbb8bc25f7dc0c3ba97Eric Laurent mMusicActiveMs += MUSIC_ACTIVE_POLL_PERIOD_MS; 2528c34dcc1e1ebf152bb400abbb8bc25f7dc0c3ba97Eric Laurent if (mMusicActiveMs > UNSAFE_VOLUME_MUSIC_ACTIVE_MS_MAX) { 2529c34dcc1e1ebf152bb400abbb8bc25f7dc0c3ba97Eric Laurent setSafeMediaVolumeEnabled(true); 2530c34dcc1e1ebf152bb400abbb8bc25f7dc0c3ba97Eric Laurent mMusicActiveMs = 0; 2531c34dcc1e1ebf152bb400abbb8bc25f7dc0c3ba97Eric Laurent } 2532c34dcc1e1ebf152bb400abbb8bc25f7dc0c3ba97Eric Laurent } 2533c34dcc1e1ebf152bb400abbb8bc25f7dc0c3ba97Eric Laurent } 2534c34dcc1e1ebf152bb400abbb8bc25f7dc0c3ba97Eric Laurent } 2535c34dcc1e1ebf152bb400abbb8bc25f7dc0c3ba97Eric Laurent } 2536c34dcc1e1ebf152bb400abbb8bc25f7dc0c3ba97Eric Laurent } 2537c34dcc1e1ebf152bb400abbb8bc25f7dc0c3ba97Eric Laurent 2538d640bd325c3be9a350058c835b880a7e0b40dc60Eric Laurent private void onConfigureSafeVolume(boolean force) { 2539d640bd325c3be9a350058c835b880a7e0b40dc60Eric Laurent synchronized (mSafeMediaVolumeState) { 2540d640bd325c3be9a350058c835b880a7e0b40dc60Eric Laurent int mcc = mContext.getResources().getConfiguration().mcc; 2541d640bd325c3be9a350058c835b880a7e0b40dc60Eric Laurent if ((mMcc != mcc) || ((mMcc == 0) && force)) { 2542d640bd325c3be9a350058c835b880a7e0b40dc60Eric Laurent mSafeMediaVolumeIndex = mContext.getResources().getInteger( 2543d640bd325c3be9a350058c835b880a7e0b40dc60Eric Laurent com.android.internal.R.integer.config_safe_media_volume_index) * 10; 2544d640bd325c3be9a350058c835b880a7e0b40dc60Eric Laurent boolean safeMediaVolumeEnabled = mContext.getResources().getBoolean( 2545d640bd325c3be9a350058c835b880a7e0b40dc60Eric Laurent com.android.internal.R.bool.config_safe_media_volume_enabled); 254605274f348e12983eb8613cc6eb9ae561e8197e28Eric Laurent 254705274f348e12983eb8613cc6eb9ae561e8197e28Eric Laurent // The persisted state is either "disabled" or "active": this is the state applied 254805274f348e12983eb8613cc6eb9ae561e8197e28Eric Laurent // next time we boot and cannot be "inactive" 254905274f348e12983eb8613cc6eb9ae561e8197e28Eric Laurent int persistedState; 2550d640bd325c3be9a350058c835b880a7e0b40dc60Eric Laurent if (safeMediaVolumeEnabled) { 255105274f348e12983eb8613cc6eb9ae561e8197e28Eric Laurent persistedState = SAFE_MEDIA_VOLUME_ACTIVE; 255205274f348e12983eb8613cc6eb9ae561e8197e28Eric Laurent // The state can already be "inactive" here if the user has forced it before 255305274f348e12983eb8613cc6eb9ae561e8197e28Eric Laurent // the 30 seconds timeout for forced configuration. In this case we don't reset 255405274f348e12983eb8613cc6eb9ae561e8197e28Eric Laurent // it to "active". 255505274f348e12983eb8613cc6eb9ae561e8197e28Eric Laurent if (mSafeMediaVolumeState != SAFE_MEDIA_VOLUME_INACTIVE) { 255605274f348e12983eb8613cc6eb9ae561e8197e28Eric Laurent mSafeMediaVolumeState = SAFE_MEDIA_VOLUME_ACTIVE; 255705274f348e12983eb8613cc6eb9ae561e8197e28Eric Laurent enforceSafeMediaVolume(); 255805274f348e12983eb8613cc6eb9ae561e8197e28Eric Laurent } 2559d640bd325c3be9a350058c835b880a7e0b40dc60Eric Laurent } else { 256005274f348e12983eb8613cc6eb9ae561e8197e28Eric Laurent persistedState = SAFE_MEDIA_VOLUME_DISABLED; 2561d640bd325c3be9a350058c835b880a7e0b40dc60Eric Laurent mSafeMediaVolumeState = SAFE_MEDIA_VOLUME_DISABLED; 2562d640bd325c3be9a350058c835b880a7e0b40dc60Eric Laurent } 2563d640bd325c3be9a350058c835b880a7e0b40dc60Eric Laurent mMcc = mcc; 256405274f348e12983eb8613cc6eb9ae561e8197e28Eric Laurent sendMsg(mAudioHandler, 256505274f348e12983eb8613cc6eb9ae561e8197e28Eric Laurent MSG_PERSIST_SAFE_VOLUME_STATE, 256605274f348e12983eb8613cc6eb9ae561e8197e28Eric Laurent SENDMSG_QUEUE, 256705274f348e12983eb8613cc6eb9ae561e8197e28Eric Laurent persistedState, 256805274f348e12983eb8613cc6eb9ae561e8197e28Eric Laurent 0, 256905274f348e12983eb8613cc6eb9ae561e8197e28Eric Laurent null, 257005274f348e12983eb8613cc6eb9ae561e8197e28Eric Laurent 0); 2571d640bd325c3be9a350058c835b880a7e0b40dc60Eric Laurent } 2572d640bd325c3be9a350058c835b880a7e0b40dc60Eric Laurent } 2573d640bd325c3be9a350058c835b880a7e0b40dc60Eric Laurent } 2574d640bd325c3be9a350058c835b880a7e0b40dc60Eric Laurent 25759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /////////////////////////////////////////////////////////////////////////// 25769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Internal methods 25779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /////////////////////////////////////////////////////////////////////////// 25789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 25799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 25809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Checks if the adjustment should change ringer mode instead of just 25819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * adjusting volume. If so, this will set the proper ringer mode and volume 25829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * indices on the stream states. 25839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 2584a11b4affcad3d255aa723a89b768ea222506f2e8John Spurlock private int checkForRingerModeChange(int oldIndex, int direction, int step) { 2585a11b4affcad3d255aa723a89b768ea222506f2e8John Spurlock int result = FLAG_ADJUST_VOLUME; 2586ba195ebc76f23b6679443724ab58c9dc9f2df884Glenn Kasten int ringerMode = getRingerMode(); 2587bffc3d1bd33eb2d8e00a9f8b6261d815db503311Eric Laurent 2588bffc3d1bd33eb2d8e00a9f8b6261d815db503311Eric Laurent switch (ringerMode) { 2589bffc3d1bd33eb2d8e00a9f8b6261d815db503311Eric Laurent case RINGER_MODE_NORMAL: 2590bffc3d1bd33eb2d8e00a9f8b6261d815db503311Eric Laurent if (direction == AudioManager.ADJUST_LOWER) { 2591bffc3d1bd33eb2d8e00a9f8b6261d815db503311Eric Laurent if (mHasVibrator) { 2592244820185269991186d07068b92985624cede4a5Eric Laurent // "step" is the delta in internal index units corresponding to a 2593244820185269991186d07068b92985624cede4a5Eric Laurent // change of 1 in UI index units. 2594244820185269991186d07068b92985624cede4a5Eric Laurent // Because of rounding when rescaling from one stream index range to its alias 2595244820185269991186d07068b92985624cede4a5Eric Laurent // index range, we cannot simply test oldIndex == step: 2596244820185269991186d07068b92985624cede4a5Eric Laurent // (step <= oldIndex < 2 * step) is equivalent to: (old UI index == 1) 2597244820185269991186d07068b92985624cede4a5Eric Laurent if (step <= oldIndex && oldIndex < 2 * step) { 2598bffc3d1bd33eb2d8e00a9f8b6261d815db503311Eric Laurent ringerMode = RINGER_MODE_VIBRATE; 2599bffc3d1bd33eb2d8e00a9f8b6261d815db503311Eric Laurent } 2600bffc3d1bd33eb2d8e00a9f8b6261d815db503311Eric Laurent } else { 2601244820185269991186d07068b92985624cede4a5Eric Laurent // (oldIndex < step) is equivalent to (old UI index == 0) 26028600534df66c2ff5846ed230b50c56229322d48aJohn Spurlock if ((oldIndex < step) 26038600534df66c2ff5846ed230b50c56229322d48aJohn Spurlock && VOLUME_SETS_RINGER_MODE_SILENT 26048600534df66c2ff5846ed230b50c56229322d48aJohn Spurlock && mPrevVolDirection != AudioManager.ADJUST_LOWER) { 2605bffc3d1bd33eb2d8e00a9f8b6261d815db503311Eric Laurent ringerMode = RINGER_MODE_SILENT; 2606bffc3d1bd33eb2d8e00a9f8b6261d815db503311Eric Laurent } 26073d4c06f90726a85e89dab13c41ddc15b9c912a3fEric Laurent } 26086329bf7b1e2217c6c9477bd57349a1edade18417Daniel Sandler } 2609bffc3d1bd33eb2d8e00a9f8b6261d815db503311Eric Laurent break; 2610bffc3d1bd33eb2d8e00a9f8b6261d815db503311Eric Laurent case RINGER_MODE_VIBRATE: 2611bffc3d1bd33eb2d8e00a9f8b6261d815db503311Eric Laurent if (!mHasVibrator) { 2612bffc3d1bd33eb2d8e00a9f8b6261d815db503311Eric Laurent Log.e(TAG, "checkForRingerModeChange() current ringer mode is vibrate" + 2613bffc3d1bd33eb2d8e00a9f8b6261d815db503311Eric Laurent "but no vibrator is present"); 2614bffc3d1bd33eb2d8e00a9f8b6261d815db503311Eric Laurent break; 2615bffc3d1bd33eb2d8e00a9f8b6261d815db503311Eric Laurent } 2616c696a53d1fe4d61373c5dc64dd057d322da90c8fAmith Yamasani if ((direction == AudioManager.ADJUST_LOWER)) { 26178600534df66c2ff5846ed230b50c56229322d48aJohn Spurlock if (VOLUME_SETS_RINGER_MODE_SILENT 26188600534df66c2ff5846ed230b50c56229322d48aJohn Spurlock && mPrevVolDirection != AudioManager.ADJUST_LOWER) { 2619bffc3d1bd33eb2d8e00a9f8b6261d815db503311Eric Laurent ringerMode = RINGER_MODE_SILENT; 2620c696a53d1fe4d61373c5dc64dd057d322da90c8fAmith Yamasani } 2621c696a53d1fe4d61373c5dc64dd057d322da90c8fAmith Yamasani } else if (direction == AudioManager.ADJUST_RAISE) { 2622bffc3d1bd33eb2d8e00a9f8b6261d815db503311Eric Laurent ringerMode = RINGER_MODE_NORMAL; 2623c696a53d1fe4d61373c5dc64dd057d322da90c8fAmith Yamasani } 2624a11b4affcad3d255aa723a89b768ea222506f2e8John Spurlock result &= ~FLAG_ADJUST_VOLUME; 2625bffc3d1bd33eb2d8e00a9f8b6261d815db503311Eric Laurent break; 2626bffc3d1bd33eb2d8e00a9f8b6261d815db503311Eric Laurent case RINGER_MODE_SILENT: 26279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (direction == AudioManager.ADJUST_RAISE) { 2628a11b4affcad3d255aa723a89b768ea222506f2e8John Spurlock if (PREVENT_VOLUME_ADJUSTMENT_IF_SILENT) { 2629a11b4affcad3d255aa723a89b768ea222506f2e8John Spurlock result |= AudioManager.FLAG_SHOW_SILENT_HINT; 2630bffc3d1bd33eb2d8e00a9f8b6261d815db503311Eric Laurent } else { 2631a11b4affcad3d255aa723a89b768ea222506f2e8John Spurlock if (mHasVibrator) { 2632a11b4affcad3d255aa723a89b768ea222506f2e8John Spurlock ringerMode = RINGER_MODE_VIBRATE; 2633a11b4affcad3d255aa723a89b768ea222506f2e8John Spurlock } else { 2634a11b4affcad3d255aa723a89b768ea222506f2e8John Spurlock ringerMode = RINGER_MODE_NORMAL; 2635a11b4affcad3d255aa723a89b768ea222506f2e8John Spurlock } 2636bffc3d1bd33eb2d8e00a9f8b6261d815db503311Eric Laurent } 26379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2638a11b4affcad3d255aa723a89b768ea222506f2e8John Spurlock result &= ~FLAG_ADJUST_VOLUME; 2639bffc3d1bd33eb2d8e00a9f8b6261d815db503311Eric Laurent break; 2640bffc3d1bd33eb2d8e00a9f8b6261d815db503311Eric Laurent default: 2641bffc3d1bd33eb2d8e00a9f8b6261d815db503311Eric Laurent Log.e(TAG, "checkForRingerModeChange() wrong ringer mode: "+ringerMode); 2642bffc3d1bd33eb2d8e00a9f8b6261d815db503311Eric Laurent break; 26439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 26449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2645bffc3d1bd33eb2d8e00a9f8b6261d815db503311Eric Laurent setRingerMode(ringerMode); 26469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 264725101b0b9a84571ead15b26e9f4cd9c4298d7823Eric Laurent mPrevVolDirection = direction; 264825101b0b9a84571ead15b26e9f4cd9c4298d7823Eric Laurent 2649a11b4affcad3d255aa723a89b768ea222506f2e8John Spurlock return result; 26509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 26519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 26523346a802087f621c6441bc512dfcc17b07143fc6John Spurlock @Override 26539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public boolean isStreamAffectedByRingerMode(int streamType) { 26549bcf401d13d47416043a704430388abd59aef7cdEric Laurent return (mRingerModeAffectedStreams & (1 << streamType)) != 0; 26559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 26569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 26575b4e654d0c7de8e4d58d73e73b0d5220f19b68f7Eric Laurent private boolean isStreamMutedByRingerMode(int streamType) { 26585b4e654d0c7de8e4d58d73e73b0d5220f19b68f7Eric Laurent return (mRingerModeMutedStreams & (1 << streamType)) != 0; 26595b4e654d0c7de8e4d58d73e73b0d5220f19b68f7Eric Laurent } 26605b4e654d0c7de8e4d58d73e73b0d5220f19b68f7Eric Laurent 266124e0d9b6c40712a297e4c287435a3b0fdd30e9daEric Laurent boolean updateRingerModeAffectedStreams() { 266224e0d9b6c40712a297e4c287435a3b0fdd30e9daEric Laurent int ringerModeAffectedStreams; 266324e0d9b6c40712a297e4c287435a3b0fdd30e9daEric Laurent // make sure settings for ringer mode are consistent with device type: non voice capable 266424e0d9b6c40712a297e4c287435a3b0fdd30e9daEric Laurent // devices (tablets) include media stream in silent mode whereas phones don't. 266524e0d9b6c40712a297e4c287435a3b0fdd30e9daEric Laurent ringerModeAffectedStreams = Settings.System.getIntForUser(mContentResolver, 266624e0d9b6c40712a297e4c287435a3b0fdd30e9daEric Laurent Settings.System.MODE_RINGER_STREAMS_AFFECTED, 266724e0d9b6c40712a297e4c287435a3b0fdd30e9daEric Laurent ((1 << AudioSystem.STREAM_RING)|(1 << AudioSystem.STREAM_NOTIFICATION)| 266824e0d9b6c40712a297e4c287435a3b0fdd30e9daEric Laurent (1 << AudioSystem.STREAM_SYSTEM)|(1 << AudioSystem.STREAM_SYSTEM_ENFORCED)), 266924e0d9b6c40712a297e4c287435a3b0fdd30e9daEric Laurent UserHandle.USER_CURRENT); 267024e0d9b6c40712a297e4c287435a3b0fdd30e9daEric Laurent 267124e0d9b6c40712a297e4c287435a3b0fdd30e9daEric Laurent // ringtone, notification and system streams are always affected by ringer mode 267224e0d9b6c40712a297e4c287435a3b0fdd30e9daEric Laurent ringerModeAffectedStreams |= (1 << AudioSystem.STREAM_RING)| 267324e0d9b6c40712a297e4c287435a3b0fdd30e9daEric Laurent (1 << AudioSystem.STREAM_NOTIFICATION)| 267424e0d9b6c40712a297e4c287435a3b0fdd30e9daEric Laurent (1 << AudioSystem.STREAM_SYSTEM); 267524e0d9b6c40712a297e4c287435a3b0fdd30e9daEric Laurent 267624e0d9b6c40712a297e4c287435a3b0fdd30e9daEric Laurent if (mVoiceCapable) { 267724e0d9b6c40712a297e4c287435a3b0fdd30e9daEric Laurent ringerModeAffectedStreams &= ~(1 << AudioSystem.STREAM_MUSIC); 267824e0d9b6c40712a297e4c287435a3b0fdd30e9daEric Laurent } else { 267924e0d9b6c40712a297e4c287435a3b0fdd30e9daEric Laurent ringerModeAffectedStreams |= (1 << AudioSystem.STREAM_MUSIC); 268024e0d9b6c40712a297e4c287435a3b0fdd30e9daEric Laurent } 268124e0d9b6c40712a297e4c287435a3b0fdd30e9daEric Laurent synchronized (mCameraSoundForced) { 268224e0d9b6c40712a297e4c287435a3b0fdd30e9daEric Laurent if (mCameraSoundForced) { 268324e0d9b6c40712a297e4c287435a3b0fdd30e9daEric Laurent ringerModeAffectedStreams &= ~(1 << AudioSystem.STREAM_SYSTEM_ENFORCED); 268424e0d9b6c40712a297e4c287435a3b0fdd30e9daEric Laurent } else { 268524e0d9b6c40712a297e4c287435a3b0fdd30e9daEric Laurent ringerModeAffectedStreams |= (1 << AudioSystem.STREAM_SYSTEM_ENFORCED); 268624e0d9b6c40712a297e4c287435a3b0fdd30e9daEric Laurent } 268724e0d9b6c40712a297e4c287435a3b0fdd30e9daEric Laurent } 268824e0d9b6c40712a297e4c287435a3b0fdd30e9daEric Laurent if (mStreamVolumeAlias[AudioSystem.STREAM_DTMF] == AudioSystem.STREAM_RING) { 268924e0d9b6c40712a297e4c287435a3b0fdd30e9daEric Laurent ringerModeAffectedStreams |= (1 << AudioSystem.STREAM_DTMF); 269024e0d9b6c40712a297e4c287435a3b0fdd30e9daEric Laurent } else { 269124e0d9b6c40712a297e4c287435a3b0fdd30e9daEric Laurent ringerModeAffectedStreams &= ~(1 << AudioSystem.STREAM_DTMF); 269224e0d9b6c40712a297e4c287435a3b0fdd30e9daEric Laurent } 269324e0d9b6c40712a297e4c287435a3b0fdd30e9daEric Laurent 269424e0d9b6c40712a297e4c287435a3b0fdd30e9daEric Laurent if (ringerModeAffectedStreams != mRingerModeAffectedStreams) { 269524e0d9b6c40712a297e4c287435a3b0fdd30e9daEric Laurent Settings.System.putIntForUser(mContentResolver, 269624e0d9b6c40712a297e4c287435a3b0fdd30e9daEric Laurent Settings.System.MODE_RINGER_STREAMS_AFFECTED, 269724e0d9b6c40712a297e4c287435a3b0fdd30e9daEric Laurent ringerModeAffectedStreams, 269824e0d9b6c40712a297e4c287435a3b0fdd30e9daEric Laurent UserHandle.USER_CURRENT); 269924e0d9b6c40712a297e4c287435a3b0fdd30e9daEric Laurent mRingerModeAffectedStreams = ringerModeAffectedStreams; 270024e0d9b6c40712a297e4c287435a3b0fdd30e9daEric Laurent return true; 270124e0d9b6c40712a297e4c287435a3b0fdd30e9daEric Laurent } 270224e0d9b6c40712a297e4c287435a3b0fdd30e9daEric Laurent return false; 270324e0d9b6c40712a297e4c287435a3b0fdd30e9daEric Laurent } 270424e0d9b6c40712a297e4c287435a3b0fdd30e9daEric Laurent 27059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public boolean isStreamAffectedByMute(int streamType) { 27069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return (mMuteAffectedStreams & (1 << streamType)) != 0; 27079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 27089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 27099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private void ensureValidDirection(int direction) { 27109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (direction < AudioManager.ADJUST_LOWER || direction > AudioManager.ADJUST_RAISE) { 27119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project throw new IllegalArgumentException("Bad direction " + direction); 27129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 27139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 27149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 27156c798970ccb8759d1e613b57111daa8da0ab44c7Lei Zhang private void ensureValidSteps(int steps) { 27166c798970ccb8759d1e613b57111daa8da0ab44c7Lei Zhang if (Math.abs(steps) > MAX_BATCH_VOLUME_ADJUST_STEPS) { 27176c798970ccb8759d1e613b57111daa8da0ab44c7Lei Zhang throw new IllegalArgumentException("Bad volume adjust steps " + steps); 27186c798970ccb8759d1e613b57111daa8da0ab44c7Lei Zhang } 27196c798970ccb8759d1e613b57111daa8da0ab44c7Lei Zhang } 27206c798970ccb8759d1e613b57111daa8da0ab44c7Lei Zhang 27219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private void ensureValidStreamType(int streamType) { 27229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (streamType < 0 || streamType >= mStreamStates.length) { 27239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project throw new IllegalArgumentException("Bad stream type " + streamType); 27249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 27259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 27269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 27276d5176638c2189595cede38fb92c3e7e8700e221Eric Laurent private boolean isInCommunication() { 27286d5176638c2189595cede38fb92c3e7e8700e221Eric Laurent boolean isOffhook = false; 272925101b0b9a84571ead15b26e9f4cd9c4298d7823Eric Laurent 273025101b0b9a84571ead15b26e9f4cd9c4298d7823Eric Laurent if (mVoiceCapable) { 273125101b0b9a84571ead15b26e9f4cd9c4298d7823Eric Laurent try { 273225101b0b9a84571ead15b26e9f4cd9c4298d7823Eric Laurent ITelephony phone = ITelephony.Stub.asInterface(ServiceManager.checkService("phone")); 273325101b0b9a84571ead15b26e9f4cd9c4298d7823Eric Laurent if (phone != null) isOffhook = phone.isOffhook(); 273425101b0b9a84571ead15b26e9f4cd9c4298d7823Eric Laurent } catch (RemoteException e) { 273525101b0b9a84571ead15b26e9f4cd9c4298d7823Eric Laurent Log.w(TAG, "Couldn't connect to phone service", e); 273625101b0b9a84571ead15b26e9f4cd9c4298d7823Eric Laurent } 27376d5176638c2189595cede38fb92c3e7e8700e221Eric Laurent } 27386d5176638c2189595cede38fb92c3e7e8700e221Eric Laurent return (isOffhook || getMode() == AudioManager.MODE_IN_COMMUNICATION); 27396d5176638c2189595cede38fb92c3e7e8700e221Eric Laurent } 274025101b0b9a84571ead15b26e9f4cd9c4298d7823Eric Laurent 2741fca1e603236b8d1681f784e77e3719d1d59c1428Jean-Michel Trivi /** 2742fca1e603236b8d1681f784e77e3719d1d59c1428Jean-Michel Trivi * For code clarity for getActiveStreamType(int) 2743fca1e603236b8d1681f784e77e3719d1d59c1428Jean-Michel Trivi * @param delay_ms max time since last STREAM_MUSIC activity to consider 2744fca1e603236b8d1681f784e77e3719d1d59c1428Jean-Michel Trivi * @return true if STREAM_MUSIC is active in streams handled by AudioFlinger now or 2745fca1e603236b8d1681f784e77e3719d1d59c1428Jean-Michel Trivi * in the last "delay_ms" ms. 2746fca1e603236b8d1681f784e77e3719d1d59c1428Jean-Michel Trivi */ 2747fca1e603236b8d1681f784e77e3719d1d59c1428Jean-Michel Trivi private boolean isAfMusicActiveRecently(int delay_ms) { 2748fca1e603236b8d1681f784e77e3719d1d59c1428Jean-Michel Trivi return AudioSystem.isStreamActive(AudioSystem.STREAM_MUSIC, delay_ms) 2749fca1e603236b8d1681f784e77e3719d1d59c1428Jean-Michel Trivi || AudioSystem.isStreamActiveRemotely(AudioSystem.STREAM_MUSIC, delay_ms); 2750fca1e603236b8d1681f784e77e3719d1d59c1428Jean-Michel Trivi } 2751fca1e603236b8d1681f784e77e3719d1d59c1428Jean-Michel Trivi 27526d5176638c2189595cede38fb92c3e7e8700e221Eric Laurent private int getActiveStreamType(int suggestedStreamType) { 27536d5176638c2189595cede38fb92c3e7e8700e221Eric Laurent if (mVoiceCapable) { 27546d5176638c2189595cede38fb92c3e7e8700e221Eric Laurent if (isInCommunication()) { 275525101b0b9a84571ead15b26e9f4cd9c4298d7823Eric Laurent if (AudioSystem.getForceUse(AudioSystem.FOR_COMMUNICATION) 275625101b0b9a84571ead15b26e9f4cd9c4298d7823Eric Laurent == AudioSystem.FORCE_BT_SCO) { 275725101b0b9a84571ead15b26e9f4cd9c4298d7823Eric Laurent // Log.v(TAG, "getActiveStreamType: Forcing STREAM_BLUETOOTH_SCO..."); 275825101b0b9a84571ead15b26e9f4cd9c4298d7823Eric Laurent return AudioSystem.STREAM_BLUETOOTH_SCO; 275925101b0b9a84571ead15b26e9f4cd9c4298d7823Eric Laurent } else { 276025101b0b9a84571ead15b26e9f4cd9c4298d7823Eric Laurent // Log.v(TAG, "getActiveStreamType: Forcing STREAM_VOICE_CALL..."); 276125101b0b9a84571ead15b26e9f4cd9c4298d7823Eric Laurent return AudioSystem.STREAM_VOICE_CALL; 276225101b0b9a84571ead15b26e9f4cd9c4298d7823Eric Laurent } 27633114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi } else if (suggestedStreamType == AudioManager.USE_DEFAULT_STREAM_TYPE) { 2764fca1e603236b8d1681f784e77e3719d1d59c1428Jean-Michel Trivi if (isAfMusicActiveRecently(DEFAULT_STREAM_TYPE_OVERRIDE_DELAY_MS)) { 27653114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi if (DEBUG_VOL) 27663114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi Log.v(TAG, "getActiveStreamType: Forcing STREAM_MUSIC stream active"); 27673114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi return AudioSystem.STREAM_MUSIC; 2768fca1e603236b8d1681f784e77e3719d1d59c1428Jean-Michel Trivi } else 2769fca1e603236b8d1681f784e77e3719d1d59c1428Jean-Michel Trivi if (mMediaFocusControl.checkUpdateRemoteStateIfActive(AudioSystem.STREAM_MUSIC)) 2770fca1e603236b8d1681f784e77e3719d1d59c1428Jean-Michel Trivi { 2771fca1e603236b8d1681f784e77e3719d1d59c1428Jean-Michel Trivi if (DEBUG_VOL) 2772fca1e603236b8d1681f784e77e3719d1d59c1428Jean-Michel Trivi Log.v(TAG, "getActiveStreamType: Forcing STREAM_REMOTE_MUSIC"); 2773fca1e603236b8d1681f784e77e3719d1d59c1428Jean-Michel Trivi return STREAM_REMOTE_MUSIC; 2774fca1e603236b8d1681f784e77e3719d1d59c1428Jean-Michel Trivi } else { 2775fca1e603236b8d1681f784e77e3719d1d59c1428Jean-Michel Trivi if (DEBUG_VOL) 2776fca1e603236b8d1681f784e77e3719d1d59c1428Jean-Michel Trivi Log.v(TAG, "getActiveStreamType: Forcing STREAM_RING b/c default"); 2777fca1e603236b8d1681f784e77e3719d1d59c1428Jean-Michel Trivi return AudioSystem.STREAM_RING; 27783114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi } 2779fca1e603236b8d1681f784e77e3719d1d59c1428Jean-Michel Trivi } else if (isAfMusicActiveRecently(0)) { 27803114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi if (DEBUG_VOL) 27813114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi Log.v(TAG, "getActiveStreamType: Forcing STREAM_MUSIC stream active"); 278225101b0b9a84571ead15b26e9f4cd9c4298d7823Eric Laurent return AudioSystem.STREAM_MUSIC; 2783c7fcba4b7bd3d78e7cfe975a3f8e4dde2f6738b7Joe Onorato } else { 27843114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi if (DEBUG_VOL) Log.v(TAG, "getActiveStreamType: Returning suggested type " 27853114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi + suggestedStreamType); 278625101b0b9a84571ead15b26e9f4cd9c4298d7823Eric Laurent return suggestedStreamType; 278725101b0b9a84571ead15b26e9f4cd9c4298d7823Eric Laurent } 278825101b0b9a84571ead15b26e9f4cd9c4298d7823Eric Laurent } else { 27896d5176638c2189595cede38fb92c3e7e8700e221Eric Laurent if (isInCommunication()) { 279025101b0b9a84571ead15b26e9f4cd9c4298d7823Eric Laurent if (AudioSystem.getForceUse(AudioSystem.FOR_COMMUNICATION) 279125101b0b9a84571ead15b26e9f4cd9c4298d7823Eric Laurent == AudioSystem.FORCE_BT_SCO) { 27923114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi if (DEBUG_VOL) Log.v(TAG, "getActiveStreamType: Forcing STREAM_BLUETOOTH_SCO"); 279325101b0b9a84571ead15b26e9f4cd9c4298d7823Eric Laurent return AudioSystem.STREAM_BLUETOOTH_SCO; 279425101b0b9a84571ead15b26e9f4cd9c4298d7823Eric Laurent } else { 27953114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi if (DEBUG_VOL) Log.v(TAG, "getActiveStreamType: Forcing STREAM_VOICE_CALL"); 279625101b0b9a84571ead15b26e9f4cd9c4298d7823Eric Laurent return AudioSystem.STREAM_VOICE_CALL; 279725101b0b9a84571ead15b26e9f4cd9c4298d7823Eric Laurent } 279825101b0b9a84571ead15b26e9f4cd9c4298d7823Eric Laurent } else if (AudioSystem.isStreamActive(AudioSystem.STREAM_NOTIFICATION, 27999903e2638a6c502d96413680d3ebae4fb77fc412Eric Laurent DEFAULT_STREAM_TYPE_OVERRIDE_DELAY_MS) || 28003114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi AudioSystem.isStreamActive(AudioSystem.STREAM_RING, 28019903e2638a6c502d96413680d3ebae4fb77fc412Eric Laurent DEFAULT_STREAM_TYPE_OVERRIDE_DELAY_MS)) { 28023114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi if (DEBUG_VOL) Log.v(TAG, "getActiveStreamType: Forcing STREAM_NOTIFICATION"); 280325101b0b9a84571ead15b26e9f4cd9c4298d7823Eric Laurent return AudioSystem.STREAM_NOTIFICATION; 28043114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi } else if (suggestedStreamType == AudioManager.USE_DEFAULT_STREAM_TYPE) { 2805fca1e603236b8d1681f784e77e3719d1d59c1428Jean-Michel Trivi if (isAfMusicActiveRecently(DEFAULT_STREAM_TYPE_OVERRIDE_DELAY_MS)) { 2806fca1e603236b8d1681f784e77e3719d1d59c1428Jean-Michel Trivi if (DEBUG_VOL) Log.v(TAG, "getActiveStreamType: forcing STREAM_MUSIC"); 2807fca1e603236b8d1681f784e77e3719d1d59c1428Jean-Michel Trivi return AudioSystem.STREAM_MUSIC; 2808fca1e603236b8d1681f784e77e3719d1d59c1428Jean-Michel Trivi } else 2809fca1e603236b8d1681f784e77e3719d1d59c1428Jean-Michel Trivi if (mMediaFocusControl.checkUpdateRemoteStateIfActive(AudioSystem.STREAM_MUSIC)) 2810fca1e603236b8d1681f784e77e3719d1d59c1428Jean-Michel Trivi { 2811fca1e603236b8d1681f784e77e3719d1d59c1428Jean-Michel Trivi if (DEBUG_VOL) 2812fca1e603236b8d1681f784e77e3719d1d59c1428Jean-Michel Trivi Log.v(TAG, "getActiveStreamType: Forcing STREAM_REMOTE_MUSIC"); 2813fca1e603236b8d1681f784e77e3719d1d59c1428Jean-Michel Trivi return STREAM_REMOTE_MUSIC; 28143114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi } else { 2815fca1e603236b8d1681f784e77e3719d1d59c1428Jean-Michel Trivi if (DEBUG_VOL) Log.v(TAG, "getActiveStreamType: using STREAM_MUSIC as default"); 28163114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi return AudioSystem.STREAM_MUSIC; 28173114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi } 281825101b0b9a84571ead15b26e9f4cd9c4298d7823Eric Laurent } else { 28193114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi if (DEBUG_VOL) Log.v(TAG, "getActiveStreamType: Returning suggested type " 28203114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi + suggestedStreamType); 282125101b0b9a84571ead15b26e9f4cd9c4298d7823Eric Laurent return suggestedStreamType; 2822c7fcba4b7bd3d78e7cfe975a3f8e4dde2f6738b7Joe Onorato } 28239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 28249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 28259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2826ba195ebc76f23b6679443724ab58c9dc9f2df884Glenn Kasten private void broadcastRingerMode(int ringerMode) { 28279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Send sticky broadcast 28281c633fc89bae9bf0af6fe643ac7ad2e744f27bedDianne Hackborn Intent broadcast = new Intent(AudioManager.RINGER_MODE_CHANGED_ACTION); 2829ba195ebc76f23b6679443724ab58c9dc9f2df884Glenn Kasten broadcast.putExtra(AudioManager.EXTRA_RINGER_MODE, ringerMode); 28301c633fc89bae9bf0af6fe643ac7ad2e744f27bedDianne Hackborn broadcast.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT 28311c633fc89bae9bf0af6fe643ac7ad2e744f27bedDianne Hackborn | Intent.FLAG_RECEIVER_REPLACE_PENDING); 28325ac72a29593ab9a20337a2225df52bdf4754be02Dianne Hackborn sendStickyBroadcastToAll(broadcast); 28339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 28349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 28359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private void broadcastVibrateSetting(int vibrateType) { 28369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Send broadcast 28379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (ActivityManagerNative.isSystemReady()) { 28389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Intent broadcast = new Intent(AudioManager.VIBRATE_SETTING_CHANGED_ACTION); 28399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project broadcast.putExtra(AudioManager.EXTRA_VIBRATE_TYPE, vibrateType); 28409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project broadcast.putExtra(AudioManager.EXTRA_VIBRATE_SETTING, getVibrateSetting(vibrateType)); 28415ac72a29593ab9a20337a2225df52bdf4754be02Dianne Hackborn sendBroadcastToAll(broadcast); 28429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 28439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 28449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 28459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Message helper methods 28462d8dab5a549b25b6f36df4614d7c0166d4d099e2Jean-Michel Trivi /** 28472d8dab5a549b25b6f36df4614d7c0166d4d099e2Jean-Michel Trivi * Queue a message on the given handler's message queue, after acquiring the service wake lock. 28482d8dab5a549b25b6f36df4614d7c0166d4d099e2Jean-Michel Trivi * Note that the wake lock needs to be released after the message has been handled. 28492d8dab5a549b25b6f36df4614d7c0166d4d099e2Jean-Michel Trivi */ 28502d8dab5a549b25b6f36df4614d7c0166d4d099e2Jean-Michel Trivi private void queueMsgUnderWakeLock(Handler handler, int msg, 28512d8dab5a549b25b6f36df4614d7c0166d4d099e2Jean-Michel Trivi int arg1, int arg2, Object obj, int delay) { 2852a4dfbdc54d8898491d3a7d1d9d818c7db3fd773dEric Laurent final long ident = Binder.clearCallingIdentity(); 2853a4dfbdc54d8898491d3a7d1d9d818c7db3fd773dEric Laurent // Always acquire the wake lock as AudioService because it is released by the 2854a4dfbdc54d8898491d3a7d1d9d818c7db3fd773dEric Laurent // message handler. 2855fa9a69805b001034aa04c3b33989a7ac21522371Jean-Michel Trivi mAudioEventWakeLock.acquire(); 2856a4dfbdc54d8898491d3a7d1d9d818c7db3fd773dEric Laurent Binder.restoreCallingIdentity(ident); 28572d8dab5a549b25b6f36df4614d7c0166d4d099e2Jean-Michel Trivi sendMsg(handler, msg, SENDMSG_QUEUE, arg1, arg2, obj, delay); 28582d8dab5a549b25b6f36df4614d7c0166d4d099e2Jean-Michel Trivi } 28599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2860afbb047c3945e9c2b7e9bc6b25098d5fb80bba4eEric Laurent private static void sendMsg(Handler handler, int msg, 28619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int existingMsgPolicy, int arg1, int arg2, Object obj, int delay) { 28629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 28639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (existingMsgPolicy == SENDMSG_REPLACE) { 28649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project handler.removeMessages(msg); 28659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else if (existingMsgPolicy == SENDMSG_NOOP && handler.hasMessages(msg)) { 28669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return; 28679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 28689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2869afbb047c3945e9c2b7e9bc6b25098d5fb80bba4eEric Laurent handler.sendMessageDelayed(handler.obtainMessage(msg, arg1, arg2, obj), delay); 28709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 28719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 28729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project boolean checkAudioSettingsPermission(String method) { 28739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (mContext.checkCallingOrSelfPermission("android.permission.MODIFY_AUDIO_SETTINGS") 28749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project == PackageManager.PERMISSION_GRANTED) { 28759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return true; 28769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 28779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project String msg = "Audio Settings Permission Denial: " + method + " from pid=" 28789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project + Binder.getCallingPid() 28799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project + ", uid=" + Binder.getCallingUid(); 28809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Log.w(TAG, msg); 28819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return false; 28829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 28839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 28849bc8358ddaa01c3490f9709991989633a6a3dd42Eric Laurent private int getDeviceForStream(int stream) { 28859bc8358ddaa01c3490f9709991989633a6a3dd42Eric Laurent int device = AudioSystem.getDevicesForStream(stream); 28869bc8358ddaa01c3490f9709991989633a6a3dd42Eric Laurent if ((device & (device - 1)) != 0) { 28879bc8358ddaa01c3490f9709991989633a6a3dd42Eric Laurent // Multiple device selection is either: 28889bc8358ddaa01c3490f9709991989633a6a3dd42Eric Laurent // - speaker + one other device: give priority to speaker in this case. 28899bc8358ddaa01c3490f9709991989633a6a3dd42Eric Laurent // - one A2DP device + another device: happens with duplicated output. In this case 28909bc8358ddaa01c3490f9709991989633a6a3dd42Eric Laurent // retain the device on the A2DP output as the other must not correspond to an active 28919bc8358ddaa01c3490f9709991989633a6a3dd42Eric Laurent // selection if not the speaker. 28929bc8358ddaa01c3490f9709991989633a6a3dd42Eric Laurent if ((device & AudioSystem.DEVICE_OUT_SPEAKER) != 0) { 28939bc8358ddaa01c3490f9709991989633a6a3dd42Eric Laurent device = AudioSystem.DEVICE_OUT_SPEAKER; 28949bc8358ddaa01c3490f9709991989633a6a3dd42Eric Laurent } else { 28959bc8358ddaa01c3490f9709991989633a6a3dd42Eric Laurent device &= AudioSystem.DEVICE_OUT_ALL_A2DP; 28969bc8358ddaa01c3490f9709991989633a6a3dd42Eric Laurent } 28979bc8358ddaa01c3490f9709991989633a6a3dd42Eric Laurent } 28989bc8358ddaa01c3490f9709991989633a6a3dd42Eric Laurent return device; 28999bc8358ddaa01c3490f9709991989633a6a3dd42Eric Laurent } 29009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2901b1fbaaccb656ef09a8770c28df15e3e91a452e64Eric Laurent public void setWiredDeviceConnectionState(int device, int state, String name) { 2902b1fbaaccb656ef09a8770c28df15e3e91a452e64Eric Laurent synchronized (mConnectedDevices) { 2903b1fbaaccb656ef09a8770c28df15e3e91a452e64Eric Laurent int delay = checkSendBecomingNoisyIntent(device, state); 29042d8dab5a549b25b6f36df4614d7c0166d4d099e2Jean-Michel Trivi queueMsgUnderWakeLock(mAudioHandler, 2905b1fbaaccb656ef09a8770c28df15e3e91a452e64Eric Laurent MSG_SET_WIRED_DEVICE_CONNECTION_STATE, 2906b1fbaaccb656ef09a8770c28df15e3e91a452e64Eric Laurent device, 2907b1fbaaccb656ef09a8770c28df15e3e91a452e64Eric Laurent state, 2908b1fbaaccb656ef09a8770c28df15e3e91a452e64Eric Laurent name, 2909b1fbaaccb656ef09a8770c28df15e3e91a452e64Eric Laurent delay); 2910b1fbaaccb656ef09a8770c28df15e3e91a452e64Eric Laurent } 2911b1fbaaccb656ef09a8770c28df15e3e91a452e64Eric Laurent } 2912b1fbaaccb656ef09a8770c28df15e3e91a452e64Eric Laurent 29130a40ec2192e4836b2fcb6ba51a7688aa6bd4ee98Mike Lockwood public int setBluetoothA2dpDeviceConnectionState(BluetoothDevice device, int state, int profile) 2914b1fbaaccb656ef09a8770c28df15e3e91a452e64Eric Laurent { 2915b1fbaaccb656ef09a8770c28df15e3e91a452e64Eric Laurent int delay; 29160a40ec2192e4836b2fcb6ba51a7688aa6bd4ee98Mike Lockwood if (profile != BluetoothProfile.A2DP && profile != BluetoothProfile.A2DP_SINK) { 29170a40ec2192e4836b2fcb6ba51a7688aa6bd4ee98Mike Lockwood throw new IllegalArgumentException("invalid profile " + profile); 29180a40ec2192e4836b2fcb6ba51a7688aa6bd4ee98Mike Lockwood } 2919b1fbaaccb656ef09a8770c28df15e3e91a452e64Eric Laurent synchronized (mConnectedDevices) { 29200a40ec2192e4836b2fcb6ba51a7688aa6bd4ee98Mike Lockwood if (profile == BluetoothProfile.A2DP) { 29210a40ec2192e4836b2fcb6ba51a7688aa6bd4ee98Mike Lockwood delay = checkSendBecomingNoisyIntent(AudioSystem.DEVICE_OUT_BLUETOOTH_A2DP, 29220a40ec2192e4836b2fcb6ba51a7688aa6bd4ee98Mike Lockwood (state == BluetoothA2dp.STATE_CONNECTED) ? 1 : 0); 29230a40ec2192e4836b2fcb6ba51a7688aa6bd4ee98Mike Lockwood } else { 29240a40ec2192e4836b2fcb6ba51a7688aa6bd4ee98Mike Lockwood delay = 0; 29250a40ec2192e4836b2fcb6ba51a7688aa6bd4ee98Mike Lockwood } 29262d8dab5a549b25b6f36df4614d7c0166d4d099e2Jean-Michel Trivi queueMsgUnderWakeLock(mAudioHandler, 29270a40ec2192e4836b2fcb6ba51a7688aa6bd4ee98Mike Lockwood (profile == BluetoothProfile.A2DP ? 29280a40ec2192e4836b2fcb6ba51a7688aa6bd4ee98Mike Lockwood MSG_SET_A2DP_SINK_CONNECTION_STATE : MSG_SET_A2DP_SRC_CONNECTION_STATE), 2929b1fbaaccb656ef09a8770c28df15e3e91a452e64Eric Laurent state, 2930b1fbaaccb656ef09a8770c28df15e3e91a452e64Eric Laurent 0, 2931b1fbaaccb656ef09a8770c28df15e3e91a452e64Eric Laurent device, 2932b1fbaaccb656ef09a8770c28df15e3e91a452e64Eric Laurent delay); 2933b1fbaaccb656ef09a8770c28df15e3e91a452e64Eric Laurent } 2934b1fbaaccb656ef09a8770c28df15e3e91a452e64Eric Laurent return delay; 2935b1fbaaccb656ef09a8770c28df15e3e91a452e64Eric Laurent } 2936b1fbaaccb656ef09a8770c28df15e3e91a452e64Eric Laurent 29379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /////////////////////////////////////////////////////////////////////////// 29389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Inner classes 29399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /////////////////////////////////////////////////////////////////////////// 29409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 29419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public class VolumeStreamState { 29429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private final int mStreamType; 29439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 294411a74a75653197a3d31fe91590cd8312f5270c44Jean-Michel Trivi private String mVolumeIndexSettingName; 2945a553c25b33c99b345cf1c8688f8df0ed8df14e5aEric Laurent private int mIndexMax; 29463172d5e3e7520a745fa37b71fc1c7bf244b57085Eric Laurent private final ConcurrentHashMap<Integer, Integer> mIndex = 29473172d5e3e7520a745fa37b71fc1c7bf244b57085Eric Laurent new ConcurrentHashMap<Integer, Integer>(8, 0.75f, 4); 29489bc8358ddaa01c3490f9709991989633a6a3dd42Eric Laurent private ArrayList<VolumeDeathHandler> mDeathHandlers; //handles mute/solo clients death 29499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2950a553c25b33c99b345cf1c8688f8df0ed8df14e5aEric Laurent private VolumeStreamState(String settingName, int streamType) { 29519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 29529bc8358ddaa01c3490f9709991989633a6a3dd42Eric Laurent mVolumeIndexSettingName = settingName; 29539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 29549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mStreamType = streamType; 29555982013cfc8274ff0bafaba83c676b3a8890cba9Jared Suttles mIndexMax = MAX_STREAM_VOLUME[streamType]; 2956a553c25b33c99b345cf1c8688f8df0ed8df14e5aEric Laurent AudioSystem.initStreamVolume(streamType, 0, mIndexMax); 2957a553c25b33c99b345cf1c8688f8df0ed8df14e5aEric Laurent mIndexMax *= 10; 29589bc8358ddaa01c3490f9709991989633a6a3dd42Eric Laurent 295933902db75011d863009585682bd08560c5b89a75Eric Laurent // mDeathHandlers must be created before calling readSettings() 29609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mDeathHandlers = new ArrayList<VolumeDeathHandler>(); 296133902db75011d863009585682bd08560c5b89a75Eric Laurent 296233902db75011d863009585682bd08560c5b89a75Eric Laurent readSettings(); 29639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 29649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 296542b041ed4f184e3af7f788eb07307f556a2a6616Eric Laurent public String getSettingNameForDevice(int device) { 296642b041ed4f184e3af7f788eb07307f556a2a6616Eric Laurent String name = mVolumeIndexSettingName; 2967948d32748caaac5be06c991ebf00f74265a7849fEric Laurent String suffix = AudioSystem.getOutputDeviceName(device); 29689bc8358ddaa01c3490f9709991989633a6a3dd42Eric Laurent if (suffix.isEmpty()) { 29699bc8358ddaa01c3490f9709991989633a6a3dd42Eric Laurent return name; 29709bc8358ddaa01c3490f9709991989633a6a3dd42Eric Laurent } 29719bc8358ddaa01c3490f9709991989633a6a3dd42Eric Laurent return name + "_" + suffix; 29729bc8358ddaa01c3490f9709991989633a6a3dd42Eric Laurent } 29739bc8358ddaa01c3490f9709991989633a6a3dd42Eric Laurent 2974fdbee869be504e399efce1127a68281bd9b158c5Eric Laurent public void readSettings() { 2975fdbee869be504e399efce1127a68281bd9b158c5Eric Laurent synchronized (VolumeStreamState.class) { 2976fdbee869be504e399efce1127a68281bd9b158c5Eric Laurent // force maximum volume on all streams if fixed volume property is set 2977fdbee869be504e399efce1127a68281bd9b158c5Eric Laurent if (mUseFixedVolume) { 2978fdbee869be504e399efce1127a68281bd9b158c5Eric Laurent mIndex.put(AudioSystem.DEVICE_OUT_DEFAULT, mIndexMax); 2979fdbee869be504e399efce1127a68281bd9b158c5Eric Laurent return; 2980fdbee869be504e399efce1127a68281bd9b158c5Eric Laurent } 2981fdbee869be504e399efce1127a68281bd9b158c5Eric Laurent // do not read system stream volume from settings: this stream is always aliased 2982fdbee869be504e399efce1127a68281bd9b158c5Eric Laurent // to another stream type and its volume is never persisted. Values in settings can 2983fdbee869be504e399efce1127a68281bd9b158c5Eric Laurent // only be stale values 2984fdbee869be504e399efce1127a68281bd9b158c5Eric Laurent if ((mStreamType == AudioSystem.STREAM_SYSTEM) || 2985fdbee869be504e399efce1127a68281bd9b158c5Eric Laurent (mStreamType == AudioSystem.STREAM_SYSTEM_ENFORCED)) { 2986fdbee869be504e399efce1127a68281bd9b158c5Eric Laurent int index = 10 * AudioManager.DEFAULT_STREAM_VOLUME[mStreamType]; 2987fdbee869be504e399efce1127a68281bd9b158c5Eric Laurent synchronized (mCameraSoundForced) { 2988fdbee869be504e399efce1127a68281bd9b158c5Eric Laurent if (mCameraSoundForced) { 2989fdbee869be504e399efce1127a68281bd9b158c5Eric Laurent index = mIndexMax; 2990fdbee869be504e399efce1127a68281bd9b158c5Eric Laurent } 2991dd45d01128423a82652a3c9d77fa393631d95229Eric Laurent } 2992fdbee869be504e399efce1127a68281bd9b158c5Eric Laurent mIndex.put(AudioSystem.DEVICE_OUT_DEFAULT, index); 2993fdbee869be504e399efce1127a68281bd9b158c5Eric Laurent return; 2994dd45d01128423a82652a3c9d77fa393631d95229Eric Laurent } 2995002e9d382d2daa7ed41636463ecdbddbd4897abaEric Laurent 2996fdbee869be504e399efce1127a68281bd9b158c5Eric Laurent int remainingDevices = AudioSystem.DEVICE_OUT_ALL; 299783a017b6b7c099d1a0293e5839be6477325aef06Eric Laurent 2998fdbee869be504e399efce1127a68281bd9b158c5Eric Laurent for (int i = 0; remainingDevices != 0; i++) { 2999fdbee869be504e399efce1127a68281bd9b158c5Eric Laurent int device = (1 << i); 3000fdbee869be504e399efce1127a68281bd9b158c5Eric Laurent if ((device & remainingDevices) == 0) { 3001fdbee869be504e399efce1127a68281bd9b158c5Eric Laurent continue; 3002fdbee869be504e399efce1127a68281bd9b158c5Eric Laurent } 3003fdbee869be504e399efce1127a68281bd9b158c5Eric Laurent remainingDevices &= ~device; 3004fdbee869be504e399efce1127a68281bd9b158c5Eric Laurent 3005fdbee869be504e399efce1127a68281bd9b158c5Eric Laurent // retrieve current volume for device 3006fdbee869be504e399efce1127a68281bd9b158c5Eric Laurent String name = getSettingNameForDevice(device); 3007fdbee869be504e399efce1127a68281bd9b158c5Eric Laurent // if no volume stored for current stream and device, use default volume if default 3008fdbee869be504e399efce1127a68281bd9b158c5Eric Laurent // device, continue otherwise 3009fdbee869be504e399efce1127a68281bd9b158c5Eric Laurent int defaultIndex = (device == AudioSystem.DEVICE_OUT_DEFAULT) ? 3010fdbee869be504e399efce1127a68281bd9b158c5Eric Laurent AudioManager.DEFAULT_STREAM_VOLUME[mStreamType] : -1; 3011fdbee869be504e399efce1127a68281bd9b158c5Eric Laurent int index = Settings.System.getIntForUser( 3012fdbee869be504e399efce1127a68281bd9b158c5Eric Laurent mContentResolver, name, defaultIndex, UserHandle.USER_CURRENT); 3013fdbee869be504e399efce1127a68281bd9b158c5Eric Laurent if (index == -1) { 3014fdbee869be504e399efce1127a68281bd9b158c5Eric Laurent continue; 3015fdbee869be504e399efce1127a68281bd9b158c5Eric Laurent } 30169bc8358ddaa01c3490f9709991989633a6a3dd42Eric Laurent 3017fdbee869be504e399efce1127a68281bd9b158c5Eric Laurent // ignore settings for fixed volume devices: volume should always be at max or 0 3018fdbee869be504e399efce1127a68281bd9b158c5Eric Laurent if ((mStreamVolumeAlias[mStreamType] == AudioSystem.STREAM_MUSIC) && 3019fdbee869be504e399efce1127a68281bd9b158c5Eric Laurent ((device & mFixedVolumeDevices) != 0)) { 3020fdbee869be504e399efce1127a68281bd9b158c5Eric Laurent mIndex.put(device, (index != 0) ? mIndexMax : 0); 3021fdbee869be504e399efce1127a68281bd9b158c5Eric Laurent } else { 3022fdbee869be504e399efce1127a68281bd9b158c5Eric Laurent mIndex.put(device, getValidIndex(10 * index)); 3023fdbee869be504e399efce1127a68281bd9b158c5Eric Laurent } 3024dd45d01128423a82652a3c9d77fa393631d95229Eric Laurent } 30259bc8358ddaa01c3490f9709991989633a6a3dd42Eric Laurent } 30269bc8358ddaa01c3490f9709991989633a6a3dd42Eric Laurent } 30279bc8358ddaa01c3490f9709991989633a6a3dd42Eric Laurent 30289bc8358ddaa01c3490f9709991989633a6a3dd42Eric Laurent public void applyDeviceVolume(int device) { 302942b041ed4f184e3af7f788eb07307f556a2a6616Eric Laurent int index; 303042b041ed4f184e3af7f788eb07307f556a2a6616Eric Laurent if (isMuted()) { 303142b041ed4f184e3af7f788eb07307f556a2a6616Eric Laurent index = 0; 3032cd772d04345850e160a45613fcf6b86da0dce4cfEric Laurent } else if ((device & AudioSystem.DEVICE_OUT_ALL_A2DP) != 0 && 3033c9d1d5f35091226e96fcfa91817480f589eb36e2Matthew Xie mAvrcpAbsVolSupported) { 3034c9d1d5f35091226e96fcfa91817480f589eb36e2Matthew Xie index = (mIndexMax + 5)/10; 3035cd772d04345850e160a45613fcf6b86da0dce4cfEric Laurent } else { 303642b041ed4f184e3af7f788eb07307f556a2a6616Eric Laurent index = (getIndex(device) + 5)/10; 303742b041ed4f184e3af7f788eb07307f556a2a6616Eric Laurent } 303842b041ed4f184e3af7f788eb07307f556a2a6616Eric Laurent AudioSystem.setStreamVolumeIndex(mStreamType, index, device); 30399bc8358ddaa01c3490f9709991989633a6a3dd42Eric Laurent } 30409bc8358ddaa01c3490f9709991989633a6a3dd42Eric Laurent 3041fdbee869be504e399efce1127a68281bd9b158c5Eric Laurent public void applyAllVolumes() { 3042fdbee869be504e399efce1127a68281bd9b158c5Eric Laurent synchronized (VolumeStreamState.class) { 3043fdbee869be504e399efce1127a68281bd9b158c5Eric Laurent // apply default volume first: by convention this will reset all 3044fdbee869be504e399efce1127a68281bd9b158c5Eric Laurent // devices volumes in audio policy manager to the supplied value 3045fdbee869be504e399efce1127a68281bd9b158c5Eric Laurent int index; 3046fdbee869be504e399efce1127a68281bd9b158c5Eric Laurent if (isMuted()) { 3047fdbee869be504e399efce1127a68281bd9b158c5Eric Laurent index = 0; 3048fdbee869be504e399efce1127a68281bd9b158c5Eric Laurent } else { 3049fdbee869be504e399efce1127a68281bd9b158c5Eric Laurent index = (getIndex(AudioSystem.DEVICE_OUT_DEFAULT) + 5)/10; 3050fdbee869be504e399efce1127a68281bd9b158c5Eric Laurent } 3051fdbee869be504e399efce1127a68281bd9b158c5Eric Laurent AudioSystem.setStreamVolumeIndex(mStreamType, index, AudioSystem.DEVICE_OUT_DEFAULT); 3052fdbee869be504e399efce1127a68281bd9b158c5Eric Laurent // then apply device specific volumes 3053fdbee869be504e399efce1127a68281bd9b158c5Eric Laurent Set set = mIndex.entrySet(); 3054fdbee869be504e399efce1127a68281bd9b158c5Eric Laurent Iterator i = set.iterator(); 3055fdbee869be504e399efce1127a68281bd9b158c5Eric Laurent while (i.hasNext()) { 3056fdbee869be504e399efce1127a68281bd9b158c5Eric Laurent Map.Entry entry = (Map.Entry)i.next(); 3057fdbee869be504e399efce1127a68281bd9b158c5Eric Laurent int device = ((Integer)entry.getKey()).intValue(); 3058fdbee869be504e399efce1127a68281bd9b158c5Eric Laurent if (device != AudioSystem.DEVICE_OUT_DEFAULT) { 3059fdbee869be504e399efce1127a68281bd9b158c5Eric Laurent if (isMuted()) { 3060fdbee869be504e399efce1127a68281bd9b158c5Eric Laurent index = 0; 3061fdbee869be504e399efce1127a68281bd9b158c5Eric Laurent } else if ((device & AudioSystem.DEVICE_OUT_ALL_A2DP) != 0 && 3062fdbee869be504e399efce1127a68281bd9b158c5Eric Laurent mAvrcpAbsVolSupported) { 3063fdbee869be504e399efce1127a68281bd9b158c5Eric Laurent index = (mIndexMax + 5)/10; 3064fdbee869be504e399efce1127a68281bd9b158c5Eric Laurent } else { 3065fdbee869be504e399efce1127a68281bd9b158c5Eric Laurent index = ((Integer)entry.getValue() + 5)/10; 3066fdbee869be504e399efce1127a68281bd9b158c5Eric Laurent } 3067fdbee869be504e399efce1127a68281bd9b158c5Eric Laurent AudioSystem.setStreamVolumeIndex(mStreamType, index, device); 306842b041ed4f184e3af7f788eb07307f556a2a6616Eric Laurent } 30699bc8358ddaa01c3490f9709991989633a6a3dd42Eric Laurent } 30709bc8358ddaa01c3490f9709991989633a6a3dd42Eric Laurent } 307111a74a75653197a3d31fe91590cd8312f5270c44Jean-Michel Trivi } 307211a74a75653197a3d31fe91590cd8312f5270c44Jean-Michel Trivi 30739bc8358ddaa01c3490f9709991989633a6a3dd42Eric Laurent public boolean adjustIndex(int deltaIndex, int device) { 307442b041ed4f184e3af7f788eb07307f556a2a6616Eric Laurent return setIndex(getIndex(device) + deltaIndex, 307542b041ed4f184e3af7f788eb07307f556a2a6616Eric Laurent device); 30769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 30779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3078fdbee869be504e399efce1127a68281bd9b158c5Eric Laurent public boolean setIndex(int index, int device) { 3079fdbee869be504e399efce1127a68281bd9b158c5Eric Laurent synchronized (VolumeStreamState.class) { 3080fdbee869be504e399efce1127a68281bd9b158c5Eric Laurent int oldIndex = getIndex(device); 3081fdbee869be504e399efce1127a68281bd9b158c5Eric Laurent index = getValidIndex(index); 3082fdbee869be504e399efce1127a68281bd9b158c5Eric Laurent synchronized (mCameraSoundForced) { 3083fdbee869be504e399efce1127a68281bd9b158c5Eric Laurent if ((mStreamType == AudioSystem.STREAM_SYSTEM_ENFORCED) && mCameraSoundForced) { 3084fdbee869be504e399efce1127a68281bd9b158c5Eric Laurent index = mIndexMax; 3085fdbee869be504e399efce1127a68281bd9b158c5Eric Laurent } 3086dd45d01128423a82652a3c9d77fa393631d95229Eric Laurent } 3087fdbee869be504e399efce1127a68281bd9b158c5Eric Laurent mIndex.put(device, index); 3088fdbee869be504e399efce1127a68281bd9b158c5Eric Laurent 3089fdbee869be504e399efce1127a68281bd9b158c5Eric Laurent if (oldIndex != index) { 3090fdbee869be504e399efce1127a68281bd9b158c5Eric Laurent // Apply change to all streams using this one as alias 3091fdbee869be504e399efce1127a68281bd9b158c5Eric Laurent // if changing volume of current device, also change volume of current 3092fdbee869be504e399efce1127a68281bd9b158c5Eric Laurent // device on aliased stream 3093fdbee869be504e399efce1127a68281bd9b158c5Eric Laurent boolean currentDevice = (device == getDeviceForStream(mStreamType)); 3094fdbee869be504e399efce1127a68281bd9b158c5Eric Laurent int numStreamTypes = AudioSystem.getNumStreamTypes(); 3095fdbee869be504e399efce1127a68281bd9b158c5Eric Laurent for (int streamType = numStreamTypes - 1; streamType >= 0; streamType--) { 3096fdbee869be504e399efce1127a68281bd9b158c5Eric Laurent if (streamType != mStreamType && 3097fdbee869be504e399efce1127a68281bd9b158c5Eric Laurent mStreamVolumeAlias[streamType] == mStreamType) { 3098fdbee869be504e399efce1127a68281bd9b158c5Eric Laurent int scaledIndex = rescaleIndex(index, mStreamType, streamType); 3099bffc3d1bd33eb2d8e00a9f8b6261d815db503311Eric Laurent mStreamStates[streamType].setIndex(scaledIndex, 3100fdbee869be504e399efce1127a68281bd9b158c5Eric Laurent device); 3101fdbee869be504e399efce1127a68281bd9b158c5Eric Laurent if (currentDevice) { 3102fdbee869be504e399efce1127a68281bd9b158c5Eric Laurent mStreamStates[streamType].setIndex(scaledIndex, 3103fdbee869be504e399efce1127a68281bd9b158c5Eric Laurent getDeviceForStream(streamType)); 3104fdbee869be504e399efce1127a68281bd9b158c5Eric Laurent } 3105bffc3d1bd33eb2d8e00a9f8b6261d815db503311Eric Laurent } 3106a553c25b33c99b345cf1c8688f8df0ed8df14e5aEric Laurent } 3107fdbee869be504e399efce1127a68281bd9b158c5Eric Laurent return true; 3108fdbee869be504e399efce1127a68281bd9b158c5Eric Laurent } else { 3109fdbee869be504e399efce1127a68281bd9b158c5Eric Laurent return false; 3110a553c25b33c99b345cf1c8688f8df0ed8df14e5aEric Laurent } 31119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 31129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 31139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3114fdbee869be504e399efce1127a68281bd9b158c5Eric Laurent public int getIndex(int device) { 3115fdbee869be504e399efce1127a68281bd9b158c5Eric Laurent synchronized (VolumeStreamState.class) { 3116fdbee869be504e399efce1127a68281bd9b158c5Eric Laurent Integer index = mIndex.get(device); 3117fdbee869be504e399efce1127a68281bd9b158c5Eric Laurent if (index == null) { 3118fdbee869be504e399efce1127a68281bd9b158c5Eric Laurent // there is always an entry for AudioSystem.DEVICE_OUT_DEFAULT 3119fdbee869be504e399efce1127a68281bd9b158c5Eric Laurent index = mIndex.get(AudioSystem.DEVICE_OUT_DEFAULT); 3120fdbee869be504e399efce1127a68281bd9b158c5Eric Laurent } 3121fdbee869be504e399efce1127a68281bd9b158c5Eric Laurent return index.intValue(); 31229bc8358ddaa01c3490f9709991989633a6a3dd42Eric Laurent } 31239bc8358ddaa01c3490f9709991989633a6a3dd42Eric Laurent } 31249bc8358ddaa01c3490f9709991989633a6a3dd42Eric Laurent 31259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public int getMaxIndex() { 3126a553c25b33c99b345cf1c8688f8df0ed8df14e5aEric Laurent return mIndexMax; 31279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 31289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3129fdbee869be504e399efce1127a68281bd9b158c5Eric Laurent public void setAllIndexes(VolumeStreamState srcStream) { 3130fdbee869be504e399efce1127a68281bd9b158c5Eric Laurent synchronized (VolumeStreamState.class) { 3131fdbee869be504e399efce1127a68281bd9b158c5Eric Laurent int srcStreamType = srcStream.getStreamType(); 3132fdbee869be504e399efce1127a68281bd9b158c5Eric Laurent // apply default device volume from source stream to all devices first in case 3133fdbee869be504e399efce1127a68281bd9b158c5Eric Laurent // some devices are present in this stream state but not in source stream state 3134fdbee869be504e399efce1127a68281bd9b158c5Eric Laurent int index = srcStream.getIndex(AudioSystem.DEVICE_OUT_DEFAULT); 313524e0d9b6c40712a297e4c287435a3b0fdd30e9daEric Laurent index = rescaleIndex(index, srcStreamType, mStreamType); 3136fdbee869be504e399efce1127a68281bd9b158c5Eric Laurent Set set = mIndex.entrySet(); 3137fdbee869be504e399efce1127a68281bd9b158c5Eric Laurent Iterator i = set.iterator(); 3138fdbee869be504e399efce1127a68281bd9b158c5Eric Laurent while (i.hasNext()) { 3139fdbee869be504e399efce1127a68281bd9b158c5Eric Laurent Map.Entry entry = (Map.Entry)i.next(); 3140fdbee869be504e399efce1127a68281bd9b158c5Eric Laurent entry.setValue(index); 3141fdbee869be504e399efce1127a68281bd9b158c5Eric Laurent } 3142fdbee869be504e399efce1127a68281bd9b158c5Eric Laurent // Now apply actual volume for devices in source stream state 3143fdbee869be504e399efce1127a68281bd9b158c5Eric Laurent set = srcStream.mIndex.entrySet(); 3144fdbee869be504e399efce1127a68281bd9b158c5Eric Laurent i = set.iterator(); 3145fdbee869be504e399efce1127a68281bd9b158c5Eric Laurent while (i.hasNext()) { 3146fdbee869be504e399efce1127a68281bd9b158c5Eric Laurent Map.Entry entry = (Map.Entry)i.next(); 3147fdbee869be504e399efce1127a68281bd9b158c5Eric Laurent int device = ((Integer)entry.getKey()).intValue(); 3148fdbee869be504e399efce1127a68281bd9b158c5Eric Laurent index = ((Integer)entry.getValue()).intValue(); 3149fdbee869be504e399efce1127a68281bd9b158c5Eric Laurent index = rescaleIndex(index, srcStreamType, mStreamType); 3150fdbee869be504e399efce1127a68281bd9b158c5Eric Laurent 3151fdbee869be504e399efce1127a68281bd9b158c5Eric Laurent setIndex(index, device); 3152fdbee869be504e399efce1127a68281bd9b158c5Eric Laurent } 31536d5176638c2189595cede38fb92c3e7e8700e221Eric Laurent } 31546d5176638c2189595cede38fb92c3e7e8700e221Eric Laurent } 31556d5176638c2189595cede38fb92c3e7e8700e221Eric Laurent 3156fdbee869be504e399efce1127a68281bd9b158c5Eric Laurent public void setAllIndexesToMax() { 3157fdbee869be504e399efce1127a68281bd9b158c5Eric Laurent synchronized (VolumeStreamState.class) { 3158fdbee869be504e399efce1127a68281bd9b158c5Eric Laurent Set set = mIndex.entrySet(); 3159fdbee869be504e399efce1127a68281bd9b158c5Eric Laurent Iterator i = set.iterator(); 3160fdbee869be504e399efce1127a68281bd9b158c5Eric Laurent while (i.hasNext()) { 3161fdbee869be504e399efce1127a68281bd9b158c5Eric Laurent Map.Entry entry = (Map.Entry)i.next(); 3162fdbee869be504e399efce1127a68281bd9b158c5Eric Laurent entry.setValue(mIndexMax); 3163fdbee869be504e399efce1127a68281bd9b158c5Eric Laurent } 3164dd45d01128423a82652a3c9d77fa393631d95229Eric Laurent } 3165dd45d01128423a82652a3c9d77fa393631d95229Eric Laurent } 3166dd45d01128423a82652a3c9d77fa393631d95229Eric Laurent 3167fdbee869be504e399efce1127a68281bd9b158c5Eric Laurent public void mute(IBinder cb, boolean state) { 3168fdbee869be504e399efce1127a68281bd9b158c5Eric Laurent synchronized (VolumeStreamState.class) { 3169fdbee869be504e399efce1127a68281bd9b158c5Eric Laurent VolumeDeathHandler handler = getDeathHandler(cb, state); 3170fdbee869be504e399efce1127a68281bd9b158c5Eric Laurent if (handler == null) { 3171fdbee869be504e399efce1127a68281bd9b158c5Eric Laurent Log.e(TAG, "Could not get client death handler for stream: "+mStreamType); 3172fdbee869be504e399efce1127a68281bd9b158c5Eric Laurent return; 3173fdbee869be504e399efce1127a68281bd9b158c5Eric Laurent } 3174fdbee869be504e399efce1127a68281bd9b158c5Eric Laurent handler.mute(state); 31759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 31769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 31779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 31786d5176638c2189595cede38fb92c3e7e8700e221Eric Laurent public int getStreamType() { 31796d5176638c2189595cede38fb92c3e7e8700e221Eric Laurent return mStreamType; 31806d5176638c2189595cede38fb92c3e7e8700e221Eric Laurent } 31816d5176638c2189595cede38fb92c3e7e8700e221Eric Laurent 31829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private int getValidIndex(int index) { 31839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (index < 0) { 31849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return 0; 318583a017b6b7c099d1a0293e5839be6477325aef06Eric Laurent } else if (mUseFixedVolume || index > mIndexMax) { 3186a553c25b33c99b345cf1c8688f8df0ed8df14e5aEric Laurent return mIndexMax; 31879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 31889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 31899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return index; 31909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 31919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 31929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private class VolumeDeathHandler implements IBinder.DeathRecipient { 31939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private IBinder mICallback; // To be notified of client's death 31949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private int mMuteCount; // Number of active mutes for this client 31959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 31969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project VolumeDeathHandler(IBinder cb) { 31979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mICallback = cb; 31989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 31999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 32003172d5e3e7520a745fa37b71fc1c7bf244b57085Eric Laurent // must be called while synchronized on parent VolumeStreamState 32019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public void mute(boolean state) { 320242b041ed4f184e3af7f788eb07307f556a2a6616Eric Laurent boolean updateVolume = false; 32033172d5e3e7520a745fa37b71fc1c7bf244b57085Eric Laurent if (state) { 32043172d5e3e7520a745fa37b71fc1c7bf244b57085Eric Laurent if (mMuteCount == 0) { 32053172d5e3e7520a745fa37b71fc1c7bf244b57085Eric Laurent // Register for client death notification 32063172d5e3e7520a745fa37b71fc1c7bf244b57085Eric Laurent try { 32073172d5e3e7520a745fa37b71fc1c7bf244b57085Eric Laurent // mICallback can be 0 if muted by AudioService 32083172d5e3e7520a745fa37b71fc1c7bf244b57085Eric Laurent if (mICallback != null) { 32093172d5e3e7520a745fa37b71fc1c7bf244b57085Eric Laurent mICallback.linkToDeath(this, 0); 32103172d5e3e7520a745fa37b71fc1c7bf244b57085Eric Laurent } 321142b041ed4f184e3af7f788eb07307f556a2a6616Eric Laurent VolumeStreamState.this.mDeathHandlers.add(this); 32123172d5e3e7520a745fa37b71fc1c7bf244b57085Eric Laurent // If the stream is not yet muted by any client, set level to 0 321342b041ed4f184e3af7f788eb07307f556a2a6616Eric Laurent if (!VolumeStreamState.this.isMuted()) { 321442b041ed4f184e3af7f788eb07307f556a2a6616Eric Laurent updateVolume = true; 32153172d5e3e7520a745fa37b71fc1c7bf244b57085Eric Laurent } 32163172d5e3e7520a745fa37b71fc1c7bf244b57085Eric Laurent } catch (RemoteException e) { 32173172d5e3e7520a745fa37b71fc1c7bf244b57085Eric Laurent // Client has died! 32183172d5e3e7520a745fa37b71fc1c7bf244b57085Eric Laurent binderDied(); 32193172d5e3e7520a745fa37b71fc1c7bf244b57085Eric Laurent return; 32203172d5e3e7520a745fa37b71fc1c7bf244b57085Eric Laurent } 32213172d5e3e7520a745fa37b71fc1c7bf244b57085Eric Laurent } else { 32223172d5e3e7520a745fa37b71fc1c7bf244b57085Eric Laurent Log.w(TAG, "stream: "+mStreamType+" was already muted by this client"); 32233172d5e3e7520a745fa37b71fc1c7bf244b57085Eric Laurent } 32243172d5e3e7520a745fa37b71fc1c7bf244b57085Eric Laurent mMuteCount++; 32253172d5e3e7520a745fa37b71fc1c7bf244b57085Eric Laurent } else { 32263172d5e3e7520a745fa37b71fc1c7bf244b57085Eric Laurent if (mMuteCount == 0) { 32273172d5e3e7520a745fa37b71fc1c7bf244b57085Eric Laurent Log.e(TAG, "unexpected unmute for stream: "+mStreamType); 32283172d5e3e7520a745fa37b71fc1c7bf244b57085Eric Laurent } else { 32293172d5e3e7520a745fa37b71fc1c7bf244b57085Eric Laurent mMuteCount--; 32303172d5e3e7520a745fa37b71fc1c7bf244b57085Eric Laurent if (mMuteCount == 0) { 32313172d5e3e7520a745fa37b71fc1c7bf244b57085Eric Laurent // Unregister from client death notification 323242b041ed4f184e3af7f788eb07307f556a2a6616Eric Laurent VolumeStreamState.this.mDeathHandlers.remove(this); 32333172d5e3e7520a745fa37b71fc1c7bf244b57085Eric Laurent // mICallback can be 0 if muted by AudioService 32343172d5e3e7520a745fa37b71fc1c7bf244b57085Eric Laurent if (mICallback != null) { 32353172d5e3e7520a745fa37b71fc1c7bf244b57085Eric Laurent mICallback.unlinkToDeath(this, 0); 32363172d5e3e7520a745fa37b71fc1c7bf244b57085Eric Laurent } 323742b041ed4f184e3af7f788eb07307f556a2a6616Eric Laurent if (!VolumeStreamState.this.isMuted()) { 323842b041ed4f184e3af7f788eb07307f556a2a6616Eric Laurent updateVolume = true; 32399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 32409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 32419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 32429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 324342b041ed4f184e3af7f788eb07307f556a2a6616Eric Laurent if (updateVolume) { 324442b041ed4f184e3af7f788eb07307f556a2a6616Eric Laurent sendMsg(mAudioHandler, 324542b041ed4f184e3af7f788eb07307f556a2a6616Eric Laurent MSG_SET_ALL_VOLUMES, 324642b041ed4f184e3af7f788eb07307f556a2a6616Eric Laurent SENDMSG_QUEUE, 324742b041ed4f184e3af7f788eb07307f556a2a6616Eric Laurent 0, 324842b041ed4f184e3af7f788eb07307f556a2a6616Eric Laurent 0, 324942b041ed4f184e3af7f788eb07307f556a2a6616Eric Laurent VolumeStreamState.this, 0); 325042b041ed4f184e3af7f788eb07307f556a2a6616Eric Laurent } 32519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 32529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 32539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public void binderDied() { 32549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Log.w(TAG, "Volume service client died for stream: "+mStreamType); 32559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (mMuteCount != 0) { 32569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Reset all active mute requests from this client. 32579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mMuteCount = 1; 32589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mute(false); 32599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 32609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 32619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 32629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 32633172d5e3e7520a745fa37b71fc1c7bf244b57085Eric Laurent private synchronized int muteCount() { 32649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int count = 0; 32659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int size = mDeathHandlers.size(); 32669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project for (int i = 0; i < size; i++) { 32679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project count += mDeathHandlers.get(i).mMuteCount; 32689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 32699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return count; 32709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 32719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 327242b041ed4f184e3af7f788eb07307f556a2a6616Eric Laurent private synchronized boolean isMuted() { 327342b041ed4f184e3af7f788eb07307f556a2a6616Eric Laurent return muteCount() != 0; 327442b041ed4f184e3af7f788eb07307f556a2a6616Eric Laurent } 327542b041ed4f184e3af7f788eb07307f556a2a6616Eric Laurent 32763172d5e3e7520a745fa37b71fc1c7bf244b57085Eric Laurent // only called by mute() which is already synchronized 32779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private VolumeDeathHandler getDeathHandler(IBinder cb, boolean state) { 32783172d5e3e7520a745fa37b71fc1c7bf244b57085Eric Laurent VolumeDeathHandler handler; 32793172d5e3e7520a745fa37b71fc1c7bf244b57085Eric Laurent int size = mDeathHandlers.size(); 32803172d5e3e7520a745fa37b71fc1c7bf244b57085Eric Laurent for (int i = 0; i < size; i++) { 32813172d5e3e7520a745fa37b71fc1c7bf244b57085Eric Laurent handler = mDeathHandlers.get(i); 32823172d5e3e7520a745fa37b71fc1c7bf244b57085Eric Laurent if (cb == handler.mICallback) { 32833172d5e3e7520a745fa37b71fc1c7bf244b57085Eric Laurent return handler; 3284ce952c8e13c535bedde77bcdb94dfcc7508475aaMike Lockwood } 3285ce952c8e13c535bedde77bcdb94dfcc7508475aaMike Lockwood } 32863172d5e3e7520a745fa37b71fc1c7bf244b57085Eric Laurent // If this is the first mute request for this client, create a new 32873172d5e3e7520a745fa37b71fc1c7bf244b57085Eric Laurent // client death handler. Otherwise, it is an out of sequence unmute request. 32883172d5e3e7520a745fa37b71fc1c7bf244b57085Eric Laurent if (state) { 32893172d5e3e7520a745fa37b71fc1c7bf244b57085Eric Laurent handler = new VolumeDeathHandler(cb); 32903172d5e3e7520a745fa37b71fc1c7bf244b57085Eric Laurent } else { 32913172d5e3e7520a745fa37b71fc1c7bf244b57085Eric Laurent Log.w(TAG, "stream was not muted by this client"); 32923172d5e3e7520a745fa37b71fc1c7bf244b57085Eric Laurent handler = null; 32933172d5e3e7520a745fa37b71fc1c7bf244b57085Eric Laurent } 32943172d5e3e7520a745fa37b71fc1c7bf244b57085Eric Laurent return handler; 3295ce952c8e13c535bedde77bcdb94dfcc7508475aaMike Lockwood } 3296bffc3d1bd33eb2d8e00a9f8b6261d815db503311Eric Laurent 3297bffc3d1bd33eb2d8e00a9f8b6261d815db503311Eric Laurent private void dump(PrintWriter pw) { 3298dd45d01128423a82652a3c9d77fa393631d95229Eric Laurent pw.print(" Mute count: "); 3299dd45d01128423a82652a3c9d77fa393631d95229Eric Laurent pw.println(muteCount()); 3300bffc3d1bd33eb2d8e00a9f8b6261d815db503311Eric Laurent pw.print(" Current: "); 3301bffc3d1bd33eb2d8e00a9f8b6261d815db503311Eric Laurent Set set = mIndex.entrySet(); 3302bffc3d1bd33eb2d8e00a9f8b6261d815db503311Eric Laurent Iterator i = set.iterator(); 3303bffc3d1bd33eb2d8e00a9f8b6261d815db503311Eric Laurent while (i.hasNext()) { 3304bffc3d1bd33eb2d8e00a9f8b6261d815db503311Eric Laurent Map.Entry entry = (Map.Entry)i.next(); 3305bffc3d1bd33eb2d8e00a9f8b6261d815db503311Eric Laurent pw.print(Integer.toHexString(((Integer)entry.getKey()).intValue()) 3306bffc3d1bd33eb2d8e00a9f8b6261d815db503311Eric Laurent + ": " + ((((Integer)entry.getValue()).intValue() + 5) / 10)+", "); 3307bffc3d1bd33eb2d8e00a9f8b6261d815db503311Eric Laurent } 3308bffc3d1bd33eb2d8e00a9f8b6261d815db503311Eric Laurent } 3309ce952c8e13c535bedde77bcdb94dfcc7508475aaMike Lockwood } 3310ce952c8e13c535bedde77bcdb94dfcc7508475aaMike Lockwood 33119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** Thread that handles native AudioSystem control. */ 33129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private class AudioSystemThread extends Thread { 33139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project AudioSystemThread() { 33149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project super("AudioService"); 33159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 33169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 33179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project @Override 33189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public void run() { 33199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Set this thread up so the handler will work on it 33209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Looper.prepare(); 33219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 33229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project synchronized(AudioService.this) { 33239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mAudioHandler = new AudioHandler(); 33249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 33259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Notify that the handler has been created 33269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project AudioService.this.notify(); 33279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 33289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 33299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Listen for volume change requests that are set by VolumePanel 33309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Looper.loop(); 33319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 33329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 33339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 33349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** Handles internal volume messages in separate volume thread. */ 33359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private class AudioHandler extends Handler { 33369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 33379bc8358ddaa01c3490f9709991989633a6a3dd42Eric Laurent private void setDeviceVolume(VolumeStreamState streamState, int device) { 33389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 33399bc8358ddaa01c3490f9709991989633a6a3dd42Eric Laurent // Apply volume 33409bc8358ddaa01c3490f9709991989633a6a3dd42Eric Laurent streamState.applyDeviceVolume(device); 3341a553c25b33c99b345cf1c8688f8df0ed8df14e5aEric Laurent 3342a553c25b33c99b345cf1c8688f8df0ed8df14e5aEric Laurent // Apply change to all streams using this one as alias 3343a553c25b33c99b345cf1c8688f8df0ed8df14e5aEric Laurent int numStreamTypes = AudioSystem.getNumStreamTypes(); 3344a553c25b33c99b345cf1c8688f8df0ed8df14e5aEric Laurent for (int streamType = numStreamTypes - 1; streamType >= 0; streamType--) { 3345a553c25b33c99b345cf1c8688f8df0ed8df14e5aEric Laurent if (streamType != streamState.mStreamType && 33466d5176638c2189595cede38fb92c3e7e8700e221Eric Laurent mStreamVolumeAlias[streamType] == streamState.mStreamType) { 3347cd772d04345850e160a45613fcf6b86da0dce4cfEric Laurent // Make sure volume is also maxed out on A2DP device for aliased stream 3348cd772d04345850e160a45613fcf6b86da0dce4cfEric Laurent // that may have a different device selected 3349cd772d04345850e160a45613fcf6b86da0dce4cfEric Laurent int streamDevice = getDeviceForStream(streamType); 3350cd772d04345850e160a45613fcf6b86da0dce4cfEric Laurent if ((device != streamDevice) && mAvrcpAbsVolSupported && 3351cd772d04345850e160a45613fcf6b86da0dce4cfEric Laurent ((device & AudioSystem.DEVICE_OUT_ALL_A2DP) != 0)) { 3352cd772d04345850e160a45613fcf6b86da0dce4cfEric Laurent mStreamStates[streamType].applyDeviceVolume(device); 3353cd772d04345850e160a45613fcf6b86da0dce4cfEric Laurent } 3354cd772d04345850e160a45613fcf6b86da0dce4cfEric Laurent mStreamStates[streamType].applyDeviceVolume(streamDevice); 3355a553c25b33c99b345cf1c8688f8df0ed8df14e5aEric Laurent } 3356a553c25b33c99b345cf1c8688f8df0ed8df14e5aEric Laurent } 33579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 33589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Post a persist volume msg 3359afbb047c3945e9c2b7e9bc6b25098d5fb80bba4eEric Laurent sendMsg(mAudioHandler, 3360afbb047c3945e9c2b7e9bc6b25098d5fb80bba4eEric Laurent MSG_PERSIST_VOLUME, 336198ad9b9d6fd34aad487933170f50b5519313df61Eric Laurent SENDMSG_QUEUE, 33629bc8358ddaa01c3490f9709991989633a6a3dd42Eric Laurent device, 336342b041ed4f184e3af7f788eb07307f556a2a6616Eric Laurent 0, 3364afbb047c3945e9c2b7e9bc6b25098d5fb80bba4eEric Laurent streamState, 3365afbb047c3945e9c2b7e9bc6b25098d5fb80bba4eEric Laurent PERSIST_DELAY); 3366afbb047c3945e9c2b7e9bc6b25098d5fb80bba4eEric Laurent 33679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 33689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 33699bc8358ddaa01c3490f9709991989633a6a3dd42Eric Laurent private void setAllVolumes(VolumeStreamState streamState) { 33709bc8358ddaa01c3490f9709991989633a6a3dd42Eric Laurent 33719bc8358ddaa01c3490f9709991989633a6a3dd42Eric Laurent // Apply volume 33729bc8358ddaa01c3490f9709991989633a6a3dd42Eric Laurent streamState.applyAllVolumes(); 33739bc8358ddaa01c3490f9709991989633a6a3dd42Eric Laurent 33749bc8358ddaa01c3490f9709991989633a6a3dd42Eric Laurent // Apply change to all streams using this one as alias 33759bc8358ddaa01c3490f9709991989633a6a3dd42Eric Laurent int numStreamTypes = AudioSystem.getNumStreamTypes(); 33769bc8358ddaa01c3490f9709991989633a6a3dd42Eric Laurent for (int streamType = numStreamTypes - 1; streamType >= 0; streamType--) { 33779bc8358ddaa01c3490f9709991989633a6a3dd42Eric Laurent if (streamType != streamState.mStreamType && 33786d5176638c2189595cede38fb92c3e7e8700e221Eric Laurent mStreamVolumeAlias[streamType] == streamState.mStreamType) { 33799bc8358ddaa01c3490f9709991989633a6a3dd42Eric Laurent mStreamStates[streamType].applyAllVolumes(); 33809bc8358ddaa01c3490f9709991989633a6a3dd42Eric Laurent } 33819bc8358ddaa01c3490f9709991989633a6a3dd42Eric Laurent } 33829bc8358ddaa01c3490f9709991989633a6a3dd42Eric Laurent } 33839bc8358ddaa01c3490f9709991989633a6a3dd42Eric Laurent 338442b041ed4f184e3af7f788eb07307f556a2a6616Eric Laurent private void persistVolume(VolumeStreamState streamState, int device) { 338583a017b6b7c099d1a0293e5839be6477325aef06Eric Laurent if (mUseFixedVolume) { 338683a017b6b7c099d1a0293e5839be6477325aef06Eric Laurent return; 338783a017b6b7c099d1a0293e5839be6477325aef06Eric Laurent } 338842b041ed4f184e3af7f788eb07307f556a2a6616Eric Laurent System.putIntForUser(mContentResolver, 338942b041ed4f184e3af7f788eb07307f556a2a6616Eric Laurent streamState.getSettingNameForDevice(device), 339042b041ed4f184e3af7f788eb07307f556a2a6616Eric Laurent (streamState.getIndex(device) + 5)/ 10, 339142b041ed4f184e3af7f788eb07307f556a2a6616Eric Laurent UserHandle.USER_CURRENT); 33929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 33939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3394ba195ebc76f23b6679443724ab58c9dc9f2df884Glenn Kasten private void persistRingerMode(int ringerMode) { 339583a017b6b7c099d1a0293e5839be6477325aef06Eric Laurent if (mUseFixedVolume) { 339683a017b6b7c099d1a0293e5839be6477325aef06Eric Laurent return; 339783a017b6b7c099d1a0293e5839be6477325aef06Eric Laurent } 33988d9a1f66d9d3dbbd45a56d441a746ec11dba7645Jeff Sharkey Settings.Global.putInt(mContentResolver, Settings.Global.MODE_RINGER, ringerMode); 33999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 34009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 34015d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent private boolean onLoadSoundEffects() { 34025d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent int status; 34035d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent 34045d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent synchronized (mSoundEffectsLock) { 34054a5eeb9c727d77bb57fef87a70c8c9cc23dbfee3Eric Laurent if (!mSystemReady) { 34065d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent Log.w(TAG, "onLoadSoundEffects() called before boot complete"); 34075d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent return false; 34085d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent } 34095d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent 34105d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent if (mSoundPool != null) { 34115d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent return true; 34125d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent } 34135d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent 34145d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent loadTouchSoundAssets(); 34155d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent 34165d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent mSoundPool = new SoundPool(NUM_SOUNDPOOL_CHANNELS, AudioSystem.STREAM_SYSTEM, 0); 34175d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent mSoundPoolCallBack = null; 34185d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent mSoundPoolListenerThread = new SoundPoolListenerThread(); 34195d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent mSoundPoolListenerThread.start(); 34205d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent int attempts = 3; 34215d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent while ((mSoundPoolCallBack == null) && (attempts-- > 0)) { 34225d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent try { 34235d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent // Wait for mSoundPoolCallBack to be set by the other thread 3424167d1a27713ab64cd3c0aa70de96434083ef0400Glenn Kasten mSoundEffectsLock.wait(SOUND_EFFECTS_LOAD_TIMEOUT_MS); 34255d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent } catch (InterruptedException e) { 34265d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent Log.w(TAG, "Interrupted while waiting sound pool listener thread."); 34275d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent } 34285d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent } 34295d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent 34305d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent if (mSoundPoolCallBack == null) { 34315d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent Log.w(TAG, "onLoadSoundEffects() SoundPool listener or thread creation error"); 34325d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent if (mSoundPoolLooper != null) { 34335d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent mSoundPoolLooper.quit(); 34345d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent mSoundPoolLooper = null; 34355d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent } 34365d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent mSoundPoolListenerThread = null; 34375d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent mSoundPool.release(); 34385d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent mSoundPool = null; 34395d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent return false; 34405d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent } 34415d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent /* 34425d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent * poolId table: The value -1 in this table indicates that corresponding 34435d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent * file (same index in SOUND_EFFECT_FILES[] has not been loaded. 34445d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent * Once loaded, the value in poolId is the sample ID and the same 34455d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent * sample can be reused for another effect using the same file. 34465d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent */ 34475d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent int[] poolId = new int[SOUND_EFFECT_FILES.size()]; 34485d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent for (int fileIdx = 0; fileIdx < SOUND_EFFECT_FILES.size(); fileIdx++) { 34495d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent poolId[fileIdx] = -1; 34505d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent } 34515d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent /* 34525d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent * Effects whose value in SOUND_EFFECT_FILES_MAP[effect][1] is -1 must be loaded. 34535d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent * If load succeeds, value in SOUND_EFFECT_FILES_MAP[effect][1] is > 0: 34545d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent * this indicates we have a valid sample loaded for this effect. 34555d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent */ 34565d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent 34575d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent int numSamples = 0; 34585d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent for (int effect = 0; effect < AudioManager.NUM_SOUND_EFFECTS; effect++) { 34595d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent // Do not load sample if this effect uses the MediaPlayer 34605d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent if (SOUND_EFFECT_FILES_MAP[effect][1] == 0) { 34615d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent continue; 34625d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent } 34635d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent if (poolId[SOUND_EFFECT_FILES_MAP[effect][0]] == -1) { 34645d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent String filePath = Environment.getRootDirectory() 34655d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent + SOUND_EFFECTS_PATH 34665d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent + SOUND_EFFECT_FILES.get(SOUND_EFFECT_FILES_MAP[effect][0]); 34675d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent int sampleId = mSoundPool.load(filePath, 0); 34685d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent if (sampleId <= 0) { 34695d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent Log.w(TAG, "Soundpool could not load file: "+filePath); 34705d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent } else { 34715d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent SOUND_EFFECT_FILES_MAP[effect][1] = sampleId; 34725d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent poolId[SOUND_EFFECT_FILES_MAP[effect][0]] = sampleId; 34735d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent numSamples++; 34745d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent } 34755d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent } else { 34765d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent SOUND_EFFECT_FILES_MAP[effect][1] = 34775d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent poolId[SOUND_EFFECT_FILES_MAP[effect][0]]; 34785d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent } 34795d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent } 34805d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent // wait for all samples to be loaded 34815d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent if (numSamples > 0) { 34825d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent mSoundPoolCallBack.setSamples(poolId); 34835d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent 34845d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent attempts = 3; 34855d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent status = 1; 34865d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent while ((status == 1) && (attempts-- > 0)) { 34875d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent try { 3488167d1a27713ab64cd3c0aa70de96434083ef0400Glenn Kasten mSoundEffectsLock.wait(SOUND_EFFECTS_LOAD_TIMEOUT_MS); 34895d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent status = mSoundPoolCallBack.status(); 34905d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent } catch (InterruptedException e) { 34915d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent Log.w(TAG, "Interrupted while waiting sound pool callback."); 34925d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent } 34935d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent } 34945d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent } else { 34955d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent status = -1; 34965d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent } 34975d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent 34985d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent if (mSoundPoolLooper != null) { 34995d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent mSoundPoolLooper.quit(); 35005d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent mSoundPoolLooper = null; 35015d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent } 35025d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent mSoundPoolListenerThread = null; 35035d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent if (status != 0) { 35045d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent Log.w(TAG, 35055d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent "onLoadSoundEffects(), Error "+status+ " while loading samples"); 35065d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent for (int effect = 0; effect < AudioManager.NUM_SOUND_EFFECTS; effect++) { 35075d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent if (SOUND_EFFECT_FILES_MAP[effect][1] > 0) { 35085d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent SOUND_EFFECT_FILES_MAP[effect][1] = -1; 35095d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent } 35105d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent } 35115d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent 35125d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent mSoundPool.release(); 35135d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent mSoundPool = null; 35145d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent } 35155d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent } 35165d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent return (status == 0); 35175d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent } 35185d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent 35195d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent /** 35205d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent * Unloads samples from the sound pool. 35215d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent * This method can be called to free some memory when 35225d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent * sound effects are disabled. 35235d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent */ 35245d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent private void onUnloadSoundEffects() { 35255d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent synchronized (mSoundEffectsLock) { 35265d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent if (mSoundPool == null) { 35275d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent return; 35285d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent } 35295d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent 35305d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent int[] poolId = new int[SOUND_EFFECT_FILES.size()]; 35315d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent for (int fileIdx = 0; fileIdx < SOUND_EFFECT_FILES.size(); fileIdx++) { 35325d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent poolId[fileIdx] = 0; 35335d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent } 35345d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent 35355d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent for (int effect = 0; effect < AudioManager.NUM_SOUND_EFFECTS; effect++) { 35365d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent if (SOUND_EFFECT_FILES_MAP[effect][1] <= 0) { 35375d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent continue; 35385d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent } 35395d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent if (poolId[SOUND_EFFECT_FILES_MAP[effect][0]] == 0) { 35405d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent mSoundPool.unload(SOUND_EFFECT_FILES_MAP[effect][1]); 35415d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent SOUND_EFFECT_FILES_MAP[effect][1] = -1; 35425d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent poolId[SOUND_EFFECT_FILES_MAP[effect][0]] = -1; 35435d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent } 35445d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent } 35455d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent mSoundPool.release(); 35465d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent mSoundPool = null; 35475d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent } 35485d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent } 35495d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent 35505d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent private void onPlaySoundEffect(int effectType, int volume) { 35519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project synchronized (mSoundEffectsLock) { 35525d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent 35535d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent onLoadSoundEffects(); 35545d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent 35559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (mSoundPool == null) { 35569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return; 35579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3558a2ef57dba9ac77d8eccacd646b2b8a8d99fe9d8bEric Laurent float volFloat; 355925101b0b9a84571ead15b26e9f4cd9c4298d7823Eric Laurent // use default if volume is not specified by caller 3560a2ef57dba9ac77d8eccacd646b2b8a8d99fe9d8bEric Laurent if (volume < 0) { 3561f2b0c11f4e797e183131261724d8de310dac5431Jean-Michel Trivi volFloat = (float)Math.pow(10, (float)sSoundEffectVolumeDb/20); 3562a2ef57dba9ac77d8eccacd646b2b8a8d99fe9d8bEric Laurent } else { 35638a2cfc309ab9126e90022916967c65a793c034f0RoboErik volFloat = volume / 1000.0f; 3564a2ef57dba9ac77d8eccacd646b2b8a8d99fe9d8bEric Laurent } 35659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 35669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (SOUND_EFFECT_FILES_MAP[effectType][1] > 0) { 35675d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent mSoundPool.play(SOUND_EFFECT_FILES_MAP[effectType][1], 35685d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent volFloat, volFloat, 0, 0, 1.0f); 35699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else { 35709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project MediaPlayer mediaPlayer = new MediaPlayer(); 357162b9aec7a0a4e1cf8cfec7e39ea3103ab510d72eGlenn Kasten try { 3572e78fced559d879b2e37b610d0d9a89daf08f0f2bEric Laurent String filePath = Environment.getRootDirectory() + SOUND_EFFECTS_PATH + 3573e78fced559d879b2e37b610d0d9a89daf08f0f2bEric Laurent SOUND_EFFECT_FILES.get(SOUND_EFFECT_FILES_MAP[effectType][0]); 357462b9aec7a0a4e1cf8cfec7e39ea3103ab510d72eGlenn Kasten mediaPlayer.setDataSource(filePath); 357562b9aec7a0a4e1cf8cfec7e39ea3103ab510d72eGlenn Kasten mediaPlayer.setAudioStreamType(AudioSystem.STREAM_SYSTEM); 357662b9aec7a0a4e1cf8cfec7e39ea3103ab510d72eGlenn Kasten mediaPlayer.prepare(); 3577068225de0197df07a0247b2877666ea91c22c992Glenn Kasten mediaPlayer.setVolume(volFloat); 357862b9aec7a0a4e1cf8cfec7e39ea3103ab510d72eGlenn Kasten mediaPlayer.setOnCompletionListener(new OnCompletionListener() { 357962b9aec7a0a4e1cf8cfec7e39ea3103ab510d72eGlenn Kasten public void onCompletion(MediaPlayer mp) { 358062b9aec7a0a4e1cf8cfec7e39ea3103ab510d72eGlenn Kasten cleanupPlayer(mp); 358162b9aec7a0a4e1cf8cfec7e39ea3103ab510d72eGlenn Kasten } 358262b9aec7a0a4e1cf8cfec7e39ea3103ab510d72eGlenn Kasten }); 358362b9aec7a0a4e1cf8cfec7e39ea3103ab510d72eGlenn Kasten mediaPlayer.setOnErrorListener(new OnErrorListener() { 358462b9aec7a0a4e1cf8cfec7e39ea3103ab510d72eGlenn Kasten public boolean onError(MediaPlayer mp, int what, int extra) { 358562b9aec7a0a4e1cf8cfec7e39ea3103ab510d72eGlenn Kasten cleanupPlayer(mp); 358662b9aec7a0a4e1cf8cfec7e39ea3103ab510d72eGlenn Kasten return true; 358762b9aec7a0a4e1cf8cfec7e39ea3103ab510d72eGlenn Kasten } 358862b9aec7a0a4e1cf8cfec7e39ea3103ab510d72eGlenn Kasten }); 358962b9aec7a0a4e1cf8cfec7e39ea3103ab510d72eGlenn Kasten mediaPlayer.start(); 359062b9aec7a0a4e1cf8cfec7e39ea3103ab510d72eGlenn Kasten } catch (IOException ex) { 359162b9aec7a0a4e1cf8cfec7e39ea3103ab510d72eGlenn Kasten Log.w(TAG, "MediaPlayer IOException: "+ex); 359262b9aec7a0a4e1cf8cfec7e39ea3103ab510d72eGlenn Kasten } catch (IllegalArgumentException ex) { 359362b9aec7a0a4e1cf8cfec7e39ea3103ab510d72eGlenn Kasten Log.w(TAG, "MediaPlayer IllegalArgumentException: "+ex); 359462b9aec7a0a4e1cf8cfec7e39ea3103ab510d72eGlenn Kasten } catch (IllegalStateException ex) { 359562b9aec7a0a4e1cf8cfec7e39ea3103ab510d72eGlenn Kasten Log.w(TAG, "MediaPlayer IllegalStateException: "+ex); 35969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 35979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 35989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 35999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 36009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 36019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private void cleanupPlayer(MediaPlayer mp) { 36029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (mp != null) { 36039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project try { 36049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mp.stop(); 36059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mp.release(); 36069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } catch (IllegalStateException ex) { 36079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Log.w(TAG, "MediaPlayer IllegalStateException: "+ex); 36089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 36099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 36109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 36119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3612fa640154f1f42121d81242b2f1a10f03e52f0014Eric Laurent private void setForceUse(int usage, int config) { 3613fa640154f1f42121d81242b2f1a10f03e52f0014Eric Laurent AudioSystem.setForceUse(usage, config); 3614fa640154f1f42121d81242b2f1a10f03e52f0014Eric Laurent } 3615fa640154f1f42121d81242b2f1a10f03e52f0014Eric Laurent 361605274f348e12983eb8613cc6eb9ae561e8197e28Eric Laurent private void onPersistSafeVolumeState(int state) { 361705274f348e12983eb8613cc6eb9ae561e8197e28Eric Laurent Settings.Global.putInt(mContentResolver, 361805274f348e12983eb8613cc6eb9ae561e8197e28Eric Laurent Settings.Global.AUDIO_SAFE_VOLUME_STATE, 361905274f348e12983eb8613cc6eb9ae561e8197e28Eric Laurent state); 362005274f348e12983eb8613cc6eb9ae561e8197e28Eric Laurent } 362105274f348e12983eb8613cc6eb9ae561e8197e28Eric Laurent 36229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project @Override 36239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public void handleMessage(Message msg) { 36249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3625afbb047c3945e9c2b7e9bc6b25098d5fb80bba4eEric Laurent switch (msg.what) { 36269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 36279bc8358ddaa01c3490f9709991989633a6a3dd42Eric Laurent case MSG_SET_DEVICE_VOLUME: 36289bc8358ddaa01c3490f9709991989633a6a3dd42Eric Laurent setDeviceVolume((VolumeStreamState) msg.obj, msg.arg1); 36299bc8358ddaa01c3490f9709991989633a6a3dd42Eric Laurent break; 36309bc8358ddaa01c3490f9709991989633a6a3dd42Eric Laurent 36319bc8358ddaa01c3490f9709991989633a6a3dd42Eric Laurent case MSG_SET_ALL_VOLUMES: 36329bc8358ddaa01c3490f9709991989633a6a3dd42Eric Laurent setAllVolumes((VolumeStreamState) msg.obj); 36339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project break; 36349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 36359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project case MSG_PERSIST_VOLUME: 363642b041ed4f184e3af7f788eb07307f556a2a6616Eric Laurent persistVolume((VolumeStreamState) msg.obj, msg.arg1); 36379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project break; 36389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 36395c55a051ad7d86a464fb91426f1ea3c0250e38b3Mike Lockwood case MSG_PERSIST_MASTER_VOLUME: 364083a017b6b7c099d1a0293e5839be6477325aef06Eric Laurent if (mUseFixedVolume) { 364183a017b6b7c099d1a0293e5839be6477325aef06Eric Laurent return; 364283a017b6b7c099d1a0293e5839be6477325aef06Eric Laurent } 3643bc0fab1fc2db832ef86d8a33466ec4d68b103ca0Eric Laurent Settings.System.putFloatForUser(mContentResolver, 3644bc0fab1fc2db832ef86d8a33466ec4d68b103ca0Eric Laurent Settings.System.VOLUME_MASTER, 36458a2cfc309ab9126e90022916967c65a793c034f0RoboErik msg.arg1 / (float)1000.0, 3646bc0fab1fc2db832ef86d8a33466ec4d68b103ca0Eric Laurent UserHandle.USER_CURRENT); 36475c55a051ad7d86a464fb91426f1ea3c0250e38b3Mike Lockwood break; 36485c55a051ad7d86a464fb91426f1ea3c0250e38b3Mike Lockwood 364957978ed86286a33d5b1a0fd000ca3406ba9d87b3Justin Koh case MSG_PERSIST_MASTER_VOLUME_MUTE: 365083a017b6b7c099d1a0293e5839be6477325aef06Eric Laurent if (mUseFixedVolume) { 365183a017b6b7c099d1a0293e5839be6477325aef06Eric Laurent return; 365283a017b6b7c099d1a0293e5839be6477325aef06Eric Laurent } 3653bc0fab1fc2db832ef86d8a33466ec4d68b103ca0Eric Laurent Settings.System.putIntForUser(mContentResolver, 3654bc0fab1fc2db832ef86d8a33466ec4d68b103ca0Eric Laurent Settings.System.VOLUME_MASTER_MUTE, 3655bc0fab1fc2db832ef86d8a33466ec4d68b103ca0Eric Laurent msg.arg1, 3656bc0fab1fc2db832ef86d8a33466ec4d68b103ca0Eric Laurent UserHandle.USER_CURRENT); 365757978ed86286a33d5b1a0fd000ca3406ba9d87b3Justin Koh break; 365857978ed86286a33d5b1a0fd000ca3406ba9d87b3Justin Koh 36599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project case MSG_PERSIST_RINGER_MODE: 3660ba195ebc76f23b6679443724ab58c9dc9f2df884Glenn Kasten // note that the value persisted is the current ringer mode, not the 3661ba195ebc76f23b6679443724ab58c9dc9f2df884Glenn Kasten // value of ringer mode as of the time the request was made to persist 3662ba195ebc76f23b6679443724ab58c9dc9f2df884Glenn Kasten persistRingerMode(getRingerMode()); 36639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project break; 36649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 36659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project case MSG_MEDIA_SERVER_DIED: 3666dfb881f96af7898151940a4bbc52e45e6043d38bEric Laurent if (AudioSystem.checkAudioFlinger() != AudioSystem.AUDIO_STATUS_OK) { 366789e74ba1419732dd5c7f939e48d4aa7989fd3a51Eric Laurent Log.e(TAG, "Media server died."); 3668afbb047c3945e9c2b7e9bc6b25098d5fb80bba4eEric Laurent sendMsg(mAudioHandler, MSG_MEDIA_SERVER_DIED, SENDMSG_NOOP, 0, 0, 366989e74ba1419732dd5c7f939e48d4aa7989fd3a51Eric Laurent null, 500); 3670dfb881f96af7898151940a4bbc52e45e6043d38bEric Laurent break; 367189e74ba1419732dd5c7f939e48d4aa7989fd3a51Eric Laurent } 36729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Log.e(TAG, "Media server started."); 3673dfb881f96af7898151940a4bbc52e45e6043d38bEric Laurent 36743c652ca5a546e7227a5f4bdbf0f81552b2c91383Eric Laurent // indicate to audio HAL that we start the reconfiguration phase after a media 36753c652ca5a546e7227a5f4bdbf0f81552b2c91383Eric Laurent // server crash 3676dfb881f96af7898151940a4bbc52e45e6043d38bEric Laurent // Note that we only execute this when the media server 36773c652ca5a546e7227a5f4bdbf0f81552b2c91383Eric Laurent // process restarts after a crash, not the first time it is started. 36783c652ca5a546e7227a5f4bdbf0f81552b2c91383Eric Laurent AudioSystem.setParameters("restarting=true"); 36793c652ca5a546e7227a5f4bdbf0f81552b2c91383Eric Laurent 3680fd116ad1ab02f6060a0b2201f018317fa32e28b4Glenn Kasten readAndSetLowRamDevice(); 3681fd116ad1ab02f6060a0b2201f018317fa32e28b4Glenn Kasten 3682c42ac9d4d03f62c3a1ba197a28a81fda44bd8b7fEric Laurent // Restore device connection states 36836bc7f2cd30b6bd90806942b0722e22daa2108493Eric Laurent synchronized (mConnectedDevices) { 36846bc7f2cd30b6bd90806942b0722e22daa2108493Eric Laurent Set set = mConnectedDevices.entrySet(); 36856bc7f2cd30b6bd90806942b0722e22daa2108493Eric Laurent Iterator i = set.iterator(); 36869bc8358ddaa01c3490f9709991989633a6a3dd42Eric Laurent while (i.hasNext()) { 36876bc7f2cd30b6bd90806942b0722e22daa2108493Eric Laurent Map.Entry device = (Map.Entry)i.next(); 36886bc7f2cd30b6bd90806942b0722e22daa2108493Eric Laurent AudioSystem.setDeviceConnectionState( 36896bc7f2cd30b6bd90806942b0722e22daa2108493Eric Laurent ((Integer)device.getKey()).intValue(), 36906bc7f2cd30b6bd90806942b0722e22daa2108493Eric Laurent AudioSystem.DEVICE_STATE_AVAILABLE, 36916bc7f2cd30b6bd90806942b0722e22daa2108493Eric Laurent (String)device.getValue()); 36926bc7f2cd30b6bd90806942b0722e22daa2108493Eric Laurent } 3693c42ac9d4d03f62c3a1ba197a28a81fda44bd8b7fEric Laurent } 3694c42ac9d4d03f62c3a1ba197a28a81fda44bd8b7fEric Laurent // Restore call state 3695c42ac9d4d03f62c3a1ba197a28a81fda44bd8b7fEric Laurent AudioSystem.setPhoneState(mMode); 3696c42ac9d4d03f62c3a1ba197a28a81fda44bd8b7fEric Laurent 3697d5603c126acdd94d9f7400bb1d04188020a425b4Eric Laurent // Restore forced usage for communcations and record 3698c42ac9d4d03f62c3a1ba197a28a81fda44bd8b7fEric Laurent AudioSystem.setForceUse(AudioSystem.FOR_COMMUNICATION, mForcedUseForComm); 3699d5603c126acdd94d9f7400bb1d04188020a425b4Eric Laurent AudioSystem.setForceUse(AudioSystem.FOR_RECORD, mForcedUseForComm); 3700dd45d01128423a82652a3c9d77fa393631d95229Eric Laurent AudioSystem.setForceUse(AudioSystem.FOR_SYSTEM, mCameraSoundForced ? 3701dd45d01128423a82652a3c9d77fa393631d95229Eric Laurent AudioSystem.FORCE_SYSTEM_ENFORCED : AudioSystem.FORCE_NONE); 3702c42ac9d4d03f62c3a1ba197a28a81fda44bd8b7fEric Laurent 3703a553c25b33c99b345cf1c8688f8df0ed8df14e5aEric Laurent // Restore stream volumes 37049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int numStreamTypes = AudioSystem.getNumStreamTypes(); 37059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project for (int streamType = numStreamTypes - 1; streamType >= 0; streamType--) { 37069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project VolumeStreamState streamState = mStreamStates[streamType]; 3707c42ac9d4d03f62c3a1ba197a28a81fda44bd8b7fEric Laurent AudioSystem.initStreamVolume(streamType, 0, (streamState.mIndexMax + 5) / 10); 37089bc8358ddaa01c3490f9709991989633a6a3dd42Eric Laurent 37099bc8358ddaa01c3490f9709991989633a6a3dd42Eric Laurent streamState.applyAllVolumes(); 37109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3711c42ac9d4d03f62c3a1ba197a28a81fda44bd8b7fEric Laurent 3712c42ac9d4d03f62c3a1ba197a28a81fda44bd8b7fEric Laurent // Restore ringer mode 3713c42ac9d4d03f62c3a1ba197a28a81fda44bd8b7fEric Laurent setRingerModeInt(getRingerMode(), false); 37143c652ca5a546e7227a5f4bdbf0f81552b2c91383Eric Laurent 37159063154a793b0ab38b3c5992cbaed046427b4a82Mike Lockwood // Restore master volume 37169063154a793b0ab38b3c5992cbaed046427b4a82Mike Lockwood restoreMasterVolume(); 37179063154a793b0ab38b3c5992cbaed046427b4a82Mike Lockwood 3718f26f01784e1c733c53cad3ed31918e73448ce369Jean-Michel Trivi // Reset device orientation (if monitored for this device) 3719d640bd325c3be9a350058c835b880a7e0b40dc60Eric Laurent if (mMonitorOrientation) { 3720f26f01784e1c733c53cad3ed31918e73448ce369Jean-Michel Trivi setOrientationForAudioSystem(); 3721f26f01784e1c733c53cad3ed31918e73448ce369Jean-Michel Trivi } 3722bb6f8711a7f804d39c45218db2d6339940cc5d35Jean-Michel Trivi if (mMonitorRotation) { 3723bb6f8711a7f804d39c45218db2d6339940cc5d35Jean-Michel Trivi setRotationForAudioSystem(); 3724bb6f8711a7f804d39c45218db2d6339940cc5d35Jean-Michel Trivi } 3725f26f01784e1c733c53cad3ed31918e73448ce369Jean-Michel Trivi 37267847211fb4699bf6018e29d214a918ed6657319bEric Laurent synchronized (mBluetoothA2dpEnabledLock) { 37277847211fb4699bf6018e29d214a918ed6657319bEric Laurent AudioSystem.setForceUse(AudioSystem.FOR_MEDIA, 37287847211fb4699bf6018e29d214a918ed6657319bEric Laurent mBluetoothA2dpEnabled ? 37297847211fb4699bf6018e29d214a918ed6657319bEric Laurent AudioSystem.FORCE_NONE : AudioSystem.FORCE_NO_BT_A2DP); 37307847211fb4699bf6018e29d214a918ed6657319bEric Laurent } 3731bff5ca576ef55bfdd51a0d2ff39f4bac614fa728Eric Laurent 3732bff5ca576ef55bfdd51a0d2ff39f4bac614fa728Eric Laurent synchronized (mSettingsLock) { 3733bff5ca576ef55bfdd51a0d2ff39f4bac614fa728Eric Laurent AudioSystem.setForceUse(AudioSystem.FOR_DOCK, 3734bff5ca576ef55bfdd51a0d2ff39f4bac614fa728Eric Laurent mDockAudioMediaEnabled ? 3735bff5ca576ef55bfdd51a0d2ff39f4bac614fa728Eric Laurent AudioSystem.FORCE_ANALOG_DOCK : AudioSystem.FORCE_NONE); 3736bff5ca576ef55bfdd51a0d2ff39f4bac614fa728Eric Laurent } 3737bff5ca576ef55bfdd51a0d2ff39f4bac614fa728Eric Laurent 37383c652ca5a546e7227a5f4bdbf0f81552b2c91383Eric Laurent // indicate the end of reconfiguration phase to audio HAL 37393c652ca5a546e7227a5f4bdbf0f81552b2c91383Eric Laurent AudioSystem.setParameters("restarting=false"); 37409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project break; 37419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 37425d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent case MSG_UNLOAD_SOUND_EFFECTS: 37435d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent onUnloadSoundEffects(); 37445d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent break; 37455d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent 3746117b7bb5b5a4457711f59bde3dcc83d8f111c524Eric Laurent case MSG_LOAD_SOUND_EFFECTS: 37475d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent //FIXME: onLoadSoundEffects() should be executed in a separate thread as it 37485d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent // can take several dozens of milliseconds to complete 37495d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent boolean loaded = onLoadSoundEffects(); 37505d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent if (msg.obj != null) { 37515d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent LoadSoundEffectReply reply = (LoadSoundEffectReply)msg.obj; 37525d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent synchronized (reply) { 37535d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent reply.mStatus = loaded ? 0 : -1; 37545d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent reply.notify(); 37555d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent } 37565d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent } 3757117b7bb5b5a4457711f59bde3dcc83d8f111c524Eric Laurent break; 3758117b7bb5b5a4457711f59bde3dcc83d8f111c524Eric Laurent 37599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project case MSG_PLAY_SOUND_EFFECT: 37605d3eb44a749ece55ce345f9d8ac608fc3715f9daEric Laurent onPlaySoundEffect(msg.arg1, msg.arg2); 37619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project break; 37624c637b9e34f4c8db69a64ad21a4e2bcfa7485b5fJean-Michel Trivi 37634c637b9e34f4c8db69a64ad21a4e2bcfa7485b5fJean-Michel Trivi case MSG_BTA2DP_DOCK_TIMEOUT: 37644c637b9e34f4c8db69a64ad21a4e2bcfa7485b5fJean-Michel Trivi // msg.obj == address of BTA2DP device 37656bc7f2cd30b6bd90806942b0722e22daa2108493Eric Laurent synchronized (mConnectedDevices) { 37666bc7f2cd30b6bd90806942b0722e22daa2108493Eric Laurent makeA2dpDeviceUnavailableNow( (String) msg.obj ); 37676bc7f2cd30b6bd90806942b0722e22daa2108493Eric Laurent } 37684c637b9e34f4c8db69a64ad21a4e2bcfa7485b5fJean-Michel Trivi break; 3769fa640154f1f42121d81242b2f1a10f03e52f0014Eric Laurent 3770fa640154f1f42121d81242b2f1a10f03e52f0014Eric Laurent case MSG_SET_FORCE_USE: 3771c390bed06b4a572e273ead1254da9a932e04dce3Eric Laurent case MSG_SET_FORCE_BT_A2DP_USE: 3772fa640154f1f42121d81242b2f1a10f03e52f0014Eric Laurent setForceUse(msg.arg1, msg.arg2); 3773fa640154f1f42121d81242b2f1a10f03e52f0014Eric Laurent break; 3774d589fea865e90859324f00d21765fa7d7759e465Jean-Michel Trivi 3775dc03c61fe3cd8d0805480e48a974986439977a60Eric Laurent case MSG_BT_HEADSET_CNCT_FAILED: 3776dc03c61fe3cd8d0805480e48a974986439977a60Eric Laurent resetBluetoothSco(); 3777dc03c61fe3cd8d0805480e48a974986439977a60Eric Laurent break; 3778b1fbaaccb656ef09a8770c28df15e3e91a452e64Eric Laurent 3779b1fbaaccb656ef09a8770c28df15e3e91a452e64Eric Laurent case MSG_SET_WIRED_DEVICE_CONNECTION_STATE: 3780b1fbaaccb656ef09a8770c28df15e3e91a452e64Eric Laurent onSetWiredDeviceConnectionState(msg.arg1, msg.arg2, (String)msg.obj); 3781fa9a69805b001034aa04c3b33989a7ac21522371Jean-Michel Trivi mAudioEventWakeLock.release(); 3782b1fbaaccb656ef09a8770c28df15e3e91a452e64Eric Laurent break; 3783b1fbaaccb656ef09a8770c28df15e3e91a452e64Eric Laurent 37840a40ec2192e4836b2fcb6ba51a7688aa6bd4ee98Mike Lockwood case MSG_SET_A2DP_SRC_CONNECTION_STATE: 37850a40ec2192e4836b2fcb6ba51a7688aa6bd4ee98Mike Lockwood onSetA2dpSourceConnectionState((BluetoothDevice)msg.obj, msg.arg1); 37860a40ec2192e4836b2fcb6ba51a7688aa6bd4ee98Mike Lockwood mAudioEventWakeLock.release(); 37870a40ec2192e4836b2fcb6ba51a7688aa6bd4ee98Mike Lockwood break; 37880a40ec2192e4836b2fcb6ba51a7688aa6bd4ee98Mike Lockwood 37890a40ec2192e4836b2fcb6ba51a7688aa6bd4ee98Mike Lockwood case MSG_SET_A2DP_SINK_CONNECTION_STATE: 37900a40ec2192e4836b2fcb6ba51a7688aa6bd4ee98Mike Lockwood onSetA2dpSinkConnectionState((BluetoothDevice)msg.obj, msg.arg1); 3791fa9a69805b001034aa04c3b33989a7ac21522371Jean-Michel Trivi mAudioEventWakeLock.release(); 3792b1fbaaccb656ef09a8770c28df15e3e91a452e64Eric Laurent break; 3793632ca417f0a33e3fa9ccece531afa2db3f0d4a30Dianne Hackborn 3794632ca417f0a33e3fa9ccece531afa2db3f0d4a30Dianne Hackborn case MSG_REPORT_NEW_ROUTES: { 3795632ca417f0a33e3fa9ccece531afa2db3f0d4a30Dianne Hackborn int N = mRoutesObservers.beginBroadcast(); 3796632ca417f0a33e3fa9ccece531afa2db3f0d4a30Dianne Hackborn if (N > 0) { 3797632ca417f0a33e3fa9ccece531afa2db3f0d4a30Dianne Hackborn AudioRoutesInfo routes; 3798632ca417f0a33e3fa9ccece531afa2db3f0d4a30Dianne Hackborn synchronized (mCurAudioRoutes) { 3799632ca417f0a33e3fa9ccece531afa2db3f0d4a30Dianne Hackborn routes = new AudioRoutesInfo(mCurAudioRoutes); 3800632ca417f0a33e3fa9ccece531afa2db3f0d4a30Dianne Hackborn } 3801632ca417f0a33e3fa9ccece531afa2db3f0d4a30Dianne Hackborn while (N > 0) { 3802632ca417f0a33e3fa9ccece531afa2db3f0d4a30Dianne Hackborn N--; 3803632ca417f0a33e3fa9ccece531afa2db3f0d4a30Dianne Hackborn IAudioRoutesObserver obs = mRoutesObservers.getBroadcastItem(N); 3804632ca417f0a33e3fa9ccece531afa2db3f0d4a30Dianne Hackborn try { 3805632ca417f0a33e3fa9ccece531afa2db3f0d4a30Dianne Hackborn obs.dispatchAudioRoutesChanged(routes); 3806632ca417f0a33e3fa9ccece531afa2db3f0d4a30Dianne Hackborn } catch (RemoteException e) { 3807632ca417f0a33e3fa9ccece531afa2db3f0d4a30Dianne Hackborn } 3808632ca417f0a33e3fa9ccece531afa2db3f0d4a30Dianne Hackborn } 3809632ca417f0a33e3fa9ccece531afa2db3f0d4a30Dianne Hackborn } 3810632ca417f0a33e3fa9ccece531afa2db3f0d4a30Dianne Hackborn mRoutesObservers.finishBroadcast(); 3811632ca417f0a33e3fa9ccece531afa2db3f0d4a30Dianne Hackborn break; 3812632ca417f0a33e3fa9ccece531afa2db3f0d4a30Dianne Hackborn } 38133114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi 3814c34dcc1e1ebf152bb400abbb8bc25f7dc0c3ba97Eric Laurent case MSG_CHECK_MUSIC_ACTIVE: 3815c34dcc1e1ebf152bb400abbb8bc25f7dc0c3ba97Eric Laurent onCheckMusicActive(); 3816c34dcc1e1ebf152bb400abbb8bc25f7dc0c3ba97Eric Laurent break; 38175bfaeaef3fc348d66f48b86be08655e91dff910aEric Laurent 38185bfaeaef3fc348d66f48b86be08655e91dff910aEric Laurent case MSG_BROADCAST_AUDIO_BECOMING_NOISY: 38195bfaeaef3fc348d66f48b86be08655e91dff910aEric Laurent onSendBecomingNoisyIntent(); 38205bfaeaef3fc348d66f48b86be08655e91dff910aEric Laurent break; 3821d640bd325c3be9a350058c835b880a7e0b40dc60Eric Laurent 3822d640bd325c3be9a350058c835b880a7e0b40dc60Eric Laurent case MSG_CONFIGURE_SAFE_MEDIA_VOLUME_FORCED: 3823d640bd325c3be9a350058c835b880a7e0b40dc60Eric Laurent case MSG_CONFIGURE_SAFE_MEDIA_VOLUME: 3824d640bd325c3be9a350058c835b880a7e0b40dc60Eric Laurent onConfigureSafeVolume((msg.what == MSG_CONFIGURE_SAFE_MEDIA_VOLUME_FORCED)); 3825d640bd325c3be9a350058c835b880a7e0b40dc60Eric Laurent break; 382605274f348e12983eb8613cc6eb9ae561e8197e28Eric Laurent case MSG_PERSIST_SAFE_VOLUME_STATE: 382705274f348e12983eb8613cc6eb9ae561e8197e28Eric Laurent onPersistSafeVolumeState(msg.arg1); 382805274f348e12983eb8613cc6eb9ae561e8197e28Eric Laurent break; 3829a578c48e6c8677bcb54340aadb9470f8a275e56cJean-Michel Trivi 38302a57ca931fefe817b6110101289721acaacfc808Eric Laurent case MSG_BROADCAST_BT_CONNECTION_STATE: 38312a57ca931fefe817b6110101289721acaacfc808Eric Laurent onBroadcastScoConnectionState(msg.arg1); 38322a57ca931fefe817b6110101289721acaacfc808Eric Laurent break; 38334a5eeb9c727d77bb57fef87a70c8c9cc23dbfee3Eric Laurent 38344a5eeb9c727d77bb57fef87a70c8c9cc23dbfee3Eric Laurent case MSG_SYSTEM_READY: 38354a5eeb9c727d77bb57fef87a70c8c9cc23dbfee3Eric Laurent onSystemReady(); 38364a5eeb9c727d77bb57fef87a70c8c9cc23dbfee3Eric Laurent break; 38379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 38389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 38399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 38409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3841b109615ebebd6f3b9ae789412279f576c3ace46bJason Parekh private class SettingsObserver extends ContentObserver { 3842a553c25b33c99b345cf1c8688f8df0ed8df14e5aEric Laurent 3843b109615ebebd6f3b9ae789412279f576c3ace46bJason Parekh SettingsObserver() { 3844b109615ebebd6f3b9ae789412279f576c3ace46bJason Parekh super(new Handler()); 3845b109615ebebd6f3b9ae789412279f576c3ace46bJason Parekh mContentResolver.registerContentObserver(Settings.System.getUriFor( 3846b109615ebebd6f3b9ae789412279f576c3ace46bJason Parekh Settings.System.MODE_RINGER_STREAMS_AFFECTED), false, this); 38477ee1e4ff7346a278a6722108fbc1869240b3e866Eric Laurent mContentResolver.registerContentObserver(Settings.Global.getUriFor( 38487ee1e4ff7346a278a6722108fbc1869240b3e866Eric Laurent Settings.Global.DOCK_AUDIO_MEDIA_ENABLED), false, this); 3849b109615ebebd6f3b9ae789412279f576c3ace46bJason Parekh } 3850b109615ebebd6f3b9ae789412279f576c3ace46bJason Parekh 3851b109615ebebd6f3b9ae789412279f576c3ace46bJason Parekh @Override 3852b109615ebebd6f3b9ae789412279f576c3ace46bJason Parekh public void onChange(boolean selfChange) { 3853b109615ebebd6f3b9ae789412279f576c3ace46bJason Parekh super.onChange(selfChange); 3854ba195ebc76f23b6679443724ab58c9dc9f2df884Glenn Kasten // FIXME This synchronized is not necessary if mSettingsLock only protects mRingerMode. 3855ba195ebc76f23b6679443724ab58c9dc9f2df884Glenn Kasten // However there appear to be some missing locks around mRingerModeMutedStreams 3856ba195ebc76f23b6679443724ab58c9dc9f2df884Glenn Kasten // and mRingerModeAffectedStreams, so will leave this synchronized for now. 3857ba195ebc76f23b6679443724ab58c9dc9f2df884Glenn Kasten // mRingerModeMutedStreams and mMuteAffectedStreams are safe (only accessed once). 3858a553c25b33c99b345cf1c8688f8df0ed8df14e5aEric Laurent synchronized (mSettingsLock) { 385924e0d9b6c40712a297e4c287435a3b0fdd30e9daEric Laurent if (updateRingerModeAffectedStreams()) { 3860a553c25b33c99b345cf1c8688f8df0ed8df14e5aEric Laurent /* 3861a553c25b33c99b345cf1c8688f8df0ed8df14e5aEric Laurent * Ensure all stream types that should be affected by ringer mode 3862a553c25b33c99b345cf1c8688f8df0ed8df14e5aEric Laurent * are in the proper state. 3863a553c25b33c99b345cf1c8688f8df0ed8df14e5aEric Laurent */ 3864a553c25b33c99b345cf1c8688f8df0ed8df14e5aEric Laurent setRingerModeInt(getRingerMode(), false); 3865a553c25b33c99b345cf1c8688f8df0ed8df14e5aEric Laurent } 38667ee1e4ff7346a278a6722108fbc1869240b3e866Eric Laurent readDockAudioSettings(mContentResolver); 3867a553c25b33c99b345cf1c8688f8df0ed8df14e5aEric Laurent } 3868b109615ebebd6f3b9ae789412279f576c3ace46bJason Parekh } 3869b109615ebebd6f3b9ae789412279f576c3ace46bJason Parekh } 3870a553c25b33c99b345cf1c8688f8df0ed8df14e5aEric Laurent 38716bc7f2cd30b6bd90806942b0722e22daa2108493Eric Laurent // must be called synchronized on mConnectedDevices 38724c637b9e34f4c8db69a64ad21a4e2bcfa7485b5fJean-Michel Trivi private void makeA2dpDeviceAvailable(String address) { 38737847211fb4699bf6018e29d214a918ed6657319bEric Laurent // enable A2DP before notifying A2DP connection to avoid unecessary processing in 38747847211fb4699bf6018e29d214a918ed6657319bEric Laurent // audio policy manager 3875c9d1d5f35091226e96fcfa91817480f589eb36e2Matthew Xie VolumeStreamState streamState = mStreamStates[AudioSystem.STREAM_MUSIC]; 3876c9d1d5f35091226e96fcfa91817480f589eb36e2Matthew Xie sendMsg(mAudioHandler, MSG_SET_DEVICE_VOLUME, SENDMSG_QUEUE, 3877c9d1d5f35091226e96fcfa91817480f589eb36e2Matthew Xie AudioSystem.DEVICE_OUT_BLUETOOTH_A2DP, 0, streamState, 0); 38787847211fb4699bf6018e29d214a918ed6657319bEric Laurent setBluetoothA2dpOnInt(true); 38794c637b9e34f4c8db69a64ad21a4e2bcfa7485b5fJean-Michel Trivi AudioSystem.setDeviceConnectionState(AudioSystem.DEVICE_OUT_BLUETOOTH_A2DP, 38804c637b9e34f4c8db69a64ad21a4e2bcfa7485b5fJean-Michel Trivi AudioSystem.DEVICE_STATE_AVAILABLE, 38814c637b9e34f4c8db69a64ad21a4e2bcfa7485b5fJean-Michel Trivi address); 38824c637b9e34f4c8db69a64ad21a4e2bcfa7485b5fJean-Michel Trivi // Reset A2DP suspend state each time a new sink is connected 38834c637b9e34f4c8db69a64ad21a4e2bcfa7485b5fJean-Michel Trivi AudioSystem.setParameters("A2dpSuspended=false"); 38844c637b9e34f4c8db69a64ad21a4e2bcfa7485b5fJean-Michel Trivi mConnectedDevices.put( new Integer(AudioSystem.DEVICE_OUT_BLUETOOTH_A2DP), 38854c637b9e34f4c8db69a64ad21a4e2bcfa7485b5fJean-Michel Trivi address); 38864c637b9e34f4c8db69a64ad21a4e2bcfa7485b5fJean-Michel Trivi } 38874c637b9e34f4c8db69a64ad21a4e2bcfa7485b5fJean-Michel Trivi 38885bfaeaef3fc348d66f48b86be08655e91dff910aEric Laurent private void onSendBecomingNoisyIntent() { 38895ac72a29593ab9a20337a2225df52bdf4754be02Dianne Hackborn sendBroadcastToAll(new Intent(AudioManager.ACTION_AUDIO_BECOMING_NOISY)); 38909841818b9a0280abf59343c9e00a2976dbc084faMike Lockwood } 38919841818b9a0280abf59343c9e00a2976dbc084faMike Lockwood 38926bc7f2cd30b6bd90806942b0722e22daa2108493Eric Laurent // must be called synchronized on mConnectedDevices 38934c637b9e34f4c8db69a64ad21a4e2bcfa7485b5fJean-Michel Trivi private void makeA2dpDeviceUnavailableNow(String address) { 3894c9d1d5f35091226e96fcfa91817480f589eb36e2Matthew Xie synchronized (mA2dpAvrcpLock) { 3895c9d1d5f35091226e96fcfa91817480f589eb36e2Matthew Xie mAvrcpAbsVolSupported = false; 3896c9d1d5f35091226e96fcfa91817480f589eb36e2Matthew Xie } 38974c637b9e34f4c8db69a64ad21a4e2bcfa7485b5fJean-Michel Trivi AudioSystem.setDeviceConnectionState(AudioSystem.DEVICE_OUT_BLUETOOTH_A2DP, 38984c637b9e34f4c8db69a64ad21a4e2bcfa7485b5fJean-Michel Trivi AudioSystem.DEVICE_STATE_UNAVAILABLE, 38994c637b9e34f4c8db69a64ad21a4e2bcfa7485b5fJean-Michel Trivi address); 39004c637b9e34f4c8db69a64ad21a4e2bcfa7485b5fJean-Michel Trivi mConnectedDevices.remove(AudioSystem.DEVICE_OUT_BLUETOOTH_A2DP); 39014c637b9e34f4c8db69a64ad21a4e2bcfa7485b5fJean-Michel Trivi } 39024c637b9e34f4c8db69a64ad21a4e2bcfa7485b5fJean-Michel Trivi 39036bc7f2cd30b6bd90806942b0722e22daa2108493Eric Laurent // must be called synchronized on mConnectedDevices 39044c637b9e34f4c8db69a64ad21a4e2bcfa7485b5fJean-Michel Trivi private void makeA2dpDeviceUnavailableLater(String address) { 39053b5912602bec6ccbe8eef8a576730b1565f0067cEric Laurent // prevent any activity on the A2DP audio output to avoid unwanted 39063b5912602bec6ccbe8eef8a576730b1565f0067cEric Laurent // reconnection of the sink. 39073b5912602bec6ccbe8eef8a576730b1565f0067cEric Laurent AudioSystem.setParameters("A2dpSuspended=true"); 39084c637b9e34f4c8db69a64ad21a4e2bcfa7485b5fJean-Michel Trivi // the device will be made unavailable later, so consider it disconnected right away 39094c637b9e34f4c8db69a64ad21a4e2bcfa7485b5fJean-Michel Trivi mConnectedDevices.remove(AudioSystem.DEVICE_OUT_BLUETOOTH_A2DP); 39104c637b9e34f4c8db69a64ad21a4e2bcfa7485b5fJean-Michel Trivi // send the delayed message to make the device unavailable later 39114c637b9e34f4c8db69a64ad21a4e2bcfa7485b5fJean-Michel Trivi Message msg = mAudioHandler.obtainMessage(MSG_BTA2DP_DOCK_TIMEOUT, address); 39124c637b9e34f4c8db69a64ad21a4e2bcfa7485b5fJean-Michel Trivi mAudioHandler.sendMessageDelayed(msg, BTA2DP_DOCK_TIMEOUT_MILLIS); 39134c637b9e34f4c8db69a64ad21a4e2bcfa7485b5fJean-Michel Trivi 39144c637b9e34f4c8db69a64ad21a4e2bcfa7485b5fJean-Michel Trivi } 39154c637b9e34f4c8db69a64ad21a4e2bcfa7485b5fJean-Michel Trivi 39166bc7f2cd30b6bd90806942b0722e22daa2108493Eric Laurent // must be called synchronized on mConnectedDevices 39170a40ec2192e4836b2fcb6ba51a7688aa6bd4ee98Mike Lockwood private void makeA2dpSrcAvailable(String address) { 39180a40ec2192e4836b2fcb6ba51a7688aa6bd4ee98Mike Lockwood AudioSystem.setDeviceConnectionState(AudioSystem.DEVICE_IN_BLUETOOTH_A2DP, 39190a40ec2192e4836b2fcb6ba51a7688aa6bd4ee98Mike Lockwood AudioSystem.DEVICE_STATE_AVAILABLE, 39200a40ec2192e4836b2fcb6ba51a7688aa6bd4ee98Mike Lockwood address); 39210a40ec2192e4836b2fcb6ba51a7688aa6bd4ee98Mike Lockwood mConnectedDevices.put( new Integer(AudioSystem.DEVICE_IN_BLUETOOTH_A2DP), 39220a40ec2192e4836b2fcb6ba51a7688aa6bd4ee98Mike Lockwood address); 39230a40ec2192e4836b2fcb6ba51a7688aa6bd4ee98Mike Lockwood } 39240a40ec2192e4836b2fcb6ba51a7688aa6bd4ee98Mike Lockwood 39250a40ec2192e4836b2fcb6ba51a7688aa6bd4ee98Mike Lockwood // must be called synchronized on mConnectedDevices 39260a40ec2192e4836b2fcb6ba51a7688aa6bd4ee98Mike Lockwood private void makeA2dpSrcUnavailable(String address) { 39270a40ec2192e4836b2fcb6ba51a7688aa6bd4ee98Mike Lockwood AudioSystem.setDeviceConnectionState(AudioSystem.DEVICE_IN_BLUETOOTH_A2DP, 39280a40ec2192e4836b2fcb6ba51a7688aa6bd4ee98Mike Lockwood AudioSystem.DEVICE_STATE_UNAVAILABLE, 39290a40ec2192e4836b2fcb6ba51a7688aa6bd4ee98Mike Lockwood address); 39300a40ec2192e4836b2fcb6ba51a7688aa6bd4ee98Mike Lockwood mConnectedDevices.remove(AudioSystem.DEVICE_IN_BLUETOOTH_A2DP); 39310a40ec2192e4836b2fcb6ba51a7688aa6bd4ee98Mike Lockwood } 39320a40ec2192e4836b2fcb6ba51a7688aa6bd4ee98Mike Lockwood 39330a40ec2192e4836b2fcb6ba51a7688aa6bd4ee98Mike Lockwood // must be called synchronized on mConnectedDevices 3934a847ba4080675d395de725cfac5dfd9d5a993d4eJean-Michel Trivi private void cancelA2dpDeviceTimeout() { 39354c637b9e34f4c8db69a64ad21a4e2bcfa7485b5fJean-Michel Trivi mAudioHandler.removeMessages(MSG_BTA2DP_DOCK_TIMEOUT); 39364c637b9e34f4c8db69a64ad21a4e2bcfa7485b5fJean-Michel Trivi } 39374c637b9e34f4c8db69a64ad21a4e2bcfa7485b5fJean-Michel Trivi 39386bc7f2cd30b6bd90806942b0722e22daa2108493Eric Laurent // must be called synchronized on mConnectedDevices 3939a847ba4080675d395de725cfac5dfd9d5a993d4eJean-Michel Trivi private boolean hasScheduledA2dpDockTimeout() { 3940a847ba4080675d395de725cfac5dfd9d5a993d4eJean-Michel Trivi return mAudioHandler.hasMessages(MSG_BTA2DP_DOCK_TIMEOUT); 3941a847ba4080675d395de725cfac5dfd9d5a993d4eJean-Michel Trivi } 3942a847ba4080675d395de725cfac5dfd9d5a993d4eJean-Michel Trivi 39430a40ec2192e4836b2fcb6ba51a7688aa6bd4ee98Mike Lockwood private void onSetA2dpSinkConnectionState(BluetoothDevice btDevice, int state) 39446bc7f2cd30b6bd90806942b0722e22daa2108493Eric Laurent { 39450a40ec2192e4836b2fcb6ba51a7688aa6bd4ee98Mike Lockwood if (DEBUG_VOL) { 39460a40ec2192e4836b2fcb6ba51a7688aa6bd4ee98Mike Lockwood Log.d(TAG, "onSetA2dpSinkConnectionState btDevice="+btDevice+"state="+state); 39470a40ec2192e4836b2fcb6ba51a7688aa6bd4ee98Mike Lockwood } 39486bc7f2cd30b6bd90806942b0722e22daa2108493Eric Laurent if (btDevice == null) { 39496bc7f2cd30b6bd90806942b0722e22daa2108493Eric Laurent return; 39506bc7f2cd30b6bd90806942b0722e22daa2108493Eric Laurent } 39516bc7f2cd30b6bd90806942b0722e22daa2108493Eric Laurent String address = btDevice.getAddress(); 39526bc7f2cd30b6bd90806942b0722e22daa2108493Eric Laurent if (!BluetoothAdapter.checkBluetoothAddress(address)) { 39536bc7f2cd30b6bd90806942b0722e22daa2108493Eric Laurent address = ""; 39546bc7f2cd30b6bd90806942b0722e22daa2108493Eric Laurent } 39555a0cf7a27f3953a1266af48543ccd9024f4cd89fJohn Du 39566bc7f2cd30b6bd90806942b0722e22daa2108493Eric Laurent synchronized (mConnectedDevices) { 39576bc7f2cd30b6bd90806942b0722e22daa2108493Eric Laurent boolean isConnected = 39586bc7f2cd30b6bd90806942b0722e22daa2108493Eric Laurent (mConnectedDevices.containsKey(AudioSystem.DEVICE_OUT_BLUETOOTH_A2DP) && 39596bc7f2cd30b6bd90806942b0722e22daa2108493Eric Laurent mConnectedDevices.get(AudioSystem.DEVICE_OUT_BLUETOOTH_A2DP).equals(address)); 39606bc7f2cd30b6bd90806942b0722e22daa2108493Eric Laurent 39616bc7f2cd30b6bd90806942b0722e22daa2108493Eric Laurent if (isConnected && state != BluetoothProfile.STATE_CONNECTED) { 39626bc7f2cd30b6bd90806942b0722e22daa2108493Eric Laurent if (btDevice.isBluetoothDock()) { 39636bc7f2cd30b6bd90806942b0722e22daa2108493Eric Laurent if (state == BluetoothProfile.STATE_DISCONNECTED) { 39646bc7f2cd30b6bd90806942b0722e22daa2108493Eric Laurent // introduction of a delay for transient disconnections of docks when 39656bc7f2cd30b6bd90806942b0722e22daa2108493Eric Laurent // power is rapidly turned off/on, this message will be canceled if 39666bc7f2cd30b6bd90806942b0722e22daa2108493Eric Laurent // we reconnect the dock under a preset delay 39676bc7f2cd30b6bd90806942b0722e22daa2108493Eric Laurent makeA2dpDeviceUnavailableLater(address); 39686bc7f2cd30b6bd90806942b0722e22daa2108493Eric Laurent // the next time isConnected is evaluated, it will be false for the dock 39696bc7f2cd30b6bd90806942b0722e22daa2108493Eric Laurent } 39706bc7f2cd30b6bd90806942b0722e22daa2108493Eric Laurent } else { 39716bc7f2cd30b6bd90806942b0722e22daa2108493Eric Laurent makeA2dpDeviceUnavailableNow(address); 39726bc7f2cd30b6bd90806942b0722e22daa2108493Eric Laurent } 3973632ca417f0a33e3fa9ccece531afa2db3f0d4a30Dianne Hackborn synchronized (mCurAudioRoutes) { 3974632ca417f0a33e3fa9ccece531afa2db3f0d4a30Dianne Hackborn if (mCurAudioRoutes.mBluetoothName != null) { 3975632ca417f0a33e3fa9ccece531afa2db3f0d4a30Dianne Hackborn mCurAudioRoutes.mBluetoothName = null; 3976632ca417f0a33e3fa9ccece531afa2db3f0d4a30Dianne Hackborn sendMsg(mAudioHandler, MSG_REPORT_NEW_ROUTES, 3977632ca417f0a33e3fa9ccece531afa2db3f0d4a30Dianne Hackborn SENDMSG_NOOP, 0, 0, null, 0); 3978632ca417f0a33e3fa9ccece531afa2db3f0d4a30Dianne Hackborn } 3979632ca417f0a33e3fa9ccece531afa2db3f0d4a30Dianne Hackborn } 39806bc7f2cd30b6bd90806942b0722e22daa2108493Eric Laurent } else if (!isConnected && state == BluetoothProfile.STATE_CONNECTED) { 39816bc7f2cd30b6bd90806942b0722e22daa2108493Eric Laurent if (btDevice.isBluetoothDock()) { 39826bc7f2cd30b6bd90806942b0722e22daa2108493Eric Laurent // this could be a reconnection after a transient disconnection 39836bc7f2cd30b6bd90806942b0722e22daa2108493Eric Laurent cancelA2dpDeviceTimeout(); 39846bc7f2cd30b6bd90806942b0722e22daa2108493Eric Laurent mDockAddress = address; 39856bc7f2cd30b6bd90806942b0722e22daa2108493Eric Laurent } else { 39866bc7f2cd30b6bd90806942b0722e22daa2108493Eric Laurent // this could be a connection of another A2DP device before the timeout of 39876bc7f2cd30b6bd90806942b0722e22daa2108493Eric Laurent // a dock: cancel the dock timeout, and make the dock unavailable now 39886bc7f2cd30b6bd90806942b0722e22daa2108493Eric Laurent if(hasScheduledA2dpDockTimeout()) { 39896bc7f2cd30b6bd90806942b0722e22daa2108493Eric Laurent cancelA2dpDeviceTimeout(); 39906bc7f2cd30b6bd90806942b0722e22daa2108493Eric Laurent makeA2dpDeviceUnavailableNow(mDockAddress); 39916bc7f2cd30b6bd90806942b0722e22daa2108493Eric Laurent } 39926bc7f2cd30b6bd90806942b0722e22daa2108493Eric Laurent } 39936bc7f2cd30b6bd90806942b0722e22daa2108493Eric Laurent makeA2dpDeviceAvailable(address); 3994632ca417f0a33e3fa9ccece531afa2db3f0d4a30Dianne Hackborn synchronized (mCurAudioRoutes) { 3995632ca417f0a33e3fa9ccece531afa2db3f0d4a30Dianne Hackborn String name = btDevice.getAliasName(); 3996632ca417f0a33e3fa9ccece531afa2db3f0d4a30Dianne Hackborn if (!TextUtils.equals(mCurAudioRoutes.mBluetoothName, name)) { 3997632ca417f0a33e3fa9ccece531afa2db3f0d4a30Dianne Hackborn mCurAudioRoutes.mBluetoothName = name; 3998632ca417f0a33e3fa9ccece531afa2db3f0d4a30Dianne Hackborn sendMsg(mAudioHandler, MSG_REPORT_NEW_ROUTES, 3999632ca417f0a33e3fa9ccece531afa2db3f0d4a30Dianne Hackborn SENDMSG_NOOP, 0, 0, null, 0); 4000632ca417f0a33e3fa9ccece531afa2db3f0d4a30Dianne Hackborn } 4001632ca417f0a33e3fa9ccece531afa2db3f0d4a30Dianne Hackborn } 40026bc7f2cd30b6bd90806942b0722e22daa2108493Eric Laurent } 40036bc7f2cd30b6bd90806942b0722e22daa2108493Eric Laurent } 40046bc7f2cd30b6bd90806942b0722e22daa2108493Eric Laurent } 40056bc7f2cd30b6bd90806942b0722e22daa2108493Eric Laurent 40060a40ec2192e4836b2fcb6ba51a7688aa6bd4ee98Mike Lockwood private void onSetA2dpSourceConnectionState(BluetoothDevice btDevice, int state) 40070a40ec2192e4836b2fcb6ba51a7688aa6bd4ee98Mike Lockwood { 40080a40ec2192e4836b2fcb6ba51a7688aa6bd4ee98Mike Lockwood if (DEBUG_VOL) { 40090a40ec2192e4836b2fcb6ba51a7688aa6bd4ee98Mike Lockwood Log.d(TAG, "onSetA2dpSourceConnectionState btDevice="+btDevice+" state="+state); 40100a40ec2192e4836b2fcb6ba51a7688aa6bd4ee98Mike Lockwood } 40110a40ec2192e4836b2fcb6ba51a7688aa6bd4ee98Mike Lockwood if (btDevice == null) { 40120a40ec2192e4836b2fcb6ba51a7688aa6bd4ee98Mike Lockwood return; 40130a40ec2192e4836b2fcb6ba51a7688aa6bd4ee98Mike Lockwood } 40140a40ec2192e4836b2fcb6ba51a7688aa6bd4ee98Mike Lockwood String address = btDevice.getAddress(); 40150a40ec2192e4836b2fcb6ba51a7688aa6bd4ee98Mike Lockwood if (!BluetoothAdapter.checkBluetoothAddress(address)) { 40160a40ec2192e4836b2fcb6ba51a7688aa6bd4ee98Mike Lockwood address = ""; 40170a40ec2192e4836b2fcb6ba51a7688aa6bd4ee98Mike Lockwood } 40180a40ec2192e4836b2fcb6ba51a7688aa6bd4ee98Mike Lockwood 40190a40ec2192e4836b2fcb6ba51a7688aa6bd4ee98Mike Lockwood synchronized (mConnectedDevices) { 40200a40ec2192e4836b2fcb6ba51a7688aa6bd4ee98Mike Lockwood boolean isConnected = 40210a40ec2192e4836b2fcb6ba51a7688aa6bd4ee98Mike Lockwood (mConnectedDevices.containsKey(AudioSystem.DEVICE_IN_BLUETOOTH_A2DP) && 40220a40ec2192e4836b2fcb6ba51a7688aa6bd4ee98Mike Lockwood mConnectedDevices.get(AudioSystem.DEVICE_IN_BLUETOOTH_A2DP).equals(address)); 40230a40ec2192e4836b2fcb6ba51a7688aa6bd4ee98Mike Lockwood 40240a40ec2192e4836b2fcb6ba51a7688aa6bd4ee98Mike Lockwood if (isConnected && state != BluetoothProfile.STATE_CONNECTED) { 40250a40ec2192e4836b2fcb6ba51a7688aa6bd4ee98Mike Lockwood makeA2dpSrcUnavailable(address); 40260a40ec2192e4836b2fcb6ba51a7688aa6bd4ee98Mike Lockwood } else if (!isConnected && state == BluetoothProfile.STATE_CONNECTED) { 40270a40ec2192e4836b2fcb6ba51a7688aa6bd4ee98Mike Lockwood makeA2dpSrcAvailable(address); 40280a40ec2192e4836b2fcb6ba51a7688aa6bd4ee98Mike Lockwood } 40290a40ec2192e4836b2fcb6ba51a7688aa6bd4ee98Mike Lockwood } 40300a40ec2192e4836b2fcb6ba51a7688aa6bd4ee98Mike Lockwood } 40310a40ec2192e4836b2fcb6ba51a7688aa6bd4ee98Mike Lockwood 40325a0cf7a27f3953a1266af48543ccd9024f4cd89fJohn Du public void avrcpSupportsAbsoluteVolume(String address, boolean support) { 40335a0cf7a27f3953a1266af48543ccd9024f4cd89fJohn Du // address is not used for now, but may be used when multiple a2dp devices are supported 40345a0cf7a27f3953a1266af48543ccd9024f4cd89fJohn Du synchronized (mA2dpAvrcpLock) { 40355a0cf7a27f3953a1266af48543ccd9024f4cd89fJohn Du mAvrcpAbsVolSupported = support; 4036c9d1d5f35091226e96fcfa91817480f589eb36e2Matthew Xie sendMsg(mAudioHandler, MSG_SET_DEVICE_VOLUME, SENDMSG_QUEUE, 4037cd772d04345850e160a45613fcf6b86da0dce4cfEric Laurent AudioSystem.DEVICE_OUT_BLUETOOTH_A2DP, 0, 4038cd772d04345850e160a45613fcf6b86da0dce4cfEric Laurent mStreamStates[AudioSystem.STREAM_MUSIC], 0); 4039cd772d04345850e160a45613fcf6b86da0dce4cfEric Laurent sendMsg(mAudioHandler, MSG_SET_DEVICE_VOLUME, SENDMSG_QUEUE, 4040cd772d04345850e160a45613fcf6b86da0dce4cfEric Laurent AudioSystem.DEVICE_OUT_BLUETOOTH_A2DP, 0, 4041cd772d04345850e160a45613fcf6b86da0dce4cfEric Laurent mStreamStates[AudioSystem.STREAM_RING], 0); 40425a0cf7a27f3953a1266af48543ccd9024f4cd89fJohn Du } 40435a0cf7a27f3953a1266af48543ccd9024f4cd89fJohn Du } 40445a0cf7a27f3953a1266af48543ccd9024f4cd89fJohn Du 404559f482764e346a5c5ac118ee1f7b24da645c2559Eric Laurent private boolean handleDeviceConnection(boolean connected, int device, String params) { 404659f482764e346a5c5ac118ee1f7b24da645c2559Eric Laurent synchronized (mConnectedDevices) { 404759f482764e346a5c5ac118ee1f7b24da645c2559Eric Laurent boolean isConnected = (mConnectedDevices.containsKey(device) && 40489841818b9a0280abf59343c9e00a2976dbc084faMike Lockwood (params.isEmpty() || mConnectedDevices.get(device).equals(params))); 404959f482764e346a5c5ac118ee1f7b24da645c2559Eric Laurent 405059f482764e346a5c5ac118ee1f7b24da645c2559Eric Laurent if (isConnected && !connected) { 405159f482764e346a5c5ac118ee1f7b24da645c2559Eric Laurent AudioSystem.setDeviceConnectionState(device, 405259f482764e346a5c5ac118ee1f7b24da645c2559Eric Laurent AudioSystem.DEVICE_STATE_UNAVAILABLE, 40539841818b9a0280abf59343c9e00a2976dbc084faMike Lockwood mConnectedDevices.get(device)); 405459f482764e346a5c5ac118ee1f7b24da645c2559Eric Laurent mConnectedDevices.remove(device); 405559f482764e346a5c5ac118ee1f7b24da645c2559Eric Laurent return true; 405659f482764e346a5c5ac118ee1f7b24da645c2559Eric Laurent } else if (!isConnected && connected) { 405759f482764e346a5c5ac118ee1f7b24da645c2559Eric Laurent AudioSystem.setDeviceConnectionState(device, 405859f482764e346a5c5ac118ee1f7b24da645c2559Eric Laurent AudioSystem.DEVICE_STATE_AVAILABLE, 405959f482764e346a5c5ac118ee1f7b24da645c2559Eric Laurent params); 406059f482764e346a5c5ac118ee1f7b24da645c2559Eric Laurent mConnectedDevices.put(new Integer(device), params); 406159f482764e346a5c5ac118ee1f7b24da645c2559Eric Laurent return true; 406259f482764e346a5c5ac118ee1f7b24da645c2559Eric Laurent } 406359f482764e346a5c5ac118ee1f7b24da645c2559Eric Laurent } 406459f482764e346a5c5ac118ee1f7b24da645c2559Eric Laurent return false; 406559f482764e346a5c5ac118ee1f7b24da645c2559Eric Laurent } 406659f482764e346a5c5ac118ee1f7b24da645c2559Eric Laurent 4067b1fbaaccb656ef09a8770c28df15e3e91a452e64Eric Laurent // Devices which removal triggers intent ACTION_AUDIO_BECOMING_NOISY. The intent is only 4068b1fbaaccb656ef09a8770c28df15e3e91a452e64Eric Laurent // sent if none of these devices is connected. 4069b1fbaaccb656ef09a8770c28df15e3e91a452e64Eric Laurent int mBecomingNoisyIntentDevices = 4070b1fbaaccb656ef09a8770c28df15e3e91a452e64Eric Laurent AudioSystem.DEVICE_OUT_WIRED_HEADSET | AudioSystem.DEVICE_OUT_WIRED_HEADPHONE | 4071948d32748caaac5be06c991ebf00f74265a7849fEric Laurent AudioSystem.DEVICE_OUT_ALL_A2DP | AudioSystem.DEVICE_OUT_HDMI | 4072794da7a0543cbecffefb73794aa68d1a93e41adfEric Laurent AudioSystem.DEVICE_OUT_ANLG_DOCK_HEADSET | AudioSystem.DEVICE_OUT_DGTL_DOCK_HEADSET | 4073794da7a0543cbecffefb73794aa68d1a93e41adfEric Laurent AudioSystem.DEVICE_OUT_ALL_USB; 4074b1fbaaccb656ef09a8770c28df15e3e91a452e64Eric Laurent 4075b1fbaaccb656ef09a8770c28df15e3e91a452e64Eric Laurent // must be called before removing the device from mConnectedDevices 4076b1fbaaccb656ef09a8770c28df15e3e91a452e64Eric Laurent private int checkSendBecomingNoisyIntent(int device, int state) { 4077b1fbaaccb656ef09a8770c28df15e3e91a452e64Eric Laurent int delay = 0; 4078b1fbaaccb656ef09a8770c28df15e3e91a452e64Eric Laurent if ((state == 0) && ((device & mBecomingNoisyIntentDevices) != 0)) { 4079b1fbaaccb656ef09a8770c28df15e3e91a452e64Eric Laurent int devices = 0; 4080b1fbaaccb656ef09a8770c28df15e3e91a452e64Eric Laurent for (int dev : mConnectedDevices.keySet()) { 4081b1fbaaccb656ef09a8770c28df15e3e91a452e64Eric Laurent if ((dev & mBecomingNoisyIntentDevices) != 0) { 4082b1fbaaccb656ef09a8770c28df15e3e91a452e64Eric Laurent devices |= dev; 4083b1fbaaccb656ef09a8770c28df15e3e91a452e64Eric Laurent } 4084b1fbaaccb656ef09a8770c28df15e3e91a452e64Eric Laurent } 4085b1fbaaccb656ef09a8770c28df15e3e91a452e64Eric Laurent if (devices == device) { 40865bfaeaef3fc348d66f48b86be08655e91dff910aEric Laurent sendMsg(mAudioHandler, 40875bfaeaef3fc348d66f48b86be08655e91dff910aEric Laurent MSG_BROADCAST_AUDIO_BECOMING_NOISY, 40885bfaeaef3fc348d66f48b86be08655e91dff910aEric Laurent SENDMSG_REPLACE, 40895bfaeaef3fc348d66f48b86be08655e91dff910aEric Laurent 0, 40905bfaeaef3fc348d66f48b86be08655e91dff910aEric Laurent 0, 40915bfaeaef3fc348d66f48b86be08655e91dff910aEric Laurent null, 40925bfaeaef3fc348d66f48b86be08655e91dff910aEric Laurent 0); 4093b1fbaaccb656ef09a8770c28df15e3e91a452e64Eric Laurent delay = 1000; 4094b1fbaaccb656ef09a8770c28df15e3e91a452e64Eric Laurent } 4095b1fbaaccb656ef09a8770c28df15e3e91a452e64Eric Laurent } 4096b1fbaaccb656ef09a8770c28df15e3e91a452e64Eric Laurent 40970a40ec2192e4836b2fcb6ba51a7688aa6bd4ee98Mike Lockwood if (mAudioHandler.hasMessages(MSG_SET_A2DP_SRC_CONNECTION_STATE) || 40980a40ec2192e4836b2fcb6ba51a7688aa6bd4ee98Mike Lockwood mAudioHandler.hasMessages(MSG_SET_A2DP_SINK_CONNECTION_STATE) || 4099b1fbaaccb656ef09a8770c28df15e3e91a452e64Eric Laurent mAudioHandler.hasMessages(MSG_SET_WIRED_DEVICE_CONNECTION_STATE)) { 4100b1fbaaccb656ef09a8770c28df15e3e91a452e64Eric Laurent delay = 1000; 4101b1fbaaccb656ef09a8770c28df15e3e91a452e64Eric Laurent } 4102b1fbaaccb656ef09a8770c28df15e3e91a452e64Eric Laurent return delay; 4103b1fbaaccb656ef09a8770c28df15e3e91a452e64Eric Laurent } 4104b1fbaaccb656ef09a8770c28df15e3e91a452e64Eric Laurent 4105b1fbaaccb656ef09a8770c28df15e3e91a452e64Eric Laurent private void sendDeviceConnectionIntent(int device, int state, String name) 4106b1fbaaccb656ef09a8770c28df15e3e91a452e64Eric Laurent { 4107b1fbaaccb656ef09a8770c28df15e3e91a452e64Eric Laurent Intent intent = new Intent(); 4108b1fbaaccb656ef09a8770c28df15e3e91a452e64Eric Laurent 4109b1fbaaccb656ef09a8770c28df15e3e91a452e64Eric Laurent intent.putExtra("state", state); 4110b1fbaaccb656ef09a8770c28df15e3e91a452e64Eric Laurent intent.putExtra("name", name); 4111b1fbaaccb656ef09a8770c28df15e3e91a452e64Eric Laurent intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY); 4112b1fbaaccb656ef09a8770c28df15e3e91a452e64Eric Laurent 4113632ca417f0a33e3fa9ccece531afa2db3f0d4a30Dianne Hackborn int connType = 0; 4114632ca417f0a33e3fa9ccece531afa2db3f0d4a30Dianne Hackborn 4115b1fbaaccb656ef09a8770c28df15e3e91a452e64Eric Laurent if (device == AudioSystem.DEVICE_OUT_WIRED_HEADSET) { 4116632ca417f0a33e3fa9ccece531afa2db3f0d4a30Dianne Hackborn connType = AudioRoutesInfo.MAIN_HEADSET; 4117b1fbaaccb656ef09a8770c28df15e3e91a452e64Eric Laurent intent.setAction(Intent.ACTION_HEADSET_PLUG); 4118b1fbaaccb656ef09a8770c28df15e3e91a452e64Eric Laurent intent.putExtra("microphone", 1); 4119b1fbaaccb656ef09a8770c28df15e3e91a452e64Eric Laurent } else if (device == AudioSystem.DEVICE_OUT_WIRED_HEADPHONE) { 4120632ca417f0a33e3fa9ccece531afa2db3f0d4a30Dianne Hackborn connType = AudioRoutesInfo.MAIN_HEADPHONES; 4121b1fbaaccb656ef09a8770c28df15e3e91a452e64Eric Laurent intent.setAction(Intent.ACTION_HEADSET_PLUG); 4122b1fbaaccb656ef09a8770c28df15e3e91a452e64Eric Laurent intent.putExtra("microphone", 0); 4123b1fbaaccb656ef09a8770c28df15e3e91a452e64Eric Laurent } else if (device == AudioSystem.DEVICE_OUT_ANLG_DOCK_HEADSET) { 4124632ca417f0a33e3fa9ccece531afa2db3f0d4a30Dianne Hackborn connType = AudioRoutesInfo.MAIN_DOCK_SPEAKERS; 4125b1fbaaccb656ef09a8770c28df15e3e91a452e64Eric Laurent intent.setAction(Intent.ACTION_ANALOG_AUDIO_DOCK_PLUG); 4126b1fbaaccb656ef09a8770c28df15e3e91a452e64Eric Laurent } else if (device == AudioSystem.DEVICE_OUT_DGTL_DOCK_HEADSET) { 4127632ca417f0a33e3fa9ccece531afa2db3f0d4a30Dianne Hackborn connType = AudioRoutesInfo.MAIN_DOCK_SPEAKERS; 4128b1fbaaccb656ef09a8770c28df15e3e91a452e64Eric Laurent intent.setAction(Intent.ACTION_DIGITAL_AUDIO_DOCK_PLUG); 4129948d32748caaac5be06c991ebf00f74265a7849fEric Laurent } else if (device == AudioSystem.DEVICE_OUT_HDMI) { 4130632ca417f0a33e3fa9ccece531afa2db3f0d4a30Dianne Hackborn connType = AudioRoutesInfo.MAIN_HDMI; 4131b1fbaaccb656ef09a8770c28df15e3e91a452e64Eric Laurent intent.setAction(Intent.ACTION_HDMI_AUDIO_PLUG); 4132b1fbaaccb656ef09a8770c28df15e3e91a452e64Eric Laurent } 4133b1fbaaccb656ef09a8770c28df15e3e91a452e64Eric Laurent 4134632ca417f0a33e3fa9ccece531afa2db3f0d4a30Dianne Hackborn synchronized (mCurAudioRoutes) { 4135632ca417f0a33e3fa9ccece531afa2db3f0d4a30Dianne Hackborn if (connType != 0) { 4136632ca417f0a33e3fa9ccece531afa2db3f0d4a30Dianne Hackborn int newConn = mCurAudioRoutes.mMainType; 4137632ca417f0a33e3fa9ccece531afa2db3f0d4a30Dianne Hackborn if (state != 0) { 4138632ca417f0a33e3fa9ccece531afa2db3f0d4a30Dianne Hackborn newConn |= connType; 4139632ca417f0a33e3fa9ccece531afa2db3f0d4a30Dianne Hackborn } else { 4140632ca417f0a33e3fa9ccece531afa2db3f0d4a30Dianne Hackborn newConn &= ~connType; 4141632ca417f0a33e3fa9ccece531afa2db3f0d4a30Dianne Hackborn } 4142632ca417f0a33e3fa9ccece531afa2db3f0d4a30Dianne Hackborn if (newConn != mCurAudioRoutes.mMainType) { 4143632ca417f0a33e3fa9ccece531afa2db3f0d4a30Dianne Hackborn mCurAudioRoutes.mMainType = newConn; 4144632ca417f0a33e3fa9ccece531afa2db3f0d4a30Dianne Hackborn sendMsg(mAudioHandler, MSG_REPORT_NEW_ROUTES, 4145632ca417f0a33e3fa9ccece531afa2db3f0d4a30Dianne Hackborn SENDMSG_NOOP, 0, 0, null, 0); 4146632ca417f0a33e3fa9ccece531afa2db3f0d4a30Dianne Hackborn } 4147632ca417f0a33e3fa9ccece531afa2db3f0d4a30Dianne Hackborn } 4148632ca417f0a33e3fa9ccece531afa2db3f0d4a30Dianne Hackborn } 4149632ca417f0a33e3fa9ccece531afa2db3f0d4a30Dianne Hackborn 41505ac72a29593ab9a20337a2225df52bdf4754be02Dianne Hackborn final long ident = Binder.clearCallingIdentity(); 41515ac72a29593ab9a20337a2225df52bdf4754be02Dianne Hackborn try { 41525ac72a29593ab9a20337a2225df52bdf4754be02Dianne Hackborn ActivityManagerNative.broadcastStickyIntent(intent, null, UserHandle.USER_ALL); 41535ac72a29593ab9a20337a2225df52bdf4754be02Dianne Hackborn } finally { 41545ac72a29593ab9a20337a2225df52bdf4754be02Dianne Hackborn Binder.restoreCallingIdentity(ident); 41555ac72a29593ab9a20337a2225df52bdf4754be02Dianne Hackborn } 4156b1fbaaccb656ef09a8770c28df15e3e91a452e64Eric Laurent } 4157b1fbaaccb656ef09a8770c28df15e3e91a452e64Eric Laurent 4158b1fbaaccb656ef09a8770c28df15e3e91a452e64Eric Laurent private void onSetWiredDeviceConnectionState(int device, int state, String name) 4159b1fbaaccb656ef09a8770c28df15e3e91a452e64Eric Laurent { 4160b1fbaaccb656ef09a8770c28df15e3e91a452e64Eric Laurent synchronized (mConnectedDevices) { 4161b1fbaaccb656ef09a8770c28df15e3e91a452e64Eric Laurent if ((state == 0) && ((device == AudioSystem.DEVICE_OUT_WIRED_HEADSET) || 4162b1fbaaccb656ef09a8770c28df15e3e91a452e64Eric Laurent (device == AudioSystem.DEVICE_OUT_WIRED_HEADPHONE))) { 4163b1fbaaccb656ef09a8770c28df15e3e91a452e64Eric Laurent setBluetoothA2dpOnInt(true); 4164b1fbaaccb656ef09a8770c28df15e3e91a452e64Eric Laurent } 4165ae4506e9b5fc3e0c6d9862fbc05b9af7d6742a6eEric Laurent boolean isUsb = ((device & ~AudioSystem.DEVICE_OUT_ALL_USB) == 0) || 4166ae4506e9b5fc3e0c6d9862fbc05b9af7d6742a6eEric Laurent (((device & AudioSystem.DEVICE_BIT_IN) != 0) && 4167ae4506e9b5fc3e0c6d9862fbc05b9af7d6742a6eEric Laurent ((device & ~AudioSystem.DEVICE_IN_ALL_USB) == 0)); 4168db45484e4b5858d14da93d3a06311b93bf0cf320Mike Lockwood handleDeviceConnection((state == 1), device, (isUsb ? name : "")); 4169f1a457d06c53a901ea08d2d3fb6e766bc06c4d4fEric Laurent if (state != 0) { 4170f1a457d06c53a901ea08d2d3fb6e766bc06c4d4fEric Laurent if ((device == AudioSystem.DEVICE_OUT_WIRED_HEADSET) || 4171f1a457d06c53a901ea08d2d3fb6e766bc06c4d4fEric Laurent (device == AudioSystem.DEVICE_OUT_WIRED_HEADPHONE)) { 4172f1a457d06c53a901ea08d2d3fb6e766bc06c4d4fEric Laurent setBluetoothA2dpOnInt(false); 4173f1a457d06c53a901ea08d2d3fb6e766bc06c4d4fEric Laurent } 4174f1a457d06c53a901ea08d2d3fb6e766bc06c4d4fEric Laurent if ((device & mSafeMediaVolumeDevices) != 0) { 4175f1a457d06c53a901ea08d2d3fb6e766bc06c4d4fEric Laurent sendMsg(mAudioHandler, 4176f1a457d06c53a901ea08d2d3fb6e766bc06c4d4fEric Laurent MSG_CHECK_MUSIC_ACTIVE, 4177f1a457d06c53a901ea08d2d3fb6e766bc06c4d4fEric Laurent SENDMSG_REPLACE, 4178f1a457d06c53a901ea08d2d3fb6e766bc06c4d4fEric Laurent 0, 4179f1a457d06c53a901ea08d2d3fb6e766bc06c4d4fEric Laurent 0, 4180f1a457d06c53a901ea08d2d3fb6e766bc06c4d4fEric Laurent null, 4181f1a457d06c53a901ea08d2d3fb6e766bc06c4d4fEric Laurent MUSIC_ACTIVE_POLL_PERIOD_MS); 4182f1a457d06c53a901ea08d2d3fb6e766bc06c4d4fEric Laurent } 4183b1fbaaccb656ef09a8770c28df15e3e91a452e64Eric Laurent } 4184ae4506e9b5fc3e0c6d9862fbc05b9af7d6742a6eEric Laurent if (!isUsb && (device != AudioSystem.DEVICE_IN_WIRED_HEADSET)) { 4185db45484e4b5858d14da93d3a06311b93bf0cf320Mike Lockwood sendDeviceConnectionIntent(device, state, name); 4186db45484e4b5858d14da93d3a06311b93bf0cf320Mike Lockwood } 4187b1fbaaccb656ef09a8770c28df15e3e91a452e64Eric Laurent } 4188b1fbaaccb656ef09a8770c28df15e3e91a452e64Eric Laurent } 4189b1fbaaccb656ef09a8770c28df15e3e91a452e64Eric Laurent 4190a847ba4080675d395de725cfac5dfd9d5a993d4eJean-Michel Trivi /* cache of the address of the last dock the device was connected to */ 4191a847ba4080675d395de725cfac5dfd9d5a993d4eJean-Michel Trivi private String mDockAddress; 4192a847ba4080675d395de725cfac5dfd9d5a993d4eJean-Michel Trivi 4193a553c25b33c99b345cf1c8688f8df0ed8df14e5aEric Laurent /** 4194a553c25b33c99b345cf1c8688f8df0ed8df14e5aEric Laurent * Receiver for misc intent broadcasts the Phone app cares about. 4195a553c25b33c99b345cf1c8688f8df0ed8df14e5aEric Laurent */ 4196a553c25b33c99b345cf1c8688f8df0ed8df14e5aEric Laurent private class AudioServiceBroadcastReceiver extends BroadcastReceiver { 4197a553c25b33c99b345cf1c8688f8df0ed8df14e5aEric Laurent @Override 4198a553c25b33c99b345cf1c8688f8df0ed8df14e5aEric Laurent public void onReceive(Context context, Intent intent) { 4199a553c25b33c99b345cf1c8688f8df0ed8df14e5aEric Laurent String action = intent.getAction(); 4200ae4506e9b5fc3e0c6d9862fbc05b9af7d6742a6eEric Laurent int outDevice; 4201ae4506e9b5fc3e0c6d9862fbc05b9af7d6742a6eEric Laurent int inDevice; 420259f482764e346a5c5ac118ee1f7b24da645c2559Eric Laurent int state; 4203a553c25b33c99b345cf1c8688f8df0ed8df14e5aEric Laurent 4204758559e6b7e310cf46cc269437f44decd58d68d6Jean-Michel Trivi if (action.equals(Intent.ACTION_DOCK_EVENT)) { 4205758559e6b7e310cf46cc269437f44decd58d68d6Jean-Michel Trivi int dockState = intent.getIntExtra(Intent.EXTRA_DOCK_STATE, 4206758559e6b7e310cf46cc269437f44decd58d68d6Jean-Michel Trivi Intent.EXTRA_DOCK_STATE_UNDOCKED); 4207758559e6b7e310cf46cc269437f44decd58d68d6Jean-Michel Trivi int config; 4208758559e6b7e310cf46cc269437f44decd58d68d6Jean-Michel Trivi switch (dockState) { 4209758559e6b7e310cf46cc269437f44decd58d68d6Jean-Michel Trivi case Intent.EXTRA_DOCK_STATE_DESK: 4210758559e6b7e310cf46cc269437f44decd58d68d6Jean-Michel Trivi config = AudioSystem.FORCE_BT_DESK_DOCK; 4211758559e6b7e310cf46cc269437f44decd58d68d6Jean-Michel Trivi break; 4212758559e6b7e310cf46cc269437f44decd58d68d6Jean-Michel Trivi case Intent.EXTRA_DOCK_STATE_CAR: 4213758559e6b7e310cf46cc269437f44decd58d68d6Jean-Michel Trivi config = AudioSystem.FORCE_BT_CAR_DOCK; 4214758559e6b7e310cf46cc269437f44decd58d68d6Jean-Michel Trivi break; 421521e941bf43362ddc6639a9f2d0828053360f53d7Praveen Bharathi case Intent.EXTRA_DOCK_STATE_LE_DESK: 421608ed1b9d2099ec8231b21353b33b901492ea9885Eric Laurent config = AudioSystem.FORCE_ANALOG_DOCK; 421721e941bf43362ddc6639a9f2d0828053360f53d7Praveen Bharathi break; 421821e941bf43362ddc6639a9f2d0828053360f53d7Praveen Bharathi case Intent.EXTRA_DOCK_STATE_HE_DESK: 421921e941bf43362ddc6639a9f2d0828053360f53d7Praveen Bharathi config = AudioSystem.FORCE_DIGITAL_DOCK; 422021e941bf43362ddc6639a9f2d0828053360f53d7Praveen Bharathi break; 4221758559e6b7e310cf46cc269437f44decd58d68d6Jean-Michel Trivi case Intent.EXTRA_DOCK_STATE_UNDOCKED: 4222758559e6b7e310cf46cc269437f44decd58d68d6Jean-Michel Trivi default: 4223758559e6b7e310cf46cc269437f44decd58d68d6Jean-Michel Trivi config = AudioSystem.FORCE_NONE; 4224758559e6b7e310cf46cc269437f44decd58d68d6Jean-Michel Trivi } 422508ed1b9d2099ec8231b21353b33b901492ea9885Eric Laurent // Low end docks have a menu to enable or disable audio 422608ed1b9d2099ec8231b21353b33b901492ea9885Eric Laurent // (see mDockAudioMediaEnabled) 422708ed1b9d2099ec8231b21353b33b901492ea9885Eric Laurent if (!((dockState == Intent.EXTRA_DOCK_STATE_LE_DESK) || 422808ed1b9d2099ec8231b21353b33b901492ea9885Eric Laurent ((dockState == Intent.EXTRA_DOCK_STATE_UNDOCKED) && 422908ed1b9d2099ec8231b21353b33b901492ea9885Eric Laurent (mDockState == Intent.EXTRA_DOCK_STATE_LE_DESK)))) { 423008ed1b9d2099ec8231b21353b33b901492ea9885Eric Laurent AudioSystem.setForceUse(AudioSystem.FOR_DOCK, config); 423108ed1b9d2099ec8231b21353b33b901492ea9885Eric Laurent } 423208ed1b9d2099ec8231b21353b33b901492ea9885Eric Laurent mDockState = dockState; 423382aa7f017daaaeb96c13e6e3491d5037ab471085Jaikumar Ganesh } else if (action.equals(BluetoothHeadset.ACTION_CONNECTION_STATE_CHANGED)) { 423459f482764e346a5c5ac118ee1f7b24da645c2559Eric Laurent state = intent.getIntExtra(BluetoothProfile.EXTRA_STATE, 423582aa7f017daaaeb96c13e6e3491d5037ab471085Jaikumar Ganesh BluetoothProfile.STATE_DISCONNECTED); 4236ae4506e9b5fc3e0c6d9862fbc05b9af7d6742a6eEric Laurent outDevice = AudioSystem.DEVICE_OUT_BLUETOOTH_SCO; 4237ae4506e9b5fc3e0c6d9862fbc05b9af7d6742a6eEric Laurent inDevice = AudioSystem.DEVICE_IN_BLUETOOTH_SCO_HEADSET; 4238a56d1c72190462aa9e377906583eceb58e0efcddNick Pelly String address = null; 4239dca56b9432e2cc851d1a58920071fed2e1e3d142Eric Laurent 4240dca56b9432e2cc851d1a58920071fed2e1e3d142Eric Laurent BluetoothDevice btDevice = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE); 4241dca56b9432e2cc851d1a58920071fed2e1e3d142Eric Laurent if (btDevice == null) { 4242dca56b9432e2cc851d1a58920071fed2e1e3d142Eric Laurent return; 4243dca56b9432e2cc851d1a58920071fed2e1e3d142Eric Laurent } 4244dca56b9432e2cc851d1a58920071fed2e1e3d142Eric Laurent 4245dca56b9432e2cc851d1a58920071fed2e1e3d142Eric Laurent address = btDevice.getAddress(); 4246dca56b9432e2cc851d1a58920071fed2e1e3d142Eric Laurent BluetoothClass btClass = btDevice.getBluetoothClass(); 4247dca56b9432e2cc851d1a58920071fed2e1e3d142Eric Laurent if (btClass != null) { 4248dca56b9432e2cc851d1a58920071fed2e1e3d142Eric Laurent switch (btClass.getDeviceClass()) { 4249dca56b9432e2cc851d1a58920071fed2e1e3d142Eric Laurent case BluetoothClass.Device.AUDIO_VIDEO_WEARABLE_HEADSET: 4250dca56b9432e2cc851d1a58920071fed2e1e3d142Eric Laurent case BluetoothClass.Device.AUDIO_VIDEO_HANDSFREE: 4251ae4506e9b5fc3e0c6d9862fbc05b9af7d6742a6eEric Laurent outDevice = AudioSystem.DEVICE_OUT_BLUETOOTH_SCO_HEADSET; 4252dca56b9432e2cc851d1a58920071fed2e1e3d142Eric Laurent break; 4253dca56b9432e2cc851d1a58920071fed2e1e3d142Eric Laurent case BluetoothClass.Device.AUDIO_VIDEO_CAR_AUDIO: 4254ae4506e9b5fc3e0c6d9862fbc05b9af7d6742a6eEric Laurent outDevice = AudioSystem.DEVICE_OUT_BLUETOOTH_SCO_CARKIT; 4255dca56b9432e2cc851d1a58920071fed2e1e3d142Eric Laurent break; 4256d5603c126acdd94d9f7400bb1d04188020a425b4Eric Laurent } 4257d5603c126acdd94d9f7400bb1d04188020a425b4Eric Laurent } 4258d5603c126acdd94d9f7400bb1d04188020a425b4Eric Laurent 4259dca56b9432e2cc851d1a58920071fed2e1e3d142Eric Laurent if (!BluetoothAdapter.checkBluetoothAddress(address)) { 4260dca56b9432e2cc851d1a58920071fed2e1e3d142Eric Laurent address = ""; 4261dca56b9432e2cc851d1a58920071fed2e1e3d142Eric Laurent } 4262d5603c126acdd94d9f7400bb1d04188020a425b4Eric Laurent 426359f482764e346a5c5ac118ee1f7b24da645c2559Eric Laurent boolean connected = (state == BluetoothProfile.STATE_CONNECTED); 4264ae4506e9b5fc3e0c6d9862fbc05b9af7d6742a6eEric Laurent boolean success = handleDeviceConnection(connected, outDevice, address) && 4265ae4506e9b5fc3e0c6d9862fbc05b9af7d6742a6eEric Laurent handleDeviceConnection(connected, inDevice, address); 4266ae4506e9b5fc3e0c6d9862fbc05b9af7d6742a6eEric Laurent if (success) { 42676bc7f2cd30b6bd90806942b0722e22daa2108493Eric Laurent synchronized (mScoClients) { 426859f482764e346a5c5ac118ee1f7b24da645c2559Eric Laurent if (connected) { 426959f482764e346a5c5ac118ee1f7b24da645c2559Eric Laurent mBluetoothHeadsetDevice = btDevice; 427059f482764e346a5c5ac118ee1f7b24da645c2559Eric Laurent } else { 42716bc7f2cd30b6bd90806942b0722e22daa2108493Eric Laurent mBluetoothHeadsetDevice = null; 42726bc7f2cd30b6bd90806942b0722e22daa2108493Eric Laurent resetBluetoothSco(); 42736bc7f2cd30b6bd90806942b0722e22daa2108493Eric Laurent } 427462ef767b15a712bab31cc0d5508a330906f535c2Eric Laurent } 4275a553c25b33c99b345cf1c8688f8df0ed8df14e5aEric Laurent } 4276df3614693dd4fe52a116dcd28bd74eae80818a4fPaul McLean } else if (action.equals(Intent.ACTION_USB_AUDIO_ACCESSORY_PLUG)) { 4277df3614693dd4fe52a116dcd28bd74eae80818a4fPaul McLean state = intent.getIntExtra("state", 0); 4278df3614693dd4fe52a116dcd28bd74eae80818a4fPaul McLean 4279df3614693dd4fe52a116dcd28bd74eae80818a4fPaul McLean int alsaCard = intent.getIntExtra("card", -1); 4280df3614693dd4fe52a116dcd28bd74eae80818a4fPaul McLean int alsaDevice = intent.getIntExtra("device", -1); 4281df3614693dd4fe52a116dcd28bd74eae80818a4fPaul McLean 4282df3614693dd4fe52a116dcd28bd74eae80818a4fPaul McLean String params = (alsaCard == -1 && alsaDevice == -1 ? "" 4283df3614693dd4fe52a116dcd28bd74eae80818a4fPaul McLean : "card=" + alsaCard + ";device=" + alsaDevice); 4284df3614693dd4fe52a116dcd28bd74eae80818a4fPaul McLean 4285df3614693dd4fe52a116dcd28bd74eae80818a4fPaul McLean // Playback Device 4286ae4506e9b5fc3e0c6d9862fbc05b9af7d6742a6eEric Laurent outDevice = AudioSystem.DEVICE_OUT_USB_ACCESSORY; 4287ae4506e9b5fc3e0c6d9862fbc05b9af7d6742a6eEric Laurent setWiredDeviceConnectionState(outDevice, state, params); 4288df3614693dd4fe52a116dcd28bd74eae80818a4fPaul McLean } else if (action.equals(Intent.ACTION_USB_AUDIO_DEVICE_PLUG)) { 428959f482764e346a5c5ac118ee1f7b24da645c2559Eric Laurent state = intent.getIntExtra("state", 0); 4290c837a451946b64d70ed7c642fbde03c182c28b6fPaul McLean 429159f482764e346a5c5ac118ee1f7b24da645c2559Eric Laurent int alsaCard = intent.getIntExtra("card", -1); 429259f482764e346a5c5ac118ee1f7b24da645c2559Eric Laurent int alsaDevice = intent.getIntExtra("device", -1); 4293c837a451946b64d70ed7c642fbde03c182c28b6fPaul McLean boolean hasPlayback = intent.getBooleanExtra("hasPlayback", false); 4294c837a451946b64d70ed7c642fbde03c182c28b6fPaul McLean boolean hasCapture = intent.getBooleanExtra("hasCapture", false); 4295c837a451946b64d70ed7c642fbde03c182c28b6fPaul McLean boolean hasMIDI = intent.getBooleanExtra("hasMIDI", false); 4296c837a451946b64d70ed7c642fbde03c182c28b6fPaul McLean 42979841818b9a0280abf59343c9e00a2976dbc084faMike Lockwood String params = (alsaCard == -1 && alsaDevice == -1 ? "" 42989841818b9a0280abf59343c9e00a2976dbc084faMike Lockwood : "card=" + alsaCard + ";device=" + alsaDevice); 4299c837a451946b64d70ed7c642fbde03c182c28b6fPaul McLean 4300c837a451946b64d70ed7c642fbde03c182c28b6fPaul McLean // Playback Device 4301df3614693dd4fe52a116dcd28bd74eae80818a4fPaul McLean if (hasPlayback) { 4302ae4506e9b5fc3e0c6d9862fbc05b9af7d6742a6eEric Laurent outDevice = AudioSystem.DEVICE_OUT_USB_DEVICE; 4303ae4506e9b5fc3e0c6d9862fbc05b9af7d6742a6eEric Laurent setWiredDeviceConnectionState(outDevice, state, params); 4304df3614693dd4fe52a116dcd28bd74eae80818a4fPaul McLean } 4305c837a451946b64d70ed7c642fbde03c182c28b6fPaul McLean 4306c837a451946b64d70ed7c642fbde03c182c28b6fPaul McLean // Capture Device 4307df3614693dd4fe52a116dcd28bd74eae80818a4fPaul McLean if (hasCapture) { 4308ae4506e9b5fc3e0c6d9862fbc05b9af7d6742a6eEric Laurent inDevice = AudioSystem.DEVICE_IN_USB_DEVICE; 4309ae4506e9b5fc3e0c6d9862fbc05b9af7d6742a6eEric Laurent setWiredDeviceConnectionState(inDevice, state, params); 4310df3614693dd4fe52a116dcd28bd74eae80818a4fPaul McLean } 4311df3614693dd4fe52a116dcd28bd74eae80818a4fPaul McLean } else if (action.equals(BluetoothHeadset.ACTION_AUDIO_STATE_CHANGED)) { 431262ef767b15a712bab31cc0d5508a330906f535c2Eric Laurent boolean broadcast = false; 431359f482764e346a5c5ac118ee1f7b24da645c2559Eric Laurent int scoAudioState = AudioManager.SCO_AUDIO_STATE_ERROR; 43143def1eec2baed0b8845ec32c871e249dc533a9d9Eric Laurent synchronized (mScoClients) { 431562ef767b15a712bab31cc0d5508a330906f535c2Eric Laurent int btState = intent.getIntExtra(BluetoothProfile.EXTRA_STATE, -1); 4316dc03c61fe3cd8d0805480e48a974986439977a60Eric Laurent // broadcast intent if the connection was initated by AudioService 4317dc03c61fe3cd8d0805480e48a974986439977a60Eric Laurent if (!mScoClients.isEmpty() && 4318dc03c61fe3cd8d0805480e48a974986439977a60Eric Laurent (mScoAudioState == SCO_STATE_ACTIVE_INTERNAL || 4319dc03c61fe3cd8d0805480e48a974986439977a60Eric Laurent mScoAudioState == SCO_STATE_ACTIVATE_REQ || 4320dc03c61fe3cd8d0805480e48a974986439977a60Eric Laurent mScoAudioState == SCO_STATE_DEACTIVATE_REQ)) { 432162ef767b15a712bab31cc0d5508a330906f535c2Eric Laurent broadcast = true; 432262ef767b15a712bab31cc0d5508a330906f535c2Eric Laurent } 432362ef767b15a712bab31cc0d5508a330906f535c2Eric Laurent switch (btState) { 432462ef767b15a712bab31cc0d5508a330906f535c2Eric Laurent case BluetoothHeadset.STATE_AUDIO_CONNECTED: 432559f482764e346a5c5ac118ee1f7b24da645c2559Eric Laurent scoAudioState = AudioManager.SCO_AUDIO_STATE_CONNECTED; 4326dc03c61fe3cd8d0805480e48a974986439977a60Eric Laurent if (mScoAudioState != SCO_STATE_ACTIVE_INTERNAL && 4327dc03c61fe3cd8d0805480e48a974986439977a60Eric Laurent mScoAudioState != SCO_STATE_DEACTIVATE_REQ && 4328dc03c61fe3cd8d0805480e48a974986439977a60Eric Laurent mScoAudioState != SCO_STATE_DEACTIVATE_EXT_REQ) { 432962ef767b15a712bab31cc0d5508a330906f535c2Eric Laurent mScoAudioState = SCO_STATE_ACTIVE_EXTERNAL; 43303def1eec2baed0b8845ec32c871e249dc533a9d9Eric Laurent } 433162ef767b15a712bab31cc0d5508a330906f535c2Eric Laurent break; 433262ef767b15a712bab31cc0d5508a330906f535c2Eric Laurent case BluetoothHeadset.STATE_AUDIO_DISCONNECTED: 433359f482764e346a5c5ac118ee1f7b24da645c2559Eric Laurent scoAudioState = AudioManager.SCO_AUDIO_STATE_DISCONNECTED; 433462ef767b15a712bab31cc0d5508a330906f535c2Eric Laurent mScoAudioState = SCO_STATE_INACTIVE; 4335d7454be47f4111c0478a502353e11dea401378bdEric Laurent clearAllScoClients(0, false); 433662ef767b15a712bab31cc0d5508a330906f535c2Eric Laurent break; 433762ef767b15a712bab31cc0d5508a330906f535c2Eric Laurent case BluetoothHeadset.STATE_AUDIO_CONNECTING: 4338dc03c61fe3cd8d0805480e48a974986439977a60Eric Laurent if (mScoAudioState != SCO_STATE_ACTIVE_INTERNAL && 4339dc03c61fe3cd8d0805480e48a974986439977a60Eric Laurent mScoAudioState != SCO_STATE_DEACTIVATE_REQ && 4340dc03c61fe3cd8d0805480e48a974986439977a60Eric Laurent mScoAudioState != SCO_STATE_DEACTIVATE_EXT_REQ) { 434162ef767b15a712bab31cc0d5508a330906f535c2Eric Laurent mScoAudioState = SCO_STATE_ACTIVE_EXTERNAL; 43423def1eec2baed0b8845ec32c871e249dc533a9d9Eric Laurent } 434362ef767b15a712bab31cc0d5508a330906f535c2Eric Laurent default: 434462ef767b15a712bab31cc0d5508a330906f535c2Eric Laurent // do not broadcast CONNECTING or invalid state 434562ef767b15a712bab31cc0d5508a330906f535c2Eric Laurent broadcast = false; 434662ef767b15a712bab31cc0d5508a330906f535c2Eric Laurent break; 43473def1eec2baed0b8845ec32c871e249dc533a9d9Eric Laurent } 43483def1eec2baed0b8845ec32c871e249dc533a9d9Eric Laurent } 434962ef767b15a712bab31cc0d5508a330906f535c2Eric Laurent if (broadcast) { 435059f482764e346a5c5ac118ee1f7b24da645c2559Eric Laurent broadcastScoConnectionState(scoAudioState); 4351dc03c61fe3cd8d0805480e48a974986439977a60Eric Laurent //FIXME: this is to maintain compatibility with deprecated intent 4352dc03c61fe3cd8d0805480e48a974986439977a60Eric Laurent // AudioManager.ACTION_SCO_AUDIO_STATE_CHANGED. Remove when appropriate. 435362ef767b15a712bab31cc0d5508a330906f535c2Eric Laurent Intent newIntent = new Intent(AudioManager.ACTION_SCO_AUDIO_STATE_CHANGED); 435459f482764e346a5c5ac118ee1f7b24da645c2559Eric Laurent newIntent.putExtra(AudioManager.EXTRA_SCO_AUDIO_STATE, scoAudioState); 43555ac72a29593ab9a20337a2225df52bdf4754be02Dianne Hackborn sendStickyBroadcastToAll(newIntent); 435662ef767b15a712bab31cc0d5508a330906f535c2Eric Laurent } 4357950e8cb40a6d826af4cc2eef9d3908c1b70486e6Eric Laurent } else if (action.equals(Intent.ACTION_SCREEN_ON)) { 4358950e8cb40a6d826af4cc2eef9d3908c1b70486e6Eric Laurent AudioSystem.setParameters("screen_state=on"); 4359950e8cb40a6d826af4cc2eef9d3908c1b70486e6Eric Laurent } else if (action.equals(Intent.ACTION_SCREEN_OFF)) { 4360950e8cb40a6d826af4cc2eef9d3908c1b70486e6Eric Laurent AudioSystem.setParameters("screen_state=off"); 4361961cae92540763226648813d111c5b5c3b0f1597Dianne Hackborn } else if (action.equals(Intent.ACTION_CONFIGURATION_CHANGED)) { 4362f26f01784e1c733c53cad3ed31918e73448ce369Jean-Michel Trivi handleConfigurationChanged(context); 4363bc0fab1fc2db832ef86d8a33466ec4d68b103ca0Eric Laurent } else if (action.equals(Intent.ACTION_USER_SWITCHED)) { 4364f4a8eb22112c534f436357b50f231778c5c15c25Jean-Michel Trivi // attempt to stop music playback for background user 43655bfaeaef3fc348d66f48b86be08655e91dff910aEric Laurent sendMsg(mAudioHandler, 43665bfaeaef3fc348d66f48b86be08655e91dff910aEric Laurent MSG_BROADCAST_AUDIO_BECOMING_NOISY, 43675bfaeaef3fc348d66f48b86be08655e91dff910aEric Laurent SENDMSG_REPLACE, 43685bfaeaef3fc348d66f48b86be08655e91dff910aEric Laurent 0, 43695bfaeaef3fc348d66f48b86be08655e91dff910aEric Laurent 0, 43705bfaeaef3fc348d66f48b86be08655e91dff910aEric Laurent null, 43715bfaeaef3fc348d66f48b86be08655e91dff910aEric Laurent 0); 4372f4a8eb22112c534f436357b50f231778c5c15c25Jean-Michel Trivi // the current audio focus owner is no longer valid 4373fa9a69805b001034aa04c3b33989a7ac21522371Jean-Michel Trivi mMediaFocusControl.discardAudioFocusOwner(); 4374f4a8eb22112c534f436357b50f231778c5c15c25Jean-Michel Trivi 43755bfaeaef3fc348d66f48b86be08655e91dff910aEric Laurent // load volume settings for new user 4376bc0fab1fc2db832ef86d8a33466ec4d68b103ca0Eric Laurent readAudioSettings(true /*userSwitch*/); 4377bc0fab1fc2db832ef86d8a33466ec4d68b103ca0Eric Laurent // preserve STREAM_MUSIC volume from one user to the next. 4378bc0fab1fc2db832ef86d8a33466ec4d68b103ca0Eric Laurent sendMsg(mAudioHandler, 4379bc0fab1fc2db832ef86d8a33466ec4d68b103ca0Eric Laurent MSG_SET_ALL_VOLUMES, 4380bc0fab1fc2db832ef86d8a33466ec4d68b103ca0Eric Laurent SENDMSG_QUEUE, 4381bc0fab1fc2db832ef86d8a33466ec4d68b103ca0Eric Laurent 0, 4382bc0fab1fc2db832ef86d8a33466ec4d68b103ca0Eric Laurent 0, 4383bc0fab1fc2db832ef86d8a33466ec4d68b103ca0Eric Laurent mStreamStates[AudioSystem.STREAM_MUSIC], 0); 4384a553c25b33c99b345cf1c8688f8df0ed8df14e5aEric Laurent } 4385a553c25b33c99b345cf1c8688f8df0ed8df14e5aEric Laurent } 4386c837a451946b64d70ed7c642fbde03c182c28b6fPaul McLean } // end class AudioServiceBroadcastReceiver 4387d5176cfe6eae954e9cef1e2ec17859a5089e1330Jean-Michel Trivi 4388d5176cfe6eae954e9cef1e2ec17859a5089e1330Jean-Michel Trivi //========================================================================================== 4389fa9a69805b001034aa04c3b33989a7ac21522371Jean-Michel Trivi // RemoteControlDisplay / RemoteControlClient / Remote info 4390d5176cfe6eae954e9cef1e2ec17859a5089e1330Jean-Michel Trivi //========================================================================================== 4391f108cdd9ee5efe354d87edd02a07b323298c116cJean-Michel Trivi public boolean registerRemoteController(IRemoteControlDisplay rcd, int w, int h, 4392f108cdd9ee5efe354d87edd02a07b323298c116cJean-Michel Trivi ComponentName listenerComp) { 4393f108cdd9ee5efe354d87edd02a07b323298c116cJean-Michel Trivi return mMediaFocusControl.registerRemoteController(rcd, w, h, listenerComp); 4394f108cdd9ee5efe354d87edd02a07b323298c116cJean-Michel Trivi } 4395f108cdd9ee5efe354d87edd02a07b323298c116cJean-Michel Trivi 43967ddd226e7c6e759feaf2747a90be1cc06acf37a3Jean-Michel Trivi public boolean registerRemoteControlDisplay(IRemoteControlDisplay rcd, int w, int h) { 4397f108cdd9ee5efe354d87edd02a07b323298c116cJean-Michel Trivi return mMediaFocusControl.registerRemoteControlDisplay(rcd, w, h); 4398e5e1e870fdb35f5291790e6d178bde7126f6fe35Jean-Michel Trivi } 4399e5e1e870fdb35f5291790e6d178bde7126f6fe35Jean-Michel Trivi 4400fa9a69805b001034aa04c3b33989a7ac21522371Jean-Michel Trivi public void unregisterRemoteControlDisplay(IRemoteControlDisplay rcd) { 4401fa9a69805b001034aa04c3b33989a7ac21522371Jean-Michel Trivi mMediaFocusControl.unregisterRemoteControlDisplay(rcd); 4402d5176cfe6eae954e9cef1e2ec17859a5089e1330Jean-Michel Trivi } 4403d5176cfe6eae954e9cef1e2ec17859a5089e1330Jean-Michel Trivi 4404fa9a69805b001034aa04c3b33989a7ac21522371Jean-Michel Trivi public void remoteControlDisplayUsesBitmapSize(IRemoteControlDisplay rcd, int w, int h) { 4405fa9a69805b001034aa04c3b33989a7ac21522371Jean-Michel Trivi mMediaFocusControl.remoteControlDisplayUsesBitmapSize(rcd, w, h); 4406d5176cfe6eae954e9cef1e2ec17859a5089e1330Jean-Michel Trivi } 4407d5176cfe6eae954e9cef1e2ec17859a5089e1330Jean-Michel Trivi 4408fa9a69805b001034aa04c3b33989a7ac21522371Jean-Michel Trivi public void remoteControlDisplayWantsPlaybackPositionSync(IRemoteControlDisplay rcd, 4409fa9a69805b001034aa04c3b33989a7ac21522371Jean-Michel Trivi boolean wantsSync) { 4410fa9a69805b001034aa04c3b33989a7ac21522371Jean-Michel Trivi mMediaFocusControl.remoteControlDisplayWantsPlaybackPositionSync(rcd, wantsSync); 4411d5176cfe6eae954e9cef1e2ec17859a5089e1330Jean-Michel Trivi } 4412d5176cfe6eae954e9cef1e2ec17859a5089e1330Jean-Michel Trivi 44133346a802087f621c6441bc512dfcc17b07143fc6John Spurlock @Override 4414fa9a69805b001034aa04c3b33989a7ac21522371Jean-Michel Trivi public void setRemoteStreamVolume(int index) { 44153346a802087f621c6441bc512dfcc17b07143fc6John Spurlock enforceSelfOrSystemUI("set the remote stream volume"); 4416fa9a69805b001034aa04c3b33989a7ac21522371Jean-Michel Trivi mMediaFocusControl.setRemoteStreamVolume(index); 4417d327f21626217aa3c9c0cdb7a84a742c531e59a3Jean-Michel Trivi } 4418d327f21626217aa3c9c0cdb7a84a742c531e59a3Jean-Michel Trivi 4419fa9a69805b001034aa04c3b33989a7ac21522371Jean-Michel Trivi //========================================================================================== 4420fa9a69805b001034aa04c3b33989a7ac21522371Jean-Michel Trivi // Audio Focus 4421fa9a69805b001034aa04c3b33989a7ac21522371Jean-Michel Trivi //========================================================================================== 4422fa9a69805b001034aa04c3b33989a7ac21522371Jean-Michel Trivi public int requestAudioFocus(int mainStreamType, int durationHint, IBinder cb, 4423fa9a69805b001034aa04c3b33989a7ac21522371Jean-Michel Trivi IAudioFocusDispatcher fd, String clientId, String callingPackageName) { 4424fa9a69805b001034aa04c3b33989a7ac21522371Jean-Michel Trivi return mMediaFocusControl.requestAudioFocus(mainStreamType, durationHint, cb, fd, 4425fa9a69805b001034aa04c3b33989a7ac21522371Jean-Michel Trivi clientId, callingPackageName); 44264294b83927f51e5c115ebaafd2e185ba5de91436Jean-Michel Trivi } 44274294b83927f51e5c115ebaafd2e185ba5de91436Jean-Michel Trivi 4428fa9a69805b001034aa04c3b33989a7ac21522371Jean-Michel Trivi public int abandonAudioFocus(IAudioFocusDispatcher fd, String clientId) { 4429fa9a69805b001034aa04c3b33989a7ac21522371Jean-Michel Trivi return mMediaFocusControl.abandonAudioFocus(fd, clientId); 4430c68022258ebd3dd97a5079ba99f4f3cd12b223b0Jean-Michel Trivi } 4431c68022258ebd3dd97a5079ba99f4f3cd12b223b0Jean-Michel Trivi 4432fa9a69805b001034aa04c3b33989a7ac21522371Jean-Michel Trivi public void unregisterAudioFocusClient(String clientId) { 4433fa9a69805b001034aa04c3b33989a7ac21522371Jean-Michel Trivi mMediaFocusControl.unregisterAudioFocusClient(clientId); 44343114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi } 44353114ce3861f20f9a5c2c59dd2629197a1f4874a8Jean-Michel Trivi 44362380566debfc57eb1cc07db1306ccee23b84ddd4Jean-Michel Trivi public int getCurrentAudioFocus() { 44372380566debfc57eb1cc07db1306ccee23b84ddd4Jean-Michel Trivi return mMediaFocusControl.getCurrentAudioFocus(); 44382380566debfc57eb1cc07db1306ccee23b84ddd4Jean-Michel Trivi } 44392380566debfc57eb1cc07db1306ccee23b84ddd4Jean-Michel Trivi 4440f26f01784e1c733c53cad3ed31918e73448ce369Jean-Michel Trivi //========================================================================================== 4441f26f01784e1c733c53cad3ed31918e73448ce369Jean-Michel Trivi // Device orientation 4442f26f01784e1c733c53cad3ed31918e73448ce369Jean-Michel Trivi //========================================================================================== 4443f26f01784e1c733c53cad3ed31918e73448ce369Jean-Michel Trivi /** 4444bb6f8711a7f804d39c45218db2d6339940cc5d35Jean-Michel Trivi * Handles device configuration changes that may map to a change in the orientation 4445bb6f8711a7f804d39c45218db2d6339940cc5d35Jean-Michel Trivi * or orientation. 4446bb6f8711a7f804d39c45218db2d6339940cc5d35Jean-Michel Trivi * Monitoring orientation and rotation is optional, and is defined by the definition and value 4447bb6f8711a7f804d39c45218db2d6339940cc5d35Jean-Michel Trivi * of the "ro.audio.monitorOrientation" and "ro.audio.monitorRotation" system properties. 4448f26f01784e1c733c53cad3ed31918e73448ce369Jean-Michel Trivi */ 4449f26f01784e1c733c53cad3ed31918e73448ce369Jean-Michel Trivi private void handleConfigurationChanged(Context context) { 4450f26f01784e1c733c53cad3ed31918e73448ce369Jean-Michel Trivi try { 4451f26f01784e1c733c53cad3ed31918e73448ce369Jean-Michel Trivi // reading new orientation "safely" (i.e. under try catch) in case anything 4452f26f01784e1c733c53cad3ed31918e73448ce369Jean-Michel Trivi // goes wrong when obtaining resources and configuration 4453d640bd325c3be9a350058c835b880a7e0b40dc60Eric Laurent Configuration config = context.getResources().getConfiguration(); 4454bb6f8711a7f804d39c45218db2d6339940cc5d35Jean-Michel Trivi // TODO merge rotation and orientation 4455d640bd325c3be9a350058c835b880a7e0b40dc60Eric Laurent if (mMonitorOrientation) { 4456d640bd325c3be9a350058c835b880a7e0b40dc60Eric Laurent int newOrientation = config.orientation; 4457d640bd325c3be9a350058c835b880a7e0b40dc60Eric Laurent if (newOrientation != mDeviceOrientation) { 4458d640bd325c3be9a350058c835b880a7e0b40dc60Eric Laurent mDeviceOrientation = newOrientation; 4459d640bd325c3be9a350058c835b880a7e0b40dc60Eric Laurent setOrientationForAudioSystem(); 4460d640bd325c3be9a350058c835b880a7e0b40dc60Eric Laurent } 4461f26f01784e1c733c53cad3ed31918e73448ce369Jean-Michel Trivi } 4462bb6f8711a7f804d39c45218db2d6339940cc5d35Jean-Michel Trivi if (mMonitorRotation) { 4463bb6f8711a7f804d39c45218db2d6339940cc5d35Jean-Michel Trivi int newRotation = ((WindowManager) context.getSystemService( 4464bb6f8711a7f804d39c45218db2d6339940cc5d35Jean-Michel Trivi Context.WINDOW_SERVICE)).getDefaultDisplay().getRotation(); 4465bb6f8711a7f804d39c45218db2d6339940cc5d35Jean-Michel Trivi if (newRotation != mDeviceRotation) { 4466bb6f8711a7f804d39c45218db2d6339940cc5d35Jean-Michel Trivi mDeviceRotation = newRotation; 4467bb6f8711a7f804d39c45218db2d6339940cc5d35Jean-Michel Trivi setRotationForAudioSystem(); 4468bb6f8711a7f804d39c45218db2d6339940cc5d35Jean-Michel Trivi } 4469bb6f8711a7f804d39c45218db2d6339940cc5d35Jean-Michel Trivi } 4470d640bd325c3be9a350058c835b880a7e0b40dc60Eric Laurent sendMsg(mAudioHandler, 4471d640bd325c3be9a350058c835b880a7e0b40dc60Eric Laurent MSG_CONFIGURE_SAFE_MEDIA_VOLUME, 4472d640bd325c3be9a350058c835b880a7e0b40dc60Eric Laurent SENDMSG_REPLACE, 4473d640bd325c3be9a350058c835b880a7e0b40dc60Eric Laurent 0, 4474d640bd325c3be9a350058c835b880a7e0b40dc60Eric Laurent 0, 4475d640bd325c3be9a350058c835b880a7e0b40dc60Eric Laurent null, 4476d640bd325c3be9a350058c835b880a7e0b40dc60Eric Laurent 0); 4477dd45d01128423a82652a3c9d77fa393631d95229Eric Laurent 4478dd45d01128423a82652a3c9d77fa393631d95229Eric Laurent boolean cameraSoundForced = mContext.getResources().getBoolean( 4479dd45d01128423a82652a3c9d77fa393631d95229Eric Laurent com.android.internal.R.bool.config_camera_sound_forced); 4480dd45d01128423a82652a3c9d77fa393631d95229Eric Laurent synchronized (mSettingsLock) { 4481dd45d01128423a82652a3c9d77fa393631d95229Eric Laurent synchronized (mCameraSoundForced) { 4482dd45d01128423a82652a3c9d77fa393631d95229Eric Laurent if (cameraSoundForced != mCameraSoundForced) { 4483dd45d01128423a82652a3c9d77fa393631d95229Eric Laurent mCameraSoundForced = cameraSoundForced; 4484dd45d01128423a82652a3c9d77fa393631d95229Eric Laurent 4485dd45d01128423a82652a3c9d77fa393631d95229Eric Laurent VolumeStreamState s = mStreamStates[AudioSystem.STREAM_SYSTEM_ENFORCED]; 4486dd45d01128423a82652a3c9d77fa393631d95229Eric Laurent if (cameraSoundForced) { 4487dd45d01128423a82652a3c9d77fa393631d95229Eric Laurent s.setAllIndexesToMax(); 4488dd45d01128423a82652a3c9d77fa393631d95229Eric Laurent mRingerModeAffectedStreams &= 4489dd45d01128423a82652a3c9d77fa393631d95229Eric Laurent ~(1 << AudioSystem.STREAM_SYSTEM_ENFORCED); 4490dd45d01128423a82652a3c9d77fa393631d95229Eric Laurent } else { 449142b041ed4f184e3af7f788eb07307f556a2a6616Eric Laurent s.setAllIndexes(mStreamStates[AudioSystem.STREAM_SYSTEM]); 4492dd45d01128423a82652a3c9d77fa393631d95229Eric Laurent mRingerModeAffectedStreams |= 4493dd45d01128423a82652a3c9d77fa393631d95229Eric Laurent (1 << AudioSystem.STREAM_SYSTEM_ENFORCED); 4494dd45d01128423a82652a3c9d77fa393631d95229Eric Laurent } 4495dd45d01128423a82652a3c9d77fa393631d95229Eric Laurent // take new state into account for streams muted by ringer mode 4496dd45d01128423a82652a3c9d77fa393631d95229Eric Laurent setRingerModeInt(getRingerMode(), false); 4497dd45d01128423a82652a3c9d77fa393631d95229Eric Laurent 4498dd45d01128423a82652a3c9d77fa393631d95229Eric Laurent sendMsg(mAudioHandler, 4499dd45d01128423a82652a3c9d77fa393631d95229Eric Laurent MSG_SET_FORCE_USE, 4500dd45d01128423a82652a3c9d77fa393631d95229Eric Laurent SENDMSG_QUEUE, 4501dd45d01128423a82652a3c9d77fa393631d95229Eric Laurent AudioSystem.FOR_SYSTEM, 4502dd45d01128423a82652a3c9d77fa393631d95229Eric Laurent cameraSoundForced ? 4503dd45d01128423a82652a3c9d77fa393631d95229Eric Laurent AudioSystem.FORCE_SYSTEM_ENFORCED : AudioSystem.FORCE_NONE, 4504dd45d01128423a82652a3c9d77fa393631d95229Eric Laurent null, 4505dd45d01128423a82652a3c9d77fa393631d95229Eric Laurent 0); 4506dd45d01128423a82652a3c9d77fa393631d95229Eric Laurent 4507dd45d01128423a82652a3c9d77fa393631d95229Eric Laurent sendMsg(mAudioHandler, 4508dd45d01128423a82652a3c9d77fa393631d95229Eric Laurent MSG_SET_ALL_VOLUMES, 4509dd45d01128423a82652a3c9d77fa393631d95229Eric Laurent SENDMSG_QUEUE, 4510dd45d01128423a82652a3c9d77fa393631d95229Eric Laurent 0, 4511dd45d01128423a82652a3c9d77fa393631d95229Eric Laurent 0, 4512dd45d01128423a82652a3c9d77fa393631d95229Eric Laurent mStreamStates[AudioSystem.STREAM_SYSTEM_ENFORCED], 0); 4513dd45d01128423a82652a3c9d77fa393631d95229Eric Laurent } 4514dd45d01128423a82652a3c9d77fa393631d95229Eric Laurent } 4515dd45d01128423a82652a3c9d77fa393631d95229Eric Laurent } 45163346a802087f621c6441bc512dfcc17b07143fc6John Spurlock mVolumeController.setLayoutDirection(config.getLayoutDirection()); 4517f26f01784e1c733c53cad3ed31918e73448ce369Jean-Michel Trivi } catch (Exception e) { 4518bb6f8711a7f804d39c45218db2d6339940cc5d35Jean-Michel Trivi Log.e(TAG, "Error handling configuration change: ", e); 4519f26f01784e1c733c53cad3ed31918e73448ce369Jean-Michel Trivi } 4520f26f01784e1c733c53cad3ed31918e73448ce369Jean-Michel Trivi } 4521f26f01784e1c733c53cad3ed31918e73448ce369Jean-Michel Trivi 4522f26f01784e1c733c53cad3ed31918e73448ce369Jean-Michel Trivi private void setOrientationForAudioSystem() { 4523f26f01784e1c733c53cad3ed31918e73448ce369Jean-Michel Trivi switch (mDeviceOrientation) { 4524f26f01784e1c733c53cad3ed31918e73448ce369Jean-Michel Trivi case Configuration.ORIENTATION_LANDSCAPE: 4525f26f01784e1c733c53cad3ed31918e73448ce369Jean-Michel Trivi //Log.i(TAG, "orientation is landscape"); 4526f26f01784e1c733c53cad3ed31918e73448ce369Jean-Michel Trivi AudioSystem.setParameters("orientation=landscape"); 4527f26f01784e1c733c53cad3ed31918e73448ce369Jean-Michel Trivi break; 4528f26f01784e1c733c53cad3ed31918e73448ce369Jean-Michel Trivi case Configuration.ORIENTATION_PORTRAIT: 4529f26f01784e1c733c53cad3ed31918e73448ce369Jean-Michel Trivi //Log.i(TAG, "orientation is portrait"); 4530f26f01784e1c733c53cad3ed31918e73448ce369Jean-Michel Trivi AudioSystem.setParameters("orientation=portrait"); 4531f26f01784e1c733c53cad3ed31918e73448ce369Jean-Michel Trivi break; 4532f26f01784e1c733c53cad3ed31918e73448ce369Jean-Michel Trivi case Configuration.ORIENTATION_SQUARE: 4533f26f01784e1c733c53cad3ed31918e73448ce369Jean-Michel Trivi //Log.i(TAG, "orientation is square"); 4534f26f01784e1c733c53cad3ed31918e73448ce369Jean-Michel Trivi AudioSystem.setParameters("orientation=square"); 4535f26f01784e1c733c53cad3ed31918e73448ce369Jean-Michel Trivi break; 4536f26f01784e1c733c53cad3ed31918e73448ce369Jean-Michel Trivi case Configuration.ORIENTATION_UNDEFINED: 4537f26f01784e1c733c53cad3ed31918e73448ce369Jean-Michel Trivi //Log.i(TAG, "orientation is undefined"); 4538f26f01784e1c733c53cad3ed31918e73448ce369Jean-Michel Trivi AudioSystem.setParameters("orientation=undefined"); 4539f26f01784e1c733c53cad3ed31918e73448ce369Jean-Michel Trivi break; 4540f26f01784e1c733c53cad3ed31918e73448ce369Jean-Michel Trivi default: 4541f26f01784e1c733c53cad3ed31918e73448ce369Jean-Michel Trivi Log.e(TAG, "Unknown orientation"); 4542f26f01784e1c733c53cad3ed31918e73448ce369Jean-Michel Trivi } 4543f26f01784e1c733c53cad3ed31918e73448ce369Jean-Michel Trivi } 4544f26f01784e1c733c53cad3ed31918e73448ce369Jean-Michel Trivi 4545bb6f8711a7f804d39c45218db2d6339940cc5d35Jean-Michel Trivi private void setRotationForAudioSystem() { 4546bb6f8711a7f804d39c45218db2d6339940cc5d35Jean-Michel Trivi switch (mDeviceRotation) { 4547bb6f8711a7f804d39c45218db2d6339940cc5d35Jean-Michel Trivi case Surface.ROTATION_0: 4548bb6f8711a7f804d39c45218db2d6339940cc5d35Jean-Michel Trivi AudioSystem.setParameters("rotation=0"); 4549bb6f8711a7f804d39c45218db2d6339940cc5d35Jean-Michel Trivi break; 4550bb6f8711a7f804d39c45218db2d6339940cc5d35Jean-Michel Trivi case Surface.ROTATION_90: 4551bb6f8711a7f804d39c45218db2d6339940cc5d35Jean-Michel Trivi AudioSystem.setParameters("rotation=90"); 4552bb6f8711a7f804d39c45218db2d6339940cc5d35Jean-Michel Trivi break; 4553bb6f8711a7f804d39c45218db2d6339940cc5d35Jean-Michel Trivi case Surface.ROTATION_180: 4554bb6f8711a7f804d39c45218db2d6339940cc5d35Jean-Michel Trivi AudioSystem.setParameters("rotation=180"); 4555bb6f8711a7f804d39c45218db2d6339940cc5d35Jean-Michel Trivi break; 4556bb6f8711a7f804d39c45218db2d6339940cc5d35Jean-Michel Trivi case Surface.ROTATION_270: 4557bb6f8711a7f804d39c45218db2d6339940cc5d35Jean-Michel Trivi AudioSystem.setParameters("rotation=270"); 4558bb6f8711a7f804d39c45218db2d6339940cc5d35Jean-Michel Trivi break; 4559bb6f8711a7f804d39c45218db2d6339940cc5d35Jean-Michel Trivi default: 4560bb6f8711a7f804d39c45218db2d6339940cc5d35Jean-Michel Trivi Log.e(TAG, "Unknown device rotation"); 4561bb6f8711a7f804d39c45218db2d6339940cc5d35Jean-Michel Trivi } 4562bb6f8711a7f804d39c45218db2d6339940cc5d35Jean-Michel Trivi } 4563bb6f8711a7f804d39c45218db2d6339940cc5d35Jean-Michel Trivi 4564f26f01784e1c733c53cad3ed31918e73448ce369Jean-Michel Trivi 45657847211fb4699bf6018e29d214a918ed6657319bEric Laurent // Handles request to override default use of A2DP for media. 45667847211fb4699bf6018e29d214a918ed6657319bEric Laurent public void setBluetoothA2dpOnInt(boolean on) { 45677847211fb4699bf6018e29d214a918ed6657319bEric Laurent synchronized (mBluetoothA2dpEnabledLock) { 45687847211fb4699bf6018e29d214a918ed6657319bEric Laurent mBluetoothA2dpEnabled = on; 4569c390bed06b4a572e273ead1254da9a932e04dce3Eric Laurent mAudioHandler.removeMessages(MSG_SET_FORCE_BT_A2DP_USE); 4570c390bed06b4a572e273ead1254da9a932e04dce3Eric Laurent AudioSystem.setForceUse(AudioSystem.FOR_MEDIA, 4571c390bed06b4a572e273ead1254da9a932e04dce3Eric Laurent mBluetoothA2dpEnabled ? AudioSystem.FORCE_NONE : AudioSystem.FORCE_NO_BT_A2DP); 45727847211fb4699bf6018e29d214a918ed6657319bEric Laurent } 45737847211fb4699bf6018e29d214a918ed6657319bEric Laurent } 45747847211fb4699bf6018e29d214a918ed6657319bEric Laurent 4575d5176cfe6eae954e9cef1e2ec17859a5089e1330Jean-Michel Trivi @Override 4576098d580cc2bb6c0891c756a4e5230c6c6b0d2376Jeff Sharkey public void setRingtonePlayer(IRingtonePlayer player) { 4577098d580cc2bb6c0891c756a4e5230c6c6b0d2376Jeff Sharkey mContext.enforceCallingOrSelfPermission(REMOTE_AUDIO_PLAYBACK, null); 4578098d580cc2bb6c0891c756a4e5230c6c6b0d2376Jeff Sharkey mRingtonePlayer = player; 4579098d580cc2bb6c0891c756a4e5230c6c6b0d2376Jeff Sharkey } 4580098d580cc2bb6c0891c756a4e5230c6c6b0d2376Jeff Sharkey 4581098d580cc2bb6c0891c756a4e5230c6c6b0d2376Jeff Sharkey @Override 4582098d580cc2bb6c0891c756a4e5230c6c6b0d2376Jeff Sharkey public IRingtonePlayer getRingtonePlayer() { 4583098d580cc2bb6c0891c756a4e5230c6c6b0d2376Jeff Sharkey return mRingtonePlayer; 4584098d580cc2bb6c0891c756a4e5230c6c6b0d2376Jeff Sharkey } 4585098d580cc2bb6c0891c756a4e5230c6c6b0d2376Jeff Sharkey 4586098d580cc2bb6c0891c756a4e5230c6c6b0d2376Jeff Sharkey @Override 4587632ca417f0a33e3fa9ccece531afa2db3f0d4a30Dianne Hackborn public AudioRoutesInfo startWatchingRoutes(IAudioRoutesObserver observer) { 4588632ca417f0a33e3fa9ccece531afa2db3f0d4a30Dianne Hackborn synchronized (mCurAudioRoutes) { 4589632ca417f0a33e3fa9ccece531afa2db3f0d4a30Dianne Hackborn AudioRoutesInfo routes = new AudioRoutesInfo(mCurAudioRoutes); 4590632ca417f0a33e3fa9ccece531afa2db3f0d4a30Dianne Hackborn mRoutesObservers.register(observer); 4591632ca417f0a33e3fa9ccece531afa2db3f0d4a30Dianne Hackborn return routes; 4592632ca417f0a33e3fa9ccece531afa2db3f0d4a30Dianne Hackborn } 4593632ca417f0a33e3fa9ccece531afa2db3f0d4a30Dianne Hackborn } 4594632ca417f0a33e3fa9ccece531afa2db3f0d4a30Dianne Hackborn 4595c34dcc1e1ebf152bb400abbb8bc25f7dc0c3ba97Eric Laurent 4596c34dcc1e1ebf152bb400abbb8bc25f7dc0c3ba97Eric Laurent //========================================================================================== 4597c34dcc1e1ebf152bb400abbb8bc25f7dc0c3ba97Eric Laurent // Safe media volume management. 4598c34dcc1e1ebf152bb400abbb8bc25f7dc0c3ba97Eric Laurent // MUSIC stream volume level is limited when headphones are connected according to safety 4599c34dcc1e1ebf152bb400abbb8bc25f7dc0c3ba97Eric Laurent // regulation. When the user attempts to raise the volume above the limit, a warning is 4600c34dcc1e1ebf152bb400abbb8bc25f7dc0c3ba97Eric Laurent // displayed and the user has to acknowlegde before the volume is actually changed. 4601c34dcc1e1ebf152bb400abbb8bc25f7dc0c3ba97Eric Laurent // The volume index corresponding to the limit is stored in config_safe_media_volume_index 4602c34dcc1e1ebf152bb400abbb8bc25f7dc0c3ba97Eric Laurent // property. Platforms with a different limit must set this property accordingly in their 4603c34dcc1e1ebf152bb400abbb8bc25f7dc0c3ba97Eric Laurent // overlay. 4604c34dcc1e1ebf152bb400abbb8bc25f7dc0c3ba97Eric Laurent //========================================================================================== 4605c34dcc1e1ebf152bb400abbb8bc25f7dc0c3ba97Eric Laurent 4606d640bd325c3be9a350058c835b880a7e0b40dc60Eric Laurent // mSafeMediaVolumeState indicates whether the media volume is limited over headphones. 4607d640bd325c3be9a350058c835b880a7e0b40dc60Eric Laurent // It is SAFE_MEDIA_VOLUME_NOT_CONFIGURED at boot time until a network service is connected 4608d640bd325c3be9a350058c835b880a7e0b40dc60Eric Laurent // or the configure time is elapsed. It is then set to SAFE_MEDIA_VOLUME_ACTIVE or 4609d640bd325c3be9a350058c835b880a7e0b40dc60Eric Laurent // SAFE_MEDIA_VOLUME_DISABLED according to country option. If not SAFE_MEDIA_VOLUME_DISABLED, it 4610d640bd325c3be9a350058c835b880a7e0b40dc60Eric Laurent // can be set to SAFE_MEDIA_VOLUME_INACTIVE by calling AudioService.disableSafeMediaVolume() 4611d640bd325c3be9a350058c835b880a7e0b40dc60Eric Laurent // (when user opts out). 4612d640bd325c3be9a350058c835b880a7e0b40dc60Eric Laurent private final int SAFE_MEDIA_VOLUME_NOT_CONFIGURED = 0; 4613d640bd325c3be9a350058c835b880a7e0b40dc60Eric Laurent private final int SAFE_MEDIA_VOLUME_DISABLED = 1; 4614d640bd325c3be9a350058c835b880a7e0b40dc60Eric Laurent private final int SAFE_MEDIA_VOLUME_INACTIVE = 2; 4615d640bd325c3be9a350058c835b880a7e0b40dc60Eric Laurent private final int SAFE_MEDIA_VOLUME_ACTIVE = 3; 4616d640bd325c3be9a350058c835b880a7e0b40dc60Eric Laurent private Integer mSafeMediaVolumeState; 4617d640bd325c3be9a350058c835b880a7e0b40dc60Eric Laurent 4618d640bd325c3be9a350058c835b880a7e0b40dc60Eric Laurent private int mMcc = 0; 4619c34dcc1e1ebf152bb400abbb8bc25f7dc0c3ba97Eric Laurent // mSafeMediaVolumeIndex is the cached value of config_safe_media_volume_index property 4620d640bd325c3be9a350058c835b880a7e0b40dc60Eric Laurent private int mSafeMediaVolumeIndex; 4621c34dcc1e1ebf152bb400abbb8bc25f7dc0c3ba97Eric Laurent // mSafeMediaVolumeDevices lists the devices for which safe media volume is enforced, 4622c34dcc1e1ebf152bb400abbb8bc25f7dc0c3ba97Eric Laurent private final int mSafeMediaVolumeDevices = AudioSystem.DEVICE_OUT_WIRED_HEADSET | 4623c34dcc1e1ebf152bb400abbb8bc25f7dc0c3ba97Eric Laurent AudioSystem.DEVICE_OUT_WIRED_HEADPHONE; 4624c34dcc1e1ebf152bb400abbb8bc25f7dc0c3ba97Eric Laurent // mMusicActiveMs is the cumulative time of music activity since safe volume was disabled. 4625c34dcc1e1ebf152bb400abbb8bc25f7dc0c3ba97Eric Laurent // When this time reaches UNSAFE_VOLUME_MUSIC_ACTIVE_MS_MAX, the safe media volume is re-enabled 4626c34dcc1e1ebf152bb400abbb8bc25f7dc0c3ba97Eric Laurent // automatically. mMusicActiveMs is rounded to a multiple of MUSIC_ACTIVE_POLL_PERIOD_MS. 4627c34dcc1e1ebf152bb400abbb8bc25f7dc0c3ba97Eric Laurent private int mMusicActiveMs; 4628c34dcc1e1ebf152bb400abbb8bc25f7dc0c3ba97Eric Laurent private static final int UNSAFE_VOLUME_MUSIC_ACTIVE_MS_MAX = (20 * 3600 * 1000); // 20 hours 4629c34dcc1e1ebf152bb400abbb8bc25f7dc0c3ba97Eric Laurent private static final int MUSIC_ACTIVE_POLL_PERIOD_MS = 60000; // 1 minute polling interval 4630d640bd325c3be9a350058c835b880a7e0b40dc60Eric Laurent private static final int SAFE_VOLUME_CONFIGURE_TIMEOUT_MS = 30000; // 30s after boot completed 4631c34dcc1e1ebf152bb400abbb8bc25f7dc0c3ba97Eric Laurent 4632c34dcc1e1ebf152bb400abbb8bc25f7dc0c3ba97Eric Laurent private void setSafeMediaVolumeEnabled(boolean on) { 4633d640bd325c3be9a350058c835b880a7e0b40dc60Eric Laurent synchronized (mSafeMediaVolumeState) { 4634d640bd325c3be9a350058c835b880a7e0b40dc60Eric Laurent if ((mSafeMediaVolumeState != SAFE_MEDIA_VOLUME_NOT_CONFIGURED) && 4635d640bd325c3be9a350058c835b880a7e0b40dc60Eric Laurent (mSafeMediaVolumeState != SAFE_MEDIA_VOLUME_DISABLED)) { 4636d640bd325c3be9a350058c835b880a7e0b40dc60Eric Laurent if (on && (mSafeMediaVolumeState == SAFE_MEDIA_VOLUME_INACTIVE)) { 4637d640bd325c3be9a350058c835b880a7e0b40dc60Eric Laurent mSafeMediaVolumeState = SAFE_MEDIA_VOLUME_ACTIVE; 4638d640bd325c3be9a350058c835b880a7e0b40dc60Eric Laurent enforceSafeMediaVolume(); 4639d640bd325c3be9a350058c835b880a7e0b40dc60Eric Laurent } else if (!on && (mSafeMediaVolumeState == SAFE_MEDIA_VOLUME_ACTIVE)) { 4640d640bd325c3be9a350058c835b880a7e0b40dc60Eric Laurent mSafeMediaVolumeState = SAFE_MEDIA_VOLUME_INACTIVE; 4641d640bd325c3be9a350058c835b880a7e0b40dc60Eric Laurent mMusicActiveMs = 0; 4642d640bd325c3be9a350058c835b880a7e0b40dc60Eric Laurent sendMsg(mAudioHandler, 4643d640bd325c3be9a350058c835b880a7e0b40dc60Eric Laurent MSG_CHECK_MUSIC_ACTIVE, 4644d640bd325c3be9a350058c835b880a7e0b40dc60Eric Laurent SENDMSG_REPLACE, 4645d640bd325c3be9a350058c835b880a7e0b40dc60Eric Laurent 0, 4646d640bd325c3be9a350058c835b880a7e0b40dc60Eric Laurent 0, 4647d640bd325c3be9a350058c835b880a7e0b40dc60Eric Laurent null, 4648d640bd325c3be9a350058c835b880a7e0b40dc60Eric Laurent MUSIC_ACTIVE_POLL_PERIOD_MS); 4649d640bd325c3be9a350058c835b880a7e0b40dc60Eric Laurent } 4650c34dcc1e1ebf152bb400abbb8bc25f7dc0c3ba97Eric Laurent } 4651c34dcc1e1ebf152bb400abbb8bc25f7dc0c3ba97Eric Laurent } 4652c34dcc1e1ebf152bb400abbb8bc25f7dc0c3ba97Eric Laurent } 4653c34dcc1e1ebf152bb400abbb8bc25f7dc0c3ba97Eric Laurent 4654c34dcc1e1ebf152bb400abbb8bc25f7dc0c3ba97Eric Laurent private void enforceSafeMediaVolume() { 4655c34dcc1e1ebf152bb400abbb8bc25f7dc0c3ba97Eric Laurent VolumeStreamState streamState = mStreamStates[AudioSystem.STREAM_MUSIC]; 4656c34dcc1e1ebf152bb400abbb8bc25f7dc0c3ba97Eric Laurent int devices = mSafeMediaVolumeDevices; 4657c34dcc1e1ebf152bb400abbb8bc25f7dc0c3ba97Eric Laurent int i = 0; 4658c34dcc1e1ebf152bb400abbb8bc25f7dc0c3ba97Eric Laurent 4659c34dcc1e1ebf152bb400abbb8bc25f7dc0c3ba97Eric Laurent while (devices != 0) { 4660c34dcc1e1ebf152bb400abbb8bc25f7dc0c3ba97Eric Laurent int device = 1 << i++; 4661c34dcc1e1ebf152bb400abbb8bc25f7dc0c3ba97Eric Laurent if ((device & devices) == 0) { 4662c34dcc1e1ebf152bb400abbb8bc25f7dc0c3ba97Eric Laurent continue; 4663c34dcc1e1ebf152bb400abbb8bc25f7dc0c3ba97Eric Laurent } 466442b041ed4f184e3af7f788eb07307f556a2a6616Eric Laurent int index = streamState.getIndex(device); 4665c34dcc1e1ebf152bb400abbb8bc25f7dc0c3ba97Eric Laurent if (index > mSafeMediaVolumeIndex) { 466642b041ed4f184e3af7f788eb07307f556a2a6616Eric Laurent streamState.setIndex(mSafeMediaVolumeIndex, device); 466742b041ed4f184e3af7f788eb07307f556a2a6616Eric Laurent sendMsg(mAudioHandler, 466842b041ed4f184e3af7f788eb07307f556a2a6616Eric Laurent MSG_SET_DEVICE_VOLUME, 466942b041ed4f184e3af7f788eb07307f556a2a6616Eric Laurent SENDMSG_QUEUE, 467042b041ed4f184e3af7f788eb07307f556a2a6616Eric Laurent device, 467142b041ed4f184e3af7f788eb07307f556a2a6616Eric Laurent 0, 467242b041ed4f184e3af7f788eb07307f556a2a6616Eric Laurent streamState, 467342b041ed4f184e3af7f788eb07307f556a2a6616Eric Laurent 0); 4674c34dcc1e1ebf152bb400abbb8bc25f7dc0c3ba97Eric Laurent } 4675c34dcc1e1ebf152bb400abbb8bc25f7dc0c3ba97Eric Laurent devices &= ~device; 4676c34dcc1e1ebf152bb400abbb8bc25f7dc0c3ba97Eric Laurent } 4677c34dcc1e1ebf152bb400abbb8bc25f7dc0c3ba97Eric Laurent } 4678c34dcc1e1ebf152bb400abbb8bc25f7dc0c3ba97Eric Laurent 4679c34dcc1e1ebf152bb400abbb8bc25f7dc0c3ba97Eric Laurent private boolean checkSafeMediaVolume(int streamType, int index, int device) { 4680d640bd325c3be9a350058c835b880a7e0b40dc60Eric Laurent synchronized (mSafeMediaVolumeState) { 4681d640bd325c3be9a350058c835b880a7e0b40dc60Eric Laurent if ((mSafeMediaVolumeState == SAFE_MEDIA_VOLUME_ACTIVE) && 4682c34dcc1e1ebf152bb400abbb8bc25f7dc0c3ba97Eric Laurent (mStreamVolumeAlias[streamType] == AudioSystem.STREAM_MUSIC) && 4683c34dcc1e1ebf152bb400abbb8bc25f7dc0c3ba97Eric Laurent ((device & mSafeMediaVolumeDevices) != 0) && 4684c34dcc1e1ebf152bb400abbb8bc25f7dc0c3ba97Eric Laurent (index > mSafeMediaVolumeIndex)) { 4685c34dcc1e1ebf152bb400abbb8bc25f7dc0c3ba97Eric Laurent return false; 4686c34dcc1e1ebf152bb400abbb8bc25f7dc0c3ba97Eric Laurent } 4687c34dcc1e1ebf152bb400abbb8bc25f7dc0c3ba97Eric Laurent return true; 4688c34dcc1e1ebf152bb400abbb8bc25f7dc0c3ba97Eric Laurent } 4689c34dcc1e1ebf152bb400abbb8bc25f7dc0c3ba97Eric Laurent } 4690c34dcc1e1ebf152bb400abbb8bc25f7dc0c3ba97Eric Laurent 46913346a802087f621c6441bc512dfcc17b07143fc6John Spurlock @Override 4692c34dcc1e1ebf152bb400abbb8bc25f7dc0c3ba97Eric Laurent public void disableSafeMediaVolume() { 46933346a802087f621c6441bc512dfcc17b07143fc6John Spurlock enforceSelfOrSystemUI("disable the safe media volume"); 4694d640bd325c3be9a350058c835b880a7e0b40dc60Eric Laurent synchronized (mSafeMediaVolumeState) { 4695c34dcc1e1ebf152bb400abbb8bc25f7dc0c3ba97Eric Laurent setSafeMediaVolumeEnabled(false); 4696fde16d5879ea88a971004c984093409468b6139cEric Laurent if (mPendingVolumeCommand != null) { 4697fde16d5879ea88a971004c984093409468b6139cEric Laurent onSetStreamVolume(mPendingVolumeCommand.mStreamType, 4698fde16d5879ea88a971004c984093409468b6139cEric Laurent mPendingVolumeCommand.mIndex, 4699fde16d5879ea88a971004c984093409468b6139cEric Laurent mPendingVolumeCommand.mFlags, 4700fde16d5879ea88a971004c984093409468b6139cEric Laurent mPendingVolumeCommand.mDevice); 4701fde16d5879ea88a971004c984093409468b6139cEric Laurent mPendingVolumeCommand = null; 4702fde16d5879ea88a971004c984093409468b6139cEric Laurent } 4703c34dcc1e1ebf152bb400abbb8bc25f7dc0c3ba97Eric Laurent } 4704c34dcc1e1ebf152bb400abbb8bc25f7dc0c3ba97Eric Laurent } 4705c34dcc1e1ebf152bb400abbb8bc25f7dc0c3ba97Eric Laurent 4706c34dcc1e1ebf152bb400abbb8bc25f7dc0c3ba97Eric Laurent 4707dd45d01128423a82652a3c9d77fa393631d95229Eric Laurent //========================================================================================== 4708dd45d01128423a82652a3c9d77fa393631d95229Eric Laurent // Camera shutter sound policy. 4709dd45d01128423a82652a3c9d77fa393631d95229Eric Laurent // config_camera_sound_forced configuration option in config.xml defines if the camera shutter 4710dd45d01128423a82652a3c9d77fa393631d95229Eric Laurent // sound is forced (sound even if the device is in silent mode) or not. This option is false by 4711dd45d01128423a82652a3c9d77fa393631d95229Eric Laurent // default and can be overridden by country specific overlay in values-mccXXX/config.xml. 4712dd45d01128423a82652a3c9d77fa393631d95229Eric Laurent //========================================================================================== 4713dd45d01128423a82652a3c9d77fa393631d95229Eric Laurent 4714dd45d01128423a82652a3c9d77fa393631d95229Eric Laurent // cached value of com.android.internal.R.bool.config_camera_sound_forced 4715dd45d01128423a82652a3c9d77fa393631d95229Eric Laurent private Boolean mCameraSoundForced; 4716dd45d01128423a82652a3c9d77fa393631d95229Eric Laurent 4717dd45d01128423a82652a3c9d77fa393631d95229Eric Laurent // called by android.hardware.Camera to populate CameraInfo.canDisableShutterSound 4718dd45d01128423a82652a3c9d77fa393631d95229Eric Laurent public boolean isCameraSoundForced() { 4719dd45d01128423a82652a3c9d77fa393631d95229Eric Laurent synchronized (mCameraSoundForced) { 4720dd45d01128423a82652a3c9d77fa393631d95229Eric Laurent return mCameraSoundForced; 4721dd45d01128423a82652a3c9d77fa393631d95229Eric Laurent } 4722dd45d01128423a82652a3c9d77fa393631d95229Eric Laurent } 4723dd45d01128423a82652a3c9d77fa393631d95229Eric Laurent 4724dd45d01128423a82652a3c9d77fa393631d95229Eric Laurent private static final String[] RINGER_MODE_NAMES = new String[] { 4725dd45d01128423a82652a3c9d77fa393631d95229Eric Laurent "SILENT", 4726dd45d01128423a82652a3c9d77fa393631d95229Eric Laurent "VIBRATE", 4727dd45d01128423a82652a3c9d77fa393631d95229Eric Laurent "NORMAL" 4728dd45d01128423a82652a3c9d77fa393631d95229Eric Laurent }; 4729dd45d01128423a82652a3c9d77fa393631d95229Eric Laurent 4730dd45d01128423a82652a3c9d77fa393631d95229Eric Laurent private void dumpRingerMode(PrintWriter pw) { 4731dd45d01128423a82652a3c9d77fa393631d95229Eric Laurent pw.println("\nRinger mode: "); 4732dd45d01128423a82652a3c9d77fa393631d95229Eric Laurent pw.println("- mode: "+RINGER_MODE_NAMES[mRingerMode]); 4733dd45d01128423a82652a3c9d77fa393631d95229Eric Laurent pw.print("- ringer mode affected streams = 0x"); 4734dd45d01128423a82652a3c9d77fa393631d95229Eric Laurent pw.println(Integer.toHexString(mRingerModeAffectedStreams)); 4735dd45d01128423a82652a3c9d77fa393631d95229Eric Laurent pw.print("- ringer mode muted streams = 0x"); 4736dd45d01128423a82652a3c9d77fa393631d95229Eric Laurent pw.println(Integer.toHexString(mRingerModeMutedStreams)); 4737dd45d01128423a82652a3c9d77fa393631d95229Eric Laurent } 4738dd45d01128423a82652a3c9d77fa393631d95229Eric Laurent 4739632ca417f0a33e3fa9ccece531afa2db3f0d4a30Dianne Hackborn @Override 4740d5176cfe6eae954e9cef1e2ec17859a5089e1330Jean-Michel Trivi protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) { 4741eb4cc492c93ab9635dde78b958a834120412e72aJeff Sharkey mContext.enforceCallingOrSelfPermission(android.Manifest.permission.DUMP, TAG); 4742eb4cc492c93ab9635dde78b958a834120412e72aJeff Sharkey 4743fa9a69805b001034aa04c3b33989a7ac21522371Jean-Michel Trivi mMediaFocusControl.dump(pw); 4744bffc3d1bd33eb2d8e00a9f8b6261d815db503311Eric Laurent dumpStreamStates(pw); 4745dd45d01128423a82652a3c9d77fa393631d95229Eric Laurent dumpRingerMode(pw); 4746632ca417f0a33e3fa9ccece531afa2db3f0d4a30Dianne Hackborn pw.println("\nAudio routes:"); 4747632ca417f0a33e3fa9ccece531afa2db3f0d4a30Dianne Hackborn pw.print(" mMainType=0x"); pw.println(Integer.toHexString(mCurAudioRoutes.mMainType)); 4748632ca417f0a33e3fa9ccece531afa2db3f0d4a30Dianne Hackborn pw.print(" mBluetoothName="); pw.println(mCurAudioRoutes.mBluetoothName); 47493346a802087f621c6441bc512dfcc17b07143fc6John Spurlock pw.print(" mVolumeController="); pw.println(mVolumeController); 4750d5176cfe6eae954e9cef1e2ec17859a5089e1330Jean-Michel Trivi } 4751fd116ad1ab02f6060a0b2201f018317fa32e28b4Glenn Kasten 4752fd116ad1ab02f6060a0b2201f018317fa32e28b4Glenn Kasten // Inform AudioFlinger of our device's low RAM attribute 4753fd116ad1ab02f6060a0b2201f018317fa32e28b4Glenn Kasten private static void readAndSetLowRamDevice() 4754fd116ad1ab02f6060a0b2201f018317fa32e28b4Glenn Kasten { 4755fd116ad1ab02f6060a0b2201f018317fa32e28b4Glenn Kasten int status = AudioSystem.setLowRamDevice(ActivityManager.isLowRamDeviceStatic()); 4756fd116ad1ab02f6060a0b2201f018317fa32e28b4Glenn Kasten if (status != 0) { 4757fd116ad1ab02f6060a0b2201f018317fa32e28b4Glenn Kasten Log.w(TAG, "AudioFlinger informed of device's low RAM attribute; status " + status); 4758fd116ad1ab02f6060a0b2201f018317fa32e28b4Glenn Kasten } 4759fd116ad1ab02f6060a0b2201f018317fa32e28b4Glenn Kasten } 47603346a802087f621c6441bc512dfcc17b07143fc6John Spurlock 47613346a802087f621c6441bc512dfcc17b07143fc6John Spurlock private void enforceSelfOrSystemUI(String action) { 47623346a802087f621c6441bc512dfcc17b07143fc6John Spurlock mContext.enforceCallingOrSelfPermission(android.Manifest.permission.STATUS_BAR_SERVICE, 47633346a802087f621c6441bc512dfcc17b07143fc6John Spurlock "Only SystemUI can " + action); 47643346a802087f621c6441bc512dfcc17b07143fc6John Spurlock } 47653346a802087f621c6441bc512dfcc17b07143fc6John Spurlock 47663346a802087f621c6441bc512dfcc17b07143fc6John Spurlock @Override 47673346a802087f621c6441bc512dfcc17b07143fc6John Spurlock public void setVolumeController(final IVolumeController controller) { 47683346a802087f621c6441bc512dfcc17b07143fc6John Spurlock enforceSelfOrSystemUI("set the volume controller"); 47693346a802087f621c6441bc512dfcc17b07143fc6John Spurlock 47703346a802087f621c6441bc512dfcc17b07143fc6John Spurlock // return early if things are not actually changing 47713346a802087f621c6441bc512dfcc17b07143fc6John Spurlock if (mVolumeController.isSameBinder(controller)) { 47723346a802087f621c6441bc512dfcc17b07143fc6John Spurlock return; 47733346a802087f621c6441bc512dfcc17b07143fc6John Spurlock } 47743346a802087f621c6441bc512dfcc17b07143fc6John Spurlock 47753346a802087f621c6441bc512dfcc17b07143fc6John Spurlock // dismiss the old volume controller 47763346a802087f621c6441bc512dfcc17b07143fc6John Spurlock mVolumeController.postDismiss(); 47773346a802087f621c6441bc512dfcc17b07143fc6John Spurlock if (controller != null) { 47783346a802087f621c6441bc512dfcc17b07143fc6John Spurlock // we are about to register a new controller, listen for its death 47793346a802087f621c6441bc512dfcc17b07143fc6John Spurlock try { 47803346a802087f621c6441bc512dfcc17b07143fc6John Spurlock controller.asBinder().linkToDeath(new DeathRecipient() { 47813346a802087f621c6441bc512dfcc17b07143fc6John Spurlock @Override 47823346a802087f621c6441bc512dfcc17b07143fc6John Spurlock public void binderDied() { 47833346a802087f621c6441bc512dfcc17b07143fc6John Spurlock if (mVolumeController.isSameBinder(controller)) { 47843346a802087f621c6441bc512dfcc17b07143fc6John Spurlock Log.w(TAG, "Current remote volume controller died, unregistering"); 47853346a802087f621c6441bc512dfcc17b07143fc6John Spurlock setVolumeController(null); 47863346a802087f621c6441bc512dfcc17b07143fc6John Spurlock } 47873346a802087f621c6441bc512dfcc17b07143fc6John Spurlock } 47883346a802087f621c6441bc512dfcc17b07143fc6John Spurlock }, 0); 47893346a802087f621c6441bc512dfcc17b07143fc6John Spurlock } catch (RemoteException e) { 47903346a802087f621c6441bc512dfcc17b07143fc6John Spurlock // noop 47913346a802087f621c6441bc512dfcc17b07143fc6John Spurlock } 47923346a802087f621c6441bc512dfcc17b07143fc6John Spurlock } 47933346a802087f621c6441bc512dfcc17b07143fc6John Spurlock mVolumeController.setController(controller); 47943346a802087f621c6441bc512dfcc17b07143fc6John Spurlock } 4795d09bd0c6eb8318e0122b14d7eb5324e481706e41RoboErik 4796d09bd0c6eb8318e0122b14d7eb5324e481706e41RoboErik public static class VolumeController { 4797d09bd0c6eb8318e0122b14d7eb5324e481706e41RoboErik private static final String TAG = "VolumeController"; 4798d09bd0c6eb8318e0122b14d7eb5324e481706e41RoboErik 4799d09bd0c6eb8318e0122b14d7eb5324e481706e41RoboErik private IVolumeController mController; 4800d09bd0c6eb8318e0122b14d7eb5324e481706e41RoboErik 4801d09bd0c6eb8318e0122b14d7eb5324e481706e41RoboErik public void setController(IVolumeController controller) { 4802d09bd0c6eb8318e0122b14d7eb5324e481706e41RoboErik mController = controller; 4803d09bd0c6eb8318e0122b14d7eb5324e481706e41RoboErik } 4804d09bd0c6eb8318e0122b14d7eb5324e481706e41RoboErik 4805d09bd0c6eb8318e0122b14d7eb5324e481706e41RoboErik public boolean isSameBinder(IVolumeController controller) { 4806d09bd0c6eb8318e0122b14d7eb5324e481706e41RoboErik return Objects.equals(asBinder(), binder(controller)); 4807d09bd0c6eb8318e0122b14d7eb5324e481706e41RoboErik } 4808d09bd0c6eb8318e0122b14d7eb5324e481706e41RoboErik 4809d09bd0c6eb8318e0122b14d7eb5324e481706e41RoboErik public IBinder asBinder() { 4810d09bd0c6eb8318e0122b14d7eb5324e481706e41RoboErik return binder(mController); 4811d09bd0c6eb8318e0122b14d7eb5324e481706e41RoboErik } 4812d09bd0c6eb8318e0122b14d7eb5324e481706e41RoboErik 4813d09bd0c6eb8318e0122b14d7eb5324e481706e41RoboErik private static IBinder binder(IVolumeController controller) { 4814d09bd0c6eb8318e0122b14d7eb5324e481706e41RoboErik return controller == null ? null : controller.asBinder(); 4815d09bd0c6eb8318e0122b14d7eb5324e481706e41RoboErik } 4816d09bd0c6eb8318e0122b14d7eb5324e481706e41RoboErik 4817d09bd0c6eb8318e0122b14d7eb5324e481706e41RoboErik @Override 4818d09bd0c6eb8318e0122b14d7eb5324e481706e41RoboErik public String toString() { 4819d09bd0c6eb8318e0122b14d7eb5324e481706e41RoboErik return "VolumeController(" + asBinder() + ")"; 4820d09bd0c6eb8318e0122b14d7eb5324e481706e41RoboErik } 4821d09bd0c6eb8318e0122b14d7eb5324e481706e41RoboErik 4822d09bd0c6eb8318e0122b14d7eb5324e481706e41RoboErik public void postDisplaySafeVolumeWarning(int flags) { 4823d09bd0c6eb8318e0122b14d7eb5324e481706e41RoboErik if (mController == null) 4824d09bd0c6eb8318e0122b14d7eb5324e481706e41RoboErik return; 4825d09bd0c6eb8318e0122b14d7eb5324e481706e41RoboErik try { 4826d09bd0c6eb8318e0122b14d7eb5324e481706e41RoboErik mController.displaySafeVolumeWarning(flags); 4827d09bd0c6eb8318e0122b14d7eb5324e481706e41RoboErik } catch (RemoteException e) { 4828d09bd0c6eb8318e0122b14d7eb5324e481706e41RoboErik Log.w(TAG, "Error calling displaySafeVolumeWarning", e); 4829d09bd0c6eb8318e0122b14d7eb5324e481706e41RoboErik } 4830d09bd0c6eb8318e0122b14d7eb5324e481706e41RoboErik } 4831d09bd0c6eb8318e0122b14d7eb5324e481706e41RoboErik 4832d09bd0c6eb8318e0122b14d7eb5324e481706e41RoboErik public void postVolumeChanged(int streamType, int flags) { 4833d09bd0c6eb8318e0122b14d7eb5324e481706e41RoboErik if (mController == null) 4834d09bd0c6eb8318e0122b14d7eb5324e481706e41RoboErik return; 4835d09bd0c6eb8318e0122b14d7eb5324e481706e41RoboErik try { 4836d09bd0c6eb8318e0122b14d7eb5324e481706e41RoboErik mController.volumeChanged(streamType, flags); 4837d09bd0c6eb8318e0122b14d7eb5324e481706e41RoboErik } catch (RemoteException e) { 4838d09bd0c6eb8318e0122b14d7eb5324e481706e41RoboErik Log.w(TAG, "Error calling volumeChanged", e); 4839d09bd0c6eb8318e0122b14d7eb5324e481706e41RoboErik } 4840d09bd0c6eb8318e0122b14d7eb5324e481706e41RoboErik } 4841d09bd0c6eb8318e0122b14d7eb5324e481706e41RoboErik 4842d09bd0c6eb8318e0122b14d7eb5324e481706e41RoboErik public void postMasterVolumeChanged(int flags) { 4843d09bd0c6eb8318e0122b14d7eb5324e481706e41RoboErik if (mController == null) 4844d09bd0c6eb8318e0122b14d7eb5324e481706e41RoboErik return; 4845d09bd0c6eb8318e0122b14d7eb5324e481706e41RoboErik try { 4846d09bd0c6eb8318e0122b14d7eb5324e481706e41RoboErik mController.masterVolumeChanged(flags); 4847d09bd0c6eb8318e0122b14d7eb5324e481706e41RoboErik } catch (RemoteException e) { 4848d09bd0c6eb8318e0122b14d7eb5324e481706e41RoboErik Log.w(TAG, "Error calling masterVolumeChanged", e); 4849d09bd0c6eb8318e0122b14d7eb5324e481706e41RoboErik } 4850d09bd0c6eb8318e0122b14d7eb5324e481706e41RoboErik } 4851d09bd0c6eb8318e0122b14d7eb5324e481706e41RoboErik 4852d09bd0c6eb8318e0122b14d7eb5324e481706e41RoboErik public void postMasterMuteChanged(int flags) { 4853d09bd0c6eb8318e0122b14d7eb5324e481706e41RoboErik if (mController == null) 4854d09bd0c6eb8318e0122b14d7eb5324e481706e41RoboErik return; 4855d09bd0c6eb8318e0122b14d7eb5324e481706e41RoboErik try { 4856d09bd0c6eb8318e0122b14d7eb5324e481706e41RoboErik mController.masterMuteChanged(flags); 4857d09bd0c6eb8318e0122b14d7eb5324e481706e41RoboErik } catch (RemoteException e) { 4858d09bd0c6eb8318e0122b14d7eb5324e481706e41RoboErik Log.w(TAG, "Error calling masterMuteChanged", e); 4859d09bd0c6eb8318e0122b14d7eb5324e481706e41RoboErik } 4860d09bd0c6eb8318e0122b14d7eb5324e481706e41RoboErik } 4861d09bd0c6eb8318e0122b14d7eb5324e481706e41RoboErik 4862d09bd0c6eb8318e0122b14d7eb5324e481706e41RoboErik public void setLayoutDirection(int layoutDirection) { 4863d09bd0c6eb8318e0122b14d7eb5324e481706e41RoboErik if (mController == null) 4864d09bd0c6eb8318e0122b14d7eb5324e481706e41RoboErik return; 4865d09bd0c6eb8318e0122b14d7eb5324e481706e41RoboErik try { 4866d09bd0c6eb8318e0122b14d7eb5324e481706e41RoboErik mController.setLayoutDirection(layoutDirection); 4867d09bd0c6eb8318e0122b14d7eb5324e481706e41RoboErik } catch (RemoteException e) { 4868d09bd0c6eb8318e0122b14d7eb5324e481706e41RoboErik Log.w(TAG, "Error calling setLayoutDirection", e); 4869d09bd0c6eb8318e0122b14d7eb5324e481706e41RoboErik } 4870d09bd0c6eb8318e0122b14d7eb5324e481706e41RoboErik } 4871d09bd0c6eb8318e0122b14d7eb5324e481706e41RoboErik 4872d09bd0c6eb8318e0122b14d7eb5324e481706e41RoboErik public void postDismiss() { 4873d09bd0c6eb8318e0122b14d7eb5324e481706e41RoboErik if (mController == null) 4874d09bd0c6eb8318e0122b14d7eb5324e481706e41RoboErik return; 4875d09bd0c6eb8318e0122b14d7eb5324e481706e41RoboErik try { 4876d09bd0c6eb8318e0122b14d7eb5324e481706e41RoboErik mController.dismiss(); 4877d09bd0c6eb8318e0122b14d7eb5324e481706e41RoboErik } catch (RemoteException e) { 4878d09bd0c6eb8318e0122b14d7eb5324e481706e41RoboErik Log.w(TAG, "Error calling dismiss", e); 4879d09bd0c6eb8318e0122b14d7eb5324e481706e41RoboErik } 4880d09bd0c6eb8318e0122b14d7eb5324e481706e41RoboErik } 4881d09bd0c6eb8318e0122b14d7eb5324e481706e41RoboErik } 48829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} 4883