blob: 51f1af8671bf9c977dc949f6c9fe1c4565c6a607 [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;
Shuhei Miyazaki89091ba2018-01-11 18:17:04 +0900718 }
719
720 int defaultCallVolume = SystemProperties.getInt("ro.config.vc_call_vol_default", -1);
721 if (defaultCallVolume != -1 &&
722 defaultCallVolume <= MAX_STREAM_VOLUME[AudioSystem.STREAM_VOICE_CALL] &&
723 defaultCallVolume >= MIN_STREAM_VOLUME[AudioSystem.STREAM_VOICE_CALL]) {
724 AudioSystem.DEFAULT_STREAM_VOLUME[AudioSystem.STREAM_VOICE_CALL] = defaultCallVolume;
725 } else {
Eric Laurent403bd342017-07-11 16:21:44 -0700726 AudioSystem.DEFAULT_STREAM_VOLUME[AudioSystem.STREAM_VOICE_CALL] =
727 (maxCallVolume * 3) / 4;
Eric Laurent91377de2014-10-10 15:24:04 -0700728 }
Eric Laurent403bd342017-07-11 16:21:44 -0700729
730 int maxMusicVolume = SystemProperties.getInt("ro.config.media_vol_steps", -1);
731 if (maxMusicVolume != -1) {
732 MAX_STREAM_VOLUME[AudioSystem.STREAM_MUSIC] = maxMusicVolume;
733 }
734
735 int defaultMusicVolume = SystemProperties.getInt("ro.config.media_vol_default", -1);
736 if (defaultMusicVolume != -1 &&
Shuhei Miyazaki89091ba2018-01-11 18:17:04 +0900737 defaultMusicVolume <= MAX_STREAM_VOLUME[AudioSystem.STREAM_MUSIC] &&
738 defaultMusicVolume >= MIN_STREAM_VOLUME[AudioSystem.STREAM_MUSIC]) {
Eric Laurent403bd342017-07-11 16:21:44 -0700739 AudioSystem.DEFAULT_STREAM_VOLUME[AudioSystem.STREAM_MUSIC] = defaultMusicVolume;
740 } else {
Hank Freund45926dc2015-12-11 10:50:45 -0800741 if (isPlatformTelevision()) {
Eric Laurent403bd342017-07-11 16:21:44 -0700742 AudioSystem.DEFAULT_STREAM_VOLUME[AudioSystem.STREAM_MUSIC] =
743 MAX_STREAM_VOLUME[AudioSystem.STREAM_MUSIC] / 4;
Hank Freund45926dc2015-12-11 10:50:45 -0800744 } else {
Eric Laurent403bd342017-07-11 16:21:44 -0700745 AudioSystem.DEFAULT_STREAM_VOLUME[AudioSystem.STREAM_MUSIC] =
746 MAX_STREAM_VOLUME[AudioSystem.STREAM_MUSIC] / 3;
Hank Freund45926dc2015-12-11 10:50:45 -0800747 }
Eric Laurent91377de2014-10-10 15:24:04 -0700748 }
Jared Suttles59820132009-08-13 21:50:52 -0500749
Chris Kuiper09b6c212018-01-03 22:22:13 -0800750 int maxAlarmVolume = SystemProperties.getInt("ro.config.alarm_vol_steps", -1);
751 if (maxAlarmVolume != -1) {
752 MAX_STREAM_VOLUME[AudioSystem.STREAM_ALARM] = maxAlarmVolume;
753 }
754
755 int defaultAlarmVolume = SystemProperties.getInt("ro.config.alarm_vol_default", -1);
756 if (defaultAlarmVolume != -1 &&
757 defaultAlarmVolume <= MAX_STREAM_VOLUME[AudioSystem.STREAM_ALARM]) {
758 AudioSystem.DEFAULT_STREAM_VOLUME[AudioSystem.STREAM_ALARM] = defaultAlarmVolume;
759 } else {
760 // Default is 6 out of 7 (default maximum), so scale accordingly.
761 AudioSystem.DEFAULT_STREAM_VOLUME[AudioSystem.STREAM_ALARM] =
762 6 * MAX_STREAM_VOLUME[AudioSystem.STREAM_ALARM] / 7;
763 }
764
765 int maxSystemVolume = SystemProperties.getInt("ro.config.system_vol_steps", -1);
766 if (maxSystemVolume != -1) {
767 MAX_STREAM_VOLUME[AudioSystem.STREAM_SYSTEM] = maxSystemVolume;
768 }
769
770 int defaultSystemVolume = SystemProperties.getInt("ro.config.system_vol_default", -1);
771 if (defaultSystemVolume != -1 &&
772 defaultSystemVolume <= MAX_STREAM_VOLUME[AudioSystem.STREAM_SYSTEM]) {
773 AudioSystem.DEFAULT_STREAM_VOLUME[AudioSystem.STREAM_SYSTEM] = defaultSystemVolume;
774 } else {
775 // Default is to use maximum.
776 AudioSystem.DEFAULT_STREAM_VOLUME[AudioSystem.STREAM_SYSTEM] =
777 MAX_STREAM_VOLUME[AudioSystem.STREAM_SYSTEM];
778 }
779
Jean-Michel Trivif2b0c112012-07-09 11:59:11 -0700780 sSoundEffectVolumeDb = context.getResources().getInteger(
Jean-Michel Trivic55b3932012-06-05 11:57:59 -0700781 com.android.internal.R.integer.config_soundEffectVolumeDb);
Eric Laurent25101b02011-02-02 09:33:30 -0800782
Eric Laurentc42ac9d2009-07-29 08:53:03 -0700783 mForcedUseForComm = AudioSystem.FORCE_NONE;
Eric Laurentdd45d012012-10-08 09:04:34 -0700784
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800785 createAudioSystemThread();
Eric Laurentdd45d012012-10-08 09:04:34 -0700786
Eric Laurentdfb881f2013-07-18 14:41:39 -0700787 AudioSystem.setErrorCallback(mAudioSystemCallback);
788
John Spurlock5e783732015-02-19 10:28:59 -0500789 boolean cameraSoundForced = readCameraSoundForced();
Eric Laurentdd45d012012-10-08 09:04:34 -0700790 mCameraSoundForced = new Boolean(cameraSoundForced);
791 sendMsg(mAudioHandler,
792 MSG_SET_FORCE_USE,
793 SENDMSG_QUEUE,
794 AudioSystem.FOR_SYSTEM,
795 cameraSoundForced ?
796 AudioSystem.FORCE_SYSTEM_ENFORCED : AudioSystem.FORCE_NONE,
Jean-Michel Trivi011f39e2017-08-19 18:08:06 -0700797 new String("AudioService ctor"),
Eric Laurentdd45d012012-10-08 09:04:34 -0700798 0);
799
Eric Laurent05274f32012-11-29 12:48:18 -0800800 mSafeMediaVolumeState = new Integer(Settings.Global.getInt(mContentResolver,
801 Settings.Global.AUDIO_SAFE_VOLUME_STATE,
802 SAFE_MEDIA_VOLUME_NOT_CONFIGURED));
803 // The default safe volume index read here will be replaced by the actual value when
804 // the mcc is read by onConfigureSafeVolume()
805 mSafeMediaVolumeIndex = mContext.getResources().getInteger(
806 com.android.internal.R.integer.config_safe_media_volume_index) * 10;
807
Eric Laurent83a017b2013-03-19 18:15:31 -0700808 mUseFixedVolume = mContext.getResources().getBoolean(
809 com.android.internal.R.bool.config_useFixedVolume);
810
Eric Laurent24e0d9b2013-10-03 18:15:07 -0700811 // must be called before readPersistedSettings() which needs a valid mStreamVolumeAlias[]
812 // array initialized by updateStreamVolumeAlias()
John Spurlock90874332015-03-10 16:00:54 -0400813 updateStreamVolumeAlias(false /*updateVolumes*/, TAG);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800814 readPersistedSettings();
Eric Laurentc0232482016-03-15 18:19:23 -0700815 readUserRestrictions();
Eric Laurentc1d41662011-07-19 11:21:13 -0700816 mSettingsObserver = new SettingsObserver();
Eric Laurenta553c252009-07-17 12:17:14 -0700817 createStreamStates();
Eric Laurent9f103de2011-09-08 15:04:23 -0700818
Eric Laurentb378a13a2017-07-11 14:08:11 -0700819 // mSafeUsbMediaVolumeIndex must be initialized after createStreamStates() because it
820 // relies on audio policy having correct ranges for volume indexes.
821 mSafeUsbMediaVolumeIndex = getSafeUsbMediaVolumeIndex();
822
Eric Laurente5a351c2017-09-27 20:11:51 -0700823 mPlaybackMonitor =
824 new PlaybackActivityMonitor(context, MAX_STREAM_VOLUME[AudioSystem.STREAM_ALARM]);
825
Jean-Michel Trivi99489cc2017-01-25 19:08:49 -0800826 mMediaFocusControl = new MediaFocusControl(mContext, mPlaybackMonitor);
John Spurlockb6e19e32015-03-10 21:33:44 -0400827
Jean-Michel Trivi66ffacf2017-02-04 17:25:31 -0800828 mRecordMonitor = new RecordingActivityMonitor(mContext);
829
Glenn Kastenfd116ad2013-07-12 17:10:39 -0700830 readAndSetLowRamDevice();
Eric Laurent3891c4c2010-04-20 09:40:57 -0700831
832 // Call setRingerModeInt() to apply correct mute
833 // state on streams affected by ringer mode.
Beverlyd6964762018-02-16 14:07:03 -0500834 mRingerAndZenModeMutedStreams = 0;
John Spurlock661f2cf2014-11-17 10:29:10 -0500835 setRingerModeInt(getRingerModeInternal(), false);
Eric Laurent3891c4c2010-04-20 09:40:57 -0700836
Eric Laurenta553c252009-07-17 12:17:14 -0700837 // Register for device connection intent broadcasts.
838 IntentFilter intentFilter =
Eric Laurentb1fbaac2012-05-29 09:24:28 -0700839 new IntentFilter(BluetoothHeadset.ACTION_AUDIO_STATE_CHANGED);
Jack He8dd33942018-01-17 15:45:12 -0800840 intentFilter.addAction(BluetoothHeadset.ACTION_ACTIVE_DEVICE_CHANGED);
Jaikumar Ganesh82aa7f02010-09-27 17:05:10 -0700841 intentFilter.addAction(Intent.ACTION_DOCK_EVENT);
Eric Laurent950e8cb2011-10-13 08:57:54 -0700842 intentFilter.addAction(Intent.ACTION_SCREEN_ON);
843 intentFilter.addAction(Intent.ACTION_SCREEN_OFF);
Eric Laurentbc0fab1f2012-09-19 11:24:41 -0700844 intentFilter.addAction(Intent.ACTION_USER_SWITCHED);
Fyodor Kupolovb5013302015-04-17 17:59:14 -0700845 intentFilter.addAction(Intent.ACTION_USER_BACKGROUND);
846 intentFilter.addAction(Intent.ACTION_USER_FOREGROUND);
Paul McLeanc837a452014-04-09 09:04:43 -0700847 intentFilter.addAction(UsbManager.ACTION_USB_DEVICE_ATTACHED);
Eric Laurentb70b78a2016-01-13 19:16:04 -0800848 intentFilter.addAction(BluetoothAdapter.ACTION_STATE_CHANGED);
Jean-Michel Trivif26f0172012-04-25 16:23:20 -0700849
Eric Laurentd640bd32012-09-28 18:01:48 -0700850 intentFilter.addAction(Intent.ACTION_CONFIGURATION_CHANGED);
Jean-Michel Trivibb6f8712013-05-23 15:02:41 -0700851 mMonitorRotation = SystemProperties.getBoolean("ro.audio.monitorRotation", false);
852 if (mMonitorRotation) {
Jean-Michel Trivi24806db2015-10-01 15:00:59 -0700853 RotationHelper.init(mContext, mAudioHandler);
Jean-Michel Trivibb6f8712013-05-23 15:02:41 -0700854 }
Jean-Michel Trivif26f0172012-04-25 16:23:20 -0700855
Marco Nelissenfb6df0b2017-02-15 15:25:24 -0800856 intentFilter.addAction(AudioEffect.ACTION_OPEN_AUDIO_EFFECT_CONTROL_SESSION);
857 intentFilter.addAction(AudioEffect.ACTION_CLOSE_AUDIO_EFFECT_CONTROL_SESSION);
858
Fyodor Kupolovb5013302015-04-17 17:59:14 -0700859 context.registerReceiverAsUser(mReceiver, UserHandle.ALL, intentFilter, null, null);
Jared Suttles59820132009-08-13 21:50:52 -0500860
RoboErik0dac35a2014-08-12 15:48:49 -0700861 LocalServices.addService(AudioManagerInternal.class, new AudioServiceInternal());
Makoto Onukid45a4a22015-11-02 17:17:38 -0800862
863 mUserManagerInternal.addUserRestrictionsListener(mUserRestrictionsListener);
Jean-Michel Trivid3c71f02015-12-07 11:59:31 -0800864
865 mRecordMonitor.initMonitor();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800866 }
867
Eric Laurent4a5eeb92014-05-06 10:49:04 -0700868 public void systemReady() {
869 sendMsg(mAudioHandler, MSG_SYSTEM_READY, SENDMSG_QUEUE,
870 0, 0, null, 0);
Dianne Hackborn3e3600e2017-08-31 11:15:26 -0700871 if (false) {
872 // This is turned off for now, because it is racy and thus causes apps to break.
873 // Currently banning a uid means that if an app tries to start playing an audio
874 // stream, that will be preventing, and unbanning it will not allow that stream
875 // to resume. However these changes in uid state are racy with what the app is doing,
876 // so that after taking a process out of the cached state we can't guarantee that
877 // we will unban the uid before the app actually tries to start playing audio.
878 // (To do that, the activity manager would need to wait until it knows for sure
879 // that the ban has been removed, before telling the app to do whatever it is
880 // supposed to do that caused it to go out of the cached state.)
881 try {
882 ActivityManager.getService().registerUidObserver(mUidObserver,
883 ActivityManager.UID_OBSERVER_CACHED | ActivityManager.UID_OBSERVER_GONE,
884 ActivityManager.PROCESS_STATE_UNKNOWN, null);
885 } catch (RemoteException e) {
886 // ignored; both services live in system_server
887 }
Dianne Hackborn3e99f652017-07-05 16:33:56 -0700888 }
Eric Laurent4a5eeb92014-05-06 10:49:04 -0700889 }
890
891 public void onSystemReady() {
892 mSystemReady = true;
893 sendMsg(mAudioHandler, MSG_LOAD_SOUND_EFFECTS, SENDMSG_QUEUE,
894 0, 0, null, 0);
895
Eric Laurent4a5eeb92014-05-06 10:49:04 -0700896 mScoConnectionState = AudioManager.SCO_AUDIO_STATE_ERROR;
897 resetBluetoothSco();
898 getBluetoothHeadset();
899 //FIXME: this is to maintain compatibility with deprecated intent
900 // AudioManager.ACTION_SCO_AUDIO_STATE_CHANGED. Remove when appropriate.
901 Intent newIntent = new Intent(AudioManager.ACTION_SCO_AUDIO_STATE_CHANGED);
902 newIntent.putExtra(AudioManager.EXTRA_SCO_AUDIO_STATE,
903 AudioManager.SCO_AUDIO_STATE_DISCONNECTED);
904 sendStickyBroadcastToAll(newIntent);
905
906 BluetoothAdapter adapter = BluetoothAdapter.getDefaultAdapter();
907 if (adapter != null) {
908 adapter.getProfileProxy(mContext, mBluetoothProfileServiceListener,
909 BluetoothProfile.A2DP);
Jakub Pawlowskif9570f32018-02-21 17:15:12 -0800910 adapter.getProfileProxy(mContext, mBluetoothProfileServiceListener,
911 BluetoothProfile.HEARING_AID);
Eric Laurent4a5eeb92014-05-06 10:49:04 -0700912 }
913
Jeff Sharkey73ea0ae2016-08-10 17:30:38 -0600914 if (mContext.getPackageManager().hasSystemFeature(PackageManager.FEATURE_HDMI_CEC)) {
915 mHdmiManager = mContext.getSystemService(HdmiControlManager.class);
Eric Laurent212532b2014-07-21 15:43:18 -0700916 synchronized (mHdmiManager) {
917 mHdmiTvClient = mHdmiManager.getTvClient();
Jungshik Jangc9ff9682014-09-15 17:41:06 +0900918 if (mHdmiTvClient != null) {
919 mFixedVolumeDevices &= ~AudioSystem.DEVICE_ALL_HDMI_SYSTEM_AUDIO_AND_SPEAKER;
920 }
Eric Laurent212532b2014-07-21 15:43:18 -0700921 mHdmiPlaybackClient = mHdmiManager.getPlaybackClient();
922 mHdmiCecSink = false;
923 }
924 }
Wonsik Kim7f4342e2014-07-20 23:04:59 +0900925
Julia Reynolds48034f82016-03-09 10:15:16 -0500926 mNm = (NotificationManager) mContext.getSystemService(Context.NOTIFICATION_SERVICE);
927
Eric Laurent4a5eeb92014-05-06 10:49:04 -0700928 sendMsg(mAudioHandler,
929 MSG_CONFIGURE_SAFE_MEDIA_VOLUME_FORCED,
930 SENDMSG_REPLACE,
931 0,
932 0,
John Spurlock90874332015-03-10 16:00:54 -0400933 TAG,
Eric Laurent03332ab2017-02-09 18:29:15 -0800934 SystemProperties.getBoolean("audio.safemedia.bypass", false) ?
935 0 : SAFE_VOLUME_CONFIGURE_TIMEOUT_MS);
Jean-Michel Trivi873cc452014-09-11 17:25:09 -0700936
Jean-Michel Trivicfa55532017-01-18 11:17:51 -0800937 initA11yMonitoring();
Eric Laurent0867bed2015-05-20 14:49:08 -0700938 onIndicateSystemReady();
939 }
940
941 void onIndicateSystemReady() {
942 if (AudioSystem.systemReady() == AudioSystem.SUCCESS) {
943 return;
944 }
945 sendMsg(mAudioHandler,
946 MSG_INDICATE_SYSTEM_READY,
947 SENDMSG_REPLACE,
948 0,
949 0,
950 null,
951 INDICATE_SYSTEM_READY_RETRY_DELAY_MS);
952 }
953
Andy Hunged0ea402015-10-30 14:11:46 -0700954 public void onAudioServerDied() {
Eric Laurent0867bed2015-05-20 14:49:08 -0700955 if (!mSystemReady ||
956 (AudioSystem.checkAudioFlinger() != AudioSystem.AUDIO_STATUS_OK)) {
Andy Hunged0ea402015-10-30 14:11:46 -0700957 Log.e(TAG, "Audioserver died.");
958 sendMsg(mAudioHandler, MSG_AUDIO_SERVER_DIED, SENDMSG_NOOP, 0, 0,
Eric Laurent0867bed2015-05-20 14:49:08 -0700959 null, 500);
960 return;
961 }
Andy Hunged0ea402015-10-30 14:11:46 -0700962 Log.e(TAG, "Audioserver started.");
Eric Laurent0867bed2015-05-20 14:49:08 -0700963
964 // indicate to audio HAL that we start the reconfiguration phase after a media
965 // server crash
966 // Note that we only execute this when the media server
967 // process restarts after a crash, not the first time it is started.
968 AudioSystem.setParameters("restarting=true");
969
970 readAndSetLowRamDevice();
971
972 // Restore device connection states
973 synchronized (mConnectedDevices) {
974 for (int i = 0; i < mConnectedDevices.size(); i++) {
975 DeviceListSpec spec = mConnectedDevices.valueAt(i);
976 AudioSystem.setDeviceConnectionState(
977 spec.mDeviceType,
978 AudioSystem.DEVICE_STATE_AVAILABLE,
979 spec.mDeviceAddress,
980 spec.mDeviceName);
981 }
982 }
983 // Restore call state
Jean-Michel Trivi011f39e2017-08-19 18:08:06 -0700984 if (AudioSystem.setPhoneState(mMode) == AudioSystem.AUDIO_STATUS_OK) {
985 mModeLogger.log(new AudioEventLogger.StringEvent(
986 "onAudioServerDied causes setPhoneState(" + AudioSystem.modeToString(mMode) + ")"));
987 }
Eric Laurent0867bed2015-05-20 14:49:08 -0700988
Jean-Michel Trivi011f39e2017-08-19 18:08:06 -0700989 // Restore forced usage for communications and record
990 mForceUseLogger.log(new ForceUseEvent(AudioSystem.FOR_COMMUNICATION, mForcedUseForComm,
991 "onAudioServerDied"));
Eric Laurent0867bed2015-05-20 14:49:08 -0700992 AudioSystem.setForceUse(AudioSystem.FOR_COMMUNICATION, mForcedUseForComm);
Jean-Michel Trivi011f39e2017-08-19 18:08:06 -0700993 mForceUseLogger.log(new ForceUseEvent(AudioSystem.FOR_RECORD, mForcedUseForComm,
994 "onAudioServerDied"));
Eric Laurent0867bed2015-05-20 14:49:08 -0700995 AudioSystem.setForceUse(AudioSystem.FOR_RECORD, mForcedUseForComm);
Jean-Michel Trivi8719a1d2017-11-06 11:52:51 -0800996 final int forSys;
997 synchronized (mSettingsLock) {
998 forSys = mCameraSoundForced ?
999 AudioSystem.FORCE_SYSTEM_ENFORCED : AudioSystem.FORCE_NONE;
1000 }
Jean-Michel Trivi011f39e2017-08-19 18:08:06 -07001001 mForceUseLogger.log(new ForceUseEvent(AudioSystem.FOR_SYSTEM, forSys,
1002 "onAudioServerDied"));
1003 AudioSystem.setForceUse(AudioSystem.FOR_SYSTEM, forSys);
Eric Laurent0867bed2015-05-20 14:49:08 -07001004
1005 // Restore stream volumes
1006 int numStreamTypes = AudioSystem.getNumStreamTypes();
1007 for (int streamType = numStreamTypes - 1; streamType >= 0; streamType--) {
1008 VolumeStreamState streamState = mStreamStates[streamType];
Eric Laurente4381ec2015-10-29 17:52:48 -07001009 AudioSystem.initStreamVolume(
1010 streamType, streamState.mIndexMin / 10, streamState.mIndexMax / 10);
Eric Laurent0867bed2015-05-20 14:49:08 -07001011
1012 streamState.applyAllVolumes();
1013 }
1014
Andy Hungf04b84d2015-12-18 17:33:27 -08001015 // Restore mono mode
Andy Hung7b98e9a2016-02-25 18:34:50 -08001016 updateMasterMono(mContentResolver);
Andy Hungf04b84d2015-12-18 17:33:27 -08001017
Eric Laurent0867bed2015-05-20 14:49:08 -07001018 // Restore ringer mode
1019 setRingerModeInt(getRingerModeInternal(), false);
1020
Mikhail Naganovb668bc62018-02-13 13:46:38 -08001021 // Reset device rotation (if monitored for this device)
Eric Laurent0867bed2015-05-20 14:49:08 -07001022 if (mMonitorRotation) {
Jean-Michel Trivi24806db2015-10-01 15:00:59 -07001023 RotationHelper.updateOrientation();
Eric Laurent0867bed2015-05-20 14:49:08 -07001024 }
1025
Sungsoocf09fe62016-09-28 16:21:48 +09001026 synchronized (mBluetoothA2dpEnabledLock) {
Jean-Michel Trivi011f39e2017-08-19 18:08:06 -07001027 final int forMed = mBluetoothA2dpEnabled ?
1028 AudioSystem.FORCE_NONE : AudioSystem.FORCE_NO_BT_A2DP;
1029 mForceUseLogger.log(new ForceUseEvent(AudioSystem.FOR_MEDIA, forMed,
1030 "onAudioServerDied"));
1031 AudioSystem.setForceUse(AudioSystem.FOR_MEDIA, forMed);
Sungsoocf09fe62016-09-28 16:21:48 +09001032 }
1033
Eric Laurent0867bed2015-05-20 14:49:08 -07001034 synchronized (mSettingsLock) {
Jean-Michel Trivi011f39e2017-08-19 18:08:06 -07001035 final int forDock = mDockAudioMediaEnabled ?
1036 AudioSystem.FORCE_ANALOG_DOCK : AudioSystem.FORCE_NONE;
1037 mForceUseLogger.log(new ForceUseEvent(AudioSystem.FOR_DOCK, forDock,
1038 "onAudioServerDied"));
1039 AudioSystem.setForceUse(AudioSystem.FOR_DOCK, forDock);
1040 sendEncodedSurroundMode(mContentResolver, "onAudioServerDied");
Eric Laurent0867bed2015-05-20 14:49:08 -07001041 }
1042 if (mHdmiManager != null) {
1043 synchronized (mHdmiManager) {
1044 if (mHdmiTvClient != null) {
1045 setHdmiSystemAudioSupported(mHdmiSystemAudioSupported);
1046 }
1047 }
1048 }
1049
1050 synchronized (mAudioPolicies) {
1051 for (AudioPolicyProxy policy : mAudioPolicies.values()) {
1052 policy.connectMixes();
1053 }
1054 }
1055
1056 onIndicateSystemReady();
1057 // indicate the end of reconfiguration phase to audio HAL
1058 AudioSystem.setParameters("restarting=false");
Eric Laurent1d3cdce2018-01-20 10:31:21 -08001059
1060 sendMsg(mAudioHandler, MSG_DISPATCH_AUDIO_SERVER_STATE,
1061 SENDMSG_QUEUE, 1, 0, null, 0);
1062 }
1063
1064 private void onDispatchAudioServerStateChange(boolean state) {
1065 synchronized (mAudioServerStateListeners) {
1066 for (AsdProxy asdp : mAudioServerStateListeners.values()) {
1067 try {
1068 asdp.callback().dispatchAudioServerStateChange(state);
1069 } catch (RemoteException e) {
1070 Log.w(TAG, "Could not call dispatchAudioServerStateChange()", e);
1071 }
1072 }
1073 }
Eric Laurent4a5eeb92014-05-06 10:49:04 -07001074 }
1075
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001076 private void createAudioSystemThread() {
1077 mAudioSystemThread = new AudioSystemThread();
1078 mAudioSystemThread.start();
1079 waitForAudioHandlerCreation();
1080 }
1081
1082 /** Waits for the volume handler to be created by the other thread. */
1083 private void waitForAudioHandlerCreation() {
1084 synchronized(this) {
1085 while (mAudioHandler == null) {
1086 try {
1087 // Wait for mAudioHandler to be set by the other thread
1088 wait();
1089 } catch (InterruptedException e) {
1090 Log.e(TAG, "Interrupted while waiting on volume handler.");
1091 }
1092 }
1093 }
1094 }
1095
Eric Laurent24482012012-05-10 09:41:17 -07001096 private void checkAllAliasStreamVolumes() {
Jean-Michel Trivi085346a2018-02-14 10:48:51 -08001097 synchronized (mSettingsLock) {
1098 synchronized (VolumeStreamState.class) {
1099 int numStreamTypes = AudioSystem.getNumStreamTypes();
1100 for (int streamType = 0; streamType < numStreamTypes; streamType++) {
1101 mStreamStates[streamType]
1102 .setAllIndexes(mStreamStates[mStreamVolumeAlias[streamType]], TAG);
1103 // apply stream volume
1104 if (!mStreamStates[streamType].mIsMuted) {
1105 mStreamStates[streamType].applyAllVolumes();
1106 }
Eric Laurent8fa4d6f2014-10-30 14:13:03 -07001107 }
Eric Laurent24482012012-05-10 09:41:17 -07001108 }
1109 }
1110 }
1111
Eric Laurent212532b2014-07-21 15:43:18 -07001112 private void checkAllFixedVolumeDevices()
1113 {
1114 int numStreamTypes = AudioSystem.getNumStreamTypes();
1115 for (int streamType = 0; streamType < numStreamTypes; streamType++) {
1116 mStreamStates[streamType].checkFixedVolumeDevices();
1117 }
1118 }
1119
Jean-Michel Triviba5270b2014-10-01 17:49:29 -07001120 private void checkAllFixedVolumeDevices(int streamType) {
1121 mStreamStates[streamType].checkFixedVolumeDevices();
1122 }
1123
John Spurlockb6e19e32015-03-10 21:33:44 -04001124 private void checkMuteAffectedStreams() {
1125 // any stream with a min level > 0 is not muteable by definition
Nadav Bar6b7751d2017-12-24 16:03:08 +02001126 // STREAM_VOICE_CALL can be muted by applications that has the the MODIFY_PHONE_STATE permission.
John Spurlockb6e19e32015-03-10 21:33:44 -04001127 for (int i = 0; i < mStreamStates.length; i++) {
1128 final VolumeStreamState vss = mStreamStates[i];
Nadav Bar6b7751d2017-12-24 16:03:08 +02001129 if (vss.mIndexMin > 0 &&
1130 vss.mStreamType != AudioSystem.STREAM_VOICE_CALL) {
John Spurlockb6e19e32015-03-10 21:33:44 -04001131 mMuteAffectedStreams &= ~(1 << vss.mStreamType);
1132 }
1133 }
1134 }
1135
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001136 private void createStreamStates() {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001137 int numStreamTypes = AudioSystem.getNumStreamTypes();
1138 VolumeStreamState[] streams = mStreamStates = new VolumeStreamState[numStreamTypes];
1139
1140 for (int i = 0; i < numStreamTypes; i++) {
Jean-Michel Trivia53b7052017-04-12 18:27:01 -07001141 streams[i] =
1142 new VolumeStreamState(System.VOLUME_SETTINGS_INT[mStreamVolumeAlias[i]], i);
Eric Laurenta553c252009-07-17 12:17:14 -07001143 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001144
Eric Laurent212532b2014-07-21 15:43:18 -07001145 checkAllFixedVolumeDevices();
Eric Laurent24482012012-05-10 09:41:17 -07001146 checkAllAliasStreamVolumes();
John Spurlockb6e19e32015-03-10 21:33:44 -04001147 checkMuteAffectedStreams();
Eric Laurent403bd342017-07-11 16:21:44 -07001148 updateDefaultVolumes();
1149 }
1150
1151 // Update default indexes from aliased streams. Must be called after mStreamStates is created
1152 private void updateDefaultVolumes() {
1153 for (int stream = 0; stream < mStreamStates.length; stream++) {
1154 if (stream != mStreamVolumeAlias[stream]) {
1155 AudioSystem.DEFAULT_STREAM_VOLUME[stream] = rescaleIndex(
1156 AudioSystem.DEFAULT_STREAM_VOLUME[mStreamVolumeAlias[stream]],
1157 mStreamVolumeAlias[stream],
1158 stream);
1159 }
1160 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001161 }
1162
Eric Laurentbffc3d12012-05-07 17:43:49 -07001163 private void dumpStreamStates(PrintWriter pw) {
1164 pw.println("\nStream volumes (device: index)");
1165 int numStreamTypes = AudioSystem.getNumStreamTypes();
1166 for (int i = 0; i < numStreamTypes; i++) {
John Spurlock61560172015-02-06 19:46:04 -05001167 pw.println("- " + AudioSystem.STREAM_NAMES[i] + ":");
Eric Laurentbffc3d12012-05-07 17:43:49 -07001168 mStreamStates[i].dump(pw);
1169 pw.println("");
1170 }
Eric Laurentdd45d012012-10-08 09:04:34 -07001171 pw.print("\n- mute affected streams = 0x");
1172 pw.println(Integer.toHexString(mMuteAffectedStreams));
Eric Laurentbffc3d12012-05-07 17:43:49 -07001173 }
1174
John Spurlock90874332015-03-10 16:00:54 -04001175 private void updateStreamVolumeAlias(boolean updateVolumes, String caller) {
Eric Laurent6d517662012-04-23 18:42:39 -07001176 int dtmfStreamAlias;
Jean-Michel Triviac487672016-11-11 10:05:18 -08001177 final int a11yStreamAlias = sIndependentA11yVolume ?
1178 AudioSystem.STREAM_ACCESSIBILITY : AudioSystem.STREAM_MUSIC;
Eric Laurent212532b2014-07-21 15:43:18 -07001179
Muyuan Li1ed6df62016-06-18 11:16:52 -07001180 if (mIsSingleVolume) {
Eric Laurent212532b2014-07-21 15:43:18 -07001181 mStreamVolumeAlias = STREAM_VOLUME_ALIAS_TELEVISION;
1182 dtmfStreamAlias = AudioSystem.STREAM_MUSIC;
Muyuan Li1ed6df62016-06-18 11:16:52 -07001183 } else {
1184 switch (mPlatformType) {
1185 case AudioSystem.PLATFORM_VOICE:
1186 mStreamVolumeAlias = STREAM_VOLUME_ALIAS_VOICE;
1187 dtmfStreamAlias = AudioSystem.STREAM_RING;
1188 break;
1189 default:
1190 mStreamVolumeAlias = STREAM_VOLUME_ALIAS_DEFAULT;
1191 dtmfStreamAlias = AudioSystem.STREAM_MUSIC;
1192 }
Eric Laurent6d517662012-04-23 18:42:39 -07001193 }
Eric Laurent212532b2014-07-21 15:43:18 -07001194
Muyuan Li1ed6df62016-06-18 11:16:52 -07001195 if (mIsSingleVolume) {
Eric Laurent212532b2014-07-21 15:43:18 -07001196 mRingerModeAffectedStreams = 0;
Eric Laurent24e0d9b2013-10-03 18:15:07 -07001197 } else {
Eric Laurent212532b2014-07-21 15:43:18 -07001198 if (isInCommunication()) {
1199 dtmfStreamAlias = AudioSystem.STREAM_VOICE_CALL;
1200 mRingerModeAffectedStreams &= ~(1 << AudioSystem.STREAM_DTMF);
1201 } else {
1202 mRingerModeAffectedStreams |= (1 << AudioSystem.STREAM_DTMF);
1203 }
Eric Laurent6d517662012-04-23 18:42:39 -07001204 }
Eric Laurent212532b2014-07-21 15:43:18 -07001205
Eric Laurent6d517662012-04-23 18:42:39 -07001206 mStreamVolumeAlias[AudioSystem.STREAM_DTMF] = dtmfStreamAlias;
Jean-Michel Trivi170a0ee2017-04-14 18:13:26 -07001207 mStreamVolumeAlias[AudioSystem.STREAM_ACCESSIBILITY] = a11yStreamAlias;
Jean-Michel Triviac487672016-11-11 10:05:18 -08001208
Eric Laurent403bd342017-07-11 16:21:44 -07001209 if (updateVolumes && mStreamStates != null) {
1210 updateDefaultVolumes();
1211
Jean-Michel Trivi085346a2018-02-14 10:48:51 -08001212 synchronized (mSettingsLock) {
1213 synchronized (VolumeStreamState.class) {
1214 mStreamStates[AudioSystem.STREAM_DTMF]
1215 .setAllIndexes(mStreamStates[dtmfStreamAlias], caller);
1216 mStreamStates[AudioSystem.STREAM_ACCESSIBILITY].mVolumeIndexSettingName =
1217 System.VOLUME_SETTINGS_INT[a11yStreamAlias];
1218 mStreamStates[AudioSystem.STREAM_ACCESSIBILITY].setAllIndexes(
1219 mStreamStates[a11yStreamAlias], caller);
Jean-Michel Trivie05eef82018-03-08 18:56:34 -08001220 mStreamStates[AudioSystem.STREAM_ACCESSIBILITY].refreshRange(
1221 mStreamVolumeAlias[AudioSystem.STREAM_ACCESSIBILITY]);
Jean-Michel Trivi085346a2018-02-14 10:48:51 -08001222 }
1223 }
Jean-Michel Trivi170a0ee2017-04-14 18:13:26 -07001224 if (sIndependentA11yVolume) {
1225 // restore the a11y values from the settings
1226 mStreamStates[AudioSystem.STREAM_ACCESSIBILITY].readSettings();
1227 }
1228
Eric Laurent24e0d9b2013-10-03 18:15:07 -07001229 // apply stream mute states according to new value of mRingerModeAffectedStreams
John Spurlock661f2cf2014-11-17 10:29:10 -05001230 setRingerModeInt(getRingerModeInternal(), false);
Eric Laurent6d517662012-04-23 18:42:39 -07001231 sendMsg(mAudioHandler,
1232 MSG_SET_ALL_VOLUMES,
1233 SENDMSG_QUEUE,
1234 0,
1235 0,
1236 mStreamStates[AudioSystem.STREAM_DTMF], 0);
Jean-Michel Triviac487672016-11-11 10:05:18 -08001237 sendMsg(mAudioHandler,
1238 MSG_SET_ALL_VOLUMES,
1239 SENDMSG_QUEUE,
1240 0,
1241 0,
1242 mStreamStates[AudioSystem.STREAM_ACCESSIBILITY], 0);
Eric Laurent6d517662012-04-23 18:42:39 -07001243 }
1244 }
1245
Eric Laurent7ee1e4f2012-10-26 18:11:21 -07001246 private void readDockAudioSettings(ContentResolver cr)
1247 {
1248 mDockAudioMediaEnabled = Settings.Global.getInt(
Eric Laurent5ba0ffa02012-10-29 12:31:09 -07001249 cr, Settings.Global.DOCK_AUDIO_MEDIA_ENABLED, 0) == 1;
Eric Laurent7ee1e4f2012-10-26 18:11:21 -07001250
Eric Laurent7ee1e4f2012-10-26 18:11:21 -07001251 sendMsg(mAudioHandler,
1252 MSG_SET_FORCE_USE,
1253 SENDMSG_QUEUE,
1254 AudioSystem.FOR_DOCK,
1255 mDockAudioMediaEnabled ?
1256 AudioSystem.FORCE_ANALOG_DOCK : AudioSystem.FORCE_NONE,
Jean-Michel Trivi011f39e2017-08-19 18:08:06 -07001257 new String("readDockAudioSettings"),
Eric Laurent7ee1e4f2012-10-26 18:11:21 -07001258 0);
1259 }
1260
Phil Burkac0f7042016-02-24 12:19:08 -08001261
Andy Hung7b98e9a2016-02-25 18:34:50 -08001262 private void updateMasterMono(ContentResolver cr)
1263 {
1264 final boolean masterMono = System.getIntForUser(
1265 cr, System.MASTER_MONO, 0 /* default */, UserHandle.USER_CURRENT) == 1;
1266 if (DEBUG_VOL) {
1267 Log.d(TAG, String.format("Master mono %b", masterMono));
1268 }
1269 AudioSystem.setMasterMono(masterMono);
1270 }
1271
Jean-Michel Trivi011f39e2017-08-19 18:08:06 -07001272 private void sendEncodedSurroundMode(ContentResolver cr, String eventSource)
Phil Burkac0f7042016-02-24 12:19:08 -08001273 {
1274 int encodedSurroundMode = Settings.Global.getInt(
1275 cr, Settings.Global.ENCODED_SURROUND_OUTPUT,
1276 Settings.Global.ENCODED_SURROUND_OUTPUT_AUTO);
Jean-Michel Trivi011f39e2017-08-19 18:08:06 -07001277 sendEncodedSurroundMode(encodedSurroundMode, eventSource);
Phil Burkac0f7042016-02-24 12:19:08 -08001278 }
1279
Jean-Michel Trivi011f39e2017-08-19 18:08:06 -07001280 private void sendEncodedSurroundMode(int encodedSurroundMode, String eventSource)
Phil Burkac0f7042016-02-24 12:19:08 -08001281 {
1282 // initialize to guaranteed bad value
1283 int forceSetting = AudioSystem.NUM_FORCE_CONFIG;
1284 switch (encodedSurroundMode) {
1285 case Settings.Global.ENCODED_SURROUND_OUTPUT_AUTO:
1286 forceSetting = AudioSystem.FORCE_NONE;
1287 break;
1288 case Settings.Global.ENCODED_SURROUND_OUTPUT_NEVER:
1289 forceSetting = AudioSystem.FORCE_ENCODED_SURROUND_NEVER;
1290 break;
1291 case Settings.Global.ENCODED_SURROUND_OUTPUT_ALWAYS:
1292 forceSetting = AudioSystem.FORCE_ENCODED_SURROUND_ALWAYS;
1293 break;
1294 default:
1295 Log.e(TAG, "updateSurroundSoundSettings: illegal value "
1296 + encodedSurroundMode);
1297 break;
1298 }
1299 if (forceSetting != AudioSystem.NUM_FORCE_CONFIG) {
1300 sendMsg(mAudioHandler,
1301 MSG_SET_FORCE_USE,
1302 SENDMSG_QUEUE,
1303 AudioSystem.FOR_ENCODED_SURROUND,
1304 forceSetting,
Jean-Michel Trivi011f39e2017-08-19 18:08:06 -07001305 eventSource,
Phil Burkac0f7042016-02-24 12:19:08 -08001306 0);
1307 }
1308 }
1309
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001310 private void readPersistedSettings() {
1311 final ContentResolver cr = mContentResolver;
1312
Eric Laurentbffc3d12012-05-07 17:43:49 -07001313 int ringerModeFromSettings =
Jeff Sharkey8d9a1f62012-10-18 15:38:14 -07001314 Settings.Global.getInt(
1315 cr, Settings.Global.MODE_RINGER, AudioManager.RINGER_MODE_NORMAL);
Eric Laurentbffc3d12012-05-07 17:43:49 -07001316 int ringerMode = ringerModeFromSettings;
Eric Laurent72668b22011-07-19 16:04:27 -07001317 // sanity check in case the settings are restored from a device with incompatible
1318 // ringer modes
John Spurlock97559372014-10-24 16:27:36 -04001319 if (!isValidRingerMode(ringerMode)) {
Glenn Kastenba195eb2011-12-13 09:30:40 -08001320 ringerMode = AudioManager.RINGER_MODE_NORMAL;
Eric Laurentbffc3d12012-05-07 17:43:49 -07001321 }
1322 if ((ringerMode == AudioManager.RINGER_MODE_VIBRATE) && !mHasVibrator) {
1323 ringerMode = AudioManager.RINGER_MODE_SILENT;
1324 }
1325 if (ringerMode != ringerModeFromSettings) {
Jeff Sharkey8d9a1f62012-10-18 15:38:14 -07001326 Settings.Global.putInt(cr, Settings.Global.MODE_RINGER, ringerMode);
Glenn Kastenba195eb2011-12-13 09:30:40 -08001327 }
Muyuan Li1ed6df62016-06-18 11:16:52 -07001328 if (mUseFixedVolume || mIsSingleVolume) {
Eric Laurent83a017b2013-03-19 18:15:31 -07001329 ringerMode = AudioManager.RINGER_MODE_NORMAL;
1330 }
Glenn Kastenba195eb2011-12-13 09:30:40 -08001331 synchronized(mSettingsLock) {
1332 mRingerMode = ringerMode;
John Spurlock661f2cf2014-11-17 10:29:10 -05001333 if (mRingerModeExternal == -1) {
1334 mRingerModeExternal = mRingerMode;
1335 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001336
Eric Laurentdd45d012012-10-08 09:04:34 -07001337 // System.VIBRATE_ON is not used any more but defaults for mVibrateSetting
1338 // are still needed while setVibrateSetting() and getVibrateSetting() are being
1339 // deprecated.
John Spurlock61560172015-02-06 19:46:04 -05001340 mVibrateSetting = AudioSystem.getValueForVibrateSetting(0,
Eric Laurentdd45d012012-10-08 09:04:34 -07001341 AudioManager.VIBRATE_TYPE_NOTIFICATION,
1342 mHasVibrator ? AudioManager.VIBRATE_SETTING_ONLY_SILENT
1343 : AudioManager.VIBRATE_SETTING_OFF);
John Spurlock61560172015-02-06 19:46:04 -05001344 mVibrateSetting = AudioSystem.getValueForVibrateSetting(mVibrateSetting,
Eric Laurentdd45d012012-10-08 09:04:34 -07001345 AudioManager.VIBRATE_TYPE_RINGER,
1346 mHasVibrator ? AudioManager.VIBRATE_SETTING_ONLY_SILENT
1347 : AudioManager.VIBRATE_SETTING_OFF);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001348
Beverlyd6964762018-02-16 14:07:03 -05001349 updateRingerAndZenModeAffectedStreams();
Eric Laurent7ee1e4f2012-10-26 18:11:21 -07001350 readDockAudioSettings(cr);
Jean-Michel Trivi011f39e2017-08-19 18:08:06 -07001351 sendEncodedSurroundMode(cr, "readPersistedSettings");
Eric Laurent402f7f22011-02-04 12:30:32 -08001352 }
Eric Laurentc1d41662011-07-19 11:21:13 -07001353
Eric Laurentbc0fab1f2012-09-19 11:24:41 -07001354 mMuteAffectedStreams = System.getIntForUser(cr,
John Spurlock61560172015-02-06 19:46:04 -05001355 System.MUTE_STREAMS_AFFECTED, AudioSystem.DEFAULT_MUTE_STREAMS_AFFECTED,
John Spurlock24c05182015-02-05 12:30:36 -05001356 UserHandle.USER_CURRENT);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001357
Andy Hung7b98e9a2016-02-25 18:34:50 -08001358 updateMasterMono(cr);
Andy Hungf04b84d2015-12-18 17:33:27 -08001359
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001360 // Each stream will read its own persisted settings
1361
John Spurlockbcc10872014-11-28 15:29:21 -05001362 // Broadcast the sticky intents
1363 broadcastRingerMode(AudioManager.RINGER_MODE_CHANGED_ACTION, mRingerModeExternal);
1364 broadcastRingerMode(AudioManager.INTERNAL_RINGER_MODE_CHANGED_ACTION, mRingerMode);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001365
1366 // Broadcast vibrate settings
1367 broadcastVibrateSetting(AudioManager.VIBRATE_TYPE_RINGER);
1368 broadcastVibrateSetting(AudioManager.VIBRATE_TYPE_NOTIFICATION);
Jean-Michel Trivid589fea2011-04-15 11:28:10 -07001369
John Spurlock33f4e042014-07-11 13:10:58 -04001370 // Load settings for the volume controller
1371 mVolumeController.loadSettings(cr);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001372 }
1373
Eric Laurentc0232482016-03-15 18:19:23 -07001374 private void readUserRestrictions() {
1375 final int currentUser = getCurrentUserId();
1376
1377 // Check the current user restriction.
Tony Makc1205112016-07-22 16:02:59 +01001378 boolean masterMute =
1379 mUserManagerInternal.getUserRestriction(currentUser,
Esteban Talavera492b4722017-02-13 14:59:45 +00001380 UserManager.DISALLOW_UNMUTE_DEVICE)
Tony Makc1205112016-07-22 16:02:59 +01001381 || mUserManagerInternal.getUserRestriction(currentUser,
1382 UserManager.DISALLOW_ADJUST_VOLUME);
Eric Laurentc0232482016-03-15 18:19:23 -07001383 if (mUseFixedVolume) {
1384 masterMute = false;
1385 AudioSystem.setMasterVolume(1.0f);
1386 }
1387 if (DEBUG_VOL) {
1388 Log.d(TAG, String.format("Master mute %s, user=%d", masterMute, currentUser));
1389 }
1390 setSystemAudioMute(masterMute);
1391 AudioSystem.setMasterMute(masterMute);
1392 broadcastMasterMuteStatus(masterMute);
1393
1394 boolean microphoneMute = mUserManagerInternal.getUserRestriction(
1395 currentUser, UserManager.DISALLOW_UNMUTE_MICROPHONE);
1396 if (DEBUG_VOL) {
1397 Log.d(TAG, String.format("Mic mute %s, user=%d", microphoneMute, currentUser));
1398 }
1399 AudioSystem.muteMicrophone(microphoneMute);
1400 }
1401
Eric Laurenta553c252009-07-17 12:17:14 -07001402 private int rescaleIndex(int index, int srcStream, int dstStream) {
Jean-Michel Trivie05eef82018-03-08 18:56:34 -08001403 final int rescaled =
1404 (index * mStreamStates[dstStream].getMaxIndex()
1405 + mStreamStates[srcStream].getMaxIndex() / 2)
1406 / mStreamStates[srcStream].getMaxIndex();
1407 if (rescaled < mStreamStates[dstStream].getMinIndex()) {
1408 return mStreamStates[dstStream].getMinIndex();
1409 } else {
1410 return rescaled;
1411 }
Eric Laurenta553c252009-07-17 12:17:14 -07001412 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001413
1414 ///////////////////////////////////////////////////////////////////////////
1415 // IPC methods
1416 ///////////////////////////////////////////////////////////////////////////
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001417 /** @see AudioManager#adjustVolume(int, int) */
Dianne Hackbornba50b97c2013-04-30 15:04:46 -07001418 public void adjustSuggestedStreamVolume(int direction, int suggestedStreamType, int flags,
John Spurlock90874332015-03-10 16:00:54 -04001419 String callingPackage, String caller) {
Jean-Michel Trivi610aa9b2018-01-27 15:42:42 -08001420 final IAudioPolicyCallback extVolCtlr;
1421 synchronized (mExtVolumeControllerLock) {
1422 extVolCtlr = mExtVolumeController;
1423 }
1424 if (extVolCtlr != null) {
Jean-Michel Trivi7ed71472018-02-02 16:52:09 -08001425 sendMsg(mAudioHandler, MSG_NOTIFY_VOL_EVENT, SENDMSG_QUEUE,
1426 direction, 0 /*ignored*/,
1427 extVolCtlr, 0 /*delay*/);
Jean-Michel Trivi610aa9b2018-01-27 15:42:42 -08001428 } else {
1429 adjustSuggestedStreamVolume(direction, suggestedStreamType, flags, callingPackage,
1430 caller, Binder.getCallingUid());
1431 }
RoboErik272e1612014-09-05 11:39:29 -07001432 }
1433
1434 private void adjustSuggestedStreamVolume(int direction, int suggestedStreamType, int flags,
John Spurlock90874332015-03-10 16:00:54 -04001435 String callingPackage, String caller, int uid) {
1436 if (DEBUG_VOL) Log.d(TAG, "adjustSuggestedStreamVolume() stream=" + suggestedStreamType
Jean-Michel Trivia7880d42017-04-15 12:41:05 -07001437 + ", flags=" + flags + ", caller=" + caller
1438 + ", volControlStream=" + mVolumeControlStream
1439 + ", userSelect=" + mUserSelectedVolumeControlStream);
Jean-Michel Trivicf170362017-08-24 17:24:57 -07001440 mVolumeLogger.log(new VolumeEvent(VolumeEvent.VOL_ADJUST_SUGG_VOL, suggestedStreamType,
1441 direction/*val1*/, flags/*val2*/, new StringBuilder(callingPackage)
1442 .append("/").append(caller).append(" uid:").append(uid).toString()));
Jean-Michel Trivia7880d42017-04-15 12:41:05 -07001443 final int streamType;
jiabin8fd5d5e2018-03-23 14:09:28 -07001444 synchronized (mForceControlStreamLock) {
1445 // Request lock in case mVolumeControlStream is changed by other thread.
1446 if (mUserSelectedVolumeControlStream) { // implies mVolumeControlStream != -1
Jean-Michel Trivia7880d42017-04-15 12:41:05 -07001447 streamType = mVolumeControlStream;
jiabin8fd5d5e2018-03-23 14:09:28 -07001448 } else {
1449 final int maybeActiveStreamType = getActiveStreamType(suggestedStreamType);
1450 final boolean activeForReal;
1451 if (maybeActiveStreamType == AudioSystem.STREAM_RING
1452 || maybeActiveStreamType == AudioSystem.STREAM_NOTIFICATION) {
1453 activeForReal = wasStreamActiveRecently(maybeActiveStreamType, 0);
1454 } else {
1455 activeForReal = AudioSystem.isStreamActive(maybeActiveStreamType, 0);
1456 }
1457 if (activeForReal || mVolumeControlStream == -1) {
1458 streamType = maybeActiveStreamType;
1459 } else {
1460 streamType = mVolumeControlStream;
1461 }
Jean-Michel Trivia7880d42017-04-15 12:41:05 -07001462 }
Eric Laurent402f7f22011-02-04 12:30:32 -08001463 }
Jean-Michel Trivia7880d42017-04-15 12:41:05 -07001464
1465 final boolean isMute = isMuteAdjust(direction);
1466
John Spurlock0a376af2015-03-26 16:24:12 -04001467 ensureValidStreamType(streamType);
John Spurlock33f4e042014-07-11 13:10:58 -04001468 final int resolvedStream = mStreamVolumeAlias[streamType];
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001469
RoboErik2811dd32014-08-12 09:48:13 -07001470 // Play sounds on STREAM_RING only.
1471 if ((flags & AudioManager.FLAG_PLAY_SOUND) != 0 &&
John Spurlock33f4e042014-07-11 13:10:58 -04001472 resolvedStream != AudioSystem.STREAM_RING) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001473 flags &= ~AudioManager.FLAG_PLAY_SOUND;
1474 }
1475
John Spurlock33f4e042014-07-11 13:10:58 -04001476 // For notifications/ring, show the ui before making any adjustments
RoboErik4197cb62015-01-21 15:45:32 -08001477 // Don't suppress mute/unmute requests
1478 if (mVolumeController.suppressAdjustment(resolvedStream, flags, isMute)) {
John Spurlock33f4e042014-07-11 13:10:58 -04001479 direction = 0;
1480 flags &= ~AudioManager.FLAG_PLAY_SOUND;
1481 flags &= ~AudioManager.FLAG_VIBRATE;
1482 if (DEBUG_VOL) Log.d(TAG, "Volume controller suppressed adjustment");
1483 }
1484
John Spurlock90874332015-03-10 16:00:54 -04001485 adjustStreamVolume(streamType, direction, flags, callingPackage, caller, uid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001486 }
1487
1488 /** @see AudioManager#adjustStreamVolume(int, int, int) */
Dianne Hackbornba50b97c2013-04-30 15:04:46 -07001489 public void adjustStreamVolume(int streamType, int direction, int flags,
1490 String callingPackage) {
Phil Weaverf1a9aff2017-03-23 17:21:29 -07001491 if ((streamType == AudioManager.STREAM_ACCESSIBILITY) && !canChangeAccessibilityVolume()) {
Jean-Michel Triviab2d9312017-03-13 15:33:39 -07001492 Log.w(TAG, "Trying to call adjustStreamVolume() for a11y without"
Phil Weaverf1a9aff2017-03-23 17:21:29 -07001493 + "CHANGE_ACCESSIBILITY_VOLUME / callingPackage=" + callingPackage);
Jean-Michel Triviab2d9312017-03-13 15:33:39 -07001494 return;
1495 }
Jean-Michel Trivicf170362017-08-24 17:24:57 -07001496 mVolumeLogger.log(new VolumeEvent(VolumeEvent.VOL_ADJUST_STREAM_VOL, streamType,
1497 direction/*val1*/, flags/*val2*/, callingPackage));
John Spurlock90874332015-03-10 16:00:54 -04001498 adjustStreamVolume(streamType, direction, flags, callingPackage, callingPackage,
1499 Binder.getCallingUid());
RoboErik0dac35a2014-08-12 15:48:49 -07001500 }
1501
Chinyue Chen6affe932018-01-24 14:51:43 +08001502 protected void adjustStreamVolume(int streamType, int direction, int flags,
John Spurlock90874332015-03-10 16:00:54 -04001503 String callingPackage, String caller, int uid) {
Eric Laurent83a017b2013-03-19 18:15:31 -07001504 if (mUseFixedVolume) {
1505 return;
1506 }
John Spurlock90874332015-03-10 16:00:54 -04001507 if (DEBUG_VOL) Log.d(TAG, "adjustStreamVolume() stream=" + streamType + ", dir=" + direction
1508 + ", flags=" + flags + ", caller=" + caller);
Jean-Michel Trivi3114ce32012-06-11 15:03:52 -07001509
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001510 ensureValidDirection(direction);
1511 ensureValidStreamType(streamType);
1512
RoboErik4197cb62015-01-21 15:45:32 -08001513 boolean isMuteAdjust = isMuteAdjust(direction);
1514
John Spurlock3ce37252015-02-17 13:20:45 -05001515 if (isMuteAdjust && !isStreamAffectedByMute(streamType)) {
1516 return;
1517 }
1518
Nadav Bar6b7751d2017-12-24 16:03:08 +02001519 // If adjust is mute and the stream is STREAM_VOICE_CALL, make sure
1520 // that the calling app have the MODIFY_PHONE_STATE permission.
1521 if (isMuteAdjust &&
1522 streamType == AudioSystem.STREAM_VOICE_CALL &&
1523 mContext.checkCallingOrSelfPermission(
1524 android.Manifest.permission.MODIFY_PHONE_STATE)
1525 != PackageManager.PERMISSION_GRANTED) {
1526 Log.w(TAG, "MODIFY_PHONE_STATE Permission Denial: adjustStreamVolume from pid="
1527 + Binder.getCallingPid() + ", uid=" + Binder.getCallingUid());
1528 return;
1529 }
1530
Eric Laurent96a33d12011-11-08 10:31:57 -08001531 // use stream type alias here so that streams with same alias have the same behavior,
1532 // including with regard to silent mode control (e.g the use of STREAM_RING below and in
1533 // checkForRingerModeChange() in place of STREAM_RING or STREAM_NOTIFICATION)
Eric Laurent6d517662012-04-23 18:42:39 -07001534 int streamTypeAlias = mStreamVolumeAlias[streamType];
RoboErik4197cb62015-01-21 15:45:32 -08001535
Eric Laurentb024c302011-10-14 17:19:27 -07001536 VolumeStreamState streamState = mStreamStates[streamTypeAlias];
Eric Laurent9bc8358d2011-11-18 16:43:31 -08001537
1538 final int device = getDeviceForStream(streamTypeAlias);
Eric Laurent3ef75492012-11-28 12:12:23 -08001539
Eric Laurent42b041e2013-03-29 11:36:03 -07001540 int aliasIndex = streamState.getIndex(device);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001541 boolean adjustVolume = true;
Eric Laurent3ef75492012-11-28 12:12:23 -08001542 int step;
Eric Laurent24482012012-05-10 09:41:17 -07001543
Matthew Xiec9d1d5f2013-09-12 00:32:22 -07001544 // skip a2dp absolute volume control request when the device
1545 // is not an a2dp device
1546 if ((device & AudioSystem.DEVICE_OUT_ALL_A2DP) == 0 &&
1547 (flags & AudioManager.FLAG_BLUETOOTH_ABS_VOLUME) != 0) {
1548 return;
1549 }
1550
Kenny Guy70e0c582015-06-30 19:18:28 +01001551 // If we are being called by the system (e.g. hardware keys) check for current user
1552 // so we handle user restrictions correctly.
1553 if (uid == android.os.Process.SYSTEM_UID) {
1554 uid = UserHandle.getUid(getCurrentUserId(), UserHandle.getAppId(uid));
1555 }
John Spurlock59dc9c12015-03-02 11:20:15 -05001556 if (mAppOps.noteOp(STREAM_VOLUME_OPS[streamTypeAlias], uid, callingPackage)
RoboErik0dac35a2014-08-12 15:48:49 -07001557 != AppOpsManager.MODE_ALLOWED) {
Dianne Hackbornba50b97c2013-04-30 15:04:46 -07001558 return;
1559 }
1560
Eric Laurentfde16d52012-12-03 14:42:39 -08001561 // reset any pending volume command
1562 synchronized (mSafeMediaVolumeState) {
1563 mPendingVolumeCommand = null;
1564 }
1565
Eric Laurent3ef75492012-11-28 12:12:23 -08001566 flags &= ~AudioManager.FLAG_FIXED_VOLUME;
1567 if ((streamTypeAlias == AudioSystem.STREAM_MUSIC) &&
1568 ((device & mFixedVolumeDevices) != 0)) {
1569 flags |= AudioManager.FLAG_FIXED_VOLUME;
1570
1571 // Always toggle between max safe volume and 0 for fixed volume devices where safe
1572 // volume is enforced, and max and 0 for the others.
1573 // This is simulated by stepping by the full allowed volume range
1574 if (mSafeMediaVolumeState == SAFE_MEDIA_VOLUME_ACTIVE &&
1575 (device & mSafeMediaVolumeDevices) != 0) {
Eric Laurenteab40d12017-06-09 12:45:21 -07001576 step = safeMediaVolumeIndex(device);
Eric Laurent3ef75492012-11-28 12:12:23 -08001577 } else {
1578 step = streamState.getMaxIndex();
1579 }
1580 if (aliasIndex != 0) {
1581 aliasIndex = step;
1582 }
1583 } else {
1584 // convert one UI step (+/-1) into a number of internal units on the stream alias
1585 step = rescaleIndex(10, streamType, streamTypeAlias);
1586 }
1587
Eric Laurent42b041e2013-03-29 11:36:03 -07001588 // If either the client forces allowing ringer modes for this adjustment,
1589 // or the stream type is one that is affected by ringer modes
1590 if (((flags & AudioManager.FLAG_ALLOW_RINGER_MODES) != 0) ||
John Spurlockee5ad722015-03-03 16:17:21 -05001591 (streamTypeAlias == getUiSoundsStreamType())) {
John Spurlock661f2cf2014-11-17 10:29:10 -05001592 int ringerMode = getRingerModeInternal();
Eric Laurent42b041e2013-03-29 11:36:03 -07001593 // do not vibrate if already in vibrate mode
1594 if (ringerMode == AudioManager.RINGER_MODE_VIBRATE) {
1595 flags &= ~AudioManager.FLAG_VIBRATE;
Eric Laurent3ef75492012-11-28 12:12:23 -08001596 }
RoboErik5452e252015-02-06 15:33:53 -08001597 // Check if the ringer mode handles this adjustment. If it does we don't
1598 // need to adjust the volume further.
John Spurlock50ced3f2015-05-11 16:00:09 -04001599 final int result = checkForRingerModeChange(aliasIndex, direction, step,
Julia Reynoldsed783792016-04-08 15:27:35 -04001600 streamState.mIsMuted, callingPackage, flags);
John Spurlocka11b4af2014-06-01 11:52:23 -04001601 adjustVolume = (result & FLAG_ADJUST_VOLUME) != 0;
1602 // If suppressing a volume adjustment in silent mode, display the UI hint
1603 if ((result & AudioManager.FLAG_SHOW_SILENT_HINT) != 0) {
1604 flags |= AudioManager.FLAG_SHOW_SILENT_HINT;
1605 }
John Spurlock661f2cf2014-11-17 10:29:10 -05001606 // If suppressing a volume down adjustment in vibrate mode, display the UI hint
1607 if ((result & AudioManager.FLAG_SHOW_VIBRATE_HINT) != 0) {
1608 flags |= AudioManager.FLAG_SHOW_VIBRATE_HINT;
1609 }
Eric Laurent42b041e2013-03-29 11:36:03 -07001610 }
Beverlyd6964762018-02-16 14:07:03 -05001611
1612 // If the ringer mode or zen is muting the stream, do not change stream unless
1613 // it'll cause us to exit dnd
Julia Reynoldsed783792016-04-08 15:27:35 -04001614 if (!volumeAdjustmentAllowedByDnd(streamTypeAlias, flags)) {
John Spurlock50ced3f2015-05-11 16:00:09 -04001615 adjustVolume = false;
1616 }
Eric Laurent42b041e2013-03-29 11:36:03 -07001617 int oldIndex = mStreamStates[streamType].getIndex(device);
Eric Laurent3ef75492012-11-28 12:12:23 -08001618
Eric Laurent42b041e2013-03-29 11:36:03 -07001619 if (adjustVolume && (direction != AudioManager.ADJUST_SAME)) {
RoboErik5452e252015-02-06 15:33:53 -08001620 mAudioHandler.removeMessages(MSG_UNMUTE_STREAM);
Matthew Xiec9d1d5f2013-09-12 00:32:22 -07001621
RoboErik4197cb62015-01-21 15:45:32 -08001622 if (isMuteAdjust) {
1623 boolean state;
1624 if (direction == AudioManager.ADJUST_TOGGLE_MUTE) {
1625 state = !streamState.mIsMuted;
1626 } else {
1627 state = direction == AudioManager.ADJUST_MUTE;
1628 }
1629 if (streamTypeAlias == AudioSystem.STREAM_MUSIC) {
1630 setSystemAudioMute(state);
1631 }
1632 for (int stream = 0; stream < mStreamStates.length; stream++) {
1633 if (streamTypeAlias == mStreamVolumeAlias[stream]) {
Sungmin Choi841ed0a2015-07-26 23:09:49 -07001634 if (!(readCameraSoundForced()
1635 && (mStreamStates[stream].getStreamType()
1636 == AudioSystem.STREAM_SYSTEM_ENFORCED))) {
1637 mStreamStates[stream].mute(state);
1638 }
RoboErik4197cb62015-01-21 15:45:32 -08001639 }
1640 }
1641 } else if ((direction == AudioManager.ADJUST_RAISE) &&
Eric Laurent42b041e2013-03-29 11:36:03 -07001642 !checkSafeMediaVolume(streamTypeAlias, aliasIndex + step, device)) {
RoboErik4197cb62015-01-21 15:45:32 -08001643 Log.e(TAG, "adjustStreamVolume() safe volume index = " + oldIndex);
John Spurlock3346a802014-05-20 16:25:37 -04001644 mVolumeController.postDisplaySafeVolumeWarning(flags);
John Spurlock90874332015-03-10 16:00:54 -04001645 } else if (streamState.adjustIndex(direction * step, device, caller)
1646 || streamState.mIsMuted) {
RoboErik4197cb62015-01-21 15:45:32 -08001647 // Post message to set system volume (it in turn will post a
1648 // message to persist).
1649 if (streamState.mIsMuted) {
1650 // Unmute the stream if it was previously muted
RoboErik5452e252015-02-06 15:33:53 -08001651 if (direction == AudioManager.ADJUST_RAISE) {
1652 // unmute immediately for volume up
1653 streamState.mute(false);
1654 } else if (direction == AudioManager.ADJUST_LOWER) {
Muyuan Li1ed6df62016-06-18 11:16:52 -07001655 if (mIsSingleVolume) {
John Spurlocka48d7792015-03-03 17:35:57 -05001656 sendMsg(mAudioHandler, MSG_UNMUTE_STREAM, SENDMSG_QUEUE,
1657 streamTypeAlias, flags, null, UNMUTE_STREAM_DELAY);
1658 }
RoboErik5452e252015-02-06 15:33:53 -08001659 }
RoboErik4197cb62015-01-21 15:45:32 -08001660 }
Eric Laurent42b041e2013-03-29 11:36:03 -07001661 sendMsg(mAudioHandler,
1662 MSG_SET_DEVICE_VOLUME,
1663 SENDMSG_QUEUE,
1664 device,
1665 0,
1666 streamState,
1667 0);
Eric Laurent4bbcc652012-09-24 14:26:30 -07001668 }
Jungshik Jang41d97462014-06-30 22:26:29 +09001669
Jungshik Jang41d97462014-06-30 22:26:29 +09001670 int newIndex = mStreamStates[streamType].getIndex(device);
Ajay Panickere3946c82018-02-26 16:04:15 -08001671
1672 // Check if volume update should be send to AVRCP
1673 if (streamTypeAlias == AudioSystem.STREAM_MUSIC &&
1674 (device & AudioSystem.DEVICE_OUT_ALL_A2DP) != 0 &&
1675 (flags & AudioManager.FLAG_BLUETOOTH_ABS_VOLUME) == 0) {
1676 synchronized (mA2dpAvrcpLock) {
1677 if (mA2dp != null && mAvrcpAbsVolSupported) {
1678 mA2dp.setAvrcpAbsoluteVolume(newIndex / 10);
1679 }
1680 }
1681 }
1682
Jakub Pawlowskif9570f32018-02-21 17:15:12 -08001683 // Check if volume update should be send to Hearing Aid
1684 if ((device & AudioSystem.DEVICE_OUT_HEARING_AID) != 0) {
Jakub Pawlowski21b7f492018-03-22 12:31:21 -07001685 setHearingAidVolume(newIndex, streamType);
Jakub Pawlowskif9570f32018-02-21 17:15:12 -08001686 }
1687
Ajay Panickere3946c82018-02-26 16:04:15 -08001688 // Check if volume update should be sent to Hdmi system audio.
Jinsuk Kim336cdb42014-11-29 06:27:00 +09001689 if (streamTypeAlias == AudioSystem.STREAM_MUSIC) {
1690 setSystemAudioVolume(oldIndex, newIndex, getStreamMaxVolume(streamType), flags);
1691 }
Eric Laurent212532b2014-07-21 15:43:18 -07001692 if (mHdmiManager != null) {
1693 synchronized (mHdmiManager) {
Eric Laurent212532b2014-07-21 15:43:18 -07001694 // mHdmiCecSink true => mHdmiPlaybackClient != null
1695 if (mHdmiCecSink &&
1696 streamTypeAlias == AudioSystem.STREAM_MUSIC &&
1697 oldIndex != newIndex) {
1698 synchronized (mHdmiPlaybackClient) {
1699 int keyCode = (direction == -1) ? KeyEvent.KEYCODE_VOLUME_DOWN :
RoboErik4197cb62015-01-21 15:45:32 -08001700 KeyEvent.KEYCODE_VOLUME_UP;
Donghyun Cho5f6d404e2016-03-17 20:39:25 +09001701 final long ident = Binder.clearCallingIdentity();
1702 try {
1703 mHdmiPlaybackClient.sendKeyEvent(keyCode, true);
1704 mHdmiPlaybackClient.sendKeyEvent(keyCode, false);
1705 } finally {
1706 Binder.restoreCallingIdentity(ident);
1707 }
Eric Laurent212532b2014-07-21 15:43:18 -07001708 }
Jungshik Jang41d97462014-06-30 22:26:29 +09001709 }
1710 }
1711 }
Eric Laurent4bbcc652012-09-24 14:26:30 -07001712 }
Eric Laurent42b041e2013-03-29 11:36:03 -07001713 int index = mStreamStates[streamType].getIndex(device);
Eric Laurent25101b02011-02-02 09:33:30 -08001714 sendVolumeUpdate(streamType, oldIndex, index, flags);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001715 }
1716
RoboErik5452e252015-02-06 15:33:53 -08001717 // Called after a delay when volume down is pressed while muted
1718 private void onUnmuteStream(int stream, int flags) {
1719 VolumeStreamState streamState = mStreamStates[stream];
1720 streamState.mute(false);
1721
1722 final int device = getDeviceForStream(stream);
1723 final int index = mStreamStates[stream].getIndex(device);
1724 sendVolumeUpdate(stream, index, index, flags);
1725 }
1726
Jinsuk Kim336cdb42014-11-29 06:27:00 +09001727 private void setSystemAudioVolume(int oldVolume, int newVolume, int maxVolume, int flags) {
1728 if (mHdmiManager == null
1729 || mHdmiTvClient == null
1730 || oldVolume == newVolume
1731 || (flags & AudioManager.FLAG_HDMI_SYSTEM_AUDIO_VOLUME) != 0) return;
1732
1733 // Sets the audio volume of AVR when we are in system audio mode. The new volume info
1734 // is tranformed to HDMI-CEC commands and passed through CEC bus.
1735 synchronized (mHdmiManager) {
1736 if (!mHdmiSystemAudioSupported) return;
1737 synchronized (mHdmiTvClient) {
Jinsuk Kim48cbf292014-12-13 02:16:28 +09001738 final long token = Binder.clearCallingIdentity();
1739 try {
Jinsuk Kim7a9ba422015-02-16 16:47:38 +09001740 mHdmiTvClient.setSystemAudioVolume(oldVolume, newVolume, maxVolume);
Jinsuk Kim48cbf292014-12-13 02:16:28 +09001741 } finally {
1742 Binder.restoreCallingIdentity(token);
1743 }
Jinsuk Kim336cdb42014-11-29 06:27:00 +09001744 }
1745 }
1746 }
1747
Eric Laurentfde16d52012-12-03 14:42:39 -08001748 // StreamVolumeCommand contains the information needed to defer the process of
1749 // setStreamVolume() in case the user has to acknowledge the safe volume warning message.
1750 class StreamVolumeCommand {
1751 public final int mStreamType;
1752 public final int mIndex;
1753 public final int mFlags;
1754 public final int mDevice;
Eric Laurent9ce379a2010-02-16 06:00:26 -08001755
Eric Laurentfde16d52012-12-03 14:42:39 -08001756 StreamVolumeCommand(int streamType, int index, int flags, int device) {
1757 mStreamType = streamType;
1758 mIndex = index;
1759 mFlags = flags;
1760 mDevice = device;
Eric Laurentb024c302011-10-14 17:19:27 -07001761 }
John Spurlock35134602014-07-24 18:10:48 -04001762
1763 @Override
1764 public String toString() {
1765 return new StringBuilder().append("{streamType=").append(mStreamType).append(",index=")
1766 .append(mIndex).append(",flags=").append(mFlags).append(",device=")
1767 .append(mDevice).append('}').toString();
1768 }
Eric Laurentfde16d52012-12-03 14:42:39 -08001769 };
Eric Laurent3ef75492012-11-28 12:12:23 -08001770
Julia Reynolds48034f82016-03-09 10:15:16 -05001771 private int getNewRingerMode(int stream, int index, int flags) {
Zak Cohen47798292017-11-30 12:34:20 -08001772 // setRingerMode does nothing if the device is single volume,so the value would be unchanged
1773 if (mIsSingleVolume) {
1774 return getRingerModeExternal();
1775 }
1776
John Spurlockee5ad722015-03-03 16:17:21 -05001777 // setting volume on ui sounds stream type also controls silent mode
Eric Laurent3ef75492012-11-28 12:12:23 -08001778 if (((flags & AudioManager.FLAG_ALLOW_RINGER_MODES) != 0) ||
John Spurlock75ae23c2015-06-02 16:26:43 -04001779 (stream == getUiSoundsStreamType())) {
Eric Laurent3ef75492012-11-28 12:12:23 -08001780 int newRingerMode;
1781 if (index == 0) {
1782 newRingerMode = mHasVibrator ? AudioManager.RINGER_MODE_VIBRATE
John Spurlocka48d7792015-03-03 17:35:57 -05001783 : mVolumePolicy.volumeDownToEnterSilent ? AudioManager.RINGER_MODE_SILENT
Julia Reynolds48034f82016-03-09 10:15:16 -05001784 : AudioManager.RINGER_MODE_NORMAL;
Eric Laurent3ef75492012-11-28 12:12:23 -08001785 } else {
1786 newRingerMode = AudioManager.RINGER_MODE_NORMAL;
1787 }
Julia Reynolds48034f82016-03-09 10:15:16 -05001788 return newRingerMode;
1789 }
1790 return getRingerModeExternal();
1791 }
1792
1793 private boolean isAndroidNPlus(String caller) {
1794 try {
1795 final ApplicationInfo applicationInfo =
1796 mContext.getPackageManager().getApplicationInfoAsUser(
1797 caller, 0, UserHandle.getUserId(Binder.getCallingUid()));
1798 if (applicationInfo.targetSdkVersion >= Build.VERSION_CODES.N) {
1799 return true;
1800 }
1801 return false;
1802 } catch (PackageManager.NameNotFoundException e) {
1803 return true;
1804 }
1805 }
1806
1807 private boolean wouldToggleZenMode(int newMode) {
1808 if (getRingerModeExternal() == AudioManager.RINGER_MODE_SILENT
1809 && newMode != AudioManager.RINGER_MODE_SILENT) {
1810 return true;
1811 } else if (getRingerModeExternal() != AudioManager.RINGER_MODE_SILENT
1812 && newMode == AudioManager.RINGER_MODE_SILENT) {
1813 return true;
1814 }
1815 return false;
1816 }
1817
1818 private void onSetStreamVolume(int streamType, int index, int flags, int device,
1819 String caller) {
1820 final int stream = mStreamVolumeAlias[streamType];
1821 setStreamVolumeInt(stream, index, device, false, caller);
1822 // setting volume on ui sounds stream type also controls silent mode
1823 if (((flags & AudioManager.FLAG_ALLOW_RINGER_MODES) != 0) ||
1824 (stream == getUiSoundsStreamType())) {
1825 setRingerMode(getNewRingerMode(stream, index, flags),
1826 TAG + ".onSetStreamVolume", false /*external*/);
Eric Laurent3ef75492012-11-28 12:12:23 -08001827 }
John Spurlock75ae23c2015-06-02 16:26:43 -04001828 // setting non-zero volume for a muted stream unmutes the stream and vice versa
1829 mStreamStates[stream].mute(index == 0);
Eric Laurentfde16d52012-12-03 14:42:39 -08001830 }
1831
1832 /** @see AudioManager#setStreamVolume(int, int, int) */
Dianne Hackbornba50b97c2013-04-30 15:04:46 -07001833 public void setStreamVolume(int streamType, int index, int flags, String callingPackage) {
Phil Weaverf1a9aff2017-03-23 17:21:29 -07001834 if ((streamType == AudioManager.STREAM_ACCESSIBILITY) && !canChangeAccessibilityVolume()) {
Jean-Michel Triviab2d9312017-03-13 15:33:39 -07001835 Log.w(TAG, "Trying to call setStreamVolume() for a11y without"
Phil Weaverf1a9aff2017-03-23 17:21:29 -07001836 + " CHANGE_ACCESSIBILITY_VOLUME callingPackage=" + callingPackage);
Jean-Michel Triviab2d9312017-03-13 15:33:39 -07001837 return;
1838 }
Nadav Bar6b7751d2017-12-24 16:03:08 +02001839 if ((streamType == AudioManager.STREAM_VOICE_CALL) &&
1840 (index == 0) &&
1841 (mContext.checkCallingOrSelfPermission(
1842 android.Manifest.permission.MODIFY_PHONE_STATE)
1843 != PackageManager.PERMISSION_GRANTED)) {
1844 Log.w(TAG, "Trying to call setStreamVolume() for STREAM_VOICE_CALL and index 0 without"
1845 + " MODIFY_PHONE_STATE callingPackage=" + callingPackage);
1846 return;
1847 }
Jean-Michel Trivicf170362017-08-24 17:24:57 -07001848 mVolumeLogger.log(new VolumeEvent(VolumeEvent.VOL_SET_STREAM_VOL, streamType,
1849 index/*val1*/, flags/*val2*/, callingPackage));
John Spurlock90874332015-03-10 16:00:54 -04001850 setStreamVolume(streamType, index, flags, callingPackage, callingPackage,
1851 Binder.getCallingUid());
RoboErik0dac35a2014-08-12 15:48:49 -07001852 }
1853
Phil Weaverf1a9aff2017-03-23 17:21:29 -07001854 private boolean canChangeAccessibilityVolume() {
1855 synchronized (mAccessibilityServiceUidsLock) {
1856 if (PackageManager.PERMISSION_GRANTED == mContext.checkCallingOrSelfPermission(
1857 android.Manifest.permission.CHANGE_ACCESSIBILITY_VOLUME)) {
1858 return true;
1859 }
1860 if (mAccessibilityServiceUids != null) {
1861 int callingUid = Binder.getCallingUid();
1862 for (int i = 0; i < mAccessibilityServiceUids.length; i++) {
1863 if (mAccessibilityServiceUids[i] == callingUid) {
1864 return true;
1865 }
1866 }
1867 }
1868 return false;
1869 }
1870 }
1871
RoboErik0dac35a2014-08-12 15:48:49 -07001872 private void setStreamVolume(int streamType, int index, int flags, String callingPackage,
John Spurlock90874332015-03-10 16:00:54 -04001873 String caller, int uid) {
Jean-Michel Triviac487672016-11-11 10:05:18 -08001874 if (DEBUG_VOL) {
1875 Log.d(TAG, "setStreamVolume(stream=" + streamType+", index=" + index
1876 + ", calling=" + callingPackage + ")");
1877 }
Eric Laurent83a017b2013-03-19 18:15:31 -07001878 if (mUseFixedVolume) {
1879 return;
1880 }
1881
Eric Laurentfde16d52012-12-03 14:42:39 -08001882 ensureValidStreamType(streamType);
Dianne Hackbornba50b97c2013-04-30 15:04:46 -07001883 int streamTypeAlias = mStreamVolumeAlias[streamType];
1884 VolumeStreamState streamState = mStreamStates[streamTypeAlias];
Eric Laurentfde16d52012-12-03 14:42:39 -08001885
1886 final int device = getDeviceForStream(streamType);
1887 int oldIndex;
1888
Matthew Xiec9d1d5f2013-09-12 00:32:22 -07001889 // skip a2dp absolute volume control request when the device
1890 // is not an a2dp device
1891 if ((device & AudioSystem.DEVICE_OUT_ALL_A2DP) == 0 &&
1892 (flags & AudioManager.FLAG_BLUETOOTH_ABS_VOLUME) != 0) {
1893 return;
1894 }
Kenny Guy70e0c582015-06-30 19:18:28 +01001895 // If we are being called by the system (e.g. hardware keys) check for current user
1896 // so we handle user restrictions correctly.
1897 if (uid == android.os.Process.SYSTEM_UID) {
1898 uid = UserHandle.getUid(getCurrentUserId(), UserHandle.getAppId(uid));
1899 }
John Spurlock59dc9c12015-03-02 11:20:15 -05001900 if (mAppOps.noteOp(STREAM_VOLUME_OPS[streamTypeAlias], uid, callingPackage)
RoboErik0dac35a2014-08-12 15:48:49 -07001901 != AppOpsManager.MODE_ALLOWED) {
Dianne Hackbornba50b97c2013-04-30 15:04:46 -07001902 return;
1903 }
1904
Julia Reynolds48034f82016-03-09 10:15:16 -05001905 if (isAndroidNPlus(callingPackage)
1906 && wouldToggleZenMode(getNewRingerMode(streamTypeAlias, index, flags))
1907 && !mNm.isNotificationPolicyAccessGrantedForPackage(callingPackage)) {
1908 throw new SecurityException("Not allowed to change Do Not Disturb state");
1909 }
1910
Julia Reynoldsed783792016-04-08 15:27:35 -04001911 if (!volumeAdjustmentAllowedByDnd(streamTypeAlias, flags)) {
1912 return;
1913 }
1914
Eric Laurentfde16d52012-12-03 14:42:39 -08001915 synchronized (mSafeMediaVolumeState) {
1916 // reset any pending volume command
1917 mPendingVolumeCommand = null;
1918
Eric Laurent42b041e2013-03-29 11:36:03 -07001919 oldIndex = streamState.getIndex(device);
Eric Laurentfde16d52012-12-03 14:42:39 -08001920
Dianne Hackbornba50b97c2013-04-30 15:04:46 -07001921 index = rescaleIndex(index * 10, streamType, streamTypeAlias);
Eric Laurentfde16d52012-12-03 14:42:39 -08001922
Matthew Xiec9d1d5f2013-09-12 00:32:22 -07001923 if (streamTypeAlias == AudioSystem.STREAM_MUSIC &&
1924 (device & AudioSystem.DEVICE_OUT_ALL_A2DP) != 0 &&
1925 (flags & AudioManager.FLAG_BLUETOOTH_ABS_VOLUME) == 0) {
1926 synchronized (mA2dpAvrcpLock) {
1927 if (mA2dp != null && mAvrcpAbsVolSupported) {
Zhihai Xu2f4a2b12014-01-10 16:44:39 -08001928 mA2dp.setAvrcpAbsoluteVolume(index / 10);
Matthew Xiec9d1d5f2013-09-12 00:32:22 -07001929 }
John Du5a0cf7a2013-07-19 11:30:34 -07001930 }
1931 }
1932
Jakub Pawlowskif9570f32018-02-21 17:15:12 -08001933 if ((device & AudioSystem.DEVICE_OUT_HEARING_AID) != 0) {
Jakub Pawlowski21b7f492018-03-22 12:31:21 -07001934 setHearingAidVolume(index, streamType);
Jakub Pawlowskif9570f32018-02-21 17:15:12 -08001935 }
1936
Jinsuk Kim336cdb42014-11-29 06:27:00 +09001937 if (streamTypeAlias == AudioSystem.STREAM_MUSIC) {
1938 setSystemAudioVolume(oldIndex, index, getStreamMaxVolume(streamType), flags);
Jungshik Jang41d97462014-06-30 22:26:29 +09001939 }
1940
Eric Laurentfde16d52012-12-03 14:42:39 -08001941 flags &= ~AudioManager.FLAG_FIXED_VOLUME;
Dianne Hackbornba50b97c2013-04-30 15:04:46 -07001942 if ((streamTypeAlias == AudioSystem.STREAM_MUSIC) &&
Eric Laurentfde16d52012-12-03 14:42:39 -08001943 ((device & mFixedVolumeDevices) != 0)) {
1944 flags |= AudioManager.FLAG_FIXED_VOLUME;
1945
1946 // volume is either 0 or max allowed for fixed volume devices
1947 if (index != 0) {
1948 if (mSafeMediaVolumeState == SAFE_MEDIA_VOLUME_ACTIVE &&
1949 (device & mSafeMediaVolumeDevices) != 0) {
Eric Laurenteab40d12017-06-09 12:45:21 -07001950 index = safeMediaVolumeIndex(device);
Eric Laurentfde16d52012-12-03 14:42:39 -08001951 } else {
1952 index = streamState.getMaxIndex();
1953 }
1954 }
1955 }
1956
Dianne Hackbornba50b97c2013-04-30 15:04:46 -07001957 if (!checkSafeMediaVolume(streamTypeAlias, index, device)) {
John Spurlock3346a802014-05-20 16:25:37 -04001958 mVolumeController.postDisplaySafeVolumeWarning(flags);
Eric Laurentfde16d52012-12-03 14:42:39 -08001959 mPendingVolumeCommand = new StreamVolumeCommand(
1960 streamType, index, flags, device);
1961 } else {
John Spurlock90874332015-03-10 16:00:54 -04001962 onSetStreamVolume(streamType, index, flags, device, caller);
Eric Laurent42b041e2013-03-29 11:36:03 -07001963 index = mStreamStates[streamType].getIndex(device);
Eric Laurentfde16d52012-12-03 14:42:39 -08001964 }
1965 }
Eric Laurent25101b02011-02-02 09:33:30 -08001966 sendVolumeUpdate(streamType, oldIndex, index, flags);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001967 }
1968
Beverlyd6964762018-02-16 14:07:03 -05001969 // No ringer or zen muted stream volumes can be changed unless it'll exit dnd
Julia Reynoldsed783792016-04-08 15:27:35 -04001970 private boolean volumeAdjustmentAllowedByDnd(int streamTypeAlias, int flags) {
Beverlyd6964762018-02-16 14:07:03 -05001971 switch (mNm.getZenMode()) {
1972 case Settings.Global.ZEN_MODE_OFF:
1973 return true;
1974 case Settings.Global.ZEN_MODE_NO_INTERRUPTIONS:
1975 case Settings.Global.ZEN_MODE_ALARMS:
1976 case Settings.Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS:
1977 return !isStreamMutedByRingerOrZenMode(streamTypeAlias)
1978 || streamTypeAlias == getUiSoundsStreamType()
1979 || (flags & AudioManager.FLAG_ALLOW_RINGER_MODES) != 0;
Julia Reynoldsed783792016-04-08 15:27:35 -04001980 }
Beverlyd6964762018-02-16 14:07:03 -05001981
Julia Reynoldsed783792016-04-08 15:27:35 -04001982 return true;
1983 }
1984
Eric Laurent45c90ce2012-04-24 18:44:22 -07001985 /** @see AudioManager#forceVolumeControlStream(int) */
1986 public void forceVolumeControlStream(int streamType, IBinder cb) {
Jean-Michel Trivia7880d42017-04-15 12:41:05 -07001987 if (DEBUG_VOL) { Log.d(TAG, String.format("forceVolumeControlStream(%d)", streamType)); }
Eric Laurent45c90ce2012-04-24 18:44:22 -07001988 synchronized(mForceControlStreamLock) {
Jean-Michel Trivia7880d42017-04-15 12:41:05 -07001989 if (mVolumeControlStream != -1 && streamType != -1) {
1990 mUserSelectedVolumeControlStream = true;
1991 }
Eric Laurent45c90ce2012-04-24 18:44:22 -07001992 mVolumeControlStream = streamType;
1993 if (mVolumeControlStream == -1) {
1994 if (mForceControlStreamClient != null) {
1995 mForceControlStreamClient.release();
1996 mForceControlStreamClient = null;
1997 }
Jean-Michel Trivia7880d42017-04-15 12:41:05 -07001998 mUserSelectedVolumeControlStream = false;
Eric Laurent45c90ce2012-04-24 18:44:22 -07001999 } else {
jianzhou21fb09f2018-02-28 14:03:15 +08002000 if (null == mForceControlStreamClient) {
2001 mForceControlStreamClient = new ForceControlStreamClient(cb);
2002 } else {
2003 if (mForceControlStreamClient.getBinder() == cb) {
2004 Log.d(TAG, "forceVolumeControlStream cb:" + cb + " is already linked.");
2005 } else {
2006 mForceControlStreamClient.release();
2007 mForceControlStreamClient = new ForceControlStreamClient(cb);
2008 }
2009 }
Eric Laurent45c90ce2012-04-24 18:44:22 -07002010 }
2011 }
2012 }
2013
2014 private class ForceControlStreamClient implements IBinder.DeathRecipient {
2015 private IBinder mCb; // To be notified of client's death
2016
2017 ForceControlStreamClient(IBinder cb) {
2018 if (cb != null) {
2019 try {
2020 cb.linkToDeath(this, 0);
2021 } catch (RemoteException e) {
2022 // Client has died!
2023 Log.w(TAG, "ForceControlStreamClient() could not link to "+cb+" binder death");
2024 cb = null;
2025 }
2026 }
2027 mCb = cb;
2028 }
2029
2030 public void binderDied() {
2031 synchronized(mForceControlStreamLock) {
2032 Log.w(TAG, "SCO client died");
2033 if (mForceControlStreamClient != this) {
2034 Log.w(TAG, "unregistered control stream client died");
2035 } else {
2036 mForceControlStreamClient = null;
2037 mVolumeControlStream = -1;
Jean-Michel Trivia7880d42017-04-15 12:41:05 -07002038 mUserSelectedVolumeControlStream = false;
Eric Laurent45c90ce2012-04-24 18:44:22 -07002039 }
2040 }
2041 }
2042
2043 public void release() {
2044 if (mCb != null) {
2045 mCb.unlinkToDeath(this, 0);
2046 mCb = null;
2047 }
2048 }
jianzhou21fb09f2018-02-28 14:03:15 +08002049
2050 public IBinder getBinder() {
2051 return mCb;
2052 }
Eric Laurent45c90ce2012-04-24 18:44:22 -07002053 }
2054
Dianne Hackborn5ac72a22012-08-29 18:32:08 -07002055 private void sendBroadcastToAll(Intent intent) {
Christopher Tate267603f2015-01-20 14:21:21 -08002056 intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);
John Spurlock86490862015-02-25 11:22:52 -05002057 intent.addFlags(Intent.FLAG_RECEIVER_FOREGROUND);
Dianne Hackborn5ac72a22012-08-29 18:32:08 -07002058 final long ident = Binder.clearCallingIdentity();
2059 try {
2060 mContext.sendBroadcastAsUser(intent, UserHandle.ALL);
2061 } finally {
2062 Binder.restoreCallingIdentity(ident);
2063 }
2064 }
2065
2066 private void sendStickyBroadcastToAll(Intent intent) {
John Spurlock86490862015-02-25 11:22:52 -05002067 intent.addFlags(Intent.FLAG_RECEIVER_FOREGROUND);
Dianne Hackborn5ac72a22012-08-29 18:32:08 -07002068 final long ident = Binder.clearCallingIdentity();
2069 try {
2070 mContext.sendStickyBroadcastAsUser(intent, UserHandle.ALL);
2071 } finally {
2072 Binder.restoreCallingIdentity(ident);
2073 }
2074 }
2075
Kenny Guy70e0c582015-06-30 19:18:28 +01002076 private int getCurrentUserId() {
2077 final long ident = Binder.clearCallingIdentity();
2078 try {
Sudheer Shankadc589ac2016-11-10 15:30:17 -08002079 UserInfo currentUser = ActivityManager.getService().getCurrentUser();
Kenny Guy70e0c582015-06-30 19:18:28 +01002080 return currentUser.id;
2081 } catch (RemoteException e) {
2082 // Activity manager not running, nothing we can do assume user 0.
2083 } finally {
2084 Binder.restoreCallingIdentity(ident);
2085 }
Xiaohui Chen7c696362015-09-16 09:56:14 -07002086 return UserHandle.USER_SYSTEM;
Kenny Guy70e0c582015-06-30 19:18:28 +01002087 }
2088
Eric Laurent25101b02011-02-02 09:33:30 -08002089 // UI update and Broadcast Intent
Yue Li949865b2017-05-24 17:25:28 -07002090 protected void sendVolumeUpdate(int streamType, int oldIndex, int index, int flags) {
John Spurlock72966d62015-06-18 15:45:07 -04002091 streamType = mStreamVolumeAlias[streamType];
Eric Laurent25101b02011-02-02 09:33:30 -08002092
Jinsuk Kim336cdb42014-11-29 06:27:00 +09002093 if (streamType == AudioSystem.STREAM_MUSIC) {
2094 flags = updateFlagsForSystemAudio(flags);
Jungshik Jang1a6be6e2014-09-16 11:04:54 +09002095 }
John Spurlock3346a802014-05-20 16:25:37 -04002096 mVolumeController.postVolumeChanged(streamType, flags);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002097 }
2098
Jinsuk Kim336cdb42014-11-29 06:27:00 +09002099 // If Hdmi-CEC system audio mode is on, we show volume bar only when TV
2100 // receives volume notification from Audio Receiver.
2101 private int updateFlagsForSystemAudio(int flags) {
2102 if (mHdmiTvClient != null) {
2103 synchronized (mHdmiTvClient) {
2104 if (mHdmiSystemAudioSupported &&
2105 ((flags & AudioManager.FLAG_HDMI_SYSTEM_AUDIO_VOLUME) == 0)) {
2106 flags &= ~AudioManager.FLAG_SHOW_UI;
2107 }
2108 }
2109 }
2110 return flags;
2111 }
2112
Mike Lockwood0dc37cc2011-12-01 16:14:19 -05002113 // UI update and Broadcast Intent
Mike Lockwood0dc37cc2011-12-01 16:14:19 -05002114 private void sendMasterMuteUpdate(boolean muted, int flags) {
Jinsuk Kim336cdb42014-11-29 06:27:00 +09002115 mVolumeController.postMasterMuteChanged(updateFlagsForSystemAudio(flags));
Justin Koh57978ed2012-04-03 17:37:58 -07002116 broadcastMasterMuteStatus(muted);
2117 }
Mike Lockwood0dc37cc2011-12-01 16:14:19 -05002118
Justin Koh57978ed2012-04-03 17:37:58 -07002119 private void broadcastMasterMuteStatus(boolean muted) {
Mike Lockwood0dc37cc2011-12-01 16:14:19 -05002120 Intent intent = new Intent(AudioManager.MASTER_MUTE_CHANGED_ACTION);
2121 intent.putExtra(AudioManager.EXTRA_MASTER_VOLUME_MUTED, muted);
Justin Koh57978ed2012-04-03 17:37:58 -07002122 intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT
2123 | Intent.FLAG_RECEIVER_REPLACE_PENDING);
Dianne Hackborn5ac72a22012-08-29 18:32:08 -07002124 sendStickyBroadcastToAll(intent);
Mike Lockwood0dc37cc2011-12-01 16:14:19 -05002125 }
2126
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002127 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002128 * Sets the stream state's index, and posts a message to set system volume.
2129 * This will not call out to the UI. Assumes a valid stream type.
2130 *
2131 * @param streamType Type of the stream
2132 * @param index Desired volume index of the stream
Eric Laurent9bc8358d2011-11-18 16:43:31 -08002133 * @param device the device whose volume must be changed
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002134 * @param force If true, set the volume even if the desired volume is same
2135 * as the current volume.
2136 */
Eric Laurent9bc8358d2011-11-18 16:43:31 -08002137 private void setStreamVolumeInt(int streamType,
2138 int index,
2139 int device,
John Spurlock90874332015-03-10 16:00:54 -04002140 boolean force,
2141 String caller) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002142 VolumeStreamState streamState = mStreamStates[streamType];
Eric Laurent5b4e6542010-03-19 20:02:21 -07002143
John Spurlock90874332015-03-10 16:00:54 -04002144 if (streamState.setIndex(index, device, caller) || force) {
Eric Laurent42b041e2013-03-29 11:36:03 -07002145 // Post message to set system volume (it in turn will post a message
2146 // to persist).
2147 sendMsg(mAudioHandler,
2148 MSG_SET_DEVICE_VOLUME,
2149 SENDMSG_QUEUE,
2150 device,
2151 0,
2152 streamState,
2153 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002154 }
2155 }
2156
Jinsuk Kim336cdb42014-11-29 06:27:00 +09002157 private void setSystemAudioMute(boolean state) {
2158 if (mHdmiManager == null || mHdmiTvClient == null) return;
2159 synchronized (mHdmiManager) {
Jinsuk Kim48cbf292014-12-13 02:16:28 +09002160 if (!mHdmiSystemAudioSupported) return;
2161 synchronized (mHdmiTvClient) {
2162 final long token = Binder.clearCallingIdentity();
2163 try {
2164 mHdmiTvClient.setSystemAudioMute(state);
2165 } finally {
2166 Binder.restoreCallingIdentity(token);
Jinsuk Kim336cdb42014-11-29 06:27:00 +09002167 }
Jinsuk Kim336cdb42014-11-29 06:27:00 +09002168 }
2169 }
2170 }
2171
Eric Laurent25101b02011-02-02 09:33:30 -08002172 /** get stream mute state. */
2173 public boolean isStreamMute(int streamType) {
RoboErik7c82ced2014-12-04 17:39:08 -08002174 if (streamType == AudioManager.USE_DEFAULT_STREAM_TYPE) {
2175 streamType = getActiveStreamType(streamType);
2176 }
Eric Laurent8fa4d6f2014-10-30 14:13:03 -07002177 synchronized (VolumeStreamState.class) {
jiabin93d32ef2017-07-11 13:50:02 -07002178 ensureValidStreamType(streamType);
RoboErik4197cb62015-01-21 15:45:32 -08002179 return mStreamStates[streamType].mIsMuted;
Eric Laurent8fa4d6f2014-10-30 14:13:03 -07002180 }
Eric Laurent25101b02011-02-02 09:33:30 -08002181 }
2182
Jean-Michel Triviba5270b2014-10-01 17:49:29 -07002183 private class RmtSbmxFullVolDeathHandler implements IBinder.DeathRecipient {
2184 private IBinder mICallback; // To be notified of client's death
2185
2186 RmtSbmxFullVolDeathHandler(IBinder cb) {
2187 mICallback = cb;
2188 try {
2189 cb.linkToDeath(this, 0/*flags*/);
2190 } catch (RemoteException e) {
2191 Log.e(TAG, "can't link to death", e);
2192 }
2193 }
2194
2195 boolean isHandlerFor(IBinder cb) {
2196 return mICallback.equals(cb);
2197 }
2198
2199 void forget() {
2200 try {
2201 mICallback.unlinkToDeath(this, 0/*flags*/);
2202 } catch (NoSuchElementException e) {
2203 Log.e(TAG, "error unlinking to death", e);
2204 }
2205 }
2206
2207 public void binderDied() {
2208 Log.w(TAG, "Recorder with remote submix at full volume died " + mICallback);
2209 forceRemoteSubmixFullVolume(false, mICallback);
2210 }
2211 }
2212
2213 /**
2214 * call must be synchronized on mRmtSbmxFullVolDeathHandlers
2215 * @return true if there is a registered death handler, false otherwise */
2216 private boolean discardRmtSbmxFullVolDeathHandlerFor(IBinder cb) {
2217 Iterator<RmtSbmxFullVolDeathHandler> it = mRmtSbmxFullVolDeathHandlers.iterator();
2218 while (it.hasNext()) {
2219 final RmtSbmxFullVolDeathHandler handler = it.next();
2220 if (handler.isHandlerFor(cb)) {
2221 handler.forget();
2222 mRmtSbmxFullVolDeathHandlers.remove(handler);
2223 return true;
2224 }
2225 }
2226 return false;
2227 }
2228
2229 /** call synchronized on mRmtSbmxFullVolDeathHandlers */
2230 private boolean hasRmtSbmxFullVolDeathHandlerFor(IBinder cb) {
2231 Iterator<RmtSbmxFullVolDeathHandler> it = mRmtSbmxFullVolDeathHandlers.iterator();
2232 while (it.hasNext()) {
2233 if (it.next().isHandlerFor(cb)) {
2234 return true;
2235 }
2236 }
2237 return false;
2238 }
2239
2240 private int mRmtSbmxFullVolRefCount = 0;
2241 private ArrayList<RmtSbmxFullVolDeathHandler> mRmtSbmxFullVolDeathHandlers =
2242 new ArrayList<RmtSbmxFullVolDeathHandler>();
2243
2244 public void forceRemoteSubmixFullVolume(boolean startForcing, IBinder cb) {
2245 if (cb == null) {
2246 return;
2247 }
2248 if ((PackageManager.PERMISSION_GRANTED != mContext.checkCallingOrSelfPermission(
2249 android.Manifest.permission.CAPTURE_AUDIO_OUTPUT))) {
2250 Log.w(TAG, "Trying to call forceRemoteSubmixFullVolume() without CAPTURE_AUDIO_OUTPUT");
2251 return;
2252 }
2253 synchronized(mRmtSbmxFullVolDeathHandlers) {
2254 boolean applyRequired = false;
2255 if (startForcing) {
2256 if (!hasRmtSbmxFullVolDeathHandlerFor(cb)) {
2257 mRmtSbmxFullVolDeathHandlers.add(new RmtSbmxFullVolDeathHandler(cb));
2258 if (mRmtSbmxFullVolRefCount == 0) {
2259 mFullVolumeDevices |= AudioSystem.DEVICE_OUT_REMOTE_SUBMIX;
2260 mFixedVolumeDevices |= AudioSystem.DEVICE_OUT_REMOTE_SUBMIX;
2261 applyRequired = true;
2262 }
2263 mRmtSbmxFullVolRefCount++;
2264 }
2265 } else {
2266 if (discardRmtSbmxFullVolDeathHandlerFor(cb) && (mRmtSbmxFullVolRefCount > 0)) {
2267 mRmtSbmxFullVolRefCount--;
2268 if (mRmtSbmxFullVolRefCount == 0) {
2269 mFullVolumeDevices &= ~AudioSystem.DEVICE_OUT_REMOTE_SUBMIX;
2270 mFixedVolumeDevices &= ~AudioSystem.DEVICE_OUT_REMOTE_SUBMIX;
2271 applyRequired = true;
2272 }
2273 }
2274 }
2275 if (applyRequired) {
2276 // Assumes only STREAM_MUSIC going through DEVICE_OUT_REMOTE_SUBMIX
2277 checkAllFixedVolumeDevices(AudioSystem.STREAM_MUSIC);
2278 mStreamStates[AudioSystem.STREAM_MUSIC].applyAllVolumes();
2279 }
2280 }
2281 }
2282
Kenny Guy70e0c582015-06-30 19:18:28 +01002283 private void setMasterMuteInternal(boolean mute, int flags, String callingPackage, int uid,
2284 int userId) {
2285 // If we are being called by the system check for user we are going to change
2286 // so we handle user restrictions correctly.
2287 if (uid == android.os.Process.SYSTEM_UID) {
2288 uid = UserHandle.getUid(userId, UserHandle.getAppId(uid));
2289 }
Makoto Onuki4f160732015-10-27 17:15:38 -07002290 // If OP_AUDIO_MASTER_VOLUME is set, disallow unmuting.
2291 if (!mute && mAppOps.noteOp(AppOpsManager.OP_AUDIO_MASTER_VOLUME, uid, callingPackage)
RoboErik7c82ced2014-12-04 17:39:08 -08002292 != AppOpsManager.MODE_ALLOWED) {
Julia Reynolds4a21b252014-06-04 11:11:43 -04002293 return;
2294 }
Kenny Guy70e0c582015-06-30 19:18:28 +01002295 if (userId != UserHandle.getCallingUserId() &&
2296 mContext.checkCallingOrSelfPermission(
2297 android.Manifest.permission.INTERACT_ACROSS_USERS_FULL)
2298 != PackageManager.PERMISSION_GRANTED) {
2299 return;
2300 }
Makoto Onukid45a4a22015-11-02 17:17:38 -08002301 setMasterMuteInternalNoCallerCheck(mute, flags, userId);
2302 }
2303
2304 private void setMasterMuteInternalNoCallerCheck(boolean mute, int flags, int userId) {
2305 if (DEBUG_VOL) {
2306 Log.d(TAG, String.format("Master mute %s, %d, user=%d", mute, flags, userId));
2307 }
2308 if (mUseFixedVolume) {
2309 return; // If using fixed volume, we don't mute.
2310 }
Kenny Guy70e0c582015-06-30 19:18:28 +01002311 if (getCurrentUserId() == userId) {
2312 if (mute != AudioSystem.getMasterMute()) {
2313 setSystemAudioMute(mute);
2314 AudioSystem.setMasterMute(mute);
Kenny Guy70e0c582015-06-30 19:18:28 +01002315 sendMasterMuteUpdate(mute, flags);
RoboErik7c82ced2014-12-04 17:39:08 -08002316
Kenny Guy70e0c582015-06-30 19:18:28 +01002317 Intent intent = new Intent(AudioManager.MASTER_MUTE_CHANGED_ACTION);
2318 intent.putExtra(AudioManager.EXTRA_MASTER_VOLUME_MUTED, mute);
2319 sendBroadcastToAll(intent);
2320 }
Jason Simmons1ce5b262012-02-02 13:00:17 -08002321 }
Mike Lockwoodce952c82011-11-14 10:47:42 -08002322 }
2323
2324 /** get master mute state. */
2325 public boolean isMasterMute() {
Mike Lockwood3194ea92011-12-07 11:47:31 -08002326 return AudioSystem.getMasterMute();
Mike Lockwoodce952c82011-11-14 10:47:42 -08002327 }
2328
Kenny Guy70e0c582015-06-30 19:18:28 +01002329 public void setMasterMute(boolean mute, int flags, String callingPackage, int userId) {
2330 setMasterMuteInternal(mute, flags, callingPackage, Binder.getCallingUid(),
2331 userId);
John Spurlockee5ad722015-03-03 16:17:21 -05002332 }
2333
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002334 /** @see AudioManager#getStreamVolume(int) */
2335 public int getStreamVolume(int streamType) {
2336 ensureValidStreamType(streamType);
Eric Laurent9bc8358d2011-11-18 16:43:31 -08002337 int device = getDeviceForStream(streamType);
Eric Laurent8fa4d6f2014-10-30 14:13:03 -07002338 synchronized (VolumeStreamState.class) {
2339 int index = mStreamStates[streamType].getIndex(device);
Eric Laurent4bbcc652012-09-24 14:26:30 -07002340
Eric Laurent8fa4d6f2014-10-30 14:13:03 -07002341 // by convention getStreamVolume() returns 0 when a stream is muted.
RoboErik4197cb62015-01-21 15:45:32 -08002342 if (mStreamStates[streamType].mIsMuted) {
Eric Laurent8fa4d6f2014-10-30 14:13:03 -07002343 index = 0;
2344 }
2345 if (index != 0 && (mStreamVolumeAlias[streamType] == AudioSystem.STREAM_MUSIC) &&
2346 (device & mFixedVolumeDevices) != 0) {
2347 index = mStreamStates[streamType].getMaxIndex();
2348 }
2349 return (index + 5) / 10;
Eric Laurent42b041e2013-03-29 11:36:03 -07002350 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002351 }
2352
2353 /** @see AudioManager#getStreamMaxVolume(int) */
2354 public int getStreamMaxVolume(int streamType) {
2355 ensureValidStreamType(streamType);
Eric Laurenta553c252009-07-17 12:17:14 -07002356 return (mStreamStates[streamType].getMaxIndex() + 5) / 10;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002357 }
2358
Jean-Michel Trivi8e7aca32017-11-28 18:12:38 -08002359 /** @see AudioManager#getStreamMinVolumeInt(int) */
John Spurlockb6e19e32015-03-10 21:33:44 -04002360 public int getStreamMinVolume(int streamType) {
2361 ensureValidStreamType(streamType);
2362 return (mStreamStates[streamType].getMinIndex() + 5) / 10;
2363 }
2364
Eric Laurent25101b02011-02-02 09:33:30 -08002365 /** Get last audible volume before stream was muted. */
2366 public int getLastAudibleStreamVolume(int streamType) {
2367 ensureValidStreamType(streamType);
Eric Laurent9bc8358d2011-11-18 16:43:31 -08002368 int device = getDeviceForStream(streamType);
Eric Laurent42b041e2013-03-29 11:36:03 -07002369 return (mStreamStates[streamType].getIndex(device) + 5) / 10;
Eric Laurent25101b02011-02-02 09:33:30 -08002370 }
2371
John Spurlockee5ad722015-03-03 16:17:21 -05002372 /** @see AudioManager#getUiSoundsStreamType() */
2373 public int getUiSoundsStreamType() {
John Spurlock4f0f1202014-08-05 13:28:33 -04002374 return mStreamVolumeAlias[AudioSystem.STREAM_SYSTEM];
Eric Laurent6d517662012-04-23 18:42:39 -07002375 }
2376
Makoto Onukid45a4a22015-11-02 17:17:38 -08002377 /** @see AudioManager#setMicrophoneMute(boolean) */
2378 @Override
Kenny Guy70e0c582015-06-30 19:18:28 +01002379 public void setMicrophoneMute(boolean on, String callingPackage, int userId) {
2380 // If we are being called by the system check for user we are going to change
2381 // so we handle user restrictions correctly.
2382 int uid = Binder.getCallingUid();
2383 if (uid == android.os.Process.SYSTEM_UID) {
2384 uid = UserHandle.getUid(userId, UserHandle.getAppId(uid));
2385 }
Makoto Onuki4f160732015-10-27 17:15:38 -07002386 // If OP_MUTE_MICROPHONE is set, disallow unmuting.
2387 if (!on && mAppOps.noteOp(AppOpsManager.OP_MUTE_MICROPHONE, uid, callingPackage)
Kenny Guy70e0c582015-06-30 19:18:28 +01002388 != AppOpsManager.MODE_ALLOWED) {
Emily Bernier22c921a2014-05-28 11:01:32 -04002389 return;
2390 }
Jean-Michel Trivi4a4fea02014-08-29 18:14:09 -07002391 if (!checkAudioSettingsPermission("setMicrophoneMute()")) {
2392 return;
2393 }
Kenny Guy70e0c582015-06-30 19:18:28 +01002394 if (userId != UserHandle.getCallingUserId() &&
2395 mContext.checkCallingOrSelfPermission(
2396 android.Manifest.permission.INTERACT_ACROSS_USERS_FULL)
2397 != PackageManager.PERMISSION_GRANTED) {
2398 return;
2399 }
Makoto Onukid45a4a22015-11-02 17:17:38 -08002400 setMicrophoneMuteNoCallerCheck(on, userId);
2401 }
Emily Bernier22c921a2014-05-28 11:01:32 -04002402
Makoto Onukid45a4a22015-11-02 17:17:38 -08002403 private void setMicrophoneMuteNoCallerCheck(boolean on, int userId) {
2404 if (DEBUG_VOL) {
2405 Log.d(TAG, String.format("Mic mute %s, user=%d", on, userId));
2406 }
Jean-Michel Trivi7be17d22017-12-21 18:09:21 -08002407 // only mute for the current user
Kenny Guy70e0c582015-06-30 19:18:28 +01002408 if (getCurrentUserId() == userId) {
Jean-Michel Trivi7be17d22017-12-21 18:09:21 -08002409 final boolean currentMute = AudioSystem.isMicrophoneMuted();
Eric Laurent66b69672018-01-26 18:30:51 -08002410 final long identity = Binder.clearCallingIdentity();
Kenny Guy70e0c582015-06-30 19:18:28 +01002411 AudioSystem.muteMicrophone(on);
Eric Laurent66b69672018-01-26 18:30:51 -08002412 Binder.restoreCallingIdentity(identity);
Jean-Michel Trivi7be17d22017-12-21 18:09:21 -08002413 if (on != currentMute) {
2414 mContext.sendBroadcast(new Intent(AudioManager.ACTION_MICROPHONE_MUTE_CHANGED)
2415 .setFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY));
2416 }
Kenny Guy70e0c582015-06-30 19:18:28 +01002417 }
Emily Bernier22c921a2014-05-28 11:01:32 -04002418 }
2419
John Spurlock661f2cf2014-11-17 10:29:10 -05002420 @Override
2421 public int getRingerModeExternal() {
2422 synchronized(mSettingsLock) {
2423 return mRingerModeExternal;
2424 }
2425 }
2426
2427 @Override
2428 public int getRingerModeInternal() {
Glenn Kastenba195eb2011-12-13 09:30:40 -08002429 synchronized(mSettingsLock) {
2430 return mRingerMode;
2431 }
2432 }
2433
2434 private void ensureValidRingerMode(int ringerMode) {
John Spurlock97559372014-10-24 16:27:36 -04002435 if (!isValidRingerMode(ringerMode)) {
Glenn Kastenba195eb2011-12-13 09:30:40 -08002436 throw new IllegalArgumentException("Bad ringer mode " + ringerMode);
2437 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002438 }
2439
John Spurlock97559372014-10-24 16:27:36 -04002440 /** @see AudioManager#isValidRingerMode(int) */
2441 public boolean isValidRingerMode(int ringerMode) {
2442 return ringerMode >= 0 && ringerMode <= AudioManager.RINGER_MODE_MAX;
2443 }
2444
John Spurlock661f2cf2014-11-17 10:29:10 -05002445 public void setRingerModeExternal(int ringerMode, String caller) {
Julia Reynolds48034f82016-03-09 10:15:16 -05002446 if (isAndroidNPlus(caller) && wouldToggleZenMode(ringerMode)
2447 && !mNm.isNotificationPolicyAccessGrantedForPackage(caller)) {
2448 throw new SecurityException("Not allowed to change Do Not Disturb state");
2449 }
2450
John Spurlockaf88a192014-12-23 16:14:44 -05002451 setRingerMode(ringerMode, caller, true /*external*/);
John Spurlock661f2cf2014-11-17 10:29:10 -05002452 }
2453
2454 public void setRingerModeInternal(int ringerMode, String caller) {
John Spurlockcdb57ae2015-02-11 19:04:11 -05002455 enforceVolumeController("setRingerModeInternal");
John Spurlockaf88a192014-12-23 16:14:44 -05002456 setRingerMode(ringerMode, caller, false /*external*/);
John Spurlock661f2cf2014-11-17 10:29:10 -05002457 }
2458
Mike Digman55272862018-02-20 14:35:17 -08002459 public void silenceRingerModeInternal(String reason) {
2460 VibrationEffect effect = null;
2461 int ringerMode = AudioManager.RINGER_MODE_SILENT;
2462 int toastText = 0;
2463
2464 int silenceRingerSetting = Settings.Secure.VOLUME_HUSH_OFF;
2465 if (mContext.getResources()
2466 .getBoolean(com.android.internal.R.bool.config_volumeHushGestureEnabled)) {
2467 silenceRingerSetting = Settings.Secure.getIntForUser(mContentResolver,
2468 Settings.Secure.VOLUME_HUSH_GESTURE, VOLUME_HUSH_OFF,
2469 UserHandle.USER_CURRENT);
2470 }
2471
2472 switch(silenceRingerSetting) {
2473 case VOLUME_HUSH_MUTE:
2474 effect = VibrationEffect.get(VibrationEffect.EFFECT_DOUBLE_CLICK);
2475 ringerMode = AudioManager.RINGER_MODE_SILENT;
2476 toastText = com.android.internal.R.string.volume_dialog_ringer_guidance_silent;
2477 break;
2478 case VOLUME_HUSH_VIBRATE:
2479 effect = VibrationEffect.get(VibrationEffect.EFFECT_HEAVY_CLICK);
2480 ringerMode = AudioManager.RINGER_MODE_VIBRATE;
2481 toastText = com.android.internal.R.string.volume_dialog_ringer_guidance_vibrate;
2482 break;
2483 }
2484 maybeVibrate(effect);
2485 setRingerModeInternal(ringerMode, reason);
2486 Toast.makeText(mContext, toastText, Toast.LENGTH_SHORT).show();
2487 }
2488
2489 private boolean maybeVibrate(VibrationEffect effect) {
2490 if (!mHasVibrator) {
2491 return false;
2492 }
2493 final boolean hapticsDisabled = Settings.System.getIntForUser(mContext.getContentResolver(),
2494 Settings.System.HAPTIC_FEEDBACK_ENABLED, 0, UserHandle.USER_CURRENT) == 0;
2495 if (hapticsDisabled) {
2496 return false;
2497 }
2498
2499 if (effect == null) {
2500 return false;
2501 }
2502 mVibrator.vibrate(
2503 Binder.getCallingUid(), mContext.getOpPackageName(), effect, VIBRATION_ATTRIBUTES);
2504 return true;
2505 }
2506
John Spurlock661f2cf2014-11-17 10:29:10 -05002507 private void setRingerMode(int ringerMode, String caller, boolean external) {
Muyuan Li1ed6df62016-06-18 11:16:52 -07002508 if (mUseFixedVolume || mIsSingleVolume) {
Eric Laurent83a017b2013-03-19 18:15:31 -07002509 return;
2510 }
John Spurlock661f2cf2014-11-17 10:29:10 -05002511 if (caller == null || caller.length() == 0) {
2512 throw new IllegalArgumentException("Bad caller: " + caller);
2513 }
John Spurlock97559372014-10-24 16:27:36 -04002514 ensureValidRingerMode(ringerMode);
Eric Laurent24482012012-05-10 09:41:17 -07002515 if ((ringerMode == AudioManager.RINGER_MODE_VIBRATE) && !mHasVibrator) {
2516 ringerMode = AudioManager.RINGER_MODE_SILENT;
2517 }
John Spurlockaf88a192014-12-23 16:14:44 -05002518 final long identity = Binder.clearCallingIdentity();
2519 try {
2520 synchronized (mSettingsLock) {
2521 final int ringerModeInternal = getRingerModeInternal();
2522 final int ringerModeExternal = getRingerModeExternal();
2523 if (external) {
2524 setRingerModeExt(ringerMode);
2525 if (mRingerModeDelegate != null) {
2526 ringerMode = mRingerModeDelegate.onSetRingerModeExternal(ringerModeExternal,
John Spurlocka48d7792015-03-03 17:35:57 -05002527 ringerMode, caller, ringerModeInternal, mVolumePolicy);
John Spurlockaf88a192014-12-23 16:14:44 -05002528 }
2529 if (ringerMode != ringerModeInternal) {
2530 setRingerModeInt(ringerMode, true /*persist*/);
2531 }
2532 } else /*internal*/ {
2533 if (ringerMode != ringerModeInternal) {
2534 setRingerModeInt(ringerMode, true /*persist*/);
2535 }
2536 if (mRingerModeDelegate != null) {
2537 ringerMode = mRingerModeDelegate.onSetRingerModeInternal(ringerModeInternal,
John Spurlocka48d7792015-03-03 17:35:57 -05002538 ringerMode, caller, ringerModeExternal, mVolumePolicy);
John Spurlockaf88a192014-12-23 16:14:44 -05002539 }
2540 setRingerModeExt(ringerMode);
John Spurlock57627792014-12-11 11:29:54 -05002541 }
John Spurlock661f2cf2014-11-17 10:29:10 -05002542 }
John Spurlockaf88a192014-12-23 16:14:44 -05002543 } finally {
2544 Binder.restoreCallingIdentity(identity);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002545 }
2546 }
2547
John Spurlock661f2cf2014-11-17 10:29:10 -05002548 private void setRingerModeExt(int ringerMode) {
2549 synchronized(mSettingsLock) {
2550 if (ringerMode == mRingerModeExternal) return;
2551 mRingerModeExternal = ringerMode;
John Spurlocke5b42d92014-10-15 12:03:48 -04002552 }
John Spurlock661f2cf2014-11-17 10:29:10 -05002553 // Send sticky broadcast
John Spurlockbcc10872014-11-28 15:29:21 -05002554 broadcastRingerMode(AudioManager.RINGER_MODE_CHANGED_ACTION, ringerMode);
John Spurlocke5b42d92014-10-15 12:03:48 -04002555 }
2556
John Spurlock50ced3f2015-05-11 16:00:09 -04002557 private void muteRingerModeStreams() {
Beverlyd6964762018-02-16 14:07:03 -05002558 // Mute stream if not previously muted by ringer mode and (ringer mode
2559 // is not RINGER_MODE_NORMAL OR stream is zen muted) and stream is affected by ringer mode.
2560 // Unmute stream if previously muted by ringer/zen mode and ringer mode
Eric Laurent5b4e6542010-03-19 20:02:21 -07002561 // is RINGER_MODE_NORMAL or stream is not affected by ringer mode.
Jason Parekhb1096152009-03-24 17:48:25 -07002562 int numStreamTypes = AudioSystem.getNumStreamTypes();
Beverly925cde82018-01-23 09:31:23 -05002563
2564 if (mNm == null) {
2565 mNm = (NotificationManager) mContext.getSystemService(Context.NOTIFICATION_SERVICE);
2566 }
2567
Jack He6dd78c12018-02-12 21:00:24 -08002568 final int ringerMode = mRingerMode; // Read ringer mode as reading primitives is atomic
2569 final boolean ringerModeMute = ringerMode == AudioManager.RINGER_MODE_VIBRATE
2570 || ringerMode == AudioManager.RINGER_MODE_SILENT;
2571 final boolean shouldRingSco = ringerMode == AudioManager.RINGER_MODE_VIBRATE
2572 && isBluetoothScoOn();
2573 // Ask audio policy engine to force use Bluetooth SCO channel if needed
2574 final String eventSource = "muteRingerModeStreams() from u/pid:" + Binder.getCallingUid()
2575 + "/" + Binder.getCallingPid();
2576 sendMsg(mAudioHandler, MSG_SET_FORCE_USE, SENDMSG_QUEUE, AudioSystem.FOR_VIBRATE_RINGING,
2577 shouldRingSco ? AudioSystem.FORCE_BT_SCO : AudioSystem.FORCE_NONE, eventSource, 0);
Beverly925cde82018-01-23 09:31:23 -05002578
Eric Laurent5b4e6542010-03-19 20:02:21 -07002579 for (int streamType = numStreamTypes - 1; streamType >= 0; streamType--) {
Beverlyd6964762018-02-16 14:07:03 -05002580 final boolean isMuted = isStreamMutedByRingerOrZenMode(streamType);
Jack He6dd78c12018-02-12 21:00:24 -08002581 final boolean muteAllowedBySco =
2582 !(shouldRingSco && streamType == AudioSystem.STREAM_RING);
Beverlyd6964762018-02-16 14:07:03 -05002583 final boolean shouldZenMute = shouldZenMuteStream(streamType);
2584 final boolean shouldMute = shouldZenMute || (ringerModeMute
Jack He6dd78c12018-02-12 21:00:24 -08002585 && isStreamAffectedByRingerMode(streamType) && muteAllowedBySco);
John Spurlock661f2cf2014-11-17 10:29:10 -05002586 if (isMuted == shouldMute) continue;
2587 if (!shouldMute) {
2588 // unmute
2589 // ring and notifications volume should never be 0 when not silenced
John Spurlockd9c75db2015-04-28 11:19:13 -04002590 if (mStreamVolumeAlias[streamType] == AudioSystem.STREAM_RING) {
John Spurlock661f2cf2014-11-17 10:29:10 -05002591 synchronized (VolumeStreamState.class) {
John Spurlocka48d7792015-03-03 17:35:57 -05002592 final VolumeStreamState vss = mStreamStates[streamType];
2593 for (int i = 0; i < vss.mIndexMap.size(); i++) {
2594 int device = vss.mIndexMap.keyAt(i);
2595 int value = vss.mIndexMap.valueAt(i);
John Spurlock2bb02ec2015-03-02 13:13:06 -05002596 if (value == 0) {
John Spurlocka48d7792015-03-03 17:35:57 -05002597 vss.setIndex(10, device, TAG);
Eric Laurent9bc8358d2011-11-18 16:43:31 -08002598 }
2599 }
Eric Laurent9e0d25f2015-02-12 17:28:53 -08002600 // Persist volume for stream ring when it is changed here
2601 final int device = getDeviceForStream(streamType);
2602 sendMsg(mAudioHandler,
2603 MSG_PERSIST_VOLUME,
2604 SENDMSG_QUEUE,
2605 device,
2606 0,
2607 mStreamStates[streamType],
2608 PERSIST_DELAY);
Eric Laurentb024c302011-10-14 17:19:27 -07002609 }
Eric Laurent9bcf4012009-06-12 06:09:28 -07002610 }
RoboErik4197cb62015-01-21 15:45:32 -08002611 mStreamStates[streamType].mute(false);
Beverlyd6964762018-02-16 14:07:03 -05002612 mRingerAndZenModeMutedStreams &= ~(1 << streamType);
Eric Laurent5b4e6542010-03-19 20:02:21 -07002613 } else {
John Spurlock661f2cf2014-11-17 10:29:10 -05002614 // mute
RoboErik4197cb62015-01-21 15:45:32 -08002615 mStreamStates[streamType].mute(true);
Beverlyd6964762018-02-16 14:07:03 -05002616 mRingerAndZenModeMutedStreams |= (1 << streamType);
Jason Parekhb1096152009-03-24 17:48:25 -07002617 }
2618 }
John Spurlock50ced3f2015-05-11 16:00:09 -04002619 }
2620
Beverly925cde82018-01-23 09:31:23 -05002621 private boolean isAlarm(int streamType) {
2622 return streamType == AudioSystem.STREAM_ALARM;
2623 }
2624
2625 private boolean isNotificationOrRinger(int streamType) {
2626 return streamType == AudioSystem.STREAM_NOTIFICATION
2627 || streamType == AudioSystem.STREAM_RING;
2628 }
2629
2630 private boolean isMedia(int streamType) {
Beverlyd6964762018-02-16 14:07:03 -05002631 return streamType == AudioSystem.STREAM_MUSIC;
2632 }
2633
2634
2635 private boolean isSystem(int streamType) {
2636 return streamType == AudioSystem.STREAM_SYSTEM;
Beverly925cde82018-01-23 09:31:23 -05002637 }
2638
John Spurlock50ced3f2015-05-11 16:00:09 -04002639 private void setRingerModeInt(int ringerMode, boolean persist) {
2640 final boolean change;
2641 synchronized(mSettingsLock) {
2642 change = mRingerMode != ringerMode;
2643 mRingerMode = ringerMode;
2644 }
2645
2646 muteRingerModeStreams();
Eric Laurenta553c252009-07-17 12:17:14 -07002647
Jason Parekhb1096152009-03-24 17:48:25 -07002648 // Post a persist ringer mode msg
Eric Laurent4050c932009-07-08 02:52:14 -07002649 if (persist) {
Eric Laurentafbb0472011-12-15 09:04:23 -08002650 sendMsg(mAudioHandler, MSG_PERSIST_RINGER_MODE,
Eric Laurent4050c932009-07-08 02:52:14 -07002651 SENDMSG_REPLACE, 0, 0, null, PERSIST_DELAY);
2652 }
John Spurlockbcc10872014-11-28 15:29:21 -05002653 if (change) {
2654 // Send sticky broadcast
2655 broadcastRingerMode(AudioManager.INTERNAL_RINGER_MODE_CHANGED_ACTION, ringerMode);
2656 }
Jason Parekhb1096152009-03-24 17:48:25 -07002657 }
2658
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002659 /** @see AudioManager#shouldVibrate(int) */
2660 public boolean shouldVibrate(int vibrateType) {
Eric Laurentbffc3d12012-05-07 17:43:49 -07002661 if (!mHasVibrator) return false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002662
2663 switch (getVibrateSetting(vibrateType)) {
2664
2665 case AudioManager.VIBRATE_SETTING_ON:
John Spurlock57627792014-12-11 11:29:54 -05002666 return getRingerModeExternal() != AudioManager.RINGER_MODE_SILENT;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002667
2668 case AudioManager.VIBRATE_SETTING_ONLY_SILENT:
John Spurlock57627792014-12-11 11:29:54 -05002669 return getRingerModeExternal() == AudioManager.RINGER_MODE_VIBRATE;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002670
2671 case AudioManager.VIBRATE_SETTING_OFF:
Daniel Sandlerbcac4962010-04-12 13:23:57 -04002672 // return false, even for incoming calls
2673 return false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002674
2675 default:
2676 return false;
2677 }
2678 }
2679
2680 /** @see AudioManager#getVibrateSetting(int) */
2681 public int getVibrateSetting(int vibrateType) {
Eric Laurentbffc3d12012-05-07 17:43:49 -07002682 if (!mHasVibrator) return AudioManager.VIBRATE_SETTING_OFF;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002683 return (mVibrateSetting >> (vibrateType * 2)) & 3;
2684 }
2685
2686 /** @see AudioManager#setVibrateSetting(int, int) */
2687 public void setVibrateSetting(int vibrateType, int vibrateSetting) {
2688
Eric Laurentbffc3d12012-05-07 17:43:49 -07002689 if (!mHasVibrator) return;
2690
John Spurlock61560172015-02-06 19:46:04 -05002691 mVibrateSetting = AudioSystem.getValueForVibrateSetting(mVibrateSetting, vibrateType,
2692 vibrateSetting);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002693
2694 // Broadcast change
2695 broadcastVibrateSetting(vibrateType);
2696
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002697 }
2698
Eric Laurent9272b4b2010-01-23 17:12:59 -08002699 private class SetModeDeathHandler implements IBinder.DeathRecipient {
2700 private IBinder mCb; // To be notified of client's death
Marco Nelissenf1ddd512011-08-10 14:15:44 -07002701 private int mPid;
Eric Laurent9272b4b2010-01-23 17:12:59 -08002702 private int mMode = AudioSystem.MODE_NORMAL; // Current mode set by this client
2703
Eric Laurent9f103de2011-09-08 15:04:23 -07002704 SetModeDeathHandler(IBinder cb, int pid) {
Eric Laurent9272b4b2010-01-23 17:12:59 -08002705 mCb = cb;
Eric Laurent9f103de2011-09-08 15:04:23 -07002706 mPid = pid;
Eric Laurent9272b4b2010-01-23 17:12:59 -08002707 }
2708
2709 public void binderDied() {
Eric Laurentd7454be2011-09-14 08:45:58 -07002710 int newModeOwnerPid = 0;
Eric Laurent9272b4b2010-01-23 17:12:59 -08002711 synchronized(mSetModeDeathHandlers) {
2712 Log.w(TAG, "setMode() client died");
2713 int index = mSetModeDeathHandlers.indexOf(this);
2714 if (index < 0) {
2715 Log.w(TAG, "unregistered setMode() client died");
2716 } else {
John Spurlock90874332015-03-10 16:00:54 -04002717 newModeOwnerPid = setModeInt(AudioSystem.MODE_NORMAL, mCb, mPid, TAG);
Eric Laurent9272b4b2010-01-23 17:12:59 -08002718 }
2719 }
Eric Laurent9f103de2011-09-08 15:04:23 -07002720 // when entering RINGTONE, IN_CALL or IN_COMMUNICATION mode, clear all
2721 // SCO connections not started by the application changing the mode
Eric Laurentd7454be2011-09-14 08:45:58 -07002722 if (newModeOwnerPid != 0) {
Eric Laurent6b5e22d2013-03-28 16:10:45 -07002723 final long ident = Binder.clearCallingIdentity();
2724 disconnectBluetoothSco(newModeOwnerPid);
2725 Binder.restoreCallingIdentity(ident);
Eric Laurent9f103de2011-09-08 15:04:23 -07002726 }
Eric Laurent9272b4b2010-01-23 17:12:59 -08002727 }
2728
Marco Nelissenf1ddd512011-08-10 14:15:44 -07002729 public int getPid() {
2730 return mPid;
2731 }
2732
Eric Laurent9272b4b2010-01-23 17:12:59 -08002733 public void setMode(int mode) {
2734 mMode = mode;
2735 }
2736
2737 public int getMode() {
2738 return mMode;
2739 }
2740
2741 public IBinder getBinder() {
2742 return mCb;
2743 }
2744 }
2745
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002746 /** @see AudioManager#setMode(int) */
John Spurlock90874332015-03-10 16:00:54 -04002747 public void setMode(int mode, IBinder cb, String callingPackage) {
2748 if (DEBUG_MODE) { Log.v(TAG, "setMode(mode=" + mode + ", callingPackage=" + callingPackage + ")"); }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002749 if (!checkAudioSettingsPermission("setMode()")) {
2750 return;
2751 }
Eric Laurenta553c252009-07-17 12:17:14 -07002752
Jean-Michel Triviccd654e2014-09-03 17:48:47 -07002753 if ( (mode == AudioSystem.MODE_IN_CALL) &&
2754 (mContext.checkCallingOrSelfPermission(
2755 android.Manifest.permission.MODIFY_PHONE_STATE)
2756 != PackageManager.PERMISSION_GRANTED)) {
2757 Log.w(TAG, "MODIFY_PHONE_STATE Permission Denial: setMode(MODE_IN_CALL) from pid="
2758 + Binder.getCallingPid() + ", uid=" + Binder.getCallingUid());
2759 return;
2760 }
2761
Jean-Michel Trivi8f677d62010-11-15 12:11:32 -08002762 if (mode < AudioSystem.MODE_CURRENT || mode >= AudioSystem.NUM_MODES) {
Eric Laurenta553c252009-07-17 12:17:14 -07002763 return;
2764 }
2765
Eric Laurentd7454be2011-09-14 08:45:58 -07002766 int newModeOwnerPid = 0;
Eric Laurent9f103de2011-09-08 15:04:23 -07002767 synchronized(mSetModeDeathHandlers) {
Eric Laurenta553c252009-07-17 12:17:14 -07002768 if (mode == AudioSystem.MODE_CURRENT) {
2769 mode = mMode;
2770 }
John Spurlock90874332015-03-10 16:00:54 -04002771 newModeOwnerPid = setModeInt(mode, cb, Binder.getCallingPid(), callingPackage);
Eric Laurent9f103de2011-09-08 15:04:23 -07002772 }
2773 // when entering RINGTONE, IN_CALL or IN_COMMUNICATION mode, clear all
2774 // SCO connections not started by the application changing the mode
Eric Laurentd7454be2011-09-14 08:45:58 -07002775 if (newModeOwnerPid != 0) {
2776 disconnectBluetoothSco(newModeOwnerPid);
Eric Laurent9f103de2011-09-08 15:04:23 -07002777 }
2778 }
Jean-Michel Trivi2ade5762010-12-11 13:18:30 -08002779
Eric Laurent9f103de2011-09-08 15:04:23 -07002780 // must be called synchronized on mSetModeDeathHandlers
Eric Laurentd7454be2011-09-14 08:45:58 -07002781 // setModeInt() returns a valid PID if the audio mode was successfully set to
Eric Laurent9f103de2011-09-08 15:04:23 -07002782 // any mode other than NORMAL.
John Spurlock90874332015-03-10 16:00:54 -04002783 private int setModeInt(int mode, IBinder cb, int pid, String caller) {
2784 if (DEBUG_MODE) { Log.v(TAG, "setModeInt(mode=" + mode + ", pid=" + pid + ", caller="
2785 + caller + ")"); }
Eric Laurentd7454be2011-09-14 08:45:58 -07002786 int newModeOwnerPid = 0;
Eric Laurent9f103de2011-09-08 15:04:23 -07002787 if (cb == null) {
2788 Log.e(TAG, "setModeInt() called with null binder");
Eric Laurentd7454be2011-09-14 08:45:58 -07002789 return newModeOwnerPid;
Eric Laurent9f103de2011-09-08 15:04:23 -07002790 }
Jean-Michel Trivi2ade5762010-12-11 13:18:30 -08002791
Eric Laurent9f103de2011-09-08 15:04:23 -07002792 SetModeDeathHandler hdlr = null;
2793 Iterator iter = mSetModeDeathHandlers.iterator();
2794 while (iter.hasNext()) {
2795 SetModeDeathHandler h = (SetModeDeathHandler)iter.next();
2796 if (h.getPid() == pid) {
2797 hdlr = h;
2798 // Remove from client list so that it is re-inserted at top of list
2799 iter.remove();
2800 hdlr.getBinder().unlinkToDeath(hdlr, 0);
2801 break;
2802 }
2803 }
2804 int status = AudioSystem.AUDIO_STATUS_OK;
Eric Laurent6afa6502017-09-28 15:18:19 -07002805 int actualMode;
Eric Laurent9f103de2011-09-08 15:04:23 -07002806 do {
Eric Laurent6afa6502017-09-28 15:18:19 -07002807 actualMode = mode;
Eric Laurent9f103de2011-09-08 15:04:23 -07002808 if (mode == AudioSystem.MODE_NORMAL) {
2809 // get new mode from client at top the list if any
2810 if (!mSetModeDeathHandlers.isEmpty()) {
2811 hdlr = mSetModeDeathHandlers.get(0);
2812 cb = hdlr.getBinder();
Eric Laurent6afa6502017-09-28 15:18:19 -07002813 actualMode = hdlr.getMode();
Jean-Michel Trivi339567d2014-07-29 09:53:34 -07002814 if (DEBUG_MODE) {
2815 Log.w(TAG, " using mode=" + mode + " instead due to death hdlr at pid="
2816 + hdlr.mPid);
2817 }
Eric Laurentb9c9d262009-05-06 08:13:20 -07002818 }
Eric Laurent9f103de2011-09-08 15:04:23 -07002819 } else {
2820 if (hdlr == null) {
2821 hdlr = new SetModeDeathHandler(cb, pid);
2822 }
2823 // Register for client death notification
2824 try {
2825 cb.linkToDeath(hdlr, 0);
2826 } catch (RemoteException e) {
2827 // Client has died!
2828 Log.w(TAG, "setMode() could not link to "+cb+" binder death");
2829 }
2830
2831 // Last client to call setMode() is always at top of client list
2832 // as required by SetModeDeathHandler.binderDied()
2833 mSetModeDeathHandlers.add(0, hdlr);
2834 hdlr.setMode(mode);
2835 }
2836
Eric Laurent6afa6502017-09-28 15:18:19 -07002837 if (actualMode != mMode) {
Eric Laurent66b69672018-01-26 18:30:51 -08002838 final long identity = Binder.clearCallingIdentity();
Eric Laurent6afa6502017-09-28 15:18:19 -07002839 status = AudioSystem.setPhoneState(actualMode);
Eric Laurent66b69672018-01-26 18:30:51 -08002840 Binder.restoreCallingIdentity(identity);
Eric Laurent9f103de2011-09-08 15:04:23 -07002841 if (status == AudioSystem.AUDIO_STATUS_OK) {
Eric Laurent6afa6502017-09-28 15:18:19 -07002842 if (DEBUG_MODE) { Log.v(TAG, " mode successfully set to " + actualMode); }
2843 mMode = actualMode;
Eric Laurent9f103de2011-09-08 15:04:23 -07002844 } else {
2845 if (hdlr != null) {
2846 mSetModeDeathHandlers.remove(hdlr);
2847 cb.unlinkToDeath(hdlr, 0);
2848 }
2849 // force reading new top of mSetModeDeathHandlers stack
Jean-Michel Trivi339567d2014-07-29 09:53:34 -07002850 if (DEBUG_MODE) { Log.w(TAG, " mode set to MODE_NORMAL after phoneState pb"); }
Eric Laurent9f103de2011-09-08 15:04:23 -07002851 mode = AudioSystem.MODE_NORMAL;
2852 }
2853 } else {
2854 status = AudioSystem.AUDIO_STATUS_OK;
2855 }
2856 } while (status != AudioSystem.AUDIO_STATUS_OK && !mSetModeDeathHandlers.isEmpty());
2857
2858 if (status == AudioSystem.AUDIO_STATUS_OK) {
Eric Laurent6afa6502017-09-28 15:18:19 -07002859 if (actualMode != AudioSystem.MODE_NORMAL) {
Eric Laurentd7454be2011-09-14 08:45:58 -07002860 if (mSetModeDeathHandlers.isEmpty()) {
2861 Log.e(TAG, "setMode() different from MODE_NORMAL with empty mode client stack");
2862 } else {
2863 newModeOwnerPid = mSetModeDeathHandlers.get(0).getPid();
2864 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002865 }
Eric Laurent6afa6502017-09-28 15:18:19 -07002866 // Note: newModeOwnerPid is always 0 when actualMode is MODE_NORMAL
2867 mModeLogger.log(
2868 new PhoneStateEvent(caller, pid, mode, newModeOwnerPid, actualMode));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002869 int streamType = getActiveStreamType(AudioManager.USE_DEFAULT_STREAM_TYPE);
Eric Laurent9bc8358d2011-11-18 16:43:31 -08002870 int device = getDeviceForStream(streamType);
Eric Laurent42b041e2013-03-29 11:36:03 -07002871 int index = mStreamStates[mStreamVolumeAlias[streamType]].getIndex(device);
John Spurlock90874332015-03-10 16:00:54 -04002872 setStreamVolumeInt(mStreamVolumeAlias[streamType], index, device, true, caller);
Eric Laurent6d517662012-04-23 18:42:39 -07002873
John Spurlock90874332015-03-10 16:00:54 -04002874 updateStreamVolumeAlias(true /*updateVolumes*/, caller);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002875 }
Eric Laurentd7454be2011-09-14 08:45:58 -07002876 return newModeOwnerPid;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002877 }
2878
2879 /** @see AudioManager#getMode() */
2880 public int getMode() {
2881 return mMode;
2882 }
2883
Eric Laurente78fced2013-03-15 16:03:47 -07002884 //==========================================================================================
2885 // Sound Effects
2886 //==========================================================================================
2887
2888 private static final String TAG_AUDIO_ASSETS = "audio_assets";
2889 private static final String ATTR_VERSION = "version";
2890 private static final String TAG_GROUP = "group";
2891 private static final String ATTR_GROUP_NAME = "name";
2892 private static final String TAG_ASSET = "asset";
2893 private static final String ATTR_ASSET_ID = "id";
2894 private static final String ATTR_ASSET_FILE = "file";
2895
2896 private static final String ASSET_FILE_VERSION = "1.0";
2897 private static final String GROUP_TOUCH_SOUNDS = "touch_sounds";
2898
Glenn Kasten167d1a22013-07-23 16:24:41 -07002899 private static final int SOUND_EFFECTS_LOAD_TIMEOUT_MS = 5000;
Eric Laurent5d3eb44a2013-03-21 15:35:10 -07002900
2901 class LoadSoundEffectReply {
2902 public int mStatus = 1;
2903 };
2904
Eric Laurente78fced2013-03-15 16:03:47 -07002905 private void loadTouchSoundAssetDefaults() {
2906 SOUND_EFFECT_FILES.add("Effect_Tick.ogg");
2907 for (int i = 0; i < AudioManager.NUM_SOUND_EFFECTS; i++) {
2908 SOUND_EFFECT_FILES_MAP[i][0] = 0;
2909 SOUND_EFFECT_FILES_MAP[i][1] = -1;
2910 }
2911 }
2912
2913 private void loadTouchSoundAssets() {
2914 XmlResourceParser parser = null;
2915
Eric Laurent5d3eb44a2013-03-21 15:35:10 -07002916 // only load assets once.
2917 if (!SOUND_EFFECT_FILES.isEmpty()) {
2918 return;
2919 }
2920
Eric Laurente78fced2013-03-15 16:03:47 -07002921 loadTouchSoundAssetDefaults();
2922
2923 try {
2924 parser = mContext.getResources().getXml(com.android.internal.R.xml.audio_assets);
2925
2926 XmlUtils.beginDocument(parser, TAG_AUDIO_ASSETS);
2927 String version = parser.getAttributeValue(null, ATTR_VERSION);
2928 boolean inTouchSoundsGroup = false;
2929
2930 if (ASSET_FILE_VERSION.equals(version)) {
2931 while (true) {
2932 XmlUtils.nextElement(parser);
2933 String element = parser.getName();
2934 if (element == null) {
2935 break;
2936 }
2937 if (element.equals(TAG_GROUP)) {
2938 String name = parser.getAttributeValue(null, ATTR_GROUP_NAME);
2939 if (GROUP_TOUCH_SOUNDS.equals(name)) {
2940 inTouchSoundsGroup = true;
2941 break;
2942 }
2943 }
2944 }
2945 while (inTouchSoundsGroup) {
2946 XmlUtils.nextElement(parser);
2947 String element = parser.getName();
2948 if (element == null) {
2949 break;
2950 }
2951 if (element.equals(TAG_ASSET)) {
2952 String id = parser.getAttributeValue(null, ATTR_ASSET_ID);
2953 String file = parser.getAttributeValue(null, ATTR_ASSET_FILE);
2954 int fx;
2955
2956 try {
2957 Field field = AudioManager.class.getField(id);
2958 fx = field.getInt(null);
2959 } catch (Exception e) {
2960 Log.w(TAG, "Invalid touch sound ID: "+id);
2961 continue;
2962 }
2963
2964 int i = SOUND_EFFECT_FILES.indexOf(file);
2965 if (i == -1) {
2966 i = SOUND_EFFECT_FILES.size();
2967 SOUND_EFFECT_FILES.add(file);
2968 }
2969 SOUND_EFFECT_FILES_MAP[fx][0] = i;
2970 } else {
2971 break;
2972 }
2973 }
2974 }
2975 } catch (Resources.NotFoundException e) {
2976 Log.w(TAG, "audio assets file not found", e);
2977 } catch (XmlPullParserException e) {
2978 Log.w(TAG, "XML parser exception reading touch sound assets", e);
2979 } catch (IOException e) {
2980 Log.w(TAG, "I/O exception reading touch sound assets", e);
2981 } finally {
2982 if (parser != null) {
2983 parser.close();
2984 }
2985 }
2986 }
2987
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002988 /** @see AudioManager#playSoundEffect(int) */
2989 public void playSoundEffect(int effectType) {
Eric Laurent5d3eb44a2013-03-21 15:35:10 -07002990 playSoundEffectVolume(effectType, -1.0f);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002991 }
2992
2993 /** @see AudioManager#playSoundEffect(int, float) */
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002994 public void playSoundEffectVolume(int effectType, float volume) {
Beverlyd6964762018-02-16 14:07:03 -05002995 // do not try to play the sound effect if the system stream is muted
2996 if (isStreamMutedByRingerOrZenMode(STREAM_SYSTEM)) {
2997 return;
2998 }
2999
Natalie Silvanovich559c76d2014-05-01 10:16:24 -07003000 if (effectType >= AudioManager.NUM_SOUND_EFFECTS || effectType < 0) {
3001 Log.w(TAG, "AudioService effectType value " + effectType + " out of range");
3002 return;
3003 }
3004
Eric Laurent5d3eb44a2013-03-21 15:35:10 -07003005 sendMsg(mAudioHandler, MSG_PLAY_SOUND_EFFECT, SENDMSG_QUEUE,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003006 effectType, (int) (volume * 1000), null, 0);
3007 }
3008
3009 /**
3010 * Loads samples into the soundpool.
Glenn Kasten5c17a822011-11-30 09:41:01 -08003011 * This method must be called at first when sound effects are enabled
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003012 */
3013 public boolean loadSoundEffects() {
Eric Laurent5d3eb44a2013-03-21 15:35:10 -07003014 int attempts = 3;
3015 LoadSoundEffectReply reply = new LoadSoundEffectReply();
Eric Laurenta60e2122010-12-28 16:49:07 -08003016
Eric Laurent5d3eb44a2013-03-21 15:35:10 -07003017 synchronized (reply) {
3018 sendMsg(mAudioHandler, MSG_LOAD_SOUND_EFFECTS, SENDMSG_QUEUE, 0, 0, reply, 0);
3019 while ((reply.mStatus == 1) && (attempts-- > 0)) {
Eric Laurent117b7bb2011-01-16 17:07:27 -08003020 try {
Glenn Kasten167d1a22013-07-23 16:24:41 -07003021 reply.wait(SOUND_EFFECTS_LOAD_TIMEOUT_MS);
Eric Laurent5d3eb44a2013-03-21 15:35:10 -07003022 } catch (InterruptedException e) {
3023 Log.w(TAG, "loadSoundEffects Interrupted while waiting sound pool loaded.");
Eric Laurent117b7bb2011-01-16 17:07:27 -08003024 }
Eric Laurenta60e2122010-12-28 16:49:07 -08003025 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003026 }
Eric Laurent5d3eb44a2013-03-21 15:35:10 -07003027 return (reply.mStatus == 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003028 }
3029
3030 /**
3031 * Unloads samples from the sound pool.
3032 * This method can be called to free some memory when
3033 * sound effects are disabled.
3034 */
3035 public void unloadSoundEffects() {
Eric Laurent5d3eb44a2013-03-21 15:35:10 -07003036 sendMsg(mAudioHandler, MSG_UNLOAD_SOUND_EFFECTS, SENDMSG_QUEUE, 0, 0, null, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003037 }
3038
Eric Laurenta60e2122010-12-28 16:49:07 -08003039 class SoundPoolListenerThread extends Thread {
3040 public SoundPoolListenerThread() {
3041 super("SoundPoolListenerThread");
3042 }
3043
3044 @Override
3045 public void run() {
3046
3047 Looper.prepare();
3048 mSoundPoolLooper = Looper.myLooper();
3049
3050 synchronized (mSoundEffectsLock) {
3051 if (mSoundPool != null) {
3052 mSoundPoolCallBack = new SoundPoolCallback();
3053 mSoundPool.setOnLoadCompleteListener(mSoundPoolCallBack);
3054 }
3055 mSoundEffectsLock.notify();
3056 }
3057 Looper.loop();
3058 }
3059 }
3060
3061 private final class SoundPoolCallback implements
3062 android.media.SoundPool.OnLoadCompleteListener {
3063
Eric Laurent5d3eb44a2013-03-21 15:35:10 -07003064 int mStatus = 1; // 1 means neither error nor last sample loaded yet
3065 List<Integer> mSamples = new ArrayList<Integer>();
Eric Laurenta60e2122010-12-28 16:49:07 -08003066
3067 public int status() {
3068 return mStatus;
3069 }
3070
Eric Laurent5d3eb44a2013-03-21 15:35:10 -07003071 public void setSamples(int[] samples) {
3072 for (int i = 0; i < samples.length; i++) {
3073 // do not wait ack for samples rejected upfront by SoundPool
3074 if (samples[i] > 0) {
3075 mSamples.add(samples[i]);
3076 }
3077 }
Eric Laurenta60e2122010-12-28 16:49:07 -08003078 }
3079
3080 public void onLoadComplete(SoundPool soundPool, int sampleId, int status) {
3081 synchronized (mSoundEffectsLock) {
Eric Laurent5d3eb44a2013-03-21 15:35:10 -07003082 int i = mSamples.indexOf(sampleId);
3083 if (i >= 0) {
3084 mSamples.remove(i);
Eric Laurenta60e2122010-12-28 16:49:07 -08003085 }
Eric Laurent5d3eb44a2013-03-21 15:35:10 -07003086 if ((status != 0) || mSamples. isEmpty()) {
3087 mStatus = status;
Eric Laurenta60e2122010-12-28 16:49:07 -08003088 mSoundEffectsLock.notify();
3089 }
3090 }
3091 }
3092 }
3093
Eric Laurent4050c932009-07-08 02:52:14 -07003094 /** @see AudioManager#reloadAudioSettings() */
3095 public void reloadAudioSettings() {
Eric Laurentbc0fab1f2012-09-19 11:24:41 -07003096 readAudioSettings(false /*userSwitch*/);
3097 }
3098
3099 private void readAudioSettings(boolean userSwitch) {
Eric Laurent4050c932009-07-08 02:52:14 -07003100 // restore ringer mode, ringer mode affected streams, mute affected streams and vibrate settings
3101 readPersistedSettings();
Eric Laurentc0232482016-03-15 18:19:23 -07003102 readUserRestrictions();
Eric Laurent4050c932009-07-08 02:52:14 -07003103
3104 // restore volume settings
3105 int numStreamTypes = AudioSystem.getNumStreamTypes();
3106 for (int streamType = 0; streamType < numStreamTypes; streamType++) {
3107 VolumeStreamState streamState = mStreamStates[streamType];
3108
Eric Laurentbc0fab1f2012-09-19 11:24:41 -07003109 if (userSwitch && mStreamVolumeAlias[streamType] == AudioSystem.STREAM_MUSIC) {
3110 continue;
3111 }
3112
Eric Laurent8fa4d6f2014-10-30 14:13:03 -07003113 streamState.readSettings();
3114 synchronized (VolumeStreamState.class) {
Eric Laurent3172d5e2012-05-09 11:38:16 -07003115 // unmute stream that was muted but is not affect by mute anymore
RoboErik4197cb62015-01-21 15:45:32 -08003116 if (streamState.mIsMuted && ((!isStreamAffectedByMute(streamType) &&
Beverlyd6964762018-02-16 14:07:03 -05003117 !isStreamMutedByRingerOrZenMode(streamType)) || mUseFixedVolume)) {
RoboErik4197cb62015-01-21 15:45:32 -08003118 streamState.mIsMuted = false;
Eric Laurent4050c932009-07-08 02:52:14 -07003119 }
Eric Laurent4050c932009-07-08 02:52:14 -07003120 }
3121 }
3122
Eric Laurent33902db2012-10-07 16:15:07 -07003123 // apply new ringer mode before checking volume for alias streams so that streams
3124 // muted by ringer mode have the correct volume
John Spurlock661f2cf2014-11-17 10:29:10 -05003125 setRingerModeInt(getRingerModeInternal(), false);
Eric Laurent33902db2012-10-07 16:15:07 -07003126
Eric Laurent212532b2014-07-21 15:43:18 -07003127 checkAllFixedVolumeDevices();
Eric Laurent24482012012-05-10 09:41:17 -07003128 checkAllAliasStreamVolumes();
John Spurlockb6e19e32015-03-10 21:33:44 -04003129 checkMuteAffectedStreams();
Eric Laurent24482012012-05-10 09:41:17 -07003130
Eric Laurentd640bd32012-09-28 18:01:48 -07003131 synchronized (mSafeMediaVolumeState) {
John Spurlockaa5ee4d2014-07-25 13:05:12 -04003132 mMusicActiveMs = MathUtils.constrain(Settings.Secure.getIntForUser(mContentResolver,
3133 Settings.Secure.UNSAFE_VOLUME_MUSIC_ACTIVE_MS, 0, UserHandle.USER_CURRENT),
3134 0, UNSAFE_VOLUME_MUSIC_ACTIVE_MS_MAX);
Eric Laurentd640bd32012-09-28 18:01:48 -07003135 if (mSafeMediaVolumeState == SAFE_MEDIA_VOLUME_ACTIVE) {
John Spurlock90874332015-03-10 16:00:54 -04003136 enforceSafeMediaVolume(TAG);
Eric Laurentf1a457d2012-09-20 16:27:23 -07003137 }
Eric Laurentc34dcc12012-09-10 13:51:52 -07003138 }
Eric Laurent4050c932009-07-08 02:52:14 -07003139 }
3140
Dianne Hackborn961cae92013-03-20 14:59:43 -07003141 /** @see AudioManager#setSpeakerphoneOn(boolean) */
Eric Laurentc42ac9d2009-07-29 08:53:03 -07003142 public void setSpeakerphoneOn(boolean on){
Eric Laurentdc1d17a2009-09-10 00:48:21 -07003143 if (!checkAudioSettingsPermission("setSpeakerphoneOn()")) {
3144 return;
3145 }
Jean-Michel Trivi011f39e2017-08-19 18:08:06 -07003146 // for logging only
3147 final String eventSource = new StringBuilder("setSpeakerphoneOn(").append(on)
3148 .append(") from u/pid:").append(Binder.getCallingUid()).append("/")
3149 .append(Binder.getCallingPid()).toString();
Johan Gustavsson7337bee2013-03-01 15:53:30 +01003150
3151 if (on) {
3152 if (mForcedUseForComm == AudioSystem.FORCE_BT_SCO) {
3153 sendMsg(mAudioHandler, MSG_SET_FORCE_USE, SENDMSG_QUEUE,
Jean-Michel Trivi011f39e2017-08-19 18:08:06 -07003154 AudioSystem.FOR_RECORD, AudioSystem.FORCE_NONE,
3155 eventSource, 0);
Johan Gustavsson7337bee2013-03-01 15:53:30 +01003156 }
3157 mForcedUseForComm = AudioSystem.FORCE_SPEAKER;
3158 } else if (mForcedUseForComm == AudioSystem.FORCE_SPEAKER){
3159 mForcedUseForComm = AudioSystem.FORCE_NONE;
3160 }
Eric Laurentfa640152011-03-12 15:59:51 -08003161
Sharad Sangle1d188442017-05-09 16:05:40 +05303162 mForcedUseForCommExt = mForcedUseForComm;
Eric Laurentafbb0472011-12-15 09:04:23 -08003163 sendMsg(mAudioHandler, MSG_SET_FORCE_USE, SENDMSG_QUEUE,
Jean-Michel Trivi011f39e2017-08-19 18:08:06 -07003164 AudioSystem.FOR_COMMUNICATION, mForcedUseForComm, eventSource, 0);
Eric Laurentc42ac9d2009-07-29 08:53:03 -07003165 }
3166
3167 /** @see AudioManager#isSpeakerphoneOn() */
3168 public boolean isSpeakerphoneOn() {
Sharad Sangle1d188442017-05-09 16:05:40 +05303169 return (mForcedUseForCommExt == AudioSystem.FORCE_SPEAKER);
Eric Laurentc42ac9d2009-07-29 08:53:03 -07003170 }
3171
Dianne Hackborn961cae92013-03-20 14:59:43 -07003172 /** @see AudioManager#setBluetoothScoOn(boolean) */
Eric Laurent48221252015-09-24 18:41:48 -07003173 public void setBluetoothScoOn(boolean on) {
Eric Laurentdc1d17a2009-09-10 00:48:21 -07003174 if (!checkAudioSettingsPermission("setBluetoothScoOn()")) {
3175 return;
3176 }
Sharad Sangle1d188442017-05-09 16:05:40 +05303177
3178 // Only enable calls from system components
3179 if (Binder.getCallingUid() >= FIRST_APPLICATION_UID) {
3180 mForcedUseForCommExt = on ? AudioSystem.FORCE_BT_SCO : AudioSystem.FORCE_NONE;
3181 return;
3182 }
3183
Jean-Michel Trivi011f39e2017-08-19 18:08:06 -07003184 // for logging only
3185 final String eventSource = new StringBuilder("setBluetoothScoOn(").append(on)
3186 .append(") from u/pid:").append(Binder.getCallingUid()).append("/")
3187 .append(Binder.getCallingPid()).toString();
3188 setBluetoothScoOnInt(on, eventSource);
Eric Laurent48221252015-09-24 18:41:48 -07003189 }
Johan Gustavsson7337bee2013-03-01 15:53:30 +01003190
Jean-Michel Trivi011f39e2017-08-19 18:08:06 -07003191 public void setBluetoothScoOnInt(boolean on, String eventSource) {
Jack He8dd33942018-01-17 15:45:12 -08003192 if (DEBUG_DEVICES) {
3193 Log.d(TAG, "setBluetoothScoOnInt: " + on + " " + eventSource);
3194 }
Johan Gustavsson7337bee2013-03-01 15:53:30 +01003195 if (on) {
Sharad Sangle1d188442017-05-09 16:05:40 +05303196 // do not accept SCO ON if SCO audio is not connected
Jack He8dd33942018-01-17 15:45:12 -08003197 synchronized (mScoClients) {
3198 if (mBluetoothHeadset != null) {
3199 if (mBluetoothHeadsetDevice == null) {
3200 BluetoothDevice activeDevice = mBluetoothHeadset.getActiveDevice();
3201 if (activeDevice != null) {
3202 // setBtScoActiveDevice() might trigger resetBluetoothSco() which
3203 // will call setBluetoothScoOnInt(false, "resetBluetoothSco")
3204 setBtScoActiveDevice(activeDevice);
3205 }
3206 }
3207 if (mBluetoothHeadset.getAudioState(mBluetoothHeadsetDevice)
3208 != BluetoothHeadset.STATE_AUDIO_CONNECTED) {
3209 mForcedUseForCommExt = AudioSystem.FORCE_BT_SCO;
3210 Log.w(TAG, "setBluetoothScoOnInt(true) failed because "
3211 + mBluetoothHeadsetDevice + " is not in audio connected mode");
3212 return;
3213 }
Sharad Sangle1d188442017-05-09 16:05:40 +05303214 }
3215 }
Johan Gustavsson7337bee2013-03-01 15:53:30 +01003216 mForcedUseForComm = AudioSystem.FORCE_BT_SCO;
3217 } else if (mForcedUseForComm == AudioSystem.FORCE_BT_SCO) {
3218 mForcedUseForComm = AudioSystem.FORCE_NONE;
3219 }
Sharad Sangle1d188442017-05-09 16:05:40 +05303220 mForcedUseForCommExt = mForcedUseForComm;
3221 AudioSystem.setParameters("BT_SCO="+ (on ? "on" : "off"));
Eric Laurentafbb0472011-12-15 09:04:23 -08003222 sendMsg(mAudioHandler, MSG_SET_FORCE_USE, SENDMSG_QUEUE,
Jean-Michel Trivi011f39e2017-08-19 18:08:06 -07003223 AudioSystem.FOR_COMMUNICATION, mForcedUseForComm, eventSource, 0);
Eric Laurentafbb0472011-12-15 09:04:23 -08003224 sendMsg(mAudioHandler, MSG_SET_FORCE_USE, SENDMSG_QUEUE,
Jean-Michel Trivi011f39e2017-08-19 18:08:06 -07003225 AudioSystem.FOR_RECORD, mForcedUseForComm, eventSource, 0);
Jack He6dd78c12018-02-12 21:00:24 -08003226 // Un-mute ringtone stream volume
3227 setRingerModeInt(getRingerModeInternal(), false);
Eric Laurentc42ac9d2009-07-29 08:53:03 -07003228 }
3229
3230 /** @see AudioManager#isBluetoothScoOn() */
3231 public boolean isBluetoothScoOn() {
Sharad Sangle1d188442017-05-09 16:05:40 +05303232 return (mForcedUseForCommExt == AudioSystem.FORCE_BT_SCO);
Eric Laurentc42ac9d2009-07-29 08:53:03 -07003233 }
3234
Sungsoocf09fe62016-09-28 16:21:48 +09003235 /** @see AudioManager#setBluetoothA2dpOn(boolean) */
Eric Laurent78472112012-05-21 08:57:21 -07003236 public void setBluetoothA2dpOn(boolean on) {
Jean-Michel Trivi011f39e2017-08-19 18:08:06 -07003237 // for logging only
3238 final String eventSource = new StringBuilder("setBluetoothA2dpOn(").append(on)
3239 .append(") from u/pid:").append(Binder.getCallingUid()).append("/")
3240 .append(Binder.getCallingPid()).toString();
3241
Sungsoocf09fe62016-09-28 16:21:48 +09003242 synchronized (mBluetoothA2dpEnabledLock) {
3243 mBluetoothA2dpEnabled = on;
3244 sendMsg(mAudioHandler, MSG_SET_FORCE_BT_A2DP_USE, SENDMSG_QUEUE,
3245 AudioSystem.FOR_MEDIA,
3246 mBluetoothA2dpEnabled ? AudioSystem.FORCE_NONE : AudioSystem.FORCE_NO_BT_A2DP,
Jean-Michel Trivi011f39e2017-08-19 18:08:06 -07003247 eventSource, 0);
Sungsoocf09fe62016-09-28 16:21:48 +09003248 }
Eric Laurent78472112012-05-21 08:57:21 -07003249 }
3250
Sungsoocf09fe62016-09-28 16:21:48 +09003251 /** @see AudioManager#isBluetoothA2dpOn() */
Eric Laurent78472112012-05-21 08:57:21 -07003252 public boolean isBluetoothA2dpOn() {
Sungsoocf09fe62016-09-28 16:21:48 +09003253 synchronized (mBluetoothA2dpEnabledLock) {
3254 return mBluetoothA2dpEnabled;
3255 }
Eric Laurent78472112012-05-21 08:57:21 -07003256 }
3257
Eric Laurent3def1ee2010-03-17 23:26:26 -07003258 /** @see AudioManager#startBluetoothSco() */
Eric Laurent83900752014-05-15 15:14:22 -07003259 public void startBluetoothSco(IBinder cb, int targetSdkVersion) {
3260 int scoAudioMode =
3261 (targetSdkVersion < Build.VERSION_CODES.JELLY_BEAN_MR2) ?
Liejun Taof4e51d82014-07-16 11:18:29 -07003262 SCO_MODE_VIRTUAL_CALL : SCO_MODE_UNDEFINED;
Eric Laurent83900752014-05-15 15:14:22 -07003263 startBluetoothScoInt(cb, scoAudioMode);
3264 }
3265
3266 /** @see AudioManager#startBluetoothScoVirtualCall() */
3267 public void startBluetoothScoVirtualCall(IBinder cb) {
3268 startBluetoothScoInt(cb, SCO_MODE_VIRTUAL_CALL);
3269 }
3270
3271 void startBluetoothScoInt(IBinder cb, int scoAudioMode){
Eric Laurentdc03c612011-04-01 10:59:41 -07003272 if (!checkAudioSettingsPermission("startBluetoothSco()") ||
Eric Laurent4a5eeb92014-05-06 10:49:04 -07003273 !mSystemReady) {
Eric Laurent3def1ee2010-03-17 23:26:26 -07003274 return;
3275 }
Eric Laurent854938a2011-02-22 12:05:20 -08003276 ScoClient client = getScoClient(cb, true);
Eric Laurentf5a1fc32013-03-11 18:52:57 -07003277 // The calling identity must be cleared before calling ScoClient.incCount().
3278 // inCount() calls requestScoState() which in turn can call BluetoothHeadset APIs
3279 // and this must be done on behalf of system server to make sure permissions are granted.
3280 // The caller identity must be cleared after getScoClient() because it is needed if a new
3281 // client is created.
3282 final long ident = Binder.clearCallingIdentity();
Eric Laurent83900752014-05-15 15:14:22 -07003283 client.incCount(scoAudioMode);
Eric Laurent2a57ca92013-03-07 17:29:27 -08003284 Binder.restoreCallingIdentity(ident);
Eric Laurent3def1ee2010-03-17 23:26:26 -07003285 }
3286
3287 /** @see AudioManager#stopBluetoothSco() */
3288 public void stopBluetoothSco(IBinder cb){
Eric Laurentdc03c612011-04-01 10:59:41 -07003289 if (!checkAudioSettingsPermission("stopBluetoothSco()") ||
Eric Laurent4a5eeb92014-05-06 10:49:04 -07003290 !mSystemReady) {
Eric Laurent3def1ee2010-03-17 23:26:26 -07003291 return;
3292 }
Eric Laurent854938a2011-02-22 12:05:20 -08003293 ScoClient client = getScoClient(cb, false);
Eric Laurentf5a1fc32013-03-11 18:52:57 -07003294 // The calling identity must be cleared before calling ScoClient.decCount().
3295 // decCount() calls requestScoState() which in turn can call BluetoothHeadset APIs
3296 // and this must be done on behalf of system server to make sure permissions are granted.
3297 final long ident = Binder.clearCallingIdentity();
Eric Laurent854938a2011-02-22 12:05:20 -08003298 if (client != null) {
3299 client.decCount();
3300 }
Eric Laurent2a57ca92013-03-07 17:29:27 -08003301 Binder.restoreCallingIdentity(ident);
Eric Laurent3def1ee2010-03-17 23:26:26 -07003302 }
3303
Eric Laurent78472112012-05-21 08:57:21 -07003304
Eric Laurent3def1ee2010-03-17 23:26:26 -07003305 private class ScoClient implements IBinder.DeathRecipient {
3306 private IBinder mCb; // To be notified of client's death
Marco Nelissenf1ddd512011-08-10 14:15:44 -07003307 private int mCreatorPid;
Eric Laurent3def1ee2010-03-17 23:26:26 -07003308 private int mStartcount; // number of SCO connections started by this client
3309
3310 ScoClient(IBinder cb) {
3311 mCb = cb;
Marco Nelissenf1ddd512011-08-10 14:15:44 -07003312 mCreatorPid = Binder.getCallingPid();
Eric Laurent3def1ee2010-03-17 23:26:26 -07003313 mStartcount = 0;
3314 }
3315
3316 public void binderDied() {
3317 synchronized(mScoClients) {
3318 Log.w(TAG, "SCO client died");
3319 int index = mScoClients.indexOf(this);
3320 if (index < 0) {
3321 Log.w(TAG, "unregistered SCO client died");
3322 } else {
3323 clearCount(true);
3324 mScoClients.remove(this);
3325 }
3326 }
3327 }
3328
Eric Laurent83900752014-05-15 15:14:22 -07003329 public void incCount(int scoAudioMode) {
Eric Laurent3def1ee2010-03-17 23:26:26 -07003330 synchronized(mScoClients) {
Eric Laurent83900752014-05-15 15:14:22 -07003331 requestScoState(BluetoothHeadset.STATE_AUDIO_CONNECTED, scoAudioMode);
Eric Laurent3def1ee2010-03-17 23:26:26 -07003332 if (mStartcount == 0) {
3333 try {
3334 mCb.linkToDeath(this, 0);
3335 } catch (RemoteException e) {
3336 // client has already died!
3337 Log.w(TAG, "ScoClient incCount() could not link to "+mCb+" binder death");
3338 }
3339 }
3340 mStartcount++;
3341 }
3342 }
3343
3344 public void decCount() {
3345 synchronized(mScoClients) {
3346 if (mStartcount == 0) {
3347 Log.w(TAG, "ScoClient.decCount() already 0");
3348 } else {
3349 mStartcount--;
3350 if (mStartcount == 0) {
Eric Laurente2dd8c42010-06-30 19:41:56 -07003351 try {
3352 mCb.unlinkToDeath(this, 0);
3353 } catch (NoSuchElementException e) {
3354 Log.w(TAG, "decCount() going to 0 but not registered to binder");
3355 }
Eric Laurent3def1ee2010-03-17 23:26:26 -07003356 }
Eric Laurentc18c9132013-04-12 17:24:56 -07003357 requestScoState(BluetoothHeadset.STATE_AUDIO_DISCONNECTED, 0);
Eric Laurent3def1ee2010-03-17 23:26:26 -07003358 }
3359 }
3360 }
3361
3362 public void clearCount(boolean stopSco) {
3363 synchronized(mScoClients) {
Eric Laurente2dd8c42010-06-30 19:41:56 -07003364 if (mStartcount != 0) {
3365 try {
3366 mCb.unlinkToDeath(this, 0);
3367 } catch (NoSuchElementException e) {
3368 Log.w(TAG, "clearCount() mStartcount: "+mStartcount+" != 0 but not registered to binder");
3369 }
3370 }
Eric Laurent3def1ee2010-03-17 23:26:26 -07003371 mStartcount = 0;
Eric Laurent3def1ee2010-03-17 23:26:26 -07003372 if (stopSco) {
Eric Laurentc18c9132013-04-12 17:24:56 -07003373 requestScoState(BluetoothHeadset.STATE_AUDIO_DISCONNECTED, 0);
Eric Laurent3def1ee2010-03-17 23:26:26 -07003374 }
3375 }
3376 }
3377
3378 public int getCount() {
3379 return mStartcount;
3380 }
3381
3382 public IBinder getBinder() {
3383 return mCb;
3384 }
3385
Eric Laurentd7454be2011-09-14 08:45:58 -07003386 public int getPid() {
3387 return mCreatorPid;
3388 }
3389
Eric Laurent3def1ee2010-03-17 23:26:26 -07003390 public int totalCount() {
3391 synchronized(mScoClients) {
3392 int count = 0;
3393 int size = mScoClients.size();
3394 for (int i = 0; i < size; i++) {
3395 count += mScoClients.get(i).getCount();
3396 }
3397 return count;
3398 }
3399 }
3400
Eric Laurent83900752014-05-15 15:14:22 -07003401 private void requestScoState(int state, int scoAudioMode) {
Eric Laurent62ef7672010-11-24 10:58:32 -08003402 checkScoAudioState();
Eric Laurentdc03c612011-04-01 10:59:41 -07003403 if (totalCount() == 0) {
3404 if (state == BluetoothHeadset.STATE_AUDIO_CONNECTED) {
3405 // Make sure that the state transitions to CONNECTING even if we cannot initiate
3406 // the connection.
3407 broadcastScoConnectionState(AudioManager.SCO_AUDIO_STATE_CONNECTING);
3408 // Accept SCO audio activation only in NORMAL audio mode or if the mode is
Marco Nelissenf1ddd512011-08-10 14:15:44 -07003409 // currently controlled by the same client process.
Eric Laurent9f103de2011-09-08 15:04:23 -07003410 synchronized(mSetModeDeathHandlers) {
3411 if ((mSetModeDeathHandlers.isEmpty() ||
3412 mSetModeDeathHandlers.get(0).getPid() == mCreatorPid) &&
3413 (mScoAudioState == SCO_STATE_INACTIVE ||
3414 mScoAudioState == SCO_STATE_DEACTIVATE_REQ)) {
3415 if (mScoAudioState == SCO_STATE_INACTIVE) {
Eric Laurent83900752014-05-15 15:14:22 -07003416 mScoAudioMode = scoAudioMode;
Liejun Taof4e51d82014-07-16 11:18:29 -07003417 if (scoAudioMode == SCO_MODE_UNDEFINED) {
Andre Eisenbach570cc532014-10-28 17:03:18 -07003418 if (mBluetoothHeadsetDevice != null) {
3419 mScoAudioMode = new Integer(Settings.Global.getInt(
3420 mContentResolver,
3421 "bluetooth_sco_channel_"+
3422 mBluetoothHeadsetDevice.getAddress(),
3423 SCO_MODE_VIRTUAL_CALL));
3424 if (mScoAudioMode > SCO_MODE_MAX || mScoAudioMode < 0) {
3425 mScoAudioMode = SCO_MODE_VIRTUAL_CALL;
3426 }
3427 } else {
3428 mScoAudioMode = SCO_MODE_RAW;
Liejun Taof4e51d82014-07-16 11:18:29 -07003429 }
3430 }
Eric Laurent9f103de2011-09-08 15:04:23 -07003431 if (mBluetoothHeadset != null && mBluetoothHeadsetDevice != null) {
Liejun Taof4e51d82014-07-16 11:18:29 -07003432 boolean status = false;
Eric Laurentc18c9132013-04-12 17:24:56 -07003433 if (mScoAudioMode == SCO_MODE_RAW) {
3434 status = mBluetoothHeadset.connectAudio();
Liejun Taof4e51d82014-07-16 11:18:29 -07003435 } else if (mScoAudioMode == SCO_MODE_VIRTUAL_CALL) {
Eric Laurentc18c9132013-04-12 17:24:56 -07003436 status = mBluetoothHeadset.startScoUsingVirtualVoiceCall(
3437 mBluetoothHeadsetDevice);
Liejun Taof4e51d82014-07-16 11:18:29 -07003438 } else if (mScoAudioMode == SCO_MODE_VR) {
3439 status = mBluetoothHeadset.startVoiceRecognition(
3440 mBluetoothHeadsetDevice);
Eric Laurentc18c9132013-04-12 17:24:56 -07003441 }
Liejun Taof4e51d82014-07-16 11:18:29 -07003442
Eric Laurentc18c9132013-04-12 17:24:56 -07003443 if (status) {
Eric Laurent9f103de2011-09-08 15:04:23 -07003444 mScoAudioState = SCO_STATE_ACTIVE_INTERNAL;
3445 } else {
3446 broadcastScoConnectionState(
3447 AudioManager.SCO_AUDIO_STATE_DISCONNECTED);
3448 }
3449 } else if (getBluetoothHeadset()) {
3450 mScoAudioState = SCO_STATE_ACTIVATE_REQ;
Eric Laurentdc03c612011-04-01 10:59:41 -07003451 }
Eric Laurent9f103de2011-09-08 15:04:23 -07003452 } else {
3453 mScoAudioState = SCO_STATE_ACTIVE_INTERNAL;
3454 broadcastScoConnectionState(AudioManager.SCO_AUDIO_STATE_CONNECTED);
Eric Laurentdc03c612011-04-01 10:59:41 -07003455 }
3456 } else {
Eric Laurent9f103de2011-09-08 15:04:23 -07003457 broadcastScoConnectionState(AudioManager.SCO_AUDIO_STATE_DISCONNECTED);
Eric Laurentdc03c612011-04-01 10:59:41 -07003458 }
Eric Laurentdc03c612011-04-01 10:59:41 -07003459 }
Eric Laurent62ef7672010-11-24 10:58:32 -08003460 } else if (state == BluetoothHeadset.STATE_AUDIO_DISCONNECTED &&
Eric Laurentdc03c612011-04-01 10:59:41 -07003461 (mScoAudioState == SCO_STATE_ACTIVE_INTERNAL ||
3462 mScoAudioState == SCO_STATE_ACTIVATE_REQ)) {
3463 if (mScoAudioState == SCO_STATE_ACTIVE_INTERNAL) {
Marco Nelissen671db6f2011-09-06 16:29:12 -07003464 if (mBluetoothHeadset != null && mBluetoothHeadsetDevice != null) {
Liejun Taof4e51d82014-07-16 11:18:29 -07003465 boolean status = false;
Eric Laurentc18c9132013-04-12 17:24:56 -07003466 if (mScoAudioMode == SCO_MODE_RAW) {
3467 status = mBluetoothHeadset.disconnectAudio();
Liejun Taof4e51d82014-07-16 11:18:29 -07003468 } else if (mScoAudioMode == SCO_MODE_VIRTUAL_CALL) {
Eric Laurentc18c9132013-04-12 17:24:56 -07003469 status = mBluetoothHeadset.stopScoUsingVirtualVoiceCall(
3470 mBluetoothHeadsetDevice);
Liejun Taof4e51d82014-07-16 11:18:29 -07003471 } else if (mScoAudioMode == SCO_MODE_VR) {
3472 status = mBluetoothHeadset.stopVoiceRecognition(
3473 mBluetoothHeadsetDevice);
Eric Laurentc18c9132013-04-12 17:24:56 -07003474 }
Liejun Taof4e51d82014-07-16 11:18:29 -07003475
Eric Laurentc18c9132013-04-12 17:24:56 -07003476 if (!status) {
Eric Laurentdc03c612011-04-01 10:59:41 -07003477 mScoAudioState = SCO_STATE_INACTIVE;
3478 broadcastScoConnectionState(
3479 AudioManager.SCO_AUDIO_STATE_DISCONNECTED);
3480 }
3481 } else if (getBluetoothHeadset()) {
3482 mScoAudioState = SCO_STATE_DEACTIVATE_REQ;
3483 }
3484 } else {
3485 mScoAudioState = SCO_STATE_INACTIVE;
3486 broadcastScoConnectionState(AudioManager.SCO_AUDIO_STATE_DISCONNECTED);
3487 }
Eric Laurent3def1ee2010-03-17 23:26:26 -07003488 }
3489 }
3490 }
3491 }
3492
Eric Laurent62ef7672010-11-24 10:58:32 -08003493 private void checkScoAudioState() {
3494 if (mBluetoothHeadset != null && mBluetoothHeadsetDevice != null &&
Eric Laurentdc03c612011-04-01 10:59:41 -07003495 mScoAudioState == SCO_STATE_INACTIVE &&
Eric Laurent62ef7672010-11-24 10:58:32 -08003496 mBluetoothHeadset.getAudioState(mBluetoothHeadsetDevice)
3497 != BluetoothHeadset.STATE_AUDIO_DISCONNECTED) {
3498 mScoAudioState = SCO_STATE_ACTIVE_EXTERNAL;
3499 }
3500 }
3501
Eric Laurent854938a2011-02-22 12:05:20 -08003502 private ScoClient getScoClient(IBinder cb, boolean create) {
Eric Laurent3def1ee2010-03-17 23:26:26 -07003503 synchronized(mScoClients) {
Eric Laurent854938a2011-02-22 12:05:20 -08003504 ScoClient client = null;
Eric Laurent3def1ee2010-03-17 23:26:26 -07003505 int size = mScoClients.size();
3506 for (int i = 0; i < size; i++) {
3507 client = mScoClients.get(i);
3508 if (client.getBinder() == cb)
3509 return client;
3510 }
Eric Laurent854938a2011-02-22 12:05:20 -08003511 if (create) {
3512 client = new ScoClient(cb);
3513 mScoClients.add(client);
3514 }
Eric Laurent3def1ee2010-03-17 23:26:26 -07003515 return client;
3516 }
3517 }
3518
Eric Laurentd7454be2011-09-14 08:45:58 -07003519 public void clearAllScoClients(int exceptPid, boolean stopSco) {
Eric Laurent3def1ee2010-03-17 23:26:26 -07003520 synchronized(mScoClients) {
Eric Laurent854938a2011-02-22 12:05:20 -08003521 ScoClient savedClient = null;
Eric Laurent3def1ee2010-03-17 23:26:26 -07003522 int size = mScoClients.size();
3523 for (int i = 0; i < size; i++) {
Eric Laurent854938a2011-02-22 12:05:20 -08003524 ScoClient cl = mScoClients.get(i);
Eric Laurentd7454be2011-09-14 08:45:58 -07003525 if (cl.getPid() != exceptPid) {
Eric Laurent854938a2011-02-22 12:05:20 -08003526 cl.clearCount(stopSco);
3527 } else {
3528 savedClient = cl;
3529 }
3530 }
3531 mScoClients.clear();
3532 if (savedClient != null) {
3533 mScoClients.add(savedClient);
Eric Laurent3def1ee2010-03-17 23:26:26 -07003534 }
3535 }
3536 }
3537
Eric Laurentdc03c612011-04-01 10:59:41 -07003538 private boolean getBluetoothHeadset() {
3539 boolean result = false;
3540 BluetoothAdapter adapter = BluetoothAdapter.getDefaultAdapter();
3541 if (adapter != null) {
3542 result = adapter.getProfileProxy(mContext, mBluetoothProfileServiceListener,
3543 BluetoothProfile.HEADSET);
3544 }
3545 // If we could not get a bluetooth headset proxy, send a failure message
3546 // without delay to reset the SCO audio state and clear SCO clients.
3547 // If we could get a proxy, send a delayed failure message that will reset our state
3548 // in case we don't receive onServiceConnected().
Eric Laurentafbb0472011-12-15 09:04:23 -08003549 sendMsg(mAudioHandler, MSG_BT_HEADSET_CNCT_FAILED,
Eric Laurentdc03c612011-04-01 10:59:41 -07003550 SENDMSG_REPLACE, 0, 0, null, result ? BT_HEADSET_CNCT_TIMEOUT_MS : 0);
3551 return result;
3552 }
3553
Eric Laurentd7454be2011-09-14 08:45:58 -07003554 private void disconnectBluetoothSco(int exceptPid) {
Eric Laurentdc03c612011-04-01 10:59:41 -07003555 synchronized(mScoClients) {
3556 checkScoAudioState();
3557 if (mScoAudioState == SCO_STATE_ACTIVE_EXTERNAL ||
3558 mScoAudioState == SCO_STATE_DEACTIVATE_EXT_REQ) {
3559 if (mBluetoothHeadsetDevice != null) {
3560 if (mBluetoothHeadset != null) {
3561 if (!mBluetoothHeadset.stopVoiceRecognition(
Eric Laurentb06ac832011-05-25 15:55:18 -07003562 mBluetoothHeadsetDevice)) {
Eric Laurentafbb0472011-12-15 09:04:23 -08003563 sendMsg(mAudioHandler, MSG_BT_HEADSET_CNCT_FAILED,
Eric Laurentdc03c612011-04-01 10:59:41 -07003564 SENDMSG_REPLACE, 0, 0, null, 0);
3565 }
3566 } else if (mScoAudioState == SCO_STATE_ACTIVE_EXTERNAL &&
3567 getBluetoothHeadset()) {
3568 mScoAudioState = SCO_STATE_DEACTIVATE_EXT_REQ;
3569 }
3570 }
3571 } else {
Eric Laurentd7454be2011-09-14 08:45:58 -07003572 clearAllScoClients(exceptPid, true);
Eric Laurentdc03c612011-04-01 10:59:41 -07003573 }
3574 }
3575 }
3576
3577 private void resetBluetoothSco() {
3578 synchronized(mScoClients) {
Eric Laurentd7454be2011-09-14 08:45:58 -07003579 clearAllScoClients(0, false);
Eric Laurentdc03c612011-04-01 10:59:41 -07003580 mScoAudioState = SCO_STATE_INACTIVE;
3581 broadcastScoConnectionState(AudioManager.SCO_AUDIO_STATE_DISCONNECTED);
3582 }
Eric Laurent48221252015-09-24 18:41:48 -07003583 AudioSystem.setParameters("A2dpSuspended=false");
Jean-Michel Trivi011f39e2017-08-19 18:08:06 -07003584 setBluetoothScoOnInt(false, "resetBluetoothSco");
Eric Laurentdc03c612011-04-01 10:59:41 -07003585 }
3586
3587 private void broadcastScoConnectionState(int state) {
Eric Laurent2a57ca92013-03-07 17:29:27 -08003588 sendMsg(mAudioHandler, MSG_BROADCAST_BT_CONNECTION_STATE,
3589 SENDMSG_QUEUE, state, 0, null, 0);
3590 }
3591
3592 private void onBroadcastScoConnectionState(int state) {
Eric Laurentdc03c612011-04-01 10:59:41 -07003593 if (state != mScoConnectionState) {
3594 Intent newIntent = new Intent(AudioManager.ACTION_SCO_AUDIO_STATE_UPDATED);
3595 newIntent.putExtra(AudioManager.EXTRA_SCO_AUDIO_STATE, state);
3596 newIntent.putExtra(AudioManager.EXTRA_SCO_AUDIO_PREVIOUS_STATE,
3597 mScoConnectionState);
Dianne Hackborn5ac72a22012-08-29 18:32:08 -07003598 sendStickyBroadcastToAll(newIntent);
Eric Laurentdc03c612011-04-01 10:59:41 -07003599 mScoConnectionState = state;
3600 }
3601 }
3602
Jack He8dd33942018-01-17 15:45:12 -08003603 private boolean handleBtScoActiveDeviceChange(BluetoothDevice btDevice, boolean isActive) {
Eric Laurent98859b22015-06-12 14:35:59 -07003604 if (btDevice == null) {
Jack He8dd33942018-01-17 15:45:12 -08003605 return true;
Eric Laurent98859b22015-06-12 14:35:59 -07003606 }
Eric Laurent98859b22015-06-12 14:35:59 -07003607 String address = btDevice.getAddress();
3608 BluetoothClass btClass = btDevice.getBluetoothClass();
3609 int outDevice = AudioSystem.DEVICE_OUT_BLUETOOTH_SCO;
3610 int inDevice = AudioSystem.DEVICE_IN_BLUETOOTH_SCO_HEADSET;
3611 if (btClass != null) {
3612 switch (btClass.getDeviceClass()) {
Jack He8dd33942018-01-17 15:45:12 -08003613 case BluetoothClass.Device.AUDIO_VIDEO_WEARABLE_HEADSET:
3614 case BluetoothClass.Device.AUDIO_VIDEO_HANDSFREE:
3615 outDevice = AudioSystem.DEVICE_OUT_BLUETOOTH_SCO_HEADSET;
3616 break;
3617 case BluetoothClass.Device.AUDIO_VIDEO_CAR_AUDIO:
3618 outDevice = AudioSystem.DEVICE_OUT_BLUETOOTH_SCO_CARKIT;
3619 break;
Eric Laurent98859b22015-06-12 14:35:59 -07003620 }
3621 }
3622
3623 if (!BluetoothAdapter.checkBluetoothAddress(address)) {
3624 address = "";
3625 }
3626
Eric Laurent98859b22015-06-12 14:35:59 -07003627 String btDeviceName = btDevice.getName();
Jack He8dd33942018-01-17 15:45:12 -08003628 boolean result = handleDeviceConnection(isActive, outDevice, address, btDeviceName);
3629 // handleDeviceConnection() && result to make sure the method get executed
3630 result = handleDeviceConnection(isActive, inDevice, address, btDeviceName) && result;
3631 return result;
3632 }
Satish Kodishala29809802016-01-18 14:23:12 +05303633
Jack He8dd33942018-01-17 15:45:12 -08003634 void setBtScoActiveDevice(BluetoothDevice btDevice) {
3635 if (DEBUG_DEVICES) {
3636 Log.d(TAG, "setBtScoActiveDevice(" + btDevice + ")");
Satish Kodishala29809802016-01-18 14:23:12 +05303637 }
Satish Kodishala29809802016-01-18 14:23:12 +05303638 synchronized (mScoClients) {
Jack He8dd33942018-01-17 15:45:12 -08003639 final BluetoothDevice previousActiveDevice = mBluetoothHeadsetDevice;
3640 if (!Objects.equals(btDevice, previousActiveDevice)) {
3641 if (!handleBtScoActiveDeviceChange(previousActiveDevice, false)) {
3642 Log.w(TAG, "setBtScoActiveDevice() failed to remove previous device "
3643 + previousActiveDevice);
3644 }
3645 if (!handleBtScoActiveDeviceChange(btDevice, true)) {
3646 Log.e(TAG, "setBtScoActiveDevice() failed to add new device " + btDevice);
3647 // set mBluetoothHeadsetDevice to null when failing to add new device
3648 btDevice = null;
3649 }
Satish Kodishala29809802016-01-18 14:23:12 +05303650 mBluetoothHeadsetDevice = btDevice;
Jack He8dd33942018-01-17 15:45:12 -08003651 if (mBluetoothHeadsetDevice == null) {
3652 resetBluetoothSco();
3653 }
Eric Laurent98859b22015-06-12 14:35:59 -07003654 }
3655 }
3656 }
3657
Jaikumar Ganesh82aa7f02010-09-27 17:05:10 -07003658 private BluetoothProfile.ServiceListener mBluetoothProfileServiceListener =
3659 new BluetoothProfile.ServiceListener() {
3660 public void onServiceConnected(int profile, BluetoothProfile proxy) {
Eric Laurent6bc7f2c2011-11-29 18:49:40 -08003661 BluetoothDevice btDevice;
3662 List<BluetoothDevice> deviceList;
3663 switch(profile) {
3664 case BluetoothProfile.A2DP:
seunghwan.hong4fe77952014-10-29 17:43:20 +09003665 synchronized (mConnectedDevices) {
3666 synchronized (mA2dpAvrcpLock) {
3667 mA2dp = (BluetoothA2dp) proxy;
3668 deviceList = mA2dp.getConnectedDevices();
3669 if (deviceList.size() > 0) {
3670 btDevice = deviceList.get(0);
John Du5a0cf7a2013-07-19 11:30:34 -07003671 int state = mA2dp.getConnectionState(btDevice);
Eric Laurentcdae4762017-04-28 18:00:04 -07003672 int intState = (state == BluetoothA2dp.STATE_CONNECTED) ? 1 : 0;
John Du5a0cf7a2013-07-19 11:30:34 -07003673 int delay = checkSendBecomingNoisyIntent(
Eric Laurentcdae4762017-04-28 18:00:04 -07003674 AudioSystem.DEVICE_OUT_BLUETOOTH_A2DP, intState,
3675 AudioSystem.DEVICE_NONE);
John Du5a0cf7a2013-07-19 11:30:34 -07003676 queueMsgUnderWakeLock(mAudioHandler,
Mike Lockwood0a40ec22014-05-21 10:08:50 -07003677 MSG_SET_A2DP_SINK_CONNECTION_STATE,
John Du5a0cf7a2013-07-19 11:30:34 -07003678 state,
Pavlin Radoslavov44a4ef02016-12-21 12:05:51 -08003679 0 /* arg2 unused */,
John Du5a0cf7a2013-07-19 11:30:34 -07003680 btDevice,
3681 delay);
3682 }
Eric Laurentb1fbaac2012-05-29 09:24:28 -07003683 }
Eric Laurent62ef7672010-11-24 10:58:32 -08003684 }
Eric Laurent6bc7f2c2011-11-29 18:49:40 -08003685 break;
3686
Mike Lockwood0a40ec22014-05-21 10:08:50 -07003687 case BluetoothProfile.A2DP_SINK:
3688 deviceList = proxy.getConnectedDevices();
3689 if (deviceList.size() > 0) {
3690 btDevice = deviceList.get(0);
3691 synchronized (mConnectedDevices) {
3692 int state = proxy.getConnectionState(btDevice);
3693 queueMsgUnderWakeLock(mAudioHandler,
3694 MSG_SET_A2DP_SRC_CONNECTION_STATE,
3695 state,
Pavlin Radoslavov44a4ef02016-12-21 12:05:51 -08003696 0 /* arg2 unused */,
Mike Lockwood0a40ec22014-05-21 10:08:50 -07003697 btDevice,
3698 0 /* delay */);
3699 }
3700 }
3701 break;
3702
Eric Laurent6bc7f2c2011-11-29 18:49:40 -08003703 case BluetoothProfile.HEADSET:
3704 synchronized (mScoClients) {
3705 // Discard timeout message
3706 mAudioHandler.removeMessages(MSG_BT_HEADSET_CNCT_FAILED);
3707 mBluetoothHeadset = (BluetoothHeadset) proxy;
Jack He8dd33942018-01-17 15:45:12 -08003708 setBtScoActiveDevice(mBluetoothHeadset.getActiveDevice());
Eric Laurent6bc7f2c2011-11-29 18:49:40 -08003709 // Refresh SCO audio state
3710 checkScoAudioState();
3711 // Continue pending action if any
3712 if (mScoAudioState == SCO_STATE_ACTIVATE_REQ ||
3713 mScoAudioState == SCO_STATE_DEACTIVATE_REQ ||
3714 mScoAudioState == SCO_STATE_DEACTIVATE_EXT_REQ) {
3715 boolean status = false;
3716 if (mBluetoothHeadsetDevice != null) {
3717 switch (mScoAudioState) {
3718 case SCO_STATE_ACTIVATE_REQ:
3719 mScoAudioState = SCO_STATE_ACTIVE_INTERNAL;
Eric Laurentc18c9132013-04-12 17:24:56 -07003720 if (mScoAudioMode == SCO_MODE_RAW) {
3721 status = mBluetoothHeadset.connectAudio();
Liejun Taof4e51d82014-07-16 11:18:29 -07003722 } else if (mScoAudioMode == SCO_MODE_VIRTUAL_CALL) {
Eric Laurentc18c9132013-04-12 17:24:56 -07003723 status = mBluetoothHeadset.startScoUsingVirtualVoiceCall(
3724 mBluetoothHeadsetDevice);
Liejun Taof4e51d82014-07-16 11:18:29 -07003725 } else if (mScoAudioMode == SCO_MODE_VR) {
3726 status = mBluetoothHeadset.startVoiceRecognition(
3727 mBluetoothHeadsetDevice);
Eric Laurentc18c9132013-04-12 17:24:56 -07003728 }
Eric Laurent6bc7f2c2011-11-29 18:49:40 -08003729 break;
3730 case SCO_STATE_DEACTIVATE_REQ:
Eric Laurentc18c9132013-04-12 17:24:56 -07003731 if (mScoAudioMode == SCO_MODE_RAW) {
3732 status = mBluetoothHeadset.disconnectAudio();
Liejun Taof4e51d82014-07-16 11:18:29 -07003733 } else if (mScoAudioMode == SCO_MODE_VIRTUAL_CALL) {
Eric Laurentc18c9132013-04-12 17:24:56 -07003734 status = mBluetoothHeadset.stopScoUsingVirtualVoiceCall(
3735 mBluetoothHeadsetDevice);
Liejun Taof4e51d82014-07-16 11:18:29 -07003736 } else if (mScoAudioMode == SCO_MODE_VR) {
3737 status = mBluetoothHeadset.stopVoiceRecognition(
3738 mBluetoothHeadsetDevice);
Eric Laurentc18c9132013-04-12 17:24:56 -07003739 }
Eric Laurent6bc7f2c2011-11-29 18:49:40 -08003740 break;
3741 case SCO_STATE_DEACTIVATE_EXT_REQ:
3742 status = mBluetoothHeadset.stopVoiceRecognition(
3743 mBluetoothHeadsetDevice);
3744 }
3745 }
3746 if (!status) {
Eric Laurentafbb0472011-12-15 09:04:23 -08003747 sendMsg(mAudioHandler, MSG_BT_HEADSET_CNCT_FAILED,
Eric Laurent6bc7f2c2011-11-29 18:49:40 -08003748 SENDMSG_REPLACE, 0, 0, null, 0);
Eric Laurentdc03c612011-04-01 10:59:41 -07003749 }
3750 }
Eric Laurentdc03c612011-04-01 10:59:41 -07003751 }
Eric Laurent6bc7f2c2011-11-29 18:49:40 -08003752 break;
3753
Jakub Pawlowskif9570f32018-02-21 17:15:12 -08003754 case BluetoothProfile.HEARING_AID:
3755 synchronized (mConnectedDevices) {
3756 synchronized (mHearingAidLock) {
3757 mHearingAid = (BluetoothHearingAid) proxy;
3758 deviceList = mHearingAid.getConnectedDevices();
3759 if (deviceList.size() > 0) {
3760 btDevice = deviceList.get(0);
3761 int state = mHearingAid.getConnectionState(btDevice);
3762 int intState = (state == BluetoothHearingAid.STATE_CONNECTED) ? 1 : 0;
3763 int delay = checkSendBecomingNoisyIntent(
3764 AudioSystem.DEVICE_OUT_HEARING_AID, intState,
3765 AudioSystem.DEVICE_NONE);
3766 queueMsgUnderWakeLock(mAudioHandler,
3767 MSG_SET_HEARING_AID_CONNECTION_STATE,
3768 state,
3769 0 /* arg2 unused */,
3770 btDevice,
3771 delay);
3772 }
3773 }
3774 }
3775
3776 break;
3777
Eric Laurent6bc7f2c2011-11-29 18:49:40 -08003778 default:
3779 break;
Eric Laurent3def1ee2010-03-17 23:26:26 -07003780 }
3781 }
Jaikumar Ganesh82aa7f02010-09-27 17:05:10 -07003782 public void onServiceDisconnected(int profile) {
Eric Laurentb70b78a2016-01-13 19:16:04 -08003783
Paul McLean394a8e12015-03-03 10:29:19 -07003784 switch (profile) {
Eric Laurent6bc7f2c2011-11-29 18:49:40 -08003785 case BluetoothProfile.A2DP:
Eric Laurentb70b78a2016-01-13 19:16:04 -08003786 disconnectA2dp();
Eric Laurent6bc7f2c2011-11-29 18:49:40 -08003787 break;
3788
Mike Lockwood0a40ec22014-05-21 10:08:50 -07003789 case BluetoothProfile.A2DP_SINK:
Eric Laurentb70b78a2016-01-13 19:16:04 -08003790 disconnectA2dpSink();
Mike Lockwood0a40ec22014-05-21 10:08:50 -07003791 break;
3792
Eric Laurent6bc7f2c2011-11-29 18:49:40 -08003793 case BluetoothProfile.HEADSET:
Eric Laurentb70b78a2016-01-13 19:16:04 -08003794 disconnectHeadset();
Eric Laurent6bc7f2c2011-11-29 18:49:40 -08003795 break;
3796
Jakub Pawlowskif9570f32018-02-21 17:15:12 -08003797 case BluetoothProfile.HEARING_AID:
3798 disconnectHearingAid();
3799 break;
3800
Eric Laurent6bc7f2c2011-11-29 18:49:40 -08003801 default:
3802 break;
Eric Laurent3def1ee2010-03-17 23:26:26 -07003803 }
3804 }
3805 };
Jean-Michel Trivid5176cf2010-01-28 11:56:42 -08003806
Eric Laurentb70b78a2016-01-13 19:16:04 -08003807 void disconnectAllBluetoothProfiles() {
3808 disconnectA2dp();
3809 disconnectA2dpSink();
3810 disconnectHeadset();
Jakub Pawlowskif9570f32018-02-21 17:15:12 -08003811 disconnectHearingAid();
Eric Laurentb70b78a2016-01-13 19:16:04 -08003812 }
3813
3814 void disconnectA2dp() {
3815 synchronized (mConnectedDevices) {
3816 synchronized (mA2dpAvrcpLock) {
3817 ArraySet<String> toRemove = null;
3818 // Disconnect ALL DEVICE_OUT_BLUETOOTH_A2DP devices
3819 for (int i = 0; i < mConnectedDevices.size(); i++) {
3820 DeviceListSpec deviceSpec = mConnectedDevices.valueAt(i);
3821 if (deviceSpec.mDeviceType == AudioSystem.DEVICE_OUT_BLUETOOTH_A2DP) {
3822 toRemove = toRemove != null ? toRemove : new ArraySet<String>();
3823 toRemove.add(deviceSpec.mDeviceAddress);
3824 }
3825 }
3826 if (toRemove != null) {
Eric Laurentcdae4762017-04-28 18:00:04 -07003827 int delay = checkSendBecomingNoisyIntent(AudioSystem.DEVICE_OUT_BLUETOOTH_A2DP,
3828 0, AudioSystem.DEVICE_NONE);
Eric Laurentb70b78a2016-01-13 19:16:04 -08003829 for (int i = 0; i < toRemove.size(); i++) {
3830 makeA2dpDeviceUnavailableLater(toRemove.valueAt(i), delay);
3831 }
3832 }
3833 }
3834 }
3835 }
3836
3837 void disconnectA2dpSink() {
3838 synchronized (mConnectedDevices) {
3839 ArraySet<String> toRemove = null;
3840 // Disconnect ALL DEVICE_IN_BLUETOOTH_A2DP devices
3841 for(int i = 0; i < mConnectedDevices.size(); i++) {
3842 DeviceListSpec deviceSpec = mConnectedDevices.valueAt(i);
3843 if (deviceSpec.mDeviceType == AudioSystem.DEVICE_IN_BLUETOOTH_A2DP) {
3844 toRemove = toRemove != null ? toRemove : new ArraySet<String>();
3845 toRemove.add(deviceSpec.mDeviceAddress);
3846 }
3847 }
3848 if (toRemove != null) {
3849 for (int i = 0; i < toRemove.size(); i++) {
3850 makeA2dpSrcUnavailable(toRemove.valueAt(i));
3851 }
3852 }
3853 }
3854 }
3855
3856 void disconnectHeadset() {
3857 synchronized (mScoClients) {
Jack He8dd33942018-01-17 15:45:12 -08003858 setBtScoActiveDevice(null);
Eric Laurentb70b78a2016-01-13 19:16:04 -08003859 mBluetoothHeadset = null;
3860 }
3861 }
3862
Jakub Pawlowskif9570f32018-02-21 17:15:12 -08003863 void disconnectHearingAid() {
3864 synchronized (mConnectedDevices) {
3865 synchronized (mHearingAidLock) {
3866 ArraySet<String> toRemove = null;
3867 // Disconnect ALL DEVICE_OUT_HEARING_AID devices
3868 for (int i = 0; i < mConnectedDevices.size(); i++) {
3869 DeviceListSpec deviceSpec = mConnectedDevices.valueAt(i);
3870 if (deviceSpec.mDeviceType == AudioSystem.DEVICE_OUT_HEARING_AID) {
3871 toRemove = toRemove != null ? toRemove : new ArraySet<String>();
3872 toRemove.add(deviceSpec.mDeviceAddress);
3873 }
3874 }
3875 if (toRemove != null) {
3876 int delay = checkSendBecomingNoisyIntent(AudioSystem.DEVICE_OUT_HEARING_AID,
3877 0, AudioSystem.DEVICE_NONE);
3878 for (int i = 0; i < toRemove.size(); i++) {
3879 makeHearingAidDeviceUnavailable(toRemove.valueAt(i) /*, delay*/);
3880 }
3881 }
3882 }
3883 }
3884 }
3885
John Spurlock90874332015-03-10 16:00:54 -04003886 private void onCheckMusicActive(String caller) {
Eric Laurentd640bd32012-09-28 18:01:48 -07003887 synchronized (mSafeMediaVolumeState) {
3888 if (mSafeMediaVolumeState == SAFE_MEDIA_VOLUME_INACTIVE) {
Eric Laurentc34dcc12012-09-10 13:51:52 -07003889 int device = getDeviceForStream(AudioSystem.STREAM_MUSIC);
3890
3891 if ((device & mSafeMediaVolumeDevices) != 0) {
3892 sendMsg(mAudioHandler,
3893 MSG_CHECK_MUSIC_ACTIVE,
3894 SENDMSG_REPLACE,
Eric Laurentf1a457d2012-09-20 16:27:23 -07003895 0,
Eric Laurentc34dcc12012-09-10 13:51:52 -07003896 0,
John Spurlock90874332015-03-10 16:00:54 -04003897 caller,
Eric Laurentc34dcc12012-09-10 13:51:52 -07003898 MUSIC_ACTIVE_POLL_PERIOD_MS);
Eric Laurent42b041e2013-03-29 11:36:03 -07003899 int index = mStreamStates[AudioSystem.STREAM_MUSIC].getIndex(device);
Eric Laurentf1a457d2012-09-20 16:27:23 -07003900 if (AudioSystem.isStreamActive(AudioSystem.STREAM_MUSIC, 0) &&
Eric Laurenteab40d12017-06-09 12:45:21 -07003901 (index > safeMediaVolumeIndex(device))) {
Eric Laurentc34dcc12012-09-10 13:51:52 -07003902 // Approximate cumulative active music time
3903 mMusicActiveMs += MUSIC_ACTIVE_POLL_PERIOD_MS;
3904 if (mMusicActiveMs > UNSAFE_VOLUME_MUSIC_ACTIVE_MS_MAX) {
John Spurlock90874332015-03-10 16:00:54 -04003905 setSafeMediaVolumeEnabled(true, caller);
Eric Laurentc34dcc12012-09-10 13:51:52 -07003906 mMusicActiveMs = 0;
Eric Laurentc34dcc12012-09-10 13:51:52 -07003907 }
John Spurlockaa5ee4d2014-07-25 13:05:12 -04003908 saveMusicActiveMs();
Eric Laurentc34dcc12012-09-10 13:51:52 -07003909 }
3910 }
3911 }
3912 }
3913 }
3914
John Spurlockaa5ee4d2014-07-25 13:05:12 -04003915 private void saveMusicActiveMs() {
3916 mAudioHandler.obtainMessage(MSG_PERSIST_MUSIC_ACTIVE_MS, mMusicActiveMs, 0).sendToTarget();
3917 }
3918
Eric Laurenteab40d12017-06-09 12:45:21 -07003919 private int getSafeUsbMediaVolumeIndex()
3920 {
3921 // determine UI volume index corresponding to the wanted safe gain in dBFS
3922 int min = MIN_STREAM_VOLUME[AudioSystem.STREAM_MUSIC];
3923 int max = MAX_STREAM_VOLUME[AudioSystem.STREAM_MUSIC];
3924
John Muir8b8bddd2018-02-16 14:29:14 -08003925 mSafeUsbMediaVolumeDbfs = mContext.getResources().getInteger(
3926 com.android.internal.R.integer.config_safe_media_volume_usb_mB) / 100.0f;
3927
Eric Laurenteab40d12017-06-09 12:45:21 -07003928 while (Math.abs(max-min) > 1) {
3929 int index = (max + min) / 2;
3930 float gainDB = AudioSystem.getStreamVolumeDB(
3931 AudioSystem.STREAM_MUSIC, index, AudioSystem.DEVICE_OUT_USB_HEADSET);
Eric Laurentb378a13a2017-07-11 14:08:11 -07003932 if (Float.isNaN(gainDB)) {
Eric Laurenteab40d12017-06-09 12:45:21 -07003933 //keep last min in case of read error
3934 break;
John Muir8b8bddd2018-02-16 14:29:14 -08003935 } else if (gainDB == mSafeUsbMediaVolumeDbfs) {
Eric Laurenteab40d12017-06-09 12:45:21 -07003936 min = index;
3937 break;
John Muir8b8bddd2018-02-16 14:29:14 -08003938 } else if (gainDB < mSafeUsbMediaVolumeDbfs) {
Eric Laurenteab40d12017-06-09 12:45:21 -07003939 min = index;
3940 } else {
3941 max = index;
3942 }
3943 }
3944 return min * 10;
3945 }
3946
John Spurlock90874332015-03-10 16:00:54 -04003947 private void onConfigureSafeVolume(boolean force, String caller) {
Eric Laurentd640bd32012-09-28 18:01:48 -07003948 synchronized (mSafeMediaVolumeState) {
3949 int mcc = mContext.getResources().getConfiguration().mcc;
3950 if ((mMcc != mcc) || ((mMcc == 0) && force)) {
3951 mSafeMediaVolumeIndex = mContext.getResources().getInteger(
3952 com.android.internal.R.integer.config_safe_media_volume_index) * 10;
Eric Laurenteab40d12017-06-09 12:45:21 -07003953
3954 mSafeUsbMediaVolumeIndex = getSafeUsbMediaVolumeIndex();
3955
John Spurlock35134602014-07-24 18:10:48 -04003956 boolean safeMediaVolumeEnabled =
3957 SystemProperties.getBoolean("audio.safemedia.force", false)
3958 || mContext.getResources().getBoolean(
3959 com.android.internal.R.bool.config_safe_media_volume_enabled);
Eric Laurent05274f32012-11-29 12:48:18 -08003960
Ricardo Garcia3a30a762015-06-23 15:54:45 -07003961 boolean safeMediaVolumeBypass =
3962 SystemProperties.getBoolean("audio.safemedia.bypass", false);
3963
Eric Laurent05274f32012-11-29 12:48:18 -08003964 // The persisted state is either "disabled" or "active": this is the state applied
3965 // next time we boot and cannot be "inactive"
3966 int persistedState;
Ricardo Garcia3a30a762015-06-23 15:54:45 -07003967 if (safeMediaVolumeEnabled && !safeMediaVolumeBypass) {
Eric Laurent05274f32012-11-29 12:48:18 -08003968 persistedState = SAFE_MEDIA_VOLUME_ACTIVE;
3969 // The state can already be "inactive" here if the user has forced it before
3970 // the 30 seconds timeout for forced configuration. In this case we don't reset
3971 // it to "active".
3972 if (mSafeMediaVolumeState != SAFE_MEDIA_VOLUME_INACTIVE) {
John Spurlockaa5ee4d2014-07-25 13:05:12 -04003973 if (mMusicActiveMs == 0) {
3974 mSafeMediaVolumeState = SAFE_MEDIA_VOLUME_ACTIVE;
John Spurlock90874332015-03-10 16:00:54 -04003975 enforceSafeMediaVolume(caller);
John Spurlockaa5ee4d2014-07-25 13:05:12 -04003976 } else {
3977 // We have existing playback time recorded, already confirmed.
3978 mSafeMediaVolumeState = SAFE_MEDIA_VOLUME_INACTIVE;
3979 }
Eric Laurent05274f32012-11-29 12:48:18 -08003980 }
Eric Laurentd640bd32012-09-28 18:01:48 -07003981 } else {
Eric Laurent05274f32012-11-29 12:48:18 -08003982 persistedState = SAFE_MEDIA_VOLUME_DISABLED;
Eric Laurentd640bd32012-09-28 18:01:48 -07003983 mSafeMediaVolumeState = SAFE_MEDIA_VOLUME_DISABLED;
3984 }
3985 mMcc = mcc;
Eric Laurent05274f32012-11-29 12:48:18 -08003986 sendMsg(mAudioHandler,
3987 MSG_PERSIST_SAFE_VOLUME_STATE,
3988 SENDMSG_QUEUE,
3989 persistedState,
3990 0,
3991 null,
3992 0);
Eric Laurentd640bd32012-09-28 18:01:48 -07003993 }
3994 }
3995 }
3996
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003997 ///////////////////////////////////////////////////////////////////////////
3998 // Internal methods
3999 ///////////////////////////////////////////////////////////////////////////
4000
4001 /**
4002 * Checks if the adjustment should change ringer mode instead of just
4003 * adjusting volume. If so, this will set the proper ringer mode and volume
4004 * indices on the stream states.
4005 */
Julia Reynoldsed783792016-04-08 15:27:35 -04004006 private int checkForRingerModeChange(int oldIndex, int direction, int step, boolean isMuted,
4007 String caller, int flags) {
John Spurlocka11b4af2014-06-01 11:52:23 -04004008 int result = FLAG_ADJUST_VOLUME;
Zak Cohen47798292017-11-30 12:34:20 -08004009 if (isPlatformTelevision() || mIsSingleVolume) {
Hank Freund21003f62015-12-08 09:05:46 -08004010 return result;
4011 }
4012
John Spurlock661f2cf2014-11-17 10:29:10 -05004013 int ringerMode = getRingerModeInternal();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004014
Eric Laurentbffc3d12012-05-07 17:43:49 -07004015 switch (ringerMode) {
4016 case RINGER_MODE_NORMAL:
4017 if (direction == AudioManager.ADJUST_LOWER) {
4018 if (mHasVibrator) {
Eric Laurent24482012012-05-10 09:41:17 -07004019 // "step" is the delta in internal index units corresponding to a
4020 // change of 1 in UI index units.
4021 // Because of rounding when rescaling from one stream index range to its alias
4022 // index range, we cannot simply test oldIndex == step:
4023 // (step <= oldIndex < 2 * step) is equivalent to: (old UI index == 1)
4024 if (step <= oldIndex && oldIndex < 2 * step) {
Eric Laurentbffc3d12012-05-07 17:43:49 -07004025 ringerMode = RINGER_MODE_VIBRATE;
John Spurlock07e72432015-03-13 11:46:52 -04004026 mLoweredFromNormalToVibrateTime = SystemClock.uptimeMillis();
Eric Laurentbffc3d12012-05-07 17:43:49 -07004027 }
4028 } else {
John Spurlockd9c75db2015-04-28 11:19:13 -04004029 if (oldIndex == step && mVolumePolicy.volumeDownToEnterSilent) {
Eric Laurentbffc3d12012-05-07 17:43:49 -07004030 ringerMode = RINGER_MODE_SILENT;
4031 }
Eric Laurent3d4c06f2011-08-15 19:58:28 -07004032 }
Muyuan Li1ed6df62016-06-18 11:16:52 -07004033 } else if (mIsSingleVolume && (direction == AudioManager.ADJUST_TOGGLE_MUTE
John Spurlocka48d7792015-03-03 17:35:57 -05004034 || direction == AudioManager.ADJUST_MUTE)) {
RoboErik5452e252015-02-06 15:33:53 -08004035 if (mHasVibrator) {
4036 ringerMode = RINGER_MODE_VIBRATE;
4037 } else {
4038 ringerMode = RINGER_MODE_SILENT;
4039 }
4040 // Setting the ringer mode will toggle mute
4041 result &= ~FLAG_ADJUST_VOLUME;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004042 }
Eric Laurentbffc3d12012-05-07 17:43:49 -07004043 break;
4044 case RINGER_MODE_VIBRATE:
4045 if (!mHasVibrator) {
4046 Log.e(TAG, "checkForRingerModeChange() current ringer mode is vibrate" +
4047 "but no vibrator is present");
4048 break;
4049 }
Amith Yamasanic696a532011-10-28 17:02:37 -07004050 if ((direction == AudioManager.ADJUST_LOWER)) {
RoboErik5452e252015-02-06 15:33:53 -08004051 // This is the case we were muted with the volume turned up
Muyuan Li1ed6df62016-06-18 11:16:52 -07004052 if (mIsSingleVolume && oldIndex >= 2 * step && isMuted) {
RoboErik5452e252015-02-06 15:33:53 -08004053 ringerMode = RINGER_MODE_NORMAL;
4054 } else if (mPrevVolDirection != AudioManager.ADJUST_LOWER) {
John Spurlocka48d7792015-03-03 17:35:57 -05004055 if (mVolumePolicy.volumeDownToEnterSilent) {
John Spurlock07e72432015-03-13 11:46:52 -04004056 final long diff = SystemClock.uptimeMillis()
4057 - mLoweredFromNormalToVibrateTime;
John Spurlockd9c75db2015-04-28 11:19:13 -04004058 if (diff > mVolumePolicy.vibrateToSilentDebounce
4059 && mRingerModeDelegate.canVolumeDownEnterSilent()) {
John Spurlock07e72432015-03-13 11:46:52 -04004060 ringerMode = RINGER_MODE_SILENT;
4061 }
John Spurlock795a5142014-12-08 14:09:35 -05004062 } else {
4063 result |= AudioManager.FLAG_SHOW_VIBRATE_HINT;
4064 }
Amith Yamasanic696a532011-10-28 17:02:37 -07004065 }
RoboErik5452e252015-02-06 15:33:53 -08004066 } else if (direction == AudioManager.ADJUST_RAISE
4067 || direction == AudioManager.ADJUST_TOGGLE_MUTE
4068 || direction == AudioManager.ADJUST_UNMUTE) {
Eric Laurentbffc3d12012-05-07 17:43:49 -07004069 ringerMode = RINGER_MODE_NORMAL;
Amith Yamasanic696a532011-10-28 17:02:37 -07004070 }
John Spurlocka11b4af2014-06-01 11:52:23 -04004071 result &= ~FLAG_ADJUST_VOLUME;
Eric Laurentbffc3d12012-05-07 17:43:49 -07004072 break;
4073 case RINGER_MODE_SILENT:
Muyuan Li1ed6df62016-06-18 11:16:52 -07004074 if (mIsSingleVolume && direction == AudioManager.ADJUST_LOWER && oldIndex >= 2 * step && isMuted) {
RoboErik5452e252015-02-06 15:33:53 -08004075 // This is the case we were muted with the volume turned up
4076 ringerMode = RINGER_MODE_NORMAL;
4077 } else if (direction == AudioManager.ADJUST_RAISE
4078 || direction == AudioManager.ADJUST_TOGGLE_MUTE
4079 || direction == AudioManager.ADJUST_UNMUTE) {
John Spurlocka48d7792015-03-03 17:35:57 -05004080 if (!mVolumePolicy.volumeUpToExitSilent) {
John Spurlocka11b4af2014-06-01 11:52:23 -04004081 result |= AudioManager.FLAG_SHOW_SILENT_HINT;
Eric Laurentbffc3d12012-05-07 17:43:49 -07004082 } else {
RoboErik5452e252015-02-06 15:33:53 -08004083 if (mHasVibrator && direction == AudioManager.ADJUST_RAISE) {
John Spurlocka11b4af2014-06-01 11:52:23 -04004084 ringerMode = RINGER_MODE_VIBRATE;
4085 } else {
RoboErik5452e252015-02-06 15:33:53 -08004086 // If we don't have a vibrator or they were toggling mute
4087 // go straight back to normal.
John Spurlocka11b4af2014-06-01 11:52:23 -04004088 ringerMode = RINGER_MODE_NORMAL;
4089 }
Eric Laurentbffc3d12012-05-07 17:43:49 -07004090 }
Daniel Sandler6329bf72010-02-26 15:17:44 -05004091 }
John Spurlocka11b4af2014-06-01 11:52:23 -04004092 result &= ~FLAG_ADJUST_VOLUME;
Eric Laurentbffc3d12012-05-07 17:43:49 -07004093 break;
4094 default:
4095 Log.e(TAG, "checkForRingerModeChange() wrong ringer mode: "+ringerMode);
4096 break;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004097 }
4098
Julia Reynoldsed783792016-04-08 15:27:35 -04004099 if (isAndroidNPlus(caller) && wouldToggleZenMode(ringerMode)
4100 && !mNm.isNotificationPolicyAccessGrantedForPackage(caller)
4101 && (flags & AudioManager.FLAG_FROM_KEY) == 0) {
4102 throw new SecurityException("Not allowed to change Do Not Disturb state");
4103 }
4104
John Spurlock661f2cf2014-11-17 10:29:10 -05004105 setRingerMode(ringerMode, TAG + ".checkForRingerModeChange", false /*external*/);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004106
Eric Laurent25101b02011-02-02 09:33:30 -08004107 mPrevVolDirection = direction;
4108
John Spurlocka11b4af2014-06-01 11:52:23 -04004109 return result;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004110 }
4111
John Spurlock3346a802014-05-20 16:25:37 -04004112 @Override
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004113 public boolean isStreamAffectedByRingerMode(int streamType) {
Eric Laurent9bcf4012009-06-12 06:09:28 -07004114 return (mRingerModeAffectedStreams & (1 << streamType)) != 0;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004115 }
4116
Beverlyd6964762018-02-16 14:07:03 -05004117 private boolean shouldZenMuteStream(int streamType) {
4118 if (mNm.getZenMode() != Settings.Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS) {
4119 return false;
4120 }
4121
4122 NotificationManager.Policy zenPolicy = mNm.getNotificationPolicy();
4123 final boolean muteAlarms = (zenPolicy.priorityCategories
4124 & NotificationManager.Policy.PRIORITY_CATEGORY_ALARMS) == 0;
4125 final boolean muteMedia = (zenPolicy.priorityCategories
4126 & NotificationManager.Policy.PRIORITY_CATEGORY_MEDIA) == 0;
4127 final boolean muteSystem = (zenPolicy.priorityCategories
4128 & NotificationManager.Policy.PRIORITY_CATEGORY_SYSTEM) == 0;
4129 final boolean muteNotificationAndRing = ZenModeConfig
4130 .areAllPriorityOnlyNotificationZenSoundsMuted(mNm.getNotificationPolicy());
4131 return muteAlarms && isAlarm(streamType)
4132 || muteMedia && isMedia(streamType)
4133 || muteSystem && isSystem(streamType)
4134 || muteNotificationAndRing && isNotificationOrRinger(streamType);
4135 }
4136
4137 private boolean isStreamMutedByRingerOrZenMode(int streamType) {
4138 return (mRingerAndZenModeMutedStreams & (1 << streamType)) != 0;
4139 }
4140
4141 /**
4142 * DND total silence: media and alarms streams are tied to the muted ringer
4143 * {@link ZenModeHelper.RingerModeDelegate#getRingerModeAffectedStreams(int)}
4144 * DND alarms only: notification, ringer + system muted (by default tied to muted ringer mode)
4145 * DND priority only: alarms, media, system streams can be muted separate from ringer based on
4146 * zenPolicy (this method determines which streams)
4147 * @return true if changed, else false
4148 */
4149 private boolean updateZenModeAffectedStreams() {
4150 int zenModeAffectedStreams = 0;
4151 if (mSystemReady && mNm.getZenMode() == Settings.Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS) {
4152 NotificationManager.Policy zenPolicy = mNm.getNotificationPolicy();
4153 if ((zenPolicy.priorityCategories
4154 & NotificationManager.Policy.PRIORITY_CATEGORY_ALARMS) == 0) {
4155 zenModeAffectedStreams |= 1 << AudioManager.STREAM_ALARM;
4156 }
4157
4158 if ((zenPolicy.priorityCategories
4159 & NotificationManager.Policy.PRIORITY_CATEGORY_MEDIA) == 0) {
4160 zenModeAffectedStreams |= 1 << AudioManager.STREAM_MUSIC;
4161 }
4162
4163 if ((zenPolicy.priorityCategories
4164 & NotificationManager.Policy.PRIORITY_CATEGORY_SYSTEM) == 0) {
4165 zenModeAffectedStreams |= 1 << AudioManager.STREAM_SYSTEM;
4166 }
4167 }
4168
4169 if (mZenModeAffectedStreams != zenModeAffectedStreams) {
4170 mZenModeAffectedStreams = zenModeAffectedStreams;
4171 return true;
4172 }
4173
4174 return false;
Eric Laurent5b4e6542010-03-19 20:02:21 -07004175 }
4176
Jean-Michel Trivi8719a1d2017-11-06 11:52:51 -08004177 @GuardedBy("mSettingsLock")
Beverlyd6964762018-02-16 14:07:03 -05004178 private boolean updateRingerAndZenModeAffectedStreams() {
4179 boolean updatedZenModeAffectedStreams = updateZenModeAffectedStreams();
John Spurlock50ced3f2015-05-11 16:00:09 -04004180 int ringerModeAffectedStreams = Settings.System.getIntForUser(mContentResolver,
Eric Laurent24e0d9b2013-10-03 18:15:07 -07004181 Settings.System.MODE_RINGER_STREAMS_AFFECTED,
4182 ((1 << AudioSystem.STREAM_RING)|(1 << AudioSystem.STREAM_NOTIFICATION)|
4183 (1 << AudioSystem.STREAM_SYSTEM)|(1 << AudioSystem.STREAM_SYSTEM_ENFORCED)),
4184 UserHandle.USER_CURRENT);
4185
Muyuan Li1ed6df62016-06-18 11:16:52 -07004186 if (mIsSingleVolume) {
John Spurlock50ced3f2015-05-11 16:00:09 -04004187 ringerModeAffectedStreams = 0;
4188 } else if (mRingerModeDelegate != null) {
4189 ringerModeAffectedStreams = mRingerModeDelegate
4190 .getRingerModeAffectedStreams(ringerModeAffectedStreams);
Eric Laurent24e0d9b2013-10-03 18:15:07 -07004191 }
Jean-Michel Trivi8719a1d2017-11-06 11:52:51 -08004192 if (mCameraSoundForced) {
4193 ringerModeAffectedStreams &= ~(1 << AudioSystem.STREAM_SYSTEM_ENFORCED);
4194 } else {
4195 ringerModeAffectedStreams |= (1 << AudioSystem.STREAM_SYSTEM_ENFORCED);
Eric Laurent24e0d9b2013-10-03 18:15:07 -07004196 }
4197 if (mStreamVolumeAlias[AudioSystem.STREAM_DTMF] == AudioSystem.STREAM_RING) {
4198 ringerModeAffectedStreams |= (1 << AudioSystem.STREAM_DTMF);
4199 } else {
4200 ringerModeAffectedStreams &= ~(1 << AudioSystem.STREAM_DTMF);
4201 }
4202
4203 if (ringerModeAffectedStreams != mRingerModeAffectedStreams) {
4204 Settings.System.putIntForUser(mContentResolver,
4205 Settings.System.MODE_RINGER_STREAMS_AFFECTED,
4206 ringerModeAffectedStreams,
4207 UserHandle.USER_CURRENT);
4208 mRingerModeAffectedStreams = ringerModeAffectedStreams;
4209 return true;
4210 }
Beverlyd6964762018-02-16 14:07:03 -05004211 return updatedZenModeAffectedStreams;
Eric Laurent24e0d9b2013-10-03 18:15:07 -07004212 }
4213
John Spurlocka9dfbe8b2015-02-17 11:01:51 -05004214 @Override
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004215 public boolean isStreamAffectedByMute(int streamType) {
4216 return (mMuteAffectedStreams & (1 << streamType)) != 0;
4217 }
4218
4219 private void ensureValidDirection(int direction) {
RoboErik4197cb62015-01-21 15:45:32 -08004220 switch (direction) {
4221 case AudioManager.ADJUST_LOWER:
4222 case AudioManager.ADJUST_RAISE:
4223 case AudioManager.ADJUST_SAME:
4224 case AudioManager.ADJUST_MUTE:
4225 case AudioManager.ADJUST_UNMUTE:
4226 case AudioManager.ADJUST_TOGGLE_MUTE:
4227 break;
4228 default:
4229 throw new IllegalArgumentException("Bad direction " + direction);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004230 }
4231 }
4232
4233 private void ensureValidStreamType(int streamType) {
4234 if (streamType < 0 || streamType >= mStreamStates.length) {
4235 throw new IllegalArgumentException("Bad stream type " + streamType);
4236 }
4237 }
4238
RoboErik4197cb62015-01-21 15:45:32 -08004239 private boolean isMuteAdjust(int adjust) {
4240 return adjust == AudioManager.ADJUST_MUTE || adjust == AudioManager.ADJUST_UNMUTE
4241 || adjust == AudioManager.ADJUST_TOGGLE_MUTE;
4242 }
4243
Eric Laurent6d517662012-04-23 18:42:39 -07004244 private boolean isInCommunication() {
Nancy Chen0eb1e402014-08-21 22:52:29 -07004245 boolean IsInCall = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004246
Tyler Gunnef9f6f92014-09-12 22:16:17 -07004247 TelecomManager telecomManager =
4248 (TelecomManager) mContext.getSystemService(Context.TELECOM_SERVICE);
Eric Laurent38edfda2014-12-18 17:38:04 -08004249
4250 final long ident = Binder.clearCallingIdentity();
Tyler Gunnef9f6f92014-09-12 22:16:17 -07004251 IsInCall = telecomManager.isInCall();
Eric Laurent38edfda2014-12-18 17:38:04 -08004252 Binder.restoreCallingIdentity(ident);
Santos Cordon9eb45932014-06-27 12:28:43 -07004253
Eric Laurentda1af762017-12-15 16:54:35 -08004254 return (IsInCall || getMode() == AudioManager.MODE_IN_COMMUNICATION ||
4255 getMode() == AudioManager.MODE_IN_CALL);
Eric Laurent6d517662012-04-23 18:42:39 -07004256 }
Eric Laurent25101b02011-02-02 09:33:30 -08004257
Jean-Michel Trivifca1e602013-10-10 18:12:59 -07004258 /**
4259 * For code clarity for getActiveStreamType(int)
Julia Reynoldsd9e96e22017-11-07 10:33:08 -05004260 * @param delay_ms max time since last stream activity to consider
4261 * @return true if stream is active in streams handled by AudioFlinger now or
Jean-Michel Trivifca1e602013-10-10 18:12:59 -07004262 * in the last "delay_ms" ms.
4263 */
Julia Reynoldsd9e96e22017-11-07 10:33:08 -05004264 private boolean wasStreamActiveRecently(int stream, int delay_ms) {
4265 return AudioSystem.isStreamActive(stream, delay_ms)
4266 || AudioSystem.isStreamActiveRemotely(stream, delay_ms);
Jean-Michel Trivifca1e602013-10-10 18:12:59 -07004267 }
4268
Eric Laurent6d517662012-04-23 18:42:39 -07004269 private int getActiveStreamType(int suggestedStreamType) {
Muyuan Li1ed6df62016-06-18 11:16:52 -07004270 if (mIsSingleVolume
4271 && suggestedStreamType == AudioManager.USE_DEFAULT_STREAM_TYPE) {
4272 return AudioSystem.STREAM_MUSIC;
4273 }
4274
Eric Laurent212532b2014-07-21 15:43:18 -07004275 switch (mPlatformType) {
John Spurlock61560172015-02-06 19:46:04 -05004276 case AudioSystem.PLATFORM_VOICE:
Eric Laurent6d517662012-04-23 18:42:39 -07004277 if (isInCommunication()) {
Eric Laurent25101b02011-02-02 09:33:30 -08004278 if (AudioSystem.getForceUse(AudioSystem.FOR_COMMUNICATION)
4279 == AudioSystem.FORCE_BT_SCO) {
4280 // Log.v(TAG, "getActiveStreamType: Forcing STREAM_BLUETOOTH_SCO...");
4281 return AudioSystem.STREAM_BLUETOOTH_SCO;
4282 } else {
4283 // Log.v(TAG, "getActiveStreamType: Forcing STREAM_VOICE_CALL...");
4284 return AudioSystem.STREAM_VOICE_CALL;
4285 }
Eric Laurent25101b02011-02-02 09:33:30 -08004286 } else if (suggestedStreamType == AudioManager.USE_DEFAULT_STREAM_TYPE) {
Julia Reynoldsd9e96e22017-11-07 10:33:08 -05004287 if (wasStreamActiveRecently(AudioSystem.STREAM_RING, sStreamOverrideDelayMs)) {
Jean-Michel Trivi3114ce32012-06-11 15:03:52 -07004288 if (DEBUG_VOL)
Julia Reynoldsd9e96e22017-11-07 10:33:08 -05004289 Log.v(TAG, "getActiveStreamType: Forcing STREAM_RING stream active");
4290 return AudioSystem.STREAM_RING;
4291 } else if (wasStreamActiveRecently(
4292 AudioSystem.STREAM_NOTIFICATION, sStreamOverrideDelayMs)) {
4293 if (DEBUG_VOL)
4294 Log.v(TAG, "getActiveStreamType: Forcing STREAM_NOTIFICATION stream active");
4295 return AudioSystem.STREAM_NOTIFICATION;
4296 } else {
4297 if (DEBUG_VOL)
4298 Log.v(TAG, "getActiveStreamType: Forcing STREAM_MUSIC b/c default");
Jean-Michel Trivi3114ce32012-06-11 15:03:52 -07004299 return AudioSystem.STREAM_MUSIC;
Jean-Michel Trivi3114ce32012-06-11 15:03:52 -07004300 }
Julia Reynoldsd9e96e22017-11-07 10:33:08 -05004301 } else if (
4302 wasStreamActiveRecently(AudioSystem.STREAM_NOTIFICATION, sStreamOverrideDelayMs)) {
Jean-Michel Trivi3114ce32012-06-11 15:03:52 -07004303 if (DEBUG_VOL)
Julia Reynoldsd9e96e22017-11-07 10:33:08 -05004304 Log.v(TAG, "getActiveStreamType: Forcing STREAM_NOTIFICATION stream active");
4305 return AudioSystem.STREAM_NOTIFICATION;
4306 } else if (wasStreamActiveRecently(AudioSystem.STREAM_RING, sStreamOverrideDelayMs)) {
4307 if (DEBUG_VOL)
4308 Log.v(TAG, "getActiveStreamType: Forcing STREAM_RING stream active");
4309 return AudioSystem.STREAM_RING;
Eric Laurent25101b02011-02-02 09:33:30 -08004310 }
Eric Laurent212532b2014-07-21 15:43:18 -07004311 default:
Eric Laurent6d517662012-04-23 18:42:39 -07004312 if (isInCommunication()) {
Eric Laurent25101b02011-02-02 09:33:30 -08004313 if (AudioSystem.getForceUse(AudioSystem.FOR_COMMUNICATION)
4314 == AudioSystem.FORCE_BT_SCO) {
Jean-Michel Trivi3114ce32012-06-11 15:03:52 -07004315 if (DEBUG_VOL) Log.v(TAG, "getActiveStreamType: Forcing STREAM_BLUETOOTH_SCO");
Eric Laurent25101b02011-02-02 09:33:30 -08004316 return AudioSystem.STREAM_BLUETOOTH_SCO;
4317 } else {
Jean-Michel Trivi3114ce32012-06-11 15:03:52 -07004318 if (DEBUG_VOL) Log.v(TAG, "getActiveStreamType: Forcing STREAM_VOICE_CALL");
Eric Laurent25101b02011-02-02 09:33:30 -08004319 return AudioSystem.STREAM_VOICE_CALL;
4320 }
Julia Reynoldsd9e96e22017-11-07 10:33:08 -05004321 } else if (AudioSystem.isStreamActive(
4322 AudioSystem.STREAM_NOTIFICATION, sStreamOverrideDelayMs)) {
Jean-Michel Trivi3114ce32012-06-11 15:03:52 -07004323 if (DEBUG_VOL) Log.v(TAG, "getActiveStreamType: Forcing STREAM_NOTIFICATION");
Eric Laurent25101b02011-02-02 09:33:30 -08004324 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;
Jean-Michel Trivi3114ce32012-06-11 15:03:52 -07004329 } else if (suggestedStreamType == AudioManager.USE_DEFAULT_STREAM_TYPE) {
Julia Reynoldsd9e96e22017-11-07 10:33:08 -05004330 if (AudioSystem.isStreamActive(
4331 AudioSystem.STREAM_NOTIFICATION, sStreamOverrideDelayMs)) {
4332 if (DEBUG_VOL) Log.v(TAG, "getActiveStreamType: Forcing STREAM_NOTIFICATION");
John Spurlockeb1d88d2014-07-19 14:49:19 -04004333 return AudioSystem.STREAM_NOTIFICATION;
Julia Reynoldsd9e96e22017-11-07 10:33:08 -05004334 } else if (AudioSystem.isStreamActive(
4335 AudioSystem.STREAM_RING, sStreamOverrideDelayMs)) {
4336 if (DEBUG_VOL) Log.v(TAG, "getActiveStreamType: Forcing STREAM_RING");
4337 return AudioSystem.STREAM_RING;
4338 } else {
4339 if (DEBUG_VOL) Log.v(TAG, "getActiveStreamType: using STREAM_MUSIC as default");
4340 return AudioSystem.STREAM_MUSIC;
Jean-Michel Trivi3114ce32012-06-11 15:03:52 -07004341 }
Joe Onoratoc7fcba42011-01-05 16:53:11 -08004342 }
Eric Laurent212532b2014-07-21 15:43:18 -07004343 break;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004344 }
Eric Laurent212532b2014-07-21 15:43:18 -07004345 if (DEBUG_VOL) Log.v(TAG, "getActiveStreamType: Returning suggested type "
4346 + suggestedStreamType);
4347 return suggestedStreamType;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004348 }
4349
John Spurlockbcc10872014-11-28 15:29:21 -05004350 private void broadcastRingerMode(String action, int ringerMode) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004351 // Send sticky broadcast
John Spurlockbcc10872014-11-28 15:29:21 -05004352 Intent broadcast = new Intent(action);
Glenn Kastenba195eb2011-12-13 09:30:40 -08004353 broadcast.putExtra(AudioManager.EXTRA_RINGER_MODE, ringerMode);
Dianne Hackborn1c633fc2009-12-08 19:45:14 -08004354 broadcast.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT
4355 | Intent.FLAG_RECEIVER_REPLACE_PENDING);
Dianne Hackborn5ac72a22012-08-29 18:32:08 -07004356 sendStickyBroadcastToAll(broadcast);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004357 }
4358
4359 private void broadcastVibrateSetting(int vibrateType) {
4360 // Send broadcast
Sudheer Shankafc46e9b2016-10-21 17:55:27 -07004361 if (mActivityManagerInternal.isSystemReady()) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004362 Intent broadcast = new Intent(AudioManager.VIBRATE_SETTING_CHANGED_ACTION);
4363 broadcast.putExtra(AudioManager.EXTRA_VIBRATE_TYPE, vibrateType);
4364 broadcast.putExtra(AudioManager.EXTRA_VIBRATE_SETTING, getVibrateSetting(vibrateType));
Dianne Hackborn5ac72a22012-08-29 18:32:08 -07004365 sendBroadcastToAll(broadcast);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004366 }
4367 }
4368
4369 // Message helper methods
Jean-Michel Trivi2d8dab52012-05-30 18:13:59 -07004370 /**
4371 * Queue a message on the given handler's message queue, after acquiring the service wake lock.
4372 * Note that the wake lock needs to be released after the message has been handled.
4373 */
4374 private void queueMsgUnderWakeLock(Handler handler, int msg,
4375 int arg1, int arg2, Object obj, int delay) {
Eric Laurenta4dfbdc52013-10-01 11:53:51 -07004376 final long ident = Binder.clearCallingIdentity();
4377 // Always acquire the wake lock as AudioService because it is released by the
4378 // message handler.
Jean-Michel Trivifa9a6982013-06-27 16:22:58 -07004379 mAudioEventWakeLock.acquire();
Eric Laurenta4dfbdc52013-10-01 11:53:51 -07004380 Binder.restoreCallingIdentity(ident);
Jean-Michel Trivi2d8dab52012-05-30 18:13:59 -07004381 sendMsg(handler, msg, SENDMSG_QUEUE, arg1, arg2, obj, delay);
4382 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004383
Eric Laurentafbb0472011-12-15 09:04:23 -08004384 private static void sendMsg(Handler handler, int msg,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004385 int existingMsgPolicy, int arg1, int arg2, Object obj, int delay) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004386
4387 if (existingMsgPolicy == SENDMSG_REPLACE) {
4388 handler.removeMessages(msg);
4389 } else if (existingMsgPolicy == SENDMSG_NOOP && handler.hasMessages(msg)) {
4390 return;
4391 }
Eric Laurentadbe8bf2014-11-03 18:26:32 -08004392 synchronized (mLastDeviceConnectMsgTime) {
4393 long time = SystemClock.uptimeMillis() + delay;
4394 handler.sendMessageAtTime(handler.obtainMessage(msg, arg1, arg2, obj), time);
4395 if (msg == MSG_SET_WIRED_DEVICE_CONNECTION_STATE ||
4396 msg == MSG_SET_A2DP_SRC_CONNECTION_STATE ||
Jakub Pawlowskif9570f32018-02-21 17:15:12 -08004397 msg == MSG_SET_A2DP_SINK_CONNECTION_STATE ||
4398 msg == MSG_SET_HEARING_AID_CONNECTION_STATE) {
Eric Laurentadbe8bf2014-11-03 18:26:32 -08004399 mLastDeviceConnectMsgTime = time;
4400 }
4401 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004402 }
4403
4404 boolean checkAudioSettingsPermission(String method) {
Jean-Michel Triviccd654e2014-09-03 17:48:47 -07004405 if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.MODIFY_AUDIO_SETTINGS)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004406 == PackageManager.PERMISSION_GRANTED) {
4407 return true;
4408 }
4409 String msg = "Audio Settings Permission Denial: " + method + " from pid="
4410 + Binder.getCallingPid()
4411 + ", uid=" + Binder.getCallingUid();
4412 Log.w(TAG, msg);
4413 return false;
4414 }
4415
Eric Laurent9bc8358d2011-11-18 16:43:31 -08004416 private int getDeviceForStream(int stream) {
John Spurlock8a52c442015-03-26 14:23:58 -04004417 int device = getDevicesForStream(stream);
Eric Laurent9bc8358d2011-11-18 16:43:31 -08004418 if ((device & (device - 1)) != 0) {
4419 // Multiple device selection is either:
4420 // - speaker + one other device: give priority to speaker in this case.
4421 // - one A2DP device + another device: happens with duplicated output. In this case
4422 // retain the device on the A2DP output as the other must not correspond to an active
4423 // selection if not the speaker.
Jungshik Jangc9ff9682014-09-15 17:41:06 +09004424 // - HDMI-CEC system audio mode only output: give priority to available item in order.
Eric Laurent9bc8358d2011-11-18 16:43:31 -08004425 if ((device & AudioSystem.DEVICE_OUT_SPEAKER) != 0) {
4426 device = AudioSystem.DEVICE_OUT_SPEAKER;
Jungshik Jangc9ff9682014-09-15 17:41:06 +09004427 } else if ((device & AudioSystem.DEVICE_OUT_HDMI_ARC) != 0) {
4428 device = AudioSystem.DEVICE_OUT_HDMI_ARC;
4429 } else if ((device & AudioSystem.DEVICE_OUT_SPDIF) != 0) {
4430 device = AudioSystem.DEVICE_OUT_SPDIF;
4431 } else if ((device & AudioSystem.DEVICE_OUT_AUX_LINE) != 0) {
4432 device = AudioSystem.DEVICE_OUT_AUX_LINE;
Eric Laurent9bc8358d2011-11-18 16:43:31 -08004433 } else {
4434 device &= AudioSystem.DEVICE_OUT_ALL_A2DP;
4435 }
4436 }
4437 return device;
4438 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004439
John Spurlock8a52c442015-03-26 14:23:58 -04004440 private int getDevicesForStream(int stream) {
4441 return getDevicesForStream(stream, true /*checkOthers*/);
4442 }
4443
4444 private int getDevicesForStream(int stream, boolean checkOthers) {
4445 ensureValidStreamType(stream);
4446 synchronized (VolumeStreamState.class) {
4447 return mStreamStates[stream].observeDevicesForStream_syncVSS(checkOthers);
4448 }
4449 }
4450
4451 private void observeDevicesForStreams(int skipStream) {
4452 synchronized (VolumeStreamState.class) {
4453 for (int stream = 0; stream < mStreamStates.length; stream++) {
4454 if (stream != skipStream) {
4455 mStreamStates[stream].observeDevicesForStream_syncVSS(false /*checkOthers*/);
4456 }
4457 }
4458 }
4459 }
4460
Paul McLean10804eb2015-01-28 11:16:35 -08004461 /*
4462 * A class just for packaging up a set of connection parameters.
4463 */
Jean-Michel Trivicf170362017-08-24 17:24:57 -07004464 class WiredDeviceConnectionState {
John Spurlock90874332015-03-10 16:00:54 -04004465 public final int mType;
4466 public final int mState;
4467 public final String mAddress;
4468 public final String mName;
4469 public final String mCaller;
Paul McLean10804eb2015-01-28 11:16:35 -08004470
John Spurlock90874332015-03-10 16:00:54 -04004471 public WiredDeviceConnectionState(int type, int state, String address, String name,
4472 String caller) {
Paul McLean10804eb2015-01-28 11:16:35 -08004473 mType = type;
4474 mState = state;
4475 mAddress = address;
4476 mName = name;
John Spurlock90874332015-03-10 16:00:54 -04004477 mCaller = caller;
Paul McLean10804eb2015-01-28 11:16:35 -08004478 }
4479 }
4480
John Spurlock90874332015-03-10 16:00:54 -04004481 public void setWiredDeviceConnectionState(int type, int state, String address, String name,
4482 String caller) {
Eric Laurentb1fbaac2012-05-29 09:24:28 -07004483 synchronized (mConnectedDevices) {
Paul McLean394a8e12015-03-03 10:29:19 -07004484 if (DEBUG_DEVICES) {
4485 Slog.i(TAG, "setWiredDeviceConnectionState(" + state + " nm: " + name + " addr:"
4486 + address + ")");
4487 }
Eric Laurentcdae4762017-04-28 18:00:04 -07004488 int delay = checkSendBecomingNoisyIntent(type, state, AudioSystem.DEVICE_NONE);
Jean-Michel Trivi2d8dab52012-05-30 18:13:59 -07004489 queueMsgUnderWakeLock(mAudioHandler,
Eric Laurentb1fbaac2012-05-29 09:24:28 -07004490 MSG_SET_WIRED_DEVICE_CONNECTION_STATE,
Pavlin Radoslavov44a4ef02016-12-21 12:05:51 -08004491 0 /* arg1 unused */,
4492 0 /* arg2 unused */,
John Spurlock90874332015-03-10 16:00:54 -04004493 new WiredDeviceConnectionState(type, state, address, name, caller),
Eric Laurentb1fbaac2012-05-29 09:24:28 -07004494 delay);
4495 }
4496 }
4497
Jakub Pawlowski10c90612018-02-21 13:28:46 -08004498 @Override
4499 public void setHearingAidDeviceConnectionState(BluetoothDevice device, int state)
4500 {
Jakub Pawlowskif9570f32018-02-21 17:15:12 -08004501 Log.i(TAG, "setBluetoothHearingAidDeviceConnectionState");
4502
4503 setBluetoothHearingAidDeviceConnectionState(
4504 device, state, false /* suppressNoisyIntent */, AudioSystem.DEVICE_NONE);
4505 }
4506
4507 public int setBluetoothHearingAidDeviceConnectionState(
4508 BluetoothDevice device, int state, boolean suppressNoisyIntent,
4509 int musicDevice)
4510 {
4511 int delay;
4512 synchronized (mConnectedDevices) {
4513 if (!suppressNoisyIntent) {
4514 int intState = (state == BluetoothHearingAid.STATE_CONNECTED) ? 1 : 0;
4515 delay = checkSendBecomingNoisyIntent(AudioSystem.DEVICE_OUT_HEARING_AID,
4516 intState, musicDevice);
4517 } else {
4518 delay = 0;
4519 }
4520 queueMsgUnderWakeLock(mAudioHandler,
4521 MSG_SET_HEARING_AID_CONNECTION_STATE,
4522 state,
4523 0 /* arg2 unused */,
4524 device,
4525 delay);
4526 }
4527 return delay;
Jakub Pawlowski10c90612018-02-21 13:28:46 -08004528 }
4529
Mike Lockwood0a40ec22014-05-21 10:08:50 -07004530 public int setBluetoothA2dpDeviceConnectionState(BluetoothDevice device, int state, int profile)
Eric Laurentb1fbaac2012-05-29 09:24:28 -07004531 {
Pavlin Radoslavov82e06462018-01-19 18:20:04 -08004532 return setBluetoothA2dpDeviceConnectionStateSuppressNoisyIntent(
4533 device, state, profile, false /* suppressNoisyIntent */);
4534 }
4535
4536 public int setBluetoothA2dpDeviceConnectionStateSuppressNoisyIntent(BluetoothDevice device,
4537 int state, int profile, boolean suppressNoisyIntent)
4538 {
Eric Laurent4724ea72017-05-23 10:39:38 -07004539 if (mAudioHandler.hasMessages(MSG_SET_A2DP_SINK_CONNECTION_STATE, device)) {
Eric Laurentcdae4762017-04-28 18:00:04 -07004540 return 0;
4541 }
4542 return setBluetoothA2dpDeviceConnectionStateInt(
Pavlin Radoslavov82e06462018-01-19 18:20:04 -08004543 device, state, profile, suppressNoisyIntent, AudioSystem.DEVICE_NONE);
Eric Laurentcdae4762017-04-28 18:00:04 -07004544 }
4545
4546 public int setBluetoothA2dpDeviceConnectionStateInt(
Pavlin Radoslavov82e06462018-01-19 18:20:04 -08004547 BluetoothDevice device, int state, int profile, boolean suppressNoisyIntent,
4548 int musicDevice)
Eric Laurentcdae4762017-04-28 18:00:04 -07004549 {
Eric Laurentb1fbaac2012-05-29 09:24:28 -07004550 int delay;
Mike Lockwood0a40ec22014-05-21 10:08:50 -07004551 if (profile != BluetoothProfile.A2DP && profile != BluetoothProfile.A2DP_SINK) {
4552 throw new IllegalArgumentException("invalid profile " + profile);
4553 }
Eric Laurentb1fbaac2012-05-29 09:24:28 -07004554 synchronized (mConnectedDevices) {
Pavlin Radoslavov82e06462018-01-19 18:20:04 -08004555 if (profile == BluetoothProfile.A2DP && !suppressNoisyIntent) {
Eric Laurentcdae4762017-04-28 18:00:04 -07004556 int intState = (state == BluetoothA2dp.STATE_CONNECTED) ? 1 : 0;
Mike Lockwood0a40ec22014-05-21 10:08:50 -07004557 delay = checkSendBecomingNoisyIntent(AudioSystem.DEVICE_OUT_BLUETOOTH_A2DP,
Eric Laurentcdae4762017-04-28 18:00:04 -07004558 intState, musicDevice);
Mike Lockwood0a40ec22014-05-21 10:08:50 -07004559 } else {
4560 delay = 0;
4561 }
Jean-Michel Trivi2d8dab52012-05-30 18:13:59 -07004562 queueMsgUnderWakeLock(mAudioHandler,
Mike Lockwood0a40ec22014-05-21 10:08:50 -07004563 (profile == BluetoothProfile.A2DP ?
4564 MSG_SET_A2DP_SINK_CONNECTION_STATE : MSG_SET_A2DP_SRC_CONNECTION_STATE),
Eric Laurentb1fbaac2012-05-29 09:24:28 -07004565 state,
Pavlin Radoslavov44a4ef02016-12-21 12:05:51 -08004566 0 /* arg2 unused */,
Eric Laurentb1fbaac2012-05-29 09:24:28 -07004567 device,
4568 delay);
4569 }
4570 return delay;
4571 }
4572
Pavlin Radoslavov44a4ef02016-12-21 12:05:51 -08004573 public void handleBluetoothA2dpDeviceConfigChange(BluetoothDevice device)
4574 {
4575 synchronized (mConnectedDevices) {
4576 queueMsgUnderWakeLock(mAudioHandler,
4577 MSG_A2DP_DEVICE_CONFIG_CHANGE,
4578 0 /* arg1 unused */,
4579 0 /* arg1 unused */,
4580 device,
4581 0 /* delay */);
4582 }
4583 }
4584
Jean-Michel Trivi1ab43f62017-04-27 15:37:34 -07004585 private static final int DEVICE_MEDIA_UNMUTED_ON_PLUG =
4586 AudioSystem.DEVICE_OUT_WIRED_HEADSET | AudioSystem.DEVICE_OUT_WIRED_HEADPHONE |
4587 AudioSystem.DEVICE_OUT_LINE |
4588 AudioSystem.DEVICE_OUT_ALL_A2DP |
4589 AudioSystem.DEVICE_OUT_ALL_USB |
4590 AudioSystem.DEVICE_OUT_HDMI;
4591
4592 private void onAccessoryPlugMediaUnmute(int newDevice) {
4593 if (DEBUG_VOL) {
4594 Log.i(TAG, String.format("onAccessoryPlugMediaUnmute newDevice=%d [%s]",
4595 newDevice, AudioSystem.getOutputDeviceName(newDevice)));
4596 }
4597 synchronized (mConnectedDevices) {
Eric Laurent7fb83d92017-09-28 09:36:36 -07004598 if (mNm.getZenMode() != Settings.Global.ZEN_MODE_NO_INTERRUPTIONS
4599 && (newDevice & DEVICE_MEDIA_UNMUTED_ON_PLUG) != 0
Jean-Michel Trivi1ab43f62017-04-27 15:37:34 -07004600 && mStreamStates[AudioSystem.STREAM_MUSIC].mIsMuted
4601 && mStreamStates[AudioSystem.STREAM_MUSIC].getIndex(newDevice) != 0
4602 && (newDevice & AudioSystem.getDevicesForStream(AudioSystem.STREAM_MUSIC)) != 0)
4603 {
4604 if (DEBUG_VOL) {
4605 Log.i(TAG, String.format(" onAccessoryPlugMediaUnmute unmuting device=%d [%s]",
4606 newDevice, AudioSystem.getOutputDeviceName(newDevice)));
4607 }
4608 mStreamStates[AudioSystem.STREAM_MUSIC].mute(false);
4609 }
4610 }
4611 }
4612
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004613 ///////////////////////////////////////////////////////////////////////////
4614 // Inner classes
4615 ///////////////////////////////////////////////////////////////////////////
4616
Eric Laurent8fa4d6f2014-10-30 14:13:03 -07004617 // NOTE: Locking order for synchronized objects related to volume or ringer mode management:
4618 // 1 mScoclient OR mSafeMediaVolumeState
4619 // 2 mSetModeDeathHandlers
4620 // 3 mSettingsLock
4621 // 4 VolumeStreamState.class
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004622 public class VolumeStreamState {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004623 private final int mStreamType;
Jean-Michel Trivie05eef82018-03-08 18:56:34 -08004624 private int mIndexMin;
4625 private int mIndexMax;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004626
RoboErik4197cb62015-01-21 15:45:32 -08004627 private boolean mIsMuted;
Jean-Michel Trivi11a74a72009-10-27 17:39:30 -07004628 private String mVolumeIndexSettingName;
John Spurlock8a52c442015-03-26 14:23:58 -04004629 private int mObservedDevices;
John Spurlockb6e19e32015-03-10 21:33:44 -04004630
John Spurlock2bb02ec2015-03-02 13:13:06 -05004631 private final SparseIntArray mIndexMap = new SparseIntArray(8);
John Spurlockf63860c2015-02-19 09:46:27 -05004632 private final Intent mVolumeChanged;
John Spurlock8a52c442015-03-26 14:23:58 -04004633 private final Intent mStreamDevicesChanged;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004634
Eric Laurenta553c252009-07-17 12:17:14 -07004635 private VolumeStreamState(String settingName, int streamType) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004636
Eric Laurent9bc8358d2011-11-18 16:43:31 -08004637 mVolumeIndexSettingName = settingName;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004638
4639 mStreamType = streamType;
John Spurlockb6e19e32015-03-10 21:33:44 -04004640 mIndexMin = MIN_STREAM_VOLUME[streamType] * 10;
4641 mIndexMax = MAX_STREAM_VOLUME[streamType] * 10;
4642 AudioSystem.initStreamVolume(streamType, mIndexMin / 10, mIndexMax / 10);
Eric Laurent9bc8358d2011-11-18 16:43:31 -08004643
Eric Laurent33902db2012-10-07 16:15:07 -07004644 readSettings();
John Spurlockf63860c2015-02-19 09:46:27 -05004645 mVolumeChanged = new Intent(AudioManager.VOLUME_CHANGED_ACTION);
4646 mVolumeChanged.putExtra(AudioManager.EXTRA_VOLUME_STREAM_TYPE, mStreamType);
John Spurlock8a52c442015-03-26 14:23:58 -04004647 mStreamDevicesChanged = new Intent(AudioManager.STREAM_DEVICES_CHANGED_ACTION);
4648 mStreamDevicesChanged.putExtra(AudioManager.EXTRA_VOLUME_STREAM_TYPE, mStreamType);
4649 }
4650
4651 public int observeDevicesForStream_syncVSS(boolean checkOthers) {
4652 final int devices = AudioSystem.getDevicesForStream(mStreamType);
4653 if (devices == mObservedDevices) {
4654 return devices;
4655 }
4656 final int prevDevices = mObservedDevices;
4657 mObservedDevices = devices;
4658 if (checkOthers) {
4659 // one stream's devices have changed, check the others
4660 observeDevicesForStreams(mStreamType);
4661 }
4662 // log base stream changes to the event log
4663 if (mStreamVolumeAlias[mStreamType] == mStreamType) {
4664 EventLogTags.writeStreamDevicesChanged(mStreamType, prevDevices, devices);
4665 }
4666 sendBroadcastToAll(mStreamDevicesChanged
4667 .putExtra(AudioManager.EXTRA_PREV_VOLUME_STREAM_DEVICES, prevDevices)
4668 .putExtra(AudioManager.EXTRA_VOLUME_STREAM_DEVICES, devices));
4669 return devices;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004670 }
4671
Jean-Michel Trivia53b7052017-04-12 18:27:01 -07004672 public @Nullable String getSettingNameForDevice(int device) {
4673 if (!hasValidSettingsName()) {
4674 return null;
Eric Laurent9bc8358d2011-11-18 16:43:31 -08004675 }
Jean-Michel Trivia53b7052017-04-12 18:27:01 -07004676 final String suffix = AudioSystem.getOutputDeviceName(device);
4677 if (suffix.isEmpty()) {
4678 return mVolumeIndexSettingName;
4679 }
4680 return mVolumeIndexSettingName + "_" + suffix;
4681 }
4682
4683 private boolean hasValidSettingsName() {
4684 return (mVolumeIndexSettingName != null && !mVolumeIndexSettingName.isEmpty());
Jean-Michel Trivi11a74a72009-10-27 17:39:30 -07004685 }
4686
Eric Laurentfdbee862014-05-12 15:26:12 -07004687 public void readSettings() {
Jean-Michel Trivi8719a1d2017-11-06 11:52:51 -08004688 synchronized (mSettingsLock) {
4689 synchronized (VolumeStreamState.class) {
4690 // force maximum volume on all streams if fixed volume property is set
4691 if (mUseFixedVolume) {
4692 mIndexMap.put(AudioSystem.DEVICE_OUT_DEFAULT, mIndexMax);
4693 return;
4694 }
4695 // do not read system stream volume from settings: this stream is always aliased
4696 // to another stream type and its volume is never persisted. Values in settings can
4697 // only be stale values
4698 if ((mStreamType == AudioSystem.STREAM_SYSTEM) ||
4699 (mStreamType == AudioSystem.STREAM_SYSTEM_ENFORCED)) {
4700 int index = 10 * AudioSystem.DEFAULT_STREAM_VOLUME[mStreamType];
Eric Laurentfdbee862014-05-12 15:26:12 -07004701 if (mCameraSoundForced) {
4702 index = mIndexMax;
4703 }
Jean-Michel Trivi8719a1d2017-11-06 11:52:51 -08004704 mIndexMap.put(AudioSystem.DEVICE_OUT_DEFAULT, index);
4705 return;
Eric Laurentdd45d012012-10-08 09:04:34 -07004706 }
Eric Laurent9bc8358d2011-11-18 16:43:31 -08004707 }
Jean-Michel Trivi8719a1d2017-11-06 11:52:51 -08004708 }
4709 synchronized (VolumeStreamState.class) {
Eric Laurentfdbee862014-05-12 15:26:12 -07004710 int remainingDevices = AudioSystem.DEVICE_OUT_ALL;
4711
4712 for (int i = 0; remainingDevices != 0; i++) {
4713 int device = (1 << i);
4714 if ((device & remainingDevices) == 0) {
4715 continue;
4716 }
4717 remainingDevices &= ~device;
4718
4719 // retrieve current volume for device
Eric Laurentfdbee862014-05-12 15:26:12 -07004720 // if no volume stored for current stream and device, use default volume if default
4721 // device, continue otherwise
4722 int defaultIndex = (device == AudioSystem.DEVICE_OUT_DEFAULT) ?
John Spurlock61560172015-02-06 19:46:04 -05004723 AudioSystem.DEFAULT_STREAM_VOLUME[mStreamType] : -1;
Jean-Michel Trivia53b7052017-04-12 18:27:01 -07004724 int index;
4725 if (!hasValidSettingsName()) {
4726 index = defaultIndex;
4727 } else {
4728 String name = getSettingNameForDevice(device);
4729 index = Settings.System.getIntForUser(
4730 mContentResolver, name, defaultIndex, UserHandle.USER_CURRENT);
4731 }
Eric Laurentfdbee862014-05-12 15:26:12 -07004732 if (index == -1) {
4733 continue;
4734 }
4735
John Spurlock2bb02ec2015-03-02 13:13:06 -05004736 mIndexMap.put(device, getValidIndex(10 * index));
Eric Laurentdd45d012012-10-08 09:04:34 -07004737 }
Eric Laurent9bc8358d2011-11-18 16:43:31 -08004738 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004739 }
4740
Liejun Tao39fb5672016-03-09 15:52:13 -06004741 private int getAbsoluteVolumeIndex(int index) {
4742 /* Special handling for Bluetooth Absolute Volume scenario
4743 * If we send full audio gain, some accessories are too loud even at its lowest
4744 * volume. We are not able to enumerate all such accessories, so here is the
4745 * workaround from phone side.
4746 * Pre-scale volume at lowest volume steps 1 2 and 3.
4747 * For volume step 0, set audio gain to 0 as some accessories won't mute on their end.
4748 */
4749 if (index == 0) {
4750 // 0% for volume 0
4751 index = 0;
4752 } else if (index == 1) {
4753 // 50% for volume 1
4754 index = (int)(mIndexMax * 0.5) /10;
4755 } else if (index == 2) {
4756 // 70% for volume 2
4757 index = (int)(mIndexMax * 0.70) /10;
4758 } else if (index == 3) {
4759 // 85% for volume 3
4760 index = (int)(mIndexMax * 0.85) /10;
4761 } else {
4762 // otherwise, full gain
4763 index = (mIndexMax + 5)/10;
4764 }
4765 return index;
4766 }
4767
Eric Laurent8fa4d6f2014-10-30 14:13:03 -07004768 // must be called while synchronized VolumeStreamState.class
4769 public void applyDeviceVolume_syncVSS(int device) {
Eric Laurent42b041e2013-03-29 11:36:03 -07004770 int index;
RoboErik4197cb62015-01-21 15:45:32 -08004771 if (mIsMuted) {
Eric Laurent42b041e2013-03-29 11:36:03 -07004772 index = 0;
Liejun Tao4565a472016-01-20 17:52:20 -06004773 } else if ((device & AudioSystem.DEVICE_OUT_ALL_A2DP) != 0 && mAvrcpAbsVolSupported) {
Liejun Tao39fb5672016-03-09 15:52:13 -06004774 index = getAbsoluteVolumeIndex((getIndex(device) + 5)/10);
Liejun Tao4565a472016-01-20 17:52:20 -06004775 } else if ((device & mFullVolumeDevices) != 0) {
Matthew Xiec9d1d5f2013-09-12 00:32:22 -07004776 index = (mIndexMax + 5)/10;
Jakub Pawlowskic274fb22018-04-04 10:15:12 -07004777 } else if ((device & AudioSystem.DEVICE_OUT_HEARING_AID) != 0) {
4778 index = (mIndexMax + 5)/10;
Eric Laurentcd772d02013-10-30 18:31:07 -07004779 } else {
Eric Laurent42b041e2013-03-29 11:36:03 -07004780 index = (getIndex(device) + 5)/10;
4781 }
4782 AudioSystem.setStreamVolumeIndex(mStreamType, index, device);
Eric Laurent9bc8358d2011-11-18 16:43:31 -08004783 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004784
Eric Laurentfdbee862014-05-12 15:26:12 -07004785 public void applyAllVolumes() {
4786 synchronized (VolumeStreamState.class) {
Eric Laurentd9ac2be2016-04-07 14:04:23 -07004787 // apply device specific volumes first
Eric Laurentfdbee862014-05-12 15:26:12 -07004788 int index;
John Spurlock2bb02ec2015-03-02 13:13:06 -05004789 for (int i = 0; i < mIndexMap.size(); i++) {
Eric Laurentd9ac2be2016-04-07 14:04:23 -07004790 final int device = mIndexMap.keyAt(i);
Eric Laurentfdbee862014-05-12 15:26:12 -07004791 if (device != AudioSystem.DEVICE_OUT_DEFAULT) {
RoboErik4197cb62015-01-21 15:45:32 -08004792 if (mIsMuted) {
Eric Laurentfdbee862014-05-12 15:26:12 -07004793 index = 0;
Liejun Tao39fb5672016-03-09 15:52:13 -06004794 } else if ((device & AudioSystem.DEVICE_OUT_ALL_A2DP) != 0 &&
4795 mAvrcpAbsVolSupported) {
4796 index = getAbsoluteVolumeIndex((getIndex(device) + 5)/10);
4797 } else if ((device & mFullVolumeDevices) != 0) {
Eric Laurentfdbee862014-05-12 15:26:12 -07004798 index = (mIndexMax + 5)/10;
Jakub Pawlowskic274fb22018-04-04 10:15:12 -07004799 } else if ((device & AudioSystem.DEVICE_OUT_HEARING_AID) != 0) {
4800 index = (mIndexMax + 5)/10;
Eric Laurentfdbee862014-05-12 15:26:12 -07004801 } else {
John Spurlock2bb02ec2015-03-02 13:13:06 -05004802 index = (mIndexMap.valueAt(i) + 5)/10;
Eric Laurentfdbee862014-05-12 15:26:12 -07004803 }
4804 AudioSystem.setStreamVolumeIndex(mStreamType, index, device);
Eric Laurent42b041e2013-03-29 11:36:03 -07004805 }
Eric Laurent9bc8358d2011-11-18 16:43:31 -08004806 }
Eric Laurentd9ac2be2016-04-07 14:04:23 -07004807 // apply default volume last: by convention , default device volume will be used
4808 // by audio policy manager if no explicit volume is present for a given device type
4809 if (mIsMuted) {
4810 index = 0;
4811 } else {
4812 index = (getIndex(AudioSystem.DEVICE_OUT_DEFAULT) + 5)/10;
4813 }
4814 AudioSystem.setStreamVolumeIndex(
4815 mStreamType, index, AudioSystem.DEVICE_OUT_DEFAULT);
Eric Laurent9bc8358d2011-11-18 16:43:31 -08004816 }
4817 }
4818
John Spurlock90874332015-03-10 16:00:54 -04004819 public boolean adjustIndex(int deltaIndex, int device, String caller) {
4820 return setIndex(getIndex(device) + deltaIndex, device, caller);
Eric Laurent9bc8358d2011-11-18 16:43:31 -08004821 }
4822
John Spurlock90874332015-03-10 16:00:54 -04004823 public boolean setIndex(int index, int device, String caller) {
Jack He6dd78c12018-02-12 21:00:24 -08004824 boolean changed;
John Spurlockf63860c2015-02-19 09:46:27 -05004825 int oldIndex;
Jean-Michel Trivi8719a1d2017-11-06 11:52:51 -08004826 synchronized (mSettingsLock) {
4827 synchronized (VolumeStreamState.class) {
4828 oldIndex = getIndex(device);
4829 index = getValidIndex(index);
Eric Laurentfdbee862014-05-12 15:26:12 -07004830 if ((mStreamType == AudioSystem.STREAM_SYSTEM_ENFORCED) && mCameraSoundForced) {
4831 index = mIndexMax;
Eric Laurenta553c252009-07-17 12:17:14 -07004832 }
Jean-Michel Trivi8719a1d2017-11-06 11:52:51 -08004833 mIndexMap.put(device, index);
Eric Laurentfdbee862014-05-12 15:26:12 -07004834
Jean-Michel Trivi8719a1d2017-11-06 11:52:51 -08004835 changed = oldIndex != index;
4836 // Apply change to all streams using this one as alias if:
4837 // - the index actually changed OR
4838 // - there is no volume index stored for this device on alias stream.
4839 // If changing volume of current device, also change volume of current
4840 // device on aliased stream
Jack He6dd78c12018-02-12 21:00:24 -08004841 final boolean isCurrentDevice = (device == getDeviceForStream(mStreamType));
Jean-Michel Trivi8719a1d2017-11-06 11:52:51 -08004842 final int numStreamTypes = AudioSystem.getNumStreamTypes();
4843 for (int streamType = numStreamTypes - 1; streamType >= 0; streamType--) {
4844 final VolumeStreamState aliasStreamState = mStreamStates[streamType];
4845 if (streamType != mStreamType &&
4846 mStreamVolumeAlias[streamType] == mStreamType &&
4847 (changed || !aliasStreamState.hasIndexForDevice(device))) {
4848 final int scaledIndex = rescaleIndex(index, mStreamType, streamType);
4849 aliasStreamState.setIndex(scaledIndex, device, caller);
Jack He6dd78c12018-02-12 21:00:24 -08004850 if (isCurrentDevice) {
Jean-Michel Trivi8719a1d2017-11-06 11:52:51 -08004851 aliasStreamState.setIndex(scaledIndex,
4852 getDeviceForStream(streamType), caller);
4853 }
Eric Laurentfdbee862014-05-12 15:26:12 -07004854 }
4855 }
Jack He6dd78c12018-02-12 21:00:24 -08004856 // Mirror changes in SPEAKER ringtone volume on SCO when
4857 if (changed && mStreamType == AudioSystem.STREAM_RING
4858 && device == AudioSystem.DEVICE_OUT_SPEAKER) {
4859 for (int i = 0; i < mIndexMap.size(); i++) {
4860 int otherDevice = mIndexMap.keyAt(i);
4861 if ((otherDevice & AudioSystem.DEVICE_OUT_ALL_SCO) != 0) {
4862 mIndexMap.put(otherDevice, index);
4863 }
4864 }
4865 }
Eric Laurentfdbee862014-05-12 15:26:12 -07004866 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004867 }
John Spurlockf63860c2015-02-19 09:46:27 -05004868 if (changed) {
4869 oldIndex = (oldIndex + 5) / 10;
4870 index = (index + 5) / 10;
John Spurlock90874332015-03-10 16:00:54 -04004871 // log base stream changes to the event log
4872 if (mStreamVolumeAlias[mStreamType] == mStreamType) {
4873 if (caller == null) {
4874 Log.w(TAG, "No caller for volume_changed event", new Throwable());
4875 }
4876 EventLogTags.writeVolumeChanged(mStreamType, oldIndex, index, mIndexMax / 10,
4877 caller);
4878 }
4879 // fire changed intents for all streams
John Spurlockf63860c2015-02-19 09:46:27 -05004880 mVolumeChanged.putExtra(AudioManager.EXTRA_VOLUME_STREAM_VALUE, index);
4881 mVolumeChanged.putExtra(AudioManager.EXTRA_PREV_VOLUME_STREAM_VALUE, oldIndex);
Jean-Michel Trivi560877d2015-06-25 17:38:35 -07004882 mVolumeChanged.putExtra(AudioManager.EXTRA_VOLUME_STREAM_TYPE_ALIAS,
4883 mStreamVolumeAlias[mStreamType]);
John Spurlockf63860c2015-02-19 09:46:27 -05004884 sendBroadcastToAll(mVolumeChanged);
4885 }
4886 return changed;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004887 }
4888
Eric Laurentfdbee862014-05-12 15:26:12 -07004889 public int getIndex(int device) {
4890 synchronized (VolumeStreamState.class) {
John Spurlock2bb02ec2015-03-02 13:13:06 -05004891 int index = mIndexMap.get(device, -1);
4892 if (index == -1) {
Eric Laurentfdbee862014-05-12 15:26:12 -07004893 // there is always an entry for AudioSystem.DEVICE_OUT_DEFAULT
John Spurlock2bb02ec2015-03-02 13:13:06 -05004894 index = mIndexMap.get(AudioSystem.DEVICE_OUT_DEFAULT);
Eric Laurentfdbee862014-05-12 15:26:12 -07004895 }
John Spurlock2bb02ec2015-03-02 13:13:06 -05004896 return index;
Eric Laurent9bc8358d2011-11-18 16:43:31 -08004897 }
Eric Laurent5b4e6542010-03-19 20:02:21 -07004898 }
4899
Eric Laurent3fb608e2016-11-03 16:27:40 -07004900 public boolean hasIndexForDevice(int device) {
4901 synchronized (VolumeStreamState.class) {
4902 return (mIndexMap.get(device, -1) != -1);
4903 }
4904 }
4905
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004906 public int getMaxIndex() {
Eric Laurenta553c252009-07-17 12:17:14 -07004907 return mIndexMax;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004908 }
4909
John Spurlockb6e19e32015-03-10 21:33:44 -04004910 public int getMinIndex() {
4911 return mIndexMin;
4912 }
4913
Jean-Michel Trivi170a0ee2017-04-14 18:13:26 -07004914 /**
Jean-Michel Trivie05eef82018-03-08 18:56:34 -08004915 * Updates the min/max index values from another stream. Use this when changing the alias
4916 * for the current stream type.
4917 * @param sourceStreamType
4918 */
4919 // must be sync'd on mSettingsLock before VolumeStreamState.class
4920 @GuardedBy("VolumeStreamState.class")
4921 public void refreshRange(int sourceStreamType) {
4922 mIndexMin = MIN_STREAM_VOLUME[sourceStreamType] * 10;
4923 mIndexMax = MAX_STREAM_VOLUME[sourceStreamType] * 10;
4924 // verify all current volumes are within bounds
4925 for (int i = 0 ; i < mIndexMap.size(); i++) {
4926 final int device = mIndexMap.keyAt(i);
4927 final int index = mIndexMap.valueAt(i);
4928 mIndexMap.put(device, getValidIndex(index));
4929 }
4930 }
4931
4932 /**
Jean-Michel Trivi170a0ee2017-04-14 18:13:26 -07004933 * Copies all device/index pairs from the given VolumeStreamState after initializing
4934 * them with the volume for DEVICE_OUT_DEFAULT. No-op if the source VolumeStreamState
4935 * has the same stream type as this instance.
4936 * @param srcStream
4937 * @param caller
4938 */
Jean-Michel Trivi085346a2018-02-14 10:48:51 -08004939 // must be sync'd on mSettingsLock before VolumeStreamState.class
4940 @GuardedBy("VolumeStreamState.class")
John Spurlock90874332015-03-10 16:00:54 -04004941 public void setAllIndexes(VolumeStreamState srcStream, String caller) {
Jean-Michel Trivi170a0ee2017-04-14 18:13:26 -07004942 if (mStreamType == srcStream.mStreamType) {
4943 return;
4944 }
Jean-Michel Trivi085346a2018-02-14 10:48:51 -08004945 int srcStreamType = srcStream.getStreamType();
4946 // apply default device volume from source stream to all devices first in case
4947 // some devices are present in this stream state but not in source stream state
4948 int index = srcStream.getIndex(AudioSystem.DEVICE_OUT_DEFAULT);
4949 index = rescaleIndex(index, srcStreamType, mStreamType);
4950 for (int i = 0; i < mIndexMap.size(); i++) {
4951 mIndexMap.put(mIndexMap.keyAt(i), index);
4952 }
4953 // Now apply actual volume for devices in source stream state
4954 SparseIntArray srcMap = srcStream.mIndexMap;
4955 for (int i = 0; i < srcMap.size(); i++) {
4956 int device = srcMap.keyAt(i);
4957 index = srcMap.valueAt(i);
4958 index = rescaleIndex(index, srcStreamType, mStreamType);
Eric Laurent33902db2012-10-07 16:15:07 -07004959
Jean-Michel Trivi085346a2018-02-14 10:48:51 -08004960 setIndex(index, device, caller);
Eric Laurent6d517662012-04-23 18:42:39 -07004961 }
4962 }
4963
Jean-Michel Trivi085346a2018-02-14 10:48:51 -08004964 // must be sync'd on mSettingsLock before VolumeStreamState.class
4965 @GuardedBy("VolumeStreamState.class")
Eric Laurentfdbee862014-05-12 15:26:12 -07004966 public void setAllIndexesToMax() {
Jean-Michel Trivi085346a2018-02-14 10:48:51 -08004967 for (int i = 0; i < mIndexMap.size(); i++) {
4968 mIndexMap.put(mIndexMap.keyAt(i), mIndexMax);
Eric Laurentdd45d012012-10-08 09:04:34 -07004969 }
Eric Laurentdd45d012012-10-08 09:04:34 -07004970 }
4971
RoboErik4197cb62015-01-21 15:45:32 -08004972 public void mute(boolean state) {
John Spurlock22b9ee12015-02-18 22:51:44 -05004973 boolean changed = false;
Eric Laurentfdbee862014-05-12 15:26:12 -07004974 synchronized (VolumeStreamState.class) {
RoboErik4197cb62015-01-21 15:45:32 -08004975 if (state != mIsMuted) {
John Spurlock22b9ee12015-02-18 22:51:44 -05004976 changed = true;
RoboErik4197cb62015-01-21 15:45:32 -08004977 mIsMuted = state;
John Spurlock22b9ee12015-02-18 22:51:44 -05004978
RoboErik4197cb62015-01-21 15:45:32 -08004979 // Set the new mute volume. This propagates the values to
4980 // the audio system, otherwise the volume won't be changed
4981 // at the lower level.
4982 sendMsg(mAudioHandler,
4983 MSG_SET_ALL_VOLUMES,
4984 SENDMSG_QUEUE,
4985 0,
4986 0,
4987 this, 0);
Eric Laurentfdbee862014-05-12 15:26:12 -07004988 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004989 }
John Spurlock22b9ee12015-02-18 22:51:44 -05004990 if (changed) {
4991 // Stream mute changed, fire the intent.
4992 Intent intent = new Intent(AudioManager.STREAM_MUTE_CHANGED_ACTION);
4993 intent.putExtra(AudioManager.EXTRA_VOLUME_STREAM_TYPE, mStreamType);
4994 intent.putExtra(AudioManager.EXTRA_STREAM_VOLUME_MUTED, state);
4995 sendBroadcastToAll(intent);
4996 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004997 }
4998
Eric Laurent6d517662012-04-23 18:42:39 -07004999 public int getStreamType() {
5000 return mStreamType;
5001 }
5002
Eric Laurent212532b2014-07-21 15:43:18 -07005003 public void checkFixedVolumeDevices() {
5004 synchronized (VolumeStreamState.class) {
5005 // ignore settings for fixed volume devices: volume should always be at max or 0
5006 if (mStreamVolumeAlias[mStreamType] == AudioSystem.STREAM_MUSIC) {
John Spurlock2bb02ec2015-03-02 13:13:06 -05005007 for (int i = 0; i < mIndexMap.size(); i++) {
5008 int device = mIndexMap.keyAt(i);
5009 int index = mIndexMap.valueAt(i);
Jean-Michel Triviba5270b2014-10-01 17:49:29 -07005010 if (((device & mFullVolumeDevices) != 0)
5011 || (((device & mFixedVolumeDevices) != 0) && index != 0)) {
John Spurlock2bb02ec2015-03-02 13:13:06 -05005012 mIndexMap.put(device, mIndexMax);
Eric Laurent212532b2014-07-21 15:43:18 -07005013 }
Eric Laurent8fa4d6f2014-10-30 14:13:03 -07005014 applyDeviceVolume_syncVSS(device);
Eric Laurent212532b2014-07-21 15:43:18 -07005015 }
5016 }
5017 }
5018 }
5019
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005020 private int getValidIndex(int index) {
John Spurlockb6e19e32015-03-10 21:33:44 -04005021 if (index < mIndexMin) {
5022 return mIndexMin;
John Spurlockee5ad722015-03-03 16:17:21 -05005023 } else if (mUseFixedVolume || index > mIndexMax) {
Eric Laurenta553c252009-07-17 12:17:14 -07005024 return mIndexMax;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005025 }
5026
5027 return index;
5028 }
5029
Eric Laurentbffc3d12012-05-07 17:43:49 -07005030 private void dump(PrintWriter pw) {
RoboErik4197cb62015-01-21 15:45:32 -08005031 pw.print(" Muted: ");
5032 pw.println(mIsMuted);
John Spurlockb6e19e32015-03-10 21:33:44 -04005033 pw.print(" Min: ");
5034 pw.println((mIndexMin + 5) / 10);
John Spurlock2b29bc42014-08-26 16:40:35 -04005035 pw.print(" Max: ");
5036 pw.println((mIndexMax + 5) / 10);
Eric Laurentbffc3d12012-05-07 17:43:49 -07005037 pw.print(" Current: ");
John Spurlock2bb02ec2015-03-02 13:13:06 -05005038 for (int i = 0; i < mIndexMap.size(); i++) {
5039 if (i > 0) {
5040 pw.print(", ");
5041 }
5042 final int device = mIndexMap.keyAt(i);
John Spurlock2b29bc42014-08-26 16:40:35 -04005043 pw.print(Integer.toHexString(device));
5044 final String deviceName = device == AudioSystem.DEVICE_OUT_DEFAULT ? "default"
5045 : AudioSystem.getOutputDeviceName(device);
5046 if (!deviceName.isEmpty()) {
5047 pw.print(" (");
5048 pw.print(deviceName);
5049 pw.print(")");
5050 }
5051 pw.print(": ");
John Spurlock2bb02ec2015-03-02 13:13:06 -05005052 final int index = (mIndexMap.valueAt(i) + 5) / 10;
John Spurlock2b29bc42014-08-26 16:40:35 -04005053 pw.print(index);
Eric Laurentbffc3d12012-05-07 17:43:49 -07005054 }
John Spurlockb32fc972015-03-05 13:58:00 -05005055 pw.println();
5056 pw.print(" Devices: ");
John Spurlock8a52c442015-03-26 14:23:58 -04005057 final int devices = getDevicesForStream(mStreamType);
John Spurlockb32fc972015-03-05 13:58:00 -05005058 int device, i = 0, n = 0;
John Spurlock1ff1e6e2015-03-09 14:21:20 -04005059 // iterate all devices from 1 to DEVICE_OUT_DEFAULT exclusive
5060 // (the default device is not returned by getDevicesForStream)
5061 while ((device = 1 << i) != AudioSystem.DEVICE_OUT_DEFAULT) {
John Spurlockb32fc972015-03-05 13:58:00 -05005062 if ((devices & device) != 0) {
5063 if (n++ > 0) {
5064 pw.print(", ");
5065 }
5066 pw.print(AudioSystem.getOutputDeviceName(device));
5067 }
5068 i++;
5069 }
Eric Laurentbffc3d12012-05-07 17:43:49 -07005070 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005071 }
5072
5073 /** Thread that handles native AudioSystem control. */
5074 private class AudioSystemThread extends Thread {
5075 AudioSystemThread() {
5076 super("AudioService");
5077 }
5078
5079 @Override
5080 public void run() {
5081 // Set this thread up so the handler will work on it
5082 Looper.prepare();
5083
5084 synchronized(AudioService.this) {
5085 mAudioHandler = new AudioHandler();
5086
5087 // Notify that the handler has been created
5088 AudioService.this.notify();
5089 }
5090
5091 // Listen for volume change requests that are set by VolumePanel
5092 Looper.loop();
5093 }
5094 }
5095
5096 /** Handles internal volume messages in separate volume thread. */
5097 private class AudioHandler extends Handler {
5098
Eric Laurent9bc8358d2011-11-18 16:43:31 -08005099 private void setDeviceVolume(VolumeStreamState streamState, int device) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005100
Eric Laurent8fa4d6f2014-10-30 14:13:03 -07005101 synchronized (VolumeStreamState.class) {
5102 // Apply volume
5103 streamState.applyDeviceVolume_syncVSS(device);
Eric Laurenta553c252009-07-17 12:17:14 -07005104
Eric Laurent8fa4d6f2014-10-30 14:13:03 -07005105 // Apply change to all streams using this one as alias
5106 int numStreamTypes = AudioSystem.getNumStreamTypes();
5107 for (int streamType = numStreamTypes - 1; streamType >= 0; streamType--) {
5108 if (streamType != streamState.mStreamType &&
5109 mStreamVolumeAlias[streamType] == streamState.mStreamType) {
5110 // Make sure volume is also maxed out on A2DP device for aliased stream
5111 // that may have a different device selected
5112 int streamDevice = getDeviceForStream(streamType);
5113 if ((device != streamDevice) && mAvrcpAbsVolSupported &&
5114 ((device & AudioSystem.DEVICE_OUT_ALL_A2DP) != 0)) {
5115 mStreamStates[streamType].applyDeviceVolume_syncVSS(device);
5116 }
5117 mStreamStates[streamType].applyDeviceVolume_syncVSS(streamDevice);
Eric Laurentcd772d02013-10-30 18:31:07 -07005118 }
Eric Laurenta553c252009-07-17 12:17:14 -07005119 }
5120 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005121 // Post a persist volume msg
Eric Laurentafbb0472011-12-15 09:04:23 -08005122 sendMsg(mAudioHandler,
5123 MSG_PERSIST_VOLUME,
Eric Laurent98ad9b92012-02-15 17:21:37 -08005124 SENDMSG_QUEUE,
Eric Laurent9bc8358d2011-11-18 16:43:31 -08005125 device,
Eric Laurent42b041e2013-03-29 11:36:03 -07005126 0,
Eric Laurentafbb0472011-12-15 09:04:23 -08005127 streamState,
5128 PERSIST_DELAY);
5129
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005130 }
5131
Eric Laurent9bc8358d2011-11-18 16:43:31 -08005132 private void setAllVolumes(VolumeStreamState streamState) {
5133
5134 // Apply volume
5135 streamState.applyAllVolumes();
5136
5137 // Apply change to all streams using this one as alias
5138 int numStreamTypes = AudioSystem.getNumStreamTypes();
5139 for (int streamType = numStreamTypes - 1; streamType >= 0; streamType--) {
5140 if (streamType != streamState.mStreamType &&
Eric Laurent6d517662012-04-23 18:42:39 -07005141 mStreamVolumeAlias[streamType] == streamState.mStreamType) {
Eric Laurent9bc8358d2011-11-18 16:43:31 -08005142 mStreamStates[streamType].applyAllVolumes();
5143 }
5144 }
5145 }
5146
Eric Laurent42b041e2013-03-29 11:36:03 -07005147 private void persistVolume(VolumeStreamState streamState, int device) {
Eric Laurent83a017b2013-03-19 18:15:31 -07005148 if (mUseFixedVolume) {
5149 return;
5150 }
Muyuan Li1ed6df62016-06-18 11:16:52 -07005151 if (mIsSingleVolume && (streamState.mStreamType != AudioSystem.STREAM_MUSIC)) {
Eric Laurent212532b2014-07-21 15:43:18 -07005152 return;
5153 }
Jean-Michel Trivia53b7052017-04-12 18:27:01 -07005154 if (streamState.hasValidSettingsName()) {
5155 System.putIntForUser(mContentResolver,
5156 streamState.getSettingNameForDevice(device),
5157 (streamState.getIndex(device) + 5)/ 10,
5158 UserHandle.USER_CURRENT);
5159 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005160 }
5161
Glenn Kastenba195eb2011-12-13 09:30:40 -08005162 private void persistRingerMode(int ringerMode) {
Eric Laurent83a017b2013-03-19 18:15:31 -07005163 if (mUseFixedVolume) {
5164 return;
5165 }
Jeff Sharkey8d9a1f62012-10-18 15:38:14 -07005166 Settings.Global.putInt(mContentResolver, Settings.Global.MODE_RINGER, ringerMode);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005167 }
5168
Jaekyun Seokc31033f2018-01-15 14:53:17 +09005169 private String getSoundEffectFilePath(int effectType) {
5170 String filePath = Environment.getProductDirectory() + SOUND_EFFECTS_PATH
5171 + SOUND_EFFECT_FILES.get(SOUND_EFFECT_FILES_MAP[effectType][0]);
5172 if (!new File(filePath).isFile()) {
5173 filePath = Environment.getRootDirectory() + SOUND_EFFECTS_PATH
5174 + SOUND_EFFECT_FILES.get(SOUND_EFFECT_FILES_MAP[effectType][0]);
5175 }
5176 return filePath;
5177 }
5178
Eric Laurent5d3eb44a2013-03-21 15:35:10 -07005179 private boolean onLoadSoundEffects() {
5180 int status;
5181
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005182 synchronized (mSoundEffectsLock) {
Eric Laurent4a5eeb92014-05-06 10:49:04 -07005183 if (!mSystemReady) {
Eric Laurent5d3eb44a2013-03-21 15:35:10 -07005184 Log.w(TAG, "onLoadSoundEffects() called before boot complete");
5185 return false;
5186 }
5187
5188 if (mSoundPool != null) {
5189 return true;
5190 }
5191
5192 loadTouchSoundAssets();
5193
Jean-Michel Trivi55a30c42014-07-20 17:56:11 -07005194 mSoundPool = new SoundPool.Builder()
5195 .setMaxStreams(NUM_SOUNDPOOL_CHANNELS)
5196 .setAudioAttributes(new AudioAttributes.Builder()
5197 .setUsage(AudioAttributes.USAGE_ASSISTANCE_SONIFICATION)
5198 .setContentType(AudioAttributes.CONTENT_TYPE_SONIFICATION)
5199 .build())
5200 .build();
Eric Laurent5d3eb44a2013-03-21 15:35:10 -07005201 mSoundPoolCallBack = null;
5202 mSoundPoolListenerThread = new SoundPoolListenerThread();
5203 mSoundPoolListenerThread.start();
5204 int attempts = 3;
5205 while ((mSoundPoolCallBack == null) && (attempts-- > 0)) {
5206 try {
5207 // Wait for mSoundPoolCallBack to be set by the other thread
Glenn Kasten167d1a22013-07-23 16:24:41 -07005208 mSoundEffectsLock.wait(SOUND_EFFECTS_LOAD_TIMEOUT_MS);
Eric Laurent5d3eb44a2013-03-21 15:35:10 -07005209 } catch (InterruptedException e) {
5210 Log.w(TAG, "Interrupted while waiting sound pool listener thread.");
5211 }
5212 }
5213
5214 if (mSoundPoolCallBack == null) {
5215 Log.w(TAG, "onLoadSoundEffects() SoundPool listener or thread creation error");
5216 if (mSoundPoolLooper != null) {
5217 mSoundPoolLooper.quit();
5218 mSoundPoolLooper = null;
5219 }
5220 mSoundPoolListenerThread = null;
5221 mSoundPool.release();
5222 mSoundPool = null;
5223 return false;
5224 }
5225 /*
5226 * poolId table: The value -1 in this table indicates that corresponding
5227 * file (same index in SOUND_EFFECT_FILES[] has not been loaded.
5228 * Once loaded, the value in poolId is the sample ID and the same
5229 * sample can be reused for another effect using the same file.
5230 */
5231 int[] poolId = new int[SOUND_EFFECT_FILES.size()];
5232 for (int fileIdx = 0; fileIdx < SOUND_EFFECT_FILES.size(); fileIdx++) {
5233 poolId[fileIdx] = -1;
5234 }
5235 /*
5236 * Effects whose value in SOUND_EFFECT_FILES_MAP[effect][1] is -1 must be loaded.
5237 * If load succeeds, value in SOUND_EFFECT_FILES_MAP[effect][1] is > 0:
5238 * this indicates we have a valid sample loaded for this effect.
5239 */
5240
5241 int numSamples = 0;
5242 for (int effect = 0; effect < AudioManager.NUM_SOUND_EFFECTS; effect++) {
5243 // Do not load sample if this effect uses the MediaPlayer
5244 if (SOUND_EFFECT_FILES_MAP[effect][1] == 0) {
5245 continue;
5246 }
5247 if (poolId[SOUND_EFFECT_FILES_MAP[effect][0]] == -1) {
Jaekyun Seokc31033f2018-01-15 14:53:17 +09005248 String filePath = getSoundEffectFilePath(effect);
Eric Laurent5d3eb44a2013-03-21 15:35:10 -07005249 int sampleId = mSoundPool.load(filePath, 0);
5250 if (sampleId <= 0) {
5251 Log.w(TAG, "Soundpool could not load file: "+filePath);
5252 } else {
5253 SOUND_EFFECT_FILES_MAP[effect][1] = sampleId;
5254 poolId[SOUND_EFFECT_FILES_MAP[effect][0]] = sampleId;
5255 numSamples++;
5256 }
5257 } else {
5258 SOUND_EFFECT_FILES_MAP[effect][1] =
5259 poolId[SOUND_EFFECT_FILES_MAP[effect][0]];
5260 }
5261 }
5262 // wait for all samples to be loaded
5263 if (numSamples > 0) {
5264 mSoundPoolCallBack.setSamples(poolId);
5265
5266 attempts = 3;
5267 status = 1;
5268 while ((status == 1) && (attempts-- > 0)) {
5269 try {
Glenn Kasten167d1a22013-07-23 16:24:41 -07005270 mSoundEffectsLock.wait(SOUND_EFFECTS_LOAD_TIMEOUT_MS);
Eric Laurent5d3eb44a2013-03-21 15:35:10 -07005271 status = mSoundPoolCallBack.status();
5272 } catch (InterruptedException e) {
5273 Log.w(TAG, "Interrupted while waiting sound pool callback.");
5274 }
5275 }
5276 } else {
5277 status = -1;
5278 }
5279
5280 if (mSoundPoolLooper != null) {
5281 mSoundPoolLooper.quit();
5282 mSoundPoolLooper = null;
5283 }
5284 mSoundPoolListenerThread = null;
5285 if (status != 0) {
5286 Log.w(TAG,
5287 "onLoadSoundEffects(), Error "+status+ " while loading samples");
5288 for (int effect = 0; effect < AudioManager.NUM_SOUND_EFFECTS; effect++) {
5289 if (SOUND_EFFECT_FILES_MAP[effect][1] > 0) {
5290 SOUND_EFFECT_FILES_MAP[effect][1] = -1;
5291 }
5292 }
5293
5294 mSoundPool.release();
5295 mSoundPool = null;
5296 }
5297 }
5298 return (status == 0);
5299 }
5300
5301 /**
5302 * Unloads samples from the sound pool.
5303 * This method can be called to free some memory when
5304 * sound effects are disabled.
5305 */
5306 private void onUnloadSoundEffects() {
5307 synchronized (mSoundEffectsLock) {
5308 if (mSoundPool == null) {
5309 return;
5310 }
5311
5312 int[] poolId = new int[SOUND_EFFECT_FILES.size()];
5313 for (int fileIdx = 0; fileIdx < SOUND_EFFECT_FILES.size(); fileIdx++) {
5314 poolId[fileIdx] = 0;
5315 }
5316
5317 for (int effect = 0; effect < AudioManager.NUM_SOUND_EFFECTS; effect++) {
5318 if (SOUND_EFFECT_FILES_MAP[effect][1] <= 0) {
5319 continue;
5320 }
5321 if (poolId[SOUND_EFFECT_FILES_MAP[effect][0]] == 0) {
5322 mSoundPool.unload(SOUND_EFFECT_FILES_MAP[effect][1]);
5323 SOUND_EFFECT_FILES_MAP[effect][1] = -1;
5324 poolId[SOUND_EFFECT_FILES_MAP[effect][0]] = -1;
5325 }
5326 }
5327 mSoundPool.release();
5328 mSoundPool = null;
5329 }
5330 }
5331
5332 private void onPlaySoundEffect(int effectType, int volume) {
5333 synchronized (mSoundEffectsLock) {
5334
5335 onLoadSoundEffects();
5336
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005337 if (mSoundPool == null) {
5338 return;
5339 }
Eric Laurenta2ef57d2009-09-28 04:46:10 -07005340 float volFloat;
Eric Laurent25101b02011-02-02 09:33:30 -08005341 // use default if volume is not specified by caller
Eric Laurenta2ef57d2009-09-28 04:46:10 -07005342 if (volume < 0) {
Jean-Michel Trivif2b0c112012-07-09 11:59:11 -07005343 volFloat = (float)Math.pow(10, (float)sSoundEffectVolumeDb/20);
Eric Laurenta2ef57d2009-09-28 04:46:10 -07005344 } else {
RoboErik8a2cfc32014-05-16 11:19:38 -07005345 volFloat = volume / 1000.0f;
Eric Laurenta2ef57d2009-09-28 04:46:10 -07005346 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005347
5348 if (SOUND_EFFECT_FILES_MAP[effectType][1] > 0) {
Eric Laurent5d3eb44a2013-03-21 15:35:10 -07005349 mSoundPool.play(SOUND_EFFECT_FILES_MAP[effectType][1],
5350 volFloat, volFloat, 0, 0, 1.0f);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005351 } else {
5352 MediaPlayer mediaPlayer = new MediaPlayer();
Glenn Kasten62b9aec2011-11-07 11:10:16 -08005353 try {
Jaekyun Seokc31033f2018-01-15 14:53:17 +09005354 String filePath = getSoundEffectFilePath(effectType);
Glenn Kasten62b9aec2011-11-07 11:10:16 -08005355 mediaPlayer.setDataSource(filePath);
5356 mediaPlayer.setAudioStreamType(AudioSystem.STREAM_SYSTEM);
5357 mediaPlayer.prepare();
Glenn Kasten068225d2012-02-27 16:21:04 -08005358 mediaPlayer.setVolume(volFloat);
Glenn Kasten62b9aec2011-11-07 11:10:16 -08005359 mediaPlayer.setOnCompletionListener(new OnCompletionListener() {
5360 public void onCompletion(MediaPlayer mp) {
5361 cleanupPlayer(mp);
5362 }
5363 });
5364 mediaPlayer.setOnErrorListener(new OnErrorListener() {
5365 public boolean onError(MediaPlayer mp, int what, int extra) {
5366 cleanupPlayer(mp);
5367 return true;
5368 }
5369 });
5370 mediaPlayer.start();
5371 } catch (IOException ex) {
5372 Log.w(TAG, "MediaPlayer IOException: "+ex);
5373 } catch (IllegalArgumentException ex) {
5374 Log.w(TAG, "MediaPlayer IllegalArgumentException: "+ex);
5375 } catch (IllegalStateException ex) {
5376 Log.w(TAG, "MediaPlayer IllegalStateException: "+ex);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005377 }
5378 }
5379 }
5380 }
5381
5382 private void cleanupPlayer(MediaPlayer mp) {
5383 if (mp != null) {
5384 try {
5385 mp.stop();
5386 mp.release();
5387 } catch (IllegalStateException ex) {
5388 Log.w(TAG, "MediaPlayer IllegalStateException: "+ex);
5389 }
5390 }
5391 }
5392
Jean-Michel Trivi011f39e2017-08-19 18:08:06 -07005393 private void setForceUse(int usage, int config, String eventSource) {
Jean-Michel Trivi7e2f3712015-01-12 11:01:55 -08005394 synchronized (mConnectedDevices) {
Jean-Michel Trivi011f39e2017-08-19 18:08:06 -07005395 setForceUseInt_SyncDevices(usage, config, eventSource);
Jean-Michel Trivi7e2f3712015-01-12 11:01:55 -08005396 }
Eric Laurentfa640152011-03-12 15:59:51 -08005397 }
5398
Eric Laurent05274f32012-11-29 12:48:18 -08005399 private void onPersistSafeVolumeState(int state) {
5400 Settings.Global.putInt(mContentResolver,
5401 Settings.Global.AUDIO_SAFE_VOLUME_STATE,
5402 state);
5403 }
5404
Jean-Michel Trivi7ed71472018-02-02 16:52:09 -08005405 private void onNotifyVolumeEvent(@NonNull IAudioPolicyCallback apc,
5406 @AudioManager.VolumeAdjustment int direction) {
5407 try {
5408 apc.notifyVolumeAdjust(direction);
5409 } catch(Exception e) {
5410 // nothing we can do about this. Do not log error, too much potential for spam
5411 }
5412 }
5413
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005414 @Override
5415 public void handleMessage(Message msg) {
Eric Laurentafbb0472011-12-15 09:04:23 -08005416 switch (msg.what) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005417
Eric Laurent9bc8358d2011-11-18 16:43:31 -08005418 case MSG_SET_DEVICE_VOLUME:
5419 setDeviceVolume((VolumeStreamState) msg.obj, msg.arg1);
5420 break;
5421
5422 case MSG_SET_ALL_VOLUMES:
5423 setAllVolumes((VolumeStreamState) msg.obj);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005424 break;
5425
5426 case MSG_PERSIST_VOLUME:
Eric Laurent42b041e2013-03-29 11:36:03 -07005427 persistVolume((VolumeStreamState) msg.obj, msg.arg1);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005428 break;
5429
5430 case MSG_PERSIST_RINGER_MODE:
Glenn Kastenba195eb2011-12-13 09:30:40 -08005431 // note that the value persisted is the current ringer mode, not the
5432 // value of ringer mode as of the time the request was made to persist
John Spurlock661f2cf2014-11-17 10:29:10 -05005433 persistRingerMode(getRingerModeInternal());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005434 break;
5435
Andy Hunged0ea402015-10-30 14:11:46 -07005436 case MSG_AUDIO_SERVER_DIED:
5437 onAudioServerDied();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005438 break;
5439
Eric Laurent1d3cdce2018-01-20 10:31:21 -08005440 case MSG_DISPATCH_AUDIO_SERVER_STATE:
5441 onDispatchAudioServerStateChange(msg.arg1 == 1);
5442 break;
5443
Eric Laurent5d3eb44a2013-03-21 15:35:10 -07005444 case MSG_UNLOAD_SOUND_EFFECTS:
5445 onUnloadSoundEffects();
5446 break;
5447
Eric Laurent117b7bb2011-01-16 17:07:27 -08005448 case MSG_LOAD_SOUND_EFFECTS:
Eric Laurent5d3eb44a2013-03-21 15:35:10 -07005449 //FIXME: onLoadSoundEffects() should be executed in a separate thread as it
5450 // can take several dozens of milliseconds to complete
5451 boolean loaded = onLoadSoundEffects();
5452 if (msg.obj != null) {
5453 LoadSoundEffectReply reply = (LoadSoundEffectReply)msg.obj;
5454 synchronized (reply) {
5455 reply.mStatus = loaded ? 0 : -1;
5456 reply.notify();
5457 }
5458 }
Eric Laurent117b7bb2011-01-16 17:07:27 -08005459 break;
5460
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005461 case MSG_PLAY_SOUND_EFFECT:
Eric Laurent5d3eb44a2013-03-21 15:35:10 -07005462 onPlaySoundEffect(msg.arg1, msg.arg2);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005463 break;
Jean-Michel Trivi4c637b92010-04-12 18:44:10 -07005464
5465 case MSG_BTA2DP_DOCK_TIMEOUT:
5466 // msg.obj == address of BTA2DP device
Eric Laurent6bc7f2c2011-11-29 18:49:40 -08005467 synchronized (mConnectedDevices) {
5468 makeA2dpDeviceUnavailableNow( (String) msg.obj );
5469 }
Jean-Michel Trivi4c637b92010-04-12 18:44:10 -07005470 break;
Eric Laurentfa640152011-03-12 15:59:51 -08005471
5472 case MSG_SET_FORCE_USE:
Sungsoocf09fe62016-09-28 16:21:48 +09005473 case MSG_SET_FORCE_BT_A2DP_USE:
Jean-Michel Trivi011f39e2017-08-19 18:08:06 -07005474 setForceUse(msg.arg1, msg.arg2, (String) msg.obj);
Eric Laurentfa640152011-03-12 15:59:51 -08005475 break;
Jean-Michel Trivid589fea2011-04-15 11:28:10 -07005476
Eric Laurentdc03c612011-04-01 10:59:41 -07005477 case MSG_BT_HEADSET_CNCT_FAILED:
5478 resetBluetoothSco();
5479 break;
Eric Laurentb1fbaac2012-05-29 09:24:28 -07005480
5481 case MSG_SET_WIRED_DEVICE_CONNECTION_STATE:
Paul McLean10804eb2015-01-28 11:16:35 -08005482 { WiredDeviceConnectionState connectState =
5483 (WiredDeviceConnectionState)msg.obj;
Jean-Michel Trivi011f39e2017-08-19 18:08:06 -07005484 mWiredDevLogger.log(new WiredDevConnectEvent(connectState));
Paul McLean10804eb2015-01-28 11:16:35 -08005485 onSetWiredDeviceConnectionState(connectState.mType, connectState.mState,
John Spurlock90874332015-03-10 16:00:54 -04005486 connectState.mAddress, connectState.mName, connectState.mCaller);
Paul McLean10804eb2015-01-28 11:16:35 -08005487 mAudioEventWakeLock.release();
5488 }
Eric Laurentb1fbaac2012-05-29 09:24:28 -07005489 break;
5490
Mike Lockwood0a40ec22014-05-21 10:08:50 -07005491 case MSG_SET_A2DP_SRC_CONNECTION_STATE:
5492 onSetA2dpSourceConnectionState((BluetoothDevice)msg.obj, msg.arg1);
5493 mAudioEventWakeLock.release();
5494 break;
5495
5496 case MSG_SET_A2DP_SINK_CONNECTION_STATE:
5497 onSetA2dpSinkConnectionState((BluetoothDevice)msg.obj, msg.arg1);
Jean-Michel Trivifa9a6982013-06-27 16:22:58 -07005498 mAudioEventWakeLock.release();
Eric Laurentb1fbaac2012-05-29 09:24:28 -07005499 break;
Dianne Hackborn632ca412012-06-14 19:34:10 -07005500
Jakub Pawlowskif9570f32018-02-21 17:15:12 -08005501 case MSG_SET_HEARING_AID_CONNECTION_STATE:
5502 onSetHearingAidConnectionState((BluetoothDevice)msg.obj, msg.arg1);
5503 mAudioEventWakeLock.release();
5504 break;
5505
Pavlin Radoslavov44a4ef02016-12-21 12:05:51 -08005506 case MSG_A2DP_DEVICE_CONFIG_CHANGE:
5507 onBluetoothA2dpDeviceConfigChange((BluetoothDevice)msg.obj);
5508 mAudioEventWakeLock.release();
5509 break;
5510
Jean-Michel Trivi92ed7bf2017-06-26 19:32:38 -07005511 case MSG_DISABLE_AUDIO_FOR_UID:
5512 mPlaybackMonitor.disableAudioForUid( msg.arg1 == 1 /* disable */,
5513 msg.arg2 /* uid */);
5514 mAudioEventWakeLock.release();
5515 break;
5516
Dianne Hackborn632ca412012-06-14 19:34:10 -07005517 case MSG_REPORT_NEW_ROUTES: {
5518 int N = mRoutesObservers.beginBroadcast();
5519 if (N > 0) {
5520 AudioRoutesInfo routes;
5521 synchronized (mCurAudioRoutes) {
5522 routes = new AudioRoutesInfo(mCurAudioRoutes);
5523 }
5524 while (N > 0) {
5525 N--;
5526 IAudioRoutesObserver obs = mRoutesObservers.getBroadcastItem(N);
5527 try {
5528 obs.dispatchAudioRoutesChanged(routes);
5529 } catch (RemoteException e) {
5530 }
5531 }
5532 }
5533 mRoutesObservers.finishBroadcast();
John Spurlock8a52c442015-03-26 14:23:58 -04005534 observeDevicesForStreams(-1);
Dianne Hackborn632ca412012-06-14 19:34:10 -07005535 break;
5536 }
Jean-Michel Trivi3114ce32012-06-11 15:03:52 -07005537
Eric Laurentc34dcc12012-09-10 13:51:52 -07005538 case MSG_CHECK_MUSIC_ACTIVE:
John Spurlock90874332015-03-10 16:00:54 -04005539 onCheckMusicActive((String) msg.obj);
Eric Laurentc34dcc12012-09-10 13:51:52 -07005540 break;
Eric Laurent5bfaeae2012-09-21 18:44:48 -07005541
5542 case MSG_BROADCAST_AUDIO_BECOMING_NOISY:
5543 onSendBecomingNoisyIntent();
5544 break;
Eric Laurentd640bd32012-09-28 18:01:48 -07005545
5546 case MSG_CONFIGURE_SAFE_MEDIA_VOLUME_FORCED:
5547 case MSG_CONFIGURE_SAFE_MEDIA_VOLUME:
John Spurlock90874332015-03-10 16:00:54 -04005548 onConfigureSafeVolume((msg.what == MSG_CONFIGURE_SAFE_MEDIA_VOLUME_FORCED),
5549 (String) msg.obj);
Eric Laurentd640bd32012-09-28 18:01:48 -07005550 break;
Eric Laurent05274f32012-11-29 12:48:18 -08005551 case MSG_PERSIST_SAFE_VOLUME_STATE:
5552 onPersistSafeVolumeState(msg.arg1);
5553 break;
Jean-Michel Trivia578c482012-12-28 11:19:49 -08005554
Eric Laurent2a57ca92013-03-07 17:29:27 -08005555 case MSG_BROADCAST_BT_CONNECTION_STATE:
5556 onBroadcastScoConnectionState(msg.arg1);
5557 break;
Eric Laurent4a5eeb92014-05-06 10:49:04 -07005558
5559 case MSG_SYSTEM_READY:
5560 onSystemReady();
5561 break;
John Spurlockaa5ee4d2014-07-25 13:05:12 -04005562
Eric Laurent0867bed2015-05-20 14:49:08 -07005563 case MSG_INDICATE_SYSTEM_READY:
5564 onIndicateSystemReady();
5565 break;
5566
Jean-Michel Trivi1ab43f62017-04-27 15:37:34 -07005567 case MSG_ACCESSORY_PLUG_MEDIA_UNMUTE:
5568 onAccessoryPlugMediaUnmute(msg.arg1);
5569 break;
5570
John Spurlockaa5ee4d2014-07-25 13:05:12 -04005571 case MSG_PERSIST_MUSIC_ACTIVE_MS:
5572 final int musicActiveMs = msg.arg1;
5573 Settings.Secure.putIntForUser(mContentResolver,
5574 Settings.Secure.UNSAFE_VOLUME_MUSIC_ACTIVE_MS, musicActiveMs,
5575 UserHandle.USER_CURRENT);
5576 break;
Eric Laurentc0232482016-03-15 18:19:23 -07005577
RoboErik5452e252015-02-06 15:33:53 -08005578 case MSG_UNMUTE_STREAM:
5579 onUnmuteStream(msg.arg1, msg.arg2);
5580 break;
Eric Laurentc0232482016-03-15 18:19:23 -07005581
Jean-Michel Trivi5a561092015-04-23 18:48:08 -07005582 case MSG_DYN_POLICY_MIX_STATE_UPDATE:
5583 onDynPolicyMixStateUpdate((String) msg.obj, msg.arg1);
5584 break;
Jean-Michel Trivi7ed71472018-02-02 16:52:09 -08005585
5586 case MSG_NOTIFY_VOL_EVENT:
5587 onNotifyVolumeEvent((IAudioPolicyCallback) msg.obj, msg.arg1);
5588 break;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005589 }
5590 }
5591 }
5592
Jason Parekhb1096152009-03-24 17:48:25 -07005593 private class SettingsObserver extends ContentObserver {
Eric Laurenta553c252009-07-17 12:17:14 -07005594
Phil Burked43bf52016-03-01 17:01:35 -08005595 private int mEncodedSurroundMode;
5596
Jason Parekhb1096152009-03-24 17:48:25 -07005597 SettingsObserver() {
5598 super(new Handler());
Beverlyd6964762018-02-16 14:07:03 -05005599 mContentResolver.registerContentObserver(Settings.Global.getUriFor(
5600 Settings.Global.ZEN_MODE), false, this);
5601 mContentResolver.registerContentObserver(Settings.Global.getUriFor(
5602 Settings.Global.ZEN_MODE_CONFIG_ETAG), false, this);
Jason Parekhb1096152009-03-24 17:48:25 -07005603 mContentResolver.registerContentObserver(Settings.System.getUriFor(
5604 Settings.System.MODE_RINGER_STREAMS_AFFECTED), false, this);
Eric Laurent7ee1e4f2012-10-26 18:11:21 -07005605 mContentResolver.registerContentObserver(Settings.Global.getUriFor(
5606 Settings.Global.DOCK_AUDIO_MEDIA_ENABLED), false, this);
Andy Hung7b98e9a2016-02-25 18:34:50 -08005607 mContentResolver.registerContentObserver(Settings.System.getUriFor(
5608 Settings.System.MASTER_MONO), false, this);
Phil Burked43bf52016-03-01 17:01:35 -08005609
5610 mEncodedSurroundMode = Settings.Global.getInt(
5611 mContentResolver, Settings.Global.ENCODED_SURROUND_OUTPUT,
5612 Settings.Global.ENCODED_SURROUND_OUTPUT_AUTO);
5613 mContentResolver.registerContentObserver(Settings.Global.getUriFor(
5614 Settings.Global.ENCODED_SURROUND_OUTPUT), false, this);
Jason Parekhb1096152009-03-24 17:48:25 -07005615 }
5616
5617 @Override
5618 public void onChange(boolean selfChange) {
5619 super.onChange(selfChange);
Glenn Kastenba195eb2011-12-13 09:30:40 -08005620 // FIXME This synchronized is not necessary if mSettingsLock only protects mRingerMode.
Beverlyd6964762018-02-16 14:07:03 -05005621 // However there appear to be some missing locks around mRingerAndZenModeMutedStreams
Glenn Kastenba195eb2011-12-13 09:30:40 -08005622 // and mRingerModeAffectedStreams, so will leave this synchronized for now.
Beverlyd6964762018-02-16 14:07:03 -05005623 // mRingerAndZenModeMutedStreams and mMuteAffectedStreams are safe (only accessed once).
Eric Laurenta553c252009-07-17 12:17:14 -07005624 synchronized (mSettingsLock) {
Beverlyd6964762018-02-16 14:07:03 -05005625 if (updateRingerAndZenModeAffectedStreams()) {
Eric Laurenta553c252009-07-17 12:17:14 -07005626 /*
5627 * Ensure all stream types that should be affected by ringer mode
5628 * are in the proper state.
5629 */
John Spurlock661f2cf2014-11-17 10:29:10 -05005630 setRingerModeInt(getRingerModeInternal(), false);
Eric Laurenta553c252009-07-17 12:17:14 -07005631 }
Eric Laurent7ee1e4f2012-10-26 18:11:21 -07005632 readDockAudioSettings(mContentResolver);
Andy Hung7b98e9a2016-02-25 18:34:50 -08005633 updateMasterMono(mContentResolver);
Phil Burked43bf52016-03-01 17:01:35 -08005634 updateEncodedSurroundOutput();
5635 }
5636 }
5637
5638 private void updateEncodedSurroundOutput() {
5639 int newSurroundMode = Settings.Global.getInt(
5640 mContentResolver, Settings.Global.ENCODED_SURROUND_OUTPUT,
5641 Settings.Global.ENCODED_SURROUND_OUTPUT_AUTO);
5642 // Did it change?
5643 if (mEncodedSurroundMode != newSurroundMode) {
5644 // Send to AudioPolicyManager
Jean-Michel Trivi011f39e2017-08-19 18:08:06 -07005645 sendEncodedSurroundMode(newSurroundMode, "SettingsObserver");
Phil Burked43bf52016-03-01 17:01:35 -08005646 synchronized(mConnectedDevices) {
5647 // Is HDMI connected?
5648 String key = makeDeviceListKey(AudioSystem.DEVICE_OUT_HDMI, "");
5649 DeviceListSpec deviceSpec = mConnectedDevices.get(key);
5650 if (deviceSpec != null) {
5651 // Toggle HDMI to retrigger broadcast with proper formats.
5652 setWiredDeviceConnectionState(AudioSystem.DEVICE_OUT_HDMI,
5653 AudioSystem.DEVICE_STATE_UNAVAILABLE, "", "",
5654 "android"); // disconnect
5655 setWiredDeviceConnectionState(AudioSystem.DEVICE_OUT_HDMI,
5656 AudioSystem.DEVICE_STATE_AVAILABLE, "", "",
5657 "android"); // reconnect
5658 }
5659 }
5660 mEncodedSurroundMode = newSurroundMode;
Eric Laurenta553c252009-07-17 12:17:14 -07005661 }
Jason Parekhb1096152009-03-24 17:48:25 -07005662 }
Jason Parekhb1096152009-03-24 17:48:25 -07005663 }
Eric Laurenta553c252009-07-17 12:17:14 -07005664
Eric Laurent6bc7f2c2011-11-29 18:49:40 -08005665 // must be called synchronized on mConnectedDevices
Jean-Michel Trivi011f39e2017-08-19 18:08:06 -07005666 private void makeA2dpDeviceAvailable(String address, String name, String eventSource) {
Jean-Michel Trivi1ab43f62017-04-27 15:37:34 -07005667 // enable A2DP before notifying A2DP connection to avoid unnecessary processing in
Eric Laurent78472112012-05-21 08:57:21 -07005668 // audio policy manager
Matthew Xiec9d1d5f2013-09-12 00:32:22 -07005669 VolumeStreamState streamState = mStreamStates[AudioSystem.STREAM_MUSIC];
5670 sendMsg(mAudioHandler, MSG_SET_DEVICE_VOLUME, SENDMSG_QUEUE,
5671 AudioSystem.DEVICE_OUT_BLUETOOTH_A2DP, 0, streamState, 0);
Jean-Michel Trivi011f39e2017-08-19 18:08:06 -07005672 setBluetoothA2dpOnInt(true, eventSource);
Jean-Michel Trivi4c637b92010-04-12 18:44:10 -07005673 AudioSystem.setDeviceConnectionState(AudioSystem.DEVICE_OUT_BLUETOOTH_A2DP,
Paul McLean20eec5b2015-05-09 13:02:18 -07005674 AudioSystem.DEVICE_STATE_AVAILABLE, address, name);
Jean-Michel Trivi4c637b92010-04-12 18:44:10 -07005675 // Reset A2DP suspend state each time a new sink is connected
5676 AudioSystem.setParameters("A2dpSuspended=false");
Paul McLean394a8e12015-03-03 10:29:19 -07005677 mConnectedDevices.put(
5678 makeDeviceListKey(AudioSystem.DEVICE_OUT_BLUETOOTH_A2DP, address),
Paul McLean20eec5b2015-05-09 13:02:18 -07005679 new DeviceListSpec(AudioSystem.DEVICE_OUT_BLUETOOTH_A2DP, name,
Paul McLean394a8e12015-03-03 10:29:19 -07005680 address));
Jean-Michel Trivi1ab43f62017-04-27 15:37:34 -07005681 sendMsg(mAudioHandler, MSG_ACCESSORY_PLUG_MEDIA_UNMUTE, SENDMSG_QUEUE,
5682 AudioSystem.DEVICE_OUT_BLUETOOTH_A2DP, 0, null, 0);
Jean-Michel Trivi4c637b92010-04-12 18:44:10 -07005683 }
5684
Eric Laurent5bfaeae2012-09-21 18:44:48 -07005685 private void onSendBecomingNoisyIntent() {
Dianne Hackborn5ac72a22012-08-29 18:32:08 -07005686 sendBroadcastToAll(new Intent(AudioManager.ACTION_AUDIO_BECOMING_NOISY));
Mike Lockwood98418182012-05-10 17:13:20 -07005687 }
5688
Eric Laurent6bc7f2c2011-11-29 18:49:40 -08005689 // must be called synchronized on mConnectedDevices
Jean-Michel Trivi4c637b92010-04-12 18:44:10 -07005690 private void makeA2dpDeviceUnavailableNow(String address) {
Matthew Xiec9d1d5f2013-09-12 00:32:22 -07005691 synchronized (mA2dpAvrcpLock) {
5692 mAvrcpAbsVolSupported = false;
5693 }
Jean-Michel Trivi4c637b92010-04-12 18:44:10 -07005694 AudioSystem.setDeviceConnectionState(AudioSystem.DEVICE_OUT_BLUETOOTH_A2DP,
Paul McLean20eec5b2015-05-09 13:02:18 -07005695 AudioSystem.DEVICE_STATE_UNAVAILABLE, address, "");
Paul McLean394a8e12015-03-03 10:29:19 -07005696 mConnectedDevices.remove(
5697 makeDeviceListKey(AudioSystem.DEVICE_OUT_BLUETOOTH_A2DP, address));
Jakub Pawlowskif9570f32018-02-21 17:15:12 -08005698 // Remove A2DP routes as well
5699 setCurrentAudioRouteName(null);
Jean-Michel Trivi4c637b92010-04-12 18:44:10 -07005700 }
5701
Eric Laurent6bc7f2c2011-11-29 18:49:40 -08005702 // must be called synchronized on mConnectedDevices
Eric Laurentd138e4e2015-05-15 16:41:15 -07005703 private void makeA2dpDeviceUnavailableLater(String address, int delayMs) {
Eric Laurent3b591262010-04-20 07:01:00 -07005704 // prevent any activity on the A2DP audio output to avoid unwanted
5705 // reconnection of the sink.
5706 AudioSystem.setParameters("A2dpSuspended=true");
Jean-Michel Trivi4c637b92010-04-12 18:44:10 -07005707 // the device will be made unavailable later, so consider it disconnected right away
Paul McLean394a8e12015-03-03 10:29:19 -07005708 mConnectedDevices.remove(
5709 makeDeviceListKey(AudioSystem.DEVICE_OUT_BLUETOOTH_A2DP, address));
Jean-Michel Trivi4c637b92010-04-12 18:44:10 -07005710 // send the delayed message to make the device unavailable later
5711 Message msg = mAudioHandler.obtainMessage(MSG_BTA2DP_DOCK_TIMEOUT, address);
Eric Laurentd138e4e2015-05-15 16:41:15 -07005712 mAudioHandler.sendMessageDelayed(msg, delayMs);
Jean-Michel Trivi4c637b92010-04-12 18:44:10 -07005713
5714 }
5715
Eric Laurent6bc7f2c2011-11-29 18:49:40 -08005716 // must be called synchronized on mConnectedDevices
Mike Lockwood0a40ec22014-05-21 10:08:50 -07005717 private void makeA2dpSrcAvailable(String address) {
5718 AudioSystem.setDeviceConnectionState(AudioSystem.DEVICE_IN_BLUETOOTH_A2DP,
Paul McLean20eec5b2015-05-09 13:02:18 -07005719 AudioSystem.DEVICE_STATE_AVAILABLE, address, "");
Paul McLean394a8e12015-03-03 10:29:19 -07005720 mConnectedDevices.put(
5721 makeDeviceListKey(AudioSystem.DEVICE_IN_BLUETOOTH_A2DP, address),
Paul McLean20eec5b2015-05-09 13:02:18 -07005722 new DeviceListSpec(AudioSystem.DEVICE_IN_BLUETOOTH_A2DP, "",
Paul McLean394a8e12015-03-03 10:29:19 -07005723 address));
Mike Lockwood0a40ec22014-05-21 10:08:50 -07005724 }
5725
5726 // must be called synchronized on mConnectedDevices
5727 private void makeA2dpSrcUnavailable(String address) {
5728 AudioSystem.setDeviceConnectionState(AudioSystem.DEVICE_IN_BLUETOOTH_A2DP,
Paul McLean20eec5b2015-05-09 13:02:18 -07005729 AudioSystem.DEVICE_STATE_UNAVAILABLE, address, "");
Paul McLean394a8e12015-03-03 10:29:19 -07005730 mConnectedDevices.remove(
5731 makeDeviceListKey(AudioSystem.DEVICE_IN_BLUETOOTH_A2DP, address));
Mike Lockwood0a40ec22014-05-21 10:08:50 -07005732 }
5733
Jakub Pawlowski21b7f492018-03-22 12:31:21 -07005734 private void setHearingAidVolume(int index, int streamType) {
Jakub Pawlowski09592d52018-03-19 12:23:59 -07005735 synchronized (mHearingAidLock) {
5736 if (mHearingAid != null) {
5737 //hearing aid expect volume value in range -128dB to 0dB
Jakub Pawlowski21b7f492018-03-22 12:31:21 -07005738 int gainDB = (int)AudioSystem.getStreamVolumeDB(streamType, index/10,
Jakub Pawlowski09592d52018-03-19 12:23:59 -07005739 AudioSystem.DEVICE_OUT_HEARING_AID);
5740 if (gainDB < BT_HEARING_AID_GAIN_MIN)
5741 gainDB = BT_HEARING_AID_GAIN_MIN;
5742 mHearingAid.setVolume(gainDB);
5743 }
5744 }
5745 }
5746
Mike Lockwood0a40ec22014-05-21 10:08:50 -07005747 // must be called synchronized on mConnectedDevices
Jakub Pawlowskif9570f32018-02-21 17:15:12 -08005748 private void makeHearingAidDeviceAvailable(String address, String name, String eventSource) {
Jakub Pawlowski09592d52018-03-19 12:23:59 -07005749 int index = mStreamStates[AudioSystem.STREAM_MUSIC].getIndex(AudioSystem.DEVICE_OUT_HEARING_AID);
Jakub Pawlowski21b7f492018-03-22 12:31:21 -07005750 setHearingAidVolume(index, AudioSystem.STREAM_MUSIC);
Jakub Pawlowski09592d52018-03-19 12:23:59 -07005751
Jakub Pawlowskif9570f32018-02-21 17:15:12 -08005752 AudioSystem.setDeviceConnectionState(AudioSystem.DEVICE_OUT_HEARING_AID,
5753 AudioSystem.DEVICE_STATE_AVAILABLE, address, name);
5754 mConnectedDevices.put(
5755 makeDeviceListKey(AudioSystem.DEVICE_OUT_HEARING_AID, address),
5756 new DeviceListSpec(AudioSystem.DEVICE_OUT_HEARING_AID, name,
5757 address));
5758 sendMsg(mAudioHandler, MSG_ACCESSORY_PLUG_MEDIA_UNMUTE, SENDMSG_QUEUE,
5759 AudioSystem.DEVICE_OUT_HEARING_AID, 0, null, 0);
5760 }
5761
5762 // must be called synchronized on mConnectedDevices
5763 private void makeHearingAidDeviceUnavailable(String address) {
5764 AudioSystem.setDeviceConnectionState(AudioSystem.DEVICE_OUT_HEARING_AID,
5765 AudioSystem.DEVICE_STATE_UNAVAILABLE, address, "");
5766 mConnectedDevices.remove(
5767 makeDeviceListKey(AudioSystem.DEVICE_OUT_HEARING_AID, address));
5768 // Remove Hearing Aid routes as well
5769 setCurrentAudioRouteName(null);
5770 }
5771
5772 // must be called synchronized on mConnectedDevices
Jean-Michel Trivia847ba42010-04-23 11:49:29 -07005773 private void cancelA2dpDeviceTimeout() {
Jean-Michel Trivi4c637b92010-04-12 18:44:10 -07005774 mAudioHandler.removeMessages(MSG_BTA2DP_DOCK_TIMEOUT);
5775 }
5776
Eric Laurent6bc7f2c2011-11-29 18:49:40 -08005777 // must be called synchronized on mConnectedDevices
Jean-Michel Trivia847ba42010-04-23 11:49:29 -07005778 private boolean hasScheduledA2dpDockTimeout() {
5779 return mAudioHandler.hasMessages(MSG_BTA2DP_DOCK_TIMEOUT);
5780 }
5781
Mike Lockwood0a40ec22014-05-21 10:08:50 -07005782 private void onSetA2dpSinkConnectionState(BluetoothDevice btDevice, int state)
Eric Laurent6bc7f2c2011-11-29 18:49:40 -08005783 {
Eric Laurent4724ea72017-05-23 10:39:38 -07005784 if (DEBUG_DEVICES) {
Pavlin Radoslavov44a4ef02016-12-21 12:05:51 -08005785 Log.d(TAG, "onSetA2dpSinkConnectionState btDevice=" + btDevice+"state=" + state);
Mike Lockwood0a40ec22014-05-21 10:08:50 -07005786 }
Eric Laurent6bc7f2c2011-11-29 18:49:40 -08005787 if (btDevice == null) {
5788 return;
5789 }
5790 String address = btDevice.getAddress();
5791 if (!BluetoothAdapter.checkBluetoothAddress(address)) {
5792 address = "";
5793 }
John Du5a0cf7a2013-07-19 11:30:34 -07005794
Eric Laurent6bc7f2c2011-11-29 18:49:40 -08005795 synchronized (mConnectedDevices) {
Pavlin Radoslavov44a4ef02016-12-21 12:05:51 -08005796 final String key = makeDeviceListKey(AudioSystem.DEVICE_OUT_BLUETOOTH_A2DP,
5797 btDevice.getAddress());
5798 final DeviceListSpec deviceSpec = mConnectedDevices.get(key);
Paul McLean394a8e12015-03-03 10:29:19 -07005799 boolean isConnected = deviceSpec != null;
Eric Laurent6bc7f2c2011-11-29 18:49:40 -08005800
5801 if (isConnected && state != BluetoothProfile.STATE_CONNECTED) {
5802 if (btDevice.isBluetoothDock()) {
5803 if (state == BluetoothProfile.STATE_DISCONNECTED) {
5804 // introduction of a delay for transient disconnections of docks when
5805 // power is rapidly turned off/on, this message will be canceled if
5806 // we reconnect the dock under a preset delay
Eric Laurentd138e4e2015-05-15 16:41:15 -07005807 makeA2dpDeviceUnavailableLater(address, BTA2DP_DOCK_TIMEOUT_MILLIS);
Eric Laurent6bc7f2c2011-11-29 18:49:40 -08005808 // the next time isConnected is evaluated, it will be false for the dock
5809 }
5810 } else {
5811 makeA2dpDeviceUnavailableNow(address);
5812 }
Jakub Pawlowskif9570f32018-02-21 17:15:12 -08005813 setCurrentAudioRouteName(null);
Eric Laurent6bc7f2c2011-11-29 18:49:40 -08005814 } else if (!isConnected && state == BluetoothProfile.STATE_CONNECTED) {
5815 if (btDevice.isBluetoothDock()) {
5816 // this could be a reconnection after a transient disconnection
5817 cancelA2dpDeviceTimeout();
5818 mDockAddress = address;
5819 } else {
5820 // this could be a connection of another A2DP device before the timeout of
5821 // a dock: cancel the dock timeout, and make the dock unavailable now
5822 if(hasScheduledA2dpDockTimeout()) {
5823 cancelA2dpDeviceTimeout();
5824 makeA2dpDeviceUnavailableNow(mDockAddress);
5825 }
5826 }
Jean-Michel Trivi011f39e2017-08-19 18:08:06 -07005827 makeA2dpDeviceAvailable(address, btDevice.getName(),
5828 "onSetA2dpSinkConnectionState");
Jakub Pawlowskif9570f32018-02-21 17:15:12 -08005829 setCurrentAudioRouteName(btDevice.getAliasName());
Eric Laurent6bc7f2c2011-11-29 18:49:40 -08005830 }
5831 }
5832 }
5833
Mike Lockwood0a40ec22014-05-21 10:08:50 -07005834 private void onSetA2dpSourceConnectionState(BluetoothDevice btDevice, int state)
5835 {
5836 if (DEBUG_VOL) {
Pavlin Radoslavov44a4ef02016-12-21 12:05:51 -08005837 Log.d(TAG, "onSetA2dpSourceConnectionState btDevice=" + btDevice + " state=" + state);
Mike Lockwood0a40ec22014-05-21 10:08:50 -07005838 }
5839 if (btDevice == null) {
5840 return;
5841 }
5842 String address = btDevice.getAddress();
5843 if (!BluetoothAdapter.checkBluetoothAddress(address)) {
5844 address = "";
5845 }
5846
5847 synchronized (mConnectedDevices) {
Pavlin Radoslavov44a4ef02016-12-21 12:05:51 -08005848 final String key = makeDeviceListKey(AudioSystem.DEVICE_IN_BLUETOOTH_A2DP, address);
5849 final DeviceListSpec deviceSpec = mConnectedDevices.get(key);
Paul McLean394a8e12015-03-03 10:29:19 -07005850 boolean isConnected = deviceSpec != null;
Mike Lockwood0a40ec22014-05-21 10:08:50 -07005851
5852 if (isConnected && state != BluetoothProfile.STATE_CONNECTED) {
5853 makeA2dpSrcUnavailable(address);
5854 } else if (!isConnected && state == BluetoothProfile.STATE_CONNECTED) {
5855 makeA2dpSrcAvailable(address);
5856 }
5857 }
5858 }
5859
Jakub Pawlowskif9570f32018-02-21 17:15:12 -08005860 private void onSetHearingAidConnectionState(BluetoothDevice btDevice, int state)
5861 {
5862 if (DEBUG_DEVICES) {
5863 Log.d(TAG, "onSetHearingAidConnectionState btDevice=" + btDevice+", state=" + state);
5864 }
5865 if (btDevice == null) {
5866 return;
5867 }
5868 String address = btDevice.getAddress();
5869 if (!BluetoothAdapter.checkBluetoothAddress(address)) {
5870 address = "";
5871 }
5872
5873 synchronized (mConnectedDevices) {
5874 final String key = makeDeviceListKey(AudioSystem.DEVICE_OUT_HEARING_AID,
5875 btDevice.getAddress());
5876 final DeviceListSpec deviceSpec = mConnectedDevices.get(key);
5877 boolean isConnected = deviceSpec != null;
5878
5879 if (isConnected && state != BluetoothProfile.STATE_CONNECTED) {
5880 makeHearingAidDeviceUnavailable(address);
5881 setCurrentAudioRouteName(null);
5882 } else if (!isConnected && state == BluetoothProfile.STATE_CONNECTED) {
5883 makeHearingAidDeviceAvailable(address, btDevice.getName(),
5884 "onSetHearingAidConnectionState");
5885 setCurrentAudioRouteName(btDevice.getAliasName());
5886 }
5887 }
5888 }
5889
5890 private void setCurrentAudioRouteName(String name){
5891 synchronized (mCurAudioRoutes) {
5892 if (!TextUtils.equals(mCurAudioRoutes.bluetoothName, name)) {
5893 mCurAudioRoutes.bluetoothName = name;
5894 sendMsg(mAudioHandler, MSG_REPORT_NEW_ROUTES,
5895 SENDMSG_NOOP, 0, 0, null, 0);
5896 }
5897 }
5898 }
5899
Pavlin Radoslavov44a4ef02016-12-21 12:05:51 -08005900 private void onBluetoothA2dpDeviceConfigChange(BluetoothDevice btDevice)
5901 {
Eric Laurent5205a352017-04-27 18:31:22 -07005902 if (DEBUG_DEVICES) {
Pavlin Radoslavov44a4ef02016-12-21 12:05:51 -08005903 Log.d(TAG, "onBluetoothA2dpDeviceConfigChange btDevice=" + btDevice);
5904 }
5905 if (btDevice == null) {
5906 return;
5907 }
5908 String address = btDevice.getAddress();
5909 if (!BluetoothAdapter.checkBluetoothAddress(address)) {
5910 address = "";
5911 }
5912
5913 int device = AudioSystem.DEVICE_OUT_BLUETOOTH_A2DP;
5914 synchronized (mConnectedDevices) {
Eric Laurent4724ea72017-05-23 10:39:38 -07005915 if (mAudioHandler.hasMessages(MSG_SET_A2DP_SINK_CONNECTION_STATE, btDevice)) {
Eric Laurentcdae4762017-04-28 18:00:04 -07005916 return;
5917 }
Pavlin Radoslavov44a4ef02016-12-21 12:05:51 -08005918 final String key = makeDeviceListKey(device, address);
5919 final DeviceListSpec deviceSpec = mConnectedDevices.get(key);
5920 if (deviceSpec != null) {
5921 // Device is connected
Eric Laurentcdae4762017-04-28 18:00:04 -07005922 int musicDevice = getDeviceForStream(AudioSystem.STREAM_MUSIC);
Eric Laurent5205a352017-04-27 18:31:22 -07005923 if (AudioSystem.handleDeviceConfigChange(device, address,
5924 btDevice.getName()) != AudioSystem.AUDIO_STATUS_OK) {
5925 // force A2DP device disconnection in case of error so that AudioService state is
5926 // consistent with audio policy manager state
Eric Laurentcdae4762017-04-28 18:00:04 -07005927 setBluetoothA2dpDeviceConnectionStateInt(
5928 btDevice, BluetoothA2dp.STATE_DISCONNECTED, BluetoothProfile.A2DP,
Pavlin Radoslavov82e06462018-01-19 18:20:04 -08005929 false /* suppressNoisyIntent */, musicDevice);
Eric Laurent5205a352017-04-27 18:31:22 -07005930 }
Pavlin Radoslavov44a4ef02016-12-21 12:05:51 -08005931 }
5932 }
5933 }
5934
John Du5a0cf7a2013-07-19 11:30:34 -07005935 public void avrcpSupportsAbsoluteVolume(String address, boolean support) {
5936 // address is not used for now, but may be used when multiple a2dp devices are supported
5937 synchronized (mA2dpAvrcpLock) {
5938 mAvrcpAbsVolSupported = support;
Matthew Xiec9d1d5f2013-09-12 00:32:22 -07005939 sendMsg(mAudioHandler, MSG_SET_DEVICE_VOLUME, SENDMSG_QUEUE,
Eric Laurentcd772d02013-10-30 18:31:07 -07005940 AudioSystem.DEVICE_OUT_BLUETOOTH_A2DP, 0,
5941 mStreamStates[AudioSystem.STREAM_MUSIC], 0);
5942 sendMsg(mAudioHandler, MSG_SET_DEVICE_VOLUME, SENDMSG_QUEUE,
5943 AudioSystem.DEVICE_OUT_BLUETOOTH_A2DP, 0,
5944 mStreamStates[AudioSystem.STREAM_RING], 0);
John Du5a0cf7a2013-07-19 11:30:34 -07005945 }
5946 }
5947
Paul McLean394a8e12015-03-03 10:29:19 -07005948 private boolean handleDeviceConnection(boolean connect, int device, String address,
5949 String deviceName) {
5950 if (DEBUG_DEVICES) {
5951 Slog.i(TAG, "handleDeviceConnection(" + connect + " dev:" + Integer.toHexString(device)
5952 + " address:" + address + " name:" + deviceName + ")");
5953 }
Eric Laurent59f48272012-04-05 19:42:21 -07005954 synchronized (mConnectedDevices) {
Paul McLean394a8e12015-03-03 10:29:19 -07005955 String deviceKey = makeDeviceListKey(device, address);
5956 if (DEBUG_DEVICES) {
5957 Slog.i(TAG, "deviceKey:" + deviceKey);
5958 }
5959 DeviceListSpec deviceSpec = mConnectedDevices.get(deviceKey);
5960 boolean isConnected = deviceSpec != null;
5961 if (DEBUG_DEVICES) {
5962 Slog.i(TAG, "deviceSpec:" + deviceSpec + " is(already)Connected:" + isConnected);
5963 }
5964 if (connect && !isConnected) {
Jean-Michel Trivi6d00e412015-08-03 17:26:01 -07005965 final int res = AudioSystem.setDeviceConnectionState(device,
5966 AudioSystem.DEVICE_STATE_AVAILABLE, address, deviceName);
5967 if (res != AudioSystem.AUDIO_STATUS_OK) {
5968 Slog.e(TAG, "not connecting device 0x" + Integer.toHexString(device) +
5969 " due to command error " + res );
5970 return false;
5971 }
Paul McLean394a8e12015-03-03 10:29:19 -07005972 mConnectedDevices.put(deviceKey, new DeviceListSpec(device, deviceName, address));
Jean-Michel Trivi1ab43f62017-04-27 15:37:34 -07005973 sendMsg(mAudioHandler, MSG_ACCESSORY_PLUG_MEDIA_UNMUTE, SENDMSG_QUEUE,
5974 device, 0, null, 0);
Paul McLean394a8e12015-03-03 10:29:19 -07005975 return true;
5976 } else if (!connect && isConnected) {
Jean-Michel Trivi6d00e412015-08-03 17:26:01 -07005977 AudioSystem.setDeviceConnectionState(device,
5978 AudioSystem.DEVICE_STATE_UNAVAILABLE, address, deviceName);
5979 // always remove even if disconnection failed
Paul McLean394a8e12015-03-03 10:29:19 -07005980 mConnectedDevices.remove(deviceKey);
5981 return true;
Eric Laurent59f48272012-04-05 19:42:21 -07005982 }
5983 }
5984 return false;
5985 }
5986
Eric Laurentb1fbaac2012-05-29 09:24:28 -07005987 // Devices which removal triggers intent ACTION_AUDIO_BECOMING_NOISY. The intent is only
Eric Laurent9a5b2622017-04-18 18:20:56 -07005988 // sent if:
5989 // - none of these devices are connected anymore after one is disconnected AND
5990 // - the device being disconnected is actually used for music.
Jean-Michel Trivi7e2f3712015-01-12 11:01:55 -08005991 // Access synchronized on mConnectedDevices
Eric Laurentb1fbaac2012-05-29 09:24:28 -07005992 int mBecomingNoisyIntentDevices =
5993 AudioSystem.DEVICE_OUT_WIRED_HEADSET | AudioSystem.DEVICE_OUT_WIRED_HEADPHONE |
Eric Laurent948d3272014-05-16 15:18:45 -07005994 AudioSystem.DEVICE_OUT_ALL_A2DP | AudioSystem.DEVICE_OUT_HDMI |
Eric Laurent794da7a2012-08-30 11:30:16 -07005995 AudioSystem.DEVICE_OUT_ANLG_DOCK_HEADSET | AudioSystem.DEVICE_OUT_DGTL_DOCK_HEADSET |
Jakub Pawlowski26fac412018-03-22 15:00:34 -07005996 AudioSystem.DEVICE_OUT_ALL_USB | AudioSystem.DEVICE_OUT_LINE |
5997 AudioSystem.DEVICE_OUT_HEARING_AID;
Eric Laurentb1fbaac2012-05-29 09:24:28 -07005998
5999 // must be called before removing the device from mConnectedDevices
Jean-Michel Trivi7e2f3712015-01-12 11:01:55 -08006000 // Called synchronized on mConnectedDevices
Eric Laurentcdae4762017-04-28 18:00:04 -07006001 // musicDevice argument is used when not AudioSystem.DEVICE_NONE instead of querying
6002 // from AudioSystem
6003 private int checkSendBecomingNoisyIntent(int device, int state, int musicDevice) {
Eric Laurentb1fbaac2012-05-29 09:24:28 -07006004 int delay = 0;
6005 if ((state == 0) && ((device & mBecomingNoisyIntentDevices) != 0)) {
6006 int devices = 0;
John Spurlock8c3dc852015-04-23 21:32:37 -04006007 for (int i = 0; i < mConnectedDevices.size(); i++) {
6008 int dev = mConnectedDevices.valueAt(i).mDeviceType;
Paul McLean394a8e12015-03-03 10:29:19 -07006009 if (((dev & AudioSystem.DEVICE_BIT_IN) == 0)
6010 && ((dev & mBecomingNoisyIntentDevices) != 0)) {
6011 devices |= dev;
Eric Laurentb1fbaac2012-05-29 09:24:28 -07006012 }
6013 }
Eric Laurentcdae4762017-04-28 18:00:04 -07006014 if (musicDevice == AudioSystem.DEVICE_NONE) {
6015 musicDevice = getDeviceForStream(AudioSystem.STREAM_MUSIC);
6016 }
6017 // ignore condition on device being actually used for music when in communication
6018 // because music routing is altered in this case.
Jean-Michel Trivi7db2d8f2018-03-06 10:30:59 -08006019 // also checks whether media routing if affected by a dynamic policy
6020 if (((device == musicDevice) || isInCommunication()) && (device == devices)
6021 && !hasMediaDynamicPolicy()) {
Eric Laurentcdae4762017-04-28 18:00:04 -07006022 mAudioHandler.removeMessages(MSG_BROADCAST_AUDIO_BECOMING_NOISY);
Eric Laurent5bfaeae2012-09-21 18:44:48 -07006023 sendMsg(mAudioHandler,
6024 MSG_BROADCAST_AUDIO_BECOMING_NOISY,
6025 SENDMSG_REPLACE,
6026 0,
6027 0,
6028 null,
6029 0);
Eric Laurentb1fbaac2012-05-29 09:24:28 -07006030 delay = 1000;
Eric Laurentb1fbaac2012-05-29 09:24:28 -07006031 }
6032 }
6033
Mike Lockwood0a40ec22014-05-21 10:08:50 -07006034 if (mAudioHandler.hasMessages(MSG_SET_A2DP_SRC_CONNECTION_STATE) ||
6035 mAudioHandler.hasMessages(MSG_SET_A2DP_SINK_CONNECTION_STATE) ||
Jakub Pawlowskif9570f32018-02-21 17:15:12 -08006036 mAudioHandler.hasMessages(MSG_SET_HEARING_AID_CONNECTION_STATE) ||
Eric Laurentb1fbaac2012-05-29 09:24:28 -07006037 mAudioHandler.hasMessages(MSG_SET_WIRED_DEVICE_CONNECTION_STATE)) {
Eric Laurentadbe8bf2014-11-03 18:26:32 -08006038 synchronized (mLastDeviceConnectMsgTime) {
6039 long time = SystemClock.uptimeMillis();
6040 if (mLastDeviceConnectMsgTime > time) {
Matthew Xiec525cf72015-01-22 20:13:17 -08006041 delay = (int)(mLastDeviceConnectMsgTime - time) + 30;
Eric Laurentadbe8bf2014-11-03 18:26:32 -08006042 }
6043 }
Eric Laurentb1fbaac2012-05-29 09:24:28 -07006044 }
6045 return delay;
6046 }
6047
Jean-Michel Trivi7db2d8f2018-03-06 10:30:59 -08006048 /**
6049 * @return true if there is currently a registered dynamic mixing policy that affects media
6050 */
6051 private boolean hasMediaDynamicPolicy() {
6052 synchronized (mAudioPolicies) {
6053 if (mAudioPolicies.isEmpty()) {
6054 return false;
6055 }
6056 final Collection<AudioPolicyProxy> appColl = mAudioPolicies.values();
6057 for (AudioPolicyProxy app : appColl) {
6058 if (app.hasMixAffectingUsage(AudioAttributes.USAGE_MEDIA)) {
6059 return true;
6060 }
6061 }
6062 return false;
6063 }
6064 }
6065
Eric Laurenteab40d12017-06-09 12:45:21 -07006066 private void updateAudioRoutes(int device, int state)
6067 {
Dianne Hackborn632ca412012-06-14 19:34:10 -07006068 int connType = 0;
6069
Eric Laurentb1fbaac2012-05-29 09:24:28 -07006070 if (device == AudioSystem.DEVICE_OUT_WIRED_HEADSET) {
Dianne Hackborn632ca412012-06-14 19:34:10 -07006071 connType = AudioRoutesInfo.MAIN_HEADSET;
Jon Eklund43cc8bb2014-07-28 16:07:24 -05006072 } else if (device == AudioSystem.DEVICE_OUT_WIRED_HEADPHONE ||
6073 device == AudioSystem.DEVICE_OUT_LINE) {
Dianne Hackborn632ca412012-06-14 19:34:10 -07006074 connType = AudioRoutesInfo.MAIN_HEADPHONES;
Eric Laurent6fa42452015-01-09 15:09:40 -08006075 } else if (device == AudioSystem.DEVICE_OUT_HDMI ||
6076 device == AudioSystem.DEVICE_OUT_HDMI_ARC) {
Dianne Hackborn632ca412012-06-14 19:34:10 -07006077 connType = AudioRoutesInfo.MAIN_HDMI;
Eric Laurenteab40d12017-06-09 12:45:21 -07006078 } else if (device == AudioSystem.DEVICE_OUT_USB_DEVICE||
6079 device == AudioSystem.DEVICE_OUT_USB_HEADSET) {
Paul McLean10804eb2015-01-28 11:16:35 -08006080 connType = AudioRoutesInfo.MAIN_USB;
Eric Laurentb1fbaac2012-05-29 09:24:28 -07006081 }
6082
Dianne Hackborn632ca412012-06-14 19:34:10 -07006083 synchronized (mCurAudioRoutes) {
6084 if (connType != 0) {
John Spurlock61560172015-02-06 19:46:04 -05006085 int newConn = mCurAudioRoutes.mainType;
Dianne Hackborn632ca412012-06-14 19:34:10 -07006086 if (state != 0) {
6087 newConn |= connType;
6088 } else {
6089 newConn &= ~connType;
6090 }
John Spurlock61560172015-02-06 19:46:04 -05006091 if (newConn != mCurAudioRoutes.mainType) {
6092 mCurAudioRoutes.mainType = newConn;
Dianne Hackborn632ca412012-06-14 19:34:10 -07006093 sendMsg(mAudioHandler, MSG_REPORT_NEW_ROUTES,
6094 SENDMSG_NOOP, 0, 0, null, 0);
6095 }
6096 }
6097 }
Eric Laurenteab40d12017-06-09 12:45:21 -07006098 }
6099
6100 private void sendDeviceConnectionIntent(int device, int state, String address,
6101 String deviceName) {
6102 if (DEBUG_DEVICES) {
6103 Slog.i(TAG, "sendDeviceConnectionIntent(dev:0x" + Integer.toHexString(device) +
6104 " state:0x" + Integer.toHexString(state) + " address:" + address +
6105 " name:" + deviceName + ");");
6106 }
6107 Intent intent = new Intent();
6108
6109 if (device == AudioSystem.DEVICE_OUT_WIRED_HEADSET) {
6110 intent.setAction(Intent.ACTION_HEADSET_PLUG);
6111 intent.putExtra("microphone", 1);
6112 } else if (device == AudioSystem.DEVICE_OUT_WIRED_HEADPHONE ||
6113 device == AudioSystem.DEVICE_OUT_LINE) {
6114 intent.setAction(Intent.ACTION_HEADSET_PLUG);
Jean-Michel Trivi87d31ec2017-08-11 18:28:20 -07006115 intent.putExtra("microphone", 0);
Paul McLean145c9532017-08-04 11:12:19 -06006116 } else if (device == AudioSystem.DEVICE_OUT_USB_HEADSET) {
6117 intent.setAction(Intent.ACTION_HEADSET_PLUG);
Jean-Michel Trivi87d31ec2017-08-11 18:28:20 -07006118 intent.putExtra("microphone",
6119 AudioSystem.getDeviceConnectionState(AudioSystem.DEVICE_IN_USB_HEADSET, "")
6120 == AudioSystem.DEVICE_STATE_AVAILABLE ? 1 : 0);
6121 } else if (device == AudioSystem.DEVICE_IN_USB_HEADSET) {
6122 if (AudioSystem.getDeviceConnectionState(AudioSystem.DEVICE_OUT_USB_HEADSET, "")
6123 == AudioSystem.DEVICE_STATE_AVAILABLE) {
6124 intent.setAction(Intent.ACTION_HEADSET_PLUG);
6125 intent.putExtra("microphone", 1);
6126 } else {
6127 // do not send ACTION_HEADSET_PLUG when only the input side is seen as changing
6128 return;
6129 }
Eric Laurenteab40d12017-06-09 12:45:21 -07006130 } else if (device == AudioSystem.DEVICE_OUT_HDMI ||
6131 device == AudioSystem.DEVICE_OUT_HDMI_ARC) {
6132 configureHdmiPlugIntent(intent, state);
6133 }
6134
Jean-Michel Trivi87a264d2017-08-15 17:52:22 -07006135 if (intent.getAction() == null) {
6136 return;
6137 }
6138
Eric Laurenteab40d12017-06-09 12:45:21 -07006139 intent.putExtra(CONNECT_INTENT_KEY_STATE, state);
6140 intent.putExtra(CONNECT_INTENT_KEY_ADDRESS, address);
6141 intent.putExtra(CONNECT_INTENT_KEY_PORT_NAME, deviceName);
6142
6143 intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY);
Dianne Hackborn632ca412012-06-14 19:34:10 -07006144
Dianne Hackborn5ac72a22012-08-29 18:32:08 -07006145 final long ident = Binder.clearCallingIdentity();
6146 try {
Sudheer Shankadc589ac2016-11-10 15:30:17 -08006147 ActivityManager.broadcastStickyIntent(intent, UserHandle.USER_ALL);
Dianne Hackborn5ac72a22012-08-29 18:32:08 -07006148 } finally {
6149 Binder.restoreCallingIdentity(ident);
6150 }
Eric Laurentb1fbaac2012-05-29 09:24:28 -07006151 }
6152
Eric Laurentbbe3e742017-04-28 18:11:50 -07006153 private static final int DEVICE_OVERRIDE_A2DP_ROUTE_ON_PLUG =
6154 AudioSystem.DEVICE_OUT_WIRED_HEADSET | AudioSystem.DEVICE_OUT_WIRED_HEADPHONE |
6155 AudioSystem.DEVICE_OUT_LINE |
6156 AudioSystem.DEVICE_OUT_ALL_USB;
6157
Paul McLean10804eb2015-01-28 11:16:35 -08006158 private void onSetWiredDeviceConnectionState(int device, int state, String address,
John Spurlock90874332015-03-10 16:00:54 -04006159 String deviceName, String caller) {
Paul McLean394a8e12015-03-03 10:29:19 -07006160 if (DEBUG_DEVICES) {
John Spurlock90874332015-03-10 16:00:54 -04006161 Slog.i(TAG, "onSetWiredDeviceConnectionState(dev:" + Integer.toHexString(device)
6162 + " state:" + Integer.toHexString(state)
6163 + " address:" + address
6164 + " deviceName:" + deviceName
6165 + " caller: " + caller + ");");
Paul McLean394a8e12015-03-03 10:29:19 -07006166 }
Paul McLean10804eb2015-01-28 11:16:35 -08006167
Eric Laurentb1fbaac2012-05-29 09:24:28 -07006168 synchronized (mConnectedDevices) {
Eric Laurentbbe3e742017-04-28 18:11:50 -07006169 if ((state == 0) && ((device & DEVICE_OVERRIDE_A2DP_ROUTE_ON_PLUG) != 0)) {
Jean-Michel Trivi011f39e2017-08-19 18:08:06 -07006170 setBluetoothA2dpOnInt(true, "onSetWiredDeviceConnectionState state 0");
Sungsoocf09fe62016-09-28 16:21:48 +09006171 }
Paul McLean145c9532017-08-04 11:12:19 -06006172
Jean-Michel Trivi6d00e412015-08-03 17:26:01 -07006173 if (!handleDeviceConnection(state == 1, device, address, deviceName)) {
6174 // change of connection state failed, bailout
6175 return;
6176 }
Eric Laurentf1a457d2012-09-20 16:27:23 -07006177 if (state != 0) {
Eric Laurentbbe3e742017-04-28 18:11:50 -07006178 if ((device & DEVICE_OVERRIDE_A2DP_ROUTE_ON_PLUG) != 0) {
Jean-Michel Trivi011f39e2017-08-19 18:08:06 -07006179 setBluetoothA2dpOnInt(false, "onSetWiredDeviceConnectionState state not 0");
Sungsoocf09fe62016-09-28 16:21:48 +09006180 }
Eric Laurentf1a457d2012-09-20 16:27:23 -07006181 if ((device & mSafeMediaVolumeDevices) != 0) {
6182 sendMsg(mAudioHandler,
6183 MSG_CHECK_MUSIC_ACTIVE,
6184 SENDMSG_REPLACE,
6185 0,
6186 0,
John Spurlock90874332015-03-10 16:00:54 -04006187 caller,
Eric Laurentf1a457d2012-09-20 16:27:23 -07006188 MUSIC_ACTIVE_POLL_PERIOD_MS);
6189 }
Eric Laurent212532b2014-07-21 15:43:18 -07006190 // Television devices without CEC service apply software volume on HDMI output
6191 if (isPlatformTelevision() && ((device & AudioSystem.DEVICE_OUT_HDMI) != 0)) {
6192 mFixedVolumeDevices |= AudioSystem.DEVICE_OUT_HDMI;
6193 checkAllFixedVolumeDevices();
6194 if (mHdmiManager != null) {
6195 synchronized (mHdmiManager) {
6196 if (mHdmiPlaybackClient != null) {
6197 mHdmiCecSink = false;
6198 mHdmiPlaybackClient.queryDisplayStatus(mHdmiDisplayStatusCallback);
6199 }
6200 }
6201 }
6202 }
6203 } else {
6204 if (isPlatformTelevision() && ((device & AudioSystem.DEVICE_OUT_HDMI) != 0)) {
6205 if (mHdmiManager != null) {
6206 synchronized (mHdmiManager) {
6207 mHdmiCecSink = false;
6208 }
6209 }
6210 }
Eric Laurentb1fbaac2012-05-29 09:24:28 -07006211 }
Jean-Michel Trivi87a264d2017-08-15 17:52:22 -07006212 sendDeviceConnectionIntent(device, state, address, deviceName);
Eric Laurenteab40d12017-06-09 12:45:21 -07006213 updateAudioRoutes(device, state);
Eric Laurentb1fbaac2012-05-29 09:24:28 -07006214 }
6215 }
6216
Jean-Michel Trivi37d78042014-08-10 14:59:15 -07006217 private void configureHdmiPlugIntent(Intent intent, int state) {
Jean-Michel Trivic5258432014-08-27 15:46:54 -07006218 intent.setAction(AudioManager.ACTION_HDMI_AUDIO_PLUG);
6219 intent.putExtra(AudioManager.EXTRA_AUDIO_PLUG_STATE, state);
Jean-Michel Trivi37d78042014-08-10 14:59:15 -07006220 if (state == 1) {
6221 ArrayList<AudioPort> ports = new ArrayList<AudioPort>();
6222 int[] portGeneration = new int[1];
6223 int status = AudioSystem.listAudioPorts(ports, portGeneration);
6224 if (status == AudioManager.SUCCESS) {
6225 for (AudioPort port : ports) {
6226 if (port instanceof AudioDevicePort) {
6227 final AudioDevicePort devicePort = (AudioDevicePort) port;
Eric Laurent6fa42452015-01-09 15:09:40 -08006228 if (devicePort.type() == AudioManager.DEVICE_OUT_HDMI ||
6229 devicePort.type() == AudioManager.DEVICE_OUT_HDMI_ARC) {
Jean-Michel Trivi37d78042014-08-10 14:59:15 -07006230 // format the list of supported encodings
Eric Laurentcae34662015-05-19 16:46:52 -07006231 int[] formats = AudioFormat.filterPublicFormats(devicePort.formats());
Jean-Michel Trivi37d78042014-08-10 14:59:15 -07006232 if (formats.length > 0) {
6233 ArrayList<Integer> encodingList = new ArrayList(1);
6234 for (int format : formats) {
6235 // a format in the list can be 0, skip it
6236 if (format != AudioFormat.ENCODING_INVALID) {
6237 encodingList.add(format);
6238 }
6239 }
6240 int[] encodingArray = new int[encodingList.size()];
6241 for (int i = 0 ; i < encodingArray.length ; i++) {
6242 encodingArray[i] = encodingList.get(i);
6243 }
Jean-Michel Trivic5258432014-08-27 15:46:54 -07006244 intent.putExtra(AudioManager.EXTRA_ENCODINGS, encodingArray);
Jean-Michel Trivi37d78042014-08-10 14:59:15 -07006245 }
6246 // find the maximum supported number of channels
6247 int maxChannels = 0;
6248 for (int mask : devicePort.channelMasks()) {
6249 int channelCount = AudioFormat.channelCountFromOutChannelMask(mask);
6250 if (channelCount > maxChannels) {
6251 maxChannels = channelCount;
6252 }
6253 }
Jean-Michel Trivic5258432014-08-27 15:46:54 -07006254 intent.putExtra(AudioManager.EXTRA_MAX_CHANNEL_COUNT, maxChannels);
Jean-Michel Trivi37d78042014-08-10 14:59:15 -07006255 }
6256 }
6257 }
6258 }
6259 }
6260 }
6261
Jean-Michel Trivia847ba42010-04-23 11:49:29 -07006262 /* cache of the address of the last dock the device was connected to */
6263 private String mDockAddress;
6264
Eric Laurenta553c252009-07-17 12:17:14 -07006265 /**
6266 * Receiver for misc intent broadcasts the Phone app cares about.
6267 */
6268 private class AudioServiceBroadcastReceiver extends BroadcastReceiver {
6269 @Override
6270 public void onReceive(Context context, Intent intent) {
6271 String action = intent.getAction();
Eric Laurentae4506e2014-05-29 16:04:32 -07006272 int outDevice;
6273 int inDevice;
Eric Laurent59f48272012-04-05 19:42:21 -07006274 int state;
Eric Laurenta553c252009-07-17 12:17:14 -07006275
Jean-Michel Trivi758559e2010-03-09 09:26:08 -08006276 if (action.equals(Intent.ACTION_DOCK_EVENT)) {
6277 int dockState = intent.getIntExtra(Intent.EXTRA_DOCK_STATE,
6278 Intent.EXTRA_DOCK_STATE_UNDOCKED);
6279 int config;
6280 switch (dockState) {
6281 case Intent.EXTRA_DOCK_STATE_DESK:
6282 config = AudioSystem.FORCE_BT_DESK_DOCK;
6283 break;
6284 case Intent.EXTRA_DOCK_STATE_CAR:
6285 config = AudioSystem.FORCE_BT_CAR_DOCK;
6286 break;
Praveen Bharathi21e941b2010-10-06 15:23:14 -05006287 case Intent.EXTRA_DOCK_STATE_LE_DESK:
Eric Laurent08ed1b92012-11-05 14:54:12 -08006288 config = AudioSystem.FORCE_ANALOG_DOCK;
Praveen Bharathi21e941b2010-10-06 15:23:14 -05006289 break;
6290 case Intent.EXTRA_DOCK_STATE_HE_DESK:
6291 config = AudioSystem.FORCE_DIGITAL_DOCK;
6292 break;
Jean-Michel Trivi758559e2010-03-09 09:26:08 -08006293 case Intent.EXTRA_DOCK_STATE_UNDOCKED:
6294 default:
6295 config = AudioSystem.FORCE_NONE;
6296 }
Eric Laurent08ed1b92012-11-05 14:54:12 -08006297 // Low end docks have a menu to enable or disable audio
6298 // (see mDockAudioMediaEnabled)
6299 if (!((dockState == Intent.EXTRA_DOCK_STATE_LE_DESK) ||
6300 ((dockState == Intent.EXTRA_DOCK_STATE_UNDOCKED) &&
6301 (mDockState == Intent.EXTRA_DOCK_STATE_LE_DESK)))) {
Jean-Michel Trivi011f39e2017-08-19 18:08:06 -07006302 mForceUseLogger.log(new ForceUseEvent(AudioSystem.FOR_DOCK, config,
6303 "ACTION_DOCK_EVENT intent"));
Eric Laurent08ed1b92012-11-05 14:54:12 -08006304 AudioSystem.setForceUse(AudioSystem.FOR_DOCK, config);
6305 }
6306 mDockState = dockState;
Jack He8dd33942018-01-17 15:45:12 -08006307 } else if (action.equals(BluetoothHeadset.ACTION_ACTIVE_DEVICE_CHANGED)) {
Eric Laurentdca56b92011-09-02 14:20:56 -07006308 BluetoothDevice btDevice = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
Jack He8dd33942018-01-17 15:45:12 -08006309 setBtScoActiveDevice(btDevice);
Paul McLeandf361462014-04-10 16:02:55 -07006310 } else if (action.equals(BluetoothHeadset.ACTION_AUDIO_STATE_CHANGED)) {
Eric Laurent62ef7672010-11-24 10:58:32 -08006311 boolean broadcast = false;
Eric Laurent59f48272012-04-05 19:42:21 -07006312 int scoAudioState = AudioManager.SCO_AUDIO_STATE_ERROR;
Eric Laurent3def1ee2010-03-17 23:26:26 -07006313 synchronized (mScoClients) {
Eric Laurent62ef7672010-11-24 10:58:32 -08006314 int btState = intent.getIntExtra(BluetoothProfile.EXTRA_STATE, -1);
Eric Laurentdc03c612011-04-01 10:59:41 -07006315 // broadcast intent if the connection was initated by AudioService
6316 if (!mScoClients.isEmpty() &&
6317 (mScoAudioState == SCO_STATE_ACTIVE_INTERNAL ||
6318 mScoAudioState == SCO_STATE_ACTIVATE_REQ ||
6319 mScoAudioState == SCO_STATE_DEACTIVATE_REQ)) {
Eric Laurent62ef7672010-11-24 10:58:32 -08006320 broadcast = true;
6321 }
6322 switch (btState) {
6323 case BluetoothHeadset.STATE_AUDIO_CONNECTED:
Eric Laurent59f48272012-04-05 19:42:21 -07006324 scoAudioState = AudioManager.SCO_AUDIO_STATE_CONNECTED;
Eric Laurentdc03c612011-04-01 10:59:41 -07006325 if (mScoAudioState != SCO_STATE_ACTIVE_INTERNAL &&
6326 mScoAudioState != SCO_STATE_DEACTIVATE_REQ &&
6327 mScoAudioState != SCO_STATE_DEACTIVATE_EXT_REQ) {
Eric Laurent62ef7672010-11-24 10:58:32 -08006328 mScoAudioState = SCO_STATE_ACTIVE_EXTERNAL;
Eric Laurent3def1ee2010-03-17 23:26:26 -07006329 }
Eric Laurent62ef7672010-11-24 10:58:32 -08006330 break;
6331 case BluetoothHeadset.STATE_AUDIO_DISCONNECTED:
Eric Laurent59f48272012-04-05 19:42:21 -07006332 scoAudioState = AudioManager.SCO_AUDIO_STATE_DISCONNECTED;
Eric Laurent62ef7672010-11-24 10:58:32 -08006333 mScoAudioState = SCO_STATE_INACTIVE;
Eric Laurentd7454be2011-09-14 08:45:58 -07006334 clearAllScoClients(0, false);
Eric Laurent62ef7672010-11-24 10:58:32 -08006335 break;
6336 case BluetoothHeadset.STATE_AUDIO_CONNECTING:
Eric Laurentdc03c612011-04-01 10:59:41 -07006337 if (mScoAudioState != SCO_STATE_ACTIVE_INTERNAL &&
6338 mScoAudioState != SCO_STATE_DEACTIVATE_REQ &&
6339 mScoAudioState != SCO_STATE_DEACTIVATE_EXT_REQ) {
Eric Laurent62ef7672010-11-24 10:58:32 -08006340 mScoAudioState = SCO_STATE_ACTIVE_EXTERNAL;
Eric Laurent3def1ee2010-03-17 23:26:26 -07006341 }
Eric Laurent62ef7672010-11-24 10:58:32 -08006342 default:
6343 // do not broadcast CONNECTING or invalid state
6344 broadcast = false;
6345 break;
Eric Laurent3def1ee2010-03-17 23:26:26 -07006346 }
6347 }
Eric Laurent62ef7672010-11-24 10:58:32 -08006348 if (broadcast) {
Eric Laurent59f48272012-04-05 19:42:21 -07006349 broadcastScoConnectionState(scoAudioState);
Eric Laurentdc03c612011-04-01 10:59:41 -07006350 //FIXME: this is to maintain compatibility with deprecated intent
6351 // AudioManager.ACTION_SCO_AUDIO_STATE_CHANGED. Remove when appropriate.
Eric Laurent62ef7672010-11-24 10:58:32 -08006352 Intent newIntent = new Intent(AudioManager.ACTION_SCO_AUDIO_STATE_CHANGED);
Eric Laurent59f48272012-04-05 19:42:21 -07006353 newIntent.putExtra(AudioManager.EXTRA_SCO_AUDIO_STATE, scoAudioState);
Dianne Hackborn5ac72a22012-08-29 18:32:08 -07006354 sendStickyBroadcastToAll(newIntent);
Eric Laurent62ef7672010-11-24 10:58:32 -08006355 }
Eric Laurent950e8cb2011-10-13 08:57:54 -07006356 } else if (action.equals(Intent.ACTION_SCREEN_ON)) {
Jon Eklund318f0fe2014-01-23 17:53:48 -06006357 if (mMonitorRotation) {
Jean-Michel Trivi24806db2015-10-01 15:00:59 -07006358 RotationHelper.enable();
Jon Eklund318f0fe2014-01-23 17:53:48 -06006359 }
Eric Laurent950e8cb2011-10-13 08:57:54 -07006360 AudioSystem.setParameters("screen_state=on");
6361 } else if (action.equals(Intent.ACTION_SCREEN_OFF)) {
Jon Eklund318f0fe2014-01-23 17:53:48 -06006362 if (mMonitorRotation) {
6363 //reduce wakeups (save current) by only listening when display is on
Jean-Michel Trivi24806db2015-10-01 15:00:59 -07006364 RotationHelper.disable();
Jon Eklund318f0fe2014-01-23 17:53:48 -06006365 }
Eric Laurent950e8cb2011-10-13 08:57:54 -07006366 AudioSystem.setParameters("screen_state=off");
Dianne Hackborn961cae92013-03-20 14:59:43 -07006367 } else if (action.equals(Intent.ACTION_CONFIGURATION_CHANGED)) {
Jean-Michel Trivif26f0172012-04-25 16:23:20 -07006368 handleConfigurationChanged(context);
Eric Laurentbc0fab1f2012-09-19 11:24:41 -07006369 } else if (action.equals(Intent.ACTION_USER_SWITCHED)) {
Yasuhiro Matsuda4ced7192015-07-10 22:08:44 +09006370 if (mUserSwitchedReceived) {
6371 // attempt to stop music playback for background user except on first user
6372 // switch (i.e. first boot)
6373 sendMsg(mAudioHandler,
6374 MSG_BROADCAST_AUDIO_BECOMING_NOISY,
6375 SENDMSG_REPLACE,
6376 0,
6377 0,
6378 null,
6379 0);
6380 }
6381 mUserSwitchedReceived = true;
Jean-Michel Trivif4a8eb22012-10-29 12:42:55 -07006382 // the current audio focus owner is no longer valid
Jean-Michel Trivifa9a6982013-06-27 16:22:58 -07006383 mMediaFocusControl.discardAudioFocusOwner();
Jean-Michel Trivif4a8eb22012-10-29 12:42:55 -07006384
Eric Laurent5bfaeae2012-09-21 18:44:48 -07006385 // load volume settings for new user
Eric Laurentbc0fab1f2012-09-19 11:24:41 -07006386 readAudioSettings(true /*userSwitch*/);
6387 // preserve STREAM_MUSIC volume from one user to the next.
6388 sendMsg(mAudioHandler,
6389 MSG_SET_ALL_VOLUMES,
6390 SENDMSG_QUEUE,
6391 0,
6392 0,
6393 mStreamStates[AudioSystem.STREAM_MUSIC], 0);
Fyodor Kupolovb5013302015-04-17 17:59:14 -07006394 } else if (action.equals(Intent.ACTION_USER_BACKGROUND)) {
6395 // Disable audio recording for the background user/profile
6396 int userId = intent.getIntExtra(Intent.EXTRA_USER_HANDLE, -1);
6397 if (userId >= 0) {
6398 // TODO Kill recording streams instead of killing processes holding permission
6399 UserInfo userInfo = UserManagerService.getInstance().getUserInfo(userId);
6400 killBackgroundUserProcessesWithRecordAudioPermission(userInfo);
6401 }
Makoto Onukiac65e1e2015-11-20 15:33:17 -08006402 UserManagerService.getInstance().setUserRestriction(
Fyodor Kupolovb5013302015-04-17 17:59:14 -07006403 UserManager.DISALLOW_RECORD_AUDIO, true, userId);
6404 } else if (action.equals(Intent.ACTION_USER_FOREGROUND)) {
6405 // Enable audio recording for foreground user/profile
6406 int userId = intent.getIntExtra(Intent.EXTRA_USER_HANDLE, -1);
Makoto Onukiac65e1e2015-11-20 15:33:17 -08006407 UserManagerService.getInstance().setUserRestriction(
Fyodor Kupolovb5013302015-04-17 17:59:14 -07006408 UserManager.DISALLOW_RECORD_AUDIO, false, userId);
Eric Laurentb70b78a2016-01-13 19:16:04 -08006409 } else if (action.equals(BluetoothAdapter.ACTION_STATE_CHANGED)) {
6410 state = intent.getIntExtra(BluetoothAdapter.EXTRA_STATE, -1);
6411 if (state == BluetoothAdapter.STATE_OFF ||
6412 state == BluetoothAdapter.STATE_TURNING_OFF) {
6413 disconnectAllBluetoothProfiles();
6414 }
Marco Nelissenfb6df0b2017-02-15 15:25:24 -08006415 } else if (action.equals(AudioEffect.ACTION_OPEN_AUDIO_EFFECT_CONTROL_SESSION) ||
6416 action.equals(AudioEffect.ACTION_CLOSE_AUDIO_EFFECT_CONTROL_SESSION)) {
6417 handleAudioEffectBroadcast(context, intent);
Eric Laurenta553c252009-07-17 12:17:14 -07006418 }
6419 }
Paul McLeanc837a452014-04-09 09:04:43 -07006420 } // end class AudioServiceBroadcastReceiver
Jean-Michel Trivid5176cf2010-01-28 11:56:42 -08006421
Makoto Onukid45a4a22015-11-02 17:17:38 -08006422 private class AudioServiceUserRestrictionsListener implements UserRestrictionsListener {
6423
6424 @Override
6425 public void onUserRestrictionsChanged(int userId, Bundle newRestrictions,
6426 Bundle prevRestrictions) {
6427 // Update mic mute state.
6428 {
6429 final boolean wasRestricted =
6430 prevRestrictions.getBoolean(UserManager.DISALLOW_UNMUTE_MICROPHONE);
6431 final boolean isRestricted =
6432 newRestrictions.getBoolean(UserManager.DISALLOW_UNMUTE_MICROPHONE);
6433 if (wasRestricted != isRestricted) {
6434 setMicrophoneMuteNoCallerCheck(isRestricted, userId);
6435 }
6436 }
6437
6438 // Update speaker mute state.
6439 {
6440 final boolean wasRestricted =
Tony Makc1205112016-07-22 16:02:59 +01006441 prevRestrictions.getBoolean(UserManager.DISALLOW_ADJUST_VOLUME)
Esteban Talavera492b4722017-02-13 14:59:45 +00006442 || prevRestrictions.getBoolean(UserManager.DISALLOW_UNMUTE_DEVICE);
Makoto Onukid45a4a22015-11-02 17:17:38 -08006443 final boolean isRestricted =
Tony Makc1205112016-07-22 16:02:59 +01006444 newRestrictions.getBoolean(UserManager.DISALLOW_ADJUST_VOLUME)
Esteban Talavera492b4722017-02-13 14:59:45 +00006445 || newRestrictions.getBoolean(UserManager.DISALLOW_UNMUTE_DEVICE);
Makoto Onukid45a4a22015-11-02 17:17:38 -08006446 if (wasRestricted != isRestricted) {
6447 setMasterMuteInternalNoCallerCheck(isRestricted, /* flags =*/ 0, userId);
6448 }
6449 }
6450 }
6451 } // end class AudioServiceUserRestrictionsListener
6452
Marco Nelissenfb6df0b2017-02-15 15:25:24 -08006453 private void handleAudioEffectBroadcast(Context context, Intent intent) {
6454 String target = intent.getPackage();
6455 if (target != null) {
6456 Log.w(TAG, "effect broadcast already targeted to " + target);
6457 return;
6458 }
6459 intent.addFlags(Intent.FLAG_INCLUDE_STOPPED_PACKAGES);
6460 // TODO this should target a user-selected panel
6461 List<ResolveInfo> ril = context.getPackageManager().queryBroadcastReceivers(
6462 intent, 0 /* flags */);
6463 if (ril != null && ril.size() != 0) {
6464 ResolveInfo ri = ril.get(0);
6465 if (ri != null && ri.activityInfo != null && ri.activityInfo.packageName != null) {
6466 intent.setPackage(ri.activityInfo.packageName);
6467 context.sendBroadcastAsUser(intent, UserHandle.ALL);
6468 return;
6469 }
6470 }
6471 Log.w(TAG, "couldn't find receiver package for effect intent");
6472 }
6473
Fyodor Kupolovb5013302015-04-17 17:59:14 -07006474 private void killBackgroundUserProcessesWithRecordAudioPermission(UserInfo oldUser) {
6475 PackageManager pm = mContext.getPackageManager();
6476 // Find the home activity of the user. It should not be killed to avoid expensive restart,
6477 // when the user switches back. For managed profiles, we should kill all recording apps
6478 ComponentName homeActivityName = null;
6479 if (!oldUser.isManagedProfile()) {
Sudheer Shankafc46e9b2016-10-21 17:55:27 -07006480 homeActivityName = mActivityManagerInternal.getHomeActivityForUser(oldUser.id);
Fyodor Kupolovb5013302015-04-17 17:59:14 -07006481 }
6482 final String[] permissions = { Manifest.permission.RECORD_AUDIO };
6483 List<PackageInfo> packages;
6484 try {
6485 packages = AppGlobals.getPackageManager()
6486 .getPackagesHoldingPermissions(permissions, 0, oldUser.id).getList();
6487 } catch (RemoteException e) {
6488 throw new AndroidRuntimeException(e);
6489 }
6490 for (int j = packages.size() - 1; j >= 0; j--) {
6491 PackageInfo pkg = packages.get(j);
Fyodor Kupolovbcb6c1e2015-05-11 12:05:15 -07006492 // Skip system processes
6493 if (UserHandle.getAppId(pkg.applicationInfo.uid) < FIRST_APPLICATION_UID) {
6494 continue;
6495 }
Amith Yamasanic1cbaab2015-07-21 11:46:14 -07006496 // Skip packages that have permission to interact across users
6497 if (pm.checkPermission(Manifest.permission.INTERACT_ACROSS_USERS, pkg.packageName)
6498 == PackageManager.PERMISSION_GRANTED) {
6499 continue;
6500 }
Fyodor Kupolovb5013302015-04-17 17:59:14 -07006501 if (homeActivityName != null
6502 && pkg.packageName.equals(homeActivityName.getPackageName())
6503 && pkg.applicationInfo.isSystemApp()) {
6504 continue;
6505 }
6506 try {
Svetoslavaa41add2015-08-06 15:03:55 -07006507 final int uid = pkg.applicationInfo.uid;
Sudheer Shankadc589ac2016-11-10 15:30:17 -08006508 ActivityManager.getService().killUid(UserHandle.getAppId(uid),
Svetoslavaa41add2015-08-06 15:03:55 -07006509 UserHandle.getUserId(uid),
Fyodor Kupolovb5013302015-04-17 17:59:14 -07006510 "killBackgroundUserProcessesWithAudioRecordPermission");
6511 } catch (RemoteException e) {
6512 Log.w(TAG, "Error calling killUid", e);
6513 }
6514 }
6515 }
6516
Jean-Michel Trivi3114ce32012-06-11 15:03:52 -07006517
Jean-Michel Trivifa9a6982013-06-27 16:22:58 -07006518 //==========================================================================================
6519 // Audio Focus
6520 //==========================================================================================
Jean-Michel Trivi9228af62018-01-05 17:06:17 -08006521 /**
6522 * Returns whether a focus request is eligible to force ducking.
6523 * Will return true if:
6524 * - the AudioAttributes have a usage of USAGE_ASSISTANCE_ACCESSIBILITY,
6525 * - the focus request is AUDIOFOCUS_GAIN_TRANSIENT_MAY_DUCK,
6526 * - the associated Bundle has KEY_ACCESSIBILITY_FORCE_FOCUS_DUCKING set to true,
6527 * - the uid of the requester is a known accessibility service or root.
6528 * @param aa AudioAttributes of the focus request
6529 * @param uid uid of the focus requester
6530 * @return true if ducking is to be forced
6531 */
6532 private boolean forceFocusDuckingForAccessibility(@Nullable AudioAttributes aa,
6533 int request, int uid) {
6534 if (aa == null || aa.getUsage() != AudioAttributes.USAGE_ASSISTANCE_ACCESSIBILITY
6535 || request != AudioManager.AUDIOFOCUS_GAIN_TRANSIENT_MAY_DUCK) {
6536 return false;
6537 }
6538 final Bundle extraInfo = aa.getBundle();
6539 if (extraInfo == null ||
6540 !extraInfo.getBoolean(AudioFocusRequest.KEY_ACCESSIBILITY_FORCE_FOCUS_DUCKING)) {
6541 return false;
6542 }
6543 if (uid == 0) {
6544 return true;
6545 }
6546 synchronized (mAccessibilityServiceUidsLock) {
6547 if (mAccessibilityServiceUids != null) {
6548 int callingUid = Binder.getCallingUid();
6549 for (int i = 0; i < mAccessibilityServiceUids.length; i++) {
6550 if (mAccessibilityServiceUids[i] == callingUid) {
6551 return true;
6552 }
6553 }
6554 }
6555 }
6556 return false;
6557 }
6558
Jean-Michel Trivifd6ad742014-11-10 14:38:30 -08006559 public int requestAudioFocus(AudioAttributes aa, int durationHint, IBinder cb,
Jean-Michel Trivi958876f2014-11-16 15:40:22 -08006560 IAudioFocusDispatcher fd, String clientId, String callingPackageName, int flags,
Jean-Michel Trivi461922f2017-04-25 15:23:17 -07006561 IAudioPolicyCallback pcb, int sdk) {
Jean-Michel Trivi958876f2014-11-16 15:40:22 -08006562 // permission checks
6563 if ((flags & AudioManager.AUDIOFOCUS_FLAG_LOCK) == AudioManager.AUDIOFOCUS_FLAG_LOCK) {
John Spurlock61560172015-02-06 19:46:04 -05006564 if (AudioSystem.IN_VOICE_COMM_FOCUS_ID.equals(clientId)) {
Jean-Michel Trivi958876f2014-11-16 15:40:22 -08006565 if (PackageManager.PERMISSION_GRANTED != mContext.checkCallingOrSelfPermission(
6566 android.Manifest.permission.MODIFY_PHONE_STATE)) {
6567 Log.e(TAG, "Invalid permission to (un)lock audio focus", new Exception());
6568 return AudioManager.AUDIOFOCUS_REQUEST_FAILED;
6569 }
6570 } else {
6571 // only a registered audio policy can be used to lock focus
6572 synchronized (mAudioPolicies) {
Jean-Michel Trivi0212be52014-11-24 14:43:10 -08006573 if (!mAudioPolicies.containsKey(pcb.asBinder())) {
6574 Log.e(TAG, "Invalid unregistered AudioPolicy to (un)lock audio focus");
Jean-Michel Trivi958876f2014-11-16 15:40:22 -08006575 return AudioManager.AUDIOFOCUS_REQUEST_FAILED;
6576 }
6577 }
6578 }
6579 }
6580
Jean-Michel Trivifd6ad742014-11-10 14:38:30 -08006581 return mMediaFocusControl.requestAudioFocus(aa, durationHint, cb, fd,
Jean-Michel Trivi9228af62018-01-05 17:06:17 -08006582 clientId, callingPackageName, flags, sdk,
6583 forceFocusDuckingForAccessibility(aa, durationHint, Binder.getCallingUid()));
Jean-Michel Trivifa9a6982013-06-27 16:22:58 -07006584 }
6585
Jean-Michel Trivi126cf032017-04-02 23:19:02 -07006586 public int abandonAudioFocus(IAudioFocusDispatcher fd, String clientId, AudioAttributes aa,
6587 String callingPackageName) {
6588 return mMediaFocusControl.abandonAudioFocus(fd, clientId, aa, callingPackageName);
Jean-Michel Trivifa9a6982013-06-27 16:22:58 -07006589 }
6590
6591 public void unregisterAudioFocusClient(String clientId) {
6592 mMediaFocusControl.unregisterAudioFocusClient(clientId);
Jean-Michel Trivi3114ce32012-06-11 15:03:52 -07006593 }
6594
Jean-Michel Trivi23805662013-07-31 14:19:18 -07006595 public int getCurrentAudioFocus() {
6596 return mMediaFocusControl.getCurrentAudioFocus();
6597 }
6598
Jean-Michel Trivi99489cc2017-01-25 19:08:49 -08006599 public int getFocusRampTimeMs(int focusGain, AudioAttributes attr) {
6600 return mMediaFocusControl.getFocusRampTimeMs(focusGain, attr);
6601 }
6602
Jean-Michel Trivi126cf032017-04-02 23:19:02 -07006603 //==========================================================================================
John Spurlock5e783732015-02-19 10:28:59 -05006604 private boolean readCameraSoundForced() {
6605 return SystemProperties.getBoolean("audio.camerasound.force", false) ||
6606 mContext.getResources().getBoolean(
6607 com.android.internal.R.bool.config_camera_sound_forced);
6608 }
6609
Jean-Michel Trivif26f0172012-04-25 16:23:20 -07006610 //==========================================================================================
6611 // Device orientation
6612 //==========================================================================================
6613 /**
Mikhail Naganovb668bc62018-02-13 13:46:38 -08006614 * Handles device configuration changes that may map to a change in rotation.
6615 * Monitoring rotation is optional, and is defined by the definition and value
6616 * of the "ro.audio.monitorRotation" system property.
Jean-Michel Trivif26f0172012-04-25 16:23:20 -07006617 */
6618 private void handleConfigurationChanged(Context context) {
6619 try {
Mikhail Naganovb668bc62018-02-13 13:46:38 -08006620 // reading new configuration "safely" (i.e. under try catch) in case anything
6621 // goes wrong.
Eric Laurentd640bd32012-09-28 18:01:48 -07006622 Configuration config = context.getResources().getConfiguration();
Eric Laurentd640bd32012-09-28 18:01:48 -07006623 sendMsg(mAudioHandler,
6624 MSG_CONFIGURE_SAFE_MEDIA_VOLUME,
6625 SENDMSG_REPLACE,
6626 0,
6627 0,
John Spurlock90874332015-03-10 16:00:54 -04006628 TAG,
Eric Laurentd640bd32012-09-28 18:01:48 -07006629 0);
Eric Laurentdd45d012012-10-08 09:04:34 -07006630
John Spurlock5e783732015-02-19 10:28:59 -05006631 boolean cameraSoundForced = readCameraSoundForced();
Eric Laurentdd45d012012-10-08 09:04:34 -07006632 synchronized (mSettingsLock) {
Jean-Michel Trivi8719a1d2017-11-06 11:52:51 -08006633 final boolean cameraSoundForcedChanged = (cameraSoundForced != mCameraSoundForced);
6634 mCameraSoundForced = cameraSoundForced;
Eric Laurent8fa4d6f2014-10-30 14:13:03 -07006635 if (cameraSoundForcedChanged) {
Muyuan Li1ed6df62016-06-18 11:16:52 -07006636 if (!mIsSingleVolume) {
Jean-Michel Trivi085346a2018-02-14 10:48:51 -08006637 synchronized (VolumeStreamState.class) {
6638 VolumeStreamState s = mStreamStates[AudioSystem.STREAM_SYSTEM_ENFORCED];
6639 if (cameraSoundForced) {
6640 s.setAllIndexesToMax();
6641 mRingerModeAffectedStreams &=
6642 ~(1 << AudioSystem.STREAM_SYSTEM_ENFORCED);
6643 } else {
6644 s.setAllIndexes(mStreamStates[AudioSystem.STREAM_SYSTEM], TAG);
6645 mRingerModeAffectedStreams |=
6646 (1 << AudioSystem.STREAM_SYSTEM_ENFORCED);
6647 }
Eric Laurent8fa4d6f2014-10-30 14:13:03 -07006648 }
6649 // take new state into account for streams muted by ringer mode
John Spurlock661f2cf2014-11-17 10:29:10 -05006650 setRingerModeInt(getRingerModeInternal(), false);
Eric Laurent8fa4d6f2014-10-30 14:13:03 -07006651 }
6652
6653 sendMsg(mAudioHandler,
6654 MSG_SET_FORCE_USE,
6655 SENDMSG_QUEUE,
6656 AudioSystem.FOR_SYSTEM,
6657 cameraSoundForced ?
6658 AudioSystem.FORCE_SYSTEM_ENFORCED : AudioSystem.FORCE_NONE,
Jean-Michel Trivi011f39e2017-08-19 18:08:06 -07006659 new String("handleConfigurationChanged"),
Eric Laurent8fa4d6f2014-10-30 14:13:03 -07006660 0);
6661
6662 sendMsg(mAudioHandler,
6663 MSG_SET_ALL_VOLUMES,
6664 SENDMSG_QUEUE,
6665 0,
6666 0,
6667 mStreamStates[AudioSystem.STREAM_SYSTEM_ENFORCED], 0);
6668 }
Eric Laurentdd45d012012-10-08 09:04:34 -07006669 }
John Spurlock3346a802014-05-20 16:25:37 -04006670 mVolumeController.setLayoutDirection(config.getLayoutDirection());
Jean-Michel Trivif26f0172012-04-25 16:23:20 -07006671 } catch (Exception e) {
Jean-Michel Trivibb6f8712013-05-23 15:02:41 -07006672 Log.e(TAG, "Error handling configuration change: ", e);
Jean-Michel Trivif26f0172012-04-25 16:23:20 -07006673 }
6674 }
6675
Sungsoocf09fe62016-09-28 16:21:48 +09006676 // Handles request to override default use of A2DP for media.
6677 // Must be called synchronized on mConnectedDevices
Jean-Michel Trivi011f39e2017-08-19 18:08:06 -07006678 public void setBluetoothA2dpOnInt(boolean on, String eventSource) {
Sungsoocf09fe62016-09-28 16:21:48 +09006679 synchronized (mBluetoothA2dpEnabledLock) {
6680 mBluetoothA2dpEnabled = on;
6681 mAudioHandler.removeMessages(MSG_SET_FORCE_BT_A2DP_USE);
6682 setForceUseInt_SyncDevices(AudioSystem.FOR_MEDIA,
Jean-Michel Trivi011f39e2017-08-19 18:08:06 -07006683 mBluetoothA2dpEnabled ? AudioSystem.FORCE_NONE : AudioSystem.FORCE_NO_BT_A2DP,
6684 eventSource);
Sungsoocf09fe62016-09-28 16:21:48 +09006685 }
6686 }
6687
Jean-Michel Trivi7e2f3712015-01-12 11:01:55 -08006688 // Must be called synchronized on mConnectedDevices
Jean-Michel Trivi011f39e2017-08-19 18:08:06 -07006689 private void setForceUseInt_SyncDevices(int usage, int config, String eventSource) {
Eric Laurent9a5b2622017-04-18 18:20:56 -07006690 if (usage == AudioSystem.FOR_MEDIA) {
6691 sendMsg(mAudioHandler, MSG_REPORT_NEW_ROUTES,
6692 SENDMSG_NOOP, 0, 0, null, 0);
Jean-Michel Trivi7e2f3712015-01-12 11:01:55 -08006693 }
Jean-Michel Trivi011f39e2017-08-19 18:08:06 -07006694 mForceUseLogger.log(new ForceUseEvent(usage, config, eventSource));
Jean-Michel Trivi7e2f3712015-01-12 11:01:55 -08006695 AudioSystem.setForceUse(usage, config);
6696 }
6697
Jean-Michel Trivid5176cf2010-01-28 11:56:42 -08006698 @Override
Jeff Sharkey098d5802012-04-26 17:30:34 -07006699 public void setRingtonePlayer(IRingtonePlayer player) {
6700 mContext.enforceCallingOrSelfPermission(REMOTE_AUDIO_PLAYBACK, null);
6701 mRingtonePlayer = player;
6702 }
6703
6704 @Override
6705 public IRingtonePlayer getRingtonePlayer() {
6706 return mRingtonePlayer;
6707 }
6708
6709 @Override
Dianne Hackborn632ca412012-06-14 19:34:10 -07006710 public AudioRoutesInfo startWatchingRoutes(IAudioRoutesObserver observer) {
6711 synchronized (mCurAudioRoutes) {
6712 AudioRoutesInfo routes = new AudioRoutesInfo(mCurAudioRoutes);
6713 mRoutesObservers.register(observer);
6714 return routes;
6715 }
6716 }
6717
Eric Laurentc34dcc12012-09-10 13:51:52 -07006718
6719 //==========================================================================================
6720 // Safe media volume management.
6721 // MUSIC stream volume level is limited when headphones are connected according to safety
6722 // regulation. When the user attempts to raise the volume above the limit, a warning is
6723 // displayed and the user has to acknowlegde before the volume is actually changed.
6724 // The volume index corresponding to the limit is stored in config_safe_media_volume_index
6725 // property. Platforms with a different limit must set this property accordingly in their
6726 // overlay.
6727 //==========================================================================================
6728
Eric Laurentd640bd32012-09-28 18:01:48 -07006729 // mSafeMediaVolumeState indicates whether the media volume is limited over headphones.
6730 // It is SAFE_MEDIA_VOLUME_NOT_CONFIGURED at boot time until a network service is connected
6731 // or the configure time is elapsed. It is then set to SAFE_MEDIA_VOLUME_ACTIVE or
6732 // SAFE_MEDIA_VOLUME_DISABLED according to country option. If not SAFE_MEDIA_VOLUME_DISABLED, it
6733 // can be set to SAFE_MEDIA_VOLUME_INACTIVE by calling AudioService.disableSafeMediaVolume()
6734 // (when user opts out).
John Spurlock35134602014-07-24 18:10:48 -04006735 private static final int SAFE_MEDIA_VOLUME_NOT_CONFIGURED = 0;
6736 private static final int SAFE_MEDIA_VOLUME_DISABLED = 1;
6737 private static final int SAFE_MEDIA_VOLUME_INACTIVE = 2; // confirmed
6738 private static final int SAFE_MEDIA_VOLUME_ACTIVE = 3; // unconfirmed
Eric Laurentd640bd32012-09-28 18:01:48 -07006739 private Integer mSafeMediaVolumeState;
6740
6741 private int mMcc = 0;
Eric Laurentc34dcc12012-09-10 13:51:52 -07006742 // mSafeMediaVolumeIndex is the cached value of config_safe_media_volume_index property
Eric Laurentd640bd32012-09-28 18:01:48 -07006743 private int mSafeMediaVolumeIndex;
John Muir8b8bddd2018-02-16 14:29:14 -08006744 // mSafeUsbMediaVolumeDbfs is the cached value of the config_safe_media_volume_usb_mB
6745 // property, divided by 100.0.
6746 private float mSafeUsbMediaVolumeDbfs;
Eric Laurentb378a13a2017-07-11 14:08:11 -07006747 // mSafeUsbMediaVolumeIndex is used for USB Headsets and is the music volume UI index
John Muir8b8bddd2018-02-16 14:29:14 -08006748 // corresponding to a gain of mSafeUsbMediaVolumeDbfs (defaulting to -37dB) in audio
6749 // flinger mixer.
Eric Laurent0e5deb32017-09-01 15:12:42 -07006750 // We remove -22 dBs from the theoretical -15dB to account for the EQ + bass boost
6751 // amplification when both effects are on with all band gains at maximum.
Eric Laurentb378a13a2017-07-11 14:08:11 -07006752 // This level corresponds to a loudness of 85 dB SPL for the warning to be displayed when
6753 // the headset is compliant to EN 60950 with a max loudness of 100dB SPL.
Eric Laurenteab40d12017-06-09 12:45:21 -07006754 private int mSafeUsbMediaVolumeIndex;
Eric Laurentc34dcc12012-09-10 13:51:52 -07006755 // mSafeMediaVolumeDevices lists the devices for which safe media volume is enforced,
6756 private final int mSafeMediaVolumeDevices = AudioSystem.DEVICE_OUT_WIRED_HEADSET |
Eric Laurenteab40d12017-06-09 12:45:21 -07006757 AudioSystem.DEVICE_OUT_WIRED_HEADPHONE |
6758 AudioSystem.DEVICE_OUT_USB_HEADSET;
Eric Laurentc34dcc12012-09-10 13:51:52 -07006759 // mMusicActiveMs is the cumulative time of music activity since safe volume was disabled.
6760 // When this time reaches UNSAFE_VOLUME_MUSIC_ACTIVE_MS_MAX, the safe media volume is re-enabled
6761 // automatically. mMusicActiveMs is rounded to a multiple of MUSIC_ACTIVE_POLL_PERIOD_MS.
6762 private int mMusicActiveMs;
6763 private static final int UNSAFE_VOLUME_MUSIC_ACTIVE_MS_MAX = (20 * 3600 * 1000); // 20 hours
6764 private static final int MUSIC_ACTIVE_POLL_PERIOD_MS = 60000; // 1 minute polling interval
Eric Laurentd640bd32012-09-28 18:01:48 -07006765 private static final int SAFE_VOLUME_CONFIGURE_TIMEOUT_MS = 30000; // 30s after boot completed
Eric Laurentc34dcc12012-09-10 13:51:52 -07006766
Eric Laurenteab40d12017-06-09 12:45:21 -07006767 private int safeMediaVolumeIndex(int device) {
6768 if ((device & mSafeMediaVolumeDevices) == 0) {
6769 return MAX_STREAM_VOLUME[AudioSystem.STREAM_MUSIC];
6770 }
6771 if (device == AudioSystem.DEVICE_OUT_USB_HEADSET) {
6772 return mSafeUsbMediaVolumeIndex;
6773 } else {
6774 return mSafeMediaVolumeIndex;
6775 }
6776 }
6777
John Spurlock90874332015-03-10 16:00:54 -04006778 private void setSafeMediaVolumeEnabled(boolean on, String caller) {
Eric Laurentd640bd32012-09-28 18:01:48 -07006779 synchronized (mSafeMediaVolumeState) {
6780 if ((mSafeMediaVolumeState != SAFE_MEDIA_VOLUME_NOT_CONFIGURED) &&
6781 (mSafeMediaVolumeState != SAFE_MEDIA_VOLUME_DISABLED)) {
6782 if (on && (mSafeMediaVolumeState == SAFE_MEDIA_VOLUME_INACTIVE)) {
6783 mSafeMediaVolumeState = SAFE_MEDIA_VOLUME_ACTIVE;
John Spurlock90874332015-03-10 16:00:54 -04006784 enforceSafeMediaVolume(caller);
Eric Laurentd640bd32012-09-28 18:01:48 -07006785 } else if (!on && (mSafeMediaVolumeState == SAFE_MEDIA_VOLUME_ACTIVE)) {
6786 mSafeMediaVolumeState = SAFE_MEDIA_VOLUME_INACTIVE;
John Spurlockaa5ee4d2014-07-25 13:05:12 -04006787 mMusicActiveMs = 1; // nonzero = confirmed
6788 saveMusicActiveMs();
Eric Laurentd640bd32012-09-28 18:01:48 -07006789 sendMsg(mAudioHandler,
6790 MSG_CHECK_MUSIC_ACTIVE,
6791 SENDMSG_REPLACE,
6792 0,
6793 0,
John Spurlock90874332015-03-10 16:00:54 -04006794 caller,
Eric Laurentd640bd32012-09-28 18:01:48 -07006795 MUSIC_ACTIVE_POLL_PERIOD_MS);
6796 }
Eric Laurentc34dcc12012-09-10 13:51:52 -07006797 }
Eric Laurentc34dcc12012-09-10 13:51:52 -07006798 }
6799 }
6800
John Spurlock90874332015-03-10 16:00:54 -04006801 private void enforceSafeMediaVolume(String caller) {
Eric Laurentc34dcc12012-09-10 13:51:52 -07006802 VolumeStreamState streamState = mStreamStates[AudioSystem.STREAM_MUSIC];
Eric Laurentc34dcc12012-09-10 13:51:52 -07006803 int devices = mSafeMediaVolumeDevices;
6804 int i = 0;
6805
6806 while (devices != 0) {
6807 int device = 1 << i++;
6808 if ((device & devices) == 0) {
6809 continue;
6810 }
Eric Laurent42b041e2013-03-29 11:36:03 -07006811 int index = streamState.getIndex(device);
Eric Laurenteab40d12017-06-09 12:45:21 -07006812 if (index > safeMediaVolumeIndex(device)) {
6813 streamState.setIndex(safeMediaVolumeIndex(device), device, caller);
Eric Laurent42b041e2013-03-29 11:36:03 -07006814 sendMsg(mAudioHandler,
6815 MSG_SET_DEVICE_VOLUME,
6816 SENDMSG_QUEUE,
6817 device,
6818 0,
6819 streamState,
6820 0);
Eric Laurentc34dcc12012-09-10 13:51:52 -07006821 }
6822 devices &= ~device;
6823 }
6824 }
6825
6826 private boolean checkSafeMediaVolume(int streamType, int index, int device) {
Eric Laurentd640bd32012-09-28 18:01:48 -07006827 synchronized (mSafeMediaVolumeState) {
6828 if ((mSafeMediaVolumeState == SAFE_MEDIA_VOLUME_ACTIVE) &&
Eric Laurentc34dcc12012-09-10 13:51:52 -07006829 (mStreamVolumeAlias[streamType] == AudioSystem.STREAM_MUSIC) &&
6830 ((device & mSafeMediaVolumeDevices) != 0) &&
Eric Laurenteab40d12017-06-09 12:45:21 -07006831 (index > safeMediaVolumeIndex(device))) {
Eric Laurentc34dcc12012-09-10 13:51:52 -07006832 return false;
6833 }
6834 return true;
6835 }
6836 }
6837
John Spurlock3346a802014-05-20 16:25:37 -04006838 @Override
John Spurlock90874332015-03-10 16:00:54 -04006839 public void disableSafeMediaVolume(String callingPackage) {
John Spurlockcdb57ae2015-02-11 19:04:11 -05006840 enforceVolumeController("disable the safe media volume");
Eric Laurentd640bd32012-09-28 18:01:48 -07006841 synchronized (mSafeMediaVolumeState) {
John Spurlock90874332015-03-10 16:00:54 -04006842 setSafeMediaVolumeEnabled(false, callingPackage);
Eric Laurentfde16d52012-12-03 14:42:39 -08006843 if (mPendingVolumeCommand != null) {
6844 onSetStreamVolume(mPendingVolumeCommand.mStreamType,
6845 mPendingVolumeCommand.mIndex,
6846 mPendingVolumeCommand.mFlags,
John Spurlock90874332015-03-10 16:00:54 -04006847 mPendingVolumeCommand.mDevice,
6848 callingPackage);
Eric Laurentfde16d52012-12-03 14:42:39 -08006849 mPendingVolumeCommand = null;
6850 }
Eric Laurentc34dcc12012-09-10 13:51:52 -07006851 }
6852 }
6853
Jungshik Jang41d97462014-06-30 22:26:29 +09006854 //==========================================================================================
6855 // Hdmi Cec system audio mode.
John Spurlockbc82b122015-03-02 16:12:38 -05006856 // If Hdmi Cec's system audio mode is on, audio service should send the volume change
6857 // to HdmiControlService so that the audio receiver can handle it.
Jungshik Jang41d97462014-06-30 22:26:29 +09006858 //==========================================================================================
6859
Eric Laurent212532b2014-07-21 15:43:18 -07006860 private class MyDisplayStatusCallback implements HdmiPlaybackClient.DisplayStatusCallback {
6861 public void onComplete(int status) {
6862 if (mHdmiManager != null) {
6863 synchronized (mHdmiManager) {
6864 mHdmiCecSink = (status != HdmiControlManager.POWER_STATUS_UNKNOWN);
6865 // Television devices without CEC service apply software volume on HDMI output
6866 if (isPlatformTelevision() && !mHdmiCecSink) {
6867 mFixedVolumeDevices &= ~AudioSystem.DEVICE_OUT_HDMI;
6868 }
6869 checkAllFixedVolumeDevices();
6870 }
6871 }
6872 }
6873 };
6874
Jungshik Jang41d97462014-06-30 22:26:29 +09006875 // If HDMI-CEC system audio is supported
6876 private boolean mHdmiSystemAudioSupported = false;
6877 // Set only when device is tv.
6878 private HdmiTvClient mHdmiTvClient;
Eric Laurent0b03f992014-11-18 18:08:02 -08006879 // true if the device has system feature PackageManager.FEATURE_LEANBACK.
Eric Laurent212532b2014-07-21 15:43:18 -07006880 // cached HdmiControlManager interface
6881 private HdmiControlManager mHdmiManager;
6882 // Set only when device is a set-top box.
6883 private HdmiPlaybackClient mHdmiPlaybackClient;
6884 // true if we are a set-top box, an HDMI sink is connected and it supports CEC.
6885 private boolean mHdmiCecSink;
6886
6887 private MyDisplayStatusCallback mHdmiDisplayStatusCallback = new MyDisplayStatusCallback();
Jungshik Jang41d97462014-06-30 22:26:29 +09006888
6889 @Override
Jungshik Jang12307ca2014-07-15 19:27:56 +09006890 public int setHdmiSystemAudioSupported(boolean on) {
Eric Laurent212532b2014-07-21 15:43:18 -07006891 int device = AudioSystem.DEVICE_NONE;
6892 if (mHdmiManager != null) {
6893 synchronized (mHdmiManager) {
6894 if (mHdmiTvClient == null) {
6895 Log.w(TAG, "Only Hdmi-Cec enabled TV device supports system audio mode.");
6896 return device;
6897 }
Jungshik Jang41d97462014-06-30 22:26:29 +09006898
Eric Laurent212532b2014-07-21 15:43:18 -07006899 synchronized (mHdmiTvClient) {
6900 if (mHdmiSystemAudioSupported != on) {
6901 mHdmiSystemAudioSupported = on;
Jean-Michel Trivi011f39e2017-08-19 18:08:06 -07006902 final int config = on ? AudioSystem.FORCE_HDMI_SYSTEM_AUDIO_ENFORCED :
6903 AudioSystem.FORCE_NONE;
6904 mForceUseLogger.log(new ForceUseEvent(AudioSystem.FOR_HDMI_SYSTEM_AUDIO,
6905 config, "setHdmiSystemAudioSupported"));
6906 AudioSystem.setForceUse(AudioSystem.FOR_HDMI_SYSTEM_AUDIO, config);
Eric Laurent212532b2014-07-21 15:43:18 -07006907 }
John Spurlock8a52c442015-03-26 14:23:58 -04006908 device = getDevicesForStream(AudioSystem.STREAM_MUSIC);
Eric Laurent212532b2014-07-21 15:43:18 -07006909 }
Jungshik Jang6f34f5a2014-07-08 21:17:29 +09006910 }
Jungshik Jang6f34f5a2014-07-08 21:17:29 +09006911 }
Eric Laurent212532b2014-07-21 15:43:18 -07006912 return device;
Jungshik Jang6f34f5a2014-07-08 21:17:29 +09006913 }
Jungshik Jang41d97462014-06-30 22:26:29 +09006914
Terry Heoe7d6d972014-09-04 21:05:28 +09006915 @Override
6916 public boolean isHdmiSystemAudioSupported() {
6917 return mHdmiSystemAudioSupported;
6918 }
6919
Eric Laurentdd45d012012-10-08 09:04:34 -07006920 //==========================================================================================
Jean-Michel Triviac487672016-11-11 10:05:18 -08006921 // Accessibility
6922
Jean-Michel Trivicfa55532017-01-18 11:17:51 -08006923 private void initA11yMonitoring() {
6924 final AccessibilityManager accessibilityManager =
6925 (AccessibilityManager) mContext.getSystemService(Context.ACCESSIBILITY_SERVICE);
Jean-Michel Triviac487672016-11-11 10:05:18 -08006926 updateDefaultStreamOverrideDelay(accessibilityManager.isTouchExplorationEnabled());
Jean-Michel Trivi7592b982017-02-01 15:12:15 -08006927 updateA11yVolumeAlias(accessibilityManager.isAccessibilityVolumeStreamActive());
Phil Weaver26d709f2017-04-20 17:19:14 -07006928 accessibilityManager.addTouchExplorationStateChangeListener(this, null);
6929 accessibilityManager.addAccessibilityServicesStateChangeListener(this, null);
Jean-Michel Triviac487672016-11-11 10:05:18 -08006930 }
6931
6932 //---------------------------------------------------------------------------------
6933 // A11y: taking touch exploration into account for selecting the default
Jean-Michel Trivi873cc452014-09-11 17:25:09 -07006934 // stream override timeout when adjusting volume
Jean-Michel Triviac487672016-11-11 10:05:18 -08006935 //---------------------------------------------------------------------------------
Jean-Michel Trivi873cc452014-09-11 17:25:09 -07006936
Jean-Michel Triviac487672016-11-11 10:05:18 -08006937 // - STREAM_NOTIFICATION on tablets during this period after a notification stopped
Julia Reynoldsd9e96e22017-11-07 10:33:08 -05006938 // - STREAM_RING on phones during this period after a notification stopped
6939 // - STREAM_MUSIC otherwise
6940
Jean-Michel Triviac487672016-11-11 10:05:18 -08006941 private static final int DEFAULT_STREAM_TYPE_OVERRIDE_DELAY_MS = 0;
6942 private static final int TOUCH_EXPLORE_STREAM_TYPE_OVERRIDE_DELAY_MS = 1000;
Jean-Michel Trivi873cc452014-09-11 17:25:09 -07006943
Jean-Michel Triviac487672016-11-11 10:05:18 -08006944 private static int sStreamOverrideDelayMs;
Jean-Michel Trivi873cc452014-09-11 17:25:09 -07006945
Jean-Michel Triviac487672016-11-11 10:05:18 -08006946 @Override
6947 public void onTouchExplorationStateChanged(boolean enabled) {
6948 updateDefaultStreamOverrideDelay(enabled);
6949 }
6950
6951 private void updateDefaultStreamOverrideDelay(boolean touchExploreEnabled) {
6952 if (touchExploreEnabled) {
6953 sStreamOverrideDelayMs = TOUCH_EXPLORE_STREAM_TYPE_OVERRIDE_DELAY_MS;
6954 } else {
6955 sStreamOverrideDelayMs = DEFAULT_STREAM_TYPE_OVERRIDE_DELAY_MS;
Jean-Michel Trivi873cc452014-09-11 17:25:09 -07006956 }
Jean-Michel Triviac487672016-11-11 10:05:18 -08006957 if (DEBUG_VOL) Log.d(TAG, "Touch exploration enabled=" + touchExploreEnabled
6958 + " stream override delay is now " + sStreamOverrideDelayMs + " ms");
6959 }
Jean-Michel Trivi873cc452014-09-11 17:25:09 -07006960
Jean-Michel Triviac487672016-11-11 10:05:18 -08006961 //---------------------------------------------------------------------------------
6962 // A11y: taking a11y state into account for the handling of a11y prompts volume
6963 //---------------------------------------------------------------------------------
Jean-Michel Trivi873cc452014-09-11 17:25:09 -07006964
Jean-Michel Triviac487672016-11-11 10:05:18 -08006965 private static boolean sIndependentA11yVolume = false;
6966
Jean-Michel Trivicfa55532017-01-18 11:17:51 -08006967 // implementation of AccessibilityServicesStateChangeListener
6968 @Override
Phil Weaver4cab9302017-03-30 15:27:39 -07006969 public void onAccessibilityServicesStateChanged(AccessibilityManager accessibilityManager) {
Jean-Michel Trivicfa55532017-01-18 11:17:51 -08006970 updateA11yVolumeAlias(accessibilityManager.isAccessibilityVolumeStreamActive());
6971 }
6972
6973 private void updateA11yVolumeAlias(boolean a11VolEnabled) {
6974 if (DEBUG_VOL) Log.d(TAG, "Accessibility volume enabled = " + a11VolEnabled);
6975 if (sIndependentA11yVolume != a11VolEnabled) {
6976 sIndependentA11yVolume = a11VolEnabled;
6977 // update the volume mapping scheme
6978 updateStreamVolumeAlias(true /*updateVolumes*/, TAG);
6979 // update the volume controller behavior
6980 mVolumeController.setA11yMode(sIndependentA11yVolume ?
6981 VolumePolicy.A11Y_MODE_INDEPENDENT_A11Y_VOLUME :
6982 VolumePolicy.A11Y_MODE_MEDIA_A11Y_VOLUME);
Jean-Michel Trivia53b7052017-04-12 18:27:01 -07006983 mVolumeController.postVolumeChanged(AudioManager.STREAM_ACCESSIBILITY, 0);
Jean-Michel Trivicfa55532017-01-18 11:17:51 -08006984 }
Jean-Michel Trivi873cc452014-09-11 17:25:09 -07006985 }
6986
6987 //==========================================================================================
Eric Laurentdd45d012012-10-08 09:04:34 -07006988 // Camera shutter sound policy.
6989 // config_camera_sound_forced configuration option in config.xml defines if the camera shutter
6990 // sound is forced (sound even if the device is in silent mode) or not. This option is false by
6991 // default and can be overridden by country specific overlay in values-mccXXX/config.xml.
6992 //==========================================================================================
6993
6994 // cached value of com.android.internal.R.bool.config_camera_sound_forced
Jean-Michel Trivi8719a1d2017-11-06 11:52:51 -08006995 @GuardedBy("mSettingsLock")
6996 private boolean mCameraSoundForced;
Eric Laurentdd45d012012-10-08 09:04:34 -07006997
6998 // called by android.hardware.Camera to populate CameraInfo.canDisableShutterSound
6999 public boolean isCameraSoundForced() {
Jean-Michel Trivi8719a1d2017-11-06 11:52:51 -08007000 synchronized (mSettingsLock) {
Eric Laurentdd45d012012-10-08 09:04:34 -07007001 return mCameraSoundForced;
7002 }
7003 }
7004
Jean-Michel Trivi011f39e2017-08-19 18:08:06 -07007005 //==========================================================================================
7006 // AudioService logging and dumpsys
7007 //==========================================================================================
7008 final int LOG_NB_EVENTS_PHONE_STATE = 20;
7009 final int LOG_NB_EVENTS_WIRED_DEV_CONNECTION = 30;
7010 final int LOG_NB_EVENTS_FORCE_USE = 20;
Jean-Michel Trivicf170362017-08-24 17:24:57 -07007011 final int LOG_NB_EVENTS_VOLUME = 40;
Jean-Michel Trivi011f39e2017-08-19 18:08:06 -07007012
7013 final private AudioEventLogger mModeLogger = new AudioEventLogger(LOG_NB_EVENTS_PHONE_STATE,
7014 "phone state (logged after successfull call to AudioSystem.setPhoneState(int))");
7015
7016 final private AudioEventLogger mWiredDevLogger = new AudioEventLogger(
7017 LOG_NB_EVENTS_WIRED_DEV_CONNECTION,
7018 "wired device connection (logged before onSetWiredDeviceConnectionState() is executed)"
7019 );
7020
7021 final private AudioEventLogger mForceUseLogger = new AudioEventLogger(
7022 LOG_NB_EVENTS_FORCE_USE,
7023 "force use (logged before setForceUse() is executed)");
7024
Jean-Michel Trivicf170362017-08-24 17:24:57 -07007025 final private AudioEventLogger mVolumeLogger = new AudioEventLogger(LOG_NB_EVENTS_VOLUME,
7026 "volume changes (logged when command received by AudioService)");
7027
Eric Laurentdd45d012012-10-08 09:04:34 -07007028 private static final String[] RINGER_MODE_NAMES = new String[] {
7029 "SILENT",
7030 "VIBRATE",
7031 "NORMAL"
7032 };
7033
7034 private void dumpRingerMode(PrintWriter pw) {
7035 pw.println("\nRinger mode: ");
John Spurlock661f2cf2014-11-17 10:29:10 -05007036 pw.println("- mode (internal) = " + RINGER_MODE_NAMES[mRingerMode]);
7037 pw.println("- mode (external) = " + RINGER_MODE_NAMES[mRingerModeExternal]);
John Spurlock50ced3f2015-05-11 16:00:09 -04007038 dumpRingerModeStreams(pw, "affected", mRingerModeAffectedStreams);
Beverlyd6964762018-02-16 14:07:03 -05007039 dumpRingerModeStreams(pw, "muted", mRingerAndZenModeMutedStreams);
John Spurlock661f2cf2014-11-17 10:29:10 -05007040 pw.print("- delegate = "); pw.println(mRingerModeDelegate);
Eric Laurentdd45d012012-10-08 09:04:34 -07007041 }
7042
John Spurlock50ced3f2015-05-11 16:00:09 -04007043 private void dumpRingerModeStreams(PrintWriter pw, String type, int streams) {
7044 pw.print("- ringer mode "); pw.print(type); pw.print(" streams = 0x");
7045 pw.print(Integer.toHexString(streams));
7046 if (streams != 0) {
7047 pw.print(" (");
7048 boolean first = true;
7049 for (int i = 0; i < AudioSystem.STREAM_NAMES.length; i++) {
7050 final int stream = (1 << i);
7051 if ((streams & stream) != 0) {
7052 if (!first) pw.print(',');
7053 pw.print(AudioSystem.STREAM_NAMES[i]);
7054 streams &= ~stream;
7055 first = false;
7056 }
7057 }
7058 if (streams != 0) {
7059 if (!first) pw.print(',');
7060 pw.print(streams);
7061 }
7062 pw.print(')');
7063 }
7064 pw.println();
7065 }
7066
Dianne Hackborn632ca412012-06-14 19:34:10 -07007067 @Override
Jean-Michel Trivid5176cf2010-01-28 11:56:42 -08007068 protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
Jeff Sharkeyfe9a53b2017-03-31 14:08:23 -06007069 if (!DumpUtils.checkDumpPermission(mContext, TAG, pw)) return;
Jeff Sharkeyeb4cc4922012-04-26 18:17:29 -07007070
Jean-Michel Trivifa9a6982013-06-27 16:22:58 -07007071 mMediaFocusControl.dump(pw);
Eric Laurentbffc3d12012-05-07 17:43:49 -07007072 dumpStreamStates(pw);
Eric Laurentdd45d012012-10-08 09:04:34 -07007073 dumpRingerMode(pw);
Dianne Hackborn632ca412012-06-14 19:34:10 -07007074 pw.println("\nAudio routes:");
John Spurlock61560172015-02-06 19:46:04 -05007075 pw.print(" mMainType=0x"); pw.println(Integer.toHexString(mCurAudioRoutes.mainType));
7076 pw.print(" mBluetoothName="); pw.println(mCurAudioRoutes.bluetoothName);
John Spurlock35134602014-07-24 18:10:48 -04007077
7078 pw.println("\nOther state:");
John Spurlock3346a802014-05-20 16:25:37 -04007079 pw.print(" mVolumeController="); pw.println(mVolumeController);
John Spurlock35134602014-07-24 18:10:48 -04007080 pw.print(" mSafeMediaVolumeState=");
7081 pw.println(safeMediaVolumeStateToString(mSafeMediaVolumeState));
7082 pw.print(" mSafeMediaVolumeIndex="); pw.println(mSafeMediaVolumeIndex);
Eric Laurenteab40d12017-06-09 12:45:21 -07007083 pw.print(" mSafeUsbMediaVolumeIndex="); pw.println(mSafeUsbMediaVolumeIndex);
John Muir8b8bddd2018-02-16 14:29:14 -08007084 pw.print(" mSafeUsbMediaVolumeDbfs="); pw.println(mSafeUsbMediaVolumeDbfs);
Jean-Michel Trivi7592b982017-02-01 15:12:15 -08007085 pw.print(" sIndependentA11yVolume="); pw.println(sIndependentA11yVolume);
John Spurlock35134602014-07-24 18:10:48 -04007086 pw.print(" mPendingVolumeCommand="); pw.println(mPendingVolumeCommand);
7087 pw.print(" mMusicActiveMs="); pw.println(mMusicActiveMs);
John Spurlockaa5ee4d2014-07-25 13:05:12 -04007088 pw.print(" mMcc="); pw.println(mMcc);
John Spurlock5e783732015-02-19 10:28:59 -05007089 pw.print(" mCameraSoundForced="); pw.println(mCameraSoundForced);
John Spurlock661f2cf2014-11-17 10:29:10 -05007090 pw.print(" mHasVibrator="); pw.println(mHasVibrator);
John Spurlocka48d7792015-03-03 17:35:57 -05007091 pw.print(" mVolumePolicy="); pw.println(mVolumePolicy);
Jean-Michel Trivi1ab43f62017-04-27 15:37:34 -07007092 pw.print(" mAvrcpAbsVolSupported="); pw.println(mAvrcpAbsVolSupported);
Jean-Michel Trivi1b3541d2014-11-25 12:53:41 -08007093
7094 dumpAudioPolicies(pw);
Jean-Michel Trivi292a6a42016-12-01 08:32:15 -08007095
7096 mPlaybackMonitor.dump(pw);
Jean-Michel Trivi66ffacf2017-02-04 17:25:31 -08007097
7098 mRecordMonitor.dump(pw);
Jean-Michel Trivi011f39e2017-08-19 18:08:06 -07007099
Jean-Michel Trivicf170362017-08-24 17:24:57 -07007100 pw.println("\n");
Jean-Michel Trivi011f39e2017-08-19 18:08:06 -07007101 pw.println("\nEvent logs:");
7102 mModeLogger.dump(pw);
7103 pw.println("\n");
7104 mWiredDevLogger.dump(pw);
7105 pw.println("\n");
7106 mForceUseLogger.dump(pw);
Jean-Michel Trivicf170362017-08-24 17:24:57 -07007107 pw.println("\n");
7108 mVolumeLogger.dump(pw);
John Spurlock35134602014-07-24 18:10:48 -04007109 }
7110
7111 private static String safeMediaVolumeStateToString(Integer state) {
7112 switch(state) {
7113 case SAFE_MEDIA_VOLUME_NOT_CONFIGURED: return "SAFE_MEDIA_VOLUME_NOT_CONFIGURED";
7114 case SAFE_MEDIA_VOLUME_DISABLED: return "SAFE_MEDIA_VOLUME_DISABLED";
7115 case SAFE_MEDIA_VOLUME_INACTIVE: return "SAFE_MEDIA_VOLUME_INACTIVE";
7116 case SAFE_MEDIA_VOLUME_ACTIVE: return "SAFE_MEDIA_VOLUME_ACTIVE";
7117 }
7118 return null;
Jean-Michel Trivid5176cf2010-01-28 11:56:42 -08007119 }
Glenn Kastenfd116ad2013-07-12 17:10:39 -07007120
7121 // Inform AudioFlinger of our device's low RAM attribute
7122 private static void readAndSetLowRamDevice()
7123 {
Andy Hung79583582018-01-23 13:58:02 -08007124 boolean isLowRamDevice = ActivityManager.isLowRamDeviceStatic();
7125 long totalMemory = 1024 * 1024 * 1024; // 1GB is the default if ActivityManager fails.
7126
7127 try {
7128 final ActivityManager.MemoryInfo info = new ActivityManager.MemoryInfo();
7129 ActivityManager.getService().getMemoryInfo(info);
7130 totalMemory = info.totalMem;
7131 } catch (RemoteException e) {
7132 Log.w(TAG, "Cannot obtain MemoryInfo from ActivityManager, assume low memory device");
7133 isLowRamDevice = true;
7134 }
7135
7136 final int status = AudioSystem.setLowRamDevice(isLowRamDevice, totalMemory);
Glenn Kastenfd116ad2013-07-12 17:10:39 -07007137 if (status != 0) {
7138 Log.w(TAG, "AudioFlinger informed of device's low RAM attribute; status " + status);
7139 }
7140 }
John Spurlock3346a802014-05-20 16:25:37 -04007141
John Spurlockcdb57ae2015-02-11 19:04:11 -05007142 private void enforceVolumeController(String action) {
John Spurlock3346a802014-05-20 16:25:37 -04007143 mContext.enforceCallingOrSelfPermission(android.Manifest.permission.STATUS_BAR_SERVICE,
7144 "Only SystemUI can " + action);
7145 }
7146
7147 @Override
7148 public void setVolumeController(final IVolumeController controller) {
John Spurlockcdb57ae2015-02-11 19:04:11 -05007149 enforceVolumeController("set the volume controller");
John Spurlock3346a802014-05-20 16:25:37 -04007150
7151 // return early if things are not actually changing
7152 if (mVolumeController.isSameBinder(controller)) {
7153 return;
7154 }
7155
7156 // dismiss the old volume controller
7157 mVolumeController.postDismiss();
7158 if (controller != null) {
7159 // we are about to register a new controller, listen for its death
7160 try {
7161 controller.asBinder().linkToDeath(new DeathRecipient() {
7162 @Override
7163 public void binderDied() {
7164 if (mVolumeController.isSameBinder(controller)) {
7165 Log.w(TAG, "Current remote volume controller died, unregistering");
7166 setVolumeController(null);
7167 }
7168 }
7169 }, 0);
7170 } catch (RemoteException e) {
7171 // noop
7172 }
7173 }
7174 mVolumeController.setController(controller);
John Spurlock33f4e042014-07-11 13:10:58 -04007175 if (DEBUG_VOL) Log.d(TAG, "Volume controller: " + mVolumeController);
7176 }
7177
7178 @Override
7179 public void notifyVolumeControllerVisible(final IVolumeController controller, boolean visible) {
John Spurlockcdb57ae2015-02-11 19:04:11 -05007180 enforceVolumeController("notify about volume controller visibility");
John Spurlock33f4e042014-07-11 13:10:58 -04007181
7182 // return early if the controller is not current
7183 if (!mVolumeController.isSameBinder(controller)) {
7184 return;
7185 }
7186
7187 mVolumeController.setVisible(visible);
7188 if (DEBUG_VOL) Log.d(TAG, "Volume controller visible: " + visible);
John Spurlock3346a802014-05-20 16:25:37 -04007189 }
RoboErikd09bd0c2014-06-24 17:45:19 -07007190
John Spurlocka48d7792015-03-03 17:35:57 -05007191 @Override
7192 public void setVolumePolicy(VolumePolicy policy) {
7193 enforceVolumeController("set volume policy");
John Spurlockb02c7442015-04-14 09:32:25 -04007194 if (policy != null && !policy.equals(mVolumePolicy)) {
John Spurlocka48d7792015-03-03 17:35:57 -05007195 mVolumePolicy = policy;
John Spurlockb02c7442015-04-14 09:32:25 -04007196 if (DEBUG_VOL) Log.d(TAG, "Volume policy changed: " + mVolumePolicy);
John Spurlocka48d7792015-03-03 17:35:57 -05007197 }
7198 }
7199
RoboErikd09bd0c2014-06-24 17:45:19 -07007200 public static class VolumeController {
7201 private static final String TAG = "VolumeController";
7202
7203 private IVolumeController mController;
John Spurlock33f4e042014-07-11 13:10:58 -04007204 private boolean mVisible;
7205 private long mNextLongPress;
7206 private int mLongPressTimeout;
RoboErikd09bd0c2014-06-24 17:45:19 -07007207
7208 public void setController(IVolumeController controller) {
7209 mController = controller;
John Spurlock33f4e042014-07-11 13:10:58 -04007210 mVisible = false;
7211 }
7212
7213 public void loadSettings(ContentResolver cr) {
7214 mLongPressTimeout = Settings.Secure.getIntForUser(cr,
7215 Settings.Secure.LONG_PRESS_TIMEOUT, 500, UserHandle.USER_CURRENT);
7216 }
7217
RoboErik4197cb62015-01-21 15:45:32 -08007218 public boolean suppressAdjustment(int resolvedStream, int flags, boolean isMute) {
7219 if (isMute) {
7220 return false;
7221 }
John Spurlock33f4e042014-07-11 13:10:58 -04007222 boolean suppress = false;
7223 if (resolvedStream == AudioSystem.STREAM_RING && mController != null) {
7224 final long now = SystemClock.uptimeMillis();
7225 if ((flags & AudioManager.FLAG_SHOW_UI) != 0 && !mVisible) {
7226 // ui will become visible
7227 if (mNextLongPress < now) {
7228 mNextLongPress = now + mLongPressTimeout;
7229 }
7230 suppress = true;
7231 } else if (mNextLongPress > 0) { // in a long-press
7232 if (now > mNextLongPress) {
7233 // long press triggered, no more suppression
7234 mNextLongPress = 0;
7235 } else {
7236 // keep suppressing until the long press triggers
7237 suppress = true;
7238 }
7239 }
7240 }
7241 return suppress;
7242 }
7243
7244 public void setVisible(boolean visible) {
7245 mVisible = visible;
RoboErikd09bd0c2014-06-24 17:45:19 -07007246 }
7247
7248 public boolean isSameBinder(IVolumeController controller) {
7249 return Objects.equals(asBinder(), binder(controller));
7250 }
7251
7252 public IBinder asBinder() {
7253 return binder(mController);
7254 }
7255
7256 private static IBinder binder(IVolumeController controller) {
7257 return controller == null ? null : controller.asBinder();
7258 }
7259
7260 @Override
7261 public String toString() {
John Spurlock33f4e042014-07-11 13:10:58 -04007262 return "VolumeController(" + asBinder() + ",mVisible=" + mVisible + ")";
RoboErikd09bd0c2014-06-24 17:45:19 -07007263 }
7264
7265 public void postDisplaySafeVolumeWarning(int flags) {
7266 if (mController == null)
7267 return;
7268 try {
7269 mController.displaySafeVolumeWarning(flags);
7270 } catch (RemoteException e) {
7271 Log.w(TAG, "Error calling displaySafeVolumeWarning", e);
7272 }
7273 }
7274
7275 public void postVolumeChanged(int streamType, int flags) {
7276 if (mController == null)
7277 return;
7278 try {
7279 mController.volumeChanged(streamType, flags);
7280 } catch (RemoteException e) {
7281 Log.w(TAG, "Error calling volumeChanged", e);
7282 }
7283 }
7284
RoboErikd09bd0c2014-06-24 17:45:19 -07007285 public void postMasterMuteChanged(int flags) {
7286 if (mController == null)
7287 return;
7288 try {
7289 mController.masterMuteChanged(flags);
7290 } catch (RemoteException e) {
7291 Log.w(TAG, "Error calling masterMuteChanged", e);
7292 }
7293 }
7294
7295 public void setLayoutDirection(int layoutDirection) {
7296 if (mController == null)
7297 return;
7298 try {
7299 mController.setLayoutDirection(layoutDirection);
7300 } catch (RemoteException e) {
7301 Log.w(TAG, "Error calling setLayoutDirection", e);
7302 }
7303 }
7304
7305 public void postDismiss() {
7306 if (mController == null)
7307 return;
7308 try {
7309 mController.dismiss();
7310 } catch (RemoteException e) {
7311 Log.w(TAG, "Error calling dismiss", e);
7312 }
7313 }
Jean-Michel Triviac487672016-11-11 10:05:18 -08007314
7315 public void setA11yMode(int a11yMode) {
7316 if (mController == null)
7317 return;
7318 try {
7319 mController.setA11yMode(a11yMode);
7320 } catch (RemoteException e) {
7321 Log.w(TAG, "Error calling setA11Mode", e);
7322 }
7323 }
RoboErikd09bd0c2014-06-24 17:45:19 -07007324 }
Jean-Michel Trivia8b6bd82014-07-01 09:48:46 -07007325
RoboErik0dac35a2014-08-12 15:48:49 -07007326 /**
7327 * Interface for system components to get some extra functionality through
7328 * LocalServices.
7329 */
7330 final class AudioServiceInternal extends AudioManagerInternal {
John Spurlock661f2cf2014-11-17 10:29:10 -05007331 @Override
7332 public void setRingerModeDelegate(RingerModeDelegate delegate) {
7333 mRingerModeDelegate = delegate;
7334 if (mRingerModeDelegate != null) {
Jean-Michel Trivi8719a1d2017-11-06 11:52:51 -08007335 synchronized (mSettingsLock) {
Beverlyd6964762018-02-16 14:07:03 -05007336 updateRingerAndZenModeAffectedStreams();
Jean-Michel Trivi8719a1d2017-11-06 11:52:51 -08007337 }
John Spurlock661f2cf2014-11-17 10:29:10 -05007338 setRingerModeInternal(getRingerModeInternal(), TAG + ".setRingerModeDelegate");
7339 }
7340 }
RoboErik272e1612014-09-05 11:39:29 -07007341
7342 @Override
7343 public void adjustSuggestedStreamVolumeForUid(int streamType, int direction, int flags,
7344 String callingPackage, int uid) {
7345 // direction and stream type swap here because the public
7346 // adjustSuggested has a different order than the other methods.
John Spurlock90874332015-03-10 16:00:54 -04007347 adjustSuggestedStreamVolume(direction, streamType, flags, callingPackage,
7348 callingPackage, uid);
RoboErik272e1612014-09-05 11:39:29 -07007349 }
7350
RoboErik0dac35a2014-08-12 15:48:49 -07007351 @Override
7352 public void adjustStreamVolumeForUid(int streamType, int direction, int flags,
7353 String callingPackage, int uid) {
John Spurlock90874332015-03-10 16:00:54 -04007354 adjustStreamVolume(streamType, direction, flags, callingPackage,
7355 callingPackage, uid);
RoboErik0dac35a2014-08-12 15:48:49 -07007356 }
7357
7358 @Override
7359 public void setStreamVolumeForUid(int streamType, int direction, int flags,
7360 String callingPackage, int uid) {
John Spurlock90874332015-03-10 16:00:54 -04007361 setStreamVolume(streamType, direction, flags, callingPackage, callingPackage, uid);
RoboErik0dac35a2014-08-12 15:48:49 -07007362 }
RoboErik519c7742014-11-18 10:59:09 -08007363
7364 @Override
John Spurlock661f2cf2014-11-17 10:29:10 -05007365 public int getRingerModeInternal() {
7366 return AudioService.this.getRingerModeInternal();
7367 }
7368
7369 @Override
7370 public void setRingerModeInternal(int ringerMode, String caller) {
7371 AudioService.this.setRingerModeInternal(ringerMode, caller);
7372 }
John Spurlockcdb57ae2015-02-11 19:04:11 -05007373
7374 @Override
Mike Digman55272862018-02-20 14:35:17 -08007375 public void silenceRingerModeInternal(String caller) {
7376 AudioService.this.silenceRingerModeInternal(caller);
7377 }
7378
7379 @Override
John Spurlock50ced3f2015-05-11 16:00:09 -04007380 public void updateRingerModeAffectedStreamsInternal() {
7381 synchronized (mSettingsLock) {
Beverlyd6964762018-02-16 14:07:03 -05007382 if (updateRingerAndZenModeAffectedStreams()) {
John Spurlock50ced3f2015-05-11 16:00:09 -04007383 setRingerModeInt(getRingerModeInternal(), false);
7384 }
7385 }
7386 }
Phil Weaverf1a9aff2017-03-23 17:21:29 -07007387
7388 @Override
7389 public void setAccessibilityServiceUids(IntArray uids) {
7390 synchronized (mAccessibilityServiceUidsLock) {
7391 if (uids.size() == 0) {
7392 mAccessibilityServiceUids = null;
7393 } else {
7394 boolean changed = (mAccessibilityServiceUids == null)
7395 || (mAccessibilityServiceUids.length != uids.size());
7396 if (!changed) {
7397 for (int i = 0; i < mAccessibilityServiceUids.length; i++) {
7398 if (uids.get(i) != mAccessibilityServiceUids[i]) {
7399 changed = true;
7400 break;
7401 }
7402 }
7403 }
7404 if (changed) {
7405 mAccessibilityServiceUids = uids.toArray();
7406 }
7407 }
7408 }
7409 }
RoboErik0dac35a2014-08-12 15:48:49 -07007410 }
7411
Jean-Michel Trivia8b6bd82014-07-01 09:48:46 -07007412 //==========================================================================================
7413 // Audio policy management
7414 //==========================================================================================
Jean-Michel Trivi0212be52014-11-24 14:43:10 -08007415 public String registerAudioPolicy(AudioPolicyConfig policyConfig, IAudioPolicyCallback pcb,
Jean-Michel Trivi610aa9b2018-01-27 15:42:42 -08007416 boolean hasFocusListener, boolean isFocusPolicy, boolean isVolumeController) {
Jean-Michel Trivi5a561092015-04-23 18:48:08 -07007417 AudioSystem.setDynamicPolicyCallback(mDynPolicyCallback);
7418
Jean-Michel Trivi0212be52014-11-24 14:43:10 -08007419 if (DEBUG_AP) Log.d(TAG, "registerAudioPolicy for " + pcb.asBinder()
7420 + " with config:" + policyConfig);
Jean-Michel Trivi8fdb0d42014-07-16 19:08:37 -07007421 String regId = null;
Jean-Michel Trivi0212be52014-11-24 14:43:10 -08007422 // error handling
Jean-Michel Trivia8b6bd82014-07-01 09:48:46 -07007423 boolean hasPermissionForPolicy =
Jean-Michel Trivi0212be52014-11-24 14:43:10 -08007424 (PackageManager.PERMISSION_GRANTED == mContext.checkCallingPermission(
Jean-Michel Trivia8b6bd82014-07-01 09:48:46 -07007425 android.Manifest.permission.MODIFY_AUDIO_ROUTING));
7426 if (!hasPermissionForPolicy) {
7427 Slog.w(TAG, "Can't register audio policy for pid " + Binder.getCallingPid() + " / uid "
7428 + Binder.getCallingUid() + ", need MODIFY_AUDIO_ROUTING");
Jean-Michel Trivi8fdb0d42014-07-16 19:08:37 -07007429 return null;
Jean-Michel Trivia8b6bd82014-07-01 09:48:46 -07007430 }
Jean-Michel Trivi0212be52014-11-24 14:43:10 -08007431
Jean-Michel Trivia8b6bd82014-07-01 09:48:46 -07007432 synchronized (mAudioPolicies) {
Jean-Michel Trivia8b6bd82014-07-01 09:48:46 -07007433 try {
Jean-Michel Trivi0212be52014-11-24 14:43:10 -08007434 if (mAudioPolicies.containsKey(pcb.asBinder())) {
Jean-Michel Trivi1b3541d2014-11-25 12:53:41 -08007435 Slog.e(TAG, "Cannot re-register policy");
7436 return null;
7437 }
Jean-Michel Trivi126cf032017-04-02 23:19:02 -07007438 AudioPolicyProxy app = new AudioPolicyProxy(policyConfig, pcb, hasFocusListener,
Jean-Michel Trivi610aa9b2018-01-27 15:42:42 -08007439 isFocusPolicy, isVolumeController);
Jean-Michel Trivi0212be52014-11-24 14:43:10 -08007440 pcb.asBinder().linkToDeath(app, 0/*flags*/);
7441 regId = app.getRegistrationId();
7442 mAudioPolicies.put(pcb.asBinder(), app);
Jean-Michel Trivia8b6bd82014-07-01 09:48:46 -07007443 } catch (RemoteException e) {
7444 // audio policy owner has already died!
Jean-Michel Trivi0212be52014-11-24 14:43:10 -08007445 Slog.w(TAG, "Audio policy registration failed, could not link to " + pcb +
Jean-Michel Trivia8b6bd82014-07-01 09:48:46 -07007446 " binder death", e);
Jean-Michel Trivi8fdb0d42014-07-16 19:08:37 -07007447 return null;
Jean-Michel Trivia8b6bd82014-07-01 09:48:46 -07007448 }
7449 }
Jean-Michel Trivi8fdb0d42014-07-16 19:08:37 -07007450 return regId;
Jean-Michel Trivia8b6bd82014-07-01 09:48:46 -07007451 }
Jean-Michel Trivi8fdb0d42014-07-16 19:08:37 -07007452
Jean-Michel Trivi0212be52014-11-24 14:43:10 -08007453 public void unregisterAudioPolicyAsync(IAudioPolicyCallback pcb) {
7454 if (DEBUG_AP) Log.d(TAG, "unregisterAudioPolicyAsync for " + pcb.asBinder());
Jean-Michel Trivia8b6bd82014-07-01 09:48:46 -07007455 synchronized (mAudioPolicies) {
Jean-Michel Trivi0212be52014-11-24 14:43:10 -08007456 AudioPolicyProxy app = mAudioPolicies.remove(pcb.asBinder());
Jean-Michel Trivia8b6bd82014-07-01 09:48:46 -07007457 if (app == null) {
7458 Slog.w(TAG, "Trying to unregister unknown audio policy for pid "
7459 + Binder.getCallingPid() + " / uid " + Binder.getCallingUid());
Jean-Michel Trivi1b3541d2014-11-25 12:53:41 -08007460 return;
Jean-Michel Trivia8b6bd82014-07-01 09:48:46 -07007461 } else {
Jean-Michel Trivi0212be52014-11-24 14:43:10 -08007462 pcb.asBinder().unlinkToDeath(app, 0/*flags*/);
Jean-Michel Trivia8b6bd82014-07-01 09:48:46 -07007463 }
Jean-Michel Trivi0212be52014-11-24 14:43:10 -08007464 app.release();
Jean-Michel Trivia8b6bd82014-07-01 09:48:46 -07007465 }
Jean-Michel Trivi8fdb0d42014-07-16 19:08:37 -07007466 // TODO implement clearing mix attribute matching info in native audio policy
Jean-Michel Trivia8b6bd82014-07-01 09:48:46 -07007467 }
7468
Jean-Michel Triviaf576a02018-02-14 08:57:46 -08007469 /**
7470 * Checks whether caller has MODIFY_AUDIO_ROUTING permission, and the policy is registered.
7471 * @param errorMsg log warning if permission check failed.
7472 * @return null if the operation on the audio mixes should be cancelled.
7473 */
7474 @GuardedBy("mAudioPolicies")
7475 private AudioPolicyProxy checkUpdateForPolicy(IAudioPolicyCallback pcb, String errorMsg) {
7476 // permission check
7477 final boolean hasPermissionForPolicy =
Jean-Michel Trivi0212be52014-11-24 14:43:10 -08007478 (PackageManager.PERMISSION_GRANTED == mContext.checkCallingPermission(
7479 android.Manifest.permission.MODIFY_AUDIO_ROUTING));
7480 if (!hasPermissionForPolicy) {
Jean-Michel Triviaf576a02018-02-14 08:57:46 -08007481 Slog.w(TAG, errorMsg + " for pid " +
Jean-Michel Trivi0212be52014-11-24 14:43:10 -08007482 + Binder.getCallingPid() + " / uid "
7483 + Binder.getCallingUid() + ", need MODIFY_AUDIO_ROUTING");
Jean-Michel Triviaf576a02018-02-14 08:57:46 -08007484 return null;
Jean-Michel Trivi0212be52014-11-24 14:43:10 -08007485 }
Jean-Michel Triviaf576a02018-02-14 08:57:46 -08007486 // policy registered?
7487 final AudioPolicyProxy app = mAudioPolicies.get(pcb.asBinder());
7488 if (app == null) {
7489 Slog.w(TAG, errorMsg + " for pid " +
7490 + Binder.getCallingPid() + " / uid "
7491 + Binder.getCallingUid() + ", unregistered policy");
7492 return null;
7493 }
7494 return app;
7495 }
Jean-Michel Trivi0212be52014-11-24 14:43:10 -08007496
Jean-Michel Triviaf576a02018-02-14 08:57:46 -08007497 public int addMixForPolicy(AudioPolicyConfig policyConfig, IAudioPolicyCallback pcb) {
7498 if (DEBUG_AP) { Log.d(TAG, "addMixForPolicy for " + pcb.asBinder()
7499 + " with config:" + policyConfig); }
Jean-Michel Trivi0212be52014-11-24 14:43:10 -08007500 synchronized (mAudioPolicies) {
Jean-Michel Triviaf576a02018-02-14 08:57:46 -08007501 final AudioPolicyProxy app =
7502 checkUpdateForPolicy(pcb, "Cannot add AudioMix in audio policy");
7503 if (app == null){
7504 return AudioManager.ERROR;
7505 }
7506 app.addMixes(policyConfig.getMixes());
7507 }
7508 return AudioManager.SUCCESS;
7509 }
7510
7511 public int removeMixForPolicy(AudioPolicyConfig policyConfig, IAudioPolicyCallback pcb) {
7512 if (DEBUG_AP) { Log.d(TAG, "removeMixForPolicy for " + pcb.asBinder()
7513 + " with config:" + policyConfig); }
7514 synchronized (mAudioPolicies) {
7515 final AudioPolicyProxy app =
7516 checkUpdateForPolicy(pcb, "Cannot add AudioMix in audio policy");
7517 if (app == null) {
7518 return AudioManager.ERROR;
7519 }
7520 app.removeMixes(policyConfig.getMixes());
7521 }
7522 return AudioManager.SUCCESS;
7523 }
7524
7525 public int setFocusPropertiesForPolicy(int duckingBehavior, IAudioPolicyCallback pcb) {
7526 if (DEBUG_AP) Log.d(TAG, "setFocusPropertiesForPolicy() duck behavior=" + duckingBehavior
7527 + " policy " + pcb.asBinder());
7528 synchronized (mAudioPolicies) {
7529 final AudioPolicyProxy app =
7530 checkUpdateForPolicy(pcb, "Cannot change audio policy focus properties");
7531 if (app == null){
7532 return AudioManager.ERROR;
7533 }
Jean-Michel Trivi0212be52014-11-24 14:43:10 -08007534 if (!mAudioPolicies.containsKey(pcb.asBinder())) {
7535 Slog.e(TAG, "Cannot change audio policy focus properties, unregistered policy");
7536 return AudioManager.ERROR;
7537 }
Jean-Michel Trivi0212be52014-11-24 14:43:10 -08007538 if (duckingBehavior == AudioPolicy.FOCUS_POLICY_DUCKING_IN_POLICY) {
7539 // is there already one policy managing ducking?
Eric Laurent0867bed2015-05-20 14:49:08 -07007540 for (AudioPolicyProxy policy : mAudioPolicies.values()) {
Jean-Michel Trivi0212be52014-11-24 14:43:10 -08007541 if (policy.mFocusDuckBehavior == AudioPolicy.FOCUS_POLICY_DUCKING_IN_POLICY) {
7542 Slog.e(TAG, "Cannot change audio policy ducking behavior, already handled");
7543 return AudioManager.ERROR;
7544 }
7545 }
7546 }
7547 app.mFocusDuckBehavior = duckingBehavior;
7548 mMediaFocusControl.setDuckingInExtPolicyAvailable(
7549 duckingBehavior == AudioPolicy.FOCUS_POLICY_DUCKING_IN_POLICY);
7550 }
7551 return AudioManager.SUCCESS;
7552 }
7553
Jean-Michel Trivi610aa9b2018-01-27 15:42:42 -08007554 private final Object mExtVolumeControllerLock = new Object();
7555 private IAudioPolicyCallback mExtVolumeController;
7556 private void setExtVolumeController(IAudioPolicyCallback apc) {
7557 if (!mContext.getResources().getBoolean(
7558 com.android.internal.R.bool.config_handleVolumeKeysInWindowManager)) {
7559 Log.e(TAG, "Cannot set external volume controller: device not set for volume keys" +
7560 " handled in PhoneWindowManager");
7561 return;
7562 }
7563 synchronized (mExtVolumeControllerLock) {
7564 if (mExtVolumeController != null && !mExtVolumeController.asBinder().pingBinder()) {
7565 Log.e(TAG, "Cannot set external volume controller: existing controller");
7566 }
7567 mExtVolumeController = apc;
7568 }
7569 }
7570
Jean-Michel Trivi1b3541d2014-11-25 12:53:41 -08007571 private void dumpAudioPolicies(PrintWriter pw) {
7572 pw.println("\nAudio policies:");
7573 synchronized (mAudioPolicies) {
Eric Laurent0867bed2015-05-20 14:49:08 -07007574 for (AudioPolicyProxy policy : mAudioPolicies.values()) {
Jean-Michel Trivi1b3541d2014-11-25 12:53:41 -08007575 pw.println(policy.toLogFriendlyString());
7576 }
7577 }
7578 }
7579
Jean-Michel Trivi958876f2014-11-16 15:40:22 -08007580 //======================
Jean-Michel Trivid3c71f02015-12-07 11:59:31 -08007581 // Audio policy callbacks from AudioSystem for dynamic policies
Jean-Michel Trivi5a561092015-04-23 18:48:08 -07007582 //======================
7583 private final AudioSystem.DynamicPolicyCallback mDynPolicyCallback =
7584 new AudioSystem.DynamicPolicyCallback() {
7585 public void onDynamicPolicyMixStateUpdate(String regId, int state) {
7586 if (!TextUtils.isEmpty(regId)) {
7587 sendMsg(mAudioHandler, MSG_DYN_POLICY_MIX_STATE_UPDATE, SENDMSG_QUEUE,
7588 state /*arg1*/, 0 /*arg2 ignored*/, regId /*obj*/, 0 /*delay*/);
7589 }
7590 }
7591 };
7592
7593 private void onDynPolicyMixStateUpdate(String regId, int state) {
7594 if (DEBUG_AP) Log.d(TAG, "onDynamicPolicyMixStateUpdate("+ regId + ", " + state +")");
7595 synchronized (mAudioPolicies) {
7596 for (AudioPolicyProxy policy : mAudioPolicies.values()) {
7597 for (AudioMix mix : policy.getMixes()) {
7598 if (mix.getRegistration().equals(regId)) {
7599 try {
7600 policy.mPolicyCallback.notifyMixStateUpdate(regId, state);
7601 } catch (RemoteException e) {
7602 Log.e(TAG, "Can't call notifyMixStateUpdate() on IAudioPolicyCallback "
7603 + policy.mPolicyCallback.asBinder(), e);
7604 }
7605 return;
7606 }
7607 }
7608 }
7609 }
Jean-Michel Trivid3c71f02015-12-07 11:59:31 -08007610 }
Jean-Michel Trivi5a561092015-04-23 18:48:08 -07007611
Jean-Michel Trivid3c71f02015-12-07 11:59:31 -08007612 //======================
7613 // Audio policy callbacks from AudioSystem for recording configuration updates
7614 //======================
Jean-Michel Trivi66ffacf2017-02-04 17:25:31 -08007615 private final RecordingActivityMonitor mRecordMonitor;
Jean-Michel Trivid3c71f02015-12-07 11:59:31 -08007616
7617 public void registerRecordingCallback(IRecordingConfigDispatcher rcdb) {
Jean-Michel Trivi66ffacf2017-02-04 17:25:31 -08007618 final boolean isPrivileged =
7619 (PackageManager.PERMISSION_GRANTED == mContext.checkCallingPermission(
7620 android.Manifest.permission.MODIFY_AUDIO_ROUTING));
7621 mRecordMonitor.registerRecordingCallback(rcdb, isPrivileged);
Jean-Michel Trivid3c71f02015-12-07 11:59:31 -08007622 }
7623
7624 public void unregisterRecordingCallback(IRecordingConfigDispatcher rcdb) {
7625 mRecordMonitor.unregisterRecordingCallback(rcdb);
7626 }
7627
Jean-Michel Trivif04fab12016-05-19 10:42:35 -07007628 public List<AudioRecordingConfiguration> getActiveRecordingConfigurations() {
Jean-Michel Trivi66ffacf2017-02-04 17:25:31 -08007629 final boolean isPrivileged =
7630 (PackageManager.PERMISSION_GRANTED == mContext.checkCallingPermission(
7631 android.Manifest.permission.MODIFY_AUDIO_ROUTING));
7632 return mRecordMonitor.getActiveRecordingConfigurations(isPrivileged);
Jean-Michel Trivi5a561092015-04-23 18:48:08 -07007633 }
7634
Robin Lee7af9a742017-02-20 14:47:30 +00007635 public void disableRingtoneSync(final int userId) {
Andre Lago7bdc6d82016-09-22 18:00:41 +01007636 final int callingUserId = UserHandle.getCallingUserId();
Robin Lee7af9a742017-02-20 14:47:30 +00007637 if (callingUserId != userId) {
7638 mContext.enforceCallingOrSelfPermission(Manifest.permission.INTERACT_ACROSS_USERS_FULL,
7639 "disable sound settings syncing for another profile");
7640 }
Andre Lago7bdc6d82016-09-22 18:00:41 +01007641 final long token = Binder.clearCallingIdentity();
7642 try {
Robin Lee7af9a742017-02-20 14:47:30 +00007643 // Disable the sync setting so the profile uses its own sound settings.
7644 Settings.Secure.putIntForUser(mContentResolver, Settings.Secure.SYNC_PARENT_SOUNDS,
7645 0 /* false */, userId);
Andre Lago7bdc6d82016-09-22 18:00:41 +01007646 } finally {
7647 Binder.restoreCallingIdentity(token);
7648 }
7649 }
7650
Jean-Michel Trivi5a561092015-04-23 18:48:08 -07007651 //======================
Jean-Michel Trivi46e310b2017-01-04 15:58:02 -08007652 // Audio playback notification
Jean-Michel Trivi292a6a42016-12-01 08:32:15 -08007653 //======================
Eric Laurente5a351c2017-09-27 20:11:51 -07007654 private final PlaybackActivityMonitor mPlaybackMonitor;
Jean-Michel Trivi292a6a42016-12-01 08:32:15 -08007655
7656 public void registerPlaybackCallback(IPlaybackConfigDispatcher pcdb) {
Jean-Michel Trivi44a8f532017-01-02 14:36:43 -08007657 final boolean isPrivileged =
Jaewan Kim92dea332017-02-02 11:52:08 +09007658 (PackageManager.PERMISSION_GRANTED == mContext.checkCallingOrSelfPermission(
Jean-Michel Trivi292a6a42016-12-01 08:32:15 -08007659 android.Manifest.permission.MODIFY_AUDIO_ROUTING));
7660 mPlaybackMonitor.registerPlaybackCallback(pcdb, isPrivileged);
7661 }
7662
7663 public void unregisterPlaybackCallback(IPlaybackConfigDispatcher pcdb) {
7664 mPlaybackMonitor.unregisterPlaybackCallback(pcdb);
7665 }
7666
7667 public List<AudioPlaybackConfiguration> getActivePlaybackConfigurations() {
Jean-Michel Trivi44a8f532017-01-02 14:36:43 -08007668 final boolean isPrivileged =
Jaewan Kim92dea332017-02-02 11:52:08 +09007669 (PackageManager.PERMISSION_GRANTED == mContext.checkCallingOrSelfPermission(
Jean-Michel Trivi44a8f532017-01-02 14:36:43 -08007670 android.Manifest.permission.MODIFY_AUDIO_ROUTING));
7671 return mPlaybackMonitor.getActivePlaybackConfigurations(isPrivileged);
Jean-Michel Trivi292a6a42016-12-01 08:32:15 -08007672 }
7673
Jean-Michel Trivi44a8f532017-01-02 14:36:43 -08007674 public int trackPlayer(PlayerBase.PlayerIdCard pic) {
7675 return mPlaybackMonitor.trackPlayer(pic);
Jean-Michel Trivi292a6a42016-12-01 08:32:15 -08007676 }
7677
7678 public void playerAttributes(int piid, AudioAttributes attr) {
Jean-Michel Trivi46e310b2017-01-04 15:58:02 -08007679 mPlaybackMonitor.playerAttributes(piid, attr, Binder.getCallingUid());
Jean-Michel Trivi292a6a42016-12-01 08:32:15 -08007680 }
7681
7682 public void playerEvent(int piid, int event) {
Jean-Michel Trivi46e310b2017-01-04 15:58:02 -08007683 mPlaybackMonitor.playerEvent(piid, event, Binder.getCallingUid());
Jean-Michel Trivi292a6a42016-12-01 08:32:15 -08007684 }
7685
Jean-Michel Trivi3120059d2017-08-28 12:40:55 -07007686 public void playerHasOpPlayAudio(int piid, boolean hasOpPlayAudio) {
7687 mPlaybackMonitor.playerHasOpPlayAudio(piid, hasOpPlayAudio, Binder.getCallingUid());
7688 }
7689
Jean-Michel Trivi292a6a42016-12-01 08:32:15 -08007690 public void releasePlayer(int piid) {
Jean-Michel Trivi46e310b2017-01-04 15:58:02 -08007691 mPlaybackMonitor.releasePlayer(piid, Binder.getCallingUid());
Jean-Michel Trivi292a6a42016-12-01 08:32:15 -08007692 }
7693
7694 //======================
Jean-Michel Trivi958876f2014-11-16 15:40:22 -08007695 // Audio policy proxy
7696 //======================
Jean-Michel Trivi8fdb0d42014-07-16 19:08:37 -07007697 /**
Jean-Michel Trivi1b3541d2014-11-25 12:53:41 -08007698 * This internal class inherits from AudioPolicyConfig, each instance contains all the
7699 * mixes of an AudioPolicy and their configurations.
Jean-Michel Trivi8fdb0d42014-07-16 19:08:37 -07007700 */
7701 public class AudioPolicyProxy extends AudioPolicyConfig implements IBinder.DeathRecipient {
Jean-Michel Trivia8b6bd82014-07-01 09:48:46 -07007702 private static final String TAG = "AudioPolicyProxy";
Jean-Michel Trivi610aa9b2018-01-27 15:42:42 -08007703 final IAudioPolicyCallback mPolicyCallback;
7704 final boolean mHasFocusListener;
7705 final boolean mIsVolumeController;
Jean-Michel Trivi0212be52014-11-24 14:43:10 -08007706 /**
7707 * Audio focus ducking behavior for an audio policy.
7708 * This variable reflects the value that was successfully set in
7709 * {@link AudioService#setFocusPropertiesForPolicy(int, IAudioPolicyCallback)}. This
7710 * implies that a value of FOCUS_POLICY_DUCKING_IN_POLICY means the corresponding policy
7711 * is handling ducking for audio focus.
7712 */
7713 int mFocusDuckBehavior = AudioPolicy.FOCUS_POLICY_DUCKING_DEFAULT;
Jean-Michel Trivi126cf032017-04-02 23:19:02 -07007714 boolean mIsFocusPolicy = false;
Jean-Michel Trivi0212be52014-11-24 14:43:10 -08007715
7716 AudioPolicyProxy(AudioPolicyConfig config, IAudioPolicyCallback token,
Jean-Michel Trivi610aa9b2018-01-27 15:42:42 -08007717 boolean hasFocusListener, boolean isFocusPolicy, boolean isVolumeController) {
Jean-Michel Trivi8fdb0d42014-07-16 19:08:37 -07007718 super(config);
Jean-Michel Trivi1b3541d2014-11-25 12:53:41 -08007719 setRegistration(new String(config.hashCode() + ":ap:" + mAudioPolicyCounter++));
Jean-Michel Trivi5a561092015-04-23 18:48:08 -07007720 mPolicyCallback = token;
Jean-Michel Trivi0212be52014-11-24 14:43:10 -08007721 mHasFocusListener = hasFocusListener;
Jean-Michel Trivi610aa9b2018-01-27 15:42:42 -08007722 mIsVolumeController = isVolumeController;
Jean-Michel Trivi0212be52014-11-24 14:43:10 -08007723 if (mHasFocusListener) {
Jean-Michel Trivi5a561092015-04-23 18:48:08 -07007724 mMediaFocusControl.addFocusFollower(mPolicyCallback);
Jean-Michel Trivi126cf032017-04-02 23:19:02 -07007725 // can only ever be true if there is a focus listener
7726 if (isFocusPolicy) {
7727 mIsFocusPolicy = true;
7728 mMediaFocusControl.setFocusPolicy(mPolicyCallback);
7729 }
Jean-Michel Trivi0212be52014-11-24 14:43:10 -08007730 }
Jean-Michel Trivi610aa9b2018-01-27 15:42:42 -08007731 if (mIsVolumeController) {
7732 setExtVolumeController(mPolicyCallback);
7733 }
Eric Laurent7f5eb9f2014-12-01 19:36:30 -08007734 connectMixes();
Jean-Michel Trivia8b6bd82014-07-01 09:48:46 -07007735 }
7736
7737 public void binderDied() {
7738 synchronized (mAudioPolicies) {
Jean-Michel Trivi5a561092015-04-23 18:48:08 -07007739 Log.i(TAG, "audio policy " + mPolicyCallback + " died");
Jean-Michel Trivi0212be52014-11-24 14:43:10 -08007740 release();
Jean-Michel Trivi5a561092015-04-23 18:48:08 -07007741 mAudioPolicies.remove(mPolicyCallback.asBinder());
Jean-Michel Trivi8fdb0d42014-07-16 19:08:37 -07007742 }
Jean-Michel Trivi610aa9b2018-01-27 15:42:42 -08007743 if (mIsVolumeController) {
7744 synchronized (mExtVolumeControllerLock) {
7745 mExtVolumeController = null;
7746 }
7747 }
Jean-Michel Trivi8fdb0d42014-07-16 19:08:37 -07007748 }
7749
Jean-Michel Trivi0212be52014-11-24 14:43:10 -08007750 String getRegistrationId() {
Jean-Michel Trivi1b3541d2014-11-25 12:53:41 -08007751 return getRegistration();
Jean-Michel Trivi8fdb0d42014-07-16 19:08:37 -07007752 }
7753
Jean-Michel Trivi0212be52014-11-24 14:43:10 -08007754 void release() {
Jean-Michel Trivi126cf032017-04-02 23:19:02 -07007755 if (mIsFocusPolicy) {
7756 mMediaFocusControl.unsetFocusPolicy(mPolicyCallback);
7757 }
Jean-Michel Trivi0212be52014-11-24 14:43:10 -08007758 if (mFocusDuckBehavior == AudioPolicy.FOCUS_POLICY_DUCKING_IN_POLICY) {
7759 mMediaFocusControl.setDuckingInExtPolicyAvailable(false);
7760 }
7761 if (mHasFocusListener) {
Jean-Michel Trivi5a561092015-04-23 18:48:08 -07007762 mMediaFocusControl.removeFocusFollower(mPolicyCallback);
Jean-Michel Trivi0212be52014-11-24 14:43:10 -08007763 }
Eric Laurent66b69672018-01-26 18:30:51 -08007764 final long identity = Binder.clearCallingIdentity();
Eric Laurent7f5eb9f2014-12-01 19:36:30 -08007765 AudioSystem.registerPolicyMixes(mMixes, false);
Eric Laurent66b69672018-01-26 18:30:51 -08007766 Binder.restoreCallingIdentity(identity);
Jean-Michel Trivi8fdb0d42014-07-16 19:08:37 -07007767 }
7768
Jean-Michel Trivi7db2d8f2018-03-06 10:30:59 -08007769 boolean hasMixAffectingUsage(int usage) {
7770 for (AudioMix mix : mMixes) {
7771 if (mix.isAffectingUsage(usage)) {
7772 return true;
7773 }
7774 }
7775 return false;
7776 }
7777
Jean-Michel Triviaf576a02018-02-14 08:57:46 -08007778 void addMixes(@NonNull ArrayList<AudioMix> mixes) {
7779 // TODO optimize to not have to unregister the mixes already in place
7780 synchronized (mMixes) {
7781 AudioSystem.registerPolicyMixes(mMixes, false);
7782 this.add(mixes);
7783 AudioSystem.registerPolicyMixes(mMixes, true);
7784 }
7785 }
7786
7787 void removeMixes(@NonNull ArrayList<AudioMix> mixes) {
7788 // TODO optimize to not have to unregister the mixes already in place
7789 synchronized (mMixes) {
7790 AudioSystem.registerPolicyMixes(mMixes, false);
7791 this.remove(mixes);
7792 AudioSystem.registerPolicyMixes(mMixes, true);
7793 }
7794 }
7795
Eric Laurent7f5eb9f2014-12-01 19:36:30 -08007796 void connectMixes() {
Eric Laurent66b69672018-01-26 18:30:51 -08007797 final long identity = Binder.clearCallingIdentity();
Eric Laurent7f5eb9f2014-12-01 19:36:30 -08007798 AudioSystem.registerPolicyMixes(mMixes, true);
Eric Laurent66b69672018-01-26 18:30:51 -08007799 Binder.restoreCallingIdentity(identity);
Jean-Michel Trivia8b6bd82014-07-01 09:48:46 -07007800 }
7801 };
7802
Jean-Michel Trivi126cf032017-04-02 23:19:02 -07007803 //======================
7804 // Audio policy: focus
7805 //======================
7806 /** */
7807 public int dispatchFocusChange(AudioFocusInfo afi, int focusChange, IAudioPolicyCallback pcb) {
Jean-Michel Trivie2d8aae2018-01-30 15:09:47 -08007808 if (afi == null) {
7809 throw new IllegalArgumentException("Illegal null AudioFocusInfo");
7810 }
7811 if (pcb == null) {
7812 throw new IllegalArgumentException("Illegal null AudioPolicy callback");
7813 }
Jean-Michel Trivi126cf032017-04-02 23:19:02 -07007814 synchronized (mAudioPolicies) {
7815 if (!mAudioPolicies.containsKey(pcb.asBinder())) {
7816 throw new IllegalStateException("Unregistered AudioPolicy for focus dispatch");
7817 }
7818 return mMediaFocusControl.dispatchFocusChange(afi, focusChange);
7819 }
7820 }
7821
Jean-Michel Trivie2d8aae2018-01-30 15:09:47 -08007822 public void setFocusRequestResultFromExtPolicy(AudioFocusInfo afi, int requestResult,
7823 IAudioPolicyCallback pcb) {
7824 if (afi == null) {
7825 throw new IllegalArgumentException("Illegal null AudioFocusInfo");
7826 }
7827 if (pcb == null) {
7828 throw new IllegalArgumentException("Illegal null AudioPolicy callback");
7829 }
7830 synchronized (mAudioPolicies) {
7831 if (!mAudioPolicies.containsKey(pcb.asBinder())) {
7832 throw new IllegalStateException("Unregistered AudioPolicy for external focus");
7833 }
7834 mMediaFocusControl.setFocusRequestResultFromExtPolicy(afi, requestResult);
7835 }
7836 }
7837
7838
Jean-Michel Trivi126cf032017-04-02 23:19:02 -07007839 //======================
Eric Laurent1d3cdce2018-01-20 10:31:21 -08007840 // Audioserver state displatch
7841 //======================
7842 private class AsdProxy implements IBinder.DeathRecipient {
7843 private final IAudioServerStateDispatcher mAsd;
7844
7845 AsdProxy(IAudioServerStateDispatcher asd) {
7846 mAsd = asd;
7847 }
7848
7849 public void binderDied() {
7850 synchronized (mAudioServerStateListeners) {
7851 mAudioServerStateListeners.remove(mAsd.asBinder());
7852 }
7853 }
7854
7855 IAudioServerStateDispatcher callback() {
7856 return mAsd;
7857 }
7858 }
7859
7860 private HashMap<IBinder, AsdProxy> mAudioServerStateListeners =
7861 new HashMap<IBinder, AsdProxy>();
7862
7863 private void checkMonitorAudioServerStatePermission() {
7864 if (!(mContext.checkCallingOrSelfPermission(
7865 android.Manifest.permission.MODIFY_PHONE_STATE) ==
7866 PackageManager.PERMISSION_GRANTED ||
7867 mContext.checkCallingOrSelfPermission(
7868 android.Manifest.permission.MODIFY_AUDIO_ROUTING) ==
7869 PackageManager.PERMISSION_GRANTED)) {
7870 throw new SecurityException("Not allowed to monitor audioserver state");
7871 }
7872 }
7873
7874 public void registerAudioServerStateDispatcher(IAudioServerStateDispatcher asd) {
7875 checkMonitorAudioServerStatePermission();
7876 synchronized (mAudioServerStateListeners) {
7877 if (mAudioServerStateListeners.containsKey(asd.asBinder())) {
7878 Slog.w(TAG, "Cannot re-register audio server state dispatcher");
7879 return;
7880 }
7881 AsdProxy asdp = new AsdProxy(asd);
7882 try {
7883 asd.asBinder().linkToDeath(asdp, 0/*flags*/);
7884 } catch (RemoteException e) {
7885
7886 }
7887 mAudioServerStateListeners.put(asd.asBinder(), asdp);
7888 }
7889 }
7890
7891 public void unregisterAudioServerStateDispatcher(IAudioServerStateDispatcher asd) {
7892 checkMonitorAudioServerStatePermission();
7893 synchronized (mAudioServerStateListeners) {
7894 AsdProxy asdp = mAudioServerStateListeners.remove(asd.asBinder());
7895 if (asdp == null) {
7896 Slog.w(TAG, "Trying to unregister unknown audioserver state dispatcher for pid "
7897 + Binder.getCallingPid() + " / uid " + Binder.getCallingUid());
7898 return;
7899 } else {
7900 asd.asBinder().unlinkToDeath(asdp, 0/*flags*/);
7901 }
7902 }
7903 }
7904
7905 public boolean isAudioServerRunning() {
7906 checkMonitorAudioServerStatePermission();
7907 return (AudioSystem.checkAudioFlinger() == AudioSystem.AUDIO_STATUS_OK);
7908 }
7909
7910 //======================
Jean-Michel Trivi126cf032017-04-02 23:19:02 -07007911 // misc
7912 //======================
Jean-Michel Triviaf576a02018-02-14 08:57:46 -08007913 private final HashMap<IBinder, AudioPolicyProxy> mAudioPolicies =
Jean-Michel Trivia8b6bd82014-07-01 09:48:46 -07007914 new HashMap<IBinder, AudioPolicyProxy>();
Jean-Michel Triviaf576a02018-02-14 08:57:46 -08007915 @GuardedBy("mAudioPolicies")
7916 private int mAudioPolicyCounter = 0;
Phil Burkac0f7042016-02-24 12:19:08 -08007917}