blob: 91d19def17667f0c647cfcffb2e72652efdb320d [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_SYSTEM;
Fyodor Kupolovbcb6c1e2015-05-11 12:05:15 -070024import static android.os.Process.FIRST_APPLICATION_UID;
Mike Digman55272862018-02-20 14:35:17 -080025import static android.provider.Settings.Secure.VOLUME_HUSH_MUTE;
26import static android.provider.Settings.Secure.VOLUME_HUSH_OFF;
27import static android.provider.Settings.Secure.VOLUME_HUSH_VIBRATE;
Amith Yamasanic696a532011-10-28 17:02:37 -070028
Fyodor Kupolovb5013302015-04-17 17:59:14 -070029import android.Manifest;
Jean-Michel Trivi58850372018-09-14 16:01:28 -070030import android.annotation.IntDef;
Jean-Michel Trivi7ed71472018-02-02 16:52:09 -080031import android.annotation.NonNull;
Jean-Michel Trivia53b7052017-04-12 18:27:01 -070032import android.annotation.Nullable;
Glenn Kastenfd116ad2013-07-12 17:10:39 -070033import android.app.ActivityManager;
Fyodor Kupolovb5013302015-04-17 17:59:14 -070034import android.app.ActivityManagerInternal;
Fyodor Kupolovb5013302015-04-17 17:59:14 -070035import android.app.AppGlobals;
Dianne Hackbornba50b97c2013-04-30 15:04:46 -070036import android.app.AppOpsManager;
Dianne Hackborn3e99f652017-07-05 16:33:56 -070037import android.app.IUidObserver;
Julia Reynolds48034f82016-03-09 10:15:16 -050038import android.app.NotificationManager;
Jaikumar Ganesh82aa7f02010-09-27 17:05:10 -070039import android.bluetooth.BluetoothAdapter;
Jaikumar Ganesh82aa7f02010-09-27 17:05:10 -070040import android.bluetooth.BluetoothDevice;
41import android.bluetooth.BluetoothHeadset;
42import android.bluetooth.BluetoothProfile;
Nick Pellybd022f42009-08-14 18:33:38 -070043import android.content.BroadcastReceiver;
Jean-Michel Trivid327f212010-03-16 21:44:33 -070044import android.content.ComponentName;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080045import android.content.ContentResolver;
46import android.content.Context;
47import android.content.Intent;
Eric Laurenta553c252009-07-17 12:17:14 -070048import android.content.IntentFilter;
Julia Reynolds48034f82016-03-09 10:15:16 -050049import android.content.pm.ApplicationInfo;
Fyodor Kupolovb5013302015-04-17 17:59:14 -070050import android.content.pm.PackageInfo;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080051import android.content.pm.PackageManager;
Marco Nelissenfb6df0b2017-02-15 15:25:24 -080052import android.content.pm.ResolveInfo;
Fyodor Kupolovb5013302015-04-17 17:59:14 -070053import android.content.pm.UserInfo;
Jean-Michel Trivif26f0172012-04-25 16:23:20 -070054import android.content.res.Configuration;
Eric Laurente78fced2013-03-15 16:03:47 -070055import android.content.res.Resources;
56import android.content.res.XmlResourceParser;
Jason Parekhb1096152009-03-24 17:48:25 -070057import android.database.ContentObserver;
Shubangc480a712018-06-11 18:02:42 -070058import android.hardware.hdmi.HdmiAudioSystemClient;
Jungshik Jang41d97462014-06-30 22:26:29 +090059import android.hardware.hdmi.HdmiControlManager;
Eric Laurent212532b2014-07-21 15:43:18 -070060import android.hardware.hdmi.HdmiPlaybackClient;
Jungshik Jang41d97462014-06-30 22:26:29 +090061import android.hardware.hdmi.HdmiTvClient;
Paul McLeanc837a452014-04-09 09:04:43 -070062import android.hardware.usb.UsbManager;
John Spurlock61560172015-02-06 19:46:04 -050063import android.media.AudioAttributes;
Jean-Michel Trivi126cf032017-04-02 23:19:02 -070064import android.media.AudioFocusInfo;
Jean-Michel Trivi9228af62018-01-05 17:06:17 -080065import android.media.AudioFocusRequest;
John Spurlock61560172015-02-06 19:46:04 -050066import android.media.AudioFormat;
67import android.media.AudioManager;
68import android.media.AudioManagerInternal;
Jean-Michel Trivi292a6a42016-12-01 08:32:15 -080069import android.media.AudioPlaybackConfiguration;
Jean-Michel Trivi598c0c92016-03-07 14:13:03 -080070import android.media.AudioRecordingConfiguration;
John Spurlock61560172015-02-06 19:46:04 -050071import android.media.AudioRoutesInfo;
Beverly925cde82018-01-23 09:31:23 -050072import android.media.AudioSystem;
John Spurlock61560172015-02-06 19:46:04 -050073import android.media.IAudioFocusDispatcher;
74import android.media.IAudioRoutesObserver;
Eric Laurent1d3cdce2018-01-20 10:31:21 -080075import android.media.IAudioServerStateDispatcher;
John Spurlock61560172015-02-06 19:46:04 -050076import android.media.IAudioService;
Jean-Michel Trivi292a6a42016-12-01 08:32:15 -080077import android.media.IPlaybackConfigDispatcher;
Jean-Michel Trivid3c71f02015-12-07 11:59:31 -080078import android.media.IRecordingConfigDispatcher;
John Spurlock61560172015-02-06 19:46:04 -050079import android.media.IRingtonePlayer;
80import android.media.IVolumeController;
81import android.media.MediaPlayer;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080082import android.media.MediaPlayer.OnCompletionListener;
83import android.media.MediaPlayer.OnErrorListener;
Jean-Michel Trivi292a6a42016-12-01 08:32:15 -080084import android.media.PlayerBase;
Beverly925cde82018-01-23 09:31:23 -050085import android.media.SoundPool;
86import android.media.VolumePolicy;
87import android.media.audiofx.AudioEffect;
Jean-Michel Trivi5a561092015-04-23 18:48:08 -070088import android.media.audiopolicy.AudioMix;
Jean-Michel Trivi958876f2014-11-16 15:40:22 -080089import android.media.audiopolicy.AudioPolicy;
Jean-Michel Trivia8b6bd82014-07-01 09:48:46 -070090import android.media.audiopolicy.AudioPolicyConfig;
François Gaffie0699fec2018-07-09 14:35:10 +020091import android.media.audiopolicy.AudioProductStrategies;
François Gaffie9c362102018-09-21 17:43:52 +020092import android.media.audiopolicy.AudioVolumeGroup;
93import android.media.audiopolicy.AudioVolumeGroups;
Jean-Michel Trivi0212be52014-11-24 14:43:10 -080094import android.media.audiopolicy.IAudioPolicyCallback;
Kevin Rocard2fe8b8b2019-02-20 11:25:23 -080095import android.media.projection.IMediaProjection;
96import android.media.projection.IMediaProjectionManager;
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;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800106import android.os.RemoteException;
Kevin Rocard2fe8b8b2019-02-20 11:25:23 -0800107import android.os.ServiceManager;
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;
Phil Weaverf1a9aff2017-03-23 17:21:29 -0700122import android.util.IntArray;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800123import android.util.Log;
John Spurlockaa5ee4d2014-07-25 13:05:12 -0400124import android.util.MathUtils;
Jean-Michel Trivia8b6bd82014-07-01 09:48:46 -0700125import android.util.Slog;
John Spurlock2bb02ec2015-03-02 13:13:06 -0500126import android.util.SparseIntArray;
Jean-Michel Trivid327f212010-03-16 21:44:33 -0700127import android.view.KeyEvent;
Jean-Michel Trivi873cc452014-09-11 17:25:09 -0700128import android.view.accessibility.AccessibilityManager;
Mike Digman55272862018-02-20 14:35:17 -0800129import android.widget.Toast;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800130
Jean-Michel Trivi8719a1d2017-11-06 11:52:51 -0800131import com.android.internal.annotations.GuardedBy;
Jeff Sharkeyfe9a53b2017-03-31 14:08:23 -0600132import com.android.internal.util.DumpUtils;
François Gaffie9c362102018-09-21 17:43:52 +0200133import com.android.internal.util.Preconditions;
Eric Laurente78fced2013-03-15 16:03:47 -0700134import com.android.internal.util.XmlUtils;
John Spurlock90874332015-03-10 16:00:54 -0400135import com.android.server.EventLogTags;
RoboErik0dac35a2014-08-12 15:48:49 -0700136import com.android.server.LocalServices;
Makoto Onukie1aef852015-10-15 17:28:35 -0700137import com.android.server.SystemService;
Beverly925cde82018-01-23 09:31:23 -0500138import com.android.server.audio.AudioServiceEvents.PhoneStateEvent;
139import com.android.server.audio.AudioServiceEvents.VolumeEvent;
Fyodor Kupolovb5013302015-04-17 17:59:14 -0700140import com.android.server.pm.UserManagerService;
Wale Ogunwale9e4f3e02018-05-17 09:35:39 -0700141import com.android.server.wm.ActivityTaskManagerInternal;
Eric Laurente78fced2013-03-15 16:03:47 -0700142
143import org.xmlpull.v1.XmlPullParserException;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800144
Jaekyun Seokc31033f2018-01-15 14:53:17 +0900145import java.io.File;
Jean-Michel Trivid5176cf2010-01-28 11:56:42 -0800146import java.io.FileDescriptor;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800147import java.io.IOException;
Jean-Michel Trivid5176cf2010-01-28 11:56:42 -0800148import java.io.PrintWriter;
Jean-Michel Trivi58850372018-09-14 16:01:28 -0700149import java.lang.annotation.Retention;
150import java.lang.annotation.RetentionPolicy;
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
Jean-Michel Trivi58850372018-09-14 16:01:28 -0700176 private static final String TAG = "AS.AudioService";
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800177
Jean-Michel Trivi339567d2014-07-29 09:53:34 -0700178 /** Debug audio mode */
Jean-Michel Trivi58850372018-09-14 16:01:28 -0700179 protected static final boolean DEBUG_MODE = false;
Jean-Michel Trivi8fdb0d42014-07-16 19:08:37 -0700180
181 /** Debug audio policy feature */
Jean-Michel Trivi58850372018-09-14 16:01:28 -0700182 protected static final boolean DEBUG_AP = false;
Jean-Michel Trivi8fdb0d42014-07-16 19:08:37 -0700183
Jean-Michel Trivi3114ce32012-06-11 15:03:52 -0700184 /** Debug volumes */
Jean-Michel Trivi58850372018-09-14 16:01:28 -0700185 protected static final boolean DEBUG_VOL = false;
Jean-Michel Trivi18e7bce2011-08-26 12:11:36 -0700186
Paul McLean394a8e12015-03-03 10:29:19 -0700187 /** debug calls to devices APIs */
Jean-Michel Trivi58850372018-09-14 16:01:28 -0700188 protected static final boolean DEBUG_DEVICES = false;
189
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800190 /** How long to delay before persisting a change in volume/ringer mode. */
RoboErik45edba12012-03-27 17:54:36 -0700191 private static final int PERSIST_DELAY = 500;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800192
RoboErik5452e252015-02-06 15:33:53 -0800193 /** How long to delay after a volume down event before unmuting a stream */
194 private static final int UNMUTE_STREAM_DELAY = 350;
195
John Spurlock3346a802014-05-20 16:25:37 -0400196 /**
John Spurlocka11b4af2014-06-01 11:52:23 -0400197 * Only used in the result from {@link #checkForRingerModeChange(int, int, int)}
198 */
199 private static final int FLAG_ADJUST_VOLUME = 1;
200
Dianne Hackbornba50b97c2013-04-30 15:04:46 -0700201 private final Context mContext;
202 private final ContentResolver mContentResolver;
203 private final AppOpsManager mAppOps;
Eric Laurent212532b2014-07-21 15:43:18 -0700204
Eric Laurent212532b2014-07-21 15:43:18 -0700205 // the platform type affects volume and silent mode behavior
206 private final int mPlatformType;
207
Muyuan Li1ed6df62016-06-18 11:16:52 -0700208 // indicates whether the system maps all streams to a single stream.
209 private final boolean mIsSingleVolume;
210
Eric Laurent212532b2014-07-21 15:43:18 -0700211 private boolean isPlatformVoice() {
John Spurlock61560172015-02-06 19:46:04 -0500212 return mPlatformType == AudioSystem.PLATFORM_VOICE;
Eric Laurent212532b2014-07-21 15:43:18 -0700213 }
214
Jean-Michel Trivi58850372018-09-14 16:01:28 -0700215 /*package*/ boolean isPlatformTelevision() {
John Spurlock61560172015-02-06 19:46:04 -0500216 return mPlatformType == AudioSystem.PLATFORM_TELEVISION;
Eric Laurent212532b2014-07-21 15:43:18 -0700217 }
Jean-Michel Trivid5176cf2010-01-28 11:56:42 -0800218
Jean-Michel Trivi58850372018-09-14 16:01:28 -0700219 /*package*/ boolean isPlatformAutomotive() {
Hongwei Wangdaba1242018-05-29 14:36:16 -0700220 return mContext.getPackageManager().hasSystemFeature(PackageManager.FEATURE_AUTOMOTIVE);
221 }
222
John Spurlock3346a802014-05-20 16:25:37 -0400223 /** The controller for the volume UI. */
224 private final VolumeController mVolumeController = new VolumeController();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800225
226 // sendMsg() flags
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800227 /** If the msg is already queued, replace it with this one. */
228 private static final int SENDMSG_REPLACE = 0;
229 /** If the msg is already queued, ignore this one and leave the old. */
230 private static final int SENDMSG_NOOP = 1;
231 /** If the msg is already queued, queue this one and leave the old. */
232 private static final int SENDMSG_QUEUE = 2;
233
Jean-Michel Trivi3114ce32012-06-11 15:03:52 -0700234 // AudioHandler messages
Eric Laurent9bc8358d2011-11-18 16:43:31 -0800235 private static final int MSG_SET_DEVICE_VOLUME = 0;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800236 private static final int MSG_PERSIST_VOLUME = 1;
237 private static final int MSG_PERSIST_RINGER_MODE = 3;
Andy Hunged0ea402015-10-30 14:11:46 -0700238 private static final int MSG_AUDIO_SERVER_DIED = 4;
Eric Laurentdfb881f2013-07-18 14:41:39 -0700239 private static final int MSG_PLAY_SOUND_EFFECT = 5;
Eric Laurentdfb881f2013-07-18 14:41:39 -0700240 private static final int MSG_LOAD_SOUND_EFFECTS = 7;
241 private static final int MSG_SET_FORCE_USE = 8;
242 private static final int MSG_BT_HEADSET_CNCT_FAILED = 9;
243 private static final int MSG_SET_ALL_VOLUMES = 10;
Jean-Michel Trivi58850372018-09-14 16:01:28 -0700244 private static final int MSG_CHECK_MUSIC_ACTIVE = 11;
245 private static final int MSG_CONFIGURE_SAFE_MEDIA_VOLUME = 12;
246 private static final int MSG_CONFIGURE_SAFE_MEDIA_VOLUME_FORCED = 13;
247 private static final int MSG_PERSIST_SAFE_VOLUME_STATE = 14;
248 private static final int MSG_UNLOAD_SOUND_EFFECTS = 15;
249 private static final int MSG_SYSTEM_READY = 16;
250 private static final int MSG_PERSIST_MUSIC_ACTIVE_MS = 17;
251 private static final int MSG_UNMUTE_STREAM = 18;
252 private static final int MSG_DYN_POLICY_MIX_STATE_UPDATE = 19;
253 private static final int MSG_INDICATE_SYSTEM_READY = 20;
254 private static final int MSG_ACCESSORY_PLUG_MEDIA_UNMUTE = 21;
255 private static final int MSG_NOTIFY_VOL_EVENT = 22;
256 private static final int MSG_DISPATCH_AUDIO_SERVER_STATE = 23;
257 private static final int MSG_ENABLE_SURROUND_FORMATS = 24;
Jean-Michel Trivica49d312019-02-14 15:55:39 -0800258 private static final int MSG_UPDATE_RINGER_MODE = 25;
Jean-Michel Trivi3114ce32012-06-11 15:03:52 -0700259 // start of messages handled under wakelock
260 // these messages can only be queued, i.e. sent with queueMsgUnderWakeLock(),
Jean-Michel Trivie12c39b2012-06-06 10:51:58 -0700261 // and not with sendMsg(..., ..., SENDMSG_QUEUE, ...)
Jean-Michel Trivi58850372018-09-14 16:01:28 -0700262 private static final int MSG_DISABLE_AUDIO_FOR_UID = 100;
Jean-Michel Trivi3114ce32012-06-11 15:03:52 -0700263 // end of messages handled under wakelock
Eric Laurentafbb0472011-12-15 09:04:23 -0800264
Eric Laurent0867bed2015-05-20 14:49:08 -0700265 // retry delay in case of failure to indicate system ready to AudioFlinger
266 private static final int INDICATE_SYSTEM_READY_RETRY_DELAY_MS = 1000;
267
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800268 /** @see AudioSystemThread */
269 private AudioSystemThread mAudioSystemThread;
270 /** @see AudioHandler */
271 private AudioHandler mAudioHandler;
272 /** @see VolumeStreamState */
273 private VolumeStreamState[] mStreamStates;
Jean-Michel Trivi58850372018-09-14 16:01:28 -0700274
275 /*package*/ VolumeStreamState getStreamState(int stream) {
276 return mStreamStates[stream];
277 }
278
Jason Parekhb1096152009-03-24 17:48:25 -0700279 private SettingsObserver mSettingsObserver;
Eric Laurenta553c252009-07-17 12:17:14 -0700280
François Gaffie0699fec2018-07-09 14:35:10 +0200281 /** @see AudioProductStrategies */
282 private static AudioProductStrategies sAudioProductStrategies;
François Gaffie9c362102018-09-21 17:43:52 +0200283 /** @see AudioVolumeGroups */
284 private static AudioVolumeGroups sAudioVolumeGroups;
François Gaffie0699fec2018-07-09 14:35:10 +0200285
Jean-Michel Trivifa9a6982013-06-27 16:22:58 -0700286 private int mMode = AudioSystem.MODE_NORMAL;
Glenn Kastenba195eb2011-12-13 09:30:40 -0800287 // protects mRingerMode
288 private final Object mSettingsLock = new Object();
Eric Laurent45c90ce2012-04-24 18:44:22 -0700289
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800290 private SoundPool mSoundPool;
Glenn Kasten30c918c2011-11-10 17:56:41 -0800291 private final Object mSoundEffectsLock = new Object();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800292 private static final int NUM_SOUNDPOOL_CHANNELS = 4;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800293
294 /* Sound effect file names */
295 private static final String SOUND_EFFECTS_PATH = "/media/audio/ui/";
Eric Laurente78fced2013-03-15 16:03:47 -0700296 private static final List<String> SOUND_EFFECT_FILES = new ArrayList<String>();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800297
298 /* Sound effect file name mapping sound effect id (AudioManager.FX_xxx) to
299 * file index in SOUND_EFFECT_FILES[] (first column) and indicating if effect
300 * uses soundpool (second column) */
Eric Laurente78fced2013-03-15 16:03:47 -0700301 private final int[][] SOUND_EFFECT_FILES_MAP = new int[AudioManager.NUM_SOUND_EFFECTS][2];
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800302
John Spurlockb6e19e32015-03-10 21:33:44 -0400303 /** Maximum volume index values for audio streams */
Chinyue Chen6affe932018-01-24 14:51:43 +0800304 protected static int[] MAX_STREAM_VOLUME = new int[] {
Eric Laurent6ee99522009-08-25 06:30:59 -0700305 5, // STREAM_VOICE_CALL
306 7, // STREAM_SYSTEM
307 7, // STREAM_RING
308 15, // STREAM_MUSIC
309 7, // STREAM_ALARM
310 7, // STREAM_NOTIFICATION
311 15, // STREAM_BLUETOOTH_SCO
312 7, // STREAM_SYSTEM_ENFORCED
313 15, // STREAM_DTMF
Jean-Michel Trivi3f0945a2016-11-11 10:05:18 -0800314 15, // STREAM_TTS
315 15 // STREAM_ACCESSIBILITY
Jared Suttles59820132009-08-13 21:50:52 -0500316 };
Eric Laurent91377de2014-10-10 15:24:04 -0700317
John Spurlockb6e19e32015-03-10 21:33:44 -0400318 /** Minimum volume index values for audio streams */
Chinyue Chen6affe932018-01-24 14:51:43 +0800319 protected static int[] MIN_STREAM_VOLUME = new int[] {
John Spurlockb6e19e32015-03-10 21:33:44 -0400320 1, // STREAM_VOICE_CALL
321 0, // STREAM_SYSTEM
322 0, // STREAM_RING
323 0, // STREAM_MUSIC
Jean-Michel Trivie05eef82018-03-08 18:56:34 -0800324 1, // STREAM_ALARM
John Spurlockb6e19e32015-03-10 21:33:44 -0400325 0, // STREAM_NOTIFICATION
Eric Laurente4381ec2015-10-29 17:52:48 -0700326 0, // STREAM_BLUETOOTH_SCO
John Spurlockb6e19e32015-03-10 21:33:44 -0400327 0, // STREAM_SYSTEM_ENFORCED
328 0, // STREAM_DTMF
Jean-Michel Trivi3f0945a2016-11-11 10:05:18 -0800329 0, // STREAM_TTS
Jean-Michel Trivie05eef82018-03-08 18:56:34 -0800330 1 // STREAM_ACCESSIBILITY
John Spurlockb6e19e32015-03-10 21:33:44 -0400331 };
332
Eric Laurent6d517662012-04-23 18:42:39 -0700333 /* mStreamVolumeAlias[] indicates for each stream if it uses the volume settings
Eric Laurenta553c252009-07-17 12:17:14 -0700334 * of another stream: This avoids multiplying the volume settings for hidden
335 * stream types that follow other stream behavior for volume settings
Eric Laurent6d517662012-04-23 18:42:39 -0700336 * NOTE: do not create loops in aliases!
337 * Some streams alias to different streams according to device category (phone or tablet) or
Eric Laurent24e0d9b2013-10-03 18:15:07 -0700338 * use case (in call vs off call...). See updateStreamVolumeAlias() for more details.
Eric Laurent212532b2014-07-21 15:43:18 -0700339 * mStreamVolumeAlias contains STREAM_VOLUME_ALIAS_VOICE aliases for a voice capable device
340 * (phone), STREAM_VOLUME_ALIAS_TELEVISION for a television or set-top box and
341 * STREAM_VOLUME_ALIAS_DEFAULT for other devices (e.g. tablets).*/
342 private final int[] STREAM_VOLUME_ALIAS_VOICE = new int[] {
Eric Laurent6d517662012-04-23 18:42:39 -0700343 AudioSystem.STREAM_VOICE_CALL, // STREAM_VOICE_CALL
344 AudioSystem.STREAM_RING, // STREAM_SYSTEM
345 AudioSystem.STREAM_RING, // STREAM_RING
346 AudioSystem.STREAM_MUSIC, // STREAM_MUSIC
347 AudioSystem.STREAM_ALARM, // STREAM_ALARM
348 AudioSystem.STREAM_RING, // STREAM_NOTIFICATION
349 AudioSystem.STREAM_BLUETOOTH_SCO, // STREAM_BLUETOOTH_SCO
350 AudioSystem.STREAM_RING, // STREAM_SYSTEM_ENFORCED
351 AudioSystem.STREAM_RING, // STREAM_DTMF
Jean-Michel Trivi3f0945a2016-11-11 10:05:18 -0800352 AudioSystem.STREAM_MUSIC, // STREAM_TTS
353 AudioSystem.STREAM_MUSIC // STREAM_ACCESSIBILITY
Eric Laurenta553c252009-07-17 12:17:14 -0700354 };
Eric Laurent212532b2014-07-21 15:43:18 -0700355 private final int[] STREAM_VOLUME_ALIAS_TELEVISION = new int[] {
356 AudioSystem.STREAM_MUSIC, // STREAM_VOICE_CALL
357 AudioSystem.STREAM_MUSIC, // STREAM_SYSTEM
358 AudioSystem.STREAM_MUSIC, // STREAM_RING
359 AudioSystem.STREAM_MUSIC, // STREAM_MUSIC
360 AudioSystem.STREAM_MUSIC, // STREAM_ALARM
361 AudioSystem.STREAM_MUSIC, // STREAM_NOTIFICATION
362 AudioSystem.STREAM_MUSIC, // STREAM_BLUETOOTH_SCO
363 AudioSystem.STREAM_MUSIC, // STREAM_SYSTEM_ENFORCED
364 AudioSystem.STREAM_MUSIC, // STREAM_DTMF
Jean-Michel Trivi3f0945a2016-11-11 10:05:18 -0800365 AudioSystem.STREAM_MUSIC, // STREAM_TTS
366 AudioSystem.STREAM_MUSIC // STREAM_ACCESSIBILITY
Eric Laurent212532b2014-07-21 15:43:18 -0700367 };
368 private final int[] STREAM_VOLUME_ALIAS_DEFAULT = new int[] {
Eric Laurent6d517662012-04-23 18:42:39 -0700369 AudioSystem.STREAM_VOICE_CALL, // STREAM_VOICE_CALL
John Spurlock4f0f1202014-08-05 13:28:33 -0400370 AudioSystem.STREAM_RING, // STREAM_SYSTEM
Eric Laurent6d517662012-04-23 18:42:39 -0700371 AudioSystem.STREAM_RING, // STREAM_RING
372 AudioSystem.STREAM_MUSIC, // STREAM_MUSIC
373 AudioSystem.STREAM_ALARM, // STREAM_ALARM
374 AudioSystem.STREAM_RING, // STREAM_NOTIFICATION
375 AudioSystem.STREAM_BLUETOOTH_SCO, // STREAM_BLUETOOTH_SCO
John Spurlock4f0f1202014-08-05 13:28:33 -0400376 AudioSystem.STREAM_RING, // STREAM_SYSTEM_ENFORCED
377 AudioSystem.STREAM_RING, // STREAM_DTMF
Jean-Michel Trivi3f0945a2016-11-11 10:05:18 -0800378 AudioSystem.STREAM_MUSIC, // STREAM_TTS
379 AudioSystem.STREAM_MUSIC // STREAM_ACCESSIBILITY
Eric Laurent6d517662012-04-23 18:42:39 -0700380 };
Yue Li949865b2017-05-24 17:25:28 -0700381 protected static int[] mStreamVolumeAlias;
Eric Laurenta553c252009-07-17 12:17:14 -0700382
Dianne Hackbornba50b97c2013-04-30 15:04:46 -0700383 /**
384 * Map AudioSystem.STREAM_* constants to app ops. This should be used
385 * after mapping through mStreamVolumeAlias.
386 */
John Spurlock59dc9c12015-03-02 11:20:15 -0500387 private static final int[] STREAM_VOLUME_OPS = new int[] {
Dianne Hackbornba50b97c2013-04-30 15:04:46 -0700388 AppOpsManager.OP_AUDIO_VOICE_VOLUME, // STREAM_VOICE_CALL
389 AppOpsManager.OP_AUDIO_MEDIA_VOLUME, // STREAM_SYSTEM
390 AppOpsManager.OP_AUDIO_RING_VOLUME, // STREAM_RING
391 AppOpsManager.OP_AUDIO_MEDIA_VOLUME, // STREAM_MUSIC
392 AppOpsManager.OP_AUDIO_ALARM_VOLUME, // STREAM_ALARM
393 AppOpsManager.OP_AUDIO_NOTIFICATION_VOLUME, // STREAM_NOTIFICATION
394 AppOpsManager.OP_AUDIO_BLUETOOTH_VOLUME, // STREAM_BLUETOOTH_SCO
395 AppOpsManager.OP_AUDIO_MEDIA_VOLUME, // STREAM_SYSTEM_ENFORCED
396 AppOpsManager.OP_AUDIO_MEDIA_VOLUME, // STREAM_DTMF
397 AppOpsManager.OP_AUDIO_MEDIA_VOLUME, // STREAM_TTS
Jean-Michel Trivi3f0945a2016-11-11 10:05:18 -0800398 AppOpsManager.OP_AUDIO_ACCESSIBILITY_VOLUME, // STREAM_ACCESSIBILITY
Dianne Hackbornba50b97c2013-04-30 15:04:46 -0700399 };
400
Eric Laurent83a017b2013-03-19 18:15:31 -0700401 private final boolean mUseFixedVolume;
402
Julia Reynoldseb0ce472018-05-04 15:34:55 -0400403 /**
404 * Default stream type used for volume control in the absence of playback
405 * e.g. user on homescreen, no app playing anything, presses hardware volume buttons, this
406 * stream type is controlled.
407 */
Eric Laurent07584202019-01-24 18:33:49 -0800408 protected static final int DEFAULT_VOL_STREAM_NO_PLAYBACK = AudioSystem.STREAM_MUSIC;
Julia Reynoldseb0ce472018-05-04 15:34:55 -0400409
Glenn Kasten30c918c2011-11-10 17:56:41 -0800410 private final AudioSystem.ErrorCallback mAudioSystemCallback = new AudioSystem.ErrorCallback() {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800411 public void onError(int error) {
412 switch (error) {
413 case AudioSystem.AUDIO_STATUS_SERVER_DIED:
Eric Laurent07584202019-01-24 18:33:49 -0800414 mRecordMonitor.clear();
415
Andy Hunged0ea402015-10-30 14:11:46 -0700416 sendMsg(mAudioHandler, MSG_AUDIO_SERVER_DIED,
Eric Laurentdfb881f2013-07-18 14:41:39 -0700417 SENDMSG_NOOP, 0, 0, null, 0);
Eric Laurent1d3cdce2018-01-20 10:31:21 -0800418 sendMsg(mAudioHandler, MSG_DISPATCH_AUDIO_SERVER_STATE,
419 SENDMSG_QUEUE, 0, 0, null, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800420 break;
421 default:
422 break;
423 }
Eric Laurentdfb881f2013-07-18 14:41:39 -0700424 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800425 };
426
427 /**
428 * Current ringer mode from one of {@link AudioManager#RINGER_MODE_NORMAL},
429 * {@link AudioManager#RINGER_MODE_SILENT}, or
430 * {@link AudioManager#RINGER_MODE_VIBRATE}.
431 */
Jean-Michel Trivi8719a1d2017-11-06 11:52:51 -0800432 @GuardedBy("mSettingsLock")
John Spurlock661f2cf2014-11-17 10:29:10 -0500433 private int mRingerMode; // internal ringer mode, affects muting of underlying streams
Jean-Michel Trivi8719a1d2017-11-06 11:52:51 -0800434 @GuardedBy("mSettingsLock")
John Spurlock661f2cf2014-11-17 10:29:10 -0500435 private int mRingerModeExternal = -1; // reported ringer mode to outside clients (AudioManager)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800436
Eric Laurent9bcf4012009-06-12 06:09:28 -0700437 /** @see System#MODE_RINGER_STREAMS_AFFECTED */
Eric Laurent24e0d9b2013-10-03 18:15:07 -0700438 private int mRingerModeAffectedStreams = 0;
Eric Laurent9bcf4012009-06-12 06:09:28 -0700439
Beverlyd6964762018-02-16 14:07:03 -0500440 private int mZenModeAffectedStreams = 0;
441
442 // Streams currently muted by ringer mode and dnd
443 private int mRingerAndZenModeMutedStreams;
Eric Laurent5b4e6542010-03-19 20:02:21 -0700444
John Spurlock3ce37252015-02-17 13:20:45 -0500445 /** Streams that can be muted. Do not resolve to aliases when checking.
446 * @see System#MUTE_STREAMS_AFFECTED */
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800447 private int mMuteAffectedStreams;
448
449 /**
Eric Laurentbffc3d12012-05-07 17:43:49 -0700450 * NOTE: setVibrateSetting(), getVibrateSetting(), shouldVibrate() are deprecated.
451 * mVibrateSetting is just maintained during deprecation period but vibration policy is
452 * now only controlled by mHasVibrator and mRingerMode
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800453 */
454 private int mVibrateSetting;
455
Eric Laurentbffc3d12012-05-07 17:43:49 -0700456 // Is there a vibrator
457 private final boolean mHasVibrator;
Mike Digman55272862018-02-20 14:35:17 -0800458 // Used to play vibrations
459 private Vibrator mVibrator;
460 private static final AudioAttributes VIBRATION_ATTRIBUTES = new AudioAttributes.Builder()
461 .setContentType(AudioAttributes.CONTENT_TYPE_SONIFICATION)
462 .setUsage(AudioAttributes.USAGE_ASSISTANCE_SONIFICATION)
463 .build();
Eric Laurentbffc3d12012-05-07 17:43:49 -0700464
Eric Laurenta553c252009-07-17 12:17:14 -0700465 // Broadcast receiver for device connections intent broadcasts
466 private final BroadcastReceiver mReceiver = new AudioServiceBroadcastReceiver();
467
Kevin Rocard2fe8b8b2019-02-20 11:25:23 -0800468 private IMediaProjectionManager mProjectionService; // to validate projection token
469
Makoto Onukid45a4a22015-11-02 17:17:38 -0800470 /** Interface for UserManagerService. */
471 private final UserManagerInternal mUserManagerInternal;
Sudheer Shankafc46e9b2016-10-21 17:55:27 -0700472 private final ActivityManagerInternal mActivityManagerInternal;
Makoto Onukid45a4a22015-11-02 17:17:38 -0800473
474 private final UserRestrictionsListener mUserRestrictionsListener =
475 new AudioServiceUserRestrictionsListener();
476
Eric Laurent9272b4b2010-01-23 17:12:59 -0800477 // List of binder death handlers for setMode() client processes.
478 // The last process to have called setMode() is at the top of the list.
Jean-Michel Trivi58850372018-09-14 16:01:28 -0700479 // package-private so it can be accessed in AudioDeviceBroker.getSetModeDeathHandlers
480 //TODO candidate to be moved to separate class that handles synchronization
481 @GuardedBy("mDeviceBroker.mSetModeLock")
482 /*package*/ final ArrayList<SetModeDeathHandler> mSetModeDeathHandlers =
483 new ArrayList<SetModeDeathHandler>();
Eric Laurent62ef7672010-11-24 10:58:32 -0800484
Eric Laurenta60e2122010-12-28 16:49:07 -0800485 // true if boot sequence has been completed
Eric Laurent4a5eeb92014-05-06 10:49:04 -0700486 private boolean mSystemReady;
Yasuhiro Matsuda4ced7192015-07-10 22:08:44 +0900487 // true if Intent.ACTION_USER_SWITCHED has ever been received
488 private boolean mUserSwitchedReceived;
Eric Laurenta60e2122010-12-28 16:49:07 -0800489 // listener for SoundPool sample load completion indication
490 private SoundPoolCallback mSoundPoolCallBack;
491 // thread for SoundPool listener
492 private SoundPoolListenerThread mSoundPoolListenerThread;
493 // message looper for SoundPool listener
494 private Looper mSoundPoolLooper = null;
Jean-Michel Trivic55b3932012-06-05 11:57:59 -0700495 // volume applied to sound played with playSoundEffect()
Jean-Michel Trivif2b0c112012-07-09 11:59:11 -0700496 private static int sSoundEffectVolumeDb;
Eric Laurent25101b02011-02-02 09:33:30 -0800497 // previous volume adjustment direction received by checkForRingerModeChange()
498 private int mPrevVolDirection = AudioManager.ADJUST_SAME;
Eric Laurent45c90ce2012-04-24 18:44:22 -0700499 // mVolumeControlStream is set by VolumePanel to temporarily force the stream type which volume
500 // is controlled by Vol keys.
Jean-Michel Trivia7880d42017-04-15 12:41:05 -0700501 private int mVolumeControlStream = -1;
502 // interpretation of whether the volume stream has been selected by the user by clicking on a
503 // volume slider to change which volume is controlled by the volume keys. Is false
504 // when mVolumeControlStream is -1.
505 private boolean mUserSelectedVolumeControlStream = false;
Eric Laurent45c90ce2012-04-24 18:44:22 -0700506 private final Object mForceControlStreamLock = new Object();
507 // VolumePanel is currently the only client of forceVolumeControlStream() and runs in system
508 // server process so in theory it is not necessary to monitor the client death.
509 // However it is good to be ready for future evolutions.
510 private ForceControlStreamClient mForceControlStreamClient = null;
Jeff Sharkey098d5802012-04-26 17:30:34 -0700511 // Used to play ringtones outside system_server
512 private volatile IRingtonePlayer mRingtonePlayer;
Eric Laurent9bc8358d2011-11-18 16:43:31 -0800513
Eric Laurent4bbcc652012-09-24 14:26:30 -0700514 // Devices for which the volume is fixed and VolumePanel slider should be disabled
Eric Laurent212532b2014-07-21 15:43:18 -0700515 int mFixedVolumeDevices = AudioSystem.DEVICE_OUT_HDMI |
Eric Laurent4bbcc652012-09-24 14:26:30 -0700516 AudioSystem.DEVICE_OUT_DGTL_DOCK_HEADSET |
Eric Laurent212532b2014-07-21 15:43:18 -0700517 AudioSystem.DEVICE_OUT_ANLG_DOCK_HEADSET |
518 AudioSystem.DEVICE_OUT_HDMI_ARC |
519 AudioSystem.DEVICE_OUT_SPDIF |
520 AudioSystem.DEVICE_OUT_AUX_LINE;
Jakub Pawlowskic274fb22018-04-04 10:15:12 -0700521 int mFullVolumeDevices = 0;
Eric Laurent4bbcc652012-09-24 14:26:30 -0700522
Jean-Michel Trivibb6f8712013-05-23 15:02:41 -0700523 private final boolean mMonitorRotation;
Eric Laurentd640bd32012-09-28 18:01:48 -0700524
Eric Laurent7ee1e4f2012-10-26 18:11:21 -0700525 private boolean mDockAudioMediaEnabled = true;
526
Eric Laurent08ed1b92012-11-05 14:54:12 -0800527 private int mDockState = Intent.EXTRA_DOCK_STATE_UNDOCKED;
528
Eric Laurentfde16d52012-12-03 14:42:39 -0800529 // Used when safe volume warning message display is requested by setStreamVolume(). In this
530 // case, the new requested volume, stream type and device are stored in mPendingVolumeCommand
531 // and used later when/if disableSafeMediaVolume() is called.
532 private StreamVolumeCommand mPendingVolumeCommand;
533
Jean-Michel Trivifa9a6982013-06-27 16:22:58 -0700534 private PowerManager.WakeLock mAudioEventWakeLock;
535
536 private final MediaFocusControl mMediaFocusControl;
537
Tomoharu Kasaharaf0fecb12018-09-06 20:04:38 +0900538 // Pre-scale for Bluetooth Absolute Volume
539 private float[] mPrescaleAbsoluteVolume = new float[] {
540 0.5f, // Pre-scale for index 1
541 0.7f, // Pre-scale for index 2
542 0.85f, // Pre-scale for index 3
543 };
544
Julia Reynolds48034f82016-03-09 10:15:16 -0500545 private NotificationManager mNm;
John Spurlock661f2cf2014-11-17 10:29:10 -0500546 private AudioManagerInternal.RingerModeDelegate mRingerModeDelegate;
John Spurlocka48d7792015-03-03 17:35:57 -0500547 private VolumePolicy mVolumePolicy = VolumePolicy.DEFAULT;
John Spurlock07e72432015-03-13 11:46:52 -0400548 private long mLoweredFromNormalToVibrateTime;
John Spurlock661f2cf2014-11-17 10:29:10 -0500549
Phil Weaverf1a9aff2017-03-23 17:21:29 -0700550 // Array of Uids of valid accessibility services to check if caller is one of them
551 private int[] mAccessibilityServiceUids;
552 private final Object mAccessibilityServiceUidsLock = new Object();
553
jiabin39940752018-04-02 18:18:45 -0700554 private int mEncodedSurroundMode;
555 private String mEnabledSurroundFormats;
556 private boolean mSurroundModeChanged;
557
Eric Laurent1c9c1d52018-10-17 10:06:46 -0700558 @GuardedBy("mSettingsLock")
559 private int mAssistantUid;
560
Paul McLean10804eb2015-01-28 11:16:35 -0800561 // Defines the format for the connection "address" for ALSA devices
562 public static String makeAlsaAddressString(int card, int device) {
563 return "card=" + card + ";device=" + device + ";";
564 }
565
Makoto Onukie1aef852015-10-15 17:28:35 -0700566 public static final class Lifecycle extends SystemService {
567 private AudioService mService;
568
569 public Lifecycle(Context context) {
570 super(context);
571 mService = new AudioService(context);
572 }
573
574 @Override
575 public void onStart() {
576 publishBinderService(Context.AUDIO_SERVICE, mService);
577 }
578
579 @Override
580 public void onBootPhase(int phase) {
581 if (phase == SystemService.PHASE_ACTIVITY_MANAGER_READY) {
582 mService.systemReady();
583 }
584 }
585 }
586
Dianne Hackborn3e99f652017-07-05 16:33:56 -0700587 final private IUidObserver mUidObserver = new IUidObserver.Stub() {
588 @Override public void onUidStateChanged(int uid, int procState, long procStateSeq) {
589 }
590
591 @Override public void onUidGone(int uid, boolean disabled) {
592 // Once the uid is no longer running, no need to keep trying to disable its audio.
593 disableAudioForUid(false, uid);
594 }
595
596 @Override public void onUidActive(int uid) throws RemoteException {
597 }
598
599 @Override public void onUidIdle(int uid, boolean disabled) {
600 }
601
602 @Override public void onUidCachedChanged(int uid, boolean cached) {
603 disableAudioForUid(cached, uid);
604 }
605
606 private void disableAudioForUid(boolean disable, int uid) {
607 queueMsgUnderWakeLock(mAudioHandler, MSG_DISABLE_AUDIO_FOR_UID,
608 disable ? 1 : 0 /* arg1 */, uid /* arg2 */,
609 null /* obj */, 0 /* delay */);
610 }
611 };
612
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800613 ///////////////////////////////////////////////////////////////////////////
614 // Construction
615 ///////////////////////////////////////////////////////////////////////////
616
617 /** @hide */
618 public AudioService(Context context) {
619 mContext = context;
620 mContentResolver = context.getContentResolver();
Dianne Hackbornba50b97c2013-04-30 15:04:46 -0700621 mAppOps = (AppOpsManager)context.getSystemService(Context.APP_OPS_SERVICE);
Eric Laurent212532b2014-07-21 15:43:18 -0700622
John Spurlock61560172015-02-06 19:46:04 -0500623 mPlatformType = AudioSystem.getPlatformType(context);
Jared Suttles59820132009-08-13 21:50:52 -0500624
Muyuan Li1ed6df62016-06-18 11:16:52 -0700625 mIsSingleVolume = AudioSystem.isSingleVolume(context);
626
Makoto Onukid45a4a22015-11-02 17:17:38 -0800627 mUserManagerInternal = LocalServices.getService(UserManagerInternal.class);
Sudheer Shankafc46e9b2016-10-21 17:55:27 -0700628 mActivityManagerInternal = LocalServices.getService(ActivityManagerInternal.class);
Makoto Onukid45a4a22015-11-02 17:17:38 -0800629
Jean-Michel Trivic6802222012-04-30 11:15:03 -0700630 PowerManager pm = (PowerManager)context.getSystemService(Context.POWER_SERVICE);
Jean-Michel Trivifa9a6982013-06-27 16:22:58 -0700631 mAudioEventWakeLock = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "handleAudioEvent");
Jean-Michel Trivic6802222012-04-30 11:15:03 -0700632
Mike Digman55272862018-02-20 14:35:17 -0800633 mVibrator = (Vibrator) context.getSystemService(Context.VIBRATOR_SERVICE);
634 mHasVibrator = mVibrator == null ? false : mVibrator.hasVibrator();
Eric Laurentbffc3d12012-05-07 17:43:49 -0700635
François Gaffie0699fec2018-07-09 14:35:10 +0200636 sAudioProductStrategies = new AudioProductStrategies();
François Gaffie9c362102018-09-21 17:43:52 +0200637 sAudioVolumeGroups = new AudioVolumeGroups();
François Gaffie0699fec2018-07-09 14:35:10 +0200638
John Spurlockb6e19e32015-03-10 21:33:44 -0400639 // Initialize volume
Eric Laurent403bd342017-07-11 16:21:44 -0700640 int maxCallVolume = SystemProperties.getInt("ro.config.vc_call_vol_steps", -1);
641 if (maxCallVolume != -1) {
642 MAX_STREAM_VOLUME[AudioSystem.STREAM_VOICE_CALL] = maxCallVolume;
Shuhei Miyazaki89091ba2018-01-11 18:17:04 +0900643 }
644
645 int defaultCallVolume = SystemProperties.getInt("ro.config.vc_call_vol_default", -1);
646 if (defaultCallVolume != -1 &&
647 defaultCallVolume <= MAX_STREAM_VOLUME[AudioSystem.STREAM_VOICE_CALL] &&
648 defaultCallVolume >= MIN_STREAM_VOLUME[AudioSystem.STREAM_VOICE_CALL]) {
649 AudioSystem.DEFAULT_STREAM_VOLUME[AudioSystem.STREAM_VOICE_CALL] = defaultCallVolume;
650 } else {
Eric Laurent403bd342017-07-11 16:21:44 -0700651 AudioSystem.DEFAULT_STREAM_VOLUME[AudioSystem.STREAM_VOICE_CALL] =
652 (maxCallVolume * 3) / 4;
Eric Laurent91377de2014-10-10 15:24:04 -0700653 }
Eric Laurent403bd342017-07-11 16:21:44 -0700654
655 int maxMusicVolume = SystemProperties.getInt("ro.config.media_vol_steps", -1);
656 if (maxMusicVolume != -1) {
657 MAX_STREAM_VOLUME[AudioSystem.STREAM_MUSIC] = maxMusicVolume;
658 }
659
660 int defaultMusicVolume = SystemProperties.getInt("ro.config.media_vol_default", -1);
661 if (defaultMusicVolume != -1 &&
Shuhei Miyazaki89091ba2018-01-11 18:17:04 +0900662 defaultMusicVolume <= MAX_STREAM_VOLUME[AudioSystem.STREAM_MUSIC] &&
663 defaultMusicVolume >= MIN_STREAM_VOLUME[AudioSystem.STREAM_MUSIC]) {
Eric Laurent403bd342017-07-11 16:21:44 -0700664 AudioSystem.DEFAULT_STREAM_VOLUME[AudioSystem.STREAM_MUSIC] = defaultMusicVolume;
665 } else {
Hank Freund45926dc2015-12-11 10:50:45 -0800666 if (isPlatformTelevision()) {
Eric Laurent403bd342017-07-11 16:21:44 -0700667 AudioSystem.DEFAULT_STREAM_VOLUME[AudioSystem.STREAM_MUSIC] =
668 MAX_STREAM_VOLUME[AudioSystem.STREAM_MUSIC] / 4;
Hank Freund45926dc2015-12-11 10:50:45 -0800669 } else {
Eric Laurent403bd342017-07-11 16:21:44 -0700670 AudioSystem.DEFAULT_STREAM_VOLUME[AudioSystem.STREAM_MUSIC] =
671 MAX_STREAM_VOLUME[AudioSystem.STREAM_MUSIC] / 3;
Hank Freund45926dc2015-12-11 10:50:45 -0800672 }
Eric Laurent91377de2014-10-10 15:24:04 -0700673 }
Jared Suttles59820132009-08-13 21:50:52 -0500674
Chris Kuiper09b6c212018-01-03 22:22:13 -0800675 int maxAlarmVolume = SystemProperties.getInt("ro.config.alarm_vol_steps", -1);
676 if (maxAlarmVolume != -1) {
677 MAX_STREAM_VOLUME[AudioSystem.STREAM_ALARM] = maxAlarmVolume;
678 }
679
680 int defaultAlarmVolume = SystemProperties.getInt("ro.config.alarm_vol_default", -1);
681 if (defaultAlarmVolume != -1 &&
682 defaultAlarmVolume <= MAX_STREAM_VOLUME[AudioSystem.STREAM_ALARM]) {
683 AudioSystem.DEFAULT_STREAM_VOLUME[AudioSystem.STREAM_ALARM] = defaultAlarmVolume;
684 } else {
685 // Default is 6 out of 7 (default maximum), so scale accordingly.
686 AudioSystem.DEFAULT_STREAM_VOLUME[AudioSystem.STREAM_ALARM] =
687 6 * MAX_STREAM_VOLUME[AudioSystem.STREAM_ALARM] / 7;
688 }
689
690 int maxSystemVolume = SystemProperties.getInt("ro.config.system_vol_steps", -1);
691 if (maxSystemVolume != -1) {
692 MAX_STREAM_VOLUME[AudioSystem.STREAM_SYSTEM] = maxSystemVolume;
693 }
694
695 int defaultSystemVolume = SystemProperties.getInt("ro.config.system_vol_default", -1);
696 if (defaultSystemVolume != -1 &&
697 defaultSystemVolume <= MAX_STREAM_VOLUME[AudioSystem.STREAM_SYSTEM]) {
698 AudioSystem.DEFAULT_STREAM_VOLUME[AudioSystem.STREAM_SYSTEM] = defaultSystemVolume;
699 } else {
700 // Default is to use maximum.
701 AudioSystem.DEFAULT_STREAM_VOLUME[AudioSystem.STREAM_SYSTEM] =
702 MAX_STREAM_VOLUME[AudioSystem.STREAM_SYSTEM];
703 }
704
Jean-Michel Trivif2b0c112012-07-09 11:59:11 -0700705 sSoundEffectVolumeDb = context.getResources().getInteger(
Jean-Michel Trivic55b3932012-06-05 11:57:59 -0700706 com.android.internal.R.integer.config_soundEffectVolumeDb);
Eric Laurent25101b02011-02-02 09:33:30 -0800707
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800708 createAudioSystemThread();
Eric Laurentdd45d012012-10-08 09:04:34 -0700709
Eric Laurentdfb881f2013-07-18 14:41:39 -0700710 AudioSystem.setErrorCallback(mAudioSystemCallback);
711
John Spurlock5e783732015-02-19 10:28:59 -0500712 boolean cameraSoundForced = readCameraSoundForced();
Eric Laurentdd45d012012-10-08 09:04:34 -0700713 mCameraSoundForced = new Boolean(cameraSoundForced);
714 sendMsg(mAudioHandler,
715 MSG_SET_FORCE_USE,
716 SENDMSG_QUEUE,
717 AudioSystem.FOR_SYSTEM,
718 cameraSoundForced ?
719 AudioSystem.FORCE_SYSTEM_ENFORCED : AudioSystem.FORCE_NONE,
Jean-Michel Trivi011f39e2017-08-19 18:08:06 -0700720 new String("AudioService ctor"),
Eric Laurentdd45d012012-10-08 09:04:34 -0700721 0);
722
hyomin.ohd0446dc2018-10-18 13:58:27 +0900723 mSafeMediaVolumeState = Settings.Global.getInt(mContentResolver,
724 Settings.Global.AUDIO_SAFE_VOLUME_STATE,
725 SAFE_MEDIA_VOLUME_NOT_CONFIGURED);
Eric Laurent05274f32012-11-29 12:48:18 -0800726 // The default safe volume index read here will be replaced by the actual value when
727 // the mcc is read by onConfigureSafeVolume()
728 mSafeMediaVolumeIndex = mContext.getResources().getInteger(
729 com.android.internal.R.integer.config_safe_media_volume_index) * 10;
730
Eric Laurent83a017b2013-03-19 18:15:31 -0700731 mUseFixedVolume = mContext.getResources().getBoolean(
732 com.android.internal.R.bool.config_useFixedVolume);
733
Jean-Michel Trivi58850372018-09-14 16:01:28 -0700734 mDeviceBroker = new AudioDeviceBroker(mContext, this);
735
Eric Laurent24e0d9b2013-10-03 18:15:07 -0700736 // must be called before readPersistedSettings() which needs a valid mStreamVolumeAlias[]
737 // array initialized by updateStreamVolumeAlias()
John Spurlock90874332015-03-10 16:00:54 -0400738 updateStreamVolumeAlias(false /*updateVolumes*/, TAG);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800739 readPersistedSettings();
Eric Laurentc0232482016-03-15 18:19:23 -0700740 readUserRestrictions();
Eric Laurentc1d41662011-07-19 11:21:13 -0700741 mSettingsObserver = new SettingsObserver();
Eric Laurenta553c252009-07-17 12:17:14 -0700742 createStreamStates();
Eric Laurent9f103de2011-09-08 15:04:23 -0700743
Eric Laurentb378a13a2017-07-11 14:08:11 -0700744 // mSafeUsbMediaVolumeIndex must be initialized after createStreamStates() because it
745 // relies on audio policy having correct ranges for volume indexes.
746 mSafeUsbMediaVolumeIndex = getSafeUsbMediaVolumeIndex();
747
Eric Laurente5a351c2017-09-27 20:11:51 -0700748 mPlaybackMonitor =
749 new PlaybackActivityMonitor(context, MAX_STREAM_VOLUME[AudioSystem.STREAM_ALARM]);
750
Jean-Michel Trivi99489cc2017-01-25 19:08:49 -0800751 mMediaFocusControl = new MediaFocusControl(mContext, mPlaybackMonitor);
John Spurlockb6e19e32015-03-10 21:33:44 -0400752
Jean-Michel Trivi66ffacf2017-02-04 17:25:31 -0800753 mRecordMonitor = new RecordingActivityMonitor(mContext);
754
Glenn Kastenfd116ad2013-07-12 17:10:39 -0700755 readAndSetLowRamDevice();
Eric Laurent3891c4c2010-04-20 09:40:57 -0700756
757 // Call setRingerModeInt() to apply correct mute
758 // state on streams affected by ringer mode.
Beverlyd6964762018-02-16 14:07:03 -0500759 mRingerAndZenModeMutedStreams = 0;
John Spurlock661f2cf2014-11-17 10:29:10 -0500760 setRingerModeInt(getRingerModeInternal(), false);
Eric Laurent3891c4c2010-04-20 09:40:57 -0700761
Eric Laurenta553c252009-07-17 12:17:14 -0700762 // Register for device connection intent broadcasts.
763 IntentFilter intentFilter =
Eric Laurentb1fbaac2012-05-29 09:24:28 -0700764 new IntentFilter(BluetoothHeadset.ACTION_AUDIO_STATE_CHANGED);
Jack He8dd33942018-01-17 15:45:12 -0800765 intentFilter.addAction(BluetoothHeadset.ACTION_ACTIVE_DEVICE_CHANGED);
Jaikumar Ganesh82aa7f02010-09-27 17:05:10 -0700766 intentFilter.addAction(Intent.ACTION_DOCK_EVENT);
Eric Laurent950e8cb2011-10-13 08:57:54 -0700767 intentFilter.addAction(Intent.ACTION_SCREEN_ON);
768 intentFilter.addAction(Intent.ACTION_SCREEN_OFF);
Eric Laurentbc0fab1f2012-09-19 11:24:41 -0700769 intentFilter.addAction(Intent.ACTION_USER_SWITCHED);
Fyodor Kupolovb5013302015-04-17 17:59:14 -0700770 intentFilter.addAction(Intent.ACTION_USER_BACKGROUND);
771 intentFilter.addAction(Intent.ACTION_USER_FOREGROUND);
Paul McLeanc837a452014-04-09 09:04:43 -0700772 intentFilter.addAction(UsbManager.ACTION_USB_DEVICE_ATTACHED);
Eric Laurentb70b78a2016-01-13 19:16:04 -0800773 intentFilter.addAction(BluetoothAdapter.ACTION_STATE_CHANGED);
Jean-Michel Trivib2251822019-02-06 07:32:06 -0800774 intentFilter.addAction(Intent.ACTION_PACKAGES_SUSPENDED);
Jean-Michel Trivif26f0172012-04-25 16:23:20 -0700775
Eric Laurentd640bd32012-09-28 18:01:48 -0700776 intentFilter.addAction(Intent.ACTION_CONFIGURATION_CHANGED);
Jean-Michel Trivibb6f8712013-05-23 15:02:41 -0700777 mMonitorRotation = SystemProperties.getBoolean("ro.audio.monitorRotation", false);
778 if (mMonitorRotation) {
Jean-Michel Trivi24806db2015-10-01 15:00:59 -0700779 RotationHelper.init(mContext, mAudioHandler);
Jean-Michel Trivibb6f8712013-05-23 15:02:41 -0700780 }
Jean-Michel Trivif26f0172012-04-25 16:23:20 -0700781
Marco Nelissenfb6df0b2017-02-15 15:25:24 -0800782 intentFilter.addAction(AudioEffect.ACTION_OPEN_AUDIO_EFFECT_CONTROL_SESSION);
783 intentFilter.addAction(AudioEffect.ACTION_CLOSE_AUDIO_EFFECT_CONTROL_SESSION);
784
Fyodor Kupolovb5013302015-04-17 17:59:14 -0700785 context.registerReceiverAsUser(mReceiver, UserHandle.ALL, intentFilter, null, null);
Jared Suttles59820132009-08-13 21:50:52 -0500786
RoboErik0dac35a2014-08-12 15:48:49 -0700787 LocalServices.addService(AudioManagerInternal.class, new AudioServiceInternal());
Makoto Onukid45a4a22015-11-02 17:17:38 -0800788
789 mUserManagerInternal.addUserRestrictionsListener(mUserRestrictionsListener);
Jean-Michel Trivid3c71f02015-12-07 11:59:31 -0800790
791 mRecordMonitor.initMonitor();
Tomoharu Kasaharaf0fecb12018-09-06 20:04:38 +0900792
793 final float[] preScale = new float[3];
794 preScale[0] = mContext.getResources().getFraction(
795 com.android.internal.R.fraction.config_prescaleAbsoluteVolume_index1,
796 1, 1);
797 preScale[1] = mContext.getResources().getFraction(
798 com.android.internal.R.fraction.config_prescaleAbsoluteVolume_index2,
799 1, 1);
800 preScale[2] = mContext.getResources().getFraction(
801 com.android.internal.R.fraction.config_prescaleAbsoluteVolume_index3,
802 1, 1);
803 for (int i = 0; i < preScale.length; i++) {
804 if (0.0f <= preScale[i] && preScale[i] <= 1.0f) {
805 mPrescaleAbsoluteVolume[i] = preScale[i];
806 }
807 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800808 }
809
Eric Laurent4a5eeb92014-05-06 10:49:04 -0700810 public void systemReady() {
811 sendMsg(mAudioHandler, MSG_SYSTEM_READY, SENDMSG_QUEUE,
812 0, 0, null, 0);
Dianne Hackborn3e3600e2017-08-31 11:15:26 -0700813 if (false) {
814 // This is turned off for now, because it is racy and thus causes apps to break.
815 // Currently banning a uid means that if an app tries to start playing an audio
816 // stream, that will be preventing, and unbanning it will not allow that stream
817 // to resume. However these changes in uid state are racy with what the app is doing,
818 // so that after taking a process out of the cached state we can't guarantee that
819 // we will unban the uid before the app actually tries to start playing audio.
820 // (To do that, the activity manager would need to wait until it knows for sure
821 // that the ban has been removed, before telling the app to do whatever it is
822 // supposed to do that caused it to go out of the cached state.)
823 try {
824 ActivityManager.getService().registerUidObserver(mUidObserver,
825 ActivityManager.UID_OBSERVER_CACHED | ActivityManager.UID_OBSERVER_GONE,
826 ActivityManager.PROCESS_STATE_UNKNOWN, null);
827 } catch (RemoteException e) {
828 // ignored; both services live in system_server
829 }
Dianne Hackborn3e99f652017-07-05 16:33:56 -0700830 }
Eric Laurent4a5eeb92014-05-06 10:49:04 -0700831 }
832
833 public void onSystemReady() {
834 mSystemReady = true;
835 sendMsg(mAudioHandler, MSG_LOAD_SOUND_EFFECTS, SENDMSG_QUEUE,
836 0, 0, null, 0);
837
Jean-Michel Trivi58850372018-09-14 16:01:28 -0700838 mDeviceBroker.onSystemReady();
Eric Laurent4a5eeb92014-05-06 10:49:04 -0700839
Jeff Sharkey73ea0ae2016-08-10 17:30:38 -0600840 if (mContext.getPackageManager().hasSystemFeature(PackageManager.FEATURE_HDMI_CEC)) {
Shubangc480a712018-06-11 18:02:42 -0700841 synchronized (mHdmiClientLock) {
842 mHdmiManager = mContext.getSystemService(HdmiControlManager.class);
Eric Laurent212532b2014-07-21 15:43:18 -0700843 mHdmiTvClient = mHdmiManager.getTvClient();
Jungshik Jangc9ff9682014-09-15 17:41:06 +0900844 if (mHdmiTvClient != null) {
845 mFixedVolumeDevices &= ~AudioSystem.DEVICE_ALL_HDMI_SYSTEM_AUDIO_AND_SPEAKER;
846 }
Eric Laurent212532b2014-07-21 15:43:18 -0700847 mHdmiPlaybackClient = mHdmiManager.getPlaybackClient();
848 mHdmiCecSink = false;
Shubangc480a712018-06-11 18:02:42 -0700849 mHdmiAudioSystemClient = mHdmiManager.getAudioSystemClient();
Eric Laurent212532b2014-07-21 15:43:18 -0700850 }
851 }
Wonsik Kim7f4342e2014-07-20 23:04:59 +0900852
Julia Reynolds48034f82016-03-09 10:15:16 -0500853 mNm = (NotificationManager) mContext.getSystemService(Context.NOTIFICATION_SERVICE);
854
Eric Laurent4a5eeb92014-05-06 10:49:04 -0700855 sendMsg(mAudioHandler,
856 MSG_CONFIGURE_SAFE_MEDIA_VOLUME_FORCED,
857 SENDMSG_REPLACE,
858 0,
859 0,
John Spurlock90874332015-03-10 16:00:54 -0400860 TAG,
Eric Laurent03332ab2017-02-09 18:29:15 -0800861 SystemProperties.getBoolean("audio.safemedia.bypass", false) ?
862 0 : SAFE_VOLUME_CONFIGURE_TIMEOUT_MS);
Jean-Michel Trivi873cc452014-09-11 17:25:09 -0700863
Jean-Michel Trivicfa55532017-01-18 11:17:51 -0800864 initA11yMonitoring();
Eric Laurent0867bed2015-05-20 14:49:08 -0700865 onIndicateSystemReady();
866 }
867
868 void onIndicateSystemReady() {
869 if (AudioSystem.systemReady() == AudioSystem.SUCCESS) {
870 return;
871 }
872 sendMsg(mAudioHandler,
873 MSG_INDICATE_SYSTEM_READY,
874 SENDMSG_REPLACE,
875 0,
876 0,
877 null,
878 INDICATE_SYSTEM_READY_RETRY_DELAY_MS);
879 }
880
Andy Hunged0ea402015-10-30 14:11:46 -0700881 public void onAudioServerDied() {
Eric Laurent0867bed2015-05-20 14:49:08 -0700882 if (!mSystemReady ||
883 (AudioSystem.checkAudioFlinger() != AudioSystem.AUDIO_STATUS_OK)) {
Andy Hunged0ea402015-10-30 14:11:46 -0700884 Log.e(TAG, "Audioserver died.");
885 sendMsg(mAudioHandler, MSG_AUDIO_SERVER_DIED, SENDMSG_NOOP, 0, 0,
Eric Laurent0867bed2015-05-20 14:49:08 -0700886 null, 500);
887 return;
888 }
Andy Hunged0ea402015-10-30 14:11:46 -0700889 Log.e(TAG, "Audioserver started.");
Eric Laurent0867bed2015-05-20 14:49:08 -0700890
891 // indicate to audio HAL that we start the reconfiguration phase after a media
892 // server crash
893 // Note that we only execute this when the media server
894 // process restarts after a crash, not the first time it is started.
895 AudioSystem.setParameters("restarting=true");
896
897 readAndSetLowRamDevice();
898
Jean-Michel Trivi58850372018-09-14 16:01:28 -0700899 // Restore device connection states, BT state
900 mDeviceBroker.onAudioServerDied();
901
Eric Laurent0867bed2015-05-20 14:49:08 -0700902 // Restore call state
Jean-Michel Trivi011f39e2017-08-19 18:08:06 -0700903 if (AudioSystem.setPhoneState(mMode) == AudioSystem.AUDIO_STATUS_OK) {
904 mModeLogger.log(new AudioEventLogger.StringEvent(
905 "onAudioServerDied causes setPhoneState(" + AudioSystem.modeToString(mMode) + ")"));
906 }
Eric Laurent0867bed2015-05-20 14:49:08 -0700907
Jean-Michel Trivi8719a1d2017-11-06 11:52:51 -0800908 final int forSys;
909 synchronized (mSettingsLock) {
910 forSys = mCameraSoundForced ?
911 AudioSystem.FORCE_SYSTEM_ENFORCED : AudioSystem.FORCE_NONE;
912 }
Jean-Michel Trivi58850372018-09-14 16:01:28 -0700913
914 mDeviceBroker.setForceUse_Async(AudioSystem.FOR_SYSTEM, forSys, "onAudioServerDied");
Eric Laurent0867bed2015-05-20 14:49:08 -0700915
916 // Restore stream volumes
917 int numStreamTypes = AudioSystem.getNumStreamTypes();
918 for (int streamType = numStreamTypes - 1; streamType >= 0; streamType--) {
919 VolumeStreamState streamState = mStreamStates[streamType];
Eric Laurente4381ec2015-10-29 17:52:48 -0700920 AudioSystem.initStreamVolume(
921 streamType, streamState.mIndexMin / 10, streamState.mIndexMax / 10);
Eric Laurent0867bed2015-05-20 14:49:08 -0700922
923 streamState.applyAllVolumes();
924 }
925
Andy Hungf04b84d2015-12-18 17:33:27 -0800926 // Restore mono mode
Andy Hung7b98e9a2016-02-25 18:34:50 -0800927 updateMasterMono(mContentResolver);
Andy Hungf04b84d2015-12-18 17:33:27 -0800928
Edward Savage-Jones35c292f2017-01-13 09:04:34 +0100929 // Restore audio balance
930 updateMasterBalance(mContentResolver);
931
Eric Laurent0867bed2015-05-20 14:49:08 -0700932 // Restore ringer mode
933 setRingerModeInt(getRingerModeInternal(), false);
934
Mikhail Naganovb668bc62018-02-13 13:46:38 -0800935 // Reset device rotation (if monitored for this device)
Eric Laurent0867bed2015-05-20 14:49:08 -0700936 if (mMonitorRotation) {
Jean-Michel Trivi24806db2015-10-01 15:00:59 -0700937 RotationHelper.updateOrientation();
Eric Laurent0867bed2015-05-20 14:49:08 -0700938 }
939
Eric Laurent0867bed2015-05-20 14:49:08 -0700940 synchronized (mSettingsLock) {
Jean-Michel Trivi011f39e2017-08-19 18:08:06 -0700941 final int forDock = mDockAudioMediaEnabled ?
942 AudioSystem.FORCE_ANALOG_DOCK : AudioSystem.FORCE_NONE;
Jean-Michel Trivi58850372018-09-14 16:01:28 -0700943 mDeviceBroker.setForceUse_Async(AudioSystem.FOR_DOCK, forDock, "onAudioServerDied");
Jean-Michel Trivi011f39e2017-08-19 18:08:06 -0700944 sendEncodedSurroundMode(mContentResolver, "onAudioServerDied");
jiabin39940752018-04-02 18:18:45 -0700945 sendEnabledSurroundFormats(mContentResolver, true);
Eric Laurent1c9c1d52018-10-17 10:06:46 -0700946 updateAssistantUId(true);
947 }
948 synchronized (mAccessibilityServiceUidsLock) {
949 AudioSystem.setA11yServicesUids(mAccessibilityServiceUids);
Eric Laurent0867bed2015-05-20 14:49:08 -0700950 }
Shubangc480a712018-06-11 18:02:42 -0700951 synchronized (mHdmiClientLock) {
952 if (mHdmiManager != null && mHdmiTvClient != null) {
953 setHdmiSystemAudioSupported(mHdmiSystemAudioSupported);
Eric Laurent0867bed2015-05-20 14:49:08 -0700954 }
955 }
956
957 synchronized (mAudioPolicies) {
958 for (AudioPolicyProxy policy : mAudioPolicies.values()) {
959 policy.connectMixes();
960 }
961 }
962
963 onIndicateSystemReady();
964 // indicate the end of reconfiguration phase to audio HAL
965 AudioSystem.setParameters("restarting=false");
Eric Laurent1d3cdce2018-01-20 10:31:21 -0800966
967 sendMsg(mAudioHandler, MSG_DISPATCH_AUDIO_SERVER_STATE,
968 SENDMSG_QUEUE, 1, 0, null, 0);
969 }
970
971 private void onDispatchAudioServerStateChange(boolean state) {
972 synchronized (mAudioServerStateListeners) {
973 for (AsdProxy asdp : mAudioServerStateListeners.values()) {
974 try {
975 asdp.callback().dispatchAudioServerStateChange(state);
976 } catch (RemoteException e) {
977 Log.w(TAG, "Could not call dispatchAudioServerStateChange()", e);
978 }
979 }
980 }
Eric Laurent4a5eeb92014-05-06 10:49:04 -0700981 }
982
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800983 private void createAudioSystemThread() {
984 mAudioSystemThread = new AudioSystemThread();
985 mAudioSystemThread.start();
986 waitForAudioHandlerCreation();
987 }
988
989 /** Waits for the volume handler to be created by the other thread. */
990 private void waitForAudioHandlerCreation() {
991 synchronized(this) {
992 while (mAudioHandler == null) {
993 try {
994 // Wait for mAudioHandler to be set by the other thread
995 wait();
996 } catch (InterruptedException e) {
997 Log.e(TAG, "Interrupted while waiting on volume handler.");
998 }
999 }
1000 }
1001 }
1002
François Gaffie0699fec2018-07-09 14:35:10 +02001003 /**
1004 * @return the {@link android.media.audiopolicy.AudioProductStrategies} discovered from the
1005 * platform configuration file.
1006 */
1007 public @NonNull AudioProductStrategies getAudioProductStrategies() {
1008 return sAudioProductStrategies;
1009 }
1010
François Gaffie9c362102018-09-21 17:43:52 +02001011 /**
1012 * @return the {@link android.media.audiopolicy.AudioVolumeGroups} discovered from the
1013 * platform configuration file.
1014 */
1015 public @NonNull AudioVolumeGroups listAudioVolumeGroups() {
1016 return sAudioVolumeGroups;
1017 }
1018
Eric Laurent24482012012-05-10 09:41:17 -07001019 private void checkAllAliasStreamVolumes() {
Jean-Michel Trivi085346a2018-02-14 10:48:51 -08001020 synchronized (mSettingsLock) {
1021 synchronized (VolumeStreamState.class) {
1022 int numStreamTypes = AudioSystem.getNumStreamTypes();
1023 for (int streamType = 0; streamType < numStreamTypes; streamType++) {
1024 mStreamStates[streamType]
1025 .setAllIndexes(mStreamStates[mStreamVolumeAlias[streamType]], TAG);
1026 // apply stream volume
1027 if (!mStreamStates[streamType].mIsMuted) {
1028 mStreamStates[streamType].applyAllVolumes();
1029 }
Eric Laurent8fa4d6f2014-10-30 14:13:03 -07001030 }
Eric Laurent24482012012-05-10 09:41:17 -07001031 }
1032 }
1033 }
1034
Jean-Michel Trivi58850372018-09-14 16:01:28 -07001035 /**
1036 * Called from AudioDeviceBroker when DEVICE_OUT_HDMI is connected or disconnected.
1037 */
1038 /*package*/ void checkVolumeCecOnHdmiConnection(int state, String caller) {
1039 if (state != 0) {
1040 // DEVICE_OUT_HDMI is now connected
1041 if ((AudioSystem.DEVICE_OUT_HDMI & mSafeMediaVolumeDevices) != 0) {
1042 sendMsg(mAudioHandler,
1043 MSG_CHECK_MUSIC_ACTIVE,
1044 SENDMSG_REPLACE,
1045 0,
1046 0,
1047 caller,
1048 MUSIC_ACTIVE_POLL_PERIOD_MS);
1049 }
1050
1051 if (isPlatformTelevision()) {
1052 mFixedVolumeDevices |= AudioSystem.DEVICE_OUT_HDMI;
1053 checkAllFixedVolumeDevices();
1054 synchronized (mHdmiClientLock) {
1055 if (mHdmiManager != null && mHdmiPlaybackClient != null) {
1056 mHdmiCecSink = false;
1057 mHdmiPlaybackClient.queryDisplayStatus(mHdmiDisplayStatusCallback);
1058 }
1059 }
1060 }
1061 sendEnabledSurroundFormats(mContentResolver, true);
1062 } else {
1063 // DEVICE_OUT_HDMI disconnected
1064 if (isPlatformTelevision()) {
1065 synchronized (mHdmiClientLock) {
1066 if (mHdmiManager != null) {
1067 mHdmiCecSink = false;
1068 }
1069 }
1070 }
1071 }
1072 }
1073
Eric Laurent212532b2014-07-21 15:43:18 -07001074 private void checkAllFixedVolumeDevices()
1075 {
1076 int numStreamTypes = AudioSystem.getNumStreamTypes();
1077 for (int streamType = 0; streamType < numStreamTypes; streamType++) {
1078 mStreamStates[streamType].checkFixedVolumeDevices();
1079 }
1080 }
1081
Jean-Michel Triviba5270b2014-10-01 17:49:29 -07001082 private void checkAllFixedVolumeDevices(int streamType) {
1083 mStreamStates[streamType].checkFixedVolumeDevices();
1084 }
1085
John Spurlockb6e19e32015-03-10 21:33:44 -04001086 private void checkMuteAffectedStreams() {
1087 // any stream with a min level > 0 is not muteable by definition
Tomoharu Kasaharaa0d0c542019-01-18 20:04:38 +09001088 // STREAM_VOICE_CALL and STREAM_BLUETOOTH_SCO can be muted by applications
1089 // that has the the MODIFY_PHONE_STATE permission.
John Spurlockb6e19e32015-03-10 21:33:44 -04001090 for (int i = 0; i < mStreamStates.length; i++) {
1091 final VolumeStreamState vss = mStreamStates[i];
Nadav Bar6b7751d2017-12-24 16:03:08 +02001092 if (vss.mIndexMin > 0 &&
Tomoharu Kasaharaa0d0c542019-01-18 20:04:38 +09001093 (vss.mStreamType != AudioSystem.STREAM_VOICE_CALL &&
1094 vss.mStreamType != AudioSystem.STREAM_BLUETOOTH_SCO)) {
John Spurlockb6e19e32015-03-10 21:33:44 -04001095 mMuteAffectedStreams &= ~(1 << vss.mStreamType);
1096 }
1097 }
1098 }
1099
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001100 private void createStreamStates() {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001101 int numStreamTypes = AudioSystem.getNumStreamTypes();
1102 VolumeStreamState[] streams = mStreamStates = new VolumeStreamState[numStreamTypes];
1103
1104 for (int i = 0; i < numStreamTypes; i++) {
Jean-Michel Trivia53b7052017-04-12 18:27:01 -07001105 streams[i] =
1106 new VolumeStreamState(System.VOLUME_SETTINGS_INT[mStreamVolumeAlias[i]], i);
Eric Laurenta553c252009-07-17 12:17:14 -07001107 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001108
Eric Laurent212532b2014-07-21 15:43:18 -07001109 checkAllFixedVolumeDevices();
Eric Laurent24482012012-05-10 09:41:17 -07001110 checkAllAliasStreamVolumes();
John Spurlockb6e19e32015-03-10 21:33:44 -04001111 checkMuteAffectedStreams();
Eric Laurent403bd342017-07-11 16:21:44 -07001112 updateDefaultVolumes();
1113 }
1114
1115 // Update default indexes from aliased streams. Must be called after mStreamStates is created
1116 private void updateDefaultVolumes() {
1117 for (int stream = 0; stream < mStreamStates.length; stream++) {
1118 if (stream != mStreamVolumeAlias[stream]) {
1119 AudioSystem.DEFAULT_STREAM_VOLUME[stream] = rescaleIndex(
1120 AudioSystem.DEFAULT_STREAM_VOLUME[mStreamVolumeAlias[stream]],
1121 mStreamVolumeAlias[stream],
1122 stream);
1123 }
1124 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001125 }
1126
Eric Laurentbffc3d12012-05-07 17:43:49 -07001127 private void dumpStreamStates(PrintWriter pw) {
1128 pw.println("\nStream volumes (device: index)");
1129 int numStreamTypes = AudioSystem.getNumStreamTypes();
1130 for (int i = 0; i < numStreamTypes; i++) {
John Spurlock61560172015-02-06 19:46:04 -05001131 pw.println("- " + AudioSystem.STREAM_NAMES[i] + ":");
Eric Laurentbffc3d12012-05-07 17:43:49 -07001132 mStreamStates[i].dump(pw);
1133 pw.println("");
1134 }
Eric Laurentdd45d012012-10-08 09:04:34 -07001135 pw.print("\n- mute affected streams = 0x");
1136 pw.println(Integer.toHexString(mMuteAffectedStreams));
Eric Laurentbffc3d12012-05-07 17:43:49 -07001137 }
1138
John Spurlock90874332015-03-10 16:00:54 -04001139 private void updateStreamVolumeAlias(boolean updateVolumes, String caller) {
Eric Laurent6d517662012-04-23 18:42:39 -07001140 int dtmfStreamAlias;
Jean-Michel Triviac487672016-11-11 10:05:18 -08001141 final int a11yStreamAlias = sIndependentA11yVolume ?
1142 AudioSystem.STREAM_ACCESSIBILITY : AudioSystem.STREAM_MUSIC;
Eric Laurent212532b2014-07-21 15:43:18 -07001143
Muyuan Li1ed6df62016-06-18 11:16:52 -07001144 if (mIsSingleVolume) {
Eric Laurent212532b2014-07-21 15:43:18 -07001145 mStreamVolumeAlias = STREAM_VOLUME_ALIAS_TELEVISION;
1146 dtmfStreamAlias = AudioSystem.STREAM_MUSIC;
Muyuan Li1ed6df62016-06-18 11:16:52 -07001147 } else {
1148 switch (mPlatformType) {
1149 case AudioSystem.PLATFORM_VOICE:
1150 mStreamVolumeAlias = STREAM_VOLUME_ALIAS_VOICE;
1151 dtmfStreamAlias = AudioSystem.STREAM_RING;
1152 break;
1153 default:
1154 mStreamVolumeAlias = STREAM_VOLUME_ALIAS_DEFAULT;
1155 dtmfStreamAlias = AudioSystem.STREAM_MUSIC;
1156 }
Eric Laurent6d517662012-04-23 18:42:39 -07001157 }
Eric Laurent212532b2014-07-21 15:43:18 -07001158
Muyuan Li1ed6df62016-06-18 11:16:52 -07001159 if (mIsSingleVolume) {
Eric Laurent212532b2014-07-21 15:43:18 -07001160 mRingerModeAffectedStreams = 0;
Eric Laurent24e0d9b2013-10-03 18:15:07 -07001161 } else {
Eric Laurent212532b2014-07-21 15:43:18 -07001162 if (isInCommunication()) {
1163 dtmfStreamAlias = AudioSystem.STREAM_VOICE_CALL;
1164 mRingerModeAffectedStreams &= ~(1 << AudioSystem.STREAM_DTMF);
1165 } else {
1166 mRingerModeAffectedStreams |= (1 << AudioSystem.STREAM_DTMF);
1167 }
Eric Laurent6d517662012-04-23 18:42:39 -07001168 }
Eric Laurent212532b2014-07-21 15:43:18 -07001169
Eric Laurent6d517662012-04-23 18:42:39 -07001170 mStreamVolumeAlias[AudioSystem.STREAM_DTMF] = dtmfStreamAlias;
Jean-Michel Trivi170a0ee2017-04-14 18:13:26 -07001171 mStreamVolumeAlias[AudioSystem.STREAM_ACCESSIBILITY] = a11yStreamAlias;
Jean-Michel Triviac487672016-11-11 10:05:18 -08001172
Eric Laurent403bd342017-07-11 16:21:44 -07001173 if (updateVolumes && mStreamStates != null) {
1174 updateDefaultVolumes();
1175
Jean-Michel Trivi085346a2018-02-14 10:48:51 -08001176 synchronized (mSettingsLock) {
1177 synchronized (VolumeStreamState.class) {
1178 mStreamStates[AudioSystem.STREAM_DTMF]
1179 .setAllIndexes(mStreamStates[dtmfStreamAlias], caller);
1180 mStreamStates[AudioSystem.STREAM_ACCESSIBILITY].mVolumeIndexSettingName =
1181 System.VOLUME_SETTINGS_INT[a11yStreamAlias];
1182 mStreamStates[AudioSystem.STREAM_ACCESSIBILITY].setAllIndexes(
1183 mStreamStates[a11yStreamAlias], caller);
Jean-Michel Trivie05eef82018-03-08 18:56:34 -08001184 mStreamStates[AudioSystem.STREAM_ACCESSIBILITY].refreshRange(
1185 mStreamVolumeAlias[AudioSystem.STREAM_ACCESSIBILITY]);
Jean-Michel Trivi085346a2018-02-14 10:48:51 -08001186 }
1187 }
Jean-Michel Trivi170a0ee2017-04-14 18:13:26 -07001188 if (sIndependentA11yVolume) {
1189 // restore the a11y values from the settings
1190 mStreamStates[AudioSystem.STREAM_ACCESSIBILITY].readSettings();
1191 }
1192
Eric Laurent24e0d9b2013-10-03 18:15:07 -07001193 // apply stream mute states according to new value of mRingerModeAffectedStreams
John Spurlock661f2cf2014-11-17 10:29:10 -05001194 setRingerModeInt(getRingerModeInternal(), false);
Eric Laurent6d517662012-04-23 18:42:39 -07001195 sendMsg(mAudioHandler,
1196 MSG_SET_ALL_VOLUMES,
1197 SENDMSG_QUEUE,
1198 0,
1199 0,
1200 mStreamStates[AudioSystem.STREAM_DTMF], 0);
Jean-Michel Triviac487672016-11-11 10:05:18 -08001201 sendMsg(mAudioHandler,
1202 MSG_SET_ALL_VOLUMES,
1203 SENDMSG_QUEUE,
1204 0,
1205 0,
1206 mStreamStates[AudioSystem.STREAM_ACCESSIBILITY], 0);
Eric Laurent6d517662012-04-23 18:42:39 -07001207 }
1208 }
1209
Eric Laurent7ee1e4f2012-10-26 18:11:21 -07001210 private void readDockAudioSettings(ContentResolver cr)
1211 {
1212 mDockAudioMediaEnabled = Settings.Global.getInt(
Eric Laurent5ba0ffa02012-10-29 12:31:09 -07001213 cr, Settings.Global.DOCK_AUDIO_MEDIA_ENABLED, 0) == 1;
Eric Laurent7ee1e4f2012-10-26 18:11:21 -07001214
Eric Laurent7ee1e4f2012-10-26 18:11:21 -07001215 sendMsg(mAudioHandler,
1216 MSG_SET_FORCE_USE,
1217 SENDMSG_QUEUE,
1218 AudioSystem.FOR_DOCK,
1219 mDockAudioMediaEnabled ?
1220 AudioSystem.FORCE_ANALOG_DOCK : AudioSystem.FORCE_NONE,
Jean-Michel Trivi011f39e2017-08-19 18:08:06 -07001221 new String("readDockAudioSettings"),
Eric Laurent7ee1e4f2012-10-26 18:11:21 -07001222 0);
1223 }
1224
Phil Burkac0f7042016-02-24 12:19:08 -08001225
Andy Hung7b98e9a2016-02-25 18:34:50 -08001226 private void updateMasterMono(ContentResolver cr)
1227 {
1228 final boolean masterMono = System.getIntForUser(
1229 cr, System.MASTER_MONO, 0 /* default */, UserHandle.USER_CURRENT) == 1;
1230 if (DEBUG_VOL) {
1231 Log.d(TAG, String.format("Master mono %b", masterMono));
1232 }
1233 AudioSystem.setMasterMono(masterMono);
1234 }
1235
Edward Savage-Jones35c292f2017-01-13 09:04:34 +01001236 private void updateMasterBalance(ContentResolver cr) {
1237 final float masterBalance = System.getFloatForUser(
1238 cr, System.MASTER_BALANCE, 0.f /* default */, UserHandle.USER_CURRENT);
1239 if (DEBUG_VOL) {
1240 Log.d(TAG, String.format("Master balance %f", masterBalance));
1241 }
1242 if (AudioSystem.setMasterBalance(masterBalance) != 0) {
1243 Log.e(TAG, String.format("setMasterBalance failed for %f", masterBalance));
1244 }
1245 }
1246
Jean-Michel Trivi011f39e2017-08-19 18:08:06 -07001247 private void sendEncodedSurroundMode(ContentResolver cr, String eventSource)
Phil Burkac0f7042016-02-24 12:19:08 -08001248 {
Jean-Michel Trivi58850372018-09-14 16:01:28 -07001249 final int encodedSurroundMode = Settings.Global.getInt(
Phil Burkac0f7042016-02-24 12:19:08 -08001250 cr, Settings.Global.ENCODED_SURROUND_OUTPUT,
1251 Settings.Global.ENCODED_SURROUND_OUTPUT_AUTO);
Jean-Michel Trivi011f39e2017-08-19 18:08:06 -07001252 sendEncodedSurroundMode(encodedSurroundMode, eventSource);
Phil Burkac0f7042016-02-24 12:19:08 -08001253 }
1254
Jean-Michel Trivi011f39e2017-08-19 18:08:06 -07001255 private void sendEncodedSurroundMode(int encodedSurroundMode, String eventSource)
Phil Burkac0f7042016-02-24 12:19:08 -08001256 {
1257 // initialize to guaranteed bad value
1258 int forceSetting = AudioSystem.NUM_FORCE_CONFIG;
1259 switch (encodedSurroundMode) {
1260 case Settings.Global.ENCODED_SURROUND_OUTPUT_AUTO:
1261 forceSetting = AudioSystem.FORCE_NONE;
1262 break;
1263 case Settings.Global.ENCODED_SURROUND_OUTPUT_NEVER:
1264 forceSetting = AudioSystem.FORCE_ENCODED_SURROUND_NEVER;
1265 break;
1266 case Settings.Global.ENCODED_SURROUND_OUTPUT_ALWAYS:
1267 forceSetting = AudioSystem.FORCE_ENCODED_SURROUND_ALWAYS;
1268 break;
jiabin39940752018-04-02 18:18:45 -07001269 case Settings.Global.ENCODED_SURROUND_OUTPUT_MANUAL:
1270 forceSetting = AudioSystem.FORCE_ENCODED_SURROUND_MANUAL;
1271 break;
Phil Burkac0f7042016-02-24 12:19:08 -08001272 default:
1273 Log.e(TAG, "updateSurroundSoundSettings: illegal value "
1274 + encodedSurroundMode);
1275 break;
1276 }
1277 if (forceSetting != AudioSystem.NUM_FORCE_CONFIG) {
Jean-Michel Trivi58850372018-09-14 16:01:28 -07001278 mDeviceBroker.setForceUse_Async(AudioSystem.FOR_ENCODED_SURROUND, forceSetting,
1279 eventSource);
Phil Burkac0f7042016-02-24 12:19:08 -08001280 }
1281 }
1282
jiabin39940752018-04-02 18:18:45 -07001283 private void sendEnabledSurroundFormats(ContentResolver cr, boolean forceUpdate) {
1284 if (mEncodedSurroundMode != Settings.Global.ENCODED_SURROUND_OUTPUT_MANUAL) {
1285 // Manually enable surround formats only when the setting is in manual mode.
1286 return;
1287 }
1288 String enabledSurroundFormats = Settings.Global.getString(
1289 cr, Settings.Global.ENCODED_SURROUND_OUTPUT_ENABLED_FORMATS);
jiabin6db5f862018-05-17 10:33:09 -07001290 if (enabledSurroundFormats == null) {
1291 // Never allow enabledSurroundFormats as a null, which could happen when
1292 // ENCODED_SURROUND_OUTPUT_ENABLED_FORMATS is not appear in settings DB.
1293 enabledSurroundFormats = "";
1294 }
jiabin39940752018-04-02 18:18:45 -07001295 if (!forceUpdate && TextUtils.equals(enabledSurroundFormats, mEnabledSurroundFormats)) {
1296 // Update enabled surround formats to AudioPolicyManager only when forceUpdate
1297 // is true or enabled surround formats changed.
1298 return;
1299 }
1300
1301 mEnabledSurroundFormats = enabledSurroundFormats;
1302 String[] surroundFormats = TextUtils.split(enabledSurroundFormats, ",");
1303 ArrayList<Integer> formats = new ArrayList<>();
1304 for (String format : surroundFormats) {
1305 try {
1306 int audioFormat = Integer.valueOf(format);
1307 boolean isSurroundFormat = false;
1308 for (int sf : AudioFormat.SURROUND_SOUND_ENCODING) {
1309 if (sf == audioFormat) {
1310 isSurroundFormat = true;
1311 break;
1312 }
1313 }
1314 if (isSurroundFormat && !formats.contains(audioFormat)) {
1315 formats.add(audioFormat);
1316 }
1317 } catch (Exception e) {
1318 Log.e(TAG, "Invalid enabled surround format:" + format);
1319 }
1320 }
1321 // Set filtered surround formats to settings DB in case
1322 // there are invalid surround formats in original settings.
1323 Settings.Global.putString(mContext.getContentResolver(),
1324 Settings.Global.ENCODED_SURROUND_OUTPUT_ENABLED_FORMATS,
1325 TextUtils.join(",", formats));
1326 sendMsg(mAudioHandler, MSG_ENABLE_SURROUND_FORMATS, SENDMSG_QUEUE, 0, 0, formats, 0);
1327 }
1328
1329 private void onEnableSurroundFormats(ArrayList<Integer> enabledSurroundFormats) {
1330 // Set surround format enabled accordingly.
1331 for (int surroundFormat : AudioFormat.SURROUND_SOUND_ENCODING) {
1332 boolean enabled = enabledSurroundFormats.contains(surroundFormat);
1333 int ret = AudioSystem.setSurroundFormatEnabled(surroundFormat, enabled);
1334 Log.i(TAG, "enable surround format:" + surroundFormat + " " + enabled + " " + ret);
1335 }
1336 }
1337
Eric Laurent1c9c1d52018-10-17 10:06:46 -07001338 @GuardedBy("mSettingsLock")
1339 private void updateAssistantUId(boolean forceUpdate) {
1340 int assistantUid = 0;
1341
1342 // Consider assistants in the following order of priority:
1343 // 1) voice interaction service
1344 // 2) assistant
1345 String assistantName = Settings.Secure.getStringForUser(
1346 mContentResolver,
1347 Settings.Secure.VOICE_INTERACTION_SERVICE, UserHandle.USER_CURRENT);
1348 if (TextUtils.isEmpty(assistantName)) {
1349 assistantName = Settings.Secure.getStringForUser(
1350 mContentResolver,
1351 Settings.Secure.ASSISTANT, UserHandle.USER_CURRENT);
1352 }
1353 if (!TextUtils.isEmpty(assistantName)) {
1354 String packageName = ComponentName.unflattenFromString(assistantName).getPackageName();
1355 if (!TextUtils.isEmpty(packageName)) {
1356 try {
1357 assistantUid = mContext.getPackageManager().getPackageUid(packageName, 0);
1358 } catch (PackageManager.NameNotFoundException e) {
1359 Log.e(TAG,
1360 "updateAssistantUId() could not find UID for package: " + packageName);
1361 }
1362 }
1363 }
1364
1365 if (assistantUid != mAssistantUid || forceUpdate) {
1366 AudioSystem.setAssistantUid(assistantUid);
1367 mAssistantUid = assistantUid;
1368 }
1369 }
1370
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001371 private void readPersistedSettings() {
1372 final ContentResolver cr = mContentResolver;
1373
Eric Laurentbffc3d12012-05-07 17:43:49 -07001374 int ringerModeFromSettings =
Jeff Sharkey8d9a1f62012-10-18 15:38:14 -07001375 Settings.Global.getInt(
1376 cr, Settings.Global.MODE_RINGER, AudioManager.RINGER_MODE_NORMAL);
Eric Laurentbffc3d12012-05-07 17:43:49 -07001377 int ringerMode = ringerModeFromSettings;
Eric Laurent72668b22011-07-19 16:04:27 -07001378 // sanity check in case the settings are restored from a device with incompatible
1379 // ringer modes
John Spurlock97559372014-10-24 16:27:36 -04001380 if (!isValidRingerMode(ringerMode)) {
Glenn Kastenba195eb2011-12-13 09:30:40 -08001381 ringerMode = AudioManager.RINGER_MODE_NORMAL;
Eric Laurentbffc3d12012-05-07 17:43:49 -07001382 }
1383 if ((ringerMode == AudioManager.RINGER_MODE_VIBRATE) && !mHasVibrator) {
1384 ringerMode = AudioManager.RINGER_MODE_SILENT;
1385 }
1386 if (ringerMode != ringerModeFromSettings) {
Jeff Sharkey8d9a1f62012-10-18 15:38:14 -07001387 Settings.Global.putInt(cr, Settings.Global.MODE_RINGER, ringerMode);
Glenn Kastenba195eb2011-12-13 09:30:40 -08001388 }
Muyuan Li1ed6df62016-06-18 11:16:52 -07001389 if (mUseFixedVolume || mIsSingleVolume) {
Eric Laurent83a017b2013-03-19 18:15:31 -07001390 ringerMode = AudioManager.RINGER_MODE_NORMAL;
1391 }
Glenn Kastenba195eb2011-12-13 09:30:40 -08001392 synchronized(mSettingsLock) {
1393 mRingerMode = ringerMode;
John Spurlock661f2cf2014-11-17 10:29:10 -05001394 if (mRingerModeExternal == -1) {
1395 mRingerModeExternal = mRingerMode;
1396 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001397
Eric Laurentdd45d012012-10-08 09:04:34 -07001398 // System.VIBRATE_ON is not used any more but defaults for mVibrateSetting
1399 // are still needed while setVibrateSetting() and getVibrateSetting() are being
1400 // deprecated.
John Spurlock61560172015-02-06 19:46:04 -05001401 mVibrateSetting = AudioSystem.getValueForVibrateSetting(0,
Eric Laurentdd45d012012-10-08 09:04:34 -07001402 AudioManager.VIBRATE_TYPE_NOTIFICATION,
1403 mHasVibrator ? AudioManager.VIBRATE_SETTING_ONLY_SILENT
1404 : AudioManager.VIBRATE_SETTING_OFF);
John Spurlock61560172015-02-06 19:46:04 -05001405 mVibrateSetting = AudioSystem.getValueForVibrateSetting(mVibrateSetting,
Eric Laurentdd45d012012-10-08 09:04:34 -07001406 AudioManager.VIBRATE_TYPE_RINGER,
1407 mHasVibrator ? AudioManager.VIBRATE_SETTING_ONLY_SILENT
1408 : AudioManager.VIBRATE_SETTING_OFF);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001409
Beverlyd6964762018-02-16 14:07:03 -05001410 updateRingerAndZenModeAffectedStreams();
Eric Laurent7ee1e4f2012-10-26 18:11:21 -07001411 readDockAudioSettings(cr);
Jean-Michel Trivi011f39e2017-08-19 18:08:06 -07001412 sendEncodedSurroundMode(cr, "readPersistedSettings");
jiabin39940752018-04-02 18:18:45 -07001413 sendEnabledSurroundFormats(cr, true);
Eric Laurent1c9c1d52018-10-17 10:06:46 -07001414 updateAssistantUId(true);
Eric Laurent402f7f22011-02-04 12:30:32 -08001415 }
Eric Laurentc1d41662011-07-19 11:21:13 -07001416
Eric Laurentbc0fab1f2012-09-19 11:24:41 -07001417 mMuteAffectedStreams = System.getIntForUser(cr,
John Spurlock61560172015-02-06 19:46:04 -05001418 System.MUTE_STREAMS_AFFECTED, AudioSystem.DEFAULT_MUTE_STREAMS_AFFECTED,
John Spurlock24c05182015-02-05 12:30:36 -05001419 UserHandle.USER_CURRENT);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001420
Andy Hung7b98e9a2016-02-25 18:34:50 -08001421 updateMasterMono(cr);
Andy Hungf04b84d2015-12-18 17:33:27 -08001422
Edward Savage-Jones35c292f2017-01-13 09:04:34 +01001423 updateMasterBalance(cr);
1424
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001425 // Each stream will read its own persisted settings
1426
John Spurlockbcc10872014-11-28 15:29:21 -05001427 // Broadcast the sticky intents
1428 broadcastRingerMode(AudioManager.RINGER_MODE_CHANGED_ACTION, mRingerModeExternal);
1429 broadcastRingerMode(AudioManager.INTERNAL_RINGER_MODE_CHANGED_ACTION, mRingerMode);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001430
1431 // Broadcast vibrate settings
1432 broadcastVibrateSetting(AudioManager.VIBRATE_TYPE_RINGER);
1433 broadcastVibrateSetting(AudioManager.VIBRATE_TYPE_NOTIFICATION);
Jean-Michel Trivid589fea2011-04-15 11:28:10 -07001434
John Spurlock33f4e042014-07-11 13:10:58 -04001435 // Load settings for the volume controller
1436 mVolumeController.loadSettings(cr);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001437 }
1438
Eric Laurentc0232482016-03-15 18:19:23 -07001439 private void readUserRestrictions() {
1440 final int currentUser = getCurrentUserId();
1441
1442 // Check the current user restriction.
Tony Makc1205112016-07-22 16:02:59 +01001443 boolean masterMute =
1444 mUserManagerInternal.getUserRestriction(currentUser,
Esteban Talavera492b4722017-02-13 14:59:45 +00001445 UserManager.DISALLOW_UNMUTE_DEVICE)
Tony Makc1205112016-07-22 16:02:59 +01001446 || mUserManagerInternal.getUserRestriction(currentUser,
1447 UserManager.DISALLOW_ADJUST_VOLUME);
Eric Laurentc0232482016-03-15 18:19:23 -07001448 if (mUseFixedVolume) {
1449 masterMute = false;
1450 AudioSystem.setMasterVolume(1.0f);
1451 }
1452 if (DEBUG_VOL) {
1453 Log.d(TAG, String.format("Master mute %s, user=%d", masterMute, currentUser));
1454 }
1455 setSystemAudioMute(masterMute);
1456 AudioSystem.setMasterMute(masterMute);
1457 broadcastMasterMuteStatus(masterMute);
1458
1459 boolean microphoneMute = mUserManagerInternal.getUserRestriction(
1460 currentUser, UserManager.DISALLOW_UNMUTE_MICROPHONE);
1461 if (DEBUG_VOL) {
1462 Log.d(TAG, String.format("Mic mute %s, user=%d", microphoneMute, currentUser));
1463 }
1464 AudioSystem.muteMicrophone(microphoneMute);
1465 }
1466
Eric Laurenta553c252009-07-17 12:17:14 -07001467 private int rescaleIndex(int index, int srcStream, int dstStream) {
Jean-Michel Trivie05eef82018-03-08 18:56:34 -08001468 final int rescaled =
1469 (index * mStreamStates[dstStream].getMaxIndex()
1470 + mStreamStates[srcStream].getMaxIndex() / 2)
1471 / mStreamStates[srcStream].getMaxIndex();
1472 if (rescaled < mStreamStates[dstStream].getMinIndex()) {
1473 return mStreamStates[dstStream].getMinIndex();
1474 } else {
1475 return rescaled;
1476 }
Eric Laurenta553c252009-07-17 12:17:14 -07001477 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001478
1479 ///////////////////////////////////////////////////////////////////////////
1480 // IPC methods
1481 ///////////////////////////////////////////////////////////////////////////
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001482 /** @see AudioManager#adjustVolume(int, int) */
Dianne Hackbornba50b97c2013-04-30 15:04:46 -07001483 public void adjustSuggestedStreamVolume(int direction, int suggestedStreamType, int flags,
John Spurlock90874332015-03-10 16:00:54 -04001484 String callingPackage, String caller) {
Jean-Michel Trivi610aa9b2018-01-27 15:42:42 -08001485 final IAudioPolicyCallback extVolCtlr;
1486 synchronized (mExtVolumeControllerLock) {
1487 extVolCtlr = mExtVolumeController;
1488 }
1489 if (extVolCtlr != null) {
Jean-Michel Trivi7ed71472018-02-02 16:52:09 -08001490 sendMsg(mAudioHandler, MSG_NOTIFY_VOL_EVENT, SENDMSG_QUEUE,
1491 direction, 0 /*ignored*/,
1492 extVolCtlr, 0 /*delay*/);
Jean-Michel Trivi610aa9b2018-01-27 15:42:42 -08001493 } else {
1494 adjustSuggestedStreamVolume(direction, suggestedStreamType, flags, callingPackage,
1495 caller, Binder.getCallingUid());
1496 }
RoboErik272e1612014-09-05 11:39:29 -07001497 }
1498
1499 private void adjustSuggestedStreamVolume(int direction, int suggestedStreamType, int flags,
John Spurlock90874332015-03-10 16:00:54 -04001500 String callingPackage, String caller, int uid) {
1501 if (DEBUG_VOL) Log.d(TAG, "adjustSuggestedStreamVolume() stream=" + suggestedStreamType
Jean-Michel Trivia7880d42017-04-15 12:41:05 -07001502 + ", flags=" + flags + ", caller=" + caller
1503 + ", volControlStream=" + mVolumeControlStream
1504 + ", userSelect=" + mUserSelectedVolumeControlStream);
Jean-Michel Trivi58850372018-09-14 16:01:28 -07001505 sVolumeLogger.log(new VolumeEvent(VolumeEvent.VOL_ADJUST_SUGG_VOL, suggestedStreamType,
Jean-Michel Trivicf170362017-08-24 17:24:57 -07001506 direction/*val1*/, flags/*val2*/, new StringBuilder(callingPackage)
1507 .append("/").append(caller).append(" uid:").append(uid).toString()));
Jean-Michel Trivia7880d42017-04-15 12:41:05 -07001508 final int streamType;
jiabin8fd5d5e2018-03-23 14:09:28 -07001509 synchronized (mForceControlStreamLock) {
1510 // Request lock in case mVolumeControlStream is changed by other thread.
1511 if (mUserSelectedVolumeControlStream) { // implies mVolumeControlStream != -1
Jean-Michel Trivia7880d42017-04-15 12:41:05 -07001512 streamType = mVolumeControlStream;
jiabin8fd5d5e2018-03-23 14:09:28 -07001513 } else {
1514 final int maybeActiveStreamType = getActiveStreamType(suggestedStreamType);
1515 final boolean activeForReal;
1516 if (maybeActiveStreamType == AudioSystem.STREAM_RING
1517 || maybeActiveStreamType == AudioSystem.STREAM_NOTIFICATION) {
1518 activeForReal = wasStreamActiveRecently(maybeActiveStreamType, 0);
1519 } else {
1520 activeForReal = AudioSystem.isStreamActive(maybeActiveStreamType, 0);
1521 }
1522 if (activeForReal || mVolumeControlStream == -1) {
1523 streamType = maybeActiveStreamType;
1524 } else {
1525 streamType = mVolumeControlStream;
1526 }
Jean-Michel Trivia7880d42017-04-15 12:41:05 -07001527 }
Eric Laurent402f7f22011-02-04 12:30:32 -08001528 }
Jean-Michel Trivia7880d42017-04-15 12:41:05 -07001529
1530 final boolean isMute = isMuteAdjust(direction);
1531
John Spurlock0a376af2015-03-26 16:24:12 -04001532 ensureValidStreamType(streamType);
John Spurlock33f4e042014-07-11 13:10:58 -04001533 final int resolvedStream = mStreamVolumeAlias[streamType];
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001534
RoboErik2811dd32014-08-12 09:48:13 -07001535 // Play sounds on STREAM_RING only.
1536 if ((flags & AudioManager.FLAG_PLAY_SOUND) != 0 &&
John Spurlock33f4e042014-07-11 13:10:58 -04001537 resolvedStream != AudioSystem.STREAM_RING) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001538 flags &= ~AudioManager.FLAG_PLAY_SOUND;
1539 }
1540
John Spurlock33f4e042014-07-11 13:10:58 -04001541 // For notifications/ring, show the ui before making any adjustments
RoboErik4197cb62015-01-21 15:45:32 -08001542 // Don't suppress mute/unmute requests
Stanley Changb77e13d2018-08-28 08:16:03 +08001543 // Don't suppress adjustments for single volume device
1544 if (mVolumeController.suppressAdjustment(resolvedStream, flags, isMute)
1545 && !mIsSingleVolume) {
John Spurlock33f4e042014-07-11 13:10:58 -04001546 direction = 0;
1547 flags &= ~AudioManager.FLAG_PLAY_SOUND;
1548 flags &= ~AudioManager.FLAG_VIBRATE;
1549 if (DEBUG_VOL) Log.d(TAG, "Volume controller suppressed adjustment");
1550 }
1551
John Spurlock90874332015-03-10 16:00:54 -04001552 adjustStreamVolume(streamType, direction, flags, callingPackage, caller, uid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001553 }
1554
1555 /** @see AudioManager#adjustStreamVolume(int, int, int) */
Dianne Hackbornba50b97c2013-04-30 15:04:46 -07001556 public void adjustStreamVolume(int streamType, int direction, int flags,
1557 String callingPackage) {
Phil Weaverf1a9aff2017-03-23 17:21:29 -07001558 if ((streamType == AudioManager.STREAM_ACCESSIBILITY) && !canChangeAccessibilityVolume()) {
Jean-Michel Triviab2d9312017-03-13 15:33:39 -07001559 Log.w(TAG, "Trying to call adjustStreamVolume() for a11y without"
Phil Weaverf1a9aff2017-03-23 17:21:29 -07001560 + "CHANGE_ACCESSIBILITY_VOLUME / callingPackage=" + callingPackage);
Jean-Michel Triviab2d9312017-03-13 15:33:39 -07001561 return;
1562 }
Jean-Michel Trivi58850372018-09-14 16:01:28 -07001563 sVolumeLogger.log(new VolumeEvent(VolumeEvent.VOL_ADJUST_STREAM_VOL, streamType,
Jean-Michel Trivicf170362017-08-24 17:24:57 -07001564 direction/*val1*/, flags/*val2*/, callingPackage));
John Spurlock90874332015-03-10 16:00:54 -04001565 adjustStreamVolume(streamType, direction, flags, callingPackage, callingPackage,
1566 Binder.getCallingUid());
RoboErik0dac35a2014-08-12 15:48:49 -07001567 }
1568
Chinyue Chen6affe932018-01-24 14:51:43 +08001569 protected void adjustStreamVolume(int streamType, int direction, int flags,
John Spurlock90874332015-03-10 16:00:54 -04001570 String callingPackage, String caller, int uid) {
Eric Laurent83a017b2013-03-19 18:15:31 -07001571 if (mUseFixedVolume) {
1572 return;
1573 }
John Spurlock90874332015-03-10 16:00:54 -04001574 if (DEBUG_VOL) Log.d(TAG, "adjustStreamVolume() stream=" + streamType + ", dir=" + direction
1575 + ", flags=" + flags + ", caller=" + caller);
Jean-Michel Trivi3114ce32012-06-11 15:03:52 -07001576
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001577 ensureValidDirection(direction);
1578 ensureValidStreamType(streamType);
1579
RoboErik4197cb62015-01-21 15:45:32 -08001580 boolean isMuteAdjust = isMuteAdjust(direction);
1581
John Spurlock3ce37252015-02-17 13:20:45 -05001582 if (isMuteAdjust && !isStreamAffectedByMute(streamType)) {
1583 return;
1584 }
1585
Tomoharu Kasaharaa0d0c542019-01-18 20:04:38 +09001586 // If adjust is mute and the stream is STREAM_VOICE_CALL or STREAM_BLUETOOTH_SCO, make sure
Nadav Bar6b7751d2017-12-24 16:03:08 +02001587 // that the calling app have the MODIFY_PHONE_STATE permission.
1588 if (isMuteAdjust &&
Tomoharu Kasaharaa0d0c542019-01-18 20:04:38 +09001589 (streamType == AudioSystem.STREAM_VOICE_CALL ||
1590 streamType == AudioSystem.STREAM_BLUETOOTH_SCO) &&
Nadav Bar6b7751d2017-12-24 16:03:08 +02001591 mContext.checkCallingOrSelfPermission(
1592 android.Manifest.permission.MODIFY_PHONE_STATE)
1593 != PackageManager.PERMISSION_GRANTED) {
1594 Log.w(TAG, "MODIFY_PHONE_STATE Permission Denial: adjustStreamVolume from pid="
1595 + Binder.getCallingPid() + ", uid=" + Binder.getCallingUid());
1596 return;
1597 }
1598
Eric Laurent96a33d12011-11-08 10:31:57 -08001599 // use stream type alias here so that streams with same alias have the same behavior,
1600 // including with regard to silent mode control (e.g the use of STREAM_RING below and in
1601 // checkForRingerModeChange() in place of STREAM_RING or STREAM_NOTIFICATION)
Eric Laurent6d517662012-04-23 18:42:39 -07001602 int streamTypeAlias = mStreamVolumeAlias[streamType];
RoboErik4197cb62015-01-21 15:45:32 -08001603
Eric Laurentb024c302011-10-14 17:19:27 -07001604 VolumeStreamState streamState = mStreamStates[streamTypeAlias];
Eric Laurent9bc8358d2011-11-18 16:43:31 -08001605
1606 final int device = getDeviceForStream(streamTypeAlias);
Eric Laurent3ef75492012-11-28 12:12:23 -08001607
Eric Laurent42b041e2013-03-29 11:36:03 -07001608 int aliasIndex = streamState.getIndex(device);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001609 boolean adjustVolume = true;
Eric Laurent3ef75492012-11-28 12:12:23 -08001610 int step;
Eric Laurent24482012012-05-10 09:41:17 -07001611
Matthew Xiec9d1d5f2013-09-12 00:32:22 -07001612 // skip a2dp absolute volume control request when the device
1613 // is not an a2dp device
1614 if ((device & AudioSystem.DEVICE_OUT_ALL_A2DP) == 0 &&
1615 (flags & AudioManager.FLAG_BLUETOOTH_ABS_VOLUME) != 0) {
1616 return;
1617 }
1618
Kenny Guy70e0c582015-06-30 19:18:28 +01001619 // If we are being called by the system (e.g. hardware keys) check for current user
1620 // so we handle user restrictions correctly.
1621 if (uid == android.os.Process.SYSTEM_UID) {
1622 uid = UserHandle.getUid(getCurrentUserId(), UserHandle.getAppId(uid));
1623 }
John Spurlock59dc9c12015-03-02 11:20:15 -05001624 if (mAppOps.noteOp(STREAM_VOLUME_OPS[streamTypeAlias], uid, callingPackage)
RoboErik0dac35a2014-08-12 15:48:49 -07001625 != AppOpsManager.MODE_ALLOWED) {
Dianne Hackbornba50b97c2013-04-30 15:04:46 -07001626 return;
1627 }
1628
Eric Laurentfde16d52012-12-03 14:42:39 -08001629 // reset any pending volume command
hyomin.ohd0446dc2018-10-18 13:58:27 +09001630 synchronized (mSafeMediaVolumeStateLock) {
Eric Laurentfde16d52012-12-03 14:42:39 -08001631 mPendingVolumeCommand = null;
1632 }
1633
Eric Laurent3ef75492012-11-28 12:12:23 -08001634 flags &= ~AudioManager.FLAG_FIXED_VOLUME;
1635 if ((streamTypeAlias == AudioSystem.STREAM_MUSIC) &&
1636 ((device & mFixedVolumeDevices) != 0)) {
1637 flags |= AudioManager.FLAG_FIXED_VOLUME;
1638
1639 // Always toggle between max safe volume and 0 for fixed volume devices where safe
1640 // volume is enforced, and max and 0 for the others.
1641 // This is simulated by stepping by the full allowed volume range
1642 if (mSafeMediaVolumeState == SAFE_MEDIA_VOLUME_ACTIVE &&
1643 (device & mSafeMediaVolumeDevices) != 0) {
Eric Laurenteab40d12017-06-09 12:45:21 -07001644 step = safeMediaVolumeIndex(device);
Eric Laurent3ef75492012-11-28 12:12:23 -08001645 } else {
1646 step = streamState.getMaxIndex();
1647 }
1648 if (aliasIndex != 0) {
1649 aliasIndex = step;
1650 }
1651 } else {
1652 // convert one UI step (+/-1) into a number of internal units on the stream alias
1653 step = rescaleIndex(10, streamType, streamTypeAlias);
1654 }
1655
Eric Laurent42b041e2013-03-29 11:36:03 -07001656 // If either the client forces allowing ringer modes for this adjustment,
1657 // or the stream type is one that is affected by ringer modes
1658 if (((flags & AudioManager.FLAG_ALLOW_RINGER_MODES) != 0) ||
John Spurlockee5ad722015-03-03 16:17:21 -05001659 (streamTypeAlias == getUiSoundsStreamType())) {
John Spurlock661f2cf2014-11-17 10:29:10 -05001660 int ringerMode = getRingerModeInternal();
Eric Laurent42b041e2013-03-29 11:36:03 -07001661 // do not vibrate if already in vibrate mode
1662 if (ringerMode == AudioManager.RINGER_MODE_VIBRATE) {
1663 flags &= ~AudioManager.FLAG_VIBRATE;
Eric Laurent3ef75492012-11-28 12:12:23 -08001664 }
RoboErik5452e252015-02-06 15:33:53 -08001665 // Check if the ringer mode handles this adjustment. If it does we don't
1666 // need to adjust the volume further.
John Spurlock50ced3f2015-05-11 16:00:09 -04001667 final int result = checkForRingerModeChange(aliasIndex, direction, step,
Julia Reynoldsed783792016-04-08 15:27:35 -04001668 streamState.mIsMuted, callingPackage, flags);
John Spurlocka11b4af2014-06-01 11:52:23 -04001669 adjustVolume = (result & FLAG_ADJUST_VOLUME) != 0;
1670 // If suppressing a volume adjustment in silent mode, display the UI hint
1671 if ((result & AudioManager.FLAG_SHOW_SILENT_HINT) != 0) {
1672 flags |= AudioManager.FLAG_SHOW_SILENT_HINT;
1673 }
John Spurlock661f2cf2014-11-17 10:29:10 -05001674 // If suppressing a volume down adjustment in vibrate mode, display the UI hint
1675 if ((result & AudioManager.FLAG_SHOW_VIBRATE_HINT) != 0) {
1676 flags |= AudioManager.FLAG_SHOW_VIBRATE_HINT;
1677 }
Eric Laurent42b041e2013-03-29 11:36:03 -07001678 }
Beverlyd6964762018-02-16 14:07:03 -05001679
1680 // If the ringer mode or zen is muting the stream, do not change stream unless
1681 // it'll cause us to exit dnd
Julia Reynoldsed783792016-04-08 15:27:35 -04001682 if (!volumeAdjustmentAllowedByDnd(streamTypeAlias, flags)) {
John Spurlock50ced3f2015-05-11 16:00:09 -04001683 adjustVolume = false;
1684 }
Eric Laurent42b041e2013-03-29 11:36:03 -07001685 int oldIndex = mStreamStates[streamType].getIndex(device);
Eric Laurent3ef75492012-11-28 12:12:23 -08001686
Eric Laurent42b041e2013-03-29 11:36:03 -07001687 if (adjustVolume && (direction != AudioManager.ADJUST_SAME)) {
RoboErik5452e252015-02-06 15:33:53 -08001688 mAudioHandler.removeMessages(MSG_UNMUTE_STREAM);
Matthew Xiec9d1d5f2013-09-12 00:32:22 -07001689
RoboErik4197cb62015-01-21 15:45:32 -08001690 if (isMuteAdjust) {
1691 boolean state;
1692 if (direction == AudioManager.ADJUST_TOGGLE_MUTE) {
1693 state = !streamState.mIsMuted;
1694 } else {
1695 state = direction == AudioManager.ADJUST_MUTE;
1696 }
1697 if (streamTypeAlias == AudioSystem.STREAM_MUSIC) {
1698 setSystemAudioMute(state);
1699 }
1700 for (int stream = 0; stream < mStreamStates.length; stream++) {
1701 if (streamTypeAlias == mStreamVolumeAlias[stream]) {
Sungmin Choi841ed0a2015-07-26 23:09:49 -07001702 if (!(readCameraSoundForced()
1703 && (mStreamStates[stream].getStreamType()
1704 == AudioSystem.STREAM_SYSTEM_ENFORCED))) {
1705 mStreamStates[stream].mute(state);
1706 }
RoboErik4197cb62015-01-21 15:45:32 -08001707 }
1708 }
1709 } else if ((direction == AudioManager.ADJUST_RAISE) &&
Eric Laurent42b041e2013-03-29 11:36:03 -07001710 !checkSafeMediaVolume(streamTypeAlias, aliasIndex + step, device)) {
RoboErik4197cb62015-01-21 15:45:32 -08001711 Log.e(TAG, "adjustStreamVolume() safe volume index = " + oldIndex);
John Spurlock3346a802014-05-20 16:25:37 -04001712 mVolumeController.postDisplaySafeVolumeWarning(flags);
John Spurlock90874332015-03-10 16:00:54 -04001713 } else if (streamState.adjustIndex(direction * step, device, caller)
1714 || streamState.mIsMuted) {
RoboErik4197cb62015-01-21 15:45:32 -08001715 // Post message to set system volume (it in turn will post a
1716 // message to persist).
1717 if (streamState.mIsMuted) {
1718 // Unmute the stream if it was previously muted
RoboErik5452e252015-02-06 15:33:53 -08001719 if (direction == AudioManager.ADJUST_RAISE) {
1720 // unmute immediately for volume up
1721 streamState.mute(false);
1722 } else if (direction == AudioManager.ADJUST_LOWER) {
Muyuan Li1ed6df62016-06-18 11:16:52 -07001723 if (mIsSingleVolume) {
John Spurlocka48d7792015-03-03 17:35:57 -05001724 sendMsg(mAudioHandler, MSG_UNMUTE_STREAM, SENDMSG_QUEUE,
1725 streamTypeAlias, flags, null, UNMUTE_STREAM_DELAY);
1726 }
RoboErik5452e252015-02-06 15:33:53 -08001727 }
RoboErik4197cb62015-01-21 15:45:32 -08001728 }
Eric Laurent42b041e2013-03-29 11:36:03 -07001729 sendMsg(mAudioHandler,
1730 MSG_SET_DEVICE_VOLUME,
1731 SENDMSG_QUEUE,
1732 device,
1733 0,
1734 streamState,
1735 0);
Eric Laurent4bbcc652012-09-24 14:26:30 -07001736 }
Jungshik Jang41d97462014-06-30 22:26:29 +09001737
Jungshik Jang41d97462014-06-30 22:26:29 +09001738 int newIndex = mStreamStates[streamType].getIndex(device);
Ajay Panickere3946c82018-02-26 16:04:15 -08001739
1740 // Check if volume update should be send to AVRCP
1741 if (streamTypeAlias == AudioSystem.STREAM_MUSIC &&
1742 (device & AudioSystem.DEVICE_OUT_ALL_A2DP) != 0 &&
1743 (flags & AudioManager.FLAG_BLUETOOTH_ABS_VOLUME) == 0) {
Jean-Michel Trivi58850372018-09-14 16:01:28 -07001744 if (DEBUG_VOL) {
1745 Log.d(TAG, "adjustSreamVolume: postSetAvrcpAbsoluteVolumeIndex index="
1746 + newIndex + "stream=" + streamType);
Ajay Panickere3946c82018-02-26 16:04:15 -08001747 }
Jean-Michel Trivi734819a2019-02-04 15:44:28 -08001748 mDeviceBroker.postSetAvrcpAbsoluteVolumeIndex(newIndex / 10);
Ajay Panickere3946c82018-02-26 16:04:15 -08001749 }
1750
Jakub Pawlowskif9570f32018-02-21 17:15:12 -08001751 // Check if volume update should be send to Hearing Aid
1752 if ((device & AudioSystem.DEVICE_OUT_HEARING_AID) != 0) {
Jean-Michel Trivi58850372018-09-14 16:01:28 -07001753 Log.i(TAG, "adjustSreamVolume postSetHearingAidVolumeIndex index=" + newIndex
1754 + " stream=" + streamType);
1755 mDeviceBroker.postSetHearingAidVolumeIndex(newIndex, streamType);
Jakub Pawlowskif9570f32018-02-21 17:15:12 -08001756 }
1757
Ajay Panickere3946c82018-02-26 16:04:15 -08001758 // Check if volume update should be sent to Hdmi system audio.
Jinsuk Kim336cdb42014-11-29 06:27:00 +09001759 if (streamTypeAlias == AudioSystem.STREAM_MUSIC) {
1760 setSystemAudioVolume(oldIndex, newIndex, getStreamMaxVolume(streamType), flags);
1761 }
Shubangc480a712018-06-11 18:02:42 -07001762 synchronized (mHdmiClientLock) {
1763 if (mHdmiManager != null) {
Eric Laurent212532b2014-07-21 15:43:18 -07001764 // mHdmiCecSink true => mHdmiPlaybackClient != null
1765 if (mHdmiCecSink &&
1766 streamTypeAlias == AudioSystem.STREAM_MUSIC &&
1767 oldIndex != newIndex) {
Shubangc480a712018-06-11 18:02:42 -07001768 int keyCode = (direction == -1) ? KeyEvent.KEYCODE_VOLUME_DOWN :
1769 KeyEvent.KEYCODE_VOLUME_UP;
1770 final long ident = Binder.clearCallingIdentity();
1771 try {
1772 mHdmiPlaybackClient.sendKeyEvent(keyCode, true);
1773 mHdmiPlaybackClient.sendKeyEvent(keyCode, false);
1774 } finally {
1775 Binder.restoreCallingIdentity(ident);
Eric Laurent212532b2014-07-21 15:43:18 -07001776 }
Jungshik Jang41d97462014-06-30 22:26:29 +09001777 }
Shubangc480a712018-06-11 18:02:42 -07001778
1779 if (mHdmiAudioSystemClient != null &&
Shubangde728822018-07-16 16:46:51 -07001780 mHdmiSystemAudioSupported &&
Shubangc480a712018-06-11 18:02:42 -07001781 streamTypeAlias == AudioSystem.STREAM_MUSIC &&
1782 (oldIndex != newIndex || isMuteAdjust)) {
Shubangde728822018-07-16 16:46:51 -07001783 final long identity = Binder.clearCallingIdentity();
Shubangc480a712018-06-11 18:02:42 -07001784 mHdmiAudioSystemClient.sendReportAudioStatusCecCommand(
1785 isMuteAdjust, getStreamVolume(AudioSystem.STREAM_MUSIC),
1786 getStreamMaxVolume(AudioSystem.STREAM_MUSIC),
1787 isStreamMute(AudioSystem.STREAM_MUSIC));
Shubangde728822018-07-16 16:46:51 -07001788 Binder.restoreCallingIdentity(identity);
Shubangc480a712018-06-11 18:02:42 -07001789 }
Jungshik Jang41d97462014-06-30 22:26:29 +09001790 }
1791 }
Eric Laurent4bbcc652012-09-24 14:26:30 -07001792 }
Eric Laurent42b041e2013-03-29 11:36:03 -07001793 int index = mStreamStates[streamType].getIndex(device);
Eric Laurent25101b02011-02-02 09:33:30 -08001794 sendVolumeUpdate(streamType, oldIndex, index, flags);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001795 }
1796
RoboErik5452e252015-02-06 15:33:53 -08001797 // Called after a delay when volume down is pressed while muted
1798 private void onUnmuteStream(int stream, int flags) {
1799 VolumeStreamState streamState = mStreamStates[stream];
1800 streamState.mute(false);
1801
1802 final int device = getDeviceForStream(stream);
1803 final int index = mStreamStates[stream].getIndex(device);
1804 sendVolumeUpdate(stream, index, index, flags);
1805 }
1806
Jinsuk Kim336cdb42014-11-29 06:27:00 +09001807 private void setSystemAudioVolume(int oldVolume, int newVolume, int maxVolume, int flags) {
Jinsuk Kim336cdb42014-11-29 06:27:00 +09001808 // Sets the audio volume of AVR when we are in system audio mode. The new volume info
1809 // is tranformed to HDMI-CEC commands and passed through CEC bus.
Shubangc480a712018-06-11 18:02:42 -07001810 synchronized (mHdmiClientLock) {
1811 if (mHdmiManager == null
1812 || mHdmiTvClient == null
1813 || oldVolume == newVolume
1814 || (flags & AudioManager.FLAG_HDMI_SYSTEM_AUDIO_VOLUME) != 0
1815 || !mHdmiSystemAudioSupported) return;
1816 final long token = Binder.clearCallingIdentity();
1817 try {
1818 mHdmiTvClient.setSystemAudioVolume(oldVolume, newVolume, maxVolume);
1819 } finally {
1820 Binder.restoreCallingIdentity(token);
Jinsuk Kim336cdb42014-11-29 06:27:00 +09001821 }
1822 }
1823 }
1824
Eric Laurentfde16d52012-12-03 14:42:39 -08001825 // StreamVolumeCommand contains the information needed to defer the process of
1826 // setStreamVolume() in case the user has to acknowledge the safe volume warning message.
1827 class StreamVolumeCommand {
1828 public final int mStreamType;
1829 public final int mIndex;
1830 public final int mFlags;
1831 public final int mDevice;
Eric Laurent9ce379a2010-02-16 06:00:26 -08001832
Eric Laurentfde16d52012-12-03 14:42:39 -08001833 StreamVolumeCommand(int streamType, int index, int flags, int device) {
1834 mStreamType = streamType;
1835 mIndex = index;
1836 mFlags = flags;
1837 mDevice = device;
Eric Laurentb024c302011-10-14 17:19:27 -07001838 }
John Spurlock35134602014-07-24 18:10:48 -04001839
1840 @Override
1841 public String toString() {
1842 return new StringBuilder().append("{streamType=").append(mStreamType).append(",index=")
1843 .append(mIndex).append(",flags=").append(mFlags).append(",device=")
1844 .append(mDevice).append('}').toString();
1845 }
Eric Laurentfde16d52012-12-03 14:42:39 -08001846 };
Eric Laurent3ef75492012-11-28 12:12:23 -08001847
Julia Reynolds48034f82016-03-09 10:15:16 -05001848 private int getNewRingerMode(int stream, int index, int flags) {
Zak Cohen47798292017-11-30 12:34:20 -08001849 // setRingerMode does nothing if the device is single volume,so the value would be unchanged
1850 if (mIsSingleVolume) {
1851 return getRingerModeExternal();
1852 }
1853
John Spurlockee5ad722015-03-03 16:17:21 -05001854 // setting volume on ui sounds stream type also controls silent mode
Eric Laurent3ef75492012-11-28 12:12:23 -08001855 if (((flags & AudioManager.FLAG_ALLOW_RINGER_MODES) != 0) ||
John Spurlock75ae23c2015-06-02 16:26:43 -04001856 (stream == getUiSoundsStreamType())) {
Eric Laurent3ef75492012-11-28 12:12:23 -08001857 int newRingerMode;
1858 if (index == 0) {
1859 newRingerMode = mHasVibrator ? AudioManager.RINGER_MODE_VIBRATE
John Spurlocka48d7792015-03-03 17:35:57 -05001860 : mVolumePolicy.volumeDownToEnterSilent ? AudioManager.RINGER_MODE_SILENT
Julia Reynolds48034f82016-03-09 10:15:16 -05001861 : AudioManager.RINGER_MODE_NORMAL;
Eric Laurent3ef75492012-11-28 12:12:23 -08001862 } else {
1863 newRingerMode = AudioManager.RINGER_MODE_NORMAL;
1864 }
Julia Reynolds48034f82016-03-09 10:15:16 -05001865 return newRingerMode;
1866 }
1867 return getRingerModeExternal();
1868 }
1869
1870 private boolean isAndroidNPlus(String caller) {
1871 try {
1872 final ApplicationInfo applicationInfo =
1873 mContext.getPackageManager().getApplicationInfoAsUser(
1874 caller, 0, UserHandle.getUserId(Binder.getCallingUid()));
1875 if (applicationInfo.targetSdkVersion >= Build.VERSION_CODES.N) {
1876 return true;
1877 }
1878 return false;
1879 } catch (PackageManager.NameNotFoundException e) {
1880 return true;
1881 }
1882 }
1883
1884 private boolean wouldToggleZenMode(int newMode) {
1885 if (getRingerModeExternal() == AudioManager.RINGER_MODE_SILENT
1886 && newMode != AudioManager.RINGER_MODE_SILENT) {
1887 return true;
1888 } else if (getRingerModeExternal() != AudioManager.RINGER_MODE_SILENT
1889 && newMode == AudioManager.RINGER_MODE_SILENT) {
1890 return true;
1891 }
1892 return false;
1893 }
1894
1895 private void onSetStreamVolume(int streamType, int index, int flags, int device,
1896 String caller) {
1897 final int stream = mStreamVolumeAlias[streamType];
1898 setStreamVolumeInt(stream, index, device, false, caller);
1899 // setting volume on ui sounds stream type also controls silent mode
1900 if (((flags & AudioManager.FLAG_ALLOW_RINGER_MODES) != 0) ||
1901 (stream == getUiSoundsStreamType())) {
1902 setRingerMode(getNewRingerMode(stream, index, flags),
1903 TAG + ".onSetStreamVolume", false /*external*/);
Eric Laurent3ef75492012-11-28 12:12:23 -08001904 }
John Spurlock75ae23c2015-06-02 16:26:43 -04001905 // setting non-zero volume for a muted stream unmutes the stream and vice versa
1906 mStreamStates[stream].mute(index == 0);
Eric Laurentfde16d52012-12-03 14:42:39 -08001907 }
1908
François Gaffie9c362102018-09-21 17:43:52 +02001909 private void enforceModifyAudioRoutingPermission() {
1910 if (mContext.checkCallingPermission(
1911 android.Manifest.permission.MODIFY_AUDIO_ROUTING)
1912 != PackageManager.PERMISSION_GRANTED) {
1913 throw new SecurityException("Missing MODIFY_AUDIO_ROUTING permission");
1914 }
1915 }
1916
1917 /** @see AudioManager#setVolumeIndexForAttributes(attr, int, int) */
1918 public void setVolumeIndexForAttributes(@NonNull AudioAttributes attr, int index, int flags,
1919 String callingPackage) {
1920 enforceModifyAudioRoutingPermission();
1921 Preconditions.checkNotNull(attr, "attr must not be null");
1922 // @todo not hold the caller context, post message
1923 int stream = sAudioProductStrategies.getLegacyStreamTypeForAudioAttributes(attr);
1924 final int device = getDeviceForStream(stream);
1925
1926 int oldIndex = AudioSystem.getVolumeIndexForAttributes(attr, device);
1927
1928 AudioSystem.setVolumeIndexForAttributes(attr, index, device);
1929
1930 final int volumeGroup = sAudioProductStrategies.getVolumeGroupIdForAttributes(attr);
1931 final AudioVolumeGroup avg = sAudioVolumeGroups.getById(volumeGroup);
1932 if (avg == null) {
1933 return;
1934 }
1935 for (final int groupedStream : avg.getLegacyStreamTypes()) {
1936 setStreamVolume(stream, index, flags, callingPackage, callingPackage,
1937 Binder.getCallingUid());
1938 }
1939 }
1940
1941 /** @see AudioManager#getVolumeIndexForAttributes(attr) */
1942 public int getVolumeIndexForAttributes(@NonNull AudioAttributes attr) {
1943 enforceModifyAudioRoutingPermission();
1944 Preconditions.checkNotNull(attr, "attr must not be null");
1945 int stream = sAudioProductStrategies.getLegacyStreamTypeForAudioAttributes(attr);
1946 final int device = getDeviceForStream(stream);
1947
1948 return AudioSystem.getVolumeIndexForAttributes(attr, device);
1949 }
1950
1951 /** @see AudioManager#getMaxVolumeIndexForAttributes(attr) */
1952 public int getMaxVolumeIndexForAttributes(@NonNull AudioAttributes attr) {
1953 enforceModifyAudioRoutingPermission();
1954 Preconditions.checkNotNull(attr, "attr must not be null");
1955 return AudioSystem.getMaxVolumeIndexForAttributes(attr);
1956 }
1957
1958 /** @see AudioManager#getMinVolumeIndexForAttributes(attr) */
1959 public int getMinVolumeIndexForAttributes(@NonNull AudioAttributes attr) {
1960 enforceModifyAudioRoutingPermission();
1961 Preconditions.checkNotNull(attr, "attr must not be null");
1962 return AudioSystem.getMinVolumeIndexForAttributes(attr);
1963 }
1964
Eric Laurentfde16d52012-12-03 14:42:39 -08001965 /** @see AudioManager#setStreamVolume(int, int, int) */
Dianne Hackbornba50b97c2013-04-30 15:04:46 -07001966 public void setStreamVolume(int streamType, int index, int flags, String callingPackage) {
Phil Weaverf1a9aff2017-03-23 17:21:29 -07001967 if ((streamType == AudioManager.STREAM_ACCESSIBILITY) && !canChangeAccessibilityVolume()) {
Jean-Michel Triviab2d9312017-03-13 15:33:39 -07001968 Log.w(TAG, "Trying to call setStreamVolume() for a11y without"
Phil Weaverf1a9aff2017-03-23 17:21:29 -07001969 + " CHANGE_ACCESSIBILITY_VOLUME callingPackage=" + callingPackage);
Jean-Michel Triviab2d9312017-03-13 15:33:39 -07001970 return;
1971 }
Tomoharu Kasaharaa0d0c542019-01-18 20:04:38 +09001972 if ((streamType == AudioManager.STREAM_VOICE_CALL ||
1973 streamType == AudioManager.STREAM_BLUETOOTH_SCO) &&
Nadav Bar6b7751d2017-12-24 16:03:08 +02001974 (index == 0) &&
1975 (mContext.checkCallingOrSelfPermission(
1976 android.Manifest.permission.MODIFY_PHONE_STATE)
1977 != PackageManager.PERMISSION_GRANTED)) {
Tomoharu Kasaharaa0d0c542019-01-18 20:04:38 +09001978 Log.w(TAG, "Trying to call setStreamVolume() for STREAM_VOICE_CALL or"
1979 + " STREAM_BLUETOOTH_SCO and index 0 without"
Nadav Bar6b7751d2017-12-24 16:03:08 +02001980 + " MODIFY_PHONE_STATE callingPackage=" + callingPackage);
1981 return;
1982 }
Jean-Michel Trivi58850372018-09-14 16:01:28 -07001983 sVolumeLogger.log(new VolumeEvent(VolumeEvent.VOL_SET_STREAM_VOL, streamType,
Jean-Michel Trivicf170362017-08-24 17:24:57 -07001984 index/*val1*/, flags/*val2*/, callingPackage));
John Spurlock90874332015-03-10 16:00:54 -04001985 setStreamVolume(streamType, index, flags, callingPackage, callingPackage,
1986 Binder.getCallingUid());
RoboErik0dac35a2014-08-12 15:48:49 -07001987 }
1988
Phil Weaverf1a9aff2017-03-23 17:21:29 -07001989 private boolean canChangeAccessibilityVolume() {
1990 synchronized (mAccessibilityServiceUidsLock) {
1991 if (PackageManager.PERMISSION_GRANTED == mContext.checkCallingOrSelfPermission(
1992 android.Manifest.permission.CHANGE_ACCESSIBILITY_VOLUME)) {
1993 return true;
1994 }
1995 if (mAccessibilityServiceUids != null) {
1996 int callingUid = Binder.getCallingUid();
1997 for (int i = 0; i < mAccessibilityServiceUids.length; i++) {
1998 if (mAccessibilityServiceUids[i] == callingUid) {
1999 return true;
2000 }
2001 }
2002 }
2003 return false;
2004 }
2005 }
2006
RoboErik0dac35a2014-08-12 15:48:49 -07002007 private void setStreamVolume(int streamType, int index, int flags, String callingPackage,
John Spurlock90874332015-03-10 16:00:54 -04002008 String caller, int uid) {
Jean-Michel Triviac487672016-11-11 10:05:18 -08002009 if (DEBUG_VOL) {
2010 Log.d(TAG, "setStreamVolume(stream=" + streamType+", index=" + index
2011 + ", calling=" + callingPackage + ")");
2012 }
Eric Laurent83a017b2013-03-19 18:15:31 -07002013 if (mUseFixedVolume) {
2014 return;
2015 }
2016
Eric Laurentfde16d52012-12-03 14:42:39 -08002017 ensureValidStreamType(streamType);
Dianne Hackbornba50b97c2013-04-30 15:04:46 -07002018 int streamTypeAlias = mStreamVolumeAlias[streamType];
2019 VolumeStreamState streamState = mStreamStates[streamTypeAlias];
Eric Laurentfde16d52012-12-03 14:42:39 -08002020
2021 final int device = getDeviceForStream(streamType);
2022 int oldIndex;
2023
Matthew Xiec9d1d5f2013-09-12 00:32:22 -07002024 // skip a2dp absolute volume control request when the device
2025 // is not an a2dp device
2026 if ((device & AudioSystem.DEVICE_OUT_ALL_A2DP) == 0 &&
2027 (flags & AudioManager.FLAG_BLUETOOTH_ABS_VOLUME) != 0) {
2028 return;
2029 }
Kenny Guy70e0c582015-06-30 19:18:28 +01002030 // If we are being called by the system (e.g. hardware keys) check for current user
2031 // so we handle user restrictions correctly.
2032 if (uid == android.os.Process.SYSTEM_UID) {
2033 uid = UserHandle.getUid(getCurrentUserId(), UserHandle.getAppId(uid));
2034 }
John Spurlock59dc9c12015-03-02 11:20:15 -05002035 if (mAppOps.noteOp(STREAM_VOLUME_OPS[streamTypeAlias], uid, callingPackage)
RoboErik0dac35a2014-08-12 15:48:49 -07002036 != AppOpsManager.MODE_ALLOWED) {
Dianne Hackbornba50b97c2013-04-30 15:04:46 -07002037 return;
2038 }
2039
Julia Reynolds48034f82016-03-09 10:15:16 -05002040 if (isAndroidNPlus(callingPackage)
2041 && wouldToggleZenMode(getNewRingerMode(streamTypeAlias, index, flags))
2042 && !mNm.isNotificationPolicyAccessGrantedForPackage(callingPackage)) {
2043 throw new SecurityException("Not allowed to change Do Not Disturb state");
2044 }
2045
Julia Reynoldsed783792016-04-08 15:27:35 -04002046 if (!volumeAdjustmentAllowedByDnd(streamTypeAlias, flags)) {
2047 return;
2048 }
2049
hyomin.ohd0446dc2018-10-18 13:58:27 +09002050 synchronized (mSafeMediaVolumeStateLock) {
Eric Laurentfde16d52012-12-03 14:42:39 -08002051 // reset any pending volume command
2052 mPendingVolumeCommand = null;
2053
Eric Laurent42b041e2013-03-29 11:36:03 -07002054 oldIndex = streamState.getIndex(device);
Eric Laurentfde16d52012-12-03 14:42:39 -08002055
Dianne Hackbornba50b97c2013-04-30 15:04:46 -07002056 index = rescaleIndex(index * 10, streamType, streamTypeAlias);
Eric Laurentfde16d52012-12-03 14:42:39 -08002057
Jean-Michel Trivi58850372018-09-14 16:01:28 -07002058 if (streamTypeAlias == AudioSystem.STREAM_MUSIC
2059 && (device & AudioSystem.DEVICE_OUT_ALL_A2DP) != 0
2060 && (flags & AudioManager.FLAG_BLUETOOTH_ABS_VOLUME) == 0) {
2061 if (DEBUG_VOL) {
2062 Log.d(TAG, "setStreamVolume postSetAvrcpAbsoluteVolumeIndex index=" + index
2063 + "stream=" + streamType);
John Du5a0cf7a2013-07-19 11:30:34 -07002064 }
Jean-Michel Trivi58850372018-09-14 16:01:28 -07002065 mDeviceBroker.postSetAvrcpAbsoluteVolumeIndex(index / 10);
John Du5a0cf7a2013-07-19 11:30:34 -07002066 }
2067
Jakub Pawlowskif9570f32018-02-21 17:15:12 -08002068 if ((device & AudioSystem.DEVICE_OUT_HEARING_AID) != 0) {
Jean-Michel Trivi58850372018-09-14 16:01:28 -07002069 Log.i(TAG, "setStreamVolume postSetHearingAidVolumeIndex index=" + index
2070 + " stream=" + streamType);
2071 mDeviceBroker.postSetHearingAidVolumeIndex(index, streamType);
Jakub Pawlowskif9570f32018-02-21 17:15:12 -08002072 }
2073
Jinsuk Kim336cdb42014-11-29 06:27:00 +09002074 if (streamTypeAlias == AudioSystem.STREAM_MUSIC) {
2075 setSystemAudioVolume(oldIndex, index, getStreamMaxVolume(streamType), flags);
Jungshik Jang41d97462014-06-30 22:26:29 +09002076 }
2077
Eric Laurentfde16d52012-12-03 14:42:39 -08002078 flags &= ~AudioManager.FLAG_FIXED_VOLUME;
Dianne Hackbornba50b97c2013-04-30 15:04:46 -07002079 if ((streamTypeAlias == AudioSystem.STREAM_MUSIC) &&
Eric Laurentfde16d52012-12-03 14:42:39 -08002080 ((device & mFixedVolumeDevices) != 0)) {
2081 flags |= AudioManager.FLAG_FIXED_VOLUME;
2082
2083 // volume is either 0 or max allowed for fixed volume devices
2084 if (index != 0) {
2085 if (mSafeMediaVolumeState == SAFE_MEDIA_VOLUME_ACTIVE &&
2086 (device & mSafeMediaVolumeDevices) != 0) {
Eric Laurenteab40d12017-06-09 12:45:21 -07002087 index = safeMediaVolumeIndex(device);
Eric Laurentfde16d52012-12-03 14:42:39 -08002088 } else {
2089 index = streamState.getMaxIndex();
2090 }
2091 }
2092 }
2093
Dianne Hackbornba50b97c2013-04-30 15:04:46 -07002094 if (!checkSafeMediaVolume(streamTypeAlias, index, device)) {
John Spurlock3346a802014-05-20 16:25:37 -04002095 mVolumeController.postDisplaySafeVolumeWarning(flags);
Eric Laurentfde16d52012-12-03 14:42:39 -08002096 mPendingVolumeCommand = new StreamVolumeCommand(
2097 streamType, index, flags, device);
2098 } else {
John Spurlock90874332015-03-10 16:00:54 -04002099 onSetStreamVolume(streamType, index, flags, device, caller);
Eric Laurent42b041e2013-03-29 11:36:03 -07002100 index = mStreamStates[streamType].getIndex(device);
Eric Laurentfde16d52012-12-03 14:42:39 -08002101 }
2102 }
Shubangc480a712018-06-11 18:02:42 -07002103 synchronized (mHdmiClientLock) {
2104 if (mHdmiManager != null &&
2105 mHdmiAudioSystemClient != null &&
Shubangde728822018-07-16 16:46:51 -07002106 mHdmiSystemAudioSupported &&
Shubangc480a712018-06-11 18:02:42 -07002107 streamTypeAlias == AudioSystem.STREAM_MUSIC &&
2108 (oldIndex != index)) {
Shubangde728822018-07-16 16:46:51 -07002109 final long identity = Binder.clearCallingIdentity();
Shubangc480a712018-06-11 18:02:42 -07002110 mHdmiAudioSystemClient.sendReportAudioStatusCecCommand(
2111 false, getStreamVolume(AudioSystem.STREAM_MUSIC),
2112 getStreamMaxVolume(AudioSystem.STREAM_MUSIC),
2113 isStreamMute(AudioSystem.STREAM_MUSIC));
Shubangde728822018-07-16 16:46:51 -07002114 Binder.restoreCallingIdentity(identity);
Shubangc480a712018-06-11 18:02:42 -07002115 }
2116 }
Eric Laurent25101b02011-02-02 09:33:30 -08002117 sendVolumeUpdate(streamType, oldIndex, index, flags);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002118 }
2119
Beverlyd6964762018-02-16 14:07:03 -05002120 // No ringer or zen muted stream volumes can be changed unless it'll exit dnd
Julia Reynoldsed783792016-04-08 15:27:35 -04002121 private boolean volumeAdjustmentAllowedByDnd(int streamTypeAlias, int flags) {
Beverlyd6964762018-02-16 14:07:03 -05002122 switch (mNm.getZenMode()) {
2123 case Settings.Global.ZEN_MODE_OFF:
2124 return true;
2125 case Settings.Global.ZEN_MODE_NO_INTERRUPTIONS:
2126 case Settings.Global.ZEN_MODE_ALARMS:
2127 case Settings.Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS:
2128 return !isStreamMutedByRingerOrZenMode(streamTypeAlias)
2129 || streamTypeAlias == getUiSoundsStreamType()
2130 || (flags & AudioManager.FLAG_ALLOW_RINGER_MODES) != 0;
Julia Reynoldsed783792016-04-08 15:27:35 -04002131 }
Beverlyd6964762018-02-16 14:07:03 -05002132
Julia Reynoldsed783792016-04-08 15:27:35 -04002133 return true;
2134 }
2135
Eric Laurent45c90ce2012-04-24 18:44:22 -07002136 /** @see AudioManager#forceVolumeControlStream(int) */
2137 public void forceVolumeControlStream(int streamType, IBinder cb) {
Jean-Michel Trivi60eddfd2018-03-09 15:31:12 -08002138 if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.MODIFY_PHONE_STATE)
2139 != PackageManager.PERMISSION_GRANTED) {
2140 return;
2141 }
Jean-Michel Trivia7880d42017-04-15 12:41:05 -07002142 if (DEBUG_VOL) { Log.d(TAG, String.format("forceVolumeControlStream(%d)", streamType)); }
Eric Laurent45c90ce2012-04-24 18:44:22 -07002143 synchronized(mForceControlStreamLock) {
Jean-Michel Trivia7880d42017-04-15 12:41:05 -07002144 if (mVolumeControlStream != -1 && streamType != -1) {
2145 mUserSelectedVolumeControlStream = true;
2146 }
Eric Laurent45c90ce2012-04-24 18:44:22 -07002147 mVolumeControlStream = streamType;
2148 if (mVolumeControlStream == -1) {
2149 if (mForceControlStreamClient != null) {
2150 mForceControlStreamClient.release();
2151 mForceControlStreamClient = null;
2152 }
Jean-Michel Trivia7880d42017-04-15 12:41:05 -07002153 mUserSelectedVolumeControlStream = false;
Eric Laurent45c90ce2012-04-24 18:44:22 -07002154 } else {
jianzhou21fb09f2018-02-28 14:03:15 +08002155 if (null == mForceControlStreamClient) {
2156 mForceControlStreamClient = new ForceControlStreamClient(cb);
2157 } else {
2158 if (mForceControlStreamClient.getBinder() == cb) {
2159 Log.d(TAG, "forceVolumeControlStream cb:" + cb + " is already linked.");
2160 } else {
2161 mForceControlStreamClient.release();
2162 mForceControlStreamClient = new ForceControlStreamClient(cb);
2163 }
2164 }
Eric Laurent45c90ce2012-04-24 18:44:22 -07002165 }
2166 }
2167 }
2168
2169 private class ForceControlStreamClient implements IBinder.DeathRecipient {
2170 private IBinder mCb; // To be notified of client's death
2171
2172 ForceControlStreamClient(IBinder cb) {
2173 if (cb != null) {
2174 try {
2175 cb.linkToDeath(this, 0);
2176 } catch (RemoteException e) {
2177 // Client has died!
2178 Log.w(TAG, "ForceControlStreamClient() could not link to "+cb+" binder death");
2179 cb = null;
2180 }
2181 }
2182 mCb = cb;
2183 }
2184
2185 public void binderDied() {
2186 synchronized(mForceControlStreamLock) {
2187 Log.w(TAG, "SCO client died");
2188 if (mForceControlStreamClient != this) {
2189 Log.w(TAG, "unregistered control stream client died");
2190 } else {
2191 mForceControlStreamClient = null;
2192 mVolumeControlStream = -1;
Jean-Michel Trivia7880d42017-04-15 12:41:05 -07002193 mUserSelectedVolumeControlStream = false;
Eric Laurent45c90ce2012-04-24 18:44:22 -07002194 }
2195 }
2196 }
2197
2198 public void release() {
2199 if (mCb != null) {
2200 mCb.unlinkToDeath(this, 0);
2201 mCb = null;
2202 }
2203 }
jianzhou21fb09f2018-02-28 14:03:15 +08002204
2205 public IBinder getBinder() {
2206 return mCb;
2207 }
Eric Laurent45c90ce2012-04-24 18:44:22 -07002208 }
2209
Dianne Hackborn5ac72a22012-08-29 18:32:08 -07002210 private void sendBroadcastToAll(Intent intent) {
Christopher Tate267603f2015-01-20 14:21:21 -08002211 intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);
John Spurlock86490862015-02-25 11:22:52 -05002212 intent.addFlags(Intent.FLAG_RECEIVER_FOREGROUND);
Dianne Hackborn5ac72a22012-08-29 18:32:08 -07002213 final long ident = Binder.clearCallingIdentity();
2214 try {
2215 mContext.sendBroadcastAsUser(intent, UserHandle.ALL);
2216 } finally {
2217 Binder.restoreCallingIdentity(ident);
2218 }
2219 }
2220
2221 private void sendStickyBroadcastToAll(Intent intent) {
John Spurlock86490862015-02-25 11:22:52 -05002222 intent.addFlags(Intent.FLAG_RECEIVER_FOREGROUND);
Dianne Hackborn5ac72a22012-08-29 18:32:08 -07002223 final long ident = Binder.clearCallingIdentity();
2224 try {
2225 mContext.sendStickyBroadcastAsUser(intent, UserHandle.ALL);
2226 } finally {
2227 Binder.restoreCallingIdentity(ident);
2228 }
2229 }
2230
Kenny Guy70e0c582015-06-30 19:18:28 +01002231 private int getCurrentUserId() {
2232 final long ident = Binder.clearCallingIdentity();
2233 try {
Sudheer Shankadc589ac2016-11-10 15:30:17 -08002234 UserInfo currentUser = ActivityManager.getService().getCurrentUser();
Kenny Guy70e0c582015-06-30 19:18:28 +01002235 return currentUser.id;
2236 } catch (RemoteException e) {
2237 // Activity manager not running, nothing we can do assume user 0.
2238 } finally {
2239 Binder.restoreCallingIdentity(ident);
2240 }
Xiaohui Chen7c696362015-09-16 09:56:14 -07002241 return UserHandle.USER_SYSTEM;
Kenny Guy70e0c582015-06-30 19:18:28 +01002242 }
2243
Eric Laurent25101b02011-02-02 09:33:30 -08002244 // UI update and Broadcast Intent
Yue Li949865b2017-05-24 17:25:28 -07002245 protected void sendVolumeUpdate(int streamType, int oldIndex, int index, int flags) {
John Spurlock72966d62015-06-18 15:45:07 -04002246 streamType = mStreamVolumeAlias[streamType];
Eric Laurent25101b02011-02-02 09:33:30 -08002247
Jinsuk Kim336cdb42014-11-29 06:27:00 +09002248 if (streamType == AudioSystem.STREAM_MUSIC) {
2249 flags = updateFlagsForSystemAudio(flags);
Jungshik Jang1a6be6e2014-09-16 11:04:54 +09002250 }
John Spurlock3346a802014-05-20 16:25:37 -04002251 mVolumeController.postVolumeChanged(streamType, flags);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002252 }
2253
Jinsuk Kim336cdb42014-11-29 06:27:00 +09002254 // If Hdmi-CEC system audio mode is on, we show volume bar only when TV
2255 // receives volume notification from Audio Receiver.
2256 private int updateFlagsForSystemAudio(int flags) {
Shubangc480a712018-06-11 18:02:42 -07002257 synchronized (mHdmiClientLock) {
2258 if (mHdmiTvClient != null) {
Jinsuk Kim336cdb42014-11-29 06:27:00 +09002259 if (mHdmiSystemAudioSupported &&
2260 ((flags & AudioManager.FLAG_HDMI_SYSTEM_AUDIO_VOLUME) == 0)) {
2261 flags &= ~AudioManager.FLAG_SHOW_UI;
2262 }
2263 }
2264 }
2265 return flags;
2266 }
2267
Mike Lockwood0dc37cc2011-12-01 16:14:19 -05002268 // UI update and Broadcast Intent
Mike Lockwood0dc37cc2011-12-01 16:14:19 -05002269 private void sendMasterMuteUpdate(boolean muted, int flags) {
Jinsuk Kim336cdb42014-11-29 06:27:00 +09002270 mVolumeController.postMasterMuteChanged(updateFlagsForSystemAudio(flags));
Justin Koh57978ed2012-04-03 17:37:58 -07002271 broadcastMasterMuteStatus(muted);
2272 }
Mike Lockwood0dc37cc2011-12-01 16:14:19 -05002273
Justin Koh57978ed2012-04-03 17:37:58 -07002274 private void broadcastMasterMuteStatus(boolean muted) {
Mike Lockwood0dc37cc2011-12-01 16:14:19 -05002275 Intent intent = new Intent(AudioManager.MASTER_MUTE_CHANGED_ACTION);
2276 intent.putExtra(AudioManager.EXTRA_MASTER_VOLUME_MUTED, muted);
Justin Koh57978ed2012-04-03 17:37:58 -07002277 intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT
2278 | Intent.FLAG_RECEIVER_REPLACE_PENDING);
Dianne Hackborn5ac72a22012-08-29 18:32:08 -07002279 sendStickyBroadcastToAll(intent);
Mike Lockwood0dc37cc2011-12-01 16:14:19 -05002280 }
2281
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002282 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002283 * Sets the stream state's index, and posts a message to set system volume.
2284 * This will not call out to the UI. Assumes a valid stream type.
2285 *
2286 * @param streamType Type of the stream
2287 * @param index Desired volume index of the stream
Eric Laurent9bc8358d2011-11-18 16:43:31 -08002288 * @param device the device whose volume must be changed
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002289 * @param force If true, set the volume even if the desired volume is same
2290 * as the current volume.
2291 */
Eric Laurent9bc8358d2011-11-18 16:43:31 -08002292 private void setStreamVolumeInt(int streamType,
2293 int index,
2294 int device,
John Spurlock90874332015-03-10 16:00:54 -04002295 boolean force,
2296 String caller) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002297 VolumeStreamState streamState = mStreamStates[streamType];
Eric Laurent5b4e6542010-03-19 20:02:21 -07002298
John Spurlock90874332015-03-10 16:00:54 -04002299 if (streamState.setIndex(index, device, caller) || force) {
Eric Laurent42b041e2013-03-29 11:36:03 -07002300 // Post message to set system volume (it in turn will post a message
2301 // to persist).
2302 sendMsg(mAudioHandler,
2303 MSG_SET_DEVICE_VOLUME,
2304 SENDMSG_QUEUE,
2305 device,
2306 0,
2307 streamState,
2308 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002309 }
2310 }
2311
Jinsuk Kim336cdb42014-11-29 06:27:00 +09002312 private void setSystemAudioMute(boolean state) {
Shubangc480a712018-06-11 18:02:42 -07002313 synchronized (mHdmiClientLock) {
2314 if (mHdmiManager == null || mHdmiTvClient == null || !mHdmiSystemAudioSupported) return;
2315 final long token = Binder.clearCallingIdentity();
2316 try {
2317 mHdmiTvClient.setSystemAudioMute(state);
2318 } finally {
2319 Binder.restoreCallingIdentity(token);
Jinsuk Kim336cdb42014-11-29 06:27:00 +09002320 }
2321 }
2322 }
2323
Eric Laurent25101b02011-02-02 09:33:30 -08002324 /** get stream mute state. */
2325 public boolean isStreamMute(int streamType) {
RoboErik7c82ced2014-12-04 17:39:08 -08002326 if (streamType == AudioManager.USE_DEFAULT_STREAM_TYPE) {
2327 streamType = getActiveStreamType(streamType);
2328 }
Eric Laurent8fa4d6f2014-10-30 14:13:03 -07002329 synchronized (VolumeStreamState.class) {
jiabin93d32ef2017-07-11 13:50:02 -07002330 ensureValidStreamType(streamType);
RoboErik4197cb62015-01-21 15:45:32 -08002331 return mStreamStates[streamType].mIsMuted;
Eric Laurent8fa4d6f2014-10-30 14:13:03 -07002332 }
Eric Laurent25101b02011-02-02 09:33:30 -08002333 }
2334
Jean-Michel Triviba5270b2014-10-01 17:49:29 -07002335 private class RmtSbmxFullVolDeathHandler implements IBinder.DeathRecipient {
2336 private IBinder mICallback; // To be notified of client's death
2337
2338 RmtSbmxFullVolDeathHandler(IBinder cb) {
2339 mICallback = cb;
2340 try {
2341 cb.linkToDeath(this, 0/*flags*/);
2342 } catch (RemoteException e) {
2343 Log.e(TAG, "can't link to death", e);
2344 }
2345 }
2346
2347 boolean isHandlerFor(IBinder cb) {
2348 return mICallback.equals(cb);
2349 }
2350
2351 void forget() {
2352 try {
2353 mICallback.unlinkToDeath(this, 0/*flags*/);
2354 } catch (NoSuchElementException e) {
2355 Log.e(TAG, "error unlinking to death", e);
2356 }
2357 }
2358
2359 public void binderDied() {
2360 Log.w(TAG, "Recorder with remote submix at full volume died " + mICallback);
2361 forceRemoteSubmixFullVolume(false, mICallback);
2362 }
2363 }
2364
2365 /**
2366 * call must be synchronized on mRmtSbmxFullVolDeathHandlers
2367 * @return true if there is a registered death handler, false otherwise */
2368 private boolean discardRmtSbmxFullVolDeathHandlerFor(IBinder cb) {
2369 Iterator<RmtSbmxFullVolDeathHandler> it = mRmtSbmxFullVolDeathHandlers.iterator();
2370 while (it.hasNext()) {
2371 final RmtSbmxFullVolDeathHandler handler = it.next();
2372 if (handler.isHandlerFor(cb)) {
2373 handler.forget();
2374 mRmtSbmxFullVolDeathHandlers.remove(handler);
2375 return true;
2376 }
2377 }
2378 return false;
2379 }
2380
2381 /** call synchronized on mRmtSbmxFullVolDeathHandlers */
2382 private boolean hasRmtSbmxFullVolDeathHandlerFor(IBinder cb) {
2383 Iterator<RmtSbmxFullVolDeathHandler> it = mRmtSbmxFullVolDeathHandlers.iterator();
2384 while (it.hasNext()) {
2385 if (it.next().isHandlerFor(cb)) {
2386 return true;
2387 }
2388 }
2389 return false;
2390 }
2391
2392 private int mRmtSbmxFullVolRefCount = 0;
2393 private ArrayList<RmtSbmxFullVolDeathHandler> mRmtSbmxFullVolDeathHandlers =
2394 new ArrayList<RmtSbmxFullVolDeathHandler>();
2395
2396 public void forceRemoteSubmixFullVolume(boolean startForcing, IBinder cb) {
2397 if (cb == null) {
2398 return;
2399 }
2400 if ((PackageManager.PERMISSION_GRANTED != mContext.checkCallingOrSelfPermission(
2401 android.Manifest.permission.CAPTURE_AUDIO_OUTPUT))) {
2402 Log.w(TAG, "Trying to call forceRemoteSubmixFullVolume() without CAPTURE_AUDIO_OUTPUT");
2403 return;
2404 }
2405 synchronized(mRmtSbmxFullVolDeathHandlers) {
2406 boolean applyRequired = false;
2407 if (startForcing) {
2408 if (!hasRmtSbmxFullVolDeathHandlerFor(cb)) {
2409 mRmtSbmxFullVolDeathHandlers.add(new RmtSbmxFullVolDeathHandler(cb));
2410 if (mRmtSbmxFullVolRefCount == 0) {
2411 mFullVolumeDevices |= AudioSystem.DEVICE_OUT_REMOTE_SUBMIX;
2412 mFixedVolumeDevices |= AudioSystem.DEVICE_OUT_REMOTE_SUBMIX;
2413 applyRequired = true;
2414 }
2415 mRmtSbmxFullVolRefCount++;
2416 }
2417 } else {
2418 if (discardRmtSbmxFullVolDeathHandlerFor(cb) && (mRmtSbmxFullVolRefCount > 0)) {
2419 mRmtSbmxFullVolRefCount--;
2420 if (mRmtSbmxFullVolRefCount == 0) {
2421 mFullVolumeDevices &= ~AudioSystem.DEVICE_OUT_REMOTE_SUBMIX;
2422 mFixedVolumeDevices &= ~AudioSystem.DEVICE_OUT_REMOTE_SUBMIX;
2423 applyRequired = true;
2424 }
2425 }
2426 }
2427 if (applyRequired) {
2428 // Assumes only STREAM_MUSIC going through DEVICE_OUT_REMOTE_SUBMIX
2429 checkAllFixedVolumeDevices(AudioSystem.STREAM_MUSIC);
2430 mStreamStates[AudioSystem.STREAM_MUSIC].applyAllVolumes();
2431 }
2432 }
2433 }
2434
Kenny Guy70e0c582015-06-30 19:18:28 +01002435 private void setMasterMuteInternal(boolean mute, int flags, String callingPackage, int uid,
2436 int userId) {
2437 // If we are being called by the system check for user we are going to change
2438 // so we handle user restrictions correctly.
2439 if (uid == android.os.Process.SYSTEM_UID) {
2440 uid = UserHandle.getUid(userId, UserHandle.getAppId(uid));
2441 }
Makoto Onuki4f160732015-10-27 17:15:38 -07002442 // If OP_AUDIO_MASTER_VOLUME is set, disallow unmuting.
2443 if (!mute && mAppOps.noteOp(AppOpsManager.OP_AUDIO_MASTER_VOLUME, uid, callingPackage)
RoboErik7c82ced2014-12-04 17:39:08 -08002444 != AppOpsManager.MODE_ALLOWED) {
Julia Reynolds4a21b252014-06-04 11:11:43 -04002445 return;
2446 }
Kenny Guy70e0c582015-06-30 19:18:28 +01002447 if (userId != UserHandle.getCallingUserId() &&
2448 mContext.checkCallingOrSelfPermission(
2449 android.Manifest.permission.INTERACT_ACROSS_USERS_FULL)
2450 != PackageManager.PERMISSION_GRANTED) {
2451 return;
2452 }
Makoto Onukid45a4a22015-11-02 17:17:38 -08002453 setMasterMuteInternalNoCallerCheck(mute, flags, userId);
2454 }
2455
2456 private void setMasterMuteInternalNoCallerCheck(boolean mute, int flags, int userId) {
2457 if (DEBUG_VOL) {
2458 Log.d(TAG, String.format("Master mute %s, %d, user=%d", mute, flags, userId));
2459 }
Hongwei Wangdaba1242018-05-29 14:36:16 -07002460 if (!isPlatformAutomotive() && mUseFixedVolume) {
2461 // If using fixed volume, we don't mute.
2462 // TODO: remove the isPlatformAutomotive check here.
2463 // The isPlatformAutomotive check is added for safety but may not be necessary.
2464 return;
Makoto Onukid45a4a22015-11-02 17:17:38 -08002465 }
Kenny Guy70e0c582015-06-30 19:18:28 +01002466 if (getCurrentUserId() == userId) {
2467 if (mute != AudioSystem.getMasterMute()) {
2468 setSystemAudioMute(mute);
2469 AudioSystem.setMasterMute(mute);
Kenny Guy70e0c582015-06-30 19:18:28 +01002470 sendMasterMuteUpdate(mute, flags);
RoboErik7c82ced2014-12-04 17:39:08 -08002471
Kenny Guy70e0c582015-06-30 19:18:28 +01002472 Intent intent = new Intent(AudioManager.MASTER_MUTE_CHANGED_ACTION);
2473 intent.putExtra(AudioManager.EXTRA_MASTER_VOLUME_MUTED, mute);
2474 sendBroadcastToAll(intent);
2475 }
Jason Simmons1ce5b262012-02-02 13:00:17 -08002476 }
Mike Lockwoodce952c82011-11-14 10:47:42 -08002477 }
2478
2479 /** get master mute state. */
2480 public boolean isMasterMute() {
Mike Lockwood3194ea92011-12-07 11:47:31 -08002481 return AudioSystem.getMasterMute();
Mike Lockwoodce952c82011-11-14 10:47:42 -08002482 }
2483
Kenny Guy70e0c582015-06-30 19:18:28 +01002484 public void setMasterMute(boolean mute, int flags, String callingPackage, int userId) {
2485 setMasterMuteInternal(mute, flags, callingPackage, Binder.getCallingUid(),
2486 userId);
John Spurlockee5ad722015-03-03 16:17:21 -05002487 }
2488
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002489 /** @see AudioManager#getStreamVolume(int) */
2490 public int getStreamVolume(int streamType) {
2491 ensureValidStreamType(streamType);
Eric Laurent9bc8358d2011-11-18 16:43:31 -08002492 int device = getDeviceForStream(streamType);
Eric Laurent8fa4d6f2014-10-30 14:13:03 -07002493 synchronized (VolumeStreamState.class) {
2494 int index = mStreamStates[streamType].getIndex(device);
Eric Laurent4bbcc652012-09-24 14:26:30 -07002495
Eric Laurent8fa4d6f2014-10-30 14:13:03 -07002496 // by convention getStreamVolume() returns 0 when a stream is muted.
RoboErik4197cb62015-01-21 15:45:32 -08002497 if (mStreamStates[streamType].mIsMuted) {
Eric Laurent8fa4d6f2014-10-30 14:13:03 -07002498 index = 0;
2499 }
2500 if (index != 0 && (mStreamVolumeAlias[streamType] == AudioSystem.STREAM_MUSIC) &&
2501 (device & mFixedVolumeDevices) != 0) {
2502 index = mStreamStates[streamType].getMaxIndex();
2503 }
2504 return (index + 5) / 10;
Eric Laurent42b041e2013-03-29 11:36:03 -07002505 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002506 }
2507
2508 /** @see AudioManager#getStreamMaxVolume(int) */
2509 public int getStreamMaxVolume(int streamType) {
2510 ensureValidStreamType(streamType);
Eric Laurenta553c252009-07-17 12:17:14 -07002511 return (mStreamStates[streamType].getMaxIndex() + 5) / 10;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002512 }
2513
Jean-Michel Trivi8e7aca32017-11-28 18:12:38 -08002514 /** @see AudioManager#getStreamMinVolumeInt(int) */
John Spurlockb6e19e32015-03-10 21:33:44 -04002515 public int getStreamMinVolume(int streamType) {
2516 ensureValidStreamType(streamType);
2517 return (mStreamStates[streamType].getMinIndex() + 5) / 10;
2518 }
2519
Eric Laurent25101b02011-02-02 09:33:30 -08002520 /** Get last audible volume before stream was muted. */
2521 public int getLastAudibleStreamVolume(int streamType) {
2522 ensureValidStreamType(streamType);
Eric Laurent9bc8358d2011-11-18 16:43:31 -08002523 int device = getDeviceForStream(streamType);
Eric Laurent42b041e2013-03-29 11:36:03 -07002524 return (mStreamStates[streamType].getIndex(device) + 5) / 10;
Eric Laurent25101b02011-02-02 09:33:30 -08002525 }
2526
John Spurlockee5ad722015-03-03 16:17:21 -05002527 /** @see AudioManager#getUiSoundsStreamType() */
2528 public int getUiSoundsStreamType() {
John Spurlock4f0f1202014-08-05 13:28:33 -04002529 return mStreamVolumeAlias[AudioSystem.STREAM_SYSTEM];
Eric Laurent6d517662012-04-23 18:42:39 -07002530 }
2531
Makoto Onukid45a4a22015-11-02 17:17:38 -08002532 /** @see AudioManager#setMicrophoneMute(boolean) */
2533 @Override
Kenny Guy70e0c582015-06-30 19:18:28 +01002534 public void setMicrophoneMute(boolean on, String callingPackage, int userId) {
2535 // If we are being called by the system check for user we are going to change
2536 // so we handle user restrictions correctly.
2537 int uid = Binder.getCallingUid();
2538 if (uid == android.os.Process.SYSTEM_UID) {
2539 uid = UserHandle.getUid(userId, UserHandle.getAppId(uid));
2540 }
Makoto Onuki4f160732015-10-27 17:15:38 -07002541 // If OP_MUTE_MICROPHONE is set, disallow unmuting.
2542 if (!on && mAppOps.noteOp(AppOpsManager.OP_MUTE_MICROPHONE, uid, callingPackage)
Kenny Guy70e0c582015-06-30 19:18:28 +01002543 != AppOpsManager.MODE_ALLOWED) {
Emily Bernier22c921a2014-05-28 11:01:32 -04002544 return;
2545 }
Jean-Michel Trivi4a4fea02014-08-29 18:14:09 -07002546 if (!checkAudioSettingsPermission("setMicrophoneMute()")) {
2547 return;
2548 }
Kenny Guy70e0c582015-06-30 19:18:28 +01002549 if (userId != UserHandle.getCallingUserId() &&
2550 mContext.checkCallingOrSelfPermission(
2551 android.Manifest.permission.INTERACT_ACROSS_USERS_FULL)
2552 != PackageManager.PERMISSION_GRANTED) {
2553 return;
2554 }
Makoto Onukid45a4a22015-11-02 17:17:38 -08002555 setMicrophoneMuteNoCallerCheck(on, userId);
2556 }
Emily Bernier22c921a2014-05-28 11:01:32 -04002557
Makoto Onukid45a4a22015-11-02 17:17:38 -08002558 private void setMicrophoneMuteNoCallerCheck(boolean on, int userId) {
2559 if (DEBUG_VOL) {
2560 Log.d(TAG, String.format("Mic mute %s, user=%d", on, userId));
2561 }
Jean-Michel Trivi7be17d22017-12-21 18:09:21 -08002562 // only mute for the current user
Kenny Guy70e0c582015-06-30 19:18:28 +01002563 if (getCurrentUserId() == userId) {
Jean-Michel Trivi7be17d22017-12-21 18:09:21 -08002564 final boolean currentMute = AudioSystem.isMicrophoneMuted();
Eric Laurent66b69672018-01-26 18:30:51 -08002565 final long identity = Binder.clearCallingIdentity();
Kenny Guy70e0c582015-06-30 19:18:28 +01002566 AudioSystem.muteMicrophone(on);
Eric Laurent66b69672018-01-26 18:30:51 -08002567 Binder.restoreCallingIdentity(identity);
Jean-Michel Trivi7be17d22017-12-21 18:09:21 -08002568 if (on != currentMute) {
2569 mContext.sendBroadcast(new Intent(AudioManager.ACTION_MICROPHONE_MUTE_CHANGED)
2570 .setFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY));
2571 }
Kenny Guy70e0c582015-06-30 19:18:28 +01002572 }
Emily Bernier22c921a2014-05-28 11:01:32 -04002573 }
2574
John Spurlock661f2cf2014-11-17 10:29:10 -05002575 @Override
2576 public int getRingerModeExternal() {
2577 synchronized(mSettingsLock) {
2578 return mRingerModeExternal;
2579 }
2580 }
2581
2582 @Override
2583 public int getRingerModeInternal() {
Glenn Kastenba195eb2011-12-13 09:30:40 -08002584 synchronized(mSettingsLock) {
2585 return mRingerMode;
2586 }
2587 }
2588
2589 private void ensureValidRingerMode(int ringerMode) {
John Spurlock97559372014-10-24 16:27:36 -04002590 if (!isValidRingerMode(ringerMode)) {
Glenn Kastenba195eb2011-12-13 09:30:40 -08002591 throw new IllegalArgumentException("Bad ringer mode " + ringerMode);
2592 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002593 }
2594
John Spurlock97559372014-10-24 16:27:36 -04002595 /** @see AudioManager#isValidRingerMode(int) */
2596 public boolean isValidRingerMode(int ringerMode) {
2597 return ringerMode >= 0 && ringerMode <= AudioManager.RINGER_MODE_MAX;
2598 }
2599
John Spurlock661f2cf2014-11-17 10:29:10 -05002600 public void setRingerModeExternal(int ringerMode, String caller) {
Julia Reynolds48034f82016-03-09 10:15:16 -05002601 if (isAndroidNPlus(caller) && wouldToggleZenMode(ringerMode)
2602 && !mNm.isNotificationPolicyAccessGrantedForPackage(caller)) {
2603 throw new SecurityException("Not allowed to change Do Not Disturb state");
2604 }
2605
John Spurlockaf88a192014-12-23 16:14:44 -05002606 setRingerMode(ringerMode, caller, true /*external*/);
John Spurlock661f2cf2014-11-17 10:29:10 -05002607 }
2608
2609 public void setRingerModeInternal(int ringerMode, String caller) {
John Spurlockcdb57ae2015-02-11 19:04:11 -05002610 enforceVolumeController("setRingerModeInternal");
John Spurlockaf88a192014-12-23 16:14:44 -05002611 setRingerMode(ringerMode, caller, false /*external*/);
John Spurlock661f2cf2014-11-17 10:29:10 -05002612 }
2613
Mike Digman55272862018-02-20 14:35:17 -08002614 public void silenceRingerModeInternal(String reason) {
2615 VibrationEffect effect = null;
2616 int ringerMode = AudioManager.RINGER_MODE_SILENT;
2617 int toastText = 0;
2618
2619 int silenceRingerSetting = Settings.Secure.VOLUME_HUSH_OFF;
2620 if (mContext.getResources()
2621 .getBoolean(com.android.internal.R.bool.config_volumeHushGestureEnabled)) {
2622 silenceRingerSetting = Settings.Secure.getIntForUser(mContentResolver,
2623 Settings.Secure.VOLUME_HUSH_GESTURE, VOLUME_HUSH_OFF,
2624 UserHandle.USER_CURRENT);
2625 }
2626
2627 switch(silenceRingerSetting) {
2628 case VOLUME_HUSH_MUTE:
2629 effect = VibrationEffect.get(VibrationEffect.EFFECT_DOUBLE_CLICK);
2630 ringerMode = AudioManager.RINGER_MODE_SILENT;
2631 toastText = com.android.internal.R.string.volume_dialog_ringer_guidance_silent;
2632 break;
2633 case VOLUME_HUSH_VIBRATE:
2634 effect = VibrationEffect.get(VibrationEffect.EFFECT_HEAVY_CLICK);
2635 ringerMode = AudioManager.RINGER_MODE_VIBRATE;
2636 toastText = com.android.internal.R.string.volume_dialog_ringer_guidance_vibrate;
2637 break;
2638 }
Alexey Kuzmine1f06b82018-06-20 17:48:43 +01002639 maybeVibrate(effect, reason);
Mike Digman55272862018-02-20 14:35:17 -08002640 setRingerModeInternal(ringerMode, reason);
2641 Toast.makeText(mContext, toastText, Toast.LENGTH_SHORT).show();
2642 }
2643
Alexey Kuzmine1f06b82018-06-20 17:48:43 +01002644 private boolean maybeVibrate(VibrationEffect effect, String reason) {
Mike Digman55272862018-02-20 14:35:17 -08002645 if (!mHasVibrator) {
2646 return false;
2647 }
2648 final boolean hapticsDisabled = Settings.System.getIntForUser(mContext.getContentResolver(),
2649 Settings.System.HAPTIC_FEEDBACK_ENABLED, 0, UserHandle.USER_CURRENT) == 0;
2650 if (hapticsDisabled) {
2651 return false;
2652 }
2653
2654 if (effect == null) {
2655 return false;
2656 }
Alexey Kuzmine1f06b82018-06-20 17:48:43 +01002657 mVibrator.vibrate(Binder.getCallingUid(), mContext.getOpPackageName(), effect,
2658 reason, VIBRATION_ATTRIBUTES);
Mike Digman55272862018-02-20 14:35:17 -08002659 return true;
2660 }
2661
John Spurlock661f2cf2014-11-17 10:29:10 -05002662 private void setRingerMode(int ringerMode, String caller, boolean external) {
Muyuan Li1ed6df62016-06-18 11:16:52 -07002663 if (mUseFixedVolume || mIsSingleVolume) {
Eric Laurent83a017b2013-03-19 18:15:31 -07002664 return;
2665 }
John Spurlock661f2cf2014-11-17 10:29:10 -05002666 if (caller == null || caller.length() == 0) {
2667 throw new IllegalArgumentException("Bad caller: " + caller);
2668 }
John Spurlock97559372014-10-24 16:27:36 -04002669 ensureValidRingerMode(ringerMode);
Eric Laurent24482012012-05-10 09:41:17 -07002670 if ((ringerMode == AudioManager.RINGER_MODE_VIBRATE) && !mHasVibrator) {
2671 ringerMode = AudioManager.RINGER_MODE_SILENT;
2672 }
John Spurlockaf88a192014-12-23 16:14:44 -05002673 final long identity = Binder.clearCallingIdentity();
2674 try {
2675 synchronized (mSettingsLock) {
2676 final int ringerModeInternal = getRingerModeInternal();
2677 final int ringerModeExternal = getRingerModeExternal();
2678 if (external) {
2679 setRingerModeExt(ringerMode);
2680 if (mRingerModeDelegate != null) {
2681 ringerMode = mRingerModeDelegate.onSetRingerModeExternal(ringerModeExternal,
John Spurlocka48d7792015-03-03 17:35:57 -05002682 ringerMode, caller, ringerModeInternal, mVolumePolicy);
John Spurlockaf88a192014-12-23 16:14:44 -05002683 }
2684 if (ringerMode != ringerModeInternal) {
2685 setRingerModeInt(ringerMode, true /*persist*/);
2686 }
2687 } else /*internal*/ {
2688 if (ringerMode != ringerModeInternal) {
2689 setRingerModeInt(ringerMode, true /*persist*/);
2690 }
2691 if (mRingerModeDelegate != null) {
2692 ringerMode = mRingerModeDelegate.onSetRingerModeInternal(ringerModeInternal,
John Spurlocka48d7792015-03-03 17:35:57 -05002693 ringerMode, caller, ringerModeExternal, mVolumePolicy);
John Spurlockaf88a192014-12-23 16:14:44 -05002694 }
2695 setRingerModeExt(ringerMode);
John Spurlock57627792014-12-11 11:29:54 -05002696 }
John Spurlock661f2cf2014-11-17 10:29:10 -05002697 }
John Spurlockaf88a192014-12-23 16:14:44 -05002698 } finally {
2699 Binder.restoreCallingIdentity(identity);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002700 }
2701 }
2702
John Spurlock661f2cf2014-11-17 10:29:10 -05002703 private void setRingerModeExt(int ringerMode) {
2704 synchronized(mSettingsLock) {
2705 if (ringerMode == mRingerModeExternal) return;
2706 mRingerModeExternal = ringerMode;
John Spurlocke5b42d92014-10-15 12:03:48 -04002707 }
John Spurlock661f2cf2014-11-17 10:29:10 -05002708 // Send sticky broadcast
John Spurlockbcc10872014-11-28 15:29:21 -05002709 broadcastRingerMode(AudioManager.RINGER_MODE_CHANGED_ACTION, ringerMode);
John Spurlocke5b42d92014-10-15 12:03:48 -04002710 }
2711
Jean-Michel Trivic106d9f2018-06-07 12:28:27 -07002712 @GuardedBy("mSettingsLock")
John Spurlock50ced3f2015-05-11 16:00:09 -04002713 private void muteRingerModeStreams() {
Beverlyd6964762018-02-16 14:07:03 -05002714 // Mute stream if not previously muted by ringer mode and (ringer mode
2715 // is not RINGER_MODE_NORMAL OR stream is zen muted) and stream is affected by ringer mode.
2716 // Unmute stream if previously muted by ringer/zen mode and ringer mode
Eric Laurent5b4e6542010-03-19 20:02:21 -07002717 // is RINGER_MODE_NORMAL or stream is not affected by ringer mode.
Jason Parekhb1096152009-03-24 17:48:25 -07002718 int numStreamTypes = AudioSystem.getNumStreamTypes();
Beverly925cde82018-01-23 09:31:23 -05002719
2720 if (mNm == null) {
2721 mNm = (NotificationManager) mContext.getSystemService(Context.NOTIFICATION_SERVICE);
2722 }
2723
Jack He6dd78c12018-02-12 21:00:24 -08002724 final int ringerMode = mRingerMode; // Read ringer mode as reading primitives is atomic
2725 final boolean ringerModeMute = ringerMode == AudioManager.RINGER_MODE_VIBRATE
2726 || ringerMode == AudioManager.RINGER_MODE_SILENT;
2727 final boolean shouldRingSco = ringerMode == AudioManager.RINGER_MODE_VIBRATE
2728 && isBluetoothScoOn();
2729 // Ask audio policy engine to force use Bluetooth SCO channel if needed
2730 final String eventSource = "muteRingerModeStreams() from u/pid:" + Binder.getCallingUid()
2731 + "/" + Binder.getCallingPid();
2732 sendMsg(mAudioHandler, MSG_SET_FORCE_USE, SENDMSG_QUEUE, AudioSystem.FOR_VIBRATE_RINGING,
2733 shouldRingSco ? AudioSystem.FORCE_BT_SCO : AudioSystem.FORCE_NONE, eventSource, 0);
Beverly925cde82018-01-23 09:31:23 -05002734
Eric Laurent5b4e6542010-03-19 20:02:21 -07002735 for (int streamType = numStreamTypes - 1; streamType >= 0; streamType--) {
Beverlyd6964762018-02-16 14:07:03 -05002736 final boolean isMuted = isStreamMutedByRingerOrZenMode(streamType);
Jack He6dd78c12018-02-12 21:00:24 -08002737 final boolean muteAllowedBySco =
2738 !(shouldRingSco && streamType == AudioSystem.STREAM_RING);
Beverlyd6964762018-02-16 14:07:03 -05002739 final boolean shouldZenMute = shouldZenMuteStream(streamType);
2740 final boolean shouldMute = shouldZenMute || (ringerModeMute
Jack He6dd78c12018-02-12 21:00:24 -08002741 && isStreamAffectedByRingerMode(streamType) && muteAllowedBySco);
John Spurlock661f2cf2014-11-17 10:29:10 -05002742 if (isMuted == shouldMute) continue;
2743 if (!shouldMute) {
2744 // unmute
2745 // ring and notifications volume should never be 0 when not silenced
John Spurlockd9c75db2015-04-28 11:19:13 -04002746 if (mStreamVolumeAlias[streamType] == AudioSystem.STREAM_RING) {
John Spurlock661f2cf2014-11-17 10:29:10 -05002747 synchronized (VolumeStreamState.class) {
John Spurlocka48d7792015-03-03 17:35:57 -05002748 final VolumeStreamState vss = mStreamStates[streamType];
2749 for (int i = 0; i < vss.mIndexMap.size(); i++) {
2750 int device = vss.mIndexMap.keyAt(i);
2751 int value = vss.mIndexMap.valueAt(i);
John Spurlock2bb02ec2015-03-02 13:13:06 -05002752 if (value == 0) {
John Spurlocka48d7792015-03-03 17:35:57 -05002753 vss.setIndex(10, device, TAG);
Eric Laurent9bc8358d2011-11-18 16:43:31 -08002754 }
2755 }
Eric Laurent9e0d25f2015-02-12 17:28:53 -08002756 // Persist volume for stream ring when it is changed here
2757 final int device = getDeviceForStream(streamType);
2758 sendMsg(mAudioHandler,
2759 MSG_PERSIST_VOLUME,
2760 SENDMSG_QUEUE,
2761 device,
2762 0,
2763 mStreamStates[streamType],
2764 PERSIST_DELAY);
Eric Laurentb024c302011-10-14 17:19:27 -07002765 }
Eric Laurent9bcf4012009-06-12 06:09:28 -07002766 }
RoboErik4197cb62015-01-21 15:45:32 -08002767 mStreamStates[streamType].mute(false);
Beverlyd6964762018-02-16 14:07:03 -05002768 mRingerAndZenModeMutedStreams &= ~(1 << streamType);
Eric Laurent5b4e6542010-03-19 20:02:21 -07002769 } else {
John Spurlock661f2cf2014-11-17 10:29:10 -05002770 // mute
RoboErik4197cb62015-01-21 15:45:32 -08002771 mStreamStates[streamType].mute(true);
Beverlyd6964762018-02-16 14:07:03 -05002772 mRingerAndZenModeMutedStreams |= (1 << streamType);
Jason Parekhb1096152009-03-24 17:48:25 -07002773 }
2774 }
John Spurlock50ced3f2015-05-11 16:00:09 -04002775 }
2776
Beverly925cde82018-01-23 09:31:23 -05002777 private boolean isAlarm(int streamType) {
2778 return streamType == AudioSystem.STREAM_ALARM;
2779 }
2780
2781 private boolean isNotificationOrRinger(int streamType) {
2782 return streamType == AudioSystem.STREAM_NOTIFICATION
2783 || streamType == AudioSystem.STREAM_RING;
2784 }
2785
2786 private boolean isMedia(int streamType) {
Beverlyd6964762018-02-16 14:07:03 -05002787 return streamType == AudioSystem.STREAM_MUSIC;
2788 }
2789
2790
2791 private boolean isSystem(int streamType) {
2792 return streamType == AudioSystem.STREAM_SYSTEM;
Beverly925cde82018-01-23 09:31:23 -05002793 }
2794
John Spurlock50ced3f2015-05-11 16:00:09 -04002795 private void setRingerModeInt(int ringerMode, boolean persist) {
2796 final boolean change;
2797 synchronized(mSettingsLock) {
2798 change = mRingerMode != ringerMode;
2799 mRingerMode = ringerMode;
Jean-Michel Trivic106d9f2018-06-07 12:28:27 -07002800 muteRingerModeStreams();
John Spurlock50ced3f2015-05-11 16:00:09 -04002801 }
2802
Jason Parekhb1096152009-03-24 17:48:25 -07002803 // Post a persist ringer mode msg
Eric Laurent4050c932009-07-08 02:52:14 -07002804 if (persist) {
Eric Laurentafbb0472011-12-15 09:04:23 -08002805 sendMsg(mAudioHandler, MSG_PERSIST_RINGER_MODE,
Eric Laurent4050c932009-07-08 02:52:14 -07002806 SENDMSG_REPLACE, 0, 0, null, PERSIST_DELAY);
2807 }
John Spurlockbcc10872014-11-28 15:29:21 -05002808 if (change) {
2809 // Send sticky broadcast
2810 broadcastRingerMode(AudioManager.INTERNAL_RINGER_MODE_CHANGED_ACTION, ringerMode);
2811 }
Jason Parekhb1096152009-03-24 17:48:25 -07002812 }
2813
Jean-Michel Trivica49d312019-02-14 15:55:39 -08002814 /*package*/ void postUpdateRingerModeServiceInt() {
2815 sendMsg(mAudioHandler, MSG_UPDATE_RINGER_MODE, SENDMSG_QUEUE, 0, 0, null, 0);
2816 }
2817
2818 private void onUpdateRingerModeServiceInt() {
Jean-Michel Trivi58850372018-09-14 16:01:28 -07002819 setRingerModeInt(getRingerModeInternal(), false);
2820 }
2821
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002822 /** @see AudioManager#shouldVibrate(int) */
2823 public boolean shouldVibrate(int vibrateType) {
Eric Laurentbffc3d12012-05-07 17:43:49 -07002824 if (!mHasVibrator) return false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002825
2826 switch (getVibrateSetting(vibrateType)) {
2827
2828 case AudioManager.VIBRATE_SETTING_ON:
John Spurlock57627792014-12-11 11:29:54 -05002829 return getRingerModeExternal() != AudioManager.RINGER_MODE_SILENT;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002830
2831 case AudioManager.VIBRATE_SETTING_ONLY_SILENT:
John Spurlock57627792014-12-11 11:29:54 -05002832 return getRingerModeExternal() == AudioManager.RINGER_MODE_VIBRATE;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002833
2834 case AudioManager.VIBRATE_SETTING_OFF:
Daniel Sandlerbcac4962010-04-12 13:23:57 -04002835 // return false, even for incoming calls
2836 return false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002837
2838 default:
2839 return false;
2840 }
2841 }
2842
2843 /** @see AudioManager#getVibrateSetting(int) */
2844 public int getVibrateSetting(int vibrateType) {
Eric Laurentbffc3d12012-05-07 17:43:49 -07002845 if (!mHasVibrator) return AudioManager.VIBRATE_SETTING_OFF;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002846 return (mVibrateSetting >> (vibrateType * 2)) & 3;
2847 }
2848
2849 /** @see AudioManager#setVibrateSetting(int, int) */
2850 public void setVibrateSetting(int vibrateType, int vibrateSetting) {
2851
Eric Laurentbffc3d12012-05-07 17:43:49 -07002852 if (!mHasVibrator) return;
2853
John Spurlock61560172015-02-06 19:46:04 -05002854 mVibrateSetting = AudioSystem.getValueForVibrateSetting(mVibrateSetting, vibrateType,
2855 vibrateSetting);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002856
2857 // Broadcast change
2858 broadcastVibrateSetting(vibrateType);
2859
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002860 }
2861
Jean-Michel Trivi58850372018-09-14 16:01:28 -07002862 /*package*/ class SetModeDeathHandler implements IBinder.DeathRecipient {
Eric Laurent9272b4b2010-01-23 17:12:59 -08002863 private IBinder mCb; // To be notified of client's death
Marco Nelissenf1ddd512011-08-10 14:15:44 -07002864 private int mPid;
Eric Laurent9272b4b2010-01-23 17:12:59 -08002865 private int mMode = AudioSystem.MODE_NORMAL; // Current mode set by this client
2866
Eric Laurent9f103de2011-09-08 15:04:23 -07002867 SetModeDeathHandler(IBinder cb, int pid) {
Eric Laurent9272b4b2010-01-23 17:12:59 -08002868 mCb = cb;
Eric Laurent9f103de2011-09-08 15:04:23 -07002869 mPid = pid;
Eric Laurent9272b4b2010-01-23 17:12:59 -08002870 }
2871
2872 public void binderDied() {
Jack He89f97982018-05-02 19:10:56 -07002873 int oldModeOwnerPid = 0;
Eric Laurentd7454be2011-09-14 08:45:58 -07002874 int newModeOwnerPid = 0;
Jean-Michel Trivi58850372018-09-14 16:01:28 -07002875 synchronized (mDeviceBroker.mSetModeLock) {
Eric Laurent9272b4b2010-01-23 17:12:59 -08002876 Log.w(TAG, "setMode() client died");
Jack He89f97982018-05-02 19:10:56 -07002877 if (!mSetModeDeathHandlers.isEmpty()) {
2878 oldModeOwnerPid = mSetModeDeathHandlers.get(0).getPid();
2879 }
Eric Laurent9272b4b2010-01-23 17:12:59 -08002880 int index = mSetModeDeathHandlers.indexOf(this);
2881 if (index < 0) {
2882 Log.w(TAG, "unregistered setMode() client died");
2883 } else {
John Spurlock90874332015-03-10 16:00:54 -04002884 newModeOwnerPid = setModeInt(AudioSystem.MODE_NORMAL, mCb, mPid, TAG);
Eric Laurent9272b4b2010-01-23 17:12:59 -08002885 }
2886 }
Eric Laurent9f103de2011-09-08 15:04:23 -07002887 // when entering RINGTONE, IN_CALL or IN_COMMUNICATION mode, clear all
Jack He89f97982018-05-02 19:10:56 -07002888 // SCO connections not started by the application changing the mode when pid changes
2889 if ((newModeOwnerPid != oldModeOwnerPid) && (newModeOwnerPid != 0)) {
Jean-Michel Trivi58850372018-09-14 16:01:28 -07002890 mDeviceBroker.postDisconnectBluetoothSco(newModeOwnerPid);
Eric Laurent9f103de2011-09-08 15:04:23 -07002891 }
Eric Laurent9272b4b2010-01-23 17:12:59 -08002892 }
2893
Marco Nelissenf1ddd512011-08-10 14:15:44 -07002894 public int getPid() {
2895 return mPid;
2896 }
2897
Eric Laurent9272b4b2010-01-23 17:12:59 -08002898 public void setMode(int mode) {
2899 mMode = mode;
2900 }
2901
2902 public int getMode() {
2903 return mMode;
2904 }
2905
2906 public IBinder getBinder() {
2907 return mCb;
2908 }
2909 }
2910
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002911 /** @see AudioManager#setMode(int) */
John Spurlock90874332015-03-10 16:00:54 -04002912 public void setMode(int mode, IBinder cb, String callingPackage) {
2913 if (DEBUG_MODE) { Log.v(TAG, "setMode(mode=" + mode + ", callingPackage=" + callingPackage + ")"); }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002914 if (!checkAudioSettingsPermission("setMode()")) {
2915 return;
2916 }
Eric Laurenta553c252009-07-17 12:17:14 -07002917
Jean-Michel Triviccd654e2014-09-03 17:48:47 -07002918 if ( (mode == AudioSystem.MODE_IN_CALL) &&
2919 (mContext.checkCallingOrSelfPermission(
2920 android.Manifest.permission.MODIFY_PHONE_STATE)
2921 != PackageManager.PERMISSION_GRANTED)) {
2922 Log.w(TAG, "MODIFY_PHONE_STATE Permission Denial: setMode(MODE_IN_CALL) from pid="
2923 + Binder.getCallingPid() + ", uid=" + Binder.getCallingUid());
2924 return;
2925 }
2926
Jean-Michel Trivi8f677d62010-11-15 12:11:32 -08002927 if (mode < AudioSystem.MODE_CURRENT || mode >= AudioSystem.NUM_MODES) {
Eric Laurenta553c252009-07-17 12:17:14 -07002928 return;
2929 }
2930
Jack He89f97982018-05-02 19:10:56 -07002931 int oldModeOwnerPid = 0;
Eric Laurentd7454be2011-09-14 08:45:58 -07002932 int newModeOwnerPid = 0;
Jean-Michel Trivi58850372018-09-14 16:01:28 -07002933 synchronized (mDeviceBroker.mSetModeLock) {
Jack He89f97982018-05-02 19:10:56 -07002934 if (!mSetModeDeathHandlers.isEmpty()) {
2935 oldModeOwnerPid = mSetModeDeathHandlers.get(0).getPid();
2936 }
Eric Laurenta553c252009-07-17 12:17:14 -07002937 if (mode == AudioSystem.MODE_CURRENT) {
2938 mode = mMode;
2939 }
John Spurlock90874332015-03-10 16:00:54 -04002940 newModeOwnerPid = setModeInt(mode, cb, Binder.getCallingPid(), callingPackage);
Eric Laurent9f103de2011-09-08 15:04:23 -07002941 }
2942 // when entering RINGTONE, IN_CALL or IN_COMMUNICATION mode, clear all
Jack He89f97982018-05-02 19:10:56 -07002943 // SCO connections not started by the application changing the mode when pid changes
2944 if ((newModeOwnerPid != oldModeOwnerPid) && (newModeOwnerPid != 0)) {
Jean-Michel Trivi58850372018-09-14 16:01:28 -07002945 mDeviceBroker.postDisconnectBluetoothSco(newModeOwnerPid);
Eric Laurent9f103de2011-09-08 15:04:23 -07002946 }
2947 }
Jean-Michel Trivi2ade5762010-12-11 13:18:30 -08002948
Jean-Michel Trivi58850372018-09-14 16:01:28 -07002949 // must be called synchronized on mSetModeLock
Eric Laurentd7454be2011-09-14 08:45:58 -07002950 // setModeInt() returns a valid PID if the audio mode was successfully set to
Eric Laurent9f103de2011-09-08 15:04:23 -07002951 // any mode other than NORMAL.
John Spurlock90874332015-03-10 16:00:54 -04002952 private int setModeInt(int mode, IBinder cb, int pid, String caller) {
2953 if (DEBUG_MODE) { Log.v(TAG, "setModeInt(mode=" + mode + ", pid=" + pid + ", caller="
2954 + caller + ")"); }
Eric Laurentd7454be2011-09-14 08:45:58 -07002955 int newModeOwnerPid = 0;
Eric Laurent9f103de2011-09-08 15:04:23 -07002956 if (cb == null) {
2957 Log.e(TAG, "setModeInt() called with null binder");
Eric Laurentd7454be2011-09-14 08:45:58 -07002958 return newModeOwnerPid;
Eric Laurent9f103de2011-09-08 15:04:23 -07002959 }
Jean-Michel Trivi2ade5762010-12-11 13:18:30 -08002960
Eric Laurent9f103de2011-09-08 15:04:23 -07002961 SetModeDeathHandler hdlr = null;
2962 Iterator iter = mSetModeDeathHandlers.iterator();
2963 while (iter.hasNext()) {
2964 SetModeDeathHandler h = (SetModeDeathHandler)iter.next();
2965 if (h.getPid() == pid) {
2966 hdlr = h;
2967 // Remove from client list so that it is re-inserted at top of list
2968 iter.remove();
2969 hdlr.getBinder().unlinkToDeath(hdlr, 0);
2970 break;
2971 }
2972 }
2973 int status = AudioSystem.AUDIO_STATUS_OK;
Eric Laurent6afa6502017-09-28 15:18:19 -07002974 int actualMode;
Eric Laurent9f103de2011-09-08 15:04:23 -07002975 do {
Eric Laurent6afa6502017-09-28 15:18:19 -07002976 actualMode = mode;
Eric Laurent9f103de2011-09-08 15:04:23 -07002977 if (mode == AudioSystem.MODE_NORMAL) {
2978 // get new mode from client at top the list if any
2979 if (!mSetModeDeathHandlers.isEmpty()) {
2980 hdlr = mSetModeDeathHandlers.get(0);
2981 cb = hdlr.getBinder();
Eric Laurent6afa6502017-09-28 15:18:19 -07002982 actualMode = hdlr.getMode();
Jean-Michel Trivi339567d2014-07-29 09:53:34 -07002983 if (DEBUG_MODE) {
2984 Log.w(TAG, " using mode=" + mode + " instead due to death hdlr at pid="
2985 + hdlr.mPid);
2986 }
Eric Laurentb9c9d262009-05-06 08:13:20 -07002987 }
Eric Laurent9f103de2011-09-08 15:04:23 -07002988 } else {
2989 if (hdlr == null) {
2990 hdlr = new SetModeDeathHandler(cb, pid);
2991 }
2992 // Register for client death notification
2993 try {
2994 cb.linkToDeath(hdlr, 0);
2995 } catch (RemoteException e) {
2996 // Client has died!
2997 Log.w(TAG, "setMode() could not link to "+cb+" binder death");
2998 }
2999
3000 // Last client to call setMode() is always at top of client list
3001 // as required by SetModeDeathHandler.binderDied()
3002 mSetModeDeathHandlers.add(0, hdlr);
3003 hdlr.setMode(mode);
3004 }
3005
Eric Laurent6afa6502017-09-28 15:18:19 -07003006 if (actualMode != mMode) {
Eric Laurent66b69672018-01-26 18:30:51 -08003007 final long identity = Binder.clearCallingIdentity();
Eric Laurent6afa6502017-09-28 15:18:19 -07003008 status = AudioSystem.setPhoneState(actualMode);
Eric Laurent66b69672018-01-26 18:30:51 -08003009 Binder.restoreCallingIdentity(identity);
Eric Laurent9f103de2011-09-08 15:04:23 -07003010 if (status == AudioSystem.AUDIO_STATUS_OK) {
Eric Laurent6afa6502017-09-28 15:18:19 -07003011 if (DEBUG_MODE) { Log.v(TAG, " mode successfully set to " + actualMode); }
3012 mMode = actualMode;
Eric Laurent9f103de2011-09-08 15:04:23 -07003013 } else {
3014 if (hdlr != null) {
3015 mSetModeDeathHandlers.remove(hdlr);
3016 cb.unlinkToDeath(hdlr, 0);
3017 }
3018 // force reading new top of mSetModeDeathHandlers stack
Jean-Michel Trivi339567d2014-07-29 09:53:34 -07003019 if (DEBUG_MODE) { Log.w(TAG, " mode set to MODE_NORMAL after phoneState pb"); }
Eric Laurent9f103de2011-09-08 15:04:23 -07003020 mode = AudioSystem.MODE_NORMAL;
3021 }
3022 } else {
3023 status = AudioSystem.AUDIO_STATUS_OK;
3024 }
3025 } while (status != AudioSystem.AUDIO_STATUS_OK && !mSetModeDeathHandlers.isEmpty());
3026
3027 if (status == AudioSystem.AUDIO_STATUS_OK) {
Eric Laurent6afa6502017-09-28 15:18:19 -07003028 if (actualMode != AudioSystem.MODE_NORMAL) {
Eric Laurentd7454be2011-09-14 08:45:58 -07003029 if (mSetModeDeathHandlers.isEmpty()) {
3030 Log.e(TAG, "setMode() different from MODE_NORMAL with empty mode client stack");
3031 } else {
3032 newModeOwnerPid = mSetModeDeathHandlers.get(0).getPid();
3033 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003034 }
Eric Laurent6afa6502017-09-28 15:18:19 -07003035 // Note: newModeOwnerPid is always 0 when actualMode is MODE_NORMAL
3036 mModeLogger.log(
3037 new PhoneStateEvent(caller, pid, mode, newModeOwnerPid, actualMode));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003038 int streamType = getActiveStreamType(AudioManager.USE_DEFAULT_STREAM_TYPE);
Eric Laurent9bc8358d2011-11-18 16:43:31 -08003039 int device = getDeviceForStream(streamType);
Eric Laurent42b041e2013-03-29 11:36:03 -07003040 int index = mStreamStates[mStreamVolumeAlias[streamType]].getIndex(device);
John Spurlock90874332015-03-10 16:00:54 -04003041 setStreamVolumeInt(mStreamVolumeAlias[streamType], index, device, true, caller);
Eric Laurent6d517662012-04-23 18:42:39 -07003042
John Spurlock90874332015-03-10 16:00:54 -04003043 updateStreamVolumeAlias(true /*updateVolumes*/, caller);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003044 }
Eric Laurentd7454be2011-09-14 08:45:58 -07003045 return newModeOwnerPid;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003046 }
3047
3048 /** @see AudioManager#getMode() */
3049 public int getMode() {
3050 return mMode;
3051 }
3052
Eric Laurente78fced2013-03-15 16:03:47 -07003053 //==========================================================================================
3054 // Sound Effects
3055 //==========================================================================================
3056
3057 private static final String TAG_AUDIO_ASSETS = "audio_assets";
3058 private static final String ATTR_VERSION = "version";
3059 private static final String TAG_GROUP = "group";
3060 private static final String ATTR_GROUP_NAME = "name";
3061 private static final String TAG_ASSET = "asset";
3062 private static final String ATTR_ASSET_ID = "id";
3063 private static final String ATTR_ASSET_FILE = "file";
3064
3065 private static final String ASSET_FILE_VERSION = "1.0";
3066 private static final String GROUP_TOUCH_SOUNDS = "touch_sounds";
3067
Glenn Kasten167d1a22013-07-23 16:24:41 -07003068 private static final int SOUND_EFFECTS_LOAD_TIMEOUT_MS = 5000;
Eric Laurent5d3eb44a2013-03-21 15:35:10 -07003069
3070 class LoadSoundEffectReply {
3071 public int mStatus = 1;
3072 };
3073
Eric Laurente78fced2013-03-15 16:03:47 -07003074 private void loadTouchSoundAssetDefaults() {
3075 SOUND_EFFECT_FILES.add("Effect_Tick.ogg");
3076 for (int i = 0; i < AudioManager.NUM_SOUND_EFFECTS; i++) {
3077 SOUND_EFFECT_FILES_MAP[i][0] = 0;
3078 SOUND_EFFECT_FILES_MAP[i][1] = -1;
3079 }
3080 }
3081
3082 private void loadTouchSoundAssets() {
3083 XmlResourceParser parser = null;
3084
Eric Laurent5d3eb44a2013-03-21 15:35:10 -07003085 // only load assets once.
3086 if (!SOUND_EFFECT_FILES.isEmpty()) {
3087 return;
3088 }
3089
Eric Laurente78fced2013-03-15 16:03:47 -07003090 loadTouchSoundAssetDefaults();
3091
3092 try {
3093 parser = mContext.getResources().getXml(com.android.internal.R.xml.audio_assets);
3094
3095 XmlUtils.beginDocument(parser, TAG_AUDIO_ASSETS);
3096 String version = parser.getAttributeValue(null, ATTR_VERSION);
3097 boolean inTouchSoundsGroup = false;
3098
3099 if (ASSET_FILE_VERSION.equals(version)) {
3100 while (true) {
3101 XmlUtils.nextElement(parser);
3102 String element = parser.getName();
3103 if (element == null) {
3104 break;
3105 }
3106 if (element.equals(TAG_GROUP)) {
3107 String name = parser.getAttributeValue(null, ATTR_GROUP_NAME);
3108 if (GROUP_TOUCH_SOUNDS.equals(name)) {
3109 inTouchSoundsGroup = true;
3110 break;
3111 }
3112 }
3113 }
3114 while (inTouchSoundsGroup) {
3115 XmlUtils.nextElement(parser);
3116 String element = parser.getName();
3117 if (element == null) {
3118 break;
3119 }
3120 if (element.equals(TAG_ASSET)) {
3121 String id = parser.getAttributeValue(null, ATTR_ASSET_ID);
3122 String file = parser.getAttributeValue(null, ATTR_ASSET_FILE);
3123 int fx;
3124
3125 try {
3126 Field field = AudioManager.class.getField(id);
3127 fx = field.getInt(null);
3128 } catch (Exception e) {
3129 Log.w(TAG, "Invalid touch sound ID: "+id);
3130 continue;
3131 }
3132
3133 int i = SOUND_EFFECT_FILES.indexOf(file);
3134 if (i == -1) {
3135 i = SOUND_EFFECT_FILES.size();
3136 SOUND_EFFECT_FILES.add(file);
3137 }
3138 SOUND_EFFECT_FILES_MAP[fx][0] = i;
3139 } else {
3140 break;
3141 }
3142 }
3143 }
3144 } catch (Resources.NotFoundException e) {
3145 Log.w(TAG, "audio assets file not found", e);
3146 } catch (XmlPullParserException e) {
3147 Log.w(TAG, "XML parser exception reading touch sound assets", e);
3148 } catch (IOException e) {
3149 Log.w(TAG, "I/O exception reading touch sound assets", e);
3150 } finally {
3151 if (parser != null) {
3152 parser.close();
3153 }
3154 }
3155 }
3156
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003157 /** @see AudioManager#playSoundEffect(int) */
3158 public void playSoundEffect(int effectType) {
Eric Laurent5d3eb44a2013-03-21 15:35:10 -07003159 playSoundEffectVolume(effectType, -1.0f);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003160 }
3161
3162 /** @see AudioManager#playSoundEffect(int, float) */
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003163 public void playSoundEffectVolume(int effectType, float volume) {
Beverlyd6964762018-02-16 14:07:03 -05003164 // do not try to play the sound effect if the system stream is muted
3165 if (isStreamMutedByRingerOrZenMode(STREAM_SYSTEM)) {
3166 return;
3167 }
3168
Natalie Silvanovich559c76d2014-05-01 10:16:24 -07003169 if (effectType >= AudioManager.NUM_SOUND_EFFECTS || effectType < 0) {
3170 Log.w(TAG, "AudioService effectType value " + effectType + " out of range");
3171 return;
3172 }
3173
Eric Laurent5d3eb44a2013-03-21 15:35:10 -07003174 sendMsg(mAudioHandler, MSG_PLAY_SOUND_EFFECT, SENDMSG_QUEUE,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003175 effectType, (int) (volume * 1000), null, 0);
3176 }
3177
3178 /**
3179 * Loads samples into the soundpool.
Glenn Kasten5c17a822011-11-30 09:41:01 -08003180 * This method must be called at first when sound effects are enabled
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003181 */
3182 public boolean loadSoundEffects() {
Eric Laurent5d3eb44a2013-03-21 15:35:10 -07003183 int attempts = 3;
3184 LoadSoundEffectReply reply = new LoadSoundEffectReply();
Eric Laurenta60e2122010-12-28 16:49:07 -08003185
Eric Laurent5d3eb44a2013-03-21 15:35:10 -07003186 synchronized (reply) {
3187 sendMsg(mAudioHandler, MSG_LOAD_SOUND_EFFECTS, SENDMSG_QUEUE, 0, 0, reply, 0);
3188 while ((reply.mStatus == 1) && (attempts-- > 0)) {
Eric Laurent117b7bb2011-01-16 17:07:27 -08003189 try {
Glenn Kasten167d1a22013-07-23 16:24:41 -07003190 reply.wait(SOUND_EFFECTS_LOAD_TIMEOUT_MS);
Eric Laurent5d3eb44a2013-03-21 15:35:10 -07003191 } catch (InterruptedException e) {
3192 Log.w(TAG, "loadSoundEffects Interrupted while waiting sound pool loaded.");
Eric Laurent117b7bb2011-01-16 17:07:27 -08003193 }
Eric Laurenta60e2122010-12-28 16:49:07 -08003194 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003195 }
Eric Laurent5d3eb44a2013-03-21 15:35:10 -07003196 return (reply.mStatus == 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003197 }
3198
3199 /**
3200 * Unloads samples from the sound pool.
3201 * This method can be called to free some memory when
3202 * sound effects are disabled.
3203 */
3204 public void unloadSoundEffects() {
Eric Laurent5d3eb44a2013-03-21 15:35:10 -07003205 sendMsg(mAudioHandler, MSG_UNLOAD_SOUND_EFFECTS, SENDMSG_QUEUE, 0, 0, null, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003206 }
3207
Eric Laurenta60e2122010-12-28 16:49:07 -08003208 class SoundPoolListenerThread extends Thread {
3209 public SoundPoolListenerThread() {
3210 super("SoundPoolListenerThread");
3211 }
3212
3213 @Override
3214 public void run() {
3215
3216 Looper.prepare();
3217 mSoundPoolLooper = Looper.myLooper();
3218
3219 synchronized (mSoundEffectsLock) {
3220 if (mSoundPool != null) {
3221 mSoundPoolCallBack = new SoundPoolCallback();
3222 mSoundPool.setOnLoadCompleteListener(mSoundPoolCallBack);
3223 }
3224 mSoundEffectsLock.notify();
3225 }
3226 Looper.loop();
3227 }
3228 }
3229
3230 private final class SoundPoolCallback implements
3231 android.media.SoundPool.OnLoadCompleteListener {
3232
Eric Laurent5d3eb44a2013-03-21 15:35:10 -07003233 int mStatus = 1; // 1 means neither error nor last sample loaded yet
3234 List<Integer> mSamples = new ArrayList<Integer>();
Eric Laurenta60e2122010-12-28 16:49:07 -08003235
3236 public int status() {
3237 return mStatus;
3238 }
3239
Eric Laurent5d3eb44a2013-03-21 15:35:10 -07003240 public void setSamples(int[] samples) {
3241 for (int i = 0; i < samples.length; i++) {
3242 // do not wait ack for samples rejected upfront by SoundPool
3243 if (samples[i] > 0) {
3244 mSamples.add(samples[i]);
3245 }
3246 }
Eric Laurenta60e2122010-12-28 16:49:07 -08003247 }
3248
3249 public void onLoadComplete(SoundPool soundPool, int sampleId, int status) {
3250 synchronized (mSoundEffectsLock) {
Eric Laurent5d3eb44a2013-03-21 15:35:10 -07003251 int i = mSamples.indexOf(sampleId);
3252 if (i >= 0) {
3253 mSamples.remove(i);
Eric Laurenta60e2122010-12-28 16:49:07 -08003254 }
Eric Laurent5d3eb44a2013-03-21 15:35:10 -07003255 if ((status != 0) || mSamples. isEmpty()) {
3256 mStatus = status;
Eric Laurenta60e2122010-12-28 16:49:07 -08003257 mSoundEffectsLock.notify();
3258 }
3259 }
3260 }
3261 }
3262
Eric Laurent4050c932009-07-08 02:52:14 -07003263 /** @see AudioManager#reloadAudioSettings() */
3264 public void reloadAudioSettings() {
Eric Laurentbc0fab1f2012-09-19 11:24:41 -07003265 readAudioSettings(false /*userSwitch*/);
3266 }
3267
3268 private void readAudioSettings(boolean userSwitch) {
Eric Laurent4050c932009-07-08 02:52:14 -07003269 // restore ringer mode, ringer mode affected streams, mute affected streams and vibrate settings
3270 readPersistedSettings();
Eric Laurentc0232482016-03-15 18:19:23 -07003271 readUserRestrictions();
Eric Laurent4050c932009-07-08 02:52:14 -07003272
3273 // restore volume settings
3274 int numStreamTypes = AudioSystem.getNumStreamTypes();
3275 for (int streamType = 0; streamType < numStreamTypes; streamType++) {
3276 VolumeStreamState streamState = mStreamStates[streamType];
3277
Eric Laurentbc0fab1f2012-09-19 11:24:41 -07003278 if (userSwitch && mStreamVolumeAlias[streamType] == AudioSystem.STREAM_MUSIC) {
3279 continue;
3280 }
3281
Eric Laurent8fa4d6f2014-10-30 14:13:03 -07003282 streamState.readSettings();
3283 synchronized (VolumeStreamState.class) {
Eric Laurent3172d5e2012-05-09 11:38:16 -07003284 // unmute stream that was muted but is not affect by mute anymore
RoboErik4197cb62015-01-21 15:45:32 -08003285 if (streamState.mIsMuted && ((!isStreamAffectedByMute(streamType) &&
Beverlyd6964762018-02-16 14:07:03 -05003286 !isStreamMutedByRingerOrZenMode(streamType)) || mUseFixedVolume)) {
RoboErik4197cb62015-01-21 15:45:32 -08003287 streamState.mIsMuted = false;
Eric Laurent4050c932009-07-08 02:52:14 -07003288 }
Eric Laurent4050c932009-07-08 02:52:14 -07003289 }
3290 }
3291
Eric Laurent33902db2012-10-07 16:15:07 -07003292 // apply new ringer mode before checking volume for alias streams so that streams
3293 // muted by ringer mode have the correct volume
John Spurlock661f2cf2014-11-17 10:29:10 -05003294 setRingerModeInt(getRingerModeInternal(), false);
Eric Laurent33902db2012-10-07 16:15:07 -07003295
Eric Laurent212532b2014-07-21 15:43:18 -07003296 checkAllFixedVolumeDevices();
Eric Laurent24482012012-05-10 09:41:17 -07003297 checkAllAliasStreamVolumes();
John Spurlockb6e19e32015-03-10 21:33:44 -04003298 checkMuteAffectedStreams();
Eric Laurent24482012012-05-10 09:41:17 -07003299
hyomin.ohd0446dc2018-10-18 13:58:27 +09003300 synchronized (mSafeMediaVolumeStateLock) {
John Spurlockaa5ee4d2014-07-25 13:05:12 -04003301 mMusicActiveMs = MathUtils.constrain(Settings.Secure.getIntForUser(mContentResolver,
3302 Settings.Secure.UNSAFE_VOLUME_MUSIC_ACTIVE_MS, 0, UserHandle.USER_CURRENT),
3303 0, UNSAFE_VOLUME_MUSIC_ACTIVE_MS_MAX);
Eric Laurentd640bd32012-09-28 18:01:48 -07003304 if (mSafeMediaVolumeState == SAFE_MEDIA_VOLUME_ACTIVE) {
John Spurlock90874332015-03-10 16:00:54 -04003305 enforceSafeMediaVolume(TAG);
Eric Laurentf1a457d2012-09-20 16:27:23 -07003306 }
Eric Laurentc34dcc12012-09-10 13:51:52 -07003307 }
Eric Laurent4050c932009-07-08 02:52:14 -07003308 }
3309
Dianne Hackborn961cae92013-03-20 14:59:43 -07003310 /** @see AudioManager#setSpeakerphoneOn(boolean) */
Eric Laurentc42ac9d2009-07-29 08:53:03 -07003311 public void setSpeakerphoneOn(boolean on){
Eric Laurentdc1d17a2009-09-10 00:48:21 -07003312 if (!checkAudioSettingsPermission("setSpeakerphoneOn()")) {
3313 return;
3314 }
JW Kwon6e144772018-10-04 17:39:29 +09003315
3316 if (mContext.checkCallingOrSelfPermission(
3317 android.Manifest.permission.MODIFY_PHONE_STATE)
3318 != PackageManager.PERMISSION_GRANTED) {
3319 synchronized (mSetModeDeathHandlers) {
3320 for (SetModeDeathHandler h : mSetModeDeathHandlers) {
3321 if (h.getMode() == AudioSystem.MODE_IN_CALL) {
3322 Log.w(TAG, "getMode is call, Permission Denial: setSpeakerphoneOn from pid="
3323 + Binder.getCallingPid() + ", uid=" + Binder.getCallingUid());
3324 return;
3325 }
3326 }
3327 }
3328 }
3329
Jean-Michel Trivi011f39e2017-08-19 18:08:06 -07003330 // for logging only
3331 final String eventSource = new StringBuilder("setSpeakerphoneOn(").append(on)
3332 .append(") from u/pid:").append(Binder.getCallingUid()).append("/")
3333 .append(Binder.getCallingPid()).toString();
Jean-Michel Trivi58850372018-09-14 16:01:28 -07003334 mDeviceBroker.setSpeakerphoneOn(on, eventSource);
Eric Laurentc42ac9d2009-07-29 08:53:03 -07003335 }
3336
3337 /** @see AudioManager#isSpeakerphoneOn() */
3338 public boolean isSpeakerphoneOn() {
Jean-Michel Trivi58850372018-09-14 16:01:28 -07003339 return mDeviceBroker.isSpeakerphoneOn();
Eric Laurentc42ac9d2009-07-29 08:53:03 -07003340 }
3341
Dianne Hackborn961cae92013-03-20 14:59:43 -07003342 /** @see AudioManager#setBluetoothScoOn(boolean) */
Eric Laurent48221252015-09-24 18:41:48 -07003343 public void setBluetoothScoOn(boolean on) {
Eric Laurentdc1d17a2009-09-10 00:48:21 -07003344 if (!checkAudioSettingsPermission("setBluetoothScoOn()")) {
3345 return;
3346 }
Sharad Sangle1d188442017-05-09 16:05:40 +05303347
3348 // Only enable calls from system components
Vitor Albuquerquec3bb48c2018-03-07 10:39:59 -03003349 if (UserHandle.getCallingAppId() >= FIRST_APPLICATION_UID) {
Jean-Michel Trivi58850372018-09-14 16:01:28 -07003350 mDeviceBroker.setBluetoothScoOnByApp(on);
Sharad Sangle1d188442017-05-09 16:05:40 +05303351 return;
3352 }
3353
Jean-Michel Trivi011f39e2017-08-19 18:08:06 -07003354 // for logging only
3355 final String eventSource = new StringBuilder("setBluetoothScoOn(").append(on)
3356 .append(") from u/pid:").append(Binder.getCallingUid()).append("/")
3357 .append(Binder.getCallingPid()).toString();
Jean-Michel Trivi58850372018-09-14 16:01:28 -07003358
3359 mDeviceBroker.setBluetoothScoOn(on, eventSource);
Eric Laurent48221252015-09-24 18:41:48 -07003360 }
Johan Gustavsson7337bee2013-03-01 15:53:30 +01003361
Jean-Michel Trivi58850372018-09-14 16:01:28 -07003362 /** @see AudioManager#isBluetoothScoOn()
3363 * Note that it doesn't report internal state, but state seen by apps (which may have
3364 * called setBluetoothScoOn() */
Eric Laurentc42ac9d2009-07-29 08:53:03 -07003365 public boolean isBluetoothScoOn() {
Jean-Michel Trivi58850372018-09-14 16:01:28 -07003366 return mDeviceBroker.isBluetoothScoOnForApp();
Eric Laurentc42ac9d2009-07-29 08:53:03 -07003367 }
3368
Jean-Michel Trivi58850372018-09-14 16:01:28 -07003369 // TODO investigate internal users due to deprecation of SDK API
Sungsoocf09fe62016-09-28 16:21:48 +09003370 /** @see AudioManager#setBluetoothA2dpOn(boolean) */
Eric Laurent78472112012-05-21 08:57:21 -07003371 public void setBluetoothA2dpOn(boolean on) {
Jean-Michel Trivi011f39e2017-08-19 18:08:06 -07003372 // for logging only
3373 final String eventSource = new StringBuilder("setBluetoothA2dpOn(").append(on)
3374 .append(") from u/pid:").append(Binder.getCallingUid()).append("/")
3375 .append(Binder.getCallingPid()).toString();
Jean-Michel Trivi58850372018-09-14 16:01:28 -07003376 mDeviceBroker.setBluetoothA2dpOn_Async(on, eventSource);
Eric Laurent78472112012-05-21 08:57:21 -07003377 }
3378
Sungsoocf09fe62016-09-28 16:21:48 +09003379 /** @see AudioManager#isBluetoothA2dpOn() */
Eric Laurent78472112012-05-21 08:57:21 -07003380 public boolean isBluetoothA2dpOn() {
Jean-Michel Trivi58850372018-09-14 16:01:28 -07003381 return mDeviceBroker.isBluetoothA2dpOn();
Eric Laurent78472112012-05-21 08:57:21 -07003382 }
3383
Eric Laurent3def1ee2010-03-17 23:26:26 -07003384 /** @see AudioManager#startBluetoothSco() */
Eric Laurent83900752014-05-15 15:14:22 -07003385 public void startBluetoothSco(IBinder cb, int targetSdkVersion) {
Jean-Michel Trivi58850372018-09-14 16:01:28 -07003386 final int scoAudioMode =
Eric Laurent83900752014-05-15 15:14:22 -07003387 (targetSdkVersion < Build.VERSION_CODES.JELLY_BEAN_MR2) ?
Jean-Michel Trivi58850372018-09-14 16:01:28 -07003388 BtHelper.SCO_MODE_VIRTUAL_CALL : BtHelper.SCO_MODE_UNDEFINED;
3389 final String eventSource = new StringBuilder("startBluetoothSco()")
3390 .append(") from u/pid:").append(Binder.getCallingUid()).append("/")
3391 .append(Binder.getCallingPid()).toString();
3392 startBluetoothScoInt(cb, scoAudioMode, eventSource);
Eric Laurent83900752014-05-15 15:14:22 -07003393 }
3394
3395 /** @see AudioManager#startBluetoothScoVirtualCall() */
3396 public void startBluetoothScoVirtualCall(IBinder cb) {
Jean-Michel Trivi58850372018-09-14 16:01:28 -07003397 final String eventSource = new StringBuilder("startBluetoothScoVirtualCall()")
3398 .append(") from u/pid:").append(Binder.getCallingUid()).append("/")
3399 .append(Binder.getCallingPid()).toString();
3400 startBluetoothScoInt(cb, BtHelper.SCO_MODE_VIRTUAL_CALL, eventSource);
Eric Laurent83900752014-05-15 15:14:22 -07003401 }
3402
Jean-Michel Trivi58850372018-09-14 16:01:28 -07003403 void startBluetoothScoInt(IBinder cb, int scoAudioMode, @NonNull String eventSource) {
Eric Laurentdc03c612011-04-01 10:59:41 -07003404 if (!checkAudioSettingsPermission("startBluetoothSco()") ||
Eric Laurent4a5eeb92014-05-06 10:49:04 -07003405 !mSystemReady) {
Eric Laurent3def1ee2010-03-17 23:26:26 -07003406 return;
3407 }
Jean-Michel Trivi58850372018-09-14 16:01:28 -07003408 mDeviceBroker.startBluetoothScoForClient_Sync(cb, scoAudioMode, eventSource);
Eric Laurent3def1ee2010-03-17 23:26:26 -07003409 }
3410
3411 /** @see AudioManager#stopBluetoothSco() */
3412 public void stopBluetoothSco(IBinder cb){
Eric Laurentdc03c612011-04-01 10:59:41 -07003413 if (!checkAudioSettingsPermission("stopBluetoothSco()") ||
Eric Laurent4a5eeb92014-05-06 10:49:04 -07003414 !mSystemReady) {
Eric Laurent3def1ee2010-03-17 23:26:26 -07003415 return;
3416 }
Jean-Michel Trivi58850372018-09-14 16:01:28 -07003417 final String eventSource = new StringBuilder("stopBluetoothSco()")
3418 .append(") from u/pid:").append(Binder.getCallingUid()).append("/")
3419 .append(Binder.getCallingPid()).toString();
3420 mDeviceBroker.stopBluetoothScoForClient_Sync(cb, eventSource);
Eric Laurent3def1ee2010-03-17 23:26:26 -07003421 }
3422
Eric Laurent78472112012-05-21 08:57:21 -07003423
Jean-Michel Trivi58850372018-09-14 16:01:28 -07003424 /*package*/ ContentResolver getContentResolver() {
3425 return mContentResolver;
Jakub Pawlowskif9570f32018-02-21 17:15:12 -08003426 }
3427
John Spurlock90874332015-03-10 16:00:54 -04003428 private void onCheckMusicActive(String caller) {
hyomin.ohd0446dc2018-10-18 13:58:27 +09003429 synchronized (mSafeMediaVolumeStateLock) {
Eric Laurentd640bd32012-09-28 18:01:48 -07003430 if (mSafeMediaVolumeState == SAFE_MEDIA_VOLUME_INACTIVE) {
Eric Laurentc34dcc12012-09-10 13:51:52 -07003431 int device = getDeviceForStream(AudioSystem.STREAM_MUSIC);
3432
3433 if ((device & mSafeMediaVolumeDevices) != 0) {
3434 sendMsg(mAudioHandler,
3435 MSG_CHECK_MUSIC_ACTIVE,
3436 SENDMSG_REPLACE,
Eric Laurentf1a457d2012-09-20 16:27:23 -07003437 0,
Eric Laurentc34dcc12012-09-10 13:51:52 -07003438 0,
John Spurlock90874332015-03-10 16:00:54 -04003439 caller,
Eric Laurentc34dcc12012-09-10 13:51:52 -07003440 MUSIC_ACTIVE_POLL_PERIOD_MS);
Eric Laurent42b041e2013-03-29 11:36:03 -07003441 int index = mStreamStates[AudioSystem.STREAM_MUSIC].getIndex(device);
Jean-Michel Trivi58850372018-09-14 16:01:28 -07003442 if (AudioSystem.isStreamActive(AudioSystem.STREAM_MUSIC, 0)
3443 && (index > safeMediaVolumeIndex(device))) {
Eric Laurentc34dcc12012-09-10 13:51:52 -07003444 // Approximate cumulative active music time
3445 mMusicActiveMs += MUSIC_ACTIVE_POLL_PERIOD_MS;
3446 if (mMusicActiveMs > UNSAFE_VOLUME_MUSIC_ACTIVE_MS_MAX) {
John Spurlock90874332015-03-10 16:00:54 -04003447 setSafeMediaVolumeEnabled(true, caller);
Eric Laurentc34dcc12012-09-10 13:51:52 -07003448 mMusicActiveMs = 0;
Eric Laurentc34dcc12012-09-10 13:51:52 -07003449 }
John Spurlockaa5ee4d2014-07-25 13:05:12 -04003450 saveMusicActiveMs();
Eric Laurentc34dcc12012-09-10 13:51:52 -07003451 }
3452 }
3453 }
3454 }
3455 }
3456
John Spurlockaa5ee4d2014-07-25 13:05:12 -04003457 private void saveMusicActiveMs() {
3458 mAudioHandler.obtainMessage(MSG_PERSIST_MUSIC_ACTIVE_MS, mMusicActiveMs, 0).sendToTarget();
3459 }
3460
Jean-Michel Trivi58850372018-09-14 16:01:28 -07003461 private int getSafeUsbMediaVolumeIndex() {
Eric Laurenteab40d12017-06-09 12:45:21 -07003462 // determine UI volume index corresponding to the wanted safe gain in dBFS
3463 int min = MIN_STREAM_VOLUME[AudioSystem.STREAM_MUSIC];
3464 int max = MAX_STREAM_VOLUME[AudioSystem.STREAM_MUSIC];
3465
John Muir8b8bddd2018-02-16 14:29:14 -08003466 mSafeUsbMediaVolumeDbfs = mContext.getResources().getInteger(
3467 com.android.internal.R.integer.config_safe_media_volume_usb_mB) / 100.0f;
3468
Jean-Michel Trivi58850372018-09-14 16:01:28 -07003469 while (Math.abs(max - min) > 1) {
Eric Laurenteab40d12017-06-09 12:45:21 -07003470 int index = (max + min) / 2;
3471 float gainDB = AudioSystem.getStreamVolumeDB(
3472 AudioSystem.STREAM_MUSIC, index, AudioSystem.DEVICE_OUT_USB_HEADSET);
Eric Laurentb378a13a2017-07-11 14:08:11 -07003473 if (Float.isNaN(gainDB)) {
Eric Laurenteab40d12017-06-09 12:45:21 -07003474 //keep last min in case of read error
3475 break;
John Muir8b8bddd2018-02-16 14:29:14 -08003476 } else if (gainDB == mSafeUsbMediaVolumeDbfs) {
Eric Laurenteab40d12017-06-09 12:45:21 -07003477 min = index;
3478 break;
John Muir8b8bddd2018-02-16 14:29:14 -08003479 } else if (gainDB < mSafeUsbMediaVolumeDbfs) {
Eric Laurenteab40d12017-06-09 12:45:21 -07003480 min = index;
3481 } else {
3482 max = index;
3483 }
3484 }
3485 return min * 10;
3486 }
3487
John Spurlock90874332015-03-10 16:00:54 -04003488 private void onConfigureSafeVolume(boolean force, String caller) {
hyomin.ohd0446dc2018-10-18 13:58:27 +09003489 synchronized (mSafeMediaVolumeStateLock) {
Eric Laurentd640bd32012-09-28 18:01:48 -07003490 int mcc = mContext.getResources().getConfiguration().mcc;
3491 if ((mMcc != mcc) || ((mMcc == 0) && force)) {
3492 mSafeMediaVolumeIndex = mContext.getResources().getInteger(
3493 com.android.internal.R.integer.config_safe_media_volume_index) * 10;
Eric Laurenteab40d12017-06-09 12:45:21 -07003494
3495 mSafeUsbMediaVolumeIndex = getSafeUsbMediaVolumeIndex();
3496
John Spurlock35134602014-07-24 18:10:48 -04003497 boolean safeMediaVolumeEnabled =
3498 SystemProperties.getBoolean("audio.safemedia.force", false)
3499 || mContext.getResources().getBoolean(
3500 com.android.internal.R.bool.config_safe_media_volume_enabled);
Eric Laurent05274f32012-11-29 12:48:18 -08003501
Ricardo Garcia3a30a762015-06-23 15:54:45 -07003502 boolean safeMediaVolumeBypass =
3503 SystemProperties.getBoolean("audio.safemedia.bypass", false);
3504
Eric Laurent05274f32012-11-29 12:48:18 -08003505 // The persisted state is either "disabled" or "active": this is the state applied
3506 // next time we boot and cannot be "inactive"
3507 int persistedState;
Ricardo Garcia3a30a762015-06-23 15:54:45 -07003508 if (safeMediaVolumeEnabled && !safeMediaVolumeBypass) {
Eric Laurent05274f32012-11-29 12:48:18 -08003509 persistedState = SAFE_MEDIA_VOLUME_ACTIVE;
3510 // The state can already be "inactive" here if the user has forced it before
3511 // the 30 seconds timeout for forced configuration. In this case we don't reset
3512 // it to "active".
3513 if (mSafeMediaVolumeState != SAFE_MEDIA_VOLUME_INACTIVE) {
John Spurlockaa5ee4d2014-07-25 13:05:12 -04003514 if (mMusicActiveMs == 0) {
3515 mSafeMediaVolumeState = SAFE_MEDIA_VOLUME_ACTIVE;
John Spurlock90874332015-03-10 16:00:54 -04003516 enforceSafeMediaVolume(caller);
John Spurlockaa5ee4d2014-07-25 13:05:12 -04003517 } else {
3518 // We have existing playback time recorded, already confirmed.
3519 mSafeMediaVolumeState = SAFE_MEDIA_VOLUME_INACTIVE;
3520 }
Eric Laurent05274f32012-11-29 12:48:18 -08003521 }
Eric Laurentd640bd32012-09-28 18:01:48 -07003522 } else {
Eric Laurent05274f32012-11-29 12:48:18 -08003523 persistedState = SAFE_MEDIA_VOLUME_DISABLED;
Eric Laurentd640bd32012-09-28 18:01:48 -07003524 mSafeMediaVolumeState = SAFE_MEDIA_VOLUME_DISABLED;
3525 }
3526 mMcc = mcc;
Eric Laurent05274f32012-11-29 12:48:18 -08003527 sendMsg(mAudioHandler,
3528 MSG_PERSIST_SAFE_VOLUME_STATE,
3529 SENDMSG_QUEUE,
3530 persistedState,
3531 0,
3532 null,
3533 0);
Eric Laurentd640bd32012-09-28 18:01:48 -07003534 }
3535 }
3536 }
3537
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003538 ///////////////////////////////////////////////////////////////////////////
3539 // Internal methods
3540 ///////////////////////////////////////////////////////////////////////////
3541
3542 /**
3543 * Checks if the adjustment should change ringer mode instead of just
3544 * adjusting volume. If so, this will set the proper ringer mode and volume
3545 * indices on the stream states.
3546 */
Julia Reynoldsed783792016-04-08 15:27:35 -04003547 private int checkForRingerModeChange(int oldIndex, int direction, int step, boolean isMuted,
3548 String caller, int flags) {
John Spurlocka11b4af2014-06-01 11:52:23 -04003549 int result = FLAG_ADJUST_VOLUME;
Zak Cohen47798292017-11-30 12:34:20 -08003550 if (isPlatformTelevision() || mIsSingleVolume) {
Hank Freund21003f62015-12-08 09:05:46 -08003551 return result;
3552 }
3553
John Spurlock661f2cf2014-11-17 10:29:10 -05003554 int ringerMode = getRingerModeInternal();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003555
Eric Laurentbffc3d12012-05-07 17:43:49 -07003556 switch (ringerMode) {
3557 case RINGER_MODE_NORMAL:
3558 if (direction == AudioManager.ADJUST_LOWER) {
3559 if (mHasVibrator) {
Eric Laurent24482012012-05-10 09:41:17 -07003560 // "step" is the delta in internal index units corresponding to a
3561 // change of 1 in UI index units.
3562 // Because of rounding when rescaling from one stream index range to its alias
3563 // index range, we cannot simply test oldIndex == step:
3564 // (step <= oldIndex < 2 * step) is equivalent to: (old UI index == 1)
3565 if (step <= oldIndex && oldIndex < 2 * step) {
Eric Laurentbffc3d12012-05-07 17:43:49 -07003566 ringerMode = RINGER_MODE_VIBRATE;
John Spurlock07e72432015-03-13 11:46:52 -04003567 mLoweredFromNormalToVibrateTime = SystemClock.uptimeMillis();
Eric Laurentbffc3d12012-05-07 17:43:49 -07003568 }
3569 } else {
John Spurlockd9c75db2015-04-28 11:19:13 -04003570 if (oldIndex == step && mVolumePolicy.volumeDownToEnterSilent) {
Eric Laurentbffc3d12012-05-07 17:43:49 -07003571 ringerMode = RINGER_MODE_SILENT;
3572 }
Eric Laurent3d4c06f2011-08-15 19:58:28 -07003573 }
Muyuan Li1ed6df62016-06-18 11:16:52 -07003574 } else if (mIsSingleVolume && (direction == AudioManager.ADJUST_TOGGLE_MUTE
John Spurlocka48d7792015-03-03 17:35:57 -05003575 || direction == AudioManager.ADJUST_MUTE)) {
RoboErik5452e252015-02-06 15:33:53 -08003576 if (mHasVibrator) {
3577 ringerMode = RINGER_MODE_VIBRATE;
3578 } else {
3579 ringerMode = RINGER_MODE_SILENT;
3580 }
3581 // Setting the ringer mode will toggle mute
3582 result &= ~FLAG_ADJUST_VOLUME;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003583 }
Eric Laurentbffc3d12012-05-07 17:43:49 -07003584 break;
3585 case RINGER_MODE_VIBRATE:
3586 if (!mHasVibrator) {
3587 Log.e(TAG, "checkForRingerModeChange() current ringer mode is vibrate" +
3588 "but no vibrator is present");
3589 break;
3590 }
Amith Yamasanic696a532011-10-28 17:02:37 -07003591 if ((direction == AudioManager.ADJUST_LOWER)) {
RoboErik5452e252015-02-06 15:33:53 -08003592 // This is the case we were muted with the volume turned up
Muyuan Li1ed6df62016-06-18 11:16:52 -07003593 if (mIsSingleVolume && oldIndex >= 2 * step && isMuted) {
RoboErik5452e252015-02-06 15:33:53 -08003594 ringerMode = RINGER_MODE_NORMAL;
3595 } else if (mPrevVolDirection != AudioManager.ADJUST_LOWER) {
John Spurlocka48d7792015-03-03 17:35:57 -05003596 if (mVolumePolicy.volumeDownToEnterSilent) {
John Spurlock07e72432015-03-13 11:46:52 -04003597 final long diff = SystemClock.uptimeMillis()
3598 - mLoweredFromNormalToVibrateTime;
John Spurlockd9c75db2015-04-28 11:19:13 -04003599 if (diff > mVolumePolicy.vibrateToSilentDebounce
3600 && mRingerModeDelegate.canVolumeDownEnterSilent()) {
John Spurlock07e72432015-03-13 11:46:52 -04003601 ringerMode = RINGER_MODE_SILENT;
3602 }
John Spurlock795a5142014-12-08 14:09:35 -05003603 } else {
3604 result |= AudioManager.FLAG_SHOW_VIBRATE_HINT;
3605 }
Amith Yamasanic696a532011-10-28 17:02:37 -07003606 }
RoboErik5452e252015-02-06 15:33:53 -08003607 } else if (direction == AudioManager.ADJUST_RAISE
3608 || direction == AudioManager.ADJUST_TOGGLE_MUTE
3609 || direction == AudioManager.ADJUST_UNMUTE) {
Eric Laurentbffc3d12012-05-07 17:43:49 -07003610 ringerMode = RINGER_MODE_NORMAL;
Amith Yamasanic696a532011-10-28 17:02:37 -07003611 }
John Spurlocka11b4af2014-06-01 11:52:23 -04003612 result &= ~FLAG_ADJUST_VOLUME;
Eric Laurentbffc3d12012-05-07 17:43:49 -07003613 break;
3614 case RINGER_MODE_SILENT:
Muyuan Li1ed6df62016-06-18 11:16:52 -07003615 if (mIsSingleVolume && direction == AudioManager.ADJUST_LOWER && oldIndex >= 2 * step && isMuted) {
RoboErik5452e252015-02-06 15:33:53 -08003616 // This is the case we were muted with the volume turned up
3617 ringerMode = RINGER_MODE_NORMAL;
3618 } else if (direction == AudioManager.ADJUST_RAISE
3619 || direction == AudioManager.ADJUST_TOGGLE_MUTE
3620 || direction == AudioManager.ADJUST_UNMUTE) {
John Spurlocka48d7792015-03-03 17:35:57 -05003621 if (!mVolumePolicy.volumeUpToExitSilent) {
John Spurlocka11b4af2014-06-01 11:52:23 -04003622 result |= AudioManager.FLAG_SHOW_SILENT_HINT;
Eric Laurentbffc3d12012-05-07 17:43:49 -07003623 } else {
RoboErik5452e252015-02-06 15:33:53 -08003624 if (mHasVibrator && direction == AudioManager.ADJUST_RAISE) {
John Spurlocka11b4af2014-06-01 11:52:23 -04003625 ringerMode = RINGER_MODE_VIBRATE;
3626 } else {
RoboErik5452e252015-02-06 15:33:53 -08003627 // If we don't have a vibrator or they were toggling mute
3628 // go straight back to normal.
John Spurlocka11b4af2014-06-01 11:52:23 -04003629 ringerMode = RINGER_MODE_NORMAL;
3630 }
Eric Laurentbffc3d12012-05-07 17:43:49 -07003631 }
Daniel Sandler6329bf72010-02-26 15:17:44 -05003632 }
John Spurlocka11b4af2014-06-01 11:52:23 -04003633 result &= ~FLAG_ADJUST_VOLUME;
Eric Laurentbffc3d12012-05-07 17:43:49 -07003634 break;
3635 default:
3636 Log.e(TAG, "checkForRingerModeChange() wrong ringer mode: "+ringerMode);
3637 break;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003638 }
3639
Julia Reynoldsed783792016-04-08 15:27:35 -04003640 if (isAndroidNPlus(caller) && wouldToggleZenMode(ringerMode)
3641 && !mNm.isNotificationPolicyAccessGrantedForPackage(caller)
3642 && (flags & AudioManager.FLAG_FROM_KEY) == 0) {
3643 throw new SecurityException("Not allowed to change Do Not Disturb state");
3644 }
3645
John Spurlock661f2cf2014-11-17 10:29:10 -05003646 setRingerMode(ringerMode, TAG + ".checkForRingerModeChange", false /*external*/);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003647
Eric Laurent25101b02011-02-02 09:33:30 -08003648 mPrevVolDirection = direction;
3649
John Spurlocka11b4af2014-06-01 11:52:23 -04003650 return result;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003651 }
3652
John Spurlock3346a802014-05-20 16:25:37 -04003653 @Override
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003654 public boolean isStreamAffectedByRingerMode(int streamType) {
Eric Laurent9bcf4012009-06-12 06:09:28 -07003655 return (mRingerModeAffectedStreams & (1 << streamType)) != 0;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003656 }
3657
Beverlyd6964762018-02-16 14:07:03 -05003658 private boolean shouldZenMuteStream(int streamType) {
3659 if (mNm.getZenMode() != Settings.Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS) {
3660 return false;
3661 }
3662
Beverlyff2df9b2018-10-10 16:54:10 -04003663 NotificationManager.Policy zenPolicy = mNm.getConsolidatedNotificationPolicy();
Beverlyd6964762018-02-16 14:07:03 -05003664 final boolean muteAlarms = (zenPolicy.priorityCategories
3665 & NotificationManager.Policy.PRIORITY_CATEGORY_ALARMS) == 0;
3666 final boolean muteMedia = (zenPolicy.priorityCategories
3667 & NotificationManager.Policy.PRIORITY_CATEGORY_MEDIA) == 0;
3668 final boolean muteSystem = (zenPolicy.priorityCategories
3669 & NotificationManager.Policy.PRIORITY_CATEGORY_SYSTEM) == 0;
3670 final boolean muteNotificationAndRing = ZenModeConfig
Beverlyff2df9b2018-10-10 16:54:10 -04003671 .areAllPriorityOnlyNotificationZenSoundsMuted(
3672 mNm.getConsolidatedNotificationPolicy());
Beverlyd6964762018-02-16 14:07:03 -05003673 return muteAlarms && isAlarm(streamType)
3674 || muteMedia && isMedia(streamType)
3675 || muteSystem && isSystem(streamType)
3676 || muteNotificationAndRing && isNotificationOrRinger(streamType);
3677 }
3678
3679 private boolean isStreamMutedByRingerOrZenMode(int streamType) {
3680 return (mRingerAndZenModeMutedStreams & (1 << streamType)) != 0;
3681 }
3682
3683 /**
3684 * DND total silence: media and alarms streams are tied to the muted ringer
3685 * {@link ZenModeHelper.RingerModeDelegate#getRingerModeAffectedStreams(int)}
3686 * DND alarms only: notification, ringer + system muted (by default tied to muted ringer mode)
3687 * DND priority only: alarms, media, system streams can be muted separate from ringer based on
3688 * zenPolicy (this method determines which streams)
3689 * @return true if changed, else false
3690 */
3691 private boolean updateZenModeAffectedStreams() {
3692 int zenModeAffectedStreams = 0;
3693 if (mSystemReady && mNm.getZenMode() == Settings.Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS) {
Beverlyff2df9b2018-10-10 16:54:10 -04003694 NotificationManager.Policy zenPolicy = mNm.getConsolidatedNotificationPolicy();
Beverlyd6964762018-02-16 14:07:03 -05003695 if ((zenPolicy.priorityCategories
3696 & NotificationManager.Policy.PRIORITY_CATEGORY_ALARMS) == 0) {
3697 zenModeAffectedStreams |= 1 << AudioManager.STREAM_ALARM;
3698 }
3699
3700 if ((zenPolicy.priorityCategories
3701 & NotificationManager.Policy.PRIORITY_CATEGORY_MEDIA) == 0) {
3702 zenModeAffectedStreams |= 1 << AudioManager.STREAM_MUSIC;
3703 }
3704
3705 if ((zenPolicy.priorityCategories
3706 & NotificationManager.Policy.PRIORITY_CATEGORY_SYSTEM) == 0) {
3707 zenModeAffectedStreams |= 1 << AudioManager.STREAM_SYSTEM;
3708 }
3709 }
3710
3711 if (mZenModeAffectedStreams != zenModeAffectedStreams) {
3712 mZenModeAffectedStreams = zenModeAffectedStreams;
3713 return true;
3714 }
3715
3716 return false;
Eric Laurent5b4e6542010-03-19 20:02:21 -07003717 }
3718
Jean-Michel Trivi8719a1d2017-11-06 11:52:51 -08003719 @GuardedBy("mSettingsLock")
Beverlyd6964762018-02-16 14:07:03 -05003720 private boolean updateRingerAndZenModeAffectedStreams() {
3721 boolean updatedZenModeAffectedStreams = updateZenModeAffectedStreams();
John Spurlock50ced3f2015-05-11 16:00:09 -04003722 int ringerModeAffectedStreams = Settings.System.getIntForUser(mContentResolver,
Eric Laurent24e0d9b2013-10-03 18:15:07 -07003723 Settings.System.MODE_RINGER_STREAMS_AFFECTED,
3724 ((1 << AudioSystem.STREAM_RING)|(1 << AudioSystem.STREAM_NOTIFICATION)|
3725 (1 << AudioSystem.STREAM_SYSTEM)|(1 << AudioSystem.STREAM_SYSTEM_ENFORCED)),
3726 UserHandle.USER_CURRENT);
3727
Muyuan Li1ed6df62016-06-18 11:16:52 -07003728 if (mIsSingleVolume) {
John Spurlock50ced3f2015-05-11 16:00:09 -04003729 ringerModeAffectedStreams = 0;
3730 } else if (mRingerModeDelegate != null) {
3731 ringerModeAffectedStreams = mRingerModeDelegate
3732 .getRingerModeAffectedStreams(ringerModeAffectedStreams);
Eric Laurent24e0d9b2013-10-03 18:15:07 -07003733 }
Jean-Michel Trivi8719a1d2017-11-06 11:52:51 -08003734 if (mCameraSoundForced) {
3735 ringerModeAffectedStreams &= ~(1 << AudioSystem.STREAM_SYSTEM_ENFORCED);
3736 } else {
3737 ringerModeAffectedStreams |= (1 << AudioSystem.STREAM_SYSTEM_ENFORCED);
Eric Laurent24e0d9b2013-10-03 18:15:07 -07003738 }
3739 if (mStreamVolumeAlias[AudioSystem.STREAM_DTMF] == AudioSystem.STREAM_RING) {
3740 ringerModeAffectedStreams |= (1 << AudioSystem.STREAM_DTMF);
3741 } else {
3742 ringerModeAffectedStreams &= ~(1 << AudioSystem.STREAM_DTMF);
3743 }
3744
3745 if (ringerModeAffectedStreams != mRingerModeAffectedStreams) {
3746 Settings.System.putIntForUser(mContentResolver,
3747 Settings.System.MODE_RINGER_STREAMS_AFFECTED,
3748 ringerModeAffectedStreams,
3749 UserHandle.USER_CURRENT);
3750 mRingerModeAffectedStreams = ringerModeAffectedStreams;
3751 return true;
3752 }
Beverlyd6964762018-02-16 14:07:03 -05003753 return updatedZenModeAffectedStreams;
Eric Laurent24e0d9b2013-10-03 18:15:07 -07003754 }
3755
John Spurlocka9dfbe8b2015-02-17 11:01:51 -05003756 @Override
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003757 public boolean isStreamAffectedByMute(int streamType) {
3758 return (mMuteAffectedStreams & (1 << streamType)) != 0;
3759 }
3760
3761 private void ensureValidDirection(int direction) {
RoboErik4197cb62015-01-21 15:45:32 -08003762 switch (direction) {
3763 case AudioManager.ADJUST_LOWER:
3764 case AudioManager.ADJUST_RAISE:
3765 case AudioManager.ADJUST_SAME:
3766 case AudioManager.ADJUST_MUTE:
3767 case AudioManager.ADJUST_UNMUTE:
3768 case AudioManager.ADJUST_TOGGLE_MUTE:
3769 break;
3770 default:
3771 throw new IllegalArgumentException("Bad direction " + direction);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003772 }
3773 }
3774
3775 private void ensureValidStreamType(int streamType) {
3776 if (streamType < 0 || streamType >= mStreamStates.length) {
3777 throw new IllegalArgumentException("Bad stream type " + streamType);
3778 }
3779 }
3780
RoboErik4197cb62015-01-21 15:45:32 -08003781 private boolean isMuteAdjust(int adjust) {
3782 return adjust == AudioManager.ADJUST_MUTE || adjust == AudioManager.ADJUST_UNMUTE
3783 || adjust == AudioManager.ADJUST_TOGGLE_MUTE;
3784 }
3785
Jean-Michel Trivi58850372018-09-14 16:01:28 -07003786 /*package*/ boolean isInCommunication() {
Nancy Chen0eb1e402014-08-21 22:52:29 -07003787 boolean IsInCall = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003788
Tyler Gunnef9f6f92014-09-12 22:16:17 -07003789 TelecomManager telecomManager =
3790 (TelecomManager) mContext.getSystemService(Context.TELECOM_SERVICE);
Eric Laurent38edfda2014-12-18 17:38:04 -08003791
3792 final long ident = Binder.clearCallingIdentity();
Tyler Gunnef9f6f92014-09-12 22:16:17 -07003793 IsInCall = telecomManager.isInCall();
Eric Laurent38edfda2014-12-18 17:38:04 -08003794 Binder.restoreCallingIdentity(ident);
Santos Cordon9eb45932014-06-27 12:28:43 -07003795
Eric Laurentda1af762017-12-15 16:54:35 -08003796 return (IsInCall || getMode() == AudioManager.MODE_IN_COMMUNICATION ||
3797 getMode() == AudioManager.MODE_IN_CALL);
Eric Laurent6d517662012-04-23 18:42:39 -07003798 }
Eric Laurent25101b02011-02-02 09:33:30 -08003799
Jean-Michel Trivifca1e602013-10-10 18:12:59 -07003800 /**
3801 * For code clarity for getActiveStreamType(int)
Julia Reynoldsd9e96e22017-11-07 10:33:08 -05003802 * @param delay_ms max time since last stream activity to consider
3803 * @return true if stream is active in streams handled by AudioFlinger now or
Jean-Michel Trivifca1e602013-10-10 18:12:59 -07003804 * in the last "delay_ms" ms.
3805 */
Julia Reynoldsd9e96e22017-11-07 10:33:08 -05003806 private boolean wasStreamActiveRecently(int stream, int delay_ms) {
3807 return AudioSystem.isStreamActive(stream, delay_ms)
3808 || AudioSystem.isStreamActiveRemotely(stream, delay_ms);
Jean-Michel Trivifca1e602013-10-10 18:12:59 -07003809 }
3810
Eric Laurent6d517662012-04-23 18:42:39 -07003811 private int getActiveStreamType(int suggestedStreamType) {
Muyuan Li1ed6df62016-06-18 11:16:52 -07003812 if (mIsSingleVolume
3813 && suggestedStreamType == AudioManager.USE_DEFAULT_STREAM_TYPE) {
3814 return AudioSystem.STREAM_MUSIC;
3815 }
3816
Eric Laurent212532b2014-07-21 15:43:18 -07003817 switch (mPlatformType) {
John Spurlock61560172015-02-06 19:46:04 -05003818 case AudioSystem.PLATFORM_VOICE:
Eric Laurent6d517662012-04-23 18:42:39 -07003819 if (isInCommunication()) {
Eric Laurent25101b02011-02-02 09:33:30 -08003820 if (AudioSystem.getForceUse(AudioSystem.FOR_COMMUNICATION)
3821 == AudioSystem.FORCE_BT_SCO) {
3822 // Log.v(TAG, "getActiveStreamType: Forcing STREAM_BLUETOOTH_SCO...");
3823 return AudioSystem.STREAM_BLUETOOTH_SCO;
3824 } else {
3825 // Log.v(TAG, "getActiveStreamType: Forcing STREAM_VOICE_CALL...");
3826 return AudioSystem.STREAM_VOICE_CALL;
3827 }
Eric Laurent25101b02011-02-02 09:33:30 -08003828 } else if (suggestedStreamType == AudioManager.USE_DEFAULT_STREAM_TYPE) {
Julia Reynoldsd9e96e22017-11-07 10:33:08 -05003829 if (wasStreamActiveRecently(AudioSystem.STREAM_RING, sStreamOverrideDelayMs)) {
Jean-Michel Trivi3114ce32012-06-11 15:03:52 -07003830 if (DEBUG_VOL)
Julia Reynoldsd9e96e22017-11-07 10:33:08 -05003831 Log.v(TAG, "getActiveStreamType: Forcing STREAM_RING stream active");
3832 return AudioSystem.STREAM_RING;
3833 } else if (wasStreamActiveRecently(
3834 AudioSystem.STREAM_NOTIFICATION, sStreamOverrideDelayMs)) {
3835 if (DEBUG_VOL)
3836 Log.v(TAG, "getActiveStreamType: Forcing STREAM_NOTIFICATION stream active");
3837 return AudioSystem.STREAM_NOTIFICATION;
3838 } else {
Julia Reynoldseb0ce472018-05-04 15:34:55 -04003839 if (DEBUG_VOL) {
3840 Log.v(TAG, "getActiveStreamType: Forcing DEFAULT_VOL_STREAM_NO_PLAYBACK("
3841 + DEFAULT_VOL_STREAM_NO_PLAYBACK + ") b/c default");
3842 }
3843 return DEFAULT_VOL_STREAM_NO_PLAYBACK;
Jean-Michel Trivi3114ce32012-06-11 15:03:52 -07003844 }
Julia Reynoldsd9e96e22017-11-07 10:33:08 -05003845 } else if (
3846 wasStreamActiveRecently(AudioSystem.STREAM_NOTIFICATION, sStreamOverrideDelayMs)) {
Jean-Michel Trivi3114ce32012-06-11 15:03:52 -07003847 if (DEBUG_VOL)
Julia Reynoldsd9e96e22017-11-07 10:33:08 -05003848 Log.v(TAG, "getActiveStreamType: Forcing STREAM_NOTIFICATION stream active");
3849 return AudioSystem.STREAM_NOTIFICATION;
3850 } else if (wasStreamActiveRecently(AudioSystem.STREAM_RING, sStreamOverrideDelayMs)) {
3851 if (DEBUG_VOL)
3852 Log.v(TAG, "getActiveStreamType: Forcing STREAM_RING stream active");
3853 return AudioSystem.STREAM_RING;
Eric Laurent25101b02011-02-02 09:33:30 -08003854 }
Eric Laurent212532b2014-07-21 15:43:18 -07003855 default:
Eric Laurent6d517662012-04-23 18:42:39 -07003856 if (isInCommunication()) {
Eric Laurent25101b02011-02-02 09:33:30 -08003857 if (AudioSystem.getForceUse(AudioSystem.FOR_COMMUNICATION)
3858 == AudioSystem.FORCE_BT_SCO) {
Jean-Michel Trivi3114ce32012-06-11 15:03:52 -07003859 if (DEBUG_VOL) Log.v(TAG, "getActiveStreamType: Forcing STREAM_BLUETOOTH_SCO");
Eric Laurent25101b02011-02-02 09:33:30 -08003860 return AudioSystem.STREAM_BLUETOOTH_SCO;
3861 } else {
Jean-Michel Trivi3114ce32012-06-11 15:03:52 -07003862 if (DEBUG_VOL) Log.v(TAG, "getActiveStreamType: Forcing STREAM_VOICE_CALL");
Eric Laurent25101b02011-02-02 09:33:30 -08003863 return AudioSystem.STREAM_VOICE_CALL;
3864 }
Julia Reynoldsd9e96e22017-11-07 10:33:08 -05003865 } else if (AudioSystem.isStreamActive(
3866 AudioSystem.STREAM_NOTIFICATION, sStreamOverrideDelayMs)) {
Jean-Michel Trivi3114ce32012-06-11 15:03:52 -07003867 if (DEBUG_VOL) Log.v(TAG, "getActiveStreamType: Forcing STREAM_NOTIFICATION");
Eric Laurent25101b02011-02-02 09:33:30 -08003868 return AudioSystem.STREAM_NOTIFICATION;
Julia Reynoldsd9e96e22017-11-07 10:33:08 -05003869 } else if (AudioSystem.isStreamActive(
3870 AudioSystem.STREAM_RING, sStreamOverrideDelayMs)) {
3871 if (DEBUG_VOL) Log.v(TAG, "getActiveStreamType: Forcing STREAM_RING");
3872 return AudioSystem.STREAM_RING;
Jean-Michel Trivi3114ce32012-06-11 15:03:52 -07003873 } else if (suggestedStreamType == AudioManager.USE_DEFAULT_STREAM_TYPE) {
Julia Reynoldsd9e96e22017-11-07 10:33:08 -05003874 if (AudioSystem.isStreamActive(
3875 AudioSystem.STREAM_NOTIFICATION, sStreamOverrideDelayMs)) {
3876 if (DEBUG_VOL) Log.v(TAG, "getActiveStreamType: Forcing STREAM_NOTIFICATION");
John Spurlockeb1d88d2014-07-19 14:49:19 -04003877 return AudioSystem.STREAM_NOTIFICATION;
Julia Reynoldsd9e96e22017-11-07 10:33:08 -05003878 } else if (AudioSystem.isStreamActive(
3879 AudioSystem.STREAM_RING, sStreamOverrideDelayMs)) {
3880 if (DEBUG_VOL) Log.v(TAG, "getActiveStreamType: Forcing STREAM_RING");
3881 return AudioSystem.STREAM_RING;
3882 } else {
Julia Reynoldseb0ce472018-05-04 15:34:55 -04003883 if (DEBUG_VOL) {
3884 Log.v(TAG, "getActiveStreamType: Forcing DEFAULT_VOL_STREAM_NO_PLAYBACK("
3885 + DEFAULT_VOL_STREAM_NO_PLAYBACK + ") b/c default");
3886 }
3887 return DEFAULT_VOL_STREAM_NO_PLAYBACK;
Jean-Michel Trivi3114ce32012-06-11 15:03:52 -07003888 }
Joe Onoratoc7fcba42011-01-05 16:53:11 -08003889 }
Eric Laurent212532b2014-07-21 15:43:18 -07003890 break;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003891 }
Eric Laurent212532b2014-07-21 15:43:18 -07003892 if (DEBUG_VOL) Log.v(TAG, "getActiveStreamType: Returning suggested type "
3893 + suggestedStreamType);
3894 return suggestedStreamType;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003895 }
3896
John Spurlockbcc10872014-11-28 15:29:21 -05003897 private void broadcastRingerMode(String action, int ringerMode) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003898 // Send sticky broadcast
John Spurlockbcc10872014-11-28 15:29:21 -05003899 Intent broadcast = new Intent(action);
Glenn Kastenba195eb2011-12-13 09:30:40 -08003900 broadcast.putExtra(AudioManager.EXTRA_RINGER_MODE, ringerMode);
Dianne Hackborn1c633fc2009-12-08 19:45:14 -08003901 broadcast.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT
3902 | Intent.FLAG_RECEIVER_REPLACE_PENDING);
Dianne Hackborn5ac72a22012-08-29 18:32:08 -07003903 sendStickyBroadcastToAll(broadcast);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003904 }
3905
3906 private void broadcastVibrateSetting(int vibrateType) {
3907 // Send broadcast
Sudheer Shankafc46e9b2016-10-21 17:55:27 -07003908 if (mActivityManagerInternal.isSystemReady()) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003909 Intent broadcast = new Intent(AudioManager.VIBRATE_SETTING_CHANGED_ACTION);
3910 broadcast.putExtra(AudioManager.EXTRA_VIBRATE_TYPE, vibrateType);
3911 broadcast.putExtra(AudioManager.EXTRA_VIBRATE_SETTING, getVibrateSetting(vibrateType));
Dianne Hackborn5ac72a22012-08-29 18:32:08 -07003912 sendBroadcastToAll(broadcast);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003913 }
3914 }
3915
3916 // Message helper methods
Jean-Michel Trivi2d8dab52012-05-30 18:13:59 -07003917 /**
3918 * Queue a message on the given handler's message queue, after acquiring the service wake lock.
3919 * Note that the wake lock needs to be released after the message has been handled.
3920 */
3921 private void queueMsgUnderWakeLock(Handler handler, int msg,
3922 int arg1, int arg2, Object obj, int delay) {
Eric Laurenta4dfbdc52013-10-01 11:53:51 -07003923 final long ident = Binder.clearCallingIdentity();
3924 // Always acquire the wake lock as AudioService because it is released by the
3925 // message handler.
Jean-Michel Trivifa9a6982013-06-27 16:22:58 -07003926 mAudioEventWakeLock.acquire();
Eric Laurenta4dfbdc52013-10-01 11:53:51 -07003927 Binder.restoreCallingIdentity(ident);
Jean-Michel Trivi2d8dab52012-05-30 18:13:59 -07003928 sendMsg(handler, msg, SENDMSG_QUEUE, arg1, arg2, obj, delay);
3929 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003930
Eric Laurentafbb0472011-12-15 09:04:23 -08003931 private static void sendMsg(Handler handler, int msg,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003932 int existingMsgPolicy, int arg1, int arg2, Object obj, int delay) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003933 if (existingMsgPolicy == SENDMSG_REPLACE) {
3934 handler.removeMessages(msg);
3935 } else if (existingMsgPolicy == SENDMSG_NOOP && handler.hasMessages(msg)) {
3936 return;
3937 }
Eric Laurent3c4636c2018-06-13 19:36:42 -07003938
Jean-Michel Trivi58850372018-09-14 16:01:28 -07003939 final long time = SystemClock.uptimeMillis() + delay;
3940 handler.sendMessageAtTime(handler.obtainMessage(msg, arg1, arg2, obj), time);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003941 }
3942
3943 boolean checkAudioSettingsPermission(String method) {
Jean-Michel Triviccd654e2014-09-03 17:48:47 -07003944 if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.MODIFY_AUDIO_SETTINGS)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003945 == PackageManager.PERMISSION_GRANTED) {
3946 return true;
3947 }
3948 String msg = "Audio Settings Permission Denial: " + method + " from pid="
3949 + Binder.getCallingPid()
3950 + ", uid=" + Binder.getCallingUid();
3951 Log.w(TAG, msg);
3952 return false;
3953 }
3954
Jean-Michel Trivi58850372018-09-14 16:01:28 -07003955 /*package*/ int getDeviceForStream(int stream) {
John Spurlock8a52c442015-03-26 14:23:58 -04003956 int device = getDevicesForStream(stream);
Eric Laurent9bc8358d2011-11-18 16:43:31 -08003957 if ((device & (device - 1)) != 0) {
3958 // Multiple device selection is either:
3959 // - speaker + one other device: give priority to speaker in this case.
3960 // - one A2DP device + another device: happens with duplicated output. In this case
3961 // retain the device on the A2DP output as the other must not correspond to an active
3962 // selection if not the speaker.
Jungshik Jangc9ff9682014-09-15 17:41:06 +09003963 // - HDMI-CEC system audio mode only output: give priority to available item in order.
Eric Laurent9bc8358d2011-11-18 16:43:31 -08003964 if ((device & AudioSystem.DEVICE_OUT_SPEAKER) != 0) {
3965 device = AudioSystem.DEVICE_OUT_SPEAKER;
Jungshik Jangc9ff9682014-09-15 17:41:06 +09003966 } else if ((device & AudioSystem.DEVICE_OUT_HDMI_ARC) != 0) {
3967 device = AudioSystem.DEVICE_OUT_HDMI_ARC;
3968 } else if ((device & AudioSystem.DEVICE_OUT_SPDIF) != 0) {
3969 device = AudioSystem.DEVICE_OUT_SPDIF;
3970 } else if ((device & AudioSystem.DEVICE_OUT_AUX_LINE) != 0) {
3971 device = AudioSystem.DEVICE_OUT_AUX_LINE;
Eric Laurent9bc8358d2011-11-18 16:43:31 -08003972 } else {
3973 device &= AudioSystem.DEVICE_OUT_ALL_A2DP;
3974 }
3975 }
3976 return device;
3977 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003978
John Spurlock8a52c442015-03-26 14:23:58 -04003979 private int getDevicesForStream(int stream) {
3980 return getDevicesForStream(stream, true /*checkOthers*/);
3981 }
3982
3983 private int getDevicesForStream(int stream, boolean checkOthers) {
3984 ensureValidStreamType(stream);
3985 synchronized (VolumeStreamState.class) {
3986 return mStreamStates[stream].observeDevicesForStream_syncVSS(checkOthers);
3987 }
3988 }
3989
3990 private void observeDevicesForStreams(int skipStream) {
3991 synchronized (VolumeStreamState.class) {
3992 for (int stream = 0; stream < mStreamStates.length; stream++) {
3993 if (stream != skipStream) {
3994 mStreamStates[stream].observeDevicesForStream_syncVSS(false /*checkOthers*/);
3995 }
3996 }
3997 }
3998 }
3999
Jean-Michel Trivi58850372018-09-14 16:01:28 -07004000
4001 /*package*/ void observeDevicesForAllStreams() {
4002 observeDevicesForStreams(-1);
Aniket Kumar Lata9fbc2052019-01-11 02:02:33 -08004003 }
4004
Jean-Michel Trivi58850372018-09-14 16:01:28 -07004005 /*package*/ static final int CONNECTION_STATE_DISCONNECTED = 0;
4006 /*package*/ static final int CONNECTION_STATE_CONNECTED = 1;
4007 /**
4008 * The states that can be used with AudioService.setWiredDeviceConnectionState()
4009 * Attention: those values differ from those in BluetoothProfile, follow annotations to
4010 * distinguish between @ConnectionState and @BtProfileConnectionState
Paul McLean10804eb2015-01-28 11:16:35 -08004011 */
Jean-Michel Trivi58850372018-09-14 16:01:28 -07004012 @IntDef({
4013 CONNECTION_STATE_DISCONNECTED,
4014 CONNECTION_STATE_CONNECTED,
4015 })
4016 @Retention(RetentionPolicy.SOURCE)
4017 public @interface ConnectionState {}
Paul McLean10804eb2015-01-28 11:16:35 -08004018
Jean-Michel Trivi58850372018-09-14 16:01:28 -07004019 /**
4020 * see AudioManager.setWiredDeviceConnectionState()
4021 */
4022 public void setWiredDeviceConnectionState(int type,
4023 @ConnectionState int state, String address, String name,
John Spurlock90874332015-03-10 16:00:54 -04004024 String caller) {
Jean-Michel Trivi58850372018-09-14 16:01:28 -07004025 if (state != CONNECTION_STATE_CONNECTED
4026 && state != CONNECTION_STATE_DISCONNECTED) {
4027 throw new IllegalArgumentException("Invalid state " + state);
Eric Laurentb1fbaac2012-05-29 09:24:28 -07004028 }
Jean-Michel Trivi58850372018-09-14 16:01:28 -07004029 mDeviceBroker.setWiredDeviceConnectionState(type, state, address, name, caller);
Eric Laurentb1fbaac2012-05-29 09:24:28 -07004030 }
4031
Jean-Michel Trivi58850372018-09-14 16:01:28 -07004032 /**
4033 * @hide
4034 * The states that can be used with AudioService.setBluetoothHearingAidDeviceConnectionState()
4035 * and AudioService.setBluetoothA2dpDeviceConnectionStateSuppressNoisyIntent()
4036 */
4037 @IntDef({
4038 BluetoothProfile.STATE_DISCONNECTED,
4039 BluetoothProfile.STATE_CONNECTED,
4040 })
4041 @Retention(RetentionPolicy.SOURCE)
4042 public @interface BtProfileConnectionState {}
4043
Jean-Michel Trivifc86cfa2019-03-01 10:15:47 -08004044 /**
4045 * See AudioManager.setBluetoothHearingAidDeviceConnectionState()
4046 */
4047 public void setBluetoothHearingAidDeviceConnectionState(
Jean-Michel Trivi58850372018-09-14 16:01:28 -07004048 @NonNull BluetoothDevice device, @BtProfileConnectionState int state,
4049 boolean suppressNoisyIntent, int musicDevice)
Jakub Pawlowskif9570f32018-02-21 17:15:12 -08004050 {
Jean-Michel Trivi58850372018-09-14 16:01:28 -07004051 if (device == null) {
4052 throw new IllegalArgumentException("Illegal null device");
Jakub Pawlowskif9570f32018-02-21 17:15:12 -08004053 }
Jean-Michel Trivi58850372018-09-14 16:01:28 -07004054 if (state != BluetoothProfile.STATE_CONNECTED
4055 && state != BluetoothProfile.STATE_DISCONNECTED) {
4056 throw new IllegalArgumentException("Illegal BluetoothProfile state for device "
4057 + " (dis)connection, got " + state);
4058 }
Jean-Michel Trivifc86cfa2019-03-01 10:15:47 -08004059 mDeviceBroker.postBluetoothHearingAidDeviceConnectionState(
Jean-Michel Trivi58850372018-09-14 16:01:28 -07004060 device, state, suppressNoisyIntent, musicDevice, "AudioService");
Jakub Pawlowski10c90612018-02-21 13:28:46 -08004061 }
4062
Jean-Michel Trivi58850372018-09-14 16:01:28 -07004063 /**
4064 * See AudioManager.setBluetoothA2dpDeviceConnectionStateSuppressNoisyIntent()
4065 */
Jean-Michel Trivifc86cfa2019-03-01 10:15:47 -08004066 public void setBluetoothA2dpDeviceConnectionStateSuppressNoisyIntent(
Jean-Michel Trivi58850372018-09-14 16:01:28 -07004067 @NonNull BluetoothDevice device, @AudioService.BtProfileConnectionState int state,
4068 int profile, boolean suppressNoisyIntent, int a2dpVolume) {
4069 if (device == null) {
4070 throw new IllegalArgumentException("Illegal null device");
4071 }
4072 if (state != BluetoothProfile.STATE_CONNECTED
4073 && state != BluetoothProfile.STATE_DISCONNECTED) {
4074 throw new IllegalArgumentException("Illegal BluetoothProfile state for device "
4075 + " (dis)connection, got " + state);
4076 }
Jean-Michel Trivifc86cfa2019-03-01 10:15:47 -08004077 mDeviceBroker.postBluetoothA2dpDeviceConnectionStateSuppressNoisyIntent(device, state,
Jean-Michel Trivi58850372018-09-14 16:01:28 -07004078 profile, suppressNoisyIntent, a2dpVolume);
Pavlin Radoslavov82e06462018-01-19 18:20:04 -08004079 }
4080
Jean-Michel Trivi58850372018-09-14 16:01:28 -07004081 /**
4082 * See AudioManager.handleBluetoothA2dpDeviceConfigChange()
4083 * @param device
4084 */
Pavlin Radoslavov44a4ef02016-12-21 12:05:51 -08004085 public void handleBluetoothA2dpDeviceConfigChange(BluetoothDevice device)
4086 {
Jean-Michel Trivi58850372018-09-14 16:01:28 -07004087 if (device == null) {
4088 throw new IllegalArgumentException("Illegal null device");
Pavlin Radoslavov44a4ef02016-12-21 12:05:51 -08004089 }
Jean-Michel Trivi58850372018-09-14 16:01:28 -07004090 mDeviceBroker.postBluetoothA2dpDeviceConfigChange(device);
Pavlin Radoslavov44a4ef02016-12-21 12:05:51 -08004091 }
4092
Aniket Kumar Lataa8439e22019-01-11 03:59:00 -08004093 /**
4094 * @see AudioManager#handleBluetoothA2dpActiveDeviceChange(BluetoothDevice, int, int,
4095 * boolean, int)
4096 */
4097 public int handleBluetoothA2dpActiveDeviceChange(
4098 BluetoothDevice device, int state, int profile, boolean suppressNoisyIntent,
4099 int a2dpVolume) {
Jean-Michel Trivifc86cfa2019-03-01 10:15:47 -08004100 // FIXME method was added by @a8439e2 but never used, and now conflicts with async behavior
4101 // of handleBluetoothA2dpDeviceConfigChange and
4102 // setBluetoothA2dpDeviceConnectionStateSuppressNoisyIntent
Jean-Michel Trivi58850372018-09-14 16:01:28 -07004103 if (device == null) {
4104 throw new IllegalArgumentException("Illegal null device");
4105 }
Aniket Kumar Lataa8439e22019-01-11 03:59:00 -08004106 if (profile != BluetoothProfile.A2DP && profile != BluetoothProfile.A2DP_SINK) {
4107 throw new IllegalArgumentException("invalid profile " + profile);
4108 }
Jean-Michel Trivi58850372018-09-14 16:01:28 -07004109 if (state != BluetoothProfile.STATE_CONNECTED
4110 && state != BluetoothProfile.STATE_DISCONNECTED) {
4111 throw new IllegalArgumentException("Invalid state " + state);
Aniket Kumar Lataa8439e22019-01-11 03:59:00 -08004112 }
Jean-Michel Trivi58850372018-09-14 16:01:28 -07004113 return mDeviceBroker.handleBluetoothA2dpActiveDeviceChange(device, state, profile,
4114 suppressNoisyIntent, a2dpVolume);
Aniket Kumar Lataa8439e22019-01-11 03:59:00 -08004115 }
4116
Jean-Michel Trivi1ab43f62017-04-27 15:37:34 -07004117 private static final int DEVICE_MEDIA_UNMUTED_ON_PLUG =
4118 AudioSystem.DEVICE_OUT_WIRED_HEADSET | AudioSystem.DEVICE_OUT_WIRED_HEADPHONE |
4119 AudioSystem.DEVICE_OUT_LINE |
4120 AudioSystem.DEVICE_OUT_ALL_A2DP |
4121 AudioSystem.DEVICE_OUT_ALL_USB |
4122 AudioSystem.DEVICE_OUT_HDMI;
4123
Jean-Michel Trivi58850372018-09-14 16:01:28 -07004124 /*package*/ void postAccessoryPlugMediaUnmute(int newDevice) {
4125 sendMsg(mAudioHandler, MSG_ACCESSORY_PLUG_MEDIA_UNMUTE, SENDMSG_QUEUE,
4126 newDevice, 0, null, 0);
4127 }
4128
Jean-Michel Trivi1ab43f62017-04-27 15:37:34 -07004129 private void onAccessoryPlugMediaUnmute(int newDevice) {
4130 if (DEBUG_VOL) {
4131 Log.i(TAG, String.format("onAccessoryPlugMediaUnmute newDevice=%d [%s]",
4132 newDevice, AudioSystem.getOutputDeviceName(newDevice)));
4133 }
Jean-Michel Trivi58850372018-09-14 16:01:28 -07004134
4135 if (mNm.getZenMode() != Settings.Global.ZEN_MODE_NO_INTERRUPTIONS
4136 && (newDevice & DEVICE_MEDIA_UNMUTED_ON_PLUG) != 0
4137 && mStreamStates[AudioSystem.STREAM_MUSIC].mIsMuted
4138 && mStreamStates[AudioSystem.STREAM_MUSIC].getIndex(newDevice) != 0
4139 && (newDevice & AudioSystem.getDevicesForStream(AudioSystem.STREAM_MUSIC)) != 0) {
4140 if (DEBUG_VOL) {
4141 Log.i(TAG, String.format(" onAccessoryPlugMediaUnmute unmuting device=%d [%s]",
4142 newDevice, AudioSystem.getOutputDeviceName(newDevice)));
Jean-Michel Trivi1ab43f62017-04-27 15:37:34 -07004143 }
Jean-Michel Trivi58850372018-09-14 16:01:28 -07004144 mStreamStates[AudioSystem.STREAM_MUSIC].mute(false);
Jean-Michel Trivi1ab43f62017-04-27 15:37:34 -07004145 }
4146 }
4147
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004148 ///////////////////////////////////////////////////////////////////////////
4149 // Inner classes
4150 ///////////////////////////////////////////////////////////////////////////
4151
Eric Laurent8fa4d6f2014-10-30 14:13:03 -07004152 // NOTE: Locking order for synchronized objects related to volume or ringer mode management:
4153 // 1 mScoclient OR mSafeMediaVolumeState
Jean-Michel Trivi58850372018-09-14 16:01:28 -07004154 // 2 mSetModeLock
Eric Laurent8fa4d6f2014-10-30 14:13:03 -07004155 // 3 mSettingsLock
4156 // 4 VolumeStreamState.class
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004157 public class VolumeStreamState {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004158 private final int mStreamType;
Jean-Michel Trivie05eef82018-03-08 18:56:34 -08004159 private int mIndexMin;
4160 private int mIndexMax;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004161
RoboErik4197cb62015-01-21 15:45:32 -08004162 private boolean mIsMuted;
Jean-Michel Trivi11a74a72009-10-27 17:39:30 -07004163 private String mVolumeIndexSettingName;
John Spurlock8a52c442015-03-26 14:23:58 -04004164 private int mObservedDevices;
John Spurlockb6e19e32015-03-10 21:33:44 -04004165
John Spurlock2bb02ec2015-03-02 13:13:06 -05004166 private final SparseIntArray mIndexMap = new SparseIntArray(8);
John Spurlockf63860c2015-02-19 09:46:27 -05004167 private final Intent mVolumeChanged;
John Spurlock8a52c442015-03-26 14:23:58 -04004168 private final Intent mStreamDevicesChanged;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004169
Eric Laurenta553c252009-07-17 12:17:14 -07004170 private VolumeStreamState(String settingName, int streamType) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004171
Eric Laurent9bc8358d2011-11-18 16:43:31 -08004172 mVolumeIndexSettingName = settingName;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004173
4174 mStreamType = streamType;
John Spurlockb6e19e32015-03-10 21:33:44 -04004175 mIndexMin = MIN_STREAM_VOLUME[streamType] * 10;
4176 mIndexMax = MAX_STREAM_VOLUME[streamType] * 10;
4177 AudioSystem.initStreamVolume(streamType, mIndexMin / 10, mIndexMax / 10);
Eric Laurent9bc8358d2011-11-18 16:43:31 -08004178
Eric Laurent33902db2012-10-07 16:15:07 -07004179 readSettings();
John Spurlockf63860c2015-02-19 09:46:27 -05004180 mVolumeChanged = new Intent(AudioManager.VOLUME_CHANGED_ACTION);
4181 mVolumeChanged.putExtra(AudioManager.EXTRA_VOLUME_STREAM_TYPE, mStreamType);
John Spurlock8a52c442015-03-26 14:23:58 -04004182 mStreamDevicesChanged = new Intent(AudioManager.STREAM_DEVICES_CHANGED_ACTION);
4183 mStreamDevicesChanged.putExtra(AudioManager.EXTRA_VOLUME_STREAM_TYPE, mStreamType);
4184 }
4185
4186 public int observeDevicesForStream_syncVSS(boolean checkOthers) {
4187 final int devices = AudioSystem.getDevicesForStream(mStreamType);
4188 if (devices == mObservedDevices) {
4189 return devices;
4190 }
4191 final int prevDevices = mObservedDevices;
4192 mObservedDevices = devices;
4193 if (checkOthers) {
4194 // one stream's devices have changed, check the others
4195 observeDevicesForStreams(mStreamType);
4196 }
4197 // log base stream changes to the event log
4198 if (mStreamVolumeAlias[mStreamType] == mStreamType) {
4199 EventLogTags.writeStreamDevicesChanged(mStreamType, prevDevices, devices);
4200 }
4201 sendBroadcastToAll(mStreamDevicesChanged
4202 .putExtra(AudioManager.EXTRA_PREV_VOLUME_STREAM_DEVICES, prevDevices)
4203 .putExtra(AudioManager.EXTRA_VOLUME_STREAM_DEVICES, devices));
4204 return devices;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004205 }
4206
Jean-Michel Trivia53b7052017-04-12 18:27:01 -07004207 public @Nullable String getSettingNameForDevice(int device) {
4208 if (!hasValidSettingsName()) {
4209 return null;
Eric Laurent9bc8358d2011-11-18 16:43:31 -08004210 }
Jean-Michel Trivia53b7052017-04-12 18:27:01 -07004211 final String suffix = AudioSystem.getOutputDeviceName(device);
4212 if (suffix.isEmpty()) {
4213 return mVolumeIndexSettingName;
4214 }
4215 return mVolumeIndexSettingName + "_" + suffix;
4216 }
4217
4218 private boolean hasValidSettingsName() {
4219 return (mVolumeIndexSettingName != null && !mVolumeIndexSettingName.isEmpty());
Jean-Michel Trivi11a74a72009-10-27 17:39:30 -07004220 }
4221
Eric Laurentfdbee862014-05-12 15:26:12 -07004222 public void readSettings() {
Jean-Michel Trivi8719a1d2017-11-06 11:52:51 -08004223 synchronized (mSettingsLock) {
4224 synchronized (VolumeStreamState.class) {
4225 // force maximum volume on all streams if fixed volume property is set
4226 if (mUseFixedVolume) {
4227 mIndexMap.put(AudioSystem.DEVICE_OUT_DEFAULT, mIndexMax);
4228 return;
4229 }
4230 // do not read system stream volume from settings: this stream is always aliased
4231 // to another stream type and its volume is never persisted. Values in settings can
4232 // only be stale values
4233 if ((mStreamType == AudioSystem.STREAM_SYSTEM) ||
4234 (mStreamType == AudioSystem.STREAM_SYSTEM_ENFORCED)) {
4235 int index = 10 * AudioSystem.DEFAULT_STREAM_VOLUME[mStreamType];
Eric Laurentfdbee862014-05-12 15:26:12 -07004236 if (mCameraSoundForced) {
4237 index = mIndexMax;
4238 }
Jean-Michel Trivi8719a1d2017-11-06 11:52:51 -08004239 mIndexMap.put(AudioSystem.DEVICE_OUT_DEFAULT, index);
4240 return;
Eric Laurentdd45d012012-10-08 09:04:34 -07004241 }
Eric Laurent9bc8358d2011-11-18 16:43:31 -08004242 }
Jean-Michel Trivi8719a1d2017-11-06 11:52:51 -08004243 }
4244 synchronized (VolumeStreamState.class) {
Eric Laurentfdbee862014-05-12 15:26:12 -07004245 int remainingDevices = AudioSystem.DEVICE_OUT_ALL;
4246
4247 for (int i = 0; remainingDevices != 0; i++) {
4248 int device = (1 << i);
4249 if ((device & remainingDevices) == 0) {
4250 continue;
4251 }
4252 remainingDevices &= ~device;
4253
4254 // retrieve current volume for device
Eric Laurentfdbee862014-05-12 15:26:12 -07004255 // if no volume stored for current stream and device, use default volume if default
4256 // device, continue otherwise
4257 int defaultIndex = (device == AudioSystem.DEVICE_OUT_DEFAULT) ?
John Spurlock61560172015-02-06 19:46:04 -05004258 AudioSystem.DEFAULT_STREAM_VOLUME[mStreamType] : -1;
Jean-Michel Trivia53b7052017-04-12 18:27:01 -07004259 int index;
4260 if (!hasValidSettingsName()) {
4261 index = defaultIndex;
4262 } else {
4263 String name = getSettingNameForDevice(device);
4264 index = Settings.System.getIntForUser(
4265 mContentResolver, name, defaultIndex, UserHandle.USER_CURRENT);
4266 }
Eric Laurentfdbee862014-05-12 15:26:12 -07004267 if (index == -1) {
4268 continue;
4269 }
4270
John Spurlock2bb02ec2015-03-02 13:13:06 -05004271 mIndexMap.put(device, getValidIndex(10 * index));
Eric Laurentdd45d012012-10-08 09:04:34 -07004272 }
Eric Laurent9bc8358d2011-11-18 16:43:31 -08004273 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004274 }
4275
Liejun Tao39fb5672016-03-09 15:52:13 -06004276 private int getAbsoluteVolumeIndex(int index) {
4277 /* Special handling for Bluetooth Absolute Volume scenario
4278 * If we send full audio gain, some accessories are too loud even at its lowest
4279 * volume. We are not able to enumerate all such accessories, so here is the
4280 * workaround from phone side.
4281 * Pre-scale volume at lowest volume steps 1 2 and 3.
4282 * For volume step 0, set audio gain to 0 as some accessories won't mute on their end.
4283 */
4284 if (index == 0) {
4285 // 0% for volume 0
4286 index = 0;
Tomoharu Kasaharaf0fecb12018-09-06 20:04:38 +09004287 } else if (index > 0 && index <= 3) {
4288 // Pre-scale for volume steps 1 2 and 3
4289 index = (int) (mIndexMax * mPrescaleAbsoluteVolume[index - 1]) / 10;
Liejun Tao39fb5672016-03-09 15:52:13 -06004290 } else {
4291 // otherwise, full gain
Tomoharu Kasaharaf0fecb12018-09-06 20:04:38 +09004292 index = (mIndexMax + 5) / 10;
Liejun Tao39fb5672016-03-09 15:52:13 -06004293 }
4294 return index;
4295 }
4296
Eric Laurent8fa4d6f2014-10-30 14:13:03 -07004297 // must be called while synchronized VolumeStreamState.class
Jean-Michel Trivi58850372018-09-14 16:01:28 -07004298 /*package*/ void applyDeviceVolume_syncVSS(int device, boolean isAvrcpAbsVolSupported) {
Eric Laurent42b041e2013-03-29 11:36:03 -07004299 int index;
RoboErik4197cb62015-01-21 15:45:32 -08004300 if (mIsMuted) {
Eric Laurent42b041e2013-03-29 11:36:03 -07004301 index = 0;
Jean-Michel Trivi58850372018-09-14 16:01:28 -07004302 } else if ((device & AudioSystem.DEVICE_OUT_ALL_A2DP) != 0 && isAvrcpAbsVolSupported) {
Liejun Tao39fb5672016-03-09 15:52:13 -06004303 index = getAbsoluteVolumeIndex((getIndex(device) + 5)/10);
Liejun Tao4565a472016-01-20 17:52:20 -06004304 } else if ((device & mFullVolumeDevices) != 0) {
Matthew Xiec9d1d5f2013-09-12 00:32:22 -07004305 index = (mIndexMax + 5)/10;
Jakub Pawlowskic274fb22018-04-04 10:15:12 -07004306 } else if ((device & AudioSystem.DEVICE_OUT_HEARING_AID) != 0) {
4307 index = (mIndexMax + 5)/10;
Eric Laurentcd772d02013-10-30 18:31:07 -07004308 } else {
Eric Laurent42b041e2013-03-29 11:36:03 -07004309 index = (getIndex(device) + 5)/10;
4310 }
Jean-Michel Trivi58850372018-09-14 16:01:28 -07004311 AudioSystem.setStreamVolumeIndexAS(mStreamType, index, device);
Eric Laurent9bc8358d2011-11-18 16:43:31 -08004312 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004313
Eric Laurentfdbee862014-05-12 15:26:12 -07004314 public void applyAllVolumes() {
Jean-Michel Trivi58850372018-09-14 16:01:28 -07004315 final boolean isAvrcpAbsVolSupported = mDeviceBroker.isAvrcpAbsoluteVolumeSupported();
Eric Laurentfdbee862014-05-12 15:26:12 -07004316 synchronized (VolumeStreamState.class) {
Eric Laurentd9ac2be2016-04-07 14:04:23 -07004317 // apply device specific volumes first
Eric Laurentfdbee862014-05-12 15:26:12 -07004318 int index;
John Spurlock2bb02ec2015-03-02 13:13:06 -05004319 for (int i = 0; i < mIndexMap.size(); i++) {
Eric Laurentd9ac2be2016-04-07 14:04:23 -07004320 final int device = mIndexMap.keyAt(i);
Eric Laurentfdbee862014-05-12 15:26:12 -07004321 if (device != AudioSystem.DEVICE_OUT_DEFAULT) {
RoboErik4197cb62015-01-21 15:45:32 -08004322 if (mIsMuted) {
Eric Laurentfdbee862014-05-12 15:26:12 -07004323 index = 0;
Liejun Tao39fb5672016-03-09 15:52:13 -06004324 } else if ((device & AudioSystem.DEVICE_OUT_ALL_A2DP) != 0 &&
Jean-Michel Trivi58850372018-09-14 16:01:28 -07004325 isAvrcpAbsVolSupported) {
Liejun Tao39fb5672016-03-09 15:52:13 -06004326 index = getAbsoluteVolumeIndex((getIndex(device) + 5)/10);
4327 } else if ((device & mFullVolumeDevices) != 0) {
Eric Laurentfdbee862014-05-12 15:26:12 -07004328 index = (mIndexMax + 5)/10;
Jakub Pawlowskic274fb22018-04-04 10:15:12 -07004329 } else if ((device & AudioSystem.DEVICE_OUT_HEARING_AID) != 0) {
4330 index = (mIndexMax + 5)/10;
Eric Laurentfdbee862014-05-12 15:26:12 -07004331 } else {
John Spurlock2bb02ec2015-03-02 13:13:06 -05004332 index = (mIndexMap.valueAt(i) + 5)/10;
Eric Laurentfdbee862014-05-12 15:26:12 -07004333 }
Jean-Michel Trivi58850372018-09-14 16:01:28 -07004334 AudioSystem.setStreamVolumeIndexAS(mStreamType, index, device);
Eric Laurent42b041e2013-03-29 11:36:03 -07004335 }
Eric Laurent9bc8358d2011-11-18 16:43:31 -08004336 }
Eric Laurentd9ac2be2016-04-07 14:04:23 -07004337 // apply default volume last: by convention , default device volume will be used
4338 // by audio policy manager if no explicit volume is present for a given device type
4339 if (mIsMuted) {
4340 index = 0;
4341 } else {
4342 index = (getIndex(AudioSystem.DEVICE_OUT_DEFAULT) + 5)/10;
4343 }
Jean-Michel Trivi58850372018-09-14 16:01:28 -07004344 AudioSystem.setStreamVolumeIndexAS(
Eric Laurentd9ac2be2016-04-07 14:04:23 -07004345 mStreamType, index, AudioSystem.DEVICE_OUT_DEFAULT);
Eric Laurent9bc8358d2011-11-18 16:43:31 -08004346 }
4347 }
4348
John Spurlock90874332015-03-10 16:00:54 -04004349 public boolean adjustIndex(int deltaIndex, int device, String caller) {
4350 return setIndex(getIndex(device) + deltaIndex, device, caller);
Eric Laurent9bc8358d2011-11-18 16:43:31 -08004351 }
4352
John Spurlock90874332015-03-10 16:00:54 -04004353 public boolean setIndex(int index, int device, String caller) {
Jack He6dd78c12018-02-12 21:00:24 -08004354 boolean changed;
John Spurlockf63860c2015-02-19 09:46:27 -05004355 int oldIndex;
Jean-Michel Trivi8719a1d2017-11-06 11:52:51 -08004356 synchronized (mSettingsLock) {
4357 synchronized (VolumeStreamState.class) {
4358 oldIndex = getIndex(device);
4359 index = getValidIndex(index);
Eric Laurentfdbee862014-05-12 15:26:12 -07004360 if ((mStreamType == AudioSystem.STREAM_SYSTEM_ENFORCED) && mCameraSoundForced) {
4361 index = mIndexMax;
Eric Laurenta553c252009-07-17 12:17:14 -07004362 }
Jean-Michel Trivi8719a1d2017-11-06 11:52:51 -08004363 mIndexMap.put(device, index);
Eric Laurentfdbee862014-05-12 15:26:12 -07004364
Jean-Michel Trivi8719a1d2017-11-06 11:52:51 -08004365 changed = oldIndex != index;
4366 // Apply change to all streams using this one as alias if:
4367 // - the index actually changed OR
4368 // - there is no volume index stored for this device on alias stream.
4369 // If changing volume of current device, also change volume of current
4370 // device on aliased stream
Jack He6dd78c12018-02-12 21:00:24 -08004371 final boolean isCurrentDevice = (device == getDeviceForStream(mStreamType));
Jean-Michel Trivi8719a1d2017-11-06 11:52:51 -08004372 final int numStreamTypes = AudioSystem.getNumStreamTypes();
4373 for (int streamType = numStreamTypes - 1; streamType >= 0; streamType--) {
4374 final VolumeStreamState aliasStreamState = mStreamStates[streamType];
4375 if (streamType != mStreamType &&
4376 mStreamVolumeAlias[streamType] == mStreamType &&
4377 (changed || !aliasStreamState.hasIndexForDevice(device))) {
4378 final int scaledIndex = rescaleIndex(index, mStreamType, streamType);
4379 aliasStreamState.setIndex(scaledIndex, device, caller);
Jack He6dd78c12018-02-12 21:00:24 -08004380 if (isCurrentDevice) {
Jean-Michel Trivi8719a1d2017-11-06 11:52:51 -08004381 aliasStreamState.setIndex(scaledIndex,
4382 getDeviceForStream(streamType), caller);
4383 }
Eric Laurentfdbee862014-05-12 15:26:12 -07004384 }
4385 }
Jack He6dd78c12018-02-12 21:00:24 -08004386 // Mirror changes in SPEAKER ringtone volume on SCO when
4387 if (changed && mStreamType == AudioSystem.STREAM_RING
4388 && device == AudioSystem.DEVICE_OUT_SPEAKER) {
4389 for (int i = 0; i < mIndexMap.size(); i++) {
4390 int otherDevice = mIndexMap.keyAt(i);
4391 if ((otherDevice & AudioSystem.DEVICE_OUT_ALL_SCO) != 0) {
4392 mIndexMap.put(otherDevice, index);
4393 }
4394 }
4395 }
Eric Laurentfdbee862014-05-12 15:26:12 -07004396 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004397 }
John Spurlockf63860c2015-02-19 09:46:27 -05004398 if (changed) {
4399 oldIndex = (oldIndex + 5) / 10;
4400 index = (index + 5) / 10;
John Spurlock90874332015-03-10 16:00:54 -04004401 // log base stream changes to the event log
4402 if (mStreamVolumeAlias[mStreamType] == mStreamType) {
4403 if (caller == null) {
4404 Log.w(TAG, "No caller for volume_changed event", new Throwable());
4405 }
4406 EventLogTags.writeVolumeChanged(mStreamType, oldIndex, index, mIndexMax / 10,
4407 caller);
4408 }
4409 // fire changed intents for all streams
John Spurlockf63860c2015-02-19 09:46:27 -05004410 mVolumeChanged.putExtra(AudioManager.EXTRA_VOLUME_STREAM_VALUE, index);
4411 mVolumeChanged.putExtra(AudioManager.EXTRA_PREV_VOLUME_STREAM_VALUE, oldIndex);
Jean-Michel Trivi560877d2015-06-25 17:38:35 -07004412 mVolumeChanged.putExtra(AudioManager.EXTRA_VOLUME_STREAM_TYPE_ALIAS,
4413 mStreamVolumeAlias[mStreamType]);
John Spurlockf63860c2015-02-19 09:46:27 -05004414 sendBroadcastToAll(mVolumeChanged);
4415 }
4416 return changed;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004417 }
4418
Eric Laurentfdbee862014-05-12 15:26:12 -07004419 public int getIndex(int device) {
4420 synchronized (VolumeStreamState.class) {
John Spurlock2bb02ec2015-03-02 13:13:06 -05004421 int index = mIndexMap.get(device, -1);
4422 if (index == -1) {
Eric Laurentfdbee862014-05-12 15:26:12 -07004423 // there is always an entry for AudioSystem.DEVICE_OUT_DEFAULT
John Spurlock2bb02ec2015-03-02 13:13:06 -05004424 index = mIndexMap.get(AudioSystem.DEVICE_OUT_DEFAULT);
Eric Laurentfdbee862014-05-12 15:26:12 -07004425 }
John Spurlock2bb02ec2015-03-02 13:13:06 -05004426 return index;
Eric Laurent9bc8358d2011-11-18 16:43:31 -08004427 }
Eric Laurent5b4e6542010-03-19 20:02:21 -07004428 }
4429
Eric Laurent3fb608e2016-11-03 16:27:40 -07004430 public boolean hasIndexForDevice(int device) {
4431 synchronized (VolumeStreamState.class) {
4432 return (mIndexMap.get(device, -1) != -1);
4433 }
4434 }
4435
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004436 public int getMaxIndex() {
Eric Laurenta553c252009-07-17 12:17:14 -07004437 return mIndexMax;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004438 }
4439
John Spurlockb6e19e32015-03-10 21:33:44 -04004440 public int getMinIndex() {
4441 return mIndexMin;
4442 }
4443
Jean-Michel Trivi170a0ee2017-04-14 18:13:26 -07004444 /**
Jean-Michel Trivie05eef82018-03-08 18:56:34 -08004445 * Updates the min/max index values from another stream. Use this when changing the alias
4446 * for the current stream type.
4447 * @param sourceStreamType
4448 */
4449 // must be sync'd on mSettingsLock before VolumeStreamState.class
4450 @GuardedBy("VolumeStreamState.class")
4451 public void refreshRange(int sourceStreamType) {
4452 mIndexMin = MIN_STREAM_VOLUME[sourceStreamType] * 10;
4453 mIndexMax = MAX_STREAM_VOLUME[sourceStreamType] * 10;
4454 // verify all current volumes are within bounds
4455 for (int i = 0 ; i < mIndexMap.size(); i++) {
4456 final int device = mIndexMap.keyAt(i);
4457 final int index = mIndexMap.valueAt(i);
4458 mIndexMap.put(device, getValidIndex(index));
4459 }
4460 }
4461
4462 /**
Jean-Michel Trivi170a0ee2017-04-14 18:13:26 -07004463 * Copies all device/index pairs from the given VolumeStreamState after initializing
4464 * them with the volume for DEVICE_OUT_DEFAULT. No-op if the source VolumeStreamState
4465 * has the same stream type as this instance.
4466 * @param srcStream
4467 * @param caller
4468 */
Jean-Michel Trivi085346a2018-02-14 10:48:51 -08004469 // must be sync'd on mSettingsLock before VolumeStreamState.class
4470 @GuardedBy("VolumeStreamState.class")
John Spurlock90874332015-03-10 16:00:54 -04004471 public void setAllIndexes(VolumeStreamState srcStream, String caller) {
Jean-Michel Trivi170a0ee2017-04-14 18:13:26 -07004472 if (mStreamType == srcStream.mStreamType) {
4473 return;
4474 }
Jean-Michel Trivi085346a2018-02-14 10:48:51 -08004475 int srcStreamType = srcStream.getStreamType();
4476 // apply default device volume from source stream to all devices first in case
4477 // some devices are present in this stream state but not in source stream state
4478 int index = srcStream.getIndex(AudioSystem.DEVICE_OUT_DEFAULT);
4479 index = rescaleIndex(index, srcStreamType, mStreamType);
4480 for (int i = 0; i < mIndexMap.size(); i++) {
4481 mIndexMap.put(mIndexMap.keyAt(i), index);
4482 }
4483 // Now apply actual volume for devices in source stream state
4484 SparseIntArray srcMap = srcStream.mIndexMap;
4485 for (int i = 0; i < srcMap.size(); i++) {
4486 int device = srcMap.keyAt(i);
4487 index = srcMap.valueAt(i);
4488 index = rescaleIndex(index, srcStreamType, mStreamType);
Eric Laurent33902db2012-10-07 16:15:07 -07004489
Jean-Michel Trivi085346a2018-02-14 10:48:51 -08004490 setIndex(index, device, caller);
Eric Laurent6d517662012-04-23 18:42:39 -07004491 }
4492 }
4493
Jean-Michel Trivi085346a2018-02-14 10:48:51 -08004494 // must be sync'd on mSettingsLock before VolumeStreamState.class
4495 @GuardedBy("VolumeStreamState.class")
Eric Laurentfdbee862014-05-12 15:26:12 -07004496 public void setAllIndexesToMax() {
Jean-Michel Trivi085346a2018-02-14 10:48:51 -08004497 for (int i = 0; i < mIndexMap.size(); i++) {
4498 mIndexMap.put(mIndexMap.keyAt(i), mIndexMax);
Eric Laurentdd45d012012-10-08 09:04:34 -07004499 }
Eric Laurentdd45d012012-10-08 09:04:34 -07004500 }
4501
RoboErik4197cb62015-01-21 15:45:32 -08004502 public void mute(boolean state) {
John Spurlock22b9ee12015-02-18 22:51:44 -05004503 boolean changed = false;
Eric Laurentfdbee862014-05-12 15:26:12 -07004504 synchronized (VolumeStreamState.class) {
RoboErik4197cb62015-01-21 15:45:32 -08004505 if (state != mIsMuted) {
John Spurlock22b9ee12015-02-18 22:51:44 -05004506 changed = true;
RoboErik4197cb62015-01-21 15:45:32 -08004507 mIsMuted = state;
John Spurlock22b9ee12015-02-18 22:51:44 -05004508
RoboErik4197cb62015-01-21 15:45:32 -08004509 // Set the new mute volume. This propagates the values to
4510 // the audio system, otherwise the volume won't be changed
4511 // at the lower level.
4512 sendMsg(mAudioHandler,
4513 MSG_SET_ALL_VOLUMES,
4514 SENDMSG_QUEUE,
4515 0,
4516 0,
4517 this, 0);
Eric Laurentfdbee862014-05-12 15:26:12 -07004518 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004519 }
John Spurlock22b9ee12015-02-18 22:51:44 -05004520 if (changed) {
4521 // Stream mute changed, fire the intent.
4522 Intent intent = new Intent(AudioManager.STREAM_MUTE_CHANGED_ACTION);
4523 intent.putExtra(AudioManager.EXTRA_VOLUME_STREAM_TYPE, mStreamType);
4524 intent.putExtra(AudioManager.EXTRA_STREAM_VOLUME_MUTED, state);
4525 sendBroadcastToAll(intent);
4526 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004527 }
4528
Eric Laurent6d517662012-04-23 18:42:39 -07004529 public int getStreamType() {
4530 return mStreamType;
4531 }
4532
Eric Laurent212532b2014-07-21 15:43:18 -07004533 public void checkFixedVolumeDevices() {
Jean-Michel Trivi58850372018-09-14 16:01:28 -07004534 final boolean isAvrcpAbsVolSupported = mDeviceBroker.isAvrcpAbsoluteVolumeSupported();
Eric Laurent212532b2014-07-21 15:43:18 -07004535 synchronized (VolumeStreamState.class) {
4536 // ignore settings for fixed volume devices: volume should always be at max or 0
4537 if (mStreamVolumeAlias[mStreamType] == AudioSystem.STREAM_MUSIC) {
John Spurlock2bb02ec2015-03-02 13:13:06 -05004538 for (int i = 0; i < mIndexMap.size(); i++) {
4539 int device = mIndexMap.keyAt(i);
4540 int index = mIndexMap.valueAt(i);
Jean-Michel Triviba5270b2014-10-01 17:49:29 -07004541 if (((device & mFullVolumeDevices) != 0)
4542 || (((device & mFixedVolumeDevices) != 0) && index != 0)) {
John Spurlock2bb02ec2015-03-02 13:13:06 -05004543 mIndexMap.put(device, mIndexMax);
Eric Laurent212532b2014-07-21 15:43:18 -07004544 }
Jean-Michel Trivi58850372018-09-14 16:01:28 -07004545 applyDeviceVolume_syncVSS(device, isAvrcpAbsVolSupported);
Eric Laurent212532b2014-07-21 15:43:18 -07004546 }
4547 }
4548 }
4549 }
4550
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004551 private int getValidIndex(int index) {
John Spurlockb6e19e32015-03-10 21:33:44 -04004552 if (index < mIndexMin) {
4553 return mIndexMin;
John Spurlockee5ad722015-03-03 16:17:21 -05004554 } else if (mUseFixedVolume || index > mIndexMax) {
Eric Laurenta553c252009-07-17 12:17:14 -07004555 return mIndexMax;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004556 }
4557
4558 return index;
4559 }
4560
Eric Laurentbffc3d12012-05-07 17:43:49 -07004561 private void dump(PrintWriter pw) {
RoboErik4197cb62015-01-21 15:45:32 -08004562 pw.print(" Muted: ");
4563 pw.println(mIsMuted);
John Spurlockb6e19e32015-03-10 21:33:44 -04004564 pw.print(" Min: ");
4565 pw.println((mIndexMin + 5) / 10);
John Spurlock2b29bc42014-08-26 16:40:35 -04004566 pw.print(" Max: ");
4567 pw.println((mIndexMax + 5) / 10);
Eric Laurentbffc3d12012-05-07 17:43:49 -07004568 pw.print(" Current: ");
John Spurlock2bb02ec2015-03-02 13:13:06 -05004569 for (int i = 0; i < mIndexMap.size(); i++) {
4570 if (i > 0) {
4571 pw.print(", ");
4572 }
4573 final int device = mIndexMap.keyAt(i);
John Spurlock2b29bc42014-08-26 16:40:35 -04004574 pw.print(Integer.toHexString(device));
4575 final String deviceName = device == AudioSystem.DEVICE_OUT_DEFAULT ? "default"
4576 : AudioSystem.getOutputDeviceName(device);
4577 if (!deviceName.isEmpty()) {
4578 pw.print(" (");
4579 pw.print(deviceName);
4580 pw.print(")");
4581 }
4582 pw.print(": ");
John Spurlock2bb02ec2015-03-02 13:13:06 -05004583 final int index = (mIndexMap.valueAt(i) + 5) / 10;
John Spurlock2b29bc42014-08-26 16:40:35 -04004584 pw.print(index);
Eric Laurentbffc3d12012-05-07 17:43:49 -07004585 }
John Spurlockb32fc972015-03-05 13:58:00 -05004586 pw.println();
4587 pw.print(" Devices: ");
John Spurlock8a52c442015-03-26 14:23:58 -04004588 final int devices = getDevicesForStream(mStreamType);
John Spurlockb32fc972015-03-05 13:58:00 -05004589 int device, i = 0, n = 0;
John Spurlock1ff1e6e2015-03-09 14:21:20 -04004590 // iterate all devices from 1 to DEVICE_OUT_DEFAULT exclusive
4591 // (the default device is not returned by getDevicesForStream)
4592 while ((device = 1 << i) != AudioSystem.DEVICE_OUT_DEFAULT) {
John Spurlockb32fc972015-03-05 13:58:00 -05004593 if ((devices & device) != 0) {
4594 if (n++ > 0) {
4595 pw.print(", ");
4596 }
4597 pw.print(AudioSystem.getOutputDeviceName(device));
4598 }
4599 i++;
4600 }
Eric Laurentbffc3d12012-05-07 17:43:49 -07004601 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004602 }
4603
4604 /** Thread that handles native AudioSystem control. */
4605 private class AudioSystemThread extends Thread {
4606 AudioSystemThread() {
4607 super("AudioService");
4608 }
4609
4610 @Override
4611 public void run() {
4612 // Set this thread up so the handler will work on it
4613 Looper.prepare();
4614
4615 synchronized(AudioService.this) {
4616 mAudioHandler = new AudioHandler();
4617
4618 // Notify that the handler has been created
4619 AudioService.this.notify();
4620 }
4621
4622 // Listen for volume change requests that are set by VolumePanel
4623 Looper.loop();
4624 }
4625 }
4626
Jean-Michel Trivi58850372018-09-14 16:01:28 -07004627 /*package*/ void setDeviceVolume(VolumeStreamState streamState, int device) {
4628
4629 final boolean isAvrcpAbsVolSupported = mDeviceBroker.isAvrcpAbsoluteVolumeSupported();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004630
Eric Laurent3e6fb632018-05-21 09:28:46 -07004631 synchronized (VolumeStreamState.class) {
4632 // Apply volume
Jean-Michel Trivi58850372018-09-14 16:01:28 -07004633 streamState.applyDeviceVolume_syncVSS(device, isAvrcpAbsVolSupported);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004634
Eric Laurent3e6fb632018-05-21 09:28:46 -07004635 // Apply change to all streams using this one as alias
4636 int numStreamTypes = AudioSystem.getNumStreamTypes();
4637 for (int streamType = numStreamTypes - 1; streamType >= 0; streamType--) {
4638 if (streamType != streamState.mStreamType &&
4639 mStreamVolumeAlias[streamType] == streamState.mStreamType) {
4640 // Make sure volume is also maxed out on A2DP device for aliased stream
4641 // that may have a different device selected
4642 int streamDevice = getDeviceForStream(streamType);
Jean-Michel Trivi58850372018-09-14 16:01:28 -07004643 if ((device != streamDevice) && isAvrcpAbsVolSupported
4644 && ((device & AudioSystem.DEVICE_OUT_ALL_A2DP) != 0)) {
4645 mStreamStates[streamType].applyDeviceVolume_syncVSS(device,
4646 isAvrcpAbsVolSupported);
Eric Laurentcd772d02013-10-30 18:31:07 -07004647 }
Jean-Michel Trivi58850372018-09-14 16:01:28 -07004648 mStreamStates[streamType].applyDeviceVolume_syncVSS(streamDevice,
4649 isAvrcpAbsVolSupported);
Eric Laurenta553c252009-07-17 12:17:14 -07004650 }
4651 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004652 }
Eric Laurent3e6fb632018-05-21 09:28:46 -07004653 // Post a persist volume msg
4654 sendMsg(mAudioHandler,
4655 MSG_PERSIST_VOLUME,
4656 SENDMSG_QUEUE,
4657 device,
4658 0,
4659 streamState,
4660 PERSIST_DELAY);
4661
4662 }
4663
4664 /** Handles internal volume messages in separate volume thread. */
4665 private class AudioHandler extends Handler {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004666
Eric Laurent9bc8358d2011-11-18 16:43:31 -08004667 private void setAllVolumes(VolumeStreamState streamState) {
4668
4669 // Apply volume
4670 streamState.applyAllVolumes();
4671
4672 // Apply change to all streams using this one as alias
4673 int numStreamTypes = AudioSystem.getNumStreamTypes();
4674 for (int streamType = numStreamTypes - 1; streamType >= 0; streamType--) {
4675 if (streamType != streamState.mStreamType &&
Eric Laurent6d517662012-04-23 18:42:39 -07004676 mStreamVolumeAlias[streamType] == streamState.mStreamType) {
Eric Laurent9bc8358d2011-11-18 16:43:31 -08004677 mStreamStates[streamType].applyAllVolumes();
4678 }
4679 }
4680 }
4681
Eric Laurent42b041e2013-03-29 11:36:03 -07004682 private void persistVolume(VolumeStreamState streamState, int device) {
Eric Laurent83a017b2013-03-19 18:15:31 -07004683 if (mUseFixedVolume) {
4684 return;
4685 }
Muyuan Li1ed6df62016-06-18 11:16:52 -07004686 if (mIsSingleVolume && (streamState.mStreamType != AudioSystem.STREAM_MUSIC)) {
Eric Laurent212532b2014-07-21 15:43:18 -07004687 return;
4688 }
Jean-Michel Trivia53b7052017-04-12 18:27:01 -07004689 if (streamState.hasValidSettingsName()) {
4690 System.putIntForUser(mContentResolver,
4691 streamState.getSettingNameForDevice(device),
4692 (streamState.getIndex(device) + 5)/ 10,
4693 UserHandle.USER_CURRENT);
4694 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004695 }
4696
Glenn Kastenba195eb2011-12-13 09:30:40 -08004697 private void persistRingerMode(int ringerMode) {
Eric Laurent83a017b2013-03-19 18:15:31 -07004698 if (mUseFixedVolume) {
4699 return;
4700 }
Jeff Sharkey8d9a1f62012-10-18 15:38:14 -07004701 Settings.Global.putInt(mContentResolver, Settings.Global.MODE_RINGER, ringerMode);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004702 }
4703
Jaekyun Seokc31033f2018-01-15 14:53:17 +09004704 private String getSoundEffectFilePath(int effectType) {
4705 String filePath = Environment.getProductDirectory() + SOUND_EFFECTS_PATH
4706 + SOUND_EFFECT_FILES.get(SOUND_EFFECT_FILES_MAP[effectType][0]);
4707 if (!new File(filePath).isFile()) {
4708 filePath = Environment.getRootDirectory() + SOUND_EFFECTS_PATH
4709 + SOUND_EFFECT_FILES.get(SOUND_EFFECT_FILES_MAP[effectType][0]);
4710 }
4711 return filePath;
4712 }
4713
Eric Laurent5d3eb44a2013-03-21 15:35:10 -07004714 private boolean onLoadSoundEffects() {
4715 int status;
4716
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004717 synchronized (mSoundEffectsLock) {
Eric Laurent4a5eeb92014-05-06 10:49:04 -07004718 if (!mSystemReady) {
Eric Laurent5d3eb44a2013-03-21 15:35:10 -07004719 Log.w(TAG, "onLoadSoundEffects() called before boot complete");
4720 return false;
4721 }
4722
4723 if (mSoundPool != null) {
4724 return true;
4725 }
4726
4727 loadTouchSoundAssets();
4728
Jean-Michel Trivi55a30c42014-07-20 17:56:11 -07004729 mSoundPool = new SoundPool.Builder()
4730 .setMaxStreams(NUM_SOUNDPOOL_CHANNELS)
4731 .setAudioAttributes(new AudioAttributes.Builder()
4732 .setUsage(AudioAttributes.USAGE_ASSISTANCE_SONIFICATION)
4733 .setContentType(AudioAttributes.CONTENT_TYPE_SONIFICATION)
4734 .build())
4735 .build();
Eric Laurent5d3eb44a2013-03-21 15:35:10 -07004736 mSoundPoolCallBack = null;
4737 mSoundPoolListenerThread = new SoundPoolListenerThread();
4738 mSoundPoolListenerThread.start();
4739 int attempts = 3;
4740 while ((mSoundPoolCallBack == null) && (attempts-- > 0)) {
4741 try {
4742 // Wait for mSoundPoolCallBack to be set by the other thread
Glenn Kasten167d1a22013-07-23 16:24:41 -07004743 mSoundEffectsLock.wait(SOUND_EFFECTS_LOAD_TIMEOUT_MS);
Eric Laurent5d3eb44a2013-03-21 15:35:10 -07004744 } catch (InterruptedException e) {
4745 Log.w(TAG, "Interrupted while waiting sound pool listener thread.");
4746 }
4747 }
4748
4749 if (mSoundPoolCallBack == null) {
4750 Log.w(TAG, "onLoadSoundEffects() SoundPool listener or thread creation error");
4751 if (mSoundPoolLooper != null) {
4752 mSoundPoolLooper.quit();
4753 mSoundPoolLooper = null;
4754 }
4755 mSoundPoolListenerThread = null;
4756 mSoundPool.release();
4757 mSoundPool = null;
4758 return false;
4759 }
4760 /*
4761 * poolId table: The value -1 in this table indicates that corresponding
4762 * file (same index in SOUND_EFFECT_FILES[] has not been loaded.
4763 * Once loaded, the value in poolId is the sample ID and the same
4764 * sample can be reused for another effect using the same file.
4765 */
4766 int[] poolId = new int[SOUND_EFFECT_FILES.size()];
4767 for (int fileIdx = 0; fileIdx < SOUND_EFFECT_FILES.size(); fileIdx++) {
4768 poolId[fileIdx] = -1;
4769 }
4770 /*
4771 * Effects whose value in SOUND_EFFECT_FILES_MAP[effect][1] is -1 must be loaded.
4772 * If load succeeds, value in SOUND_EFFECT_FILES_MAP[effect][1] is > 0:
4773 * this indicates we have a valid sample loaded for this effect.
4774 */
4775
4776 int numSamples = 0;
4777 for (int effect = 0; effect < AudioManager.NUM_SOUND_EFFECTS; effect++) {
4778 // Do not load sample if this effect uses the MediaPlayer
4779 if (SOUND_EFFECT_FILES_MAP[effect][1] == 0) {
4780 continue;
4781 }
4782 if (poolId[SOUND_EFFECT_FILES_MAP[effect][0]] == -1) {
Jaekyun Seokc31033f2018-01-15 14:53:17 +09004783 String filePath = getSoundEffectFilePath(effect);
Eric Laurent5d3eb44a2013-03-21 15:35:10 -07004784 int sampleId = mSoundPool.load(filePath, 0);
4785 if (sampleId <= 0) {
4786 Log.w(TAG, "Soundpool could not load file: "+filePath);
4787 } else {
4788 SOUND_EFFECT_FILES_MAP[effect][1] = sampleId;
4789 poolId[SOUND_EFFECT_FILES_MAP[effect][0]] = sampleId;
4790 numSamples++;
4791 }
4792 } else {
4793 SOUND_EFFECT_FILES_MAP[effect][1] =
4794 poolId[SOUND_EFFECT_FILES_MAP[effect][0]];
4795 }
4796 }
4797 // wait for all samples to be loaded
4798 if (numSamples > 0) {
4799 mSoundPoolCallBack.setSamples(poolId);
4800
4801 attempts = 3;
4802 status = 1;
4803 while ((status == 1) && (attempts-- > 0)) {
4804 try {
Glenn Kasten167d1a22013-07-23 16:24:41 -07004805 mSoundEffectsLock.wait(SOUND_EFFECTS_LOAD_TIMEOUT_MS);
Eric Laurent5d3eb44a2013-03-21 15:35:10 -07004806 status = mSoundPoolCallBack.status();
4807 } catch (InterruptedException e) {
4808 Log.w(TAG, "Interrupted while waiting sound pool callback.");
4809 }
4810 }
4811 } else {
4812 status = -1;
4813 }
4814
4815 if (mSoundPoolLooper != null) {
4816 mSoundPoolLooper.quit();
4817 mSoundPoolLooper = null;
4818 }
4819 mSoundPoolListenerThread = null;
4820 if (status != 0) {
4821 Log.w(TAG,
4822 "onLoadSoundEffects(), Error "+status+ " while loading samples");
4823 for (int effect = 0; effect < AudioManager.NUM_SOUND_EFFECTS; effect++) {
4824 if (SOUND_EFFECT_FILES_MAP[effect][1] > 0) {
4825 SOUND_EFFECT_FILES_MAP[effect][1] = -1;
4826 }
4827 }
4828
4829 mSoundPool.release();
4830 mSoundPool = null;
4831 }
4832 }
4833 return (status == 0);
4834 }
4835
4836 /**
4837 * Unloads samples from the sound pool.
4838 * This method can be called to free some memory when
4839 * sound effects are disabled.
4840 */
4841 private void onUnloadSoundEffects() {
4842 synchronized (mSoundEffectsLock) {
4843 if (mSoundPool == null) {
4844 return;
4845 }
4846
4847 int[] poolId = new int[SOUND_EFFECT_FILES.size()];
4848 for (int fileIdx = 0; fileIdx < SOUND_EFFECT_FILES.size(); fileIdx++) {
4849 poolId[fileIdx] = 0;
4850 }
4851
4852 for (int effect = 0; effect < AudioManager.NUM_SOUND_EFFECTS; effect++) {
4853 if (SOUND_EFFECT_FILES_MAP[effect][1] <= 0) {
4854 continue;
4855 }
4856 if (poolId[SOUND_EFFECT_FILES_MAP[effect][0]] == 0) {
4857 mSoundPool.unload(SOUND_EFFECT_FILES_MAP[effect][1]);
4858 SOUND_EFFECT_FILES_MAP[effect][1] = -1;
4859 poolId[SOUND_EFFECT_FILES_MAP[effect][0]] = -1;
4860 }
4861 }
4862 mSoundPool.release();
4863 mSoundPool = null;
4864 }
4865 }
4866
4867 private void onPlaySoundEffect(int effectType, int volume) {
4868 synchronized (mSoundEffectsLock) {
4869
4870 onLoadSoundEffects();
4871
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004872 if (mSoundPool == null) {
4873 return;
4874 }
Eric Laurenta2ef57d2009-09-28 04:46:10 -07004875 float volFloat;
Eric Laurent25101b02011-02-02 09:33:30 -08004876 // use default if volume is not specified by caller
Eric Laurenta2ef57d2009-09-28 04:46:10 -07004877 if (volume < 0) {
Jean-Michel Trivif2b0c112012-07-09 11:59:11 -07004878 volFloat = (float)Math.pow(10, (float)sSoundEffectVolumeDb/20);
Eric Laurenta2ef57d2009-09-28 04:46:10 -07004879 } else {
RoboErik8a2cfc32014-05-16 11:19:38 -07004880 volFloat = volume / 1000.0f;
Eric Laurenta2ef57d2009-09-28 04:46:10 -07004881 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004882
4883 if (SOUND_EFFECT_FILES_MAP[effectType][1] > 0) {
Eric Laurent5d3eb44a2013-03-21 15:35:10 -07004884 mSoundPool.play(SOUND_EFFECT_FILES_MAP[effectType][1],
4885 volFloat, volFloat, 0, 0, 1.0f);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004886 } else {
4887 MediaPlayer mediaPlayer = new MediaPlayer();
Glenn Kasten62b9aec2011-11-07 11:10:16 -08004888 try {
Jaekyun Seokc31033f2018-01-15 14:53:17 +09004889 String filePath = getSoundEffectFilePath(effectType);
Glenn Kasten62b9aec2011-11-07 11:10:16 -08004890 mediaPlayer.setDataSource(filePath);
4891 mediaPlayer.setAudioStreamType(AudioSystem.STREAM_SYSTEM);
4892 mediaPlayer.prepare();
Glenn Kasten068225d2012-02-27 16:21:04 -08004893 mediaPlayer.setVolume(volFloat);
Glenn Kasten62b9aec2011-11-07 11:10:16 -08004894 mediaPlayer.setOnCompletionListener(new OnCompletionListener() {
4895 public void onCompletion(MediaPlayer mp) {
4896 cleanupPlayer(mp);
4897 }
4898 });
4899 mediaPlayer.setOnErrorListener(new OnErrorListener() {
4900 public boolean onError(MediaPlayer mp, int what, int extra) {
4901 cleanupPlayer(mp);
4902 return true;
4903 }
4904 });
4905 mediaPlayer.start();
4906 } catch (IOException ex) {
4907 Log.w(TAG, "MediaPlayer IOException: "+ex);
4908 } catch (IllegalArgumentException ex) {
4909 Log.w(TAG, "MediaPlayer IllegalArgumentException: "+ex);
4910 } catch (IllegalStateException ex) {
4911 Log.w(TAG, "MediaPlayer IllegalStateException: "+ex);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004912 }
4913 }
4914 }
4915 }
4916
4917 private void cleanupPlayer(MediaPlayer mp) {
4918 if (mp != null) {
4919 try {
4920 mp.stop();
4921 mp.release();
4922 } catch (IllegalStateException ex) {
4923 Log.w(TAG, "MediaPlayer IllegalStateException: "+ex);
4924 }
4925 }
4926 }
4927
Eric Laurent05274f32012-11-29 12:48:18 -08004928 private void onPersistSafeVolumeState(int state) {
4929 Settings.Global.putInt(mContentResolver,
4930 Settings.Global.AUDIO_SAFE_VOLUME_STATE,
4931 state);
4932 }
4933
Jean-Michel Trivi7ed71472018-02-02 16:52:09 -08004934 private void onNotifyVolumeEvent(@NonNull IAudioPolicyCallback apc,
4935 @AudioManager.VolumeAdjustment int direction) {
4936 try {
4937 apc.notifyVolumeAdjust(direction);
4938 } catch(Exception e) {
4939 // nothing we can do about this. Do not log error, too much potential for spam
4940 }
4941 }
4942
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004943 @Override
4944 public void handleMessage(Message msg) {
Eric Laurentafbb0472011-12-15 09:04:23 -08004945 switch (msg.what) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004946
Eric Laurent9bc8358d2011-11-18 16:43:31 -08004947 case MSG_SET_DEVICE_VOLUME:
4948 setDeviceVolume((VolumeStreamState) msg.obj, msg.arg1);
4949 break;
4950
4951 case MSG_SET_ALL_VOLUMES:
4952 setAllVolumes((VolumeStreamState) msg.obj);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004953 break;
4954
4955 case MSG_PERSIST_VOLUME:
Eric Laurent42b041e2013-03-29 11:36:03 -07004956 persistVolume((VolumeStreamState) msg.obj, msg.arg1);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004957 break;
4958
4959 case MSG_PERSIST_RINGER_MODE:
Glenn Kastenba195eb2011-12-13 09:30:40 -08004960 // note that the value persisted is the current ringer mode, not the
4961 // value of ringer mode as of the time the request was made to persist
John Spurlock661f2cf2014-11-17 10:29:10 -05004962 persistRingerMode(getRingerModeInternal());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004963 break;
4964
Andy Hunged0ea402015-10-30 14:11:46 -07004965 case MSG_AUDIO_SERVER_DIED:
4966 onAudioServerDied();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004967 break;
4968
Eric Laurent1d3cdce2018-01-20 10:31:21 -08004969 case MSG_DISPATCH_AUDIO_SERVER_STATE:
4970 onDispatchAudioServerStateChange(msg.arg1 == 1);
4971 break;
4972
Eric Laurent5d3eb44a2013-03-21 15:35:10 -07004973 case MSG_UNLOAD_SOUND_EFFECTS:
4974 onUnloadSoundEffects();
4975 break;
4976
Eric Laurent117b7bb2011-01-16 17:07:27 -08004977 case MSG_LOAD_SOUND_EFFECTS:
Eric Laurent5d3eb44a2013-03-21 15:35:10 -07004978 //FIXME: onLoadSoundEffects() should be executed in a separate thread as it
4979 // can take several dozens of milliseconds to complete
4980 boolean loaded = onLoadSoundEffects();
4981 if (msg.obj != null) {
4982 LoadSoundEffectReply reply = (LoadSoundEffectReply)msg.obj;
4983 synchronized (reply) {
4984 reply.mStatus = loaded ? 0 : -1;
4985 reply.notify();
4986 }
4987 }
Eric Laurent117b7bb2011-01-16 17:07:27 -08004988 break;
4989
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004990 case MSG_PLAY_SOUND_EFFECT:
Eric Laurent5d3eb44a2013-03-21 15:35:10 -07004991 onPlaySoundEffect(msg.arg1, msg.arg2);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004992 break;
Jean-Michel Trivi4c637b92010-04-12 18:44:10 -07004993
Eric Laurentfa640152011-03-12 15:59:51 -08004994 case MSG_SET_FORCE_USE:
Jean-Michel Trivi58850372018-09-14 16:01:28 -07004995 {
4996 final String eventSource = (String) msg.obj;
4997 final int useCase = msg.arg1;
4998 final int config = msg.arg2;
4999 if (useCase == AudioSystem.FOR_MEDIA) {
5000 Log.wtf(TAG, "Invalid force use FOR_MEDIA in AudioService from "
5001 + eventSource);
5002 break;
Paul McLean10804eb2015-01-28 11:16:35 -08005003 }
Jean-Michel Trivi58850372018-09-14 16:01:28 -07005004 sForceUseLogger.log(
5005 new AudioServiceEvents.ForceUseEvent(useCase, config, eventSource));
5006 AudioSystem.setForceUse(useCase, config);
5007 }
Aniket Kumar Lataa8439e22019-01-11 03:59:00 -08005008 break;
5009
Jean-Michel Trivi92ed7bf2017-06-26 19:32:38 -07005010 case MSG_DISABLE_AUDIO_FOR_UID:
5011 mPlaybackMonitor.disableAudioForUid( msg.arg1 == 1 /* disable */,
5012 msg.arg2 /* uid */);
5013 mAudioEventWakeLock.release();
5014 break;
5015
Eric Laurentc34dcc12012-09-10 13:51:52 -07005016 case MSG_CHECK_MUSIC_ACTIVE:
John Spurlock90874332015-03-10 16:00:54 -04005017 onCheckMusicActive((String) msg.obj);
Eric Laurentc34dcc12012-09-10 13:51:52 -07005018 break;
Eric Laurent5bfaeae2012-09-21 18:44:48 -07005019
Eric Laurentd640bd32012-09-28 18:01:48 -07005020 case MSG_CONFIGURE_SAFE_MEDIA_VOLUME_FORCED:
5021 case MSG_CONFIGURE_SAFE_MEDIA_VOLUME:
John Spurlock90874332015-03-10 16:00:54 -04005022 onConfigureSafeVolume((msg.what == MSG_CONFIGURE_SAFE_MEDIA_VOLUME_FORCED),
5023 (String) msg.obj);
Eric Laurentd640bd32012-09-28 18:01:48 -07005024 break;
Eric Laurent05274f32012-11-29 12:48:18 -08005025 case MSG_PERSIST_SAFE_VOLUME_STATE:
5026 onPersistSafeVolumeState(msg.arg1);
5027 break;
Jean-Michel Trivia578c482012-12-28 11:19:49 -08005028
Eric Laurent4a5eeb92014-05-06 10:49:04 -07005029 case MSG_SYSTEM_READY:
5030 onSystemReady();
5031 break;
John Spurlockaa5ee4d2014-07-25 13:05:12 -04005032
Eric Laurent0867bed2015-05-20 14:49:08 -07005033 case MSG_INDICATE_SYSTEM_READY:
5034 onIndicateSystemReady();
5035 break;
5036
Jean-Michel Trivi1ab43f62017-04-27 15:37:34 -07005037 case MSG_ACCESSORY_PLUG_MEDIA_UNMUTE:
5038 onAccessoryPlugMediaUnmute(msg.arg1);
5039 break;
5040
John Spurlockaa5ee4d2014-07-25 13:05:12 -04005041 case MSG_PERSIST_MUSIC_ACTIVE_MS:
5042 final int musicActiveMs = msg.arg1;
5043 Settings.Secure.putIntForUser(mContentResolver,
5044 Settings.Secure.UNSAFE_VOLUME_MUSIC_ACTIVE_MS, musicActiveMs,
5045 UserHandle.USER_CURRENT);
5046 break;
Eric Laurentc0232482016-03-15 18:19:23 -07005047
RoboErik5452e252015-02-06 15:33:53 -08005048 case MSG_UNMUTE_STREAM:
5049 onUnmuteStream(msg.arg1, msg.arg2);
5050 break;
Eric Laurentc0232482016-03-15 18:19:23 -07005051
Jean-Michel Trivi5a561092015-04-23 18:48:08 -07005052 case MSG_DYN_POLICY_MIX_STATE_UPDATE:
5053 onDynPolicyMixStateUpdate((String) msg.obj, msg.arg1);
5054 break;
Jean-Michel Trivi7ed71472018-02-02 16:52:09 -08005055
5056 case MSG_NOTIFY_VOL_EVENT:
5057 onNotifyVolumeEvent((IAudioPolicyCallback) msg.obj, msg.arg1);
5058 break;
jiabin39940752018-04-02 18:18:45 -07005059
5060 case MSG_ENABLE_SURROUND_FORMATS:
5061 onEnableSurroundFormats((ArrayList<Integer>) msg.obj);
5062 break;
Jean-Michel Trivica49d312019-02-14 15:55:39 -08005063
5064 case MSG_UPDATE_RINGER_MODE:
5065 onUpdateRingerModeServiceInt();
5066 break;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005067 }
5068 }
5069 }
5070
Jason Parekhb1096152009-03-24 17:48:25 -07005071 private class SettingsObserver extends ContentObserver {
Eric Laurenta553c252009-07-17 12:17:14 -07005072
Jason Parekhb1096152009-03-24 17:48:25 -07005073 SettingsObserver() {
5074 super(new Handler());
Beverlyd6964762018-02-16 14:07:03 -05005075 mContentResolver.registerContentObserver(Settings.Global.getUriFor(
5076 Settings.Global.ZEN_MODE), false, this);
5077 mContentResolver.registerContentObserver(Settings.Global.getUriFor(
5078 Settings.Global.ZEN_MODE_CONFIG_ETAG), false, this);
Jason Parekhb1096152009-03-24 17:48:25 -07005079 mContentResolver.registerContentObserver(Settings.System.getUriFor(
5080 Settings.System.MODE_RINGER_STREAMS_AFFECTED), false, this);
Eric Laurent7ee1e4f2012-10-26 18:11:21 -07005081 mContentResolver.registerContentObserver(Settings.Global.getUriFor(
5082 Settings.Global.DOCK_AUDIO_MEDIA_ENABLED), false, this);
Andy Hung7b98e9a2016-02-25 18:34:50 -08005083 mContentResolver.registerContentObserver(Settings.System.getUriFor(
5084 Settings.System.MASTER_MONO), false, this);
Edward Savage-Jones35c292f2017-01-13 09:04:34 +01005085 mContentResolver.registerContentObserver(Settings.System.getUriFor(
5086 Settings.System.MASTER_BALANCE), false, this);
Phil Burked43bf52016-03-01 17:01:35 -08005087
5088 mEncodedSurroundMode = Settings.Global.getInt(
5089 mContentResolver, Settings.Global.ENCODED_SURROUND_OUTPUT,
5090 Settings.Global.ENCODED_SURROUND_OUTPUT_AUTO);
5091 mContentResolver.registerContentObserver(Settings.Global.getUriFor(
5092 Settings.Global.ENCODED_SURROUND_OUTPUT), false, this);
jiabin39940752018-04-02 18:18:45 -07005093
5094 mEnabledSurroundFormats = Settings.Global.getString(
5095 mContentResolver, Settings.Global.ENCODED_SURROUND_OUTPUT_ENABLED_FORMATS);
5096 mContentResolver.registerContentObserver(Settings.Global.getUriFor(
5097 Settings.Global.ENCODED_SURROUND_OUTPUT_ENABLED_FORMATS), false, this);
Eric Laurent1c9c1d52018-10-17 10:06:46 -07005098
5099 mContentResolver.registerContentObserver(Settings.Secure.getUriFor(
5100 Settings.Secure.VOICE_INTERACTION_SERVICE), false, this);
Jason Parekhb1096152009-03-24 17:48:25 -07005101 }
5102
5103 @Override
5104 public void onChange(boolean selfChange) {
5105 super.onChange(selfChange);
Glenn Kastenba195eb2011-12-13 09:30:40 -08005106 // FIXME This synchronized is not necessary if mSettingsLock only protects mRingerMode.
Beverlyd6964762018-02-16 14:07:03 -05005107 // However there appear to be some missing locks around mRingerAndZenModeMutedStreams
Glenn Kastenba195eb2011-12-13 09:30:40 -08005108 // and mRingerModeAffectedStreams, so will leave this synchronized for now.
Beverlyd6964762018-02-16 14:07:03 -05005109 // mRingerAndZenModeMutedStreams and mMuteAffectedStreams are safe (only accessed once).
Eric Laurenta553c252009-07-17 12:17:14 -07005110 synchronized (mSettingsLock) {
Beverlyd6964762018-02-16 14:07:03 -05005111 if (updateRingerAndZenModeAffectedStreams()) {
Eric Laurenta553c252009-07-17 12:17:14 -07005112 /*
5113 * Ensure all stream types that should be affected by ringer mode
5114 * are in the proper state.
5115 */
John Spurlock661f2cf2014-11-17 10:29:10 -05005116 setRingerModeInt(getRingerModeInternal(), false);
Eric Laurenta553c252009-07-17 12:17:14 -07005117 }
Eric Laurent7ee1e4f2012-10-26 18:11:21 -07005118 readDockAudioSettings(mContentResolver);
Andy Hung7b98e9a2016-02-25 18:34:50 -08005119 updateMasterMono(mContentResolver);
Edward Savage-Jones35c292f2017-01-13 09:04:34 +01005120 updateMasterBalance(mContentResolver);
Phil Burked43bf52016-03-01 17:01:35 -08005121 updateEncodedSurroundOutput();
jiabin39940752018-04-02 18:18:45 -07005122 sendEnabledSurroundFormats(mContentResolver, mSurroundModeChanged);
Eric Laurent1c9c1d52018-10-17 10:06:46 -07005123 updateAssistantUId(false);
Phil Burked43bf52016-03-01 17:01:35 -08005124 }
5125 }
5126
5127 private void updateEncodedSurroundOutput() {
5128 int newSurroundMode = Settings.Global.getInt(
5129 mContentResolver, Settings.Global.ENCODED_SURROUND_OUTPUT,
5130 Settings.Global.ENCODED_SURROUND_OUTPUT_AUTO);
5131 // Did it change?
5132 if (mEncodedSurroundMode != newSurroundMode) {
5133 // Send to AudioPolicyManager
Jean-Michel Trivi011f39e2017-08-19 18:08:06 -07005134 sendEncodedSurroundMode(newSurroundMode, "SettingsObserver");
Jean-Michel Trivi58850372018-09-14 16:01:28 -07005135 mDeviceBroker.toggleHdmiIfConnected_Async();
Phil Burked43bf52016-03-01 17:01:35 -08005136 mEncodedSurroundMode = newSurroundMode;
jiabin39940752018-04-02 18:18:45 -07005137 mSurroundModeChanged = true;
5138 } else {
5139 mSurroundModeChanged = false;
Eric Laurenta553c252009-07-17 12:17:14 -07005140 }
Jason Parekhb1096152009-03-24 17:48:25 -07005141 }
Jason Parekhb1096152009-03-24 17:48:25 -07005142 }
Eric Laurenta553c252009-07-17 12:17:14 -07005143
John Du5a0cf7a2013-07-19 11:30:34 -07005144 public void avrcpSupportsAbsoluteVolume(String address, boolean support) {
5145 // address is not used for now, but may be used when multiple a2dp devices are supported
Jean-Michel Trivi58850372018-09-14 16:01:28 -07005146 mDeviceBroker.setAvrcpAbsoluteVolumeSupported(support);
5147 sendMsg(mAudioHandler, MSG_SET_DEVICE_VOLUME, SENDMSG_QUEUE,
Eric Laurent3e6fb632018-05-21 09:28:46 -07005148 AudioSystem.DEVICE_OUT_BLUETOOTH_A2DP, 0,
5149 mStreamStates[AudioSystem.STREAM_MUSIC], 0);
Eric Laurentb1fbaac2012-05-29 09:24:28 -07005150 }
5151
Jean-Michel Trivi7db2d8f2018-03-06 10:30:59 -08005152 /**
5153 * @return true if there is currently a registered dynamic mixing policy that affects media
5154 */
Jean-Michel Trivi58850372018-09-14 16:01:28 -07005155 /*package*/ boolean hasMediaDynamicPolicy() {
Jean-Michel Trivi7db2d8f2018-03-06 10:30:59 -08005156 synchronized (mAudioPolicies) {
5157 if (mAudioPolicies.isEmpty()) {
5158 return false;
5159 }
5160 final Collection<AudioPolicyProxy> appColl = mAudioPolicies.values();
5161 for (AudioPolicyProxy app : appColl) {
5162 if (app.hasMixAffectingUsage(AudioAttributes.USAGE_MEDIA)) {
5163 return true;
5164 }
5165 }
5166 return false;
5167 }
5168 }
5169
Jean-Michel Trivi58850372018-09-14 16:01:28 -07005170 /*package*/ void checkMusicActive(int deviceType, String caller) {
5171 if ((deviceType & mSafeMediaVolumeDevices) != 0) {
5172 sendMsg(mAudioHandler,
5173 MSG_CHECK_MUSIC_ACTIVE,
5174 SENDMSG_REPLACE,
5175 0,
5176 0,
5177 caller,
5178 MUSIC_ACTIVE_POLL_PERIOD_MS);
Dianne Hackborn632ca412012-06-14 19:34:10 -07005179 }
Eric Laurenteab40d12017-06-09 12:45:21 -07005180 }
5181
Eric Laurenta553c252009-07-17 12:17:14 -07005182 /**
5183 * Receiver for misc intent broadcasts the Phone app cares about.
5184 */
5185 private class AudioServiceBroadcastReceiver extends BroadcastReceiver {
5186 @Override
5187 public void onReceive(Context context, Intent intent) {
Jean-Michel Trivi58850372018-09-14 16:01:28 -07005188 final String action = intent.getAction();
Eric Laurentae4506e2014-05-29 16:04:32 -07005189 int outDevice;
5190 int inDevice;
Eric Laurent59f48272012-04-05 19:42:21 -07005191 int state;
Eric Laurenta553c252009-07-17 12:17:14 -07005192
Jean-Michel Trivi758559e2010-03-09 09:26:08 -08005193 if (action.equals(Intent.ACTION_DOCK_EVENT)) {
5194 int dockState = intent.getIntExtra(Intent.EXTRA_DOCK_STATE,
5195 Intent.EXTRA_DOCK_STATE_UNDOCKED);
5196 int config;
5197 switch (dockState) {
5198 case Intent.EXTRA_DOCK_STATE_DESK:
5199 config = AudioSystem.FORCE_BT_DESK_DOCK;
5200 break;
5201 case Intent.EXTRA_DOCK_STATE_CAR:
5202 config = AudioSystem.FORCE_BT_CAR_DOCK;
5203 break;
Praveen Bharathi21e941b2010-10-06 15:23:14 -05005204 case Intent.EXTRA_DOCK_STATE_LE_DESK:
Eric Laurent08ed1b92012-11-05 14:54:12 -08005205 config = AudioSystem.FORCE_ANALOG_DOCK;
Praveen Bharathi21e941b2010-10-06 15:23:14 -05005206 break;
5207 case Intent.EXTRA_DOCK_STATE_HE_DESK:
5208 config = AudioSystem.FORCE_DIGITAL_DOCK;
5209 break;
Jean-Michel Trivi758559e2010-03-09 09:26:08 -08005210 case Intent.EXTRA_DOCK_STATE_UNDOCKED:
5211 default:
5212 config = AudioSystem.FORCE_NONE;
5213 }
Eric Laurent08ed1b92012-11-05 14:54:12 -08005214 // Low end docks have a menu to enable or disable audio
5215 // (see mDockAudioMediaEnabled)
Jean-Michel Trivi58850372018-09-14 16:01:28 -07005216 if (!((dockState == Intent.EXTRA_DOCK_STATE_LE_DESK)
5217 || ((dockState == Intent.EXTRA_DOCK_STATE_UNDOCKED)
5218 && (mDockState == Intent.EXTRA_DOCK_STATE_LE_DESK)))) {
5219 mDeviceBroker.setForceUse_Async(AudioSystem.FOR_DOCK, config,
5220 "ACTION_DOCK_EVENT intent");
Eric Laurent08ed1b92012-11-05 14:54:12 -08005221 }
5222 mDockState = dockState;
Jean-Michel Trivi58850372018-09-14 16:01:28 -07005223 } else if (action.equals(BluetoothHeadset.ACTION_ACTIVE_DEVICE_CHANGED)
5224 || action.equals(BluetoothHeadset.ACTION_AUDIO_STATE_CHANGED)) {
5225 mDeviceBroker.receiveBtEvent(intent);
Eric Laurent950e8cb2011-10-13 08:57:54 -07005226 } else if (action.equals(Intent.ACTION_SCREEN_ON)) {
Jon Eklund318f0fe2014-01-23 17:53:48 -06005227 if (mMonitorRotation) {
Jean-Michel Trivi24806db2015-10-01 15:00:59 -07005228 RotationHelper.enable();
Jon Eklund318f0fe2014-01-23 17:53:48 -06005229 }
Eric Laurent950e8cb2011-10-13 08:57:54 -07005230 AudioSystem.setParameters("screen_state=on");
5231 } else if (action.equals(Intent.ACTION_SCREEN_OFF)) {
Jon Eklund318f0fe2014-01-23 17:53:48 -06005232 if (mMonitorRotation) {
5233 //reduce wakeups (save current) by only listening when display is on
Jean-Michel Trivi24806db2015-10-01 15:00:59 -07005234 RotationHelper.disable();
Jon Eklund318f0fe2014-01-23 17:53:48 -06005235 }
Eric Laurent950e8cb2011-10-13 08:57:54 -07005236 AudioSystem.setParameters("screen_state=off");
Dianne Hackborn961cae92013-03-20 14:59:43 -07005237 } else if (action.equals(Intent.ACTION_CONFIGURATION_CHANGED)) {
Jean-Michel Trivif26f0172012-04-25 16:23:20 -07005238 handleConfigurationChanged(context);
Eric Laurentbc0fab1f2012-09-19 11:24:41 -07005239 } else if (action.equals(Intent.ACTION_USER_SWITCHED)) {
Yasuhiro Matsuda4ced7192015-07-10 22:08:44 +09005240 if (mUserSwitchedReceived) {
5241 // attempt to stop music playback for background user except on first user
5242 // switch (i.e. first boot)
Jean-Michel Trivib9465152019-02-06 15:20:19 -08005243 mDeviceBroker.postBroadcastBecomingNoisy();
Yasuhiro Matsuda4ced7192015-07-10 22:08:44 +09005244 }
5245 mUserSwitchedReceived = true;
Jean-Michel Trivif4a8eb22012-10-29 12:42:55 -07005246 // the current audio focus owner is no longer valid
Jean-Michel Trivifa9a6982013-06-27 16:22:58 -07005247 mMediaFocusControl.discardAudioFocusOwner();
Jean-Michel Trivif4a8eb22012-10-29 12:42:55 -07005248
Eric Laurent5bfaeae2012-09-21 18:44:48 -07005249 // load volume settings for new user
Eric Laurentbc0fab1f2012-09-19 11:24:41 -07005250 readAudioSettings(true /*userSwitch*/);
5251 // preserve STREAM_MUSIC volume from one user to the next.
5252 sendMsg(mAudioHandler,
5253 MSG_SET_ALL_VOLUMES,
5254 SENDMSG_QUEUE,
5255 0,
5256 0,
5257 mStreamStates[AudioSystem.STREAM_MUSIC], 0);
Fyodor Kupolovb5013302015-04-17 17:59:14 -07005258 } else if (action.equals(Intent.ACTION_USER_BACKGROUND)) {
5259 // Disable audio recording for the background user/profile
5260 int userId = intent.getIntExtra(Intent.EXTRA_USER_HANDLE, -1);
5261 if (userId >= 0) {
5262 // TODO Kill recording streams instead of killing processes holding permission
5263 UserInfo userInfo = UserManagerService.getInstance().getUserInfo(userId);
5264 killBackgroundUserProcessesWithRecordAudioPermission(userInfo);
5265 }
Makoto Onukiac65e1e2015-11-20 15:33:17 -08005266 UserManagerService.getInstance().setUserRestriction(
Fyodor Kupolovb5013302015-04-17 17:59:14 -07005267 UserManager.DISALLOW_RECORD_AUDIO, true, userId);
5268 } else if (action.equals(Intent.ACTION_USER_FOREGROUND)) {
5269 // Enable audio recording for foreground user/profile
5270 int userId = intent.getIntExtra(Intent.EXTRA_USER_HANDLE, -1);
Makoto Onukiac65e1e2015-11-20 15:33:17 -08005271 UserManagerService.getInstance().setUserRestriction(
Fyodor Kupolovb5013302015-04-17 17:59:14 -07005272 UserManager.DISALLOW_RECORD_AUDIO, false, userId);
Eric Laurentb70b78a2016-01-13 19:16:04 -08005273 } else if (action.equals(BluetoothAdapter.ACTION_STATE_CHANGED)) {
5274 state = intent.getIntExtra(BluetoothAdapter.EXTRA_STATE, -1);
5275 if (state == BluetoothAdapter.STATE_OFF ||
5276 state == BluetoothAdapter.STATE_TURNING_OFF) {
Jean-Michel Trivi58850372018-09-14 16:01:28 -07005277 mDeviceBroker.disconnectAllBluetoothProfiles();
Eric Laurentb70b78a2016-01-13 19:16:04 -08005278 }
Marco Nelissenfb6df0b2017-02-15 15:25:24 -08005279 } else if (action.equals(AudioEffect.ACTION_OPEN_AUDIO_EFFECT_CONTROL_SESSION) ||
5280 action.equals(AudioEffect.ACTION_CLOSE_AUDIO_EFFECT_CONTROL_SESSION)) {
5281 handleAudioEffectBroadcast(context, intent);
Jean-Michel Trivib2251822019-02-06 07:32:06 -08005282 } else if (action.equals(Intent.ACTION_PACKAGES_SUSPENDED)) {
5283 final int[] suspendedUids = intent.getIntArrayExtra(Intent.EXTRA_CHANGED_UID_LIST);
5284 final String[] suspendedPackages =
5285 intent.getStringArrayExtra(Intent.EXTRA_CHANGED_PACKAGE_LIST);
5286 if (suspendedPackages == null || suspendedUids == null
5287 || suspendedPackages.length != suspendedUids.length) {
5288 return;
5289 }
5290 for (int i = 0; i < suspendedUids.length; i++) {
5291 if (!TextUtils.isEmpty(suspendedPackages[i])) {
5292 mMediaFocusControl.noFocusForSuspendedApp(
5293 suspendedPackages[i], suspendedUids[i]);
5294 }
5295 }
Eric Laurenta553c252009-07-17 12:17:14 -07005296 }
5297 }
Paul McLeanc837a452014-04-09 09:04:43 -07005298 } // end class AudioServiceBroadcastReceiver
Jean-Michel Trivid5176cf2010-01-28 11:56:42 -08005299
Makoto Onukid45a4a22015-11-02 17:17:38 -08005300 private class AudioServiceUserRestrictionsListener implements UserRestrictionsListener {
5301
5302 @Override
5303 public void onUserRestrictionsChanged(int userId, Bundle newRestrictions,
5304 Bundle prevRestrictions) {
5305 // Update mic mute state.
5306 {
5307 final boolean wasRestricted =
5308 prevRestrictions.getBoolean(UserManager.DISALLOW_UNMUTE_MICROPHONE);
5309 final boolean isRestricted =
5310 newRestrictions.getBoolean(UserManager.DISALLOW_UNMUTE_MICROPHONE);
5311 if (wasRestricted != isRestricted) {
5312 setMicrophoneMuteNoCallerCheck(isRestricted, userId);
5313 }
5314 }
5315
5316 // Update speaker mute state.
5317 {
5318 final boolean wasRestricted =
Tony Makc1205112016-07-22 16:02:59 +01005319 prevRestrictions.getBoolean(UserManager.DISALLOW_ADJUST_VOLUME)
Esteban Talavera492b4722017-02-13 14:59:45 +00005320 || prevRestrictions.getBoolean(UserManager.DISALLOW_UNMUTE_DEVICE);
Makoto Onukid45a4a22015-11-02 17:17:38 -08005321 final boolean isRestricted =
Tony Makc1205112016-07-22 16:02:59 +01005322 newRestrictions.getBoolean(UserManager.DISALLOW_ADJUST_VOLUME)
Esteban Talavera492b4722017-02-13 14:59:45 +00005323 || newRestrictions.getBoolean(UserManager.DISALLOW_UNMUTE_DEVICE);
Makoto Onukid45a4a22015-11-02 17:17:38 -08005324 if (wasRestricted != isRestricted) {
5325 setMasterMuteInternalNoCallerCheck(isRestricted, /* flags =*/ 0, userId);
5326 }
5327 }
5328 }
5329 } // end class AudioServiceUserRestrictionsListener
5330
Marco Nelissenfb6df0b2017-02-15 15:25:24 -08005331 private void handleAudioEffectBroadcast(Context context, Intent intent) {
5332 String target = intent.getPackage();
5333 if (target != null) {
5334 Log.w(TAG, "effect broadcast already targeted to " + target);
5335 return;
5336 }
5337 intent.addFlags(Intent.FLAG_INCLUDE_STOPPED_PACKAGES);
5338 // TODO this should target a user-selected panel
5339 List<ResolveInfo> ril = context.getPackageManager().queryBroadcastReceivers(
5340 intent, 0 /* flags */);
5341 if (ril != null && ril.size() != 0) {
5342 ResolveInfo ri = ril.get(0);
5343 if (ri != null && ri.activityInfo != null && ri.activityInfo.packageName != null) {
5344 intent.setPackage(ri.activityInfo.packageName);
5345 context.sendBroadcastAsUser(intent, UserHandle.ALL);
5346 return;
5347 }
5348 }
5349 Log.w(TAG, "couldn't find receiver package for effect intent");
5350 }
5351
Fyodor Kupolovb5013302015-04-17 17:59:14 -07005352 private void killBackgroundUserProcessesWithRecordAudioPermission(UserInfo oldUser) {
5353 PackageManager pm = mContext.getPackageManager();
5354 // Find the home activity of the user. It should not be killed to avoid expensive restart,
5355 // when the user switches back. For managed profiles, we should kill all recording apps
5356 ComponentName homeActivityName = null;
5357 if (!oldUser.isManagedProfile()) {
Wale Ogunwale6767eae2018-05-03 15:52:51 -07005358 homeActivityName = LocalServices.getService(
5359 ActivityTaskManagerInternal.class).getHomeActivityForUser(oldUser.id);
Fyodor Kupolovb5013302015-04-17 17:59:14 -07005360 }
5361 final String[] permissions = { Manifest.permission.RECORD_AUDIO };
5362 List<PackageInfo> packages;
5363 try {
5364 packages = AppGlobals.getPackageManager()
5365 .getPackagesHoldingPermissions(permissions, 0, oldUser.id).getList();
5366 } catch (RemoteException e) {
5367 throw new AndroidRuntimeException(e);
5368 }
5369 for (int j = packages.size() - 1; j >= 0; j--) {
5370 PackageInfo pkg = packages.get(j);
Fyodor Kupolovbcb6c1e2015-05-11 12:05:15 -07005371 // Skip system processes
5372 if (UserHandle.getAppId(pkg.applicationInfo.uid) < FIRST_APPLICATION_UID) {
5373 continue;
5374 }
Amith Yamasanic1cbaab2015-07-21 11:46:14 -07005375 // Skip packages that have permission to interact across users
5376 if (pm.checkPermission(Manifest.permission.INTERACT_ACROSS_USERS, pkg.packageName)
5377 == PackageManager.PERMISSION_GRANTED) {
5378 continue;
5379 }
Fyodor Kupolovb5013302015-04-17 17:59:14 -07005380 if (homeActivityName != null
5381 && pkg.packageName.equals(homeActivityName.getPackageName())
5382 && pkg.applicationInfo.isSystemApp()) {
5383 continue;
5384 }
5385 try {
Svetoslavaa41add2015-08-06 15:03:55 -07005386 final int uid = pkg.applicationInfo.uid;
Sudheer Shankadc589ac2016-11-10 15:30:17 -08005387 ActivityManager.getService().killUid(UserHandle.getAppId(uid),
Svetoslavaa41add2015-08-06 15:03:55 -07005388 UserHandle.getUserId(uid),
Fyodor Kupolovb5013302015-04-17 17:59:14 -07005389 "killBackgroundUserProcessesWithAudioRecordPermission");
5390 } catch (RemoteException e) {
5391 Log.w(TAG, "Error calling killUid", e);
5392 }
5393 }
5394 }
5395
Jean-Michel Trivi3114ce32012-06-11 15:03:52 -07005396
Jean-Michel Trivifa9a6982013-06-27 16:22:58 -07005397 //==========================================================================================
5398 // Audio Focus
5399 //==========================================================================================
Jean-Michel Trivi9228af62018-01-05 17:06:17 -08005400 /**
5401 * Returns whether a focus request is eligible to force ducking.
5402 * Will return true if:
5403 * - the AudioAttributes have a usage of USAGE_ASSISTANCE_ACCESSIBILITY,
5404 * - the focus request is AUDIOFOCUS_GAIN_TRANSIENT_MAY_DUCK,
5405 * - the associated Bundle has KEY_ACCESSIBILITY_FORCE_FOCUS_DUCKING set to true,
5406 * - the uid of the requester is a known accessibility service or root.
5407 * @param aa AudioAttributes of the focus request
5408 * @param uid uid of the focus requester
5409 * @return true if ducking is to be forced
5410 */
5411 private boolean forceFocusDuckingForAccessibility(@Nullable AudioAttributes aa,
5412 int request, int uid) {
5413 if (aa == null || aa.getUsage() != AudioAttributes.USAGE_ASSISTANCE_ACCESSIBILITY
5414 || request != AudioManager.AUDIOFOCUS_GAIN_TRANSIENT_MAY_DUCK) {
5415 return false;
5416 }
5417 final Bundle extraInfo = aa.getBundle();
5418 if (extraInfo == null ||
5419 !extraInfo.getBoolean(AudioFocusRequest.KEY_ACCESSIBILITY_FORCE_FOCUS_DUCKING)) {
5420 return false;
5421 }
5422 if (uid == 0) {
5423 return true;
5424 }
5425 synchronized (mAccessibilityServiceUidsLock) {
5426 if (mAccessibilityServiceUids != null) {
5427 int callingUid = Binder.getCallingUid();
5428 for (int i = 0; i < mAccessibilityServiceUids.length; i++) {
5429 if (mAccessibilityServiceUids[i] == callingUid) {
5430 return true;
5431 }
5432 }
5433 }
5434 }
5435 return false;
5436 }
5437
Jean-Michel Trivifd6ad742014-11-10 14:38:30 -08005438 public int requestAudioFocus(AudioAttributes aa, int durationHint, IBinder cb,
Jean-Michel Trivi958876f2014-11-16 15:40:22 -08005439 IAudioFocusDispatcher fd, String clientId, String callingPackageName, int flags,
Jean-Michel Trivi461922f2017-04-25 15:23:17 -07005440 IAudioPolicyCallback pcb, int sdk) {
Jean-Michel Trivi958876f2014-11-16 15:40:22 -08005441 // permission checks
5442 if ((flags & AudioManager.AUDIOFOCUS_FLAG_LOCK) == AudioManager.AUDIOFOCUS_FLAG_LOCK) {
John Spurlock61560172015-02-06 19:46:04 -05005443 if (AudioSystem.IN_VOICE_COMM_FOCUS_ID.equals(clientId)) {
Jean-Michel Trivi958876f2014-11-16 15:40:22 -08005444 if (PackageManager.PERMISSION_GRANTED != mContext.checkCallingOrSelfPermission(
5445 android.Manifest.permission.MODIFY_PHONE_STATE)) {
5446 Log.e(TAG, "Invalid permission to (un)lock audio focus", new Exception());
5447 return AudioManager.AUDIOFOCUS_REQUEST_FAILED;
5448 }
5449 } else {
5450 // only a registered audio policy can be used to lock focus
5451 synchronized (mAudioPolicies) {
Jean-Michel Trivi0212be52014-11-24 14:43:10 -08005452 if (!mAudioPolicies.containsKey(pcb.asBinder())) {
5453 Log.e(TAG, "Invalid unregistered AudioPolicy to (un)lock audio focus");
Jean-Michel Trivi958876f2014-11-16 15:40:22 -08005454 return AudioManager.AUDIOFOCUS_REQUEST_FAILED;
5455 }
5456 }
5457 }
5458 }
5459
Jean-Michel Trivib2251822019-02-06 07:32:06 -08005460 if (callingPackageName == null || clientId == null || aa == null) {
5461 Log.e(TAG, "Invalid null parameter to request audio focus");
5462 return AudioManager.AUDIOFOCUS_REQUEST_FAILED;
5463 }
5464
Jean-Michel Trivifd6ad742014-11-10 14:38:30 -08005465 return mMediaFocusControl.requestAudioFocus(aa, durationHint, cb, fd,
Jean-Michel Trivi9228af62018-01-05 17:06:17 -08005466 clientId, callingPackageName, flags, sdk,
5467 forceFocusDuckingForAccessibility(aa, durationHint, Binder.getCallingUid()));
Jean-Michel Trivifa9a6982013-06-27 16:22:58 -07005468 }
5469
Jean-Michel Trivi126cf032017-04-02 23:19:02 -07005470 public int abandonAudioFocus(IAudioFocusDispatcher fd, String clientId, AudioAttributes aa,
5471 String callingPackageName) {
5472 return mMediaFocusControl.abandonAudioFocus(fd, clientId, aa, callingPackageName);
Jean-Michel Trivifa9a6982013-06-27 16:22:58 -07005473 }
5474
5475 public void unregisterAudioFocusClient(String clientId) {
5476 mMediaFocusControl.unregisterAudioFocusClient(clientId);
Jean-Michel Trivi3114ce32012-06-11 15:03:52 -07005477 }
5478
Jean-Michel Trivi23805662013-07-31 14:19:18 -07005479 public int getCurrentAudioFocus() {
5480 return mMediaFocusControl.getCurrentAudioFocus();
5481 }
5482
Jean-Michel Trivi99489cc2017-01-25 19:08:49 -08005483 public int getFocusRampTimeMs(int focusGain, AudioAttributes attr) {
5484 return mMediaFocusControl.getFocusRampTimeMs(focusGain, attr);
5485 }
5486
Jean-Michel Trivi126cf032017-04-02 23:19:02 -07005487 //==========================================================================================
John Spurlock5e783732015-02-19 10:28:59 -05005488 private boolean readCameraSoundForced() {
5489 return SystemProperties.getBoolean("audio.camerasound.force", false) ||
5490 mContext.getResources().getBoolean(
5491 com.android.internal.R.bool.config_camera_sound_forced);
5492 }
5493
Jean-Michel Trivif26f0172012-04-25 16:23:20 -07005494 //==========================================================================================
5495 // Device orientation
5496 //==========================================================================================
5497 /**
Mikhail Naganovb668bc62018-02-13 13:46:38 -08005498 * Handles device configuration changes that may map to a change in rotation.
5499 * Monitoring rotation is optional, and is defined by the definition and value
5500 * of the "ro.audio.monitorRotation" system property.
Jean-Michel Trivif26f0172012-04-25 16:23:20 -07005501 */
5502 private void handleConfigurationChanged(Context context) {
5503 try {
Mikhail Naganovb668bc62018-02-13 13:46:38 -08005504 // reading new configuration "safely" (i.e. under try catch) in case anything
5505 // goes wrong.
Eric Laurentd640bd32012-09-28 18:01:48 -07005506 Configuration config = context.getResources().getConfiguration();
Eric Laurentd640bd32012-09-28 18:01:48 -07005507 sendMsg(mAudioHandler,
5508 MSG_CONFIGURE_SAFE_MEDIA_VOLUME,
5509 SENDMSG_REPLACE,
5510 0,
5511 0,
John Spurlock90874332015-03-10 16:00:54 -04005512 TAG,
Eric Laurentd640bd32012-09-28 18:01:48 -07005513 0);
Eric Laurentdd45d012012-10-08 09:04:34 -07005514
John Spurlock5e783732015-02-19 10:28:59 -05005515 boolean cameraSoundForced = readCameraSoundForced();
Eric Laurentdd45d012012-10-08 09:04:34 -07005516 synchronized (mSettingsLock) {
Jean-Michel Trivi8719a1d2017-11-06 11:52:51 -08005517 final boolean cameraSoundForcedChanged = (cameraSoundForced != mCameraSoundForced);
5518 mCameraSoundForced = cameraSoundForced;
Eric Laurent8fa4d6f2014-10-30 14:13:03 -07005519 if (cameraSoundForcedChanged) {
Muyuan Li1ed6df62016-06-18 11:16:52 -07005520 if (!mIsSingleVolume) {
Jean-Michel Trivi085346a2018-02-14 10:48:51 -08005521 synchronized (VolumeStreamState.class) {
5522 VolumeStreamState s = mStreamStates[AudioSystem.STREAM_SYSTEM_ENFORCED];
5523 if (cameraSoundForced) {
5524 s.setAllIndexesToMax();
5525 mRingerModeAffectedStreams &=
5526 ~(1 << AudioSystem.STREAM_SYSTEM_ENFORCED);
5527 } else {
5528 s.setAllIndexes(mStreamStates[AudioSystem.STREAM_SYSTEM], TAG);
5529 mRingerModeAffectedStreams |=
5530 (1 << AudioSystem.STREAM_SYSTEM_ENFORCED);
5531 }
Eric Laurent8fa4d6f2014-10-30 14:13:03 -07005532 }
5533 // take new state into account for streams muted by ringer mode
John Spurlock661f2cf2014-11-17 10:29:10 -05005534 setRingerModeInt(getRingerModeInternal(), false);
Eric Laurent8fa4d6f2014-10-30 14:13:03 -07005535 }
Jean-Michel Trivi58850372018-09-14 16:01:28 -07005536 mDeviceBroker.setForceUse_Async(AudioSystem.FOR_SYSTEM,
Eric Laurent8fa4d6f2014-10-30 14:13:03 -07005537 cameraSoundForced ?
5538 AudioSystem.FORCE_SYSTEM_ENFORCED : AudioSystem.FORCE_NONE,
Jean-Michel Trivi58850372018-09-14 16:01:28 -07005539 "handleConfigurationChanged");
Eric Laurent8fa4d6f2014-10-30 14:13:03 -07005540 sendMsg(mAudioHandler,
5541 MSG_SET_ALL_VOLUMES,
5542 SENDMSG_QUEUE,
5543 0,
5544 0,
5545 mStreamStates[AudioSystem.STREAM_SYSTEM_ENFORCED], 0);
Jean-Michel Trivi58850372018-09-14 16:01:28 -07005546
Eric Laurent8fa4d6f2014-10-30 14:13:03 -07005547 }
Eric Laurentdd45d012012-10-08 09:04:34 -07005548 }
John Spurlock3346a802014-05-20 16:25:37 -04005549 mVolumeController.setLayoutDirection(config.getLayoutDirection());
Jean-Michel Trivif26f0172012-04-25 16:23:20 -07005550 } catch (Exception e) {
Jean-Michel Trivibb6f8712013-05-23 15:02:41 -07005551 Log.e(TAG, "Error handling configuration change: ", e);
Jean-Michel Trivif26f0172012-04-25 16:23:20 -07005552 }
5553 }
5554
Jean-Michel Trivid5176cf2010-01-28 11:56:42 -08005555 @Override
Jeff Sharkey098d5802012-04-26 17:30:34 -07005556 public void setRingtonePlayer(IRingtonePlayer player) {
5557 mContext.enforceCallingOrSelfPermission(REMOTE_AUDIO_PLAYBACK, null);
5558 mRingtonePlayer = player;
5559 }
5560
5561 @Override
5562 public IRingtonePlayer getRingtonePlayer() {
5563 return mRingtonePlayer;
5564 }
5565
5566 @Override
Dianne Hackborn632ca412012-06-14 19:34:10 -07005567 public AudioRoutesInfo startWatchingRoutes(IAudioRoutesObserver observer) {
Jean-Michel Trivi58850372018-09-14 16:01:28 -07005568 return mDeviceBroker.startWatchingRoutes(observer);
Dianne Hackborn632ca412012-06-14 19:34:10 -07005569 }
5570
Eric Laurentc34dcc12012-09-10 13:51:52 -07005571
5572 //==========================================================================================
5573 // Safe media volume management.
5574 // MUSIC stream volume level is limited when headphones are connected according to safety
5575 // regulation. When the user attempts to raise the volume above the limit, a warning is
5576 // displayed and the user has to acknowlegde before the volume is actually changed.
5577 // The volume index corresponding to the limit is stored in config_safe_media_volume_index
5578 // property. Platforms with a different limit must set this property accordingly in their
5579 // overlay.
5580 //==========================================================================================
5581
Eric Laurentd640bd32012-09-28 18:01:48 -07005582 // mSafeMediaVolumeState indicates whether the media volume is limited over headphones.
5583 // It is SAFE_MEDIA_VOLUME_NOT_CONFIGURED at boot time until a network service is connected
5584 // or the configure time is elapsed. It is then set to SAFE_MEDIA_VOLUME_ACTIVE or
5585 // SAFE_MEDIA_VOLUME_DISABLED according to country option. If not SAFE_MEDIA_VOLUME_DISABLED, it
5586 // can be set to SAFE_MEDIA_VOLUME_INACTIVE by calling AudioService.disableSafeMediaVolume()
5587 // (when user opts out).
John Spurlock35134602014-07-24 18:10:48 -04005588 private static final int SAFE_MEDIA_VOLUME_NOT_CONFIGURED = 0;
5589 private static final int SAFE_MEDIA_VOLUME_DISABLED = 1;
5590 private static final int SAFE_MEDIA_VOLUME_INACTIVE = 2; // confirmed
5591 private static final int SAFE_MEDIA_VOLUME_ACTIVE = 3; // unconfirmed
hyomin.ohd0446dc2018-10-18 13:58:27 +09005592 private int mSafeMediaVolumeState;
5593 private final Object mSafeMediaVolumeStateLock = new Object();
Eric Laurentd640bd32012-09-28 18:01:48 -07005594
5595 private int mMcc = 0;
Eric Laurentc34dcc12012-09-10 13:51:52 -07005596 // mSafeMediaVolumeIndex is the cached value of config_safe_media_volume_index property
Eric Laurentd640bd32012-09-28 18:01:48 -07005597 private int mSafeMediaVolumeIndex;
John Muir8b8bddd2018-02-16 14:29:14 -08005598 // mSafeUsbMediaVolumeDbfs is the cached value of the config_safe_media_volume_usb_mB
5599 // property, divided by 100.0.
5600 private float mSafeUsbMediaVolumeDbfs;
Eric Laurentb378a13a2017-07-11 14:08:11 -07005601 // mSafeUsbMediaVolumeIndex is used for USB Headsets and is the music volume UI index
John Muir8b8bddd2018-02-16 14:29:14 -08005602 // corresponding to a gain of mSafeUsbMediaVolumeDbfs (defaulting to -37dB) in audio
5603 // flinger mixer.
Eric Laurent0e5deb32017-09-01 15:12:42 -07005604 // We remove -22 dBs from the theoretical -15dB to account for the EQ + bass boost
5605 // amplification when both effects are on with all band gains at maximum.
Eric Laurentb378a13a2017-07-11 14:08:11 -07005606 // This level corresponds to a loudness of 85 dB SPL for the warning to be displayed when
5607 // the headset is compliant to EN 60950 with a max loudness of 100dB SPL.
Eric Laurenteab40d12017-06-09 12:45:21 -07005608 private int mSafeUsbMediaVolumeIndex;
Eric Laurentc34dcc12012-09-10 13:51:52 -07005609 // mSafeMediaVolumeDevices lists the devices for which safe media volume is enforced,
Jean-Michel Trivi58850372018-09-14 16:01:28 -07005610 /*package*/ final int mSafeMediaVolumeDevices = AudioSystem.DEVICE_OUT_WIRED_HEADSET
5611 | AudioSystem.DEVICE_OUT_WIRED_HEADPHONE
5612 | AudioSystem.DEVICE_OUT_USB_HEADSET;
Eric Laurentc34dcc12012-09-10 13:51:52 -07005613 // mMusicActiveMs is the cumulative time of music activity since safe volume was disabled.
5614 // When this time reaches UNSAFE_VOLUME_MUSIC_ACTIVE_MS_MAX, the safe media volume is re-enabled
5615 // automatically. mMusicActiveMs is rounded to a multiple of MUSIC_ACTIVE_POLL_PERIOD_MS.
5616 private int mMusicActiveMs;
5617 private static final int UNSAFE_VOLUME_MUSIC_ACTIVE_MS_MAX = (20 * 3600 * 1000); // 20 hours
5618 private static final int MUSIC_ACTIVE_POLL_PERIOD_MS = 60000; // 1 minute polling interval
Eric Laurentd640bd32012-09-28 18:01:48 -07005619 private static final int SAFE_VOLUME_CONFIGURE_TIMEOUT_MS = 30000; // 30s after boot completed
Eric Laurentc34dcc12012-09-10 13:51:52 -07005620
Eric Laurenteab40d12017-06-09 12:45:21 -07005621 private int safeMediaVolumeIndex(int device) {
5622 if ((device & mSafeMediaVolumeDevices) == 0) {
5623 return MAX_STREAM_VOLUME[AudioSystem.STREAM_MUSIC];
5624 }
5625 if (device == AudioSystem.DEVICE_OUT_USB_HEADSET) {
5626 return mSafeUsbMediaVolumeIndex;
5627 } else {
5628 return mSafeMediaVolumeIndex;
5629 }
5630 }
5631
John Spurlock90874332015-03-10 16:00:54 -04005632 private void setSafeMediaVolumeEnabled(boolean on, String caller) {
hyomin.ohd0446dc2018-10-18 13:58:27 +09005633 synchronized (mSafeMediaVolumeStateLock) {
Eric Laurentd640bd32012-09-28 18:01:48 -07005634 if ((mSafeMediaVolumeState != SAFE_MEDIA_VOLUME_NOT_CONFIGURED) &&
5635 (mSafeMediaVolumeState != SAFE_MEDIA_VOLUME_DISABLED)) {
5636 if (on && (mSafeMediaVolumeState == SAFE_MEDIA_VOLUME_INACTIVE)) {
5637 mSafeMediaVolumeState = SAFE_MEDIA_VOLUME_ACTIVE;
John Spurlock90874332015-03-10 16:00:54 -04005638 enforceSafeMediaVolume(caller);
Eric Laurentd640bd32012-09-28 18:01:48 -07005639 } else if (!on && (mSafeMediaVolumeState == SAFE_MEDIA_VOLUME_ACTIVE)) {
5640 mSafeMediaVolumeState = SAFE_MEDIA_VOLUME_INACTIVE;
John Spurlockaa5ee4d2014-07-25 13:05:12 -04005641 mMusicActiveMs = 1; // nonzero = confirmed
5642 saveMusicActiveMs();
Eric Laurentd640bd32012-09-28 18:01:48 -07005643 sendMsg(mAudioHandler,
5644 MSG_CHECK_MUSIC_ACTIVE,
5645 SENDMSG_REPLACE,
5646 0,
5647 0,
John Spurlock90874332015-03-10 16:00:54 -04005648 caller,
Eric Laurentd640bd32012-09-28 18:01:48 -07005649 MUSIC_ACTIVE_POLL_PERIOD_MS);
5650 }
Eric Laurentc34dcc12012-09-10 13:51:52 -07005651 }
Eric Laurentc34dcc12012-09-10 13:51:52 -07005652 }
5653 }
5654
John Spurlock90874332015-03-10 16:00:54 -04005655 private void enforceSafeMediaVolume(String caller) {
Eric Laurentc34dcc12012-09-10 13:51:52 -07005656 VolumeStreamState streamState = mStreamStates[AudioSystem.STREAM_MUSIC];
Eric Laurentc34dcc12012-09-10 13:51:52 -07005657 int devices = mSafeMediaVolumeDevices;
5658 int i = 0;
5659
5660 while (devices != 0) {
5661 int device = 1 << i++;
5662 if ((device & devices) == 0) {
5663 continue;
5664 }
Eric Laurent42b041e2013-03-29 11:36:03 -07005665 int index = streamState.getIndex(device);
Eric Laurenteab40d12017-06-09 12:45:21 -07005666 if (index > safeMediaVolumeIndex(device)) {
5667 streamState.setIndex(safeMediaVolumeIndex(device), device, caller);
Eric Laurent42b041e2013-03-29 11:36:03 -07005668 sendMsg(mAudioHandler,
5669 MSG_SET_DEVICE_VOLUME,
5670 SENDMSG_QUEUE,
5671 device,
5672 0,
5673 streamState,
5674 0);
Eric Laurentc34dcc12012-09-10 13:51:52 -07005675 }
5676 devices &= ~device;
5677 }
5678 }
5679
5680 private boolean checkSafeMediaVolume(int streamType, int index, int device) {
hyomin.ohd0446dc2018-10-18 13:58:27 +09005681 synchronized (mSafeMediaVolumeStateLock) {
Eric Laurentd640bd32012-09-28 18:01:48 -07005682 if ((mSafeMediaVolumeState == SAFE_MEDIA_VOLUME_ACTIVE) &&
Eric Laurentc34dcc12012-09-10 13:51:52 -07005683 (mStreamVolumeAlias[streamType] == AudioSystem.STREAM_MUSIC) &&
5684 ((device & mSafeMediaVolumeDevices) != 0) &&
Eric Laurenteab40d12017-06-09 12:45:21 -07005685 (index > safeMediaVolumeIndex(device))) {
Eric Laurentc34dcc12012-09-10 13:51:52 -07005686 return false;
5687 }
5688 return true;
5689 }
5690 }
5691
John Spurlock3346a802014-05-20 16:25:37 -04005692 @Override
John Spurlock90874332015-03-10 16:00:54 -04005693 public void disableSafeMediaVolume(String callingPackage) {
John Spurlockcdb57ae2015-02-11 19:04:11 -05005694 enforceVolumeController("disable the safe media volume");
hyomin.ohd0446dc2018-10-18 13:58:27 +09005695 synchronized (mSafeMediaVolumeStateLock) {
John Spurlock90874332015-03-10 16:00:54 -04005696 setSafeMediaVolumeEnabled(false, callingPackage);
Eric Laurentfde16d52012-12-03 14:42:39 -08005697 if (mPendingVolumeCommand != null) {
5698 onSetStreamVolume(mPendingVolumeCommand.mStreamType,
5699 mPendingVolumeCommand.mIndex,
5700 mPendingVolumeCommand.mFlags,
John Spurlock90874332015-03-10 16:00:54 -04005701 mPendingVolumeCommand.mDevice,
5702 callingPackage);
Eric Laurentfde16d52012-12-03 14:42:39 -08005703 mPendingVolumeCommand = null;
5704 }
Eric Laurentc34dcc12012-09-10 13:51:52 -07005705 }
5706 }
5707
Jungshik Jang41d97462014-06-30 22:26:29 +09005708 //==========================================================================================
5709 // Hdmi Cec system audio mode.
John Spurlockbc82b122015-03-02 16:12:38 -05005710 // If Hdmi Cec's system audio mode is on, audio service should send the volume change
5711 // to HdmiControlService so that the audio receiver can handle it.
Jungshik Jang41d97462014-06-30 22:26:29 +09005712 //==========================================================================================
5713
Eric Laurent212532b2014-07-21 15:43:18 -07005714 private class MyDisplayStatusCallback implements HdmiPlaybackClient.DisplayStatusCallback {
5715 public void onComplete(int status) {
Shubangc480a712018-06-11 18:02:42 -07005716 synchronized (mHdmiClientLock) {
5717 if (mHdmiManager != null) {
Eric Laurent212532b2014-07-21 15:43:18 -07005718 mHdmiCecSink = (status != HdmiControlManager.POWER_STATUS_UNKNOWN);
5719 // Television devices without CEC service apply software volume on HDMI output
5720 if (isPlatformTelevision() && !mHdmiCecSink) {
5721 mFixedVolumeDevices &= ~AudioSystem.DEVICE_OUT_HDMI;
5722 }
5723 checkAllFixedVolumeDevices();
5724 }
5725 }
5726 }
Shubangc480a712018-06-11 18:02:42 -07005727 }
5728
5729 private final Object mHdmiClientLock = new Object();
Eric Laurent212532b2014-07-21 15:43:18 -07005730
Jungshik Jang41d97462014-06-30 22:26:29 +09005731 // If HDMI-CEC system audio is supported
5732 private boolean mHdmiSystemAudioSupported = false;
5733 // Set only when device is tv.
Shubangc480a712018-06-11 18:02:42 -07005734 @GuardedBy("mHdmiClientLock")
Jungshik Jang41d97462014-06-30 22:26:29 +09005735 private HdmiTvClient mHdmiTvClient;
Eric Laurent0b03f992014-11-18 18:08:02 -08005736 // true if the device has system feature PackageManager.FEATURE_LEANBACK.
Eric Laurent212532b2014-07-21 15:43:18 -07005737 // cached HdmiControlManager interface
Shubangc480a712018-06-11 18:02:42 -07005738 @GuardedBy("mHdmiClientLock")
Eric Laurent212532b2014-07-21 15:43:18 -07005739 private HdmiControlManager mHdmiManager;
5740 // Set only when device is a set-top box.
Shubangc480a712018-06-11 18:02:42 -07005741 @GuardedBy("mHdmiClientLock")
Eric Laurent212532b2014-07-21 15:43:18 -07005742 private HdmiPlaybackClient mHdmiPlaybackClient;
5743 // true if we are a set-top box, an HDMI sink is connected and it supports CEC.
5744 private boolean mHdmiCecSink;
Shubangc480a712018-06-11 18:02:42 -07005745 // Set only when device is an audio system.
5746 @GuardedBy("mHdmiClientLock")
5747 private HdmiAudioSystemClient mHdmiAudioSystemClient;
Eric Laurent212532b2014-07-21 15:43:18 -07005748
5749 private MyDisplayStatusCallback mHdmiDisplayStatusCallback = new MyDisplayStatusCallback();
Jungshik Jang41d97462014-06-30 22:26:29 +09005750
5751 @Override
Jungshik Jang12307ca2014-07-15 19:27:56 +09005752 public int setHdmiSystemAudioSupported(boolean on) {
Eric Laurent212532b2014-07-21 15:43:18 -07005753 int device = AudioSystem.DEVICE_NONE;
Shubangc480a712018-06-11 18:02:42 -07005754 synchronized (mHdmiClientLock) {
5755 if (mHdmiManager != null) {
Shubangde728822018-07-16 16:46:51 -07005756 if (mHdmiTvClient == null && mHdmiAudioSystemClient == null) {
5757 Log.w(TAG, "Only Hdmi-Cec enabled TV or audio system device supports"
5758 + "system audio mode.");
Eric Laurent212532b2014-07-21 15:43:18 -07005759 return device;
5760 }
Shubangc480a712018-06-11 18:02:42 -07005761 if (mHdmiSystemAudioSupported != on) {
5762 mHdmiSystemAudioSupported = on;
5763 final int config = on ? AudioSystem.FORCE_HDMI_SYSTEM_AUDIO_ENFORCED :
5764 AudioSystem.FORCE_NONE;
Jean-Michel Trivi58850372018-09-14 16:01:28 -07005765 mDeviceBroker.setForceUse_Async(AudioSystem.FOR_HDMI_SYSTEM_AUDIO, config,
5766 "setHdmiSystemAudioSupported");
Eric Laurent212532b2014-07-21 15:43:18 -07005767 }
Shubangc480a712018-06-11 18:02:42 -07005768 device = getDevicesForStream(AudioSystem.STREAM_MUSIC);
Jungshik Jang6f34f5a2014-07-08 21:17:29 +09005769 }
Jungshik Jang6f34f5a2014-07-08 21:17:29 +09005770 }
Eric Laurent212532b2014-07-21 15:43:18 -07005771 return device;
Jungshik Jang6f34f5a2014-07-08 21:17:29 +09005772 }
Jungshik Jang41d97462014-06-30 22:26:29 +09005773
Terry Heoe7d6d972014-09-04 21:05:28 +09005774 @Override
5775 public boolean isHdmiSystemAudioSupported() {
5776 return mHdmiSystemAudioSupported;
5777 }
5778
Eric Laurentdd45d012012-10-08 09:04:34 -07005779 //==========================================================================================
Jean-Michel Triviac487672016-11-11 10:05:18 -08005780 // Accessibility
5781
Jean-Michel Trivicfa55532017-01-18 11:17:51 -08005782 private void initA11yMonitoring() {
5783 final AccessibilityManager accessibilityManager =
5784 (AccessibilityManager) mContext.getSystemService(Context.ACCESSIBILITY_SERVICE);
Jean-Michel Triviac487672016-11-11 10:05:18 -08005785 updateDefaultStreamOverrideDelay(accessibilityManager.isTouchExplorationEnabled());
Jean-Michel Trivi7592b982017-02-01 15:12:15 -08005786 updateA11yVolumeAlias(accessibilityManager.isAccessibilityVolumeStreamActive());
Phil Weaver26d709f2017-04-20 17:19:14 -07005787 accessibilityManager.addTouchExplorationStateChangeListener(this, null);
5788 accessibilityManager.addAccessibilityServicesStateChangeListener(this, null);
Jean-Michel Triviac487672016-11-11 10:05:18 -08005789 }
5790
5791 //---------------------------------------------------------------------------------
5792 // A11y: taking touch exploration into account for selecting the default
Jean-Michel Trivi873cc452014-09-11 17:25:09 -07005793 // stream override timeout when adjusting volume
Jean-Michel Triviac487672016-11-11 10:05:18 -08005794 //---------------------------------------------------------------------------------
Jean-Michel Trivi873cc452014-09-11 17:25:09 -07005795
Jean-Michel Triviac487672016-11-11 10:05:18 -08005796 // - STREAM_NOTIFICATION on tablets during this period after a notification stopped
Julia Reynoldsd9e96e22017-11-07 10:33:08 -05005797 // - STREAM_RING on phones during this period after a notification stopped
5798 // - STREAM_MUSIC otherwise
5799
Jean-Michel Triviac487672016-11-11 10:05:18 -08005800 private static final int DEFAULT_STREAM_TYPE_OVERRIDE_DELAY_MS = 0;
5801 private static final int TOUCH_EXPLORE_STREAM_TYPE_OVERRIDE_DELAY_MS = 1000;
Jean-Michel Trivi873cc452014-09-11 17:25:09 -07005802
Jean-Michel Triviac487672016-11-11 10:05:18 -08005803 private static int sStreamOverrideDelayMs;
Jean-Michel Trivi873cc452014-09-11 17:25:09 -07005804
Jean-Michel Triviac487672016-11-11 10:05:18 -08005805 @Override
5806 public void onTouchExplorationStateChanged(boolean enabled) {
5807 updateDefaultStreamOverrideDelay(enabled);
5808 }
5809
5810 private void updateDefaultStreamOverrideDelay(boolean touchExploreEnabled) {
5811 if (touchExploreEnabled) {
5812 sStreamOverrideDelayMs = TOUCH_EXPLORE_STREAM_TYPE_OVERRIDE_DELAY_MS;
5813 } else {
5814 sStreamOverrideDelayMs = DEFAULT_STREAM_TYPE_OVERRIDE_DELAY_MS;
Jean-Michel Trivi873cc452014-09-11 17:25:09 -07005815 }
Jean-Michel Triviac487672016-11-11 10:05:18 -08005816 if (DEBUG_VOL) Log.d(TAG, "Touch exploration enabled=" + touchExploreEnabled
5817 + " stream override delay is now " + sStreamOverrideDelayMs + " ms");
5818 }
Jean-Michel Trivi873cc452014-09-11 17:25:09 -07005819
Jean-Michel Triviac487672016-11-11 10:05:18 -08005820 //---------------------------------------------------------------------------------
5821 // A11y: taking a11y state into account for the handling of a11y prompts volume
5822 //---------------------------------------------------------------------------------
Jean-Michel Trivi873cc452014-09-11 17:25:09 -07005823
Jean-Michel Triviac487672016-11-11 10:05:18 -08005824 private static boolean sIndependentA11yVolume = false;
5825
Jean-Michel Trivicfa55532017-01-18 11:17:51 -08005826 // implementation of AccessibilityServicesStateChangeListener
5827 @Override
Phil Weaver4cab9302017-03-30 15:27:39 -07005828 public void onAccessibilityServicesStateChanged(AccessibilityManager accessibilityManager) {
Jean-Michel Trivicfa55532017-01-18 11:17:51 -08005829 updateA11yVolumeAlias(accessibilityManager.isAccessibilityVolumeStreamActive());
5830 }
5831
5832 private void updateA11yVolumeAlias(boolean a11VolEnabled) {
5833 if (DEBUG_VOL) Log.d(TAG, "Accessibility volume enabled = " + a11VolEnabled);
5834 if (sIndependentA11yVolume != a11VolEnabled) {
5835 sIndependentA11yVolume = a11VolEnabled;
5836 // update the volume mapping scheme
5837 updateStreamVolumeAlias(true /*updateVolumes*/, TAG);
5838 // update the volume controller behavior
5839 mVolumeController.setA11yMode(sIndependentA11yVolume ?
5840 VolumePolicy.A11Y_MODE_INDEPENDENT_A11Y_VOLUME :
5841 VolumePolicy.A11Y_MODE_MEDIA_A11Y_VOLUME);
Jean-Michel Trivia53b7052017-04-12 18:27:01 -07005842 mVolumeController.postVolumeChanged(AudioManager.STREAM_ACCESSIBILITY, 0);
Jean-Michel Trivicfa55532017-01-18 11:17:51 -08005843 }
Jean-Michel Trivi873cc452014-09-11 17:25:09 -07005844 }
5845
5846 //==========================================================================================
Eric Laurentdd45d012012-10-08 09:04:34 -07005847 // Camera shutter sound policy.
5848 // config_camera_sound_forced configuration option in config.xml defines if the camera shutter
5849 // sound is forced (sound even if the device is in silent mode) or not. This option is false by
5850 // default and can be overridden by country specific overlay in values-mccXXX/config.xml.
5851 //==========================================================================================
5852
5853 // cached value of com.android.internal.R.bool.config_camera_sound_forced
Jean-Michel Trivi8719a1d2017-11-06 11:52:51 -08005854 @GuardedBy("mSettingsLock")
5855 private boolean mCameraSoundForced;
Eric Laurentdd45d012012-10-08 09:04:34 -07005856
5857 // called by android.hardware.Camera to populate CameraInfo.canDisableShutterSound
5858 public boolean isCameraSoundForced() {
Jean-Michel Trivi8719a1d2017-11-06 11:52:51 -08005859 synchronized (mSettingsLock) {
Eric Laurentdd45d012012-10-08 09:04:34 -07005860 return mCameraSoundForced;
5861 }
5862 }
5863
Jean-Michel Trivi011f39e2017-08-19 18:08:06 -07005864 //==========================================================================================
5865 // AudioService logging and dumpsys
5866 //==========================================================================================
Jean-Michel Trivi3bf75782018-07-02 10:48:04 -07005867 static final int LOG_NB_EVENTS_PHONE_STATE = 20;
5868 static final int LOG_NB_EVENTS_DEVICE_CONNECTION = 30;
5869 static final int LOG_NB_EVENTS_FORCE_USE = 20;
5870 static final int LOG_NB_EVENTS_VOLUME = 40;
5871 static final int LOG_NB_EVENTS_DYN_POLICY = 10;
Jean-Michel Trivi011f39e2017-08-19 18:08:06 -07005872
5873 final private AudioEventLogger mModeLogger = new AudioEventLogger(LOG_NB_EVENTS_PHONE_STATE,
5874 "phone state (logged after successfull call to AudioSystem.setPhoneState(int))");
5875
Jean-Michel Trivi3bf75782018-07-02 10:48:04 -07005876 // logs for wired + A2DP device connections:
5877 // - wired: logged before onSetWiredDeviceConnectionState() is executed
5878 // - A2DP: logged at reception of method call
Jean-Michel Trivi58850372018-09-14 16:01:28 -07005879 /*package*/ static final AudioEventLogger sDeviceLogger = new AudioEventLogger(
Jean-Michel Trivi44abe2c2019-02-26 18:12:54 -08005880 LOG_NB_EVENTS_DEVICE_CONNECTION, "wired/A2DP/hearing aid device connection");
Jean-Michel Trivi011f39e2017-08-19 18:08:06 -07005881
Jean-Michel Trivi58850372018-09-14 16:01:28 -07005882 static final AudioEventLogger sForceUseLogger = new AudioEventLogger(
Jean-Michel Trivi011f39e2017-08-19 18:08:06 -07005883 LOG_NB_EVENTS_FORCE_USE,
5884 "force use (logged before setForceUse() is executed)");
5885
Jean-Michel Trivi58850372018-09-14 16:01:28 -07005886 static final AudioEventLogger sVolumeLogger = new AudioEventLogger(LOG_NB_EVENTS_VOLUME,
Jean-Michel Trivicf170362017-08-24 17:24:57 -07005887 "volume changes (logged when command received by AudioService)");
5888
Jean-Michel Trivi12a86762018-04-24 16:57:49 -07005889 final private AudioEventLogger mDynPolicyLogger = new AudioEventLogger(LOG_NB_EVENTS_DYN_POLICY,
5890 "dynamic policy events (logged when command received by AudioService)");
5891
Eric Laurentdd45d012012-10-08 09:04:34 -07005892 private static final String[] RINGER_MODE_NAMES = new String[] {
5893 "SILENT",
5894 "VIBRATE",
5895 "NORMAL"
5896 };
5897
5898 private void dumpRingerMode(PrintWriter pw) {
5899 pw.println("\nRinger mode: ");
John Spurlock661f2cf2014-11-17 10:29:10 -05005900 pw.println("- mode (internal) = " + RINGER_MODE_NAMES[mRingerMode]);
5901 pw.println("- mode (external) = " + RINGER_MODE_NAMES[mRingerModeExternal]);
John Spurlock50ced3f2015-05-11 16:00:09 -04005902 dumpRingerModeStreams(pw, "affected", mRingerModeAffectedStreams);
Beverlyd6964762018-02-16 14:07:03 -05005903 dumpRingerModeStreams(pw, "muted", mRingerAndZenModeMutedStreams);
John Spurlock661f2cf2014-11-17 10:29:10 -05005904 pw.print("- delegate = "); pw.println(mRingerModeDelegate);
Eric Laurentdd45d012012-10-08 09:04:34 -07005905 }
5906
John Spurlock50ced3f2015-05-11 16:00:09 -04005907 private void dumpRingerModeStreams(PrintWriter pw, String type, int streams) {
5908 pw.print("- ringer mode "); pw.print(type); pw.print(" streams = 0x");
5909 pw.print(Integer.toHexString(streams));
5910 if (streams != 0) {
5911 pw.print(" (");
5912 boolean first = true;
5913 for (int i = 0; i < AudioSystem.STREAM_NAMES.length; i++) {
5914 final int stream = (1 << i);
5915 if ((streams & stream) != 0) {
5916 if (!first) pw.print(',');
5917 pw.print(AudioSystem.STREAM_NAMES[i]);
5918 streams &= ~stream;
5919 first = false;
5920 }
5921 }
5922 if (streams != 0) {
5923 if (!first) pw.print(',');
5924 pw.print(streams);
5925 }
5926 pw.print(')');
5927 }
5928 pw.println();
5929 }
5930
Dianne Hackborn632ca412012-06-14 19:34:10 -07005931 @Override
Jean-Michel Trivid5176cf2010-01-28 11:56:42 -08005932 protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
Jeff Sharkeyfe9a53b2017-03-31 14:08:23 -06005933 if (!DumpUtils.checkDumpPermission(mContext, TAG, pw)) return;
Jeff Sharkeyeb4cc4922012-04-26 18:17:29 -07005934
Jean-Michel Trivifa9a6982013-06-27 16:22:58 -07005935 mMediaFocusControl.dump(pw);
Eric Laurentbffc3d12012-05-07 17:43:49 -07005936 dumpStreamStates(pw);
Eric Laurentdd45d012012-10-08 09:04:34 -07005937 dumpRingerMode(pw);
Dianne Hackborn632ca412012-06-14 19:34:10 -07005938 pw.println("\nAudio routes:");
Jean-Michel Trivi58850372018-09-14 16:01:28 -07005939 pw.print(" mMainType=0x"); pw.println(Integer.toHexString(
5940 mDeviceBroker.getCurAudioRoutes().mainType));
5941 pw.print(" mBluetoothName="); pw.println(mDeviceBroker.getCurAudioRoutes().bluetoothName);
John Spurlock35134602014-07-24 18:10:48 -04005942
5943 pw.println("\nOther state:");
John Spurlock3346a802014-05-20 16:25:37 -04005944 pw.print(" mVolumeController="); pw.println(mVolumeController);
John Spurlock35134602014-07-24 18:10:48 -04005945 pw.print(" mSafeMediaVolumeState=");
5946 pw.println(safeMediaVolumeStateToString(mSafeMediaVolumeState));
5947 pw.print(" mSafeMediaVolumeIndex="); pw.println(mSafeMediaVolumeIndex);
Eric Laurenteab40d12017-06-09 12:45:21 -07005948 pw.print(" mSafeUsbMediaVolumeIndex="); pw.println(mSafeUsbMediaVolumeIndex);
John Muir8b8bddd2018-02-16 14:29:14 -08005949 pw.print(" mSafeUsbMediaVolumeDbfs="); pw.println(mSafeUsbMediaVolumeDbfs);
Jean-Michel Trivi7592b982017-02-01 15:12:15 -08005950 pw.print(" sIndependentA11yVolume="); pw.println(sIndependentA11yVolume);
John Spurlock35134602014-07-24 18:10:48 -04005951 pw.print(" mPendingVolumeCommand="); pw.println(mPendingVolumeCommand);
5952 pw.print(" mMusicActiveMs="); pw.println(mMusicActiveMs);
John Spurlockaa5ee4d2014-07-25 13:05:12 -04005953 pw.print(" mMcc="); pw.println(mMcc);
John Spurlock5e783732015-02-19 10:28:59 -05005954 pw.print(" mCameraSoundForced="); pw.println(mCameraSoundForced);
John Spurlock661f2cf2014-11-17 10:29:10 -05005955 pw.print(" mHasVibrator="); pw.println(mHasVibrator);
John Spurlocka48d7792015-03-03 17:35:57 -05005956 pw.print(" mVolumePolicy="); pw.println(mVolumePolicy);
Jean-Michel Trivi58850372018-09-14 16:01:28 -07005957 pw.print(" mAvrcpAbsVolSupported=");
5958 pw.println(mDeviceBroker.isAvrcpAbsoluteVolumeSupported());
Jean-Michel Trivi1b3541d2014-11-25 12:53:41 -08005959
5960 dumpAudioPolicies(pw);
Jean-Michel Trivi12a86762018-04-24 16:57:49 -07005961 mDynPolicyLogger.dump(pw);
Jean-Michel Trivi292a6a42016-12-01 08:32:15 -08005962
5963 mPlaybackMonitor.dump(pw);
Jean-Michel Trivi66ffacf2017-02-04 17:25:31 -08005964
5965 mRecordMonitor.dump(pw);
Jean-Michel Trivi011f39e2017-08-19 18:08:06 -07005966
Jean-Michel Trivicf170362017-08-24 17:24:57 -07005967 pw.println("\n");
Jean-Michel Trivi011f39e2017-08-19 18:08:06 -07005968 pw.println("\nEvent logs:");
5969 mModeLogger.dump(pw);
5970 pw.println("\n");
Jean-Michel Trivi58850372018-09-14 16:01:28 -07005971 sDeviceLogger.dump(pw);
Jean-Michel Trivi011f39e2017-08-19 18:08:06 -07005972 pw.println("\n");
Jean-Michel Trivi58850372018-09-14 16:01:28 -07005973 sForceUseLogger.dump(pw);
Jean-Michel Trivicf170362017-08-24 17:24:57 -07005974 pw.println("\n");
Jean-Michel Trivi58850372018-09-14 16:01:28 -07005975 sVolumeLogger.dump(pw);
John Spurlock35134602014-07-24 18:10:48 -04005976 }
5977
hyomin.ohd0446dc2018-10-18 13:58:27 +09005978 private static String safeMediaVolumeStateToString(int state) {
John Spurlock35134602014-07-24 18:10:48 -04005979 switch(state) {
5980 case SAFE_MEDIA_VOLUME_NOT_CONFIGURED: return "SAFE_MEDIA_VOLUME_NOT_CONFIGURED";
5981 case SAFE_MEDIA_VOLUME_DISABLED: return "SAFE_MEDIA_VOLUME_DISABLED";
5982 case SAFE_MEDIA_VOLUME_INACTIVE: return "SAFE_MEDIA_VOLUME_INACTIVE";
5983 case SAFE_MEDIA_VOLUME_ACTIVE: return "SAFE_MEDIA_VOLUME_ACTIVE";
5984 }
5985 return null;
Jean-Michel Trivid5176cf2010-01-28 11:56:42 -08005986 }
Glenn Kastenfd116ad2013-07-12 17:10:39 -07005987
5988 // Inform AudioFlinger of our device's low RAM attribute
5989 private static void readAndSetLowRamDevice()
5990 {
Andy Hung79583582018-01-23 13:58:02 -08005991 boolean isLowRamDevice = ActivityManager.isLowRamDeviceStatic();
5992 long totalMemory = 1024 * 1024 * 1024; // 1GB is the default if ActivityManager fails.
5993
5994 try {
5995 final ActivityManager.MemoryInfo info = new ActivityManager.MemoryInfo();
5996 ActivityManager.getService().getMemoryInfo(info);
5997 totalMemory = info.totalMem;
5998 } catch (RemoteException e) {
5999 Log.w(TAG, "Cannot obtain MemoryInfo from ActivityManager, assume low memory device");
6000 isLowRamDevice = true;
6001 }
6002
6003 final int status = AudioSystem.setLowRamDevice(isLowRamDevice, totalMemory);
Glenn Kastenfd116ad2013-07-12 17:10:39 -07006004 if (status != 0) {
6005 Log.w(TAG, "AudioFlinger informed of device's low RAM attribute; status " + status);
6006 }
6007 }
John Spurlock3346a802014-05-20 16:25:37 -04006008
John Spurlockcdb57ae2015-02-11 19:04:11 -05006009 private void enforceVolumeController(String action) {
John Spurlock3346a802014-05-20 16:25:37 -04006010 mContext.enforceCallingOrSelfPermission(android.Manifest.permission.STATUS_BAR_SERVICE,
6011 "Only SystemUI can " + action);
6012 }
6013
6014 @Override
6015 public void setVolumeController(final IVolumeController controller) {
John Spurlockcdb57ae2015-02-11 19:04:11 -05006016 enforceVolumeController("set the volume controller");
John Spurlock3346a802014-05-20 16:25:37 -04006017
6018 // return early if things are not actually changing
6019 if (mVolumeController.isSameBinder(controller)) {
6020 return;
6021 }
6022
6023 // dismiss the old volume controller
6024 mVolumeController.postDismiss();
6025 if (controller != null) {
6026 // we are about to register a new controller, listen for its death
6027 try {
6028 controller.asBinder().linkToDeath(new DeathRecipient() {
6029 @Override
6030 public void binderDied() {
6031 if (mVolumeController.isSameBinder(controller)) {
6032 Log.w(TAG, "Current remote volume controller died, unregistering");
6033 setVolumeController(null);
6034 }
6035 }
6036 }, 0);
6037 } catch (RemoteException e) {
6038 // noop
6039 }
6040 }
6041 mVolumeController.setController(controller);
John Spurlock33f4e042014-07-11 13:10:58 -04006042 if (DEBUG_VOL) Log.d(TAG, "Volume controller: " + mVolumeController);
6043 }
6044
6045 @Override
6046 public void notifyVolumeControllerVisible(final IVolumeController controller, boolean visible) {
John Spurlockcdb57ae2015-02-11 19:04:11 -05006047 enforceVolumeController("notify about volume controller visibility");
John Spurlock33f4e042014-07-11 13:10:58 -04006048
6049 // return early if the controller is not current
6050 if (!mVolumeController.isSameBinder(controller)) {
6051 return;
6052 }
6053
6054 mVolumeController.setVisible(visible);
6055 if (DEBUG_VOL) Log.d(TAG, "Volume controller visible: " + visible);
John Spurlock3346a802014-05-20 16:25:37 -04006056 }
RoboErikd09bd0c2014-06-24 17:45:19 -07006057
John Spurlocka48d7792015-03-03 17:35:57 -05006058 @Override
6059 public void setVolumePolicy(VolumePolicy policy) {
6060 enforceVolumeController("set volume policy");
John Spurlockb02c7442015-04-14 09:32:25 -04006061 if (policy != null && !policy.equals(mVolumePolicy)) {
John Spurlocka48d7792015-03-03 17:35:57 -05006062 mVolumePolicy = policy;
John Spurlockb02c7442015-04-14 09:32:25 -04006063 if (DEBUG_VOL) Log.d(TAG, "Volume policy changed: " + mVolumePolicy);
John Spurlocka48d7792015-03-03 17:35:57 -05006064 }
6065 }
6066
RoboErikd09bd0c2014-06-24 17:45:19 -07006067 public static class VolumeController {
6068 private static final String TAG = "VolumeController";
6069
6070 private IVolumeController mController;
John Spurlock33f4e042014-07-11 13:10:58 -04006071 private boolean mVisible;
6072 private long mNextLongPress;
6073 private int mLongPressTimeout;
RoboErikd09bd0c2014-06-24 17:45:19 -07006074
6075 public void setController(IVolumeController controller) {
6076 mController = controller;
John Spurlock33f4e042014-07-11 13:10:58 -04006077 mVisible = false;
6078 }
6079
6080 public void loadSettings(ContentResolver cr) {
6081 mLongPressTimeout = Settings.Secure.getIntForUser(cr,
6082 Settings.Secure.LONG_PRESS_TIMEOUT, 500, UserHandle.USER_CURRENT);
6083 }
6084
RoboErik4197cb62015-01-21 15:45:32 -08006085 public boolean suppressAdjustment(int resolvedStream, int flags, boolean isMute) {
6086 if (isMute) {
6087 return false;
6088 }
John Spurlock33f4e042014-07-11 13:10:58 -04006089 boolean suppress = false;
Julia Reynoldseb0ce472018-05-04 15:34:55 -04006090 if (resolvedStream == DEFAULT_VOL_STREAM_NO_PLAYBACK && mController != null) {
John Spurlock33f4e042014-07-11 13:10:58 -04006091 final long now = SystemClock.uptimeMillis();
6092 if ((flags & AudioManager.FLAG_SHOW_UI) != 0 && !mVisible) {
6093 // ui will become visible
6094 if (mNextLongPress < now) {
6095 mNextLongPress = now + mLongPressTimeout;
6096 }
6097 suppress = true;
6098 } else if (mNextLongPress > 0) { // in a long-press
6099 if (now > mNextLongPress) {
6100 // long press triggered, no more suppression
6101 mNextLongPress = 0;
6102 } else {
6103 // keep suppressing until the long press triggers
6104 suppress = true;
6105 }
6106 }
6107 }
6108 return suppress;
6109 }
6110
6111 public void setVisible(boolean visible) {
6112 mVisible = visible;
RoboErikd09bd0c2014-06-24 17:45:19 -07006113 }
6114
6115 public boolean isSameBinder(IVolumeController controller) {
6116 return Objects.equals(asBinder(), binder(controller));
6117 }
6118
6119 public IBinder asBinder() {
6120 return binder(mController);
6121 }
6122
6123 private static IBinder binder(IVolumeController controller) {
6124 return controller == null ? null : controller.asBinder();
6125 }
6126
6127 @Override
6128 public String toString() {
John Spurlock33f4e042014-07-11 13:10:58 -04006129 return "VolumeController(" + asBinder() + ",mVisible=" + mVisible + ")";
RoboErikd09bd0c2014-06-24 17:45:19 -07006130 }
6131
6132 public void postDisplaySafeVolumeWarning(int flags) {
6133 if (mController == null)
6134 return;
6135 try {
6136 mController.displaySafeVolumeWarning(flags);
6137 } catch (RemoteException e) {
6138 Log.w(TAG, "Error calling displaySafeVolumeWarning", e);
6139 }
6140 }
6141
6142 public void postVolumeChanged(int streamType, int flags) {
6143 if (mController == null)
6144 return;
6145 try {
6146 mController.volumeChanged(streamType, flags);
6147 } catch (RemoteException e) {
6148 Log.w(TAG, "Error calling volumeChanged", e);
6149 }
6150 }
6151
RoboErikd09bd0c2014-06-24 17:45:19 -07006152 public void postMasterMuteChanged(int flags) {
6153 if (mController == null)
6154 return;
6155 try {
6156 mController.masterMuteChanged(flags);
6157 } catch (RemoteException e) {
6158 Log.w(TAG, "Error calling masterMuteChanged", e);
6159 }
6160 }
6161
6162 public void setLayoutDirection(int layoutDirection) {
6163 if (mController == null)
6164 return;
6165 try {
6166 mController.setLayoutDirection(layoutDirection);
6167 } catch (RemoteException e) {
6168 Log.w(TAG, "Error calling setLayoutDirection", e);
6169 }
6170 }
6171
6172 public void postDismiss() {
6173 if (mController == null)
6174 return;
6175 try {
6176 mController.dismiss();
6177 } catch (RemoteException e) {
6178 Log.w(TAG, "Error calling dismiss", e);
6179 }
6180 }
Jean-Michel Triviac487672016-11-11 10:05:18 -08006181
6182 public void setA11yMode(int a11yMode) {
6183 if (mController == null)
6184 return;
6185 try {
6186 mController.setA11yMode(a11yMode);
6187 } catch (RemoteException e) {
6188 Log.w(TAG, "Error calling setA11Mode", e);
6189 }
6190 }
RoboErikd09bd0c2014-06-24 17:45:19 -07006191 }
Jean-Michel Trivia8b6bd82014-07-01 09:48:46 -07006192
RoboErik0dac35a2014-08-12 15:48:49 -07006193 /**
6194 * Interface for system components to get some extra functionality through
6195 * LocalServices.
6196 */
6197 final class AudioServiceInternal extends AudioManagerInternal {
John Spurlock661f2cf2014-11-17 10:29:10 -05006198 @Override
6199 public void setRingerModeDelegate(RingerModeDelegate delegate) {
6200 mRingerModeDelegate = delegate;
6201 if (mRingerModeDelegate != null) {
Jean-Michel Trivi8719a1d2017-11-06 11:52:51 -08006202 synchronized (mSettingsLock) {
Beverlyd6964762018-02-16 14:07:03 -05006203 updateRingerAndZenModeAffectedStreams();
Jean-Michel Trivi8719a1d2017-11-06 11:52:51 -08006204 }
John Spurlock661f2cf2014-11-17 10:29:10 -05006205 setRingerModeInternal(getRingerModeInternal(), TAG + ".setRingerModeDelegate");
6206 }
6207 }
RoboErik272e1612014-09-05 11:39:29 -07006208
6209 @Override
6210 public void adjustSuggestedStreamVolumeForUid(int streamType, int direction, int flags,
6211 String callingPackage, int uid) {
6212 // direction and stream type swap here because the public
6213 // adjustSuggested has a different order than the other methods.
John Spurlock90874332015-03-10 16:00:54 -04006214 adjustSuggestedStreamVolume(direction, streamType, flags, callingPackage,
6215 callingPackage, uid);
RoboErik272e1612014-09-05 11:39:29 -07006216 }
6217
RoboErik0dac35a2014-08-12 15:48:49 -07006218 @Override
6219 public void adjustStreamVolumeForUid(int streamType, int direction, int flags,
6220 String callingPackage, int uid) {
John Spurlock90874332015-03-10 16:00:54 -04006221 adjustStreamVolume(streamType, direction, flags, callingPackage,
6222 callingPackage, uid);
RoboErik0dac35a2014-08-12 15:48:49 -07006223 }
6224
6225 @Override
6226 public void setStreamVolumeForUid(int streamType, int direction, int flags,
6227 String callingPackage, int uid) {
John Spurlock90874332015-03-10 16:00:54 -04006228 setStreamVolume(streamType, direction, flags, callingPackage, callingPackage, uid);
RoboErik0dac35a2014-08-12 15:48:49 -07006229 }
RoboErik519c7742014-11-18 10:59:09 -08006230
6231 @Override
John Spurlock661f2cf2014-11-17 10:29:10 -05006232 public int getRingerModeInternal() {
6233 return AudioService.this.getRingerModeInternal();
6234 }
6235
6236 @Override
6237 public void setRingerModeInternal(int ringerMode, String caller) {
6238 AudioService.this.setRingerModeInternal(ringerMode, caller);
6239 }
John Spurlockcdb57ae2015-02-11 19:04:11 -05006240
6241 @Override
Mike Digman55272862018-02-20 14:35:17 -08006242 public void silenceRingerModeInternal(String caller) {
6243 AudioService.this.silenceRingerModeInternal(caller);
6244 }
6245
6246 @Override
John Spurlock50ced3f2015-05-11 16:00:09 -04006247 public void updateRingerModeAffectedStreamsInternal() {
6248 synchronized (mSettingsLock) {
Beverlyd6964762018-02-16 14:07:03 -05006249 if (updateRingerAndZenModeAffectedStreams()) {
John Spurlock50ced3f2015-05-11 16:00:09 -04006250 setRingerModeInt(getRingerModeInternal(), false);
6251 }
6252 }
6253 }
Phil Weaverf1a9aff2017-03-23 17:21:29 -07006254
6255 @Override
6256 public void setAccessibilityServiceUids(IntArray uids) {
6257 synchronized (mAccessibilityServiceUidsLock) {
6258 if (uids.size() == 0) {
6259 mAccessibilityServiceUids = null;
6260 } else {
6261 boolean changed = (mAccessibilityServiceUids == null)
6262 || (mAccessibilityServiceUids.length != uids.size());
6263 if (!changed) {
6264 for (int i = 0; i < mAccessibilityServiceUids.length; i++) {
6265 if (uids.get(i) != mAccessibilityServiceUids[i]) {
6266 changed = true;
6267 break;
6268 }
6269 }
6270 }
6271 if (changed) {
6272 mAccessibilityServiceUids = uids.toArray();
6273 }
6274 }
Eric Laurent1c9c1d52018-10-17 10:06:46 -07006275 AudioSystem.setA11yServicesUids(mAccessibilityServiceUids);
Phil Weaverf1a9aff2017-03-23 17:21:29 -07006276 }
6277 }
RoboErik0dac35a2014-08-12 15:48:49 -07006278 }
6279
Jean-Michel Trivia8b6bd82014-07-01 09:48:46 -07006280 //==========================================================================================
6281 // Audio policy management
6282 //==========================================================================================
Jean-Michel Trivi0212be52014-11-24 14:43:10 -08006283 public String registerAudioPolicy(AudioPolicyConfig policyConfig, IAudioPolicyCallback pcb,
Kevin Rocard2fe8b8b2019-02-20 11:25:23 -08006284 boolean hasFocusListener, boolean isFocusPolicy, boolean isVolumeController,
6285 IMediaProjection projection) {
Jean-Michel Trivi5a561092015-04-23 18:48:08 -07006286 AudioSystem.setDynamicPolicyCallback(mDynPolicyCallback);
6287
Kevin Rocard2fe8b8b2019-02-20 11:25:23 -08006288 if (!isPolicyRegisterAllowed(policyConfig, projection)) {
6289 Slog.w(TAG, "Permission denied to register audio policy for pid "
6290 + Binder.getCallingPid() + " / uid " + Binder.getCallingUid()
6291 + ", need MODIFY_AUDIO_ROUTING or MediaProjection that can project audio");
Jean-Michel Trivi8fdb0d42014-07-16 19:08:37 -07006292 return null;
Jean-Michel Trivia8b6bd82014-07-01 09:48:46 -07006293 }
Jean-Michel Trivi0212be52014-11-24 14:43:10 -08006294
Jean-Michel Trivi12a86762018-04-24 16:57:49 -07006295 mDynPolicyLogger.log((new AudioEventLogger.StringEvent("registerAudioPolicy for "
6296 + pcb.asBinder() + " with config:" + policyConfig)).printLog(TAG));
Kevin Rocard2fe8b8b2019-02-20 11:25:23 -08006297
6298 String regId = null;
Jean-Michel Trivia8b6bd82014-07-01 09:48:46 -07006299 synchronized (mAudioPolicies) {
Jean-Michel Trivia8b6bd82014-07-01 09:48:46 -07006300 try {
Jean-Michel Trivi0212be52014-11-24 14:43:10 -08006301 if (mAudioPolicies.containsKey(pcb.asBinder())) {
Jean-Michel Trivi1b3541d2014-11-25 12:53:41 -08006302 Slog.e(TAG, "Cannot re-register policy");
6303 return null;
6304 }
Jean-Michel Trivi126cf032017-04-02 23:19:02 -07006305 AudioPolicyProxy app = new AudioPolicyProxy(policyConfig, pcb, hasFocusListener,
Jean-Michel Trivi610aa9b2018-01-27 15:42:42 -08006306 isFocusPolicy, isVolumeController);
Jean-Michel Trivi0212be52014-11-24 14:43:10 -08006307 pcb.asBinder().linkToDeath(app, 0/*flags*/);
6308 regId = app.getRegistrationId();
6309 mAudioPolicies.put(pcb.asBinder(), app);
Jean-Michel Trivia8b6bd82014-07-01 09:48:46 -07006310 } catch (RemoteException e) {
6311 // audio policy owner has already died!
Jean-Michel Trivi0212be52014-11-24 14:43:10 -08006312 Slog.w(TAG, "Audio policy registration failed, could not link to " + pcb +
Jean-Michel Trivia8b6bd82014-07-01 09:48:46 -07006313 " binder death", e);
Jean-Michel Trivi8fdb0d42014-07-16 19:08:37 -07006314 return null;
Jean-Michel Trivia8b6bd82014-07-01 09:48:46 -07006315 }
6316 }
Jean-Michel Trivi8fdb0d42014-07-16 19:08:37 -07006317 return regId;
Jean-Michel Trivia8b6bd82014-07-01 09:48:46 -07006318 }
Jean-Michel Trivi8fdb0d42014-07-16 19:08:37 -07006319
Kevin Rocard2fe8b8b2019-02-20 11:25:23 -08006320 /**
6321 * Apps with MODIFY_AUDIO_ROUTING can register any policy.
6322 * Apps with an audio capable MediaProjection are allowed to register a RENDER|LOOPBACK policy
6323 * as those policy do not modify the audio routing.
6324 */
6325 private boolean isPolicyRegisterAllowed(AudioPolicyConfig policyConfig,
6326 IMediaProjection projection) {
6327
6328 boolean isLoopbackRenderPolicy = policyConfig.getMixes().stream().allMatch(
6329 mix -> mix.getRouteFlags() == (mix.ROUTE_FLAG_RENDER | mix.ROUTE_FLAG_LOOP_BACK));
6330
6331 // Policy that do not modify the audio routing only need an audio projection
6332 if (isLoopbackRenderPolicy && canProjectAudio(projection)) {
6333 return true;
6334 }
6335
6336 boolean hasPermissionModifyAudioRouting =
6337 (PackageManager.PERMISSION_GRANTED == mContext.checkCallingPermission(
6338 android.Manifest.permission.MODIFY_AUDIO_ROUTING));
6339 if (hasPermissionModifyAudioRouting) {
6340 return true;
6341 }
6342 return false;
6343 }
6344
6345 /** @return true if projection is a valid MediaProjection that can project audio. */
6346 private boolean canProjectAudio(IMediaProjection projection) {
6347 if (projection == null) {
6348 return false;
6349 }
6350
6351 IMediaProjectionManager projectionService = getProjectionService();
6352 if (projectionService == null) {
6353 Log.e(TAG, "Can't get service IMediaProjectionManager");
6354 return false;
6355 }
6356
6357 try {
6358 if (!projectionService.isValidMediaProjection(projection)) {
6359 Log.w(TAG, "App passed invalid MediaProjection token");
6360 return false;
6361 }
6362 } catch (RemoteException e) {
6363 Log.e(TAG, "Can't call .isValidMediaProjection() on IMediaProjectionManager"
6364 + projectionService.asBinder(), e);
6365 return false;
6366 }
6367
6368 try {
6369 if (!projection.canProjectAudio()) {
6370 Log.w(TAG, "App passed MediaProjection that can not project audio");
6371 return false;
6372 }
6373 } catch (RemoteException e) {
6374 Log.e(TAG, "Can't call .canProjectAudio() on valid IMediaProjection"
6375 + projection.asBinder(), e);
6376 return false;
6377 }
6378
6379 return true;
6380 }
6381
6382 private IMediaProjectionManager getProjectionService() {
6383 if (mProjectionService == null) {
6384 IBinder b = ServiceManager.getService(Context.MEDIA_PROJECTION_SERVICE);
6385 mProjectionService = IMediaProjectionManager.Stub.asInterface(b);
6386 }
6387 return mProjectionService;
6388 }
6389
Jean-Michel Trivi0212be52014-11-24 14:43:10 -08006390 public void unregisterAudioPolicyAsync(IAudioPolicyCallback pcb) {
Jean-Michel Trivi12a86762018-04-24 16:57:49 -07006391 mDynPolicyLogger.log((new AudioEventLogger.StringEvent("unregisterAudioPolicyAsync for "
6392 + pcb.asBinder()).printLog(TAG)));
Jean-Michel Trivia8b6bd82014-07-01 09:48:46 -07006393 synchronized (mAudioPolicies) {
Jean-Michel Trivi0212be52014-11-24 14:43:10 -08006394 AudioPolicyProxy app = mAudioPolicies.remove(pcb.asBinder());
Jean-Michel Trivia8b6bd82014-07-01 09:48:46 -07006395 if (app == null) {
6396 Slog.w(TAG, "Trying to unregister unknown audio policy for pid "
6397 + Binder.getCallingPid() + " / uid " + Binder.getCallingUid());
Jean-Michel Trivi1b3541d2014-11-25 12:53:41 -08006398 return;
Jean-Michel Trivia8b6bd82014-07-01 09:48:46 -07006399 } else {
Jean-Michel Trivi0212be52014-11-24 14:43:10 -08006400 pcb.asBinder().unlinkToDeath(app, 0/*flags*/);
Jean-Michel Trivia8b6bd82014-07-01 09:48:46 -07006401 }
Jean-Michel Trivi0212be52014-11-24 14:43:10 -08006402 app.release();
Jean-Michel Trivia8b6bd82014-07-01 09:48:46 -07006403 }
Jean-Michel Trivi8fdb0d42014-07-16 19:08:37 -07006404 // TODO implement clearing mix attribute matching info in native audio policy
Jean-Michel Trivia8b6bd82014-07-01 09:48:46 -07006405 }
6406
Jean-Michel Triviaf576a02018-02-14 08:57:46 -08006407 /**
6408 * Checks whether caller has MODIFY_AUDIO_ROUTING permission, and the policy is registered.
6409 * @param errorMsg log warning if permission check failed.
6410 * @return null if the operation on the audio mixes should be cancelled.
6411 */
6412 @GuardedBy("mAudioPolicies")
6413 private AudioPolicyProxy checkUpdateForPolicy(IAudioPolicyCallback pcb, String errorMsg) {
6414 // permission check
6415 final boolean hasPermissionForPolicy =
Jean-Michel Trivi0212be52014-11-24 14:43:10 -08006416 (PackageManager.PERMISSION_GRANTED == mContext.checkCallingPermission(
6417 android.Manifest.permission.MODIFY_AUDIO_ROUTING));
6418 if (!hasPermissionForPolicy) {
Jean-Michel Triviaf576a02018-02-14 08:57:46 -08006419 Slog.w(TAG, errorMsg + " for pid " +
Jean-Michel Trivi0212be52014-11-24 14:43:10 -08006420 + Binder.getCallingPid() + " / uid "
6421 + Binder.getCallingUid() + ", need MODIFY_AUDIO_ROUTING");
Jean-Michel Triviaf576a02018-02-14 08:57:46 -08006422 return null;
Jean-Michel Trivi0212be52014-11-24 14:43:10 -08006423 }
Jean-Michel Triviaf576a02018-02-14 08:57:46 -08006424 // policy registered?
6425 final AudioPolicyProxy app = mAudioPolicies.get(pcb.asBinder());
6426 if (app == null) {
6427 Slog.w(TAG, errorMsg + " for pid " +
6428 + Binder.getCallingPid() + " / uid "
6429 + Binder.getCallingUid() + ", unregistered policy");
6430 return null;
6431 }
6432 return app;
6433 }
Jean-Michel Trivi0212be52014-11-24 14:43:10 -08006434
Jean-Michel Triviaf576a02018-02-14 08:57:46 -08006435 public int addMixForPolicy(AudioPolicyConfig policyConfig, IAudioPolicyCallback pcb) {
6436 if (DEBUG_AP) { Log.d(TAG, "addMixForPolicy for " + pcb.asBinder()
6437 + " with config:" + policyConfig); }
Jean-Michel Trivi0212be52014-11-24 14:43:10 -08006438 synchronized (mAudioPolicies) {
Jean-Michel Triviaf576a02018-02-14 08:57:46 -08006439 final AudioPolicyProxy app =
6440 checkUpdateForPolicy(pcb, "Cannot add AudioMix in audio policy");
6441 if (app == null){
6442 return AudioManager.ERROR;
6443 }
6444 app.addMixes(policyConfig.getMixes());
6445 }
6446 return AudioManager.SUCCESS;
6447 }
6448
6449 public int removeMixForPolicy(AudioPolicyConfig policyConfig, IAudioPolicyCallback pcb) {
6450 if (DEBUG_AP) { Log.d(TAG, "removeMixForPolicy for " + pcb.asBinder()
6451 + " with config:" + policyConfig); }
6452 synchronized (mAudioPolicies) {
6453 final AudioPolicyProxy app =
6454 checkUpdateForPolicy(pcb, "Cannot add AudioMix in audio policy");
6455 if (app == null) {
6456 return AudioManager.ERROR;
6457 }
6458 app.removeMixes(policyConfig.getMixes());
6459 }
6460 return AudioManager.SUCCESS;
6461 }
6462
Jean-Michel Trivid6f65de2018-12-18 18:49:14 -08006463 /** see AudioPolicy.setUidDeviceAffinity() */
6464 public int setUidDeviceAffinity(IAudioPolicyCallback pcb, int uid,
Jean-Michel Trivif93107f2019-01-08 09:38:25 -08006465 @NonNull int[] deviceTypes, @NonNull String[] deviceAddresses) {
6466 if (DEBUG_AP) {
6467 Log.d(TAG, "setUidDeviceAffinity for " + pcb.asBinder() + " uid:" + uid);
6468 }
Jean-Michel Trivid6f65de2018-12-18 18:49:14 -08006469 synchronized (mAudioPolicies) {
6470 final AudioPolicyProxy app =
6471 checkUpdateForPolicy(pcb, "Cannot change device affinity in audio policy");
6472 if (app == null) {
6473 return AudioManager.ERROR;
6474 }
6475 if (!app.hasMixRoutedToDevices(deviceTypes, deviceAddresses)) {
6476 return AudioManager.ERROR;
6477 }
Jean-Michel Trivif93107f2019-01-08 09:38:25 -08006478 return app.setUidDeviceAffinities(uid, deviceTypes, deviceAddresses);
Jean-Michel Trivid6f65de2018-12-18 18:49:14 -08006479 }
Jean-Michel Trivid6f65de2018-12-18 18:49:14 -08006480 }
6481
6482 /** see AudioPolicy.removeUidDeviceAffinity() */
6483 public int removeUidDeviceAffinity(IAudioPolicyCallback pcb, int uid) {
Jean-Michel Trivif93107f2019-01-08 09:38:25 -08006484 if (DEBUG_AP) {
6485 Log.d(TAG, "removeUidDeviceAffinity for " + pcb.asBinder() + " uid:" + uid);
6486 }
Jean-Michel Trivid6f65de2018-12-18 18:49:14 -08006487 synchronized (mAudioPolicies) {
6488 final AudioPolicyProxy app =
6489 checkUpdateForPolicy(pcb, "Cannot remove device affinity in audio policy");
6490 if (app == null) {
6491 return AudioManager.ERROR;
6492 }
Jean-Michel Trivif93107f2019-01-08 09:38:25 -08006493 return app.removeUidDeviceAffinities(uid);
Jean-Michel Trivid6f65de2018-12-18 18:49:14 -08006494 }
Jean-Michel Trivid6f65de2018-12-18 18:49:14 -08006495 }
6496
Jean-Michel Triviaf576a02018-02-14 08:57:46 -08006497 public int setFocusPropertiesForPolicy(int duckingBehavior, IAudioPolicyCallback pcb) {
6498 if (DEBUG_AP) Log.d(TAG, "setFocusPropertiesForPolicy() duck behavior=" + duckingBehavior
6499 + " policy " + pcb.asBinder());
6500 synchronized (mAudioPolicies) {
6501 final AudioPolicyProxy app =
6502 checkUpdateForPolicy(pcb, "Cannot change audio policy focus properties");
6503 if (app == null){
6504 return AudioManager.ERROR;
6505 }
Jean-Michel Trivi0212be52014-11-24 14:43:10 -08006506 if (!mAudioPolicies.containsKey(pcb.asBinder())) {
6507 Slog.e(TAG, "Cannot change audio policy focus properties, unregistered policy");
6508 return AudioManager.ERROR;
6509 }
Jean-Michel Trivi0212be52014-11-24 14:43:10 -08006510 if (duckingBehavior == AudioPolicy.FOCUS_POLICY_DUCKING_IN_POLICY) {
6511 // is there already one policy managing ducking?
Eric Laurent0867bed2015-05-20 14:49:08 -07006512 for (AudioPolicyProxy policy : mAudioPolicies.values()) {
Jean-Michel Trivi0212be52014-11-24 14:43:10 -08006513 if (policy.mFocusDuckBehavior == AudioPolicy.FOCUS_POLICY_DUCKING_IN_POLICY) {
6514 Slog.e(TAG, "Cannot change audio policy ducking behavior, already handled");
6515 return AudioManager.ERROR;
6516 }
6517 }
6518 }
6519 app.mFocusDuckBehavior = duckingBehavior;
6520 mMediaFocusControl.setDuckingInExtPolicyAvailable(
6521 duckingBehavior == AudioPolicy.FOCUS_POLICY_DUCKING_IN_POLICY);
6522 }
6523 return AudioManager.SUCCESS;
6524 }
6525
Jean-Michel Trivi610aa9b2018-01-27 15:42:42 -08006526 private final Object mExtVolumeControllerLock = new Object();
6527 private IAudioPolicyCallback mExtVolumeController;
6528 private void setExtVolumeController(IAudioPolicyCallback apc) {
6529 if (!mContext.getResources().getBoolean(
6530 com.android.internal.R.bool.config_handleVolumeKeysInWindowManager)) {
6531 Log.e(TAG, "Cannot set external volume controller: device not set for volume keys" +
6532 " handled in PhoneWindowManager");
6533 return;
6534 }
6535 synchronized (mExtVolumeControllerLock) {
6536 if (mExtVolumeController != null && !mExtVolumeController.asBinder().pingBinder()) {
6537 Log.e(TAG, "Cannot set external volume controller: existing controller");
6538 }
6539 mExtVolumeController = apc;
6540 }
6541 }
6542
Jean-Michel Trivi1b3541d2014-11-25 12:53:41 -08006543 private void dumpAudioPolicies(PrintWriter pw) {
6544 pw.println("\nAudio policies:");
6545 synchronized (mAudioPolicies) {
Eric Laurent0867bed2015-05-20 14:49:08 -07006546 for (AudioPolicyProxy policy : mAudioPolicies.values()) {
Jean-Michel Trivi1b3541d2014-11-25 12:53:41 -08006547 pw.println(policy.toLogFriendlyString());
6548 }
6549 }
6550 }
6551
Jean-Michel Trivi958876f2014-11-16 15:40:22 -08006552 //======================
Jean-Michel Trivid3c71f02015-12-07 11:59:31 -08006553 // Audio policy callbacks from AudioSystem for dynamic policies
Jean-Michel Trivi5a561092015-04-23 18:48:08 -07006554 //======================
6555 private final AudioSystem.DynamicPolicyCallback mDynPolicyCallback =
6556 new AudioSystem.DynamicPolicyCallback() {
6557 public void onDynamicPolicyMixStateUpdate(String regId, int state) {
6558 if (!TextUtils.isEmpty(regId)) {
6559 sendMsg(mAudioHandler, MSG_DYN_POLICY_MIX_STATE_UPDATE, SENDMSG_QUEUE,
6560 state /*arg1*/, 0 /*arg2 ignored*/, regId /*obj*/, 0 /*delay*/);
6561 }
6562 }
6563 };
6564
6565 private void onDynPolicyMixStateUpdate(String regId, int state) {
6566 if (DEBUG_AP) Log.d(TAG, "onDynamicPolicyMixStateUpdate("+ regId + ", " + state +")");
6567 synchronized (mAudioPolicies) {
6568 for (AudioPolicyProxy policy : mAudioPolicies.values()) {
6569 for (AudioMix mix : policy.getMixes()) {
6570 if (mix.getRegistration().equals(regId)) {
6571 try {
6572 policy.mPolicyCallback.notifyMixStateUpdate(regId, state);
6573 } catch (RemoteException e) {
6574 Log.e(TAG, "Can't call notifyMixStateUpdate() on IAudioPolicyCallback "
6575 + policy.mPolicyCallback.asBinder(), e);
6576 }
6577 return;
6578 }
6579 }
6580 }
6581 }
Jean-Michel Trivid3c71f02015-12-07 11:59:31 -08006582 }
Jean-Michel Trivi5a561092015-04-23 18:48:08 -07006583
Jean-Michel Trivid3c71f02015-12-07 11:59:31 -08006584 //======================
6585 // Audio policy callbacks from AudioSystem for recording configuration updates
6586 //======================
Jean-Michel Trivi66ffacf2017-02-04 17:25:31 -08006587 private final RecordingActivityMonitor mRecordMonitor;
Jean-Michel Trivid3c71f02015-12-07 11:59:31 -08006588
6589 public void registerRecordingCallback(IRecordingConfigDispatcher rcdb) {
Jean-Michel Trivi66ffacf2017-02-04 17:25:31 -08006590 final boolean isPrivileged =
6591 (PackageManager.PERMISSION_GRANTED == mContext.checkCallingPermission(
6592 android.Manifest.permission.MODIFY_AUDIO_ROUTING));
6593 mRecordMonitor.registerRecordingCallback(rcdb, isPrivileged);
Jean-Michel Trivid3c71f02015-12-07 11:59:31 -08006594 }
6595
6596 public void unregisterRecordingCallback(IRecordingConfigDispatcher rcdb) {
6597 mRecordMonitor.unregisterRecordingCallback(rcdb);
6598 }
6599
Jean-Michel Trivif04fab12016-05-19 10:42:35 -07006600 public List<AudioRecordingConfiguration> getActiveRecordingConfigurations() {
Jean-Michel Trivi66ffacf2017-02-04 17:25:31 -08006601 final boolean isPrivileged =
6602 (PackageManager.PERMISSION_GRANTED == mContext.checkCallingPermission(
6603 android.Manifest.permission.MODIFY_AUDIO_ROUTING));
6604 return mRecordMonitor.getActiveRecordingConfigurations(isPrivileged);
Jean-Michel Trivi5a561092015-04-23 18:48:08 -07006605 }
6606
Robin Lee7af9a742017-02-20 14:47:30 +00006607 public void disableRingtoneSync(final int userId) {
Andre Lago7bdc6d82016-09-22 18:00:41 +01006608 final int callingUserId = UserHandle.getCallingUserId();
Robin Lee7af9a742017-02-20 14:47:30 +00006609 if (callingUserId != userId) {
6610 mContext.enforceCallingOrSelfPermission(Manifest.permission.INTERACT_ACROSS_USERS_FULL,
6611 "disable sound settings syncing for another profile");
6612 }
Andre Lago7bdc6d82016-09-22 18:00:41 +01006613 final long token = Binder.clearCallingIdentity();
6614 try {
Robin Lee7af9a742017-02-20 14:47:30 +00006615 // Disable the sync setting so the profile uses its own sound settings.
6616 Settings.Secure.putIntForUser(mContentResolver, Settings.Secure.SYNC_PARENT_SOUNDS,
6617 0 /* false */, userId);
Andre Lago7bdc6d82016-09-22 18:00:41 +01006618 } finally {
6619 Binder.restoreCallingIdentity(token);
6620 }
6621 }
6622
Jean-Michel Trivi5a561092015-04-23 18:48:08 -07006623 //======================
Jean-Michel Trivi46e310b2017-01-04 15:58:02 -08006624 // Audio playback notification
Jean-Michel Trivi292a6a42016-12-01 08:32:15 -08006625 //======================
Eric Laurente5a351c2017-09-27 20:11:51 -07006626 private final PlaybackActivityMonitor mPlaybackMonitor;
Jean-Michel Trivi292a6a42016-12-01 08:32:15 -08006627
6628 public void registerPlaybackCallback(IPlaybackConfigDispatcher pcdb) {
Jean-Michel Trivi44a8f532017-01-02 14:36:43 -08006629 final boolean isPrivileged =
Jaewan Kim92dea332017-02-02 11:52:08 +09006630 (PackageManager.PERMISSION_GRANTED == mContext.checkCallingOrSelfPermission(
Jean-Michel Trivi292a6a42016-12-01 08:32:15 -08006631 android.Manifest.permission.MODIFY_AUDIO_ROUTING));
6632 mPlaybackMonitor.registerPlaybackCallback(pcdb, isPrivileged);
6633 }
6634
6635 public void unregisterPlaybackCallback(IPlaybackConfigDispatcher pcdb) {
6636 mPlaybackMonitor.unregisterPlaybackCallback(pcdb);
6637 }
6638
6639 public List<AudioPlaybackConfiguration> getActivePlaybackConfigurations() {
Jean-Michel Trivi44a8f532017-01-02 14:36:43 -08006640 final boolean isPrivileged =
Jaewan Kim92dea332017-02-02 11:52:08 +09006641 (PackageManager.PERMISSION_GRANTED == mContext.checkCallingOrSelfPermission(
Jean-Michel Trivi44a8f532017-01-02 14:36:43 -08006642 android.Manifest.permission.MODIFY_AUDIO_ROUTING));
6643 return mPlaybackMonitor.getActivePlaybackConfigurations(isPrivileged);
Jean-Michel Trivi292a6a42016-12-01 08:32:15 -08006644 }
6645
Jean-Michel Trivi44a8f532017-01-02 14:36:43 -08006646 public int trackPlayer(PlayerBase.PlayerIdCard pic) {
6647 return mPlaybackMonitor.trackPlayer(pic);
Jean-Michel Trivi292a6a42016-12-01 08:32:15 -08006648 }
6649
6650 public void playerAttributes(int piid, AudioAttributes attr) {
Jean-Michel Trivi46e310b2017-01-04 15:58:02 -08006651 mPlaybackMonitor.playerAttributes(piid, attr, Binder.getCallingUid());
Jean-Michel Trivi292a6a42016-12-01 08:32:15 -08006652 }
6653
6654 public void playerEvent(int piid, int event) {
Jean-Michel Trivi46e310b2017-01-04 15:58:02 -08006655 mPlaybackMonitor.playerEvent(piid, event, Binder.getCallingUid());
Jean-Michel Trivi292a6a42016-12-01 08:32:15 -08006656 }
6657
Jean-Michel Trivi3120059d2017-08-28 12:40:55 -07006658 public void playerHasOpPlayAudio(int piid, boolean hasOpPlayAudio) {
6659 mPlaybackMonitor.playerHasOpPlayAudio(piid, hasOpPlayAudio, Binder.getCallingUid());
6660 }
6661
Jean-Michel Trivi292a6a42016-12-01 08:32:15 -08006662 public void releasePlayer(int piid) {
Jean-Michel Trivi46e310b2017-01-04 15:58:02 -08006663 mPlaybackMonitor.releasePlayer(piid, Binder.getCallingUid());
Jean-Michel Trivi292a6a42016-12-01 08:32:15 -08006664 }
6665
6666 //======================
Jean-Michel Trivi58850372018-09-14 16:01:28 -07006667 // Audio device management
6668 //======================
6669 private final AudioDeviceBroker mDeviceBroker;
6670
6671 //======================
Jean-Michel Trivi958876f2014-11-16 15:40:22 -08006672 // Audio policy proxy
6673 //======================
Jean-Michel Trivid6f65de2018-12-18 18:49:14 -08006674 private static final class AudioDeviceArray {
6675 final @NonNull int[] mDeviceTypes;
6676 final @NonNull String[] mDeviceAddresses;
6677 AudioDeviceArray(@NonNull int[] types, @NonNull String[] addresses) {
6678 mDeviceTypes = types;
6679 mDeviceAddresses = addresses;
6680 }
6681 }
6682
Jean-Michel Trivi8fdb0d42014-07-16 19:08:37 -07006683 /**
Jean-Michel Trivi1b3541d2014-11-25 12:53:41 -08006684 * This internal class inherits from AudioPolicyConfig, each instance contains all the
6685 * mixes of an AudioPolicy and their configurations.
Jean-Michel Trivi8fdb0d42014-07-16 19:08:37 -07006686 */
6687 public class AudioPolicyProxy extends AudioPolicyConfig implements IBinder.DeathRecipient {
Jean-Michel Trivia8b6bd82014-07-01 09:48:46 -07006688 private static final String TAG = "AudioPolicyProxy";
Jean-Michel Trivi610aa9b2018-01-27 15:42:42 -08006689 final IAudioPolicyCallback mPolicyCallback;
6690 final boolean mHasFocusListener;
6691 final boolean mIsVolumeController;
Jean-Michel Trivid6f65de2018-12-18 18:49:14 -08006692 final HashMap<Integer, AudioDeviceArray> mUidDeviceAffinities =
6693 new HashMap<Integer, AudioDeviceArray>();
Jean-Michel Trivi0212be52014-11-24 14:43:10 -08006694 /**
6695 * Audio focus ducking behavior for an audio policy.
6696 * This variable reflects the value that was successfully set in
6697 * {@link AudioService#setFocusPropertiesForPolicy(int, IAudioPolicyCallback)}. This
6698 * implies that a value of FOCUS_POLICY_DUCKING_IN_POLICY means the corresponding policy
6699 * is handling ducking for audio focus.
6700 */
6701 int mFocusDuckBehavior = AudioPolicy.FOCUS_POLICY_DUCKING_DEFAULT;
Jean-Michel Trivi126cf032017-04-02 23:19:02 -07006702 boolean mIsFocusPolicy = false;
Jean-Michel Trivi0212be52014-11-24 14:43:10 -08006703
6704 AudioPolicyProxy(AudioPolicyConfig config, IAudioPolicyCallback token,
Jean-Michel Trivi610aa9b2018-01-27 15:42:42 -08006705 boolean hasFocusListener, boolean isFocusPolicy, boolean isVolumeController) {
Jean-Michel Trivi8fdb0d42014-07-16 19:08:37 -07006706 super(config);
Jean-Michel Trivi1b3541d2014-11-25 12:53:41 -08006707 setRegistration(new String(config.hashCode() + ":ap:" + mAudioPolicyCounter++));
Jean-Michel Trivi5a561092015-04-23 18:48:08 -07006708 mPolicyCallback = token;
Jean-Michel Trivi0212be52014-11-24 14:43:10 -08006709 mHasFocusListener = hasFocusListener;
Jean-Michel Trivi610aa9b2018-01-27 15:42:42 -08006710 mIsVolumeController = isVolumeController;
Jean-Michel Trivi0212be52014-11-24 14:43:10 -08006711 if (mHasFocusListener) {
Jean-Michel Trivi5a561092015-04-23 18:48:08 -07006712 mMediaFocusControl.addFocusFollower(mPolicyCallback);
Jean-Michel Trivi126cf032017-04-02 23:19:02 -07006713 // can only ever be true if there is a focus listener
6714 if (isFocusPolicy) {
6715 mIsFocusPolicy = true;
6716 mMediaFocusControl.setFocusPolicy(mPolicyCallback);
6717 }
Jean-Michel Trivi0212be52014-11-24 14:43:10 -08006718 }
Jean-Michel Trivi610aa9b2018-01-27 15:42:42 -08006719 if (mIsVolumeController) {
6720 setExtVolumeController(mPolicyCallback);
6721 }
Eric Laurent7f5eb9f2014-12-01 19:36:30 -08006722 connectMixes();
Jean-Michel Trivia8b6bd82014-07-01 09:48:46 -07006723 }
6724
6725 public void binderDied() {
6726 synchronized (mAudioPolicies) {
Jean-Michel Trivi5a561092015-04-23 18:48:08 -07006727 Log.i(TAG, "audio policy " + mPolicyCallback + " died");
Jean-Michel Trivi0212be52014-11-24 14:43:10 -08006728 release();
Jean-Michel Trivi5a561092015-04-23 18:48:08 -07006729 mAudioPolicies.remove(mPolicyCallback.asBinder());
Jean-Michel Trivi8fdb0d42014-07-16 19:08:37 -07006730 }
Jean-Michel Trivi610aa9b2018-01-27 15:42:42 -08006731 if (mIsVolumeController) {
6732 synchronized (mExtVolumeControllerLock) {
6733 mExtVolumeController = null;
6734 }
6735 }
Jean-Michel Trivi8fdb0d42014-07-16 19:08:37 -07006736 }
6737
Jean-Michel Trivi0212be52014-11-24 14:43:10 -08006738 String getRegistrationId() {
Jean-Michel Trivi1b3541d2014-11-25 12:53:41 -08006739 return getRegistration();
Jean-Michel Trivi8fdb0d42014-07-16 19:08:37 -07006740 }
6741
Jean-Michel Trivi0212be52014-11-24 14:43:10 -08006742 void release() {
Jean-Michel Trivi126cf032017-04-02 23:19:02 -07006743 if (mIsFocusPolicy) {
6744 mMediaFocusControl.unsetFocusPolicy(mPolicyCallback);
6745 }
Jean-Michel Trivi0212be52014-11-24 14:43:10 -08006746 if (mFocusDuckBehavior == AudioPolicy.FOCUS_POLICY_DUCKING_IN_POLICY) {
6747 mMediaFocusControl.setDuckingInExtPolicyAvailable(false);
6748 }
6749 if (mHasFocusListener) {
Jean-Michel Trivi5a561092015-04-23 18:48:08 -07006750 mMediaFocusControl.removeFocusFollower(mPolicyCallback);
Jean-Michel Trivi0212be52014-11-24 14:43:10 -08006751 }
Eric Laurent66b69672018-01-26 18:30:51 -08006752 final long identity = Binder.clearCallingIdentity();
Eric Laurent7f5eb9f2014-12-01 19:36:30 -08006753 AudioSystem.registerPolicyMixes(mMixes, false);
Eric Laurent66b69672018-01-26 18:30:51 -08006754 Binder.restoreCallingIdentity(identity);
Jean-Michel Trivi8fdb0d42014-07-16 19:08:37 -07006755 }
6756
Jean-Michel Trivi7db2d8f2018-03-06 10:30:59 -08006757 boolean hasMixAffectingUsage(int usage) {
6758 for (AudioMix mix : mMixes) {
6759 if (mix.isAffectingUsage(usage)) {
6760 return true;
6761 }
6762 }
6763 return false;
6764 }
6765
Jean-Michel Trivid6f65de2018-12-18 18:49:14 -08006766 // Verify all the devices in the array are served by mixes defined in this policy
6767 boolean hasMixRoutedToDevices(@NonNull int[] deviceTypes,
6768 @NonNull String[] deviceAddresses) {
6769 for (int i = 0; i < deviceTypes.length; i++) {
6770 boolean hasDevice = false;
6771 for (AudioMix mix : mMixes) {
6772 // this will check both that the mix has ROUTE_FLAG_RENDER and the device
6773 // is reached by this mix
6774 if (mix.isRoutedToDevice(deviceTypes[i], deviceAddresses[i])) {
6775 hasDevice = true;
6776 break;
6777 }
6778 }
6779 if (!hasDevice) {
6780 return false;
6781 }
6782 }
6783 return true;
6784 }
6785
Jean-Michel Triviaf576a02018-02-14 08:57:46 -08006786 void addMixes(@NonNull ArrayList<AudioMix> mixes) {
6787 // TODO optimize to not have to unregister the mixes already in place
6788 synchronized (mMixes) {
6789 AudioSystem.registerPolicyMixes(mMixes, false);
6790 this.add(mixes);
6791 AudioSystem.registerPolicyMixes(mMixes, true);
6792 }
6793 }
6794
6795 void removeMixes(@NonNull ArrayList<AudioMix> mixes) {
6796 // TODO optimize to not have to unregister the mixes already in place
6797 synchronized (mMixes) {
6798 AudioSystem.registerPolicyMixes(mMixes, false);
6799 this.remove(mixes);
6800 AudioSystem.registerPolicyMixes(mMixes, true);
6801 }
6802 }
6803
Eric Laurent7f5eb9f2014-12-01 19:36:30 -08006804 void connectMixes() {
Eric Laurent66b69672018-01-26 18:30:51 -08006805 final long identity = Binder.clearCallingIdentity();
Eric Laurent7f5eb9f2014-12-01 19:36:30 -08006806 AudioSystem.registerPolicyMixes(mMixes, true);
Eric Laurent66b69672018-01-26 18:30:51 -08006807 Binder.restoreCallingIdentity(identity);
Jean-Michel Trivia8b6bd82014-07-01 09:48:46 -07006808 }
Jean-Michel Trivid6f65de2018-12-18 18:49:14 -08006809
Jean-Michel Trivif93107f2019-01-08 09:38:25 -08006810 int setUidDeviceAffinities(int uid, @NonNull int[] types, @NonNull String[] addresses) {
Jean-Michel Trivid6f65de2018-12-18 18:49:14 -08006811 final Integer Uid = new Integer(uid);
Jean-Michel Trivif93107f2019-01-08 09:38:25 -08006812 int res;
Jean-Michel Trivid6f65de2018-12-18 18:49:14 -08006813 if (mUidDeviceAffinities.remove(Uid) != null) {
6814 final long identity = Binder.clearCallingIdentity();
Jean-Michel Trivif93107f2019-01-08 09:38:25 -08006815 res = AudioSystem.removeUidDeviceAffinities(uid);
Jean-Michel Trivid6f65de2018-12-18 18:49:14 -08006816 Binder.restoreCallingIdentity(identity);
Jean-Michel Trivif93107f2019-01-08 09:38:25 -08006817 if (res != AudioSystem.SUCCESS) {
6818 Log.e(TAG, "AudioSystem. removeUidDeviceAffinities(" + uid + ") failed, "
6819 + " cannot call AudioSystem.setUidDeviceAffinities");
6820 return AudioManager.ERROR;
6821 }
Jean-Michel Trivid6f65de2018-12-18 18:49:14 -08006822 }
6823 final long identity = Binder.clearCallingIdentity();
Jean-Michel Trivif93107f2019-01-08 09:38:25 -08006824 res = AudioSystem.setUidDeviceAffinities(uid, types, addresses);
Jean-Michel Trivid6f65de2018-12-18 18:49:14 -08006825 Binder.restoreCallingIdentity(identity);
6826 if (res == AudioSystem.SUCCESS) {
6827 mUidDeviceAffinities.put(Uid, new AudioDeviceArray(types, addresses));
Jean-Michel Trivif93107f2019-01-08 09:38:25 -08006828 return AudioManager.SUCCESS;
Jean-Michel Trivid6f65de2018-12-18 18:49:14 -08006829 }
Jean-Michel Trivif93107f2019-01-08 09:38:25 -08006830 Log.e(TAG, "AudioSystem. setUidDeviceAffinities(" + uid + ") failed");
6831 return AudioManager.ERROR;
Jean-Michel Trivid6f65de2018-12-18 18:49:14 -08006832 }
6833
Jean-Michel Trivif93107f2019-01-08 09:38:25 -08006834 int removeUidDeviceAffinities(int uid) {
Jean-Michel Trivid6f65de2018-12-18 18:49:14 -08006835 if (mUidDeviceAffinities.remove(new Integer(uid)) != null) {
6836 final long identity = Binder.clearCallingIdentity();
Jean-Michel Trivif93107f2019-01-08 09:38:25 -08006837 final int res = AudioSystem.removeUidDeviceAffinities(uid);
Jean-Michel Trivid6f65de2018-12-18 18:49:14 -08006838 Binder.restoreCallingIdentity(identity);
Jean-Michel Trivif93107f2019-01-08 09:38:25 -08006839 if (res == AudioSystem.SUCCESS) {
6840 return AudioManager.SUCCESS;
6841 }
Jean-Michel Trivid6f65de2018-12-18 18:49:14 -08006842 }
Jean-Michel Trivif93107f2019-01-08 09:38:25 -08006843 Log.e(TAG, "AudioSystem. removeUidDeviceAffinities failed");
6844 return AudioManager.ERROR;
Jean-Michel Trivid6f65de2018-12-18 18:49:14 -08006845 }
Jean-Michel Trivia8b6bd82014-07-01 09:48:46 -07006846 };
6847
Jean-Michel Trivi126cf032017-04-02 23:19:02 -07006848 //======================
6849 // Audio policy: focus
6850 //======================
6851 /** */
6852 public int dispatchFocusChange(AudioFocusInfo afi, int focusChange, IAudioPolicyCallback pcb) {
Jean-Michel Trivie2d8aae2018-01-30 15:09:47 -08006853 if (afi == null) {
6854 throw new IllegalArgumentException("Illegal null AudioFocusInfo");
6855 }
6856 if (pcb == null) {
6857 throw new IllegalArgumentException("Illegal null AudioPolicy callback");
6858 }
Jean-Michel Trivi126cf032017-04-02 23:19:02 -07006859 synchronized (mAudioPolicies) {
6860 if (!mAudioPolicies.containsKey(pcb.asBinder())) {
6861 throw new IllegalStateException("Unregistered AudioPolicy for focus dispatch");
6862 }
6863 return mMediaFocusControl.dispatchFocusChange(afi, focusChange);
6864 }
6865 }
6866
Jean-Michel Trivie2d8aae2018-01-30 15:09:47 -08006867 public void setFocusRequestResultFromExtPolicy(AudioFocusInfo afi, int requestResult,
6868 IAudioPolicyCallback pcb) {
6869 if (afi == null) {
6870 throw new IllegalArgumentException("Illegal null AudioFocusInfo");
6871 }
6872 if (pcb == null) {
6873 throw new IllegalArgumentException("Illegal null AudioPolicy callback");
6874 }
6875 synchronized (mAudioPolicies) {
6876 if (!mAudioPolicies.containsKey(pcb.asBinder())) {
6877 throw new IllegalStateException("Unregistered AudioPolicy for external focus");
6878 }
6879 mMediaFocusControl.setFocusRequestResultFromExtPolicy(afi, requestResult);
6880 }
6881 }
6882
6883
Jean-Michel Trivi126cf032017-04-02 23:19:02 -07006884 //======================
Eric Laurent1d3cdce2018-01-20 10:31:21 -08006885 // Audioserver state displatch
6886 //======================
6887 private class AsdProxy implements IBinder.DeathRecipient {
6888 private final IAudioServerStateDispatcher mAsd;
6889
6890 AsdProxy(IAudioServerStateDispatcher asd) {
6891 mAsd = asd;
6892 }
6893
6894 public void binderDied() {
6895 synchronized (mAudioServerStateListeners) {
6896 mAudioServerStateListeners.remove(mAsd.asBinder());
6897 }
6898 }
6899
6900 IAudioServerStateDispatcher callback() {
6901 return mAsd;
6902 }
6903 }
6904
6905 private HashMap<IBinder, AsdProxy> mAudioServerStateListeners =
6906 new HashMap<IBinder, AsdProxy>();
6907
6908 private void checkMonitorAudioServerStatePermission() {
6909 if (!(mContext.checkCallingOrSelfPermission(
6910 android.Manifest.permission.MODIFY_PHONE_STATE) ==
6911 PackageManager.PERMISSION_GRANTED ||
6912 mContext.checkCallingOrSelfPermission(
6913 android.Manifest.permission.MODIFY_AUDIO_ROUTING) ==
6914 PackageManager.PERMISSION_GRANTED)) {
6915 throw new SecurityException("Not allowed to monitor audioserver state");
6916 }
6917 }
6918
6919 public void registerAudioServerStateDispatcher(IAudioServerStateDispatcher asd) {
6920 checkMonitorAudioServerStatePermission();
6921 synchronized (mAudioServerStateListeners) {
6922 if (mAudioServerStateListeners.containsKey(asd.asBinder())) {
6923 Slog.w(TAG, "Cannot re-register audio server state dispatcher");
6924 return;
6925 }
6926 AsdProxy asdp = new AsdProxy(asd);
6927 try {
6928 asd.asBinder().linkToDeath(asdp, 0/*flags*/);
6929 } catch (RemoteException e) {
6930
6931 }
6932 mAudioServerStateListeners.put(asd.asBinder(), asdp);
6933 }
6934 }
6935
6936 public void unregisterAudioServerStateDispatcher(IAudioServerStateDispatcher asd) {
6937 checkMonitorAudioServerStatePermission();
6938 synchronized (mAudioServerStateListeners) {
6939 AsdProxy asdp = mAudioServerStateListeners.remove(asd.asBinder());
6940 if (asdp == null) {
6941 Slog.w(TAG, "Trying to unregister unknown audioserver state dispatcher for pid "
6942 + Binder.getCallingPid() + " / uid " + Binder.getCallingUid());
6943 return;
6944 } else {
6945 asd.asBinder().unlinkToDeath(asdp, 0/*flags*/);
6946 }
6947 }
6948 }
6949
6950 public boolean isAudioServerRunning() {
6951 checkMonitorAudioServerStatePermission();
6952 return (AudioSystem.checkAudioFlinger() == AudioSystem.AUDIO_STATUS_OK);
6953 }
6954
6955 //======================
Jean-Michel Trivi126cf032017-04-02 23:19:02 -07006956 // misc
6957 //======================
Jean-Michel Triviaf576a02018-02-14 08:57:46 -08006958 private final HashMap<IBinder, AudioPolicyProxy> mAudioPolicies =
Jean-Michel Trivia8b6bd82014-07-01 09:48:46 -07006959 new HashMap<IBinder, AudioPolicyProxy>();
Jean-Michel Triviaf576a02018-02-14 08:57:46 -08006960 @GuardedBy("mAudioPolicies")
6961 private int mAudioPolicyCounter = 0;
Phil Burkac0f7042016-02-24 12:19:08 -08006962}