blob: cc3a489c7016c53ee938bf3569854f121b205fca [file] [log] [blame]
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001/*
2 * Copyright (C) 2006 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
John Spurlock61560172015-02-06 19:46:04 -050017package com.android.server.audio;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080018
Jeff Sharkey098d5802012-04-26 17:30:34 -070019import static android.Manifest.permission.REMOTE_AUDIO_PLAYBACK;
Amith Yamasanic696a532011-10-28 17:02:37 -070020import static android.media.AudioManager.RINGER_MODE_NORMAL;
21import static android.media.AudioManager.RINGER_MODE_SILENT;
22import static android.media.AudioManager.RINGER_MODE_VIBRATE;
Beverlyd6964762018-02-16 14:07:03 -050023import static android.media.AudioManager.STREAM_ALARM;
24import static android.media.AudioManager.STREAM_MUSIC;
25import static android.media.AudioManager.STREAM_SYSTEM;
Fyodor Kupolovbcb6c1e2015-05-11 12:05:15 -070026import static android.os.Process.FIRST_APPLICATION_UID;
Mike Digman55272862018-02-20 14:35:17 -080027import static android.provider.Settings.Secure.VOLUME_HUSH_MUTE;
28import static android.provider.Settings.Secure.VOLUME_HUSH_OFF;
29import static android.provider.Settings.Secure.VOLUME_HUSH_VIBRATE;
Amith Yamasanic696a532011-10-28 17:02:37 -070030
Fyodor Kupolovb5013302015-04-17 17:59:14 -070031import android.Manifest;
Jean-Michel Trivi7ed71472018-02-02 16:52:09 -080032import android.annotation.NonNull;
Jean-Michel Trivia53b7052017-04-12 18:27:01 -070033import android.annotation.Nullable;
Glenn Kastenfd116ad2013-07-12 17:10:39 -070034import android.app.ActivityManager;
Fyodor Kupolovb5013302015-04-17 17:59:14 -070035import android.app.ActivityManagerInternal;
Fyodor Kupolovb5013302015-04-17 17:59:14 -070036import android.app.AppGlobals;
Dianne Hackbornba50b97c2013-04-30 15:04:46 -070037import android.app.AppOpsManager;
Dianne Hackborn3e99f652017-07-05 16:33:56 -070038import android.app.IUidObserver;
Julia Reynolds48034f82016-03-09 10:15:16 -050039import android.app.NotificationManager;
Jaikumar Ganesh82aa7f02010-09-27 17:05:10 -070040import android.bluetooth.BluetoothA2dp;
41import android.bluetooth.BluetoothAdapter;
42import android.bluetooth.BluetoothClass;
43import android.bluetooth.BluetoothDevice;
44import android.bluetooth.BluetoothHeadset;
Jakub Pawlowskif9570f32018-02-21 17:15:12 -080045import android.bluetooth.BluetoothHearingAid;
Jaikumar Ganesh82aa7f02010-09-27 17:05:10 -070046import android.bluetooth.BluetoothProfile;
Nick Pellybd022f42009-08-14 18:33:38 -070047import android.content.BroadcastReceiver;
Jean-Michel Trivid327f212010-03-16 21:44:33 -070048import android.content.ComponentName;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080049import android.content.ContentResolver;
50import android.content.Context;
51import android.content.Intent;
Eric Laurenta553c252009-07-17 12:17:14 -070052import android.content.IntentFilter;
Julia Reynolds48034f82016-03-09 10:15:16 -050053import android.content.pm.ApplicationInfo;
Fyodor Kupolovb5013302015-04-17 17:59:14 -070054import android.content.pm.PackageInfo;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080055import android.content.pm.PackageManager;
Marco Nelissenfb6df0b2017-02-15 15:25:24 -080056import android.content.pm.ResolveInfo;
Fyodor Kupolovb5013302015-04-17 17:59:14 -070057import android.content.pm.UserInfo;
Jean-Michel Trivif26f0172012-04-25 16:23:20 -070058import android.content.res.Configuration;
Eric Laurente78fced2013-03-15 16:03:47 -070059import android.content.res.Resources;
60import android.content.res.XmlResourceParser;
Jason Parekhb1096152009-03-24 17:48:25 -070061import android.database.ContentObserver;
Jungshik Jang41d97462014-06-30 22:26:29 +090062import android.hardware.hdmi.HdmiControlManager;
Eric Laurent212532b2014-07-21 15:43:18 -070063import android.hardware.hdmi.HdmiPlaybackClient;
Jungshik Jang41d97462014-06-30 22:26:29 +090064import android.hardware.hdmi.HdmiTvClient;
Paul McLeanc837a452014-04-09 09:04:43 -070065import android.hardware.usb.UsbManager;
John Spurlock61560172015-02-06 19:46:04 -050066import android.media.AudioAttributes;
67import android.media.AudioDevicePort;
Jean-Michel Trivi126cf032017-04-02 23:19:02 -070068import android.media.AudioFocusInfo;
Jean-Michel Trivi9228af62018-01-05 17:06:17 -080069import android.media.AudioFocusRequest;
John Spurlock61560172015-02-06 19:46:04 -050070import android.media.AudioFormat;
71import android.media.AudioManager;
72import android.media.AudioManagerInternal;
Jean-Michel Trivi292a6a42016-12-01 08:32:15 -080073import android.media.AudioPlaybackConfiguration;
Beverly925cde82018-01-23 09:31:23 -050074import android.media.AudioPort;
Jean-Michel Trivi598c0c92016-03-07 14:13:03 -080075import android.media.AudioRecordingConfiguration;
John Spurlock61560172015-02-06 19:46:04 -050076import android.media.AudioRoutesInfo;
Beverly925cde82018-01-23 09:31:23 -050077import android.media.AudioSystem;
John Spurlock61560172015-02-06 19:46:04 -050078import android.media.IAudioFocusDispatcher;
79import android.media.IAudioRoutesObserver;
Eric Laurent1d3cdce2018-01-20 10:31:21 -080080import android.media.IAudioServerStateDispatcher;
John Spurlock61560172015-02-06 19:46:04 -050081import android.media.IAudioService;
Jean-Michel Trivi292a6a42016-12-01 08:32:15 -080082import android.media.IPlaybackConfigDispatcher;
Jean-Michel Trivid3c71f02015-12-07 11:59:31 -080083import android.media.IRecordingConfigDispatcher;
John Spurlock61560172015-02-06 19:46:04 -050084import android.media.IRingtonePlayer;
85import android.media.IVolumeController;
86import android.media.MediaPlayer;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080087import android.media.MediaPlayer.OnCompletionListener;
88import android.media.MediaPlayer.OnErrorListener;
Jean-Michel Trivi292a6a42016-12-01 08:32:15 -080089import android.media.PlayerBase;
Beverly925cde82018-01-23 09:31:23 -050090import android.media.SoundPool;
91import android.media.VolumePolicy;
92import android.media.audiofx.AudioEffect;
Jean-Michel Trivi5a561092015-04-23 18:48:08 -070093import android.media.audiopolicy.AudioMix;
Jean-Michel Trivi958876f2014-11-16 15:40:22 -080094import android.media.audiopolicy.AudioPolicy;
Jean-Michel Trivia8b6bd82014-07-01 09:48:46 -070095import android.media.audiopolicy.AudioPolicyConfig;
Jean-Michel Trivi0212be52014-11-24 14:43:10 -080096import android.media.audiopolicy.IAudioPolicyCallback;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080097import android.os.Binder;
Eric Laurentc18c9132013-04-12 17:24:56 -070098import android.os.Build;
Makoto Onukid45a4a22015-11-02 17:17:38 -080099import android.os.Bundle;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800100import android.os.Environment;
101import android.os.Handler;
102import android.os.IBinder;
103import android.os.Looper;
104import android.os.Message;
Jean-Michel Trivic6802222012-04-30 11:15:03 -0700105import android.os.PowerManager;
Dianne Hackborn632ca412012-06-14 19:34:10 -0700106import android.os.RemoteCallbackList;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800107import android.os.RemoteException;
John Spurlock33f4e042014-07-11 13:10:58 -0400108import android.os.SystemClock;
Jaikumar Ganesh82aa7f02010-09-27 17:05:10 -0700109import android.os.SystemProperties;
Dianne Hackborn5ac72a22012-08-29 18:32:08 -0700110import android.os.UserHandle;
Fyodor Kupolovb5013302015-04-17 17:59:14 -0700111import android.os.UserManager;
Makoto Onukid45a4a22015-11-02 17:17:38 -0800112import android.os.UserManagerInternal;
113import android.os.UserManagerInternal.UserRestrictionsListener;
Mike Digman55272862018-02-20 14:35:17 -0800114import android.os.VibrationEffect;
Eric Laurentbffc3d12012-05-07 17:43:49 -0700115import android.os.Vibrator;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800116import android.provider.Settings;
117import android.provider.Settings.System;
Beverly925cde82018-01-23 09:31:23 -0500118import android.service.notification.ZenModeConfig;
Tyler Gunnef9f6f92014-09-12 22:16:17 -0700119import android.telecom.TelecomManager;
Dianne Hackborn632ca412012-06-14 19:34:10 -0700120import android.text.TextUtils;
Fyodor Kupolovb5013302015-04-17 17:59:14 -0700121import android.util.AndroidRuntimeException;
John Spurlock8c3dc852015-04-23 21:32:37 -0400122import android.util.ArrayMap;
123import android.util.ArraySet;
Phil Weaverf1a9aff2017-03-23 17:21:29 -0700124import android.util.IntArray;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800125import android.util.Log;
John Spurlockaa5ee4d2014-07-25 13:05:12 -0400126import android.util.MathUtils;
Jean-Michel Trivia8b6bd82014-07-01 09:48:46 -0700127import android.util.Slog;
John Spurlock2bb02ec2015-03-02 13:13:06 -0500128import android.util.SparseIntArray;
Jean-Michel Trivid327f212010-03-16 21:44:33 -0700129import android.view.KeyEvent;
Jean-Michel Trivi873cc452014-09-11 17:25:09 -0700130import android.view.accessibility.AccessibilityManager;
Mike Digman55272862018-02-20 14:35:17 -0800131import android.widget.Toast;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800132
Jean-Michel Trivi8719a1d2017-11-06 11:52:51 -0800133import com.android.internal.annotations.GuardedBy;
Jeff Sharkeyfe9a53b2017-03-31 14:08:23 -0600134import com.android.internal.util.DumpUtils;
Eric Laurente78fced2013-03-15 16:03:47 -0700135import com.android.internal.util.XmlUtils;
John Spurlock90874332015-03-10 16:00:54 -0400136import com.android.server.EventLogTags;
RoboErik0dac35a2014-08-12 15:48:49 -0700137import com.android.server.LocalServices;
Makoto Onukie1aef852015-10-15 17:28:35 -0700138import com.android.server.SystemService;
Beverly925cde82018-01-23 09:31:23 -0500139import com.android.server.audio.AudioServiceEvents.ForceUseEvent;
140import com.android.server.audio.AudioServiceEvents.PhoneStateEvent;
141import com.android.server.audio.AudioServiceEvents.VolumeEvent;
142import com.android.server.audio.AudioServiceEvents.WiredDevConnectEvent;
Fyodor Kupolovb5013302015-04-17 17:59:14 -0700143import com.android.server.pm.UserManagerService;
Eric Laurente78fced2013-03-15 16:03:47 -0700144
145import org.xmlpull.v1.XmlPullParserException;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800146
Jaekyun Seokc31033f2018-01-15 14:53:17 +0900147import java.io.File;
Jean-Michel Trivid5176cf2010-01-28 11:56:42 -0800148import java.io.FileDescriptor;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800149import java.io.IOException;
Jean-Michel Trivid5176cf2010-01-28 11:56:42 -0800150import java.io.PrintWriter;
Eric Laurente78fced2013-03-15 16:03:47 -0700151import java.lang.reflect.Field;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800152import java.util.ArrayList;
Jean-Michel Trivi7db2d8f2018-03-06 10:30:59 -0800153import java.util.Collection;
Eric Laurentc42ac9d2009-07-29 08:53:03 -0700154import java.util.HashMap;
155import java.util.Iterator;
Jaikumar Ganesh5a1e4cf2010-10-18 17:05:09 -0700156import java.util.List;
Jaikumar Ganesh82aa7f02010-09-27 17:05:10 -0700157import java.util.NoSuchElementException;
RoboErikd09bd0c2014-06-24 17:45:19 -0700158import java.util.Objects;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800159
160/**
161 * The implementation of the volume manager service.
162 * <p>
163 * This implementation focuses on delivering a responsive UI. Most methods are
164 * asynchronous to external calls. For example, the task of setting a volume
165 * will update our internal state, but in a separate thread will set the system
166 * volume and later persist to the database. Similarly, setting the ringer mode
167 * will update the state and broadcast a change and in a separate thread later
168 * persist the ringer mode.
169 *
170 * @hide
171 */
Jean-Michel Triviac487672016-11-11 10:05:18 -0800172public class AudioService extends IAudioService.Stub
173 implements AccessibilityManager.TouchExplorationStateChangeListener,
Jean-Michel Trivicfa55532017-01-18 11:17:51 -0800174 AccessibilityManager.AccessibilityServicesStateChangeListener {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800175
176 private static final String TAG = "AudioService";
177
Jean-Michel Trivi339567d2014-07-29 09:53:34 -0700178 /** Debug audio mode */
179 protected static final boolean DEBUG_MODE = Log.isLoggable(TAG + ".MOD", Log.DEBUG);
Jean-Michel Trivi8fdb0d42014-07-16 19:08:37 -0700180
181 /** Debug audio policy feature */
182 protected static final boolean DEBUG_AP = Log.isLoggable(TAG + ".AP", Log.DEBUG);
183
Jean-Michel Trivi3114ce32012-06-11 15:03:52 -0700184 /** Debug volumes */
John Spurlockae641c92014-06-30 18:11:40 -0400185 protected static final boolean DEBUG_VOL = Log.isLoggable(TAG + ".VOL", Log.DEBUG);
Jean-Michel Trivi18e7bce2011-08-26 12:11:36 -0700186
Paul McLean394a8e12015-03-03 10:29:19 -0700187 /** debug calls to devices APIs */
188 protected static final boolean DEBUG_DEVICES = Log.isLoggable(TAG + ".DEVICES", Log.DEBUG);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800189 /** How long to delay before persisting a change in volume/ringer mode. */
RoboErik45edba12012-03-27 17:54:36 -0700190 private static final int PERSIST_DELAY = 500;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800191
RoboErik5452e252015-02-06 15:33:53 -0800192 /** How long to delay after a volume down event before unmuting a stream */
193 private static final int UNMUTE_STREAM_DELAY = 350;
194
John Spurlock3346a802014-05-20 16:25:37 -0400195 /**
John Spurlocka11b4af2014-06-01 11:52:23 -0400196 * Only used in the result from {@link #checkForRingerModeChange(int, int, int)}
197 */
198 private static final int FLAG_ADJUST_VOLUME = 1;
199
Dianne Hackbornba50b97c2013-04-30 15:04:46 -0700200 private final Context mContext;
201 private final ContentResolver mContentResolver;
202 private final AppOpsManager mAppOps;
Eric Laurent212532b2014-07-21 15:43:18 -0700203
Eric Laurent212532b2014-07-21 15:43:18 -0700204 // the platform type affects volume and silent mode behavior
205 private final int mPlatformType;
206
Muyuan Li1ed6df62016-06-18 11:16:52 -0700207 // indicates whether the system maps all streams to a single stream.
208 private final boolean mIsSingleVolume;
209
Eric Laurent212532b2014-07-21 15:43:18 -0700210 private boolean isPlatformVoice() {
John Spurlock61560172015-02-06 19:46:04 -0500211 return mPlatformType == AudioSystem.PLATFORM_VOICE;
Eric Laurent212532b2014-07-21 15:43:18 -0700212 }
213
214 private boolean isPlatformTelevision() {
John Spurlock61560172015-02-06 19:46:04 -0500215 return mPlatformType == AudioSystem.PLATFORM_TELEVISION;
Eric Laurent212532b2014-07-21 15:43:18 -0700216 }
Jean-Michel Trivid5176cf2010-01-28 11:56:42 -0800217
John Spurlock3346a802014-05-20 16:25:37 -0400218 /** The controller for the volume UI. */
219 private final VolumeController mVolumeController = new VolumeController();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800220
221 // sendMsg() flags
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800222 /** If the msg is already queued, replace it with this one. */
223 private static final int SENDMSG_REPLACE = 0;
224 /** If the msg is already queued, ignore this one and leave the old. */
225 private static final int SENDMSG_NOOP = 1;
226 /** If the msg is already queued, queue this one and leave the old. */
227 private static final int SENDMSG_QUEUE = 2;
228
Jean-Michel Trivi3114ce32012-06-11 15:03:52 -0700229 // AudioHandler messages
Eric Laurent9bc8358d2011-11-18 16:43:31 -0800230 private static final int MSG_SET_DEVICE_VOLUME = 0;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800231 private static final int MSG_PERSIST_VOLUME = 1;
232 private static final int MSG_PERSIST_RINGER_MODE = 3;
Andy Hunged0ea402015-10-30 14:11:46 -0700233 private static final int MSG_AUDIO_SERVER_DIED = 4;
Eric Laurentdfb881f2013-07-18 14:41:39 -0700234 private static final int MSG_PLAY_SOUND_EFFECT = 5;
235 private static final int MSG_BTA2DP_DOCK_TIMEOUT = 6;
236 private static final int MSG_LOAD_SOUND_EFFECTS = 7;
237 private static final int MSG_SET_FORCE_USE = 8;
238 private static final int MSG_BT_HEADSET_CNCT_FAILED = 9;
239 private static final int MSG_SET_ALL_VOLUMES = 10;
Eric Laurentdfb881f2013-07-18 14:41:39 -0700240 private static final int MSG_REPORT_NEW_ROUTES = 12;
Sungsoocf09fe62016-09-28 16:21:48 +0900241 private static final int MSG_SET_FORCE_BT_A2DP_USE = 13;
Eric Laurentdfb881f2013-07-18 14:41:39 -0700242 private static final int MSG_CHECK_MUSIC_ACTIVE = 14;
243 private static final int MSG_BROADCAST_AUDIO_BECOMING_NOISY = 15;
244 private static final int MSG_CONFIGURE_SAFE_MEDIA_VOLUME = 16;
245 private static final int MSG_CONFIGURE_SAFE_MEDIA_VOLUME_FORCED = 17;
246 private static final int MSG_PERSIST_SAFE_VOLUME_STATE = 18;
247 private static final int MSG_BROADCAST_BT_CONNECTION_STATE = 19;
248 private static final int MSG_UNLOAD_SOUND_EFFECTS = 20;
Eric Laurent4a5eeb92014-05-06 10:49:04 -0700249 private static final int MSG_SYSTEM_READY = 21;
John Spurlockaa5ee4d2014-07-25 13:05:12 -0400250 private static final int MSG_PERSIST_MUSIC_ACTIVE_MS = 22;
RoboErik5452e252015-02-06 15:33:53 -0800251 private static final int MSG_UNMUTE_STREAM = 24;
Jean-Michel Trivi5a561092015-04-23 18:48:08 -0700252 private static final int MSG_DYN_POLICY_MIX_STATE_UPDATE = 25;
Eric Laurent0867bed2015-05-20 14:49:08 -0700253 private static final int MSG_INDICATE_SYSTEM_READY = 26;
Jean-Michel Trivi1ab43f62017-04-27 15:37:34 -0700254 private static final int MSG_ACCESSORY_PLUG_MEDIA_UNMUTE = 27;
Jean-Michel Trivi7ed71472018-02-02 16:52:09 -0800255 private static final int MSG_NOTIFY_VOL_EVENT = 28;
Eric Laurent1d3cdce2018-01-20 10:31:21 -0800256 private static final int MSG_DISPATCH_AUDIO_SERVER_STATE = 29;
Jean-Michel Trivi3114ce32012-06-11 15:03:52 -0700257 // start of messages handled under wakelock
258 // these messages can only be queued, i.e. sent with queueMsgUnderWakeLock(),
Jean-Michel Trivie12c39b2012-06-06 10:51:58 -0700259 // and not with sendMsg(..., ..., SENDMSG_QUEUE, ...)
Jean-Michel Trivifa9a6982013-06-27 16:22:58 -0700260 private static final int MSG_SET_WIRED_DEVICE_CONNECTION_STATE = 100;
Mike Lockwood0a40ec22014-05-21 10:08:50 -0700261 private static final int MSG_SET_A2DP_SRC_CONNECTION_STATE = 101;
262 private static final int MSG_SET_A2DP_SINK_CONNECTION_STATE = 102;
Pavlin Radoslavov44a4ef02016-12-21 12:05:51 -0800263 private static final int MSG_A2DP_DEVICE_CONFIG_CHANGE = 103;
Jean-Michel Trivi92ed7bf2017-06-26 19:32:38 -0700264 private static final int MSG_DISABLE_AUDIO_FOR_UID = 104;
Jakub Pawlowskif9570f32018-02-21 17:15:12 -0800265 private static final int MSG_SET_HEARING_AID_CONNECTION_STATE = 105;
Jean-Michel Trivi3114ce32012-06-11 15:03:52 -0700266 // end of messages handled under wakelock
Eric Laurentafbb0472011-12-15 09:04:23 -0800267
Jean-Michel Trivi4c637b92010-04-12 18:44:10 -0700268 private static final int BTA2DP_DOCK_TIMEOUT_MILLIS = 8000;
Eric Laurentdc03c612011-04-01 10:59:41 -0700269 // Timeout for connection to bluetooth headset service
270 private static final int BT_HEADSET_CNCT_TIMEOUT_MS = 3000;
271
Eric Laurent0867bed2015-05-20 14:49:08 -0700272 // retry delay in case of failure to indicate system ready to AudioFlinger
273 private static final int INDICATE_SYSTEM_READY_RETRY_DELAY_MS = 1000;
274
Jakub Pawlowskif9570f32018-02-21 17:15:12 -0800275 private static final int BT_HEARING_AID_GAIN_MIN = -128;
276
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800277 /** @see AudioSystemThread */
278 private AudioSystemThread mAudioSystemThread;
279 /** @see AudioHandler */
280 private AudioHandler mAudioHandler;
281 /** @see VolumeStreamState */
282 private VolumeStreamState[] mStreamStates;
Jason Parekhb1096152009-03-24 17:48:25 -0700283 private SettingsObserver mSettingsObserver;
Eric Laurenta553c252009-07-17 12:17:14 -0700284
Jean-Michel Trivifa9a6982013-06-27 16:22:58 -0700285 private int mMode = AudioSystem.MODE_NORMAL;
Glenn Kastenba195eb2011-12-13 09:30:40 -0800286 // protects mRingerMode
287 private final Object mSettingsLock = new Object();
Eric Laurent45c90ce2012-04-24 18:44:22 -0700288
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800289 private SoundPool mSoundPool;
Glenn Kasten30c918c2011-11-10 17:56:41 -0800290 private final Object mSoundEffectsLock = new Object();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800291 private static final int NUM_SOUNDPOOL_CHANNELS = 4;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800292
293 /* Sound effect file names */
294 private static final String SOUND_EFFECTS_PATH = "/media/audio/ui/";
Eric Laurente78fced2013-03-15 16:03:47 -0700295 private static final List<String> SOUND_EFFECT_FILES = new ArrayList<String>();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800296
297 /* Sound effect file name mapping sound effect id (AudioManager.FX_xxx) to
298 * file index in SOUND_EFFECT_FILES[] (first column) and indicating if effect
299 * uses soundpool (second column) */
Eric Laurente78fced2013-03-15 16:03:47 -0700300 private final int[][] SOUND_EFFECT_FILES_MAP = new int[AudioManager.NUM_SOUND_EFFECTS][2];
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800301
John Spurlockb6e19e32015-03-10 21:33:44 -0400302 /** Maximum volume index values for audio streams */
Chinyue Chen6affe932018-01-24 14:51:43 +0800303 protected static int[] MAX_STREAM_VOLUME = new int[] {
Eric Laurent6ee99522009-08-25 06:30:59 -0700304 5, // STREAM_VOICE_CALL
305 7, // STREAM_SYSTEM
306 7, // STREAM_RING
307 15, // STREAM_MUSIC
308 7, // STREAM_ALARM
309 7, // STREAM_NOTIFICATION
310 15, // STREAM_BLUETOOTH_SCO
311 7, // STREAM_SYSTEM_ENFORCED
312 15, // STREAM_DTMF
Jean-Michel Trivi3f0945a2016-11-11 10:05:18 -0800313 15, // STREAM_TTS
314 15 // STREAM_ACCESSIBILITY
Jared Suttles59820132009-08-13 21:50:52 -0500315 };
Eric Laurent91377de2014-10-10 15:24:04 -0700316
John Spurlockb6e19e32015-03-10 21:33:44 -0400317 /** Minimum volume index values for audio streams */
Chinyue Chen6affe932018-01-24 14:51:43 +0800318 protected static int[] MIN_STREAM_VOLUME = new int[] {
John Spurlockb6e19e32015-03-10 21:33:44 -0400319 1, // STREAM_VOICE_CALL
320 0, // STREAM_SYSTEM
321 0, // STREAM_RING
322 0, // STREAM_MUSIC
Jean-Michel Trivie05eef82018-03-08 18:56:34 -0800323 1, // STREAM_ALARM
John Spurlockb6e19e32015-03-10 21:33:44 -0400324 0, // STREAM_NOTIFICATION
Eric Laurente4381ec2015-10-29 17:52:48 -0700325 0, // STREAM_BLUETOOTH_SCO
John Spurlockb6e19e32015-03-10 21:33:44 -0400326 0, // STREAM_SYSTEM_ENFORCED
327 0, // STREAM_DTMF
Jean-Michel Trivi3f0945a2016-11-11 10:05:18 -0800328 0, // STREAM_TTS
Jean-Michel Trivie05eef82018-03-08 18:56:34 -0800329 1 // STREAM_ACCESSIBILITY
John Spurlockb6e19e32015-03-10 21:33:44 -0400330 };
331
Eric Laurent6d517662012-04-23 18:42:39 -0700332 /* mStreamVolumeAlias[] indicates for each stream if it uses the volume settings
Eric Laurenta553c252009-07-17 12:17:14 -0700333 * of another stream: This avoids multiplying the volume settings for hidden
334 * stream types that follow other stream behavior for volume settings
Eric Laurent6d517662012-04-23 18:42:39 -0700335 * NOTE: do not create loops in aliases!
336 * Some streams alias to different streams according to device category (phone or tablet) or
Eric Laurent24e0d9b2013-10-03 18:15:07 -0700337 * use case (in call vs off call...). See updateStreamVolumeAlias() for more details.
Eric Laurent212532b2014-07-21 15:43:18 -0700338 * mStreamVolumeAlias contains STREAM_VOLUME_ALIAS_VOICE aliases for a voice capable device
339 * (phone), STREAM_VOLUME_ALIAS_TELEVISION for a television or set-top box and
340 * STREAM_VOLUME_ALIAS_DEFAULT for other devices (e.g. tablets).*/
341 private final int[] STREAM_VOLUME_ALIAS_VOICE = new int[] {
Eric Laurent6d517662012-04-23 18:42:39 -0700342 AudioSystem.STREAM_VOICE_CALL, // STREAM_VOICE_CALL
343 AudioSystem.STREAM_RING, // STREAM_SYSTEM
344 AudioSystem.STREAM_RING, // STREAM_RING
345 AudioSystem.STREAM_MUSIC, // STREAM_MUSIC
346 AudioSystem.STREAM_ALARM, // STREAM_ALARM
347 AudioSystem.STREAM_RING, // STREAM_NOTIFICATION
348 AudioSystem.STREAM_BLUETOOTH_SCO, // STREAM_BLUETOOTH_SCO
349 AudioSystem.STREAM_RING, // STREAM_SYSTEM_ENFORCED
350 AudioSystem.STREAM_RING, // STREAM_DTMF
Jean-Michel Trivi3f0945a2016-11-11 10:05:18 -0800351 AudioSystem.STREAM_MUSIC, // STREAM_TTS
352 AudioSystem.STREAM_MUSIC // STREAM_ACCESSIBILITY
Eric Laurenta553c252009-07-17 12:17:14 -0700353 };
Eric Laurent212532b2014-07-21 15:43:18 -0700354 private final int[] STREAM_VOLUME_ALIAS_TELEVISION = new int[] {
355 AudioSystem.STREAM_MUSIC, // STREAM_VOICE_CALL
356 AudioSystem.STREAM_MUSIC, // STREAM_SYSTEM
357 AudioSystem.STREAM_MUSIC, // STREAM_RING
358 AudioSystem.STREAM_MUSIC, // STREAM_MUSIC
359 AudioSystem.STREAM_MUSIC, // STREAM_ALARM
360 AudioSystem.STREAM_MUSIC, // STREAM_NOTIFICATION
361 AudioSystem.STREAM_MUSIC, // STREAM_BLUETOOTH_SCO
362 AudioSystem.STREAM_MUSIC, // STREAM_SYSTEM_ENFORCED
363 AudioSystem.STREAM_MUSIC, // STREAM_DTMF
Jean-Michel Trivi3f0945a2016-11-11 10:05:18 -0800364 AudioSystem.STREAM_MUSIC, // STREAM_TTS
365 AudioSystem.STREAM_MUSIC // STREAM_ACCESSIBILITY
Eric Laurent212532b2014-07-21 15:43:18 -0700366 };
367 private final int[] STREAM_VOLUME_ALIAS_DEFAULT = new int[] {
Eric Laurent6d517662012-04-23 18:42:39 -0700368 AudioSystem.STREAM_VOICE_CALL, // STREAM_VOICE_CALL
John Spurlock4f0f1202014-08-05 13:28:33 -0400369 AudioSystem.STREAM_RING, // STREAM_SYSTEM
Eric Laurent6d517662012-04-23 18:42:39 -0700370 AudioSystem.STREAM_RING, // STREAM_RING
371 AudioSystem.STREAM_MUSIC, // STREAM_MUSIC
372 AudioSystem.STREAM_ALARM, // STREAM_ALARM
373 AudioSystem.STREAM_RING, // STREAM_NOTIFICATION
374 AudioSystem.STREAM_BLUETOOTH_SCO, // STREAM_BLUETOOTH_SCO
John Spurlock4f0f1202014-08-05 13:28:33 -0400375 AudioSystem.STREAM_RING, // STREAM_SYSTEM_ENFORCED
376 AudioSystem.STREAM_RING, // STREAM_DTMF
Jean-Michel Trivi3f0945a2016-11-11 10:05:18 -0800377 AudioSystem.STREAM_MUSIC, // STREAM_TTS
378 AudioSystem.STREAM_MUSIC // STREAM_ACCESSIBILITY
Eric Laurent6d517662012-04-23 18:42:39 -0700379 };
Yue Li949865b2017-05-24 17:25:28 -0700380 protected static int[] mStreamVolumeAlias;
Eric Laurenta553c252009-07-17 12:17:14 -0700381
Dianne Hackbornba50b97c2013-04-30 15:04:46 -0700382 /**
383 * Map AudioSystem.STREAM_* constants to app ops. This should be used
384 * after mapping through mStreamVolumeAlias.
385 */
John Spurlock59dc9c12015-03-02 11:20:15 -0500386 private static final int[] STREAM_VOLUME_OPS = new int[] {
Dianne Hackbornba50b97c2013-04-30 15:04:46 -0700387 AppOpsManager.OP_AUDIO_VOICE_VOLUME, // STREAM_VOICE_CALL
388 AppOpsManager.OP_AUDIO_MEDIA_VOLUME, // STREAM_SYSTEM
389 AppOpsManager.OP_AUDIO_RING_VOLUME, // STREAM_RING
390 AppOpsManager.OP_AUDIO_MEDIA_VOLUME, // STREAM_MUSIC
391 AppOpsManager.OP_AUDIO_ALARM_VOLUME, // STREAM_ALARM
392 AppOpsManager.OP_AUDIO_NOTIFICATION_VOLUME, // STREAM_NOTIFICATION
393 AppOpsManager.OP_AUDIO_BLUETOOTH_VOLUME, // STREAM_BLUETOOTH_SCO
394 AppOpsManager.OP_AUDIO_MEDIA_VOLUME, // STREAM_SYSTEM_ENFORCED
395 AppOpsManager.OP_AUDIO_MEDIA_VOLUME, // STREAM_DTMF
396 AppOpsManager.OP_AUDIO_MEDIA_VOLUME, // STREAM_TTS
Jean-Michel Trivi3f0945a2016-11-11 10:05:18 -0800397 AppOpsManager.OP_AUDIO_ACCESSIBILITY_VOLUME, // STREAM_ACCESSIBILITY
Dianne Hackbornba50b97c2013-04-30 15:04:46 -0700398 };
399
Eric Laurent83a017b2013-03-19 18:15:31 -0700400 private final boolean mUseFixedVolume;
401
Glenn Kasten30c918c2011-11-10 17:56:41 -0800402 private final AudioSystem.ErrorCallback mAudioSystemCallback = new AudioSystem.ErrorCallback() {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800403 public void onError(int error) {
404 switch (error) {
405 case AudioSystem.AUDIO_STATUS_SERVER_DIED:
Andy Hunged0ea402015-10-30 14:11:46 -0700406 sendMsg(mAudioHandler, MSG_AUDIO_SERVER_DIED,
Eric Laurentdfb881f2013-07-18 14:41:39 -0700407 SENDMSG_NOOP, 0, 0, null, 0);
Eric Laurent1d3cdce2018-01-20 10:31:21 -0800408 sendMsg(mAudioHandler, MSG_DISPATCH_AUDIO_SERVER_STATE,
409 SENDMSG_QUEUE, 0, 0, null, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800410 break;
411 default:
412 break;
413 }
Eric Laurentdfb881f2013-07-18 14:41:39 -0700414 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800415 };
416
417 /**
418 * Current ringer mode from one of {@link AudioManager#RINGER_MODE_NORMAL},
419 * {@link AudioManager#RINGER_MODE_SILENT}, or
420 * {@link AudioManager#RINGER_MODE_VIBRATE}.
421 */
Jean-Michel Trivi8719a1d2017-11-06 11:52:51 -0800422 @GuardedBy("mSettingsLock")
John Spurlock661f2cf2014-11-17 10:29:10 -0500423 private int mRingerMode; // internal ringer mode, affects muting of underlying streams
Jean-Michel Trivi8719a1d2017-11-06 11:52:51 -0800424 @GuardedBy("mSettingsLock")
John Spurlock661f2cf2014-11-17 10:29:10 -0500425 private int mRingerModeExternal = -1; // reported ringer mode to outside clients (AudioManager)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800426
Eric Laurent9bcf4012009-06-12 06:09:28 -0700427 /** @see System#MODE_RINGER_STREAMS_AFFECTED */
Eric Laurent24e0d9b2013-10-03 18:15:07 -0700428 private int mRingerModeAffectedStreams = 0;
Eric Laurent9bcf4012009-06-12 06:09:28 -0700429
Beverlyd6964762018-02-16 14:07:03 -0500430 private int mZenModeAffectedStreams = 0;
431
432 // Streams currently muted by ringer mode and dnd
433 private int mRingerAndZenModeMutedStreams;
Eric Laurent5b4e6542010-03-19 20:02:21 -0700434
John Spurlock3ce37252015-02-17 13:20:45 -0500435 /** Streams that can be muted. Do not resolve to aliases when checking.
436 * @see System#MUTE_STREAMS_AFFECTED */
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800437 private int mMuteAffectedStreams;
438
439 /**
Eric Laurentbffc3d12012-05-07 17:43:49 -0700440 * NOTE: setVibrateSetting(), getVibrateSetting(), shouldVibrate() are deprecated.
441 * mVibrateSetting is just maintained during deprecation period but vibration policy is
442 * now only controlled by mHasVibrator and mRingerMode
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800443 */
444 private int mVibrateSetting;
445
Eric Laurentbffc3d12012-05-07 17:43:49 -0700446 // Is there a vibrator
447 private final boolean mHasVibrator;
Mike Digman55272862018-02-20 14:35:17 -0800448 // Used to play vibrations
449 private Vibrator mVibrator;
450 private static final AudioAttributes VIBRATION_ATTRIBUTES = new AudioAttributes.Builder()
451 .setContentType(AudioAttributes.CONTENT_TYPE_SONIFICATION)
452 .setUsage(AudioAttributes.USAGE_ASSISTANCE_SONIFICATION)
453 .build();
Eric Laurentbffc3d12012-05-07 17:43:49 -0700454
Eric Laurenta553c252009-07-17 12:17:14 -0700455 // Broadcast receiver for device connections intent broadcasts
456 private final BroadcastReceiver mReceiver = new AudioServiceBroadcastReceiver();
457
Makoto Onukid45a4a22015-11-02 17:17:38 -0800458 /** Interface for UserManagerService. */
459 private final UserManagerInternal mUserManagerInternal;
Sudheer Shankafc46e9b2016-10-21 17:55:27 -0700460 private final ActivityManagerInternal mActivityManagerInternal;
Makoto Onukid45a4a22015-11-02 17:17:38 -0800461
462 private final UserRestrictionsListener mUserRestrictionsListener =
463 new AudioServiceUserRestrictionsListener();
464
Eric Laurentc42ac9d2009-07-29 08:53:03 -0700465 // Devices currently connected
Paul McLean394a8e12015-03-03 10:29:19 -0700466 // Use makeDeviceListKey() to make a unique key for this list.
467 private class DeviceListSpec {
468 int mDeviceType;
469 String mDeviceName;
470 String mDeviceAddress;
471
472 public DeviceListSpec(int deviceType, String deviceName, String deviceAddress) {
473 mDeviceType = deviceType;
474 mDeviceName = deviceName;
475 mDeviceAddress = deviceAddress;
476 }
477
478 public String toString() {
479 return "[type:0x" + Integer.toHexString(mDeviceType) + " name:" + mDeviceName
480 + " address:" + mDeviceAddress + "]";
481 }
482 }
483
484 // Generate a unique key for the mConnectedDevices List by composing the device "type"
485 // and the "address" associated with a specific instance of that device type
486 private String makeDeviceListKey(int device, String deviceAddress) {
487 return "0x" + Integer.toHexString(device) + ":" + deviceAddress;
488 }
489
John Spurlock8c3dc852015-04-23 21:32:37 -0400490 private final ArrayMap<String, DeviceListSpec> mConnectedDevices = new ArrayMap<>();
Eric Laurentc42ac9d2009-07-29 08:53:03 -0700491
492 // Forced device usage for communications
493 private int mForcedUseForComm;
Sharad Sangle1d188442017-05-09 16:05:40 +0530494 private int mForcedUseForCommExt; // External state returned by getters: always consistent
495 // with requests by setters
Eric Laurentc42ac9d2009-07-29 08:53:03 -0700496
Eric Laurent9272b4b2010-01-23 17:12:59 -0800497 // List of binder death handlers for setMode() client processes.
498 // The last process to have called setMode() is at the top of the list.
Glenn Kasten30c918c2011-11-10 17:56:41 -0800499 private final ArrayList <SetModeDeathHandler> mSetModeDeathHandlers = new ArrayList <SetModeDeathHandler>();
Eric Laurenteb14a782009-12-17 03:12:59 -0800500
Eric Laurent3def1ee2010-03-17 23:26:26 -0700501 // List of clients having issued a SCO start request
Glenn Kasten30c918c2011-11-10 17:56:41 -0800502 private final ArrayList <ScoClient> mScoClients = new ArrayList <ScoClient>();
Eric Laurent3def1ee2010-03-17 23:26:26 -0700503
504 // BluetoothHeadset API to control SCO connection
505 private BluetoothHeadset mBluetoothHeadset;
506
Jaikumar Ganesh82aa7f02010-09-27 17:05:10 -0700507 // Bluetooth headset device
508 private BluetoothDevice mBluetoothHeadsetDevice;
Eric Laurent3def1ee2010-03-17 23:26:26 -0700509
Eric Laurent62ef7672010-11-24 10:58:32 -0800510 // Indicate if SCO audio connection is currently active and if the initiator is
511 // audio service (internal) or bluetooth headset (external)
512 private int mScoAudioState;
513 // SCO audio state is not active
514 private static final int SCO_STATE_INACTIVE = 0;
Eric Laurentdc03c612011-04-01 10:59:41 -0700515 // SCO audio activation request waiting for headset service to connect
516 private static final int SCO_STATE_ACTIVATE_REQ = 1;
Eric Laurent25fc29b2013-04-05 12:13:54 -0700517 // SCO audio state is active or starting due to a request from AudioManager API
Eric Laurentdc03c612011-04-01 10:59:41 -0700518 private static final int SCO_STATE_ACTIVE_INTERNAL = 3;
519 // SCO audio deactivation request waiting for headset service to connect
520 private static final int SCO_STATE_DEACTIVATE_REQ = 5;
521
Eric Laurent62ef7672010-11-24 10:58:32 -0800522 // SCO audio state is active due to an action in BT handsfree (either voice recognition or
523 // in call audio)
524 private static final int SCO_STATE_ACTIVE_EXTERNAL = 2;
Eric Laurentdc03c612011-04-01 10:59:41 -0700525 // Deactivation request for all SCO connections (initiated by audio mode change)
526 // waiting for headset service to connect
527 private static final int SCO_STATE_DEACTIVATE_EXT_REQ = 4;
528
Eric Laurentc18c9132013-04-12 17:24:56 -0700529 // Indicates the mode used for SCO audio connection. The mode is virtual call if the request
530 // originated from an app targeting an API version before JB MR2 and raw audio after that.
531 private int mScoAudioMode;
Liejun Taof4e51d82014-07-16 11:18:29 -0700532 // SCO audio mode is undefined
533 private static final int SCO_MODE_UNDEFINED = -1;
Eric Laurentc18c9132013-04-12 17:24:56 -0700534 // SCO audio mode is virtual voice call (BluetoothHeadset.startScoUsingVirtualVoiceCall())
535 private static final int SCO_MODE_VIRTUAL_CALL = 0;
536 // SCO audio mode is raw audio (BluetoothHeadset.connectAudio())
537 private static final int SCO_MODE_RAW = 1;
Liejun Taof4e51d82014-07-16 11:18:29 -0700538 // SCO audio mode is Voice Recognition (BluetoothHeadset.startVoiceRecognition())
539 private static final int SCO_MODE_VR = 2;
540
541 private static final int SCO_MODE_MAX = 2;
Eric Laurentc18c9132013-04-12 17:24:56 -0700542
Eric Laurentdc03c612011-04-01 10:59:41 -0700543 // Current connection state indicated by bluetooth headset
544 private int mScoConnectionState;
Eric Laurent62ef7672010-11-24 10:58:32 -0800545
Eric Laurenta60e2122010-12-28 16:49:07 -0800546 // true if boot sequence has been completed
Eric Laurent4a5eeb92014-05-06 10:49:04 -0700547 private boolean mSystemReady;
Yasuhiro Matsuda4ced7192015-07-10 22:08:44 +0900548 // true if Intent.ACTION_USER_SWITCHED has ever been received
549 private boolean mUserSwitchedReceived;
Eric Laurenta60e2122010-12-28 16:49:07 -0800550 // listener for SoundPool sample load completion indication
551 private SoundPoolCallback mSoundPoolCallBack;
552 // thread for SoundPool listener
553 private SoundPoolListenerThread mSoundPoolListenerThread;
554 // message looper for SoundPool listener
555 private Looper mSoundPoolLooper = null;
Jean-Michel Trivic55b3932012-06-05 11:57:59 -0700556 // volume applied to sound played with playSoundEffect()
Jean-Michel Trivif2b0c112012-07-09 11:59:11 -0700557 private static int sSoundEffectVolumeDb;
Eric Laurent25101b02011-02-02 09:33:30 -0800558 // previous volume adjustment direction received by checkForRingerModeChange()
559 private int mPrevVolDirection = AudioManager.ADJUST_SAME;
Eric Laurent45c90ce2012-04-24 18:44:22 -0700560 // mVolumeControlStream is set by VolumePanel to temporarily force the stream type which volume
561 // is controlled by Vol keys.
Jean-Michel Trivia7880d42017-04-15 12:41:05 -0700562 private int mVolumeControlStream = -1;
563 // interpretation of whether the volume stream has been selected by the user by clicking on a
564 // volume slider to change which volume is controlled by the volume keys. Is false
565 // when mVolumeControlStream is -1.
566 private boolean mUserSelectedVolumeControlStream = false;
Eric Laurent45c90ce2012-04-24 18:44:22 -0700567 private final Object mForceControlStreamLock = new Object();
568 // VolumePanel is currently the only client of forceVolumeControlStream() and runs in system
569 // server process so in theory it is not necessary to monitor the client death.
570 // However it is good to be ready for future evolutions.
571 private ForceControlStreamClient mForceControlStreamClient = null;
Jeff Sharkey098d5802012-04-26 17:30:34 -0700572 // Used to play ringtones outside system_server
573 private volatile IRingtonePlayer mRingtonePlayer;
Eric Laurent9bc8358d2011-11-18 16:43:31 -0800574
Eric Laurent78472112012-05-21 08:57:21 -0700575 // Request to override default use of A2DP for media.
Sungsoo486f7d32016-09-28 16:20:52 +0900576 private boolean mBluetoothA2dpEnabled;
Eric Laurent78472112012-05-21 08:57:21 -0700577 private final Object mBluetoothA2dpEnabledLock = new Object();
578
Dianne Hackborn632ca412012-06-14 19:34:10 -0700579 // Monitoring of audio routes. Protected by mCurAudioRoutes.
580 final AudioRoutesInfo mCurAudioRoutes = new AudioRoutesInfo();
581 final RemoteCallbackList<IAudioRoutesObserver> mRoutesObservers
582 = new RemoteCallbackList<IAudioRoutesObserver>();
583
Eric Laurent4bbcc652012-09-24 14:26:30 -0700584 // Devices for which the volume is fixed and VolumePanel slider should be disabled
Eric Laurent212532b2014-07-21 15:43:18 -0700585 int mFixedVolumeDevices = AudioSystem.DEVICE_OUT_HDMI |
Eric Laurent4bbcc652012-09-24 14:26:30 -0700586 AudioSystem.DEVICE_OUT_DGTL_DOCK_HEADSET |
Eric Laurent212532b2014-07-21 15:43:18 -0700587 AudioSystem.DEVICE_OUT_ANLG_DOCK_HEADSET |
588 AudioSystem.DEVICE_OUT_HDMI_ARC |
589 AudioSystem.DEVICE_OUT_SPDIF |
590 AudioSystem.DEVICE_OUT_AUX_LINE;
Jakub Pawlowskic274fb22018-04-04 10:15:12 -0700591 int mFullVolumeDevices = 0;
Eric Laurent4bbcc652012-09-24 14:26:30 -0700592
Jean-Michel Trivibb6f8712013-05-23 15:02:41 -0700593 private final boolean mMonitorRotation;
Eric Laurentd640bd32012-09-28 18:01:48 -0700594
Eric Laurent7ee1e4f2012-10-26 18:11:21 -0700595 private boolean mDockAudioMediaEnabled = true;
596
Eric Laurent08ed1b92012-11-05 14:54:12 -0800597 private int mDockState = Intent.EXTRA_DOCK_STATE_UNDOCKED;
598
Eric Laurentfde16d52012-12-03 14:42:39 -0800599 // Used when safe volume warning message display is requested by setStreamVolume(). In this
600 // case, the new requested volume, stream type and device are stored in mPendingVolumeCommand
601 // and used later when/if disableSafeMediaVolume() is called.
602 private StreamVolumeCommand mPendingVolumeCommand;
603
Jean-Michel Trivifa9a6982013-06-27 16:22:58 -0700604 private PowerManager.WakeLock mAudioEventWakeLock;
605
606 private final MediaFocusControl mMediaFocusControl;
607
Jakub Pawlowskif9570f32018-02-21 17:15:12 -0800608 // Reference to BluetoothA2dp to query for volume.
609 private BluetoothHearingAid mHearingAid;
610 // lock always taken synchronized on mConnectedDevices
611 private final Object mHearingAidLock = new Object();
John Du5a0cf7a2013-07-19 11:30:34 -0700612 // Reference to BluetoothA2dp to query for AbsoluteVolume.
613 private BluetoothA2dp mA2dp;
seunghwan.hong4fe77952014-10-29 17:43:20 +0900614 // lock always taken synchronized on mConnectedDevices
John Du5a0cf7a2013-07-19 11:30:34 -0700615 private final Object mA2dpAvrcpLock = new Object();
616 // If absolute volume is supported in AVRCP device
617 private boolean mAvrcpAbsVolSupported = false;
618
Eric Laurentadbe8bf2014-11-03 18:26:32 -0800619 private static Long mLastDeviceConnectMsgTime = new Long(0);
620
Julia Reynolds48034f82016-03-09 10:15:16 -0500621 private NotificationManager mNm;
John Spurlock661f2cf2014-11-17 10:29:10 -0500622 private AudioManagerInternal.RingerModeDelegate mRingerModeDelegate;
John Spurlocka48d7792015-03-03 17:35:57 -0500623 private VolumePolicy mVolumePolicy = VolumePolicy.DEFAULT;
John Spurlock07e72432015-03-13 11:46:52 -0400624 private long mLoweredFromNormalToVibrateTime;
John Spurlock661f2cf2014-11-17 10:29:10 -0500625
Phil Weaverf1a9aff2017-03-23 17:21:29 -0700626 // Array of Uids of valid accessibility services to check if caller is one of them
627 private int[] mAccessibilityServiceUids;
628 private final Object mAccessibilityServiceUidsLock = new Object();
629
Paul McLean10804eb2015-01-28 11:16:35 -0800630 // Intent "extra" data keys.
631 public static final String CONNECT_INTENT_KEY_PORT_NAME = "portName";
632 public static final String CONNECT_INTENT_KEY_STATE = "state";
633 public static final String CONNECT_INTENT_KEY_ADDRESS = "address";
634 public static final String CONNECT_INTENT_KEY_HAS_PLAYBACK = "hasPlayback";
635 public static final String CONNECT_INTENT_KEY_HAS_CAPTURE = "hasCapture";
636 public static final String CONNECT_INTENT_KEY_HAS_MIDI = "hasMIDI";
637 public static final String CONNECT_INTENT_KEY_DEVICE_CLASS = "class";
638
639 // Defines the format for the connection "address" for ALSA devices
640 public static String makeAlsaAddressString(int card, int device) {
641 return "card=" + card + ";device=" + device + ";";
642 }
643
Makoto Onukie1aef852015-10-15 17:28:35 -0700644 public static final class Lifecycle extends SystemService {
645 private AudioService mService;
646
647 public Lifecycle(Context context) {
648 super(context);
649 mService = new AudioService(context);
650 }
651
652 @Override
653 public void onStart() {
654 publishBinderService(Context.AUDIO_SERVICE, mService);
655 }
656
657 @Override
658 public void onBootPhase(int phase) {
659 if (phase == SystemService.PHASE_ACTIVITY_MANAGER_READY) {
660 mService.systemReady();
661 }
662 }
663 }
664
Dianne Hackborn3e99f652017-07-05 16:33:56 -0700665 final private IUidObserver mUidObserver = new IUidObserver.Stub() {
666 @Override public void onUidStateChanged(int uid, int procState, long procStateSeq) {
667 }
668
669 @Override public void onUidGone(int uid, boolean disabled) {
670 // Once the uid is no longer running, no need to keep trying to disable its audio.
671 disableAudioForUid(false, uid);
672 }
673
674 @Override public void onUidActive(int uid) throws RemoteException {
675 }
676
677 @Override public void onUidIdle(int uid, boolean disabled) {
678 }
679
680 @Override public void onUidCachedChanged(int uid, boolean cached) {
681 disableAudioForUid(cached, uid);
682 }
683
684 private void disableAudioForUid(boolean disable, int uid) {
685 queueMsgUnderWakeLock(mAudioHandler, MSG_DISABLE_AUDIO_FOR_UID,
686 disable ? 1 : 0 /* arg1 */, uid /* arg2 */,
687 null /* obj */, 0 /* delay */);
688 }
689 };
690
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800691 ///////////////////////////////////////////////////////////////////////////
692 // Construction
693 ///////////////////////////////////////////////////////////////////////////
694
695 /** @hide */
696 public AudioService(Context context) {
697 mContext = context;
698 mContentResolver = context.getContentResolver();
Dianne Hackbornba50b97c2013-04-30 15:04:46 -0700699 mAppOps = (AppOpsManager)context.getSystemService(Context.APP_OPS_SERVICE);
Eric Laurent212532b2014-07-21 15:43:18 -0700700
John Spurlock61560172015-02-06 19:46:04 -0500701 mPlatformType = AudioSystem.getPlatformType(context);
Jared Suttles59820132009-08-13 21:50:52 -0500702
Muyuan Li1ed6df62016-06-18 11:16:52 -0700703 mIsSingleVolume = AudioSystem.isSingleVolume(context);
704
Makoto Onukid45a4a22015-11-02 17:17:38 -0800705 mUserManagerInternal = LocalServices.getService(UserManagerInternal.class);
Sudheer Shankafc46e9b2016-10-21 17:55:27 -0700706 mActivityManagerInternal = LocalServices.getService(ActivityManagerInternal.class);
Makoto Onukid45a4a22015-11-02 17:17:38 -0800707
Jean-Michel Trivic6802222012-04-30 11:15:03 -0700708 PowerManager pm = (PowerManager)context.getSystemService(Context.POWER_SERVICE);
Jean-Michel Trivifa9a6982013-06-27 16:22:58 -0700709 mAudioEventWakeLock = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "handleAudioEvent");
Jean-Michel Trivic6802222012-04-30 11:15:03 -0700710
Mike Digman55272862018-02-20 14:35:17 -0800711 mVibrator = (Vibrator) context.getSystemService(Context.VIBRATOR_SERVICE);
712 mHasVibrator = mVibrator == null ? false : mVibrator.hasVibrator();
Eric Laurentbffc3d12012-05-07 17:43:49 -0700713
John Spurlockb6e19e32015-03-10 21:33:44 -0400714 // Initialize volume
Eric Laurent403bd342017-07-11 16:21:44 -0700715 int maxCallVolume = SystemProperties.getInt("ro.config.vc_call_vol_steps", -1);
716 if (maxCallVolume != -1) {
717 MAX_STREAM_VOLUME[AudioSystem.STREAM_VOICE_CALL] = maxCallVolume;
718 AudioSystem.DEFAULT_STREAM_VOLUME[AudioSystem.STREAM_VOICE_CALL] =
719 (maxCallVolume * 3) / 4;
Eric Laurent91377de2014-10-10 15:24:04 -0700720 }
Eric Laurent403bd342017-07-11 16:21:44 -0700721
722 int maxMusicVolume = SystemProperties.getInt("ro.config.media_vol_steps", -1);
723 if (maxMusicVolume != -1) {
724 MAX_STREAM_VOLUME[AudioSystem.STREAM_MUSIC] = maxMusicVolume;
725 }
726
727 int defaultMusicVolume = SystemProperties.getInt("ro.config.media_vol_default", -1);
728 if (defaultMusicVolume != -1 &&
729 defaultMusicVolume <= MAX_STREAM_VOLUME[AudioSystem.STREAM_MUSIC]) {
730 AudioSystem.DEFAULT_STREAM_VOLUME[AudioSystem.STREAM_MUSIC] = defaultMusicVolume;
731 } else {
Hank Freund45926dc2015-12-11 10:50:45 -0800732 if (isPlatformTelevision()) {
Eric Laurent403bd342017-07-11 16:21:44 -0700733 AudioSystem.DEFAULT_STREAM_VOLUME[AudioSystem.STREAM_MUSIC] =
734 MAX_STREAM_VOLUME[AudioSystem.STREAM_MUSIC] / 4;
Hank Freund45926dc2015-12-11 10:50:45 -0800735 } else {
Eric Laurent403bd342017-07-11 16:21:44 -0700736 AudioSystem.DEFAULT_STREAM_VOLUME[AudioSystem.STREAM_MUSIC] =
737 MAX_STREAM_VOLUME[AudioSystem.STREAM_MUSIC] / 3;
Hank Freund45926dc2015-12-11 10:50:45 -0800738 }
Eric Laurent91377de2014-10-10 15:24:04 -0700739 }
Jared Suttles59820132009-08-13 21:50:52 -0500740
Chris Kuiper09b6c212018-01-03 22:22:13 -0800741 int maxAlarmVolume = SystemProperties.getInt("ro.config.alarm_vol_steps", -1);
742 if (maxAlarmVolume != -1) {
743 MAX_STREAM_VOLUME[AudioSystem.STREAM_ALARM] = maxAlarmVolume;
744 }
745
746 int defaultAlarmVolume = SystemProperties.getInt("ro.config.alarm_vol_default", -1);
747 if (defaultAlarmVolume != -1 &&
748 defaultAlarmVolume <= MAX_STREAM_VOLUME[AudioSystem.STREAM_ALARM]) {
749 AudioSystem.DEFAULT_STREAM_VOLUME[AudioSystem.STREAM_ALARM] = defaultAlarmVolume;
750 } else {
751 // Default is 6 out of 7 (default maximum), so scale accordingly.
752 AudioSystem.DEFAULT_STREAM_VOLUME[AudioSystem.STREAM_ALARM] =
753 6 * MAX_STREAM_VOLUME[AudioSystem.STREAM_ALARM] / 7;
754 }
755
756 int maxSystemVolume = SystemProperties.getInt("ro.config.system_vol_steps", -1);
757 if (maxSystemVolume != -1) {
758 MAX_STREAM_VOLUME[AudioSystem.STREAM_SYSTEM] = maxSystemVolume;
759 }
760
761 int defaultSystemVolume = SystemProperties.getInt("ro.config.system_vol_default", -1);
762 if (defaultSystemVolume != -1 &&
763 defaultSystemVolume <= MAX_STREAM_VOLUME[AudioSystem.STREAM_SYSTEM]) {
764 AudioSystem.DEFAULT_STREAM_VOLUME[AudioSystem.STREAM_SYSTEM] = defaultSystemVolume;
765 } else {
766 // Default is to use maximum.
767 AudioSystem.DEFAULT_STREAM_VOLUME[AudioSystem.STREAM_SYSTEM] =
768 MAX_STREAM_VOLUME[AudioSystem.STREAM_SYSTEM];
769 }
770
Jean-Michel Trivif2b0c112012-07-09 11:59:11 -0700771 sSoundEffectVolumeDb = context.getResources().getInteger(
Jean-Michel Trivic55b3932012-06-05 11:57:59 -0700772 com.android.internal.R.integer.config_soundEffectVolumeDb);
Eric Laurent25101b02011-02-02 09:33:30 -0800773
Eric Laurentc42ac9d2009-07-29 08:53:03 -0700774 mForcedUseForComm = AudioSystem.FORCE_NONE;
Eric Laurentdd45d012012-10-08 09:04:34 -0700775
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800776 createAudioSystemThread();
Eric Laurentdd45d012012-10-08 09:04:34 -0700777
Eric Laurentdfb881f2013-07-18 14:41:39 -0700778 AudioSystem.setErrorCallback(mAudioSystemCallback);
779
John Spurlock5e783732015-02-19 10:28:59 -0500780 boolean cameraSoundForced = readCameraSoundForced();
Eric Laurentdd45d012012-10-08 09:04:34 -0700781 mCameraSoundForced = new Boolean(cameraSoundForced);
782 sendMsg(mAudioHandler,
783 MSG_SET_FORCE_USE,
784 SENDMSG_QUEUE,
785 AudioSystem.FOR_SYSTEM,
786 cameraSoundForced ?
787 AudioSystem.FORCE_SYSTEM_ENFORCED : AudioSystem.FORCE_NONE,
Jean-Michel Trivi011f39e2017-08-19 18:08:06 -0700788 new String("AudioService ctor"),
Eric Laurentdd45d012012-10-08 09:04:34 -0700789 0);
790
Eric Laurent05274f32012-11-29 12:48:18 -0800791 mSafeMediaVolumeState = new Integer(Settings.Global.getInt(mContentResolver,
792 Settings.Global.AUDIO_SAFE_VOLUME_STATE,
793 SAFE_MEDIA_VOLUME_NOT_CONFIGURED));
794 // The default safe volume index read here will be replaced by the actual value when
795 // the mcc is read by onConfigureSafeVolume()
796 mSafeMediaVolumeIndex = mContext.getResources().getInteger(
797 com.android.internal.R.integer.config_safe_media_volume_index) * 10;
798
Eric Laurent83a017b2013-03-19 18:15:31 -0700799 mUseFixedVolume = mContext.getResources().getBoolean(
800 com.android.internal.R.bool.config_useFixedVolume);
801
Eric Laurent24e0d9b2013-10-03 18:15:07 -0700802 // must be called before readPersistedSettings() which needs a valid mStreamVolumeAlias[]
803 // array initialized by updateStreamVolumeAlias()
John Spurlock90874332015-03-10 16:00:54 -0400804 updateStreamVolumeAlias(false /*updateVolumes*/, TAG);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800805 readPersistedSettings();
Eric Laurentc0232482016-03-15 18:19:23 -0700806 readUserRestrictions();
Eric Laurentc1d41662011-07-19 11:21:13 -0700807 mSettingsObserver = new SettingsObserver();
Eric Laurenta553c252009-07-17 12:17:14 -0700808 createStreamStates();
Eric Laurent9f103de2011-09-08 15:04:23 -0700809
Eric Laurentb378a13a2017-07-11 14:08:11 -0700810 // mSafeUsbMediaVolumeIndex must be initialized after createStreamStates() because it
811 // relies on audio policy having correct ranges for volume indexes.
812 mSafeUsbMediaVolumeIndex = getSafeUsbMediaVolumeIndex();
813
Eric Laurente5a351c2017-09-27 20:11:51 -0700814 mPlaybackMonitor =
815 new PlaybackActivityMonitor(context, MAX_STREAM_VOLUME[AudioSystem.STREAM_ALARM]);
816
Jean-Michel Trivi99489cc2017-01-25 19:08:49 -0800817 mMediaFocusControl = new MediaFocusControl(mContext, mPlaybackMonitor);
John Spurlockb6e19e32015-03-10 21:33:44 -0400818
Jean-Michel Trivi66ffacf2017-02-04 17:25:31 -0800819 mRecordMonitor = new RecordingActivityMonitor(mContext);
820
Glenn Kastenfd116ad2013-07-12 17:10:39 -0700821 readAndSetLowRamDevice();
Eric Laurent3891c4c2010-04-20 09:40:57 -0700822
823 // Call setRingerModeInt() to apply correct mute
824 // state on streams affected by ringer mode.
Beverlyd6964762018-02-16 14:07:03 -0500825 mRingerAndZenModeMutedStreams = 0;
John Spurlock661f2cf2014-11-17 10:29:10 -0500826 setRingerModeInt(getRingerModeInternal(), false);
Eric Laurent3891c4c2010-04-20 09:40:57 -0700827
Eric Laurenta553c252009-07-17 12:17:14 -0700828 // Register for device connection intent broadcasts.
829 IntentFilter intentFilter =
Eric Laurentb1fbaac2012-05-29 09:24:28 -0700830 new IntentFilter(BluetoothHeadset.ACTION_AUDIO_STATE_CHANGED);
Jack He8dd33942018-01-17 15:45:12 -0800831 intentFilter.addAction(BluetoothHeadset.ACTION_ACTIVE_DEVICE_CHANGED);
Jaikumar Ganesh82aa7f02010-09-27 17:05:10 -0700832 intentFilter.addAction(Intent.ACTION_DOCK_EVENT);
Eric Laurent950e8cb2011-10-13 08:57:54 -0700833 intentFilter.addAction(Intent.ACTION_SCREEN_ON);
834 intentFilter.addAction(Intent.ACTION_SCREEN_OFF);
Eric Laurentbc0fab1f2012-09-19 11:24:41 -0700835 intentFilter.addAction(Intent.ACTION_USER_SWITCHED);
Fyodor Kupolovb5013302015-04-17 17:59:14 -0700836 intentFilter.addAction(Intent.ACTION_USER_BACKGROUND);
837 intentFilter.addAction(Intent.ACTION_USER_FOREGROUND);
Paul McLeanc837a452014-04-09 09:04:43 -0700838 intentFilter.addAction(UsbManager.ACTION_USB_DEVICE_ATTACHED);
Eric Laurentb70b78a2016-01-13 19:16:04 -0800839 intentFilter.addAction(BluetoothAdapter.ACTION_STATE_CHANGED);
Jean-Michel Trivif26f0172012-04-25 16:23:20 -0700840
Eric Laurentd640bd32012-09-28 18:01:48 -0700841 intentFilter.addAction(Intent.ACTION_CONFIGURATION_CHANGED);
Jean-Michel Trivibb6f8712013-05-23 15:02:41 -0700842 mMonitorRotation = SystemProperties.getBoolean("ro.audio.monitorRotation", false);
843 if (mMonitorRotation) {
Jean-Michel Trivi24806db2015-10-01 15:00:59 -0700844 RotationHelper.init(mContext, mAudioHandler);
Jean-Michel Trivibb6f8712013-05-23 15:02:41 -0700845 }
Jean-Michel Trivif26f0172012-04-25 16:23:20 -0700846
Marco Nelissenfb6df0b2017-02-15 15:25:24 -0800847 intentFilter.addAction(AudioEffect.ACTION_OPEN_AUDIO_EFFECT_CONTROL_SESSION);
848 intentFilter.addAction(AudioEffect.ACTION_CLOSE_AUDIO_EFFECT_CONTROL_SESSION);
849
Fyodor Kupolovb5013302015-04-17 17:59:14 -0700850 context.registerReceiverAsUser(mReceiver, UserHandle.ALL, intentFilter, null, null);
Jared Suttles59820132009-08-13 21:50:52 -0500851
RoboErik0dac35a2014-08-12 15:48:49 -0700852 LocalServices.addService(AudioManagerInternal.class, new AudioServiceInternal());
Makoto Onukid45a4a22015-11-02 17:17:38 -0800853
854 mUserManagerInternal.addUserRestrictionsListener(mUserRestrictionsListener);
Jean-Michel Trivid3c71f02015-12-07 11:59:31 -0800855
856 mRecordMonitor.initMonitor();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800857 }
858
Eric Laurent4a5eeb92014-05-06 10:49:04 -0700859 public void systemReady() {
860 sendMsg(mAudioHandler, MSG_SYSTEM_READY, SENDMSG_QUEUE,
861 0, 0, null, 0);
Dianne Hackborn3e3600e2017-08-31 11:15:26 -0700862 if (false) {
863 // This is turned off for now, because it is racy and thus causes apps to break.
864 // Currently banning a uid means that if an app tries to start playing an audio
865 // stream, that will be preventing, and unbanning it will not allow that stream
866 // to resume. However these changes in uid state are racy with what the app is doing,
867 // so that after taking a process out of the cached state we can't guarantee that
868 // we will unban the uid before the app actually tries to start playing audio.
869 // (To do that, the activity manager would need to wait until it knows for sure
870 // that the ban has been removed, before telling the app to do whatever it is
871 // supposed to do that caused it to go out of the cached state.)
872 try {
873 ActivityManager.getService().registerUidObserver(mUidObserver,
874 ActivityManager.UID_OBSERVER_CACHED | ActivityManager.UID_OBSERVER_GONE,
875 ActivityManager.PROCESS_STATE_UNKNOWN, null);
876 } catch (RemoteException e) {
877 // ignored; both services live in system_server
878 }
Dianne Hackborn3e99f652017-07-05 16:33:56 -0700879 }
Eric Laurent4a5eeb92014-05-06 10:49:04 -0700880 }
881
882 public void onSystemReady() {
883 mSystemReady = true;
884 sendMsg(mAudioHandler, MSG_LOAD_SOUND_EFFECTS, SENDMSG_QUEUE,
885 0, 0, null, 0);
886
Eric Laurent4a5eeb92014-05-06 10:49:04 -0700887 mScoConnectionState = AudioManager.SCO_AUDIO_STATE_ERROR;
888 resetBluetoothSco();
889 getBluetoothHeadset();
890 //FIXME: this is to maintain compatibility with deprecated intent
891 // AudioManager.ACTION_SCO_AUDIO_STATE_CHANGED. Remove when appropriate.
892 Intent newIntent = new Intent(AudioManager.ACTION_SCO_AUDIO_STATE_CHANGED);
893 newIntent.putExtra(AudioManager.EXTRA_SCO_AUDIO_STATE,
894 AudioManager.SCO_AUDIO_STATE_DISCONNECTED);
895 sendStickyBroadcastToAll(newIntent);
896
897 BluetoothAdapter adapter = BluetoothAdapter.getDefaultAdapter();
898 if (adapter != null) {
899 adapter.getProfileProxy(mContext, mBluetoothProfileServiceListener,
900 BluetoothProfile.A2DP);
Jakub Pawlowskif9570f32018-02-21 17:15:12 -0800901 adapter.getProfileProxy(mContext, mBluetoothProfileServiceListener,
902 BluetoothProfile.HEARING_AID);
Eric Laurent4a5eeb92014-05-06 10:49:04 -0700903 }
904
Jeff Sharkey73ea0ae2016-08-10 17:30:38 -0600905 if (mContext.getPackageManager().hasSystemFeature(PackageManager.FEATURE_HDMI_CEC)) {
906 mHdmiManager = mContext.getSystemService(HdmiControlManager.class);
Eric Laurent212532b2014-07-21 15:43:18 -0700907 synchronized (mHdmiManager) {
908 mHdmiTvClient = mHdmiManager.getTvClient();
Jungshik Jangc9ff9682014-09-15 17:41:06 +0900909 if (mHdmiTvClient != null) {
910 mFixedVolumeDevices &= ~AudioSystem.DEVICE_ALL_HDMI_SYSTEM_AUDIO_AND_SPEAKER;
911 }
Eric Laurent212532b2014-07-21 15:43:18 -0700912 mHdmiPlaybackClient = mHdmiManager.getPlaybackClient();
913 mHdmiCecSink = false;
914 }
915 }
Wonsik Kim7f4342e2014-07-20 23:04:59 +0900916
Julia Reynolds48034f82016-03-09 10:15:16 -0500917 mNm = (NotificationManager) mContext.getSystemService(Context.NOTIFICATION_SERVICE);
918
Eric Laurent4a5eeb92014-05-06 10:49:04 -0700919 sendMsg(mAudioHandler,
920 MSG_CONFIGURE_SAFE_MEDIA_VOLUME_FORCED,
921 SENDMSG_REPLACE,
922 0,
923 0,
John Spurlock90874332015-03-10 16:00:54 -0400924 TAG,
Eric Laurent03332ab2017-02-09 18:29:15 -0800925 SystemProperties.getBoolean("audio.safemedia.bypass", false) ?
926 0 : SAFE_VOLUME_CONFIGURE_TIMEOUT_MS);
Jean-Michel Trivi873cc452014-09-11 17:25:09 -0700927
Jean-Michel Trivicfa55532017-01-18 11:17:51 -0800928 initA11yMonitoring();
Eric Laurent0867bed2015-05-20 14:49:08 -0700929 onIndicateSystemReady();
930 }
931
932 void onIndicateSystemReady() {
933 if (AudioSystem.systemReady() == AudioSystem.SUCCESS) {
934 return;
935 }
936 sendMsg(mAudioHandler,
937 MSG_INDICATE_SYSTEM_READY,
938 SENDMSG_REPLACE,
939 0,
940 0,
941 null,
942 INDICATE_SYSTEM_READY_RETRY_DELAY_MS);
943 }
944
Andy Hunged0ea402015-10-30 14:11:46 -0700945 public void onAudioServerDied() {
Eric Laurent0867bed2015-05-20 14:49:08 -0700946 if (!mSystemReady ||
947 (AudioSystem.checkAudioFlinger() != AudioSystem.AUDIO_STATUS_OK)) {
Andy Hunged0ea402015-10-30 14:11:46 -0700948 Log.e(TAG, "Audioserver died.");
949 sendMsg(mAudioHandler, MSG_AUDIO_SERVER_DIED, SENDMSG_NOOP, 0, 0,
Eric Laurent0867bed2015-05-20 14:49:08 -0700950 null, 500);
951 return;
952 }
Andy Hunged0ea402015-10-30 14:11:46 -0700953 Log.e(TAG, "Audioserver started.");
Eric Laurent0867bed2015-05-20 14:49:08 -0700954
955 // indicate to audio HAL that we start the reconfiguration phase after a media
956 // server crash
957 // Note that we only execute this when the media server
958 // process restarts after a crash, not the first time it is started.
959 AudioSystem.setParameters("restarting=true");
960
961 readAndSetLowRamDevice();
962
963 // Restore device connection states
964 synchronized (mConnectedDevices) {
965 for (int i = 0; i < mConnectedDevices.size(); i++) {
966 DeviceListSpec spec = mConnectedDevices.valueAt(i);
967 AudioSystem.setDeviceConnectionState(
968 spec.mDeviceType,
969 AudioSystem.DEVICE_STATE_AVAILABLE,
970 spec.mDeviceAddress,
971 spec.mDeviceName);
972 }
973 }
974 // Restore call state
Jean-Michel Trivi011f39e2017-08-19 18:08:06 -0700975 if (AudioSystem.setPhoneState(mMode) == AudioSystem.AUDIO_STATUS_OK) {
976 mModeLogger.log(new AudioEventLogger.StringEvent(
977 "onAudioServerDied causes setPhoneState(" + AudioSystem.modeToString(mMode) + ")"));
978 }
Eric Laurent0867bed2015-05-20 14:49:08 -0700979
Jean-Michel Trivi011f39e2017-08-19 18:08:06 -0700980 // Restore forced usage for communications and record
981 mForceUseLogger.log(new ForceUseEvent(AudioSystem.FOR_COMMUNICATION, mForcedUseForComm,
982 "onAudioServerDied"));
Eric Laurent0867bed2015-05-20 14:49:08 -0700983 AudioSystem.setForceUse(AudioSystem.FOR_COMMUNICATION, mForcedUseForComm);
Jean-Michel Trivi011f39e2017-08-19 18:08:06 -0700984 mForceUseLogger.log(new ForceUseEvent(AudioSystem.FOR_RECORD, mForcedUseForComm,
985 "onAudioServerDied"));
Eric Laurent0867bed2015-05-20 14:49:08 -0700986 AudioSystem.setForceUse(AudioSystem.FOR_RECORD, mForcedUseForComm);
Jean-Michel Trivi8719a1d2017-11-06 11:52:51 -0800987 final int forSys;
988 synchronized (mSettingsLock) {
989 forSys = mCameraSoundForced ?
990 AudioSystem.FORCE_SYSTEM_ENFORCED : AudioSystem.FORCE_NONE;
991 }
Jean-Michel Trivi011f39e2017-08-19 18:08:06 -0700992 mForceUseLogger.log(new ForceUseEvent(AudioSystem.FOR_SYSTEM, forSys,
993 "onAudioServerDied"));
994 AudioSystem.setForceUse(AudioSystem.FOR_SYSTEM, forSys);
Eric Laurent0867bed2015-05-20 14:49:08 -0700995
996 // Restore stream volumes
997 int numStreamTypes = AudioSystem.getNumStreamTypes();
998 for (int streamType = numStreamTypes - 1; streamType >= 0; streamType--) {
999 VolumeStreamState streamState = mStreamStates[streamType];
Eric Laurente4381ec2015-10-29 17:52:48 -07001000 AudioSystem.initStreamVolume(
1001 streamType, streamState.mIndexMin / 10, streamState.mIndexMax / 10);
Eric Laurent0867bed2015-05-20 14:49:08 -07001002
1003 streamState.applyAllVolumes();
1004 }
1005
Andy Hungf04b84d2015-12-18 17:33:27 -08001006 // Restore mono mode
Andy Hung7b98e9a2016-02-25 18:34:50 -08001007 updateMasterMono(mContentResolver);
Andy Hungf04b84d2015-12-18 17:33:27 -08001008
Eric Laurent0867bed2015-05-20 14:49:08 -07001009 // Restore ringer mode
1010 setRingerModeInt(getRingerModeInternal(), false);
1011
Mikhail Naganovb668bc62018-02-13 13:46:38 -08001012 // Reset device rotation (if monitored for this device)
Eric Laurent0867bed2015-05-20 14:49:08 -07001013 if (mMonitorRotation) {
Jean-Michel Trivi24806db2015-10-01 15:00:59 -07001014 RotationHelper.updateOrientation();
Eric Laurent0867bed2015-05-20 14:49:08 -07001015 }
1016
Sungsoocf09fe62016-09-28 16:21:48 +09001017 synchronized (mBluetoothA2dpEnabledLock) {
Jean-Michel Trivi011f39e2017-08-19 18:08:06 -07001018 final int forMed = mBluetoothA2dpEnabled ?
1019 AudioSystem.FORCE_NONE : AudioSystem.FORCE_NO_BT_A2DP;
1020 mForceUseLogger.log(new ForceUseEvent(AudioSystem.FOR_MEDIA, forMed,
1021 "onAudioServerDied"));
1022 AudioSystem.setForceUse(AudioSystem.FOR_MEDIA, forMed);
Sungsoocf09fe62016-09-28 16:21:48 +09001023 }
1024
Eric Laurent0867bed2015-05-20 14:49:08 -07001025 synchronized (mSettingsLock) {
Jean-Michel Trivi011f39e2017-08-19 18:08:06 -07001026 final int forDock = mDockAudioMediaEnabled ?
1027 AudioSystem.FORCE_ANALOG_DOCK : AudioSystem.FORCE_NONE;
1028 mForceUseLogger.log(new ForceUseEvent(AudioSystem.FOR_DOCK, forDock,
1029 "onAudioServerDied"));
1030 AudioSystem.setForceUse(AudioSystem.FOR_DOCK, forDock);
1031 sendEncodedSurroundMode(mContentResolver, "onAudioServerDied");
Eric Laurent0867bed2015-05-20 14:49:08 -07001032 }
1033 if (mHdmiManager != null) {
1034 synchronized (mHdmiManager) {
1035 if (mHdmiTvClient != null) {
1036 setHdmiSystemAudioSupported(mHdmiSystemAudioSupported);
1037 }
1038 }
1039 }
1040
1041 synchronized (mAudioPolicies) {
1042 for (AudioPolicyProxy policy : mAudioPolicies.values()) {
1043 policy.connectMixes();
1044 }
1045 }
1046
1047 onIndicateSystemReady();
1048 // indicate the end of reconfiguration phase to audio HAL
1049 AudioSystem.setParameters("restarting=false");
Eric Laurent1d3cdce2018-01-20 10:31:21 -08001050
1051 sendMsg(mAudioHandler, MSG_DISPATCH_AUDIO_SERVER_STATE,
1052 SENDMSG_QUEUE, 1, 0, null, 0);
1053 }
1054
1055 private void onDispatchAudioServerStateChange(boolean state) {
1056 synchronized (mAudioServerStateListeners) {
1057 for (AsdProxy asdp : mAudioServerStateListeners.values()) {
1058 try {
1059 asdp.callback().dispatchAudioServerStateChange(state);
1060 } catch (RemoteException e) {
1061 Log.w(TAG, "Could not call dispatchAudioServerStateChange()", e);
1062 }
1063 }
1064 }
Eric Laurent4a5eeb92014-05-06 10:49:04 -07001065 }
1066
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001067 private void createAudioSystemThread() {
1068 mAudioSystemThread = new AudioSystemThread();
1069 mAudioSystemThread.start();
1070 waitForAudioHandlerCreation();
1071 }
1072
1073 /** Waits for the volume handler to be created by the other thread. */
1074 private void waitForAudioHandlerCreation() {
1075 synchronized(this) {
1076 while (mAudioHandler == null) {
1077 try {
1078 // Wait for mAudioHandler to be set by the other thread
1079 wait();
1080 } catch (InterruptedException e) {
1081 Log.e(TAG, "Interrupted while waiting on volume handler.");
1082 }
1083 }
1084 }
1085 }
1086
Eric Laurent24482012012-05-10 09:41:17 -07001087 private void checkAllAliasStreamVolumes() {
Jean-Michel Trivi085346a2018-02-14 10:48:51 -08001088 synchronized (mSettingsLock) {
1089 synchronized (VolumeStreamState.class) {
1090 int numStreamTypes = AudioSystem.getNumStreamTypes();
1091 for (int streamType = 0; streamType < numStreamTypes; streamType++) {
1092 mStreamStates[streamType]
1093 .setAllIndexes(mStreamStates[mStreamVolumeAlias[streamType]], TAG);
1094 // apply stream volume
1095 if (!mStreamStates[streamType].mIsMuted) {
1096 mStreamStates[streamType].applyAllVolumes();
1097 }
Eric Laurent8fa4d6f2014-10-30 14:13:03 -07001098 }
Eric Laurent24482012012-05-10 09:41:17 -07001099 }
1100 }
1101 }
1102
Eric Laurent212532b2014-07-21 15:43:18 -07001103 private void checkAllFixedVolumeDevices()
1104 {
1105 int numStreamTypes = AudioSystem.getNumStreamTypes();
1106 for (int streamType = 0; streamType < numStreamTypes; streamType++) {
1107 mStreamStates[streamType].checkFixedVolumeDevices();
1108 }
1109 }
1110
Jean-Michel Triviba5270b2014-10-01 17:49:29 -07001111 private void checkAllFixedVolumeDevices(int streamType) {
1112 mStreamStates[streamType].checkFixedVolumeDevices();
1113 }
1114
John Spurlockb6e19e32015-03-10 21:33:44 -04001115 private void checkMuteAffectedStreams() {
1116 // any stream with a min level > 0 is not muteable by definition
Nadav Bar6b7751d2017-12-24 16:03:08 +02001117 // STREAM_VOICE_CALL can be muted by applications that has the the MODIFY_PHONE_STATE permission.
John Spurlockb6e19e32015-03-10 21:33:44 -04001118 for (int i = 0; i < mStreamStates.length; i++) {
1119 final VolumeStreamState vss = mStreamStates[i];
Nadav Bar6b7751d2017-12-24 16:03:08 +02001120 if (vss.mIndexMin > 0 &&
1121 vss.mStreamType != AudioSystem.STREAM_VOICE_CALL) {
John Spurlockb6e19e32015-03-10 21:33:44 -04001122 mMuteAffectedStreams &= ~(1 << vss.mStreamType);
1123 }
1124 }
1125 }
1126
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001127 private void createStreamStates() {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001128 int numStreamTypes = AudioSystem.getNumStreamTypes();
1129 VolumeStreamState[] streams = mStreamStates = new VolumeStreamState[numStreamTypes];
1130
1131 for (int i = 0; i < numStreamTypes; i++) {
Jean-Michel Trivia53b7052017-04-12 18:27:01 -07001132 streams[i] =
1133 new VolumeStreamState(System.VOLUME_SETTINGS_INT[mStreamVolumeAlias[i]], i);
Eric Laurenta553c252009-07-17 12:17:14 -07001134 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001135
Eric Laurent212532b2014-07-21 15:43:18 -07001136 checkAllFixedVolumeDevices();
Eric Laurent24482012012-05-10 09:41:17 -07001137 checkAllAliasStreamVolumes();
John Spurlockb6e19e32015-03-10 21:33:44 -04001138 checkMuteAffectedStreams();
Eric Laurent403bd342017-07-11 16:21:44 -07001139 updateDefaultVolumes();
1140 }
1141
1142 // Update default indexes from aliased streams. Must be called after mStreamStates is created
1143 private void updateDefaultVolumes() {
1144 for (int stream = 0; stream < mStreamStates.length; stream++) {
1145 if (stream != mStreamVolumeAlias[stream]) {
1146 AudioSystem.DEFAULT_STREAM_VOLUME[stream] = rescaleIndex(
1147 AudioSystem.DEFAULT_STREAM_VOLUME[mStreamVolumeAlias[stream]],
1148 mStreamVolumeAlias[stream],
1149 stream);
1150 }
1151 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001152 }
1153
Eric Laurentbffc3d12012-05-07 17:43:49 -07001154 private void dumpStreamStates(PrintWriter pw) {
1155 pw.println("\nStream volumes (device: index)");
1156 int numStreamTypes = AudioSystem.getNumStreamTypes();
1157 for (int i = 0; i < numStreamTypes; i++) {
John Spurlock61560172015-02-06 19:46:04 -05001158 pw.println("- " + AudioSystem.STREAM_NAMES[i] + ":");
Eric Laurentbffc3d12012-05-07 17:43:49 -07001159 mStreamStates[i].dump(pw);
1160 pw.println("");
1161 }
Eric Laurentdd45d012012-10-08 09:04:34 -07001162 pw.print("\n- mute affected streams = 0x");
1163 pw.println(Integer.toHexString(mMuteAffectedStreams));
Eric Laurentbffc3d12012-05-07 17:43:49 -07001164 }
1165
John Spurlock90874332015-03-10 16:00:54 -04001166 private void updateStreamVolumeAlias(boolean updateVolumes, String caller) {
Eric Laurent6d517662012-04-23 18:42:39 -07001167 int dtmfStreamAlias;
Jean-Michel Triviac487672016-11-11 10:05:18 -08001168 final int a11yStreamAlias = sIndependentA11yVolume ?
1169 AudioSystem.STREAM_ACCESSIBILITY : AudioSystem.STREAM_MUSIC;
Eric Laurent212532b2014-07-21 15:43:18 -07001170
Muyuan Li1ed6df62016-06-18 11:16:52 -07001171 if (mIsSingleVolume) {
Eric Laurent212532b2014-07-21 15:43:18 -07001172 mStreamVolumeAlias = STREAM_VOLUME_ALIAS_TELEVISION;
1173 dtmfStreamAlias = AudioSystem.STREAM_MUSIC;
Muyuan Li1ed6df62016-06-18 11:16:52 -07001174 } else {
1175 switch (mPlatformType) {
1176 case AudioSystem.PLATFORM_VOICE:
1177 mStreamVolumeAlias = STREAM_VOLUME_ALIAS_VOICE;
1178 dtmfStreamAlias = AudioSystem.STREAM_RING;
1179 break;
1180 default:
1181 mStreamVolumeAlias = STREAM_VOLUME_ALIAS_DEFAULT;
1182 dtmfStreamAlias = AudioSystem.STREAM_MUSIC;
1183 }
Eric Laurent6d517662012-04-23 18:42:39 -07001184 }
Eric Laurent212532b2014-07-21 15:43:18 -07001185
Muyuan Li1ed6df62016-06-18 11:16:52 -07001186 if (mIsSingleVolume) {
Eric Laurent212532b2014-07-21 15:43:18 -07001187 mRingerModeAffectedStreams = 0;
Eric Laurent24e0d9b2013-10-03 18:15:07 -07001188 } else {
Eric Laurent212532b2014-07-21 15:43:18 -07001189 if (isInCommunication()) {
1190 dtmfStreamAlias = AudioSystem.STREAM_VOICE_CALL;
1191 mRingerModeAffectedStreams &= ~(1 << AudioSystem.STREAM_DTMF);
1192 } else {
1193 mRingerModeAffectedStreams |= (1 << AudioSystem.STREAM_DTMF);
1194 }
Eric Laurent6d517662012-04-23 18:42:39 -07001195 }
Eric Laurent212532b2014-07-21 15:43:18 -07001196
Eric Laurent6d517662012-04-23 18:42:39 -07001197 mStreamVolumeAlias[AudioSystem.STREAM_DTMF] = dtmfStreamAlias;
Jean-Michel Trivi170a0ee2017-04-14 18:13:26 -07001198 mStreamVolumeAlias[AudioSystem.STREAM_ACCESSIBILITY] = a11yStreamAlias;
Jean-Michel Triviac487672016-11-11 10:05:18 -08001199
Eric Laurent403bd342017-07-11 16:21:44 -07001200 if (updateVolumes && mStreamStates != null) {
1201 updateDefaultVolumes();
1202
Jean-Michel Trivi085346a2018-02-14 10:48:51 -08001203 synchronized (mSettingsLock) {
1204 synchronized (VolumeStreamState.class) {
1205 mStreamStates[AudioSystem.STREAM_DTMF]
1206 .setAllIndexes(mStreamStates[dtmfStreamAlias], caller);
1207 mStreamStates[AudioSystem.STREAM_ACCESSIBILITY].mVolumeIndexSettingName =
1208 System.VOLUME_SETTINGS_INT[a11yStreamAlias];
1209 mStreamStates[AudioSystem.STREAM_ACCESSIBILITY].setAllIndexes(
1210 mStreamStates[a11yStreamAlias], caller);
Jean-Michel Trivie05eef82018-03-08 18:56:34 -08001211 mStreamStates[AudioSystem.STREAM_ACCESSIBILITY].refreshRange(
1212 mStreamVolumeAlias[AudioSystem.STREAM_ACCESSIBILITY]);
Jean-Michel Trivi085346a2018-02-14 10:48:51 -08001213 }
1214 }
Jean-Michel Trivi170a0ee2017-04-14 18:13:26 -07001215 if (sIndependentA11yVolume) {
1216 // restore the a11y values from the settings
1217 mStreamStates[AudioSystem.STREAM_ACCESSIBILITY].readSettings();
1218 }
1219
Eric Laurent24e0d9b2013-10-03 18:15:07 -07001220 // apply stream mute states according to new value of mRingerModeAffectedStreams
John Spurlock661f2cf2014-11-17 10:29:10 -05001221 setRingerModeInt(getRingerModeInternal(), false);
Eric Laurent6d517662012-04-23 18:42:39 -07001222 sendMsg(mAudioHandler,
1223 MSG_SET_ALL_VOLUMES,
1224 SENDMSG_QUEUE,
1225 0,
1226 0,
1227 mStreamStates[AudioSystem.STREAM_DTMF], 0);
Jean-Michel Triviac487672016-11-11 10:05:18 -08001228 sendMsg(mAudioHandler,
1229 MSG_SET_ALL_VOLUMES,
1230 SENDMSG_QUEUE,
1231 0,
1232 0,
1233 mStreamStates[AudioSystem.STREAM_ACCESSIBILITY], 0);
Eric Laurent6d517662012-04-23 18:42:39 -07001234 }
1235 }
1236
Eric Laurent7ee1e4f2012-10-26 18:11:21 -07001237 private void readDockAudioSettings(ContentResolver cr)
1238 {
1239 mDockAudioMediaEnabled = Settings.Global.getInt(
Eric Laurent5ba0ffa02012-10-29 12:31:09 -07001240 cr, Settings.Global.DOCK_AUDIO_MEDIA_ENABLED, 0) == 1;
Eric Laurent7ee1e4f2012-10-26 18:11:21 -07001241
Eric Laurent7ee1e4f2012-10-26 18:11:21 -07001242 sendMsg(mAudioHandler,
1243 MSG_SET_FORCE_USE,
1244 SENDMSG_QUEUE,
1245 AudioSystem.FOR_DOCK,
1246 mDockAudioMediaEnabled ?
1247 AudioSystem.FORCE_ANALOG_DOCK : AudioSystem.FORCE_NONE,
Jean-Michel Trivi011f39e2017-08-19 18:08:06 -07001248 new String("readDockAudioSettings"),
Eric Laurent7ee1e4f2012-10-26 18:11:21 -07001249 0);
1250 }
1251
Phil Burkac0f7042016-02-24 12:19:08 -08001252
Andy Hung7b98e9a2016-02-25 18:34:50 -08001253 private void updateMasterMono(ContentResolver cr)
1254 {
1255 final boolean masterMono = System.getIntForUser(
1256 cr, System.MASTER_MONO, 0 /* default */, UserHandle.USER_CURRENT) == 1;
1257 if (DEBUG_VOL) {
1258 Log.d(TAG, String.format("Master mono %b", masterMono));
1259 }
1260 AudioSystem.setMasterMono(masterMono);
1261 }
1262
Jean-Michel Trivi011f39e2017-08-19 18:08:06 -07001263 private void sendEncodedSurroundMode(ContentResolver cr, String eventSource)
Phil Burkac0f7042016-02-24 12:19:08 -08001264 {
1265 int encodedSurroundMode = Settings.Global.getInt(
1266 cr, Settings.Global.ENCODED_SURROUND_OUTPUT,
1267 Settings.Global.ENCODED_SURROUND_OUTPUT_AUTO);
Jean-Michel Trivi011f39e2017-08-19 18:08:06 -07001268 sendEncodedSurroundMode(encodedSurroundMode, eventSource);
Phil Burkac0f7042016-02-24 12:19:08 -08001269 }
1270
Jean-Michel Trivi011f39e2017-08-19 18:08:06 -07001271 private void sendEncodedSurroundMode(int encodedSurroundMode, String eventSource)
Phil Burkac0f7042016-02-24 12:19:08 -08001272 {
1273 // initialize to guaranteed bad value
1274 int forceSetting = AudioSystem.NUM_FORCE_CONFIG;
1275 switch (encodedSurroundMode) {
1276 case Settings.Global.ENCODED_SURROUND_OUTPUT_AUTO:
1277 forceSetting = AudioSystem.FORCE_NONE;
1278 break;
1279 case Settings.Global.ENCODED_SURROUND_OUTPUT_NEVER:
1280 forceSetting = AudioSystem.FORCE_ENCODED_SURROUND_NEVER;
1281 break;
1282 case Settings.Global.ENCODED_SURROUND_OUTPUT_ALWAYS:
1283 forceSetting = AudioSystem.FORCE_ENCODED_SURROUND_ALWAYS;
1284 break;
1285 default:
1286 Log.e(TAG, "updateSurroundSoundSettings: illegal value "
1287 + encodedSurroundMode);
1288 break;
1289 }
1290 if (forceSetting != AudioSystem.NUM_FORCE_CONFIG) {
1291 sendMsg(mAudioHandler,
1292 MSG_SET_FORCE_USE,
1293 SENDMSG_QUEUE,
1294 AudioSystem.FOR_ENCODED_SURROUND,
1295 forceSetting,
Jean-Michel Trivi011f39e2017-08-19 18:08:06 -07001296 eventSource,
Phil Burkac0f7042016-02-24 12:19:08 -08001297 0);
1298 }
1299 }
1300
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001301 private void readPersistedSettings() {
1302 final ContentResolver cr = mContentResolver;
1303
Eric Laurentbffc3d12012-05-07 17:43:49 -07001304 int ringerModeFromSettings =
Jeff Sharkey8d9a1f62012-10-18 15:38:14 -07001305 Settings.Global.getInt(
1306 cr, Settings.Global.MODE_RINGER, AudioManager.RINGER_MODE_NORMAL);
Eric Laurentbffc3d12012-05-07 17:43:49 -07001307 int ringerMode = ringerModeFromSettings;
Eric Laurent72668b22011-07-19 16:04:27 -07001308 // sanity check in case the settings are restored from a device with incompatible
1309 // ringer modes
John Spurlock97559372014-10-24 16:27:36 -04001310 if (!isValidRingerMode(ringerMode)) {
Glenn Kastenba195eb2011-12-13 09:30:40 -08001311 ringerMode = AudioManager.RINGER_MODE_NORMAL;
Eric Laurentbffc3d12012-05-07 17:43:49 -07001312 }
1313 if ((ringerMode == AudioManager.RINGER_MODE_VIBRATE) && !mHasVibrator) {
1314 ringerMode = AudioManager.RINGER_MODE_SILENT;
1315 }
1316 if (ringerMode != ringerModeFromSettings) {
Jeff Sharkey8d9a1f62012-10-18 15:38:14 -07001317 Settings.Global.putInt(cr, Settings.Global.MODE_RINGER, ringerMode);
Glenn Kastenba195eb2011-12-13 09:30:40 -08001318 }
Muyuan Li1ed6df62016-06-18 11:16:52 -07001319 if (mUseFixedVolume || mIsSingleVolume) {
Eric Laurent83a017b2013-03-19 18:15:31 -07001320 ringerMode = AudioManager.RINGER_MODE_NORMAL;
1321 }
Glenn Kastenba195eb2011-12-13 09:30:40 -08001322 synchronized(mSettingsLock) {
1323 mRingerMode = ringerMode;
John Spurlock661f2cf2014-11-17 10:29:10 -05001324 if (mRingerModeExternal == -1) {
1325 mRingerModeExternal = mRingerMode;
1326 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001327
Eric Laurentdd45d012012-10-08 09:04:34 -07001328 // System.VIBRATE_ON is not used any more but defaults for mVibrateSetting
1329 // are still needed while setVibrateSetting() and getVibrateSetting() are being
1330 // deprecated.
John Spurlock61560172015-02-06 19:46:04 -05001331 mVibrateSetting = AudioSystem.getValueForVibrateSetting(0,
Eric Laurentdd45d012012-10-08 09:04:34 -07001332 AudioManager.VIBRATE_TYPE_NOTIFICATION,
1333 mHasVibrator ? AudioManager.VIBRATE_SETTING_ONLY_SILENT
1334 : AudioManager.VIBRATE_SETTING_OFF);
John Spurlock61560172015-02-06 19:46:04 -05001335 mVibrateSetting = AudioSystem.getValueForVibrateSetting(mVibrateSetting,
Eric Laurentdd45d012012-10-08 09:04:34 -07001336 AudioManager.VIBRATE_TYPE_RINGER,
1337 mHasVibrator ? AudioManager.VIBRATE_SETTING_ONLY_SILENT
1338 : AudioManager.VIBRATE_SETTING_OFF);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001339
Beverlyd6964762018-02-16 14:07:03 -05001340 updateRingerAndZenModeAffectedStreams();
Eric Laurent7ee1e4f2012-10-26 18:11:21 -07001341 readDockAudioSettings(cr);
Jean-Michel Trivi011f39e2017-08-19 18:08:06 -07001342 sendEncodedSurroundMode(cr, "readPersistedSettings");
Eric Laurent402f7f22011-02-04 12:30:32 -08001343 }
Eric Laurentc1d41662011-07-19 11:21:13 -07001344
Eric Laurentbc0fab1f2012-09-19 11:24:41 -07001345 mMuteAffectedStreams = System.getIntForUser(cr,
John Spurlock61560172015-02-06 19:46:04 -05001346 System.MUTE_STREAMS_AFFECTED, AudioSystem.DEFAULT_MUTE_STREAMS_AFFECTED,
John Spurlock24c05182015-02-05 12:30:36 -05001347 UserHandle.USER_CURRENT);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001348
Andy Hung7b98e9a2016-02-25 18:34:50 -08001349 updateMasterMono(cr);
Andy Hungf04b84d2015-12-18 17:33:27 -08001350
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001351 // Each stream will read its own persisted settings
1352
John Spurlockbcc10872014-11-28 15:29:21 -05001353 // Broadcast the sticky intents
1354 broadcastRingerMode(AudioManager.RINGER_MODE_CHANGED_ACTION, mRingerModeExternal);
1355 broadcastRingerMode(AudioManager.INTERNAL_RINGER_MODE_CHANGED_ACTION, mRingerMode);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001356
1357 // Broadcast vibrate settings
1358 broadcastVibrateSetting(AudioManager.VIBRATE_TYPE_RINGER);
1359 broadcastVibrateSetting(AudioManager.VIBRATE_TYPE_NOTIFICATION);
Jean-Michel Trivid589fea2011-04-15 11:28:10 -07001360
John Spurlock33f4e042014-07-11 13:10:58 -04001361 // Load settings for the volume controller
1362 mVolumeController.loadSettings(cr);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001363 }
1364
Eric Laurentc0232482016-03-15 18:19:23 -07001365 private void readUserRestrictions() {
1366 final int currentUser = getCurrentUserId();
1367
1368 // Check the current user restriction.
Tony Makc1205112016-07-22 16:02:59 +01001369 boolean masterMute =
1370 mUserManagerInternal.getUserRestriction(currentUser,
Esteban Talavera492b4722017-02-13 14:59:45 +00001371 UserManager.DISALLOW_UNMUTE_DEVICE)
Tony Makc1205112016-07-22 16:02:59 +01001372 || mUserManagerInternal.getUserRestriction(currentUser,
1373 UserManager.DISALLOW_ADJUST_VOLUME);
Eric Laurentc0232482016-03-15 18:19:23 -07001374 if (mUseFixedVolume) {
1375 masterMute = false;
1376 AudioSystem.setMasterVolume(1.0f);
1377 }
1378 if (DEBUG_VOL) {
1379 Log.d(TAG, String.format("Master mute %s, user=%d", masterMute, currentUser));
1380 }
1381 setSystemAudioMute(masterMute);
1382 AudioSystem.setMasterMute(masterMute);
1383 broadcastMasterMuteStatus(masterMute);
1384
1385 boolean microphoneMute = mUserManagerInternal.getUserRestriction(
1386 currentUser, UserManager.DISALLOW_UNMUTE_MICROPHONE);
1387 if (DEBUG_VOL) {
1388 Log.d(TAG, String.format("Mic mute %s, user=%d", microphoneMute, currentUser));
1389 }
1390 AudioSystem.muteMicrophone(microphoneMute);
1391 }
1392
Eric Laurenta553c252009-07-17 12:17:14 -07001393 private int rescaleIndex(int index, int srcStream, int dstStream) {
Jean-Michel Trivie05eef82018-03-08 18:56:34 -08001394 final int rescaled =
1395 (index * mStreamStates[dstStream].getMaxIndex()
1396 + mStreamStates[srcStream].getMaxIndex() / 2)
1397 / mStreamStates[srcStream].getMaxIndex();
1398 if (rescaled < mStreamStates[dstStream].getMinIndex()) {
1399 return mStreamStates[dstStream].getMinIndex();
1400 } else {
1401 return rescaled;
1402 }
Eric Laurenta553c252009-07-17 12:17:14 -07001403 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001404
1405 ///////////////////////////////////////////////////////////////////////////
1406 // IPC methods
1407 ///////////////////////////////////////////////////////////////////////////
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001408 /** @see AudioManager#adjustVolume(int, int) */
Dianne Hackbornba50b97c2013-04-30 15:04:46 -07001409 public void adjustSuggestedStreamVolume(int direction, int suggestedStreamType, int flags,
John Spurlock90874332015-03-10 16:00:54 -04001410 String callingPackage, String caller) {
Jean-Michel Trivi610aa9b2018-01-27 15:42:42 -08001411 final IAudioPolicyCallback extVolCtlr;
1412 synchronized (mExtVolumeControllerLock) {
1413 extVolCtlr = mExtVolumeController;
1414 }
1415 if (extVolCtlr != null) {
Jean-Michel Trivi7ed71472018-02-02 16:52:09 -08001416 sendMsg(mAudioHandler, MSG_NOTIFY_VOL_EVENT, SENDMSG_QUEUE,
1417 direction, 0 /*ignored*/,
1418 extVolCtlr, 0 /*delay*/);
Jean-Michel Trivi610aa9b2018-01-27 15:42:42 -08001419 } else {
1420 adjustSuggestedStreamVolume(direction, suggestedStreamType, flags, callingPackage,
1421 caller, Binder.getCallingUid());
1422 }
RoboErik272e1612014-09-05 11:39:29 -07001423 }
1424
1425 private void adjustSuggestedStreamVolume(int direction, int suggestedStreamType, int flags,
John Spurlock90874332015-03-10 16:00:54 -04001426 String callingPackage, String caller, int uid) {
1427 if (DEBUG_VOL) Log.d(TAG, "adjustSuggestedStreamVolume() stream=" + suggestedStreamType
Jean-Michel Trivia7880d42017-04-15 12:41:05 -07001428 + ", flags=" + flags + ", caller=" + caller
1429 + ", volControlStream=" + mVolumeControlStream
1430 + ", userSelect=" + mUserSelectedVolumeControlStream);
Jean-Michel Trivicf170362017-08-24 17:24:57 -07001431 mVolumeLogger.log(new VolumeEvent(VolumeEvent.VOL_ADJUST_SUGG_VOL, suggestedStreamType,
1432 direction/*val1*/, flags/*val2*/, new StringBuilder(callingPackage)
1433 .append("/").append(caller).append(" uid:").append(uid).toString()));
Jean-Michel Trivia7880d42017-04-15 12:41:05 -07001434 final int streamType;
jiabin8fd5d5e2018-03-23 14:09:28 -07001435 synchronized (mForceControlStreamLock) {
1436 // Request lock in case mVolumeControlStream is changed by other thread.
1437 if (mUserSelectedVolumeControlStream) { // implies mVolumeControlStream != -1
Jean-Michel Trivia7880d42017-04-15 12:41:05 -07001438 streamType = mVolumeControlStream;
jiabin8fd5d5e2018-03-23 14:09:28 -07001439 } else {
1440 final int maybeActiveStreamType = getActiveStreamType(suggestedStreamType);
1441 final boolean activeForReal;
1442 if (maybeActiveStreamType == AudioSystem.STREAM_RING
1443 || maybeActiveStreamType == AudioSystem.STREAM_NOTIFICATION) {
1444 activeForReal = wasStreamActiveRecently(maybeActiveStreamType, 0);
1445 } else {
1446 activeForReal = AudioSystem.isStreamActive(maybeActiveStreamType, 0);
1447 }
1448 if (activeForReal || mVolumeControlStream == -1) {
1449 streamType = maybeActiveStreamType;
1450 } else {
1451 streamType = mVolumeControlStream;
1452 }
Jean-Michel Trivia7880d42017-04-15 12:41:05 -07001453 }
Eric Laurent402f7f22011-02-04 12:30:32 -08001454 }
Jean-Michel Trivia7880d42017-04-15 12:41:05 -07001455
1456 final boolean isMute = isMuteAdjust(direction);
1457
John Spurlock0a376af2015-03-26 16:24:12 -04001458 ensureValidStreamType(streamType);
John Spurlock33f4e042014-07-11 13:10:58 -04001459 final int resolvedStream = mStreamVolumeAlias[streamType];
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001460
RoboErik2811dd32014-08-12 09:48:13 -07001461 // Play sounds on STREAM_RING only.
1462 if ((flags & AudioManager.FLAG_PLAY_SOUND) != 0 &&
John Spurlock33f4e042014-07-11 13:10:58 -04001463 resolvedStream != AudioSystem.STREAM_RING) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001464 flags &= ~AudioManager.FLAG_PLAY_SOUND;
1465 }
1466
John Spurlock33f4e042014-07-11 13:10:58 -04001467 // For notifications/ring, show the ui before making any adjustments
RoboErik4197cb62015-01-21 15:45:32 -08001468 // Don't suppress mute/unmute requests
1469 if (mVolumeController.suppressAdjustment(resolvedStream, flags, isMute)) {
John Spurlock33f4e042014-07-11 13:10:58 -04001470 direction = 0;
1471 flags &= ~AudioManager.FLAG_PLAY_SOUND;
1472 flags &= ~AudioManager.FLAG_VIBRATE;
1473 if (DEBUG_VOL) Log.d(TAG, "Volume controller suppressed adjustment");
1474 }
1475
John Spurlock90874332015-03-10 16:00:54 -04001476 adjustStreamVolume(streamType, direction, flags, callingPackage, caller, uid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001477 }
1478
1479 /** @see AudioManager#adjustStreamVolume(int, int, int) */
Dianne Hackbornba50b97c2013-04-30 15:04:46 -07001480 public void adjustStreamVolume(int streamType, int direction, int flags,
1481 String callingPackage) {
Phil Weaverf1a9aff2017-03-23 17:21:29 -07001482 if ((streamType == AudioManager.STREAM_ACCESSIBILITY) && !canChangeAccessibilityVolume()) {
Jean-Michel Triviab2d9312017-03-13 15:33:39 -07001483 Log.w(TAG, "Trying to call adjustStreamVolume() for a11y without"
Phil Weaverf1a9aff2017-03-23 17:21:29 -07001484 + "CHANGE_ACCESSIBILITY_VOLUME / callingPackage=" + callingPackage);
Jean-Michel Triviab2d9312017-03-13 15:33:39 -07001485 return;
1486 }
Jean-Michel Trivicf170362017-08-24 17:24:57 -07001487 mVolumeLogger.log(new VolumeEvent(VolumeEvent.VOL_ADJUST_STREAM_VOL, streamType,
1488 direction/*val1*/, flags/*val2*/, callingPackage));
John Spurlock90874332015-03-10 16:00:54 -04001489 adjustStreamVolume(streamType, direction, flags, callingPackage, callingPackage,
1490 Binder.getCallingUid());
RoboErik0dac35a2014-08-12 15:48:49 -07001491 }
1492
Chinyue Chen6affe932018-01-24 14:51:43 +08001493 protected void adjustStreamVolume(int streamType, int direction, int flags,
John Spurlock90874332015-03-10 16:00:54 -04001494 String callingPackage, String caller, int uid) {
Eric Laurent83a017b2013-03-19 18:15:31 -07001495 if (mUseFixedVolume) {
1496 return;
1497 }
John Spurlock90874332015-03-10 16:00:54 -04001498 if (DEBUG_VOL) Log.d(TAG, "adjustStreamVolume() stream=" + streamType + ", dir=" + direction
1499 + ", flags=" + flags + ", caller=" + caller);
Jean-Michel Trivi3114ce32012-06-11 15:03:52 -07001500
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001501 ensureValidDirection(direction);
1502 ensureValidStreamType(streamType);
1503
RoboErik4197cb62015-01-21 15:45:32 -08001504 boolean isMuteAdjust = isMuteAdjust(direction);
1505
John Spurlock3ce37252015-02-17 13:20:45 -05001506 if (isMuteAdjust && !isStreamAffectedByMute(streamType)) {
1507 return;
1508 }
1509
Nadav Bar6b7751d2017-12-24 16:03:08 +02001510 // If adjust is mute and the stream is STREAM_VOICE_CALL, make sure
1511 // that the calling app have the MODIFY_PHONE_STATE permission.
1512 if (isMuteAdjust &&
1513 streamType == AudioSystem.STREAM_VOICE_CALL &&
1514 mContext.checkCallingOrSelfPermission(
1515 android.Manifest.permission.MODIFY_PHONE_STATE)
1516 != PackageManager.PERMISSION_GRANTED) {
1517 Log.w(TAG, "MODIFY_PHONE_STATE Permission Denial: adjustStreamVolume from pid="
1518 + Binder.getCallingPid() + ", uid=" + Binder.getCallingUid());
1519 return;
1520 }
1521
Eric Laurent96a33d12011-11-08 10:31:57 -08001522 // use stream type alias here so that streams with same alias have the same behavior,
1523 // including with regard to silent mode control (e.g the use of STREAM_RING below and in
1524 // checkForRingerModeChange() in place of STREAM_RING or STREAM_NOTIFICATION)
Eric Laurent6d517662012-04-23 18:42:39 -07001525 int streamTypeAlias = mStreamVolumeAlias[streamType];
RoboErik4197cb62015-01-21 15:45:32 -08001526
Eric Laurentb024c302011-10-14 17:19:27 -07001527 VolumeStreamState streamState = mStreamStates[streamTypeAlias];
Eric Laurent9bc8358d2011-11-18 16:43:31 -08001528
1529 final int device = getDeviceForStream(streamTypeAlias);
Eric Laurent3ef75492012-11-28 12:12:23 -08001530
Eric Laurent42b041e2013-03-29 11:36:03 -07001531 int aliasIndex = streamState.getIndex(device);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001532 boolean adjustVolume = true;
Eric Laurent3ef75492012-11-28 12:12:23 -08001533 int step;
Eric Laurent24482012012-05-10 09:41:17 -07001534
Matthew Xiec9d1d5f2013-09-12 00:32:22 -07001535 // skip a2dp absolute volume control request when the device
1536 // is not an a2dp device
1537 if ((device & AudioSystem.DEVICE_OUT_ALL_A2DP) == 0 &&
1538 (flags & AudioManager.FLAG_BLUETOOTH_ABS_VOLUME) != 0) {
1539 return;
1540 }
1541
Kenny Guy70e0c582015-06-30 19:18:28 +01001542 // If we are being called by the system (e.g. hardware keys) check for current user
1543 // so we handle user restrictions correctly.
1544 if (uid == android.os.Process.SYSTEM_UID) {
1545 uid = UserHandle.getUid(getCurrentUserId(), UserHandle.getAppId(uid));
1546 }
John Spurlock59dc9c12015-03-02 11:20:15 -05001547 if (mAppOps.noteOp(STREAM_VOLUME_OPS[streamTypeAlias], uid, callingPackage)
RoboErik0dac35a2014-08-12 15:48:49 -07001548 != AppOpsManager.MODE_ALLOWED) {
Dianne Hackbornba50b97c2013-04-30 15:04:46 -07001549 return;
1550 }
1551
Eric Laurentfde16d52012-12-03 14:42:39 -08001552 // reset any pending volume command
1553 synchronized (mSafeMediaVolumeState) {
1554 mPendingVolumeCommand = null;
1555 }
1556
Eric Laurent3ef75492012-11-28 12:12:23 -08001557 flags &= ~AudioManager.FLAG_FIXED_VOLUME;
1558 if ((streamTypeAlias == AudioSystem.STREAM_MUSIC) &&
1559 ((device & mFixedVolumeDevices) != 0)) {
1560 flags |= AudioManager.FLAG_FIXED_VOLUME;
1561
1562 // Always toggle between max safe volume and 0 for fixed volume devices where safe
1563 // volume is enforced, and max and 0 for the others.
1564 // This is simulated by stepping by the full allowed volume range
1565 if (mSafeMediaVolumeState == SAFE_MEDIA_VOLUME_ACTIVE &&
1566 (device & mSafeMediaVolumeDevices) != 0) {
Eric Laurenteab40d12017-06-09 12:45:21 -07001567 step = safeMediaVolumeIndex(device);
Eric Laurent3ef75492012-11-28 12:12:23 -08001568 } else {
1569 step = streamState.getMaxIndex();
1570 }
1571 if (aliasIndex != 0) {
1572 aliasIndex = step;
1573 }
1574 } else {
1575 // convert one UI step (+/-1) into a number of internal units on the stream alias
1576 step = rescaleIndex(10, streamType, streamTypeAlias);
1577 }
1578
Eric Laurent42b041e2013-03-29 11:36:03 -07001579 // If either the client forces allowing ringer modes for this adjustment,
1580 // or the stream type is one that is affected by ringer modes
1581 if (((flags & AudioManager.FLAG_ALLOW_RINGER_MODES) != 0) ||
John Spurlockee5ad722015-03-03 16:17:21 -05001582 (streamTypeAlias == getUiSoundsStreamType())) {
John Spurlock661f2cf2014-11-17 10:29:10 -05001583 int ringerMode = getRingerModeInternal();
Eric Laurent42b041e2013-03-29 11:36:03 -07001584 // do not vibrate if already in vibrate mode
1585 if (ringerMode == AudioManager.RINGER_MODE_VIBRATE) {
1586 flags &= ~AudioManager.FLAG_VIBRATE;
Eric Laurent3ef75492012-11-28 12:12:23 -08001587 }
RoboErik5452e252015-02-06 15:33:53 -08001588 // Check if the ringer mode handles this adjustment. If it does we don't
1589 // need to adjust the volume further.
John Spurlock50ced3f2015-05-11 16:00:09 -04001590 final int result = checkForRingerModeChange(aliasIndex, direction, step,
Julia Reynoldsed783792016-04-08 15:27:35 -04001591 streamState.mIsMuted, callingPackage, flags);
John Spurlocka11b4af2014-06-01 11:52:23 -04001592 adjustVolume = (result & FLAG_ADJUST_VOLUME) != 0;
1593 // If suppressing a volume adjustment in silent mode, display the UI hint
1594 if ((result & AudioManager.FLAG_SHOW_SILENT_HINT) != 0) {
1595 flags |= AudioManager.FLAG_SHOW_SILENT_HINT;
1596 }
John Spurlock661f2cf2014-11-17 10:29:10 -05001597 // If suppressing a volume down adjustment in vibrate mode, display the UI hint
1598 if ((result & AudioManager.FLAG_SHOW_VIBRATE_HINT) != 0) {
1599 flags |= AudioManager.FLAG_SHOW_VIBRATE_HINT;
1600 }
Eric Laurent42b041e2013-03-29 11:36:03 -07001601 }
Beverlyd6964762018-02-16 14:07:03 -05001602
1603 // If the ringer mode or zen is muting the stream, do not change stream unless
1604 // it'll cause us to exit dnd
Julia Reynoldsed783792016-04-08 15:27:35 -04001605 if (!volumeAdjustmentAllowedByDnd(streamTypeAlias, flags)) {
John Spurlock50ced3f2015-05-11 16:00:09 -04001606 adjustVolume = false;
1607 }
Eric Laurent42b041e2013-03-29 11:36:03 -07001608 int oldIndex = mStreamStates[streamType].getIndex(device);
Eric Laurent3ef75492012-11-28 12:12:23 -08001609
Eric Laurent42b041e2013-03-29 11:36:03 -07001610 if (adjustVolume && (direction != AudioManager.ADJUST_SAME)) {
RoboErik5452e252015-02-06 15:33:53 -08001611 mAudioHandler.removeMessages(MSG_UNMUTE_STREAM);
Matthew Xiec9d1d5f2013-09-12 00:32:22 -07001612
RoboErik4197cb62015-01-21 15:45:32 -08001613 if (isMuteAdjust) {
1614 boolean state;
1615 if (direction == AudioManager.ADJUST_TOGGLE_MUTE) {
1616 state = !streamState.mIsMuted;
1617 } else {
1618 state = direction == AudioManager.ADJUST_MUTE;
1619 }
1620 if (streamTypeAlias == AudioSystem.STREAM_MUSIC) {
1621 setSystemAudioMute(state);
1622 }
1623 for (int stream = 0; stream < mStreamStates.length; stream++) {
1624 if (streamTypeAlias == mStreamVolumeAlias[stream]) {
Sungmin Choi841ed0a2015-07-26 23:09:49 -07001625 if (!(readCameraSoundForced()
1626 && (mStreamStates[stream].getStreamType()
1627 == AudioSystem.STREAM_SYSTEM_ENFORCED))) {
1628 mStreamStates[stream].mute(state);
1629 }
RoboErik4197cb62015-01-21 15:45:32 -08001630 }
1631 }
1632 } else if ((direction == AudioManager.ADJUST_RAISE) &&
Eric Laurent42b041e2013-03-29 11:36:03 -07001633 !checkSafeMediaVolume(streamTypeAlias, aliasIndex + step, device)) {
RoboErik4197cb62015-01-21 15:45:32 -08001634 Log.e(TAG, "adjustStreamVolume() safe volume index = " + oldIndex);
John Spurlock3346a802014-05-20 16:25:37 -04001635 mVolumeController.postDisplaySafeVolumeWarning(flags);
John Spurlock90874332015-03-10 16:00:54 -04001636 } else if (streamState.adjustIndex(direction * step, device, caller)
1637 || streamState.mIsMuted) {
RoboErik4197cb62015-01-21 15:45:32 -08001638 // Post message to set system volume (it in turn will post a
1639 // message to persist).
1640 if (streamState.mIsMuted) {
1641 // Unmute the stream if it was previously muted
RoboErik5452e252015-02-06 15:33:53 -08001642 if (direction == AudioManager.ADJUST_RAISE) {
1643 // unmute immediately for volume up
1644 streamState.mute(false);
1645 } else if (direction == AudioManager.ADJUST_LOWER) {
Muyuan Li1ed6df62016-06-18 11:16:52 -07001646 if (mIsSingleVolume) {
John Spurlocka48d7792015-03-03 17:35:57 -05001647 sendMsg(mAudioHandler, MSG_UNMUTE_STREAM, SENDMSG_QUEUE,
1648 streamTypeAlias, flags, null, UNMUTE_STREAM_DELAY);
1649 }
RoboErik5452e252015-02-06 15:33:53 -08001650 }
RoboErik4197cb62015-01-21 15:45:32 -08001651 }
Eric Laurent42b041e2013-03-29 11:36:03 -07001652 sendMsg(mAudioHandler,
1653 MSG_SET_DEVICE_VOLUME,
1654 SENDMSG_QUEUE,
1655 device,
1656 0,
1657 streamState,
1658 0);
Eric Laurent4bbcc652012-09-24 14:26:30 -07001659 }
Jungshik Jang41d97462014-06-30 22:26:29 +09001660
Jungshik Jang41d97462014-06-30 22:26:29 +09001661 int newIndex = mStreamStates[streamType].getIndex(device);
Ajay Panickere3946c82018-02-26 16:04:15 -08001662
1663 // Check if volume update should be send to AVRCP
1664 if (streamTypeAlias == AudioSystem.STREAM_MUSIC &&
1665 (device & AudioSystem.DEVICE_OUT_ALL_A2DP) != 0 &&
1666 (flags & AudioManager.FLAG_BLUETOOTH_ABS_VOLUME) == 0) {
1667 synchronized (mA2dpAvrcpLock) {
1668 if (mA2dp != null && mAvrcpAbsVolSupported) {
1669 mA2dp.setAvrcpAbsoluteVolume(newIndex / 10);
1670 }
1671 }
1672 }
1673
Jakub Pawlowskif9570f32018-02-21 17:15:12 -08001674 // Check if volume update should be send to Hearing Aid
1675 if ((device & AudioSystem.DEVICE_OUT_HEARING_AID) != 0) {
Jakub Pawlowski21b7f492018-03-22 12:31:21 -07001676 setHearingAidVolume(newIndex, streamType);
Jakub Pawlowskif9570f32018-02-21 17:15:12 -08001677 }
1678
Ajay Panickere3946c82018-02-26 16:04:15 -08001679 // Check if volume update should be sent to Hdmi system audio.
Jinsuk Kim336cdb42014-11-29 06:27:00 +09001680 if (streamTypeAlias == AudioSystem.STREAM_MUSIC) {
1681 setSystemAudioVolume(oldIndex, newIndex, getStreamMaxVolume(streamType), flags);
1682 }
Eric Laurent212532b2014-07-21 15:43:18 -07001683 if (mHdmiManager != null) {
1684 synchronized (mHdmiManager) {
Eric Laurent212532b2014-07-21 15:43:18 -07001685 // mHdmiCecSink true => mHdmiPlaybackClient != null
1686 if (mHdmiCecSink &&
1687 streamTypeAlias == AudioSystem.STREAM_MUSIC &&
1688 oldIndex != newIndex) {
1689 synchronized (mHdmiPlaybackClient) {
1690 int keyCode = (direction == -1) ? KeyEvent.KEYCODE_VOLUME_DOWN :
RoboErik4197cb62015-01-21 15:45:32 -08001691 KeyEvent.KEYCODE_VOLUME_UP;
Donghyun Cho5f6d404e2016-03-17 20:39:25 +09001692 final long ident = Binder.clearCallingIdentity();
1693 try {
1694 mHdmiPlaybackClient.sendKeyEvent(keyCode, true);
1695 mHdmiPlaybackClient.sendKeyEvent(keyCode, false);
1696 } finally {
1697 Binder.restoreCallingIdentity(ident);
1698 }
Eric Laurent212532b2014-07-21 15:43:18 -07001699 }
Jungshik Jang41d97462014-06-30 22:26:29 +09001700 }
1701 }
1702 }
Eric Laurent4bbcc652012-09-24 14:26:30 -07001703 }
Eric Laurent42b041e2013-03-29 11:36:03 -07001704 int index = mStreamStates[streamType].getIndex(device);
Eric Laurent25101b02011-02-02 09:33:30 -08001705 sendVolumeUpdate(streamType, oldIndex, index, flags);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001706 }
1707
RoboErik5452e252015-02-06 15:33:53 -08001708 // Called after a delay when volume down is pressed while muted
1709 private void onUnmuteStream(int stream, int flags) {
1710 VolumeStreamState streamState = mStreamStates[stream];
1711 streamState.mute(false);
1712
1713 final int device = getDeviceForStream(stream);
1714 final int index = mStreamStates[stream].getIndex(device);
1715 sendVolumeUpdate(stream, index, index, flags);
1716 }
1717
Jinsuk Kim336cdb42014-11-29 06:27:00 +09001718 private void setSystemAudioVolume(int oldVolume, int newVolume, int maxVolume, int flags) {
1719 if (mHdmiManager == null
1720 || mHdmiTvClient == null
1721 || oldVolume == newVolume
1722 || (flags & AudioManager.FLAG_HDMI_SYSTEM_AUDIO_VOLUME) != 0) return;
1723
1724 // Sets the audio volume of AVR when we are in system audio mode. The new volume info
1725 // is tranformed to HDMI-CEC commands and passed through CEC bus.
1726 synchronized (mHdmiManager) {
1727 if (!mHdmiSystemAudioSupported) return;
1728 synchronized (mHdmiTvClient) {
Jinsuk Kim48cbf292014-12-13 02:16:28 +09001729 final long token = Binder.clearCallingIdentity();
1730 try {
Jinsuk Kim7a9ba422015-02-16 16:47:38 +09001731 mHdmiTvClient.setSystemAudioVolume(oldVolume, newVolume, maxVolume);
Jinsuk Kim48cbf292014-12-13 02:16:28 +09001732 } finally {
1733 Binder.restoreCallingIdentity(token);
1734 }
Jinsuk Kim336cdb42014-11-29 06:27:00 +09001735 }
1736 }
1737 }
1738
Eric Laurentfde16d52012-12-03 14:42:39 -08001739 // StreamVolumeCommand contains the information needed to defer the process of
1740 // setStreamVolume() in case the user has to acknowledge the safe volume warning message.
1741 class StreamVolumeCommand {
1742 public final int mStreamType;
1743 public final int mIndex;
1744 public final int mFlags;
1745 public final int mDevice;
Eric Laurent9ce379a2010-02-16 06:00:26 -08001746
Eric Laurentfde16d52012-12-03 14:42:39 -08001747 StreamVolumeCommand(int streamType, int index, int flags, int device) {
1748 mStreamType = streamType;
1749 mIndex = index;
1750 mFlags = flags;
1751 mDevice = device;
Eric Laurentb024c302011-10-14 17:19:27 -07001752 }
John Spurlock35134602014-07-24 18:10:48 -04001753
1754 @Override
1755 public String toString() {
1756 return new StringBuilder().append("{streamType=").append(mStreamType).append(",index=")
1757 .append(mIndex).append(",flags=").append(mFlags).append(",device=")
1758 .append(mDevice).append('}').toString();
1759 }
Eric Laurentfde16d52012-12-03 14:42:39 -08001760 };
Eric Laurent3ef75492012-11-28 12:12:23 -08001761
Julia Reynolds48034f82016-03-09 10:15:16 -05001762 private int getNewRingerMode(int stream, int index, int flags) {
Zak Cohen47798292017-11-30 12:34:20 -08001763 // setRingerMode does nothing if the device is single volume,so the value would be unchanged
1764 if (mIsSingleVolume) {
1765 return getRingerModeExternal();
1766 }
1767
John Spurlockee5ad722015-03-03 16:17:21 -05001768 // setting volume on ui sounds stream type also controls silent mode
Eric Laurent3ef75492012-11-28 12:12:23 -08001769 if (((flags & AudioManager.FLAG_ALLOW_RINGER_MODES) != 0) ||
John Spurlock75ae23c2015-06-02 16:26:43 -04001770 (stream == getUiSoundsStreamType())) {
Eric Laurent3ef75492012-11-28 12:12:23 -08001771 int newRingerMode;
1772 if (index == 0) {
1773 newRingerMode = mHasVibrator ? AudioManager.RINGER_MODE_VIBRATE
John Spurlocka48d7792015-03-03 17:35:57 -05001774 : mVolumePolicy.volumeDownToEnterSilent ? AudioManager.RINGER_MODE_SILENT
Julia Reynolds48034f82016-03-09 10:15:16 -05001775 : AudioManager.RINGER_MODE_NORMAL;
Eric Laurent3ef75492012-11-28 12:12:23 -08001776 } else {
1777 newRingerMode = AudioManager.RINGER_MODE_NORMAL;
1778 }
Julia Reynolds48034f82016-03-09 10:15:16 -05001779 return newRingerMode;
1780 }
1781 return getRingerModeExternal();
1782 }
1783
1784 private boolean isAndroidNPlus(String caller) {
1785 try {
1786 final ApplicationInfo applicationInfo =
1787 mContext.getPackageManager().getApplicationInfoAsUser(
1788 caller, 0, UserHandle.getUserId(Binder.getCallingUid()));
1789 if (applicationInfo.targetSdkVersion >= Build.VERSION_CODES.N) {
1790 return true;
1791 }
1792 return false;
1793 } catch (PackageManager.NameNotFoundException e) {
1794 return true;
1795 }
1796 }
1797
1798 private boolean wouldToggleZenMode(int newMode) {
1799 if (getRingerModeExternal() == AudioManager.RINGER_MODE_SILENT
1800 && newMode != AudioManager.RINGER_MODE_SILENT) {
1801 return true;
1802 } else if (getRingerModeExternal() != AudioManager.RINGER_MODE_SILENT
1803 && newMode == AudioManager.RINGER_MODE_SILENT) {
1804 return true;
1805 }
1806 return false;
1807 }
1808
1809 private void onSetStreamVolume(int streamType, int index, int flags, int device,
1810 String caller) {
1811 final int stream = mStreamVolumeAlias[streamType];
1812 setStreamVolumeInt(stream, index, device, false, caller);
1813 // setting volume on ui sounds stream type also controls silent mode
1814 if (((flags & AudioManager.FLAG_ALLOW_RINGER_MODES) != 0) ||
1815 (stream == getUiSoundsStreamType())) {
1816 setRingerMode(getNewRingerMode(stream, index, flags),
1817 TAG + ".onSetStreamVolume", false /*external*/);
Eric Laurent3ef75492012-11-28 12:12:23 -08001818 }
John Spurlock75ae23c2015-06-02 16:26:43 -04001819 // setting non-zero volume for a muted stream unmutes the stream and vice versa
1820 mStreamStates[stream].mute(index == 0);
Eric Laurentfde16d52012-12-03 14:42:39 -08001821 }
1822
1823 /** @see AudioManager#setStreamVolume(int, int, int) */
Dianne Hackbornba50b97c2013-04-30 15:04:46 -07001824 public void setStreamVolume(int streamType, int index, int flags, String callingPackage) {
Phil Weaverf1a9aff2017-03-23 17:21:29 -07001825 if ((streamType == AudioManager.STREAM_ACCESSIBILITY) && !canChangeAccessibilityVolume()) {
Jean-Michel Triviab2d9312017-03-13 15:33:39 -07001826 Log.w(TAG, "Trying to call setStreamVolume() for a11y without"
Phil Weaverf1a9aff2017-03-23 17:21:29 -07001827 + " CHANGE_ACCESSIBILITY_VOLUME callingPackage=" + callingPackage);
Jean-Michel Triviab2d9312017-03-13 15:33:39 -07001828 return;
1829 }
Nadav Bar6b7751d2017-12-24 16:03:08 +02001830 if ((streamType == AudioManager.STREAM_VOICE_CALL) &&
1831 (index == 0) &&
1832 (mContext.checkCallingOrSelfPermission(
1833 android.Manifest.permission.MODIFY_PHONE_STATE)
1834 != PackageManager.PERMISSION_GRANTED)) {
1835 Log.w(TAG, "Trying to call setStreamVolume() for STREAM_VOICE_CALL and index 0 without"
1836 + " MODIFY_PHONE_STATE callingPackage=" + callingPackage);
1837 return;
1838 }
Jean-Michel Trivicf170362017-08-24 17:24:57 -07001839 mVolumeLogger.log(new VolumeEvent(VolumeEvent.VOL_SET_STREAM_VOL, streamType,
1840 index/*val1*/, flags/*val2*/, callingPackage));
John Spurlock90874332015-03-10 16:00:54 -04001841 setStreamVolume(streamType, index, flags, callingPackage, callingPackage,
1842 Binder.getCallingUid());
RoboErik0dac35a2014-08-12 15:48:49 -07001843 }
1844
Phil Weaverf1a9aff2017-03-23 17:21:29 -07001845 private boolean canChangeAccessibilityVolume() {
1846 synchronized (mAccessibilityServiceUidsLock) {
1847 if (PackageManager.PERMISSION_GRANTED == mContext.checkCallingOrSelfPermission(
1848 android.Manifest.permission.CHANGE_ACCESSIBILITY_VOLUME)) {
1849 return true;
1850 }
1851 if (mAccessibilityServiceUids != null) {
1852 int callingUid = Binder.getCallingUid();
1853 for (int i = 0; i < mAccessibilityServiceUids.length; i++) {
1854 if (mAccessibilityServiceUids[i] == callingUid) {
1855 return true;
1856 }
1857 }
1858 }
1859 return false;
1860 }
1861 }
1862
RoboErik0dac35a2014-08-12 15:48:49 -07001863 private void setStreamVolume(int streamType, int index, int flags, String callingPackage,
John Spurlock90874332015-03-10 16:00:54 -04001864 String caller, int uid) {
Jean-Michel Triviac487672016-11-11 10:05:18 -08001865 if (DEBUG_VOL) {
1866 Log.d(TAG, "setStreamVolume(stream=" + streamType+", index=" + index
1867 + ", calling=" + callingPackage + ")");
1868 }
Eric Laurent83a017b2013-03-19 18:15:31 -07001869 if (mUseFixedVolume) {
1870 return;
1871 }
1872
Eric Laurentfde16d52012-12-03 14:42:39 -08001873 ensureValidStreamType(streamType);
Dianne Hackbornba50b97c2013-04-30 15:04:46 -07001874 int streamTypeAlias = mStreamVolumeAlias[streamType];
1875 VolumeStreamState streamState = mStreamStates[streamTypeAlias];
Eric Laurentfde16d52012-12-03 14:42:39 -08001876
1877 final int device = getDeviceForStream(streamType);
1878 int oldIndex;
1879
Matthew Xiec9d1d5f2013-09-12 00:32:22 -07001880 // skip a2dp absolute volume control request when the device
1881 // is not an a2dp device
1882 if ((device & AudioSystem.DEVICE_OUT_ALL_A2DP) == 0 &&
1883 (flags & AudioManager.FLAG_BLUETOOTH_ABS_VOLUME) != 0) {
1884 return;
1885 }
Kenny Guy70e0c582015-06-30 19:18:28 +01001886 // If we are being called by the system (e.g. hardware keys) check for current user
1887 // so we handle user restrictions correctly.
1888 if (uid == android.os.Process.SYSTEM_UID) {
1889 uid = UserHandle.getUid(getCurrentUserId(), UserHandle.getAppId(uid));
1890 }
John Spurlock59dc9c12015-03-02 11:20:15 -05001891 if (mAppOps.noteOp(STREAM_VOLUME_OPS[streamTypeAlias], uid, callingPackage)
RoboErik0dac35a2014-08-12 15:48:49 -07001892 != AppOpsManager.MODE_ALLOWED) {
Dianne Hackbornba50b97c2013-04-30 15:04:46 -07001893 return;
1894 }
1895
Julia Reynolds48034f82016-03-09 10:15:16 -05001896 if (isAndroidNPlus(callingPackage)
1897 && wouldToggleZenMode(getNewRingerMode(streamTypeAlias, index, flags))
1898 && !mNm.isNotificationPolicyAccessGrantedForPackage(callingPackage)) {
1899 throw new SecurityException("Not allowed to change Do Not Disturb state");
1900 }
1901
Julia Reynoldsed783792016-04-08 15:27:35 -04001902 if (!volumeAdjustmentAllowedByDnd(streamTypeAlias, flags)) {
1903 return;
1904 }
1905
Eric Laurentfde16d52012-12-03 14:42:39 -08001906 synchronized (mSafeMediaVolumeState) {
1907 // reset any pending volume command
1908 mPendingVolumeCommand = null;
1909
Eric Laurent42b041e2013-03-29 11:36:03 -07001910 oldIndex = streamState.getIndex(device);
Eric Laurentfde16d52012-12-03 14:42:39 -08001911
Dianne Hackbornba50b97c2013-04-30 15:04:46 -07001912 index = rescaleIndex(index * 10, streamType, streamTypeAlias);
Eric Laurentfde16d52012-12-03 14:42:39 -08001913
Matthew Xiec9d1d5f2013-09-12 00:32:22 -07001914 if (streamTypeAlias == AudioSystem.STREAM_MUSIC &&
1915 (device & AudioSystem.DEVICE_OUT_ALL_A2DP) != 0 &&
1916 (flags & AudioManager.FLAG_BLUETOOTH_ABS_VOLUME) == 0) {
1917 synchronized (mA2dpAvrcpLock) {
1918 if (mA2dp != null && mAvrcpAbsVolSupported) {
Zhihai Xu2f4a2b12014-01-10 16:44:39 -08001919 mA2dp.setAvrcpAbsoluteVolume(index / 10);
Matthew Xiec9d1d5f2013-09-12 00:32:22 -07001920 }
John Du5a0cf7a2013-07-19 11:30:34 -07001921 }
1922 }
1923
Jakub Pawlowskif9570f32018-02-21 17:15:12 -08001924 if ((device & AudioSystem.DEVICE_OUT_HEARING_AID) != 0) {
Jakub Pawlowski21b7f492018-03-22 12:31:21 -07001925 setHearingAidVolume(index, streamType);
Jakub Pawlowskif9570f32018-02-21 17:15:12 -08001926 }
1927
Jinsuk Kim336cdb42014-11-29 06:27:00 +09001928 if (streamTypeAlias == AudioSystem.STREAM_MUSIC) {
1929 setSystemAudioVolume(oldIndex, index, getStreamMaxVolume(streamType), flags);
Jungshik Jang41d97462014-06-30 22:26:29 +09001930 }
1931
Eric Laurentfde16d52012-12-03 14:42:39 -08001932 flags &= ~AudioManager.FLAG_FIXED_VOLUME;
Dianne Hackbornba50b97c2013-04-30 15:04:46 -07001933 if ((streamTypeAlias == AudioSystem.STREAM_MUSIC) &&
Eric Laurentfde16d52012-12-03 14:42:39 -08001934 ((device & mFixedVolumeDevices) != 0)) {
1935 flags |= AudioManager.FLAG_FIXED_VOLUME;
1936
1937 // volume is either 0 or max allowed for fixed volume devices
1938 if (index != 0) {
1939 if (mSafeMediaVolumeState == SAFE_MEDIA_VOLUME_ACTIVE &&
1940 (device & mSafeMediaVolumeDevices) != 0) {
Eric Laurenteab40d12017-06-09 12:45:21 -07001941 index = safeMediaVolumeIndex(device);
Eric Laurentfde16d52012-12-03 14:42:39 -08001942 } else {
1943 index = streamState.getMaxIndex();
1944 }
1945 }
1946 }
1947
Dianne Hackbornba50b97c2013-04-30 15:04:46 -07001948 if (!checkSafeMediaVolume(streamTypeAlias, index, device)) {
John Spurlock3346a802014-05-20 16:25:37 -04001949 mVolumeController.postDisplaySafeVolumeWarning(flags);
Eric Laurentfde16d52012-12-03 14:42:39 -08001950 mPendingVolumeCommand = new StreamVolumeCommand(
1951 streamType, index, flags, device);
1952 } else {
John Spurlock90874332015-03-10 16:00:54 -04001953 onSetStreamVolume(streamType, index, flags, device, caller);
Eric Laurent42b041e2013-03-29 11:36:03 -07001954 index = mStreamStates[streamType].getIndex(device);
Eric Laurentfde16d52012-12-03 14:42:39 -08001955 }
1956 }
Eric Laurent25101b02011-02-02 09:33:30 -08001957 sendVolumeUpdate(streamType, oldIndex, index, flags);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001958 }
1959
Beverlyd6964762018-02-16 14:07:03 -05001960 // No ringer or zen muted stream volumes can be changed unless it'll exit dnd
Julia Reynoldsed783792016-04-08 15:27:35 -04001961 private boolean volumeAdjustmentAllowedByDnd(int streamTypeAlias, int flags) {
Beverlyd6964762018-02-16 14:07:03 -05001962 switch (mNm.getZenMode()) {
1963 case Settings.Global.ZEN_MODE_OFF:
1964 return true;
1965 case Settings.Global.ZEN_MODE_NO_INTERRUPTIONS:
1966 case Settings.Global.ZEN_MODE_ALARMS:
1967 case Settings.Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS:
1968 return !isStreamMutedByRingerOrZenMode(streamTypeAlias)
1969 || streamTypeAlias == getUiSoundsStreamType()
1970 || (flags & AudioManager.FLAG_ALLOW_RINGER_MODES) != 0;
Julia Reynoldsed783792016-04-08 15:27:35 -04001971 }
Beverlyd6964762018-02-16 14:07:03 -05001972
Julia Reynoldsed783792016-04-08 15:27:35 -04001973 return true;
1974 }
1975
Eric Laurent45c90ce2012-04-24 18:44:22 -07001976 /** @see AudioManager#forceVolumeControlStream(int) */
1977 public void forceVolumeControlStream(int streamType, IBinder cb) {
Jean-Michel Trivia7880d42017-04-15 12:41:05 -07001978 if (DEBUG_VOL) { Log.d(TAG, String.format("forceVolumeControlStream(%d)", streamType)); }
Eric Laurent45c90ce2012-04-24 18:44:22 -07001979 synchronized(mForceControlStreamLock) {
Jean-Michel Trivia7880d42017-04-15 12:41:05 -07001980 if (mVolumeControlStream != -1 && streamType != -1) {
1981 mUserSelectedVolumeControlStream = true;
1982 }
Eric Laurent45c90ce2012-04-24 18:44:22 -07001983 mVolumeControlStream = streamType;
1984 if (mVolumeControlStream == -1) {
1985 if (mForceControlStreamClient != null) {
1986 mForceControlStreamClient.release();
1987 mForceControlStreamClient = null;
1988 }
Jean-Michel Trivia7880d42017-04-15 12:41:05 -07001989 mUserSelectedVolumeControlStream = false;
Eric Laurent45c90ce2012-04-24 18:44:22 -07001990 } else {
jianzhou21fb09f2018-02-28 14:03:15 +08001991 if (null == mForceControlStreamClient) {
1992 mForceControlStreamClient = new ForceControlStreamClient(cb);
1993 } else {
1994 if (mForceControlStreamClient.getBinder() == cb) {
1995 Log.d(TAG, "forceVolumeControlStream cb:" + cb + " is already linked.");
1996 } else {
1997 mForceControlStreamClient.release();
1998 mForceControlStreamClient = new ForceControlStreamClient(cb);
1999 }
2000 }
Eric Laurent45c90ce2012-04-24 18:44:22 -07002001 }
2002 }
2003 }
2004
2005 private class ForceControlStreamClient implements IBinder.DeathRecipient {
2006 private IBinder mCb; // To be notified of client's death
2007
2008 ForceControlStreamClient(IBinder cb) {
2009 if (cb != null) {
2010 try {
2011 cb.linkToDeath(this, 0);
2012 } catch (RemoteException e) {
2013 // Client has died!
2014 Log.w(TAG, "ForceControlStreamClient() could not link to "+cb+" binder death");
2015 cb = null;
2016 }
2017 }
2018 mCb = cb;
2019 }
2020
2021 public void binderDied() {
2022 synchronized(mForceControlStreamLock) {
2023 Log.w(TAG, "SCO client died");
2024 if (mForceControlStreamClient != this) {
2025 Log.w(TAG, "unregistered control stream client died");
2026 } else {
2027 mForceControlStreamClient = null;
2028 mVolumeControlStream = -1;
Jean-Michel Trivia7880d42017-04-15 12:41:05 -07002029 mUserSelectedVolumeControlStream = false;
Eric Laurent45c90ce2012-04-24 18:44:22 -07002030 }
2031 }
2032 }
2033
2034 public void release() {
2035 if (mCb != null) {
2036 mCb.unlinkToDeath(this, 0);
2037 mCb = null;
2038 }
2039 }
jianzhou21fb09f2018-02-28 14:03:15 +08002040
2041 public IBinder getBinder() {
2042 return mCb;
2043 }
Eric Laurent45c90ce2012-04-24 18:44:22 -07002044 }
2045
Dianne Hackborn5ac72a22012-08-29 18:32:08 -07002046 private void sendBroadcastToAll(Intent intent) {
Christopher Tate267603f2015-01-20 14:21:21 -08002047 intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);
John Spurlock86490862015-02-25 11:22:52 -05002048 intent.addFlags(Intent.FLAG_RECEIVER_FOREGROUND);
Dianne Hackborn5ac72a22012-08-29 18:32:08 -07002049 final long ident = Binder.clearCallingIdentity();
2050 try {
2051 mContext.sendBroadcastAsUser(intent, UserHandle.ALL);
2052 } finally {
2053 Binder.restoreCallingIdentity(ident);
2054 }
2055 }
2056
2057 private void sendStickyBroadcastToAll(Intent intent) {
John Spurlock86490862015-02-25 11:22:52 -05002058 intent.addFlags(Intent.FLAG_RECEIVER_FOREGROUND);
Dianne Hackborn5ac72a22012-08-29 18:32:08 -07002059 final long ident = Binder.clearCallingIdentity();
2060 try {
2061 mContext.sendStickyBroadcastAsUser(intent, UserHandle.ALL);
2062 } finally {
2063 Binder.restoreCallingIdentity(ident);
2064 }
2065 }
2066
Kenny Guy70e0c582015-06-30 19:18:28 +01002067 private int getCurrentUserId() {
2068 final long ident = Binder.clearCallingIdentity();
2069 try {
Sudheer Shankadc589ac2016-11-10 15:30:17 -08002070 UserInfo currentUser = ActivityManager.getService().getCurrentUser();
Kenny Guy70e0c582015-06-30 19:18:28 +01002071 return currentUser.id;
2072 } catch (RemoteException e) {
2073 // Activity manager not running, nothing we can do assume user 0.
2074 } finally {
2075 Binder.restoreCallingIdentity(ident);
2076 }
Xiaohui Chen7c696362015-09-16 09:56:14 -07002077 return UserHandle.USER_SYSTEM;
Kenny Guy70e0c582015-06-30 19:18:28 +01002078 }
2079
Eric Laurent25101b02011-02-02 09:33:30 -08002080 // UI update and Broadcast Intent
Yue Li949865b2017-05-24 17:25:28 -07002081 protected void sendVolumeUpdate(int streamType, int oldIndex, int index, int flags) {
John Spurlock72966d62015-06-18 15:45:07 -04002082 streamType = mStreamVolumeAlias[streamType];
Eric Laurent25101b02011-02-02 09:33:30 -08002083
Jinsuk Kim336cdb42014-11-29 06:27:00 +09002084 if (streamType == AudioSystem.STREAM_MUSIC) {
2085 flags = updateFlagsForSystemAudio(flags);
Jungshik Jang1a6be6e2014-09-16 11:04:54 +09002086 }
John Spurlock3346a802014-05-20 16:25:37 -04002087 mVolumeController.postVolumeChanged(streamType, flags);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002088 }
2089
Jinsuk Kim336cdb42014-11-29 06:27:00 +09002090 // If Hdmi-CEC system audio mode is on, we show volume bar only when TV
2091 // receives volume notification from Audio Receiver.
2092 private int updateFlagsForSystemAudio(int flags) {
2093 if (mHdmiTvClient != null) {
2094 synchronized (mHdmiTvClient) {
2095 if (mHdmiSystemAudioSupported &&
2096 ((flags & AudioManager.FLAG_HDMI_SYSTEM_AUDIO_VOLUME) == 0)) {
2097 flags &= ~AudioManager.FLAG_SHOW_UI;
2098 }
2099 }
2100 }
2101 return flags;
2102 }
2103
Mike Lockwood0dc37cc2011-12-01 16:14:19 -05002104 // UI update and Broadcast Intent
Mike Lockwood0dc37cc2011-12-01 16:14:19 -05002105 private void sendMasterMuteUpdate(boolean muted, int flags) {
Jinsuk Kim336cdb42014-11-29 06:27:00 +09002106 mVolumeController.postMasterMuteChanged(updateFlagsForSystemAudio(flags));
Justin Koh57978ed2012-04-03 17:37:58 -07002107 broadcastMasterMuteStatus(muted);
2108 }
Mike Lockwood0dc37cc2011-12-01 16:14:19 -05002109
Justin Koh57978ed2012-04-03 17:37:58 -07002110 private void broadcastMasterMuteStatus(boolean muted) {
Mike Lockwood0dc37cc2011-12-01 16:14:19 -05002111 Intent intent = new Intent(AudioManager.MASTER_MUTE_CHANGED_ACTION);
2112 intent.putExtra(AudioManager.EXTRA_MASTER_VOLUME_MUTED, muted);
Justin Koh57978ed2012-04-03 17:37:58 -07002113 intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT
2114 | Intent.FLAG_RECEIVER_REPLACE_PENDING);
Dianne Hackborn5ac72a22012-08-29 18:32:08 -07002115 sendStickyBroadcastToAll(intent);
Mike Lockwood0dc37cc2011-12-01 16:14:19 -05002116 }
2117
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002118 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002119 * Sets the stream state's index, and posts a message to set system volume.
2120 * This will not call out to the UI. Assumes a valid stream type.
2121 *
2122 * @param streamType Type of the stream
2123 * @param index Desired volume index of the stream
Eric Laurent9bc8358d2011-11-18 16:43:31 -08002124 * @param device the device whose volume must be changed
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002125 * @param force If true, set the volume even if the desired volume is same
2126 * as the current volume.
2127 */
Eric Laurent9bc8358d2011-11-18 16:43:31 -08002128 private void setStreamVolumeInt(int streamType,
2129 int index,
2130 int device,
John Spurlock90874332015-03-10 16:00:54 -04002131 boolean force,
2132 String caller) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002133 VolumeStreamState streamState = mStreamStates[streamType];
Eric Laurent5b4e6542010-03-19 20:02:21 -07002134
John Spurlock90874332015-03-10 16:00:54 -04002135 if (streamState.setIndex(index, device, caller) || force) {
Eric Laurent42b041e2013-03-29 11:36:03 -07002136 // Post message to set system volume (it in turn will post a message
2137 // to persist).
2138 sendMsg(mAudioHandler,
2139 MSG_SET_DEVICE_VOLUME,
2140 SENDMSG_QUEUE,
2141 device,
2142 0,
2143 streamState,
2144 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002145 }
2146 }
2147
Jinsuk Kim336cdb42014-11-29 06:27:00 +09002148 private void setSystemAudioMute(boolean state) {
2149 if (mHdmiManager == null || mHdmiTvClient == null) return;
2150 synchronized (mHdmiManager) {
Jinsuk Kim48cbf292014-12-13 02:16:28 +09002151 if (!mHdmiSystemAudioSupported) return;
2152 synchronized (mHdmiTvClient) {
2153 final long token = Binder.clearCallingIdentity();
2154 try {
2155 mHdmiTvClient.setSystemAudioMute(state);
2156 } finally {
2157 Binder.restoreCallingIdentity(token);
Jinsuk Kim336cdb42014-11-29 06:27:00 +09002158 }
Jinsuk Kim336cdb42014-11-29 06:27:00 +09002159 }
2160 }
2161 }
2162
Eric Laurent25101b02011-02-02 09:33:30 -08002163 /** get stream mute state. */
2164 public boolean isStreamMute(int streamType) {
RoboErik7c82ced2014-12-04 17:39:08 -08002165 if (streamType == AudioManager.USE_DEFAULT_STREAM_TYPE) {
2166 streamType = getActiveStreamType(streamType);
2167 }
Eric Laurent8fa4d6f2014-10-30 14:13:03 -07002168 synchronized (VolumeStreamState.class) {
jiabin93d32ef2017-07-11 13:50:02 -07002169 ensureValidStreamType(streamType);
RoboErik4197cb62015-01-21 15:45:32 -08002170 return mStreamStates[streamType].mIsMuted;
Eric Laurent8fa4d6f2014-10-30 14:13:03 -07002171 }
Eric Laurent25101b02011-02-02 09:33:30 -08002172 }
2173
Jean-Michel Triviba5270b2014-10-01 17:49:29 -07002174 private class RmtSbmxFullVolDeathHandler implements IBinder.DeathRecipient {
2175 private IBinder mICallback; // To be notified of client's death
2176
2177 RmtSbmxFullVolDeathHandler(IBinder cb) {
2178 mICallback = cb;
2179 try {
2180 cb.linkToDeath(this, 0/*flags*/);
2181 } catch (RemoteException e) {
2182 Log.e(TAG, "can't link to death", e);
2183 }
2184 }
2185
2186 boolean isHandlerFor(IBinder cb) {
2187 return mICallback.equals(cb);
2188 }
2189
2190 void forget() {
2191 try {
2192 mICallback.unlinkToDeath(this, 0/*flags*/);
2193 } catch (NoSuchElementException e) {
2194 Log.e(TAG, "error unlinking to death", e);
2195 }
2196 }
2197
2198 public void binderDied() {
2199 Log.w(TAG, "Recorder with remote submix at full volume died " + mICallback);
2200 forceRemoteSubmixFullVolume(false, mICallback);
2201 }
2202 }
2203
2204 /**
2205 * call must be synchronized on mRmtSbmxFullVolDeathHandlers
2206 * @return true if there is a registered death handler, false otherwise */
2207 private boolean discardRmtSbmxFullVolDeathHandlerFor(IBinder cb) {
2208 Iterator<RmtSbmxFullVolDeathHandler> it = mRmtSbmxFullVolDeathHandlers.iterator();
2209 while (it.hasNext()) {
2210 final RmtSbmxFullVolDeathHandler handler = it.next();
2211 if (handler.isHandlerFor(cb)) {
2212 handler.forget();
2213 mRmtSbmxFullVolDeathHandlers.remove(handler);
2214 return true;
2215 }
2216 }
2217 return false;
2218 }
2219
2220 /** call synchronized on mRmtSbmxFullVolDeathHandlers */
2221 private boolean hasRmtSbmxFullVolDeathHandlerFor(IBinder cb) {
2222 Iterator<RmtSbmxFullVolDeathHandler> it = mRmtSbmxFullVolDeathHandlers.iterator();
2223 while (it.hasNext()) {
2224 if (it.next().isHandlerFor(cb)) {
2225 return true;
2226 }
2227 }
2228 return false;
2229 }
2230
2231 private int mRmtSbmxFullVolRefCount = 0;
2232 private ArrayList<RmtSbmxFullVolDeathHandler> mRmtSbmxFullVolDeathHandlers =
2233 new ArrayList<RmtSbmxFullVolDeathHandler>();
2234
2235 public void forceRemoteSubmixFullVolume(boolean startForcing, IBinder cb) {
2236 if (cb == null) {
2237 return;
2238 }
2239 if ((PackageManager.PERMISSION_GRANTED != mContext.checkCallingOrSelfPermission(
2240 android.Manifest.permission.CAPTURE_AUDIO_OUTPUT))) {
2241 Log.w(TAG, "Trying to call forceRemoteSubmixFullVolume() without CAPTURE_AUDIO_OUTPUT");
2242 return;
2243 }
2244 synchronized(mRmtSbmxFullVolDeathHandlers) {
2245 boolean applyRequired = false;
2246 if (startForcing) {
2247 if (!hasRmtSbmxFullVolDeathHandlerFor(cb)) {
2248 mRmtSbmxFullVolDeathHandlers.add(new RmtSbmxFullVolDeathHandler(cb));
2249 if (mRmtSbmxFullVolRefCount == 0) {
2250 mFullVolumeDevices |= AudioSystem.DEVICE_OUT_REMOTE_SUBMIX;
2251 mFixedVolumeDevices |= AudioSystem.DEVICE_OUT_REMOTE_SUBMIX;
2252 applyRequired = true;
2253 }
2254 mRmtSbmxFullVolRefCount++;
2255 }
2256 } else {
2257 if (discardRmtSbmxFullVolDeathHandlerFor(cb) && (mRmtSbmxFullVolRefCount > 0)) {
2258 mRmtSbmxFullVolRefCount--;
2259 if (mRmtSbmxFullVolRefCount == 0) {
2260 mFullVolumeDevices &= ~AudioSystem.DEVICE_OUT_REMOTE_SUBMIX;
2261 mFixedVolumeDevices &= ~AudioSystem.DEVICE_OUT_REMOTE_SUBMIX;
2262 applyRequired = true;
2263 }
2264 }
2265 }
2266 if (applyRequired) {
2267 // Assumes only STREAM_MUSIC going through DEVICE_OUT_REMOTE_SUBMIX
2268 checkAllFixedVolumeDevices(AudioSystem.STREAM_MUSIC);
2269 mStreamStates[AudioSystem.STREAM_MUSIC].applyAllVolumes();
2270 }
2271 }
2272 }
2273
Kenny Guy70e0c582015-06-30 19:18:28 +01002274 private void setMasterMuteInternal(boolean mute, int flags, String callingPackage, int uid,
2275 int userId) {
2276 // If we are being called by the system check for user we are going to change
2277 // so we handle user restrictions correctly.
2278 if (uid == android.os.Process.SYSTEM_UID) {
2279 uid = UserHandle.getUid(userId, UserHandle.getAppId(uid));
2280 }
Makoto Onuki4f160732015-10-27 17:15:38 -07002281 // If OP_AUDIO_MASTER_VOLUME is set, disallow unmuting.
2282 if (!mute && mAppOps.noteOp(AppOpsManager.OP_AUDIO_MASTER_VOLUME, uid, callingPackage)
RoboErik7c82ced2014-12-04 17:39:08 -08002283 != AppOpsManager.MODE_ALLOWED) {
Julia Reynolds4a21b252014-06-04 11:11:43 -04002284 return;
2285 }
Kenny Guy70e0c582015-06-30 19:18:28 +01002286 if (userId != UserHandle.getCallingUserId() &&
2287 mContext.checkCallingOrSelfPermission(
2288 android.Manifest.permission.INTERACT_ACROSS_USERS_FULL)
2289 != PackageManager.PERMISSION_GRANTED) {
2290 return;
2291 }
Makoto Onukid45a4a22015-11-02 17:17:38 -08002292 setMasterMuteInternalNoCallerCheck(mute, flags, userId);
2293 }
2294
2295 private void setMasterMuteInternalNoCallerCheck(boolean mute, int flags, int userId) {
2296 if (DEBUG_VOL) {
2297 Log.d(TAG, String.format("Master mute %s, %d, user=%d", mute, flags, userId));
2298 }
2299 if (mUseFixedVolume) {
2300 return; // If using fixed volume, we don't mute.
2301 }
Kenny Guy70e0c582015-06-30 19:18:28 +01002302 if (getCurrentUserId() == userId) {
2303 if (mute != AudioSystem.getMasterMute()) {
2304 setSystemAudioMute(mute);
2305 AudioSystem.setMasterMute(mute);
Kenny Guy70e0c582015-06-30 19:18:28 +01002306 sendMasterMuteUpdate(mute, flags);
RoboErik7c82ced2014-12-04 17:39:08 -08002307
Kenny Guy70e0c582015-06-30 19:18:28 +01002308 Intent intent = new Intent(AudioManager.MASTER_MUTE_CHANGED_ACTION);
2309 intent.putExtra(AudioManager.EXTRA_MASTER_VOLUME_MUTED, mute);
2310 sendBroadcastToAll(intent);
2311 }
Jason Simmons1ce5b262012-02-02 13:00:17 -08002312 }
Mike Lockwoodce952c82011-11-14 10:47:42 -08002313 }
2314
2315 /** get master mute state. */
2316 public boolean isMasterMute() {
Mike Lockwood3194ea92011-12-07 11:47:31 -08002317 return AudioSystem.getMasterMute();
Mike Lockwoodce952c82011-11-14 10:47:42 -08002318 }
2319
Kenny Guy70e0c582015-06-30 19:18:28 +01002320 public void setMasterMute(boolean mute, int flags, String callingPackage, int userId) {
2321 setMasterMuteInternal(mute, flags, callingPackage, Binder.getCallingUid(),
2322 userId);
John Spurlockee5ad722015-03-03 16:17:21 -05002323 }
2324
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002325 /** @see AudioManager#getStreamVolume(int) */
2326 public int getStreamVolume(int streamType) {
2327 ensureValidStreamType(streamType);
Eric Laurent9bc8358d2011-11-18 16:43:31 -08002328 int device = getDeviceForStream(streamType);
Eric Laurent8fa4d6f2014-10-30 14:13:03 -07002329 synchronized (VolumeStreamState.class) {
2330 int index = mStreamStates[streamType].getIndex(device);
Eric Laurent4bbcc652012-09-24 14:26:30 -07002331
Eric Laurent8fa4d6f2014-10-30 14:13:03 -07002332 // by convention getStreamVolume() returns 0 when a stream is muted.
RoboErik4197cb62015-01-21 15:45:32 -08002333 if (mStreamStates[streamType].mIsMuted) {
Eric Laurent8fa4d6f2014-10-30 14:13:03 -07002334 index = 0;
2335 }
2336 if (index != 0 && (mStreamVolumeAlias[streamType] == AudioSystem.STREAM_MUSIC) &&
2337 (device & mFixedVolumeDevices) != 0) {
2338 index = mStreamStates[streamType].getMaxIndex();
2339 }
2340 return (index + 5) / 10;
Eric Laurent42b041e2013-03-29 11:36:03 -07002341 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002342 }
2343
2344 /** @see AudioManager#getStreamMaxVolume(int) */
2345 public int getStreamMaxVolume(int streamType) {
2346 ensureValidStreamType(streamType);
Eric Laurenta553c252009-07-17 12:17:14 -07002347 return (mStreamStates[streamType].getMaxIndex() + 5) / 10;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002348 }
2349
Jean-Michel Trivi8e7aca32017-11-28 18:12:38 -08002350 /** @see AudioManager#getStreamMinVolumeInt(int) */
John Spurlockb6e19e32015-03-10 21:33:44 -04002351 public int getStreamMinVolume(int streamType) {
2352 ensureValidStreamType(streamType);
2353 return (mStreamStates[streamType].getMinIndex() + 5) / 10;
2354 }
2355
Eric Laurent25101b02011-02-02 09:33:30 -08002356 /** Get last audible volume before stream was muted. */
2357 public int getLastAudibleStreamVolume(int streamType) {
2358 ensureValidStreamType(streamType);
Eric Laurent9bc8358d2011-11-18 16:43:31 -08002359 int device = getDeviceForStream(streamType);
Eric Laurent42b041e2013-03-29 11:36:03 -07002360 return (mStreamStates[streamType].getIndex(device) + 5) / 10;
Eric Laurent25101b02011-02-02 09:33:30 -08002361 }
2362
John Spurlockee5ad722015-03-03 16:17:21 -05002363 /** @see AudioManager#getUiSoundsStreamType() */
2364 public int getUiSoundsStreamType() {
John Spurlock4f0f1202014-08-05 13:28:33 -04002365 return mStreamVolumeAlias[AudioSystem.STREAM_SYSTEM];
Eric Laurent6d517662012-04-23 18:42:39 -07002366 }
2367
Makoto Onukid45a4a22015-11-02 17:17:38 -08002368 /** @see AudioManager#setMicrophoneMute(boolean) */
2369 @Override
Kenny Guy70e0c582015-06-30 19:18:28 +01002370 public void setMicrophoneMute(boolean on, String callingPackage, int userId) {
2371 // If we are being called by the system check for user we are going to change
2372 // so we handle user restrictions correctly.
2373 int uid = Binder.getCallingUid();
2374 if (uid == android.os.Process.SYSTEM_UID) {
2375 uid = UserHandle.getUid(userId, UserHandle.getAppId(uid));
2376 }
Makoto Onuki4f160732015-10-27 17:15:38 -07002377 // If OP_MUTE_MICROPHONE is set, disallow unmuting.
2378 if (!on && mAppOps.noteOp(AppOpsManager.OP_MUTE_MICROPHONE, uid, callingPackage)
Kenny Guy70e0c582015-06-30 19:18:28 +01002379 != AppOpsManager.MODE_ALLOWED) {
Emily Bernier22c921a2014-05-28 11:01:32 -04002380 return;
2381 }
Jean-Michel Trivi4a4fea02014-08-29 18:14:09 -07002382 if (!checkAudioSettingsPermission("setMicrophoneMute()")) {
2383 return;
2384 }
Kenny Guy70e0c582015-06-30 19:18:28 +01002385 if (userId != UserHandle.getCallingUserId() &&
2386 mContext.checkCallingOrSelfPermission(
2387 android.Manifest.permission.INTERACT_ACROSS_USERS_FULL)
2388 != PackageManager.PERMISSION_GRANTED) {
2389 return;
2390 }
Makoto Onukid45a4a22015-11-02 17:17:38 -08002391 setMicrophoneMuteNoCallerCheck(on, userId);
2392 }
Emily Bernier22c921a2014-05-28 11:01:32 -04002393
Makoto Onukid45a4a22015-11-02 17:17:38 -08002394 private void setMicrophoneMuteNoCallerCheck(boolean on, int userId) {
2395 if (DEBUG_VOL) {
2396 Log.d(TAG, String.format("Mic mute %s, user=%d", on, userId));
2397 }
Jean-Michel Trivi7be17d22017-12-21 18:09:21 -08002398 // only mute for the current user
Kenny Guy70e0c582015-06-30 19:18:28 +01002399 if (getCurrentUserId() == userId) {
Jean-Michel Trivi7be17d22017-12-21 18:09:21 -08002400 final boolean currentMute = AudioSystem.isMicrophoneMuted();
Eric Laurent66b69672018-01-26 18:30:51 -08002401 final long identity = Binder.clearCallingIdentity();
Kenny Guy70e0c582015-06-30 19:18:28 +01002402 AudioSystem.muteMicrophone(on);
Eric Laurent66b69672018-01-26 18:30:51 -08002403 Binder.restoreCallingIdentity(identity);
Jean-Michel Trivi7be17d22017-12-21 18:09:21 -08002404 if (on != currentMute) {
2405 mContext.sendBroadcast(new Intent(AudioManager.ACTION_MICROPHONE_MUTE_CHANGED)
2406 .setFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY));
2407 }
Kenny Guy70e0c582015-06-30 19:18:28 +01002408 }
Emily Bernier22c921a2014-05-28 11:01:32 -04002409 }
2410
John Spurlock661f2cf2014-11-17 10:29:10 -05002411 @Override
2412 public int getRingerModeExternal() {
2413 synchronized(mSettingsLock) {
2414 return mRingerModeExternal;
2415 }
2416 }
2417
2418 @Override
2419 public int getRingerModeInternal() {
Glenn Kastenba195eb2011-12-13 09:30:40 -08002420 synchronized(mSettingsLock) {
2421 return mRingerMode;
2422 }
2423 }
2424
2425 private void ensureValidRingerMode(int ringerMode) {
John Spurlock97559372014-10-24 16:27:36 -04002426 if (!isValidRingerMode(ringerMode)) {
Glenn Kastenba195eb2011-12-13 09:30:40 -08002427 throw new IllegalArgumentException("Bad ringer mode " + ringerMode);
2428 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002429 }
2430
John Spurlock97559372014-10-24 16:27:36 -04002431 /** @see AudioManager#isValidRingerMode(int) */
2432 public boolean isValidRingerMode(int ringerMode) {
2433 return ringerMode >= 0 && ringerMode <= AudioManager.RINGER_MODE_MAX;
2434 }
2435
John Spurlock661f2cf2014-11-17 10:29:10 -05002436 public void setRingerModeExternal(int ringerMode, String caller) {
Julia Reynolds48034f82016-03-09 10:15:16 -05002437 if (isAndroidNPlus(caller) && wouldToggleZenMode(ringerMode)
2438 && !mNm.isNotificationPolicyAccessGrantedForPackage(caller)) {
2439 throw new SecurityException("Not allowed to change Do Not Disturb state");
2440 }
2441
John Spurlockaf88a192014-12-23 16:14:44 -05002442 setRingerMode(ringerMode, caller, true /*external*/);
John Spurlock661f2cf2014-11-17 10:29:10 -05002443 }
2444
2445 public void setRingerModeInternal(int ringerMode, String caller) {
John Spurlockcdb57ae2015-02-11 19:04:11 -05002446 enforceVolumeController("setRingerModeInternal");
John Spurlockaf88a192014-12-23 16:14:44 -05002447 setRingerMode(ringerMode, caller, false /*external*/);
John Spurlock661f2cf2014-11-17 10:29:10 -05002448 }
2449
Mike Digman55272862018-02-20 14:35:17 -08002450 public void silenceRingerModeInternal(String reason) {
2451 VibrationEffect effect = null;
2452 int ringerMode = AudioManager.RINGER_MODE_SILENT;
2453 int toastText = 0;
2454
2455 int silenceRingerSetting = Settings.Secure.VOLUME_HUSH_OFF;
2456 if (mContext.getResources()
2457 .getBoolean(com.android.internal.R.bool.config_volumeHushGestureEnabled)) {
2458 silenceRingerSetting = Settings.Secure.getIntForUser(mContentResolver,
2459 Settings.Secure.VOLUME_HUSH_GESTURE, VOLUME_HUSH_OFF,
2460 UserHandle.USER_CURRENT);
2461 }
2462
2463 switch(silenceRingerSetting) {
2464 case VOLUME_HUSH_MUTE:
2465 effect = VibrationEffect.get(VibrationEffect.EFFECT_DOUBLE_CLICK);
2466 ringerMode = AudioManager.RINGER_MODE_SILENT;
2467 toastText = com.android.internal.R.string.volume_dialog_ringer_guidance_silent;
2468 break;
2469 case VOLUME_HUSH_VIBRATE:
2470 effect = VibrationEffect.get(VibrationEffect.EFFECT_HEAVY_CLICK);
2471 ringerMode = AudioManager.RINGER_MODE_VIBRATE;
2472 toastText = com.android.internal.R.string.volume_dialog_ringer_guidance_vibrate;
2473 break;
2474 }
2475 maybeVibrate(effect);
2476 setRingerModeInternal(ringerMode, reason);
2477 Toast.makeText(mContext, toastText, Toast.LENGTH_SHORT).show();
2478 }
2479
2480 private boolean maybeVibrate(VibrationEffect effect) {
2481 if (!mHasVibrator) {
2482 return false;
2483 }
2484 final boolean hapticsDisabled = Settings.System.getIntForUser(mContext.getContentResolver(),
2485 Settings.System.HAPTIC_FEEDBACK_ENABLED, 0, UserHandle.USER_CURRENT) == 0;
2486 if (hapticsDisabled) {
2487 return false;
2488 }
2489
2490 if (effect == null) {
2491 return false;
2492 }
2493 mVibrator.vibrate(
2494 Binder.getCallingUid(), mContext.getOpPackageName(), effect, VIBRATION_ATTRIBUTES);
2495 return true;
2496 }
2497
John Spurlock661f2cf2014-11-17 10:29:10 -05002498 private void setRingerMode(int ringerMode, String caller, boolean external) {
Muyuan Li1ed6df62016-06-18 11:16:52 -07002499 if (mUseFixedVolume || mIsSingleVolume) {
Eric Laurent83a017b2013-03-19 18:15:31 -07002500 return;
2501 }
John Spurlock661f2cf2014-11-17 10:29:10 -05002502 if (caller == null || caller.length() == 0) {
2503 throw new IllegalArgumentException("Bad caller: " + caller);
2504 }
John Spurlock97559372014-10-24 16:27:36 -04002505 ensureValidRingerMode(ringerMode);
Eric Laurent24482012012-05-10 09:41:17 -07002506 if ((ringerMode == AudioManager.RINGER_MODE_VIBRATE) && !mHasVibrator) {
2507 ringerMode = AudioManager.RINGER_MODE_SILENT;
2508 }
John Spurlockaf88a192014-12-23 16:14:44 -05002509 final long identity = Binder.clearCallingIdentity();
2510 try {
2511 synchronized (mSettingsLock) {
2512 final int ringerModeInternal = getRingerModeInternal();
2513 final int ringerModeExternal = getRingerModeExternal();
2514 if (external) {
2515 setRingerModeExt(ringerMode);
2516 if (mRingerModeDelegate != null) {
2517 ringerMode = mRingerModeDelegate.onSetRingerModeExternal(ringerModeExternal,
John Spurlocka48d7792015-03-03 17:35:57 -05002518 ringerMode, caller, ringerModeInternal, mVolumePolicy);
John Spurlockaf88a192014-12-23 16:14:44 -05002519 }
2520 if (ringerMode != ringerModeInternal) {
2521 setRingerModeInt(ringerMode, true /*persist*/);
2522 }
2523 } else /*internal*/ {
2524 if (ringerMode != ringerModeInternal) {
2525 setRingerModeInt(ringerMode, true /*persist*/);
2526 }
2527 if (mRingerModeDelegate != null) {
2528 ringerMode = mRingerModeDelegate.onSetRingerModeInternal(ringerModeInternal,
John Spurlocka48d7792015-03-03 17:35:57 -05002529 ringerMode, caller, ringerModeExternal, mVolumePolicy);
John Spurlockaf88a192014-12-23 16:14:44 -05002530 }
2531 setRingerModeExt(ringerMode);
John Spurlock57627792014-12-11 11:29:54 -05002532 }
John Spurlock661f2cf2014-11-17 10:29:10 -05002533 }
John Spurlockaf88a192014-12-23 16:14:44 -05002534 } finally {
2535 Binder.restoreCallingIdentity(identity);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002536 }
2537 }
2538
John Spurlock661f2cf2014-11-17 10:29:10 -05002539 private void setRingerModeExt(int ringerMode) {
2540 synchronized(mSettingsLock) {
2541 if (ringerMode == mRingerModeExternal) return;
2542 mRingerModeExternal = ringerMode;
John Spurlocke5b42d92014-10-15 12:03:48 -04002543 }
John Spurlock661f2cf2014-11-17 10:29:10 -05002544 // Send sticky broadcast
John Spurlockbcc10872014-11-28 15:29:21 -05002545 broadcastRingerMode(AudioManager.RINGER_MODE_CHANGED_ACTION, ringerMode);
John Spurlocke5b42d92014-10-15 12:03:48 -04002546 }
2547
John Spurlock50ced3f2015-05-11 16:00:09 -04002548 private void muteRingerModeStreams() {
Beverlyd6964762018-02-16 14:07:03 -05002549 // Mute stream if not previously muted by ringer mode and (ringer mode
2550 // is not RINGER_MODE_NORMAL OR stream is zen muted) and stream is affected by ringer mode.
2551 // Unmute stream if previously muted by ringer/zen mode and ringer mode
Eric Laurent5b4e6542010-03-19 20:02:21 -07002552 // is RINGER_MODE_NORMAL or stream is not affected by ringer mode.
Jason Parekhb1096152009-03-24 17:48:25 -07002553 int numStreamTypes = AudioSystem.getNumStreamTypes();
Beverly925cde82018-01-23 09:31:23 -05002554
2555 if (mNm == null) {
2556 mNm = (NotificationManager) mContext.getSystemService(Context.NOTIFICATION_SERVICE);
2557 }
2558
Jack He6dd78c12018-02-12 21:00:24 -08002559 final int ringerMode = mRingerMode; // Read ringer mode as reading primitives is atomic
2560 final boolean ringerModeMute = ringerMode == AudioManager.RINGER_MODE_VIBRATE
2561 || ringerMode == AudioManager.RINGER_MODE_SILENT;
2562 final boolean shouldRingSco = ringerMode == AudioManager.RINGER_MODE_VIBRATE
2563 && isBluetoothScoOn();
2564 // Ask audio policy engine to force use Bluetooth SCO channel if needed
2565 final String eventSource = "muteRingerModeStreams() from u/pid:" + Binder.getCallingUid()
2566 + "/" + Binder.getCallingPid();
2567 sendMsg(mAudioHandler, MSG_SET_FORCE_USE, SENDMSG_QUEUE, AudioSystem.FOR_VIBRATE_RINGING,
2568 shouldRingSco ? AudioSystem.FORCE_BT_SCO : AudioSystem.FORCE_NONE, eventSource, 0);
Beverly925cde82018-01-23 09:31:23 -05002569
Eric Laurent5b4e6542010-03-19 20:02:21 -07002570 for (int streamType = numStreamTypes - 1; streamType >= 0; streamType--) {
Beverlyd6964762018-02-16 14:07:03 -05002571 final boolean isMuted = isStreamMutedByRingerOrZenMode(streamType);
Jack He6dd78c12018-02-12 21:00:24 -08002572 final boolean muteAllowedBySco =
2573 !(shouldRingSco && streamType == AudioSystem.STREAM_RING);
Beverlyd6964762018-02-16 14:07:03 -05002574 final boolean shouldZenMute = shouldZenMuteStream(streamType);
2575 final boolean shouldMute = shouldZenMute || (ringerModeMute
Jack He6dd78c12018-02-12 21:00:24 -08002576 && isStreamAffectedByRingerMode(streamType) && muteAllowedBySco);
John Spurlock661f2cf2014-11-17 10:29:10 -05002577 if (isMuted == shouldMute) continue;
2578 if (!shouldMute) {
2579 // unmute
2580 // ring and notifications volume should never be 0 when not silenced
John Spurlockd9c75db2015-04-28 11:19:13 -04002581 if (mStreamVolumeAlias[streamType] == AudioSystem.STREAM_RING) {
John Spurlock661f2cf2014-11-17 10:29:10 -05002582 synchronized (VolumeStreamState.class) {
John Spurlocka48d7792015-03-03 17:35:57 -05002583 final VolumeStreamState vss = mStreamStates[streamType];
2584 for (int i = 0; i < vss.mIndexMap.size(); i++) {
2585 int device = vss.mIndexMap.keyAt(i);
2586 int value = vss.mIndexMap.valueAt(i);
John Spurlock2bb02ec2015-03-02 13:13:06 -05002587 if (value == 0) {
John Spurlocka48d7792015-03-03 17:35:57 -05002588 vss.setIndex(10, device, TAG);
Eric Laurent9bc8358d2011-11-18 16:43:31 -08002589 }
2590 }
Eric Laurent9e0d25f2015-02-12 17:28:53 -08002591 // Persist volume for stream ring when it is changed here
2592 final int device = getDeviceForStream(streamType);
2593 sendMsg(mAudioHandler,
2594 MSG_PERSIST_VOLUME,
2595 SENDMSG_QUEUE,
2596 device,
2597 0,
2598 mStreamStates[streamType],
2599 PERSIST_DELAY);
Eric Laurentb024c302011-10-14 17:19:27 -07002600 }
Eric Laurent9bcf4012009-06-12 06:09:28 -07002601 }
RoboErik4197cb62015-01-21 15:45:32 -08002602 mStreamStates[streamType].mute(false);
Beverlyd6964762018-02-16 14:07:03 -05002603 mRingerAndZenModeMutedStreams &= ~(1 << streamType);
Eric Laurent5b4e6542010-03-19 20:02:21 -07002604 } else {
John Spurlock661f2cf2014-11-17 10:29:10 -05002605 // mute
RoboErik4197cb62015-01-21 15:45:32 -08002606 mStreamStates[streamType].mute(true);
Beverlyd6964762018-02-16 14:07:03 -05002607 mRingerAndZenModeMutedStreams |= (1 << streamType);
Jason Parekhb1096152009-03-24 17:48:25 -07002608 }
2609 }
John Spurlock50ced3f2015-05-11 16:00:09 -04002610 }
2611
Beverly925cde82018-01-23 09:31:23 -05002612 private boolean isAlarm(int streamType) {
2613 return streamType == AudioSystem.STREAM_ALARM;
2614 }
2615
2616 private boolean isNotificationOrRinger(int streamType) {
2617 return streamType == AudioSystem.STREAM_NOTIFICATION
2618 || streamType == AudioSystem.STREAM_RING;
2619 }
2620
2621 private boolean isMedia(int streamType) {
Beverlyd6964762018-02-16 14:07:03 -05002622 return streamType == AudioSystem.STREAM_MUSIC;
2623 }
2624
2625
2626 private boolean isSystem(int streamType) {
2627 return streamType == AudioSystem.STREAM_SYSTEM;
Beverly925cde82018-01-23 09:31:23 -05002628 }
2629
John Spurlock50ced3f2015-05-11 16:00:09 -04002630 private void setRingerModeInt(int ringerMode, boolean persist) {
2631 final boolean change;
2632 synchronized(mSettingsLock) {
2633 change = mRingerMode != ringerMode;
2634 mRingerMode = ringerMode;
2635 }
2636
2637 muteRingerModeStreams();
Eric Laurenta553c252009-07-17 12:17:14 -07002638
Jason Parekhb1096152009-03-24 17:48:25 -07002639 // Post a persist ringer mode msg
Eric Laurent4050c932009-07-08 02:52:14 -07002640 if (persist) {
Eric Laurentafbb0472011-12-15 09:04:23 -08002641 sendMsg(mAudioHandler, MSG_PERSIST_RINGER_MODE,
Eric Laurent4050c932009-07-08 02:52:14 -07002642 SENDMSG_REPLACE, 0, 0, null, PERSIST_DELAY);
2643 }
John Spurlockbcc10872014-11-28 15:29:21 -05002644 if (change) {
2645 // Send sticky broadcast
2646 broadcastRingerMode(AudioManager.INTERNAL_RINGER_MODE_CHANGED_ACTION, ringerMode);
2647 }
Jason Parekhb1096152009-03-24 17:48:25 -07002648 }
2649
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002650 /** @see AudioManager#shouldVibrate(int) */
2651 public boolean shouldVibrate(int vibrateType) {
Eric Laurentbffc3d12012-05-07 17:43:49 -07002652 if (!mHasVibrator) return false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002653
2654 switch (getVibrateSetting(vibrateType)) {
2655
2656 case AudioManager.VIBRATE_SETTING_ON:
John Spurlock57627792014-12-11 11:29:54 -05002657 return getRingerModeExternal() != AudioManager.RINGER_MODE_SILENT;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002658
2659 case AudioManager.VIBRATE_SETTING_ONLY_SILENT:
John Spurlock57627792014-12-11 11:29:54 -05002660 return getRingerModeExternal() == AudioManager.RINGER_MODE_VIBRATE;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002661
2662 case AudioManager.VIBRATE_SETTING_OFF:
Daniel Sandlerbcac4962010-04-12 13:23:57 -04002663 // return false, even for incoming calls
2664 return false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002665
2666 default:
2667 return false;
2668 }
2669 }
2670
2671 /** @see AudioManager#getVibrateSetting(int) */
2672 public int getVibrateSetting(int vibrateType) {
Eric Laurentbffc3d12012-05-07 17:43:49 -07002673 if (!mHasVibrator) return AudioManager.VIBRATE_SETTING_OFF;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002674 return (mVibrateSetting >> (vibrateType * 2)) & 3;
2675 }
2676
2677 /** @see AudioManager#setVibrateSetting(int, int) */
2678 public void setVibrateSetting(int vibrateType, int vibrateSetting) {
2679
Eric Laurentbffc3d12012-05-07 17:43:49 -07002680 if (!mHasVibrator) return;
2681
John Spurlock61560172015-02-06 19:46:04 -05002682 mVibrateSetting = AudioSystem.getValueForVibrateSetting(mVibrateSetting, vibrateType,
2683 vibrateSetting);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002684
2685 // Broadcast change
2686 broadcastVibrateSetting(vibrateType);
2687
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002688 }
2689
Eric Laurent9272b4b2010-01-23 17:12:59 -08002690 private class SetModeDeathHandler implements IBinder.DeathRecipient {
2691 private IBinder mCb; // To be notified of client's death
Marco Nelissenf1ddd512011-08-10 14:15:44 -07002692 private int mPid;
Eric Laurent9272b4b2010-01-23 17:12:59 -08002693 private int mMode = AudioSystem.MODE_NORMAL; // Current mode set by this client
2694
Eric Laurent9f103de2011-09-08 15:04:23 -07002695 SetModeDeathHandler(IBinder cb, int pid) {
Eric Laurent9272b4b2010-01-23 17:12:59 -08002696 mCb = cb;
Eric Laurent9f103de2011-09-08 15:04:23 -07002697 mPid = pid;
Eric Laurent9272b4b2010-01-23 17:12:59 -08002698 }
2699
2700 public void binderDied() {
Eric Laurentd7454be2011-09-14 08:45:58 -07002701 int newModeOwnerPid = 0;
Eric Laurent9272b4b2010-01-23 17:12:59 -08002702 synchronized(mSetModeDeathHandlers) {
2703 Log.w(TAG, "setMode() client died");
2704 int index = mSetModeDeathHandlers.indexOf(this);
2705 if (index < 0) {
2706 Log.w(TAG, "unregistered setMode() client died");
2707 } else {
John Spurlock90874332015-03-10 16:00:54 -04002708 newModeOwnerPid = setModeInt(AudioSystem.MODE_NORMAL, mCb, mPid, TAG);
Eric Laurent9272b4b2010-01-23 17:12:59 -08002709 }
2710 }
Eric Laurent9f103de2011-09-08 15:04:23 -07002711 // when entering RINGTONE, IN_CALL or IN_COMMUNICATION mode, clear all
2712 // SCO connections not started by the application changing the mode
Eric Laurentd7454be2011-09-14 08:45:58 -07002713 if (newModeOwnerPid != 0) {
Eric Laurent6b5e22d2013-03-28 16:10:45 -07002714 final long ident = Binder.clearCallingIdentity();
2715 disconnectBluetoothSco(newModeOwnerPid);
2716 Binder.restoreCallingIdentity(ident);
Eric Laurent9f103de2011-09-08 15:04:23 -07002717 }
Eric Laurent9272b4b2010-01-23 17:12:59 -08002718 }
2719
Marco Nelissenf1ddd512011-08-10 14:15:44 -07002720 public int getPid() {
2721 return mPid;
2722 }
2723
Eric Laurent9272b4b2010-01-23 17:12:59 -08002724 public void setMode(int mode) {
2725 mMode = mode;
2726 }
2727
2728 public int getMode() {
2729 return mMode;
2730 }
2731
2732 public IBinder getBinder() {
2733 return mCb;
2734 }
2735 }
2736
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002737 /** @see AudioManager#setMode(int) */
John Spurlock90874332015-03-10 16:00:54 -04002738 public void setMode(int mode, IBinder cb, String callingPackage) {
2739 if (DEBUG_MODE) { Log.v(TAG, "setMode(mode=" + mode + ", callingPackage=" + callingPackage + ")"); }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002740 if (!checkAudioSettingsPermission("setMode()")) {
2741 return;
2742 }
Eric Laurenta553c252009-07-17 12:17:14 -07002743
Jean-Michel Triviccd654e2014-09-03 17:48:47 -07002744 if ( (mode == AudioSystem.MODE_IN_CALL) &&
2745 (mContext.checkCallingOrSelfPermission(
2746 android.Manifest.permission.MODIFY_PHONE_STATE)
2747 != PackageManager.PERMISSION_GRANTED)) {
2748 Log.w(TAG, "MODIFY_PHONE_STATE Permission Denial: setMode(MODE_IN_CALL) from pid="
2749 + Binder.getCallingPid() + ", uid=" + Binder.getCallingUid());
2750 return;
2751 }
2752
Jean-Michel Trivi8f677d62010-11-15 12:11:32 -08002753 if (mode < AudioSystem.MODE_CURRENT || mode >= AudioSystem.NUM_MODES) {
Eric Laurenta553c252009-07-17 12:17:14 -07002754 return;
2755 }
2756
Eric Laurentd7454be2011-09-14 08:45:58 -07002757 int newModeOwnerPid = 0;
Eric Laurent9f103de2011-09-08 15:04:23 -07002758 synchronized(mSetModeDeathHandlers) {
Eric Laurenta553c252009-07-17 12:17:14 -07002759 if (mode == AudioSystem.MODE_CURRENT) {
2760 mode = mMode;
2761 }
John Spurlock90874332015-03-10 16:00:54 -04002762 newModeOwnerPid = setModeInt(mode, cb, Binder.getCallingPid(), callingPackage);
Eric Laurent9f103de2011-09-08 15:04:23 -07002763 }
2764 // when entering RINGTONE, IN_CALL or IN_COMMUNICATION mode, clear all
2765 // SCO connections not started by the application changing the mode
Eric Laurentd7454be2011-09-14 08:45:58 -07002766 if (newModeOwnerPid != 0) {
2767 disconnectBluetoothSco(newModeOwnerPid);
Eric Laurent9f103de2011-09-08 15:04:23 -07002768 }
2769 }
Jean-Michel Trivi2ade5762010-12-11 13:18:30 -08002770
Eric Laurent9f103de2011-09-08 15:04:23 -07002771 // must be called synchronized on mSetModeDeathHandlers
Eric Laurentd7454be2011-09-14 08:45:58 -07002772 // setModeInt() returns a valid PID if the audio mode was successfully set to
Eric Laurent9f103de2011-09-08 15:04:23 -07002773 // any mode other than NORMAL.
John Spurlock90874332015-03-10 16:00:54 -04002774 private int setModeInt(int mode, IBinder cb, int pid, String caller) {
2775 if (DEBUG_MODE) { Log.v(TAG, "setModeInt(mode=" + mode + ", pid=" + pid + ", caller="
2776 + caller + ")"); }
Eric Laurentd7454be2011-09-14 08:45:58 -07002777 int newModeOwnerPid = 0;
Eric Laurent9f103de2011-09-08 15:04:23 -07002778 if (cb == null) {
2779 Log.e(TAG, "setModeInt() called with null binder");
Eric Laurentd7454be2011-09-14 08:45:58 -07002780 return newModeOwnerPid;
Eric Laurent9f103de2011-09-08 15:04:23 -07002781 }
Jean-Michel Trivi2ade5762010-12-11 13:18:30 -08002782
Eric Laurent9f103de2011-09-08 15:04:23 -07002783 SetModeDeathHandler hdlr = null;
2784 Iterator iter = mSetModeDeathHandlers.iterator();
2785 while (iter.hasNext()) {
2786 SetModeDeathHandler h = (SetModeDeathHandler)iter.next();
2787 if (h.getPid() == pid) {
2788 hdlr = h;
2789 // Remove from client list so that it is re-inserted at top of list
2790 iter.remove();
2791 hdlr.getBinder().unlinkToDeath(hdlr, 0);
2792 break;
2793 }
2794 }
2795 int status = AudioSystem.AUDIO_STATUS_OK;
Eric Laurent6afa6502017-09-28 15:18:19 -07002796 int actualMode;
Eric Laurent9f103de2011-09-08 15:04:23 -07002797 do {
Eric Laurent6afa6502017-09-28 15:18:19 -07002798 actualMode = mode;
Eric Laurent9f103de2011-09-08 15:04:23 -07002799 if (mode == AudioSystem.MODE_NORMAL) {
2800 // get new mode from client at top the list if any
2801 if (!mSetModeDeathHandlers.isEmpty()) {
2802 hdlr = mSetModeDeathHandlers.get(0);
2803 cb = hdlr.getBinder();
Eric Laurent6afa6502017-09-28 15:18:19 -07002804 actualMode = hdlr.getMode();
Jean-Michel Trivi339567d2014-07-29 09:53:34 -07002805 if (DEBUG_MODE) {
2806 Log.w(TAG, " using mode=" + mode + " instead due to death hdlr at pid="
2807 + hdlr.mPid);
2808 }
Eric Laurentb9c9d262009-05-06 08:13:20 -07002809 }
Eric Laurent9f103de2011-09-08 15:04:23 -07002810 } else {
2811 if (hdlr == null) {
2812 hdlr = new SetModeDeathHandler(cb, pid);
2813 }
2814 // Register for client death notification
2815 try {
2816 cb.linkToDeath(hdlr, 0);
2817 } catch (RemoteException e) {
2818 // Client has died!
2819 Log.w(TAG, "setMode() could not link to "+cb+" binder death");
2820 }
2821
2822 // Last client to call setMode() is always at top of client list
2823 // as required by SetModeDeathHandler.binderDied()
2824 mSetModeDeathHandlers.add(0, hdlr);
2825 hdlr.setMode(mode);
2826 }
2827
Eric Laurent6afa6502017-09-28 15:18:19 -07002828 if (actualMode != mMode) {
Eric Laurent66b69672018-01-26 18:30:51 -08002829 final long identity = Binder.clearCallingIdentity();
Eric Laurent6afa6502017-09-28 15:18:19 -07002830 status = AudioSystem.setPhoneState(actualMode);
Eric Laurent66b69672018-01-26 18:30:51 -08002831 Binder.restoreCallingIdentity(identity);
Eric Laurent9f103de2011-09-08 15:04:23 -07002832 if (status == AudioSystem.AUDIO_STATUS_OK) {
Eric Laurent6afa6502017-09-28 15:18:19 -07002833 if (DEBUG_MODE) { Log.v(TAG, " mode successfully set to " + actualMode); }
2834 mMode = actualMode;
Eric Laurent9f103de2011-09-08 15:04:23 -07002835 } else {
2836 if (hdlr != null) {
2837 mSetModeDeathHandlers.remove(hdlr);
2838 cb.unlinkToDeath(hdlr, 0);
2839 }
2840 // force reading new top of mSetModeDeathHandlers stack
Jean-Michel Trivi339567d2014-07-29 09:53:34 -07002841 if (DEBUG_MODE) { Log.w(TAG, " mode set to MODE_NORMAL after phoneState pb"); }
Eric Laurent9f103de2011-09-08 15:04:23 -07002842 mode = AudioSystem.MODE_NORMAL;
2843 }
2844 } else {
2845 status = AudioSystem.AUDIO_STATUS_OK;
2846 }
2847 } while (status != AudioSystem.AUDIO_STATUS_OK && !mSetModeDeathHandlers.isEmpty());
2848
2849 if (status == AudioSystem.AUDIO_STATUS_OK) {
Eric Laurent6afa6502017-09-28 15:18:19 -07002850 if (actualMode != AudioSystem.MODE_NORMAL) {
Eric Laurentd7454be2011-09-14 08:45:58 -07002851 if (mSetModeDeathHandlers.isEmpty()) {
2852 Log.e(TAG, "setMode() different from MODE_NORMAL with empty mode client stack");
2853 } else {
2854 newModeOwnerPid = mSetModeDeathHandlers.get(0).getPid();
2855 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002856 }
Eric Laurent6afa6502017-09-28 15:18:19 -07002857 // Note: newModeOwnerPid is always 0 when actualMode is MODE_NORMAL
2858 mModeLogger.log(
2859 new PhoneStateEvent(caller, pid, mode, newModeOwnerPid, actualMode));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002860 int streamType = getActiveStreamType(AudioManager.USE_DEFAULT_STREAM_TYPE);
Eric Laurent9bc8358d2011-11-18 16:43:31 -08002861 int device = getDeviceForStream(streamType);
Eric Laurent42b041e2013-03-29 11:36:03 -07002862 int index = mStreamStates[mStreamVolumeAlias[streamType]].getIndex(device);
John Spurlock90874332015-03-10 16:00:54 -04002863 setStreamVolumeInt(mStreamVolumeAlias[streamType], index, device, true, caller);
Eric Laurent6d517662012-04-23 18:42:39 -07002864
John Spurlock90874332015-03-10 16:00:54 -04002865 updateStreamVolumeAlias(true /*updateVolumes*/, caller);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002866 }
Eric Laurentd7454be2011-09-14 08:45:58 -07002867 return newModeOwnerPid;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002868 }
2869
2870 /** @see AudioManager#getMode() */
2871 public int getMode() {
2872 return mMode;
2873 }
2874
Eric Laurente78fced2013-03-15 16:03:47 -07002875 //==========================================================================================
2876 // Sound Effects
2877 //==========================================================================================
2878
2879 private static final String TAG_AUDIO_ASSETS = "audio_assets";
2880 private static final String ATTR_VERSION = "version";
2881 private static final String TAG_GROUP = "group";
2882 private static final String ATTR_GROUP_NAME = "name";
2883 private static final String TAG_ASSET = "asset";
2884 private static final String ATTR_ASSET_ID = "id";
2885 private static final String ATTR_ASSET_FILE = "file";
2886
2887 private static final String ASSET_FILE_VERSION = "1.0";
2888 private static final String GROUP_TOUCH_SOUNDS = "touch_sounds";
2889
Glenn Kasten167d1a22013-07-23 16:24:41 -07002890 private static final int SOUND_EFFECTS_LOAD_TIMEOUT_MS = 5000;
Eric Laurent5d3eb44a2013-03-21 15:35:10 -07002891
2892 class LoadSoundEffectReply {
2893 public int mStatus = 1;
2894 };
2895
Eric Laurente78fced2013-03-15 16:03:47 -07002896 private void loadTouchSoundAssetDefaults() {
2897 SOUND_EFFECT_FILES.add("Effect_Tick.ogg");
2898 for (int i = 0; i < AudioManager.NUM_SOUND_EFFECTS; i++) {
2899 SOUND_EFFECT_FILES_MAP[i][0] = 0;
2900 SOUND_EFFECT_FILES_MAP[i][1] = -1;
2901 }
2902 }
2903
2904 private void loadTouchSoundAssets() {
2905 XmlResourceParser parser = null;
2906
Eric Laurent5d3eb44a2013-03-21 15:35:10 -07002907 // only load assets once.
2908 if (!SOUND_EFFECT_FILES.isEmpty()) {
2909 return;
2910 }
2911
Eric Laurente78fced2013-03-15 16:03:47 -07002912 loadTouchSoundAssetDefaults();
2913
2914 try {
2915 parser = mContext.getResources().getXml(com.android.internal.R.xml.audio_assets);
2916
2917 XmlUtils.beginDocument(parser, TAG_AUDIO_ASSETS);
2918 String version = parser.getAttributeValue(null, ATTR_VERSION);
2919 boolean inTouchSoundsGroup = false;
2920
2921 if (ASSET_FILE_VERSION.equals(version)) {
2922 while (true) {
2923 XmlUtils.nextElement(parser);
2924 String element = parser.getName();
2925 if (element == null) {
2926 break;
2927 }
2928 if (element.equals(TAG_GROUP)) {
2929 String name = parser.getAttributeValue(null, ATTR_GROUP_NAME);
2930 if (GROUP_TOUCH_SOUNDS.equals(name)) {
2931 inTouchSoundsGroup = true;
2932 break;
2933 }
2934 }
2935 }
2936 while (inTouchSoundsGroup) {
2937 XmlUtils.nextElement(parser);
2938 String element = parser.getName();
2939 if (element == null) {
2940 break;
2941 }
2942 if (element.equals(TAG_ASSET)) {
2943 String id = parser.getAttributeValue(null, ATTR_ASSET_ID);
2944 String file = parser.getAttributeValue(null, ATTR_ASSET_FILE);
2945 int fx;
2946
2947 try {
2948 Field field = AudioManager.class.getField(id);
2949 fx = field.getInt(null);
2950 } catch (Exception e) {
2951 Log.w(TAG, "Invalid touch sound ID: "+id);
2952 continue;
2953 }
2954
2955 int i = SOUND_EFFECT_FILES.indexOf(file);
2956 if (i == -1) {
2957 i = SOUND_EFFECT_FILES.size();
2958 SOUND_EFFECT_FILES.add(file);
2959 }
2960 SOUND_EFFECT_FILES_MAP[fx][0] = i;
2961 } else {
2962 break;
2963 }
2964 }
2965 }
2966 } catch (Resources.NotFoundException e) {
2967 Log.w(TAG, "audio assets file not found", e);
2968 } catch (XmlPullParserException e) {
2969 Log.w(TAG, "XML parser exception reading touch sound assets", e);
2970 } catch (IOException e) {
2971 Log.w(TAG, "I/O exception reading touch sound assets", e);
2972 } finally {
2973 if (parser != null) {
2974 parser.close();
2975 }
2976 }
2977 }
2978
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002979 /** @see AudioManager#playSoundEffect(int) */
2980 public void playSoundEffect(int effectType) {
Eric Laurent5d3eb44a2013-03-21 15:35:10 -07002981 playSoundEffectVolume(effectType, -1.0f);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002982 }
2983
2984 /** @see AudioManager#playSoundEffect(int, float) */
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002985 public void playSoundEffectVolume(int effectType, float volume) {
Beverlyd6964762018-02-16 14:07:03 -05002986 // do not try to play the sound effect if the system stream is muted
2987 if (isStreamMutedByRingerOrZenMode(STREAM_SYSTEM)) {
2988 return;
2989 }
2990
Natalie Silvanovich559c76d2014-05-01 10:16:24 -07002991 if (effectType >= AudioManager.NUM_SOUND_EFFECTS || effectType < 0) {
2992 Log.w(TAG, "AudioService effectType value " + effectType + " out of range");
2993 return;
2994 }
2995
Eric Laurent5d3eb44a2013-03-21 15:35:10 -07002996 sendMsg(mAudioHandler, MSG_PLAY_SOUND_EFFECT, SENDMSG_QUEUE,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002997 effectType, (int) (volume * 1000), null, 0);
2998 }
2999
3000 /**
3001 * Loads samples into the soundpool.
Glenn Kasten5c17a822011-11-30 09:41:01 -08003002 * This method must be called at first when sound effects are enabled
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003003 */
3004 public boolean loadSoundEffects() {
Eric Laurent5d3eb44a2013-03-21 15:35:10 -07003005 int attempts = 3;
3006 LoadSoundEffectReply reply = new LoadSoundEffectReply();
Eric Laurenta60e2122010-12-28 16:49:07 -08003007
Eric Laurent5d3eb44a2013-03-21 15:35:10 -07003008 synchronized (reply) {
3009 sendMsg(mAudioHandler, MSG_LOAD_SOUND_EFFECTS, SENDMSG_QUEUE, 0, 0, reply, 0);
3010 while ((reply.mStatus == 1) && (attempts-- > 0)) {
Eric Laurent117b7bb2011-01-16 17:07:27 -08003011 try {
Glenn Kasten167d1a22013-07-23 16:24:41 -07003012 reply.wait(SOUND_EFFECTS_LOAD_TIMEOUT_MS);
Eric Laurent5d3eb44a2013-03-21 15:35:10 -07003013 } catch (InterruptedException e) {
3014 Log.w(TAG, "loadSoundEffects Interrupted while waiting sound pool loaded.");
Eric Laurent117b7bb2011-01-16 17:07:27 -08003015 }
Eric Laurenta60e2122010-12-28 16:49:07 -08003016 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003017 }
Eric Laurent5d3eb44a2013-03-21 15:35:10 -07003018 return (reply.mStatus == 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003019 }
3020
3021 /**
3022 * Unloads samples from the sound pool.
3023 * This method can be called to free some memory when
3024 * sound effects are disabled.
3025 */
3026 public void unloadSoundEffects() {
Eric Laurent5d3eb44a2013-03-21 15:35:10 -07003027 sendMsg(mAudioHandler, MSG_UNLOAD_SOUND_EFFECTS, SENDMSG_QUEUE, 0, 0, null, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003028 }
3029
Eric Laurenta60e2122010-12-28 16:49:07 -08003030 class SoundPoolListenerThread extends Thread {
3031 public SoundPoolListenerThread() {
3032 super("SoundPoolListenerThread");
3033 }
3034
3035 @Override
3036 public void run() {
3037
3038 Looper.prepare();
3039 mSoundPoolLooper = Looper.myLooper();
3040
3041 synchronized (mSoundEffectsLock) {
3042 if (mSoundPool != null) {
3043 mSoundPoolCallBack = new SoundPoolCallback();
3044 mSoundPool.setOnLoadCompleteListener(mSoundPoolCallBack);
3045 }
3046 mSoundEffectsLock.notify();
3047 }
3048 Looper.loop();
3049 }
3050 }
3051
3052 private final class SoundPoolCallback implements
3053 android.media.SoundPool.OnLoadCompleteListener {
3054
Eric Laurent5d3eb44a2013-03-21 15:35:10 -07003055 int mStatus = 1; // 1 means neither error nor last sample loaded yet
3056 List<Integer> mSamples = new ArrayList<Integer>();
Eric Laurenta60e2122010-12-28 16:49:07 -08003057
3058 public int status() {
3059 return mStatus;
3060 }
3061
Eric Laurent5d3eb44a2013-03-21 15:35:10 -07003062 public void setSamples(int[] samples) {
3063 for (int i = 0; i < samples.length; i++) {
3064 // do not wait ack for samples rejected upfront by SoundPool
3065 if (samples[i] > 0) {
3066 mSamples.add(samples[i]);
3067 }
3068 }
Eric Laurenta60e2122010-12-28 16:49:07 -08003069 }
3070
3071 public void onLoadComplete(SoundPool soundPool, int sampleId, int status) {
3072 synchronized (mSoundEffectsLock) {
Eric Laurent5d3eb44a2013-03-21 15:35:10 -07003073 int i = mSamples.indexOf(sampleId);
3074 if (i >= 0) {
3075 mSamples.remove(i);
Eric Laurenta60e2122010-12-28 16:49:07 -08003076 }
Eric Laurent5d3eb44a2013-03-21 15:35:10 -07003077 if ((status != 0) || mSamples. isEmpty()) {
3078 mStatus = status;
Eric Laurenta60e2122010-12-28 16:49:07 -08003079 mSoundEffectsLock.notify();
3080 }
3081 }
3082 }
3083 }
3084
Eric Laurent4050c932009-07-08 02:52:14 -07003085 /** @see AudioManager#reloadAudioSettings() */
3086 public void reloadAudioSettings() {
Eric Laurentbc0fab1f2012-09-19 11:24:41 -07003087 readAudioSettings(false /*userSwitch*/);
3088 }
3089
3090 private void readAudioSettings(boolean userSwitch) {
Eric Laurent4050c932009-07-08 02:52:14 -07003091 // restore ringer mode, ringer mode affected streams, mute affected streams and vibrate settings
3092 readPersistedSettings();
Eric Laurentc0232482016-03-15 18:19:23 -07003093 readUserRestrictions();
Eric Laurent4050c932009-07-08 02:52:14 -07003094
3095 // restore volume settings
3096 int numStreamTypes = AudioSystem.getNumStreamTypes();
3097 for (int streamType = 0; streamType < numStreamTypes; streamType++) {
3098 VolumeStreamState streamState = mStreamStates[streamType];
3099
Eric Laurentbc0fab1f2012-09-19 11:24:41 -07003100 if (userSwitch && mStreamVolumeAlias[streamType] == AudioSystem.STREAM_MUSIC) {
3101 continue;
3102 }
3103
Eric Laurent8fa4d6f2014-10-30 14:13:03 -07003104 streamState.readSettings();
3105 synchronized (VolumeStreamState.class) {
Eric Laurent3172d5e2012-05-09 11:38:16 -07003106 // unmute stream that was muted but is not affect by mute anymore
RoboErik4197cb62015-01-21 15:45:32 -08003107 if (streamState.mIsMuted && ((!isStreamAffectedByMute(streamType) &&
Beverlyd6964762018-02-16 14:07:03 -05003108 !isStreamMutedByRingerOrZenMode(streamType)) || mUseFixedVolume)) {
RoboErik4197cb62015-01-21 15:45:32 -08003109 streamState.mIsMuted = false;
Eric Laurent4050c932009-07-08 02:52:14 -07003110 }
Eric Laurent4050c932009-07-08 02:52:14 -07003111 }
3112 }
3113
Eric Laurent33902db2012-10-07 16:15:07 -07003114 // apply new ringer mode before checking volume for alias streams so that streams
3115 // muted by ringer mode have the correct volume
John Spurlock661f2cf2014-11-17 10:29:10 -05003116 setRingerModeInt(getRingerModeInternal(), false);
Eric Laurent33902db2012-10-07 16:15:07 -07003117
Eric Laurent212532b2014-07-21 15:43:18 -07003118 checkAllFixedVolumeDevices();
Eric Laurent24482012012-05-10 09:41:17 -07003119 checkAllAliasStreamVolumes();
John Spurlockb6e19e32015-03-10 21:33:44 -04003120 checkMuteAffectedStreams();
Eric Laurent24482012012-05-10 09:41:17 -07003121
Eric Laurentd640bd32012-09-28 18:01:48 -07003122 synchronized (mSafeMediaVolumeState) {
John Spurlockaa5ee4d2014-07-25 13:05:12 -04003123 mMusicActiveMs = MathUtils.constrain(Settings.Secure.getIntForUser(mContentResolver,
3124 Settings.Secure.UNSAFE_VOLUME_MUSIC_ACTIVE_MS, 0, UserHandle.USER_CURRENT),
3125 0, UNSAFE_VOLUME_MUSIC_ACTIVE_MS_MAX);
Eric Laurentd640bd32012-09-28 18:01:48 -07003126 if (mSafeMediaVolumeState == SAFE_MEDIA_VOLUME_ACTIVE) {
John Spurlock90874332015-03-10 16:00:54 -04003127 enforceSafeMediaVolume(TAG);
Eric Laurentf1a457d2012-09-20 16:27:23 -07003128 }
Eric Laurentc34dcc12012-09-10 13:51:52 -07003129 }
Eric Laurent4050c932009-07-08 02:52:14 -07003130 }
3131
Dianne Hackborn961cae92013-03-20 14:59:43 -07003132 /** @see AudioManager#setSpeakerphoneOn(boolean) */
Eric Laurentc42ac9d2009-07-29 08:53:03 -07003133 public void setSpeakerphoneOn(boolean on){
Eric Laurentdc1d17a2009-09-10 00:48:21 -07003134 if (!checkAudioSettingsPermission("setSpeakerphoneOn()")) {
3135 return;
3136 }
Jean-Michel Trivi011f39e2017-08-19 18:08:06 -07003137 // for logging only
3138 final String eventSource = new StringBuilder("setSpeakerphoneOn(").append(on)
3139 .append(") from u/pid:").append(Binder.getCallingUid()).append("/")
3140 .append(Binder.getCallingPid()).toString();
Johan Gustavsson7337bee2013-03-01 15:53:30 +01003141
3142 if (on) {
3143 if (mForcedUseForComm == AudioSystem.FORCE_BT_SCO) {
3144 sendMsg(mAudioHandler, MSG_SET_FORCE_USE, SENDMSG_QUEUE,
Jean-Michel Trivi011f39e2017-08-19 18:08:06 -07003145 AudioSystem.FOR_RECORD, AudioSystem.FORCE_NONE,
3146 eventSource, 0);
Johan Gustavsson7337bee2013-03-01 15:53:30 +01003147 }
3148 mForcedUseForComm = AudioSystem.FORCE_SPEAKER;
3149 } else if (mForcedUseForComm == AudioSystem.FORCE_SPEAKER){
3150 mForcedUseForComm = AudioSystem.FORCE_NONE;
3151 }
Eric Laurentfa640152011-03-12 15:59:51 -08003152
Sharad Sangle1d188442017-05-09 16:05:40 +05303153 mForcedUseForCommExt = mForcedUseForComm;
Eric Laurentafbb0472011-12-15 09:04:23 -08003154 sendMsg(mAudioHandler, MSG_SET_FORCE_USE, SENDMSG_QUEUE,
Jean-Michel Trivi011f39e2017-08-19 18:08:06 -07003155 AudioSystem.FOR_COMMUNICATION, mForcedUseForComm, eventSource, 0);
Eric Laurentc42ac9d2009-07-29 08:53:03 -07003156 }
3157
3158 /** @see AudioManager#isSpeakerphoneOn() */
3159 public boolean isSpeakerphoneOn() {
Sharad Sangle1d188442017-05-09 16:05:40 +05303160 return (mForcedUseForCommExt == AudioSystem.FORCE_SPEAKER);
Eric Laurentc42ac9d2009-07-29 08:53:03 -07003161 }
3162
Dianne Hackborn961cae92013-03-20 14:59:43 -07003163 /** @see AudioManager#setBluetoothScoOn(boolean) */
Eric Laurent48221252015-09-24 18:41:48 -07003164 public void setBluetoothScoOn(boolean on) {
Eric Laurentdc1d17a2009-09-10 00:48:21 -07003165 if (!checkAudioSettingsPermission("setBluetoothScoOn()")) {
3166 return;
3167 }
Sharad Sangle1d188442017-05-09 16:05:40 +05303168
3169 // Only enable calls from system components
3170 if (Binder.getCallingUid() >= FIRST_APPLICATION_UID) {
3171 mForcedUseForCommExt = on ? AudioSystem.FORCE_BT_SCO : AudioSystem.FORCE_NONE;
3172 return;
3173 }
3174
Jean-Michel Trivi011f39e2017-08-19 18:08:06 -07003175 // for logging only
3176 final String eventSource = new StringBuilder("setBluetoothScoOn(").append(on)
3177 .append(") from u/pid:").append(Binder.getCallingUid()).append("/")
3178 .append(Binder.getCallingPid()).toString();
3179 setBluetoothScoOnInt(on, eventSource);
Eric Laurent48221252015-09-24 18:41:48 -07003180 }
Johan Gustavsson7337bee2013-03-01 15:53:30 +01003181
Jean-Michel Trivi011f39e2017-08-19 18:08:06 -07003182 public void setBluetoothScoOnInt(boolean on, String eventSource) {
Jack He8dd33942018-01-17 15:45:12 -08003183 if (DEBUG_DEVICES) {
3184 Log.d(TAG, "setBluetoothScoOnInt: " + on + " " + eventSource);
3185 }
Johan Gustavsson7337bee2013-03-01 15:53:30 +01003186 if (on) {
Sharad Sangle1d188442017-05-09 16:05:40 +05303187 // do not accept SCO ON if SCO audio is not connected
Jack He8dd33942018-01-17 15:45:12 -08003188 synchronized (mScoClients) {
3189 if (mBluetoothHeadset != null) {
3190 if (mBluetoothHeadsetDevice == null) {
3191 BluetoothDevice activeDevice = mBluetoothHeadset.getActiveDevice();
3192 if (activeDevice != null) {
3193 // setBtScoActiveDevice() might trigger resetBluetoothSco() which
3194 // will call setBluetoothScoOnInt(false, "resetBluetoothSco")
3195 setBtScoActiveDevice(activeDevice);
3196 }
3197 }
3198 if (mBluetoothHeadset.getAudioState(mBluetoothHeadsetDevice)
3199 != BluetoothHeadset.STATE_AUDIO_CONNECTED) {
3200 mForcedUseForCommExt = AudioSystem.FORCE_BT_SCO;
3201 Log.w(TAG, "setBluetoothScoOnInt(true) failed because "
3202 + mBluetoothHeadsetDevice + " is not in audio connected mode");
3203 return;
3204 }
Sharad Sangle1d188442017-05-09 16:05:40 +05303205 }
3206 }
Johan Gustavsson7337bee2013-03-01 15:53:30 +01003207 mForcedUseForComm = AudioSystem.FORCE_BT_SCO;
3208 } else if (mForcedUseForComm == AudioSystem.FORCE_BT_SCO) {
3209 mForcedUseForComm = AudioSystem.FORCE_NONE;
3210 }
Sharad Sangle1d188442017-05-09 16:05:40 +05303211 mForcedUseForCommExt = mForcedUseForComm;
3212 AudioSystem.setParameters("BT_SCO="+ (on ? "on" : "off"));
Eric Laurentafbb0472011-12-15 09:04:23 -08003213 sendMsg(mAudioHandler, MSG_SET_FORCE_USE, SENDMSG_QUEUE,
Jean-Michel Trivi011f39e2017-08-19 18:08:06 -07003214 AudioSystem.FOR_COMMUNICATION, mForcedUseForComm, eventSource, 0);
Eric Laurentafbb0472011-12-15 09:04:23 -08003215 sendMsg(mAudioHandler, MSG_SET_FORCE_USE, SENDMSG_QUEUE,
Jean-Michel Trivi011f39e2017-08-19 18:08:06 -07003216 AudioSystem.FOR_RECORD, mForcedUseForComm, eventSource, 0);
Jack He6dd78c12018-02-12 21:00:24 -08003217 // Un-mute ringtone stream volume
3218 setRingerModeInt(getRingerModeInternal(), false);
Eric Laurentc42ac9d2009-07-29 08:53:03 -07003219 }
3220
3221 /** @see AudioManager#isBluetoothScoOn() */
3222 public boolean isBluetoothScoOn() {
Sharad Sangle1d188442017-05-09 16:05:40 +05303223 return (mForcedUseForCommExt == AudioSystem.FORCE_BT_SCO);
Eric Laurentc42ac9d2009-07-29 08:53:03 -07003224 }
3225
Sungsoocf09fe62016-09-28 16:21:48 +09003226 /** @see AudioManager#setBluetoothA2dpOn(boolean) */
Eric Laurent78472112012-05-21 08:57:21 -07003227 public void setBluetoothA2dpOn(boolean on) {
Jean-Michel Trivi011f39e2017-08-19 18:08:06 -07003228 // for logging only
3229 final String eventSource = new StringBuilder("setBluetoothA2dpOn(").append(on)
3230 .append(") from u/pid:").append(Binder.getCallingUid()).append("/")
3231 .append(Binder.getCallingPid()).toString();
3232
Sungsoocf09fe62016-09-28 16:21:48 +09003233 synchronized (mBluetoothA2dpEnabledLock) {
3234 mBluetoothA2dpEnabled = on;
3235 sendMsg(mAudioHandler, MSG_SET_FORCE_BT_A2DP_USE, SENDMSG_QUEUE,
3236 AudioSystem.FOR_MEDIA,
3237 mBluetoothA2dpEnabled ? AudioSystem.FORCE_NONE : AudioSystem.FORCE_NO_BT_A2DP,
Jean-Michel Trivi011f39e2017-08-19 18:08:06 -07003238 eventSource, 0);
Sungsoocf09fe62016-09-28 16:21:48 +09003239 }
Eric Laurent78472112012-05-21 08:57:21 -07003240 }
3241
Sungsoocf09fe62016-09-28 16:21:48 +09003242 /** @see AudioManager#isBluetoothA2dpOn() */
Eric Laurent78472112012-05-21 08:57:21 -07003243 public boolean isBluetoothA2dpOn() {
Sungsoocf09fe62016-09-28 16:21:48 +09003244 synchronized (mBluetoothA2dpEnabledLock) {
3245 return mBluetoothA2dpEnabled;
3246 }
Eric Laurent78472112012-05-21 08:57:21 -07003247 }
3248
Eric Laurent3def1ee2010-03-17 23:26:26 -07003249 /** @see AudioManager#startBluetoothSco() */
Eric Laurent83900752014-05-15 15:14:22 -07003250 public void startBluetoothSco(IBinder cb, int targetSdkVersion) {
3251 int scoAudioMode =
3252 (targetSdkVersion < Build.VERSION_CODES.JELLY_BEAN_MR2) ?
Liejun Taof4e51d82014-07-16 11:18:29 -07003253 SCO_MODE_VIRTUAL_CALL : SCO_MODE_UNDEFINED;
Eric Laurent83900752014-05-15 15:14:22 -07003254 startBluetoothScoInt(cb, scoAudioMode);
3255 }
3256
3257 /** @see AudioManager#startBluetoothScoVirtualCall() */
3258 public void startBluetoothScoVirtualCall(IBinder cb) {
3259 startBluetoothScoInt(cb, SCO_MODE_VIRTUAL_CALL);
3260 }
3261
3262 void startBluetoothScoInt(IBinder cb, int scoAudioMode){
Eric Laurentdc03c612011-04-01 10:59:41 -07003263 if (!checkAudioSettingsPermission("startBluetoothSco()") ||
Eric Laurent4a5eeb92014-05-06 10:49:04 -07003264 !mSystemReady) {
Eric Laurent3def1ee2010-03-17 23:26:26 -07003265 return;
3266 }
Eric Laurent854938a2011-02-22 12:05:20 -08003267 ScoClient client = getScoClient(cb, true);
Eric Laurentf5a1fc32013-03-11 18:52:57 -07003268 // The calling identity must be cleared before calling ScoClient.incCount().
3269 // inCount() calls requestScoState() which in turn can call BluetoothHeadset APIs
3270 // and this must be done on behalf of system server to make sure permissions are granted.
3271 // The caller identity must be cleared after getScoClient() because it is needed if a new
3272 // client is created.
3273 final long ident = Binder.clearCallingIdentity();
Eric Laurent83900752014-05-15 15:14:22 -07003274 client.incCount(scoAudioMode);
Eric Laurent2a57ca92013-03-07 17:29:27 -08003275 Binder.restoreCallingIdentity(ident);
Eric Laurent3def1ee2010-03-17 23:26:26 -07003276 }
3277
3278 /** @see AudioManager#stopBluetoothSco() */
3279 public void stopBluetoothSco(IBinder cb){
Eric Laurentdc03c612011-04-01 10:59:41 -07003280 if (!checkAudioSettingsPermission("stopBluetoothSco()") ||
Eric Laurent4a5eeb92014-05-06 10:49:04 -07003281 !mSystemReady) {
Eric Laurent3def1ee2010-03-17 23:26:26 -07003282 return;
3283 }
Eric Laurent854938a2011-02-22 12:05:20 -08003284 ScoClient client = getScoClient(cb, false);
Eric Laurentf5a1fc32013-03-11 18:52:57 -07003285 // The calling identity must be cleared before calling ScoClient.decCount().
3286 // decCount() calls requestScoState() which in turn can call BluetoothHeadset APIs
3287 // and this must be done on behalf of system server to make sure permissions are granted.
3288 final long ident = Binder.clearCallingIdentity();
Eric Laurent854938a2011-02-22 12:05:20 -08003289 if (client != null) {
3290 client.decCount();
3291 }
Eric Laurent2a57ca92013-03-07 17:29:27 -08003292 Binder.restoreCallingIdentity(ident);
Eric Laurent3def1ee2010-03-17 23:26:26 -07003293 }
3294
Eric Laurent78472112012-05-21 08:57:21 -07003295
Eric Laurent3def1ee2010-03-17 23:26:26 -07003296 private class ScoClient implements IBinder.DeathRecipient {
3297 private IBinder mCb; // To be notified of client's death
Marco Nelissenf1ddd512011-08-10 14:15:44 -07003298 private int mCreatorPid;
Eric Laurent3def1ee2010-03-17 23:26:26 -07003299 private int mStartcount; // number of SCO connections started by this client
3300
3301 ScoClient(IBinder cb) {
3302 mCb = cb;
Marco Nelissenf1ddd512011-08-10 14:15:44 -07003303 mCreatorPid = Binder.getCallingPid();
Eric Laurent3def1ee2010-03-17 23:26:26 -07003304 mStartcount = 0;
3305 }
3306
3307 public void binderDied() {
3308 synchronized(mScoClients) {
3309 Log.w(TAG, "SCO client died");
3310 int index = mScoClients.indexOf(this);
3311 if (index < 0) {
3312 Log.w(TAG, "unregistered SCO client died");
3313 } else {
3314 clearCount(true);
3315 mScoClients.remove(this);
3316 }
3317 }
3318 }
3319
Eric Laurent83900752014-05-15 15:14:22 -07003320 public void incCount(int scoAudioMode) {
Eric Laurent3def1ee2010-03-17 23:26:26 -07003321 synchronized(mScoClients) {
Eric Laurent83900752014-05-15 15:14:22 -07003322 requestScoState(BluetoothHeadset.STATE_AUDIO_CONNECTED, scoAudioMode);
Eric Laurent3def1ee2010-03-17 23:26:26 -07003323 if (mStartcount == 0) {
3324 try {
3325 mCb.linkToDeath(this, 0);
3326 } catch (RemoteException e) {
3327 // client has already died!
3328 Log.w(TAG, "ScoClient incCount() could not link to "+mCb+" binder death");
3329 }
3330 }
3331 mStartcount++;
3332 }
3333 }
3334
3335 public void decCount() {
3336 synchronized(mScoClients) {
3337 if (mStartcount == 0) {
3338 Log.w(TAG, "ScoClient.decCount() already 0");
3339 } else {
3340 mStartcount--;
3341 if (mStartcount == 0) {
Eric Laurente2dd8c42010-06-30 19:41:56 -07003342 try {
3343 mCb.unlinkToDeath(this, 0);
3344 } catch (NoSuchElementException e) {
3345 Log.w(TAG, "decCount() going to 0 but not registered to binder");
3346 }
Eric Laurent3def1ee2010-03-17 23:26:26 -07003347 }
Eric Laurentc18c9132013-04-12 17:24:56 -07003348 requestScoState(BluetoothHeadset.STATE_AUDIO_DISCONNECTED, 0);
Eric Laurent3def1ee2010-03-17 23:26:26 -07003349 }
3350 }
3351 }
3352
3353 public void clearCount(boolean stopSco) {
3354 synchronized(mScoClients) {
Eric Laurente2dd8c42010-06-30 19:41:56 -07003355 if (mStartcount != 0) {
3356 try {
3357 mCb.unlinkToDeath(this, 0);
3358 } catch (NoSuchElementException e) {
3359 Log.w(TAG, "clearCount() mStartcount: "+mStartcount+" != 0 but not registered to binder");
3360 }
3361 }
Eric Laurent3def1ee2010-03-17 23:26:26 -07003362 mStartcount = 0;
Eric Laurent3def1ee2010-03-17 23:26:26 -07003363 if (stopSco) {
Eric Laurentc18c9132013-04-12 17:24:56 -07003364 requestScoState(BluetoothHeadset.STATE_AUDIO_DISCONNECTED, 0);
Eric Laurent3def1ee2010-03-17 23:26:26 -07003365 }
3366 }
3367 }
3368
3369 public int getCount() {
3370 return mStartcount;
3371 }
3372
3373 public IBinder getBinder() {
3374 return mCb;
3375 }
3376
Eric Laurentd7454be2011-09-14 08:45:58 -07003377 public int getPid() {
3378 return mCreatorPid;
3379 }
3380
Eric Laurent3def1ee2010-03-17 23:26:26 -07003381 public int totalCount() {
3382 synchronized(mScoClients) {
3383 int count = 0;
3384 int size = mScoClients.size();
3385 for (int i = 0; i < size; i++) {
3386 count += mScoClients.get(i).getCount();
3387 }
3388 return count;
3389 }
3390 }
3391
Eric Laurent83900752014-05-15 15:14:22 -07003392 private void requestScoState(int state, int scoAudioMode) {
Eric Laurent62ef7672010-11-24 10:58:32 -08003393 checkScoAudioState();
Eric Laurentdc03c612011-04-01 10:59:41 -07003394 if (totalCount() == 0) {
3395 if (state == BluetoothHeadset.STATE_AUDIO_CONNECTED) {
3396 // Make sure that the state transitions to CONNECTING even if we cannot initiate
3397 // the connection.
3398 broadcastScoConnectionState(AudioManager.SCO_AUDIO_STATE_CONNECTING);
3399 // Accept SCO audio activation only in NORMAL audio mode or if the mode is
Marco Nelissenf1ddd512011-08-10 14:15:44 -07003400 // currently controlled by the same client process.
Eric Laurent9f103de2011-09-08 15:04:23 -07003401 synchronized(mSetModeDeathHandlers) {
3402 if ((mSetModeDeathHandlers.isEmpty() ||
3403 mSetModeDeathHandlers.get(0).getPid() == mCreatorPid) &&
3404 (mScoAudioState == SCO_STATE_INACTIVE ||
3405 mScoAudioState == SCO_STATE_DEACTIVATE_REQ)) {
3406 if (mScoAudioState == SCO_STATE_INACTIVE) {
Eric Laurent83900752014-05-15 15:14:22 -07003407 mScoAudioMode = scoAudioMode;
Liejun Taof4e51d82014-07-16 11:18:29 -07003408 if (scoAudioMode == SCO_MODE_UNDEFINED) {
Andre Eisenbach570cc532014-10-28 17:03:18 -07003409 if (mBluetoothHeadsetDevice != null) {
3410 mScoAudioMode = new Integer(Settings.Global.getInt(
3411 mContentResolver,
3412 "bluetooth_sco_channel_"+
3413 mBluetoothHeadsetDevice.getAddress(),
3414 SCO_MODE_VIRTUAL_CALL));
3415 if (mScoAudioMode > SCO_MODE_MAX || mScoAudioMode < 0) {
3416 mScoAudioMode = SCO_MODE_VIRTUAL_CALL;
3417 }
3418 } else {
3419 mScoAudioMode = SCO_MODE_RAW;
Liejun Taof4e51d82014-07-16 11:18:29 -07003420 }
3421 }
Eric Laurent9f103de2011-09-08 15:04:23 -07003422 if (mBluetoothHeadset != null && mBluetoothHeadsetDevice != null) {
Liejun Taof4e51d82014-07-16 11:18:29 -07003423 boolean status = false;
Eric Laurentc18c9132013-04-12 17:24:56 -07003424 if (mScoAudioMode == SCO_MODE_RAW) {
3425 status = mBluetoothHeadset.connectAudio();
Liejun Taof4e51d82014-07-16 11:18:29 -07003426 } else if (mScoAudioMode == SCO_MODE_VIRTUAL_CALL) {
Eric Laurentc18c9132013-04-12 17:24:56 -07003427 status = mBluetoothHeadset.startScoUsingVirtualVoiceCall(
3428 mBluetoothHeadsetDevice);
Liejun Taof4e51d82014-07-16 11:18:29 -07003429 } else if (mScoAudioMode == SCO_MODE_VR) {
3430 status = mBluetoothHeadset.startVoiceRecognition(
3431 mBluetoothHeadsetDevice);
Eric Laurentc18c9132013-04-12 17:24:56 -07003432 }
Liejun Taof4e51d82014-07-16 11:18:29 -07003433
Eric Laurentc18c9132013-04-12 17:24:56 -07003434 if (status) {
Eric Laurent9f103de2011-09-08 15:04:23 -07003435 mScoAudioState = SCO_STATE_ACTIVE_INTERNAL;
3436 } else {
3437 broadcastScoConnectionState(
3438 AudioManager.SCO_AUDIO_STATE_DISCONNECTED);
3439 }
3440 } else if (getBluetoothHeadset()) {
3441 mScoAudioState = SCO_STATE_ACTIVATE_REQ;
Eric Laurentdc03c612011-04-01 10:59:41 -07003442 }
Eric Laurent9f103de2011-09-08 15:04:23 -07003443 } else {
3444 mScoAudioState = SCO_STATE_ACTIVE_INTERNAL;
3445 broadcastScoConnectionState(AudioManager.SCO_AUDIO_STATE_CONNECTED);
Eric Laurentdc03c612011-04-01 10:59:41 -07003446 }
3447 } else {
Eric Laurent9f103de2011-09-08 15:04:23 -07003448 broadcastScoConnectionState(AudioManager.SCO_AUDIO_STATE_DISCONNECTED);
Eric Laurentdc03c612011-04-01 10:59:41 -07003449 }
Eric Laurentdc03c612011-04-01 10:59:41 -07003450 }
Eric Laurent62ef7672010-11-24 10:58:32 -08003451 } else if (state == BluetoothHeadset.STATE_AUDIO_DISCONNECTED &&
Eric Laurentdc03c612011-04-01 10:59:41 -07003452 (mScoAudioState == SCO_STATE_ACTIVE_INTERNAL ||
3453 mScoAudioState == SCO_STATE_ACTIVATE_REQ)) {
3454 if (mScoAudioState == SCO_STATE_ACTIVE_INTERNAL) {
Marco Nelissen671db6f2011-09-06 16:29:12 -07003455 if (mBluetoothHeadset != null && mBluetoothHeadsetDevice != null) {
Liejun Taof4e51d82014-07-16 11:18:29 -07003456 boolean status = false;
Eric Laurentc18c9132013-04-12 17:24:56 -07003457 if (mScoAudioMode == SCO_MODE_RAW) {
3458 status = mBluetoothHeadset.disconnectAudio();
Liejun Taof4e51d82014-07-16 11:18:29 -07003459 } else if (mScoAudioMode == SCO_MODE_VIRTUAL_CALL) {
Eric Laurentc18c9132013-04-12 17:24:56 -07003460 status = mBluetoothHeadset.stopScoUsingVirtualVoiceCall(
3461 mBluetoothHeadsetDevice);
Liejun Taof4e51d82014-07-16 11:18:29 -07003462 } else if (mScoAudioMode == SCO_MODE_VR) {
3463 status = mBluetoothHeadset.stopVoiceRecognition(
3464 mBluetoothHeadsetDevice);
Eric Laurentc18c9132013-04-12 17:24:56 -07003465 }
Liejun Taof4e51d82014-07-16 11:18:29 -07003466
Eric Laurentc18c9132013-04-12 17:24:56 -07003467 if (!status) {
Eric Laurentdc03c612011-04-01 10:59:41 -07003468 mScoAudioState = SCO_STATE_INACTIVE;
3469 broadcastScoConnectionState(
3470 AudioManager.SCO_AUDIO_STATE_DISCONNECTED);
3471 }
3472 } else if (getBluetoothHeadset()) {
3473 mScoAudioState = SCO_STATE_DEACTIVATE_REQ;
3474 }
3475 } else {
3476 mScoAudioState = SCO_STATE_INACTIVE;
3477 broadcastScoConnectionState(AudioManager.SCO_AUDIO_STATE_DISCONNECTED);
3478 }
Eric Laurent3def1ee2010-03-17 23:26:26 -07003479 }
3480 }
3481 }
3482 }
3483
Eric Laurent62ef7672010-11-24 10:58:32 -08003484 private void checkScoAudioState() {
3485 if (mBluetoothHeadset != null && mBluetoothHeadsetDevice != null &&
Eric Laurentdc03c612011-04-01 10:59:41 -07003486 mScoAudioState == SCO_STATE_INACTIVE &&
Eric Laurent62ef7672010-11-24 10:58:32 -08003487 mBluetoothHeadset.getAudioState(mBluetoothHeadsetDevice)
3488 != BluetoothHeadset.STATE_AUDIO_DISCONNECTED) {
3489 mScoAudioState = SCO_STATE_ACTIVE_EXTERNAL;
3490 }
3491 }
3492
Eric Laurent854938a2011-02-22 12:05:20 -08003493 private ScoClient getScoClient(IBinder cb, boolean create) {
Eric Laurent3def1ee2010-03-17 23:26:26 -07003494 synchronized(mScoClients) {
Eric Laurent854938a2011-02-22 12:05:20 -08003495 ScoClient client = null;
Eric Laurent3def1ee2010-03-17 23:26:26 -07003496 int size = mScoClients.size();
3497 for (int i = 0; i < size; i++) {
3498 client = mScoClients.get(i);
3499 if (client.getBinder() == cb)
3500 return client;
3501 }
Eric Laurent854938a2011-02-22 12:05:20 -08003502 if (create) {
3503 client = new ScoClient(cb);
3504 mScoClients.add(client);
3505 }
Eric Laurent3def1ee2010-03-17 23:26:26 -07003506 return client;
3507 }
3508 }
3509
Eric Laurentd7454be2011-09-14 08:45:58 -07003510 public void clearAllScoClients(int exceptPid, boolean stopSco) {
Eric Laurent3def1ee2010-03-17 23:26:26 -07003511 synchronized(mScoClients) {
Eric Laurent854938a2011-02-22 12:05:20 -08003512 ScoClient savedClient = null;
Eric Laurent3def1ee2010-03-17 23:26:26 -07003513 int size = mScoClients.size();
3514 for (int i = 0; i < size; i++) {
Eric Laurent854938a2011-02-22 12:05:20 -08003515 ScoClient cl = mScoClients.get(i);
Eric Laurentd7454be2011-09-14 08:45:58 -07003516 if (cl.getPid() != exceptPid) {
Eric Laurent854938a2011-02-22 12:05:20 -08003517 cl.clearCount(stopSco);
3518 } else {
3519 savedClient = cl;
3520 }
3521 }
3522 mScoClients.clear();
3523 if (savedClient != null) {
3524 mScoClients.add(savedClient);
Eric Laurent3def1ee2010-03-17 23:26:26 -07003525 }
3526 }
3527 }
3528
Eric Laurentdc03c612011-04-01 10:59:41 -07003529 private boolean getBluetoothHeadset() {
3530 boolean result = false;
3531 BluetoothAdapter adapter = BluetoothAdapter.getDefaultAdapter();
3532 if (adapter != null) {
3533 result = adapter.getProfileProxy(mContext, mBluetoothProfileServiceListener,
3534 BluetoothProfile.HEADSET);
3535 }
3536 // If we could not get a bluetooth headset proxy, send a failure message
3537 // without delay to reset the SCO audio state and clear SCO clients.
3538 // If we could get a proxy, send a delayed failure message that will reset our state
3539 // in case we don't receive onServiceConnected().
Eric Laurentafbb0472011-12-15 09:04:23 -08003540 sendMsg(mAudioHandler, MSG_BT_HEADSET_CNCT_FAILED,
Eric Laurentdc03c612011-04-01 10:59:41 -07003541 SENDMSG_REPLACE, 0, 0, null, result ? BT_HEADSET_CNCT_TIMEOUT_MS : 0);
3542 return result;
3543 }
3544
Eric Laurentd7454be2011-09-14 08:45:58 -07003545 private void disconnectBluetoothSco(int exceptPid) {
Eric Laurentdc03c612011-04-01 10:59:41 -07003546 synchronized(mScoClients) {
3547 checkScoAudioState();
3548 if (mScoAudioState == SCO_STATE_ACTIVE_EXTERNAL ||
3549 mScoAudioState == SCO_STATE_DEACTIVATE_EXT_REQ) {
3550 if (mBluetoothHeadsetDevice != null) {
3551 if (mBluetoothHeadset != null) {
3552 if (!mBluetoothHeadset.stopVoiceRecognition(
Eric Laurentb06ac832011-05-25 15:55:18 -07003553 mBluetoothHeadsetDevice)) {
Eric Laurentafbb0472011-12-15 09:04:23 -08003554 sendMsg(mAudioHandler, MSG_BT_HEADSET_CNCT_FAILED,
Eric Laurentdc03c612011-04-01 10:59:41 -07003555 SENDMSG_REPLACE, 0, 0, null, 0);
3556 }
3557 } else if (mScoAudioState == SCO_STATE_ACTIVE_EXTERNAL &&
3558 getBluetoothHeadset()) {
3559 mScoAudioState = SCO_STATE_DEACTIVATE_EXT_REQ;
3560 }
3561 }
3562 } else {
Eric Laurentd7454be2011-09-14 08:45:58 -07003563 clearAllScoClients(exceptPid, true);
Eric Laurentdc03c612011-04-01 10:59:41 -07003564 }
3565 }
3566 }
3567
3568 private void resetBluetoothSco() {
3569 synchronized(mScoClients) {
Eric Laurentd7454be2011-09-14 08:45:58 -07003570 clearAllScoClients(0, false);
Eric Laurentdc03c612011-04-01 10:59:41 -07003571 mScoAudioState = SCO_STATE_INACTIVE;
3572 broadcastScoConnectionState(AudioManager.SCO_AUDIO_STATE_DISCONNECTED);
3573 }
Eric Laurent48221252015-09-24 18:41:48 -07003574 AudioSystem.setParameters("A2dpSuspended=false");
Jean-Michel Trivi011f39e2017-08-19 18:08:06 -07003575 setBluetoothScoOnInt(false, "resetBluetoothSco");
Eric Laurentdc03c612011-04-01 10:59:41 -07003576 }
3577
3578 private void broadcastScoConnectionState(int state) {
Eric Laurent2a57ca92013-03-07 17:29:27 -08003579 sendMsg(mAudioHandler, MSG_BROADCAST_BT_CONNECTION_STATE,
3580 SENDMSG_QUEUE, state, 0, null, 0);
3581 }
3582
3583 private void onBroadcastScoConnectionState(int state) {
Eric Laurentdc03c612011-04-01 10:59:41 -07003584 if (state != mScoConnectionState) {
3585 Intent newIntent = new Intent(AudioManager.ACTION_SCO_AUDIO_STATE_UPDATED);
3586 newIntent.putExtra(AudioManager.EXTRA_SCO_AUDIO_STATE, state);
3587 newIntent.putExtra(AudioManager.EXTRA_SCO_AUDIO_PREVIOUS_STATE,
3588 mScoConnectionState);
Dianne Hackborn5ac72a22012-08-29 18:32:08 -07003589 sendStickyBroadcastToAll(newIntent);
Eric Laurentdc03c612011-04-01 10:59:41 -07003590 mScoConnectionState = state;
3591 }
3592 }
3593
Jack He8dd33942018-01-17 15:45:12 -08003594 private boolean handleBtScoActiveDeviceChange(BluetoothDevice btDevice, boolean isActive) {
Eric Laurent98859b22015-06-12 14:35:59 -07003595 if (btDevice == null) {
Jack He8dd33942018-01-17 15:45:12 -08003596 return true;
Eric Laurent98859b22015-06-12 14:35:59 -07003597 }
Eric Laurent98859b22015-06-12 14:35:59 -07003598 String address = btDevice.getAddress();
3599 BluetoothClass btClass = btDevice.getBluetoothClass();
3600 int outDevice = AudioSystem.DEVICE_OUT_BLUETOOTH_SCO;
3601 int inDevice = AudioSystem.DEVICE_IN_BLUETOOTH_SCO_HEADSET;
3602 if (btClass != null) {
3603 switch (btClass.getDeviceClass()) {
Jack He8dd33942018-01-17 15:45:12 -08003604 case BluetoothClass.Device.AUDIO_VIDEO_WEARABLE_HEADSET:
3605 case BluetoothClass.Device.AUDIO_VIDEO_HANDSFREE:
3606 outDevice = AudioSystem.DEVICE_OUT_BLUETOOTH_SCO_HEADSET;
3607 break;
3608 case BluetoothClass.Device.AUDIO_VIDEO_CAR_AUDIO:
3609 outDevice = AudioSystem.DEVICE_OUT_BLUETOOTH_SCO_CARKIT;
3610 break;
Eric Laurent98859b22015-06-12 14:35:59 -07003611 }
3612 }
3613
3614 if (!BluetoothAdapter.checkBluetoothAddress(address)) {
3615 address = "";
3616 }
3617
Eric Laurent98859b22015-06-12 14:35:59 -07003618 String btDeviceName = btDevice.getName();
Jack He8dd33942018-01-17 15:45:12 -08003619 boolean result = handleDeviceConnection(isActive, outDevice, address, btDeviceName);
3620 // handleDeviceConnection() && result to make sure the method get executed
3621 result = handleDeviceConnection(isActive, inDevice, address, btDeviceName) && result;
3622 return result;
3623 }
Satish Kodishala29809802016-01-18 14:23:12 +05303624
Jack He8dd33942018-01-17 15:45:12 -08003625 void setBtScoActiveDevice(BluetoothDevice btDevice) {
3626 if (DEBUG_DEVICES) {
3627 Log.d(TAG, "setBtScoActiveDevice(" + btDevice + ")");
Satish Kodishala29809802016-01-18 14:23:12 +05303628 }
Satish Kodishala29809802016-01-18 14:23:12 +05303629 synchronized (mScoClients) {
Jack He8dd33942018-01-17 15:45:12 -08003630 final BluetoothDevice previousActiveDevice = mBluetoothHeadsetDevice;
3631 if (!Objects.equals(btDevice, previousActiveDevice)) {
3632 if (!handleBtScoActiveDeviceChange(previousActiveDevice, false)) {
3633 Log.w(TAG, "setBtScoActiveDevice() failed to remove previous device "
3634 + previousActiveDevice);
3635 }
3636 if (!handleBtScoActiveDeviceChange(btDevice, true)) {
3637 Log.e(TAG, "setBtScoActiveDevice() failed to add new device " + btDevice);
3638 // set mBluetoothHeadsetDevice to null when failing to add new device
3639 btDevice = null;
3640 }
Satish Kodishala29809802016-01-18 14:23:12 +05303641 mBluetoothHeadsetDevice = btDevice;
Jack He8dd33942018-01-17 15:45:12 -08003642 if (mBluetoothHeadsetDevice == null) {
3643 resetBluetoothSco();
3644 }
Eric Laurent98859b22015-06-12 14:35:59 -07003645 }
3646 }
3647 }
3648
Jaikumar Ganesh82aa7f02010-09-27 17:05:10 -07003649 private BluetoothProfile.ServiceListener mBluetoothProfileServiceListener =
3650 new BluetoothProfile.ServiceListener() {
3651 public void onServiceConnected(int profile, BluetoothProfile proxy) {
Eric Laurent6bc7f2c2011-11-29 18:49:40 -08003652 BluetoothDevice btDevice;
3653 List<BluetoothDevice> deviceList;
3654 switch(profile) {
3655 case BluetoothProfile.A2DP:
seunghwan.hong4fe77952014-10-29 17:43:20 +09003656 synchronized (mConnectedDevices) {
3657 synchronized (mA2dpAvrcpLock) {
3658 mA2dp = (BluetoothA2dp) proxy;
3659 deviceList = mA2dp.getConnectedDevices();
3660 if (deviceList.size() > 0) {
3661 btDevice = deviceList.get(0);
John Du5a0cf7a2013-07-19 11:30:34 -07003662 int state = mA2dp.getConnectionState(btDevice);
Eric Laurentcdae4762017-04-28 18:00:04 -07003663 int intState = (state == BluetoothA2dp.STATE_CONNECTED) ? 1 : 0;
John Du5a0cf7a2013-07-19 11:30:34 -07003664 int delay = checkSendBecomingNoisyIntent(
Eric Laurentcdae4762017-04-28 18:00:04 -07003665 AudioSystem.DEVICE_OUT_BLUETOOTH_A2DP, intState,
3666 AudioSystem.DEVICE_NONE);
John Du5a0cf7a2013-07-19 11:30:34 -07003667 queueMsgUnderWakeLock(mAudioHandler,
Mike Lockwood0a40ec22014-05-21 10:08:50 -07003668 MSG_SET_A2DP_SINK_CONNECTION_STATE,
John Du5a0cf7a2013-07-19 11:30:34 -07003669 state,
Pavlin Radoslavov44a4ef02016-12-21 12:05:51 -08003670 0 /* arg2 unused */,
John Du5a0cf7a2013-07-19 11:30:34 -07003671 btDevice,
3672 delay);
3673 }
Eric Laurentb1fbaac2012-05-29 09:24:28 -07003674 }
Eric Laurent62ef7672010-11-24 10:58:32 -08003675 }
Eric Laurent6bc7f2c2011-11-29 18:49:40 -08003676 break;
3677
Mike Lockwood0a40ec22014-05-21 10:08:50 -07003678 case BluetoothProfile.A2DP_SINK:
3679 deviceList = proxy.getConnectedDevices();
3680 if (deviceList.size() > 0) {
3681 btDevice = deviceList.get(0);
3682 synchronized (mConnectedDevices) {
3683 int state = proxy.getConnectionState(btDevice);
3684 queueMsgUnderWakeLock(mAudioHandler,
3685 MSG_SET_A2DP_SRC_CONNECTION_STATE,
3686 state,
Pavlin Radoslavov44a4ef02016-12-21 12:05:51 -08003687 0 /* arg2 unused */,
Mike Lockwood0a40ec22014-05-21 10:08:50 -07003688 btDevice,
3689 0 /* delay */);
3690 }
3691 }
3692 break;
3693
Eric Laurent6bc7f2c2011-11-29 18:49:40 -08003694 case BluetoothProfile.HEADSET:
3695 synchronized (mScoClients) {
3696 // Discard timeout message
3697 mAudioHandler.removeMessages(MSG_BT_HEADSET_CNCT_FAILED);
3698 mBluetoothHeadset = (BluetoothHeadset) proxy;
Jack He8dd33942018-01-17 15:45:12 -08003699 setBtScoActiveDevice(mBluetoothHeadset.getActiveDevice());
Eric Laurent6bc7f2c2011-11-29 18:49:40 -08003700 // Refresh SCO audio state
3701 checkScoAudioState();
3702 // Continue pending action if any
3703 if (mScoAudioState == SCO_STATE_ACTIVATE_REQ ||
3704 mScoAudioState == SCO_STATE_DEACTIVATE_REQ ||
3705 mScoAudioState == SCO_STATE_DEACTIVATE_EXT_REQ) {
3706 boolean status = false;
3707 if (mBluetoothHeadsetDevice != null) {
3708 switch (mScoAudioState) {
3709 case SCO_STATE_ACTIVATE_REQ:
3710 mScoAudioState = SCO_STATE_ACTIVE_INTERNAL;
Eric Laurentc18c9132013-04-12 17:24:56 -07003711 if (mScoAudioMode == SCO_MODE_RAW) {
3712 status = mBluetoothHeadset.connectAudio();
Liejun Taof4e51d82014-07-16 11:18:29 -07003713 } else if (mScoAudioMode == SCO_MODE_VIRTUAL_CALL) {
Eric Laurentc18c9132013-04-12 17:24:56 -07003714 status = mBluetoothHeadset.startScoUsingVirtualVoiceCall(
3715 mBluetoothHeadsetDevice);
Liejun Taof4e51d82014-07-16 11:18:29 -07003716 } else if (mScoAudioMode == SCO_MODE_VR) {
3717 status = mBluetoothHeadset.startVoiceRecognition(
3718 mBluetoothHeadsetDevice);
Eric Laurentc18c9132013-04-12 17:24:56 -07003719 }
Eric Laurent6bc7f2c2011-11-29 18:49:40 -08003720 break;
3721 case SCO_STATE_DEACTIVATE_REQ:
Eric Laurentc18c9132013-04-12 17:24:56 -07003722 if (mScoAudioMode == SCO_MODE_RAW) {
3723 status = mBluetoothHeadset.disconnectAudio();
Liejun Taof4e51d82014-07-16 11:18:29 -07003724 } else if (mScoAudioMode == SCO_MODE_VIRTUAL_CALL) {
Eric Laurentc18c9132013-04-12 17:24:56 -07003725 status = mBluetoothHeadset.stopScoUsingVirtualVoiceCall(
3726 mBluetoothHeadsetDevice);
Liejun Taof4e51d82014-07-16 11:18:29 -07003727 } else if (mScoAudioMode == SCO_MODE_VR) {
3728 status = mBluetoothHeadset.stopVoiceRecognition(
3729 mBluetoothHeadsetDevice);
Eric Laurentc18c9132013-04-12 17:24:56 -07003730 }
Eric Laurent6bc7f2c2011-11-29 18:49:40 -08003731 break;
3732 case SCO_STATE_DEACTIVATE_EXT_REQ:
3733 status = mBluetoothHeadset.stopVoiceRecognition(
3734 mBluetoothHeadsetDevice);
3735 }
3736 }
3737 if (!status) {
Eric Laurentafbb0472011-12-15 09:04:23 -08003738 sendMsg(mAudioHandler, MSG_BT_HEADSET_CNCT_FAILED,
Eric Laurent6bc7f2c2011-11-29 18:49:40 -08003739 SENDMSG_REPLACE, 0, 0, null, 0);
Eric Laurentdc03c612011-04-01 10:59:41 -07003740 }
3741 }
Eric Laurentdc03c612011-04-01 10:59:41 -07003742 }
Eric Laurent6bc7f2c2011-11-29 18:49:40 -08003743 break;
3744
Jakub Pawlowskif9570f32018-02-21 17:15:12 -08003745 case BluetoothProfile.HEARING_AID:
3746 synchronized (mConnectedDevices) {
3747 synchronized (mHearingAidLock) {
3748 mHearingAid = (BluetoothHearingAid) proxy;
3749 deviceList = mHearingAid.getConnectedDevices();
3750 if (deviceList.size() > 0) {
3751 btDevice = deviceList.get(0);
3752 int state = mHearingAid.getConnectionState(btDevice);
3753 int intState = (state == BluetoothHearingAid.STATE_CONNECTED) ? 1 : 0;
3754 int delay = checkSendBecomingNoisyIntent(
3755 AudioSystem.DEVICE_OUT_HEARING_AID, intState,
3756 AudioSystem.DEVICE_NONE);
3757 queueMsgUnderWakeLock(mAudioHandler,
3758 MSG_SET_HEARING_AID_CONNECTION_STATE,
3759 state,
3760 0 /* arg2 unused */,
3761 btDevice,
3762 delay);
3763 }
3764 }
3765 }
3766
3767 break;
3768
Eric Laurent6bc7f2c2011-11-29 18:49:40 -08003769 default:
3770 break;
Eric Laurent3def1ee2010-03-17 23:26:26 -07003771 }
3772 }
Jaikumar Ganesh82aa7f02010-09-27 17:05:10 -07003773 public void onServiceDisconnected(int profile) {
Eric Laurentb70b78a2016-01-13 19:16:04 -08003774
Paul McLean394a8e12015-03-03 10:29:19 -07003775 switch (profile) {
Eric Laurent6bc7f2c2011-11-29 18:49:40 -08003776 case BluetoothProfile.A2DP:
Eric Laurentb70b78a2016-01-13 19:16:04 -08003777 disconnectA2dp();
Eric Laurent6bc7f2c2011-11-29 18:49:40 -08003778 break;
3779
Mike Lockwood0a40ec22014-05-21 10:08:50 -07003780 case BluetoothProfile.A2DP_SINK:
Eric Laurentb70b78a2016-01-13 19:16:04 -08003781 disconnectA2dpSink();
Mike Lockwood0a40ec22014-05-21 10:08:50 -07003782 break;
3783
Eric Laurent6bc7f2c2011-11-29 18:49:40 -08003784 case BluetoothProfile.HEADSET:
Eric Laurentb70b78a2016-01-13 19:16:04 -08003785 disconnectHeadset();
Eric Laurent6bc7f2c2011-11-29 18:49:40 -08003786 break;
3787
Jakub Pawlowskif9570f32018-02-21 17:15:12 -08003788 case BluetoothProfile.HEARING_AID:
3789 disconnectHearingAid();
3790 break;
3791
Eric Laurent6bc7f2c2011-11-29 18:49:40 -08003792 default:
3793 break;
Eric Laurent3def1ee2010-03-17 23:26:26 -07003794 }
3795 }
3796 };
Jean-Michel Trivid5176cf2010-01-28 11:56:42 -08003797
Eric Laurentb70b78a2016-01-13 19:16:04 -08003798 void disconnectAllBluetoothProfiles() {
3799 disconnectA2dp();
3800 disconnectA2dpSink();
3801 disconnectHeadset();
Jakub Pawlowskif9570f32018-02-21 17:15:12 -08003802 disconnectHearingAid();
Eric Laurentb70b78a2016-01-13 19:16:04 -08003803 }
3804
3805 void disconnectA2dp() {
3806 synchronized (mConnectedDevices) {
3807 synchronized (mA2dpAvrcpLock) {
3808 ArraySet<String> toRemove = null;
3809 // Disconnect ALL DEVICE_OUT_BLUETOOTH_A2DP devices
3810 for (int i = 0; i < mConnectedDevices.size(); i++) {
3811 DeviceListSpec deviceSpec = mConnectedDevices.valueAt(i);
3812 if (deviceSpec.mDeviceType == AudioSystem.DEVICE_OUT_BLUETOOTH_A2DP) {
3813 toRemove = toRemove != null ? toRemove : new ArraySet<String>();
3814 toRemove.add(deviceSpec.mDeviceAddress);
3815 }
3816 }
3817 if (toRemove != null) {
Eric Laurentcdae4762017-04-28 18:00:04 -07003818 int delay = checkSendBecomingNoisyIntent(AudioSystem.DEVICE_OUT_BLUETOOTH_A2DP,
3819 0, AudioSystem.DEVICE_NONE);
Eric Laurentb70b78a2016-01-13 19:16:04 -08003820 for (int i = 0; i < toRemove.size(); i++) {
3821 makeA2dpDeviceUnavailableLater(toRemove.valueAt(i), delay);
3822 }
3823 }
3824 }
3825 }
3826 }
3827
3828 void disconnectA2dpSink() {
3829 synchronized (mConnectedDevices) {
3830 ArraySet<String> toRemove = null;
3831 // Disconnect ALL DEVICE_IN_BLUETOOTH_A2DP devices
3832 for(int i = 0; i < mConnectedDevices.size(); i++) {
3833 DeviceListSpec deviceSpec = mConnectedDevices.valueAt(i);
3834 if (deviceSpec.mDeviceType == AudioSystem.DEVICE_IN_BLUETOOTH_A2DP) {
3835 toRemove = toRemove != null ? toRemove : new ArraySet<String>();
3836 toRemove.add(deviceSpec.mDeviceAddress);
3837 }
3838 }
3839 if (toRemove != null) {
3840 for (int i = 0; i < toRemove.size(); i++) {
3841 makeA2dpSrcUnavailable(toRemove.valueAt(i));
3842 }
3843 }
3844 }
3845 }
3846
3847 void disconnectHeadset() {
3848 synchronized (mScoClients) {
Jack He8dd33942018-01-17 15:45:12 -08003849 setBtScoActiveDevice(null);
Eric Laurentb70b78a2016-01-13 19:16:04 -08003850 mBluetoothHeadset = null;
3851 }
3852 }
3853
Jakub Pawlowskif9570f32018-02-21 17:15:12 -08003854 void disconnectHearingAid() {
3855 synchronized (mConnectedDevices) {
3856 synchronized (mHearingAidLock) {
3857 ArraySet<String> toRemove = null;
3858 // Disconnect ALL DEVICE_OUT_HEARING_AID devices
3859 for (int i = 0; i < mConnectedDevices.size(); i++) {
3860 DeviceListSpec deviceSpec = mConnectedDevices.valueAt(i);
3861 if (deviceSpec.mDeviceType == AudioSystem.DEVICE_OUT_HEARING_AID) {
3862 toRemove = toRemove != null ? toRemove : new ArraySet<String>();
3863 toRemove.add(deviceSpec.mDeviceAddress);
3864 }
3865 }
3866 if (toRemove != null) {
3867 int delay = checkSendBecomingNoisyIntent(AudioSystem.DEVICE_OUT_HEARING_AID,
3868 0, AudioSystem.DEVICE_NONE);
3869 for (int i = 0; i < toRemove.size(); i++) {
3870 makeHearingAidDeviceUnavailable(toRemove.valueAt(i) /*, delay*/);
3871 }
3872 }
3873 }
3874 }
3875 }
3876
John Spurlock90874332015-03-10 16:00:54 -04003877 private void onCheckMusicActive(String caller) {
Eric Laurentd640bd32012-09-28 18:01:48 -07003878 synchronized (mSafeMediaVolumeState) {
3879 if (mSafeMediaVolumeState == SAFE_MEDIA_VOLUME_INACTIVE) {
Eric Laurentc34dcc12012-09-10 13:51:52 -07003880 int device = getDeviceForStream(AudioSystem.STREAM_MUSIC);
3881
3882 if ((device & mSafeMediaVolumeDevices) != 0) {
3883 sendMsg(mAudioHandler,
3884 MSG_CHECK_MUSIC_ACTIVE,
3885 SENDMSG_REPLACE,
Eric Laurentf1a457d2012-09-20 16:27:23 -07003886 0,
Eric Laurentc34dcc12012-09-10 13:51:52 -07003887 0,
John Spurlock90874332015-03-10 16:00:54 -04003888 caller,
Eric Laurentc34dcc12012-09-10 13:51:52 -07003889 MUSIC_ACTIVE_POLL_PERIOD_MS);
Eric Laurent42b041e2013-03-29 11:36:03 -07003890 int index = mStreamStates[AudioSystem.STREAM_MUSIC].getIndex(device);
Eric Laurentf1a457d2012-09-20 16:27:23 -07003891 if (AudioSystem.isStreamActive(AudioSystem.STREAM_MUSIC, 0) &&
Eric Laurenteab40d12017-06-09 12:45:21 -07003892 (index > safeMediaVolumeIndex(device))) {
Eric Laurentc34dcc12012-09-10 13:51:52 -07003893 // Approximate cumulative active music time
3894 mMusicActiveMs += MUSIC_ACTIVE_POLL_PERIOD_MS;
3895 if (mMusicActiveMs > UNSAFE_VOLUME_MUSIC_ACTIVE_MS_MAX) {
John Spurlock90874332015-03-10 16:00:54 -04003896 setSafeMediaVolumeEnabled(true, caller);
Eric Laurentc34dcc12012-09-10 13:51:52 -07003897 mMusicActiveMs = 0;
Eric Laurentc34dcc12012-09-10 13:51:52 -07003898 }
John Spurlockaa5ee4d2014-07-25 13:05:12 -04003899 saveMusicActiveMs();
Eric Laurentc34dcc12012-09-10 13:51:52 -07003900 }
3901 }
3902 }
3903 }
3904 }
3905
John Spurlockaa5ee4d2014-07-25 13:05:12 -04003906 private void saveMusicActiveMs() {
3907 mAudioHandler.obtainMessage(MSG_PERSIST_MUSIC_ACTIVE_MS, mMusicActiveMs, 0).sendToTarget();
3908 }
3909
Eric Laurenteab40d12017-06-09 12:45:21 -07003910 private int getSafeUsbMediaVolumeIndex()
3911 {
3912 // determine UI volume index corresponding to the wanted safe gain in dBFS
3913 int min = MIN_STREAM_VOLUME[AudioSystem.STREAM_MUSIC];
3914 int max = MAX_STREAM_VOLUME[AudioSystem.STREAM_MUSIC];
3915
John Muir8b8bddd2018-02-16 14:29:14 -08003916 mSafeUsbMediaVolumeDbfs = mContext.getResources().getInteger(
3917 com.android.internal.R.integer.config_safe_media_volume_usb_mB) / 100.0f;
3918
Eric Laurenteab40d12017-06-09 12:45:21 -07003919 while (Math.abs(max-min) > 1) {
3920 int index = (max + min) / 2;
3921 float gainDB = AudioSystem.getStreamVolumeDB(
3922 AudioSystem.STREAM_MUSIC, index, AudioSystem.DEVICE_OUT_USB_HEADSET);
Eric Laurentb378a13a2017-07-11 14:08:11 -07003923 if (Float.isNaN(gainDB)) {
Eric Laurenteab40d12017-06-09 12:45:21 -07003924 //keep last min in case of read error
3925 break;
John Muir8b8bddd2018-02-16 14:29:14 -08003926 } else if (gainDB == mSafeUsbMediaVolumeDbfs) {
Eric Laurenteab40d12017-06-09 12:45:21 -07003927 min = index;
3928 break;
John Muir8b8bddd2018-02-16 14:29:14 -08003929 } else if (gainDB < mSafeUsbMediaVolumeDbfs) {
Eric Laurenteab40d12017-06-09 12:45:21 -07003930 min = index;
3931 } else {
3932 max = index;
3933 }
3934 }
3935 return min * 10;
3936 }
3937
John Spurlock90874332015-03-10 16:00:54 -04003938 private void onConfigureSafeVolume(boolean force, String caller) {
Eric Laurentd640bd32012-09-28 18:01:48 -07003939 synchronized (mSafeMediaVolumeState) {
3940 int mcc = mContext.getResources().getConfiguration().mcc;
3941 if ((mMcc != mcc) || ((mMcc == 0) && force)) {
3942 mSafeMediaVolumeIndex = mContext.getResources().getInteger(
3943 com.android.internal.R.integer.config_safe_media_volume_index) * 10;
Eric Laurenteab40d12017-06-09 12:45:21 -07003944
3945 mSafeUsbMediaVolumeIndex = getSafeUsbMediaVolumeIndex();
3946
John Spurlock35134602014-07-24 18:10:48 -04003947 boolean safeMediaVolumeEnabled =
3948 SystemProperties.getBoolean("audio.safemedia.force", false)
3949 || mContext.getResources().getBoolean(
3950 com.android.internal.R.bool.config_safe_media_volume_enabled);
Eric Laurent05274f32012-11-29 12:48:18 -08003951
Ricardo Garcia3a30a762015-06-23 15:54:45 -07003952 boolean safeMediaVolumeBypass =
3953 SystemProperties.getBoolean("audio.safemedia.bypass", false);
3954
Eric Laurent05274f32012-11-29 12:48:18 -08003955 // The persisted state is either "disabled" or "active": this is the state applied
3956 // next time we boot and cannot be "inactive"
3957 int persistedState;
Ricardo Garcia3a30a762015-06-23 15:54:45 -07003958 if (safeMediaVolumeEnabled && !safeMediaVolumeBypass) {
Eric Laurent05274f32012-11-29 12:48:18 -08003959 persistedState = SAFE_MEDIA_VOLUME_ACTIVE;
3960 // The state can already be "inactive" here if the user has forced it before
3961 // the 30 seconds timeout for forced configuration. In this case we don't reset
3962 // it to "active".
3963 if (mSafeMediaVolumeState != SAFE_MEDIA_VOLUME_INACTIVE) {
John Spurlockaa5ee4d2014-07-25 13:05:12 -04003964 if (mMusicActiveMs == 0) {
3965 mSafeMediaVolumeState = SAFE_MEDIA_VOLUME_ACTIVE;
John Spurlock90874332015-03-10 16:00:54 -04003966 enforceSafeMediaVolume(caller);
John Spurlockaa5ee4d2014-07-25 13:05:12 -04003967 } else {
3968 // We have existing playback time recorded, already confirmed.
3969 mSafeMediaVolumeState = SAFE_MEDIA_VOLUME_INACTIVE;
3970 }
Eric Laurent05274f32012-11-29 12:48:18 -08003971 }
Eric Laurentd640bd32012-09-28 18:01:48 -07003972 } else {
Eric Laurent05274f32012-11-29 12:48:18 -08003973 persistedState = SAFE_MEDIA_VOLUME_DISABLED;
Eric Laurentd640bd32012-09-28 18:01:48 -07003974 mSafeMediaVolumeState = SAFE_MEDIA_VOLUME_DISABLED;
3975 }
3976 mMcc = mcc;
Eric Laurent05274f32012-11-29 12:48:18 -08003977 sendMsg(mAudioHandler,
3978 MSG_PERSIST_SAFE_VOLUME_STATE,
3979 SENDMSG_QUEUE,
3980 persistedState,
3981 0,
3982 null,
3983 0);
Eric Laurentd640bd32012-09-28 18:01:48 -07003984 }
3985 }
3986 }
3987
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003988 ///////////////////////////////////////////////////////////////////////////
3989 // Internal methods
3990 ///////////////////////////////////////////////////////////////////////////
3991
3992 /**
3993 * Checks if the adjustment should change ringer mode instead of just
3994 * adjusting volume. If so, this will set the proper ringer mode and volume
3995 * indices on the stream states.
3996 */
Julia Reynoldsed783792016-04-08 15:27:35 -04003997 private int checkForRingerModeChange(int oldIndex, int direction, int step, boolean isMuted,
3998 String caller, int flags) {
John Spurlocka11b4af2014-06-01 11:52:23 -04003999 int result = FLAG_ADJUST_VOLUME;
Zak Cohen47798292017-11-30 12:34:20 -08004000 if (isPlatformTelevision() || mIsSingleVolume) {
Hank Freund21003f62015-12-08 09:05:46 -08004001 return result;
4002 }
4003
John Spurlock661f2cf2014-11-17 10:29:10 -05004004 int ringerMode = getRingerModeInternal();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004005
Eric Laurentbffc3d12012-05-07 17:43:49 -07004006 switch (ringerMode) {
4007 case RINGER_MODE_NORMAL:
4008 if (direction == AudioManager.ADJUST_LOWER) {
4009 if (mHasVibrator) {
Eric Laurent24482012012-05-10 09:41:17 -07004010 // "step" is the delta in internal index units corresponding to a
4011 // change of 1 in UI index units.
4012 // Because of rounding when rescaling from one stream index range to its alias
4013 // index range, we cannot simply test oldIndex == step:
4014 // (step <= oldIndex < 2 * step) is equivalent to: (old UI index == 1)
4015 if (step <= oldIndex && oldIndex < 2 * step) {
Eric Laurentbffc3d12012-05-07 17:43:49 -07004016 ringerMode = RINGER_MODE_VIBRATE;
John Spurlock07e72432015-03-13 11:46:52 -04004017 mLoweredFromNormalToVibrateTime = SystemClock.uptimeMillis();
Eric Laurentbffc3d12012-05-07 17:43:49 -07004018 }
4019 } else {
John Spurlockd9c75db2015-04-28 11:19:13 -04004020 if (oldIndex == step && mVolumePolicy.volumeDownToEnterSilent) {
Eric Laurentbffc3d12012-05-07 17:43:49 -07004021 ringerMode = RINGER_MODE_SILENT;
4022 }
Eric Laurent3d4c06f2011-08-15 19:58:28 -07004023 }
Muyuan Li1ed6df62016-06-18 11:16:52 -07004024 } else if (mIsSingleVolume && (direction == AudioManager.ADJUST_TOGGLE_MUTE
John Spurlocka48d7792015-03-03 17:35:57 -05004025 || direction == AudioManager.ADJUST_MUTE)) {
RoboErik5452e252015-02-06 15:33:53 -08004026 if (mHasVibrator) {
4027 ringerMode = RINGER_MODE_VIBRATE;
4028 } else {
4029 ringerMode = RINGER_MODE_SILENT;
4030 }
4031 // Setting the ringer mode will toggle mute
4032 result &= ~FLAG_ADJUST_VOLUME;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004033 }
Eric Laurentbffc3d12012-05-07 17:43:49 -07004034 break;
4035 case RINGER_MODE_VIBRATE:
4036 if (!mHasVibrator) {
4037 Log.e(TAG, "checkForRingerModeChange() current ringer mode is vibrate" +
4038 "but no vibrator is present");
4039 break;
4040 }
Amith Yamasanic696a532011-10-28 17:02:37 -07004041 if ((direction == AudioManager.ADJUST_LOWER)) {
RoboErik5452e252015-02-06 15:33:53 -08004042 // This is the case we were muted with the volume turned up
Muyuan Li1ed6df62016-06-18 11:16:52 -07004043 if (mIsSingleVolume && oldIndex >= 2 * step && isMuted) {
RoboErik5452e252015-02-06 15:33:53 -08004044 ringerMode = RINGER_MODE_NORMAL;
4045 } else if (mPrevVolDirection != AudioManager.ADJUST_LOWER) {
John Spurlocka48d7792015-03-03 17:35:57 -05004046 if (mVolumePolicy.volumeDownToEnterSilent) {
John Spurlock07e72432015-03-13 11:46:52 -04004047 final long diff = SystemClock.uptimeMillis()
4048 - mLoweredFromNormalToVibrateTime;
John Spurlockd9c75db2015-04-28 11:19:13 -04004049 if (diff > mVolumePolicy.vibrateToSilentDebounce
4050 && mRingerModeDelegate.canVolumeDownEnterSilent()) {
John Spurlock07e72432015-03-13 11:46:52 -04004051 ringerMode = RINGER_MODE_SILENT;
4052 }
John Spurlock795a5142014-12-08 14:09:35 -05004053 } else {
4054 result |= AudioManager.FLAG_SHOW_VIBRATE_HINT;
4055 }
Amith Yamasanic696a532011-10-28 17:02:37 -07004056 }
RoboErik5452e252015-02-06 15:33:53 -08004057 } else if (direction == AudioManager.ADJUST_RAISE
4058 || direction == AudioManager.ADJUST_TOGGLE_MUTE
4059 || direction == AudioManager.ADJUST_UNMUTE) {
Eric Laurentbffc3d12012-05-07 17:43:49 -07004060 ringerMode = RINGER_MODE_NORMAL;
Amith Yamasanic696a532011-10-28 17:02:37 -07004061 }
John Spurlocka11b4af2014-06-01 11:52:23 -04004062 result &= ~FLAG_ADJUST_VOLUME;
Eric Laurentbffc3d12012-05-07 17:43:49 -07004063 break;
4064 case RINGER_MODE_SILENT:
Muyuan Li1ed6df62016-06-18 11:16:52 -07004065 if (mIsSingleVolume && direction == AudioManager.ADJUST_LOWER && oldIndex >= 2 * step && isMuted) {
RoboErik5452e252015-02-06 15:33:53 -08004066 // This is the case we were muted with the volume turned up
4067 ringerMode = RINGER_MODE_NORMAL;
4068 } else if (direction == AudioManager.ADJUST_RAISE
4069 || direction == AudioManager.ADJUST_TOGGLE_MUTE
4070 || direction == AudioManager.ADJUST_UNMUTE) {
John Spurlocka48d7792015-03-03 17:35:57 -05004071 if (!mVolumePolicy.volumeUpToExitSilent) {
John Spurlocka11b4af2014-06-01 11:52:23 -04004072 result |= AudioManager.FLAG_SHOW_SILENT_HINT;
Eric Laurentbffc3d12012-05-07 17:43:49 -07004073 } else {
RoboErik5452e252015-02-06 15:33:53 -08004074 if (mHasVibrator && direction == AudioManager.ADJUST_RAISE) {
John Spurlocka11b4af2014-06-01 11:52:23 -04004075 ringerMode = RINGER_MODE_VIBRATE;
4076 } else {
RoboErik5452e252015-02-06 15:33:53 -08004077 // If we don't have a vibrator or they were toggling mute
4078 // go straight back to normal.
John Spurlocka11b4af2014-06-01 11:52:23 -04004079 ringerMode = RINGER_MODE_NORMAL;
4080 }
Eric Laurentbffc3d12012-05-07 17:43:49 -07004081 }
Daniel Sandler6329bf72010-02-26 15:17:44 -05004082 }
John Spurlocka11b4af2014-06-01 11:52:23 -04004083 result &= ~FLAG_ADJUST_VOLUME;
Eric Laurentbffc3d12012-05-07 17:43:49 -07004084 break;
4085 default:
4086 Log.e(TAG, "checkForRingerModeChange() wrong ringer mode: "+ringerMode);
4087 break;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004088 }
4089
Julia Reynoldsed783792016-04-08 15:27:35 -04004090 if (isAndroidNPlus(caller) && wouldToggleZenMode(ringerMode)
4091 && !mNm.isNotificationPolicyAccessGrantedForPackage(caller)
4092 && (flags & AudioManager.FLAG_FROM_KEY) == 0) {
4093 throw new SecurityException("Not allowed to change Do Not Disturb state");
4094 }
4095
John Spurlock661f2cf2014-11-17 10:29:10 -05004096 setRingerMode(ringerMode, TAG + ".checkForRingerModeChange", false /*external*/);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004097
Eric Laurent25101b02011-02-02 09:33:30 -08004098 mPrevVolDirection = direction;
4099
John Spurlocka11b4af2014-06-01 11:52:23 -04004100 return result;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004101 }
4102
John Spurlock3346a802014-05-20 16:25:37 -04004103 @Override
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004104 public boolean isStreamAffectedByRingerMode(int streamType) {
Eric Laurent9bcf4012009-06-12 06:09:28 -07004105 return (mRingerModeAffectedStreams & (1 << streamType)) != 0;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004106 }
4107
Beverlyd6964762018-02-16 14:07:03 -05004108 private boolean shouldZenMuteStream(int streamType) {
4109 if (mNm.getZenMode() != Settings.Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS) {
4110 return false;
4111 }
4112
4113 NotificationManager.Policy zenPolicy = mNm.getNotificationPolicy();
4114 final boolean muteAlarms = (zenPolicy.priorityCategories
4115 & NotificationManager.Policy.PRIORITY_CATEGORY_ALARMS) == 0;
4116 final boolean muteMedia = (zenPolicy.priorityCategories
4117 & NotificationManager.Policy.PRIORITY_CATEGORY_MEDIA) == 0;
4118 final boolean muteSystem = (zenPolicy.priorityCategories
4119 & NotificationManager.Policy.PRIORITY_CATEGORY_SYSTEM) == 0;
4120 final boolean muteNotificationAndRing = ZenModeConfig
4121 .areAllPriorityOnlyNotificationZenSoundsMuted(mNm.getNotificationPolicy());
4122 return muteAlarms && isAlarm(streamType)
4123 || muteMedia && isMedia(streamType)
4124 || muteSystem && isSystem(streamType)
4125 || muteNotificationAndRing && isNotificationOrRinger(streamType);
4126 }
4127
4128 private boolean isStreamMutedByRingerOrZenMode(int streamType) {
4129 return (mRingerAndZenModeMutedStreams & (1 << streamType)) != 0;
4130 }
4131
4132 /**
4133 * DND total silence: media and alarms streams are tied to the muted ringer
4134 * {@link ZenModeHelper.RingerModeDelegate#getRingerModeAffectedStreams(int)}
4135 * DND alarms only: notification, ringer + system muted (by default tied to muted ringer mode)
4136 * DND priority only: alarms, media, system streams can be muted separate from ringer based on
4137 * zenPolicy (this method determines which streams)
4138 * @return true if changed, else false
4139 */
4140 private boolean updateZenModeAffectedStreams() {
4141 int zenModeAffectedStreams = 0;
4142 if (mSystemReady && mNm.getZenMode() == Settings.Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS) {
4143 NotificationManager.Policy zenPolicy = mNm.getNotificationPolicy();
4144 if ((zenPolicy.priorityCategories
4145 & NotificationManager.Policy.PRIORITY_CATEGORY_ALARMS) == 0) {
4146 zenModeAffectedStreams |= 1 << AudioManager.STREAM_ALARM;
4147 }
4148
4149 if ((zenPolicy.priorityCategories
4150 & NotificationManager.Policy.PRIORITY_CATEGORY_MEDIA) == 0) {
4151 zenModeAffectedStreams |= 1 << AudioManager.STREAM_MUSIC;
4152 }
4153
4154 if ((zenPolicy.priorityCategories
4155 & NotificationManager.Policy.PRIORITY_CATEGORY_SYSTEM) == 0) {
4156 zenModeAffectedStreams |= 1 << AudioManager.STREAM_SYSTEM;
4157 }
4158 }
4159
4160 if (mZenModeAffectedStreams != zenModeAffectedStreams) {
4161 mZenModeAffectedStreams = zenModeAffectedStreams;
4162 return true;
4163 }
4164
4165 return false;
Eric Laurent5b4e6542010-03-19 20:02:21 -07004166 }
4167
Jean-Michel Trivi8719a1d2017-11-06 11:52:51 -08004168 @GuardedBy("mSettingsLock")
Beverlyd6964762018-02-16 14:07:03 -05004169 private boolean updateRingerAndZenModeAffectedStreams() {
4170 boolean updatedZenModeAffectedStreams = updateZenModeAffectedStreams();
John Spurlock50ced3f2015-05-11 16:00:09 -04004171 int ringerModeAffectedStreams = Settings.System.getIntForUser(mContentResolver,
Eric Laurent24e0d9b2013-10-03 18:15:07 -07004172 Settings.System.MODE_RINGER_STREAMS_AFFECTED,
4173 ((1 << AudioSystem.STREAM_RING)|(1 << AudioSystem.STREAM_NOTIFICATION)|
4174 (1 << AudioSystem.STREAM_SYSTEM)|(1 << AudioSystem.STREAM_SYSTEM_ENFORCED)),
4175 UserHandle.USER_CURRENT);
4176
Muyuan Li1ed6df62016-06-18 11:16:52 -07004177 if (mIsSingleVolume) {
John Spurlock50ced3f2015-05-11 16:00:09 -04004178 ringerModeAffectedStreams = 0;
4179 } else if (mRingerModeDelegate != null) {
4180 ringerModeAffectedStreams = mRingerModeDelegate
4181 .getRingerModeAffectedStreams(ringerModeAffectedStreams);
Eric Laurent24e0d9b2013-10-03 18:15:07 -07004182 }
Jean-Michel Trivi8719a1d2017-11-06 11:52:51 -08004183 if (mCameraSoundForced) {
4184 ringerModeAffectedStreams &= ~(1 << AudioSystem.STREAM_SYSTEM_ENFORCED);
4185 } else {
4186 ringerModeAffectedStreams |= (1 << AudioSystem.STREAM_SYSTEM_ENFORCED);
Eric Laurent24e0d9b2013-10-03 18:15:07 -07004187 }
4188 if (mStreamVolumeAlias[AudioSystem.STREAM_DTMF] == AudioSystem.STREAM_RING) {
4189 ringerModeAffectedStreams |= (1 << AudioSystem.STREAM_DTMF);
4190 } else {
4191 ringerModeAffectedStreams &= ~(1 << AudioSystem.STREAM_DTMF);
4192 }
4193
4194 if (ringerModeAffectedStreams != mRingerModeAffectedStreams) {
4195 Settings.System.putIntForUser(mContentResolver,
4196 Settings.System.MODE_RINGER_STREAMS_AFFECTED,
4197 ringerModeAffectedStreams,
4198 UserHandle.USER_CURRENT);
4199 mRingerModeAffectedStreams = ringerModeAffectedStreams;
4200 return true;
4201 }
Beverlyd6964762018-02-16 14:07:03 -05004202 return updatedZenModeAffectedStreams;
Eric Laurent24e0d9b2013-10-03 18:15:07 -07004203 }
4204
John Spurlocka9dfbe8b2015-02-17 11:01:51 -05004205 @Override
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004206 public boolean isStreamAffectedByMute(int streamType) {
4207 return (mMuteAffectedStreams & (1 << streamType)) != 0;
4208 }
4209
4210 private void ensureValidDirection(int direction) {
RoboErik4197cb62015-01-21 15:45:32 -08004211 switch (direction) {
4212 case AudioManager.ADJUST_LOWER:
4213 case AudioManager.ADJUST_RAISE:
4214 case AudioManager.ADJUST_SAME:
4215 case AudioManager.ADJUST_MUTE:
4216 case AudioManager.ADJUST_UNMUTE:
4217 case AudioManager.ADJUST_TOGGLE_MUTE:
4218 break;
4219 default:
4220 throw new IllegalArgumentException("Bad direction " + direction);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004221 }
4222 }
4223
4224 private void ensureValidStreamType(int streamType) {
4225 if (streamType < 0 || streamType >= mStreamStates.length) {
4226 throw new IllegalArgumentException("Bad stream type " + streamType);
4227 }
4228 }
4229
RoboErik4197cb62015-01-21 15:45:32 -08004230 private boolean isMuteAdjust(int adjust) {
4231 return adjust == AudioManager.ADJUST_MUTE || adjust == AudioManager.ADJUST_UNMUTE
4232 || adjust == AudioManager.ADJUST_TOGGLE_MUTE;
4233 }
4234
Eric Laurent6d517662012-04-23 18:42:39 -07004235 private boolean isInCommunication() {
Nancy Chen0eb1e402014-08-21 22:52:29 -07004236 boolean IsInCall = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004237
Tyler Gunnef9f6f92014-09-12 22:16:17 -07004238 TelecomManager telecomManager =
4239 (TelecomManager) mContext.getSystemService(Context.TELECOM_SERVICE);
Eric Laurent38edfda2014-12-18 17:38:04 -08004240
4241 final long ident = Binder.clearCallingIdentity();
Tyler Gunnef9f6f92014-09-12 22:16:17 -07004242 IsInCall = telecomManager.isInCall();
Eric Laurent38edfda2014-12-18 17:38:04 -08004243 Binder.restoreCallingIdentity(ident);
Santos Cordon9eb45932014-06-27 12:28:43 -07004244
Eric Laurentda1af762017-12-15 16:54:35 -08004245 return (IsInCall || getMode() == AudioManager.MODE_IN_COMMUNICATION ||
4246 getMode() == AudioManager.MODE_IN_CALL);
Eric Laurent6d517662012-04-23 18:42:39 -07004247 }
Eric Laurent25101b02011-02-02 09:33:30 -08004248
Jean-Michel Trivifca1e602013-10-10 18:12:59 -07004249 /**
4250 * For code clarity for getActiveStreamType(int)
Julia Reynoldsd9e96e22017-11-07 10:33:08 -05004251 * @param delay_ms max time since last stream activity to consider
4252 * @return true if stream is active in streams handled by AudioFlinger now or
Jean-Michel Trivifca1e602013-10-10 18:12:59 -07004253 * in the last "delay_ms" ms.
4254 */
Julia Reynoldsd9e96e22017-11-07 10:33:08 -05004255 private boolean wasStreamActiveRecently(int stream, int delay_ms) {
4256 return AudioSystem.isStreamActive(stream, delay_ms)
4257 || AudioSystem.isStreamActiveRemotely(stream, delay_ms);
Jean-Michel Trivifca1e602013-10-10 18:12:59 -07004258 }
4259
Eric Laurent6d517662012-04-23 18:42:39 -07004260 private int getActiveStreamType(int suggestedStreamType) {
Muyuan Li1ed6df62016-06-18 11:16:52 -07004261 if (mIsSingleVolume
4262 && suggestedStreamType == AudioManager.USE_DEFAULT_STREAM_TYPE) {
4263 return AudioSystem.STREAM_MUSIC;
4264 }
4265
Eric Laurent212532b2014-07-21 15:43:18 -07004266 switch (mPlatformType) {
John Spurlock61560172015-02-06 19:46:04 -05004267 case AudioSystem.PLATFORM_VOICE:
Eric Laurent6d517662012-04-23 18:42:39 -07004268 if (isInCommunication()) {
Eric Laurent25101b02011-02-02 09:33:30 -08004269 if (AudioSystem.getForceUse(AudioSystem.FOR_COMMUNICATION)
4270 == AudioSystem.FORCE_BT_SCO) {
4271 // Log.v(TAG, "getActiveStreamType: Forcing STREAM_BLUETOOTH_SCO...");
4272 return AudioSystem.STREAM_BLUETOOTH_SCO;
4273 } else {
4274 // Log.v(TAG, "getActiveStreamType: Forcing STREAM_VOICE_CALL...");
4275 return AudioSystem.STREAM_VOICE_CALL;
4276 }
Eric Laurent25101b02011-02-02 09:33:30 -08004277 } else if (suggestedStreamType == AudioManager.USE_DEFAULT_STREAM_TYPE) {
Julia Reynoldsd9e96e22017-11-07 10:33:08 -05004278 if (wasStreamActiveRecently(AudioSystem.STREAM_RING, sStreamOverrideDelayMs)) {
Jean-Michel Trivi3114ce32012-06-11 15:03:52 -07004279 if (DEBUG_VOL)
Julia Reynoldsd9e96e22017-11-07 10:33:08 -05004280 Log.v(TAG, "getActiveStreamType: Forcing STREAM_RING stream active");
4281 return AudioSystem.STREAM_RING;
4282 } else if (wasStreamActiveRecently(
4283 AudioSystem.STREAM_NOTIFICATION, sStreamOverrideDelayMs)) {
4284 if (DEBUG_VOL)
4285 Log.v(TAG, "getActiveStreamType: Forcing STREAM_NOTIFICATION stream active");
4286 return AudioSystem.STREAM_NOTIFICATION;
4287 } else {
4288 if (DEBUG_VOL)
4289 Log.v(TAG, "getActiveStreamType: Forcing STREAM_MUSIC b/c default");
Jean-Michel Trivi3114ce32012-06-11 15:03:52 -07004290 return AudioSystem.STREAM_MUSIC;
Jean-Michel Trivi3114ce32012-06-11 15:03:52 -07004291 }
Julia Reynoldsd9e96e22017-11-07 10:33:08 -05004292 } else if (
4293 wasStreamActiveRecently(AudioSystem.STREAM_NOTIFICATION, sStreamOverrideDelayMs)) {
Jean-Michel Trivi3114ce32012-06-11 15:03:52 -07004294 if (DEBUG_VOL)
Julia Reynoldsd9e96e22017-11-07 10:33:08 -05004295 Log.v(TAG, "getActiveStreamType: Forcing STREAM_NOTIFICATION stream active");
4296 return AudioSystem.STREAM_NOTIFICATION;
4297 } else if (wasStreamActiveRecently(AudioSystem.STREAM_RING, sStreamOverrideDelayMs)) {
4298 if (DEBUG_VOL)
4299 Log.v(TAG, "getActiveStreamType: Forcing STREAM_RING stream active");
4300 return AudioSystem.STREAM_RING;
Eric Laurent25101b02011-02-02 09:33:30 -08004301 }
Eric Laurent212532b2014-07-21 15:43:18 -07004302 default:
Eric Laurent6d517662012-04-23 18:42:39 -07004303 if (isInCommunication()) {
Eric Laurent25101b02011-02-02 09:33:30 -08004304 if (AudioSystem.getForceUse(AudioSystem.FOR_COMMUNICATION)
4305 == AudioSystem.FORCE_BT_SCO) {
Jean-Michel Trivi3114ce32012-06-11 15:03:52 -07004306 if (DEBUG_VOL) Log.v(TAG, "getActiveStreamType: Forcing STREAM_BLUETOOTH_SCO");
Eric Laurent25101b02011-02-02 09:33:30 -08004307 return AudioSystem.STREAM_BLUETOOTH_SCO;
4308 } else {
Jean-Michel Trivi3114ce32012-06-11 15:03:52 -07004309 if (DEBUG_VOL) Log.v(TAG, "getActiveStreamType: Forcing STREAM_VOICE_CALL");
Eric Laurent25101b02011-02-02 09:33:30 -08004310 return AudioSystem.STREAM_VOICE_CALL;
4311 }
Julia Reynoldsd9e96e22017-11-07 10:33:08 -05004312 } else if (AudioSystem.isStreamActive(
4313 AudioSystem.STREAM_NOTIFICATION, sStreamOverrideDelayMs)) {
Jean-Michel Trivi3114ce32012-06-11 15:03:52 -07004314 if (DEBUG_VOL) Log.v(TAG, "getActiveStreamType: Forcing STREAM_NOTIFICATION");
Eric Laurent25101b02011-02-02 09:33:30 -08004315 return AudioSystem.STREAM_NOTIFICATION;
Julia Reynoldsd9e96e22017-11-07 10:33:08 -05004316 } else if (AudioSystem.isStreamActive(
4317 AudioSystem.STREAM_RING, sStreamOverrideDelayMs)) {
4318 if (DEBUG_VOL) Log.v(TAG, "getActiveStreamType: Forcing STREAM_RING");
4319 return AudioSystem.STREAM_RING;
Jean-Michel Trivi3114ce32012-06-11 15:03:52 -07004320 } else if (suggestedStreamType == AudioManager.USE_DEFAULT_STREAM_TYPE) {
Julia Reynoldsd9e96e22017-11-07 10:33:08 -05004321 if (AudioSystem.isStreamActive(
4322 AudioSystem.STREAM_NOTIFICATION, sStreamOverrideDelayMs)) {
4323 if (DEBUG_VOL) Log.v(TAG, "getActiveStreamType: Forcing STREAM_NOTIFICATION");
John Spurlockeb1d88d2014-07-19 14:49:19 -04004324 return AudioSystem.STREAM_NOTIFICATION;
Julia Reynoldsd9e96e22017-11-07 10:33:08 -05004325 } else if (AudioSystem.isStreamActive(
4326 AudioSystem.STREAM_RING, sStreamOverrideDelayMs)) {
4327 if (DEBUG_VOL) Log.v(TAG, "getActiveStreamType: Forcing STREAM_RING");
4328 return AudioSystem.STREAM_RING;
4329 } else {
4330 if (DEBUG_VOL) Log.v(TAG, "getActiveStreamType: using STREAM_MUSIC as default");
4331 return AudioSystem.STREAM_MUSIC;
Jean-Michel Trivi3114ce32012-06-11 15:03:52 -07004332 }
Joe Onoratoc7fcba42011-01-05 16:53:11 -08004333 }
Eric Laurent212532b2014-07-21 15:43:18 -07004334 break;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004335 }
Eric Laurent212532b2014-07-21 15:43:18 -07004336 if (DEBUG_VOL) Log.v(TAG, "getActiveStreamType: Returning suggested type "
4337 + suggestedStreamType);
4338 return suggestedStreamType;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004339 }
4340
John Spurlockbcc10872014-11-28 15:29:21 -05004341 private void broadcastRingerMode(String action, int ringerMode) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004342 // Send sticky broadcast
John Spurlockbcc10872014-11-28 15:29:21 -05004343 Intent broadcast = new Intent(action);
Glenn Kastenba195eb2011-12-13 09:30:40 -08004344 broadcast.putExtra(AudioManager.EXTRA_RINGER_MODE, ringerMode);
Dianne Hackborn1c633fc2009-12-08 19:45:14 -08004345 broadcast.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT
4346 | Intent.FLAG_RECEIVER_REPLACE_PENDING);
Dianne Hackborn5ac72a22012-08-29 18:32:08 -07004347 sendStickyBroadcastToAll(broadcast);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004348 }
4349
4350 private void broadcastVibrateSetting(int vibrateType) {
4351 // Send broadcast
Sudheer Shankafc46e9b2016-10-21 17:55:27 -07004352 if (mActivityManagerInternal.isSystemReady()) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004353 Intent broadcast = new Intent(AudioManager.VIBRATE_SETTING_CHANGED_ACTION);
4354 broadcast.putExtra(AudioManager.EXTRA_VIBRATE_TYPE, vibrateType);
4355 broadcast.putExtra(AudioManager.EXTRA_VIBRATE_SETTING, getVibrateSetting(vibrateType));
Dianne Hackborn5ac72a22012-08-29 18:32:08 -07004356 sendBroadcastToAll(broadcast);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004357 }
4358 }
4359
4360 // Message helper methods
Jean-Michel Trivi2d8dab52012-05-30 18:13:59 -07004361 /**
4362 * Queue a message on the given handler's message queue, after acquiring the service wake lock.
4363 * Note that the wake lock needs to be released after the message has been handled.
4364 */
4365 private void queueMsgUnderWakeLock(Handler handler, int msg,
4366 int arg1, int arg2, Object obj, int delay) {
Eric Laurenta4dfbdc52013-10-01 11:53:51 -07004367 final long ident = Binder.clearCallingIdentity();
4368 // Always acquire the wake lock as AudioService because it is released by the
4369 // message handler.
Jean-Michel Trivifa9a6982013-06-27 16:22:58 -07004370 mAudioEventWakeLock.acquire();
Eric Laurenta4dfbdc52013-10-01 11:53:51 -07004371 Binder.restoreCallingIdentity(ident);
Jean-Michel Trivi2d8dab52012-05-30 18:13:59 -07004372 sendMsg(handler, msg, SENDMSG_QUEUE, arg1, arg2, obj, delay);
4373 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004374
Eric Laurentafbb0472011-12-15 09:04:23 -08004375 private static void sendMsg(Handler handler, int msg,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004376 int existingMsgPolicy, int arg1, int arg2, Object obj, int delay) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004377
4378 if (existingMsgPolicy == SENDMSG_REPLACE) {
4379 handler.removeMessages(msg);
4380 } else if (existingMsgPolicy == SENDMSG_NOOP && handler.hasMessages(msg)) {
4381 return;
4382 }
Eric Laurentadbe8bf2014-11-03 18:26:32 -08004383 synchronized (mLastDeviceConnectMsgTime) {
4384 long time = SystemClock.uptimeMillis() + delay;
4385 handler.sendMessageAtTime(handler.obtainMessage(msg, arg1, arg2, obj), time);
4386 if (msg == MSG_SET_WIRED_DEVICE_CONNECTION_STATE ||
4387 msg == MSG_SET_A2DP_SRC_CONNECTION_STATE ||
Jakub Pawlowskif9570f32018-02-21 17:15:12 -08004388 msg == MSG_SET_A2DP_SINK_CONNECTION_STATE ||
4389 msg == MSG_SET_HEARING_AID_CONNECTION_STATE) {
Eric Laurentadbe8bf2014-11-03 18:26:32 -08004390 mLastDeviceConnectMsgTime = time;
4391 }
4392 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004393 }
4394
4395 boolean checkAudioSettingsPermission(String method) {
Jean-Michel Triviccd654e2014-09-03 17:48:47 -07004396 if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.MODIFY_AUDIO_SETTINGS)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004397 == PackageManager.PERMISSION_GRANTED) {
4398 return true;
4399 }
4400 String msg = "Audio Settings Permission Denial: " + method + " from pid="
4401 + Binder.getCallingPid()
4402 + ", uid=" + Binder.getCallingUid();
4403 Log.w(TAG, msg);
4404 return false;
4405 }
4406
Eric Laurent9bc8358d2011-11-18 16:43:31 -08004407 private int getDeviceForStream(int stream) {
John Spurlock8a52c442015-03-26 14:23:58 -04004408 int device = getDevicesForStream(stream);
Eric Laurent9bc8358d2011-11-18 16:43:31 -08004409 if ((device & (device - 1)) != 0) {
4410 // Multiple device selection is either:
4411 // - speaker + one other device: give priority to speaker in this case.
4412 // - one A2DP device + another device: happens with duplicated output. In this case
4413 // retain the device on the A2DP output as the other must not correspond to an active
4414 // selection if not the speaker.
Jungshik Jangc9ff9682014-09-15 17:41:06 +09004415 // - HDMI-CEC system audio mode only output: give priority to available item in order.
Eric Laurent9bc8358d2011-11-18 16:43:31 -08004416 if ((device & AudioSystem.DEVICE_OUT_SPEAKER) != 0) {
4417 device = AudioSystem.DEVICE_OUT_SPEAKER;
Jungshik Jangc9ff9682014-09-15 17:41:06 +09004418 } else if ((device & AudioSystem.DEVICE_OUT_HDMI_ARC) != 0) {
4419 device = AudioSystem.DEVICE_OUT_HDMI_ARC;
4420 } else if ((device & AudioSystem.DEVICE_OUT_SPDIF) != 0) {
4421 device = AudioSystem.DEVICE_OUT_SPDIF;
4422 } else if ((device & AudioSystem.DEVICE_OUT_AUX_LINE) != 0) {
4423 device = AudioSystem.DEVICE_OUT_AUX_LINE;
Eric Laurent9bc8358d2011-11-18 16:43:31 -08004424 } else {
4425 device &= AudioSystem.DEVICE_OUT_ALL_A2DP;
4426 }
4427 }
4428 return device;
4429 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004430
John Spurlock8a52c442015-03-26 14:23:58 -04004431 private int getDevicesForStream(int stream) {
4432 return getDevicesForStream(stream, true /*checkOthers*/);
4433 }
4434
4435 private int getDevicesForStream(int stream, boolean checkOthers) {
4436 ensureValidStreamType(stream);
4437 synchronized (VolumeStreamState.class) {
4438 return mStreamStates[stream].observeDevicesForStream_syncVSS(checkOthers);
4439 }
4440 }
4441
4442 private void observeDevicesForStreams(int skipStream) {
4443 synchronized (VolumeStreamState.class) {
4444 for (int stream = 0; stream < mStreamStates.length; stream++) {
4445 if (stream != skipStream) {
4446 mStreamStates[stream].observeDevicesForStream_syncVSS(false /*checkOthers*/);
4447 }
4448 }
4449 }
4450 }
4451
Paul McLean10804eb2015-01-28 11:16:35 -08004452 /*
4453 * A class just for packaging up a set of connection parameters.
4454 */
Jean-Michel Trivicf170362017-08-24 17:24:57 -07004455 class WiredDeviceConnectionState {
John Spurlock90874332015-03-10 16:00:54 -04004456 public final int mType;
4457 public final int mState;
4458 public final String mAddress;
4459 public final String mName;
4460 public final String mCaller;
Paul McLean10804eb2015-01-28 11:16:35 -08004461
John Spurlock90874332015-03-10 16:00:54 -04004462 public WiredDeviceConnectionState(int type, int state, String address, String name,
4463 String caller) {
Paul McLean10804eb2015-01-28 11:16:35 -08004464 mType = type;
4465 mState = state;
4466 mAddress = address;
4467 mName = name;
John Spurlock90874332015-03-10 16:00:54 -04004468 mCaller = caller;
Paul McLean10804eb2015-01-28 11:16:35 -08004469 }
4470 }
4471
John Spurlock90874332015-03-10 16:00:54 -04004472 public void setWiredDeviceConnectionState(int type, int state, String address, String name,
4473 String caller) {
Eric Laurentb1fbaac2012-05-29 09:24:28 -07004474 synchronized (mConnectedDevices) {
Paul McLean394a8e12015-03-03 10:29:19 -07004475 if (DEBUG_DEVICES) {
4476 Slog.i(TAG, "setWiredDeviceConnectionState(" + state + " nm: " + name + " addr:"
4477 + address + ")");
4478 }
Eric Laurentcdae4762017-04-28 18:00:04 -07004479 int delay = checkSendBecomingNoisyIntent(type, state, AudioSystem.DEVICE_NONE);
Jean-Michel Trivi2d8dab52012-05-30 18:13:59 -07004480 queueMsgUnderWakeLock(mAudioHandler,
Eric Laurentb1fbaac2012-05-29 09:24:28 -07004481 MSG_SET_WIRED_DEVICE_CONNECTION_STATE,
Pavlin Radoslavov44a4ef02016-12-21 12:05:51 -08004482 0 /* arg1 unused */,
4483 0 /* arg2 unused */,
John Spurlock90874332015-03-10 16:00:54 -04004484 new WiredDeviceConnectionState(type, state, address, name, caller),
Eric Laurentb1fbaac2012-05-29 09:24:28 -07004485 delay);
4486 }
4487 }
4488
Jakub Pawlowski10c90612018-02-21 13:28:46 -08004489 @Override
4490 public void setHearingAidDeviceConnectionState(BluetoothDevice device, int state)
4491 {
Jakub Pawlowskif9570f32018-02-21 17:15:12 -08004492 Log.i(TAG, "setBluetoothHearingAidDeviceConnectionState");
4493
4494 setBluetoothHearingAidDeviceConnectionState(
4495 device, state, false /* suppressNoisyIntent */, AudioSystem.DEVICE_NONE);
4496 }
4497
4498 public int setBluetoothHearingAidDeviceConnectionState(
4499 BluetoothDevice device, int state, boolean suppressNoisyIntent,
4500 int musicDevice)
4501 {
4502 int delay;
4503 synchronized (mConnectedDevices) {
4504 if (!suppressNoisyIntent) {
4505 int intState = (state == BluetoothHearingAid.STATE_CONNECTED) ? 1 : 0;
4506 delay = checkSendBecomingNoisyIntent(AudioSystem.DEVICE_OUT_HEARING_AID,
4507 intState, musicDevice);
4508 } else {
4509 delay = 0;
4510 }
4511 queueMsgUnderWakeLock(mAudioHandler,
4512 MSG_SET_HEARING_AID_CONNECTION_STATE,
4513 state,
4514 0 /* arg2 unused */,
4515 device,
4516 delay);
4517 }
4518 return delay;
Jakub Pawlowski10c90612018-02-21 13:28:46 -08004519 }
4520
Mike Lockwood0a40ec22014-05-21 10:08:50 -07004521 public int setBluetoothA2dpDeviceConnectionState(BluetoothDevice device, int state, int profile)
Eric Laurentb1fbaac2012-05-29 09:24:28 -07004522 {
Pavlin Radoslavov82e06462018-01-19 18:20:04 -08004523 return setBluetoothA2dpDeviceConnectionStateSuppressNoisyIntent(
4524 device, state, profile, false /* suppressNoisyIntent */);
4525 }
4526
4527 public int setBluetoothA2dpDeviceConnectionStateSuppressNoisyIntent(BluetoothDevice device,
4528 int state, int profile, boolean suppressNoisyIntent)
4529 {
Eric Laurent4724ea72017-05-23 10:39:38 -07004530 if (mAudioHandler.hasMessages(MSG_SET_A2DP_SINK_CONNECTION_STATE, device)) {
Eric Laurentcdae4762017-04-28 18:00:04 -07004531 return 0;
4532 }
4533 return setBluetoothA2dpDeviceConnectionStateInt(
Pavlin Radoslavov82e06462018-01-19 18:20:04 -08004534 device, state, profile, suppressNoisyIntent, AudioSystem.DEVICE_NONE);
Eric Laurentcdae4762017-04-28 18:00:04 -07004535 }
4536
4537 public int setBluetoothA2dpDeviceConnectionStateInt(
Pavlin Radoslavov82e06462018-01-19 18:20:04 -08004538 BluetoothDevice device, int state, int profile, boolean suppressNoisyIntent,
4539 int musicDevice)
Eric Laurentcdae4762017-04-28 18:00:04 -07004540 {
Eric Laurentb1fbaac2012-05-29 09:24:28 -07004541 int delay;
Mike Lockwood0a40ec22014-05-21 10:08:50 -07004542 if (profile != BluetoothProfile.A2DP && profile != BluetoothProfile.A2DP_SINK) {
4543 throw new IllegalArgumentException("invalid profile " + profile);
4544 }
Eric Laurentb1fbaac2012-05-29 09:24:28 -07004545 synchronized (mConnectedDevices) {
Pavlin Radoslavov82e06462018-01-19 18:20:04 -08004546 if (profile == BluetoothProfile.A2DP && !suppressNoisyIntent) {
Eric Laurentcdae4762017-04-28 18:00:04 -07004547 int intState = (state == BluetoothA2dp.STATE_CONNECTED) ? 1 : 0;
Mike Lockwood0a40ec22014-05-21 10:08:50 -07004548 delay = checkSendBecomingNoisyIntent(AudioSystem.DEVICE_OUT_BLUETOOTH_A2DP,
Eric Laurentcdae4762017-04-28 18:00:04 -07004549 intState, musicDevice);
Mike Lockwood0a40ec22014-05-21 10:08:50 -07004550 } else {
4551 delay = 0;
4552 }
Jean-Michel Trivi2d8dab52012-05-30 18:13:59 -07004553 queueMsgUnderWakeLock(mAudioHandler,
Mike Lockwood0a40ec22014-05-21 10:08:50 -07004554 (profile == BluetoothProfile.A2DP ?
4555 MSG_SET_A2DP_SINK_CONNECTION_STATE : MSG_SET_A2DP_SRC_CONNECTION_STATE),
Eric Laurentb1fbaac2012-05-29 09:24:28 -07004556 state,
Pavlin Radoslavov44a4ef02016-12-21 12:05:51 -08004557 0 /* arg2 unused */,
Eric Laurentb1fbaac2012-05-29 09:24:28 -07004558 device,
4559 delay);
4560 }
4561 return delay;
4562 }
4563
Pavlin Radoslavov44a4ef02016-12-21 12:05:51 -08004564 public void handleBluetoothA2dpDeviceConfigChange(BluetoothDevice device)
4565 {
4566 synchronized (mConnectedDevices) {
4567 queueMsgUnderWakeLock(mAudioHandler,
4568 MSG_A2DP_DEVICE_CONFIG_CHANGE,
4569 0 /* arg1 unused */,
4570 0 /* arg1 unused */,
4571 device,
4572 0 /* delay */);
4573 }
4574 }
4575
Jean-Michel Trivi1ab43f62017-04-27 15:37:34 -07004576 private static final int DEVICE_MEDIA_UNMUTED_ON_PLUG =
4577 AudioSystem.DEVICE_OUT_WIRED_HEADSET | AudioSystem.DEVICE_OUT_WIRED_HEADPHONE |
4578 AudioSystem.DEVICE_OUT_LINE |
4579 AudioSystem.DEVICE_OUT_ALL_A2DP |
4580 AudioSystem.DEVICE_OUT_ALL_USB |
4581 AudioSystem.DEVICE_OUT_HDMI;
4582
4583 private void onAccessoryPlugMediaUnmute(int newDevice) {
4584 if (DEBUG_VOL) {
4585 Log.i(TAG, String.format("onAccessoryPlugMediaUnmute newDevice=%d [%s]",
4586 newDevice, AudioSystem.getOutputDeviceName(newDevice)));
4587 }
4588 synchronized (mConnectedDevices) {
Eric Laurent7fb83d92017-09-28 09:36:36 -07004589 if (mNm.getZenMode() != Settings.Global.ZEN_MODE_NO_INTERRUPTIONS
4590 && (newDevice & DEVICE_MEDIA_UNMUTED_ON_PLUG) != 0
Jean-Michel Trivi1ab43f62017-04-27 15:37:34 -07004591 && mStreamStates[AudioSystem.STREAM_MUSIC].mIsMuted
4592 && mStreamStates[AudioSystem.STREAM_MUSIC].getIndex(newDevice) != 0
4593 && (newDevice & AudioSystem.getDevicesForStream(AudioSystem.STREAM_MUSIC)) != 0)
4594 {
4595 if (DEBUG_VOL) {
4596 Log.i(TAG, String.format(" onAccessoryPlugMediaUnmute unmuting device=%d [%s]",
4597 newDevice, AudioSystem.getOutputDeviceName(newDevice)));
4598 }
4599 mStreamStates[AudioSystem.STREAM_MUSIC].mute(false);
4600 }
4601 }
4602 }
4603
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004604 ///////////////////////////////////////////////////////////////////////////
4605 // Inner classes
4606 ///////////////////////////////////////////////////////////////////////////
4607
Eric Laurent8fa4d6f2014-10-30 14:13:03 -07004608 // NOTE: Locking order for synchronized objects related to volume or ringer mode management:
4609 // 1 mScoclient OR mSafeMediaVolumeState
4610 // 2 mSetModeDeathHandlers
4611 // 3 mSettingsLock
4612 // 4 VolumeStreamState.class
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004613 public class VolumeStreamState {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004614 private final int mStreamType;
Jean-Michel Trivie05eef82018-03-08 18:56:34 -08004615 private int mIndexMin;
4616 private int mIndexMax;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004617
RoboErik4197cb62015-01-21 15:45:32 -08004618 private boolean mIsMuted;
Jean-Michel Trivi11a74a72009-10-27 17:39:30 -07004619 private String mVolumeIndexSettingName;
John Spurlock8a52c442015-03-26 14:23:58 -04004620 private int mObservedDevices;
John Spurlockb6e19e32015-03-10 21:33:44 -04004621
John Spurlock2bb02ec2015-03-02 13:13:06 -05004622 private final SparseIntArray mIndexMap = new SparseIntArray(8);
John Spurlockf63860c2015-02-19 09:46:27 -05004623 private final Intent mVolumeChanged;
John Spurlock8a52c442015-03-26 14:23:58 -04004624 private final Intent mStreamDevicesChanged;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004625
Eric Laurenta553c252009-07-17 12:17:14 -07004626 private VolumeStreamState(String settingName, int streamType) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004627
Eric Laurent9bc8358d2011-11-18 16:43:31 -08004628 mVolumeIndexSettingName = settingName;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004629
4630 mStreamType = streamType;
John Spurlockb6e19e32015-03-10 21:33:44 -04004631 mIndexMin = MIN_STREAM_VOLUME[streamType] * 10;
4632 mIndexMax = MAX_STREAM_VOLUME[streamType] * 10;
4633 AudioSystem.initStreamVolume(streamType, mIndexMin / 10, mIndexMax / 10);
Eric Laurent9bc8358d2011-11-18 16:43:31 -08004634
Eric Laurent33902db2012-10-07 16:15:07 -07004635 readSettings();
John Spurlockf63860c2015-02-19 09:46:27 -05004636 mVolumeChanged = new Intent(AudioManager.VOLUME_CHANGED_ACTION);
4637 mVolumeChanged.putExtra(AudioManager.EXTRA_VOLUME_STREAM_TYPE, mStreamType);
John Spurlock8a52c442015-03-26 14:23:58 -04004638 mStreamDevicesChanged = new Intent(AudioManager.STREAM_DEVICES_CHANGED_ACTION);
4639 mStreamDevicesChanged.putExtra(AudioManager.EXTRA_VOLUME_STREAM_TYPE, mStreamType);
4640 }
4641
4642 public int observeDevicesForStream_syncVSS(boolean checkOthers) {
4643 final int devices = AudioSystem.getDevicesForStream(mStreamType);
4644 if (devices == mObservedDevices) {
4645 return devices;
4646 }
4647 final int prevDevices = mObservedDevices;
4648 mObservedDevices = devices;
4649 if (checkOthers) {
4650 // one stream's devices have changed, check the others
4651 observeDevicesForStreams(mStreamType);
4652 }
4653 // log base stream changes to the event log
4654 if (mStreamVolumeAlias[mStreamType] == mStreamType) {
4655 EventLogTags.writeStreamDevicesChanged(mStreamType, prevDevices, devices);
4656 }
4657 sendBroadcastToAll(mStreamDevicesChanged
4658 .putExtra(AudioManager.EXTRA_PREV_VOLUME_STREAM_DEVICES, prevDevices)
4659 .putExtra(AudioManager.EXTRA_VOLUME_STREAM_DEVICES, devices));
4660 return devices;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004661 }
4662
Jean-Michel Trivia53b7052017-04-12 18:27:01 -07004663 public @Nullable String getSettingNameForDevice(int device) {
4664 if (!hasValidSettingsName()) {
4665 return null;
Eric Laurent9bc8358d2011-11-18 16:43:31 -08004666 }
Jean-Michel Trivia53b7052017-04-12 18:27:01 -07004667 final String suffix = AudioSystem.getOutputDeviceName(device);
4668 if (suffix.isEmpty()) {
4669 return mVolumeIndexSettingName;
4670 }
4671 return mVolumeIndexSettingName + "_" + suffix;
4672 }
4673
4674 private boolean hasValidSettingsName() {
4675 return (mVolumeIndexSettingName != null && !mVolumeIndexSettingName.isEmpty());
Jean-Michel Trivi11a74a72009-10-27 17:39:30 -07004676 }
4677
Eric Laurentfdbee862014-05-12 15:26:12 -07004678 public void readSettings() {
Jean-Michel Trivi8719a1d2017-11-06 11:52:51 -08004679 synchronized (mSettingsLock) {
4680 synchronized (VolumeStreamState.class) {
4681 // force maximum volume on all streams if fixed volume property is set
4682 if (mUseFixedVolume) {
4683 mIndexMap.put(AudioSystem.DEVICE_OUT_DEFAULT, mIndexMax);
4684 return;
4685 }
4686 // do not read system stream volume from settings: this stream is always aliased
4687 // to another stream type and its volume is never persisted. Values in settings can
4688 // only be stale values
4689 if ((mStreamType == AudioSystem.STREAM_SYSTEM) ||
4690 (mStreamType == AudioSystem.STREAM_SYSTEM_ENFORCED)) {
4691 int index = 10 * AudioSystem.DEFAULT_STREAM_VOLUME[mStreamType];
Eric Laurentfdbee862014-05-12 15:26:12 -07004692 if (mCameraSoundForced) {
4693 index = mIndexMax;
4694 }
Jean-Michel Trivi8719a1d2017-11-06 11:52:51 -08004695 mIndexMap.put(AudioSystem.DEVICE_OUT_DEFAULT, index);
4696 return;
Eric Laurentdd45d012012-10-08 09:04:34 -07004697 }
Eric Laurent9bc8358d2011-11-18 16:43:31 -08004698 }
Jean-Michel Trivi8719a1d2017-11-06 11:52:51 -08004699 }
4700 synchronized (VolumeStreamState.class) {
Eric Laurentfdbee862014-05-12 15:26:12 -07004701 int remainingDevices = AudioSystem.DEVICE_OUT_ALL;
4702
4703 for (int i = 0; remainingDevices != 0; i++) {
4704 int device = (1 << i);
4705 if ((device & remainingDevices) == 0) {
4706 continue;
4707 }
4708 remainingDevices &= ~device;
4709
4710 // retrieve current volume for device
Eric Laurentfdbee862014-05-12 15:26:12 -07004711 // if no volume stored for current stream and device, use default volume if default
4712 // device, continue otherwise
4713 int defaultIndex = (device == AudioSystem.DEVICE_OUT_DEFAULT) ?
John Spurlock61560172015-02-06 19:46:04 -05004714 AudioSystem.DEFAULT_STREAM_VOLUME[mStreamType] : -1;
Jean-Michel Trivia53b7052017-04-12 18:27:01 -07004715 int index;
4716 if (!hasValidSettingsName()) {
4717 index = defaultIndex;
4718 } else {
4719 String name = getSettingNameForDevice(device);
4720 index = Settings.System.getIntForUser(
4721 mContentResolver, name, defaultIndex, UserHandle.USER_CURRENT);
4722 }
Eric Laurentfdbee862014-05-12 15:26:12 -07004723 if (index == -1) {
4724 continue;
4725 }
4726
John Spurlock2bb02ec2015-03-02 13:13:06 -05004727 mIndexMap.put(device, getValidIndex(10 * index));
Eric Laurentdd45d012012-10-08 09:04:34 -07004728 }
Eric Laurent9bc8358d2011-11-18 16:43:31 -08004729 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004730 }
4731
Liejun Tao39fb5672016-03-09 15:52:13 -06004732 private int getAbsoluteVolumeIndex(int index) {
4733 /* Special handling for Bluetooth Absolute Volume scenario
4734 * If we send full audio gain, some accessories are too loud even at its lowest
4735 * volume. We are not able to enumerate all such accessories, so here is the
4736 * workaround from phone side.
4737 * Pre-scale volume at lowest volume steps 1 2 and 3.
4738 * For volume step 0, set audio gain to 0 as some accessories won't mute on their end.
4739 */
4740 if (index == 0) {
4741 // 0% for volume 0
4742 index = 0;
4743 } else if (index == 1) {
4744 // 50% for volume 1
4745 index = (int)(mIndexMax * 0.5) /10;
4746 } else if (index == 2) {
4747 // 70% for volume 2
4748 index = (int)(mIndexMax * 0.70) /10;
4749 } else if (index == 3) {
4750 // 85% for volume 3
4751 index = (int)(mIndexMax * 0.85) /10;
4752 } else {
4753 // otherwise, full gain
4754 index = (mIndexMax + 5)/10;
4755 }
4756 return index;
4757 }
4758
Eric Laurent8fa4d6f2014-10-30 14:13:03 -07004759 // must be called while synchronized VolumeStreamState.class
4760 public void applyDeviceVolume_syncVSS(int device) {
Eric Laurent42b041e2013-03-29 11:36:03 -07004761 int index;
RoboErik4197cb62015-01-21 15:45:32 -08004762 if (mIsMuted) {
Eric Laurent42b041e2013-03-29 11:36:03 -07004763 index = 0;
Liejun Tao4565a472016-01-20 17:52:20 -06004764 } else if ((device & AudioSystem.DEVICE_OUT_ALL_A2DP) != 0 && mAvrcpAbsVolSupported) {
Liejun Tao39fb5672016-03-09 15:52:13 -06004765 index = getAbsoluteVolumeIndex((getIndex(device) + 5)/10);
Liejun Tao4565a472016-01-20 17:52:20 -06004766 } else if ((device & mFullVolumeDevices) != 0) {
Matthew Xiec9d1d5f2013-09-12 00:32:22 -07004767 index = (mIndexMax + 5)/10;
Jakub Pawlowskic274fb22018-04-04 10:15:12 -07004768 } else if ((device & AudioSystem.DEVICE_OUT_HEARING_AID) != 0) {
4769 index = (mIndexMax + 5)/10;
Eric Laurentcd772d02013-10-30 18:31:07 -07004770 } else {
Eric Laurent42b041e2013-03-29 11:36:03 -07004771 index = (getIndex(device) + 5)/10;
4772 }
4773 AudioSystem.setStreamVolumeIndex(mStreamType, index, device);
Eric Laurent9bc8358d2011-11-18 16:43:31 -08004774 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004775
Eric Laurentfdbee862014-05-12 15:26:12 -07004776 public void applyAllVolumes() {
4777 synchronized (VolumeStreamState.class) {
Eric Laurentd9ac2be2016-04-07 14:04:23 -07004778 // apply device specific volumes first
Eric Laurentfdbee862014-05-12 15:26:12 -07004779 int index;
John Spurlock2bb02ec2015-03-02 13:13:06 -05004780 for (int i = 0; i < mIndexMap.size(); i++) {
Eric Laurentd9ac2be2016-04-07 14:04:23 -07004781 final int device = mIndexMap.keyAt(i);
Eric Laurentfdbee862014-05-12 15:26:12 -07004782 if (device != AudioSystem.DEVICE_OUT_DEFAULT) {
RoboErik4197cb62015-01-21 15:45:32 -08004783 if (mIsMuted) {
Eric Laurentfdbee862014-05-12 15:26:12 -07004784 index = 0;
Liejun Tao39fb5672016-03-09 15:52:13 -06004785 } else if ((device & AudioSystem.DEVICE_OUT_ALL_A2DP) != 0 &&
4786 mAvrcpAbsVolSupported) {
4787 index = getAbsoluteVolumeIndex((getIndex(device) + 5)/10);
4788 } else if ((device & mFullVolumeDevices) != 0) {
Eric Laurentfdbee862014-05-12 15:26:12 -07004789 index = (mIndexMax + 5)/10;
Jakub Pawlowskic274fb22018-04-04 10:15:12 -07004790 } else if ((device & AudioSystem.DEVICE_OUT_HEARING_AID) != 0) {
4791 index = (mIndexMax + 5)/10;
Eric Laurentfdbee862014-05-12 15:26:12 -07004792 } else {
John Spurlock2bb02ec2015-03-02 13:13:06 -05004793 index = (mIndexMap.valueAt(i) + 5)/10;
Eric Laurentfdbee862014-05-12 15:26:12 -07004794 }
4795 AudioSystem.setStreamVolumeIndex(mStreamType, index, device);
Eric Laurent42b041e2013-03-29 11:36:03 -07004796 }
Eric Laurent9bc8358d2011-11-18 16:43:31 -08004797 }
Eric Laurentd9ac2be2016-04-07 14:04:23 -07004798 // apply default volume last: by convention , default device volume will be used
4799 // by audio policy manager if no explicit volume is present for a given device type
4800 if (mIsMuted) {
4801 index = 0;
4802 } else {
4803 index = (getIndex(AudioSystem.DEVICE_OUT_DEFAULT) + 5)/10;
4804 }
4805 AudioSystem.setStreamVolumeIndex(
4806 mStreamType, index, AudioSystem.DEVICE_OUT_DEFAULT);
Eric Laurent9bc8358d2011-11-18 16:43:31 -08004807 }
4808 }
4809
John Spurlock90874332015-03-10 16:00:54 -04004810 public boolean adjustIndex(int deltaIndex, int device, String caller) {
4811 return setIndex(getIndex(device) + deltaIndex, device, caller);
Eric Laurent9bc8358d2011-11-18 16:43:31 -08004812 }
4813
John Spurlock90874332015-03-10 16:00:54 -04004814 public boolean setIndex(int index, int device, String caller) {
Jack He6dd78c12018-02-12 21:00:24 -08004815 boolean changed;
John Spurlockf63860c2015-02-19 09:46:27 -05004816 int oldIndex;
Jean-Michel Trivi8719a1d2017-11-06 11:52:51 -08004817 synchronized (mSettingsLock) {
4818 synchronized (VolumeStreamState.class) {
4819 oldIndex = getIndex(device);
4820 index = getValidIndex(index);
Eric Laurentfdbee862014-05-12 15:26:12 -07004821 if ((mStreamType == AudioSystem.STREAM_SYSTEM_ENFORCED) && mCameraSoundForced) {
4822 index = mIndexMax;
Eric Laurenta553c252009-07-17 12:17:14 -07004823 }
Jean-Michel Trivi8719a1d2017-11-06 11:52:51 -08004824 mIndexMap.put(device, index);
Eric Laurentfdbee862014-05-12 15:26:12 -07004825
Jean-Michel Trivi8719a1d2017-11-06 11:52:51 -08004826 changed = oldIndex != index;
4827 // Apply change to all streams using this one as alias if:
4828 // - the index actually changed OR
4829 // - there is no volume index stored for this device on alias stream.
4830 // If changing volume of current device, also change volume of current
4831 // device on aliased stream
Jack He6dd78c12018-02-12 21:00:24 -08004832 final boolean isCurrentDevice = (device == getDeviceForStream(mStreamType));
Jean-Michel Trivi8719a1d2017-11-06 11:52:51 -08004833 final int numStreamTypes = AudioSystem.getNumStreamTypes();
4834 for (int streamType = numStreamTypes - 1; streamType >= 0; streamType--) {
4835 final VolumeStreamState aliasStreamState = mStreamStates[streamType];
4836 if (streamType != mStreamType &&
4837 mStreamVolumeAlias[streamType] == mStreamType &&
4838 (changed || !aliasStreamState.hasIndexForDevice(device))) {
4839 final int scaledIndex = rescaleIndex(index, mStreamType, streamType);
4840 aliasStreamState.setIndex(scaledIndex, device, caller);
Jack He6dd78c12018-02-12 21:00:24 -08004841 if (isCurrentDevice) {
Jean-Michel Trivi8719a1d2017-11-06 11:52:51 -08004842 aliasStreamState.setIndex(scaledIndex,
4843 getDeviceForStream(streamType), caller);
4844 }
Eric Laurentfdbee862014-05-12 15:26:12 -07004845 }
4846 }
Jack He6dd78c12018-02-12 21:00:24 -08004847 // Mirror changes in SPEAKER ringtone volume on SCO when
4848 if (changed && mStreamType == AudioSystem.STREAM_RING
4849 && device == AudioSystem.DEVICE_OUT_SPEAKER) {
4850 for (int i = 0; i < mIndexMap.size(); i++) {
4851 int otherDevice = mIndexMap.keyAt(i);
4852 if ((otherDevice & AudioSystem.DEVICE_OUT_ALL_SCO) != 0) {
4853 mIndexMap.put(otherDevice, index);
4854 }
4855 }
4856 }
Eric Laurentfdbee862014-05-12 15:26:12 -07004857 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004858 }
John Spurlockf63860c2015-02-19 09:46:27 -05004859 if (changed) {
4860 oldIndex = (oldIndex + 5) / 10;
4861 index = (index + 5) / 10;
John Spurlock90874332015-03-10 16:00:54 -04004862 // log base stream changes to the event log
4863 if (mStreamVolumeAlias[mStreamType] == mStreamType) {
4864 if (caller == null) {
4865 Log.w(TAG, "No caller for volume_changed event", new Throwable());
4866 }
4867 EventLogTags.writeVolumeChanged(mStreamType, oldIndex, index, mIndexMax / 10,
4868 caller);
4869 }
4870 // fire changed intents for all streams
John Spurlockf63860c2015-02-19 09:46:27 -05004871 mVolumeChanged.putExtra(AudioManager.EXTRA_VOLUME_STREAM_VALUE, index);
4872 mVolumeChanged.putExtra(AudioManager.EXTRA_PREV_VOLUME_STREAM_VALUE, oldIndex);
Jean-Michel Trivi560877d2015-06-25 17:38:35 -07004873 mVolumeChanged.putExtra(AudioManager.EXTRA_VOLUME_STREAM_TYPE_ALIAS,
4874 mStreamVolumeAlias[mStreamType]);
John Spurlockf63860c2015-02-19 09:46:27 -05004875 sendBroadcastToAll(mVolumeChanged);
4876 }
4877 return changed;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004878 }
4879
Eric Laurentfdbee862014-05-12 15:26:12 -07004880 public int getIndex(int device) {
4881 synchronized (VolumeStreamState.class) {
John Spurlock2bb02ec2015-03-02 13:13:06 -05004882 int index = mIndexMap.get(device, -1);
4883 if (index == -1) {
Eric Laurentfdbee862014-05-12 15:26:12 -07004884 // there is always an entry for AudioSystem.DEVICE_OUT_DEFAULT
John Spurlock2bb02ec2015-03-02 13:13:06 -05004885 index = mIndexMap.get(AudioSystem.DEVICE_OUT_DEFAULT);
Eric Laurentfdbee862014-05-12 15:26:12 -07004886 }
John Spurlock2bb02ec2015-03-02 13:13:06 -05004887 return index;
Eric Laurent9bc8358d2011-11-18 16:43:31 -08004888 }
Eric Laurent5b4e6542010-03-19 20:02:21 -07004889 }
4890
Eric Laurent3fb608e2016-11-03 16:27:40 -07004891 public boolean hasIndexForDevice(int device) {
4892 synchronized (VolumeStreamState.class) {
4893 return (mIndexMap.get(device, -1) != -1);
4894 }
4895 }
4896
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004897 public int getMaxIndex() {
Eric Laurenta553c252009-07-17 12:17:14 -07004898 return mIndexMax;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004899 }
4900
John Spurlockb6e19e32015-03-10 21:33:44 -04004901 public int getMinIndex() {
4902 return mIndexMin;
4903 }
4904
Jean-Michel Trivi170a0ee2017-04-14 18:13:26 -07004905 /**
Jean-Michel Trivie05eef82018-03-08 18:56:34 -08004906 * Updates the min/max index values from another stream. Use this when changing the alias
4907 * for the current stream type.
4908 * @param sourceStreamType
4909 */
4910 // must be sync'd on mSettingsLock before VolumeStreamState.class
4911 @GuardedBy("VolumeStreamState.class")
4912 public void refreshRange(int sourceStreamType) {
4913 mIndexMin = MIN_STREAM_VOLUME[sourceStreamType] * 10;
4914 mIndexMax = MAX_STREAM_VOLUME[sourceStreamType] * 10;
4915 // verify all current volumes are within bounds
4916 for (int i = 0 ; i < mIndexMap.size(); i++) {
4917 final int device = mIndexMap.keyAt(i);
4918 final int index = mIndexMap.valueAt(i);
4919 mIndexMap.put(device, getValidIndex(index));
4920 }
4921 }
4922
4923 /**
Jean-Michel Trivi170a0ee2017-04-14 18:13:26 -07004924 * Copies all device/index pairs from the given VolumeStreamState after initializing
4925 * them with the volume for DEVICE_OUT_DEFAULT. No-op if the source VolumeStreamState
4926 * has the same stream type as this instance.
4927 * @param srcStream
4928 * @param caller
4929 */
Jean-Michel Trivi085346a2018-02-14 10:48:51 -08004930 // must be sync'd on mSettingsLock before VolumeStreamState.class
4931 @GuardedBy("VolumeStreamState.class")
John Spurlock90874332015-03-10 16:00:54 -04004932 public void setAllIndexes(VolumeStreamState srcStream, String caller) {
Jean-Michel Trivi170a0ee2017-04-14 18:13:26 -07004933 if (mStreamType == srcStream.mStreamType) {
4934 return;
4935 }
Jean-Michel Trivi085346a2018-02-14 10:48:51 -08004936 int srcStreamType = srcStream.getStreamType();
4937 // apply default device volume from source stream to all devices first in case
4938 // some devices are present in this stream state but not in source stream state
4939 int index = srcStream.getIndex(AudioSystem.DEVICE_OUT_DEFAULT);
4940 index = rescaleIndex(index, srcStreamType, mStreamType);
4941 for (int i = 0; i < mIndexMap.size(); i++) {
4942 mIndexMap.put(mIndexMap.keyAt(i), index);
4943 }
4944 // Now apply actual volume for devices in source stream state
4945 SparseIntArray srcMap = srcStream.mIndexMap;
4946 for (int i = 0; i < srcMap.size(); i++) {
4947 int device = srcMap.keyAt(i);
4948 index = srcMap.valueAt(i);
4949 index = rescaleIndex(index, srcStreamType, mStreamType);
Eric Laurent33902db2012-10-07 16:15:07 -07004950
Jean-Michel Trivi085346a2018-02-14 10:48:51 -08004951 setIndex(index, device, caller);
Eric Laurent6d517662012-04-23 18:42:39 -07004952 }
4953 }
4954
Jean-Michel Trivi085346a2018-02-14 10:48:51 -08004955 // must be sync'd on mSettingsLock before VolumeStreamState.class
4956 @GuardedBy("VolumeStreamState.class")
Eric Laurentfdbee862014-05-12 15:26:12 -07004957 public void setAllIndexesToMax() {
Jean-Michel Trivi085346a2018-02-14 10:48:51 -08004958 for (int i = 0; i < mIndexMap.size(); i++) {
4959 mIndexMap.put(mIndexMap.keyAt(i), mIndexMax);
Eric Laurentdd45d012012-10-08 09:04:34 -07004960 }
Eric Laurentdd45d012012-10-08 09:04:34 -07004961 }
4962
RoboErik4197cb62015-01-21 15:45:32 -08004963 public void mute(boolean state) {
John Spurlock22b9ee12015-02-18 22:51:44 -05004964 boolean changed = false;
Eric Laurentfdbee862014-05-12 15:26:12 -07004965 synchronized (VolumeStreamState.class) {
RoboErik4197cb62015-01-21 15:45:32 -08004966 if (state != mIsMuted) {
John Spurlock22b9ee12015-02-18 22:51:44 -05004967 changed = true;
RoboErik4197cb62015-01-21 15:45:32 -08004968 mIsMuted = state;
John Spurlock22b9ee12015-02-18 22:51:44 -05004969
RoboErik4197cb62015-01-21 15:45:32 -08004970 // Set the new mute volume. This propagates the values to
4971 // the audio system, otherwise the volume won't be changed
4972 // at the lower level.
4973 sendMsg(mAudioHandler,
4974 MSG_SET_ALL_VOLUMES,
4975 SENDMSG_QUEUE,
4976 0,
4977 0,
4978 this, 0);
Eric Laurentfdbee862014-05-12 15:26:12 -07004979 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004980 }
John Spurlock22b9ee12015-02-18 22:51:44 -05004981 if (changed) {
4982 // Stream mute changed, fire the intent.
4983 Intent intent = new Intent(AudioManager.STREAM_MUTE_CHANGED_ACTION);
4984 intent.putExtra(AudioManager.EXTRA_VOLUME_STREAM_TYPE, mStreamType);
4985 intent.putExtra(AudioManager.EXTRA_STREAM_VOLUME_MUTED, state);
4986 sendBroadcastToAll(intent);
4987 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004988 }
4989
Eric Laurent6d517662012-04-23 18:42:39 -07004990 public int getStreamType() {
4991 return mStreamType;
4992 }
4993
Eric Laurent212532b2014-07-21 15:43:18 -07004994 public void checkFixedVolumeDevices() {
4995 synchronized (VolumeStreamState.class) {
4996 // ignore settings for fixed volume devices: volume should always be at max or 0
4997 if (mStreamVolumeAlias[mStreamType] == AudioSystem.STREAM_MUSIC) {
John Spurlock2bb02ec2015-03-02 13:13:06 -05004998 for (int i = 0; i < mIndexMap.size(); i++) {
4999 int device = mIndexMap.keyAt(i);
5000 int index = mIndexMap.valueAt(i);
Jean-Michel Triviba5270b2014-10-01 17:49:29 -07005001 if (((device & mFullVolumeDevices) != 0)
5002 || (((device & mFixedVolumeDevices) != 0) && index != 0)) {
John Spurlock2bb02ec2015-03-02 13:13:06 -05005003 mIndexMap.put(device, mIndexMax);
Eric Laurent212532b2014-07-21 15:43:18 -07005004 }
Eric Laurent8fa4d6f2014-10-30 14:13:03 -07005005 applyDeviceVolume_syncVSS(device);
Eric Laurent212532b2014-07-21 15:43:18 -07005006 }
5007 }
5008 }
5009 }
5010
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005011 private int getValidIndex(int index) {
John Spurlockb6e19e32015-03-10 21:33:44 -04005012 if (index < mIndexMin) {
5013 return mIndexMin;
John Spurlockee5ad722015-03-03 16:17:21 -05005014 } else if (mUseFixedVolume || index > mIndexMax) {
Eric Laurenta553c252009-07-17 12:17:14 -07005015 return mIndexMax;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005016 }
5017
5018 return index;
5019 }
5020
Eric Laurentbffc3d12012-05-07 17:43:49 -07005021 private void dump(PrintWriter pw) {
RoboErik4197cb62015-01-21 15:45:32 -08005022 pw.print(" Muted: ");
5023 pw.println(mIsMuted);
John Spurlockb6e19e32015-03-10 21:33:44 -04005024 pw.print(" Min: ");
5025 pw.println((mIndexMin + 5) / 10);
John Spurlock2b29bc42014-08-26 16:40:35 -04005026 pw.print(" Max: ");
5027 pw.println((mIndexMax + 5) / 10);
Eric Laurentbffc3d12012-05-07 17:43:49 -07005028 pw.print(" Current: ");
John Spurlock2bb02ec2015-03-02 13:13:06 -05005029 for (int i = 0; i < mIndexMap.size(); i++) {
5030 if (i > 0) {
5031 pw.print(", ");
5032 }
5033 final int device = mIndexMap.keyAt(i);
John Spurlock2b29bc42014-08-26 16:40:35 -04005034 pw.print(Integer.toHexString(device));
5035 final String deviceName = device == AudioSystem.DEVICE_OUT_DEFAULT ? "default"
5036 : AudioSystem.getOutputDeviceName(device);
5037 if (!deviceName.isEmpty()) {
5038 pw.print(" (");
5039 pw.print(deviceName);
5040 pw.print(")");
5041 }
5042 pw.print(": ");
John Spurlock2bb02ec2015-03-02 13:13:06 -05005043 final int index = (mIndexMap.valueAt(i) + 5) / 10;
John Spurlock2b29bc42014-08-26 16:40:35 -04005044 pw.print(index);
Eric Laurentbffc3d12012-05-07 17:43:49 -07005045 }
John Spurlockb32fc972015-03-05 13:58:00 -05005046 pw.println();
5047 pw.print(" Devices: ");
John Spurlock8a52c442015-03-26 14:23:58 -04005048 final int devices = getDevicesForStream(mStreamType);
John Spurlockb32fc972015-03-05 13:58:00 -05005049 int device, i = 0, n = 0;
John Spurlock1ff1e6e2015-03-09 14:21:20 -04005050 // iterate all devices from 1 to DEVICE_OUT_DEFAULT exclusive
5051 // (the default device is not returned by getDevicesForStream)
5052 while ((device = 1 << i) != AudioSystem.DEVICE_OUT_DEFAULT) {
John Spurlockb32fc972015-03-05 13:58:00 -05005053 if ((devices & device) != 0) {
5054 if (n++ > 0) {
5055 pw.print(", ");
5056 }
5057 pw.print(AudioSystem.getOutputDeviceName(device));
5058 }
5059 i++;
5060 }
Eric Laurentbffc3d12012-05-07 17:43:49 -07005061 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005062 }
5063
5064 /** Thread that handles native AudioSystem control. */
5065 private class AudioSystemThread extends Thread {
5066 AudioSystemThread() {
5067 super("AudioService");
5068 }
5069
5070 @Override
5071 public void run() {
5072 // Set this thread up so the handler will work on it
5073 Looper.prepare();
5074
5075 synchronized(AudioService.this) {
5076 mAudioHandler = new AudioHandler();
5077
5078 // Notify that the handler has been created
5079 AudioService.this.notify();
5080 }
5081
5082 // Listen for volume change requests that are set by VolumePanel
5083 Looper.loop();
5084 }
5085 }
5086
5087 /** Handles internal volume messages in separate volume thread. */
5088 private class AudioHandler extends Handler {
5089
Eric Laurent9bc8358d2011-11-18 16:43:31 -08005090 private void setDeviceVolume(VolumeStreamState streamState, int device) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005091
Eric Laurent8fa4d6f2014-10-30 14:13:03 -07005092 synchronized (VolumeStreamState.class) {
5093 // Apply volume
5094 streamState.applyDeviceVolume_syncVSS(device);
Eric Laurenta553c252009-07-17 12:17:14 -07005095
Eric Laurent8fa4d6f2014-10-30 14:13:03 -07005096 // Apply change to all streams using this one as alias
5097 int numStreamTypes = AudioSystem.getNumStreamTypes();
5098 for (int streamType = numStreamTypes - 1; streamType >= 0; streamType--) {
5099 if (streamType != streamState.mStreamType &&
5100 mStreamVolumeAlias[streamType] == streamState.mStreamType) {
5101 // Make sure volume is also maxed out on A2DP device for aliased stream
5102 // that may have a different device selected
5103 int streamDevice = getDeviceForStream(streamType);
5104 if ((device != streamDevice) && mAvrcpAbsVolSupported &&
5105 ((device & AudioSystem.DEVICE_OUT_ALL_A2DP) != 0)) {
5106 mStreamStates[streamType].applyDeviceVolume_syncVSS(device);
5107 }
5108 mStreamStates[streamType].applyDeviceVolume_syncVSS(streamDevice);
Eric Laurentcd772d02013-10-30 18:31:07 -07005109 }
Eric Laurenta553c252009-07-17 12:17:14 -07005110 }
5111 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005112 // Post a persist volume msg
Eric Laurentafbb0472011-12-15 09:04:23 -08005113 sendMsg(mAudioHandler,
5114 MSG_PERSIST_VOLUME,
Eric Laurent98ad9b92012-02-15 17:21:37 -08005115 SENDMSG_QUEUE,
Eric Laurent9bc8358d2011-11-18 16:43:31 -08005116 device,
Eric Laurent42b041e2013-03-29 11:36:03 -07005117 0,
Eric Laurentafbb0472011-12-15 09:04:23 -08005118 streamState,
5119 PERSIST_DELAY);
5120
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005121 }
5122
Eric Laurent9bc8358d2011-11-18 16:43:31 -08005123 private void setAllVolumes(VolumeStreamState streamState) {
5124
5125 // Apply volume
5126 streamState.applyAllVolumes();
5127
5128 // Apply change to all streams using this one as alias
5129 int numStreamTypes = AudioSystem.getNumStreamTypes();
5130 for (int streamType = numStreamTypes - 1; streamType >= 0; streamType--) {
5131 if (streamType != streamState.mStreamType &&
Eric Laurent6d517662012-04-23 18:42:39 -07005132 mStreamVolumeAlias[streamType] == streamState.mStreamType) {
Eric Laurent9bc8358d2011-11-18 16:43:31 -08005133 mStreamStates[streamType].applyAllVolumes();
5134 }
5135 }
5136 }
5137
Eric Laurent42b041e2013-03-29 11:36:03 -07005138 private void persistVolume(VolumeStreamState streamState, int device) {
Eric Laurent83a017b2013-03-19 18:15:31 -07005139 if (mUseFixedVolume) {
5140 return;
5141 }
Muyuan Li1ed6df62016-06-18 11:16:52 -07005142 if (mIsSingleVolume && (streamState.mStreamType != AudioSystem.STREAM_MUSIC)) {
Eric Laurent212532b2014-07-21 15:43:18 -07005143 return;
5144 }
Jean-Michel Trivia53b7052017-04-12 18:27:01 -07005145 if (streamState.hasValidSettingsName()) {
5146 System.putIntForUser(mContentResolver,
5147 streamState.getSettingNameForDevice(device),
5148 (streamState.getIndex(device) + 5)/ 10,
5149 UserHandle.USER_CURRENT);
5150 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005151 }
5152
Glenn Kastenba195eb2011-12-13 09:30:40 -08005153 private void persistRingerMode(int ringerMode) {
Eric Laurent83a017b2013-03-19 18:15:31 -07005154 if (mUseFixedVolume) {
5155 return;
5156 }
Jeff Sharkey8d9a1f62012-10-18 15:38:14 -07005157 Settings.Global.putInt(mContentResolver, Settings.Global.MODE_RINGER, ringerMode);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005158 }
5159
Jaekyun Seokc31033f2018-01-15 14:53:17 +09005160 private String getSoundEffectFilePath(int effectType) {
5161 String filePath = Environment.getProductDirectory() + SOUND_EFFECTS_PATH
5162 + SOUND_EFFECT_FILES.get(SOUND_EFFECT_FILES_MAP[effectType][0]);
5163 if (!new File(filePath).isFile()) {
5164 filePath = Environment.getRootDirectory() + SOUND_EFFECTS_PATH
5165 + SOUND_EFFECT_FILES.get(SOUND_EFFECT_FILES_MAP[effectType][0]);
5166 }
5167 return filePath;
5168 }
5169
Eric Laurent5d3eb44a2013-03-21 15:35:10 -07005170 private boolean onLoadSoundEffects() {
5171 int status;
5172
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005173 synchronized (mSoundEffectsLock) {
Eric Laurent4a5eeb92014-05-06 10:49:04 -07005174 if (!mSystemReady) {
Eric Laurent5d3eb44a2013-03-21 15:35:10 -07005175 Log.w(TAG, "onLoadSoundEffects() called before boot complete");
5176 return false;
5177 }
5178
5179 if (mSoundPool != null) {
5180 return true;
5181 }
5182
5183 loadTouchSoundAssets();
5184
Jean-Michel Trivi55a30c42014-07-20 17:56:11 -07005185 mSoundPool = new SoundPool.Builder()
5186 .setMaxStreams(NUM_SOUNDPOOL_CHANNELS)
5187 .setAudioAttributes(new AudioAttributes.Builder()
5188 .setUsage(AudioAttributes.USAGE_ASSISTANCE_SONIFICATION)
5189 .setContentType(AudioAttributes.CONTENT_TYPE_SONIFICATION)
5190 .build())
5191 .build();
Eric Laurent5d3eb44a2013-03-21 15:35:10 -07005192 mSoundPoolCallBack = null;
5193 mSoundPoolListenerThread = new SoundPoolListenerThread();
5194 mSoundPoolListenerThread.start();
5195 int attempts = 3;
5196 while ((mSoundPoolCallBack == null) && (attempts-- > 0)) {
5197 try {
5198 // Wait for mSoundPoolCallBack to be set by the other thread
Glenn Kasten167d1a22013-07-23 16:24:41 -07005199 mSoundEffectsLock.wait(SOUND_EFFECTS_LOAD_TIMEOUT_MS);
Eric Laurent5d3eb44a2013-03-21 15:35:10 -07005200 } catch (InterruptedException e) {
5201 Log.w(TAG, "Interrupted while waiting sound pool listener thread.");
5202 }
5203 }
5204
5205 if (mSoundPoolCallBack == null) {
5206 Log.w(TAG, "onLoadSoundEffects() SoundPool listener or thread creation error");
5207 if (mSoundPoolLooper != null) {
5208 mSoundPoolLooper.quit();
5209 mSoundPoolLooper = null;
5210 }
5211 mSoundPoolListenerThread = null;
5212 mSoundPool.release();
5213 mSoundPool = null;
5214 return false;
5215 }
5216 /*
5217 * poolId table: The value -1 in this table indicates that corresponding
5218 * file (same index in SOUND_EFFECT_FILES[] has not been loaded.
5219 * Once loaded, the value in poolId is the sample ID and the same
5220 * sample can be reused for another effect using the same file.
5221 */
5222 int[] poolId = new int[SOUND_EFFECT_FILES.size()];
5223 for (int fileIdx = 0; fileIdx < SOUND_EFFECT_FILES.size(); fileIdx++) {
5224 poolId[fileIdx] = -1;
5225 }
5226 /*
5227 * Effects whose value in SOUND_EFFECT_FILES_MAP[effect][1] is -1 must be loaded.
5228 * If load succeeds, value in SOUND_EFFECT_FILES_MAP[effect][1] is > 0:
5229 * this indicates we have a valid sample loaded for this effect.
5230 */
5231
5232 int numSamples = 0;
5233 for (int effect = 0; effect < AudioManager.NUM_SOUND_EFFECTS; effect++) {
5234 // Do not load sample if this effect uses the MediaPlayer
5235 if (SOUND_EFFECT_FILES_MAP[effect][1] == 0) {
5236 continue;
5237 }
5238 if (poolId[SOUND_EFFECT_FILES_MAP[effect][0]] == -1) {
Jaekyun Seokc31033f2018-01-15 14:53:17 +09005239 String filePath = getSoundEffectFilePath(effect);
Eric Laurent5d3eb44a2013-03-21 15:35:10 -07005240 int sampleId = mSoundPool.load(filePath, 0);
5241 if (sampleId <= 0) {
5242 Log.w(TAG, "Soundpool could not load file: "+filePath);
5243 } else {
5244 SOUND_EFFECT_FILES_MAP[effect][1] = sampleId;
5245 poolId[SOUND_EFFECT_FILES_MAP[effect][0]] = sampleId;
5246 numSamples++;
5247 }
5248 } else {
5249 SOUND_EFFECT_FILES_MAP[effect][1] =
5250 poolId[SOUND_EFFECT_FILES_MAP[effect][0]];
5251 }
5252 }
5253 // wait for all samples to be loaded
5254 if (numSamples > 0) {
5255 mSoundPoolCallBack.setSamples(poolId);
5256
5257 attempts = 3;
5258 status = 1;
5259 while ((status == 1) && (attempts-- > 0)) {
5260 try {
Glenn Kasten167d1a22013-07-23 16:24:41 -07005261 mSoundEffectsLock.wait(SOUND_EFFECTS_LOAD_TIMEOUT_MS);
Eric Laurent5d3eb44a2013-03-21 15:35:10 -07005262 status = mSoundPoolCallBack.status();
5263 } catch (InterruptedException e) {
5264 Log.w(TAG, "Interrupted while waiting sound pool callback.");
5265 }
5266 }
5267 } else {
5268 status = -1;
5269 }
5270
5271 if (mSoundPoolLooper != null) {
5272 mSoundPoolLooper.quit();
5273 mSoundPoolLooper = null;
5274 }
5275 mSoundPoolListenerThread = null;
5276 if (status != 0) {
5277 Log.w(TAG,
5278 "onLoadSoundEffects(), Error "+status+ " while loading samples");
5279 for (int effect = 0; effect < AudioManager.NUM_SOUND_EFFECTS; effect++) {
5280 if (SOUND_EFFECT_FILES_MAP[effect][1] > 0) {
5281 SOUND_EFFECT_FILES_MAP[effect][1] = -1;
5282 }
5283 }
5284
5285 mSoundPool.release();
5286 mSoundPool = null;
5287 }
5288 }
5289 return (status == 0);
5290 }
5291
5292 /**
5293 * Unloads samples from the sound pool.
5294 * This method can be called to free some memory when
5295 * sound effects are disabled.
5296 */
5297 private void onUnloadSoundEffects() {
5298 synchronized (mSoundEffectsLock) {
5299 if (mSoundPool == null) {
5300 return;
5301 }
5302
5303 int[] poolId = new int[SOUND_EFFECT_FILES.size()];
5304 for (int fileIdx = 0; fileIdx < SOUND_EFFECT_FILES.size(); fileIdx++) {
5305 poolId[fileIdx] = 0;
5306 }
5307
5308 for (int effect = 0; effect < AudioManager.NUM_SOUND_EFFECTS; effect++) {
5309 if (SOUND_EFFECT_FILES_MAP[effect][1] <= 0) {
5310 continue;
5311 }
5312 if (poolId[SOUND_EFFECT_FILES_MAP[effect][0]] == 0) {
5313 mSoundPool.unload(SOUND_EFFECT_FILES_MAP[effect][1]);
5314 SOUND_EFFECT_FILES_MAP[effect][1] = -1;
5315 poolId[SOUND_EFFECT_FILES_MAP[effect][0]] = -1;
5316 }
5317 }
5318 mSoundPool.release();
5319 mSoundPool = null;
5320 }
5321 }
5322
5323 private void onPlaySoundEffect(int effectType, int volume) {
5324 synchronized (mSoundEffectsLock) {
5325
5326 onLoadSoundEffects();
5327
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005328 if (mSoundPool == null) {
5329 return;
5330 }
Eric Laurenta2ef57d2009-09-28 04:46:10 -07005331 float volFloat;
Eric Laurent25101b02011-02-02 09:33:30 -08005332 // use default if volume is not specified by caller
Eric Laurenta2ef57d2009-09-28 04:46:10 -07005333 if (volume < 0) {
Jean-Michel Trivif2b0c112012-07-09 11:59:11 -07005334 volFloat = (float)Math.pow(10, (float)sSoundEffectVolumeDb/20);
Eric Laurenta2ef57d2009-09-28 04:46:10 -07005335 } else {
RoboErik8a2cfc32014-05-16 11:19:38 -07005336 volFloat = volume / 1000.0f;
Eric Laurenta2ef57d2009-09-28 04:46:10 -07005337 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005338
5339 if (SOUND_EFFECT_FILES_MAP[effectType][1] > 0) {
Eric Laurent5d3eb44a2013-03-21 15:35:10 -07005340 mSoundPool.play(SOUND_EFFECT_FILES_MAP[effectType][1],
5341 volFloat, volFloat, 0, 0, 1.0f);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005342 } else {
5343 MediaPlayer mediaPlayer = new MediaPlayer();
Glenn Kasten62b9aec2011-11-07 11:10:16 -08005344 try {
Jaekyun Seokc31033f2018-01-15 14:53:17 +09005345 String filePath = getSoundEffectFilePath(effectType);
Glenn Kasten62b9aec2011-11-07 11:10:16 -08005346 mediaPlayer.setDataSource(filePath);
5347 mediaPlayer.setAudioStreamType(AudioSystem.STREAM_SYSTEM);
5348 mediaPlayer.prepare();
Glenn Kasten068225d2012-02-27 16:21:04 -08005349 mediaPlayer.setVolume(volFloat);
Glenn Kasten62b9aec2011-11-07 11:10:16 -08005350 mediaPlayer.setOnCompletionListener(new OnCompletionListener() {
5351 public void onCompletion(MediaPlayer mp) {
5352 cleanupPlayer(mp);
5353 }
5354 });
5355 mediaPlayer.setOnErrorListener(new OnErrorListener() {
5356 public boolean onError(MediaPlayer mp, int what, int extra) {
5357 cleanupPlayer(mp);
5358 return true;
5359 }
5360 });
5361 mediaPlayer.start();
5362 } catch (IOException ex) {
5363 Log.w(TAG, "MediaPlayer IOException: "+ex);
5364 } catch (IllegalArgumentException ex) {
5365 Log.w(TAG, "MediaPlayer IllegalArgumentException: "+ex);
5366 } catch (IllegalStateException ex) {
5367 Log.w(TAG, "MediaPlayer IllegalStateException: "+ex);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005368 }
5369 }
5370 }
5371 }
5372
5373 private void cleanupPlayer(MediaPlayer mp) {
5374 if (mp != null) {
5375 try {
5376 mp.stop();
5377 mp.release();
5378 } catch (IllegalStateException ex) {
5379 Log.w(TAG, "MediaPlayer IllegalStateException: "+ex);
5380 }
5381 }
5382 }
5383
Jean-Michel Trivi011f39e2017-08-19 18:08:06 -07005384 private void setForceUse(int usage, int config, String eventSource) {
Jean-Michel Trivi7e2f3712015-01-12 11:01:55 -08005385 synchronized (mConnectedDevices) {
Jean-Michel Trivi011f39e2017-08-19 18:08:06 -07005386 setForceUseInt_SyncDevices(usage, config, eventSource);
Jean-Michel Trivi7e2f3712015-01-12 11:01:55 -08005387 }
Eric Laurentfa640152011-03-12 15:59:51 -08005388 }
5389
Eric Laurent05274f32012-11-29 12:48:18 -08005390 private void onPersistSafeVolumeState(int state) {
5391 Settings.Global.putInt(mContentResolver,
5392 Settings.Global.AUDIO_SAFE_VOLUME_STATE,
5393 state);
5394 }
5395
Jean-Michel Trivi7ed71472018-02-02 16:52:09 -08005396 private void onNotifyVolumeEvent(@NonNull IAudioPolicyCallback apc,
5397 @AudioManager.VolumeAdjustment int direction) {
5398 try {
5399 apc.notifyVolumeAdjust(direction);
5400 } catch(Exception e) {
5401 // nothing we can do about this. Do not log error, too much potential for spam
5402 }
5403 }
5404
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005405 @Override
5406 public void handleMessage(Message msg) {
Eric Laurentafbb0472011-12-15 09:04:23 -08005407 switch (msg.what) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005408
Eric Laurent9bc8358d2011-11-18 16:43:31 -08005409 case MSG_SET_DEVICE_VOLUME:
5410 setDeviceVolume((VolumeStreamState) msg.obj, msg.arg1);
5411 break;
5412
5413 case MSG_SET_ALL_VOLUMES:
5414 setAllVolumes((VolumeStreamState) msg.obj);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005415 break;
5416
5417 case MSG_PERSIST_VOLUME:
Eric Laurent42b041e2013-03-29 11:36:03 -07005418 persistVolume((VolumeStreamState) msg.obj, msg.arg1);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005419 break;
5420
5421 case MSG_PERSIST_RINGER_MODE:
Glenn Kastenba195eb2011-12-13 09:30:40 -08005422 // note that the value persisted is the current ringer mode, not the
5423 // value of ringer mode as of the time the request was made to persist
John Spurlock661f2cf2014-11-17 10:29:10 -05005424 persistRingerMode(getRingerModeInternal());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005425 break;
5426
Andy Hunged0ea402015-10-30 14:11:46 -07005427 case MSG_AUDIO_SERVER_DIED:
5428 onAudioServerDied();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005429 break;
5430
Eric Laurent1d3cdce2018-01-20 10:31:21 -08005431 case MSG_DISPATCH_AUDIO_SERVER_STATE:
5432 onDispatchAudioServerStateChange(msg.arg1 == 1);
5433 break;
5434
Eric Laurent5d3eb44a2013-03-21 15:35:10 -07005435 case MSG_UNLOAD_SOUND_EFFECTS:
5436 onUnloadSoundEffects();
5437 break;
5438
Eric Laurent117b7bb2011-01-16 17:07:27 -08005439 case MSG_LOAD_SOUND_EFFECTS:
Eric Laurent5d3eb44a2013-03-21 15:35:10 -07005440 //FIXME: onLoadSoundEffects() should be executed in a separate thread as it
5441 // can take several dozens of milliseconds to complete
5442 boolean loaded = onLoadSoundEffects();
5443 if (msg.obj != null) {
5444 LoadSoundEffectReply reply = (LoadSoundEffectReply)msg.obj;
5445 synchronized (reply) {
5446 reply.mStatus = loaded ? 0 : -1;
5447 reply.notify();
5448 }
5449 }
Eric Laurent117b7bb2011-01-16 17:07:27 -08005450 break;
5451
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005452 case MSG_PLAY_SOUND_EFFECT:
Eric Laurent5d3eb44a2013-03-21 15:35:10 -07005453 onPlaySoundEffect(msg.arg1, msg.arg2);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005454 break;
Jean-Michel Trivi4c637b92010-04-12 18:44:10 -07005455
5456 case MSG_BTA2DP_DOCK_TIMEOUT:
5457 // msg.obj == address of BTA2DP device
Eric Laurent6bc7f2c2011-11-29 18:49:40 -08005458 synchronized (mConnectedDevices) {
5459 makeA2dpDeviceUnavailableNow( (String) msg.obj );
5460 }
Jean-Michel Trivi4c637b92010-04-12 18:44:10 -07005461 break;
Eric Laurentfa640152011-03-12 15:59:51 -08005462
5463 case MSG_SET_FORCE_USE:
Sungsoocf09fe62016-09-28 16:21:48 +09005464 case MSG_SET_FORCE_BT_A2DP_USE:
Jean-Michel Trivi011f39e2017-08-19 18:08:06 -07005465 setForceUse(msg.arg1, msg.arg2, (String) msg.obj);
Eric Laurentfa640152011-03-12 15:59:51 -08005466 break;
Jean-Michel Trivid589fea2011-04-15 11:28:10 -07005467
Eric Laurentdc03c612011-04-01 10:59:41 -07005468 case MSG_BT_HEADSET_CNCT_FAILED:
5469 resetBluetoothSco();
5470 break;
Eric Laurentb1fbaac2012-05-29 09:24:28 -07005471
5472 case MSG_SET_WIRED_DEVICE_CONNECTION_STATE:
Paul McLean10804eb2015-01-28 11:16:35 -08005473 { WiredDeviceConnectionState connectState =
5474 (WiredDeviceConnectionState)msg.obj;
Jean-Michel Trivi011f39e2017-08-19 18:08:06 -07005475 mWiredDevLogger.log(new WiredDevConnectEvent(connectState));
Paul McLean10804eb2015-01-28 11:16:35 -08005476 onSetWiredDeviceConnectionState(connectState.mType, connectState.mState,
John Spurlock90874332015-03-10 16:00:54 -04005477 connectState.mAddress, connectState.mName, connectState.mCaller);
Paul McLean10804eb2015-01-28 11:16:35 -08005478 mAudioEventWakeLock.release();
5479 }
Eric Laurentb1fbaac2012-05-29 09:24:28 -07005480 break;
5481
Mike Lockwood0a40ec22014-05-21 10:08:50 -07005482 case MSG_SET_A2DP_SRC_CONNECTION_STATE:
5483 onSetA2dpSourceConnectionState((BluetoothDevice)msg.obj, msg.arg1);
5484 mAudioEventWakeLock.release();
5485 break;
5486
5487 case MSG_SET_A2DP_SINK_CONNECTION_STATE:
5488 onSetA2dpSinkConnectionState((BluetoothDevice)msg.obj, msg.arg1);
Jean-Michel Trivifa9a6982013-06-27 16:22:58 -07005489 mAudioEventWakeLock.release();
Eric Laurentb1fbaac2012-05-29 09:24:28 -07005490 break;
Dianne Hackborn632ca412012-06-14 19:34:10 -07005491
Jakub Pawlowskif9570f32018-02-21 17:15:12 -08005492 case MSG_SET_HEARING_AID_CONNECTION_STATE:
5493 onSetHearingAidConnectionState((BluetoothDevice)msg.obj, msg.arg1);
5494 mAudioEventWakeLock.release();
5495 break;
5496
Pavlin Radoslavov44a4ef02016-12-21 12:05:51 -08005497 case MSG_A2DP_DEVICE_CONFIG_CHANGE:
5498 onBluetoothA2dpDeviceConfigChange((BluetoothDevice)msg.obj);
5499 mAudioEventWakeLock.release();
5500 break;
5501
Jean-Michel Trivi92ed7bf2017-06-26 19:32:38 -07005502 case MSG_DISABLE_AUDIO_FOR_UID:
5503 mPlaybackMonitor.disableAudioForUid( msg.arg1 == 1 /* disable */,
5504 msg.arg2 /* uid */);
5505 mAudioEventWakeLock.release();
5506 break;
5507
Dianne Hackborn632ca412012-06-14 19:34:10 -07005508 case MSG_REPORT_NEW_ROUTES: {
5509 int N = mRoutesObservers.beginBroadcast();
5510 if (N > 0) {
5511 AudioRoutesInfo routes;
5512 synchronized (mCurAudioRoutes) {
5513 routes = new AudioRoutesInfo(mCurAudioRoutes);
5514 }
5515 while (N > 0) {
5516 N--;
5517 IAudioRoutesObserver obs = mRoutesObservers.getBroadcastItem(N);
5518 try {
5519 obs.dispatchAudioRoutesChanged(routes);
5520 } catch (RemoteException e) {
5521 }
5522 }
5523 }
5524 mRoutesObservers.finishBroadcast();
John Spurlock8a52c442015-03-26 14:23:58 -04005525 observeDevicesForStreams(-1);
Dianne Hackborn632ca412012-06-14 19:34:10 -07005526 break;
5527 }
Jean-Michel Trivi3114ce32012-06-11 15:03:52 -07005528
Eric Laurentc34dcc12012-09-10 13:51:52 -07005529 case MSG_CHECK_MUSIC_ACTIVE:
John Spurlock90874332015-03-10 16:00:54 -04005530 onCheckMusicActive((String) msg.obj);
Eric Laurentc34dcc12012-09-10 13:51:52 -07005531 break;
Eric Laurent5bfaeae2012-09-21 18:44:48 -07005532
5533 case MSG_BROADCAST_AUDIO_BECOMING_NOISY:
5534 onSendBecomingNoisyIntent();
5535 break;
Eric Laurentd640bd32012-09-28 18:01:48 -07005536
5537 case MSG_CONFIGURE_SAFE_MEDIA_VOLUME_FORCED:
5538 case MSG_CONFIGURE_SAFE_MEDIA_VOLUME:
John Spurlock90874332015-03-10 16:00:54 -04005539 onConfigureSafeVolume((msg.what == MSG_CONFIGURE_SAFE_MEDIA_VOLUME_FORCED),
5540 (String) msg.obj);
Eric Laurentd640bd32012-09-28 18:01:48 -07005541 break;
Eric Laurent05274f32012-11-29 12:48:18 -08005542 case MSG_PERSIST_SAFE_VOLUME_STATE:
5543 onPersistSafeVolumeState(msg.arg1);
5544 break;
Jean-Michel Trivia578c482012-12-28 11:19:49 -08005545
Eric Laurent2a57ca92013-03-07 17:29:27 -08005546 case MSG_BROADCAST_BT_CONNECTION_STATE:
5547 onBroadcastScoConnectionState(msg.arg1);
5548 break;
Eric Laurent4a5eeb92014-05-06 10:49:04 -07005549
5550 case MSG_SYSTEM_READY:
5551 onSystemReady();
5552 break;
John Spurlockaa5ee4d2014-07-25 13:05:12 -04005553
Eric Laurent0867bed2015-05-20 14:49:08 -07005554 case MSG_INDICATE_SYSTEM_READY:
5555 onIndicateSystemReady();
5556 break;
5557
Jean-Michel Trivi1ab43f62017-04-27 15:37:34 -07005558 case MSG_ACCESSORY_PLUG_MEDIA_UNMUTE:
5559 onAccessoryPlugMediaUnmute(msg.arg1);
5560 break;
5561
John Spurlockaa5ee4d2014-07-25 13:05:12 -04005562 case MSG_PERSIST_MUSIC_ACTIVE_MS:
5563 final int musicActiveMs = msg.arg1;
5564 Settings.Secure.putIntForUser(mContentResolver,
5565 Settings.Secure.UNSAFE_VOLUME_MUSIC_ACTIVE_MS, musicActiveMs,
5566 UserHandle.USER_CURRENT);
5567 break;
Eric Laurentc0232482016-03-15 18:19:23 -07005568
RoboErik5452e252015-02-06 15:33:53 -08005569 case MSG_UNMUTE_STREAM:
5570 onUnmuteStream(msg.arg1, msg.arg2);
5571 break;
Eric Laurentc0232482016-03-15 18:19:23 -07005572
Jean-Michel Trivi5a561092015-04-23 18:48:08 -07005573 case MSG_DYN_POLICY_MIX_STATE_UPDATE:
5574 onDynPolicyMixStateUpdate((String) msg.obj, msg.arg1);
5575 break;
Jean-Michel Trivi7ed71472018-02-02 16:52:09 -08005576
5577 case MSG_NOTIFY_VOL_EVENT:
5578 onNotifyVolumeEvent((IAudioPolicyCallback) msg.obj, msg.arg1);
5579 break;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005580 }
5581 }
5582 }
5583
Jason Parekhb1096152009-03-24 17:48:25 -07005584 private class SettingsObserver extends ContentObserver {
Eric Laurenta553c252009-07-17 12:17:14 -07005585
Phil Burked43bf52016-03-01 17:01:35 -08005586 private int mEncodedSurroundMode;
5587
Jason Parekhb1096152009-03-24 17:48:25 -07005588 SettingsObserver() {
5589 super(new Handler());
Beverlyd6964762018-02-16 14:07:03 -05005590 mContentResolver.registerContentObserver(Settings.Global.getUriFor(
5591 Settings.Global.ZEN_MODE), false, this);
5592 mContentResolver.registerContentObserver(Settings.Global.getUriFor(
5593 Settings.Global.ZEN_MODE_CONFIG_ETAG), false, this);
Jason Parekhb1096152009-03-24 17:48:25 -07005594 mContentResolver.registerContentObserver(Settings.System.getUriFor(
5595 Settings.System.MODE_RINGER_STREAMS_AFFECTED), false, this);
Eric Laurent7ee1e4f2012-10-26 18:11:21 -07005596 mContentResolver.registerContentObserver(Settings.Global.getUriFor(
5597 Settings.Global.DOCK_AUDIO_MEDIA_ENABLED), false, this);
Andy Hung7b98e9a2016-02-25 18:34:50 -08005598 mContentResolver.registerContentObserver(Settings.System.getUriFor(
5599 Settings.System.MASTER_MONO), false, this);
Phil Burked43bf52016-03-01 17:01:35 -08005600
5601 mEncodedSurroundMode = Settings.Global.getInt(
5602 mContentResolver, Settings.Global.ENCODED_SURROUND_OUTPUT,
5603 Settings.Global.ENCODED_SURROUND_OUTPUT_AUTO);
5604 mContentResolver.registerContentObserver(Settings.Global.getUriFor(
5605 Settings.Global.ENCODED_SURROUND_OUTPUT), false, this);
Jason Parekhb1096152009-03-24 17:48:25 -07005606 }
5607
5608 @Override
5609 public void onChange(boolean selfChange) {
5610 super.onChange(selfChange);
Glenn Kastenba195eb2011-12-13 09:30:40 -08005611 // FIXME This synchronized is not necessary if mSettingsLock only protects mRingerMode.
Beverlyd6964762018-02-16 14:07:03 -05005612 // However there appear to be some missing locks around mRingerAndZenModeMutedStreams
Glenn Kastenba195eb2011-12-13 09:30:40 -08005613 // and mRingerModeAffectedStreams, so will leave this synchronized for now.
Beverlyd6964762018-02-16 14:07:03 -05005614 // mRingerAndZenModeMutedStreams and mMuteAffectedStreams are safe (only accessed once).
Eric Laurenta553c252009-07-17 12:17:14 -07005615 synchronized (mSettingsLock) {
Beverlyd6964762018-02-16 14:07:03 -05005616 if (updateRingerAndZenModeAffectedStreams()) {
Eric Laurenta553c252009-07-17 12:17:14 -07005617 /*
5618 * Ensure all stream types that should be affected by ringer mode
5619 * are in the proper state.
5620 */
John Spurlock661f2cf2014-11-17 10:29:10 -05005621 setRingerModeInt(getRingerModeInternal(), false);
Eric Laurenta553c252009-07-17 12:17:14 -07005622 }
Eric Laurent7ee1e4f2012-10-26 18:11:21 -07005623 readDockAudioSettings(mContentResolver);
Andy Hung7b98e9a2016-02-25 18:34:50 -08005624 updateMasterMono(mContentResolver);
Phil Burked43bf52016-03-01 17:01:35 -08005625 updateEncodedSurroundOutput();
5626 }
5627 }
5628
5629 private void updateEncodedSurroundOutput() {
5630 int newSurroundMode = Settings.Global.getInt(
5631 mContentResolver, Settings.Global.ENCODED_SURROUND_OUTPUT,
5632 Settings.Global.ENCODED_SURROUND_OUTPUT_AUTO);
5633 // Did it change?
5634 if (mEncodedSurroundMode != newSurroundMode) {
5635 // Send to AudioPolicyManager
Jean-Michel Trivi011f39e2017-08-19 18:08:06 -07005636 sendEncodedSurroundMode(newSurroundMode, "SettingsObserver");
Phil Burked43bf52016-03-01 17:01:35 -08005637 synchronized(mConnectedDevices) {
5638 // Is HDMI connected?
5639 String key = makeDeviceListKey(AudioSystem.DEVICE_OUT_HDMI, "");
5640 DeviceListSpec deviceSpec = mConnectedDevices.get(key);
5641 if (deviceSpec != null) {
5642 // Toggle HDMI to retrigger broadcast with proper formats.
5643 setWiredDeviceConnectionState(AudioSystem.DEVICE_OUT_HDMI,
5644 AudioSystem.DEVICE_STATE_UNAVAILABLE, "", "",
5645 "android"); // disconnect
5646 setWiredDeviceConnectionState(AudioSystem.DEVICE_OUT_HDMI,
5647 AudioSystem.DEVICE_STATE_AVAILABLE, "", "",
5648 "android"); // reconnect
5649 }
5650 }
5651 mEncodedSurroundMode = newSurroundMode;
Eric Laurenta553c252009-07-17 12:17:14 -07005652 }
Jason Parekhb1096152009-03-24 17:48:25 -07005653 }
Jason Parekhb1096152009-03-24 17:48:25 -07005654 }
Eric Laurenta553c252009-07-17 12:17:14 -07005655
Eric Laurent6bc7f2c2011-11-29 18:49:40 -08005656 // must be called synchronized on mConnectedDevices
Jean-Michel Trivi011f39e2017-08-19 18:08:06 -07005657 private void makeA2dpDeviceAvailable(String address, String name, String eventSource) {
Jean-Michel Trivi1ab43f62017-04-27 15:37:34 -07005658 // enable A2DP before notifying A2DP connection to avoid unnecessary processing in
Eric Laurent78472112012-05-21 08:57:21 -07005659 // audio policy manager
Matthew Xiec9d1d5f2013-09-12 00:32:22 -07005660 VolumeStreamState streamState = mStreamStates[AudioSystem.STREAM_MUSIC];
5661 sendMsg(mAudioHandler, MSG_SET_DEVICE_VOLUME, SENDMSG_QUEUE,
5662 AudioSystem.DEVICE_OUT_BLUETOOTH_A2DP, 0, streamState, 0);
Jean-Michel Trivi011f39e2017-08-19 18:08:06 -07005663 setBluetoothA2dpOnInt(true, eventSource);
Jean-Michel Trivi4c637b92010-04-12 18:44:10 -07005664 AudioSystem.setDeviceConnectionState(AudioSystem.DEVICE_OUT_BLUETOOTH_A2DP,
Paul McLean20eec5b2015-05-09 13:02:18 -07005665 AudioSystem.DEVICE_STATE_AVAILABLE, address, name);
Jean-Michel Trivi4c637b92010-04-12 18:44:10 -07005666 // Reset A2DP suspend state each time a new sink is connected
5667 AudioSystem.setParameters("A2dpSuspended=false");
Paul McLean394a8e12015-03-03 10:29:19 -07005668 mConnectedDevices.put(
5669 makeDeviceListKey(AudioSystem.DEVICE_OUT_BLUETOOTH_A2DP, address),
Paul McLean20eec5b2015-05-09 13:02:18 -07005670 new DeviceListSpec(AudioSystem.DEVICE_OUT_BLUETOOTH_A2DP, name,
Paul McLean394a8e12015-03-03 10:29:19 -07005671 address));
Jean-Michel Trivi1ab43f62017-04-27 15:37:34 -07005672 sendMsg(mAudioHandler, MSG_ACCESSORY_PLUG_MEDIA_UNMUTE, SENDMSG_QUEUE,
5673 AudioSystem.DEVICE_OUT_BLUETOOTH_A2DP, 0, null, 0);
Jean-Michel Trivi4c637b92010-04-12 18:44:10 -07005674 }
5675
Eric Laurent5bfaeae2012-09-21 18:44:48 -07005676 private void onSendBecomingNoisyIntent() {
Dianne Hackborn5ac72a22012-08-29 18:32:08 -07005677 sendBroadcastToAll(new Intent(AudioManager.ACTION_AUDIO_BECOMING_NOISY));
Mike Lockwood98418182012-05-10 17:13:20 -07005678 }
5679
Eric Laurent6bc7f2c2011-11-29 18:49:40 -08005680 // must be called synchronized on mConnectedDevices
Jean-Michel Trivi4c637b92010-04-12 18:44:10 -07005681 private void makeA2dpDeviceUnavailableNow(String address) {
Matthew Xiec9d1d5f2013-09-12 00:32:22 -07005682 synchronized (mA2dpAvrcpLock) {
5683 mAvrcpAbsVolSupported = false;
5684 }
Jean-Michel Trivi4c637b92010-04-12 18:44:10 -07005685 AudioSystem.setDeviceConnectionState(AudioSystem.DEVICE_OUT_BLUETOOTH_A2DP,
Paul McLean20eec5b2015-05-09 13:02:18 -07005686 AudioSystem.DEVICE_STATE_UNAVAILABLE, address, "");
Paul McLean394a8e12015-03-03 10:29:19 -07005687 mConnectedDevices.remove(
5688 makeDeviceListKey(AudioSystem.DEVICE_OUT_BLUETOOTH_A2DP, address));
Jakub Pawlowskif9570f32018-02-21 17:15:12 -08005689 // Remove A2DP routes as well
5690 setCurrentAudioRouteName(null);
Jean-Michel Trivi4c637b92010-04-12 18:44:10 -07005691 }
5692
Eric Laurent6bc7f2c2011-11-29 18:49:40 -08005693 // must be called synchronized on mConnectedDevices
Eric Laurentd138e4e2015-05-15 16:41:15 -07005694 private void makeA2dpDeviceUnavailableLater(String address, int delayMs) {
Eric Laurent3b591262010-04-20 07:01:00 -07005695 // prevent any activity on the A2DP audio output to avoid unwanted
5696 // reconnection of the sink.
5697 AudioSystem.setParameters("A2dpSuspended=true");
Jean-Michel Trivi4c637b92010-04-12 18:44:10 -07005698 // the device will be made unavailable later, so consider it disconnected right away
Paul McLean394a8e12015-03-03 10:29:19 -07005699 mConnectedDevices.remove(
5700 makeDeviceListKey(AudioSystem.DEVICE_OUT_BLUETOOTH_A2DP, address));
Jean-Michel Trivi4c637b92010-04-12 18:44:10 -07005701 // send the delayed message to make the device unavailable later
5702 Message msg = mAudioHandler.obtainMessage(MSG_BTA2DP_DOCK_TIMEOUT, address);
Eric Laurentd138e4e2015-05-15 16:41:15 -07005703 mAudioHandler.sendMessageDelayed(msg, delayMs);
Jean-Michel Trivi4c637b92010-04-12 18:44:10 -07005704
5705 }
5706
Eric Laurent6bc7f2c2011-11-29 18:49:40 -08005707 // must be called synchronized on mConnectedDevices
Mike Lockwood0a40ec22014-05-21 10:08:50 -07005708 private void makeA2dpSrcAvailable(String address) {
5709 AudioSystem.setDeviceConnectionState(AudioSystem.DEVICE_IN_BLUETOOTH_A2DP,
Paul McLean20eec5b2015-05-09 13:02:18 -07005710 AudioSystem.DEVICE_STATE_AVAILABLE, address, "");
Paul McLean394a8e12015-03-03 10:29:19 -07005711 mConnectedDevices.put(
5712 makeDeviceListKey(AudioSystem.DEVICE_IN_BLUETOOTH_A2DP, address),
Paul McLean20eec5b2015-05-09 13:02:18 -07005713 new DeviceListSpec(AudioSystem.DEVICE_IN_BLUETOOTH_A2DP, "",
Paul McLean394a8e12015-03-03 10:29:19 -07005714 address));
Mike Lockwood0a40ec22014-05-21 10:08:50 -07005715 }
5716
5717 // must be called synchronized on mConnectedDevices
5718 private void makeA2dpSrcUnavailable(String address) {
5719 AudioSystem.setDeviceConnectionState(AudioSystem.DEVICE_IN_BLUETOOTH_A2DP,
Paul McLean20eec5b2015-05-09 13:02:18 -07005720 AudioSystem.DEVICE_STATE_UNAVAILABLE, address, "");
Paul McLean394a8e12015-03-03 10:29:19 -07005721 mConnectedDevices.remove(
5722 makeDeviceListKey(AudioSystem.DEVICE_IN_BLUETOOTH_A2DP, address));
Mike Lockwood0a40ec22014-05-21 10:08:50 -07005723 }
5724
Jakub Pawlowski21b7f492018-03-22 12:31:21 -07005725 private void setHearingAidVolume(int index, int streamType) {
Jakub Pawlowski09592d52018-03-19 12:23:59 -07005726 synchronized (mHearingAidLock) {
5727 if (mHearingAid != null) {
5728 //hearing aid expect volume value in range -128dB to 0dB
Jakub Pawlowski21b7f492018-03-22 12:31:21 -07005729 int gainDB = (int)AudioSystem.getStreamVolumeDB(streamType, index/10,
Jakub Pawlowski09592d52018-03-19 12:23:59 -07005730 AudioSystem.DEVICE_OUT_HEARING_AID);
5731 if (gainDB < BT_HEARING_AID_GAIN_MIN)
5732 gainDB = BT_HEARING_AID_GAIN_MIN;
5733 mHearingAid.setVolume(gainDB);
5734 }
5735 }
5736 }
5737
Mike Lockwood0a40ec22014-05-21 10:08:50 -07005738 // must be called synchronized on mConnectedDevices
Jakub Pawlowskif9570f32018-02-21 17:15:12 -08005739 private void makeHearingAidDeviceAvailable(String address, String name, String eventSource) {
Jakub Pawlowski09592d52018-03-19 12:23:59 -07005740 int index = mStreamStates[AudioSystem.STREAM_MUSIC].getIndex(AudioSystem.DEVICE_OUT_HEARING_AID);
Jakub Pawlowski21b7f492018-03-22 12:31:21 -07005741 setHearingAidVolume(index, AudioSystem.STREAM_MUSIC);
Jakub Pawlowski09592d52018-03-19 12:23:59 -07005742
Jakub Pawlowskif9570f32018-02-21 17:15:12 -08005743 AudioSystem.setDeviceConnectionState(AudioSystem.DEVICE_OUT_HEARING_AID,
5744 AudioSystem.DEVICE_STATE_AVAILABLE, address, name);
5745 mConnectedDevices.put(
5746 makeDeviceListKey(AudioSystem.DEVICE_OUT_HEARING_AID, address),
5747 new DeviceListSpec(AudioSystem.DEVICE_OUT_HEARING_AID, name,
5748 address));
5749 sendMsg(mAudioHandler, MSG_ACCESSORY_PLUG_MEDIA_UNMUTE, SENDMSG_QUEUE,
5750 AudioSystem.DEVICE_OUT_HEARING_AID, 0, null, 0);
5751 }
5752
5753 // must be called synchronized on mConnectedDevices
5754 private void makeHearingAidDeviceUnavailable(String address) {
5755 AudioSystem.setDeviceConnectionState(AudioSystem.DEVICE_OUT_HEARING_AID,
5756 AudioSystem.DEVICE_STATE_UNAVAILABLE, address, "");
5757 mConnectedDevices.remove(
5758 makeDeviceListKey(AudioSystem.DEVICE_OUT_HEARING_AID, address));
5759 // Remove Hearing Aid routes as well
5760 setCurrentAudioRouteName(null);
5761 }
5762
5763 // must be called synchronized on mConnectedDevices
Jean-Michel Trivia847ba42010-04-23 11:49:29 -07005764 private void cancelA2dpDeviceTimeout() {
Jean-Michel Trivi4c637b92010-04-12 18:44:10 -07005765 mAudioHandler.removeMessages(MSG_BTA2DP_DOCK_TIMEOUT);
5766 }
5767
Eric Laurent6bc7f2c2011-11-29 18:49:40 -08005768 // must be called synchronized on mConnectedDevices
Jean-Michel Trivia847ba42010-04-23 11:49:29 -07005769 private boolean hasScheduledA2dpDockTimeout() {
5770 return mAudioHandler.hasMessages(MSG_BTA2DP_DOCK_TIMEOUT);
5771 }
5772
Mike Lockwood0a40ec22014-05-21 10:08:50 -07005773 private void onSetA2dpSinkConnectionState(BluetoothDevice btDevice, int state)
Eric Laurent6bc7f2c2011-11-29 18:49:40 -08005774 {
Eric Laurent4724ea72017-05-23 10:39:38 -07005775 if (DEBUG_DEVICES) {
Pavlin Radoslavov44a4ef02016-12-21 12:05:51 -08005776 Log.d(TAG, "onSetA2dpSinkConnectionState btDevice=" + btDevice+"state=" + state);
Mike Lockwood0a40ec22014-05-21 10:08:50 -07005777 }
Eric Laurent6bc7f2c2011-11-29 18:49:40 -08005778 if (btDevice == null) {
5779 return;
5780 }
5781 String address = btDevice.getAddress();
5782 if (!BluetoothAdapter.checkBluetoothAddress(address)) {
5783 address = "";
5784 }
John Du5a0cf7a2013-07-19 11:30:34 -07005785
Eric Laurent6bc7f2c2011-11-29 18:49:40 -08005786 synchronized (mConnectedDevices) {
Pavlin Radoslavov44a4ef02016-12-21 12:05:51 -08005787 final String key = makeDeviceListKey(AudioSystem.DEVICE_OUT_BLUETOOTH_A2DP,
5788 btDevice.getAddress());
5789 final DeviceListSpec deviceSpec = mConnectedDevices.get(key);
Paul McLean394a8e12015-03-03 10:29:19 -07005790 boolean isConnected = deviceSpec != null;
Eric Laurent6bc7f2c2011-11-29 18:49:40 -08005791
5792 if (isConnected && state != BluetoothProfile.STATE_CONNECTED) {
5793 if (btDevice.isBluetoothDock()) {
5794 if (state == BluetoothProfile.STATE_DISCONNECTED) {
5795 // introduction of a delay for transient disconnections of docks when
5796 // power is rapidly turned off/on, this message will be canceled if
5797 // we reconnect the dock under a preset delay
Eric Laurentd138e4e2015-05-15 16:41:15 -07005798 makeA2dpDeviceUnavailableLater(address, BTA2DP_DOCK_TIMEOUT_MILLIS);
Eric Laurent6bc7f2c2011-11-29 18:49:40 -08005799 // the next time isConnected is evaluated, it will be false for the dock
5800 }
5801 } else {
5802 makeA2dpDeviceUnavailableNow(address);
5803 }
Jakub Pawlowskif9570f32018-02-21 17:15:12 -08005804 setCurrentAudioRouteName(null);
Eric Laurent6bc7f2c2011-11-29 18:49:40 -08005805 } else if (!isConnected && state == BluetoothProfile.STATE_CONNECTED) {
5806 if (btDevice.isBluetoothDock()) {
5807 // this could be a reconnection after a transient disconnection
5808 cancelA2dpDeviceTimeout();
5809 mDockAddress = address;
5810 } else {
5811 // this could be a connection of another A2DP device before the timeout of
5812 // a dock: cancel the dock timeout, and make the dock unavailable now
5813 if(hasScheduledA2dpDockTimeout()) {
5814 cancelA2dpDeviceTimeout();
5815 makeA2dpDeviceUnavailableNow(mDockAddress);
5816 }
5817 }
Jean-Michel Trivi011f39e2017-08-19 18:08:06 -07005818 makeA2dpDeviceAvailable(address, btDevice.getName(),
5819 "onSetA2dpSinkConnectionState");
Jakub Pawlowskif9570f32018-02-21 17:15:12 -08005820 setCurrentAudioRouteName(btDevice.getAliasName());
Eric Laurent6bc7f2c2011-11-29 18:49:40 -08005821 }
5822 }
5823 }
5824
Mike Lockwood0a40ec22014-05-21 10:08:50 -07005825 private void onSetA2dpSourceConnectionState(BluetoothDevice btDevice, int state)
5826 {
5827 if (DEBUG_VOL) {
Pavlin Radoslavov44a4ef02016-12-21 12:05:51 -08005828 Log.d(TAG, "onSetA2dpSourceConnectionState btDevice=" + btDevice + " state=" + state);
Mike Lockwood0a40ec22014-05-21 10:08:50 -07005829 }
5830 if (btDevice == null) {
5831 return;
5832 }
5833 String address = btDevice.getAddress();
5834 if (!BluetoothAdapter.checkBluetoothAddress(address)) {
5835 address = "";
5836 }
5837
5838 synchronized (mConnectedDevices) {
Pavlin Radoslavov44a4ef02016-12-21 12:05:51 -08005839 final String key = makeDeviceListKey(AudioSystem.DEVICE_IN_BLUETOOTH_A2DP, address);
5840 final DeviceListSpec deviceSpec = mConnectedDevices.get(key);
Paul McLean394a8e12015-03-03 10:29:19 -07005841 boolean isConnected = deviceSpec != null;
Mike Lockwood0a40ec22014-05-21 10:08:50 -07005842
5843 if (isConnected && state != BluetoothProfile.STATE_CONNECTED) {
5844 makeA2dpSrcUnavailable(address);
5845 } else if (!isConnected && state == BluetoothProfile.STATE_CONNECTED) {
5846 makeA2dpSrcAvailable(address);
5847 }
5848 }
5849 }
5850
Jakub Pawlowskif9570f32018-02-21 17:15:12 -08005851 private void onSetHearingAidConnectionState(BluetoothDevice btDevice, int state)
5852 {
5853 if (DEBUG_DEVICES) {
5854 Log.d(TAG, "onSetHearingAidConnectionState btDevice=" + btDevice+", state=" + state);
5855 }
5856 if (btDevice == null) {
5857 return;
5858 }
5859 String address = btDevice.getAddress();
5860 if (!BluetoothAdapter.checkBluetoothAddress(address)) {
5861 address = "";
5862 }
5863
5864 synchronized (mConnectedDevices) {
5865 final String key = makeDeviceListKey(AudioSystem.DEVICE_OUT_HEARING_AID,
5866 btDevice.getAddress());
5867 final DeviceListSpec deviceSpec = mConnectedDevices.get(key);
5868 boolean isConnected = deviceSpec != null;
5869
5870 if (isConnected && state != BluetoothProfile.STATE_CONNECTED) {
5871 makeHearingAidDeviceUnavailable(address);
5872 setCurrentAudioRouteName(null);
5873 } else if (!isConnected && state == BluetoothProfile.STATE_CONNECTED) {
5874 makeHearingAidDeviceAvailable(address, btDevice.getName(),
5875 "onSetHearingAidConnectionState");
5876 setCurrentAudioRouteName(btDevice.getAliasName());
5877 }
5878 }
5879 }
5880
5881 private void setCurrentAudioRouteName(String name){
5882 synchronized (mCurAudioRoutes) {
5883 if (!TextUtils.equals(mCurAudioRoutes.bluetoothName, name)) {
5884 mCurAudioRoutes.bluetoothName = name;
5885 sendMsg(mAudioHandler, MSG_REPORT_NEW_ROUTES,
5886 SENDMSG_NOOP, 0, 0, null, 0);
5887 }
5888 }
5889 }
5890
Pavlin Radoslavov44a4ef02016-12-21 12:05:51 -08005891 private void onBluetoothA2dpDeviceConfigChange(BluetoothDevice btDevice)
5892 {
Eric Laurent5205a352017-04-27 18:31:22 -07005893 if (DEBUG_DEVICES) {
Pavlin Radoslavov44a4ef02016-12-21 12:05:51 -08005894 Log.d(TAG, "onBluetoothA2dpDeviceConfigChange btDevice=" + btDevice);
5895 }
5896 if (btDevice == null) {
5897 return;
5898 }
5899 String address = btDevice.getAddress();
5900 if (!BluetoothAdapter.checkBluetoothAddress(address)) {
5901 address = "";
5902 }
5903
5904 int device = AudioSystem.DEVICE_OUT_BLUETOOTH_A2DP;
5905 synchronized (mConnectedDevices) {
Eric Laurent4724ea72017-05-23 10:39:38 -07005906 if (mAudioHandler.hasMessages(MSG_SET_A2DP_SINK_CONNECTION_STATE, btDevice)) {
Eric Laurentcdae4762017-04-28 18:00:04 -07005907 return;
5908 }
Pavlin Radoslavov44a4ef02016-12-21 12:05:51 -08005909 final String key = makeDeviceListKey(device, address);
5910 final DeviceListSpec deviceSpec = mConnectedDevices.get(key);
5911 if (deviceSpec != null) {
5912 // Device is connected
Eric Laurentcdae4762017-04-28 18:00:04 -07005913 int musicDevice = getDeviceForStream(AudioSystem.STREAM_MUSIC);
Eric Laurent5205a352017-04-27 18:31:22 -07005914 if (AudioSystem.handleDeviceConfigChange(device, address,
5915 btDevice.getName()) != AudioSystem.AUDIO_STATUS_OK) {
5916 // force A2DP device disconnection in case of error so that AudioService state is
5917 // consistent with audio policy manager state
Eric Laurentcdae4762017-04-28 18:00:04 -07005918 setBluetoothA2dpDeviceConnectionStateInt(
5919 btDevice, BluetoothA2dp.STATE_DISCONNECTED, BluetoothProfile.A2DP,
Pavlin Radoslavov82e06462018-01-19 18:20:04 -08005920 false /* suppressNoisyIntent */, musicDevice);
Eric Laurent5205a352017-04-27 18:31:22 -07005921 }
Pavlin Radoslavov44a4ef02016-12-21 12:05:51 -08005922 }
5923 }
5924 }
5925
John Du5a0cf7a2013-07-19 11:30:34 -07005926 public void avrcpSupportsAbsoluteVolume(String address, boolean support) {
5927 // address is not used for now, but may be used when multiple a2dp devices are supported
5928 synchronized (mA2dpAvrcpLock) {
5929 mAvrcpAbsVolSupported = support;
Matthew Xiec9d1d5f2013-09-12 00:32:22 -07005930 sendMsg(mAudioHandler, MSG_SET_DEVICE_VOLUME, SENDMSG_QUEUE,
Eric Laurentcd772d02013-10-30 18:31:07 -07005931 AudioSystem.DEVICE_OUT_BLUETOOTH_A2DP, 0,
5932 mStreamStates[AudioSystem.STREAM_MUSIC], 0);
5933 sendMsg(mAudioHandler, MSG_SET_DEVICE_VOLUME, SENDMSG_QUEUE,
5934 AudioSystem.DEVICE_OUT_BLUETOOTH_A2DP, 0,
5935 mStreamStates[AudioSystem.STREAM_RING], 0);
John Du5a0cf7a2013-07-19 11:30:34 -07005936 }
5937 }
5938
Paul McLean394a8e12015-03-03 10:29:19 -07005939 private boolean handleDeviceConnection(boolean connect, int device, String address,
5940 String deviceName) {
5941 if (DEBUG_DEVICES) {
5942 Slog.i(TAG, "handleDeviceConnection(" + connect + " dev:" + Integer.toHexString(device)
5943 + " address:" + address + " name:" + deviceName + ")");
5944 }
Eric Laurent59f48272012-04-05 19:42:21 -07005945 synchronized (mConnectedDevices) {
Paul McLean394a8e12015-03-03 10:29:19 -07005946 String deviceKey = makeDeviceListKey(device, address);
5947 if (DEBUG_DEVICES) {
5948 Slog.i(TAG, "deviceKey:" + deviceKey);
5949 }
5950 DeviceListSpec deviceSpec = mConnectedDevices.get(deviceKey);
5951 boolean isConnected = deviceSpec != null;
5952 if (DEBUG_DEVICES) {
5953 Slog.i(TAG, "deviceSpec:" + deviceSpec + " is(already)Connected:" + isConnected);
5954 }
5955 if (connect && !isConnected) {
Jean-Michel Trivi6d00e412015-08-03 17:26:01 -07005956 final int res = AudioSystem.setDeviceConnectionState(device,
5957 AudioSystem.DEVICE_STATE_AVAILABLE, address, deviceName);
5958 if (res != AudioSystem.AUDIO_STATUS_OK) {
5959 Slog.e(TAG, "not connecting device 0x" + Integer.toHexString(device) +
5960 " due to command error " + res );
5961 return false;
5962 }
Paul McLean394a8e12015-03-03 10:29:19 -07005963 mConnectedDevices.put(deviceKey, new DeviceListSpec(device, deviceName, address));
Jean-Michel Trivi1ab43f62017-04-27 15:37:34 -07005964 sendMsg(mAudioHandler, MSG_ACCESSORY_PLUG_MEDIA_UNMUTE, SENDMSG_QUEUE,
5965 device, 0, null, 0);
Paul McLean394a8e12015-03-03 10:29:19 -07005966 return true;
5967 } else if (!connect && isConnected) {
Jean-Michel Trivi6d00e412015-08-03 17:26:01 -07005968 AudioSystem.setDeviceConnectionState(device,
5969 AudioSystem.DEVICE_STATE_UNAVAILABLE, address, deviceName);
5970 // always remove even if disconnection failed
Paul McLean394a8e12015-03-03 10:29:19 -07005971 mConnectedDevices.remove(deviceKey);
5972 return true;
Eric Laurent59f48272012-04-05 19:42:21 -07005973 }
Jack Hef05e5162018-04-19 15:03:43 -07005974 Log.w(TAG, "handleDeviceConnection() failed, deviceKey=" + deviceKey + ", deviceSpec="
5975 + deviceSpec + ", connect=" + connect);
Eric Laurent59f48272012-04-05 19:42:21 -07005976 }
5977 return false;
5978 }
5979
Eric Laurentb1fbaac2012-05-29 09:24:28 -07005980 // Devices which removal triggers intent ACTION_AUDIO_BECOMING_NOISY. The intent is only
Eric Laurent9a5b2622017-04-18 18:20:56 -07005981 // sent if:
5982 // - none of these devices are connected anymore after one is disconnected AND
5983 // - the device being disconnected is actually used for music.
Jean-Michel Trivi7e2f3712015-01-12 11:01:55 -08005984 // Access synchronized on mConnectedDevices
Eric Laurentb1fbaac2012-05-29 09:24:28 -07005985 int mBecomingNoisyIntentDevices =
5986 AudioSystem.DEVICE_OUT_WIRED_HEADSET | AudioSystem.DEVICE_OUT_WIRED_HEADPHONE |
Eric Laurent948d3272014-05-16 15:18:45 -07005987 AudioSystem.DEVICE_OUT_ALL_A2DP | AudioSystem.DEVICE_OUT_HDMI |
Eric Laurent794da7a2012-08-30 11:30:16 -07005988 AudioSystem.DEVICE_OUT_ANLG_DOCK_HEADSET | AudioSystem.DEVICE_OUT_DGTL_DOCK_HEADSET |
Jakub Pawlowski26fac412018-03-22 15:00:34 -07005989 AudioSystem.DEVICE_OUT_ALL_USB | AudioSystem.DEVICE_OUT_LINE |
5990 AudioSystem.DEVICE_OUT_HEARING_AID;
Eric Laurentb1fbaac2012-05-29 09:24:28 -07005991
5992 // must be called before removing the device from mConnectedDevices
Jean-Michel Trivi7e2f3712015-01-12 11:01:55 -08005993 // Called synchronized on mConnectedDevices
Eric Laurentcdae4762017-04-28 18:00:04 -07005994 // musicDevice argument is used when not AudioSystem.DEVICE_NONE instead of querying
5995 // from AudioSystem
5996 private int checkSendBecomingNoisyIntent(int device, int state, int musicDevice) {
Eric Laurentb1fbaac2012-05-29 09:24:28 -07005997 int delay = 0;
5998 if ((state == 0) && ((device & mBecomingNoisyIntentDevices) != 0)) {
5999 int devices = 0;
John Spurlock8c3dc852015-04-23 21:32:37 -04006000 for (int i = 0; i < mConnectedDevices.size(); i++) {
6001 int dev = mConnectedDevices.valueAt(i).mDeviceType;
Paul McLean394a8e12015-03-03 10:29:19 -07006002 if (((dev & AudioSystem.DEVICE_BIT_IN) == 0)
6003 && ((dev & mBecomingNoisyIntentDevices) != 0)) {
6004 devices |= dev;
Eric Laurentb1fbaac2012-05-29 09:24:28 -07006005 }
6006 }
Eric Laurentcdae4762017-04-28 18:00:04 -07006007 if (musicDevice == AudioSystem.DEVICE_NONE) {
6008 musicDevice = getDeviceForStream(AudioSystem.STREAM_MUSIC);
6009 }
6010 // ignore condition on device being actually used for music when in communication
6011 // because music routing is altered in this case.
Jean-Michel Trivi7db2d8f2018-03-06 10:30:59 -08006012 // also checks whether media routing if affected by a dynamic policy
6013 if (((device == musicDevice) || isInCommunication()) && (device == devices)
6014 && !hasMediaDynamicPolicy()) {
Eric Laurentcdae4762017-04-28 18:00:04 -07006015 mAudioHandler.removeMessages(MSG_BROADCAST_AUDIO_BECOMING_NOISY);
Eric Laurent5bfaeae2012-09-21 18:44:48 -07006016 sendMsg(mAudioHandler,
6017 MSG_BROADCAST_AUDIO_BECOMING_NOISY,
6018 SENDMSG_REPLACE,
6019 0,
6020 0,
6021 null,
6022 0);
Eric Laurentb1fbaac2012-05-29 09:24:28 -07006023 delay = 1000;
Eric Laurentb1fbaac2012-05-29 09:24:28 -07006024 }
6025 }
6026
Mike Lockwood0a40ec22014-05-21 10:08:50 -07006027 if (mAudioHandler.hasMessages(MSG_SET_A2DP_SRC_CONNECTION_STATE) ||
6028 mAudioHandler.hasMessages(MSG_SET_A2DP_SINK_CONNECTION_STATE) ||
Jakub Pawlowskif9570f32018-02-21 17:15:12 -08006029 mAudioHandler.hasMessages(MSG_SET_HEARING_AID_CONNECTION_STATE) ||
Eric Laurentb1fbaac2012-05-29 09:24:28 -07006030 mAudioHandler.hasMessages(MSG_SET_WIRED_DEVICE_CONNECTION_STATE)) {
Eric Laurentadbe8bf2014-11-03 18:26:32 -08006031 synchronized (mLastDeviceConnectMsgTime) {
6032 long time = SystemClock.uptimeMillis();
6033 if (mLastDeviceConnectMsgTime > time) {
Matthew Xiec525cf72015-01-22 20:13:17 -08006034 delay = (int)(mLastDeviceConnectMsgTime - time) + 30;
Eric Laurentadbe8bf2014-11-03 18:26:32 -08006035 }
6036 }
Eric Laurentb1fbaac2012-05-29 09:24:28 -07006037 }
6038 return delay;
6039 }
6040
Jean-Michel Trivi7db2d8f2018-03-06 10:30:59 -08006041 /**
6042 * @return true if there is currently a registered dynamic mixing policy that affects media
6043 */
6044 private boolean hasMediaDynamicPolicy() {
6045 synchronized (mAudioPolicies) {
6046 if (mAudioPolicies.isEmpty()) {
6047 return false;
6048 }
6049 final Collection<AudioPolicyProxy> appColl = mAudioPolicies.values();
6050 for (AudioPolicyProxy app : appColl) {
6051 if (app.hasMixAffectingUsage(AudioAttributes.USAGE_MEDIA)) {
6052 return true;
6053 }
6054 }
6055 return false;
6056 }
6057 }
6058
Eric Laurenteab40d12017-06-09 12:45:21 -07006059 private void updateAudioRoutes(int device, int state)
6060 {
Dianne Hackborn632ca412012-06-14 19:34:10 -07006061 int connType = 0;
6062
Eric Laurentb1fbaac2012-05-29 09:24:28 -07006063 if (device == AudioSystem.DEVICE_OUT_WIRED_HEADSET) {
Dianne Hackborn632ca412012-06-14 19:34:10 -07006064 connType = AudioRoutesInfo.MAIN_HEADSET;
Jon Eklund43cc8bb2014-07-28 16:07:24 -05006065 } else if (device == AudioSystem.DEVICE_OUT_WIRED_HEADPHONE ||
6066 device == AudioSystem.DEVICE_OUT_LINE) {
Dianne Hackborn632ca412012-06-14 19:34:10 -07006067 connType = AudioRoutesInfo.MAIN_HEADPHONES;
Eric Laurent6fa42452015-01-09 15:09:40 -08006068 } else if (device == AudioSystem.DEVICE_OUT_HDMI ||
6069 device == AudioSystem.DEVICE_OUT_HDMI_ARC) {
Dianne Hackborn632ca412012-06-14 19:34:10 -07006070 connType = AudioRoutesInfo.MAIN_HDMI;
Eric Laurenteab40d12017-06-09 12:45:21 -07006071 } else if (device == AudioSystem.DEVICE_OUT_USB_DEVICE||
6072 device == AudioSystem.DEVICE_OUT_USB_HEADSET) {
Paul McLean10804eb2015-01-28 11:16:35 -08006073 connType = AudioRoutesInfo.MAIN_USB;
Eric Laurentb1fbaac2012-05-29 09:24:28 -07006074 }
6075
Dianne Hackborn632ca412012-06-14 19:34:10 -07006076 synchronized (mCurAudioRoutes) {
6077 if (connType != 0) {
John Spurlock61560172015-02-06 19:46:04 -05006078 int newConn = mCurAudioRoutes.mainType;
Dianne Hackborn632ca412012-06-14 19:34:10 -07006079 if (state != 0) {
6080 newConn |= connType;
6081 } else {
6082 newConn &= ~connType;
6083 }
John Spurlock61560172015-02-06 19:46:04 -05006084 if (newConn != mCurAudioRoutes.mainType) {
6085 mCurAudioRoutes.mainType = newConn;
Dianne Hackborn632ca412012-06-14 19:34:10 -07006086 sendMsg(mAudioHandler, MSG_REPORT_NEW_ROUTES,
6087 SENDMSG_NOOP, 0, 0, null, 0);
6088 }
6089 }
6090 }
Eric Laurenteab40d12017-06-09 12:45:21 -07006091 }
6092
6093 private void sendDeviceConnectionIntent(int device, int state, String address,
6094 String deviceName) {
6095 if (DEBUG_DEVICES) {
6096 Slog.i(TAG, "sendDeviceConnectionIntent(dev:0x" + Integer.toHexString(device) +
6097 " state:0x" + Integer.toHexString(state) + " address:" + address +
6098 " name:" + deviceName + ");");
6099 }
6100 Intent intent = new Intent();
6101
6102 if (device == AudioSystem.DEVICE_OUT_WIRED_HEADSET) {
6103 intent.setAction(Intent.ACTION_HEADSET_PLUG);
6104 intent.putExtra("microphone", 1);
6105 } else if (device == AudioSystem.DEVICE_OUT_WIRED_HEADPHONE ||
6106 device == AudioSystem.DEVICE_OUT_LINE) {
6107 intent.setAction(Intent.ACTION_HEADSET_PLUG);
Jean-Michel Trivi87d31ec2017-08-11 18:28:20 -07006108 intent.putExtra("microphone", 0);
Paul McLean145c9532017-08-04 11:12:19 -06006109 } else if (device == AudioSystem.DEVICE_OUT_USB_HEADSET) {
6110 intent.setAction(Intent.ACTION_HEADSET_PLUG);
Jean-Michel Trivi87d31ec2017-08-11 18:28:20 -07006111 intent.putExtra("microphone",
6112 AudioSystem.getDeviceConnectionState(AudioSystem.DEVICE_IN_USB_HEADSET, "")
6113 == AudioSystem.DEVICE_STATE_AVAILABLE ? 1 : 0);
6114 } else if (device == AudioSystem.DEVICE_IN_USB_HEADSET) {
6115 if (AudioSystem.getDeviceConnectionState(AudioSystem.DEVICE_OUT_USB_HEADSET, "")
6116 == AudioSystem.DEVICE_STATE_AVAILABLE) {
6117 intent.setAction(Intent.ACTION_HEADSET_PLUG);
6118 intent.putExtra("microphone", 1);
6119 } else {
6120 // do not send ACTION_HEADSET_PLUG when only the input side is seen as changing
6121 return;
6122 }
Eric Laurenteab40d12017-06-09 12:45:21 -07006123 } else if (device == AudioSystem.DEVICE_OUT_HDMI ||
6124 device == AudioSystem.DEVICE_OUT_HDMI_ARC) {
6125 configureHdmiPlugIntent(intent, state);
6126 }
6127
Jean-Michel Trivi87a264d2017-08-15 17:52:22 -07006128 if (intent.getAction() == null) {
6129 return;
6130 }
6131
Eric Laurenteab40d12017-06-09 12:45:21 -07006132 intent.putExtra(CONNECT_INTENT_KEY_STATE, state);
6133 intent.putExtra(CONNECT_INTENT_KEY_ADDRESS, address);
6134 intent.putExtra(CONNECT_INTENT_KEY_PORT_NAME, deviceName);
6135
6136 intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY);
Dianne Hackborn632ca412012-06-14 19:34:10 -07006137
Dianne Hackborn5ac72a22012-08-29 18:32:08 -07006138 final long ident = Binder.clearCallingIdentity();
6139 try {
Sudheer Shankadc589ac2016-11-10 15:30:17 -08006140 ActivityManager.broadcastStickyIntent(intent, UserHandle.USER_ALL);
Dianne Hackborn5ac72a22012-08-29 18:32:08 -07006141 } finally {
6142 Binder.restoreCallingIdentity(ident);
6143 }
Eric Laurentb1fbaac2012-05-29 09:24:28 -07006144 }
6145
Eric Laurentbbe3e742017-04-28 18:11:50 -07006146 private static final int DEVICE_OVERRIDE_A2DP_ROUTE_ON_PLUG =
6147 AudioSystem.DEVICE_OUT_WIRED_HEADSET | AudioSystem.DEVICE_OUT_WIRED_HEADPHONE |
6148 AudioSystem.DEVICE_OUT_LINE |
6149 AudioSystem.DEVICE_OUT_ALL_USB;
6150
Paul McLean10804eb2015-01-28 11:16:35 -08006151 private void onSetWiredDeviceConnectionState(int device, int state, String address,
John Spurlock90874332015-03-10 16:00:54 -04006152 String deviceName, String caller) {
Paul McLean394a8e12015-03-03 10:29:19 -07006153 if (DEBUG_DEVICES) {
John Spurlock90874332015-03-10 16:00:54 -04006154 Slog.i(TAG, "onSetWiredDeviceConnectionState(dev:" + Integer.toHexString(device)
6155 + " state:" + Integer.toHexString(state)
6156 + " address:" + address
6157 + " deviceName:" + deviceName
6158 + " caller: " + caller + ");");
Paul McLean394a8e12015-03-03 10:29:19 -07006159 }
Paul McLean10804eb2015-01-28 11:16:35 -08006160
Eric Laurentb1fbaac2012-05-29 09:24:28 -07006161 synchronized (mConnectedDevices) {
Eric Laurentbbe3e742017-04-28 18:11:50 -07006162 if ((state == 0) && ((device & DEVICE_OVERRIDE_A2DP_ROUTE_ON_PLUG) != 0)) {
Jean-Michel Trivi011f39e2017-08-19 18:08:06 -07006163 setBluetoothA2dpOnInt(true, "onSetWiredDeviceConnectionState state 0");
Sungsoocf09fe62016-09-28 16:21:48 +09006164 }
Paul McLean145c9532017-08-04 11:12:19 -06006165
Jean-Michel Trivi6d00e412015-08-03 17:26:01 -07006166 if (!handleDeviceConnection(state == 1, device, address, deviceName)) {
6167 // change of connection state failed, bailout
6168 return;
6169 }
Eric Laurentf1a457d2012-09-20 16:27:23 -07006170 if (state != 0) {
Eric Laurentbbe3e742017-04-28 18:11:50 -07006171 if ((device & DEVICE_OVERRIDE_A2DP_ROUTE_ON_PLUG) != 0) {
Jean-Michel Trivi011f39e2017-08-19 18:08:06 -07006172 setBluetoothA2dpOnInt(false, "onSetWiredDeviceConnectionState state not 0");
Sungsoocf09fe62016-09-28 16:21:48 +09006173 }
Eric Laurentf1a457d2012-09-20 16:27:23 -07006174 if ((device & mSafeMediaVolumeDevices) != 0) {
6175 sendMsg(mAudioHandler,
6176 MSG_CHECK_MUSIC_ACTIVE,
6177 SENDMSG_REPLACE,
6178 0,
6179 0,
John Spurlock90874332015-03-10 16:00:54 -04006180 caller,
Eric Laurentf1a457d2012-09-20 16:27:23 -07006181 MUSIC_ACTIVE_POLL_PERIOD_MS);
6182 }
Eric Laurent212532b2014-07-21 15:43:18 -07006183 // Television devices without CEC service apply software volume on HDMI output
6184 if (isPlatformTelevision() && ((device & AudioSystem.DEVICE_OUT_HDMI) != 0)) {
6185 mFixedVolumeDevices |= AudioSystem.DEVICE_OUT_HDMI;
6186 checkAllFixedVolumeDevices();
6187 if (mHdmiManager != null) {
6188 synchronized (mHdmiManager) {
6189 if (mHdmiPlaybackClient != null) {
6190 mHdmiCecSink = false;
6191 mHdmiPlaybackClient.queryDisplayStatus(mHdmiDisplayStatusCallback);
6192 }
6193 }
6194 }
6195 }
6196 } else {
6197 if (isPlatformTelevision() && ((device & AudioSystem.DEVICE_OUT_HDMI) != 0)) {
6198 if (mHdmiManager != null) {
6199 synchronized (mHdmiManager) {
6200 mHdmiCecSink = false;
6201 }
6202 }
6203 }
Eric Laurentb1fbaac2012-05-29 09:24:28 -07006204 }
Jean-Michel Trivi87a264d2017-08-15 17:52:22 -07006205 sendDeviceConnectionIntent(device, state, address, deviceName);
Eric Laurenteab40d12017-06-09 12:45:21 -07006206 updateAudioRoutes(device, state);
Eric Laurentb1fbaac2012-05-29 09:24:28 -07006207 }
6208 }
6209
Jean-Michel Trivi37d78042014-08-10 14:59:15 -07006210 private void configureHdmiPlugIntent(Intent intent, int state) {
Jean-Michel Trivic5258432014-08-27 15:46:54 -07006211 intent.setAction(AudioManager.ACTION_HDMI_AUDIO_PLUG);
6212 intent.putExtra(AudioManager.EXTRA_AUDIO_PLUG_STATE, state);
Jean-Michel Trivi37d78042014-08-10 14:59:15 -07006213 if (state == 1) {
6214 ArrayList<AudioPort> ports = new ArrayList<AudioPort>();
6215 int[] portGeneration = new int[1];
6216 int status = AudioSystem.listAudioPorts(ports, portGeneration);
6217 if (status == AudioManager.SUCCESS) {
6218 for (AudioPort port : ports) {
6219 if (port instanceof AudioDevicePort) {
6220 final AudioDevicePort devicePort = (AudioDevicePort) port;
Eric Laurent6fa42452015-01-09 15:09:40 -08006221 if (devicePort.type() == AudioManager.DEVICE_OUT_HDMI ||
6222 devicePort.type() == AudioManager.DEVICE_OUT_HDMI_ARC) {
Jean-Michel Trivi37d78042014-08-10 14:59:15 -07006223 // format the list of supported encodings
Eric Laurentcae34662015-05-19 16:46:52 -07006224 int[] formats = AudioFormat.filterPublicFormats(devicePort.formats());
Jean-Michel Trivi37d78042014-08-10 14:59:15 -07006225 if (formats.length > 0) {
6226 ArrayList<Integer> encodingList = new ArrayList(1);
6227 for (int format : formats) {
6228 // a format in the list can be 0, skip it
6229 if (format != AudioFormat.ENCODING_INVALID) {
6230 encodingList.add(format);
6231 }
6232 }
6233 int[] encodingArray = new int[encodingList.size()];
6234 for (int i = 0 ; i < encodingArray.length ; i++) {
6235 encodingArray[i] = encodingList.get(i);
6236 }
Jean-Michel Trivic5258432014-08-27 15:46:54 -07006237 intent.putExtra(AudioManager.EXTRA_ENCODINGS, encodingArray);
Jean-Michel Trivi37d78042014-08-10 14:59:15 -07006238 }
6239 // find the maximum supported number of channels
6240 int maxChannels = 0;
6241 for (int mask : devicePort.channelMasks()) {
6242 int channelCount = AudioFormat.channelCountFromOutChannelMask(mask);
6243 if (channelCount > maxChannels) {
6244 maxChannels = channelCount;
6245 }
6246 }
Jean-Michel Trivic5258432014-08-27 15:46:54 -07006247 intent.putExtra(AudioManager.EXTRA_MAX_CHANNEL_COUNT, maxChannels);
Jean-Michel Trivi37d78042014-08-10 14:59:15 -07006248 }
6249 }
6250 }
6251 }
6252 }
6253 }
6254
Jean-Michel Trivia847ba42010-04-23 11:49:29 -07006255 /* cache of the address of the last dock the device was connected to */
6256 private String mDockAddress;
6257
Eric Laurenta553c252009-07-17 12:17:14 -07006258 /**
6259 * Receiver for misc intent broadcasts the Phone app cares about.
6260 */
6261 private class AudioServiceBroadcastReceiver extends BroadcastReceiver {
6262 @Override
6263 public void onReceive(Context context, Intent intent) {
6264 String action = intent.getAction();
Eric Laurentae4506e2014-05-29 16:04:32 -07006265 int outDevice;
6266 int inDevice;
Eric Laurent59f48272012-04-05 19:42:21 -07006267 int state;
Eric Laurenta553c252009-07-17 12:17:14 -07006268
Jean-Michel Trivi758559e2010-03-09 09:26:08 -08006269 if (action.equals(Intent.ACTION_DOCK_EVENT)) {
6270 int dockState = intent.getIntExtra(Intent.EXTRA_DOCK_STATE,
6271 Intent.EXTRA_DOCK_STATE_UNDOCKED);
6272 int config;
6273 switch (dockState) {
6274 case Intent.EXTRA_DOCK_STATE_DESK:
6275 config = AudioSystem.FORCE_BT_DESK_DOCK;
6276 break;
6277 case Intent.EXTRA_DOCK_STATE_CAR:
6278 config = AudioSystem.FORCE_BT_CAR_DOCK;
6279 break;
Praveen Bharathi21e941b2010-10-06 15:23:14 -05006280 case Intent.EXTRA_DOCK_STATE_LE_DESK:
Eric Laurent08ed1b92012-11-05 14:54:12 -08006281 config = AudioSystem.FORCE_ANALOG_DOCK;
Praveen Bharathi21e941b2010-10-06 15:23:14 -05006282 break;
6283 case Intent.EXTRA_DOCK_STATE_HE_DESK:
6284 config = AudioSystem.FORCE_DIGITAL_DOCK;
6285 break;
Jean-Michel Trivi758559e2010-03-09 09:26:08 -08006286 case Intent.EXTRA_DOCK_STATE_UNDOCKED:
6287 default:
6288 config = AudioSystem.FORCE_NONE;
6289 }
Eric Laurent08ed1b92012-11-05 14:54:12 -08006290 // Low end docks have a menu to enable or disable audio
6291 // (see mDockAudioMediaEnabled)
6292 if (!((dockState == Intent.EXTRA_DOCK_STATE_LE_DESK) ||
6293 ((dockState == Intent.EXTRA_DOCK_STATE_UNDOCKED) &&
6294 (mDockState == Intent.EXTRA_DOCK_STATE_LE_DESK)))) {
Jean-Michel Trivi011f39e2017-08-19 18:08:06 -07006295 mForceUseLogger.log(new ForceUseEvent(AudioSystem.FOR_DOCK, config,
6296 "ACTION_DOCK_EVENT intent"));
Eric Laurent08ed1b92012-11-05 14:54:12 -08006297 AudioSystem.setForceUse(AudioSystem.FOR_DOCK, config);
6298 }
6299 mDockState = dockState;
Jack He8dd33942018-01-17 15:45:12 -08006300 } else if (action.equals(BluetoothHeadset.ACTION_ACTIVE_DEVICE_CHANGED)) {
Eric Laurentdca56b92011-09-02 14:20:56 -07006301 BluetoothDevice btDevice = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
Jack He8dd33942018-01-17 15:45:12 -08006302 setBtScoActiveDevice(btDevice);
Paul McLeandf361462014-04-10 16:02:55 -07006303 } else if (action.equals(BluetoothHeadset.ACTION_AUDIO_STATE_CHANGED)) {
Eric Laurent62ef7672010-11-24 10:58:32 -08006304 boolean broadcast = false;
Eric Laurent59f48272012-04-05 19:42:21 -07006305 int scoAudioState = AudioManager.SCO_AUDIO_STATE_ERROR;
Eric Laurent3def1ee2010-03-17 23:26:26 -07006306 synchronized (mScoClients) {
Eric Laurent62ef7672010-11-24 10:58:32 -08006307 int btState = intent.getIntExtra(BluetoothProfile.EXTRA_STATE, -1);
Eric Laurentdc03c612011-04-01 10:59:41 -07006308 // broadcast intent if the connection was initated by AudioService
6309 if (!mScoClients.isEmpty() &&
6310 (mScoAudioState == SCO_STATE_ACTIVE_INTERNAL ||
6311 mScoAudioState == SCO_STATE_ACTIVATE_REQ ||
6312 mScoAudioState == SCO_STATE_DEACTIVATE_REQ)) {
Eric Laurent62ef7672010-11-24 10:58:32 -08006313 broadcast = true;
6314 }
6315 switch (btState) {
6316 case BluetoothHeadset.STATE_AUDIO_CONNECTED:
Eric Laurent59f48272012-04-05 19:42:21 -07006317 scoAudioState = AudioManager.SCO_AUDIO_STATE_CONNECTED;
Eric Laurentdc03c612011-04-01 10:59:41 -07006318 if (mScoAudioState != SCO_STATE_ACTIVE_INTERNAL &&
6319 mScoAudioState != SCO_STATE_DEACTIVATE_REQ &&
6320 mScoAudioState != SCO_STATE_DEACTIVATE_EXT_REQ) {
Eric Laurent62ef7672010-11-24 10:58:32 -08006321 mScoAudioState = SCO_STATE_ACTIVE_EXTERNAL;
Eric Laurent3def1ee2010-03-17 23:26:26 -07006322 }
Eric Laurent62ef7672010-11-24 10:58:32 -08006323 break;
6324 case BluetoothHeadset.STATE_AUDIO_DISCONNECTED:
Eric Laurent59f48272012-04-05 19:42:21 -07006325 scoAudioState = AudioManager.SCO_AUDIO_STATE_DISCONNECTED;
Eric Laurent62ef7672010-11-24 10:58:32 -08006326 mScoAudioState = SCO_STATE_INACTIVE;
Eric Laurentd7454be2011-09-14 08:45:58 -07006327 clearAllScoClients(0, false);
Eric Laurent62ef7672010-11-24 10:58:32 -08006328 break;
6329 case BluetoothHeadset.STATE_AUDIO_CONNECTING:
Eric Laurentdc03c612011-04-01 10:59:41 -07006330 if (mScoAudioState != SCO_STATE_ACTIVE_INTERNAL &&
6331 mScoAudioState != SCO_STATE_DEACTIVATE_REQ &&
6332 mScoAudioState != SCO_STATE_DEACTIVATE_EXT_REQ) {
Eric Laurent62ef7672010-11-24 10:58:32 -08006333 mScoAudioState = SCO_STATE_ACTIVE_EXTERNAL;
Eric Laurent3def1ee2010-03-17 23:26:26 -07006334 }
Eric Laurent62ef7672010-11-24 10:58:32 -08006335 default:
6336 // do not broadcast CONNECTING or invalid state
6337 broadcast = false;
6338 break;
Eric Laurent3def1ee2010-03-17 23:26:26 -07006339 }
6340 }
Eric Laurent62ef7672010-11-24 10:58:32 -08006341 if (broadcast) {
Eric Laurent59f48272012-04-05 19:42:21 -07006342 broadcastScoConnectionState(scoAudioState);
Eric Laurentdc03c612011-04-01 10:59:41 -07006343 //FIXME: this is to maintain compatibility with deprecated intent
6344 // AudioManager.ACTION_SCO_AUDIO_STATE_CHANGED. Remove when appropriate.
Eric Laurent62ef7672010-11-24 10:58:32 -08006345 Intent newIntent = new Intent(AudioManager.ACTION_SCO_AUDIO_STATE_CHANGED);
Eric Laurent59f48272012-04-05 19:42:21 -07006346 newIntent.putExtra(AudioManager.EXTRA_SCO_AUDIO_STATE, scoAudioState);
Dianne Hackborn5ac72a22012-08-29 18:32:08 -07006347 sendStickyBroadcastToAll(newIntent);
Eric Laurent62ef7672010-11-24 10:58:32 -08006348 }
Eric Laurent950e8cb2011-10-13 08:57:54 -07006349 } else if (action.equals(Intent.ACTION_SCREEN_ON)) {
Jon Eklund318f0fe2014-01-23 17:53:48 -06006350 if (mMonitorRotation) {
Jean-Michel Trivi24806db2015-10-01 15:00:59 -07006351 RotationHelper.enable();
Jon Eklund318f0fe2014-01-23 17:53:48 -06006352 }
Eric Laurent950e8cb2011-10-13 08:57:54 -07006353 AudioSystem.setParameters("screen_state=on");
6354 } else if (action.equals(Intent.ACTION_SCREEN_OFF)) {
Jon Eklund318f0fe2014-01-23 17:53:48 -06006355 if (mMonitorRotation) {
6356 //reduce wakeups (save current) by only listening when display is on
Jean-Michel Trivi24806db2015-10-01 15:00:59 -07006357 RotationHelper.disable();
Jon Eklund318f0fe2014-01-23 17:53:48 -06006358 }
Eric Laurent950e8cb2011-10-13 08:57:54 -07006359 AudioSystem.setParameters("screen_state=off");
Dianne Hackborn961cae92013-03-20 14:59:43 -07006360 } else if (action.equals(Intent.ACTION_CONFIGURATION_CHANGED)) {
Jean-Michel Trivif26f0172012-04-25 16:23:20 -07006361 handleConfigurationChanged(context);
Eric Laurentbc0fab1f2012-09-19 11:24:41 -07006362 } else if (action.equals(Intent.ACTION_USER_SWITCHED)) {
Yasuhiro Matsuda4ced7192015-07-10 22:08:44 +09006363 if (mUserSwitchedReceived) {
6364 // attempt to stop music playback for background user except on first user
6365 // switch (i.e. first boot)
6366 sendMsg(mAudioHandler,
6367 MSG_BROADCAST_AUDIO_BECOMING_NOISY,
6368 SENDMSG_REPLACE,
6369 0,
6370 0,
6371 null,
6372 0);
6373 }
6374 mUserSwitchedReceived = true;
Jean-Michel Trivif4a8eb22012-10-29 12:42:55 -07006375 // the current audio focus owner is no longer valid
Jean-Michel Trivifa9a6982013-06-27 16:22:58 -07006376 mMediaFocusControl.discardAudioFocusOwner();
Jean-Michel Trivif4a8eb22012-10-29 12:42:55 -07006377
Eric Laurent5bfaeae2012-09-21 18:44:48 -07006378 // load volume settings for new user
Eric Laurentbc0fab1f2012-09-19 11:24:41 -07006379 readAudioSettings(true /*userSwitch*/);
6380 // preserve STREAM_MUSIC volume from one user to the next.
6381 sendMsg(mAudioHandler,
6382 MSG_SET_ALL_VOLUMES,
6383 SENDMSG_QUEUE,
6384 0,
6385 0,
6386 mStreamStates[AudioSystem.STREAM_MUSIC], 0);
Fyodor Kupolovb5013302015-04-17 17:59:14 -07006387 } else if (action.equals(Intent.ACTION_USER_BACKGROUND)) {
6388 // Disable audio recording for the background user/profile
6389 int userId = intent.getIntExtra(Intent.EXTRA_USER_HANDLE, -1);
6390 if (userId >= 0) {
6391 // TODO Kill recording streams instead of killing processes holding permission
6392 UserInfo userInfo = UserManagerService.getInstance().getUserInfo(userId);
6393 killBackgroundUserProcessesWithRecordAudioPermission(userInfo);
6394 }
Makoto Onukiac65e1e2015-11-20 15:33:17 -08006395 UserManagerService.getInstance().setUserRestriction(
Fyodor Kupolovb5013302015-04-17 17:59:14 -07006396 UserManager.DISALLOW_RECORD_AUDIO, true, userId);
6397 } else if (action.equals(Intent.ACTION_USER_FOREGROUND)) {
6398 // Enable audio recording for foreground user/profile
6399 int userId = intent.getIntExtra(Intent.EXTRA_USER_HANDLE, -1);
Makoto Onukiac65e1e2015-11-20 15:33:17 -08006400 UserManagerService.getInstance().setUserRestriction(
Fyodor Kupolovb5013302015-04-17 17:59:14 -07006401 UserManager.DISALLOW_RECORD_AUDIO, false, userId);
Eric Laurentb70b78a2016-01-13 19:16:04 -08006402 } else if (action.equals(BluetoothAdapter.ACTION_STATE_CHANGED)) {
6403 state = intent.getIntExtra(BluetoothAdapter.EXTRA_STATE, -1);
6404 if (state == BluetoothAdapter.STATE_OFF ||
6405 state == BluetoothAdapter.STATE_TURNING_OFF) {
6406 disconnectAllBluetoothProfiles();
6407 }
Marco Nelissenfb6df0b2017-02-15 15:25:24 -08006408 } else if (action.equals(AudioEffect.ACTION_OPEN_AUDIO_EFFECT_CONTROL_SESSION) ||
6409 action.equals(AudioEffect.ACTION_CLOSE_AUDIO_EFFECT_CONTROL_SESSION)) {
6410 handleAudioEffectBroadcast(context, intent);
Eric Laurenta553c252009-07-17 12:17:14 -07006411 }
6412 }
Paul McLeanc837a452014-04-09 09:04:43 -07006413 } // end class AudioServiceBroadcastReceiver
Jean-Michel Trivid5176cf2010-01-28 11:56:42 -08006414
Makoto Onukid45a4a22015-11-02 17:17:38 -08006415 private class AudioServiceUserRestrictionsListener implements UserRestrictionsListener {
6416
6417 @Override
6418 public void onUserRestrictionsChanged(int userId, Bundle newRestrictions,
6419 Bundle prevRestrictions) {
6420 // Update mic mute state.
6421 {
6422 final boolean wasRestricted =
6423 prevRestrictions.getBoolean(UserManager.DISALLOW_UNMUTE_MICROPHONE);
6424 final boolean isRestricted =
6425 newRestrictions.getBoolean(UserManager.DISALLOW_UNMUTE_MICROPHONE);
6426 if (wasRestricted != isRestricted) {
6427 setMicrophoneMuteNoCallerCheck(isRestricted, userId);
6428 }
6429 }
6430
6431 // Update speaker mute state.
6432 {
6433 final boolean wasRestricted =
Tony Makc1205112016-07-22 16:02:59 +01006434 prevRestrictions.getBoolean(UserManager.DISALLOW_ADJUST_VOLUME)
Esteban Talavera492b4722017-02-13 14:59:45 +00006435 || prevRestrictions.getBoolean(UserManager.DISALLOW_UNMUTE_DEVICE);
Makoto Onukid45a4a22015-11-02 17:17:38 -08006436 final boolean isRestricted =
Tony Makc1205112016-07-22 16:02:59 +01006437 newRestrictions.getBoolean(UserManager.DISALLOW_ADJUST_VOLUME)
Esteban Talavera492b4722017-02-13 14:59:45 +00006438 || newRestrictions.getBoolean(UserManager.DISALLOW_UNMUTE_DEVICE);
Makoto Onukid45a4a22015-11-02 17:17:38 -08006439 if (wasRestricted != isRestricted) {
6440 setMasterMuteInternalNoCallerCheck(isRestricted, /* flags =*/ 0, userId);
6441 }
6442 }
6443 }
6444 } // end class AudioServiceUserRestrictionsListener
6445
Marco Nelissenfb6df0b2017-02-15 15:25:24 -08006446 private void handleAudioEffectBroadcast(Context context, Intent intent) {
6447 String target = intent.getPackage();
6448 if (target != null) {
6449 Log.w(TAG, "effect broadcast already targeted to " + target);
6450 return;
6451 }
6452 intent.addFlags(Intent.FLAG_INCLUDE_STOPPED_PACKAGES);
6453 // TODO this should target a user-selected panel
6454 List<ResolveInfo> ril = context.getPackageManager().queryBroadcastReceivers(
6455 intent, 0 /* flags */);
6456 if (ril != null && ril.size() != 0) {
6457 ResolveInfo ri = ril.get(0);
6458 if (ri != null && ri.activityInfo != null && ri.activityInfo.packageName != null) {
6459 intent.setPackage(ri.activityInfo.packageName);
6460 context.sendBroadcastAsUser(intent, UserHandle.ALL);
6461 return;
6462 }
6463 }
6464 Log.w(TAG, "couldn't find receiver package for effect intent");
6465 }
6466
Fyodor Kupolovb5013302015-04-17 17:59:14 -07006467 private void killBackgroundUserProcessesWithRecordAudioPermission(UserInfo oldUser) {
6468 PackageManager pm = mContext.getPackageManager();
6469 // Find the home activity of the user. It should not be killed to avoid expensive restart,
6470 // when the user switches back. For managed profiles, we should kill all recording apps
6471 ComponentName homeActivityName = null;
6472 if (!oldUser.isManagedProfile()) {
Sudheer Shankafc46e9b2016-10-21 17:55:27 -07006473 homeActivityName = mActivityManagerInternal.getHomeActivityForUser(oldUser.id);
Fyodor Kupolovb5013302015-04-17 17:59:14 -07006474 }
6475 final String[] permissions = { Manifest.permission.RECORD_AUDIO };
6476 List<PackageInfo> packages;
6477 try {
6478 packages = AppGlobals.getPackageManager()
6479 .getPackagesHoldingPermissions(permissions, 0, oldUser.id).getList();
6480 } catch (RemoteException e) {
6481 throw new AndroidRuntimeException(e);
6482 }
6483 for (int j = packages.size() - 1; j >= 0; j--) {
6484 PackageInfo pkg = packages.get(j);
Fyodor Kupolovbcb6c1e2015-05-11 12:05:15 -07006485 // Skip system processes
6486 if (UserHandle.getAppId(pkg.applicationInfo.uid) < FIRST_APPLICATION_UID) {
6487 continue;
6488 }
Amith Yamasanic1cbaab2015-07-21 11:46:14 -07006489 // Skip packages that have permission to interact across users
6490 if (pm.checkPermission(Manifest.permission.INTERACT_ACROSS_USERS, pkg.packageName)
6491 == PackageManager.PERMISSION_GRANTED) {
6492 continue;
6493 }
Fyodor Kupolovb5013302015-04-17 17:59:14 -07006494 if (homeActivityName != null
6495 && pkg.packageName.equals(homeActivityName.getPackageName())
6496 && pkg.applicationInfo.isSystemApp()) {
6497 continue;
6498 }
6499 try {
Svetoslavaa41add2015-08-06 15:03:55 -07006500 final int uid = pkg.applicationInfo.uid;
Sudheer Shankadc589ac2016-11-10 15:30:17 -08006501 ActivityManager.getService().killUid(UserHandle.getAppId(uid),
Svetoslavaa41add2015-08-06 15:03:55 -07006502 UserHandle.getUserId(uid),
Fyodor Kupolovb5013302015-04-17 17:59:14 -07006503 "killBackgroundUserProcessesWithAudioRecordPermission");
6504 } catch (RemoteException e) {
6505 Log.w(TAG, "Error calling killUid", e);
6506 }
6507 }
6508 }
6509
Jean-Michel Trivi3114ce32012-06-11 15:03:52 -07006510
Jean-Michel Trivifa9a6982013-06-27 16:22:58 -07006511 //==========================================================================================
6512 // Audio Focus
6513 //==========================================================================================
Jean-Michel Trivi9228af62018-01-05 17:06:17 -08006514 /**
6515 * Returns whether a focus request is eligible to force ducking.
6516 * Will return true if:
6517 * - the AudioAttributes have a usage of USAGE_ASSISTANCE_ACCESSIBILITY,
6518 * - the focus request is AUDIOFOCUS_GAIN_TRANSIENT_MAY_DUCK,
6519 * - the associated Bundle has KEY_ACCESSIBILITY_FORCE_FOCUS_DUCKING set to true,
6520 * - the uid of the requester is a known accessibility service or root.
6521 * @param aa AudioAttributes of the focus request
6522 * @param uid uid of the focus requester
6523 * @return true if ducking is to be forced
6524 */
6525 private boolean forceFocusDuckingForAccessibility(@Nullable AudioAttributes aa,
6526 int request, int uid) {
6527 if (aa == null || aa.getUsage() != AudioAttributes.USAGE_ASSISTANCE_ACCESSIBILITY
6528 || request != AudioManager.AUDIOFOCUS_GAIN_TRANSIENT_MAY_DUCK) {
6529 return false;
6530 }
6531 final Bundle extraInfo = aa.getBundle();
6532 if (extraInfo == null ||
6533 !extraInfo.getBoolean(AudioFocusRequest.KEY_ACCESSIBILITY_FORCE_FOCUS_DUCKING)) {
6534 return false;
6535 }
6536 if (uid == 0) {
6537 return true;
6538 }
6539 synchronized (mAccessibilityServiceUidsLock) {
6540 if (mAccessibilityServiceUids != null) {
6541 int callingUid = Binder.getCallingUid();
6542 for (int i = 0; i < mAccessibilityServiceUids.length; i++) {
6543 if (mAccessibilityServiceUids[i] == callingUid) {
6544 return true;
6545 }
6546 }
6547 }
6548 }
6549 return false;
6550 }
6551
Jean-Michel Trivifd6ad742014-11-10 14:38:30 -08006552 public int requestAudioFocus(AudioAttributes aa, int durationHint, IBinder cb,
Jean-Michel Trivi958876f2014-11-16 15:40:22 -08006553 IAudioFocusDispatcher fd, String clientId, String callingPackageName, int flags,
Jean-Michel Trivi461922f2017-04-25 15:23:17 -07006554 IAudioPolicyCallback pcb, int sdk) {
Jean-Michel Trivi958876f2014-11-16 15:40:22 -08006555 // permission checks
6556 if ((flags & AudioManager.AUDIOFOCUS_FLAG_LOCK) == AudioManager.AUDIOFOCUS_FLAG_LOCK) {
John Spurlock61560172015-02-06 19:46:04 -05006557 if (AudioSystem.IN_VOICE_COMM_FOCUS_ID.equals(clientId)) {
Jean-Michel Trivi958876f2014-11-16 15:40:22 -08006558 if (PackageManager.PERMISSION_GRANTED != mContext.checkCallingOrSelfPermission(
6559 android.Manifest.permission.MODIFY_PHONE_STATE)) {
6560 Log.e(TAG, "Invalid permission to (un)lock audio focus", new Exception());
6561 return AudioManager.AUDIOFOCUS_REQUEST_FAILED;
6562 }
6563 } else {
6564 // only a registered audio policy can be used to lock focus
6565 synchronized (mAudioPolicies) {
Jean-Michel Trivi0212be52014-11-24 14:43:10 -08006566 if (!mAudioPolicies.containsKey(pcb.asBinder())) {
6567 Log.e(TAG, "Invalid unregistered AudioPolicy to (un)lock audio focus");
Jean-Michel Trivi958876f2014-11-16 15:40:22 -08006568 return AudioManager.AUDIOFOCUS_REQUEST_FAILED;
6569 }
6570 }
6571 }
6572 }
6573
Jean-Michel Trivifd6ad742014-11-10 14:38:30 -08006574 return mMediaFocusControl.requestAudioFocus(aa, durationHint, cb, fd,
Jean-Michel Trivi9228af62018-01-05 17:06:17 -08006575 clientId, callingPackageName, flags, sdk,
6576 forceFocusDuckingForAccessibility(aa, durationHint, Binder.getCallingUid()));
Jean-Michel Trivifa9a6982013-06-27 16:22:58 -07006577 }
6578
Jean-Michel Trivi126cf032017-04-02 23:19:02 -07006579 public int abandonAudioFocus(IAudioFocusDispatcher fd, String clientId, AudioAttributes aa,
6580 String callingPackageName) {
6581 return mMediaFocusControl.abandonAudioFocus(fd, clientId, aa, callingPackageName);
Jean-Michel Trivifa9a6982013-06-27 16:22:58 -07006582 }
6583
6584 public void unregisterAudioFocusClient(String clientId) {
6585 mMediaFocusControl.unregisterAudioFocusClient(clientId);
Jean-Michel Trivi3114ce32012-06-11 15:03:52 -07006586 }
6587
Jean-Michel Trivi23805662013-07-31 14:19:18 -07006588 public int getCurrentAudioFocus() {
6589 return mMediaFocusControl.getCurrentAudioFocus();
6590 }
6591
Jean-Michel Trivi99489cc2017-01-25 19:08:49 -08006592 public int getFocusRampTimeMs(int focusGain, AudioAttributes attr) {
6593 return mMediaFocusControl.getFocusRampTimeMs(focusGain, attr);
6594 }
6595
Jean-Michel Trivi126cf032017-04-02 23:19:02 -07006596 //==========================================================================================
John Spurlock5e783732015-02-19 10:28:59 -05006597 private boolean readCameraSoundForced() {
6598 return SystemProperties.getBoolean("audio.camerasound.force", false) ||
6599 mContext.getResources().getBoolean(
6600 com.android.internal.R.bool.config_camera_sound_forced);
6601 }
6602
Jean-Michel Trivif26f0172012-04-25 16:23:20 -07006603 //==========================================================================================
6604 // Device orientation
6605 //==========================================================================================
6606 /**
Mikhail Naganovb668bc62018-02-13 13:46:38 -08006607 * Handles device configuration changes that may map to a change in rotation.
6608 * Monitoring rotation is optional, and is defined by the definition and value
6609 * of the "ro.audio.monitorRotation" system property.
Jean-Michel Trivif26f0172012-04-25 16:23:20 -07006610 */
6611 private void handleConfigurationChanged(Context context) {
6612 try {
Mikhail Naganovb668bc62018-02-13 13:46:38 -08006613 // reading new configuration "safely" (i.e. under try catch) in case anything
6614 // goes wrong.
Eric Laurentd640bd32012-09-28 18:01:48 -07006615 Configuration config = context.getResources().getConfiguration();
Eric Laurentd640bd32012-09-28 18:01:48 -07006616 sendMsg(mAudioHandler,
6617 MSG_CONFIGURE_SAFE_MEDIA_VOLUME,
6618 SENDMSG_REPLACE,
6619 0,
6620 0,
John Spurlock90874332015-03-10 16:00:54 -04006621 TAG,
Eric Laurentd640bd32012-09-28 18:01:48 -07006622 0);
Eric Laurentdd45d012012-10-08 09:04:34 -07006623
John Spurlock5e783732015-02-19 10:28:59 -05006624 boolean cameraSoundForced = readCameraSoundForced();
Eric Laurentdd45d012012-10-08 09:04:34 -07006625 synchronized (mSettingsLock) {
Jean-Michel Trivi8719a1d2017-11-06 11:52:51 -08006626 final boolean cameraSoundForcedChanged = (cameraSoundForced != mCameraSoundForced);
6627 mCameraSoundForced = cameraSoundForced;
Eric Laurent8fa4d6f2014-10-30 14:13:03 -07006628 if (cameraSoundForcedChanged) {
Muyuan Li1ed6df62016-06-18 11:16:52 -07006629 if (!mIsSingleVolume) {
Jean-Michel Trivi085346a2018-02-14 10:48:51 -08006630 synchronized (VolumeStreamState.class) {
6631 VolumeStreamState s = mStreamStates[AudioSystem.STREAM_SYSTEM_ENFORCED];
6632 if (cameraSoundForced) {
6633 s.setAllIndexesToMax();
6634 mRingerModeAffectedStreams &=
6635 ~(1 << AudioSystem.STREAM_SYSTEM_ENFORCED);
6636 } else {
6637 s.setAllIndexes(mStreamStates[AudioSystem.STREAM_SYSTEM], TAG);
6638 mRingerModeAffectedStreams |=
6639 (1 << AudioSystem.STREAM_SYSTEM_ENFORCED);
6640 }
Eric Laurent8fa4d6f2014-10-30 14:13:03 -07006641 }
6642 // take new state into account for streams muted by ringer mode
John Spurlock661f2cf2014-11-17 10:29:10 -05006643 setRingerModeInt(getRingerModeInternal(), false);
Eric Laurent8fa4d6f2014-10-30 14:13:03 -07006644 }
6645
6646 sendMsg(mAudioHandler,
6647 MSG_SET_FORCE_USE,
6648 SENDMSG_QUEUE,
6649 AudioSystem.FOR_SYSTEM,
6650 cameraSoundForced ?
6651 AudioSystem.FORCE_SYSTEM_ENFORCED : AudioSystem.FORCE_NONE,
Jean-Michel Trivi011f39e2017-08-19 18:08:06 -07006652 new String("handleConfigurationChanged"),
Eric Laurent8fa4d6f2014-10-30 14:13:03 -07006653 0);
6654
6655 sendMsg(mAudioHandler,
6656 MSG_SET_ALL_VOLUMES,
6657 SENDMSG_QUEUE,
6658 0,
6659 0,
6660 mStreamStates[AudioSystem.STREAM_SYSTEM_ENFORCED], 0);
6661 }
Eric Laurentdd45d012012-10-08 09:04:34 -07006662 }
John Spurlock3346a802014-05-20 16:25:37 -04006663 mVolumeController.setLayoutDirection(config.getLayoutDirection());
Jean-Michel Trivif26f0172012-04-25 16:23:20 -07006664 } catch (Exception e) {
Jean-Michel Trivibb6f8712013-05-23 15:02:41 -07006665 Log.e(TAG, "Error handling configuration change: ", e);
Jean-Michel Trivif26f0172012-04-25 16:23:20 -07006666 }
6667 }
6668
Sungsoocf09fe62016-09-28 16:21:48 +09006669 // Handles request to override default use of A2DP for media.
6670 // Must be called synchronized on mConnectedDevices
Jean-Michel Trivi011f39e2017-08-19 18:08:06 -07006671 public void setBluetoothA2dpOnInt(boolean on, String eventSource) {
Sungsoocf09fe62016-09-28 16:21:48 +09006672 synchronized (mBluetoothA2dpEnabledLock) {
6673 mBluetoothA2dpEnabled = on;
6674 mAudioHandler.removeMessages(MSG_SET_FORCE_BT_A2DP_USE);
6675 setForceUseInt_SyncDevices(AudioSystem.FOR_MEDIA,
Jean-Michel Trivi011f39e2017-08-19 18:08:06 -07006676 mBluetoothA2dpEnabled ? AudioSystem.FORCE_NONE : AudioSystem.FORCE_NO_BT_A2DP,
6677 eventSource);
Sungsoocf09fe62016-09-28 16:21:48 +09006678 }
6679 }
6680
Jean-Michel Trivi7e2f3712015-01-12 11:01:55 -08006681 // Must be called synchronized on mConnectedDevices
Jean-Michel Trivi011f39e2017-08-19 18:08:06 -07006682 private void setForceUseInt_SyncDevices(int usage, int config, String eventSource) {
Eric Laurent9a5b2622017-04-18 18:20:56 -07006683 if (usage == AudioSystem.FOR_MEDIA) {
6684 sendMsg(mAudioHandler, MSG_REPORT_NEW_ROUTES,
6685 SENDMSG_NOOP, 0, 0, null, 0);
Jean-Michel Trivi7e2f3712015-01-12 11:01:55 -08006686 }
Jean-Michel Trivi011f39e2017-08-19 18:08:06 -07006687 mForceUseLogger.log(new ForceUseEvent(usage, config, eventSource));
Jean-Michel Trivi7e2f3712015-01-12 11:01:55 -08006688 AudioSystem.setForceUse(usage, config);
6689 }
6690
Jean-Michel Trivid5176cf2010-01-28 11:56:42 -08006691 @Override
Jeff Sharkey098d5802012-04-26 17:30:34 -07006692 public void setRingtonePlayer(IRingtonePlayer player) {
6693 mContext.enforceCallingOrSelfPermission(REMOTE_AUDIO_PLAYBACK, null);
6694 mRingtonePlayer = player;
6695 }
6696
6697 @Override
6698 public IRingtonePlayer getRingtonePlayer() {
6699 return mRingtonePlayer;
6700 }
6701
6702 @Override
Dianne Hackborn632ca412012-06-14 19:34:10 -07006703 public AudioRoutesInfo startWatchingRoutes(IAudioRoutesObserver observer) {
6704 synchronized (mCurAudioRoutes) {
6705 AudioRoutesInfo routes = new AudioRoutesInfo(mCurAudioRoutes);
6706 mRoutesObservers.register(observer);
6707 return routes;
6708 }
6709 }
6710
Eric Laurentc34dcc12012-09-10 13:51:52 -07006711
6712 //==========================================================================================
6713 // Safe media volume management.
6714 // MUSIC stream volume level is limited when headphones are connected according to safety
6715 // regulation. When the user attempts to raise the volume above the limit, a warning is
6716 // displayed and the user has to acknowlegde before the volume is actually changed.
6717 // The volume index corresponding to the limit is stored in config_safe_media_volume_index
6718 // property. Platforms with a different limit must set this property accordingly in their
6719 // overlay.
6720 //==========================================================================================
6721
Eric Laurentd640bd32012-09-28 18:01:48 -07006722 // mSafeMediaVolumeState indicates whether the media volume is limited over headphones.
6723 // It is SAFE_MEDIA_VOLUME_NOT_CONFIGURED at boot time until a network service is connected
6724 // or the configure time is elapsed. It is then set to SAFE_MEDIA_VOLUME_ACTIVE or
6725 // SAFE_MEDIA_VOLUME_DISABLED according to country option. If not SAFE_MEDIA_VOLUME_DISABLED, it
6726 // can be set to SAFE_MEDIA_VOLUME_INACTIVE by calling AudioService.disableSafeMediaVolume()
6727 // (when user opts out).
John Spurlock35134602014-07-24 18:10:48 -04006728 private static final int SAFE_MEDIA_VOLUME_NOT_CONFIGURED = 0;
6729 private static final int SAFE_MEDIA_VOLUME_DISABLED = 1;
6730 private static final int SAFE_MEDIA_VOLUME_INACTIVE = 2; // confirmed
6731 private static final int SAFE_MEDIA_VOLUME_ACTIVE = 3; // unconfirmed
Eric Laurentd640bd32012-09-28 18:01:48 -07006732 private Integer mSafeMediaVolumeState;
6733
6734 private int mMcc = 0;
Eric Laurentc34dcc12012-09-10 13:51:52 -07006735 // mSafeMediaVolumeIndex is the cached value of config_safe_media_volume_index property
Eric Laurentd640bd32012-09-28 18:01:48 -07006736 private int mSafeMediaVolumeIndex;
John Muir8b8bddd2018-02-16 14:29:14 -08006737 // mSafeUsbMediaVolumeDbfs is the cached value of the config_safe_media_volume_usb_mB
6738 // property, divided by 100.0.
6739 private float mSafeUsbMediaVolumeDbfs;
Eric Laurentb378a13a2017-07-11 14:08:11 -07006740 // mSafeUsbMediaVolumeIndex is used for USB Headsets and is the music volume UI index
John Muir8b8bddd2018-02-16 14:29:14 -08006741 // corresponding to a gain of mSafeUsbMediaVolumeDbfs (defaulting to -37dB) in audio
6742 // flinger mixer.
Eric Laurent0e5deb32017-09-01 15:12:42 -07006743 // We remove -22 dBs from the theoretical -15dB to account for the EQ + bass boost
6744 // amplification when both effects are on with all band gains at maximum.
Eric Laurentb378a13a2017-07-11 14:08:11 -07006745 // This level corresponds to a loudness of 85 dB SPL for the warning to be displayed when
6746 // the headset is compliant to EN 60950 with a max loudness of 100dB SPL.
Eric Laurenteab40d12017-06-09 12:45:21 -07006747 private int mSafeUsbMediaVolumeIndex;
Eric Laurentc34dcc12012-09-10 13:51:52 -07006748 // mSafeMediaVolumeDevices lists the devices for which safe media volume is enforced,
6749 private final int mSafeMediaVolumeDevices = AudioSystem.DEVICE_OUT_WIRED_HEADSET |
Eric Laurenteab40d12017-06-09 12:45:21 -07006750 AudioSystem.DEVICE_OUT_WIRED_HEADPHONE |
6751 AudioSystem.DEVICE_OUT_USB_HEADSET;
Eric Laurentc34dcc12012-09-10 13:51:52 -07006752 // mMusicActiveMs is the cumulative time of music activity since safe volume was disabled.
6753 // When this time reaches UNSAFE_VOLUME_MUSIC_ACTIVE_MS_MAX, the safe media volume is re-enabled
6754 // automatically. mMusicActiveMs is rounded to a multiple of MUSIC_ACTIVE_POLL_PERIOD_MS.
6755 private int mMusicActiveMs;
6756 private static final int UNSAFE_VOLUME_MUSIC_ACTIVE_MS_MAX = (20 * 3600 * 1000); // 20 hours
6757 private static final int MUSIC_ACTIVE_POLL_PERIOD_MS = 60000; // 1 minute polling interval
Eric Laurentd640bd32012-09-28 18:01:48 -07006758 private static final int SAFE_VOLUME_CONFIGURE_TIMEOUT_MS = 30000; // 30s after boot completed
Eric Laurentc34dcc12012-09-10 13:51:52 -07006759
Eric Laurenteab40d12017-06-09 12:45:21 -07006760 private int safeMediaVolumeIndex(int device) {
6761 if ((device & mSafeMediaVolumeDevices) == 0) {
6762 return MAX_STREAM_VOLUME[AudioSystem.STREAM_MUSIC];
6763 }
6764 if (device == AudioSystem.DEVICE_OUT_USB_HEADSET) {
6765 return mSafeUsbMediaVolumeIndex;
6766 } else {
6767 return mSafeMediaVolumeIndex;
6768 }
6769 }
6770
John Spurlock90874332015-03-10 16:00:54 -04006771 private void setSafeMediaVolumeEnabled(boolean on, String caller) {
Eric Laurentd640bd32012-09-28 18:01:48 -07006772 synchronized (mSafeMediaVolumeState) {
6773 if ((mSafeMediaVolumeState != SAFE_MEDIA_VOLUME_NOT_CONFIGURED) &&
6774 (mSafeMediaVolumeState != SAFE_MEDIA_VOLUME_DISABLED)) {
6775 if (on && (mSafeMediaVolumeState == SAFE_MEDIA_VOLUME_INACTIVE)) {
6776 mSafeMediaVolumeState = SAFE_MEDIA_VOLUME_ACTIVE;
John Spurlock90874332015-03-10 16:00:54 -04006777 enforceSafeMediaVolume(caller);
Eric Laurentd640bd32012-09-28 18:01:48 -07006778 } else if (!on && (mSafeMediaVolumeState == SAFE_MEDIA_VOLUME_ACTIVE)) {
6779 mSafeMediaVolumeState = SAFE_MEDIA_VOLUME_INACTIVE;
John Spurlockaa5ee4d2014-07-25 13:05:12 -04006780 mMusicActiveMs = 1; // nonzero = confirmed
6781 saveMusicActiveMs();
Eric Laurentd640bd32012-09-28 18:01:48 -07006782 sendMsg(mAudioHandler,
6783 MSG_CHECK_MUSIC_ACTIVE,
6784 SENDMSG_REPLACE,
6785 0,
6786 0,
John Spurlock90874332015-03-10 16:00:54 -04006787 caller,
Eric Laurentd640bd32012-09-28 18:01:48 -07006788 MUSIC_ACTIVE_POLL_PERIOD_MS);
6789 }
Eric Laurentc34dcc12012-09-10 13:51:52 -07006790 }
Eric Laurentc34dcc12012-09-10 13:51:52 -07006791 }
6792 }
6793
John Spurlock90874332015-03-10 16:00:54 -04006794 private void enforceSafeMediaVolume(String caller) {
Eric Laurentc34dcc12012-09-10 13:51:52 -07006795 VolumeStreamState streamState = mStreamStates[AudioSystem.STREAM_MUSIC];
Eric Laurentc34dcc12012-09-10 13:51:52 -07006796 int devices = mSafeMediaVolumeDevices;
6797 int i = 0;
6798
6799 while (devices != 0) {
6800 int device = 1 << i++;
6801 if ((device & devices) == 0) {
6802 continue;
6803 }
Eric Laurent42b041e2013-03-29 11:36:03 -07006804 int index = streamState.getIndex(device);
Eric Laurenteab40d12017-06-09 12:45:21 -07006805 if (index > safeMediaVolumeIndex(device)) {
6806 streamState.setIndex(safeMediaVolumeIndex(device), device, caller);
Eric Laurent42b041e2013-03-29 11:36:03 -07006807 sendMsg(mAudioHandler,
6808 MSG_SET_DEVICE_VOLUME,
6809 SENDMSG_QUEUE,
6810 device,
6811 0,
6812 streamState,
6813 0);
Eric Laurentc34dcc12012-09-10 13:51:52 -07006814 }
6815 devices &= ~device;
6816 }
6817 }
6818
6819 private boolean checkSafeMediaVolume(int streamType, int index, int device) {
Eric Laurentd640bd32012-09-28 18:01:48 -07006820 synchronized (mSafeMediaVolumeState) {
6821 if ((mSafeMediaVolumeState == SAFE_MEDIA_VOLUME_ACTIVE) &&
Eric Laurentc34dcc12012-09-10 13:51:52 -07006822 (mStreamVolumeAlias[streamType] == AudioSystem.STREAM_MUSIC) &&
6823 ((device & mSafeMediaVolumeDevices) != 0) &&
Eric Laurenteab40d12017-06-09 12:45:21 -07006824 (index > safeMediaVolumeIndex(device))) {
Eric Laurentc34dcc12012-09-10 13:51:52 -07006825 return false;
6826 }
6827 return true;
6828 }
6829 }
6830
John Spurlock3346a802014-05-20 16:25:37 -04006831 @Override
John Spurlock90874332015-03-10 16:00:54 -04006832 public void disableSafeMediaVolume(String callingPackage) {
John Spurlockcdb57ae2015-02-11 19:04:11 -05006833 enforceVolumeController("disable the safe media volume");
Eric Laurentd640bd32012-09-28 18:01:48 -07006834 synchronized (mSafeMediaVolumeState) {
John Spurlock90874332015-03-10 16:00:54 -04006835 setSafeMediaVolumeEnabled(false, callingPackage);
Eric Laurentfde16d52012-12-03 14:42:39 -08006836 if (mPendingVolumeCommand != null) {
6837 onSetStreamVolume(mPendingVolumeCommand.mStreamType,
6838 mPendingVolumeCommand.mIndex,
6839 mPendingVolumeCommand.mFlags,
John Spurlock90874332015-03-10 16:00:54 -04006840 mPendingVolumeCommand.mDevice,
6841 callingPackage);
Eric Laurentfde16d52012-12-03 14:42:39 -08006842 mPendingVolumeCommand = null;
6843 }
Eric Laurentc34dcc12012-09-10 13:51:52 -07006844 }
6845 }
6846
Jungshik Jang41d97462014-06-30 22:26:29 +09006847 //==========================================================================================
6848 // Hdmi Cec system audio mode.
John Spurlockbc82b122015-03-02 16:12:38 -05006849 // If Hdmi Cec's system audio mode is on, audio service should send the volume change
6850 // to HdmiControlService so that the audio receiver can handle it.
Jungshik Jang41d97462014-06-30 22:26:29 +09006851 //==========================================================================================
6852
Eric Laurent212532b2014-07-21 15:43:18 -07006853 private class MyDisplayStatusCallback implements HdmiPlaybackClient.DisplayStatusCallback {
6854 public void onComplete(int status) {
6855 if (mHdmiManager != null) {
6856 synchronized (mHdmiManager) {
6857 mHdmiCecSink = (status != HdmiControlManager.POWER_STATUS_UNKNOWN);
6858 // Television devices without CEC service apply software volume on HDMI output
6859 if (isPlatformTelevision() && !mHdmiCecSink) {
6860 mFixedVolumeDevices &= ~AudioSystem.DEVICE_OUT_HDMI;
6861 }
6862 checkAllFixedVolumeDevices();
6863 }
6864 }
6865 }
6866 };
6867
Jungshik Jang41d97462014-06-30 22:26:29 +09006868 // If HDMI-CEC system audio is supported
6869 private boolean mHdmiSystemAudioSupported = false;
6870 // Set only when device is tv.
6871 private HdmiTvClient mHdmiTvClient;
Eric Laurent0b03f992014-11-18 18:08:02 -08006872 // true if the device has system feature PackageManager.FEATURE_LEANBACK.
Eric Laurent212532b2014-07-21 15:43:18 -07006873 // cached HdmiControlManager interface
6874 private HdmiControlManager mHdmiManager;
6875 // Set only when device is a set-top box.
6876 private HdmiPlaybackClient mHdmiPlaybackClient;
6877 // true if we are a set-top box, an HDMI sink is connected and it supports CEC.
6878 private boolean mHdmiCecSink;
6879
6880 private MyDisplayStatusCallback mHdmiDisplayStatusCallback = new MyDisplayStatusCallback();
Jungshik Jang41d97462014-06-30 22:26:29 +09006881
6882 @Override
Jungshik Jang12307ca2014-07-15 19:27:56 +09006883 public int setHdmiSystemAudioSupported(boolean on) {
Eric Laurent212532b2014-07-21 15:43:18 -07006884 int device = AudioSystem.DEVICE_NONE;
6885 if (mHdmiManager != null) {
6886 synchronized (mHdmiManager) {
6887 if (mHdmiTvClient == null) {
6888 Log.w(TAG, "Only Hdmi-Cec enabled TV device supports system audio mode.");
6889 return device;
6890 }
Jungshik Jang41d97462014-06-30 22:26:29 +09006891
Eric Laurent212532b2014-07-21 15:43:18 -07006892 synchronized (mHdmiTvClient) {
6893 if (mHdmiSystemAudioSupported != on) {
6894 mHdmiSystemAudioSupported = on;
Jean-Michel Trivi011f39e2017-08-19 18:08:06 -07006895 final int config = on ? AudioSystem.FORCE_HDMI_SYSTEM_AUDIO_ENFORCED :
6896 AudioSystem.FORCE_NONE;
6897 mForceUseLogger.log(new ForceUseEvent(AudioSystem.FOR_HDMI_SYSTEM_AUDIO,
6898 config, "setHdmiSystemAudioSupported"));
6899 AudioSystem.setForceUse(AudioSystem.FOR_HDMI_SYSTEM_AUDIO, config);
Eric Laurent212532b2014-07-21 15:43:18 -07006900 }
John Spurlock8a52c442015-03-26 14:23:58 -04006901 device = getDevicesForStream(AudioSystem.STREAM_MUSIC);
Eric Laurent212532b2014-07-21 15:43:18 -07006902 }
Jungshik Jang6f34f5a2014-07-08 21:17:29 +09006903 }
Jungshik Jang6f34f5a2014-07-08 21:17:29 +09006904 }
Eric Laurent212532b2014-07-21 15:43:18 -07006905 return device;
Jungshik Jang6f34f5a2014-07-08 21:17:29 +09006906 }
Jungshik Jang41d97462014-06-30 22:26:29 +09006907
Terry Heoe7d6d972014-09-04 21:05:28 +09006908 @Override
6909 public boolean isHdmiSystemAudioSupported() {
6910 return mHdmiSystemAudioSupported;
6911 }
6912
Eric Laurentdd45d012012-10-08 09:04:34 -07006913 //==========================================================================================
Jean-Michel Triviac487672016-11-11 10:05:18 -08006914 // Accessibility
6915
Jean-Michel Trivicfa55532017-01-18 11:17:51 -08006916 private void initA11yMonitoring() {
6917 final AccessibilityManager accessibilityManager =
6918 (AccessibilityManager) mContext.getSystemService(Context.ACCESSIBILITY_SERVICE);
Jean-Michel Triviac487672016-11-11 10:05:18 -08006919 updateDefaultStreamOverrideDelay(accessibilityManager.isTouchExplorationEnabled());
Jean-Michel Trivi7592b982017-02-01 15:12:15 -08006920 updateA11yVolumeAlias(accessibilityManager.isAccessibilityVolumeStreamActive());
Phil Weaver26d709f2017-04-20 17:19:14 -07006921 accessibilityManager.addTouchExplorationStateChangeListener(this, null);
6922 accessibilityManager.addAccessibilityServicesStateChangeListener(this, null);
Jean-Michel Triviac487672016-11-11 10:05:18 -08006923 }
6924
6925 //---------------------------------------------------------------------------------
6926 // A11y: taking touch exploration into account for selecting the default
Jean-Michel Trivi873cc452014-09-11 17:25:09 -07006927 // stream override timeout when adjusting volume
Jean-Michel Triviac487672016-11-11 10:05:18 -08006928 //---------------------------------------------------------------------------------
Jean-Michel Trivi873cc452014-09-11 17:25:09 -07006929
Jean-Michel Triviac487672016-11-11 10:05:18 -08006930 // - STREAM_NOTIFICATION on tablets during this period after a notification stopped
Julia Reynoldsd9e96e22017-11-07 10:33:08 -05006931 // - STREAM_RING on phones during this period after a notification stopped
6932 // - STREAM_MUSIC otherwise
6933
Jean-Michel Triviac487672016-11-11 10:05:18 -08006934 private static final int DEFAULT_STREAM_TYPE_OVERRIDE_DELAY_MS = 0;
6935 private static final int TOUCH_EXPLORE_STREAM_TYPE_OVERRIDE_DELAY_MS = 1000;
Jean-Michel Trivi873cc452014-09-11 17:25:09 -07006936
Jean-Michel Triviac487672016-11-11 10:05:18 -08006937 private static int sStreamOverrideDelayMs;
Jean-Michel Trivi873cc452014-09-11 17:25:09 -07006938
Jean-Michel Triviac487672016-11-11 10:05:18 -08006939 @Override
6940 public void onTouchExplorationStateChanged(boolean enabled) {
6941 updateDefaultStreamOverrideDelay(enabled);
6942 }
6943
6944 private void updateDefaultStreamOverrideDelay(boolean touchExploreEnabled) {
6945 if (touchExploreEnabled) {
6946 sStreamOverrideDelayMs = TOUCH_EXPLORE_STREAM_TYPE_OVERRIDE_DELAY_MS;
6947 } else {
6948 sStreamOverrideDelayMs = DEFAULT_STREAM_TYPE_OVERRIDE_DELAY_MS;
Jean-Michel Trivi873cc452014-09-11 17:25:09 -07006949 }
Jean-Michel Triviac487672016-11-11 10:05:18 -08006950 if (DEBUG_VOL) Log.d(TAG, "Touch exploration enabled=" + touchExploreEnabled
6951 + " stream override delay is now " + sStreamOverrideDelayMs + " ms");
6952 }
Jean-Michel Trivi873cc452014-09-11 17:25:09 -07006953
Jean-Michel Triviac487672016-11-11 10:05:18 -08006954 //---------------------------------------------------------------------------------
6955 // A11y: taking a11y state into account for the handling of a11y prompts volume
6956 //---------------------------------------------------------------------------------
Jean-Michel Trivi873cc452014-09-11 17:25:09 -07006957
Jean-Michel Triviac487672016-11-11 10:05:18 -08006958 private static boolean sIndependentA11yVolume = false;
6959
Jean-Michel Trivicfa55532017-01-18 11:17:51 -08006960 // implementation of AccessibilityServicesStateChangeListener
6961 @Override
Phil Weaver4cab9302017-03-30 15:27:39 -07006962 public void onAccessibilityServicesStateChanged(AccessibilityManager accessibilityManager) {
Jean-Michel Trivicfa55532017-01-18 11:17:51 -08006963 updateA11yVolumeAlias(accessibilityManager.isAccessibilityVolumeStreamActive());
6964 }
6965
6966 private void updateA11yVolumeAlias(boolean a11VolEnabled) {
6967 if (DEBUG_VOL) Log.d(TAG, "Accessibility volume enabled = " + a11VolEnabled);
6968 if (sIndependentA11yVolume != a11VolEnabled) {
6969 sIndependentA11yVolume = a11VolEnabled;
6970 // update the volume mapping scheme
6971 updateStreamVolumeAlias(true /*updateVolumes*/, TAG);
6972 // update the volume controller behavior
6973 mVolumeController.setA11yMode(sIndependentA11yVolume ?
6974 VolumePolicy.A11Y_MODE_INDEPENDENT_A11Y_VOLUME :
6975 VolumePolicy.A11Y_MODE_MEDIA_A11Y_VOLUME);
Jean-Michel Trivia53b7052017-04-12 18:27:01 -07006976 mVolumeController.postVolumeChanged(AudioManager.STREAM_ACCESSIBILITY, 0);
Jean-Michel Trivicfa55532017-01-18 11:17:51 -08006977 }
Jean-Michel Trivi873cc452014-09-11 17:25:09 -07006978 }
6979
6980 //==========================================================================================
Eric Laurentdd45d012012-10-08 09:04:34 -07006981 // Camera shutter sound policy.
6982 // config_camera_sound_forced configuration option in config.xml defines if the camera shutter
6983 // sound is forced (sound even if the device is in silent mode) or not. This option is false by
6984 // default and can be overridden by country specific overlay in values-mccXXX/config.xml.
6985 //==========================================================================================
6986
6987 // cached value of com.android.internal.R.bool.config_camera_sound_forced
Jean-Michel Trivi8719a1d2017-11-06 11:52:51 -08006988 @GuardedBy("mSettingsLock")
6989 private boolean mCameraSoundForced;
Eric Laurentdd45d012012-10-08 09:04:34 -07006990
6991 // called by android.hardware.Camera to populate CameraInfo.canDisableShutterSound
6992 public boolean isCameraSoundForced() {
Jean-Michel Trivi8719a1d2017-11-06 11:52:51 -08006993 synchronized (mSettingsLock) {
Eric Laurentdd45d012012-10-08 09:04:34 -07006994 return mCameraSoundForced;
6995 }
6996 }
6997
Jean-Michel Trivi011f39e2017-08-19 18:08:06 -07006998 //==========================================================================================
6999 // AudioService logging and dumpsys
7000 //==========================================================================================
7001 final int LOG_NB_EVENTS_PHONE_STATE = 20;
7002 final int LOG_NB_EVENTS_WIRED_DEV_CONNECTION = 30;
7003 final int LOG_NB_EVENTS_FORCE_USE = 20;
Jean-Michel Trivicf170362017-08-24 17:24:57 -07007004 final int LOG_NB_EVENTS_VOLUME = 40;
Jean-Michel Trivi011f39e2017-08-19 18:08:06 -07007005
7006 final private AudioEventLogger mModeLogger = new AudioEventLogger(LOG_NB_EVENTS_PHONE_STATE,
7007 "phone state (logged after successfull call to AudioSystem.setPhoneState(int))");
7008
7009 final private AudioEventLogger mWiredDevLogger = new AudioEventLogger(
7010 LOG_NB_EVENTS_WIRED_DEV_CONNECTION,
7011 "wired device connection (logged before onSetWiredDeviceConnectionState() is executed)"
7012 );
7013
7014 final private AudioEventLogger mForceUseLogger = new AudioEventLogger(
7015 LOG_NB_EVENTS_FORCE_USE,
7016 "force use (logged before setForceUse() is executed)");
7017
Jean-Michel Trivicf170362017-08-24 17:24:57 -07007018 final private AudioEventLogger mVolumeLogger = new AudioEventLogger(LOG_NB_EVENTS_VOLUME,
7019 "volume changes (logged when command received by AudioService)");
7020
Eric Laurentdd45d012012-10-08 09:04:34 -07007021 private static final String[] RINGER_MODE_NAMES = new String[] {
7022 "SILENT",
7023 "VIBRATE",
7024 "NORMAL"
7025 };
7026
7027 private void dumpRingerMode(PrintWriter pw) {
7028 pw.println("\nRinger mode: ");
John Spurlock661f2cf2014-11-17 10:29:10 -05007029 pw.println("- mode (internal) = " + RINGER_MODE_NAMES[mRingerMode]);
7030 pw.println("- mode (external) = " + RINGER_MODE_NAMES[mRingerModeExternal]);
John Spurlock50ced3f2015-05-11 16:00:09 -04007031 dumpRingerModeStreams(pw, "affected", mRingerModeAffectedStreams);
Beverlyd6964762018-02-16 14:07:03 -05007032 dumpRingerModeStreams(pw, "muted", mRingerAndZenModeMutedStreams);
John Spurlock661f2cf2014-11-17 10:29:10 -05007033 pw.print("- delegate = "); pw.println(mRingerModeDelegate);
Eric Laurentdd45d012012-10-08 09:04:34 -07007034 }
7035
John Spurlock50ced3f2015-05-11 16:00:09 -04007036 private void dumpRingerModeStreams(PrintWriter pw, String type, int streams) {
7037 pw.print("- ringer mode "); pw.print(type); pw.print(" streams = 0x");
7038 pw.print(Integer.toHexString(streams));
7039 if (streams != 0) {
7040 pw.print(" (");
7041 boolean first = true;
7042 for (int i = 0; i < AudioSystem.STREAM_NAMES.length; i++) {
7043 final int stream = (1 << i);
7044 if ((streams & stream) != 0) {
7045 if (!first) pw.print(',');
7046 pw.print(AudioSystem.STREAM_NAMES[i]);
7047 streams &= ~stream;
7048 first = false;
7049 }
7050 }
7051 if (streams != 0) {
7052 if (!first) pw.print(',');
7053 pw.print(streams);
7054 }
7055 pw.print(')');
7056 }
7057 pw.println();
7058 }
7059
Dianne Hackborn632ca412012-06-14 19:34:10 -07007060 @Override
Jean-Michel Trivid5176cf2010-01-28 11:56:42 -08007061 protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
Jeff Sharkeyfe9a53b2017-03-31 14:08:23 -06007062 if (!DumpUtils.checkDumpPermission(mContext, TAG, pw)) return;
Jeff Sharkeyeb4cc4922012-04-26 18:17:29 -07007063
Jean-Michel Trivifa9a6982013-06-27 16:22:58 -07007064 mMediaFocusControl.dump(pw);
Eric Laurentbffc3d12012-05-07 17:43:49 -07007065 dumpStreamStates(pw);
Eric Laurentdd45d012012-10-08 09:04:34 -07007066 dumpRingerMode(pw);
Dianne Hackborn632ca412012-06-14 19:34:10 -07007067 pw.println("\nAudio routes:");
John Spurlock61560172015-02-06 19:46:04 -05007068 pw.print(" mMainType=0x"); pw.println(Integer.toHexString(mCurAudioRoutes.mainType));
7069 pw.print(" mBluetoothName="); pw.println(mCurAudioRoutes.bluetoothName);
John Spurlock35134602014-07-24 18:10:48 -04007070
7071 pw.println("\nOther state:");
John Spurlock3346a802014-05-20 16:25:37 -04007072 pw.print(" mVolumeController="); pw.println(mVolumeController);
John Spurlock35134602014-07-24 18:10:48 -04007073 pw.print(" mSafeMediaVolumeState=");
7074 pw.println(safeMediaVolumeStateToString(mSafeMediaVolumeState));
7075 pw.print(" mSafeMediaVolumeIndex="); pw.println(mSafeMediaVolumeIndex);
Eric Laurenteab40d12017-06-09 12:45:21 -07007076 pw.print(" mSafeUsbMediaVolumeIndex="); pw.println(mSafeUsbMediaVolumeIndex);
John Muir8b8bddd2018-02-16 14:29:14 -08007077 pw.print(" mSafeUsbMediaVolumeDbfs="); pw.println(mSafeUsbMediaVolumeDbfs);
Jean-Michel Trivi7592b982017-02-01 15:12:15 -08007078 pw.print(" sIndependentA11yVolume="); pw.println(sIndependentA11yVolume);
John Spurlock35134602014-07-24 18:10:48 -04007079 pw.print(" mPendingVolumeCommand="); pw.println(mPendingVolumeCommand);
7080 pw.print(" mMusicActiveMs="); pw.println(mMusicActiveMs);
John Spurlockaa5ee4d2014-07-25 13:05:12 -04007081 pw.print(" mMcc="); pw.println(mMcc);
John Spurlock5e783732015-02-19 10:28:59 -05007082 pw.print(" mCameraSoundForced="); pw.println(mCameraSoundForced);
John Spurlock661f2cf2014-11-17 10:29:10 -05007083 pw.print(" mHasVibrator="); pw.println(mHasVibrator);
John Spurlocka48d7792015-03-03 17:35:57 -05007084 pw.print(" mVolumePolicy="); pw.println(mVolumePolicy);
Jean-Michel Trivi1ab43f62017-04-27 15:37:34 -07007085 pw.print(" mAvrcpAbsVolSupported="); pw.println(mAvrcpAbsVolSupported);
Jean-Michel Trivi1b3541d2014-11-25 12:53:41 -08007086
7087 dumpAudioPolicies(pw);
Jean-Michel Trivi292a6a42016-12-01 08:32:15 -08007088
7089 mPlaybackMonitor.dump(pw);
Jean-Michel Trivi66ffacf2017-02-04 17:25:31 -08007090
7091 mRecordMonitor.dump(pw);
Jean-Michel Trivi011f39e2017-08-19 18:08:06 -07007092
Jean-Michel Trivicf170362017-08-24 17:24:57 -07007093 pw.println("\n");
Jean-Michel Trivi011f39e2017-08-19 18:08:06 -07007094 pw.println("\nEvent logs:");
7095 mModeLogger.dump(pw);
7096 pw.println("\n");
7097 mWiredDevLogger.dump(pw);
7098 pw.println("\n");
7099 mForceUseLogger.dump(pw);
Jean-Michel Trivicf170362017-08-24 17:24:57 -07007100 pw.println("\n");
7101 mVolumeLogger.dump(pw);
John Spurlock35134602014-07-24 18:10:48 -04007102 }
7103
7104 private static String safeMediaVolumeStateToString(Integer state) {
7105 switch(state) {
7106 case SAFE_MEDIA_VOLUME_NOT_CONFIGURED: return "SAFE_MEDIA_VOLUME_NOT_CONFIGURED";
7107 case SAFE_MEDIA_VOLUME_DISABLED: return "SAFE_MEDIA_VOLUME_DISABLED";
7108 case SAFE_MEDIA_VOLUME_INACTIVE: return "SAFE_MEDIA_VOLUME_INACTIVE";
7109 case SAFE_MEDIA_VOLUME_ACTIVE: return "SAFE_MEDIA_VOLUME_ACTIVE";
7110 }
7111 return null;
Jean-Michel Trivid5176cf2010-01-28 11:56:42 -08007112 }
Glenn Kastenfd116ad2013-07-12 17:10:39 -07007113
7114 // Inform AudioFlinger of our device's low RAM attribute
7115 private static void readAndSetLowRamDevice()
7116 {
Andy Hung79583582018-01-23 13:58:02 -08007117 boolean isLowRamDevice = ActivityManager.isLowRamDeviceStatic();
7118 long totalMemory = 1024 * 1024 * 1024; // 1GB is the default if ActivityManager fails.
7119
7120 try {
7121 final ActivityManager.MemoryInfo info = new ActivityManager.MemoryInfo();
7122 ActivityManager.getService().getMemoryInfo(info);
7123 totalMemory = info.totalMem;
7124 } catch (RemoteException e) {
7125 Log.w(TAG, "Cannot obtain MemoryInfo from ActivityManager, assume low memory device");
7126 isLowRamDevice = true;
7127 }
7128
7129 final int status = AudioSystem.setLowRamDevice(isLowRamDevice, totalMemory);
Glenn Kastenfd116ad2013-07-12 17:10:39 -07007130 if (status != 0) {
7131 Log.w(TAG, "AudioFlinger informed of device's low RAM attribute; status " + status);
7132 }
7133 }
John Spurlock3346a802014-05-20 16:25:37 -04007134
John Spurlockcdb57ae2015-02-11 19:04:11 -05007135 private void enforceVolumeController(String action) {
John Spurlock3346a802014-05-20 16:25:37 -04007136 mContext.enforceCallingOrSelfPermission(android.Manifest.permission.STATUS_BAR_SERVICE,
7137 "Only SystemUI can " + action);
7138 }
7139
7140 @Override
7141 public void setVolumeController(final IVolumeController controller) {
John Spurlockcdb57ae2015-02-11 19:04:11 -05007142 enforceVolumeController("set the volume controller");
John Spurlock3346a802014-05-20 16:25:37 -04007143
7144 // return early if things are not actually changing
7145 if (mVolumeController.isSameBinder(controller)) {
7146 return;
7147 }
7148
7149 // dismiss the old volume controller
7150 mVolumeController.postDismiss();
7151 if (controller != null) {
7152 // we are about to register a new controller, listen for its death
7153 try {
7154 controller.asBinder().linkToDeath(new DeathRecipient() {
7155 @Override
7156 public void binderDied() {
7157 if (mVolumeController.isSameBinder(controller)) {
7158 Log.w(TAG, "Current remote volume controller died, unregistering");
7159 setVolumeController(null);
7160 }
7161 }
7162 }, 0);
7163 } catch (RemoteException e) {
7164 // noop
7165 }
7166 }
7167 mVolumeController.setController(controller);
John Spurlock33f4e042014-07-11 13:10:58 -04007168 if (DEBUG_VOL) Log.d(TAG, "Volume controller: " + mVolumeController);
7169 }
7170
7171 @Override
7172 public void notifyVolumeControllerVisible(final IVolumeController controller, boolean visible) {
John Spurlockcdb57ae2015-02-11 19:04:11 -05007173 enforceVolumeController("notify about volume controller visibility");
John Spurlock33f4e042014-07-11 13:10:58 -04007174
7175 // return early if the controller is not current
7176 if (!mVolumeController.isSameBinder(controller)) {
7177 return;
7178 }
7179
7180 mVolumeController.setVisible(visible);
7181 if (DEBUG_VOL) Log.d(TAG, "Volume controller visible: " + visible);
John Spurlock3346a802014-05-20 16:25:37 -04007182 }
RoboErikd09bd0c2014-06-24 17:45:19 -07007183
John Spurlocka48d7792015-03-03 17:35:57 -05007184 @Override
7185 public void setVolumePolicy(VolumePolicy policy) {
7186 enforceVolumeController("set volume policy");
John Spurlockb02c7442015-04-14 09:32:25 -04007187 if (policy != null && !policy.equals(mVolumePolicy)) {
John Spurlocka48d7792015-03-03 17:35:57 -05007188 mVolumePolicy = policy;
John Spurlockb02c7442015-04-14 09:32:25 -04007189 if (DEBUG_VOL) Log.d(TAG, "Volume policy changed: " + mVolumePolicy);
John Spurlocka48d7792015-03-03 17:35:57 -05007190 }
7191 }
7192
RoboErikd09bd0c2014-06-24 17:45:19 -07007193 public static class VolumeController {
7194 private static final String TAG = "VolumeController";
7195
7196 private IVolumeController mController;
John Spurlock33f4e042014-07-11 13:10:58 -04007197 private boolean mVisible;
7198 private long mNextLongPress;
7199 private int mLongPressTimeout;
RoboErikd09bd0c2014-06-24 17:45:19 -07007200
7201 public void setController(IVolumeController controller) {
7202 mController = controller;
John Spurlock33f4e042014-07-11 13:10:58 -04007203 mVisible = false;
7204 }
7205
7206 public void loadSettings(ContentResolver cr) {
7207 mLongPressTimeout = Settings.Secure.getIntForUser(cr,
7208 Settings.Secure.LONG_PRESS_TIMEOUT, 500, UserHandle.USER_CURRENT);
7209 }
7210
RoboErik4197cb62015-01-21 15:45:32 -08007211 public boolean suppressAdjustment(int resolvedStream, int flags, boolean isMute) {
7212 if (isMute) {
7213 return false;
7214 }
John Spurlock33f4e042014-07-11 13:10:58 -04007215 boolean suppress = false;
7216 if (resolvedStream == AudioSystem.STREAM_RING && mController != null) {
7217 final long now = SystemClock.uptimeMillis();
7218 if ((flags & AudioManager.FLAG_SHOW_UI) != 0 && !mVisible) {
7219 // ui will become visible
7220 if (mNextLongPress < now) {
7221 mNextLongPress = now + mLongPressTimeout;
7222 }
7223 suppress = true;
7224 } else if (mNextLongPress > 0) { // in a long-press
7225 if (now > mNextLongPress) {
7226 // long press triggered, no more suppression
7227 mNextLongPress = 0;
7228 } else {
7229 // keep suppressing until the long press triggers
7230 suppress = true;
7231 }
7232 }
7233 }
7234 return suppress;
7235 }
7236
7237 public void setVisible(boolean visible) {
7238 mVisible = visible;
RoboErikd09bd0c2014-06-24 17:45:19 -07007239 }
7240
7241 public boolean isSameBinder(IVolumeController controller) {
7242 return Objects.equals(asBinder(), binder(controller));
7243 }
7244
7245 public IBinder asBinder() {
7246 return binder(mController);
7247 }
7248
7249 private static IBinder binder(IVolumeController controller) {
7250 return controller == null ? null : controller.asBinder();
7251 }
7252
7253 @Override
7254 public String toString() {
John Spurlock33f4e042014-07-11 13:10:58 -04007255 return "VolumeController(" + asBinder() + ",mVisible=" + mVisible + ")";
RoboErikd09bd0c2014-06-24 17:45:19 -07007256 }
7257
7258 public void postDisplaySafeVolumeWarning(int flags) {
7259 if (mController == null)
7260 return;
7261 try {
7262 mController.displaySafeVolumeWarning(flags);
7263 } catch (RemoteException e) {
7264 Log.w(TAG, "Error calling displaySafeVolumeWarning", e);
7265 }
7266 }
7267
7268 public void postVolumeChanged(int streamType, int flags) {
7269 if (mController == null)
7270 return;
7271 try {
7272 mController.volumeChanged(streamType, flags);
7273 } catch (RemoteException e) {
7274 Log.w(TAG, "Error calling volumeChanged", e);
7275 }
7276 }
7277
RoboErikd09bd0c2014-06-24 17:45:19 -07007278 public void postMasterMuteChanged(int flags) {
7279 if (mController == null)
7280 return;
7281 try {
7282 mController.masterMuteChanged(flags);
7283 } catch (RemoteException e) {
7284 Log.w(TAG, "Error calling masterMuteChanged", e);
7285 }
7286 }
7287
7288 public void setLayoutDirection(int layoutDirection) {
7289 if (mController == null)
7290 return;
7291 try {
7292 mController.setLayoutDirection(layoutDirection);
7293 } catch (RemoteException e) {
7294 Log.w(TAG, "Error calling setLayoutDirection", e);
7295 }
7296 }
7297
7298 public void postDismiss() {
7299 if (mController == null)
7300 return;
7301 try {
7302 mController.dismiss();
7303 } catch (RemoteException e) {
7304 Log.w(TAG, "Error calling dismiss", e);
7305 }
7306 }
Jean-Michel Triviac487672016-11-11 10:05:18 -08007307
7308 public void setA11yMode(int a11yMode) {
7309 if (mController == null)
7310 return;
7311 try {
7312 mController.setA11yMode(a11yMode);
7313 } catch (RemoteException e) {
7314 Log.w(TAG, "Error calling setA11Mode", e);
7315 }
7316 }
RoboErikd09bd0c2014-06-24 17:45:19 -07007317 }
Jean-Michel Trivia8b6bd82014-07-01 09:48:46 -07007318
RoboErik0dac35a2014-08-12 15:48:49 -07007319 /**
7320 * Interface for system components to get some extra functionality through
7321 * LocalServices.
7322 */
7323 final class AudioServiceInternal extends AudioManagerInternal {
John Spurlock661f2cf2014-11-17 10:29:10 -05007324 @Override
7325 public void setRingerModeDelegate(RingerModeDelegate delegate) {
7326 mRingerModeDelegate = delegate;
7327 if (mRingerModeDelegate != null) {
Jean-Michel Trivi8719a1d2017-11-06 11:52:51 -08007328 synchronized (mSettingsLock) {
Beverlyd6964762018-02-16 14:07:03 -05007329 updateRingerAndZenModeAffectedStreams();
Jean-Michel Trivi8719a1d2017-11-06 11:52:51 -08007330 }
John Spurlock661f2cf2014-11-17 10:29:10 -05007331 setRingerModeInternal(getRingerModeInternal(), TAG + ".setRingerModeDelegate");
7332 }
7333 }
RoboErik272e1612014-09-05 11:39:29 -07007334
7335 @Override
7336 public void adjustSuggestedStreamVolumeForUid(int streamType, int direction, int flags,
7337 String callingPackage, int uid) {
7338 // direction and stream type swap here because the public
7339 // adjustSuggested has a different order than the other methods.
John Spurlock90874332015-03-10 16:00:54 -04007340 adjustSuggestedStreamVolume(direction, streamType, flags, callingPackage,
7341 callingPackage, uid);
RoboErik272e1612014-09-05 11:39:29 -07007342 }
7343
RoboErik0dac35a2014-08-12 15:48:49 -07007344 @Override
7345 public void adjustStreamVolumeForUid(int streamType, int direction, int flags,
7346 String callingPackage, int uid) {
John Spurlock90874332015-03-10 16:00:54 -04007347 adjustStreamVolume(streamType, direction, flags, callingPackage,
7348 callingPackage, uid);
RoboErik0dac35a2014-08-12 15:48:49 -07007349 }
7350
7351 @Override
7352 public void setStreamVolumeForUid(int streamType, int direction, int flags,
7353 String callingPackage, int uid) {
John Spurlock90874332015-03-10 16:00:54 -04007354 setStreamVolume(streamType, direction, flags, callingPackage, callingPackage, uid);
RoboErik0dac35a2014-08-12 15:48:49 -07007355 }
RoboErik519c7742014-11-18 10:59:09 -08007356
7357 @Override
John Spurlock661f2cf2014-11-17 10:29:10 -05007358 public int getRingerModeInternal() {
7359 return AudioService.this.getRingerModeInternal();
7360 }
7361
7362 @Override
7363 public void setRingerModeInternal(int ringerMode, String caller) {
7364 AudioService.this.setRingerModeInternal(ringerMode, caller);
7365 }
John Spurlockcdb57ae2015-02-11 19:04:11 -05007366
7367 @Override
Mike Digman55272862018-02-20 14:35:17 -08007368 public void silenceRingerModeInternal(String caller) {
7369 AudioService.this.silenceRingerModeInternal(caller);
7370 }
7371
7372 @Override
John Spurlock50ced3f2015-05-11 16:00:09 -04007373 public void updateRingerModeAffectedStreamsInternal() {
7374 synchronized (mSettingsLock) {
Beverlyd6964762018-02-16 14:07:03 -05007375 if (updateRingerAndZenModeAffectedStreams()) {
John Spurlock50ced3f2015-05-11 16:00:09 -04007376 setRingerModeInt(getRingerModeInternal(), false);
7377 }
7378 }
7379 }
Phil Weaverf1a9aff2017-03-23 17:21:29 -07007380
7381 @Override
7382 public void setAccessibilityServiceUids(IntArray uids) {
7383 synchronized (mAccessibilityServiceUidsLock) {
7384 if (uids.size() == 0) {
7385 mAccessibilityServiceUids = null;
7386 } else {
7387 boolean changed = (mAccessibilityServiceUids == null)
7388 || (mAccessibilityServiceUids.length != uids.size());
7389 if (!changed) {
7390 for (int i = 0; i < mAccessibilityServiceUids.length; i++) {
7391 if (uids.get(i) != mAccessibilityServiceUids[i]) {
7392 changed = true;
7393 break;
7394 }
7395 }
7396 }
7397 if (changed) {
7398 mAccessibilityServiceUids = uids.toArray();
7399 }
7400 }
7401 }
7402 }
RoboErik0dac35a2014-08-12 15:48:49 -07007403 }
7404
Jean-Michel Trivia8b6bd82014-07-01 09:48:46 -07007405 //==========================================================================================
7406 // Audio policy management
7407 //==========================================================================================
Jean-Michel Trivi0212be52014-11-24 14:43:10 -08007408 public String registerAudioPolicy(AudioPolicyConfig policyConfig, IAudioPolicyCallback pcb,
Jean-Michel Trivi610aa9b2018-01-27 15:42:42 -08007409 boolean hasFocusListener, boolean isFocusPolicy, boolean isVolumeController) {
Jean-Michel Trivi5a561092015-04-23 18:48:08 -07007410 AudioSystem.setDynamicPolicyCallback(mDynPolicyCallback);
7411
Jean-Michel Trivi0212be52014-11-24 14:43:10 -08007412 if (DEBUG_AP) Log.d(TAG, "registerAudioPolicy for " + pcb.asBinder()
7413 + " with config:" + policyConfig);
Jean-Michel Trivi8fdb0d42014-07-16 19:08:37 -07007414 String regId = null;
Jean-Michel Trivi0212be52014-11-24 14:43:10 -08007415 // error handling
Jean-Michel Trivia8b6bd82014-07-01 09:48:46 -07007416 boolean hasPermissionForPolicy =
Jean-Michel Trivi0212be52014-11-24 14:43:10 -08007417 (PackageManager.PERMISSION_GRANTED == mContext.checkCallingPermission(
Jean-Michel Trivia8b6bd82014-07-01 09:48:46 -07007418 android.Manifest.permission.MODIFY_AUDIO_ROUTING));
7419 if (!hasPermissionForPolicy) {
7420 Slog.w(TAG, "Can't register audio policy for pid " + Binder.getCallingPid() + " / uid "
7421 + Binder.getCallingUid() + ", need MODIFY_AUDIO_ROUTING");
Jean-Michel Trivi8fdb0d42014-07-16 19:08:37 -07007422 return null;
Jean-Michel Trivia8b6bd82014-07-01 09:48:46 -07007423 }
Jean-Michel Trivi0212be52014-11-24 14:43:10 -08007424
Jean-Michel Trivia8b6bd82014-07-01 09:48:46 -07007425 synchronized (mAudioPolicies) {
Jean-Michel Trivia8b6bd82014-07-01 09:48:46 -07007426 try {
Jean-Michel Trivi0212be52014-11-24 14:43:10 -08007427 if (mAudioPolicies.containsKey(pcb.asBinder())) {
Jean-Michel Trivi1b3541d2014-11-25 12:53:41 -08007428 Slog.e(TAG, "Cannot re-register policy");
7429 return null;
7430 }
Jean-Michel Trivi126cf032017-04-02 23:19:02 -07007431 AudioPolicyProxy app = new AudioPolicyProxy(policyConfig, pcb, hasFocusListener,
Jean-Michel Trivi610aa9b2018-01-27 15:42:42 -08007432 isFocusPolicy, isVolumeController);
Jean-Michel Trivi0212be52014-11-24 14:43:10 -08007433 pcb.asBinder().linkToDeath(app, 0/*flags*/);
7434 regId = app.getRegistrationId();
7435 mAudioPolicies.put(pcb.asBinder(), app);
Jean-Michel Trivia8b6bd82014-07-01 09:48:46 -07007436 } catch (RemoteException e) {
7437 // audio policy owner has already died!
Jean-Michel Trivi0212be52014-11-24 14:43:10 -08007438 Slog.w(TAG, "Audio policy registration failed, could not link to " + pcb +
Jean-Michel Trivia8b6bd82014-07-01 09:48:46 -07007439 " binder death", e);
Jean-Michel Trivi8fdb0d42014-07-16 19:08:37 -07007440 return null;
Jean-Michel Trivia8b6bd82014-07-01 09:48:46 -07007441 }
7442 }
Jean-Michel Trivi8fdb0d42014-07-16 19:08:37 -07007443 return regId;
Jean-Michel Trivia8b6bd82014-07-01 09:48:46 -07007444 }
Jean-Michel Trivi8fdb0d42014-07-16 19:08:37 -07007445
Jean-Michel Trivi0212be52014-11-24 14:43:10 -08007446 public void unregisterAudioPolicyAsync(IAudioPolicyCallback pcb) {
7447 if (DEBUG_AP) Log.d(TAG, "unregisterAudioPolicyAsync for " + pcb.asBinder());
Jean-Michel Trivia8b6bd82014-07-01 09:48:46 -07007448 synchronized (mAudioPolicies) {
Jean-Michel Trivi0212be52014-11-24 14:43:10 -08007449 AudioPolicyProxy app = mAudioPolicies.remove(pcb.asBinder());
Jean-Michel Trivia8b6bd82014-07-01 09:48:46 -07007450 if (app == null) {
7451 Slog.w(TAG, "Trying to unregister unknown audio policy for pid "
7452 + Binder.getCallingPid() + " / uid " + Binder.getCallingUid());
Jean-Michel Trivi1b3541d2014-11-25 12:53:41 -08007453 return;
Jean-Michel Trivia8b6bd82014-07-01 09:48:46 -07007454 } else {
Jean-Michel Trivi0212be52014-11-24 14:43:10 -08007455 pcb.asBinder().unlinkToDeath(app, 0/*flags*/);
Jean-Michel Trivia8b6bd82014-07-01 09:48:46 -07007456 }
Jean-Michel Trivi0212be52014-11-24 14:43:10 -08007457 app.release();
Jean-Michel Trivia8b6bd82014-07-01 09:48:46 -07007458 }
Jean-Michel Trivi8fdb0d42014-07-16 19:08:37 -07007459 // TODO implement clearing mix attribute matching info in native audio policy
Jean-Michel Trivia8b6bd82014-07-01 09:48:46 -07007460 }
7461
Jean-Michel Triviaf576a02018-02-14 08:57:46 -08007462 /**
7463 * Checks whether caller has MODIFY_AUDIO_ROUTING permission, and the policy is registered.
7464 * @param errorMsg log warning if permission check failed.
7465 * @return null if the operation on the audio mixes should be cancelled.
7466 */
7467 @GuardedBy("mAudioPolicies")
7468 private AudioPolicyProxy checkUpdateForPolicy(IAudioPolicyCallback pcb, String errorMsg) {
7469 // permission check
7470 final boolean hasPermissionForPolicy =
Jean-Michel Trivi0212be52014-11-24 14:43:10 -08007471 (PackageManager.PERMISSION_GRANTED == mContext.checkCallingPermission(
7472 android.Manifest.permission.MODIFY_AUDIO_ROUTING));
7473 if (!hasPermissionForPolicy) {
Jean-Michel Triviaf576a02018-02-14 08:57:46 -08007474 Slog.w(TAG, errorMsg + " for pid " +
Jean-Michel Trivi0212be52014-11-24 14:43:10 -08007475 + Binder.getCallingPid() + " / uid "
7476 + Binder.getCallingUid() + ", need MODIFY_AUDIO_ROUTING");
Jean-Michel Triviaf576a02018-02-14 08:57:46 -08007477 return null;
Jean-Michel Trivi0212be52014-11-24 14:43:10 -08007478 }
Jean-Michel Triviaf576a02018-02-14 08:57:46 -08007479 // policy registered?
7480 final AudioPolicyProxy app = mAudioPolicies.get(pcb.asBinder());
7481 if (app == null) {
7482 Slog.w(TAG, errorMsg + " for pid " +
7483 + Binder.getCallingPid() + " / uid "
7484 + Binder.getCallingUid() + ", unregistered policy");
7485 return null;
7486 }
7487 return app;
7488 }
Jean-Michel Trivi0212be52014-11-24 14:43:10 -08007489
Jean-Michel Triviaf576a02018-02-14 08:57:46 -08007490 public int addMixForPolicy(AudioPolicyConfig policyConfig, IAudioPolicyCallback pcb) {
7491 if (DEBUG_AP) { Log.d(TAG, "addMixForPolicy for " + pcb.asBinder()
7492 + " with config:" + policyConfig); }
Jean-Michel Trivi0212be52014-11-24 14:43:10 -08007493 synchronized (mAudioPolicies) {
Jean-Michel Triviaf576a02018-02-14 08:57:46 -08007494 final AudioPolicyProxy app =
7495 checkUpdateForPolicy(pcb, "Cannot add AudioMix in audio policy");
7496 if (app == null){
7497 return AudioManager.ERROR;
7498 }
7499 app.addMixes(policyConfig.getMixes());
7500 }
7501 return AudioManager.SUCCESS;
7502 }
7503
7504 public int removeMixForPolicy(AudioPolicyConfig policyConfig, IAudioPolicyCallback pcb) {
7505 if (DEBUG_AP) { Log.d(TAG, "removeMixForPolicy for " + pcb.asBinder()
7506 + " with config:" + policyConfig); }
7507 synchronized (mAudioPolicies) {
7508 final AudioPolicyProxy app =
7509 checkUpdateForPolicy(pcb, "Cannot add AudioMix in audio policy");
7510 if (app == null) {
7511 return AudioManager.ERROR;
7512 }
7513 app.removeMixes(policyConfig.getMixes());
7514 }
7515 return AudioManager.SUCCESS;
7516 }
7517
7518 public int setFocusPropertiesForPolicy(int duckingBehavior, IAudioPolicyCallback pcb) {
7519 if (DEBUG_AP) Log.d(TAG, "setFocusPropertiesForPolicy() duck behavior=" + duckingBehavior
7520 + " policy " + pcb.asBinder());
7521 synchronized (mAudioPolicies) {
7522 final AudioPolicyProxy app =
7523 checkUpdateForPolicy(pcb, "Cannot change audio policy focus properties");
7524 if (app == null){
7525 return AudioManager.ERROR;
7526 }
Jean-Michel Trivi0212be52014-11-24 14:43:10 -08007527 if (!mAudioPolicies.containsKey(pcb.asBinder())) {
7528 Slog.e(TAG, "Cannot change audio policy focus properties, unregistered policy");
7529 return AudioManager.ERROR;
7530 }
Jean-Michel Trivi0212be52014-11-24 14:43:10 -08007531 if (duckingBehavior == AudioPolicy.FOCUS_POLICY_DUCKING_IN_POLICY) {
7532 // is there already one policy managing ducking?
Eric Laurent0867bed2015-05-20 14:49:08 -07007533 for (AudioPolicyProxy policy : mAudioPolicies.values()) {
Jean-Michel Trivi0212be52014-11-24 14:43:10 -08007534 if (policy.mFocusDuckBehavior == AudioPolicy.FOCUS_POLICY_DUCKING_IN_POLICY) {
7535 Slog.e(TAG, "Cannot change audio policy ducking behavior, already handled");
7536 return AudioManager.ERROR;
7537 }
7538 }
7539 }
7540 app.mFocusDuckBehavior = duckingBehavior;
7541 mMediaFocusControl.setDuckingInExtPolicyAvailable(
7542 duckingBehavior == AudioPolicy.FOCUS_POLICY_DUCKING_IN_POLICY);
7543 }
7544 return AudioManager.SUCCESS;
7545 }
7546
Jean-Michel Trivi610aa9b2018-01-27 15:42:42 -08007547 private final Object mExtVolumeControllerLock = new Object();
7548 private IAudioPolicyCallback mExtVolumeController;
7549 private void setExtVolumeController(IAudioPolicyCallback apc) {
7550 if (!mContext.getResources().getBoolean(
7551 com.android.internal.R.bool.config_handleVolumeKeysInWindowManager)) {
7552 Log.e(TAG, "Cannot set external volume controller: device not set for volume keys" +
7553 " handled in PhoneWindowManager");
7554 return;
7555 }
7556 synchronized (mExtVolumeControllerLock) {
7557 if (mExtVolumeController != null && !mExtVolumeController.asBinder().pingBinder()) {
7558 Log.e(TAG, "Cannot set external volume controller: existing controller");
7559 }
7560 mExtVolumeController = apc;
7561 }
7562 }
7563
Jean-Michel Trivi1b3541d2014-11-25 12:53:41 -08007564 private void dumpAudioPolicies(PrintWriter pw) {
7565 pw.println("\nAudio policies:");
7566 synchronized (mAudioPolicies) {
Eric Laurent0867bed2015-05-20 14:49:08 -07007567 for (AudioPolicyProxy policy : mAudioPolicies.values()) {
Jean-Michel Trivi1b3541d2014-11-25 12:53:41 -08007568 pw.println(policy.toLogFriendlyString());
7569 }
7570 }
7571 }
7572
Jean-Michel Trivi958876f2014-11-16 15:40:22 -08007573 //======================
Jean-Michel Trivid3c71f02015-12-07 11:59:31 -08007574 // Audio policy callbacks from AudioSystem for dynamic policies
Jean-Michel Trivi5a561092015-04-23 18:48:08 -07007575 //======================
7576 private final AudioSystem.DynamicPolicyCallback mDynPolicyCallback =
7577 new AudioSystem.DynamicPolicyCallback() {
7578 public void onDynamicPolicyMixStateUpdate(String regId, int state) {
7579 if (!TextUtils.isEmpty(regId)) {
7580 sendMsg(mAudioHandler, MSG_DYN_POLICY_MIX_STATE_UPDATE, SENDMSG_QUEUE,
7581 state /*arg1*/, 0 /*arg2 ignored*/, regId /*obj*/, 0 /*delay*/);
7582 }
7583 }
7584 };
7585
7586 private void onDynPolicyMixStateUpdate(String regId, int state) {
7587 if (DEBUG_AP) Log.d(TAG, "onDynamicPolicyMixStateUpdate("+ regId + ", " + state +")");
7588 synchronized (mAudioPolicies) {
7589 for (AudioPolicyProxy policy : mAudioPolicies.values()) {
7590 for (AudioMix mix : policy.getMixes()) {
7591 if (mix.getRegistration().equals(regId)) {
7592 try {
7593 policy.mPolicyCallback.notifyMixStateUpdate(regId, state);
7594 } catch (RemoteException e) {
7595 Log.e(TAG, "Can't call notifyMixStateUpdate() on IAudioPolicyCallback "
7596 + policy.mPolicyCallback.asBinder(), e);
7597 }
7598 return;
7599 }
7600 }
7601 }
7602 }
Jean-Michel Trivid3c71f02015-12-07 11:59:31 -08007603 }
Jean-Michel Trivi5a561092015-04-23 18:48:08 -07007604
Jean-Michel Trivid3c71f02015-12-07 11:59:31 -08007605 //======================
7606 // Audio policy callbacks from AudioSystem for recording configuration updates
7607 //======================
Jean-Michel Trivi66ffacf2017-02-04 17:25:31 -08007608 private final RecordingActivityMonitor mRecordMonitor;
Jean-Michel Trivid3c71f02015-12-07 11:59:31 -08007609
7610 public void registerRecordingCallback(IRecordingConfigDispatcher rcdb) {
Jean-Michel Trivi66ffacf2017-02-04 17:25:31 -08007611 final boolean isPrivileged =
7612 (PackageManager.PERMISSION_GRANTED == mContext.checkCallingPermission(
7613 android.Manifest.permission.MODIFY_AUDIO_ROUTING));
7614 mRecordMonitor.registerRecordingCallback(rcdb, isPrivileged);
Jean-Michel Trivid3c71f02015-12-07 11:59:31 -08007615 }
7616
7617 public void unregisterRecordingCallback(IRecordingConfigDispatcher rcdb) {
7618 mRecordMonitor.unregisterRecordingCallback(rcdb);
7619 }
7620
Jean-Michel Trivif04fab12016-05-19 10:42:35 -07007621 public List<AudioRecordingConfiguration> getActiveRecordingConfigurations() {
Jean-Michel Trivi66ffacf2017-02-04 17:25:31 -08007622 final boolean isPrivileged =
7623 (PackageManager.PERMISSION_GRANTED == mContext.checkCallingPermission(
7624 android.Manifest.permission.MODIFY_AUDIO_ROUTING));
7625 return mRecordMonitor.getActiveRecordingConfigurations(isPrivileged);
Jean-Michel Trivi5a561092015-04-23 18:48:08 -07007626 }
7627
Robin Lee7af9a742017-02-20 14:47:30 +00007628 public void disableRingtoneSync(final int userId) {
Andre Lago7bdc6d82016-09-22 18:00:41 +01007629 final int callingUserId = UserHandle.getCallingUserId();
Robin Lee7af9a742017-02-20 14:47:30 +00007630 if (callingUserId != userId) {
7631 mContext.enforceCallingOrSelfPermission(Manifest.permission.INTERACT_ACROSS_USERS_FULL,
7632 "disable sound settings syncing for another profile");
7633 }
Andre Lago7bdc6d82016-09-22 18:00:41 +01007634 final long token = Binder.clearCallingIdentity();
7635 try {
Robin Lee7af9a742017-02-20 14:47:30 +00007636 // Disable the sync setting so the profile uses its own sound settings.
7637 Settings.Secure.putIntForUser(mContentResolver, Settings.Secure.SYNC_PARENT_SOUNDS,
7638 0 /* false */, userId);
Andre Lago7bdc6d82016-09-22 18:00:41 +01007639 } finally {
7640 Binder.restoreCallingIdentity(token);
7641 }
7642 }
7643
Jean-Michel Trivi5a561092015-04-23 18:48:08 -07007644 //======================
Jean-Michel Trivi46e310b2017-01-04 15:58:02 -08007645 // Audio playback notification
Jean-Michel Trivi292a6a42016-12-01 08:32:15 -08007646 //======================
Eric Laurente5a351c2017-09-27 20:11:51 -07007647 private final PlaybackActivityMonitor mPlaybackMonitor;
Jean-Michel Trivi292a6a42016-12-01 08:32:15 -08007648
7649 public void registerPlaybackCallback(IPlaybackConfigDispatcher pcdb) {
Jean-Michel Trivi44a8f532017-01-02 14:36:43 -08007650 final boolean isPrivileged =
Jaewan Kim92dea332017-02-02 11:52:08 +09007651 (PackageManager.PERMISSION_GRANTED == mContext.checkCallingOrSelfPermission(
Jean-Michel Trivi292a6a42016-12-01 08:32:15 -08007652 android.Manifest.permission.MODIFY_AUDIO_ROUTING));
7653 mPlaybackMonitor.registerPlaybackCallback(pcdb, isPrivileged);
7654 }
7655
7656 public void unregisterPlaybackCallback(IPlaybackConfigDispatcher pcdb) {
7657 mPlaybackMonitor.unregisterPlaybackCallback(pcdb);
7658 }
7659
7660 public List<AudioPlaybackConfiguration> getActivePlaybackConfigurations() {
Jean-Michel Trivi44a8f532017-01-02 14:36:43 -08007661 final boolean isPrivileged =
Jaewan Kim92dea332017-02-02 11:52:08 +09007662 (PackageManager.PERMISSION_GRANTED == mContext.checkCallingOrSelfPermission(
Jean-Michel Trivi44a8f532017-01-02 14:36:43 -08007663 android.Manifest.permission.MODIFY_AUDIO_ROUTING));
7664 return mPlaybackMonitor.getActivePlaybackConfigurations(isPrivileged);
Jean-Michel Trivi292a6a42016-12-01 08:32:15 -08007665 }
7666
Jean-Michel Trivi44a8f532017-01-02 14:36:43 -08007667 public int trackPlayer(PlayerBase.PlayerIdCard pic) {
7668 return mPlaybackMonitor.trackPlayer(pic);
Jean-Michel Trivi292a6a42016-12-01 08:32:15 -08007669 }
7670
7671 public void playerAttributes(int piid, AudioAttributes attr) {
Jean-Michel Trivi46e310b2017-01-04 15:58:02 -08007672 mPlaybackMonitor.playerAttributes(piid, attr, Binder.getCallingUid());
Jean-Michel Trivi292a6a42016-12-01 08:32:15 -08007673 }
7674
7675 public void playerEvent(int piid, int event) {
Jean-Michel Trivi46e310b2017-01-04 15:58:02 -08007676 mPlaybackMonitor.playerEvent(piid, event, Binder.getCallingUid());
Jean-Michel Trivi292a6a42016-12-01 08:32:15 -08007677 }
7678
Jean-Michel Trivi3120059d2017-08-28 12:40:55 -07007679 public void playerHasOpPlayAudio(int piid, boolean hasOpPlayAudio) {
7680 mPlaybackMonitor.playerHasOpPlayAudio(piid, hasOpPlayAudio, Binder.getCallingUid());
7681 }
7682
Jean-Michel Trivi292a6a42016-12-01 08:32:15 -08007683 public void releasePlayer(int piid) {
Jean-Michel Trivi46e310b2017-01-04 15:58:02 -08007684 mPlaybackMonitor.releasePlayer(piid, Binder.getCallingUid());
Jean-Michel Trivi292a6a42016-12-01 08:32:15 -08007685 }
7686
7687 //======================
Jean-Michel Trivi958876f2014-11-16 15:40:22 -08007688 // Audio policy proxy
7689 //======================
Jean-Michel Trivi8fdb0d42014-07-16 19:08:37 -07007690 /**
Jean-Michel Trivi1b3541d2014-11-25 12:53:41 -08007691 * This internal class inherits from AudioPolicyConfig, each instance contains all the
7692 * mixes of an AudioPolicy and their configurations.
Jean-Michel Trivi8fdb0d42014-07-16 19:08:37 -07007693 */
7694 public class AudioPolicyProxy extends AudioPolicyConfig implements IBinder.DeathRecipient {
Jean-Michel Trivia8b6bd82014-07-01 09:48:46 -07007695 private static final String TAG = "AudioPolicyProxy";
Jean-Michel Trivi610aa9b2018-01-27 15:42:42 -08007696 final IAudioPolicyCallback mPolicyCallback;
7697 final boolean mHasFocusListener;
7698 final boolean mIsVolumeController;
Jean-Michel Trivi0212be52014-11-24 14:43:10 -08007699 /**
7700 * Audio focus ducking behavior for an audio policy.
7701 * This variable reflects the value that was successfully set in
7702 * {@link AudioService#setFocusPropertiesForPolicy(int, IAudioPolicyCallback)}. This
7703 * implies that a value of FOCUS_POLICY_DUCKING_IN_POLICY means the corresponding policy
7704 * is handling ducking for audio focus.
7705 */
7706 int mFocusDuckBehavior = AudioPolicy.FOCUS_POLICY_DUCKING_DEFAULT;
Jean-Michel Trivi126cf032017-04-02 23:19:02 -07007707 boolean mIsFocusPolicy = false;
Jean-Michel Trivi0212be52014-11-24 14:43:10 -08007708
7709 AudioPolicyProxy(AudioPolicyConfig config, IAudioPolicyCallback token,
Jean-Michel Trivi610aa9b2018-01-27 15:42:42 -08007710 boolean hasFocusListener, boolean isFocusPolicy, boolean isVolumeController) {
Jean-Michel Trivi8fdb0d42014-07-16 19:08:37 -07007711 super(config);
Jean-Michel Trivi1b3541d2014-11-25 12:53:41 -08007712 setRegistration(new String(config.hashCode() + ":ap:" + mAudioPolicyCounter++));
Jean-Michel Trivi5a561092015-04-23 18:48:08 -07007713 mPolicyCallback = token;
Jean-Michel Trivi0212be52014-11-24 14:43:10 -08007714 mHasFocusListener = hasFocusListener;
Jean-Michel Trivi610aa9b2018-01-27 15:42:42 -08007715 mIsVolumeController = isVolumeController;
Jean-Michel Trivi0212be52014-11-24 14:43:10 -08007716 if (mHasFocusListener) {
Jean-Michel Trivi5a561092015-04-23 18:48:08 -07007717 mMediaFocusControl.addFocusFollower(mPolicyCallback);
Jean-Michel Trivi126cf032017-04-02 23:19:02 -07007718 // can only ever be true if there is a focus listener
7719 if (isFocusPolicy) {
7720 mIsFocusPolicy = true;
7721 mMediaFocusControl.setFocusPolicy(mPolicyCallback);
7722 }
Jean-Michel Trivi0212be52014-11-24 14:43:10 -08007723 }
Jean-Michel Trivi610aa9b2018-01-27 15:42:42 -08007724 if (mIsVolumeController) {
7725 setExtVolumeController(mPolicyCallback);
7726 }
Eric Laurent7f5eb9f2014-12-01 19:36:30 -08007727 connectMixes();
Jean-Michel Trivia8b6bd82014-07-01 09:48:46 -07007728 }
7729
7730 public void binderDied() {
7731 synchronized (mAudioPolicies) {
Jean-Michel Trivi5a561092015-04-23 18:48:08 -07007732 Log.i(TAG, "audio policy " + mPolicyCallback + " died");
Jean-Michel Trivi0212be52014-11-24 14:43:10 -08007733 release();
Jean-Michel Trivi5a561092015-04-23 18:48:08 -07007734 mAudioPolicies.remove(mPolicyCallback.asBinder());
Jean-Michel Trivi8fdb0d42014-07-16 19:08:37 -07007735 }
Jean-Michel Trivi610aa9b2018-01-27 15:42:42 -08007736 if (mIsVolumeController) {
7737 synchronized (mExtVolumeControllerLock) {
7738 mExtVolumeController = null;
7739 }
7740 }
Jean-Michel Trivi8fdb0d42014-07-16 19:08:37 -07007741 }
7742
Jean-Michel Trivi0212be52014-11-24 14:43:10 -08007743 String getRegistrationId() {
Jean-Michel Trivi1b3541d2014-11-25 12:53:41 -08007744 return getRegistration();
Jean-Michel Trivi8fdb0d42014-07-16 19:08:37 -07007745 }
7746
Jean-Michel Trivi0212be52014-11-24 14:43:10 -08007747 void release() {
Jean-Michel Trivi126cf032017-04-02 23:19:02 -07007748 if (mIsFocusPolicy) {
7749 mMediaFocusControl.unsetFocusPolicy(mPolicyCallback);
7750 }
Jean-Michel Trivi0212be52014-11-24 14:43:10 -08007751 if (mFocusDuckBehavior == AudioPolicy.FOCUS_POLICY_DUCKING_IN_POLICY) {
7752 mMediaFocusControl.setDuckingInExtPolicyAvailable(false);
7753 }
7754 if (mHasFocusListener) {
Jean-Michel Trivi5a561092015-04-23 18:48:08 -07007755 mMediaFocusControl.removeFocusFollower(mPolicyCallback);
Jean-Michel Trivi0212be52014-11-24 14:43:10 -08007756 }
Eric Laurent66b69672018-01-26 18:30:51 -08007757 final long identity = Binder.clearCallingIdentity();
Eric Laurent7f5eb9f2014-12-01 19:36:30 -08007758 AudioSystem.registerPolicyMixes(mMixes, false);
Eric Laurent66b69672018-01-26 18:30:51 -08007759 Binder.restoreCallingIdentity(identity);
Jean-Michel Trivi8fdb0d42014-07-16 19:08:37 -07007760 }
7761
Jean-Michel Trivi7db2d8f2018-03-06 10:30:59 -08007762 boolean hasMixAffectingUsage(int usage) {
7763 for (AudioMix mix : mMixes) {
7764 if (mix.isAffectingUsage(usage)) {
7765 return true;
7766 }
7767 }
7768 return false;
7769 }
7770
Jean-Michel Triviaf576a02018-02-14 08:57:46 -08007771 void addMixes(@NonNull ArrayList<AudioMix> mixes) {
7772 // TODO optimize to not have to unregister the mixes already in place
7773 synchronized (mMixes) {
7774 AudioSystem.registerPolicyMixes(mMixes, false);
7775 this.add(mixes);
7776 AudioSystem.registerPolicyMixes(mMixes, true);
7777 }
7778 }
7779
7780 void removeMixes(@NonNull ArrayList<AudioMix> mixes) {
7781 // TODO optimize to not have to unregister the mixes already in place
7782 synchronized (mMixes) {
7783 AudioSystem.registerPolicyMixes(mMixes, false);
7784 this.remove(mixes);
7785 AudioSystem.registerPolicyMixes(mMixes, true);
7786 }
7787 }
7788
Eric Laurent7f5eb9f2014-12-01 19:36:30 -08007789 void connectMixes() {
Eric Laurent66b69672018-01-26 18:30:51 -08007790 final long identity = Binder.clearCallingIdentity();
Eric Laurent7f5eb9f2014-12-01 19:36:30 -08007791 AudioSystem.registerPolicyMixes(mMixes, true);
Eric Laurent66b69672018-01-26 18:30:51 -08007792 Binder.restoreCallingIdentity(identity);
Jean-Michel Trivia8b6bd82014-07-01 09:48:46 -07007793 }
7794 };
7795
Jean-Michel Trivi126cf032017-04-02 23:19:02 -07007796 //======================
7797 // Audio policy: focus
7798 //======================
7799 /** */
7800 public int dispatchFocusChange(AudioFocusInfo afi, int focusChange, IAudioPolicyCallback pcb) {
Jean-Michel Trivie2d8aae2018-01-30 15:09:47 -08007801 if (afi == null) {
7802 throw new IllegalArgumentException("Illegal null AudioFocusInfo");
7803 }
7804 if (pcb == null) {
7805 throw new IllegalArgumentException("Illegal null AudioPolicy callback");
7806 }
Jean-Michel Trivi126cf032017-04-02 23:19:02 -07007807 synchronized (mAudioPolicies) {
7808 if (!mAudioPolicies.containsKey(pcb.asBinder())) {
7809 throw new IllegalStateException("Unregistered AudioPolicy for focus dispatch");
7810 }
7811 return mMediaFocusControl.dispatchFocusChange(afi, focusChange);
7812 }
7813 }
7814
Jean-Michel Trivie2d8aae2018-01-30 15:09:47 -08007815 public void setFocusRequestResultFromExtPolicy(AudioFocusInfo afi, int requestResult,
7816 IAudioPolicyCallback pcb) {
7817 if (afi == null) {
7818 throw new IllegalArgumentException("Illegal null AudioFocusInfo");
7819 }
7820 if (pcb == null) {
7821 throw new IllegalArgumentException("Illegal null AudioPolicy callback");
7822 }
7823 synchronized (mAudioPolicies) {
7824 if (!mAudioPolicies.containsKey(pcb.asBinder())) {
7825 throw new IllegalStateException("Unregistered AudioPolicy for external focus");
7826 }
7827 mMediaFocusControl.setFocusRequestResultFromExtPolicy(afi, requestResult);
7828 }
7829 }
7830
7831
Jean-Michel Trivi126cf032017-04-02 23:19:02 -07007832 //======================
Eric Laurent1d3cdce2018-01-20 10:31:21 -08007833 // Audioserver state displatch
7834 //======================
7835 private class AsdProxy implements IBinder.DeathRecipient {
7836 private final IAudioServerStateDispatcher mAsd;
7837
7838 AsdProxy(IAudioServerStateDispatcher asd) {
7839 mAsd = asd;
7840 }
7841
7842 public void binderDied() {
7843 synchronized (mAudioServerStateListeners) {
7844 mAudioServerStateListeners.remove(mAsd.asBinder());
7845 }
7846 }
7847
7848 IAudioServerStateDispatcher callback() {
7849 return mAsd;
7850 }
7851 }
7852
7853 private HashMap<IBinder, AsdProxy> mAudioServerStateListeners =
7854 new HashMap<IBinder, AsdProxy>();
7855
7856 private void checkMonitorAudioServerStatePermission() {
7857 if (!(mContext.checkCallingOrSelfPermission(
7858 android.Manifest.permission.MODIFY_PHONE_STATE) ==
7859 PackageManager.PERMISSION_GRANTED ||
7860 mContext.checkCallingOrSelfPermission(
7861 android.Manifest.permission.MODIFY_AUDIO_ROUTING) ==
7862 PackageManager.PERMISSION_GRANTED)) {
7863 throw new SecurityException("Not allowed to monitor audioserver state");
7864 }
7865 }
7866
7867 public void registerAudioServerStateDispatcher(IAudioServerStateDispatcher asd) {
7868 checkMonitorAudioServerStatePermission();
7869 synchronized (mAudioServerStateListeners) {
7870 if (mAudioServerStateListeners.containsKey(asd.asBinder())) {
7871 Slog.w(TAG, "Cannot re-register audio server state dispatcher");
7872 return;
7873 }
7874 AsdProxy asdp = new AsdProxy(asd);
7875 try {
7876 asd.asBinder().linkToDeath(asdp, 0/*flags*/);
7877 } catch (RemoteException e) {
7878
7879 }
7880 mAudioServerStateListeners.put(asd.asBinder(), asdp);
7881 }
7882 }
7883
7884 public void unregisterAudioServerStateDispatcher(IAudioServerStateDispatcher asd) {
7885 checkMonitorAudioServerStatePermission();
7886 synchronized (mAudioServerStateListeners) {
7887 AsdProxy asdp = mAudioServerStateListeners.remove(asd.asBinder());
7888 if (asdp == null) {
7889 Slog.w(TAG, "Trying to unregister unknown audioserver state dispatcher for pid "
7890 + Binder.getCallingPid() + " / uid " + Binder.getCallingUid());
7891 return;
7892 } else {
7893 asd.asBinder().unlinkToDeath(asdp, 0/*flags*/);
7894 }
7895 }
7896 }
7897
7898 public boolean isAudioServerRunning() {
7899 checkMonitorAudioServerStatePermission();
7900 return (AudioSystem.checkAudioFlinger() == AudioSystem.AUDIO_STATUS_OK);
7901 }
7902
7903 //======================
Jean-Michel Trivi126cf032017-04-02 23:19:02 -07007904 // misc
7905 //======================
Jean-Michel Triviaf576a02018-02-14 08:57:46 -08007906 private final HashMap<IBinder, AudioPolicyProxy> mAudioPolicies =
Jean-Michel Trivia8b6bd82014-07-01 09:48:46 -07007907 new HashMap<IBinder, AudioPolicyProxy>();
Jean-Michel Triviaf576a02018-02-14 08:57:46 -08007908 @GuardedBy("mAudioPolicies")
7909 private int mAudioPolicyCounter = 0;
Phil Burkac0f7042016-02-24 12:19:08 -08007910}