blob: e38defdae0d36a35fd83f7236eba3cdc8cfd615c [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;
jiabinad225202019-03-20 15:22:50 -070081import android.media.MediaExtractor;
82import android.media.MediaFormat;
John Spurlock61560172015-02-06 19:46:04 -050083import android.media.MediaPlayer;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080084import android.media.MediaPlayer.OnCompletionListener;
85import android.media.MediaPlayer.OnErrorListener;
Jean-Michel Trivi292a6a42016-12-01 08:32:15 -080086import android.media.PlayerBase;
Beverly925cde82018-01-23 09:31:23 -050087import android.media.SoundPool;
88import android.media.VolumePolicy;
89import android.media.audiofx.AudioEffect;
Jean-Michel Trivi5a561092015-04-23 18:48:08 -070090import android.media.audiopolicy.AudioMix;
Jean-Michel Trivi958876f2014-11-16 15:40:22 -080091import android.media.audiopolicy.AudioPolicy;
Jean-Michel Trivia8b6bd82014-07-01 09:48:46 -070092import android.media.audiopolicy.AudioPolicyConfig;
Hayden Gomes6d69bde2019-04-04 13:10:13 -070093import android.media.audiopolicy.AudioProductStrategy;
François Gaffie9c362102018-09-21 17:43:52 +020094import android.media.audiopolicy.AudioVolumeGroup;
Jean-Michel Trivi0212be52014-11-24 14:43:10 -080095import android.media.audiopolicy.IAudioPolicyCallback;
Kevin Rocard2fe8b8b2019-02-20 11:25:23 -080096import android.media.projection.IMediaProjection;
97import android.media.projection.IMediaProjectionManager;
jiabinad225202019-03-20 15:22:50 -070098import android.net.Uri;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080099import android.os.Binder;
Eric Laurentc18c9132013-04-12 17:24:56 -0700100import android.os.Build;
Makoto Onukid45a4a22015-11-02 17:17:38 -0800101import android.os.Bundle;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800102import android.os.Environment;
103import android.os.Handler;
104import android.os.IBinder;
105import android.os.Looper;
106import android.os.Message;
Jean-Michel Trivic6802222012-04-30 11:15:03 -0700107import android.os.PowerManager;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800108import android.os.RemoteException;
Kevin Rocard2fe8b8b2019-02-20 11:25:23 -0800109import android.os.ServiceManager;
John Spurlock33f4e042014-07-11 13:10:58 -0400110import android.os.SystemClock;
Jaikumar Ganesh82aa7f02010-09-27 17:05:10 -0700111import android.os.SystemProperties;
Dianne Hackborn5ac72a22012-08-29 18:32:08 -0700112import android.os.UserHandle;
Fyodor Kupolovb5013302015-04-17 17:59:14 -0700113import android.os.UserManager;
Makoto Onukid45a4a22015-11-02 17:17:38 -0800114import android.os.UserManagerInternal;
115import android.os.UserManagerInternal.UserRestrictionsListener;
Mike Digman55272862018-02-20 14:35:17 -0800116import android.os.VibrationEffect;
Eric Laurentbffc3d12012-05-07 17:43:49 -0700117import android.os.Vibrator;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800118import android.provider.Settings;
119import android.provider.Settings.System;
Beverly925cde82018-01-23 09:31:23 -0500120import android.service.notification.ZenModeConfig;
Tyler Gunnef9f6f92014-09-12 22:16:17 -0700121import android.telecom.TelecomManager;
Dianne Hackborn632ca412012-06-14 19:34:10 -0700122import android.text.TextUtils;
Fyodor Kupolovb5013302015-04-17 17:59:14 -0700123import android.util.AndroidRuntimeException;
Phil Weaverf1a9aff2017-03-23 17:21:29 -0700124import android.util.IntArray;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800125import android.util.Log;
John Spurlockaa5ee4d2014-07-25 13:05:12 -0400126import android.util.MathUtils;
Jean-Michel Trivia8b6bd82014-07-01 09:48:46 -0700127import android.util.Slog;
John Spurlock2bb02ec2015-03-02 13:13:06 -0500128import android.util.SparseIntArray;
Jean-Michel Trivid327f212010-03-16 21:44:33 -0700129import android.view.KeyEvent;
Jean-Michel Trivi873cc452014-09-11 17:25:09 -0700130import android.view.accessibility.AccessibilityManager;
Mike Digman55272862018-02-20 14:35:17 -0800131import android.widget.Toast;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800132
Jean-Michel Trivi8719a1d2017-11-06 11:52:51 -0800133import com.android.internal.annotations.GuardedBy;
Jeff Sharkeyfe9a53b2017-03-31 14:08:23 -0600134import com.android.internal.util.DumpUtils;
François Gaffie9c362102018-09-21 17:43:52 +0200135import com.android.internal.util.Preconditions;
Eric Laurente78fced2013-03-15 16:03:47 -0700136import com.android.internal.util.XmlUtils;
John Spurlock90874332015-03-10 16:00:54 -0400137import com.android.server.EventLogTags;
RoboErik0dac35a2014-08-12 15:48:49 -0700138import com.android.server.LocalServices;
Makoto Onukie1aef852015-10-15 17:28:35 -0700139import com.android.server.SystemService;
Beverly925cde82018-01-23 09:31:23 -0500140import com.android.server.audio.AudioServiceEvents.PhoneStateEvent;
141import com.android.server.audio.AudioServiceEvents.VolumeEvent;
Fyodor Kupolovb5013302015-04-17 17:59:14 -0700142import com.android.server.pm.UserManagerService;
Wale Ogunwale9e4f3e02018-05-17 09:35:39 -0700143import com.android.server.wm.ActivityTaskManagerInternal;
Eric Laurente78fced2013-03-15 16:03:47 -0700144
145import org.xmlpull.v1.XmlPullParserException;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800146
Jaekyun Seokc31033f2018-01-15 14:53:17 +0900147import java.io.File;
Jean-Michel Trivid5176cf2010-01-28 11:56:42 -0800148import java.io.FileDescriptor;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800149import java.io.IOException;
Jean-Michel Trivid5176cf2010-01-28 11:56:42 -0800150import java.io.PrintWriter;
Jean-Michel Trivi58850372018-09-14 16:01:28 -0700151import java.lang.annotation.Retention;
152import java.lang.annotation.RetentionPolicy;
Eric Laurente78fced2013-03-15 16:03:47 -0700153import java.lang.reflect.Field;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800154import java.util.ArrayList;
Jean-Michel Trivi7db2d8f2018-03-06 10:30:59 -0800155import java.util.Collection;
Eric Laurentc42ac9d2009-07-29 08:53:03 -0700156import java.util.HashMap;
157import java.util.Iterator;
Jaikumar Ganesh5a1e4cf2010-10-18 17:05:09 -0700158import java.util.List;
Jaikumar Ganesh82aa7f02010-09-27 17:05:10 -0700159import java.util.NoSuchElementException;
RoboErikd09bd0c2014-06-24 17:45:19 -0700160import java.util.Objects;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800161
162/**
163 * The implementation of the volume manager service.
164 * <p>
165 * This implementation focuses on delivering a responsive UI. Most methods are
166 * asynchronous to external calls. For example, the task of setting a volume
167 * will update our internal state, but in a separate thread will set the system
168 * volume and later persist to the database. Similarly, setting the ringer mode
169 * will update the state and broadcast a change and in a separate thread later
170 * persist the ringer mode.
171 *
172 * @hide
173 */
Jean-Michel Triviac487672016-11-11 10:05:18 -0800174public class AudioService extends IAudioService.Stub
175 implements AccessibilityManager.TouchExplorationStateChangeListener,
Jean-Michel Trivicfa55532017-01-18 11:17:51 -0800176 AccessibilityManager.AccessibilityServicesStateChangeListener {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800177
Jean-Michel Trivi58850372018-09-14 16:01:28 -0700178 private static final String TAG = "AS.AudioService";
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800179
Jean-Michel Trivi339567d2014-07-29 09:53:34 -0700180 /** Debug audio mode */
Jean-Michel Trivi58850372018-09-14 16:01:28 -0700181 protected static final boolean DEBUG_MODE = false;
Jean-Michel Trivi8fdb0d42014-07-16 19:08:37 -0700182
183 /** Debug audio policy feature */
Jean-Michel Trivi58850372018-09-14 16:01:28 -0700184 protected static final boolean DEBUG_AP = false;
Jean-Michel Trivi8fdb0d42014-07-16 19:08:37 -0700185
Jean-Michel Trivi3114ce32012-06-11 15:03:52 -0700186 /** Debug volumes */
Jean-Michel Trivi58850372018-09-14 16:01:28 -0700187 protected static final boolean DEBUG_VOL = false;
Jean-Michel Trivi18e7bce2011-08-26 12:11:36 -0700188
Paul McLean394a8e12015-03-03 10:29:19 -0700189 /** debug calls to devices APIs */
Jean-Michel Trivi58850372018-09-14 16:01:28 -0700190 protected static final boolean DEBUG_DEVICES = false;
191
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800192 /** How long to delay before persisting a change in volume/ringer mode. */
RoboErik45edba12012-03-27 17:54:36 -0700193 private static final int PERSIST_DELAY = 500;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800194
RoboErik5452e252015-02-06 15:33:53 -0800195 /** How long to delay after a volume down event before unmuting a stream */
196 private static final int UNMUTE_STREAM_DELAY = 350;
197
John Spurlock3346a802014-05-20 16:25:37 -0400198 /**
John Spurlocka11b4af2014-06-01 11:52:23 -0400199 * Only used in the result from {@link #checkForRingerModeChange(int, int, int)}
200 */
201 private static final int FLAG_ADJUST_VOLUME = 1;
202
Dianne Hackbornba50b97c2013-04-30 15:04:46 -0700203 private final Context mContext;
204 private final ContentResolver mContentResolver;
205 private final AppOpsManager mAppOps;
Eric Laurent212532b2014-07-21 15:43:18 -0700206
Eric Laurent212532b2014-07-21 15:43:18 -0700207 // the platform type affects volume and silent mode behavior
208 private final int mPlatformType;
209
Muyuan Li1ed6df62016-06-18 11:16:52 -0700210 // indicates whether the system maps all streams to a single stream.
211 private final boolean mIsSingleVolume;
212
Eric Laurent212532b2014-07-21 15:43:18 -0700213 private boolean isPlatformVoice() {
John Spurlock61560172015-02-06 19:46:04 -0500214 return mPlatformType == AudioSystem.PLATFORM_VOICE;
Eric Laurent212532b2014-07-21 15:43:18 -0700215 }
216
Jean-Michel Trivi58850372018-09-14 16:01:28 -0700217 /*package*/ boolean isPlatformTelevision() {
John Spurlock61560172015-02-06 19:46:04 -0500218 return mPlatformType == AudioSystem.PLATFORM_TELEVISION;
Eric Laurent212532b2014-07-21 15:43:18 -0700219 }
Jean-Michel Trivid5176cf2010-01-28 11:56:42 -0800220
Jean-Michel Trivi58850372018-09-14 16:01:28 -0700221 /*package*/ boolean isPlatformAutomotive() {
Hongwei Wangdaba1242018-05-29 14:36:16 -0700222 return mContext.getPackageManager().hasSystemFeature(PackageManager.FEATURE_AUTOMOTIVE);
223 }
224
John Spurlock3346a802014-05-20 16:25:37 -0400225 /** The controller for the volume UI. */
226 private final VolumeController mVolumeController = new VolumeController();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800227
228 // sendMsg() flags
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800229 /** If the msg is already queued, replace it with this one. */
230 private static final int SENDMSG_REPLACE = 0;
231 /** If the msg is already queued, ignore this one and leave the old. */
232 private static final int SENDMSG_NOOP = 1;
233 /** If the msg is already queued, queue this one and leave the old. */
234 private static final int SENDMSG_QUEUE = 2;
235
Jean-Michel Trivi3114ce32012-06-11 15:03:52 -0700236 // AudioHandler messages
Eric Laurent9bc8358d2011-11-18 16:43:31 -0800237 private static final int MSG_SET_DEVICE_VOLUME = 0;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800238 private static final int MSG_PERSIST_VOLUME = 1;
239 private static final int MSG_PERSIST_RINGER_MODE = 3;
Andy Hunged0ea402015-10-30 14:11:46 -0700240 private static final int MSG_AUDIO_SERVER_DIED = 4;
Eric Laurentdfb881f2013-07-18 14:41:39 -0700241 private static final int MSG_PLAY_SOUND_EFFECT = 5;
Eric Laurentdfb881f2013-07-18 14:41:39 -0700242 private static final int MSG_LOAD_SOUND_EFFECTS = 7;
243 private static final int MSG_SET_FORCE_USE = 8;
244 private static final int MSG_BT_HEADSET_CNCT_FAILED = 9;
245 private static final int MSG_SET_ALL_VOLUMES = 10;
Jean-Michel Trivi58850372018-09-14 16:01:28 -0700246 private static final int MSG_CHECK_MUSIC_ACTIVE = 11;
247 private static final int MSG_CONFIGURE_SAFE_MEDIA_VOLUME = 12;
248 private static final int MSG_CONFIGURE_SAFE_MEDIA_VOLUME_FORCED = 13;
249 private static final int MSG_PERSIST_SAFE_VOLUME_STATE = 14;
250 private static final int MSG_UNLOAD_SOUND_EFFECTS = 15;
251 private static final int MSG_SYSTEM_READY = 16;
252 private static final int MSG_PERSIST_MUSIC_ACTIVE_MS = 17;
253 private static final int MSG_UNMUTE_STREAM = 18;
254 private static final int MSG_DYN_POLICY_MIX_STATE_UPDATE = 19;
255 private static final int MSG_INDICATE_SYSTEM_READY = 20;
256 private static final int MSG_ACCESSORY_PLUG_MEDIA_UNMUTE = 21;
257 private static final int MSG_NOTIFY_VOL_EVENT = 22;
258 private static final int MSG_DISPATCH_AUDIO_SERVER_STATE = 23;
259 private static final int MSG_ENABLE_SURROUND_FORMATS = 24;
Jean-Michel Trivica49d312019-02-14 15:55:39 -0800260 private static final int MSG_UPDATE_RINGER_MODE = 25;
Jean-Michel Trivi5bbcd442019-04-18 12:07:34 -0700261 private static final int MSG_SET_DEVICE_STREAM_VOLUME = 26;
262 private static final int MSG_OBSERVE_DEVICES_FOR_ALL_STREAMS = 27;
Jean-Michel Trivi3114ce32012-06-11 15:03:52 -0700263 // start of messages handled under wakelock
264 // these messages can only be queued, i.e. sent with queueMsgUnderWakeLock(),
Jean-Michel Trivie12c39b2012-06-06 10:51:58 -0700265 // and not with sendMsg(..., ..., SENDMSG_QUEUE, ...)
Jean-Michel Trivi58850372018-09-14 16:01:28 -0700266 private static final int MSG_DISABLE_AUDIO_FOR_UID = 100;
Jean-Michel Trivi3114ce32012-06-11 15:03:52 -0700267 // end of messages handled under wakelock
Eric Laurentafbb0472011-12-15 09:04:23 -0800268
Eric Laurent0867bed2015-05-20 14:49:08 -0700269 // retry delay in case of failure to indicate system ready to AudioFlinger
270 private static final int INDICATE_SYSTEM_READY_RETRY_DELAY_MS = 1000;
271
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800272 /** @see AudioSystemThread */
273 private AudioSystemThread mAudioSystemThread;
274 /** @see AudioHandler */
275 private AudioHandler mAudioHandler;
276 /** @see VolumeStreamState */
277 private VolumeStreamState[] mStreamStates;
Jean-Michel Trivi58850372018-09-14 16:01:28 -0700278
Jean-Michel Trivi5bbcd442019-04-18 12:07:34 -0700279 /*package*/ int getVssVolumeForDevice(int stream, int device) {
280 return mStreamStates[stream].getIndex(device);
Jean-Michel Trivi58850372018-09-14 16:01:28 -0700281 }
282
Jason Parekhb1096152009-03-24 17:48:25 -0700283 private SettingsObserver mSettingsObserver;
Eric Laurenta553c252009-07-17 12:17:14 -0700284
Jean-Michel Trivifa9a6982013-06-27 16:22:58 -0700285 private int mMode = AudioSystem.MODE_NORMAL;
Glenn Kastenba195eb2011-12-13 09:30:40 -0800286 // protects mRingerMode
287 private final Object mSettingsLock = new Object();
Eric Laurent45c90ce2012-04-24 18:44:22 -0700288
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800289 private SoundPool mSoundPool;
Glenn Kasten30c918c2011-11-10 17:56:41 -0800290 private final Object mSoundEffectsLock = new Object();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800291 private static final int NUM_SOUNDPOOL_CHANNELS = 4;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800292
293 /* Sound effect file names */
294 private static final String SOUND_EFFECTS_PATH = "/media/audio/ui/";
Eric Laurente78fced2013-03-15 16:03:47 -0700295 private static final List<String> SOUND_EFFECT_FILES = new ArrayList<String>();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800296
297 /* Sound effect file name mapping sound effect id (AudioManager.FX_xxx) to
298 * file index in SOUND_EFFECT_FILES[] (first column) and indicating if effect
299 * uses soundpool (second column) */
Eric Laurente78fced2013-03-15 16:03:47 -0700300 private final int[][] SOUND_EFFECT_FILES_MAP = new int[AudioManager.NUM_SOUND_EFFECTS][2];
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800301
John Spurlockb6e19e32015-03-10 21:33:44 -0400302 /** Maximum volume index values for audio streams */
Chinyue Chen6affe932018-01-24 14:51:43 +0800303 protected static int[] MAX_STREAM_VOLUME = new int[] {
Eric Laurent6ee99522009-08-25 06:30:59 -0700304 5, // STREAM_VOICE_CALL
305 7, // STREAM_SYSTEM
306 7, // STREAM_RING
307 15, // STREAM_MUSIC
308 7, // STREAM_ALARM
309 7, // STREAM_NOTIFICATION
310 15, // STREAM_BLUETOOTH_SCO
311 7, // STREAM_SYSTEM_ENFORCED
312 15, // STREAM_DTMF
Jean-Michel Trivi3f0945a2016-11-11 10:05:18 -0800313 15, // STREAM_TTS
314 15 // STREAM_ACCESSIBILITY
Jared Suttles59820132009-08-13 21:50:52 -0500315 };
Eric Laurent91377de2014-10-10 15:24:04 -0700316
John Spurlockb6e19e32015-03-10 21:33:44 -0400317 /** Minimum volume index values for audio streams */
Chinyue Chen6affe932018-01-24 14:51:43 +0800318 protected static int[] MIN_STREAM_VOLUME = new int[] {
John Spurlockb6e19e32015-03-10 21:33:44 -0400319 1, // STREAM_VOICE_CALL
320 0, // STREAM_SYSTEM
321 0, // STREAM_RING
322 0, // STREAM_MUSIC
Jean-Michel Trivie05eef82018-03-08 18:56:34 -0800323 1, // STREAM_ALARM
John Spurlockb6e19e32015-03-10 21:33:44 -0400324 0, // STREAM_NOTIFICATION
Eric Laurente4381ec2015-10-29 17:52:48 -0700325 0, // STREAM_BLUETOOTH_SCO
John Spurlockb6e19e32015-03-10 21:33:44 -0400326 0, // STREAM_SYSTEM_ENFORCED
327 0, // STREAM_DTMF
Jean-Michel Trivi3f0945a2016-11-11 10:05:18 -0800328 0, // STREAM_TTS
Jean-Michel Trivie05eef82018-03-08 18:56:34 -0800329 1 // STREAM_ACCESSIBILITY
John Spurlockb6e19e32015-03-10 21:33:44 -0400330 };
331
Eric Laurent6d517662012-04-23 18:42:39 -0700332 /* mStreamVolumeAlias[] indicates for each stream if it uses the volume settings
Eric Laurenta553c252009-07-17 12:17:14 -0700333 * of another stream: This avoids multiplying the volume settings for hidden
334 * stream types that follow other stream behavior for volume settings
Eric Laurent6d517662012-04-23 18:42:39 -0700335 * NOTE: do not create loops in aliases!
336 * Some streams alias to different streams according to device category (phone or tablet) or
Eric Laurent24e0d9b2013-10-03 18:15:07 -0700337 * use case (in call vs off call...). See updateStreamVolumeAlias() for more details.
Eric Laurent212532b2014-07-21 15:43:18 -0700338 * mStreamVolumeAlias contains STREAM_VOLUME_ALIAS_VOICE aliases for a voice capable device
339 * (phone), STREAM_VOLUME_ALIAS_TELEVISION for a television or set-top box and
340 * STREAM_VOLUME_ALIAS_DEFAULT for other devices (e.g. tablets).*/
341 private final int[] STREAM_VOLUME_ALIAS_VOICE = new int[] {
Eric Laurent6d517662012-04-23 18:42:39 -0700342 AudioSystem.STREAM_VOICE_CALL, // STREAM_VOICE_CALL
343 AudioSystem.STREAM_RING, // STREAM_SYSTEM
344 AudioSystem.STREAM_RING, // STREAM_RING
345 AudioSystem.STREAM_MUSIC, // STREAM_MUSIC
346 AudioSystem.STREAM_ALARM, // STREAM_ALARM
347 AudioSystem.STREAM_RING, // STREAM_NOTIFICATION
348 AudioSystem.STREAM_BLUETOOTH_SCO, // STREAM_BLUETOOTH_SCO
349 AudioSystem.STREAM_RING, // STREAM_SYSTEM_ENFORCED
350 AudioSystem.STREAM_RING, // STREAM_DTMF
Jean-Michel Trivi3f0945a2016-11-11 10:05:18 -0800351 AudioSystem.STREAM_MUSIC, // STREAM_TTS
352 AudioSystem.STREAM_MUSIC // STREAM_ACCESSIBILITY
Eric Laurenta553c252009-07-17 12:17:14 -0700353 };
Eric Laurent212532b2014-07-21 15:43:18 -0700354 private final int[] STREAM_VOLUME_ALIAS_TELEVISION = new int[] {
355 AudioSystem.STREAM_MUSIC, // STREAM_VOICE_CALL
356 AudioSystem.STREAM_MUSIC, // STREAM_SYSTEM
357 AudioSystem.STREAM_MUSIC, // STREAM_RING
358 AudioSystem.STREAM_MUSIC, // STREAM_MUSIC
359 AudioSystem.STREAM_MUSIC, // STREAM_ALARM
360 AudioSystem.STREAM_MUSIC, // STREAM_NOTIFICATION
361 AudioSystem.STREAM_MUSIC, // STREAM_BLUETOOTH_SCO
362 AudioSystem.STREAM_MUSIC, // STREAM_SYSTEM_ENFORCED
363 AudioSystem.STREAM_MUSIC, // STREAM_DTMF
Jean-Michel Trivi3f0945a2016-11-11 10:05:18 -0800364 AudioSystem.STREAM_MUSIC, // STREAM_TTS
365 AudioSystem.STREAM_MUSIC // STREAM_ACCESSIBILITY
Eric Laurent212532b2014-07-21 15:43:18 -0700366 };
367 private final int[] STREAM_VOLUME_ALIAS_DEFAULT = new int[] {
Eric Laurent6d517662012-04-23 18:42:39 -0700368 AudioSystem.STREAM_VOICE_CALL, // STREAM_VOICE_CALL
John Spurlock4f0f1202014-08-05 13:28:33 -0400369 AudioSystem.STREAM_RING, // STREAM_SYSTEM
Eric Laurent6d517662012-04-23 18:42:39 -0700370 AudioSystem.STREAM_RING, // STREAM_RING
371 AudioSystem.STREAM_MUSIC, // STREAM_MUSIC
372 AudioSystem.STREAM_ALARM, // STREAM_ALARM
373 AudioSystem.STREAM_RING, // STREAM_NOTIFICATION
374 AudioSystem.STREAM_BLUETOOTH_SCO, // STREAM_BLUETOOTH_SCO
John Spurlock4f0f1202014-08-05 13:28:33 -0400375 AudioSystem.STREAM_RING, // STREAM_SYSTEM_ENFORCED
376 AudioSystem.STREAM_RING, // STREAM_DTMF
Jean-Michel Trivi3f0945a2016-11-11 10:05:18 -0800377 AudioSystem.STREAM_MUSIC, // STREAM_TTS
378 AudioSystem.STREAM_MUSIC // STREAM_ACCESSIBILITY
Eric Laurent6d517662012-04-23 18:42:39 -0700379 };
Yue Li949865b2017-05-24 17:25:28 -0700380 protected static int[] mStreamVolumeAlias;
Eric Laurenta553c252009-07-17 12:17:14 -0700381
Dianne Hackbornba50b97c2013-04-30 15:04:46 -0700382 /**
383 * Map AudioSystem.STREAM_* constants to app ops. This should be used
384 * after mapping through mStreamVolumeAlias.
385 */
John Spurlock59dc9c12015-03-02 11:20:15 -0500386 private static final int[] STREAM_VOLUME_OPS = new int[] {
Dianne Hackbornba50b97c2013-04-30 15:04:46 -0700387 AppOpsManager.OP_AUDIO_VOICE_VOLUME, // STREAM_VOICE_CALL
388 AppOpsManager.OP_AUDIO_MEDIA_VOLUME, // STREAM_SYSTEM
389 AppOpsManager.OP_AUDIO_RING_VOLUME, // STREAM_RING
390 AppOpsManager.OP_AUDIO_MEDIA_VOLUME, // STREAM_MUSIC
391 AppOpsManager.OP_AUDIO_ALARM_VOLUME, // STREAM_ALARM
392 AppOpsManager.OP_AUDIO_NOTIFICATION_VOLUME, // STREAM_NOTIFICATION
393 AppOpsManager.OP_AUDIO_BLUETOOTH_VOLUME, // STREAM_BLUETOOTH_SCO
394 AppOpsManager.OP_AUDIO_MEDIA_VOLUME, // STREAM_SYSTEM_ENFORCED
395 AppOpsManager.OP_AUDIO_MEDIA_VOLUME, // STREAM_DTMF
396 AppOpsManager.OP_AUDIO_MEDIA_VOLUME, // STREAM_TTS
Jean-Michel Trivi3f0945a2016-11-11 10:05:18 -0800397 AppOpsManager.OP_AUDIO_ACCESSIBILITY_VOLUME, // STREAM_ACCESSIBILITY
Dianne Hackbornba50b97c2013-04-30 15:04:46 -0700398 };
399
Eric Laurent83a017b2013-03-19 18:15:31 -0700400 private final boolean mUseFixedVolume;
401
Julia Reynoldseb0ce472018-05-04 15:34:55 -0400402 /**
403 * Default stream type used for volume control in the absence of playback
404 * e.g. user on homescreen, no app playing anything, presses hardware volume buttons, this
405 * stream type is controlled.
406 */
Eric Laurent07584202019-01-24 18:33:49 -0800407 protected static final int DEFAULT_VOL_STREAM_NO_PLAYBACK = AudioSystem.STREAM_MUSIC;
Julia Reynoldseb0ce472018-05-04 15:34:55 -0400408
Glenn Kasten30c918c2011-11-10 17:56:41 -0800409 private final AudioSystem.ErrorCallback mAudioSystemCallback = new AudioSystem.ErrorCallback() {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800410 public void onError(int error) {
411 switch (error) {
Mikhail Naganova00883d2019-04-18 12:36:27 -0700412 case AudioSystem.AUDIO_STATUS_SERVER_DIED:
413 mRecordMonitor.onAudioServerDied();
Eric Laurent07584202019-01-24 18:33:49 -0800414
Mikhail Naganova00883d2019-04-18 12:36:27 -0700415 sendMsg(mAudioHandler, MSG_AUDIO_SERVER_DIED,
416 SENDMSG_NOOP, 0, 0, null, 0);
417 sendMsg(mAudioHandler, MSG_DISPATCH_AUDIO_SERVER_STATE,
418 SENDMSG_QUEUE, 0, 0, null, 0);
419 break;
420 default:
421 break;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800422 }
Eric Laurentdfb881f2013-07-18 14:41:39 -0700423 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800424 };
425
426 /**
427 * Current ringer mode from one of {@link AudioManager#RINGER_MODE_NORMAL},
428 * {@link AudioManager#RINGER_MODE_SILENT}, or
429 * {@link AudioManager#RINGER_MODE_VIBRATE}.
430 */
Jean-Michel Trivi8719a1d2017-11-06 11:52:51 -0800431 @GuardedBy("mSettingsLock")
John Spurlock661f2cf2014-11-17 10:29:10 -0500432 private int mRingerMode; // internal ringer mode, affects muting of underlying streams
Jean-Michel Trivi8719a1d2017-11-06 11:52:51 -0800433 @GuardedBy("mSettingsLock")
John Spurlock661f2cf2014-11-17 10:29:10 -0500434 private int mRingerModeExternal = -1; // reported ringer mode to outside clients (AudioManager)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800435
Eric Laurent9bcf4012009-06-12 06:09:28 -0700436 /** @see System#MODE_RINGER_STREAMS_AFFECTED */
Eric Laurent24e0d9b2013-10-03 18:15:07 -0700437 private int mRingerModeAffectedStreams = 0;
Eric Laurent9bcf4012009-06-12 06:09:28 -0700438
Beverlyd6964762018-02-16 14:07:03 -0500439 private int mZenModeAffectedStreams = 0;
440
441 // Streams currently muted by ringer mode and dnd
442 private int mRingerAndZenModeMutedStreams;
Eric Laurent5b4e6542010-03-19 20:02:21 -0700443
John Spurlock3ce37252015-02-17 13:20:45 -0500444 /** Streams that can be muted. Do not resolve to aliases when checking.
445 * @see System#MUTE_STREAMS_AFFECTED */
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800446 private int mMuteAffectedStreams;
447
448 /**
Eric Laurentbffc3d12012-05-07 17:43:49 -0700449 * NOTE: setVibrateSetting(), getVibrateSetting(), shouldVibrate() are deprecated.
450 * mVibrateSetting is just maintained during deprecation period but vibration policy is
451 * now only controlled by mHasVibrator and mRingerMode
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800452 */
453 private int mVibrateSetting;
454
Eric Laurentbffc3d12012-05-07 17:43:49 -0700455 // Is there a vibrator
456 private final boolean mHasVibrator;
Mike Digman55272862018-02-20 14:35:17 -0800457 // Used to play vibrations
458 private Vibrator mVibrator;
459 private static final AudioAttributes VIBRATION_ATTRIBUTES = new AudioAttributes.Builder()
460 .setContentType(AudioAttributes.CONTENT_TYPE_SONIFICATION)
461 .setUsage(AudioAttributes.USAGE_ASSISTANCE_SONIFICATION)
462 .build();
Eric Laurentbffc3d12012-05-07 17:43:49 -0700463
Eric Laurenta553c252009-07-17 12:17:14 -0700464 // Broadcast receiver for device connections intent broadcasts
465 private final BroadcastReceiver mReceiver = new AudioServiceBroadcastReceiver();
466
Kevin Rocard2fe8b8b2019-02-20 11:25:23 -0800467 private IMediaProjectionManager mProjectionService; // to validate projection token
468
Makoto Onukid45a4a22015-11-02 17:17:38 -0800469 /** Interface for UserManagerService. */
470 private final UserManagerInternal mUserManagerInternal;
Sudheer Shankafc46e9b2016-10-21 17:55:27 -0700471 private final ActivityManagerInternal mActivityManagerInternal;
Makoto Onukid45a4a22015-11-02 17:17:38 -0800472
473 private final UserRestrictionsListener mUserRestrictionsListener =
474 new AudioServiceUserRestrictionsListener();
475
Eric Laurent9272b4b2010-01-23 17:12:59 -0800476 // List of binder death handlers for setMode() client processes.
477 // The last process to have called setMode() is at the top of the list.
Jean-Michel Trivi58850372018-09-14 16:01:28 -0700478 // package-private so it can be accessed in AudioDeviceBroker.getSetModeDeathHandlers
479 //TODO candidate to be moved to separate class that handles synchronization
480 @GuardedBy("mDeviceBroker.mSetModeLock")
481 /*package*/ final ArrayList<SetModeDeathHandler> mSetModeDeathHandlers =
482 new ArrayList<SetModeDeathHandler>();
Eric Laurent62ef7672010-11-24 10:58:32 -0800483
Eric Laurenta60e2122010-12-28 16:49:07 -0800484 // true if boot sequence has been completed
Eric Laurent4a5eeb92014-05-06 10:49:04 -0700485 private boolean mSystemReady;
Yasuhiro Matsuda4ced7192015-07-10 22:08:44 +0900486 // true if Intent.ACTION_USER_SWITCHED has ever been received
487 private boolean mUserSwitchedReceived;
Eric Laurenta60e2122010-12-28 16:49:07 -0800488 // listener for SoundPool sample load completion indication
489 private SoundPoolCallback mSoundPoolCallBack;
490 // thread for SoundPool listener
491 private SoundPoolListenerThread mSoundPoolListenerThread;
492 // message looper for SoundPool listener
493 private Looper mSoundPoolLooper = null;
Jean-Michel Trivic55b3932012-06-05 11:57:59 -0700494 // volume applied to sound played with playSoundEffect()
Jean-Michel Trivif2b0c112012-07-09 11:59:11 -0700495 private static int sSoundEffectVolumeDb;
Eric Laurent25101b02011-02-02 09:33:30 -0800496 // previous volume adjustment direction received by checkForRingerModeChange()
497 private int mPrevVolDirection = AudioManager.ADJUST_SAME;
Eric Laurent45c90ce2012-04-24 18:44:22 -0700498 // mVolumeControlStream is set by VolumePanel to temporarily force the stream type which volume
499 // is controlled by Vol keys.
Jean-Michel Trivia7880d42017-04-15 12:41:05 -0700500 private int mVolumeControlStream = -1;
501 // interpretation of whether the volume stream has been selected by the user by clicking on a
502 // volume slider to change which volume is controlled by the volume keys. Is false
503 // when mVolumeControlStream is -1.
504 private boolean mUserSelectedVolumeControlStream = false;
Eric Laurent45c90ce2012-04-24 18:44:22 -0700505 private final Object mForceControlStreamLock = new Object();
506 // VolumePanel is currently the only client of forceVolumeControlStream() and runs in system
507 // server process so in theory it is not necessary to monitor the client death.
508 // However it is good to be ready for future evolutions.
509 private ForceControlStreamClient mForceControlStreamClient = null;
Jeff Sharkey098d5802012-04-26 17:30:34 -0700510 // Used to play ringtones outside system_server
511 private volatile IRingtonePlayer mRingtonePlayer;
Eric Laurent9bc8358d2011-11-18 16:43:31 -0800512
Jean-Michel Trivi90dbfdf2019-04-10 14:11:40 -0700513 // Devices for which the volume is fixed (volume is either max or muted)
Eric Laurent212532b2014-07-21 15:43:18 -0700514 int mFixedVolumeDevices = AudioSystem.DEVICE_OUT_HDMI |
Eric Laurent4bbcc652012-09-24 14:26:30 -0700515 AudioSystem.DEVICE_OUT_DGTL_DOCK_HEADSET |
Eric Laurent212532b2014-07-21 15:43:18 -0700516 AudioSystem.DEVICE_OUT_ANLG_DOCK_HEADSET |
517 AudioSystem.DEVICE_OUT_HDMI_ARC |
518 AudioSystem.DEVICE_OUT_SPDIF |
519 AudioSystem.DEVICE_OUT_AUX_LINE;
Jean-Michel Trivi90dbfdf2019-04-10 14:11:40 -0700520 // Devices for which the volume is always max, no volume panel
Jakub Pawlowskic274fb22018-04-04 10:15:12 -0700521 int mFullVolumeDevices = 0;
Jean-Michel Trivib32faaa2019-04-22 12:21:50 -0700522 // Devices for the which use the "absolute volume" concept (framework sends audio signal
523 // full scale, and volume control separately) and can be used for multiple use cases reflected
524 // by the audio mode (e.g. media playback in MODE_NORMAL, and phone calls in MODE_IN_CALL).
525 int mAbsVolumeMultiModeCaseDevices = AudioSystem.DEVICE_OUT_HEARING_AID;
Eric Laurent4bbcc652012-09-24 14:26:30 -0700526
Jean-Michel Trivibb6f8712013-05-23 15:02:41 -0700527 private final boolean mMonitorRotation;
Eric Laurentd640bd32012-09-28 18:01:48 -0700528
Eric Laurent7ee1e4f2012-10-26 18:11:21 -0700529 private boolean mDockAudioMediaEnabled = true;
530
Eric Laurent08ed1b92012-11-05 14:54:12 -0800531 private int mDockState = Intent.EXTRA_DOCK_STATE_UNDOCKED;
532
Eric Laurentfde16d52012-12-03 14:42:39 -0800533 // Used when safe volume warning message display is requested by setStreamVolume(). In this
534 // case, the new requested volume, stream type and device are stored in mPendingVolumeCommand
535 // and used later when/if disableSafeMediaVolume() is called.
536 private StreamVolumeCommand mPendingVolumeCommand;
537
Jean-Michel Trivifa9a6982013-06-27 16:22:58 -0700538 private PowerManager.WakeLock mAudioEventWakeLock;
539
540 private final MediaFocusControl mMediaFocusControl;
541
Tomoharu Kasaharaf0fecb12018-09-06 20:04:38 +0900542 // Pre-scale for Bluetooth Absolute Volume
543 private float[] mPrescaleAbsoluteVolume = new float[] {
544 0.5f, // Pre-scale for index 1
545 0.7f, // Pre-scale for index 2
546 0.85f, // Pre-scale for index 3
547 };
548
Julia Reynolds48034f82016-03-09 10:15:16 -0500549 private NotificationManager mNm;
John Spurlock661f2cf2014-11-17 10:29:10 -0500550 private AudioManagerInternal.RingerModeDelegate mRingerModeDelegate;
John Spurlocka48d7792015-03-03 17:35:57 -0500551 private VolumePolicy mVolumePolicy = VolumePolicy.DEFAULT;
John Spurlock07e72432015-03-13 11:46:52 -0400552 private long mLoweredFromNormalToVibrateTime;
John Spurlock661f2cf2014-11-17 10:29:10 -0500553
Phil Weaverf1a9aff2017-03-23 17:21:29 -0700554 // Array of Uids of valid accessibility services to check if caller is one of them
555 private int[] mAccessibilityServiceUids;
556 private final Object mAccessibilityServiceUidsLock = new Object();
557
jiabin39940752018-04-02 18:18:45 -0700558 private int mEncodedSurroundMode;
559 private String mEnabledSurroundFormats;
560 private boolean mSurroundModeChanged;
561
Eric Laurent1c9c1d52018-10-17 10:06:46 -0700562 @GuardedBy("mSettingsLock")
563 private int mAssistantUid;
564
Paul McLean10804eb2015-01-28 11:16:35 -0800565 // Defines the format for the connection "address" for ALSA devices
566 public static String makeAlsaAddressString(int card, int device) {
567 return "card=" + card + ";device=" + device + ";";
568 }
569
Makoto Onukie1aef852015-10-15 17:28:35 -0700570 public static final class Lifecycle extends SystemService {
571 private AudioService mService;
572
573 public Lifecycle(Context context) {
574 super(context);
575 mService = new AudioService(context);
576 }
577
578 @Override
579 public void onStart() {
580 publishBinderService(Context.AUDIO_SERVICE, mService);
581 }
582
583 @Override
584 public void onBootPhase(int phase) {
585 if (phase == SystemService.PHASE_ACTIVITY_MANAGER_READY) {
586 mService.systemReady();
587 }
588 }
589 }
590
Dianne Hackborn3e99f652017-07-05 16:33:56 -0700591 final private IUidObserver mUidObserver = new IUidObserver.Stub() {
592 @Override public void onUidStateChanged(int uid, int procState, long procStateSeq) {
593 }
594
595 @Override public void onUidGone(int uid, boolean disabled) {
596 // Once the uid is no longer running, no need to keep trying to disable its audio.
597 disableAudioForUid(false, uid);
598 }
599
600 @Override public void onUidActive(int uid) throws RemoteException {
601 }
602
603 @Override public void onUidIdle(int uid, boolean disabled) {
604 }
605
606 @Override public void onUidCachedChanged(int uid, boolean cached) {
607 disableAudioForUid(cached, uid);
608 }
609
610 private void disableAudioForUid(boolean disable, int uid) {
611 queueMsgUnderWakeLock(mAudioHandler, MSG_DISABLE_AUDIO_FOR_UID,
612 disable ? 1 : 0 /* arg1 */, uid /* arg2 */,
613 null /* obj */, 0 /* delay */);
614 }
615 };
616
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800617 ///////////////////////////////////////////////////////////////////////////
618 // Construction
619 ///////////////////////////////////////////////////////////////////////////
620
621 /** @hide */
622 public AudioService(Context context) {
623 mContext = context;
624 mContentResolver = context.getContentResolver();
Dianne Hackbornba50b97c2013-04-30 15:04:46 -0700625 mAppOps = (AppOpsManager)context.getSystemService(Context.APP_OPS_SERVICE);
Eric Laurent212532b2014-07-21 15:43:18 -0700626
John Spurlock61560172015-02-06 19:46:04 -0500627 mPlatformType = AudioSystem.getPlatformType(context);
Jared Suttles59820132009-08-13 21:50:52 -0500628
Muyuan Li1ed6df62016-06-18 11:16:52 -0700629 mIsSingleVolume = AudioSystem.isSingleVolume(context);
630
Makoto Onukid45a4a22015-11-02 17:17:38 -0800631 mUserManagerInternal = LocalServices.getService(UserManagerInternal.class);
Sudheer Shankafc46e9b2016-10-21 17:55:27 -0700632 mActivityManagerInternal = LocalServices.getService(ActivityManagerInternal.class);
Makoto Onukid45a4a22015-11-02 17:17:38 -0800633
Jean-Michel Trivic6802222012-04-30 11:15:03 -0700634 PowerManager pm = (PowerManager)context.getSystemService(Context.POWER_SERVICE);
Jean-Michel Trivifa9a6982013-06-27 16:22:58 -0700635 mAudioEventWakeLock = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "handleAudioEvent");
Jean-Michel Trivic6802222012-04-30 11:15:03 -0700636
Mike Digman55272862018-02-20 14:35:17 -0800637 mVibrator = (Vibrator) context.getSystemService(Context.VIBRATOR_SERVICE);
638 mHasVibrator = mVibrator == null ? false : mVibrator.hasVibrator();
Eric Laurentbffc3d12012-05-07 17:43:49 -0700639
John Spurlockb6e19e32015-03-10 21:33:44 -0400640 // Initialize volume
David Brageule220d3b2018-09-24 08:40:49 +0200641 // Priority 1 - Android Property
642 // Priority 2 - Audio Policy Service
643 // Priority 3 - Default Value
Hayden Gomes6d69bde2019-04-04 13:10:13 -0700644 if (AudioProductStrategy.getAudioProductStrategies().size() > 0) {
David Brageule220d3b2018-09-24 08:40:49 +0200645 int numStreamTypes = AudioSystem.getNumStreamTypes();
646
647 for (int streamType = numStreamTypes - 1; streamType >= 0; streamType--) {
648 AudioAttributes attr =
Hayden Gomes6d69bde2019-04-04 13:10:13 -0700649 AudioProductStrategy.getAudioAttributesForStrategyWithLegacyStreamType(
650 streamType);
David Brageule220d3b2018-09-24 08:40:49 +0200651 int maxVolume = AudioSystem.getMaxVolumeIndexForAttributes(attr);
652 if (maxVolume != -1) {
653 MAX_STREAM_VOLUME[streamType] = maxVolume;
654 }
655 int minVolume = AudioSystem.getMinVolumeIndexForAttributes(attr);
656 if (minVolume != -1) {
657 MIN_STREAM_VOLUME[streamType] = minVolume;
658 }
659 }
660 }
661
Eric Laurent403bd342017-07-11 16:21:44 -0700662 int maxCallVolume = SystemProperties.getInt("ro.config.vc_call_vol_steps", -1);
663 if (maxCallVolume != -1) {
664 MAX_STREAM_VOLUME[AudioSystem.STREAM_VOICE_CALL] = maxCallVolume;
Shuhei Miyazaki89091ba2018-01-11 18:17:04 +0900665 }
666
667 int defaultCallVolume = SystemProperties.getInt("ro.config.vc_call_vol_default", -1);
668 if (defaultCallVolume != -1 &&
669 defaultCallVolume <= MAX_STREAM_VOLUME[AudioSystem.STREAM_VOICE_CALL] &&
670 defaultCallVolume >= MIN_STREAM_VOLUME[AudioSystem.STREAM_VOICE_CALL]) {
671 AudioSystem.DEFAULT_STREAM_VOLUME[AudioSystem.STREAM_VOICE_CALL] = defaultCallVolume;
672 } else {
Eric Laurent403bd342017-07-11 16:21:44 -0700673 AudioSystem.DEFAULT_STREAM_VOLUME[AudioSystem.STREAM_VOICE_CALL] =
674 (maxCallVolume * 3) / 4;
Eric Laurent91377de2014-10-10 15:24:04 -0700675 }
Eric Laurent403bd342017-07-11 16:21:44 -0700676
677 int maxMusicVolume = SystemProperties.getInt("ro.config.media_vol_steps", -1);
678 if (maxMusicVolume != -1) {
679 MAX_STREAM_VOLUME[AudioSystem.STREAM_MUSIC] = maxMusicVolume;
680 }
681
682 int defaultMusicVolume = SystemProperties.getInt("ro.config.media_vol_default", -1);
683 if (defaultMusicVolume != -1 &&
Shuhei Miyazaki89091ba2018-01-11 18:17:04 +0900684 defaultMusicVolume <= MAX_STREAM_VOLUME[AudioSystem.STREAM_MUSIC] &&
685 defaultMusicVolume >= MIN_STREAM_VOLUME[AudioSystem.STREAM_MUSIC]) {
Eric Laurent403bd342017-07-11 16:21:44 -0700686 AudioSystem.DEFAULT_STREAM_VOLUME[AudioSystem.STREAM_MUSIC] = defaultMusicVolume;
687 } else {
Hank Freund45926dc2015-12-11 10:50:45 -0800688 if (isPlatformTelevision()) {
Eric Laurent403bd342017-07-11 16:21:44 -0700689 AudioSystem.DEFAULT_STREAM_VOLUME[AudioSystem.STREAM_MUSIC] =
690 MAX_STREAM_VOLUME[AudioSystem.STREAM_MUSIC] / 4;
Hank Freund45926dc2015-12-11 10:50:45 -0800691 } else {
Eric Laurent403bd342017-07-11 16:21:44 -0700692 AudioSystem.DEFAULT_STREAM_VOLUME[AudioSystem.STREAM_MUSIC] =
693 MAX_STREAM_VOLUME[AudioSystem.STREAM_MUSIC] / 3;
Hank Freund45926dc2015-12-11 10:50:45 -0800694 }
Eric Laurent91377de2014-10-10 15:24:04 -0700695 }
Jared Suttles59820132009-08-13 21:50:52 -0500696
Chris Kuiper09b6c212018-01-03 22:22:13 -0800697 int maxAlarmVolume = SystemProperties.getInt("ro.config.alarm_vol_steps", -1);
698 if (maxAlarmVolume != -1) {
699 MAX_STREAM_VOLUME[AudioSystem.STREAM_ALARM] = maxAlarmVolume;
700 }
701
702 int defaultAlarmVolume = SystemProperties.getInt("ro.config.alarm_vol_default", -1);
703 if (defaultAlarmVolume != -1 &&
704 defaultAlarmVolume <= MAX_STREAM_VOLUME[AudioSystem.STREAM_ALARM]) {
705 AudioSystem.DEFAULT_STREAM_VOLUME[AudioSystem.STREAM_ALARM] = defaultAlarmVolume;
706 } else {
707 // Default is 6 out of 7 (default maximum), so scale accordingly.
708 AudioSystem.DEFAULT_STREAM_VOLUME[AudioSystem.STREAM_ALARM] =
709 6 * MAX_STREAM_VOLUME[AudioSystem.STREAM_ALARM] / 7;
710 }
711
712 int maxSystemVolume = SystemProperties.getInt("ro.config.system_vol_steps", -1);
713 if (maxSystemVolume != -1) {
714 MAX_STREAM_VOLUME[AudioSystem.STREAM_SYSTEM] = maxSystemVolume;
715 }
716
717 int defaultSystemVolume = SystemProperties.getInt("ro.config.system_vol_default", -1);
718 if (defaultSystemVolume != -1 &&
719 defaultSystemVolume <= MAX_STREAM_VOLUME[AudioSystem.STREAM_SYSTEM]) {
720 AudioSystem.DEFAULT_STREAM_VOLUME[AudioSystem.STREAM_SYSTEM] = defaultSystemVolume;
721 } else {
722 // Default is to use maximum.
723 AudioSystem.DEFAULT_STREAM_VOLUME[AudioSystem.STREAM_SYSTEM] =
724 MAX_STREAM_VOLUME[AudioSystem.STREAM_SYSTEM];
725 }
726
Jean-Michel Trivif2b0c112012-07-09 11:59:11 -0700727 sSoundEffectVolumeDb = context.getResources().getInteger(
Jean-Michel Trivic55b3932012-06-05 11:57:59 -0700728 com.android.internal.R.integer.config_soundEffectVolumeDb);
Eric Laurent25101b02011-02-02 09:33:30 -0800729
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800730 createAudioSystemThread();
Eric Laurentdd45d012012-10-08 09:04:34 -0700731
Eric Laurentdfb881f2013-07-18 14:41:39 -0700732 AudioSystem.setErrorCallback(mAudioSystemCallback);
733
John Spurlock5e783732015-02-19 10:28:59 -0500734 boolean cameraSoundForced = readCameraSoundForced();
Eric Laurentdd45d012012-10-08 09:04:34 -0700735 mCameraSoundForced = new Boolean(cameraSoundForced);
736 sendMsg(mAudioHandler,
737 MSG_SET_FORCE_USE,
738 SENDMSG_QUEUE,
739 AudioSystem.FOR_SYSTEM,
740 cameraSoundForced ?
741 AudioSystem.FORCE_SYSTEM_ENFORCED : AudioSystem.FORCE_NONE,
Jean-Michel Trivi011f39e2017-08-19 18:08:06 -0700742 new String("AudioService ctor"),
Eric Laurentdd45d012012-10-08 09:04:34 -0700743 0);
744
hyomin.ohd0446dc2018-10-18 13:58:27 +0900745 mSafeMediaVolumeState = Settings.Global.getInt(mContentResolver,
746 Settings.Global.AUDIO_SAFE_VOLUME_STATE,
747 SAFE_MEDIA_VOLUME_NOT_CONFIGURED);
Eric Laurent05274f32012-11-29 12:48:18 -0800748 // The default safe volume index read here will be replaced by the actual value when
749 // the mcc is read by onConfigureSafeVolume()
750 mSafeMediaVolumeIndex = mContext.getResources().getInteger(
751 com.android.internal.R.integer.config_safe_media_volume_index) * 10;
752
Eric Laurent83a017b2013-03-19 18:15:31 -0700753 mUseFixedVolume = mContext.getResources().getBoolean(
754 com.android.internal.R.bool.config_useFixedVolume);
755
Jean-Michel Trivi58850372018-09-14 16:01:28 -0700756 mDeviceBroker = new AudioDeviceBroker(mContext, this);
757
Eric Laurent24e0d9b2013-10-03 18:15:07 -0700758 // must be called before readPersistedSettings() which needs a valid mStreamVolumeAlias[]
759 // array initialized by updateStreamVolumeAlias()
John Spurlock90874332015-03-10 16:00:54 -0400760 updateStreamVolumeAlias(false /*updateVolumes*/, TAG);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800761 readPersistedSettings();
Eric Laurentc0232482016-03-15 18:19:23 -0700762 readUserRestrictions();
Eric Laurentc1d41662011-07-19 11:21:13 -0700763 mSettingsObserver = new SettingsObserver();
Eric Laurenta553c252009-07-17 12:17:14 -0700764 createStreamStates();
Eric Laurent9f103de2011-09-08 15:04:23 -0700765
Eric Laurentb378a13a2017-07-11 14:08:11 -0700766 // mSafeUsbMediaVolumeIndex must be initialized after createStreamStates() because it
767 // relies on audio policy having correct ranges for volume indexes.
768 mSafeUsbMediaVolumeIndex = getSafeUsbMediaVolumeIndex();
769
Eric Laurente5a351c2017-09-27 20:11:51 -0700770 mPlaybackMonitor =
771 new PlaybackActivityMonitor(context, MAX_STREAM_VOLUME[AudioSystem.STREAM_ALARM]);
772
Jean-Michel Trivi99489cc2017-01-25 19:08:49 -0800773 mMediaFocusControl = new MediaFocusControl(mContext, mPlaybackMonitor);
John Spurlockb6e19e32015-03-10 21:33:44 -0400774
Jean-Michel Trivi66ffacf2017-02-04 17:25:31 -0800775 mRecordMonitor = new RecordingActivityMonitor(mContext);
776
Glenn Kastenfd116ad2013-07-12 17:10:39 -0700777 readAndSetLowRamDevice();
Eric Laurent3891c4c2010-04-20 09:40:57 -0700778
779 // Call setRingerModeInt() to apply correct mute
780 // state on streams affected by ringer mode.
Beverlyd6964762018-02-16 14:07:03 -0500781 mRingerAndZenModeMutedStreams = 0;
John Spurlock661f2cf2014-11-17 10:29:10 -0500782 setRingerModeInt(getRingerModeInternal(), false);
Eric Laurent3891c4c2010-04-20 09:40:57 -0700783
Eric Laurenta553c252009-07-17 12:17:14 -0700784 // Register for device connection intent broadcasts.
785 IntentFilter intentFilter =
Eric Laurentb1fbaac2012-05-29 09:24:28 -0700786 new IntentFilter(BluetoothHeadset.ACTION_AUDIO_STATE_CHANGED);
Jack He8dd33942018-01-17 15:45:12 -0800787 intentFilter.addAction(BluetoothHeadset.ACTION_ACTIVE_DEVICE_CHANGED);
Jaikumar Ganesh82aa7f02010-09-27 17:05:10 -0700788 intentFilter.addAction(Intent.ACTION_DOCK_EVENT);
Eric Laurent950e8cb2011-10-13 08:57:54 -0700789 intentFilter.addAction(Intent.ACTION_SCREEN_ON);
790 intentFilter.addAction(Intent.ACTION_SCREEN_OFF);
Eric Laurentbc0fab1f2012-09-19 11:24:41 -0700791 intentFilter.addAction(Intent.ACTION_USER_SWITCHED);
Fyodor Kupolovb5013302015-04-17 17:59:14 -0700792 intentFilter.addAction(Intent.ACTION_USER_BACKGROUND);
793 intentFilter.addAction(Intent.ACTION_USER_FOREGROUND);
Paul McLeanc837a452014-04-09 09:04:43 -0700794 intentFilter.addAction(UsbManager.ACTION_USB_DEVICE_ATTACHED);
Eric Laurentb70b78a2016-01-13 19:16:04 -0800795 intentFilter.addAction(BluetoothAdapter.ACTION_STATE_CHANGED);
Jean-Michel Trivib2251822019-02-06 07:32:06 -0800796 intentFilter.addAction(Intent.ACTION_PACKAGES_SUSPENDED);
Jean-Michel Trivif26f0172012-04-25 16:23:20 -0700797
Eric Laurentd640bd32012-09-28 18:01:48 -0700798 intentFilter.addAction(Intent.ACTION_CONFIGURATION_CHANGED);
Jean-Michel Trivibb6f8712013-05-23 15:02:41 -0700799 mMonitorRotation = SystemProperties.getBoolean("ro.audio.monitorRotation", false);
800 if (mMonitorRotation) {
Jean-Michel Trivi24806db2015-10-01 15:00:59 -0700801 RotationHelper.init(mContext, mAudioHandler);
Jean-Michel Trivibb6f8712013-05-23 15:02:41 -0700802 }
Jean-Michel Trivif26f0172012-04-25 16:23:20 -0700803
Marco Nelissenfb6df0b2017-02-15 15:25:24 -0800804 intentFilter.addAction(AudioEffect.ACTION_OPEN_AUDIO_EFFECT_CONTROL_SESSION);
805 intentFilter.addAction(AudioEffect.ACTION_CLOSE_AUDIO_EFFECT_CONTROL_SESSION);
806
Fyodor Kupolovb5013302015-04-17 17:59:14 -0700807 context.registerReceiverAsUser(mReceiver, UserHandle.ALL, intentFilter, null, null);
Jared Suttles59820132009-08-13 21:50:52 -0500808
RoboErik0dac35a2014-08-12 15:48:49 -0700809 LocalServices.addService(AudioManagerInternal.class, new AudioServiceInternal());
Makoto Onukid45a4a22015-11-02 17:17:38 -0800810
811 mUserManagerInternal.addUserRestrictionsListener(mUserRestrictionsListener);
Jean-Michel Trivid3c71f02015-12-07 11:59:31 -0800812
813 mRecordMonitor.initMonitor();
Tomoharu Kasaharaf0fecb12018-09-06 20:04:38 +0900814
815 final float[] preScale = new float[3];
816 preScale[0] = mContext.getResources().getFraction(
817 com.android.internal.R.fraction.config_prescaleAbsoluteVolume_index1,
818 1, 1);
819 preScale[1] = mContext.getResources().getFraction(
820 com.android.internal.R.fraction.config_prescaleAbsoluteVolume_index2,
821 1, 1);
822 preScale[2] = mContext.getResources().getFraction(
823 com.android.internal.R.fraction.config_prescaleAbsoluteVolume_index3,
824 1, 1);
825 for (int i = 0; i < preScale.length; i++) {
826 if (0.0f <= preScale[i] && preScale[i] <= 1.0f) {
827 mPrescaleAbsoluteVolume[i] = preScale[i];
828 }
829 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800830 }
831
Eric Laurent4a5eeb92014-05-06 10:49:04 -0700832 public void systemReady() {
833 sendMsg(mAudioHandler, MSG_SYSTEM_READY, SENDMSG_QUEUE,
834 0, 0, null, 0);
Dianne Hackborn3e3600e2017-08-31 11:15:26 -0700835 if (false) {
836 // This is turned off for now, because it is racy and thus causes apps to break.
837 // Currently banning a uid means that if an app tries to start playing an audio
838 // stream, that will be preventing, and unbanning it will not allow that stream
839 // to resume. However these changes in uid state are racy with what the app is doing,
840 // so that after taking a process out of the cached state we can't guarantee that
841 // we will unban the uid before the app actually tries to start playing audio.
842 // (To do that, the activity manager would need to wait until it knows for sure
843 // that the ban has been removed, before telling the app to do whatever it is
844 // supposed to do that caused it to go out of the cached state.)
845 try {
846 ActivityManager.getService().registerUidObserver(mUidObserver,
847 ActivityManager.UID_OBSERVER_CACHED | ActivityManager.UID_OBSERVER_GONE,
848 ActivityManager.PROCESS_STATE_UNKNOWN, null);
849 } catch (RemoteException e) {
850 // ignored; both services live in system_server
851 }
Dianne Hackborn3e99f652017-07-05 16:33:56 -0700852 }
Eric Laurent4a5eeb92014-05-06 10:49:04 -0700853 }
854
855 public void onSystemReady() {
856 mSystemReady = true;
Ben Lin0c856812019-04-03 12:09:54 -0700857 scheduleLoadSoundEffects();
Eric Laurent4a5eeb92014-05-06 10:49:04 -0700858
Jean-Michel Trivi58850372018-09-14 16:01:28 -0700859 mDeviceBroker.onSystemReady();
Eric Laurent4a5eeb92014-05-06 10:49:04 -0700860
Jeff Sharkey73ea0ae2016-08-10 17:30:38 -0600861 if (mContext.getPackageManager().hasSystemFeature(PackageManager.FEATURE_HDMI_CEC)) {
Shubangc480a712018-06-11 18:02:42 -0700862 synchronized (mHdmiClientLock) {
863 mHdmiManager = mContext.getSystemService(HdmiControlManager.class);
Eric Laurent212532b2014-07-21 15:43:18 -0700864 mHdmiTvClient = mHdmiManager.getTvClient();
Jungshik Jangc9ff9682014-09-15 17:41:06 +0900865 if (mHdmiTvClient != null) {
866 mFixedVolumeDevices &= ~AudioSystem.DEVICE_ALL_HDMI_SYSTEM_AUDIO_AND_SPEAKER;
867 }
Eric Laurent212532b2014-07-21 15:43:18 -0700868 mHdmiPlaybackClient = mHdmiManager.getPlaybackClient();
Jean-Michel Trivi90dbfdf2019-04-10 14:11:40 -0700869 if (mHdmiPlaybackClient != null) {
870 // not a television: HDMI output will be always at max
871 mFixedVolumeDevices &= ~AudioSystem.DEVICE_OUT_HDMI;
872 mFullVolumeDevices |= AudioSystem.DEVICE_OUT_HDMI;
873 }
Eric Laurent212532b2014-07-21 15:43:18 -0700874 mHdmiCecSink = false;
Shubangc480a712018-06-11 18:02:42 -0700875 mHdmiAudioSystemClient = mHdmiManager.getAudioSystemClient();
Eric Laurent212532b2014-07-21 15:43:18 -0700876 }
877 }
Wonsik Kim7f4342e2014-07-20 23:04:59 +0900878
Julia Reynolds48034f82016-03-09 10:15:16 -0500879 mNm = (NotificationManager) mContext.getSystemService(Context.NOTIFICATION_SERVICE);
880
Eric Laurent4a5eeb92014-05-06 10:49:04 -0700881 sendMsg(mAudioHandler,
882 MSG_CONFIGURE_SAFE_MEDIA_VOLUME_FORCED,
883 SENDMSG_REPLACE,
884 0,
885 0,
John Spurlock90874332015-03-10 16:00:54 -0400886 TAG,
Eric Laurent03332ab2017-02-09 18:29:15 -0800887 SystemProperties.getBoolean("audio.safemedia.bypass", false) ?
888 0 : SAFE_VOLUME_CONFIGURE_TIMEOUT_MS);
Jean-Michel Trivi873cc452014-09-11 17:25:09 -0700889
Jean-Michel Trivicfa55532017-01-18 11:17:51 -0800890 initA11yMonitoring();
Eric Laurent0867bed2015-05-20 14:49:08 -0700891 onIndicateSystemReady();
892 }
893
894 void onIndicateSystemReady() {
895 if (AudioSystem.systemReady() == AudioSystem.SUCCESS) {
896 return;
897 }
898 sendMsg(mAudioHandler,
899 MSG_INDICATE_SYSTEM_READY,
900 SENDMSG_REPLACE,
901 0,
902 0,
903 null,
904 INDICATE_SYSTEM_READY_RETRY_DELAY_MS);
905 }
906
Andy Hunged0ea402015-10-30 14:11:46 -0700907 public void onAudioServerDied() {
Eric Laurent0867bed2015-05-20 14:49:08 -0700908 if (!mSystemReady ||
909 (AudioSystem.checkAudioFlinger() != AudioSystem.AUDIO_STATUS_OK)) {
Andy Hunged0ea402015-10-30 14:11:46 -0700910 Log.e(TAG, "Audioserver died.");
911 sendMsg(mAudioHandler, MSG_AUDIO_SERVER_DIED, SENDMSG_NOOP, 0, 0,
Eric Laurent0867bed2015-05-20 14:49:08 -0700912 null, 500);
913 return;
914 }
Andy Hunged0ea402015-10-30 14:11:46 -0700915 Log.e(TAG, "Audioserver started.");
Eric Laurent0867bed2015-05-20 14:49:08 -0700916
917 // indicate to audio HAL that we start the reconfiguration phase after a media
918 // server crash
919 // Note that we only execute this when the media server
920 // process restarts after a crash, not the first time it is started.
921 AudioSystem.setParameters("restarting=true");
922
923 readAndSetLowRamDevice();
924
Jean-Michel Trivi58850372018-09-14 16:01:28 -0700925 // Restore device connection states, BT state
926 mDeviceBroker.onAudioServerDied();
927
Eric Laurent0867bed2015-05-20 14:49:08 -0700928 // Restore call state
Jean-Michel Trivi011f39e2017-08-19 18:08:06 -0700929 if (AudioSystem.setPhoneState(mMode) == AudioSystem.AUDIO_STATUS_OK) {
930 mModeLogger.log(new AudioEventLogger.StringEvent(
931 "onAudioServerDied causes setPhoneState(" + AudioSystem.modeToString(mMode) + ")"));
932 }
Eric Laurent0867bed2015-05-20 14:49:08 -0700933
Jean-Michel Trivi8719a1d2017-11-06 11:52:51 -0800934 final int forSys;
935 synchronized (mSettingsLock) {
936 forSys = mCameraSoundForced ?
937 AudioSystem.FORCE_SYSTEM_ENFORCED : AudioSystem.FORCE_NONE;
938 }
Jean-Michel Trivi58850372018-09-14 16:01:28 -0700939
940 mDeviceBroker.setForceUse_Async(AudioSystem.FOR_SYSTEM, forSys, "onAudioServerDied");
Eric Laurent0867bed2015-05-20 14:49:08 -0700941
942 // Restore stream volumes
943 int numStreamTypes = AudioSystem.getNumStreamTypes();
944 for (int streamType = numStreamTypes - 1; streamType >= 0; streamType--) {
945 VolumeStreamState streamState = mStreamStates[streamType];
Eric Laurente4381ec2015-10-29 17:52:48 -0700946 AudioSystem.initStreamVolume(
947 streamType, streamState.mIndexMin / 10, streamState.mIndexMax / 10);
Eric Laurent0867bed2015-05-20 14:49:08 -0700948
949 streamState.applyAllVolumes();
950 }
951
Andy Hungf04b84d2015-12-18 17:33:27 -0800952 // Restore mono mode
Andy Hung7b98e9a2016-02-25 18:34:50 -0800953 updateMasterMono(mContentResolver);
Andy Hungf04b84d2015-12-18 17:33:27 -0800954
Edward Savage-Jones35c292f2017-01-13 09:04:34 +0100955 // Restore audio balance
956 updateMasterBalance(mContentResolver);
957
Eric Laurent0867bed2015-05-20 14:49:08 -0700958 // Restore ringer mode
959 setRingerModeInt(getRingerModeInternal(), false);
960
Mikhail Naganovb668bc62018-02-13 13:46:38 -0800961 // Reset device rotation (if monitored for this device)
Eric Laurent0867bed2015-05-20 14:49:08 -0700962 if (mMonitorRotation) {
Jean-Michel Trivi24806db2015-10-01 15:00:59 -0700963 RotationHelper.updateOrientation();
Eric Laurent0867bed2015-05-20 14:49:08 -0700964 }
965
Eric Laurent0867bed2015-05-20 14:49:08 -0700966 synchronized (mSettingsLock) {
Jean-Michel Trivi011f39e2017-08-19 18:08:06 -0700967 final int forDock = mDockAudioMediaEnabled ?
968 AudioSystem.FORCE_ANALOG_DOCK : AudioSystem.FORCE_NONE;
Jean-Michel Trivi58850372018-09-14 16:01:28 -0700969 mDeviceBroker.setForceUse_Async(AudioSystem.FOR_DOCK, forDock, "onAudioServerDied");
Jean-Michel Trivi011f39e2017-08-19 18:08:06 -0700970 sendEncodedSurroundMode(mContentResolver, "onAudioServerDied");
jiabin39940752018-04-02 18:18:45 -0700971 sendEnabledSurroundFormats(mContentResolver, true);
Eric Laurent1c9c1d52018-10-17 10:06:46 -0700972 updateAssistantUId(true);
973 }
974 synchronized (mAccessibilityServiceUidsLock) {
975 AudioSystem.setA11yServicesUids(mAccessibilityServiceUids);
Eric Laurent0867bed2015-05-20 14:49:08 -0700976 }
Shubangc480a712018-06-11 18:02:42 -0700977 synchronized (mHdmiClientLock) {
978 if (mHdmiManager != null && mHdmiTvClient != null) {
979 setHdmiSystemAudioSupported(mHdmiSystemAudioSupported);
Eric Laurent0867bed2015-05-20 14:49:08 -0700980 }
981 }
982
983 synchronized (mAudioPolicies) {
984 for (AudioPolicyProxy policy : mAudioPolicies.values()) {
985 policy.connectMixes();
986 }
987 }
988
989 onIndicateSystemReady();
990 // indicate the end of reconfiguration phase to audio HAL
991 AudioSystem.setParameters("restarting=false");
Eric Laurent1d3cdce2018-01-20 10:31:21 -0800992
993 sendMsg(mAudioHandler, MSG_DISPATCH_AUDIO_SERVER_STATE,
994 SENDMSG_QUEUE, 1, 0, null, 0);
995 }
996
997 private void onDispatchAudioServerStateChange(boolean state) {
998 synchronized (mAudioServerStateListeners) {
999 for (AsdProxy asdp : mAudioServerStateListeners.values()) {
1000 try {
1001 asdp.callback().dispatchAudioServerStateChange(state);
1002 } catch (RemoteException e) {
1003 Log.w(TAG, "Could not call dispatchAudioServerStateChange()", e);
1004 }
1005 }
1006 }
Eric Laurent4a5eeb92014-05-06 10:49:04 -07001007 }
1008
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001009 private void createAudioSystemThread() {
1010 mAudioSystemThread = new AudioSystemThread();
1011 mAudioSystemThread.start();
1012 waitForAudioHandlerCreation();
1013 }
1014
1015 /** Waits for the volume handler to be created by the other thread. */
1016 private void waitForAudioHandlerCreation() {
1017 synchronized(this) {
1018 while (mAudioHandler == null) {
1019 try {
1020 // Wait for mAudioHandler to be set by the other thread
1021 wait();
1022 } catch (InterruptedException e) {
1023 Log.e(TAG, "Interrupted while waiting on volume handler.");
1024 }
1025 }
1026 }
1027 }
1028
François Gaffie0699fec2018-07-09 14:35:10 +02001029 /**
Hayden Gomes6d69bde2019-04-04 13:10:13 -07001030 * @return the {@link android.media.audiopolicy.AudioProductStrategy} discovered from the
François Gaffie0699fec2018-07-09 14:35:10 +02001031 * platform configuration file.
1032 */
Hayden Gomes6d69bde2019-04-04 13:10:13 -07001033 @NonNull
1034 public List<AudioProductStrategy> getAudioProductStrategies() {
1035 return AudioProductStrategy.getAudioProductStrategies();
François Gaffie0699fec2018-07-09 14:35:10 +02001036 }
1037
François Gaffie9c362102018-09-21 17:43:52 +02001038 /**
Hayden Gomesebd6aaa2019-04-04 13:14:21 -07001039 * @return the List of {@link android.media.audiopolicy.AudioVolumeGroup} discovered from the
François Gaffie9c362102018-09-21 17:43:52 +02001040 * platform configuration file.
1041 */
Hayden Gomesebd6aaa2019-04-04 13:14:21 -07001042 @NonNull
1043 public List<AudioVolumeGroup> getAudioVolumeGroups() {
1044 return AudioVolumeGroup.getAudioVolumeGroups();
François Gaffie9c362102018-09-21 17:43:52 +02001045 }
1046
Eric Laurent24482012012-05-10 09:41:17 -07001047 private void checkAllAliasStreamVolumes() {
Jean-Michel Trivi085346a2018-02-14 10:48:51 -08001048 synchronized (mSettingsLock) {
1049 synchronized (VolumeStreamState.class) {
1050 int numStreamTypes = AudioSystem.getNumStreamTypes();
1051 for (int streamType = 0; streamType < numStreamTypes; streamType++) {
1052 mStreamStates[streamType]
1053 .setAllIndexes(mStreamStates[mStreamVolumeAlias[streamType]], TAG);
1054 // apply stream volume
1055 if (!mStreamStates[streamType].mIsMuted) {
1056 mStreamStates[streamType].applyAllVolumes();
1057 }
Eric Laurent8fa4d6f2014-10-30 14:13:03 -07001058 }
Eric Laurent24482012012-05-10 09:41:17 -07001059 }
1060 }
1061 }
1062
Jean-Michel Trivi58850372018-09-14 16:01:28 -07001063 /**
1064 * Called from AudioDeviceBroker when DEVICE_OUT_HDMI is connected or disconnected.
1065 */
1066 /*package*/ void checkVolumeCecOnHdmiConnection(int state, String caller) {
1067 if (state != 0) {
1068 // DEVICE_OUT_HDMI is now connected
1069 if ((AudioSystem.DEVICE_OUT_HDMI & mSafeMediaVolumeDevices) != 0) {
1070 sendMsg(mAudioHandler,
1071 MSG_CHECK_MUSIC_ACTIVE,
1072 SENDMSG_REPLACE,
1073 0,
1074 0,
1075 caller,
1076 MUSIC_ACTIVE_POLL_PERIOD_MS);
1077 }
1078
1079 if (isPlatformTelevision()) {
Jean-Michel Trivi58850372018-09-14 16:01:28 -07001080 checkAllFixedVolumeDevices();
1081 synchronized (mHdmiClientLock) {
1082 if (mHdmiManager != null && mHdmiPlaybackClient != null) {
1083 mHdmiCecSink = false;
1084 mHdmiPlaybackClient.queryDisplayStatus(mHdmiDisplayStatusCallback);
1085 }
1086 }
1087 }
1088 sendEnabledSurroundFormats(mContentResolver, true);
1089 } else {
1090 // DEVICE_OUT_HDMI disconnected
1091 if (isPlatformTelevision()) {
1092 synchronized (mHdmiClientLock) {
1093 if (mHdmiManager != null) {
1094 mHdmiCecSink = false;
1095 }
1096 }
1097 }
1098 }
1099 }
1100
Eric Laurent212532b2014-07-21 15:43:18 -07001101 private void checkAllFixedVolumeDevices()
1102 {
1103 int numStreamTypes = AudioSystem.getNumStreamTypes();
1104 for (int streamType = 0; streamType < numStreamTypes; streamType++) {
1105 mStreamStates[streamType].checkFixedVolumeDevices();
1106 }
1107 }
1108
Jean-Michel Triviba5270b2014-10-01 17:49:29 -07001109 private void checkAllFixedVolumeDevices(int streamType) {
1110 mStreamStates[streamType].checkFixedVolumeDevices();
1111 }
1112
John Spurlockb6e19e32015-03-10 21:33:44 -04001113 private void checkMuteAffectedStreams() {
1114 // any stream with a min level > 0 is not muteable by definition
Tomoharu Kasaharaa0d0c542019-01-18 20:04:38 +09001115 // STREAM_VOICE_CALL and STREAM_BLUETOOTH_SCO can be muted by applications
1116 // that has the the MODIFY_PHONE_STATE permission.
John Spurlockb6e19e32015-03-10 21:33:44 -04001117 for (int i = 0; i < mStreamStates.length; i++) {
1118 final VolumeStreamState vss = mStreamStates[i];
Nadav Bar6b7751d2017-12-24 16:03:08 +02001119 if (vss.mIndexMin > 0 &&
Tomoharu Kasaharaa0d0c542019-01-18 20:04:38 +09001120 (vss.mStreamType != AudioSystem.STREAM_VOICE_CALL &&
1121 vss.mStreamType != AudioSystem.STREAM_BLUETOOTH_SCO)) {
John Spurlockb6e19e32015-03-10 21:33:44 -04001122 mMuteAffectedStreams &= ~(1 << vss.mStreamType);
1123 }
1124 }
1125 }
1126
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001127 private void createStreamStates() {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001128 int numStreamTypes = AudioSystem.getNumStreamTypes();
1129 VolumeStreamState[] streams = mStreamStates = new VolumeStreamState[numStreamTypes];
1130
1131 for (int i = 0; i < numStreamTypes; i++) {
Jean-Michel Trivia53b7052017-04-12 18:27:01 -07001132 streams[i] =
1133 new VolumeStreamState(System.VOLUME_SETTINGS_INT[mStreamVolumeAlias[i]], i);
Eric Laurenta553c252009-07-17 12:17:14 -07001134 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001135
Eric Laurent212532b2014-07-21 15:43:18 -07001136 checkAllFixedVolumeDevices();
Eric Laurent24482012012-05-10 09:41:17 -07001137 checkAllAliasStreamVolumes();
John Spurlockb6e19e32015-03-10 21:33:44 -04001138 checkMuteAffectedStreams();
Eric Laurent403bd342017-07-11 16:21:44 -07001139 updateDefaultVolumes();
1140 }
1141
1142 // Update default indexes from aliased streams. Must be called after mStreamStates is created
1143 private void updateDefaultVolumes() {
1144 for (int stream = 0; stream < mStreamStates.length; stream++) {
1145 if (stream != mStreamVolumeAlias[stream]) {
1146 AudioSystem.DEFAULT_STREAM_VOLUME[stream] = rescaleIndex(
1147 AudioSystem.DEFAULT_STREAM_VOLUME[mStreamVolumeAlias[stream]],
1148 mStreamVolumeAlias[stream],
1149 stream);
1150 }
1151 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001152 }
1153
Eric Laurentbffc3d12012-05-07 17:43:49 -07001154 private void dumpStreamStates(PrintWriter pw) {
1155 pw.println("\nStream volumes (device: index)");
1156 int numStreamTypes = AudioSystem.getNumStreamTypes();
1157 for (int i = 0; i < numStreamTypes; i++) {
John Spurlock61560172015-02-06 19:46:04 -05001158 pw.println("- " + AudioSystem.STREAM_NAMES[i] + ":");
Eric Laurentbffc3d12012-05-07 17:43:49 -07001159 mStreamStates[i].dump(pw);
1160 pw.println("");
1161 }
Eric Laurentdd45d012012-10-08 09:04:34 -07001162 pw.print("\n- mute affected streams = 0x");
1163 pw.println(Integer.toHexString(mMuteAffectedStreams));
Eric Laurentbffc3d12012-05-07 17:43:49 -07001164 }
1165
John Spurlock90874332015-03-10 16:00:54 -04001166 private void updateStreamVolumeAlias(boolean updateVolumes, String caller) {
Eric Laurent6d517662012-04-23 18:42:39 -07001167 int dtmfStreamAlias;
Jean-Michel Triviac487672016-11-11 10:05:18 -08001168 final int a11yStreamAlias = sIndependentA11yVolume ?
1169 AudioSystem.STREAM_ACCESSIBILITY : AudioSystem.STREAM_MUSIC;
Eric Laurent212532b2014-07-21 15:43:18 -07001170
Muyuan Li1ed6df62016-06-18 11:16:52 -07001171 if (mIsSingleVolume) {
Eric Laurent212532b2014-07-21 15:43:18 -07001172 mStreamVolumeAlias = STREAM_VOLUME_ALIAS_TELEVISION;
1173 dtmfStreamAlias = AudioSystem.STREAM_MUSIC;
Muyuan Li1ed6df62016-06-18 11:16:52 -07001174 } else {
1175 switch (mPlatformType) {
1176 case AudioSystem.PLATFORM_VOICE:
1177 mStreamVolumeAlias = STREAM_VOLUME_ALIAS_VOICE;
1178 dtmfStreamAlias = AudioSystem.STREAM_RING;
1179 break;
1180 default:
1181 mStreamVolumeAlias = STREAM_VOLUME_ALIAS_DEFAULT;
1182 dtmfStreamAlias = AudioSystem.STREAM_MUSIC;
1183 }
Eric Laurent6d517662012-04-23 18:42:39 -07001184 }
Eric Laurent212532b2014-07-21 15:43:18 -07001185
Muyuan Li1ed6df62016-06-18 11:16:52 -07001186 if (mIsSingleVolume) {
Eric Laurent212532b2014-07-21 15:43:18 -07001187 mRingerModeAffectedStreams = 0;
Eric Laurent24e0d9b2013-10-03 18:15:07 -07001188 } else {
Eric Laurent212532b2014-07-21 15:43:18 -07001189 if (isInCommunication()) {
1190 dtmfStreamAlias = AudioSystem.STREAM_VOICE_CALL;
1191 mRingerModeAffectedStreams &= ~(1 << AudioSystem.STREAM_DTMF);
1192 } else {
1193 mRingerModeAffectedStreams |= (1 << AudioSystem.STREAM_DTMF);
1194 }
Eric Laurent6d517662012-04-23 18:42:39 -07001195 }
Eric Laurent212532b2014-07-21 15:43:18 -07001196
Eric Laurent6d517662012-04-23 18:42:39 -07001197 mStreamVolumeAlias[AudioSystem.STREAM_DTMF] = dtmfStreamAlias;
Jean-Michel Trivi170a0ee2017-04-14 18:13:26 -07001198 mStreamVolumeAlias[AudioSystem.STREAM_ACCESSIBILITY] = a11yStreamAlias;
Jean-Michel Triviac487672016-11-11 10:05:18 -08001199
Eric Laurent403bd342017-07-11 16:21:44 -07001200 if (updateVolumes && mStreamStates != null) {
1201 updateDefaultVolumes();
1202
Jean-Michel Trivi085346a2018-02-14 10:48:51 -08001203 synchronized (mSettingsLock) {
1204 synchronized (VolumeStreamState.class) {
1205 mStreamStates[AudioSystem.STREAM_DTMF]
1206 .setAllIndexes(mStreamStates[dtmfStreamAlias], caller);
1207 mStreamStates[AudioSystem.STREAM_ACCESSIBILITY].mVolumeIndexSettingName =
1208 System.VOLUME_SETTINGS_INT[a11yStreamAlias];
1209 mStreamStates[AudioSystem.STREAM_ACCESSIBILITY].setAllIndexes(
1210 mStreamStates[a11yStreamAlias], caller);
Jean-Michel Trivie05eef82018-03-08 18:56:34 -08001211 mStreamStates[AudioSystem.STREAM_ACCESSIBILITY].refreshRange(
1212 mStreamVolumeAlias[AudioSystem.STREAM_ACCESSIBILITY]);
Jean-Michel Trivi085346a2018-02-14 10:48:51 -08001213 }
1214 }
Jean-Michel Trivi170a0ee2017-04-14 18:13:26 -07001215 if (sIndependentA11yVolume) {
1216 // restore the a11y values from the settings
1217 mStreamStates[AudioSystem.STREAM_ACCESSIBILITY].readSettings();
1218 }
1219
Eric Laurent24e0d9b2013-10-03 18:15:07 -07001220 // apply stream mute states according to new value of mRingerModeAffectedStreams
John Spurlock661f2cf2014-11-17 10:29:10 -05001221 setRingerModeInt(getRingerModeInternal(), false);
Eric Laurent6d517662012-04-23 18:42:39 -07001222 sendMsg(mAudioHandler,
1223 MSG_SET_ALL_VOLUMES,
1224 SENDMSG_QUEUE,
1225 0,
1226 0,
1227 mStreamStates[AudioSystem.STREAM_DTMF], 0);
Jean-Michel Triviac487672016-11-11 10:05:18 -08001228 sendMsg(mAudioHandler,
1229 MSG_SET_ALL_VOLUMES,
1230 SENDMSG_QUEUE,
1231 0,
1232 0,
1233 mStreamStates[AudioSystem.STREAM_ACCESSIBILITY], 0);
Eric Laurent6d517662012-04-23 18:42:39 -07001234 }
1235 }
1236
Eric Laurent7ee1e4f2012-10-26 18:11:21 -07001237 private void readDockAudioSettings(ContentResolver cr)
1238 {
1239 mDockAudioMediaEnabled = Settings.Global.getInt(
Eric Laurent5ba0ffa02012-10-29 12:31:09 -07001240 cr, Settings.Global.DOCK_AUDIO_MEDIA_ENABLED, 0) == 1;
Eric Laurent7ee1e4f2012-10-26 18:11:21 -07001241
Eric Laurent7ee1e4f2012-10-26 18:11:21 -07001242 sendMsg(mAudioHandler,
1243 MSG_SET_FORCE_USE,
1244 SENDMSG_QUEUE,
1245 AudioSystem.FOR_DOCK,
1246 mDockAudioMediaEnabled ?
1247 AudioSystem.FORCE_ANALOG_DOCK : AudioSystem.FORCE_NONE,
Jean-Michel Trivi011f39e2017-08-19 18:08:06 -07001248 new String("readDockAudioSettings"),
Eric Laurent7ee1e4f2012-10-26 18:11:21 -07001249 0);
1250 }
1251
Phil Burkac0f7042016-02-24 12:19:08 -08001252
Andy Hung7b98e9a2016-02-25 18:34:50 -08001253 private void updateMasterMono(ContentResolver cr)
1254 {
1255 final boolean masterMono = System.getIntForUser(
1256 cr, System.MASTER_MONO, 0 /* default */, UserHandle.USER_CURRENT) == 1;
1257 if (DEBUG_VOL) {
1258 Log.d(TAG, String.format("Master mono %b", masterMono));
1259 }
1260 AudioSystem.setMasterMono(masterMono);
1261 }
1262
Edward Savage-Jones35c292f2017-01-13 09:04:34 +01001263 private void updateMasterBalance(ContentResolver cr) {
1264 final float masterBalance = System.getFloatForUser(
1265 cr, System.MASTER_BALANCE, 0.f /* default */, UserHandle.USER_CURRENT);
1266 if (DEBUG_VOL) {
1267 Log.d(TAG, String.format("Master balance %f", masterBalance));
1268 }
1269 if (AudioSystem.setMasterBalance(masterBalance) != 0) {
1270 Log.e(TAG, String.format("setMasterBalance failed for %f", masterBalance));
1271 }
1272 }
1273
Jean-Michel Trivi011f39e2017-08-19 18:08:06 -07001274 private void sendEncodedSurroundMode(ContentResolver cr, String eventSource)
Phil Burkac0f7042016-02-24 12:19:08 -08001275 {
Jean-Michel Trivi58850372018-09-14 16:01:28 -07001276 final int encodedSurroundMode = Settings.Global.getInt(
Phil Burkac0f7042016-02-24 12:19:08 -08001277 cr, Settings.Global.ENCODED_SURROUND_OUTPUT,
1278 Settings.Global.ENCODED_SURROUND_OUTPUT_AUTO);
Jean-Michel Trivi011f39e2017-08-19 18:08:06 -07001279 sendEncodedSurroundMode(encodedSurroundMode, eventSource);
Phil Burkac0f7042016-02-24 12:19:08 -08001280 }
1281
Jean-Michel Trivi011f39e2017-08-19 18:08:06 -07001282 private void sendEncodedSurroundMode(int encodedSurroundMode, String eventSource)
Phil Burkac0f7042016-02-24 12:19:08 -08001283 {
1284 // initialize to guaranteed bad value
1285 int forceSetting = AudioSystem.NUM_FORCE_CONFIG;
1286 switch (encodedSurroundMode) {
1287 case Settings.Global.ENCODED_SURROUND_OUTPUT_AUTO:
1288 forceSetting = AudioSystem.FORCE_NONE;
1289 break;
1290 case Settings.Global.ENCODED_SURROUND_OUTPUT_NEVER:
1291 forceSetting = AudioSystem.FORCE_ENCODED_SURROUND_NEVER;
1292 break;
1293 case Settings.Global.ENCODED_SURROUND_OUTPUT_ALWAYS:
1294 forceSetting = AudioSystem.FORCE_ENCODED_SURROUND_ALWAYS;
1295 break;
jiabin39940752018-04-02 18:18:45 -07001296 case Settings.Global.ENCODED_SURROUND_OUTPUT_MANUAL:
1297 forceSetting = AudioSystem.FORCE_ENCODED_SURROUND_MANUAL;
1298 break;
Phil Burkac0f7042016-02-24 12:19:08 -08001299 default:
1300 Log.e(TAG, "updateSurroundSoundSettings: illegal value "
1301 + encodedSurroundMode);
1302 break;
1303 }
1304 if (forceSetting != AudioSystem.NUM_FORCE_CONFIG) {
Jean-Michel Trivi58850372018-09-14 16:01:28 -07001305 mDeviceBroker.setForceUse_Async(AudioSystem.FOR_ENCODED_SURROUND, forceSetting,
1306 eventSource);
Phil Burkac0f7042016-02-24 12:19:08 -08001307 }
1308 }
1309
jiabin39940752018-04-02 18:18:45 -07001310 private void sendEnabledSurroundFormats(ContentResolver cr, boolean forceUpdate) {
1311 if (mEncodedSurroundMode != Settings.Global.ENCODED_SURROUND_OUTPUT_MANUAL) {
1312 // Manually enable surround formats only when the setting is in manual mode.
1313 return;
1314 }
1315 String enabledSurroundFormats = Settings.Global.getString(
1316 cr, Settings.Global.ENCODED_SURROUND_OUTPUT_ENABLED_FORMATS);
jiabin6db5f862018-05-17 10:33:09 -07001317 if (enabledSurroundFormats == null) {
1318 // Never allow enabledSurroundFormats as a null, which could happen when
1319 // ENCODED_SURROUND_OUTPUT_ENABLED_FORMATS is not appear in settings DB.
1320 enabledSurroundFormats = "";
1321 }
jiabin39940752018-04-02 18:18:45 -07001322 if (!forceUpdate && TextUtils.equals(enabledSurroundFormats, mEnabledSurroundFormats)) {
1323 // Update enabled surround formats to AudioPolicyManager only when forceUpdate
1324 // is true or enabled surround formats changed.
1325 return;
1326 }
1327
1328 mEnabledSurroundFormats = enabledSurroundFormats;
1329 String[] surroundFormats = TextUtils.split(enabledSurroundFormats, ",");
1330 ArrayList<Integer> formats = new ArrayList<>();
1331 for (String format : surroundFormats) {
1332 try {
1333 int audioFormat = Integer.valueOf(format);
1334 boolean isSurroundFormat = false;
1335 for (int sf : AudioFormat.SURROUND_SOUND_ENCODING) {
1336 if (sf == audioFormat) {
1337 isSurroundFormat = true;
1338 break;
1339 }
1340 }
1341 if (isSurroundFormat && !formats.contains(audioFormat)) {
1342 formats.add(audioFormat);
1343 }
1344 } catch (Exception e) {
1345 Log.e(TAG, "Invalid enabled surround format:" + format);
1346 }
1347 }
1348 // Set filtered surround formats to settings DB in case
1349 // there are invalid surround formats in original settings.
1350 Settings.Global.putString(mContext.getContentResolver(),
1351 Settings.Global.ENCODED_SURROUND_OUTPUT_ENABLED_FORMATS,
1352 TextUtils.join(",", formats));
1353 sendMsg(mAudioHandler, MSG_ENABLE_SURROUND_FORMATS, SENDMSG_QUEUE, 0, 0, formats, 0);
1354 }
1355
1356 private void onEnableSurroundFormats(ArrayList<Integer> enabledSurroundFormats) {
1357 // Set surround format enabled accordingly.
1358 for (int surroundFormat : AudioFormat.SURROUND_SOUND_ENCODING) {
1359 boolean enabled = enabledSurroundFormats.contains(surroundFormat);
1360 int ret = AudioSystem.setSurroundFormatEnabled(surroundFormat, enabled);
1361 Log.i(TAG, "enable surround format:" + surroundFormat + " " + enabled + " " + ret);
1362 }
1363 }
1364
Eric Laurent1c9c1d52018-10-17 10:06:46 -07001365 @GuardedBy("mSettingsLock")
1366 private void updateAssistantUId(boolean forceUpdate) {
1367 int assistantUid = 0;
1368
1369 // Consider assistants in the following order of priority:
1370 // 1) voice interaction service
1371 // 2) assistant
1372 String assistantName = Settings.Secure.getStringForUser(
1373 mContentResolver,
1374 Settings.Secure.VOICE_INTERACTION_SERVICE, UserHandle.USER_CURRENT);
1375 if (TextUtils.isEmpty(assistantName)) {
1376 assistantName = Settings.Secure.getStringForUser(
1377 mContentResolver,
1378 Settings.Secure.ASSISTANT, UserHandle.USER_CURRENT);
1379 }
1380 if (!TextUtils.isEmpty(assistantName)) {
1381 String packageName = ComponentName.unflattenFromString(assistantName).getPackageName();
1382 if (!TextUtils.isEmpty(packageName)) {
1383 try {
1384 assistantUid = mContext.getPackageManager().getPackageUid(packageName, 0);
1385 } catch (PackageManager.NameNotFoundException e) {
1386 Log.e(TAG,
1387 "updateAssistantUId() could not find UID for package: " + packageName);
1388 }
1389 }
1390 }
1391
1392 if (assistantUid != mAssistantUid || forceUpdate) {
1393 AudioSystem.setAssistantUid(assistantUid);
1394 mAssistantUid = assistantUid;
1395 }
1396 }
1397
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001398 private void readPersistedSettings() {
1399 final ContentResolver cr = mContentResolver;
1400
Eric Laurentbffc3d12012-05-07 17:43:49 -07001401 int ringerModeFromSettings =
Jeff Sharkey8d9a1f62012-10-18 15:38:14 -07001402 Settings.Global.getInt(
1403 cr, Settings.Global.MODE_RINGER, AudioManager.RINGER_MODE_NORMAL);
Eric Laurentbffc3d12012-05-07 17:43:49 -07001404 int ringerMode = ringerModeFromSettings;
Eric Laurent72668b22011-07-19 16:04:27 -07001405 // sanity check in case the settings are restored from a device with incompatible
1406 // ringer modes
John Spurlock97559372014-10-24 16:27:36 -04001407 if (!isValidRingerMode(ringerMode)) {
Glenn Kastenba195eb2011-12-13 09:30:40 -08001408 ringerMode = AudioManager.RINGER_MODE_NORMAL;
Eric Laurentbffc3d12012-05-07 17:43:49 -07001409 }
1410 if ((ringerMode == AudioManager.RINGER_MODE_VIBRATE) && !mHasVibrator) {
1411 ringerMode = AudioManager.RINGER_MODE_SILENT;
1412 }
1413 if (ringerMode != ringerModeFromSettings) {
Jeff Sharkey8d9a1f62012-10-18 15:38:14 -07001414 Settings.Global.putInt(cr, Settings.Global.MODE_RINGER, ringerMode);
Glenn Kastenba195eb2011-12-13 09:30:40 -08001415 }
Muyuan Li1ed6df62016-06-18 11:16:52 -07001416 if (mUseFixedVolume || mIsSingleVolume) {
Eric Laurent83a017b2013-03-19 18:15:31 -07001417 ringerMode = AudioManager.RINGER_MODE_NORMAL;
1418 }
Glenn Kastenba195eb2011-12-13 09:30:40 -08001419 synchronized(mSettingsLock) {
1420 mRingerMode = ringerMode;
John Spurlock661f2cf2014-11-17 10:29:10 -05001421 if (mRingerModeExternal == -1) {
1422 mRingerModeExternal = mRingerMode;
1423 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001424
Eric Laurentdd45d012012-10-08 09:04:34 -07001425 // System.VIBRATE_ON is not used any more but defaults for mVibrateSetting
1426 // are still needed while setVibrateSetting() and getVibrateSetting() are being
1427 // deprecated.
John Spurlock61560172015-02-06 19:46:04 -05001428 mVibrateSetting = AudioSystem.getValueForVibrateSetting(0,
Eric Laurentdd45d012012-10-08 09:04:34 -07001429 AudioManager.VIBRATE_TYPE_NOTIFICATION,
1430 mHasVibrator ? AudioManager.VIBRATE_SETTING_ONLY_SILENT
1431 : AudioManager.VIBRATE_SETTING_OFF);
John Spurlock61560172015-02-06 19:46:04 -05001432 mVibrateSetting = AudioSystem.getValueForVibrateSetting(mVibrateSetting,
Eric Laurentdd45d012012-10-08 09:04:34 -07001433 AudioManager.VIBRATE_TYPE_RINGER,
1434 mHasVibrator ? AudioManager.VIBRATE_SETTING_ONLY_SILENT
1435 : AudioManager.VIBRATE_SETTING_OFF);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001436
Beverlyd6964762018-02-16 14:07:03 -05001437 updateRingerAndZenModeAffectedStreams();
Eric Laurent7ee1e4f2012-10-26 18:11:21 -07001438 readDockAudioSettings(cr);
Jean-Michel Trivi011f39e2017-08-19 18:08:06 -07001439 sendEncodedSurroundMode(cr, "readPersistedSettings");
jiabin39940752018-04-02 18:18:45 -07001440 sendEnabledSurroundFormats(cr, true);
Eric Laurent1c9c1d52018-10-17 10:06:46 -07001441 updateAssistantUId(true);
Eric Laurent402f7f22011-02-04 12:30:32 -08001442 }
Eric Laurentc1d41662011-07-19 11:21:13 -07001443
Eric Laurentbc0fab1f2012-09-19 11:24:41 -07001444 mMuteAffectedStreams = System.getIntForUser(cr,
John Spurlock61560172015-02-06 19:46:04 -05001445 System.MUTE_STREAMS_AFFECTED, AudioSystem.DEFAULT_MUTE_STREAMS_AFFECTED,
John Spurlock24c05182015-02-05 12:30:36 -05001446 UserHandle.USER_CURRENT);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001447
Andy Hung7b98e9a2016-02-25 18:34:50 -08001448 updateMasterMono(cr);
Andy Hungf04b84d2015-12-18 17:33:27 -08001449
Edward Savage-Jones35c292f2017-01-13 09:04:34 +01001450 updateMasterBalance(cr);
1451
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001452 // Each stream will read its own persisted settings
1453
John Spurlockbcc10872014-11-28 15:29:21 -05001454 // Broadcast the sticky intents
1455 broadcastRingerMode(AudioManager.RINGER_MODE_CHANGED_ACTION, mRingerModeExternal);
1456 broadcastRingerMode(AudioManager.INTERNAL_RINGER_MODE_CHANGED_ACTION, mRingerMode);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001457
1458 // Broadcast vibrate settings
1459 broadcastVibrateSetting(AudioManager.VIBRATE_TYPE_RINGER);
1460 broadcastVibrateSetting(AudioManager.VIBRATE_TYPE_NOTIFICATION);
Jean-Michel Trivid589fea2011-04-15 11:28:10 -07001461
John Spurlock33f4e042014-07-11 13:10:58 -04001462 // Load settings for the volume controller
1463 mVolumeController.loadSettings(cr);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001464 }
1465
Eric Laurentc0232482016-03-15 18:19:23 -07001466 private void readUserRestrictions() {
1467 final int currentUser = getCurrentUserId();
1468
1469 // Check the current user restriction.
Tony Makc1205112016-07-22 16:02:59 +01001470 boolean masterMute =
1471 mUserManagerInternal.getUserRestriction(currentUser,
Esteban Talavera492b4722017-02-13 14:59:45 +00001472 UserManager.DISALLOW_UNMUTE_DEVICE)
Tony Makc1205112016-07-22 16:02:59 +01001473 || mUserManagerInternal.getUserRestriction(currentUser,
1474 UserManager.DISALLOW_ADJUST_VOLUME);
Eric Laurentc0232482016-03-15 18:19:23 -07001475 if (mUseFixedVolume) {
1476 masterMute = false;
1477 AudioSystem.setMasterVolume(1.0f);
1478 }
1479 if (DEBUG_VOL) {
1480 Log.d(TAG, String.format("Master mute %s, user=%d", masterMute, currentUser));
1481 }
1482 setSystemAudioMute(masterMute);
1483 AudioSystem.setMasterMute(masterMute);
1484 broadcastMasterMuteStatus(masterMute);
1485
1486 boolean microphoneMute = mUserManagerInternal.getUserRestriction(
1487 currentUser, UserManager.DISALLOW_UNMUTE_MICROPHONE);
1488 if (DEBUG_VOL) {
1489 Log.d(TAG, String.format("Mic mute %s, user=%d", microphoneMute, currentUser));
1490 }
1491 AudioSystem.muteMicrophone(microphoneMute);
1492 }
1493
Eric Laurenta553c252009-07-17 12:17:14 -07001494 private int rescaleIndex(int index, int srcStream, int dstStream) {
David Brageule220d3b2018-09-24 08:40:49 +02001495 int max = mStreamStates[srcStream].getMaxIndex();
1496 if (max == 0) {
1497 Log.e(TAG, "rescaleIndex : Max index should not be zero");
1498 return mStreamStates[srcStream].getMinIndex();
1499 }
Jean-Michel Trivie05eef82018-03-08 18:56:34 -08001500 final int rescaled =
1501 (index * mStreamStates[dstStream].getMaxIndex()
1502 + mStreamStates[srcStream].getMaxIndex() / 2)
1503 / mStreamStates[srcStream].getMaxIndex();
1504 if (rescaled < mStreamStates[dstStream].getMinIndex()) {
1505 return mStreamStates[dstStream].getMinIndex();
1506 } else {
1507 return rescaled;
1508 }
Eric Laurenta553c252009-07-17 12:17:14 -07001509 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001510
1511 ///////////////////////////////////////////////////////////////////////////
1512 // IPC methods
1513 ///////////////////////////////////////////////////////////////////////////
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001514 /** @see AudioManager#adjustVolume(int, int) */
Dianne Hackbornba50b97c2013-04-30 15:04:46 -07001515 public void adjustSuggestedStreamVolume(int direction, int suggestedStreamType, int flags,
John Spurlock90874332015-03-10 16:00:54 -04001516 String callingPackage, String caller) {
Jean-Michel Trivi610aa9b2018-01-27 15:42:42 -08001517 final IAudioPolicyCallback extVolCtlr;
1518 synchronized (mExtVolumeControllerLock) {
1519 extVolCtlr = mExtVolumeController;
1520 }
1521 if (extVolCtlr != null) {
Jean-Michel Trivi7ed71472018-02-02 16:52:09 -08001522 sendMsg(mAudioHandler, MSG_NOTIFY_VOL_EVENT, SENDMSG_QUEUE,
1523 direction, 0 /*ignored*/,
1524 extVolCtlr, 0 /*delay*/);
Jean-Michel Trivi610aa9b2018-01-27 15:42:42 -08001525 } else {
1526 adjustSuggestedStreamVolume(direction, suggestedStreamType, flags, callingPackage,
1527 caller, Binder.getCallingUid());
1528 }
RoboErik272e1612014-09-05 11:39:29 -07001529 }
1530
1531 private void adjustSuggestedStreamVolume(int direction, int suggestedStreamType, int flags,
John Spurlock90874332015-03-10 16:00:54 -04001532 String callingPackage, String caller, int uid) {
1533 if (DEBUG_VOL) Log.d(TAG, "adjustSuggestedStreamVolume() stream=" + suggestedStreamType
Jean-Michel Trivia7880d42017-04-15 12:41:05 -07001534 + ", flags=" + flags + ", caller=" + caller
1535 + ", volControlStream=" + mVolumeControlStream
1536 + ", userSelect=" + mUserSelectedVolumeControlStream);
Jean-Michel Trivi8505b232019-04-13 16:52:27 -07001537 if (direction != AudioManager.ADJUST_SAME) {
1538 sVolumeLogger.log(new VolumeEvent(VolumeEvent.VOL_ADJUST_SUGG_VOL, suggestedStreamType,
1539 direction/*val1*/, flags/*val2*/, new StringBuilder(callingPackage)
1540 .append("/").append(caller).append(" uid:").append(uid).toString()));
1541 }
Jean-Michel Trivia7880d42017-04-15 12:41:05 -07001542 final int streamType;
jiabin8fd5d5e2018-03-23 14:09:28 -07001543 synchronized (mForceControlStreamLock) {
1544 // Request lock in case mVolumeControlStream is changed by other thread.
1545 if (mUserSelectedVolumeControlStream) { // implies mVolumeControlStream != -1
Jean-Michel Trivia7880d42017-04-15 12:41:05 -07001546 streamType = mVolumeControlStream;
jiabin8fd5d5e2018-03-23 14:09:28 -07001547 } else {
1548 final int maybeActiveStreamType = getActiveStreamType(suggestedStreamType);
1549 final boolean activeForReal;
1550 if (maybeActiveStreamType == AudioSystem.STREAM_RING
1551 || maybeActiveStreamType == AudioSystem.STREAM_NOTIFICATION) {
1552 activeForReal = wasStreamActiveRecently(maybeActiveStreamType, 0);
1553 } else {
1554 activeForReal = AudioSystem.isStreamActive(maybeActiveStreamType, 0);
1555 }
1556 if (activeForReal || mVolumeControlStream == -1) {
1557 streamType = maybeActiveStreamType;
1558 } else {
1559 streamType = mVolumeControlStream;
1560 }
Jean-Michel Trivia7880d42017-04-15 12:41:05 -07001561 }
Eric Laurent402f7f22011-02-04 12:30:32 -08001562 }
Jean-Michel Trivia7880d42017-04-15 12:41:05 -07001563
1564 final boolean isMute = isMuteAdjust(direction);
1565
John Spurlock0a376af2015-03-26 16:24:12 -04001566 ensureValidStreamType(streamType);
John Spurlock33f4e042014-07-11 13:10:58 -04001567 final int resolvedStream = mStreamVolumeAlias[streamType];
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001568
RoboErik2811dd32014-08-12 09:48:13 -07001569 // Play sounds on STREAM_RING only.
1570 if ((flags & AudioManager.FLAG_PLAY_SOUND) != 0 &&
John Spurlock33f4e042014-07-11 13:10:58 -04001571 resolvedStream != AudioSystem.STREAM_RING) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001572 flags &= ~AudioManager.FLAG_PLAY_SOUND;
1573 }
1574
John Spurlock33f4e042014-07-11 13:10:58 -04001575 // For notifications/ring, show the ui before making any adjustments
RoboErik4197cb62015-01-21 15:45:32 -08001576 // Don't suppress mute/unmute requests
Stanley Changb77e13d2018-08-28 08:16:03 +08001577 // Don't suppress adjustments for single volume device
1578 if (mVolumeController.suppressAdjustment(resolvedStream, flags, isMute)
1579 && !mIsSingleVolume) {
John Spurlock33f4e042014-07-11 13:10:58 -04001580 direction = 0;
1581 flags &= ~AudioManager.FLAG_PLAY_SOUND;
1582 flags &= ~AudioManager.FLAG_VIBRATE;
1583 if (DEBUG_VOL) Log.d(TAG, "Volume controller suppressed adjustment");
1584 }
1585
John Spurlock90874332015-03-10 16:00:54 -04001586 adjustStreamVolume(streamType, direction, flags, callingPackage, caller, uid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001587 }
1588
1589 /** @see AudioManager#adjustStreamVolume(int, int, int) */
Dianne Hackbornba50b97c2013-04-30 15:04:46 -07001590 public void adjustStreamVolume(int streamType, int direction, int flags,
1591 String callingPackage) {
Phil Weaverf1a9aff2017-03-23 17:21:29 -07001592 if ((streamType == AudioManager.STREAM_ACCESSIBILITY) && !canChangeAccessibilityVolume()) {
Jean-Michel Triviab2d9312017-03-13 15:33:39 -07001593 Log.w(TAG, "Trying to call adjustStreamVolume() for a11y without"
Phil Weaverf1a9aff2017-03-23 17:21:29 -07001594 + "CHANGE_ACCESSIBILITY_VOLUME / callingPackage=" + callingPackage);
Jean-Michel Triviab2d9312017-03-13 15:33:39 -07001595 return;
1596 }
Jean-Michel Trivi58850372018-09-14 16:01:28 -07001597 sVolumeLogger.log(new VolumeEvent(VolumeEvent.VOL_ADJUST_STREAM_VOL, streamType,
Jean-Michel Trivicf170362017-08-24 17:24:57 -07001598 direction/*val1*/, flags/*val2*/, callingPackage));
John Spurlock90874332015-03-10 16:00:54 -04001599 adjustStreamVolume(streamType, direction, flags, callingPackage, callingPackage,
1600 Binder.getCallingUid());
RoboErik0dac35a2014-08-12 15:48:49 -07001601 }
1602
Chinyue Chen6affe932018-01-24 14:51:43 +08001603 protected void adjustStreamVolume(int streamType, int direction, int flags,
John Spurlock90874332015-03-10 16:00:54 -04001604 String callingPackage, String caller, int uid) {
Eric Laurent83a017b2013-03-19 18:15:31 -07001605 if (mUseFixedVolume) {
1606 return;
1607 }
John Spurlock90874332015-03-10 16:00:54 -04001608 if (DEBUG_VOL) Log.d(TAG, "adjustStreamVolume() stream=" + streamType + ", dir=" + direction
1609 + ", flags=" + flags + ", caller=" + caller);
Jean-Michel Trivi3114ce32012-06-11 15:03:52 -07001610
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001611 ensureValidDirection(direction);
1612 ensureValidStreamType(streamType);
1613
RoboErik4197cb62015-01-21 15:45:32 -08001614 boolean isMuteAdjust = isMuteAdjust(direction);
1615
John Spurlock3ce37252015-02-17 13:20:45 -05001616 if (isMuteAdjust && !isStreamAffectedByMute(streamType)) {
1617 return;
1618 }
1619
Tomoharu Kasaharaa0d0c542019-01-18 20:04:38 +09001620 // If adjust is mute and the stream is STREAM_VOICE_CALL or STREAM_BLUETOOTH_SCO, make sure
Nadav Bar6b7751d2017-12-24 16:03:08 +02001621 // that the calling app have the MODIFY_PHONE_STATE permission.
1622 if (isMuteAdjust &&
Tomoharu Kasaharaa0d0c542019-01-18 20:04:38 +09001623 (streamType == AudioSystem.STREAM_VOICE_CALL ||
1624 streamType == AudioSystem.STREAM_BLUETOOTH_SCO) &&
Nadav Bar6b7751d2017-12-24 16:03:08 +02001625 mContext.checkCallingOrSelfPermission(
1626 android.Manifest.permission.MODIFY_PHONE_STATE)
1627 != PackageManager.PERMISSION_GRANTED) {
1628 Log.w(TAG, "MODIFY_PHONE_STATE Permission Denial: adjustStreamVolume from pid="
1629 + Binder.getCallingPid() + ", uid=" + Binder.getCallingUid());
1630 return;
1631 }
1632
Eric Laurent96a33d12011-11-08 10:31:57 -08001633 // use stream type alias here so that streams with same alias have the same behavior,
1634 // including with regard to silent mode control (e.g the use of STREAM_RING below and in
1635 // checkForRingerModeChange() in place of STREAM_RING or STREAM_NOTIFICATION)
Eric Laurent6d517662012-04-23 18:42:39 -07001636 int streamTypeAlias = mStreamVolumeAlias[streamType];
RoboErik4197cb62015-01-21 15:45:32 -08001637
Eric Laurentb024c302011-10-14 17:19:27 -07001638 VolumeStreamState streamState = mStreamStates[streamTypeAlias];
Eric Laurent9bc8358d2011-11-18 16:43:31 -08001639
1640 final int device = getDeviceForStream(streamTypeAlias);
Eric Laurent3ef75492012-11-28 12:12:23 -08001641
Eric Laurent42b041e2013-03-29 11:36:03 -07001642 int aliasIndex = streamState.getIndex(device);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001643 boolean adjustVolume = true;
Eric Laurent3ef75492012-11-28 12:12:23 -08001644 int step;
Eric Laurent24482012012-05-10 09:41:17 -07001645
Matthew Xiec9d1d5f2013-09-12 00:32:22 -07001646 // skip a2dp absolute volume control request when the device
1647 // is not an a2dp device
1648 if ((device & AudioSystem.DEVICE_OUT_ALL_A2DP) == 0 &&
1649 (flags & AudioManager.FLAG_BLUETOOTH_ABS_VOLUME) != 0) {
1650 return;
1651 }
1652
Kenny Guy70e0c582015-06-30 19:18:28 +01001653 // If we are being called by the system (e.g. hardware keys) check for current user
1654 // so we handle user restrictions correctly.
1655 if (uid == android.os.Process.SYSTEM_UID) {
1656 uid = UserHandle.getUid(getCurrentUserId(), UserHandle.getAppId(uid));
1657 }
John Spurlock59dc9c12015-03-02 11:20:15 -05001658 if (mAppOps.noteOp(STREAM_VOLUME_OPS[streamTypeAlias], uid, callingPackage)
RoboErik0dac35a2014-08-12 15:48:49 -07001659 != AppOpsManager.MODE_ALLOWED) {
Dianne Hackbornba50b97c2013-04-30 15:04:46 -07001660 return;
1661 }
1662
Eric Laurentfde16d52012-12-03 14:42:39 -08001663 // reset any pending volume command
hyomin.ohd0446dc2018-10-18 13:58:27 +09001664 synchronized (mSafeMediaVolumeStateLock) {
Eric Laurentfde16d52012-12-03 14:42:39 -08001665 mPendingVolumeCommand = null;
1666 }
1667
Eric Laurent3ef75492012-11-28 12:12:23 -08001668 flags &= ~AudioManager.FLAG_FIXED_VOLUME;
1669 if ((streamTypeAlias == AudioSystem.STREAM_MUSIC) &&
Jean-Michel Trivi90dbfdf2019-04-10 14:11:40 -07001670 ((device & mFixedVolumeDevices) != 0)) {
Eric Laurent3ef75492012-11-28 12:12:23 -08001671 flags |= AudioManager.FLAG_FIXED_VOLUME;
1672
1673 // Always toggle between max safe volume and 0 for fixed volume devices where safe
1674 // volume is enforced, and max and 0 for the others.
1675 // This is simulated by stepping by the full allowed volume range
1676 if (mSafeMediaVolumeState == SAFE_MEDIA_VOLUME_ACTIVE &&
1677 (device & mSafeMediaVolumeDevices) != 0) {
Eric Laurenteab40d12017-06-09 12:45:21 -07001678 step = safeMediaVolumeIndex(device);
Eric Laurent3ef75492012-11-28 12:12:23 -08001679 } else {
1680 step = streamState.getMaxIndex();
1681 }
1682 if (aliasIndex != 0) {
1683 aliasIndex = step;
1684 }
1685 } else {
1686 // convert one UI step (+/-1) into a number of internal units on the stream alias
1687 step = rescaleIndex(10, streamType, streamTypeAlias);
1688 }
1689
Eric Laurent42b041e2013-03-29 11:36:03 -07001690 // If either the client forces allowing ringer modes for this adjustment,
1691 // or the stream type is one that is affected by ringer modes
1692 if (((flags & AudioManager.FLAG_ALLOW_RINGER_MODES) != 0) ||
John Spurlockee5ad722015-03-03 16:17:21 -05001693 (streamTypeAlias == getUiSoundsStreamType())) {
John Spurlock661f2cf2014-11-17 10:29:10 -05001694 int ringerMode = getRingerModeInternal();
Eric Laurent42b041e2013-03-29 11:36:03 -07001695 // do not vibrate if already in vibrate mode
1696 if (ringerMode == AudioManager.RINGER_MODE_VIBRATE) {
1697 flags &= ~AudioManager.FLAG_VIBRATE;
Eric Laurent3ef75492012-11-28 12:12:23 -08001698 }
RoboErik5452e252015-02-06 15:33:53 -08001699 // Check if the ringer mode handles this adjustment. If it does we don't
1700 // need to adjust the volume further.
John Spurlock50ced3f2015-05-11 16:00:09 -04001701 final int result = checkForRingerModeChange(aliasIndex, direction, step,
Julia Reynoldsed783792016-04-08 15:27:35 -04001702 streamState.mIsMuted, callingPackage, flags);
John Spurlocka11b4af2014-06-01 11:52:23 -04001703 adjustVolume = (result & FLAG_ADJUST_VOLUME) != 0;
1704 // If suppressing a volume adjustment in silent mode, display the UI hint
1705 if ((result & AudioManager.FLAG_SHOW_SILENT_HINT) != 0) {
1706 flags |= AudioManager.FLAG_SHOW_SILENT_HINT;
1707 }
John Spurlock661f2cf2014-11-17 10:29:10 -05001708 // If suppressing a volume down adjustment in vibrate mode, display the UI hint
1709 if ((result & AudioManager.FLAG_SHOW_VIBRATE_HINT) != 0) {
1710 flags |= AudioManager.FLAG_SHOW_VIBRATE_HINT;
1711 }
Eric Laurent42b041e2013-03-29 11:36:03 -07001712 }
Beverlyd6964762018-02-16 14:07:03 -05001713
1714 // If the ringer mode or zen is muting the stream, do not change stream unless
1715 // it'll cause us to exit dnd
Julia Reynoldsed783792016-04-08 15:27:35 -04001716 if (!volumeAdjustmentAllowedByDnd(streamTypeAlias, flags)) {
John Spurlock50ced3f2015-05-11 16:00:09 -04001717 adjustVolume = false;
1718 }
Eric Laurent42b041e2013-03-29 11:36:03 -07001719 int oldIndex = mStreamStates[streamType].getIndex(device);
Eric Laurent3ef75492012-11-28 12:12:23 -08001720
Eric Laurent42b041e2013-03-29 11:36:03 -07001721 if (adjustVolume && (direction != AudioManager.ADJUST_SAME)) {
RoboErik5452e252015-02-06 15:33:53 -08001722 mAudioHandler.removeMessages(MSG_UNMUTE_STREAM);
Matthew Xiec9d1d5f2013-09-12 00:32:22 -07001723
RoboErik4197cb62015-01-21 15:45:32 -08001724 if (isMuteAdjust) {
1725 boolean state;
1726 if (direction == AudioManager.ADJUST_TOGGLE_MUTE) {
1727 state = !streamState.mIsMuted;
1728 } else {
1729 state = direction == AudioManager.ADJUST_MUTE;
1730 }
1731 if (streamTypeAlias == AudioSystem.STREAM_MUSIC) {
1732 setSystemAudioMute(state);
1733 }
1734 for (int stream = 0; stream < mStreamStates.length; stream++) {
1735 if (streamTypeAlias == mStreamVolumeAlias[stream]) {
Sungmin Choi841ed0a2015-07-26 23:09:49 -07001736 if (!(readCameraSoundForced()
1737 && (mStreamStates[stream].getStreamType()
1738 == AudioSystem.STREAM_SYSTEM_ENFORCED))) {
1739 mStreamStates[stream].mute(state);
1740 }
RoboErik4197cb62015-01-21 15:45:32 -08001741 }
1742 }
1743 } else if ((direction == AudioManager.ADJUST_RAISE) &&
Eric Laurent42b041e2013-03-29 11:36:03 -07001744 !checkSafeMediaVolume(streamTypeAlias, aliasIndex + step, device)) {
RoboErik4197cb62015-01-21 15:45:32 -08001745 Log.e(TAG, "adjustStreamVolume() safe volume index = " + oldIndex);
John Spurlock3346a802014-05-20 16:25:37 -04001746 mVolumeController.postDisplaySafeVolumeWarning(flags);
Jean-Michel Trivi90dbfdf2019-04-10 14:11:40 -07001747 } else if (((device & mFullVolumeDevices) == 0)
1748 && (streamState.adjustIndex(direction * step, device, caller)
1749 || streamState.mIsMuted)) {
RoboErik4197cb62015-01-21 15:45:32 -08001750 // Post message to set system volume (it in turn will post a
1751 // message to persist).
1752 if (streamState.mIsMuted) {
1753 // Unmute the stream if it was previously muted
RoboErik5452e252015-02-06 15:33:53 -08001754 if (direction == AudioManager.ADJUST_RAISE) {
1755 // unmute immediately for volume up
1756 streamState.mute(false);
1757 } else if (direction == AudioManager.ADJUST_LOWER) {
Muyuan Li1ed6df62016-06-18 11:16:52 -07001758 if (mIsSingleVolume) {
John Spurlocka48d7792015-03-03 17:35:57 -05001759 sendMsg(mAudioHandler, MSG_UNMUTE_STREAM, SENDMSG_QUEUE,
1760 streamTypeAlias, flags, null, UNMUTE_STREAM_DELAY);
1761 }
RoboErik5452e252015-02-06 15:33:53 -08001762 }
RoboErik4197cb62015-01-21 15:45:32 -08001763 }
Eric Laurent42b041e2013-03-29 11:36:03 -07001764 sendMsg(mAudioHandler,
1765 MSG_SET_DEVICE_VOLUME,
1766 SENDMSG_QUEUE,
1767 device,
1768 0,
1769 streamState,
1770 0);
Eric Laurent4bbcc652012-09-24 14:26:30 -07001771 }
Jungshik Jang41d97462014-06-30 22:26:29 +09001772
Jungshik Jang41d97462014-06-30 22:26:29 +09001773 int newIndex = mStreamStates[streamType].getIndex(device);
Ajay Panickere3946c82018-02-26 16:04:15 -08001774
1775 // Check if volume update should be send to AVRCP
1776 if (streamTypeAlias == AudioSystem.STREAM_MUSIC &&
1777 (device & AudioSystem.DEVICE_OUT_ALL_A2DP) != 0 &&
1778 (flags & AudioManager.FLAG_BLUETOOTH_ABS_VOLUME) == 0) {
Jean-Michel Trivi58850372018-09-14 16:01:28 -07001779 if (DEBUG_VOL) {
1780 Log.d(TAG, "adjustSreamVolume: postSetAvrcpAbsoluteVolumeIndex index="
1781 + newIndex + "stream=" + streamType);
Ajay Panickere3946c82018-02-26 16:04:15 -08001782 }
Jean-Michel Trivi734819a2019-02-04 15:44:28 -08001783 mDeviceBroker.postSetAvrcpAbsoluteVolumeIndex(newIndex / 10);
Ajay Panickere3946c82018-02-26 16:04:15 -08001784 }
1785
Jakub Pawlowskif9570f32018-02-21 17:15:12 -08001786 // Check if volume update should be send to Hearing Aid
1787 if ((device & AudioSystem.DEVICE_OUT_HEARING_AID) != 0) {
Jean-Michel Trivi58850372018-09-14 16:01:28 -07001788 Log.i(TAG, "adjustSreamVolume postSetHearingAidVolumeIndex index=" + newIndex
1789 + " stream=" + streamType);
1790 mDeviceBroker.postSetHearingAidVolumeIndex(newIndex, streamType);
Jakub Pawlowskif9570f32018-02-21 17:15:12 -08001791 }
1792
Ajay Panickere3946c82018-02-26 16:04:15 -08001793 // Check if volume update should be sent to Hdmi system audio.
Jinsuk Kim336cdb42014-11-29 06:27:00 +09001794 if (streamTypeAlias == AudioSystem.STREAM_MUSIC) {
1795 setSystemAudioVolume(oldIndex, newIndex, getStreamMaxVolume(streamType), flags);
1796 }
Shubangc480a712018-06-11 18:02:42 -07001797 synchronized (mHdmiClientLock) {
1798 if (mHdmiManager != null) {
Eric Laurent212532b2014-07-21 15:43:18 -07001799 // mHdmiCecSink true => mHdmiPlaybackClient != null
Jean-Michel Trivi90dbfdf2019-04-10 14:11:40 -07001800 if (mHdmiCecSink
1801 && streamTypeAlias == AudioSystem.STREAM_MUSIC
1802 // vol change on a full volume device
1803 && ((device & mFullVolumeDevices) != 0)) {
Shubangc480a712018-06-11 18:02:42 -07001804 int keyCode = (direction == -1) ? KeyEvent.KEYCODE_VOLUME_DOWN :
1805 KeyEvent.KEYCODE_VOLUME_UP;
1806 final long ident = Binder.clearCallingIdentity();
1807 try {
1808 mHdmiPlaybackClient.sendKeyEvent(keyCode, true);
1809 mHdmiPlaybackClient.sendKeyEvent(keyCode, false);
1810 } finally {
1811 Binder.restoreCallingIdentity(ident);
Eric Laurent212532b2014-07-21 15:43:18 -07001812 }
Jungshik Jang41d97462014-06-30 22:26:29 +09001813 }
Shubangc480a712018-06-11 18:02:42 -07001814
1815 if (mHdmiAudioSystemClient != null &&
Shubangde728822018-07-16 16:46:51 -07001816 mHdmiSystemAudioSupported &&
Shubangc480a712018-06-11 18:02:42 -07001817 streamTypeAlias == AudioSystem.STREAM_MUSIC &&
1818 (oldIndex != newIndex || isMuteAdjust)) {
Shubangde728822018-07-16 16:46:51 -07001819 final long identity = Binder.clearCallingIdentity();
Shubangc480a712018-06-11 18:02:42 -07001820 mHdmiAudioSystemClient.sendReportAudioStatusCecCommand(
1821 isMuteAdjust, getStreamVolume(AudioSystem.STREAM_MUSIC),
1822 getStreamMaxVolume(AudioSystem.STREAM_MUSIC),
1823 isStreamMute(AudioSystem.STREAM_MUSIC));
Shubangde728822018-07-16 16:46:51 -07001824 Binder.restoreCallingIdentity(identity);
Shubangc480a712018-06-11 18:02:42 -07001825 }
Jungshik Jang41d97462014-06-30 22:26:29 +09001826 }
1827 }
Eric Laurent4bbcc652012-09-24 14:26:30 -07001828 }
Eric Laurent42b041e2013-03-29 11:36:03 -07001829 int index = mStreamStates[streamType].getIndex(device);
Jean-Michel Trivi90dbfdf2019-04-10 14:11:40 -07001830 sendVolumeUpdate(streamType, oldIndex, index, flags, device);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001831 }
1832
RoboErik5452e252015-02-06 15:33:53 -08001833 // Called after a delay when volume down is pressed while muted
1834 private void onUnmuteStream(int stream, int flags) {
1835 VolumeStreamState streamState = mStreamStates[stream];
1836 streamState.mute(false);
1837
1838 final int device = getDeviceForStream(stream);
1839 final int index = mStreamStates[stream].getIndex(device);
Jean-Michel Trivi90dbfdf2019-04-10 14:11:40 -07001840 sendVolumeUpdate(stream, index, index, flags, device);
RoboErik5452e252015-02-06 15:33:53 -08001841 }
1842
Jinsuk Kim336cdb42014-11-29 06:27:00 +09001843 private void setSystemAudioVolume(int oldVolume, int newVolume, int maxVolume, int flags) {
Jinsuk Kim336cdb42014-11-29 06:27:00 +09001844 // Sets the audio volume of AVR when we are in system audio mode. The new volume info
1845 // is tranformed to HDMI-CEC commands and passed through CEC bus.
Shubangc480a712018-06-11 18:02:42 -07001846 synchronized (mHdmiClientLock) {
1847 if (mHdmiManager == null
1848 || mHdmiTvClient == null
1849 || oldVolume == newVolume
1850 || (flags & AudioManager.FLAG_HDMI_SYSTEM_AUDIO_VOLUME) != 0
Jean-Michel Trivi90dbfdf2019-04-10 14:11:40 -07001851 || !mHdmiSystemAudioSupported) {
1852 return;
1853 }
Shubangc480a712018-06-11 18:02:42 -07001854 final long token = Binder.clearCallingIdentity();
1855 try {
1856 mHdmiTvClient.setSystemAudioVolume(oldVolume, newVolume, maxVolume);
1857 } finally {
1858 Binder.restoreCallingIdentity(token);
Jinsuk Kim336cdb42014-11-29 06:27:00 +09001859 }
1860 }
1861 }
1862
Eric Laurentfde16d52012-12-03 14:42:39 -08001863 // StreamVolumeCommand contains the information needed to defer the process of
1864 // setStreamVolume() in case the user has to acknowledge the safe volume warning message.
1865 class StreamVolumeCommand {
1866 public final int mStreamType;
1867 public final int mIndex;
1868 public final int mFlags;
1869 public final int mDevice;
Eric Laurent9ce379a2010-02-16 06:00:26 -08001870
Eric Laurentfde16d52012-12-03 14:42:39 -08001871 StreamVolumeCommand(int streamType, int index, int flags, int device) {
1872 mStreamType = streamType;
1873 mIndex = index;
1874 mFlags = flags;
1875 mDevice = device;
Eric Laurentb024c302011-10-14 17:19:27 -07001876 }
John Spurlock35134602014-07-24 18:10:48 -04001877
1878 @Override
1879 public String toString() {
1880 return new StringBuilder().append("{streamType=").append(mStreamType).append(",index=")
1881 .append(mIndex).append(",flags=").append(mFlags).append(",device=")
1882 .append(mDevice).append('}').toString();
1883 }
Eric Laurentfde16d52012-12-03 14:42:39 -08001884 };
Eric Laurent3ef75492012-11-28 12:12:23 -08001885
Julia Reynolds48034f82016-03-09 10:15:16 -05001886 private int getNewRingerMode(int stream, int index, int flags) {
Zak Cohen47798292017-11-30 12:34:20 -08001887 // setRingerMode does nothing if the device is single volume,so the value would be unchanged
1888 if (mIsSingleVolume) {
1889 return getRingerModeExternal();
1890 }
1891
John Spurlockee5ad722015-03-03 16:17:21 -05001892 // setting volume on ui sounds stream type also controls silent mode
Eric Laurent3ef75492012-11-28 12:12:23 -08001893 if (((flags & AudioManager.FLAG_ALLOW_RINGER_MODES) != 0) ||
John Spurlock75ae23c2015-06-02 16:26:43 -04001894 (stream == getUiSoundsStreamType())) {
Eric Laurent3ef75492012-11-28 12:12:23 -08001895 int newRingerMode;
1896 if (index == 0) {
1897 newRingerMode = mHasVibrator ? AudioManager.RINGER_MODE_VIBRATE
John Spurlocka48d7792015-03-03 17:35:57 -05001898 : mVolumePolicy.volumeDownToEnterSilent ? AudioManager.RINGER_MODE_SILENT
Julia Reynolds48034f82016-03-09 10:15:16 -05001899 : AudioManager.RINGER_MODE_NORMAL;
Eric Laurent3ef75492012-11-28 12:12:23 -08001900 } else {
1901 newRingerMode = AudioManager.RINGER_MODE_NORMAL;
1902 }
Julia Reynolds48034f82016-03-09 10:15:16 -05001903 return newRingerMode;
1904 }
1905 return getRingerModeExternal();
1906 }
1907
1908 private boolean isAndroidNPlus(String caller) {
1909 try {
1910 final ApplicationInfo applicationInfo =
1911 mContext.getPackageManager().getApplicationInfoAsUser(
1912 caller, 0, UserHandle.getUserId(Binder.getCallingUid()));
1913 if (applicationInfo.targetSdkVersion >= Build.VERSION_CODES.N) {
1914 return true;
1915 }
1916 return false;
1917 } catch (PackageManager.NameNotFoundException e) {
1918 return true;
1919 }
1920 }
1921
1922 private boolean wouldToggleZenMode(int newMode) {
1923 if (getRingerModeExternal() == AudioManager.RINGER_MODE_SILENT
1924 && newMode != AudioManager.RINGER_MODE_SILENT) {
1925 return true;
1926 } else if (getRingerModeExternal() != AudioManager.RINGER_MODE_SILENT
1927 && newMode == AudioManager.RINGER_MODE_SILENT) {
1928 return true;
1929 }
1930 return false;
1931 }
1932
1933 private void onSetStreamVolume(int streamType, int index, int flags, int device,
1934 String caller) {
1935 final int stream = mStreamVolumeAlias[streamType];
1936 setStreamVolumeInt(stream, index, device, false, caller);
1937 // setting volume on ui sounds stream type also controls silent mode
1938 if (((flags & AudioManager.FLAG_ALLOW_RINGER_MODES) != 0) ||
1939 (stream == getUiSoundsStreamType())) {
1940 setRingerMode(getNewRingerMode(stream, index, flags),
1941 TAG + ".onSetStreamVolume", false /*external*/);
Eric Laurent3ef75492012-11-28 12:12:23 -08001942 }
John Spurlock75ae23c2015-06-02 16:26:43 -04001943 // setting non-zero volume for a muted stream unmutes the stream and vice versa
1944 mStreamStates[stream].mute(index == 0);
Eric Laurentfde16d52012-12-03 14:42:39 -08001945 }
1946
François Gaffie9c362102018-09-21 17:43:52 +02001947 private void enforceModifyAudioRoutingPermission() {
1948 if (mContext.checkCallingPermission(
1949 android.Manifest.permission.MODIFY_AUDIO_ROUTING)
1950 != PackageManager.PERMISSION_GRANTED) {
1951 throw new SecurityException("Missing MODIFY_AUDIO_ROUTING permission");
1952 }
1953 }
1954
1955 /** @see AudioManager#setVolumeIndexForAttributes(attr, int, int) */
1956 public void setVolumeIndexForAttributes(@NonNull AudioAttributes attr, int index, int flags,
1957 String callingPackage) {
1958 enforceModifyAudioRoutingPermission();
1959 Preconditions.checkNotNull(attr, "attr must not be null");
1960 // @todo not hold the caller context, post message
Hayden Gomes6d69bde2019-04-04 13:10:13 -07001961 int stream = AudioProductStrategy.getLegacyStreamTypeForStrategyWithAudioAttributes(attr);
François Gaffie9c362102018-09-21 17:43:52 +02001962 final int device = getDeviceForStream(stream);
1963
1964 int oldIndex = AudioSystem.getVolumeIndexForAttributes(attr, device);
1965
1966 AudioSystem.setVolumeIndexForAttributes(attr, index, device);
1967
Hayden Gomes6d69bde2019-04-04 13:10:13 -07001968 final int volumeGroup = getVolumeGroupIdForAttributes(attr);
Hayden Gomesebd6aaa2019-04-04 13:14:21 -07001969 final AudioVolumeGroup avg = getAudioVolumeGroupById(volumeGroup);
François Gaffie9c362102018-09-21 17:43:52 +02001970 if (avg == null) {
1971 return;
1972 }
1973 for (final int groupedStream : avg.getLegacyStreamTypes()) {
Hayden Gomesf8c71372019-04-05 10:04:28 -07001974 setStreamVolume(groupedStream, index, flags, callingPackage, callingPackage,
François Gaffie9c362102018-09-21 17:43:52 +02001975 Binder.getCallingUid());
1976 }
1977 }
1978
Hayden Gomesebd6aaa2019-04-04 13:14:21 -07001979 @Nullable
1980 private AudioVolumeGroup getAudioVolumeGroupById(int volumeGroupId) {
1981 for (final AudioVolumeGroup avg : AudioVolumeGroup.getAudioVolumeGroups()) {
1982 if (avg.getId() == volumeGroupId) {
1983 return avg;
1984 }
1985 }
1986
1987 Log.e(TAG, ": invalid volume group id: " + volumeGroupId + " requested");
1988 return null;
1989 }
1990
François Gaffie9c362102018-09-21 17:43:52 +02001991 /** @see AudioManager#getVolumeIndexForAttributes(attr) */
1992 public int getVolumeIndexForAttributes(@NonNull AudioAttributes attr) {
1993 enforceModifyAudioRoutingPermission();
1994 Preconditions.checkNotNull(attr, "attr must not be null");
Hayden Gomes6d69bde2019-04-04 13:10:13 -07001995 int stream = AudioProductStrategy.getLegacyStreamTypeForStrategyWithAudioAttributes(attr);
François Gaffie9c362102018-09-21 17:43:52 +02001996 final int device = getDeviceForStream(stream);
1997
1998 return AudioSystem.getVolumeIndexForAttributes(attr, device);
1999 }
2000
2001 /** @see AudioManager#getMaxVolumeIndexForAttributes(attr) */
2002 public int getMaxVolumeIndexForAttributes(@NonNull AudioAttributes attr) {
2003 enforceModifyAudioRoutingPermission();
2004 Preconditions.checkNotNull(attr, "attr must not be null");
2005 return AudioSystem.getMaxVolumeIndexForAttributes(attr);
2006 }
2007
2008 /** @see AudioManager#getMinVolumeIndexForAttributes(attr) */
2009 public int getMinVolumeIndexForAttributes(@NonNull AudioAttributes attr) {
2010 enforceModifyAudioRoutingPermission();
2011 Preconditions.checkNotNull(attr, "attr must not be null");
2012 return AudioSystem.getMinVolumeIndexForAttributes(attr);
2013 }
2014
Eric Laurentfde16d52012-12-03 14:42:39 -08002015 /** @see AudioManager#setStreamVolume(int, int, int) */
Dianne Hackbornba50b97c2013-04-30 15:04:46 -07002016 public void setStreamVolume(int streamType, int index, int flags, String callingPackage) {
Phil Weaverf1a9aff2017-03-23 17:21:29 -07002017 if ((streamType == AudioManager.STREAM_ACCESSIBILITY) && !canChangeAccessibilityVolume()) {
Jean-Michel Triviab2d9312017-03-13 15:33:39 -07002018 Log.w(TAG, "Trying to call setStreamVolume() for a11y without"
Phil Weaverf1a9aff2017-03-23 17:21:29 -07002019 + " CHANGE_ACCESSIBILITY_VOLUME callingPackage=" + callingPackage);
Jean-Michel Triviab2d9312017-03-13 15:33:39 -07002020 return;
2021 }
Tomoharu Kasaharaa0d0c542019-01-18 20:04:38 +09002022 if ((streamType == AudioManager.STREAM_VOICE_CALL ||
2023 streamType == AudioManager.STREAM_BLUETOOTH_SCO) &&
Nadav Bar6b7751d2017-12-24 16:03:08 +02002024 (index == 0) &&
2025 (mContext.checkCallingOrSelfPermission(
2026 android.Manifest.permission.MODIFY_PHONE_STATE)
2027 != PackageManager.PERMISSION_GRANTED)) {
Tomoharu Kasaharaa0d0c542019-01-18 20:04:38 +09002028 Log.w(TAG, "Trying to call setStreamVolume() for STREAM_VOICE_CALL or"
2029 + " STREAM_BLUETOOTH_SCO and index 0 without"
Nadav Bar6b7751d2017-12-24 16:03:08 +02002030 + " MODIFY_PHONE_STATE callingPackage=" + callingPackage);
2031 return;
2032 }
Jean-Michel Trivi58850372018-09-14 16:01:28 -07002033 sVolumeLogger.log(new VolumeEvent(VolumeEvent.VOL_SET_STREAM_VOL, streamType,
Jean-Michel Trivicf170362017-08-24 17:24:57 -07002034 index/*val1*/, flags/*val2*/, callingPackage));
John Spurlock90874332015-03-10 16:00:54 -04002035 setStreamVolume(streamType, index, flags, callingPackage, callingPackage,
2036 Binder.getCallingUid());
RoboErik0dac35a2014-08-12 15:48:49 -07002037 }
2038
Phil Weaverf1a9aff2017-03-23 17:21:29 -07002039 private boolean canChangeAccessibilityVolume() {
2040 synchronized (mAccessibilityServiceUidsLock) {
2041 if (PackageManager.PERMISSION_GRANTED == mContext.checkCallingOrSelfPermission(
2042 android.Manifest.permission.CHANGE_ACCESSIBILITY_VOLUME)) {
2043 return true;
2044 }
2045 if (mAccessibilityServiceUids != null) {
2046 int callingUid = Binder.getCallingUid();
2047 for (int i = 0; i < mAccessibilityServiceUids.length; i++) {
2048 if (mAccessibilityServiceUids[i] == callingUid) {
2049 return true;
2050 }
2051 }
2052 }
2053 return false;
2054 }
2055 }
2056
Jean-Michel Trivib32faaa2019-04-22 12:21:50 -07002057 /**
2058 * Manage an audio mode change for audio devices that use an "absolute volume" model,
2059 * i.e. the framework sends the full scale signal, and the actual volume for the use case
2060 * is communicated separately.
2061 */
2062 void updateAbsVolumeMultiModeDevices(int oldMode, int newMode) {
2063 if (oldMode == newMode) {
2064 return;
2065 }
2066 int streamType = AudioSystem.STREAM_MUSIC;
2067 switch (newMode) {
2068 case AudioSystem.MODE_IN_COMMUNICATION:
2069 case AudioSystem.MODE_IN_CALL:
2070 streamType = AudioSystem.STREAM_VOICE_CALL;
2071 break;
2072 case AudioSystem.MODE_NORMAL:
2073 streamType = AudioSystem.STREAM_MUSIC;
2074 break;
2075 case AudioSystem.MODE_RINGTONE:
2076 // not changing anything for ringtone
2077 return;
2078 case AudioSystem.MODE_CURRENT:
2079 case AudioSystem.MODE_INVALID:
2080 default:
2081 // don't know what to do in this case, better bail
2082 return;
2083 }
2084 final int device = AudioSystem.getDevicesForStream(streamType);
2085 if ((device & mAbsVolumeMultiModeCaseDevices) == 0) {
2086 return;
2087 }
2088
2089 // handling of specific interfaces goes here:
2090 if ((device & mAbsVolumeMultiModeCaseDevices) == AudioSystem.DEVICE_OUT_HEARING_AID) {
2091 final int index = getStreamVolume(streamType);
2092 mModeLogger.log(new AudioEventLogger.StringEvent("setMode to "
2093 + AudioSystem.modeToString(newMode)
2094 + " causes setting HEARING_AID volume to idx:" + index
2095 + " stream:" + AudioSystem.streamToString(streamType)));
2096 mDeviceBroker.postSetHearingAidVolumeIndex(index * 10, streamType);
2097 }
2098 }
2099
RoboErik0dac35a2014-08-12 15:48:49 -07002100 private void setStreamVolume(int streamType, int index, int flags, String callingPackage,
John Spurlock90874332015-03-10 16:00:54 -04002101 String caller, int uid) {
Jean-Michel Triviac487672016-11-11 10:05:18 -08002102 if (DEBUG_VOL) {
2103 Log.d(TAG, "setStreamVolume(stream=" + streamType+", index=" + index
2104 + ", calling=" + callingPackage + ")");
2105 }
Eric Laurent83a017b2013-03-19 18:15:31 -07002106 if (mUseFixedVolume) {
2107 return;
2108 }
2109
Eric Laurentfde16d52012-12-03 14:42:39 -08002110 ensureValidStreamType(streamType);
Dianne Hackbornba50b97c2013-04-30 15:04:46 -07002111 int streamTypeAlias = mStreamVolumeAlias[streamType];
2112 VolumeStreamState streamState = mStreamStates[streamTypeAlias];
Eric Laurentfde16d52012-12-03 14:42:39 -08002113
2114 final int device = getDeviceForStream(streamType);
2115 int oldIndex;
2116
Matthew Xiec9d1d5f2013-09-12 00:32:22 -07002117 // skip a2dp absolute volume control request when the device
2118 // is not an a2dp device
2119 if ((device & AudioSystem.DEVICE_OUT_ALL_A2DP) == 0 &&
2120 (flags & AudioManager.FLAG_BLUETOOTH_ABS_VOLUME) != 0) {
2121 return;
2122 }
Kenny Guy70e0c582015-06-30 19:18:28 +01002123 // If we are being called by the system (e.g. hardware keys) check for current user
2124 // so we handle user restrictions correctly.
2125 if (uid == android.os.Process.SYSTEM_UID) {
2126 uid = UserHandle.getUid(getCurrentUserId(), UserHandle.getAppId(uid));
2127 }
John Spurlock59dc9c12015-03-02 11:20:15 -05002128 if (mAppOps.noteOp(STREAM_VOLUME_OPS[streamTypeAlias], uid, callingPackage)
RoboErik0dac35a2014-08-12 15:48:49 -07002129 != AppOpsManager.MODE_ALLOWED) {
Dianne Hackbornba50b97c2013-04-30 15:04:46 -07002130 return;
2131 }
2132
Julia Reynolds48034f82016-03-09 10:15:16 -05002133 if (isAndroidNPlus(callingPackage)
2134 && wouldToggleZenMode(getNewRingerMode(streamTypeAlias, index, flags))
2135 && !mNm.isNotificationPolicyAccessGrantedForPackage(callingPackage)) {
2136 throw new SecurityException("Not allowed to change Do Not Disturb state");
2137 }
2138
Julia Reynoldsed783792016-04-08 15:27:35 -04002139 if (!volumeAdjustmentAllowedByDnd(streamTypeAlias, flags)) {
2140 return;
2141 }
2142
hyomin.ohd0446dc2018-10-18 13:58:27 +09002143 synchronized (mSafeMediaVolumeStateLock) {
Eric Laurentfde16d52012-12-03 14:42:39 -08002144 // reset any pending volume command
2145 mPendingVolumeCommand = null;
2146
Eric Laurent42b041e2013-03-29 11:36:03 -07002147 oldIndex = streamState.getIndex(device);
Eric Laurentfde16d52012-12-03 14:42:39 -08002148
Dianne Hackbornba50b97c2013-04-30 15:04:46 -07002149 index = rescaleIndex(index * 10, streamType, streamTypeAlias);
Eric Laurentfde16d52012-12-03 14:42:39 -08002150
Jean-Michel Trivi58850372018-09-14 16:01:28 -07002151 if (streamTypeAlias == AudioSystem.STREAM_MUSIC
2152 && (device & AudioSystem.DEVICE_OUT_ALL_A2DP) != 0
2153 && (flags & AudioManager.FLAG_BLUETOOTH_ABS_VOLUME) == 0) {
2154 if (DEBUG_VOL) {
2155 Log.d(TAG, "setStreamVolume postSetAvrcpAbsoluteVolumeIndex index=" + index
2156 + "stream=" + streamType);
John Du5a0cf7a2013-07-19 11:30:34 -07002157 }
Jean-Michel Trivi58850372018-09-14 16:01:28 -07002158 mDeviceBroker.postSetAvrcpAbsoluteVolumeIndex(index / 10);
John Du5a0cf7a2013-07-19 11:30:34 -07002159 }
2160
Jakub Pawlowskif9570f32018-02-21 17:15:12 -08002161 if ((device & AudioSystem.DEVICE_OUT_HEARING_AID) != 0) {
Jean-Michel Trivi58850372018-09-14 16:01:28 -07002162 Log.i(TAG, "setStreamVolume postSetHearingAidVolumeIndex index=" + index
2163 + " stream=" + streamType);
2164 mDeviceBroker.postSetHearingAidVolumeIndex(index, streamType);
Jakub Pawlowskif9570f32018-02-21 17:15:12 -08002165 }
2166
Jinsuk Kim336cdb42014-11-29 06:27:00 +09002167 if (streamTypeAlias == AudioSystem.STREAM_MUSIC) {
2168 setSystemAudioVolume(oldIndex, index, getStreamMaxVolume(streamType), flags);
Jungshik Jang41d97462014-06-30 22:26:29 +09002169 }
2170
Eric Laurentfde16d52012-12-03 14:42:39 -08002171 flags &= ~AudioManager.FLAG_FIXED_VOLUME;
Dianne Hackbornba50b97c2013-04-30 15:04:46 -07002172 if ((streamTypeAlias == AudioSystem.STREAM_MUSIC) &&
Eric Laurentfde16d52012-12-03 14:42:39 -08002173 ((device & mFixedVolumeDevices) != 0)) {
2174 flags |= AudioManager.FLAG_FIXED_VOLUME;
2175
2176 // volume is either 0 or max allowed for fixed volume devices
2177 if (index != 0) {
2178 if (mSafeMediaVolumeState == SAFE_MEDIA_VOLUME_ACTIVE &&
2179 (device & mSafeMediaVolumeDevices) != 0) {
Eric Laurenteab40d12017-06-09 12:45:21 -07002180 index = safeMediaVolumeIndex(device);
Eric Laurentfde16d52012-12-03 14:42:39 -08002181 } else {
2182 index = streamState.getMaxIndex();
2183 }
2184 }
2185 }
2186
Dianne Hackbornba50b97c2013-04-30 15:04:46 -07002187 if (!checkSafeMediaVolume(streamTypeAlias, index, device)) {
John Spurlock3346a802014-05-20 16:25:37 -04002188 mVolumeController.postDisplaySafeVolumeWarning(flags);
Eric Laurentfde16d52012-12-03 14:42:39 -08002189 mPendingVolumeCommand = new StreamVolumeCommand(
2190 streamType, index, flags, device);
2191 } else {
John Spurlock90874332015-03-10 16:00:54 -04002192 onSetStreamVolume(streamType, index, flags, device, caller);
Eric Laurent42b041e2013-03-29 11:36:03 -07002193 index = mStreamStates[streamType].getIndex(device);
Eric Laurentfde16d52012-12-03 14:42:39 -08002194 }
2195 }
Shubangc480a712018-06-11 18:02:42 -07002196 synchronized (mHdmiClientLock) {
2197 if (mHdmiManager != null &&
2198 mHdmiAudioSystemClient != null &&
Shubangde728822018-07-16 16:46:51 -07002199 mHdmiSystemAudioSupported &&
Shubangc480a712018-06-11 18:02:42 -07002200 streamTypeAlias == AudioSystem.STREAM_MUSIC &&
2201 (oldIndex != index)) {
Shubangde728822018-07-16 16:46:51 -07002202 final long identity = Binder.clearCallingIdentity();
Shubangc480a712018-06-11 18:02:42 -07002203 mHdmiAudioSystemClient.sendReportAudioStatusCecCommand(
2204 false, getStreamVolume(AudioSystem.STREAM_MUSIC),
2205 getStreamMaxVolume(AudioSystem.STREAM_MUSIC),
2206 isStreamMute(AudioSystem.STREAM_MUSIC));
Shubangde728822018-07-16 16:46:51 -07002207 Binder.restoreCallingIdentity(identity);
Shubangc480a712018-06-11 18:02:42 -07002208 }
2209 }
Jean-Michel Trivi90dbfdf2019-04-10 14:11:40 -07002210 sendVolumeUpdate(streamType, oldIndex, index, flags, device);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002211 }
2212
Hayden Gomes6d69bde2019-04-04 13:10:13 -07002213
2214
2215 private int getVolumeGroupIdForAttributes(@NonNull AudioAttributes attributes) {
2216 Preconditions.checkNotNull(attributes, "attributes must not be null");
2217 int volumeGroupId = getVolumeGroupIdForAttributesInt(attributes);
Hayden Gomesebd6aaa2019-04-04 13:14:21 -07002218 if (volumeGroupId != AudioVolumeGroup.DEFAULT_VOLUME_GROUP) {
Hayden Gomes6d69bde2019-04-04 13:10:13 -07002219 return volumeGroupId;
2220 }
2221 // The default volume group is the one hosted by default product strategy, i.e.
2222 // supporting Default Attributes
2223 return getVolumeGroupIdForAttributesInt(AudioProductStrategy.sDefaultAttributes);
2224 }
2225
2226 private int getVolumeGroupIdForAttributesInt(@NonNull AudioAttributes attributes) {
2227 Preconditions.checkNotNull(attributes, "attributes must not be null");
2228 for (final AudioProductStrategy productStrategy :
2229 AudioProductStrategy.getAudioProductStrategies()) {
2230 int volumeGroupId = productStrategy.getVolumeGroupIdForAudioAttributes(attributes);
Hayden Gomesebd6aaa2019-04-04 13:14:21 -07002231 if (volumeGroupId != AudioVolumeGroup.DEFAULT_VOLUME_GROUP) {
Hayden Gomes6d69bde2019-04-04 13:10:13 -07002232 return volumeGroupId;
2233 }
2234 }
Hayden Gomesebd6aaa2019-04-04 13:14:21 -07002235 return AudioVolumeGroup.DEFAULT_VOLUME_GROUP;
Hayden Gomes6d69bde2019-04-04 13:10:13 -07002236 }
2237
2238
Beverlyd6964762018-02-16 14:07:03 -05002239 // No ringer or zen muted stream volumes can be changed unless it'll exit dnd
Julia Reynoldsed783792016-04-08 15:27:35 -04002240 private boolean volumeAdjustmentAllowedByDnd(int streamTypeAlias, int flags) {
Beverlyd6964762018-02-16 14:07:03 -05002241 switch (mNm.getZenMode()) {
2242 case Settings.Global.ZEN_MODE_OFF:
2243 return true;
2244 case Settings.Global.ZEN_MODE_NO_INTERRUPTIONS:
2245 case Settings.Global.ZEN_MODE_ALARMS:
2246 case Settings.Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS:
2247 return !isStreamMutedByRingerOrZenMode(streamTypeAlias)
2248 || streamTypeAlias == getUiSoundsStreamType()
2249 || (flags & AudioManager.FLAG_ALLOW_RINGER_MODES) != 0;
Julia Reynoldsed783792016-04-08 15:27:35 -04002250 }
Beverlyd6964762018-02-16 14:07:03 -05002251
Julia Reynoldsed783792016-04-08 15:27:35 -04002252 return true;
2253 }
2254
Eric Laurent45c90ce2012-04-24 18:44:22 -07002255 /** @see AudioManager#forceVolumeControlStream(int) */
2256 public void forceVolumeControlStream(int streamType, IBinder cb) {
Jean-Michel Trivi60eddfd2018-03-09 15:31:12 -08002257 if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.MODIFY_PHONE_STATE)
2258 != PackageManager.PERMISSION_GRANTED) {
2259 return;
2260 }
Jean-Michel Trivia7880d42017-04-15 12:41:05 -07002261 if (DEBUG_VOL) { Log.d(TAG, String.format("forceVolumeControlStream(%d)", streamType)); }
Eric Laurent45c90ce2012-04-24 18:44:22 -07002262 synchronized(mForceControlStreamLock) {
Jean-Michel Trivia7880d42017-04-15 12:41:05 -07002263 if (mVolumeControlStream != -1 && streamType != -1) {
2264 mUserSelectedVolumeControlStream = true;
2265 }
Eric Laurent45c90ce2012-04-24 18:44:22 -07002266 mVolumeControlStream = streamType;
2267 if (mVolumeControlStream == -1) {
2268 if (mForceControlStreamClient != null) {
2269 mForceControlStreamClient.release();
2270 mForceControlStreamClient = null;
2271 }
Jean-Michel Trivia7880d42017-04-15 12:41:05 -07002272 mUserSelectedVolumeControlStream = false;
Eric Laurent45c90ce2012-04-24 18:44:22 -07002273 } else {
jianzhou21fb09f2018-02-28 14:03:15 +08002274 if (null == mForceControlStreamClient) {
2275 mForceControlStreamClient = new ForceControlStreamClient(cb);
2276 } else {
2277 if (mForceControlStreamClient.getBinder() == cb) {
2278 Log.d(TAG, "forceVolumeControlStream cb:" + cb + " is already linked.");
2279 } else {
2280 mForceControlStreamClient.release();
2281 mForceControlStreamClient = new ForceControlStreamClient(cb);
2282 }
2283 }
Eric Laurent45c90ce2012-04-24 18:44:22 -07002284 }
2285 }
2286 }
2287
2288 private class ForceControlStreamClient implements IBinder.DeathRecipient {
2289 private IBinder mCb; // To be notified of client's death
2290
2291 ForceControlStreamClient(IBinder cb) {
2292 if (cb != null) {
2293 try {
2294 cb.linkToDeath(this, 0);
2295 } catch (RemoteException e) {
2296 // Client has died!
2297 Log.w(TAG, "ForceControlStreamClient() could not link to "+cb+" binder death");
2298 cb = null;
2299 }
2300 }
2301 mCb = cb;
2302 }
2303
2304 public void binderDied() {
2305 synchronized(mForceControlStreamLock) {
2306 Log.w(TAG, "SCO client died");
2307 if (mForceControlStreamClient != this) {
2308 Log.w(TAG, "unregistered control stream client died");
2309 } else {
2310 mForceControlStreamClient = null;
2311 mVolumeControlStream = -1;
Jean-Michel Trivia7880d42017-04-15 12:41:05 -07002312 mUserSelectedVolumeControlStream = false;
Eric Laurent45c90ce2012-04-24 18:44:22 -07002313 }
2314 }
2315 }
2316
2317 public void release() {
2318 if (mCb != null) {
2319 mCb.unlinkToDeath(this, 0);
2320 mCb = null;
2321 }
2322 }
jianzhou21fb09f2018-02-28 14:03:15 +08002323
2324 public IBinder getBinder() {
2325 return mCb;
2326 }
Eric Laurent45c90ce2012-04-24 18:44:22 -07002327 }
2328
Dianne Hackborn5ac72a22012-08-29 18:32:08 -07002329 private void sendBroadcastToAll(Intent intent) {
Christopher Tate267603f2015-01-20 14:21:21 -08002330 intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);
John Spurlock86490862015-02-25 11:22:52 -05002331 intent.addFlags(Intent.FLAG_RECEIVER_FOREGROUND);
Dianne Hackborn5ac72a22012-08-29 18:32:08 -07002332 final long ident = Binder.clearCallingIdentity();
2333 try {
2334 mContext.sendBroadcastAsUser(intent, UserHandle.ALL);
2335 } finally {
2336 Binder.restoreCallingIdentity(ident);
2337 }
2338 }
2339
2340 private void sendStickyBroadcastToAll(Intent intent) {
John Spurlock86490862015-02-25 11:22:52 -05002341 intent.addFlags(Intent.FLAG_RECEIVER_FOREGROUND);
Dianne Hackborn5ac72a22012-08-29 18:32:08 -07002342 final long ident = Binder.clearCallingIdentity();
2343 try {
2344 mContext.sendStickyBroadcastAsUser(intent, UserHandle.ALL);
2345 } finally {
2346 Binder.restoreCallingIdentity(ident);
2347 }
2348 }
2349
Kenny Guy70e0c582015-06-30 19:18:28 +01002350 private int getCurrentUserId() {
2351 final long ident = Binder.clearCallingIdentity();
2352 try {
Sudheer Shankadc589ac2016-11-10 15:30:17 -08002353 UserInfo currentUser = ActivityManager.getService().getCurrentUser();
Kenny Guy70e0c582015-06-30 19:18:28 +01002354 return currentUser.id;
2355 } catch (RemoteException e) {
2356 // Activity manager not running, nothing we can do assume user 0.
2357 } finally {
2358 Binder.restoreCallingIdentity(ident);
2359 }
Xiaohui Chen7c696362015-09-16 09:56:14 -07002360 return UserHandle.USER_SYSTEM;
Kenny Guy70e0c582015-06-30 19:18:28 +01002361 }
2362
Eric Laurent25101b02011-02-02 09:33:30 -08002363 // UI update and Broadcast Intent
Jean-Michel Trivi90dbfdf2019-04-10 14:11:40 -07002364 protected void sendVolumeUpdate(int streamType, int oldIndex, int index, int flags, int device)
2365 {
John Spurlock72966d62015-06-18 15:45:07 -04002366 streamType = mStreamVolumeAlias[streamType];
Eric Laurent25101b02011-02-02 09:33:30 -08002367
Jinsuk Kim336cdb42014-11-29 06:27:00 +09002368 if (streamType == AudioSystem.STREAM_MUSIC) {
Jean-Michel Trivi90dbfdf2019-04-10 14:11:40 -07002369 flags = updateFlagsForTvPlatform(flags);
2370 if ((device & mFullVolumeDevices) != 0) {
2371 flags &= ~AudioManager.FLAG_SHOW_UI;
2372 }
Jungshik Jang1a6be6e2014-09-16 11:04:54 +09002373 }
John Spurlock3346a802014-05-20 16:25:37 -04002374 mVolumeController.postVolumeChanged(streamType, flags);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002375 }
2376
Jinsuk Kim336cdb42014-11-29 06:27:00 +09002377 // If Hdmi-CEC system audio mode is on, we show volume bar only when TV
2378 // receives volume notification from Audio Receiver.
Jean-Michel Trivi90dbfdf2019-04-10 14:11:40 -07002379 private int updateFlagsForTvPlatform(int flags) {
Shubangc480a712018-06-11 18:02:42 -07002380 synchronized (mHdmiClientLock) {
2381 if (mHdmiTvClient != null) {
Jinsuk Kim336cdb42014-11-29 06:27:00 +09002382 if (mHdmiSystemAudioSupported &&
2383 ((flags & AudioManager.FLAG_HDMI_SYSTEM_AUDIO_VOLUME) == 0)) {
2384 flags &= ~AudioManager.FLAG_SHOW_UI;
2385 }
2386 }
2387 }
2388 return flags;
2389 }
2390
Mike Lockwood0dc37cc2011-12-01 16:14:19 -05002391 // UI update and Broadcast Intent
Mike Lockwood0dc37cc2011-12-01 16:14:19 -05002392 private void sendMasterMuteUpdate(boolean muted, int flags) {
Jean-Michel Trivi90dbfdf2019-04-10 14:11:40 -07002393 mVolumeController.postMasterMuteChanged(updateFlagsForTvPlatform(flags));
Justin Koh57978ed2012-04-03 17:37:58 -07002394 broadcastMasterMuteStatus(muted);
2395 }
Mike Lockwood0dc37cc2011-12-01 16:14:19 -05002396
Justin Koh57978ed2012-04-03 17:37:58 -07002397 private void broadcastMasterMuteStatus(boolean muted) {
Mike Lockwood0dc37cc2011-12-01 16:14:19 -05002398 Intent intent = new Intent(AudioManager.MASTER_MUTE_CHANGED_ACTION);
2399 intent.putExtra(AudioManager.EXTRA_MASTER_VOLUME_MUTED, muted);
Justin Koh57978ed2012-04-03 17:37:58 -07002400 intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT
2401 | Intent.FLAG_RECEIVER_REPLACE_PENDING);
Dianne Hackborn5ac72a22012-08-29 18:32:08 -07002402 sendStickyBroadcastToAll(intent);
Mike Lockwood0dc37cc2011-12-01 16:14:19 -05002403 }
2404
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002405 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002406 * Sets the stream state's index, and posts a message to set system volume.
2407 * This will not call out to the UI. Assumes a valid stream type.
2408 *
2409 * @param streamType Type of the stream
2410 * @param index Desired volume index of the stream
Eric Laurent9bc8358d2011-11-18 16:43:31 -08002411 * @param device the device whose volume must be changed
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002412 * @param force If true, set the volume even if the desired volume is same
2413 * as the current volume.
2414 */
Eric Laurent9bc8358d2011-11-18 16:43:31 -08002415 private void setStreamVolumeInt(int streamType,
2416 int index,
2417 int device,
John Spurlock90874332015-03-10 16:00:54 -04002418 boolean force,
2419 String caller) {
Jean-Michel Trivi90dbfdf2019-04-10 14:11:40 -07002420 if ((device & mFullVolumeDevices) != 0) {
2421 return;
2422 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002423 VolumeStreamState streamState = mStreamStates[streamType];
Eric Laurent5b4e6542010-03-19 20:02:21 -07002424
John Spurlock90874332015-03-10 16:00:54 -04002425 if (streamState.setIndex(index, device, caller) || force) {
Eric Laurent42b041e2013-03-29 11:36:03 -07002426 // Post message to set system volume (it in turn will post a message
2427 // to persist).
2428 sendMsg(mAudioHandler,
2429 MSG_SET_DEVICE_VOLUME,
2430 SENDMSG_QUEUE,
2431 device,
2432 0,
2433 streamState,
2434 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002435 }
2436 }
2437
Jinsuk Kim336cdb42014-11-29 06:27:00 +09002438 private void setSystemAudioMute(boolean state) {
Shubangc480a712018-06-11 18:02:42 -07002439 synchronized (mHdmiClientLock) {
2440 if (mHdmiManager == null || mHdmiTvClient == null || !mHdmiSystemAudioSupported) return;
2441 final long token = Binder.clearCallingIdentity();
2442 try {
2443 mHdmiTvClient.setSystemAudioMute(state);
2444 } finally {
2445 Binder.restoreCallingIdentity(token);
Jinsuk Kim336cdb42014-11-29 06:27:00 +09002446 }
2447 }
2448 }
2449
Eric Laurent25101b02011-02-02 09:33:30 -08002450 /** get stream mute state. */
2451 public boolean isStreamMute(int streamType) {
RoboErik7c82ced2014-12-04 17:39:08 -08002452 if (streamType == AudioManager.USE_DEFAULT_STREAM_TYPE) {
2453 streamType = getActiveStreamType(streamType);
2454 }
Eric Laurent8fa4d6f2014-10-30 14:13:03 -07002455 synchronized (VolumeStreamState.class) {
jiabin93d32ef2017-07-11 13:50:02 -07002456 ensureValidStreamType(streamType);
RoboErik4197cb62015-01-21 15:45:32 -08002457 return mStreamStates[streamType].mIsMuted;
Eric Laurent8fa4d6f2014-10-30 14:13:03 -07002458 }
Eric Laurent25101b02011-02-02 09:33:30 -08002459 }
2460
Jean-Michel Triviba5270b2014-10-01 17:49:29 -07002461 private class RmtSbmxFullVolDeathHandler implements IBinder.DeathRecipient {
2462 private IBinder mICallback; // To be notified of client's death
2463
2464 RmtSbmxFullVolDeathHandler(IBinder cb) {
2465 mICallback = cb;
2466 try {
2467 cb.linkToDeath(this, 0/*flags*/);
2468 } catch (RemoteException e) {
2469 Log.e(TAG, "can't link to death", e);
2470 }
2471 }
2472
2473 boolean isHandlerFor(IBinder cb) {
2474 return mICallback.equals(cb);
2475 }
2476
2477 void forget() {
2478 try {
2479 mICallback.unlinkToDeath(this, 0/*flags*/);
2480 } catch (NoSuchElementException e) {
2481 Log.e(TAG, "error unlinking to death", e);
2482 }
2483 }
2484
2485 public void binderDied() {
2486 Log.w(TAG, "Recorder with remote submix at full volume died " + mICallback);
2487 forceRemoteSubmixFullVolume(false, mICallback);
2488 }
2489 }
2490
2491 /**
2492 * call must be synchronized on mRmtSbmxFullVolDeathHandlers
2493 * @return true if there is a registered death handler, false otherwise */
2494 private boolean discardRmtSbmxFullVolDeathHandlerFor(IBinder cb) {
2495 Iterator<RmtSbmxFullVolDeathHandler> it = mRmtSbmxFullVolDeathHandlers.iterator();
2496 while (it.hasNext()) {
2497 final RmtSbmxFullVolDeathHandler handler = it.next();
2498 if (handler.isHandlerFor(cb)) {
2499 handler.forget();
2500 mRmtSbmxFullVolDeathHandlers.remove(handler);
2501 return true;
2502 }
2503 }
2504 return false;
2505 }
2506
2507 /** call synchronized on mRmtSbmxFullVolDeathHandlers */
2508 private boolean hasRmtSbmxFullVolDeathHandlerFor(IBinder cb) {
2509 Iterator<RmtSbmxFullVolDeathHandler> it = mRmtSbmxFullVolDeathHandlers.iterator();
2510 while (it.hasNext()) {
2511 if (it.next().isHandlerFor(cb)) {
2512 return true;
2513 }
2514 }
2515 return false;
2516 }
2517
2518 private int mRmtSbmxFullVolRefCount = 0;
2519 private ArrayList<RmtSbmxFullVolDeathHandler> mRmtSbmxFullVolDeathHandlers =
2520 new ArrayList<RmtSbmxFullVolDeathHandler>();
2521
2522 public void forceRemoteSubmixFullVolume(boolean startForcing, IBinder cb) {
2523 if (cb == null) {
2524 return;
2525 }
2526 if ((PackageManager.PERMISSION_GRANTED != mContext.checkCallingOrSelfPermission(
2527 android.Manifest.permission.CAPTURE_AUDIO_OUTPUT))) {
2528 Log.w(TAG, "Trying to call forceRemoteSubmixFullVolume() without CAPTURE_AUDIO_OUTPUT");
2529 return;
2530 }
2531 synchronized(mRmtSbmxFullVolDeathHandlers) {
2532 boolean applyRequired = false;
2533 if (startForcing) {
2534 if (!hasRmtSbmxFullVolDeathHandlerFor(cb)) {
2535 mRmtSbmxFullVolDeathHandlers.add(new RmtSbmxFullVolDeathHandler(cb));
2536 if (mRmtSbmxFullVolRefCount == 0) {
2537 mFullVolumeDevices |= AudioSystem.DEVICE_OUT_REMOTE_SUBMIX;
2538 mFixedVolumeDevices |= AudioSystem.DEVICE_OUT_REMOTE_SUBMIX;
2539 applyRequired = true;
2540 }
2541 mRmtSbmxFullVolRefCount++;
2542 }
2543 } else {
2544 if (discardRmtSbmxFullVolDeathHandlerFor(cb) && (mRmtSbmxFullVolRefCount > 0)) {
2545 mRmtSbmxFullVolRefCount--;
2546 if (mRmtSbmxFullVolRefCount == 0) {
2547 mFullVolumeDevices &= ~AudioSystem.DEVICE_OUT_REMOTE_SUBMIX;
2548 mFixedVolumeDevices &= ~AudioSystem.DEVICE_OUT_REMOTE_SUBMIX;
2549 applyRequired = true;
2550 }
2551 }
2552 }
2553 if (applyRequired) {
2554 // Assumes only STREAM_MUSIC going through DEVICE_OUT_REMOTE_SUBMIX
2555 checkAllFixedVolumeDevices(AudioSystem.STREAM_MUSIC);
2556 mStreamStates[AudioSystem.STREAM_MUSIC].applyAllVolumes();
2557 }
2558 }
2559 }
2560
Kenny Guy70e0c582015-06-30 19:18:28 +01002561 private void setMasterMuteInternal(boolean mute, int flags, String callingPackage, int uid,
2562 int userId) {
2563 // If we are being called by the system check for user we are going to change
2564 // so we handle user restrictions correctly.
2565 if (uid == android.os.Process.SYSTEM_UID) {
2566 uid = UserHandle.getUid(userId, UserHandle.getAppId(uid));
2567 }
Makoto Onuki4f160732015-10-27 17:15:38 -07002568 // If OP_AUDIO_MASTER_VOLUME is set, disallow unmuting.
2569 if (!mute && mAppOps.noteOp(AppOpsManager.OP_AUDIO_MASTER_VOLUME, uid, callingPackage)
RoboErik7c82ced2014-12-04 17:39:08 -08002570 != AppOpsManager.MODE_ALLOWED) {
Julia Reynolds4a21b252014-06-04 11:11:43 -04002571 return;
2572 }
Kenny Guy70e0c582015-06-30 19:18:28 +01002573 if (userId != UserHandle.getCallingUserId() &&
2574 mContext.checkCallingOrSelfPermission(
2575 android.Manifest.permission.INTERACT_ACROSS_USERS_FULL)
2576 != PackageManager.PERMISSION_GRANTED) {
2577 return;
2578 }
Makoto Onukid45a4a22015-11-02 17:17:38 -08002579 setMasterMuteInternalNoCallerCheck(mute, flags, userId);
2580 }
2581
2582 private void setMasterMuteInternalNoCallerCheck(boolean mute, int flags, int userId) {
2583 if (DEBUG_VOL) {
2584 Log.d(TAG, String.format("Master mute %s, %d, user=%d", mute, flags, userId));
2585 }
Hongwei Wangdaba1242018-05-29 14:36:16 -07002586 if (!isPlatformAutomotive() && mUseFixedVolume) {
2587 // If using fixed volume, we don't mute.
2588 // TODO: remove the isPlatformAutomotive check here.
2589 // The isPlatformAutomotive check is added for safety but may not be necessary.
2590 return;
Makoto Onukid45a4a22015-11-02 17:17:38 -08002591 }
Kenny Guy70e0c582015-06-30 19:18:28 +01002592 if (getCurrentUserId() == userId) {
2593 if (mute != AudioSystem.getMasterMute()) {
2594 setSystemAudioMute(mute);
2595 AudioSystem.setMasterMute(mute);
Kenny Guy70e0c582015-06-30 19:18:28 +01002596 sendMasterMuteUpdate(mute, flags);
RoboErik7c82ced2014-12-04 17:39:08 -08002597
Kenny Guy70e0c582015-06-30 19:18:28 +01002598 Intent intent = new Intent(AudioManager.MASTER_MUTE_CHANGED_ACTION);
2599 intent.putExtra(AudioManager.EXTRA_MASTER_VOLUME_MUTED, mute);
2600 sendBroadcastToAll(intent);
2601 }
Jason Simmons1ce5b262012-02-02 13:00:17 -08002602 }
Mike Lockwoodce952c82011-11-14 10:47:42 -08002603 }
2604
2605 /** get master mute state. */
2606 public boolean isMasterMute() {
Mike Lockwood3194ea92011-12-07 11:47:31 -08002607 return AudioSystem.getMasterMute();
Mike Lockwoodce952c82011-11-14 10:47:42 -08002608 }
2609
Kenny Guy70e0c582015-06-30 19:18:28 +01002610 public void setMasterMute(boolean mute, int flags, String callingPackage, int userId) {
2611 setMasterMuteInternal(mute, flags, callingPackage, Binder.getCallingUid(),
2612 userId);
John Spurlockee5ad722015-03-03 16:17:21 -05002613 }
2614
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002615 /** @see AudioManager#getStreamVolume(int) */
2616 public int getStreamVolume(int streamType) {
2617 ensureValidStreamType(streamType);
Eric Laurent9bc8358d2011-11-18 16:43:31 -08002618 int device = getDeviceForStream(streamType);
Eric Laurent8fa4d6f2014-10-30 14:13:03 -07002619 synchronized (VolumeStreamState.class) {
2620 int index = mStreamStates[streamType].getIndex(device);
Eric Laurent4bbcc652012-09-24 14:26:30 -07002621
Eric Laurent8fa4d6f2014-10-30 14:13:03 -07002622 // by convention getStreamVolume() returns 0 when a stream is muted.
RoboErik4197cb62015-01-21 15:45:32 -08002623 if (mStreamStates[streamType].mIsMuted) {
Eric Laurent8fa4d6f2014-10-30 14:13:03 -07002624 index = 0;
2625 }
2626 if (index != 0 && (mStreamVolumeAlias[streamType] == AudioSystem.STREAM_MUSIC) &&
2627 (device & mFixedVolumeDevices) != 0) {
2628 index = mStreamStates[streamType].getMaxIndex();
2629 }
2630 return (index + 5) / 10;
Eric Laurent42b041e2013-03-29 11:36:03 -07002631 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002632 }
2633
2634 /** @see AudioManager#getStreamMaxVolume(int) */
2635 public int getStreamMaxVolume(int streamType) {
2636 ensureValidStreamType(streamType);
Eric Laurenta553c252009-07-17 12:17:14 -07002637 return (mStreamStates[streamType].getMaxIndex() + 5) / 10;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002638 }
2639
Jean-Michel Trivi8e7aca32017-11-28 18:12:38 -08002640 /** @see AudioManager#getStreamMinVolumeInt(int) */
John Spurlockb6e19e32015-03-10 21:33:44 -04002641 public int getStreamMinVolume(int streamType) {
2642 ensureValidStreamType(streamType);
2643 return (mStreamStates[streamType].getMinIndex() + 5) / 10;
2644 }
2645
Eric Laurent25101b02011-02-02 09:33:30 -08002646 /** Get last audible volume before stream was muted. */
2647 public int getLastAudibleStreamVolume(int streamType) {
2648 ensureValidStreamType(streamType);
Eric Laurent9bc8358d2011-11-18 16:43:31 -08002649 int device = getDeviceForStream(streamType);
Eric Laurent42b041e2013-03-29 11:36:03 -07002650 return (mStreamStates[streamType].getIndex(device) + 5) / 10;
Eric Laurent25101b02011-02-02 09:33:30 -08002651 }
2652
John Spurlockee5ad722015-03-03 16:17:21 -05002653 /** @see AudioManager#getUiSoundsStreamType() */
2654 public int getUiSoundsStreamType() {
John Spurlock4f0f1202014-08-05 13:28:33 -04002655 return mStreamVolumeAlias[AudioSystem.STREAM_SYSTEM];
Eric Laurent6d517662012-04-23 18:42:39 -07002656 }
2657
Makoto Onukid45a4a22015-11-02 17:17:38 -08002658 /** @see AudioManager#setMicrophoneMute(boolean) */
2659 @Override
Kenny Guy70e0c582015-06-30 19:18:28 +01002660 public void setMicrophoneMute(boolean on, String callingPackage, int userId) {
2661 // If we are being called by the system check for user we are going to change
2662 // so we handle user restrictions correctly.
2663 int uid = Binder.getCallingUid();
2664 if (uid == android.os.Process.SYSTEM_UID) {
2665 uid = UserHandle.getUid(userId, UserHandle.getAppId(uid));
2666 }
Makoto Onuki4f160732015-10-27 17:15:38 -07002667 // If OP_MUTE_MICROPHONE is set, disallow unmuting.
2668 if (!on && mAppOps.noteOp(AppOpsManager.OP_MUTE_MICROPHONE, uid, callingPackage)
Kenny Guy70e0c582015-06-30 19:18:28 +01002669 != AppOpsManager.MODE_ALLOWED) {
Emily Bernier22c921a2014-05-28 11:01:32 -04002670 return;
2671 }
Jean-Michel Trivi4a4fea02014-08-29 18:14:09 -07002672 if (!checkAudioSettingsPermission("setMicrophoneMute()")) {
2673 return;
2674 }
Kenny Guy70e0c582015-06-30 19:18:28 +01002675 if (userId != UserHandle.getCallingUserId() &&
2676 mContext.checkCallingOrSelfPermission(
2677 android.Manifest.permission.INTERACT_ACROSS_USERS_FULL)
2678 != PackageManager.PERMISSION_GRANTED) {
2679 return;
2680 }
Makoto Onukid45a4a22015-11-02 17:17:38 -08002681 setMicrophoneMuteNoCallerCheck(on, userId);
2682 }
Emily Bernier22c921a2014-05-28 11:01:32 -04002683
Makoto Onukid45a4a22015-11-02 17:17:38 -08002684 private void setMicrophoneMuteNoCallerCheck(boolean on, int userId) {
2685 if (DEBUG_VOL) {
2686 Log.d(TAG, String.format("Mic mute %s, user=%d", on, userId));
2687 }
Jean-Michel Trivi7be17d22017-12-21 18:09:21 -08002688 // only mute for the current user
Kenny Guy70e0c582015-06-30 19:18:28 +01002689 if (getCurrentUserId() == userId) {
Jean-Michel Trivi7be17d22017-12-21 18:09:21 -08002690 final boolean currentMute = AudioSystem.isMicrophoneMuted();
Eric Laurent66b69672018-01-26 18:30:51 -08002691 final long identity = Binder.clearCallingIdentity();
Kenny Guy70e0c582015-06-30 19:18:28 +01002692 AudioSystem.muteMicrophone(on);
Eric Laurent66b69672018-01-26 18:30:51 -08002693 Binder.restoreCallingIdentity(identity);
Jean-Michel Trivi7be17d22017-12-21 18:09:21 -08002694 if (on != currentMute) {
2695 mContext.sendBroadcast(new Intent(AudioManager.ACTION_MICROPHONE_MUTE_CHANGED)
2696 .setFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY));
2697 }
Kenny Guy70e0c582015-06-30 19:18:28 +01002698 }
Emily Bernier22c921a2014-05-28 11:01:32 -04002699 }
2700
John Spurlock661f2cf2014-11-17 10:29:10 -05002701 @Override
2702 public int getRingerModeExternal() {
2703 synchronized(mSettingsLock) {
2704 return mRingerModeExternal;
2705 }
2706 }
2707
2708 @Override
2709 public int getRingerModeInternal() {
Glenn Kastenba195eb2011-12-13 09:30:40 -08002710 synchronized(mSettingsLock) {
2711 return mRingerMode;
2712 }
2713 }
2714
2715 private void ensureValidRingerMode(int ringerMode) {
John Spurlock97559372014-10-24 16:27:36 -04002716 if (!isValidRingerMode(ringerMode)) {
Glenn Kastenba195eb2011-12-13 09:30:40 -08002717 throw new IllegalArgumentException("Bad ringer mode " + ringerMode);
2718 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002719 }
2720
John Spurlock97559372014-10-24 16:27:36 -04002721 /** @see AudioManager#isValidRingerMode(int) */
2722 public boolean isValidRingerMode(int ringerMode) {
2723 return ringerMode >= 0 && ringerMode <= AudioManager.RINGER_MODE_MAX;
2724 }
2725
John Spurlock661f2cf2014-11-17 10:29:10 -05002726 public void setRingerModeExternal(int ringerMode, String caller) {
Julia Reynolds48034f82016-03-09 10:15:16 -05002727 if (isAndroidNPlus(caller) && wouldToggleZenMode(ringerMode)
2728 && !mNm.isNotificationPolicyAccessGrantedForPackage(caller)) {
2729 throw new SecurityException("Not allowed to change Do Not Disturb state");
2730 }
2731
John Spurlockaf88a192014-12-23 16:14:44 -05002732 setRingerMode(ringerMode, caller, true /*external*/);
John Spurlock661f2cf2014-11-17 10:29:10 -05002733 }
2734
2735 public void setRingerModeInternal(int ringerMode, String caller) {
John Spurlockcdb57ae2015-02-11 19:04:11 -05002736 enforceVolumeController("setRingerModeInternal");
John Spurlockaf88a192014-12-23 16:14:44 -05002737 setRingerMode(ringerMode, caller, false /*external*/);
John Spurlock661f2cf2014-11-17 10:29:10 -05002738 }
2739
Mike Digman55272862018-02-20 14:35:17 -08002740 public void silenceRingerModeInternal(String reason) {
2741 VibrationEffect effect = null;
2742 int ringerMode = AudioManager.RINGER_MODE_SILENT;
2743 int toastText = 0;
2744
2745 int silenceRingerSetting = Settings.Secure.VOLUME_HUSH_OFF;
2746 if (mContext.getResources()
2747 .getBoolean(com.android.internal.R.bool.config_volumeHushGestureEnabled)) {
2748 silenceRingerSetting = Settings.Secure.getIntForUser(mContentResolver,
2749 Settings.Secure.VOLUME_HUSH_GESTURE, VOLUME_HUSH_OFF,
2750 UserHandle.USER_CURRENT);
2751 }
2752
2753 switch(silenceRingerSetting) {
2754 case VOLUME_HUSH_MUTE:
2755 effect = VibrationEffect.get(VibrationEffect.EFFECT_DOUBLE_CLICK);
2756 ringerMode = AudioManager.RINGER_MODE_SILENT;
2757 toastText = com.android.internal.R.string.volume_dialog_ringer_guidance_silent;
2758 break;
2759 case VOLUME_HUSH_VIBRATE:
2760 effect = VibrationEffect.get(VibrationEffect.EFFECT_HEAVY_CLICK);
2761 ringerMode = AudioManager.RINGER_MODE_VIBRATE;
2762 toastText = com.android.internal.R.string.volume_dialog_ringer_guidance_vibrate;
2763 break;
2764 }
Alexey Kuzmine1f06b82018-06-20 17:48:43 +01002765 maybeVibrate(effect, reason);
Mike Digman55272862018-02-20 14:35:17 -08002766 setRingerModeInternal(ringerMode, reason);
2767 Toast.makeText(mContext, toastText, Toast.LENGTH_SHORT).show();
2768 }
2769
Alexey Kuzmine1f06b82018-06-20 17:48:43 +01002770 private boolean maybeVibrate(VibrationEffect effect, String reason) {
Mike Digman55272862018-02-20 14:35:17 -08002771 if (!mHasVibrator) {
2772 return false;
2773 }
2774 final boolean hapticsDisabled = Settings.System.getIntForUser(mContext.getContentResolver(),
2775 Settings.System.HAPTIC_FEEDBACK_ENABLED, 0, UserHandle.USER_CURRENT) == 0;
2776 if (hapticsDisabled) {
2777 return false;
2778 }
2779
2780 if (effect == null) {
2781 return false;
2782 }
Alexey Kuzmine1f06b82018-06-20 17:48:43 +01002783 mVibrator.vibrate(Binder.getCallingUid(), mContext.getOpPackageName(), effect,
2784 reason, VIBRATION_ATTRIBUTES);
Mike Digman55272862018-02-20 14:35:17 -08002785 return true;
2786 }
2787
John Spurlock661f2cf2014-11-17 10:29:10 -05002788 private void setRingerMode(int ringerMode, String caller, boolean external) {
Muyuan Li1ed6df62016-06-18 11:16:52 -07002789 if (mUseFixedVolume || mIsSingleVolume) {
Eric Laurent83a017b2013-03-19 18:15:31 -07002790 return;
2791 }
John Spurlock661f2cf2014-11-17 10:29:10 -05002792 if (caller == null || caller.length() == 0) {
2793 throw new IllegalArgumentException("Bad caller: " + caller);
2794 }
John Spurlock97559372014-10-24 16:27:36 -04002795 ensureValidRingerMode(ringerMode);
Eric Laurent24482012012-05-10 09:41:17 -07002796 if ((ringerMode == AudioManager.RINGER_MODE_VIBRATE) && !mHasVibrator) {
2797 ringerMode = AudioManager.RINGER_MODE_SILENT;
2798 }
John Spurlockaf88a192014-12-23 16:14:44 -05002799 final long identity = Binder.clearCallingIdentity();
2800 try {
2801 synchronized (mSettingsLock) {
2802 final int ringerModeInternal = getRingerModeInternal();
2803 final int ringerModeExternal = getRingerModeExternal();
2804 if (external) {
2805 setRingerModeExt(ringerMode);
2806 if (mRingerModeDelegate != null) {
2807 ringerMode = mRingerModeDelegate.onSetRingerModeExternal(ringerModeExternal,
John Spurlocka48d7792015-03-03 17:35:57 -05002808 ringerMode, caller, ringerModeInternal, mVolumePolicy);
John Spurlockaf88a192014-12-23 16:14:44 -05002809 }
2810 if (ringerMode != ringerModeInternal) {
2811 setRingerModeInt(ringerMode, true /*persist*/);
2812 }
2813 } else /*internal*/ {
2814 if (ringerMode != ringerModeInternal) {
2815 setRingerModeInt(ringerMode, true /*persist*/);
2816 }
2817 if (mRingerModeDelegate != null) {
2818 ringerMode = mRingerModeDelegate.onSetRingerModeInternal(ringerModeInternal,
John Spurlocka48d7792015-03-03 17:35:57 -05002819 ringerMode, caller, ringerModeExternal, mVolumePolicy);
John Spurlockaf88a192014-12-23 16:14:44 -05002820 }
2821 setRingerModeExt(ringerMode);
John Spurlock57627792014-12-11 11:29:54 -05002822 }
John Spurlock661f2cf2014-11-17 10:29:10 -05002823 }
John Spurlockaf88a192014-12-23 16:14:44 -05002824 } finally {
2825 Binder.restoreCallingIdentity(identity);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002826 }
2827 }
2828
John Spurlock661f2cf2014-11-17 10:29:10 -05002829 private void setRingerModeExt(int ringerMode) {
2830 synchronized(mSettingsLock) {
2831 if (ringerMode == mRingerModeExternal) return;
2832 mRingerModeExternal = ringerMode;
John Spurlocke5b42d92014-10-15 12:03:48 -04002833 }
John Spurlock661f2cf2014-11-17 10:29:10 -05002834 // Send sticky broadcast
John Spurlockbcc10872014-11-28 15:29:21 -05002835 broadcastRingerMode(AudioManager.RINGER_MODE_CHANGED_ACTION, ringerMode);
John Spurlocke5b42d92014-10-15 12:03:48 -04002836 }
2837
Jean-Michel Trivic106d9f2018-06-07 12:28:27 -07002838 @GuardedBy("mSettingsLock")
John Spurlock50ced3f2015-05-11 16:00:09 -04002839 private void muteRingerModeStreams() {
Beverlyd6964762018-02-16 14:07:03 -05002840 // Mute stream if not previously muted by ringer mode and (ringer mode
2841 // is not RINGER_MODE_NORMAL OR stream is zen muted) and stream is affected by ringer mode.
2842 // Unmute stream if previously muted by ringer/zen mode and ringer mode
Eric Laurent5b4e6542010-03-19 20:02:21 -07002843 // is RINGER_MODE_NORMAL or stream is not affected by ringer mode.
Jason Parekhb1096152009-03-24 17:48:25 -07002844 int numStreamTypes = AudioSystem.getNumStreamTypes();
Beverly925cde82018-01-23 09:31:23 -05002845
2846 if (mNm == null) {
2847 mNm = (NotificationManager) mContext.getSystemService(Context.NOTIFICATION_SERVICE);
2848 }
2849
Jack He6dd78c12018-02-12 21:00:24 -08002850 final int ringerMode = mRingerMode; // Read ringer mode as reading primitives is atomic
2851 final boolean ringerModeMute = ringerMode == AudioManager.RINGER_MODE_VIBRATE
2852 || ringerMode == AudioManager.RINGER_MODE_SILENT;
2853 final boolean shouldRingSco = ringerMode == AudioManager.RINGER_MODE_VIBRATE
2854 && isBluetoothScoOn();
2855 // Ask audio policy engine to force use Bluetooth SCO channel if needed
2856 final String eventSource = "muteRingerModeStreams() from u/pid:" + Binder.getCallingUid()
2857 + "/" + Binder.getCallingPid();
2858 sendMsg(mAudioHandler, MSG_SET_FORCE_USE, SENDMSG_QUEUE, AudioSystem.FOR_VIBRATE_RINGING,
2859 shouldRingSco ? AudioSystem.FORCE_BT_SCO : AudioSystem.FORCE_NONE, eventSource, 0);
Beverly925cde82018-01-23 09:31:23 -05002860
Eric Laurent5b4e6542010-03-19 20:02:21 -07002861 for (int streamType = numStreamTypes - 1; streamType >= 0; streamType--) {
Beverlyd6964762018-02-16 14:07:03 -05002862 final boolean isMuted = isStreamMutedByRingerOrZenMode(streamType);
Jack He6dd78c12018-02-12 21:00:24 -08002863 final boolean muteAllowedBySco =
2864 !(shouldRingSco && streamType == AudioSystem.STREAM_RING);
Beverlyd6964762018-02-16 14:07:03 -05002865 final boolean shouldZenMute = shouldZenMuteStream(streamType);
2866 final boolean shouldMute = shouldZenMute || (ringerModeMute
Jack He6dd78c12018-02-12 21:00:24 -08002867 && isStreamAffectedByRingerMode(streamType) && muteAllowedBySco);
John Spurlock661f2cf2014-11-17 10:29:10 -05002868 if (isMuted == shouldMute) continue;
2869 if (!shouldMute) {
2870 // unmute
2871 // ring and notifications volume should never be 0 when not silenced
John Spurlockd9c75db2015-04-28 11:19:13 -04002872 if (mStreamVolumeAlias[streamType] == AudioSystem.STREAM_RING) {
John Spurlock661f2cf2014-11-17 10:29:10 -05002873 synchronized (VolumeStreamState.class) {
John Spurlocka48d7792015-03-03 17:35:57 -05002874 final VolumeStreamState vss = mStreamStates[streamType];
2875 for (int i = 0; i < vss.mIndexMap.size(); i++) {
2876 int device = vss.mIndexMap.keyAt(i);
2877 int value = vss.mIndexMap.valueAt(i);
John Spurlock2bb02ec2015-03-02 13:13:06 -05002878 if (value == 0) {
John Spurlocka48d7792015-03-03 17:35:57 -05002879 vss.setIndex(10, device, TAG);
Eric Laurent9bc8358d2011-11-18 16:43:31 -08002880 }
2881 }
Eric Laurent9e0d25f2015-02-12 17:28:53 -08002882 // Persist volume for stream ring when it is changed here
2883 final int device = getDeviceForStream(streamType);
2884 sendMsg(mAudioHandler,
2885 MSG_PERSIST_VOLUME,
2886 SENDMSG_QUEUE,
2887 device,
2888 0,
2889 mStreamStates[streamType],
2890 PERSIST_DELAY);
Eric Laurentb024c302011-10-14 17:19:27 -07002891 }
Eric Laurent9bcf4012009-06-12 06:09:28 -07002892 }
RoboErik4197cb62015-01-21 15:45:32 -08002893 mStreamStates[streamType].mute(false);
Beverlyd6964762018-02-16 14:07:03 -05002894 mRingerAndZenModeMutedStreams &= ~(1 << streamType);
Eric Laurent5b4e6542010-03-19 20:02:21 -07002895 } else {
John Spurlock661f2cf2014-11-17 10:29:10 -05002896 // mute
RoboErik4197cb62015-01-21 15:45:32 -08002897 mStreamStates[streamType].mute(true);
Beverlyd6964762018-02-16 14:07:03 -05002898 mRingerAndZenModeMutedStreams |= (1 << streamType);
Jason Parekhb1096152009-03-24 17:48:25 -07002899 }
2900 }
John Spurlock50ced3f2015-05-11 16:00:09 -04002901 }
2902
Beverly925cde82018-01-23 09:31:23 -05002903 private boolean isAlarm(int streamType) {
2904 return streamType == AudioSystem.STREAM_ALARM;
2905 }
2906
2907 private boolean isNotificationOrRinger(int streamType) {
2908 return streamType == AudioSystem.STREAM_NOTIFICATION
2909 || streamType == AudioSystem.STREAM_RING;
2910 }
2911
2912 private boolean isMedia(int streamType) {
Beverlyd6964762018-02-16 14:07:03 -05002913 return streamType == AudioSystem.STREAM_MUSIC;
2914 }
2915
2916
2917 private boolean isSystem(int streamType) {
2918 return streamType == AudioSystem.STREAM_SYSTEM;
Beverly925cde82018-01-23 09:31:23 -05002919 }
2920
John Spurlock50ced3f2015-05-11 16:00:09 -04002921 private void setRingerModeInt(int ringerMode, boolean persist) {
2922 final boolean change;
2923 synchronized(mSettingsLock) {
2924 change = mRingerMode != ringerMode;
2925 mRingerMode = ringerMode;
Jean-Michel Trivic106d9f2018-06-07 12:28:27 -07002926 muteRingerModeStreams();
John Spurlock50ced3f2015-05-11 16:00:09 -04002927 }
2928
Jason Parekhb1096152009-03-24 17:48:25 -07002929 // Post a persist ringer mode msg
Eric Laurent4050c932009-07-08 02:52:14 -07002930 if (persist) {
Eric Laurentafbb0472011-12-15 09:04:23 -08002931 sendMsg(mAudioHandler, MSG_PERSIST_RINGER_MODE,
Eric Laurent4050c932009-07-08 02:52:14 -07002932 SENDMSG_REPLACE, 0, 0, null, PERSIST_DELAY);
2933 }
John Spurlockbcc10872014-11-28 15:29:21 -05002934 if (change) {
2935 // Send sticky broadcast
2936 broadcastRingerMode(AudioManager.INTERNAL_RINGER_MODE_CHANGED_ACTION, ringerMode);
2937 }
Jason Parekhb1096152009-03-24 17:48:25 -07002938 }
2939
Jean-Michel Trivica49d312019-02-14 15:55:39 -08002940 /*package*/ void postUpdateRingerModeServiceInt() {
2941 sendMsg(mAudioHandler, MSG_UPDATE_RINGER_MODE, SENDMSG_QUEUE, 0, 0, null, 0);
2942 }
2943
2944 private void onUpdateRingerModeServiceInt() {
Jean-Michel Trivi58850372018-09-14 16:01:28 -07002945 setRingerModeInt(getRingerModeInternal(), false);
2946 }
2947
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002948 /** @see AudioManager#shouldVibrate(int) */
2949 public boolean shouldVibrate(int vibrateType) {
Eric Laurentbffc3d12012-05-07 17:43:49 -07002950 if (!mHasVibrator) return false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002951
2952 switch (getVibrateSetting(vibrateType)) {
2953
2954 case AudioManager.VIBRATE_SETTING_ON:
John Spurlock57627792014-12-11 11:29:54 -05002955 return getRingerModeExternal() != AudioManager.RINGER_MODE_SILENT;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002956
2957 case AudioManager.VIBRATE_SETTING_ONLY_SILENT:
John Spurlock57627792014-12-11 11:29:54 -05002958 return getRingerModeExternal() == AudioManager.RINGER_MODE_VIBRATE;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002959
2960 case AudioManager.VIBRATE_SETTING_OFF:
Daniel Sandlerbcac4962010-04-12 13:23:57 -04002961 // return false, even for incoming calls
2962 return false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002963
2964 default:
2965 return false;
2966 }
2967 }
2968
2969 /** @see AudioManager#getVibrateSetting(int) */
2970 public int getVibrateSetting(int vibrateType) {
Eric Laurentbffc3d12012-05-07 17:43:49 -07002971 if (!mHasVibrator) return AudioManager.VIBRATE_SETTING_OFF;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002972 return (mVibrateSetting >> (vibrateType * 2)) & 3;
2973 }
2974
2975 /** @see AudioManager#setVibrateSetting(int, int) */
2976 public void setVibrateSetting(int vibrateType, int vibrateSetting) {
2977
Eric Laurentbffc3d12012-05-07 17:43:49 -07002978 if (!mHasVibrator) return;
2979
John Spurlock61560172015-02-06 19:46:04 -05002980 mVibrateSetting = AudioSystem.getValueForVibrateSetting(mVibrateSetting, vibrateType,
2981 vibrateSetting);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002982
2983 // Broadcast change
2984 broadcastVibrateSetting(vibrateType);
2985
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002986 }
2987
Jean-Michel Trivi5bbcd442019-04-18 12:07:34 -07002988 /**
2989 * Return the pid of the current audio mode owner
2990 * @return 0 if nobody owns the mode
2991 */
2992 /*package*/ int getModeOwnerPid() {
2993 int modeOwnerPid = 0;
2994 try {
2995 modeOwnerPid = mSetModeDeathHandlers.get(0).getPid();
2996 } catch (Exception e) {
2997 // nothing to do, modeOwnerPid is not modified
2998 }
2999 return modeOwnerPid;
3000 }
3001
3002 private class SetModeDeathHandler implements IBinder.DeathRecipient {
Eric Laurent9272b4b2010-01-23 17:12:59 -08003003 private IBinder mCb; // To be notified of client's death
Marco Nelissenf1ddd512011-08-10 14:15:44 -07003004 private int mPid;
Eric Laurent9272b4b2010-01-23 17:12:59 -08003005 private int mMode = AudioSystem.MODE_NORMAL; // Current mode set by this client
3006
Eric Laurent9f103de2011-09-08 15:04:23 -07003007 SetModeDeathHandler(IBinder cb, int pid) {
Eric Laurent9272b4b2010-01-23 17:12:59 -08003008 mCb = cb;
Eric Laurent9f103de2011-09-08 15:04:23 -07003009 mPid = pid;
Eric Laurent9272b4b2010-01-23 17:12:59 -08003010 }
3011
3012 public void binderDied() {
Jack He89f97982018-05-02 19:10:56 -07003013 int oldModeOwnerPid = 0;
Eric Laurentd7454be2011-09-14 08:45:58 -07003014 int newModeOwnerPid = 0;
Jean-Michel Trivi58850372018-09-14 16:01:28 -07003015 synchronized (mDeviceBroker.mSetModeLock) {
Eric Laurent9272b4b2010-01-23 17:12:59 -08003016 Log.w(TAG, "setMode() client died");
Jack He89f97982018-05-02 19:10:56 -07003017 if (!mSetModeDeathHandlers.isEmpty()) {
3018 oldModeOwnerPid = mSetModeDeathHandlers.get(0).getPid();
3019 }
Eric Laurent9272b4b2010-01-23 17:12:59 -08003020 int index = mSetModeDeathHandlers.indexOf(this);
3021 if (index < 0) {
3022 Log.w(TAG, "unregistered setMode() client died");
3023 } else {
John Spurlock90874332015-03-10 16:00:54 -04003024 newModeOwnerPid = setModeInt(AudioSystem.MODE_NORMAL, mCb, mPid, TAG);
Eric Laurent9272b4b2010-01-23 17:12:59 -08003025 }
3026 }
Eric Laurent9f103de2011-09-08 15:04:23 -07003027 // when entering RINGTONE, IN_CALL or IN_COMMUNICATION mode, clear all
Jack He89f97982018-05-02 19:10:56 -07003028 // SCO connections not started by the application changing the mode when pid changes
3029 if ((newModeOwnerPid != oldModeOwnerPid) && (newModeOwnerPid != 0)) {
Jean-Michel Trivi58850372018-09-14 16:01:28 -07003030 mDeviceBroker.postDisconnectBluetoothSco(newModeOwnerPid);
Eric Laurent9f103de2011-09-08 15:04:23 -07003031 }
Eric Laurent9272b4b2010-01-23 17:12:59 -08003032 }
3033
Marco Nelissenf1ddd512011-08-10 14:15:44 -07003034 public int getPid() {
3035 return mPid;
3036 }
3037
Eric Laurent9272b4b2010-01-23 17:12:59 -08003038 public void setMode(int mode) {
3039 mMode = mode;
3040 }
3041
3042 public int getMode() {
3043 return mMode;
3044 }
3045
3046 public IBinder getBinder() {
3047 return mCb;
3048 }
3049 }
3050
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003051 /** @see AudioManager#setMode(int) */
John Spurlock90874332015-03-10 16:00:54 -04003052 public void setMode(int mode, IBinder cb, String callingPackage) {
3053 if (DEBUG_MODE) { Log.v(TAG, "setMode(mode=" + mode + ", callingPackage=" + callingPackage + ")"); }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003054 if (!checkAudioSettingsPermission("setMode()")) {
3055 return;
3056 }
Eric Laurenta553c252009-07-17 12:17:14 -07003057
Jean-Michel Triviccd654e2014-09-03 17:48:47 -07003058 if ( (mode == AudioSystem.MODE_IN_CALL) &&
3059 (mContext.checkCallingOrSelfPermission(
3060 android.Manifest.permission.MODIFY_PHONE_STATE)
3061 != PackageManager.PERMISSION_GRANTED)) {
3062 Log.w(TAG, "MODIFY_PHONE_STATE Permission Denial: setMode(MODE_IN_CALL) from pid="
3063 + Binder.getCallingPid() + ", uid=" + Binder.getCallingUid());
3064 return;
3065 }
3066
Jean-Michel Trivi8f677d62010-11-15 12:11:32 -08003067 if (mode < AudioSystem.MODE_CURRENT || mode >= AudioSystem.NUM_MODES) {
Eric Laurenta553c252009-07-17 12:17:14 -07003068 return;
3069 }
3070
Jack He89f97982018-05-02 19:10:56 -07003071 int oldModeOwnerPid = 0;
Eric Laurentd7454be2011-09-14 08:45:58 -07003072 int newModeOwnerPid = 0;
Jean-Michel Trivi58850372018-09-14 16:01:28 -07003073 synchronized (mDeviceBroker.mSetModeLock) {
Jack He89f97982018-05-02 19:10:56 -07003074 if (!mSetModeDeathHandlers.isEmpty()) {
3075 oldModeOwnerPid = mSetModeDeathHandlers.get(0).getPid();
3076 }
Eric Laurenta553c252009-07-17 12:17:14 -07003077 if (mode == AudioSystem.MODE_CURRENT) {
3078 mode = mMode;
3079 }
John Spurlock90874332015-03-10 16:00:54 -04003080 newModeOwnerPid = setModeInt(mode, cb, Binder.getCallingPid(), callingPackage);
Eric Laurent9f103de2011-09-08 15:04:23 -07003081 }
3082 // when entering RINGTONE, IN_CALL or IN_COMMUNICATION mode, clear all
Jack He89f97982018-05-02 19:10:56 -07003083 // SCO connections not started by the application changing the mode when pid changes
3084 if ((newModeOwnerPid != oldModeOwnerPid) && (newModeOwnerPid != 0)) {
Jean-Michel Trivi58850372018-09-14 16:01:28 -07003085 mDeviceBroker.postDisconnectBluetoothSco(newModeOwnerPid);
Eric Laurent9f103de2011-09-08 15:04:23 -07003086 }
3087 }
Jean-Michel Trivi2ade5762010-12-11 13:18:30 -08003088
Eric Laurentd7454be2011-09-14 08:45:58 -07003089 // setModeInt() returns a valid PID if the audio mode was successfully set to
Eric Laurent9f103de2011-09-08 15:04:23 -07003090 // any mode other than NORMAL.
Jean-Michel Trivib32faaa2019-04-22 12:21:50 -07003091 @GuardedBy("mDeviceBroker.mSetModeLock")
John Spurlock90874332015-03-10 16:00:54 -04003092 private int setModeInt(int mode, IBinder cb, int pid, String caller) {
3093 if (DEBUG_MODE) { Log.v(TAG, "setModeInt(mode=" + mode + ", pid=" + pid + ", caller="
3094 + caller + ")"); }
Eric Laurentd7454be2011-09-14 08:45:58 -07003095 int newModeOwnerPid = 0;
Eric Laurent9f103de2011-09-08 15:04:23 -07003096 if (cb == null) {
3097 Log.e(TAG, "setModeInt() called with null binder");
Eric Laurentd7454be2011-09-14 08:45:58 -07003098 return newModeOwnerPid;
Eric Laurent9f103de2011-09-08 15:04:23 -07003099 }
Jean-Michel Trivi2ade5762010-12-11 13:18:30 -08003100
Eric Laurent9f103de2011-09-08 15:04:23 -07003101 SetModeDeathHandler hdlr = null;
3102 Iterator iter = mSetModeDeathHandlers.iterator();
3103 while (iter.hasNext()) {
3104 SetModeDeathHandler h = (SetModeDeathHandler)iter.next();
3105 if (h.getPid() == pid) {
3106 hdlr = h;
3107 // Remove from client list so that it is re-inserted at top of list
3108 iter.remove();
3109 hdlr.getBinder().unlinkToDeath(hdlr, 0);
3110 break;
3111 }
3112 }
Jean-Michel Trivib32faaa2019-04-22 12:21:50 -07003113 final int oldMode = mMode;
Eric Laurent9f103de2011-09-08 15:04:23 -07003114 int status = AudioSystem.AUDIO_STATUS_OK;
Eric Laurent6afa6502017-09-28 15:18:19 -07003115 int actualMode;
Eric Laurent9f103de2011-09-08 15:04:23 -07003116 do {
Eric Laurent6afa6502017-09-28 15:18:19 -07003117 actualMode = mode;
Eric Laurent9f103de2011-09-08 15:04:23 -07003118 if (mode == AudioSystem.MODE_NORMAL) {
3119 // get new mode from client at top the list if any
3120 if (!mSetModeDeathHandlers.isEmpty()) {
3121 hdlr = mSetModeDeathHandlers.get(0);
3122 cb = hdlr.getBinder();
Eric Laurent6afa6502017-09-28 15:18:19 -07003123 actualMode = hdlr.getMode();
Jean-Michel Trivi339567d2014-07-29 09:53:34 -07003124 if (DEBUG_MODE) {
3125 Log.w(TAG, " using mode=" + mode + " instead due to death hdlr at pid="
3126 + hdlr.mPid);
3127 }
Eric Laurentb9c9d262009-05-06 08:13:20 -07003128 }
Eric Laurent9f103de2011-09-08 15:04:23 -07003129 } else {
3130 if (hdlr == null) {
3131 hdlr = new SetModeDeathHandler(cb, pid);
3132 }
3133 // Register for client death notification
3134 try {
3135 cb.linkToDeath(hdlr, 0);
3136 } catch (RemoteException e) {
3137 // Client has died!
3138 Log.w(TAG, "setMode() could not link to "+cb+" binder death");
3139 }
3140
3141 // Last client to call setMode() is always at top of client list
3142 // as required by SetModeDeathHandler.binderDied()
3143 mSetModeDeathHandlers.add(0, hdlr);
3144 hdlr.setMode(mode);
3145 }
3146
Eric Laurent6afa6502017-09-28 15:18:19 -07003147 if (actualMode != mMode) {
Eric Laurent66b69672018-01-26 18:30:51 -08003148 final long identity = Binder.clearCallingIdentity();
Eric Laurent6afa6502017-09-28 15:18:19 -07003149 status = AudioSystem.setPhoneState(actualMode);
Eric Laurent66b69672018-01-26 18:30:51 -08003150 Binder.restoreCallingIdentity(identity);
Eric Laurent9f103de2011-09-08 15:04:23 -07003151 if (status == AudioSystem.AUDIO_STATUS_OK) {
Eric Laurent6afa6502017-09-28 15:18:19 -07003152 if (DEBUG_MODE) { Log.v(TAG, " mode successfully set to " + actualMode); }
3153 mMode = actualMode;
Eric Laurent9f103de2011-09-08 15:04:23 -07003154 } else {
3155 if (hdlr != null) {
3156 mSetModeDeathHandlers.remove(hdlr);
3157 cb.unlinkToDeath(hdlr, 0);
3158 }
3159 // force reading new top of mSetModeDeathHandlers stack
Jean-Michel Trivi339567d2014-07-29 09:53:34 -07003160 if (DEBUG_MODE) { Log.w(TAG, " mode set to MODE_NORMAL after phoneState pb"); }
Eric Laurent9f103de2011-09-08 15:04:23 -07003161 mode = AudioSystem.MODE_NORMAL;
3162 }
3163 } else {
3164 status = AudioSystem.AUDIO_STATUS_OK;
3165 }
3166 } while (status != AudioSystem.AUDIO_STATUS_OK && !mSetModeDeathHandlers.isEmpty());
3167
3168 if (status == AudioSystem.AUDIO_STATUS_OK) {
Eric Laurent6afa6502017-09-28 15:18:19 -07003169 if (actualMode != AudioSystem.MODE_NORMAL) {
Eric Laurentd7454be2011-09-14 08:45:58 -07003170 if (mSetModeDeathHandlers.isEmpty()) {
3171 Log.e(TAG, "setMode() different from MODE_NORMAL with empty mode client stack");
3172 } else {
3173 newModeOwnerPid = mSetModeDeathHandlers.get(0).getPid();
3174 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003175 }
Eric Laurent6afa6502017-09-28 15:18:19 -07003176 // Note: newModeOwnerPid is always 0 when actualMode is MODE_NORMAL
3177 mModeLogger.log(
3178 new PhoneStateEvent(caller, pid, mode, newModeOwnerPid, actualMode));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003179 int streamType = getActiveStreamType(AudioManager.USE_DEFAULT_STREAM_TYPE);
Eric Laurent9bc8358d2011-11-18 16:43:31 -08003180 int device = getDeviceForStream(streamType);
Eric Laurent42b041e2013-03-29 11:36:03 -07003181 int index = mStreamStates[mStreamVolumeAlias[streamType]].getIndex(device);
John Spurlock90874332015-03-10 16:00:54 -04003182 setStreamVolumeInt(mStreamVolumeAlias[streamType], index, device, true, caller);
Eric Laurent6d517662012-04-23 18:42:39 -07003183
John Spurlock90874332015-03-10 16:00:54 -04003184 updateStreamVolumeAlias(true /*updateVolumes*/, caller);
Jean-Michel Trivib32faaa2019-04-22 12:21:50 -07003185
3186 // change of mode may require volume to be re-applied on some devices
3187 updateAbsVolumeMultiModeDevices(oldMode, actualMode);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003188 }
Eric Laurentd7454be2011-09-14 08:45:58 -07003189 return newModeOwnerPid;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003190 }
3191
3192 /** @see AudioManager#getMode() */
3193 public int getMode() {
3194 return mMode;
3195 }
3196
Eric Laurente78fced2013-03-15 16:03:47 -07003197 //==========================================================================================
3198 // Sound Effects
3199 //==========================================================================================
3200
3201 private static final String TAG_AUDIO_ASSETS = "audio_assets";
3202 private static final String ATTR_VERSION = "version";
3203 private static final String TAG_GROUP = "group";
3204 private static final String ATTR_GROUP_NAME = "name";
3205 private static final String TAG_ASSET = "asset";
3206 private static final String ATTR_ASSET_ID = "id";
3207 private static final String ATTR_ASSET_FILE = "file";
3208
3209 private static final String ASSET_FILE_VERSION = "1.0";
3210 private static final String GROUP_TOUCH_SOUNDS = "touch_sounds";
3211
Glenn Kasten167d1a22013-07-23 16:24:41 -07003212 private static final int SOUND_EFFECTS_LOAD_TIMEOUT_MS = 5000;
Eric Laurent5d3eb44a2013-03-21 15:35:10 -07003213
3214 class LoadSoundEffectReply {
3215 public int mStatus = 1;
3216 };
3217
Eric Laurente78fced2013-03-15 16:03:47 -07003218 private void loadTouchSoundAssetDefaults() {
3219 SOUND_EFFECT_FILES.add("Effect_Tick.ogg");
3220 for (int i = 0; i < AudioManager.NUM_SOUND_EFFECTS; i++) {
3221 SOUND_EFFECT_FILES_MAP[i][0] = 0;
3222 SOUND_EFFECT_FILES_MAP[i][1] = -1;
3223 }
3224 }
3225
3226 private void loadTouchSoundAssets() {
3227 XmlResourceParser parser = null;
3228
Eric Laurent5d3eb44a2013-03-21 15:35:10 -07003229 // only load assets once.
3230 if (!SOUND_EFFECT_FILES.isEmpty()) {
3231 return;
3232 }
3233
Eric Laurente78fced2013-03-15 16:03:47 -07003234 loadTouchSoundAssetDefaults();
3235
3236 try {
3237 parser = mContext.getResources().getXml(com.android.internal.R.xml.audio_assets);
3238
3239 XmlUtils.beginDocument(parser, TAG_AUDIO_ASSETS);
3240 String version = parser.getAttributeValue(null, ATTR_VERSION);
3241 boolean inTouchSoundsGroup = false;
3242
3243 if (ASSET_FILE_VERSION.equals(version)) {
3244 while (true) {
3245 XmlUtils.nextElement(parser);
3246 String element = parser.getName();
3247 if (element == null) {
3248 break;
3249 }
3250 if (element.equals(TAG_GROUP)) {
3251 String name = parser.getAttributeValue(null, ATTR_GROUP_NAME);
3252 if (GROUP_TOUCH_SOUNDS.equals(name)) {
3253 inTouchSoundsGroup = true;
3254 break;
3255 }
3256 }
3257 }
3258 while (inTouchSoundsGroup) {
3259 XmlUtils.nextElement(parser);
3260 String element = parser.getName();
3261 if (element == null) {
3262 break;
3263 }
3264 if (element.equals(TAG_ASSET)) {
3265 String id = parser.getAttributeValue(null, ATTR_ASSET_ID);
3266 String file = parser.getAttributeValue(null, ATTR_ASSET_FILE);
3267 int fx;
3268
3269 try {
3270 Field field = AudioManager.class.getField(id);
3271 fx = field.getInt(null);
3272 } catch (Exception e) {
3273 Log.w(TAG, "Invalid touch sound ID: "+id);
3274 continue;
3275 }
3276
3277 int i = SOUND_EFFECT_FILES.indexOf(file);
3278 if (i == -1) {
3279 i = SOUND_EFFECT_FILES.size();
3280 SOUND_EFFECT_FILES.add(file);
3281 }
3282 SOUND_EFFECT_FILES_MAP[fx][0] = i;
3283 } else {
3284 break;
3285 }
3286 }
3287 }
3288 } catch (Resources.NotFoundException e) {
3289 Log.w(TAG, "audio assets file not found", e);
3290 } catch (XmlPullParserException e) {
3291 Log.w(TAG, "XML parser exception reading touch sound assets", e);
3292 } catch (IOException e) {
3293 Log.w(TAG, "I/O exception reading touch sound assets", e);
3294 } finally {
3295 if (parser != null) {
3296 parser.close();
3297 }
3298 }
3299 }
3300
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003301 /** @see AudioManager#playSoundEffect(int) */
3302 public void playSoundEffect(int effectType) {
Eric Laurent5d3eb44a2013-03-21 15:35:10 -07003303 playSoundEffectVolume(effectType, -1.0f);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003304 }
3305
3306 /** @see AudioManager#playSoundEffect(int, float) */
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003307 public void playSoundEffectVolume(int effectType, float volume) {
Beverlyd6964762018-02-16 14:07:03 -05003308 // do not try to play the sound effect if the system stream is muted
3309 if (isStreamMutedByRingerOrZenMode(STREAM_SYSTEM)) {
3310 return;
3311 }
3312
Natalie Silvanovich559c76d2014-05-01 10:16:24 -07003313 if (effectType >= AudioManager.NUM_SOUND_EFFECTS || effectType < 0) {
3314 Log.w(TAG, "AudioService effectType value " + effectType + " out of range");
3315 return;
3316 }
3317
Eric Laurent5d3eb44a2013-03-21 15:35:10 -07003318 sendMsg(mAudioHandler, MSG_PLAY_SOUND_EFFECT, SENDMSG_QUEUE,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003319 effectType, (int) (volume * 1000), null, 0);
3320 }
3321
3322 /**
3323 * Loads samples into the soundpool.
Glenn Kasten5c17a822011-11-30 09:41:01 -08003324 * This method must be called at first when sound effects are enabled
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003325 */
3326 public boolean loadSoundEffects() {
Eric Laurent5d3eb44a2013-03-21 15:35:10 -07003327 int attempts = 3;
3328 LoadSoundEffectReply reply = new LoadSoundEffectReply();
Eric Laurenta60e2122010-12-28 16:49:07 -08003329
Eric Laurent5d3eb44a2013-03-21 15:35:10 -07003330 synchronized (reply) {
3331 sendMsg(mAudioHandler, MSG_LOAD_SOUND_EFFECTS, SENDMSG_QUEUE, 0, 0, reply, 0);
3332 while ((reply.mStatus == 1) && (attempts-- > 0)) {
Eric Laurent117b7bb2011-01-16 17:07:27 -08003333 try {
Glenn Kasten167d1a22013-07-23 16:24:41 -07003334 reply.wait(SOUND_EFFECTS_LOAD_TIMEOUT_MS);
Eric Laurent5d3eb44a2013-03-21 15:35:10 -07003335 } catch (InterruptedException e) {
3336 Log.w(TAG, "loadSoundEffects Interrupted while waiting sound pool loaded.");
Eric Laurent117b7bb2011-01-16 17:07:27 -08003337 }
Eric Laurenta60e2122010-12-28 16:49:07 -08003338 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003339 }
Eric Laurent5d3eb44a2013-03-21 15:35:10 -07003340 return (reply.mStatus == 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003341 }
3342
3343 /**
Ben Lin0c856812019-04-03 12:09:54 -07003344 * Schedule loading samples into the soundpool.
3345 * This method can be overridden to schedule loading at a later time.
3346 */
3347 protected void scheduleLoadSoundEffects() {
3348 sendMsg(mAudioHandler, MSG_LOAD_SOUND_EFFECTS, SENDMSG_QUEUE, 0, 0, null, 0);
3349 }
3350
3351 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003352 * Unloads samples from the sound pool.
3353 * This method can be called to free some memory when
3354 * sound effects are disabled.
3355 */
3356 public void unloadSoundEffects() {
Eric Laurent5d3eb44a2013-03-21 15:35:10 -07003357 sendMsg(mAudioHandler, MSG_UNLOAD_SOUND_EFFECTS, SENDMSG_QUEUE, 0, 0, null, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003358 }
3359
Eric Laurenta60e2122010-12-28 16:49:07 -08003360 class SoundPoolListenerThread extends Thread {
3361 public SoundPoolListenerThread() {
3362 super("SoundPoolListenerThread");
3363 }
3364
3365 @Override
3366 public void run() {
3367
3368 Looper.prepare();
3369 mSoundPoolLooper = Looper.myLooper();
3370
3371 synchronized (mSoundEffectsLock) {
3372 if (mSoundPool != null) {
3373 mSoundPoolCallBack = new SoundPoolCallback();
3374 mSoundPool.setOnLoadCompleteListener(mSoundPoolCallBack);
3375 }
3376 mSoundEffectsLock.notify();
3377 }
3378 Looper.loop();
3379 }
3380 }
3381
3382 private final class SoundPoolCallback implements
3383 android.media.SoundPool.OnLoadCompleteListener {
3384
Eric Laurent5d3eb44a2013-03-21 15:35:10 -07003385 int mStatus = 1; // 1 means neither error nor last sample loaded yet
3386 List<Integer> mSamples = new ArrayList<Integer>();
Eric Laurenta60e2122010-12-28 16:49:07 -08003387
3388 public int status() {
3389 return mStatus;
3390 }
3391
Eric Laurent5d3eb44a2013-03-21 15:35:10 -07003392 public void setSamples(int[] samples) {
3393 for (int i = 0; i < samples.length; i++) {
3394 // do not wait ack for samples rejected upfront by SoundPool
3395 if (samples[i] > 0) {
3396 mSamples.add(samples[i]);
3397 }
3398 }
Eric Laurenta60e2122010-12-28 16:49:07 -08003399 }
3400
3401 public void onLoadComplete(SoundPool soundPool, int sampleId, int status) {
3402 synchronized (mSoundEffectsLock) {
Eric Laurent5d3eb44a2013-03-21 15:35:10 -07003403 int i = mSamples.indexOf(sampleId);
3404 if (i >= 0) {
3405 mSamples.remove(i);
Eric Laurenta60e2122010-12-28 16:49:07 -08003406 }
Eric Laurent5d3eb44a2013-03-21 15:35:10 -07003407 if ((status != 0) || mSamples. isEmpty()) {
3408 mStatus = status;
Eric Laurenta60e2122010-12-28 16:49:07 -08003409 mSoundEffectsLock.notify();
3410 }
3411 }
3412 }
3413 }
3414
Eric Laurent4050c932009-07-08 02:52:14 -07003415 /** @see AudioManager#reloadAudioSettings() */
3416 public void reloadAudioSettings() {
Eric Laurentbc0fab1f2012-09-19 11:24:41 -07003417 readAudioSettings(false /*userSwitch*/);
3418 }
3419
3420 private void readAudioSettings(boolean userSwitch) {
Eric Laurent4050c932009-07-08 02:52:14 -07003421 // restore ringer mode, ringer mode affected streams, mute affected streams and vibrate settings
3422 readPersistedSettings();
Eric Laurentc0232482016-03-15 18:19:23 -07003423 readUserRestrictions();
Eric Laurent4050c932009-07-08 02:52:14 -07003424
3425 // restore volume settings
3426 int numStreamTypes = AudioSystem.getNumStreamTypes();
3427 for (int streamType = 0; streamType < numStreamTypes; streamType++) {
3428 VolumeStreamState streamState = mStreamStates[streamType];
3429
Eric Laurentbc0fab1f2012-09-19 11:24:41 -07003430 if (userSwitch && mStreamVolumeAlias[streamType] == AudioSystem.STREAM_MUSIC) {
3431 continue;
3432 }
3433
Eric Laurent8fa4d6f2014-10-30 14:13:03 -07003434 streamState.readSettings();
3435 synchronized (VolumeStreamState.class) {
Eric Laurent3172d5e2012-05-09 11:38:16 -07003436 // unmute stream that was muted but is not affect by mute anymore
RoboErik4197cb62015-01-21 15:45:32 -08003437 if (streamState.mIsMuted && ((!isStreamAffectedByMute(streamType) &&
Beverlyd6964762018-02-16 14:07:03 -05003438 !isStreamMutedByRingerOrZenMode(streamType)) || mUseFixedVolume)) {
RoboErik4197cb62015-01-21 15:45:32 -08003439 streamState.mIsMuted = false;
Eric Laurent4050c932009-07-08 02:52:14 -07003440 }
Eric Laurent4050c932009-07-08 02:52:14 -07003441 }
3442 }
3443
Eric Laurent33902db2012-10-07 16:15:07 -07003444 // apply new ringer mode before checking volume for alias streams so that streams
3445 // muted by ringer mode have the correct volume
John Spurlock661f2cf2014-11-17 10:29:10 -05003446 setRingerModeInt(getRingerModeInternal(), false);
Eric Laurent33902db2012-10-07 16:15:07 -07003447
Eric Laurent212532b2014-07-21 15:43:18 -07003448 checkAllFixedVolumeDevices();
Eric Laurent24482012012-05-10 09:41:17 -07003449 checkAllAliasStreamVolumes();
John Spurlockb6e19e32015-03-10 21:33:44 -04003450 checkMuteAffectedStreams();
Eric Laurent24482012012-05-10 09:41:17 -07003451
hyomin.ohd0446dc2018-10-18 13:58:27 +09003452 synchronized (mSafeMediaVolumeStateLock) {
John Spurlockaa5ee4d2014-07-25 13:05:12 -04003453 mMusicActiveMs = MathUtils.constrain(Settings.Secure.getIntForUser(mContentResolver,
3454 Settings.Secure.UNSAFE_VOLUME_MUSIC_ACTIVE_MS, 0, UserHandle.USER_CURRENT),
3455 0, UNSAFE_VOLUME_MUSIC_ACTIVE_MS_MAX);
Eric Laurentd640bd32012-09-28 18:01:48 -07003456 if (mSafeMediaVolumeState == SAFE_MEDIA_VOLUME_ACTIVE) {
John Spurlock90874332015-03-10 16:00:54 -04003457 enforceSafeMediaVolume(TAG);
Eric Laurentf1a457d2012-09-20 16:27:23 -07003458 }
Eric Laurentc34dcc12012-09-10 13:51:52 -07003459 }
Eric Laurent4050c932009-07-08 02:52:14 -07003460 }
3461
Dianne Hackborn961cae92013-03-20 14:59:43 -07003462 /** @see AudioManager#setSpeakerphoneOn(boolean) */
Eric Laurentc42ac9d2009-07-29 08:53:03 -07003463 public void setSpeakerphoneOn(boolean on){
Eric Laurentdc1d17a2009-09-10 00:48:21 -07003464 if (!checkAudioSettingsPermission("setSpeakerphoneOn()")) {
3465 return;
3466 }
JW Kwon6e144772018-10-04 17:39:29 +09003467
3468 if (mContext.checkCallingOrSelfPermission(
3469 android.Manifest.permission.MODIFY_PHONE_STATE)
3470 != PackageManager.PERMISSION_GRANTED) {
3471 synchronized (mSetModeDeathHandlers) {
3472 for (SetModeDeathHandler h : mSetModeDeathHandlers) {
3473 if (h.getMode() == AudioSystem.MODE_IN_CALL) {
3474 Log.w(TAG, "getMode is call, Permission Denial: setSpeakerphoneOn from pid="
3475 + Binder.getCallingPid() + ", uid=" + Binder.getCallingUid());
3476 return;
3477 }
3478 }
3479 }
3480 }
3481
Jean-Michel Trivi011f39e2017-08-19 18:08:06 -07003482 // for logging only
3483 final String eventSource = new StringBuilder("setSpeakerphoneOn(").append(on)
3484 .append(") from u/pid:").append(Binder.getCallingUid()).append("/")
3485 .append(Binder.getCallingPid()).toString();
Jean-Michel Trivi90682ff2019-03-18 15:52:00 -07003486 final boolean stateChanged = mDeviceBroker.setSpeakerphoneOn(on, eventSource);
3487 if (stateChanged) {
Jean-Michel Trivi8f6fcdf2019-04-09 13:38:18 -07003488 final long ident = Binder.clearCallingIdentity();
3489 try {
3490 mContext.sendBroadcastAsUser(
3491 new Intent(AudioManager.ACTION_SPEAKERPHONE_STATE_CHANGED)
3492 .setFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY), UserHandle.ALL);
3493 } finally {
3494 Binder.restoreCallingIdentity(ident);
3495 }
Jean-Michel Trivi90682ff2019-03-18 15:52:00 -07003496 }
Eric Laurentc42ac9d2009-07-29 08:53:03 -07003497 }
3498
3499 /** @see AudioManager#isSpeakerphoneOn() */
3500 public boolean isSpeakerphoneOn() {
Jean-Michel Trivi58850372018-09-14 16:01:28 -07003501 return mDeviceBroker.isSpeakerphoneOn();
Eric Laurentc42ac9d2009-07-29 08:53:03 -07003502 }
3503
Dianne Hackborn961cae92013-03-20 14:59:43 -07003504 /** @see AudioManager#setBluetoothScoOn(boolean) */
Eric Laurent48221252015-09-24 18:41:48 -07003505 public void setBluetoothScoOn(boolean on) {
Eric Laurentdc1d17a2009-09-10 00:48:21 -07003506 if (!checkAudioSettingsPermission("setBluetoothScoOn()")) {
3507 return;
3508 }
Sharad Sangle1d188442017-05-09 16:05:40 +05303509
3510 // Only enable calls from system components
Vitor Albuquerquec3bb48c2018-03-07 10:39:59 -03003511 if (UserHandle.getCallingAppId() >= FIRST_APPLICATION_UID) {
Jean-Michel Trivi58850372018-09-14 16:01:28 -07003512 mDeviceBroker.setBluetoothScoOnByApp(on);
Sharad Sangle1d188442017-05-09 16:05:40 +05303513 return;
3514 }
3515
Jean-Michel Trivi011f39e2017-08-19 18:08:06 -07003516 // for logging only
3517 final String eventSource = new StringBuilder("setBluetoothScoOn(").append(on)
3518 .append(") from u/pid:").append(Binder.getCallingUid()).append("/")
3519 .append(Binder.getCallingPid()).toString();
Jean-Michel Trivi58850372018-09-14 16:01:28 -07003520
3521 mDeviceBroker.setBluetoothScoOn(on, eventSource);
Eric Laurent48221252015-09-24 18:41:48 -07003522 }
Johan Gustavsson7337bee2013-03-01 15:53:30 +01003523
Jean-Michel Trivi58850372018-09-14 16:01:28 -07003524 /** @see AudioManager#isBluetoothScoOn()
3525 * Note that it doesn't report internal state, but state seen by apps (which may have
3526 * called setBluetoothScoOn() */
Eric Laurentc42ac9d2009-07-29 08:53:03 -07003527 public boolean isBluetoothScoOn() {
Jean-Michel Trivi58850372018-09-14 16:01:28 -07003528 return mDeviceBroker.isBluetoothScoOnForApp();
Eric Laurentc42ac9d2009-07-29 08:53:03 -07003529 }
3530
Jean-Michel Trivi58850372018-09-14 16:01:28 -07003531 // TODO investigate internal users due to deprecation of SDK API
Sungsoocf09fe62016-09-28 16:21:48 +09003532 /** @see AudioManager#setBluetoothA2dpOn(boolean) */
Eric Laurent78472112012-05-21 08:57:21 -07003533 public void setBluetoothA2dpOn(boolean on) {
Jean-Michel Trivi011f39e2017-08-19 18:08:06 -07003534 // for logging only
3535 final String eventSource = new StringBuilder("setBluetoothA2dpOn(").append(on)
3536 .append(") from u/pid:").append(Binder.getCallingUid()).append("/")
3537 .append(Binder.getCallingPid()).toString();
Jean-Michel Trivi58850372018-09-14 16:01:28 -07003538 mDeviceBroker.setBluetoothA2dpOn_Async(on, eventSource);
Eric Laurent78472112012-05-21 08:57:21 -07003539 }
3540
Sungsoocf09fe62016-09-28 16:21:48 +09003541 /** @see AudioManager#isBluetoothA2dpOn() */
Eric Laurent78472112012-05-21 08:57:21 -07003542 public boolean isBluetoothA2dpOn() {
Jean-Michel Trivi58850372018-09-14 16:01:28 -07003543 return mDeviceBroker.isBluetoothA2dpOn();
Eric Laurent78472112012-05-21 08:57:21 -07003544 }
3545
Eric Laurent3def1ee2010-03-17 23:26:26 -07003546 /** @see AudioManager#startBluetoothSco() */
Eric Laurent83900752014-05-15 15:14:22 -07003547 public void startBluetoothSco(IBinder cb, int targetSdkVersion) {
Jean-Michel Trivi58850372018-09-14 16:01:28 -07003548 final int scoAudioMode =
Eric Laurent83900752014-05-15 15:14:22 -07003549 (targetSdkVersion < Build.VERSION_CODES.JELLY_BEAN_MR2) ?
Jean-Michel Trivi58850372018-09-14 16:01:28 -07003550 BtHelper.SCO_MODE_VIRTUAL_CALL : BtHelper.SCO_MODE_UNDEFINED;
3551 final String eventSource = new StringBuilder("startBluetoothSco()")
3552 .append(") from u/pid:").append(Binder.getCallingUid()).append("/")
3553 .append(Binder.getCallingPid()).toString();
3554 startBluetoothScoInt(cb, scoAudioMode, eventSource);
Eric Laurent83900752014-05-15 15:14:22 -07003555 }
3556
3557 /** @see AudioManager#startBluetoothScoVirtualCall() */
3558 public void startBluetoothScoVirtualCall(IBinder cb) {
Jean-Michel Trivi58850372018-09-14 16:01:28 -07003559 final String eventSource = new StringBuilder("startBluetoothScoVirtualCall()")
3560 .append(") from u/pid:").append(Binder.getCallingUid()).append("/")
3561 .append(Binder.getCallingPid()).toString();
3562 startBluetoothScoInt(cb, BtHelper.SCO_MODE_VIRTUAL_CALL, eventSource);
Eric Laurent83900752014-05-15 15:14:22 -07003563 }
3564
Jean-Michel Trivi58850372018-09-14 16:01:28 -07003565 void startBluetoothScoInt(IBinder cb, int scoAudioMode, @NonNull String eventSource) {
Eric Laurentdc03c612011-04-01 10:59:41 -07003566 if (!checkAudioSettingsPermission("startBluetoothSco()") ||
Eric Laurent4a5eeb92014-05-06 10:49:04 -07003567 !mSystemReady) {
Eric Laurent3def1ee2010-03-17 23:26:26 -07003568 return;
3569 }
Jean-Michel Trivi218da162019-04-05 16:05:04 -07003570 synchronized (mDeviceBroker.mSetModeLock) {
3571 mDeviceBroker.startBluetoothScoForClient_Sync(cb, scoAudioMode, eventSource);
3572 }
Eric Laurent3def1ee2010-03-17 23:26:26 -07003573 }
3574
3575 /** @see AudioManager#stopBluetoothSco() */
3576 public void stopBluetoothSco(IBinder cb){
Eric Laurentdc03c612011-04-01 10:59:41 -07003577 if (!checkAudioSettingsPermission("stopBluetoothSco()") ||
Eric Laurent4a5eeb92014-05-06 10:49:04 -07003578 !mSystemReady) {
Eric Laurent3def1ee2010-03-17 23:26:26 -07003579 return;
3580 }
Jean-Michel Trivi58850372018-09-14 16:01:28 -07003581 final String eventSource = new StringBuilder("stopBluetoothSco()")
3582 .append(") from u/pid:").append(Binder.getCallingUid()).append("/")
3583 .append(Binder.getCallingPid()).toString();
Jean-Michel Trivi218da162019-04-05 16:05:04 -07003584 synchronized (mDeviceBroker.mSetModeLock) {
3585 mDeviceBroker.stopBluetoothScoForClient_Sync(cb, eventSource);
3586 }
Eric Laurent3def1ee2010-03-17 23:26:26 -07003587 }
3588
Eric Laurent78472112012-05-21 08:57:21 -07003589
Jean-Michel Trivi58850372018-09-14 16:01:28 -07003590 /*package*/ ContentResolver getContentResolver() {
3591 return mContentResolver;
Jakub Pawlowskif9570f32018-02-21 17:15:12 -08003592 }
3593
John Spurlock90874332015-03-10 16:00:54 -04003594 private void onCheckMusicActive(String caller) {
hyomin.ohd0446dc2018-10-18 13:58:27 +09003595 synchronized (mSafeMediaVolumeStateLock) {
Eric Laurentd640bd32012-09-28 18:01:48 -07003596 if (mSafeMediaVolumeState == SAFE_MEDIA_VOLUME_INACTIVE) {
Eric Laurentc34dcc12012-09-10 13:51:52 -07003597 int device = getDeviceForStream(AudioSystem.STREAM_MUSIC);
3598
3599 if ((device & mSafeMediaVolumeDevices) != 0) {
3600 sendMsg(mAudioHandler,
3601 MSG_CHECK_MUSIC_ACTIVE,
3602 SENDMSG_REPLACE,
Eric Laurentf1a457d2012-09-20 16:27:23 -07003603 0,
Eric Laurentc34dcc12012-09-10 13:51:52 -07003604 0,
John Spurlock90874332015-03-10 16:00:54 -04003605 caller,
Eric Laurentc34dcc12012-09-10 13:51:52 -07003606 MUSIC_ACTIVE_POLL_PERIOD_MS);
Eric Laurent42b041e2013-03-29 11:36:03 -07003607 int index = mStreamStates[AudioSystem.STREAM_MUSIC].getIndex(device);
Jean-Michel Trivi58850372018-09-14 16:01:28 -07003608 if (AudioSystem.isStreamActive(AudioSystem.STREAM_MUSIC, 0)
3609 && (index > safeMediaVolumeIndex(device))) {
Eric Laurentc34dcc12012-09-10 13:51:52 -07003610 // Approximate cumulative active music time
3611 mMusicActiveMs += MUSIC_ACTIVE_POLL_PERIOD_MS;
3612 if (mMusicActiveMs > UNSAFE_VOLUME_MUSIC_ACTIVE_MS_MAX) {
John Spurlock90874332015-03-10 16:00:54 -04003613 setSafeMediaVolumeEnabled(true, caller);
Eric Laurentc34dcc12012-09-10 13:51:52 -07003614 mMusicActiveMs = 0;
Eric Laurentc34dcc12012-09-10 13:51:52 -07003615 }
John Spurlockaa5ee4d2014-07-25 13:05:12 -04003616 saveMusicActiveMs();
Eric Laurentc34dcc12012-09-10 13:51:52 -07003617 }
3618 }
3619 }
3620 }
3621 }
3622
John Spurlockaa5ee4d2014-07-25 13:05:12 -04003623 private void saveMusicActiveMs() {
3624 mAudioHandler.obtainMessage(MSG_PERSIST_MUSIC_ACTIVE_MS, mMusicActiveMs, 0).sendToTarget();
3625 }
3626
Jean-Michel Trivi58850372018-09-14 16:01:28 -07003627 private int getSafeUsbMediaVolumeIndex() {
Eric Laurenteab40d12017-06-09 12:45:21 -07003628 // determine UI volume index corresponding to the wanted safe gain in dBFS
3629 int min = MIN_STREAM_VOLUME[AudioSystem.STREAM_MUSIC];
3630 int max = MAX_STREAM_VOLUME[AudioSystem.STREAM_MUSIC];
3631
John Muir8b8bddd2018-02-16 14:29:14 -08003632 mSafeUsbMediaVolumeDbfs = mContext.getResources().getInteger(
3633 com.android.internal.R.integer.config_safe_media_volume_usb_mB) / 100.0f;
3634
Jean-Michel Trivi58850372018-09-14 16:01:28 -07003635 while (Math.abs(max - min) > 1) {
Eric Laurenteab40d12017-06-09 12:45:21 -07003636 int index = (max + min) / 2;
3637 float gainDB = AudioSystem.getStreamVolumeDB(
3638 AudioSystem.STREAM_MUSIC, index, AudioSystem.DEVICE_OUT_USB_HEADSET);
Eric Laurentb378a13a2017-07-11 14:08:11 -07003639 if (Float.isNaN(gainDB)) {
Eric Laurenteab40d12017-06-09 12:45:21 -07003640 //keep last min in case of read error
3641 break;
John Muir8b8bddd2018-02-16 14:29:14 -08003642 } else if (gainDB == mSafeUsbMediaVolumeDbfs) {
Eric Laurenteab40d12017-06-09 12:45:21 -07003643 min = index;
3644 break;
John Muir8b8bddd2018-02-16 14:29:14 -08003645 } else if (gainDB < mSafeUsbMediaVolumeDbfs) {
Eric Laurenteab40d12017-06-09 12:45:21 -07003646 min = index;
3647 } else {
3648 max = index;
3649 }
3650 }
3651 return min * 10;
3652 }
3653
John Spurlock90874332015-03-10 16:00:54 -04003654 private void onConfigureSafeVolume(boolean force, String caller) {
hyomin.ohd0446dc2018-10-18 13:58:27 +09003655 synchronized (mSafeMediaVolumeStateLock) {
Eric Laurentd640bd32012-09-28 18:01:48 -07003656 int mcc = mContext.getResources().getConfiguration().mcc;
3657 if ((mMcc != mcc) || ((mMcc == 0) && force)) {
3658 mSafeMediaVolumeIndex = mContext.getResources().getInteger(
3659 com.android.internal.R.integer.config_safe_media_volume_index) * 10;
Eric Laurenteab40d12017-06-09 12:45:21 -07003660
3661 mSafeUsbMediaVolumeIndex = getSafeUsbMediaVolumeIndex();
3662
John Spurlock35134602014-07-24 18:10:48 -04003663 boolean safeMediaVolumeEnabled =
3664 SystemProperties.getBoolean("audio.safemedia.force", false)
3665 || mContext.getResources().getBoolean(
3666 com.android.internal.R.bool.config_safe_media_volume_enabled);
Eric Laurent05274f32012-11-29 12:48:18 -08003667
Ricardo Garcia3a30a762015-06-23 15:54:45 -07003668 boolean safeMediaVolumeBypass =
3669 SystemProperties.getBoolean("audio.safemedia.bypass", false);
3670
Eric Laurent05274f32012-11-29 12:48:18 -08003671 // The persisted state is either "disabled" or "active": this is the state applied
3672 // next time we boot and cannot be "inactive"
3673 int persistedState;
Ricardo Garcia3a30a762015-06-23 15:54:45 -07003674 if (safeMediaVolumeEnabled && !safeMediaVolumeBypass) {
Eric Laurent05274f32012-11-29 12:48:18 -08003675 persistedState = SAFE_MEDIA_VOLUME_ACTIVE;
3676 // The state can already be "inactive" here if the user has forced it before
3677 // the 30 seconds timeout for forced configuration. In this case we don't reset
3678 // it to "active".
3679 if (mSafeMediaVolumeState != SAFE_MEDIA_VOLUME_INACTIVE) {
John Spurlockaa5ee4d2014-07-25 13:05:12 -04003680 if (mMusicActiveMs == 0) {
3681 mSafeMediaVolumeState = SAFE_MEDIA_VOLUME_ACTIVE;
John Spurlock90874332015-03-10 16:00:54 -04003682 enforceSafeMediaVolume(caller);
John Spurlockaa5ee4d2014-07-25 13:05:12 -04003683 } else {
3684 // We have existing playback time recorded, already confirmed.
3685 mSafeMediaVolumeState = SAFE_MEDIA_VOLUME_INACTIVE;
3686 }
Eric Laurent05274f32012-11-29 12:48:18 -08003687 }
Eric Laurentd640bd32012-09-28 18:01:48 -07003688 } else {
Eric Laurent05274f32012-11-29 12:48:18 -08003689 persistedState = SAFE_MEDIA_VOLUME_DISABLED;
Eric Laurentd640bd32012-09-28 18:01:48 -07003690 mSafeMediaVolumeState = SAFE_MEDIA_VOLUME_DISABLED;
3691 }
3692 mMcc = mcc;
Eric Laurent05274f32012-11-29 12:48:18 -08003693 sendMsg(mAudioHandler,
3694 MSG_PERSIST_SAFE_VOLUME_STATE,
3695 SENDMSG_QUEUE,
3696 persistedState,
3697 0,
3698 null,
3699 0);
Eric Laurentd640bd32012-09-28 18:01:48 -07003700 }
3701 }
3702 }
3703
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003704 ///////////////////////////////////////////////////////////////////////////
3705 // Internal methods
3706 ///////////////////////////////////////////////////////////////////////////
3707
3708 /**
3709 * Checks if the adjustment should change ringer mode instead of just
3710 * adjusting volume. If so, this will set the proper ringer mode and volume
3711 * indices on the stream states.
3712 */
Julia Reynoldsed783792016-04-08 15:27:35 -04003713 private int checkForRingerModeChange(int oldIndex, int direction, int step, boolean isMuted,
3714 String caller, int flags) {
John Spurlocka11b4af2014-06-01 11:52:23 -04003715 int result = FLAG_ADJUST_VOLUME;
Zak Cohen47798292017-11-30 12:34:20 -08003716 if (isPlatformTelevision() || mIsSingleVolume) {
Hank Freund21003f62015-12-08 09:05:46 -08003717 return result;
3718 }
3719
John Spurlock661f2cf2014-11-17 10:29:10 -05003720 int ringerMode = getRingerModeInternal();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003721
Eric Laurentbffc3d12012-05-07 17:43:49 -07003722 switch (ringerMode) {
3723 case RINGER_MODE_NORMAL:
3724 if (direction == AudioManager.ADJUST_LOWER) {
3725 if (mHasVibrator) {
Eric Laurent24482012012-05-10 09:41:17 -07003726 // "step" is the delta in internal index units corresponding to a
3727 // change of 1 in UI index units.
3728 // Because of rounding when rescaling from one stream index range to its alias
3729 // index range, we cannot simply test oldIndex == step:
3730 // (step <= oldIndex < 2 * step) is equivalent to: (old UI index == 1)
3731 if (step <= oldIndex && oldIndex < 2 * step) {
Eric Laurentbffc3d12012-05-07 17:43:49 -07003732 ringerMode = RINGER_MODE_VIBRATE;
John Spurlock07e72432015-03-13 11:46:52 -04003733 mLoweredFromNormalToVibrateTime = SystemClock.uptimeMillis();
Eric Laurentbffc3d12012-05-07 17:43:49 -07003734 }
3735 } else {
John Spurlockd9c75db2015-04-28 11:19:13 -04003736 if (oldIndex == step && mVolumePolicy.volumeDownToEnterSilent) {
Eric Laurentbffc3d12012-05-07 17:43:49 -07003737 ringerMode = RINGER_MODE_SILENT;
3738 }
Eric Laurent3d4c06f2011-08-15 19:58:28 -07003739 }
Muyuan Li1ed6df62016-06-18 11:16:52 -07003740 } else if (mIsSingleVolume && (direction == AudioManager.ADJUST_TOGGLE_MUTE
John Spurlocka48d7792015-03-03 17:35:57 -05003741 || direction == AudioManager.ADJUST_MUTE)) {
RoboErik5452e252015-02-06 15:33:53 -08003742 if (mHasVibrator) {
3743 ringerMode = RINGER_MODE_VIBRATE;
3744 } else {
3745 ringerMode = RINGER_MODE_SILENT;
3746 }
3747 // Setting the ringer mode will toggle mute
3748 result &= ~FLAG_ADJUST_VOLUME;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003749 }
Eric Laurentbffc3d12012-05-07 17:43:49 -07003750 break;
3751 case RINGER_MODE_VIBRATE:
3752 if (!mHasVibrator) {
3753 Log.e(TAG, "checkForRingerModeChange() current ringer mode is vibrate" +
3754 "but no vibrator is present");
3755 break;
3756 }
Amith Yamasanic696a532011-10-28 17:02:37 -07003757 if ((direction == AudioManager.ADJUST_LOWER)) {
RoboErik5452e252015-02-06 15:33:53 -08003758 // This is the case we were muted with the volume turned up
Muyuan Li1ed6df62016-06-18 11:16:52 -07003759 if (mIsSingleVolume && oldIndex >= 2 * step && isMuted) {
RoboErik5452e252015-02-06 15:33:53 -08003760 ringerMode = RINGER_MODE_NORMAL;
3761 } else if (mPrevVolDirection != AudioManager.ADJUST_LOWER) {
John Spurlocka48d7792015-03-03 17:35:57 -05003762 if (mVolumePolicy.volumeDownToEnterSilent) {
John Spurlock07e72432015-03-13 11:46:52 -04003763 final long diff = SystemClock.uptimeMillis()
3764 - mLoweredFromNormalToVibrateTime;
John Spurlockd9c75db2015-04-28 11:19:13 -04003765 if (diff > mVolumePolicy.vibrateToSilentDebounce
3766 && mRingerModeDelegate.canVolumeDownEnterSilent()) {
John Spurlock07e72432015-03-13 11:46:52 -04003767 ringerMode = RINGER_MODE_SILENT;
3768 }
John Spurlock795a5142014-12-08 14:09:35 -05003769 } else {
3770 result |= AudioManager.FLAG_SHOW_VIBRATE_HINT;
3771 }
Amith Yamasanic696a532011-10-28 17:02:37 -07003772 }
RoboErik5452e252015-02-06 15:33:53 -08003773 } else if (direction == AudioManager.ADJUST_RAISE
3774 || direction == AudioManager.ADJUST_TOGGLE_MUTE
3775 || direction == AudioManager.ADJUST_UNMUTE) {
Eric Laurentbffc3d12012-05-07 17:43:49 -07003776 ringerMode = RINGER_MODE_NORMAL;
Amith Yamasanic696a532011-10-28 17:02:37 -07003777 }
John Spurlocka11b4af2014-06-01 11:52:23 -04003778 result &= ~FLAG_ADJUST_VOLUME;
Eric Laurentbffc3d12012-05-07 17:43:49 -07003779 break;
3780 case RINGER_MODE_SILENT:
Muyuan Li1ed6df62016-06-18 11:16:52 -07003781 if (mIsSingleVolume && direction == AudioManager.ADJUST_LOWER && oldIndex >= 2 * step && isMuted) {
RoboErik5452e252015-02-06 15:33:53 -08003782 // This is the case we were muted with the volume turned up
3783 ringerMode = RINGER_MODE_NORMAL;
3784 } else if (direction == AudioManager.ADJUST_RAISE
3785 || direction == AudioManager.ADJUST_TOGGLE_MUTE
3786 || direction == AudioManager.ADJUST_UNMUTE) {
John Spurlocka48d7792015-03-03 17:35:57 -05003787 if (!mVolumePolicy.volumeUpToExitSilent) {
John Spurlocka11b4af2014-06-01 11:52:23 -04003788 result |= AudioManager.FLAG_SHOW_SILENT_HINT;
Eric Laurentbffc3d12012-05-07 17:43:49 -07003789 } else {
RoboErik5452e252015-02-06 15:33:53 -08003790 if (mHasVibrator && direction == AudioManager.ADJUST_RAISE) {
John Spurlocka11b4af2014-06-01 11:52:23 -04003791 ringerMode = RINGER_MODE_VIBRATE;
3792 } else {
RoboErik5452e252015-02-06 15:33:53 -08003793 // If we don't have a vibrator or they were toggling mute
3794 // go straight back to normal.
John Spurlocka11b4af2014-06-01 11:52:23 -04003795 ringerMode = RINGER_MODE_NORMAL;
3796 }
Eric Laurentbffc3d12012-05-07 17:43:49 -07003797 }
Daniel Sandler6329bf72010-02-26 15:17:44 -05003798 }
John Spurlocka11b4af2014-06-01 11:52:23 -04003799 result &= ~FLAG_ADJUST_VOLUME;
Eric Laurentbffc3d12012-05-07 17:43:49 -07003800 break;
3801 default:
3802 Log.e(TAG, "checkForRingerModeChange() wrong ringer mode: "+ringerMode);
3803 break;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003804 }
3805
Julia Reynoldsed783792016-04-08 15:27:35 -04003806 if (isAndroidNPlus(caller) && wouldToggleZenMode(ringerMode)
3807 && !mNm.isNotificationPolicyAccessGrantedForPackage(caller)
3808 && (flags & AudioManager.FLAG_FROM_KEY) == 0) {
3809 throw new SecurityException("Not allowed to change Do Not Disturb state");
3810 }
3811
John Spurlock661f2cf2014-11-17 10:29:10 -05003812 setRingerMode(ringerMode, TAG + ".checkForRingerModeChange", false /*external*/);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003813
Eric Laurent25101b02011-02-02 09:33:30 -08003814 mPrevVolDirection = direction;
3815
John Spurlocka11b4af2014-06-01 11:52:23 -04003816 return result;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003817 }
3818
John Spurlock3346a802014-05-20 16:25:37 -04003819 @Override
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003820 public boolean isStreamAffectedByRingerMode(int streamType) {
Eric Laurent9bcf4012009-06-12 06:09:28 -07003821 return (mRingerModeAffectedStreams & (1 << streamType)) != 0;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003822 }
3823
Beverlyd6964762018-02-16 14:07:03 -05003824 private boolean shouldZenMuteStream(int streamType) {
3825 if (mNm.getZenMode() != Settings.Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS) {
3826 return false;
3827 }
3828
Beverlyff2df9b2018-10-10 16:54:10 -04003829 NotificationManager.Policy zenPolicy = mNm.getConsolidatedNotificationPolicy();
Beverlyd6964762018-02-16 14:07:03 -05003830 final boolean muteAlarms = (zenPolicy.priorityCategories
3831 & NotificationManager.Policy.PRIORITY_CATEGORY_ALARMS) == 0;
3832 final boolean muteMedia = (zenPolicy.priorityCategories
3833 & NotificationManager.Policy.PRIORITY_CATEGORY_MEDIA) == 0;
3834 final boolean muteSystem = (zenPolicy.priorityCategories
3835 & NotificationManager.Policy.PRIORITY_CATEGORY_SYSTEM) == 0;
3836 final boolean muteNotificationAndRing = ZenModeConfig
Beverlyff2df9b2018-10-10 16:54:10 -04003837 .areAllPriorityOnlyNotificationZenSoundsMuted(
3838 mNm.getConsolidatedNotificationPolicy());
Beverlyd6964762018-02-16 14:07:03 -05003839 return muteAlarms && isAlarm(streamType)
3840 || muteMedia && isMedia(streamType)
3841 || muteSystem && isSystem(streamType)
3842 || muteNotificationAndRing && isNotificationOrRinger(streamType);
3843 }
3844
3845 private boolean isStreamMutedByRingerOrZenMode(int streamType) {
3846 return (mRingerAndZenModeMutedStreams & (1 << streamType)) != 0;
3847 }
3848
3849 /**
3850 * DND total silence: media and alarms streams are tied to the muted ringer
3851 * {@link ZenModeHelper.RingerModeDelegate#getRingerModeAffectedStreams(int)}
3852 * DND alarms only: notification, ringer + system muted (by default tied to muted ringer mode)
3853 * DND priority only: alarms, media, system streams can be muted separate from ringer based on
3854 * zenPolicy (this method determines which streams)
3855 * @return true if changed, else false
3856 */
3857 private boolean updateZenModeAffectedStreams() {
3858 int zenModeAffectedStreams = 0;
3859 if (mSystemReady && mNm.getZenMode() == Settings.Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS) {
Beverlyff2df9b2018-10-10 16:54:10 -04003860 NotificationManager.Policy zenPolicy = mNm.getConsolidatedNotificationPolicy();
Beverlyd6964762018-02-16 14:07:03 -05003861 if ((zenPolicy.priorityCategories
3862 & NotificationManager.Policy.PRIORITY_CATEGORY_ALARMS) == 0) {
3863 zenModeAffectedStreams |= 1 << AudioManager.STREAM_ALARM;
3864 }
3865
3866 if ((zenPolicy.priorityCategories
3867 & NotificationManager.Policy.PRIORITY_CATEGORY_MEDIA) == 0) {
3868 zenModeAffectedStreams |= 1 << AudioManager.STREAM_MUSIC;
3869 }
3870
3871 if ((zenPolicy.priorityCategories
3872 & NotificationManager.Policy.PRIORITY_CATEGORY_SYSTEM) == 0) {
3873 zenModeAffectedStreams |= 1 << AudioManager.STREAM_SYSTEM;
3874 }
3875 }
3876
3877 if (mZenModeAffectedStreams != zenModeAffectedStreams) {
3878 mZenModeAffectedStreams = zenModeAffectedStreams;
3879 return true;
3880 }
3881
3882 return false;
Eric Laurent5b4e6542010-03-19 20:02:21 -07003883 }
3884
Jean-Michel Trivi8719a1d2017-11-06 11:52:51 -08003885 @GuardedBy("mSettingsLock")
Beverlyd6964762018-02-16 14:07:03 -05003886 private boolean updateRingerAndZenModeAffectedStreams() {
3887 boolean updatedZenModeAffectedStreams = updateZenModeAffectedStreams();
John Spurlock50ced3f2015-05-11 16:00:09 -04003888 int ringerModeAffectedStreams = Settings.System.getIntForUser(mContentResolver,
Eric Laurent24e0d9b2013-10-03 18:15:07 -07003889 Settings.System.MODE_RINGER_STREAMS_AFFECTED,
3890 ((1 << AudioSystem.STREAM_RING)|(1 << AudioSystem.STREAM_NOTIFICATION)|
3891 (1 << AudioSystem.STREAM_SYSTEM)|(1 << AudioSystem.STREAM_SYSTEM_ENFORCED)),
3892 UserHandle.USER_CURRENT);
3893
Muyuan Li1ed6df62016-06-18 11:16:52 -07003894 if (mIsSingleVolume) {
John Spurlock50ced3f2015-05-11 16:00:09 -04003895 ringerModeAffectedStreams = 0;
3896 } else if (mRingerModeDelegate != null) {
3897 ringerModeAffectedStreams = mRingerModeDelegate
3898 .getRingerModeAffectedStreams(ringerModeAffectedStreams);
Eric Laurent24e0d9b2013-10-03 18:15:07 -07003899 }
Jean-Michel Trivi8719a1d2017-11-06 11:52:51 -08003900 if (mCameraSoundForced) {
3901 ringerModeAffectedStreams &= ~(1 << AudioSystem.STREAM_SYSTEM_ENFORCED);
3902 } else {
3903 ringerModeAffectedStreams |= (1 << AudioSystem.STREAM_SYSTEM_ENFORCED);
Eric Laurent24e0d9b2013-10-03 18:15:07 -07003904 }
3905 if (mStreamVolumeAlias[AudioSystem.STREAM_DTMF] == AudioSystem.STREAM_RING) {
3906 ringerModeAffectedStreams |= (1 << AudioSystem.STREAM_DTMF);
3907 } else {
3908 ringerModeAffectedStreams &= ~(1 << AudioSystem.STREAM_DTMF);
3909 }
3910
3911 if (ringerModeAffectedStreams != mRingerModeAffectedStreams) {
3912 Settings.System.putIntForUser(mContentResolver,
3913 Settings.System.MODE_RINGER_STREAMS_AFFECTED,
3914 ringerModeAffectedStreams,
3915 UserHandle.USER_CURRENT);
3916 mRingerModeAffectedStreams = ringerModeAffectedStreams;
3917 return true;
3918 }
Beverlyd6964762018-02-16 14:07:03 -05003919 return updatedZenModeAffectedStreams;
Eric Laurent24e0d9b2013-10-03 18:15:07 -07003920 }
3921
John Spurlocka9dfbe8b2015-02-17 11:01:51 -05003922 @Override
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003923 public boolean isStreamAffectedByMute(int streamType) {
3924 return (mMuteAffectedStreams & (1 << streamType)) != 0;
3925 }
3926
3927 private void ensureValidDirection(int direction) {
RoboErik4197cb62015-01-21 15:45:32 -08003928 switch (direction) {
3929 case AudioManager.ADJUST_LOWER:
3930 case AudioManager.ADJUST_RAISE:
3931 case AudioManager.ADJUST_SAME:
3932 case AudioManager.ADJUST_MUTE:
3933 case AudioManager.ADJUST_UNMUTE:
3934 case AudioManager.ADJUST_TOGGLE_MUTE:
3935 break;
3936 default:
3937 throw new IllegalArgumentException("Bad direction " + direction);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003938 }
3939 }
3940
3941 private void ensureValidStreamType(int streamType) {
3942 if (streamType < 0 || streamType >= mStreamStates.length) {
3943 throw new IllegalArgumentException("Bad stream type " + streamType);
3944 }
3945 }
3946
RoboErik4197cb62015-01-21 15:45:32 -08003947 private boolean isMuteAdjust(int adjust) {
3948 return adjust == AudioManager.ADJUST_MUTE || adjust == AudioManager.ADJUST_UNMUTE
3949 || adjust == AudioManager.ADJUST_TOGGLE_MUTE;
3950 }
3951
Jean-Michel Trivi58850372018-09-14 16:01:28 -07003952 /*package*/ boolean isInCommunication() {
Nancy Chen0eb1e402014-08-21 22:52:29 -07003953 boolean IsInCall = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003954
Tyler Gunnef9f6f92014-09-12 22:16:17 -07003955 TelecomManager telecomManager =
3956 (TelecomManager) mContext.getSystemService(Context.TELECOM_SERVICE);
Eric Laurent38edfda2014-12-18 17:38:04 -08003957
3958 final long ident = Binder.clearCallingIdentity();
Tyler Gunnef9f6f92014-09-12 22:16:17 -07003959 IsInCall = telecomManager.isInCall();
Eric Laurent38edfda2014-12-18 17:38:04 -08003960 Binder.restoreCallingIdentity(ident);
Santos Cordon9eb45932014-06-27 12:28:43 -07003961
Eric Laurentda1af762017-12-15 16:54:35 -08003962 return (IsInCall || getMode() == AudioManager.MODE_IN_COMMUNICATION ||
3963 getMode() == AudioManager.MODE_IN_CALL);
Eric Laurent6d517662012-04-23 18:42:39 -07003964 }
Eric Laurent25101b02011-02-02 09:33:30 -08003965
Jean-Michel Trivifca1e602013-10-10 18:12:59 -07003966 /**
3967 * For code clarity for getActiveStreamType(int)
Julia Reynoldsd9e96e22017-11-07 10:33:08 -05003968 * @param delay_ms max time since last stream activity to consider
3969 * @return true if stream is active in streams handled by AudioFlinger now or
Jean-Michel Trivifca1e602013-10-10 18:12:59 -07003970 * in the last "delay_ms" ms.
3971 */
Julia Reynoldsd9e96e22017-11-07 10:33:08 -05003972 private boolean wasStreamActiveRecently(int stream, int delay_ms) {
3973 return AudioSystem.isStreamActive(stream, delay_ms)
3974 || AudioSystem.isStreamActiveRemotely(stream, delay_ms);
Jean-Michel Trivifca1e602013-10-10 18:12:59 -07003975 }
3976
Eric Laurent6d517662012-04-23 18:42:39 -07003977 private int getActiveStreamType(int suggestedStreamType) {
Muyuan Li1ed6df62016-06-18 11:16:52 -07003978 if (mIsSingleVolume
3979 && suggestedStreamType == AudioManager.USE_DEFAULT_STREAM_TYPE) {
3980 return AudioSystem.STREAM_MUSIC;
3981 }
3982
Eric Laurent212532b2014-07-21 15:43:18 -07003983 switch (mPlatformType) {
John Spurlock61560172015-02-06 19:46:04 -05003984 case AudioSystem.PLATFORM_VOICE:
Eric Laurent6d517662012-04-23 18:42:39 -07003985 if (isInCommunication()) {
Eric Laurent25101b02011-02-02 09:33:30 -08003986 if (AudioSystem.getForceUse(AudioSystem.FOR_COMMUNICATION)
3987 == AudioSystem.FORCE_BT_SCO) {
3988 // Log.v(TAG, "getActiveStreamType: Forcing STREAM_BLUETOOTH_SCO...");
3989 return AudioSystem.STREAM_BLUETOOTH_SCO;
3990 } else {
3991 // Log.v(TAG, "getActiveStreamType: Forcing STREAM_VOICE_CALL...");
3992 return AudioSystem.STREAM_VOICE_CALL;
3993 }
Eric Laurent25101b02011-02-02 09:33:30 -08003994 } else if (suggestedStreamType == AudioManager.USE_DEFAULT_STREAM_TYPE) {
Julia Reynoldsd9e96e22017-11-07 10:33:08 -05003995 if (wasStreamActiveRecently(AudioSystem.STREAM_RING, sStreamOverrideDelayMs)) {
Jean-Michel Trivi3114ce32012-06-11 15:03:52 -07003996 if (DEBUG_VOL)
Julia Reynoldsd9e96e22017-11-07 10:33:08 -05003997 Log.v(TAG, "getActiveStreamType: Forcing STREAM_RING stream active");
3998 return AudioSystem.STREAM_RING;
3999 } else if (wasStreamActiveRecently(
4000 AudioSystem.STREAM_NOTIFICATION, sStreamOverrideDelayMs)) {
4001 if (DEBUG_VOL)
4002 Log.v(TAG, "getActiveStreamType: Forcing STREAM_NOTIFICATION stream active");
4003 return AudioSystem.STREAM_NOTIFICATION;
4004 } else {
Julia Reynoldseb0ce472018-05-04 15:34:55 -04004005 if (DEBUG_VOL) {
4006 Log.v(TAG, "getActiveStreamType: Forcing DEFAULT_VOL_STREAM_NO_PLAYBACK("
4007 + DEFAULT_VOL_STREAM_NO_PLAYBACK + ") b/c default");
4008 }
4009 return DEFAULT_VOL_STREAM_NO_PLAYBACK;
Jean-Michel Trivi3114ce32012-06-11 15:03:52 -07004010 }
Julia Reynoldsd9e96e22017-11-07 10:33:08 -05004011 } else if (
4012 wasStreamActiveRecently(AudioSystem.STREAM_NOTIFICATION, sStreamOverrideDelayMs)) {
Jean-Michel Trivi3114ce32012-06-11 15:03:52 -07004013 if (DEBUG_VOL)
Julia Reynoldsd9e96e22017-11-07 10:33:08 -05004014 Log.v(TAG, "getActiveStreamType: Forcing STREAM_NOTIFICATION stream active");
4015 return AudioSystem.STREAM_NOTIFICATION;
4016 } else if (wasStreamActiveRecently(AudioSystem.STREAM_RING, sStreamOverrideDelayMs)) {
4017 if (DEBUG_VOL)
4018 Log.v(TAG, "getActiveStreamType: Forcing STREAM_RING stream active");
4019 return AudioSystem.STREAM_RING;
Eric Laurent25101b02011-02-02 09:33:30 -08004020 }
Eric Laurent212532b2014-07-21 15:43:18 -07004021 default:
Eric Laurent6d517662012-04-23 18:42:39 -07004022 if (isInCommunication()) {
Eric Laurent25101b02011-02-02 09:33:30 -08004023 if (AudioSystem.getForceUse(AudioSystem.FOR_COMMUNICATION)
4024 == AudioSystem.FORCE_BT_SCO) {
Jean-Michel Trivi3114ce32012-06-11 15:03:52 -07004025 if (DEBUG_VOL) Log.v(TAG, "getActiveStreamType: Forcing STREAM_BLUETOOTH_SCO");
Eric Laurent25101b02011-02-02 09:33:30 -08004026 return AudioSystem.STREAM_BLUETOOTH_SCO;
4027 } else {
Jean-Michel Trivi3114ce32012-06-11 15:03:52 -07004028 if (DEBUG_VOL) Log.v(TAG, "getActiveStreamType: Forcing STREAM_VOICE_CALL");
Eric Laurent25101b02011-02-02 09:33:30 -08004029 return AudioSystem.STREAM_VOICE_CALL;
4030 }
Julia Reynoldsd9e96e22017-11-07 10:33:08 -05004031 } else if (AudioSystem.isStreamActive(
4032 AudioSystem.STREAM_NOTIFICATION, sStreamOverrideDelayMs)) {
Jean-Michel Trivi3114ce32012-06-11 15:03:52 -07004033 if (DEBUG_VOL) Log.v(TAG, "getActiveStreamType: Forcing STREAM_NOTIFICATION");
Eric Laurent25101b02011-02-02 09:33:30 -08004034 return AudioSystem.STREAM_NOTIFICATION;
Julia Reynoldsd9e96e22017-11-07 10:33:08 -05004035 } else if (AudioSystem.isStreamActive(
4036 AudioSystem.STREAM_RING, sStreamOverrideDelayMs)) {
4037 if (DEBUG_VOL) Log.v(TAG, "getActiveStreamType: Forcing STREAM_RING");
4038 return AudioSystem.STREAM_RING;
Jean-Michel Trivi3114ce32012-06-11 15:03:52 -07004039 } else if (suggestedStreamType == AudioManager.USE_DEFAULT_STREAM_TYPE) {
Julia Reynoldsd9e96e22017-11-07 10:33:08 -05004040 if (AudioSystem.isStreamActive(
4041 AudioSystem.STREAM_NOTIFICATION, sStreamOverrideDelayMs)) {
4042 if (DEBUG_VOL) Log.v(TAG, "getActiveStreamType: Forcing STREAM_NOTIFICATION");
John Spurlockeb1d88d2014-07-19 14:49:19 -04004043 return AudioSystem.STREAM_NOTIFICATION;
Julia Reynoldsd9e96e22017-11-07 10:33:08 -05004044 } else if (AudioSystem.isStreamActive(
4045 AudioSystem.STREAM_RING, sStreamOverrideDelayMs)) {
4046 if (DEBUG_VOL) Log.v(TAG, "getActiveStreamType: Forcing STREAM_RING");
4047 return AudioSystem.STREAM_RING;
4048 } else {
Julia Reynoldseb0ce472018-05-04 15:34:55 -04004049 if (DEBUG_VOL) {
4050 Log.v(TAG, "getActiveStreamType: Forcing DEFAULT_VOL_STREAM_NO_PLAYBACK("
4051 + DEFAULT_VOL_STREAM_NO_PLAYBACK + ") b/c default");
4052 }
4053 return DEFAULT_VOL_STREAM_NO_PLAYBACK;
Jean-Michel Trivi3114ce32012-06-11 15:03:52 -07004054 }
Joe Onoratoc7fcba42011-01-05 16:53:11 -08004055 }
Eric Laurent212532b2014-07-21 15:43:18 -07004056 break;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004057 }
Eric Laurent212532b2014-07-21 15:43:18 -07004058 if (DEBUG_VOL) Log.v(TAG, "getActiveStreamType: Returning suggested type "
4059 + suggestedStreamType);
4060 return suggestedStreamType;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004061 }
4062
John Spurlockbcc10872014-11-28 15:29:21 -05004063 private void broadcastRingerMode(String action, int ringerMode) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004064 // Send sticky broadcast
John Spurlockbcc10872014-11-28 15:29:21 -05004065 Intent broadcast = new Intent(action);
Glenn Kastenba195eb2011-12-13 09:30:40 -08004066 broadcast.putExtra(AudioManager.EXTRA_RINGER_MODE, ringerMode);
Dianne Hackborn1c633fc2009-12-08 19:45:14 -08004067 broadcast.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT
4068 | Intent.FLAG_RECEIVER_REPLACE_PENDING);
Dianne Hackborn5ac72a22012-08-29 18:32:08 -07004069 sendStickyBroadcastToAll(broadcast);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004070 }
4071
4072 private void broadcastVibrateSetting(int vibrateType) {
4073 // Send broadcast
Sudheer Shankafc46e9b2016-10-21 17:55:27 -07004074 if (mActivityManagerInternal.isSystemReady()) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004075 Intent broadcast = new Intent(AudioManager.VIBRATE_SETTING_CHANGED_ACTION);
4076 broadcast.putExtra(AudioManager.EXTRA_VIBRATE_TYPE, vibrateType);
4077 broadcast.putExtra(AudioManager.EXTRA_VIBRATE_SETTING, getVibrateSetting(vibrateType));
Dianne Hackborn5ac72a22012-08-29 18:32:08 -07004078 sendBroadcastToAll(broadcast);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004079 }
4080 }
4081
4082 // Message helper methods
Jean-Michel Trivi2d8dab52012-05-30 18:13:59 -07004083 /**
4084 * Queue a message on the given handler's message queue, after acquiring the service wake lock.
4085 * Note that the wake lock needs to be released after the message has been handled.
4086 */
4087 private void queueMsgUnderWakeLock(Handler handler, int msg,
4088 int arg1, int arg2, Object obj, int delay) {
Eric Laurenta4dfbdc52013-10-01 11:53:51 -07004089 final long ident = Binder.clearCallingIdentity();
4090 // Always acquire the wake lock as AudioService because it is released by the
4091 // message handler.
Jean-Michel Trivifa9a6982013-06-27 16:22:58 -07004092 mAudioEventWakeLock.acquire();
Eric Laurenta4dfbdc52013-10-01 11:53:51 -07004093 Binder.restoreCallingIdentity(ident);
Jean-Michel Trivi2d8dab52012-05-30 18:13:59 -07004094 sendMsg(handler, msg, SENDMSG_QUEUE, arg1, arg2, obj, delay);
4095 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004096
Eric Laurentafbb0472011-12-15 09:04:23 -08004097 private static void sendMsg(Handler handler, int msg,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004098 int existingMsgPolicy, int arg1, int arg2, Object obj, int delay) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004099 if (existingMsgPolicy == SENDMSG_REPLACE) {
4100 handler.removeMessages(msg);
4101 } else if (existingMsgPolicy == SENDMSG_NOOP && handler.hasMessages(msg)) {
4102 return;
4103 }
Eric Laurent3c4636c2018-06-13 19:36:42 -07004104
Jean-Michel Trivi58850372018-09-14 16:01:28 -07004105 final long time = SystemClock.uptimeMillis() + delay;
4106 handler.sendMessageAtTime(handler.obtainMessage(msg, arg1, arg2, obj), time);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004107 }
4108
4109 boolean checkAudioSettingsPermission(String method) {
Jean-Michel Triviccd654e2014-09-03 17:48:47 -07004110 if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.MODIFY_AUDIO_SETTINGS)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004111 == PackageManager.PERMISSION_GRANTED) {
4112 return true;
4113 }
4114 String msg = "Audio Settings Permission Denial: " + method + " from pid="
4115 + Binder.getCallingPid()
4116 + ", uid=" + Binder.getCallingUid();
4117 Log.w(TAG, msg);
4118 return false;
4119 }
4120
Jean-Michel Trivi58850372018-09-14 16:01:28 -07004121 /*package*/ int getDeviceForStream(int stream) {
John Spurlock8a52c442015-03-26 14:23:58 -04004122 int device = getDevicesForStream(stream);
Eric Laurent9bc8358d2011-11-18 16:43:31 -08004123 if ((device & (device - 1)) != 0) {
4124 // Multiple device selection is either:
4125 // - speaker + one other device: give priority to speaker in this case.
4126 // - one A2DP device + another device: happens with duplicated output. In this case
4127 // retain the device on the A2DP output as the other must not correspond to an active
4128 // selection if not the speaker.
Jungshik Jangc9ff9682014-09-15 17:41:06 +09004129 // - HDMI-CEC system audio mode only output: give priority to available item in order.
Eric Laurent9bc8358d2011-11-18 16:43:31 -08004130 if ((device & AudioSystem.DEVICE_OUT_SPEAKER) != 0) {
4131 device = AudioSystem.DEVICE_OUT_SPEAKER;
Jungshik Jangc9ff9682014-09-15 17:41:06 +09004132 } else if ((device & AudioSystem.DEVICE_OUT_HDMI_ARC) != 0) {
4133 device = AudioSystem.DEVICE_OUT_HDMI_ARC;
4134 } else if ((device & AudioSystem.DEVICE_OUT_SPDIF) != 0) {
4135 device = AudioSystem.DEVICE_OUT_SPDIF;
4136 } else if ((device & AudioSystem.DEVICE_OUT_AUX_LINE) != 0) {
4137 device = AudioSystem.DEVICE_OUT_AUX_LINE;
Eric Laurent9bc8358d2011-11-18 16:43:31 -08004138 } else {
4139 device &= AudioSystem.DEVICE_OUT_ALL_A2DP;
4140 }
4141 }
4142 return device;
4143 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004144
John Spurlock8a52c442015-03-26 14:23:58 -04004145 private int getDevicesForStream(int stream) {
4146 return getDevicesForStream(stream, true /*checkOthers*/);
4147 }
4148
4149 private int getDevicesForStream(int stream, boolean checkOthers) {
4150 ensureValidStreamType(stream);
4151 synchronized (VolumeStreamState.class) {
4152 return mStreamStates[stream].observeDevicesForStream_syncVSS(checkOthers);
4153 }
4154 }
4155
4156 private void observeDevicesForStreams(int skipStream) {
4157 synchronized (VolumeStreamState.class) {
4158 for (int stream = 0; stream < mStreamStates.length; stream++) {
4159 if (stream != skipStream) {
4160 mStreamStates[stream].observeDevicesForStream_syncVSS(false /*checkOthers*/);
4161 }
4162 }
4163 }
4164 }
4165
Jean-Michel Trivi5bbcd442019-04-18 12:07:34 -07004166 /*package*/ void postObserveDevicesForAllStreams() {
4167 sendMsg(mAudioHandler,
4168 MSG_OBSERVE_DEVICES_FOR_ALL_STREAMS,
4169 SENDMSG_QUEUE, 0 /*arg1*/, 0 /*arg2*/, null /*obj*/,
4170 0 /*delay*/);
4171 }
Jean-Michel Trivi58850372018-09-14 16:01:28 -07004172
Jean-Michel Trivi5bbcd442019-04-18 12:07:34 -07004173 private void onObserveDevicesForAllStreams() {
Jean-Michel Trivi58850372018-09-14 16:01:28 -07004174 observeDevicesForStreams(-1);
Aniket Kumar Lata9fbc2052019-01-11 02:02:33 -08004175 }
4176
Jean-Michel Trivi58850372018-09-14 16:01:28 -07004177 /*package*/ static final int CONNECTION_STATE_DISCONNECTED = 0;
4178 /*package*/ static final int CONNECTION_STATE_CONNECTED = 1;
4179 /**
4180 * The states that can be used with AudioService.setWiredDeviceConnectionState()
4181 * Attention: those values differ from those in BluetoothProfile, follow annotations to
4182 * distinguish between @ConnectionState and @BtProfileConnectionState
Paul McLean10804eb2015-01-28 11:16:35 -08004183 */
Jean-Michel Trivi58850372018-09-14 16:01:28 -07004184 @IntDef({
4185 CONNECTION_STATE_DISCONNECTED,
4186 CONNECTION_STATE_CONNECTED,
4187 })
4188 @Retention(RetentionPolicy.SOURCE)
4189 public @interface ConnectionState {}
Paul McLean10804eb2015-01-28 11:16:35 -08004190
Jean-Michel Trivi58850372018-09-14 16:01:28 -07004191 /**
4192 * see AudioManager.setWiredDeviceConnectionState()
4193 */
4194 public void setWiredDeviceConnectionState(int type,
4195 @ConnectionState int state, String address, String name,
John Spurlock90874332015-03-10 16:00:54 -04004196 String caller) {
Jean-Michel Trivi58850372018-09-14 16:01:28 -07004197 if (state != CONNECTION_STATE_CONNECTED
4198 && state != CONNECTION_STATE_DISCONNECTED) {
4199 throw new IllegalArgumentException("Invalid state " + state);
Eric Laurentb1fbaac2012-05-29 09:24:28 -07004200 }
Jean-Michel Trivi58850372018-09-14 16:01:28 -07004201 mDeviceBroker.setWiredDeviceConnectionState(type, state, address, name, caller);
Eric Laurentb1fbaac2012-05-29 09:24:28 -07004202 }
4203
Jean-Michel Trivi58850372018-09-14 16:01:28 -07004204 /**
4205 * @hide
4206 * The states that can be used with AudioService.setBluetoothHearingAidDeviceConnectionState()
4207 * and AudioService.setBluetoothA2dpDeviceConnectionStateSuppressNoisyIntent()
4208 */
4209 @IntDef({
4210 BluetoothProfile.STATE_DISCONNECTED,
4211 BluetoothProfile.STATE_CONNECTED,
4212 })
4213 @Retention(RetentionPolicy.SOURCE)
4214 public @interface BtProfileConnectionState {}
4215
Jean-Michel Trivifc86cfa2019-03-01 10:15:47 -08004216 /**
4217 * See AudioManager.setBluetoothHearingAidDeviceConnectionState()
4218 */
4219 public void setBluetoothHearingAidDeviceConnectionState(
Jean-Michel Trivi58850372018-09-14 16:01:28 -07004220 @NonNull BluetoothDevice device, @BtProfileConnectionState int state,
4221 boolean suppressNoisyIntent, int musicDevice)
Jakub Pawlowskif9570f32018-02-21 17:15:12 -08004222 {
Jean-Michel Trivi58850372018-09-14 16:01:28 -07004223 if (device == null) {
4224 throw new IllegalArgumentException("Illegal null device");
Jakub Pawlowskif9570f32018-02-21 17:15:12 -08004225 }
Jean-Michel Trivi58850372018-09-14 16:01:28 -07004226 if (state != BluetoothProfile.STATE_CONNECTED
4227 && state != BluetoothProfile.STATE_DISCONNECTED) {
4228 throw new IllegalArgumentException("Illegal BluetoothProfile state for device "
4229 + " (dis)connection, got " + state);
4230 }
Jean-Michel Trivifc86cfa2019-03-01 10:15:47 -08004231 mDeviceBroker.postBluetoothHearingAidDeviceConnectionState(
Jean-Michel Trivi58850372018-09-14 16:01:28 -07004232 device, state, suppressNoisyIntent, musicDevice, "AudioService");
Jakub Pawlowski10c90612018-02-21 13:28:46 -08004233 }
4234
Jean-Michel Trivi58850372018-09-14 16:01:28 -07004235 /**
4236 * See AudioManager.setBluetoothA2dpDeviceConnectionStateSuppressNoisyIntent()
4237 */
Jean-Michel Trivifc86cfa2019-03-01 10:15:47 -08004238 public void setBluetoothA2dpDeviceConnectionStateSuppressNoisyIntent(
Jean-Michel Trivi58850372018-09-14 16:01:28 -07004239 @NonNull BluetoothDevice device, @AudioService.BtProfileConnectionState int state,
4240 int profile, boolean suppressNoisyIntent, int a2dpVolume) {
4241 if (device == null) {
4242 throw new IllegalArgumentException("Illegal null device");
4243 }
4244 if (state != BluetoothProfile.STATE_CONNECTED
4245 && state != BluetoothProfile.STATE_DISCONNECTED) {
4246 throw new IllegalArgumentException("Illegal BluetoothProfile state for device "
4247 + " (dis)connection, got " + state);
4248 }
Jean-Michel Trivifc86cfa2019-03-01 10:15:47 -08004249 mDeviceBroker.postBluetoothA2dpDeviceConnectionStateSuppressNoisyIntent(device, state,
Jean-Michel Trivi58850372018-09-14 16:01:28 -07004250 profile, suppressNoisyIntent, a2dpVolume);
Pavlin Radoslavov82e06462018-01-19 18:20:04 -08004251 }
4252
Jean-Michel Trivi58850372018-09-14 16:01:28 -07004253 /**
4254 * See AudioManager.handleBluetoothA2dpDeviceConfigChange()
4255 * @param device
4256 */
Pavlin Radoslavov44a4ef02016-12-21 12:05:51 -08004257 public void handleBluetoothA2dpDeviceConfigChange(BluetoothDevice device)
4258 {
Jean-Michel Trivi58850372018-09-14 16:01:28 -07004259 if (device == null) {
4260 throw new IllegalArgumentException("Illegal null device");
Pavlin Radoslavov44a4ef02016-12-21 12:05:51 -08004261 }
Jean-Michel Trivi58850372018-09-14 16:01:28 -07004262 mDeviceBroker.postBluetoothA2dpDeviceConfigChange(device);
Pavlin Radoslavov44a4ef02016-12-21 12:05:51 -08004263 }
4264
Aniket Kumar Lataa8439e22019-01-11 03:59:00 -08004265 /**
4266 * @see AudioManager#handleBluetoothA2dpActiveDeviceChange(BluetoothDevice, int, int,
4267 * boolean, int)
4268 */
Aniket Kumar Latad7c95982019-02-26 16:23:05 -08004269 public void handleBluetoothA2dpActiveDeviceChange(
Aniket Kumar Lataa8439e22019-01-11 03:59:00 -08004270 BluetoothDevice device, int state, int profile, boolean suppressNoisyIntent,
4271 int a2dpVolume) {
Jean-Michel Trivi58850372018-09-14 16:01:28 -07004272 if (device == null) {
4273 throw new IllegalArgumentException("Illegal null device");
4274 }
Aniket Kumar Lataa8439e22019-01-11 03:59:00 -08004275 if (profile != BluetoothProfile.A2DP && profile != BluetoothProfile.A2DP_SINK) {
4276 throw new IllegalArgumentException("invalid profile " + profile);
4277 }
Jean-Michel Trivi58850372018-09-14 16:01:28 -07004278 if (state != BluetoothProfile.STATE_CONNECTED
4279 && state != BluetoothProfile.STATE_DISCONNECTED) {
4280 throw new IllegalArgumentException("Invalid state " + state);
Aniket Kumar Lataa8439e22019-01-11 03:59:00 -08004281 }
Aniket Kumar Latad7c95982019-02-26 16:23:05 -08004282 mDeviceBroker.postBluetoothA2dpDeviceConfigChangeExt(device, state, profile,
Jean-Michel Trivi58850372018-09-14 16:01:28 -07004283 suppressNoisyIntent, a2dpVolume);
Aniket Kumar Lataa8439e22019-01-11 03:59:00 -08004284 }
4285
Jean-Michel Trivi1ab43f62017-04-27 15:37:34 -07004286 private static final int DEVICE_MEDIA_UNMUTED_ON_PLUG =
4287 AudioSystem.DEVICE_OUT_WIRED_HEADSET | AudioSystem.DEVICE_OUT_WIRED_HEADPHONE |
4288 AudioSystem.DEVICE_OUT_LINE |
4289 AudioSystem.DEVICE_OUT_ALL_A2DP |
4290 AudioSystem.DEVICE_OUT_ALL_USB |
4291 AudioSystem.DEVICE_OUT_HDMI;
4292
Jean-Michel Trivi58850372018-09-14 16:01:28 -07004293 /*package*/ void postAccessoryPlugMediaUnmute(int newDevice) {
4294 sendMsg(mAudioHandler, MSG_ACCESSORY_PLUG_MEDIA_UNMUTE, SENDMSG_QUEUE,
4295 newDevice, 0, null, 0);
4296 }
4297
Jean-Michel Trivi1ab43f62017-04-27 15:37:34 -07004298 private void onAccessoryPlugMediaUnmute(int newDevice) {
4299 if (DEBUG_VOL) {
4300 Log.i(TAG, String.format("onAccessoryPlugMediaUnmute newDevice=%d [%s]",
4301 newDevice, AudioSystem.getOutputDeviceName(newDevice)));
4302 }
Jean-Michel Trivi58850372018-09-14 16:01:28 -07004303
4304 if (mNm.getZenMode() != Settings.Global.ZEN_MODE_NO_INTERRUPTIONS
4305 && (newDevice & DEVICE_MEDIA_UNMUTED_ON_PLUG) != 0
4306 && mStreamStates[AudioSystem.STREAM_MUSIC].mIsMuted
4307 && mStreamStates[AudioSystem.STREAM_MUSIC].getIndex(newDevice) != 0
4308 && (newDevice & AudioSystem.getDevicesForStream(AudioSystem.STREAM_MUSIC)) != 0) {
4309 if (DEBUG_VOL) {
4310 Log.i(TAG, String.format(" onAccessoryPlugMediaUnmute unmuting device=%d [%s]",
4311 newDevice, AudioSystem.getOutputDeviceName(newDevice)));
Jean-Michel Trivi1ab43f62017-04-27 15:37:34 -07004312 }
Jean-Michel Trivi58850372018-09-14 16:01:28 -07004313 mStreamStates[AudioSystem.STREAM_MUSIC].mute(false);
Jean-Michel Trivi1ab43f62017-04-27 15:37:34 -07004314 }
4315 }
4316
jiabinad225202019-03-20 15:22:50 -07004317 /**
4318 * See AudioManager.hasHapticChannels(Uri).
4319 */
4320 public boolean hasHapticChannels(Uri uri) {
4321 MediaExtractor extractor = new MediaExtractor();
4322 try {
4323 extractor.setDataSource(mContext, uri, null);
4324 for (int i = 0; i < extractor.getTrackCount(); i++) {
4325 MediaFormat format = extractor.getTrackFormat(i);
4326 if (format.containsKey(MediaFormat.KEY_HAPTIC_CHANNEL_COUNT)
4327 && format.getInteger(MediaFormat.KEY_HAPTIC_CHANNEL_COUNT) > 0) {
4328 return true;
4329 }
4330 }
4331 } catch (IOException e) {
4332 Log.e(TAG, "hasHapticChannels failure:" + e);
4333 }
4334 return false;
4335 }
4336
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004337 ///////////////////////////////////////////////////////////////////////////
4338 // Inner classes
4339 ///////////////////////////////////////////////////////////////////////////
4340
Eric Laurent8fa4d6f2014-10-30 14:13:03 -07004341 // NOTE: Locking order for synchronized objects related to volume or ringer mode management:
4342 // 1 mScoclient OR mSafeMediaVolumeState
Jean-Michel Trivi58850372018-09-14 16:01:28 -07004343 // 2 mSetModeLock
Eric Laurent8fa4d6f2014-10-30 14:13:03 -07004344 // 3 mSettingsLock
4345 // 4 VolumeStreamState.class
Jean-Michel Trivi5bbcd442019-04-18 12:07:34 -07004346 private class VolumeStreamState {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004347 private final int mStreamType;
Jean-Michel Trivie05eef82018-03-08 18:56:34 -08004348 private int mIndexMin;
4349 private int mIndexMax;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004350
RoboErik4197cb62015-01-21 15:45:32 -08004351 private boolean mIsMuted;
Jean-Michel Trivi11a74a72009-10-27 17:39:30 -07004352 private String mVolumeIndexSettingName;
John Spurlock8a52c442015-03-26 14:23:58 -04004353 private int mObservedDevices;
John Spurlockb6e19e32015-03-10 21:33:44 -04004354
John Spurlock2bb02ec2015-03-02 13:13:06 -05004355 private final SparseIntArray mIndexMap = new SparseIntArray(8);
John Spurlockf63860c2015-02-19 09:46:27 -05004356 private final Intent mVolumeChanged;
John Spurlock8a52c442015-03-26 14:23:58 -04004357 private final Intent mStreamDevicesChanged;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004358
Eric Laurenta553c252009-07-17 12:17:14 -07004359 private VolumeStreamState(String settingName, int streamType) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004360
Eric Laurent9bc8358d2011-11-18 16:43:31 -08004361 mVolumeIndexSettingName = settingName;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004362
4363 mStreamType = streamType;
John Spurlockb6e19e32015-03-10 21:33:44 -04004364 mIndexMin = MIN_STREAM_VOLUME[streamType] * 10;
4365 mIndexMax = MAX_STREAM_VOLUME[streamType] * 10;
4366 AudioSystem.initStreamVolume(streamType, mIndexMin / 10, mIndexMax / 10);
Eric Laurent9bc8358d2011-11-18 16:43:31 -08004367
Eric Laurent33902db2012-10-07 16:15:07 -07004368 readSettings();
John Spurlockf63860c2015-02-19 09:46:27 -05004369 mVolumeChanged = new Intent(AudioManager.VOLUME_CHANGED_ACTION);
4370 mVolumeChanged.putExtra(AudioManager.EXTRA_VOLUME_STREAM_TYPE, mStreamType);
John Spurlock8a52c442015-03-26 14:23:58 -04004371 mStreamDevicesChanged = new Intent(AudioManager.STREAM_DEVICES_CHANGED_ACTION);
4372 mStreamDevicesChanged.putExtra(AudioManager.EXTRA_VOLUME_STREAM_TYPE, mStreamType);
4373 }
4374
4375 public int observeDevicesForStream_syncVSS(boolean checkOthers) {
4376 final int devices = AudioSystem.getDevicesForStream(mStreamType);
4377 if (devices == mObservedDevices) {
4378 return devices;
4379 }
4380 final int prevDevices = mObservedDevices;
4381 mObservedDevices = devices;
4382 if (checkOthers) {
4383 // one stream's devices have changed, check the others
4384 observeDevicesForStreams(mStreamType);
4385 }
4386 // log base stream changes to the event log
4387 if (mStreamVolumeAlias[mStreamType] == mStreamType) {
4388 EventLogTags.writeStreamDevicesChanged(mStreamType, prevDevices, devices);
4389 }
4390 sendBroadcastToAll(mStreamDevicesChanged
4391 .putExtra(AudioManager.EXTRA_PREV_VOLUME_STREAM_DEVICES, prevDevices)
4392 .putExtra(AudioManager.EXTRA_VOLUME_STREAM_DEVICES, devices));
4393 return devices;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004394 }
4395
Jean-Michel Trivia53b7052017-04-12 18:27:01 -07004396 public @Nullable String getSettingNameForDevice(int device) {
4397 if (!hasValidSettingsName()) {
4398 return null;
Eric Laurent9bc8358d2011-11-18 16:43:31 -08004399 }
Jean-Michel Trivia53b7052017-04-12 18:27:01 -07004400 final String suffix = AudioSystem.getOutputDeviceName(device);
4401 if (suffix.isEmpty()) {
4402 return mVolumeIndexSettingName;
4403 }
4404 return mVolumeIndexSettingName + "_" + suffix;
4405 }
4406
4407 private boolean hasValidSettingsName() {
4408 return (mVolumeIndexSettingName != null && !mVolumeIndexSettingName.isEmpty());
Jean-Michel Trivi11a74a72009-10-27 17:39:30 -07004409 }
4410
Eric Laurentfdbee862014-05-12 15:26:12 -07004411 public void readSettings() {
Jean-Michel Trivi8719a1d2017-11-06 11:52:51 -08004412 synchronized (mSettingsLock) {
4413 synchronized (VolumeStreamState.class) {
4414 // force maximum volume on all streams if fixed volume property is set
4415 if (mUseFixedVolume) {
4416 mIndexMap.put(AudioSystem.DEVICE_OUT_DEFAULT, mIndexMax);
4417 return;
4418 }
4419 // do not read system stream volume from settings: this stream is always aliased
4420 // to another stream type and its volume is never persisted. Values in settings can
4421 // only be stale values
4422 if ((mStreamType == AudioSystem.STREAM_SYSTEM) ||
4423 (mStreamType == AudioSystem.STREAM_SYSTEM_ENFORCED)) {
4424 int index = 10 * AudioSystem.DEFAULT_STREAM_VOLUME[mStreamType];
Eric Laurentfdbee862014-05-12 15:26:12 -07004425 if (mCameraSoundForced) {
4426 index = mIndexMax;
4427 }
Jean-Michel Trivi8719a1d2017-11-06 11:52:51 -08004428 mIndexMap.put(AudioSystem.DEVICE_OUT_DEFAULT, index);
4429 return;
Eric Laurentdd45d012012-10-08 09:04:34 -07004430 }
Eric Laurent9bc8358d2011-11-18 16:43:31 -08004431 }
Jean-Michel Trivi8719a1d2017-11-06 11:52:51 -08004432 }
4433 synchronized (VolumeStreamState.class) {
Eric Laurentfdbee862014-05-12 15:26:12 -07004434 int remainingDevices = AudioSystem.DEVICE_OUT_ALL;
4435
4436 for (int i = 0; remainingDevices != 0; i++) {
4437 int device = (1 << i);
4438 if ((device & remainingDevices) == 0) {
4439 continue;
4440 }
4441 remainingDevices &= ~device;
4442
4443 // retrieve current volume for device
Eric Laurentfdbee862014-05-12 15:26:12 -07004444 // if no volume stored for current stream and device, use default volume if default
4445 // device, continue otherwise
4446 int defaultIndex = (device == AudioSystem.DEVICE_OUT_DEFAULT) ?
John Spurlock61560172015-02-06 19:46:04 -05004447 AudioSystem.DEFAULT_STREAM_VOLUME[mStreamType] : -1;
Jean-Michel Trivia53b7052017-04-12 18:27:01 -07004448 int index;
4449 if (!hasValidSettingsName()) {
4450 index = defaultIndex;
4451 } else {
4452 String name = getSettingNameForDevice(device);
4453 index = Settings.System.getIntForUser(
4454 mContentResolver, name, defaultIndex, UserHandle.USER_CURRENT);
4455 }
Eric Laurentfdbee862014-05-12 15:26:12 -07004456 if (index == -1) {
4457 continue;
4458 }
4459
John Spurlock2bb02ec2015-03-02 13:13:06 -05004460 mIndexMap.put(device, getValidIndex(10 * index));
Eric Laurentdd45d012012-10-08 09:04:34 -07004461 }
Eric Laurent9bc8358d2011-11-18 16:43:31 -08004462 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004463 }
4464
Liejun Tao39fb5672016-03-09 15:52:13 -06004465 private int getAbsoluteVolumeIndex(int index) {
4466 /* Special handling for Bluetooth Absolute Volume scenario
4467 * If we send full audio gain, some accessories are too loud even at its lowest
4468 * volume. We are not able to enumerate all such accessories, so here is the
4469 * workaround from phone side.
4470 * Pre-scale volume at lowest volume steps 1 2 and 3.
4471 * For volume step 0, set audio gain to 0 as some accessories won't mute on their end.
4472 */
4473 if (index == 0) {
4474 // 0% for volume 0
4475 index = 0;
Tomoharu Kasaharaf0fecb12018-09-06 20:04:38 +09004476 } else if (index > 0 && index <= 3) {
4477 // Pre-scale for volume steps 1 2 and 3
4478 index = (int) (mIndexMax * mPrescaleAbsoluteVolume[index - 1]) / 10;
Liejun Tao39fb5672016-03-09 15:52:13 -06004479 } else {
4480 // otherwise, full gain
Tomoharu Kasaharaf0fecb12018-09-06 20:04:38 +09004481 index = (mIndexMax + 5) / 10;
Liejun Tao39fb5672016-03-09 15:52:13 -06004482 }
4483 return index;
4484 }
4485
Eric Laurent8fa4d6f2014-10-30 14:13:03 -07004486 // must be called while synchronized VolumeStreamState.class
Jean-Michel Trivi58850372018-09-14 16:01:28 -07004487 /*package*/ void applyDeviceVolume_syncVSS(int device, boolean isAvrcpAbsVolSupported) {
Eric Laurent42b041e2013-03-29 11:36:03 -07004488 int index;
RoboErik4197cb62015-01-21 15:45:32 -08004489 if (mIsMuted) {
Eric Laurent42b041e2013-03-29 11:36:03 -07004490 index = 0;
Jean-Michel Trivi58850372018-09-14 16:01:28 -07004491 } else if ((device & AudioSystem.DEVICE_OUT_ALL_A2DP) != 0 && isAvrcpAbsVolSupported) {
Liejun Tao39fb5672016-03-09 15:52:13 -06004492 index = getAbsoluteVolumeIndex((getIndex(device) + 5)/10);
Liejun Tao4565a472016-01-20 17:52:20 -06004493 } else if ((device & mFullVolumeDevices) != 0) {
Matthew Xiec9d1d5f2013-09-12 00:32:22 -07004494 index = (mIndexMax + 5)/10;
Jakub Pawlowskic274fb22018-04-04 10:15:12 -07004495 } else if ((device & AudioSystem.DEVICE_OUT_HEARING_AID) != 0) {
4496 index = (mIndexMax + 5)/10;
Eric Laurentcd772d02013-10-30 18:31:07 -07004497 } else {
Eric Laurent42b041e2013-03-29 11:36:03 -07004498 index = (getIndex(device) + 5)/10;
4499 }
Jean-Michel Trivi58850372018-09-14 16:01:28 -07004500 AudioSystem.setStreamVolumeIndexAS(mStreamType, index, device);
Eric Laurent9bc8358d2011-11-18 16:43:31 -08004501 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004502
Eric Laurentfdbee862014-05-12 15:26:12 -07004503 public void applyAllVolumes() {
Jean-Michel Trivi58850372018-09-14 16:01:28 -07004504 final boolean isAvrcpAbsVolSupported = mDeviceBroker.isAvrcpAbsoluteVolumeSupported();
Eric Laurentfdbee862014-05-12 15:26:12 -07004505 synchronized (VolumeStreamState.class) {
Eric Laurentd9ac2be2016-04-07 14:04:23 -07004506 // apply device specific volumes first
Eric Laurentfdbee862014-05-12 15:26:12 -07004507 int index;
John Spurlock2bb02ec2015-03-02 13:13:06 -05004508 for (int i = 0; i < mIndexMap.size(); i++) {
Eric Laurentd9ac2be2016-04-07 14:04:23 -07004509 final int device = mIndexMap.keyAt(i);
Eric Laurentfdbee862014-05-12 15:26:12 -07004510 if (device != AudioSystem.DEVICE_OUT_DEFAULT) {
RoboErik4197cb62015-01-21 15:45:32 -08004511 if (mIsMuted) {
Eric Laurentfdbee862014-05-12 15:26:12 -07004512 index = 0;
Liejun Tao39fb5672016-03-09 15:52:13 -06004513 } else if ((device & AudioSystem.DEVICE_OUT_ALL_A2DP) != 0 &&
Jean-Michel Trivi58850372018-09-14 16:01:28 -07004514 isAvrcpAbsVolSupported) {
Liejun Tao39fb5672016-03-09 15:52:13 -06004515 index = getAbsoluteVolumeIndex((getIndex(device) + 5)/10);
4516 } else if ((device & mFullVolumeDevices) != 0) {
Eric Laurentfdbee862014-05-12 15:26:12 -07004517 index = (mIndexMax + 5)/10;
Jakub Pawlowskic274fb22018-04-04 10:15:12 -07004518 } else if ((device & AudioSystem.DEVICE_OUT_HEARING_AID) != 0) {
4519 index = (mIndexMax + 5)/10;
Eric Laurentfdbee862014-05-12 15:26:12 -07004520 } else {
John Spurlock2bb02ec2015-03-02 13:13:06 -05004521 index = (mIndexMap.valueAt(i) + 5)/10;
Eric Laurentfdbee862014-05-12 15:26:12 -07004522 }
Jean-Michel Trivi58850372018-09-14 16:01:28 -07004523 AudioSystem.setStreamVolumeIndexAS(mStreamType, index, device);
Eric Laurent42b041e2013-03-29 11:36:03 -07004524 }
Eric Laurent9bc8358d2011-11-18 16:43:31 -08004525 }
Eric Laurentd9ac2be2016-04-07 14:04:23 -07004526 // apply default volume last: by convention , default device volume will be used
4527 // by audio policy manager if no explicit volume is present for a given device type
4528 if (mIsMuted) {
4529 index = 0;
4530 } else {
4531 index = (getIndex(AudioSystem.DEVICE_OUT_DEFAULT) + 5)/10;
4532 }
Jean-Michel Trivi58850372018-09-14 16:01:28 -07004533 AudioSystem.setStreamVolumeIndexAS(
Eric Laurentd9ac2be2016-04-07 14:04:23 -07004534 mStreamType, index, AudioSystem.DEVICE_OUT_DEFAULT);
Eric Laurent9bc8358d2011-11-18 16:43:31 -08004535 }
4536 }
4537
John Spurlock90874332015-03-10 16:00:54 -04004538 public boolean adjustIndex(int deltaIndex, int device, String caller) {
4539 return setIndex(getIndex(device) + deltaIndex, device, caller);
Eric Laurent9bc8358d2011-11-18 16:43:31 -08004540 }
4541
John Spurlock90874332015-03-10 16:00:54 -04004542 public boolean setIndex(int index, int device, String caller) {
Jack He6dd78c12018-02-12 21:00:24 -08004543 boolean changed;
John Spurlockf63860c2015-02-19 09:46:27 -05004544 int oldIndex;
Jean-Michel Trivi8719a1d2017-11-06 11:52:51 -08004545 synchronized (mSettingsLock) {
4546 synchronized (VolumeStreamState.class) {
4547 oldIndex = getIndex(device);
4548 index = getValidIndex(index);
Eric Laurentfdbee862014-05-12 15:26:12 -07004549 if ((mStreamType == AudioSystem.STREAM_SYSTEM_ENFORCED) && mCameraSoundForced) {
4550 index = mIndexMax;
Eric Laurenta553c252009-07-17 12:17:14 -07004551 }
Jean-Michel Trivi8719a1d2017-11-06 11:52:51 -08004552 mIndexMap.put(device, index);
Eric Laurentfdbee862014-05-12 15:26:12 -07004553
Jean-Michel Trivi8719a1d2017-11-06 11:52:51 -08004554 changed = oldIndex != index;
4555 // Apply change to all streams using this one as alias if:
4556 // - the index actually changed OR
4557 // - there is no volume index stored for this device on alias stream.
4558 // If changing volume of current device, also change volume of current
4559 // device on aliased stream
Jack He6dd78c12018-02-12 21:00:24 -08004560 final boolean isCurrentDevice = (device == getDeviceForStream(mStreamType));
Jean-Michel Trivi8719a1d2017-11-06 11:52:51 -08004561 final int numStreamTypes = AudioSystem.getNumStreamTypes();
4562 for (int streamType = numStreamTypes - 1; streamType >= 0; streamType--) {
4563 final VolumeStreamState aliasStreamState = mStreamStates[streamType];
4564 if (streamType != mStreamType &&
4565 mStreamVolumeAlias[streamType] == mStreamType &&
4566 (changed || !aliasStreamState.hasIndexForDevice(device))) {
4567 final int scaledIndex = rescaleIndex(index, mStreamType, streamType);
4568 aliasStreamState.setIndex(scaledIndex, device, caller);
Jack He6dd78c12018-02-12 21:00:24 -08004569 if (isCurrentDevice) {
Jean-Michel Trivi8719a1d2017-11-06 11:52:51 -08004570 aliasStreamState.setIndex(scaledIndex,
4571 getDeviceForStream(streamType), caller);
4572 }
Eric Laurentfdbee862014-05-12 15:26:12 -07004573 }
4574 }
Jack He6dd78c12018-02-12 21:00:24 -08004575 // Mirror changes in SPEAKER ringtone volume on SCO when
4576 if (changed && mStreamType == AudioSystem.STREAM_RING
4577 && device == AudioSystem.DEVICE_OUT_SPEAKER) {
4578 for (int i = 0; i < mIndexMap.size(); i++) {
4579 int otherDevice = mIndexMap.keyAt(i);
4580 if ((otherDevice & AudioSystem.DEVICE_OUT_ALL_SCO) != 0) {
4581 mIndexMap.put(otherDevice, index);
4582 }
4583 }
4584 }
Eric Laurentfdbee862014-05-12 15:26:12 -07004585 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004586 }
John Spurlockf63860c2015-02-19 09:46:27 -05004587 if (changed) {
4588 oldIndex = (oldIndex + 5) / 10;
4589 index = (index + 5) / 10;
John Spurlock90874332015-03-10 16:00:54 -04004590 // log base stream changes to the event log
4591 if (mStreamVolumeAlias[mStreamType] == mStreamType) {
4592 if (caller == null) {
4593 Log.w(TAG, "No caller for volume_changed event", new Throwable());
4594 }
4595 EventLogTags.writeVolumeChanged(mStreamType, oldIndex, index, mIndexMax / 10,
4596 caller);
4597 }
4598 // fire changed intents for all streams
John Spurlockf63860c2015-02-19 09:46:27 -05004599 mVolumeChanged.putExtra(AudioManager.EXTRA_VOLUME_STREAM_VALUE, index);
4600 mVolumeChanged.putExtra(AudioManager.EXTRA_PREV_VOLUME_STREAM_VALUE, oldIndex);
Jean-Michel Trivi560877d2015-06-25 17:38:35 -07004601 mVolumeChanged.putExtra(AudioManager.EXTRA_VOLUME_STREAM_TYPE_ALIAS,
4602 mStreamVolumeAlias[mStreamType]);
John Spurlockf63860c2015-02-19 09:46:27 -05004603 sendBroadcastToAll(mVolumeChanged);
4604 }
4605 return changed;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004606 }
4607
Eric Laurentfdbee862014-05-12 15:26:12 -07004608 public int getIndex(int device) {
4609 synchronized (VolumeStreamState.class) {
John Spurlock2bb02ec2015-03-02 13:13:06 -05004610 int index = mIndexMap.get(device, -1);
4611 if (index == -1) {
Eric Laurentfdbee862014-05-12 15:26:12 -07004612 // there is always an entry for AudioSystem.DEVICE_OUT_DEFAULT
John Spurlock2bb02ec2015-03-02 13:13:06 -05004613 index = mIndexMap.get(AudioSystem.DEVICE_OUT_DEFAULT);
Eric Laurentfdbee862014-05-12 15:26:12 -07004614 }
John Spurlock2bb02ec2015-03-02 13:13:06 -05004615 return index;
Eric Laurent9bc8358d2011-11-18 16:43:31 -08004616 }
Eric Laurent5b4e6542010-03-19 20:02:21 -07004617 }
4618
Eric Laurent3fb608e2016-11-03 16:27:40 -07004619 public boolean hasIndexForDevice(int device) {
4620 synchronized (VolumeStreamState.class) {
4621 return (mIndexMap.get(device, -1) != -1);
4622 }
4623 }
4624
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004625 public int getMaxIndex() {
Eric Laurenta553c252009-07-17 12:17:14 -07004626 return mIndexMax;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004627 }
4628
John Spurlockb6e19e32015-03-10 21:33:44 -04004629 public int getMinIndex() {
4630 return mIndexMin;
4631 }
4632
Jean-Michel Trivi170a0ee2017-04-14 18:13:26 -07004633 /**
Jean-Michel Trivie05eef82018-03-08 18:56:34 -08004634 * Updates the min/max index values from another stream. Use this when changing the alias
4635 * for the current stream type.
4636 * @param sourceStreamType
4637 */
4638 // must be sync'd on mSettingsLock before VolumeStreamState.class
4639 @GuardedBy("VolumeStreamState.class")
4640 public void refreshRange(int sourceStreamType) {
4641 mIndexMin = MIN_STREAM_VOLUME[sourceStreamType] * 10;
4642 mIndexMax = MAX_STREAM_VOLUME[sourceStreamType] * 10;
4643 // verify all current volumes are within bounds
4644 for (int i = 0 ; i < mIndexMap.size(); i++) {
4645 final int device = mIndexMap.keyAt(i);
4646 final int index = mIndexMap.valueAt(i);
4647 mIndexMap.put(device, getValidIndex(index));
4648 }
4649 }
4650
4651 /**
Jean-Michel Trivi170a0ee2017-04-14 18:13:26 -07004652 * Copies all device/index pairs from the given VolumeStreamState after initializing
4653 * them with the volume for DEVICE_OUT_DEFAULT. No-op if the source VolumeStreamState
4654 * has the same stream type as this instance.
4655 * @param srcStream
4656 * @param caller
4657 */
Jean-Michel Trivi085346a2018-02-14 10:48:51 -08004658 // must be sync'd on mSettingsLock before VolumeStreamState.class
4659 @GuardedBy("VolumeStreamState.class")
John Spurlock90874332015-03-10 16:00:54 -04004660 public void setAllIndexes(VolumeStreamState srcStream, String caller) {
Jean-Michel Trivi170a0ee2017-04-14 18:13:26 -07004661 if (mStreamType == srcStream.mStreamType) {
4662 return;
4663 }
Jean-Michel Trivi085346a2018-02-14 10:48:51 -08004664 int srcStreamType = srcStream.getStreamType();
4665 // apply default device volume from source stream to all devices first in case
4666 // some devices are present in this stream state but not in source stream state
4667 int index = srcStream.getIndex(AudioSystem.DEVICE_OUT_DEFAULT);
4668 index = rescaleIndex(index, srcStreamType, mStreamType);
4669 for (int i = 0; i < mIndexMap.size(); i++) {
4670 mIndexMap.put(mIndexMap.keyAt(i), index);
4671 }
4672 // Now apply actual volume for devices in source stream state
4673 SparseIntArray srcMap = srcStream.mIndexMap;
4674 for (int i = 0; i < srcMap.size(); i++) {
4675 int device = srcMap.keyAt(i);
4676 index = srcMap.valueAt(i);
4677 index = rescaleIndex(index, srcStreamType, mStreamType);
Eric Laurent33902db2012-10-07 16:15:07 -07004678
Jean-Michel Trivi085346a2018-02-14 10:48:51 -08004679 setIndex(index, device, caller);
Eric Laurent6d517662012-04-23 18:42:39 -07004680 }
4681 }
4682
Jean-Michel Trivi085346a2018-02-14 10:48:51 -08004683 // must be sync'd on mSettingsLock before VolumeStreamState.class
4684 @GuardedBy("VolumeStreamState.class")
Eric Laurentfdbee862014-05-12 15:26:12 -07004685 public void setAllIndexesToMax() {
Jean-Michel Trivi085346a2018-02-14 10:48:51 -08004686 for (int i = 0; i < mIndexMap.size(); i++) {
4687 mIndexMap.put(mIndexMap.keyAt(i), mIndexMax);
Eric Laurentdd45d012012-10-08 09:04:34 -07004688 }
Eric Laurentdd45d012012-10-08 09:04:34 -07004689 }
4690
RoboErik4197cb62015-01-21 15:45:32 -08004691 public void mute(boolean state) {
John Spurlock22b9ee12015-02-18 22:51:44 -05004692 boolean changed = false;
Eric Laurentfdbee862014-05-12 15:26:12 -07004693 synchronized (VolumeStreamState.class) {
RoboErik4197cb62015-01-21 15:45:32 -08004694 if (state != mIsMuted) {
John Spurlock22b9ee12015-02-18 22:51:44 -05004695 changed = true;
RoboErik4197cb62015-01-21 15:45:32 -08004696 mIsMuted = state;
John Spurlock22b9ee12015-02-18 22:51:44 -05004697
RoboErik4197cb62015-01-21 15:45:32 -08004698 // Set the new mute volume. This propagates the values to
4699 // the audio system, otherwise the volume won't be changed
4700 // at the lower level.
4701 sendMsg(mAudioHandler,
4702 MSG_SET_ALL_VOLUMES,
4703 SENDMSG_QUEUE,
4704 0,
4705 0,
4706 this, 0);
Eric Laurentfdbee862014-05-12 15:26:12 -07004707 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004708 }
John Spurlock22b9ee12015-02-18 22:51:44 -05004709 if (changed) {
4710 // Stream mute changed, fire the intent.
4711 Intent intent = new Intent(AudioManager.STREAM_MUTE_CHANGED_ACTION);
4712 intent.putExtra(AudioManager.EXTRA_VOLUME_STREAM_TYPE, mStreamType);
4713 intent.putExtra(AudioManager.EXTRA_STREAM_VOLUME_MUTED, state);
4714 sendBroadcastToAll(intent);
4715 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004716 }
4717
Eric Laurent6d517662012-04-23 18:42:39 -07004718 public int getStreamType() {
4719 return mStreamType;
4720 }
4721
Eric Laurent212532b2014-07-21 15:43:18 -07004722 public void checkFixedVolumeDevices() {
Jean-Michel Trivi58850372018-09-14 16:01:28 -07004723 final boolean isAvrcpAbsVolSupported = mDeviceBroker.isAvrcpAbsoluteVolumeSupported();
Eric Laurent212532b2014-07-21 15:43:18 -07004724 synchronized (VolumeStreamState.class) {
4725 // ignore settings for fixed volume devices: volume should always be at max or 0
4726 if (mStreamVolumeAlias[mStreamType] == AudioSystem.STREAM_MUSIC) {
John Spurlock2bb02ec2015-03-02 13:13:06 -05004727 for (int i = 0; i < mIndexMap.size(); i++) {
4728 int device = mIndexMap.keyAt(i);
4729 int index = mIndexMap.valueAt(i);
Jean-Michel Triviba5270b2014-10-01 17:49:29 -07004730 if (((device & mFullVolumeDevices) != 0)
4731 || (((device & mFixedVolumeDevices) != 0) && index != 0)) {
John Spurlock2bb02ec2015-03-02 13:13:06 -05004732 mIndexMap.put(device, mIndexMax);
Eric Laurent212532b2014-07-21 15:43:18 -07004733 }
Jean-Michel Trivi58850372018-09-14 16:01:28 -07004734 applyDeviceVolume_syncVSS(device, isAvrcpAbsVolSupported);
Eric Laurent212532b2014-07-21 15:43:18 -07004735 }
4736 }
4737 }
4738 }
4739
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004740 private int getValidIndex(int index) {
John Spurlockb6e19e32015-03-10 21:33:44 -04004741 if (index < mIndexMin) {
4742 return mIndexMin;
John Spurlockee5ad722015-03-03 16:17:21 -05004743 } else if (mUseFixedVolume || index > mIndexMax) {
Eric Laurenta553c252009-07-17 12:17:14 -07004744 return mIndexMax;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004745 }
4746
4747 return index;
4748 }
4749
Eric Laurentbffc3d12012-05-07 17:43:49 -07004750 private void dump(PrintWriter pw) {
RoboErik4197cb62015-01-21 15:45:32 -08004751 pw.print(" Muted: ");
4752 pw.println(mIsMuted);
John Spurlockb6e19e32015-03-10 21:33:44 -04004753 pw.print(" Min: ");
4754 pw.println((mIndexMin + 5) / 10);
John Spurlock2b29bc42014-08-26 16:40:35 -04004755 pw.print(" Max: ");
4756 pw.println((mIndexMax + 5) / 10);
Eric Laurentbffc3d12012-05-07 17:43:49 -07004757 pw.print(" Current: ");
John Spurlock2bb02ec2015-03-02 13:13:06 -05004758 for (int i = 0; i < mIndexMap.size(); i++) {
4759 if (i > 0) {
4760 pw.print(", ");
4761 }
4762 final int device = mIndexMap.keyAt(i);
John Spurlock2b29bc42014-08-26 16:40:35 -04004763 pw.print(Integer.toHexString(device));
4764 final String deviceName = device == AudioSystem.DEVICE_OUT_DEFAULT ? "default"
4765 : AudioSystem.getOutputDeviceName(device);
4766 if (!deviceName.isEmpty()) {
4767 pw.print(" (");
4768 pw.print(deviceName);
4769 pw.print(")");
4770 }
4771 pw.print(": ");
John Spurlock2bb02ec2015-03-02 13:13:06 -05004772 final int index = (mIndexMap.valueAt(i) + 5) / 10;
John Spurlock2b29bc42014-08-26 16:40:35 -04004773 pw.print(index);
Eric Laurentbffc3d12012-05-07 17:43:49 -07004774 }
John Spurlockb32fc972015-03-05 13:58:00 -05004775 pw.println();
4776 pw.print(" Devices: ");
John Spurlock8a52c442015-03-26 14:23:58 -04004777 final int devices = getDevicesForStream(mStreamType);
John Spurlockb32fc972015-03-05 13:58:00 -05004778 int device, i = 0, n = 0;
John Spurlock1ff1e6e2015-03-09 14:21:20 -04004779 // iterate all devices from 1 to DEVICE_OUT_DEFAULT exclusive
4780 // (the default device is not returned by getDevicesForStream)
4781 while ((device = 1 << i) != AudioSystem.DEVICE_OUT_DEFAULT) {
John Spurlockb32fc972015-03-05 13:58:00 -05004782 if ((devices & device) != 0) {
4783 if (n++ > 0) {
4784 pw.print(", ");
4785 }
4786 pw.print(AudioSystem.getOutputDeviceName(device));
4787 }
4788 i++;
4789 }
Eric Laurentbffc3d12012-05-07 17:43:49 -07004790 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004791 }
4792
4793 /** Thread that handles native AudioSystem control. */
4794 private class AudioSystemThread extends Thread {
4795 AudioSystemThread() {
4796 super("AudioService");
4797 }
4798
4799 @Override
4800 public void run() {
4801 // Set this thread up so the handler will work on it
4802 Looper.prepare();
4803
4804 synchronized(AudioService.this) {
4805 mAudioHandler = new AudioHandler();
4806
4807 // Notify that the handler has been created
4808 AudioService.this.notify();
4809 }
4810
4811 // Listen for volume change requests that are set by VolumePanel
4812 Looper.loop();
4813 }
4814 }
4815
Jean-Michel Trivi5bbcd442019-04-18 12:07:34 -07004816 private static final class DeviceVolumeUpdate {
4817 final int mStreamType;
4818 final int mDevice;
4819 final @NonNull String mCaller;
4820 private static final int NO_NEW_INDEX = -2049;
4821 private final int mVssVolIndex;
4822
4823 // Constructor with volume index, meant to cause this volume to be set and applied for the
4824 // given stream type on the given device
4825 DeviceVolumeUpdate(int streamType, int vssVolIndex, int device, @NonNull String caller) {
4826 mStreamType = streamType;
4827 mVssVolIndex = vssVolIndex;
4828 mDevice = device;
4829 mCaller = caller;
4830 }
4831
4832 // Constructor with no volume index, meant to cause re-apply of volume for the given
4833 // stream type on the given device
4834 DeviceVolumeUpdate(int streamType, int device, @NonNull String caller) {
4835 mStreamType = streamType;
4836 mVssVolIndex = NO_NEW_INDEX;
4837 mDevice = device;
4838 mCaller = caller;
4839 }
4840
4841 boolean hasVolumeIndex() {
4842 return mVssVolIndex != NO_NEW_INDEX;
4843 }
4844
4845 int getVolumeIndex() throws IllegalStateException {
4846 Preconditions.checkState(mVssVolIndex != NO_NEW_INDEX);
4847 return mVssVolIndex;
4848 }
4849 }
4850
4851 /*package*/ void postSetVolumeIndexOnDevice(int streamType, int vssVolIndex, int device,
4852 String caller) {
4853 sendMsg(mAudioHandler,
4854 MSG_SET_DEVICE_STREAM_VOLUME,
4855 SENDMSG_QUEUE, 0 /*arg1*/, 0 /*arg2*/,
4856 new DeviceVolumeUpdate(streamType, vssVolIndex, device, caller),
4857 0 /*delay*/);
4858 }
4859
4860 /*package*/ void postApplyVolumeOnDevice(int streamType, int device, @NonNull String caller) {
4861 sendMsg(mAudioHandler,
4862 MSG_SET_DEVICE_STREAM_VOLUME,
4863 SENDMSG_QUEUE, 0 /*arg1*/, 0 /*arg2*/,
4864 new DeviceVolumeUpdate(streamType, device, caller),
4865 0 /*delay*/);
4866 }
4867
4868 private void onSetVolumeIndexOnDevice(@NonNull DeviceVolumeUpdate update) {
4869 synchronized (VolumeStreamState.class) {
4870 final VolumeStreamState streamState = mStreamStates[update.mStreamType];
4871 if (update.hasVolumeIndex()) {
4872 final int index = update.getVolumeIndex();
4873 streamState.setIndex(index, update.mDevice, update.mCaller);
4874 sVolumeLogger.log(new AudioEventLogger.StringEvent(update.mCaller + " dev:0x"
4875 + Integer.toHexString(update.mDevice) + " volIdx:" + index));
4876 } else {
4877 sVolumeLogger.log(new AudioEventLogger.StringEvent(update.mCaller
4878 + " update vol on dev:0x" + Integer.toHexString(update.mDevice)));
4879 }
4880 setDeviceVolume(streamState, update.mDevice);
4881 }
4882 }
4883
Jean-Michel Trivi58850372018-09-14 16:01:28 -07004884 /*package*/ void setDeviceVolume(VolumeStreamState streamState, int device) {
4885
4886 final boolean isAvrcpAbsVolSupported = mDeviceBroker.isAvrcpAbsoluteVolumeSupported();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004887
Eric Laurent3e6fb632018-05-21 09:28:46 -07004888 synchronized (VolumeStreamState.class) {
4889 // Apply volume
Jean-Michel Trivi58850372018-09-14 16:01:28 -07004890 streamState.applyDeviceVolume_syncVSS(device, isAvrcpAbsVolSupported);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004891
Eric Laurent3e6fb632018-05-21 09:28:46 -07004892 // Apply change to all streams using this one as alias
4893 int numStreamTypes = AudioSystem.getNumStreamTypes();
4894 for (int streamType = numStreamTypes - 1; streamType >= 0; streamType--) {
4895 if (streamType != streamState.mStreamType &&
4896 mStreamVolumeAlias[streamType] == streamState.mStreamType) {
4897 // Make sure volume is also maxed out on A2DP device for aliased stream
4898 // that may have a different device selected
4899 int streamDevice = getDeviceForStream(streamType);
Jean-Michel Trivi58850372018-09-14 16:01:28 -07004900 if ((device != streamDevice) && isAvrcpAbsVolSupported
4901 && ((device & AudioSystem.DEVICE_OUT_ALL_A2DP) != 0)) {
4902 mStreamStates[streamType].applyDeviceVolume_syncVSS(device,
4903 isAvrcpAbsVolSupported);
Eric Laurentcd772d02013-10-30 18:31:07 -07004904 }
Jean-Michel Trivi58850372018-09-14 16:01:28 -07004905 mStreamStates[streamType].applyDeviceVolume_syncVSS(streamDevice,
4906 isAvrcpAbsVolSupported);
Eric Laurenta553c252009-07-17 12:17:14 -07004907 }
4908 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004909 }
Eric Laurent3e6fb632018-05-21 09:28:46 -07004910 // Post a persist volume msg
4911 sendMsg(mAudioHandler,
4912 MSG_PERSIST_VOLUME,
4913 SENDMSG_QUEUE,
4914 device,
4915 0,
4916 streamState,
4917 PERSIST_DELAY);
4918
4919 }
4920
4921 /** Handles internal volume messages in separate volume thread. */
4922 private class AudioHandler extends Handler {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004923
Eric Laurent9bc8358d2011-11-18 16:43:31 -08004924 private void setAllVolumes(VolumeStreamState streamState) {
4925
4926 // Apply volume
4927 streamState.applyAllVolumes();
4928
4929 // Apply change to all streams using this one as alias
4930 int numStreamTypes = AudioSystem.getNumStreamTypes();
4931 for (int streamType = numStreamTypes - 1; streamType >= 0; streamType--) {
4932 if (streamType != streamState.mStreamType &&
Eric Laurent6d517662012-04-23 18:42:39 -07004933 mStreamVolumeAlias[streamType] == streamState.mStreamType) {
Eric Laurent9bc8358d2011-11-18 16:43:31 -08004934 mStreamStates[streamType].applyAllVolumes();
4935 }
4936 }
4937 }
4938
Eric Laurent42b041e2013-03-29 11:36:03 -07004939 private void persistVolume(VolumeStreamState streamState, int device) {
Eric Laurent83a017b2013-03-19 18:15:31 -07004940 if (mUseFixedVolume) {
4941 return;
4942 }
Muyuan Li1ed6df62016-06-18 11:16:52 -07004943 if (mIsSingleVolume && (streamState.mStreamType != AudioSystem.STREAM_MUSIC)) {
Eric Laurent212532b2014-07-21 15:43:18 -07004944 return;
4945 }
Jean-Michel Trivia53b7052017-04-12 18:27:01 -07004946 if (streamState.hasValidSettingsName()) {
4947 System.putIntForUser(mContentResolver,
4948 streamState.getSettingNameForDevice(device),
4949 (streamState.getIndex(device) + 5)/ 10,
4950 UserHandle.USER_CURRENT);
4951 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004952 }
4953
Glenn Kastenba195eb2011-12-13 09:30:40 -08004954 private void persistRingerMode(int ringerMode) {
Eric Laurent83a017b2013-03-19 18:15:31 -07004955 if (mUseFixedVolume) {
4956 return;
4957 }
Jeff Sharkey8d9a1f62012-10-18 15:38:14 -07004958 Settings.Global.putInt(mContentResolver, Settings.Global.MODE_RINGER, ringerMode);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004959 }
4960
Jaekyun Seokc31033f2018-01-15 14:53:17 +09004961 private String getSoundEffectFilePath(int effectType) {
4962 String filePath = Environment.getProductDirectory() + SOUND_EFFECTS_PATH
4963 + SOUND_EFFECT_FILES.get(SOUND_EFFECT_FILES_MAP[effectType][0]);
4964 if (!new File(filePath).isFile()) {
4965 filePath = Environment.getRootDirectory() + SOUND_EFFECTS_PATH
4966 + SOUND_EFFECT_FILES.get(SOUND_EFFECT_FILES_MAP[effectType][0]);
4967 }
4968 return filePath;
4969 }
4970
Eric Laurent5d3eb44a2013-03-21 15:35:10 -07004971 private boolean onLoadSoundEffects() {
4972 int status;
4973
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004974 synchronized (mSoundEffectsLock) {
Eric Laurent4a5eeb92014-05-06 10:49:04 -07004975 if (!mSystemReady) {
Eric Laurent5d3eb44a2013-03-21 15:35:10 -07004976 Log.w(TAG, "onLoadSoundEffects() called before boot complete");
4977 return false;
4978 }
4979
4980 if (mSoundPool != null) {
4981 return true;
4982 }
4983
4984 loadTouchSoundAssets();
4985
Jean-Michel Trivi55a30c42014-07-20 17:56:11 -07004986 mSoundPool = new SoundPool.Builder()
4987 .setMaxStreams(NUM_SOUNDPOOL_CHANNELS)
4988 .setAudioAttributes(new AudioAttributes.Builder()
4989 .setUsage(AudioAttributes.USAGE_ASSISTANCE_SONIFICATION)
4990 .setContentType(AudioAttributes.CONTENT_TYPE_SONIFICATION)
4991 .build())
4992 .build();
Eric Laurent5d3eb44a2013-03-21 15:35:10 -07004993 mSoundPoolCallBack = null;
4994 mSoundPoolListenerThread = new SoundPoolListenerThread();
4995 mSoundPoolListenerThread.start();
4996 int attempts = 3;
4997 while ((mSoundPoolCallBack == null) && (attempts-- > 0)) {
4998 try {
4999 // Wait for mSoundPoolCallBack to be set by the other thread
Glenn Kasten167d1a22013-07-23 16:24:41 -07005000 mSoundEffectsLock.wait(SOUND_EFFECTS_LOAD_TIMEOUT_MS);
Eric Laurent5d3eb44a2013-03-21 15:35:10 -07005001 } catch (InterruptedException e) {
5002 Log.w(TAG, "Interrupted while waiting sound pool listener thread.");
5003 }
5004 }
5005
5006 if (mSoundPoolCallBack == null) {
5007 Log.w(TAG, "onLoadSoundEffects() SoundPool listener or thread creation error");
5008 if (mSoundPoolLooper != null) {
5009 mSoundPoolLooper.quit();
5010 mSoundPoolLooper = null;
5011 }
5012 mSoundPoolListenerThread = null;
5013 mSoundPool.release();
5014 mSoundPool = null;
5015 return false;
5016 }
5017 /*
5018 * poolId table: The value -1 in this table indicates that corresponding
5019 * file (same index in SOUND_EFFECT_FILES[] has not been loaded.
5020 * Once loaded, the value in poolId is the sample ID and the same
5021 * sample can be reused for another effect using the same file.
5022 */
5023 int[] poolId = new int[SOUND_EFFECT_FILES.size()];
5024 for (int fileIdx = 0; fileIdx < SOUND_EFFECT_FILES.size(); fileIdx++) {
5025 poolId[fileIdx] = -1;
5026 }
5027 /*
5028 * Effects whose value in SOUND_EFFECT_FILES_MAP[effect][1] is -1 must be loaded.
5029 * If load succeeds, value in SOUND_EFFECT_FILES_MAP[effect][1] is > 0:
5030 * this indicates we have a valid sample loaded for this effect.
5031 */
5032
5033 int numSamples = 0;
5034 for (int effect = 0; effect < AudioManager.NUM_SOUND_EFFECTS; effect++) {
5035 // Do not load sample if this effect uses the MediaPlayer
5036 if (SOUND_EFFECT_FILES_MAP[effect][1] == 0) {
5037 continue;
5038 }
5039 if (poolId[SOUND_EFFECT_FILES_MAP[effect][0]] == -1) {
Jaekyun Seokc31033f2018-01-15 14:53:17 +09005040 String filePath = getSoundEffectFilePath(effect);
Eric Laurent5d3eb44a2013-03-21 15:35:10 -07005041 int sampleId = mSoundPool.load(filePath, 0);
5042 if (sampleId <= 0) {
5043 Log.w(TAG, "Soundpool could not load file: "+filePath);
5044 } else {
5045 SOUND_EFFECT_FILES_MAP[effect][1] = sampleId;
5046 poolId[SOUND_EFFECT_FILES_MAP[effect][0]] = sampleId;
5047 numSamples++;
5048 }
5049 } else {
5050 SOUND_EFFECT_FILES_MAP[effect][1] =
5051 poolId[SOUND_EFFECT_FILES_MAP[effect][0]];
5052 }
5053 }
5054 // wait for all samples to be loaded
5055 if (numSamples > 0) {
5056 mSoundPoolCallBack.setSamples(poolId);
5057
5058 attempts = 3;
5059 status = 1;
5060 while ((status == 1) && (attempts-- > 0)) {
5061 try {
Glenn Kasten167d1a22013-07-23 16:24:41 -07005062 mSoundEffectsLock.wait(SOUND_EFFECTS_LOAD_TIMEOUT_MS);
Eric Laurent5d3eb44a2013-03-21 15:35:10 -07005063 status = mSoundPoolCallBack.status();
5064 } catch (InterruptedException e) {
5065 Log.w(TAG, "Interrupted while waiting sound pool callback.");
5066 }
5067 }
5068 } else {
5069 status = -1;
5070 }
5071
5072 if (mSoundPoolLooper != null) {
5073 mSoundPoolLooper.quit();
5074 mSoundPoolLooper = null;
5075 }
5076 mSoundPoolListenerThread = null;
5077 if (status != 0) {
5078 Log.w(TAG,
5079 "onLoadSoundEffects(), Error "+status+ " while loading samples");
5080 for (int effect = 0; effect < AudioManager.NUM_SOUND_EFFECTS; effect++) {
5081 if (SOUND_EFFECT_FILES_MAP[effect][1] > 0) {
5082 SOUND_EFFECT_FILES_MAP[effect][1] = -1;
5083 }
5084 }
5085
5086 mSoundPool.release();
5087 mSoundPool = null;
5088 }
5089 }
5090 return (status == 0);
5091 }
5092
5093 /**
5094 * Unloads samples from the sound pool.
5095 * This method can be called to free some memory when
5096 * sound effects are disabled.
5097 */
5098 private void onUnloadSoundEffects() {
5099 synchronized (mSoundEffectsLock) {
5100 if (mSoundPool == null) {
5101 return;
5102 }
5103
5104 int[] poolId = new int[SOUND_EFFECT_FILES.size()];
5105 for (int fileIdx = 0; fileIdx < SOUND_EFFECT_FILES.size(); fileIdx++) {
5106 poolId[fileIdx] = 0;
5107 }
5108
5109 for (int effect = 0; effect < AudioManager.NUM_SOUND_EFFECTS; effect++) {
5110 if (SOUND_EFFECT_FILES_MAP[effect][1] <= 0) {
5111 continue;
5112 }
5113 if (poolId[SOUND_EFFECT_FILES_MAP[effect][0]] == 0) {
5114 mSoundPool.unload(SOUND_EFFECT_FILES_MAP[effect][1]);
5115 SOUND_EFFECT_FILES_MAP[effect][1] = -1;
5116 poolId[SOUND_EFFECT_FILES_MAP[effect][0]] = -1;
5117 }
5118 }
5119 mSoundPool.release();
5120 mSoundPool = null;
5121 }
5122 }
5123
5124 private void onPlaySoundEffect(int effectType, int volume) {
5125 synchronized (mSoundEffectsLock) {
5126
5127 onLoadSoundEffects();
5128
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005129 if (mSoundPool == null) {
5130 return;
5131 }
Eric Laurenta2ef57d2009-09-28 04:46:10 -07005132 float volFloat;
Eric Laurent25101b02011-02-02 09:33:30 -08005133 // use default if volume is not specified by caller
Eric Laurenta2ef57d2009-09-28 04:46:10 -07005134 if (volume < 0) {
Jean-Michel Trivif2b0c112012-07-09 11:59:11 -07005135 volFloat = (float)Math.pow(10, (float)sSoundEffectVolumeDb/20);
Eric Laurenta2ef57d2009-09-28 04:46:10 -07005136 } else {
RoboErik8a2cfc32014-05-16 11:19:38 -07005137 volFloat = volume / 1000.0f;
Eric Laurenta2ef57d2009-09-28 04:46:10 -07005138 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005139
5140 if (SOUND_EFFECT_FILES_MAP[effectType][1] > 0) {
Eric Laurent5d3eb44a2013-03-21 15:35:10 -07005141 mSoundPool.play(SOUND_EFFECT_FILES_MAP[effectType][1],
5142 volFloat, volFloat, 0, 0, 1.0f);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005143 } else {
5144 MediaPlayer mediaPlayer = new MediaPlayer();
Glenn Kasten62b9aec2011-11-07 11:10:16 -08005145 try {
Jaekyun Seokc31033f2018-01-15 14:53:17 +09005146 String filePath = getSoundEffectFilePath(effectType);
Glenn Kasten62b9aec2011-11-07 11:10:16 -08005147 mediaPlayer.setDataSource(filePath);
5148 mediaPlayer.setAudioStreamType(AudioSystem.STREAM_SYSTEM);
5149 mediaPlayer.prepare();
Glenn Kasten068225d2012-02-27 16:21:04 -08005150 mediaPlayer.setVolume(volFloat);
Glenn Kasten62b9aec2011-11-07 11:10:16 -08005151 mediaPlayer.setOnCompletionListener(new OnCompletionListener() {
5152 public void onCompletion(MediaPlayer mp) {
5153 cleanupPlayer(mp);
5154 }
5155 });
5156 mediaPlayer.setOnErrorListener(new OnErrorListener() {
5157 public boolean onError(MediaPlayer mp, int what, int extra) {
5158 cleanupPlayer(mp);
5159 return true;
5160 }
5161 });
5162 mediaPlayer.start();
5163 } catch (IOException ex) {
5164 Log.w(TAG, "MediaPlayer IOException: "+ex);
5165 } catch (IllegalArgumentException ex) {
5166 Log.w(TAG, "MediaPlayer IllegalArgumentException: "+ex);
5167 } catch (IllegalStateException ex) {
5168 Log.w(TAG, "MediaPlayer IllegalStateException: "+ex);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005169 }
5170 }
5171 }
5172 }
5173
5174 private void cleanupPlayer(MediaPlayer mp) {
5175 if (mp != null) {
5176 try {
5177 mp.stop();
5178 mp.release();
5179 } catch (IllegalStateException ex) {
5180 Log.w(TAG, "MediaPlayer IllegalStateException: "+ex);
5181 }
5182 }
5183 }
5184
Eric Laurent05274f32012-11-29 12:48:18 -08005185 private void onPersistSafeVolumeState(int state) {
5186 Settings.Global.putInt(mContentResolver,
5187 Settings.Global.AUDIO_SAFE_VOLUME_STATE,
5188 state);
5189 }
5190
Jean-Michel Trivi7ed71472018-02-02 16:52:09 -08005191 private void onNotifyVolumeEvent(@NonNull IAudioPolicyCallback apc,
5192 @AudioManager.VolumeAdjustment int direction) {
5193 try {
5194 apc.notifyVolumeAdjust(direction);
5195 } catch(Exception e) {
5196 // nothing we can do about this. Do not log error, too much potential for spam
5197 }
5198 }
5199
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005200 @Override
5201 public void handleMessage(Message msg) {
Eric Laurentafbb0472011-12-15 09:04:23 -08005202 switch (msg.what) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005203
Eric Laurent9bc8358d2011-11-18 16:43:31 -08005204 case MSG_SET_DEVICE_VOLUME:
5205 setDeviceVolume((VolumeStreamState) msg.obj, msg.arg1);
5206 break;
5207
5208 case MSG_SET_ALL_VOLUMES:
5209 setAllVolumes((VolumeStreamState) msg.obj);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005210 break;
5211
5212 case MSG_PERSIST_VOLUME:
Eric Laurent42b041e2013-03-29 11:36:03 -07005213 persistVolume((VolumeStreamState) msg.obj, msg.arg1);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005214 break;
5215
5216 case MSG_PERSIST_RINGER_MODE:
Glenn Kastenba195eb2011-12-13 09:30:40 -08005217 // note that the value persisted is the current ringer mode, not the
5218 // value of ringer mode as of the time the request was made to persist
John Spurlock661f2cf2014-11-17 10:29:10 -05005219 persistRingerMode(getRingerModeInternal());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005220 break;
5221
Andy Hunged0ea402015-10-30 14:11:46 -07005222 case MSG_AUDIO_SERVER_DIED:
5223 onAudioServerDied();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005224 break;
5225
Eric Laurent1d3cdce2018-01-20 10:31:21 -08005226 case MSG_DISPATCH_AUDIO_SERVER_STATE:
5227 onDispatchAudioServerStateChange(msg.arg1 == 1);
5228 break;
5229
Eric Laurent5d3eb44a2013-03-21 15:35:10 -07005230 case MSG_UNLOAD_SOUND_EFFECTS:
5231 onUnloadSoundEffects();
5232 break;
5233
Eric Laurent117b7bb2011-01-16 17:07:27 -08005234 case MSG_LOAD_SOUND_EFFECTS:
Eric Laurent5d3eb44a2013-03-21 15:35:10 -07005235 //FIXME: onLoadSoundEffects() should be executed in a separate thread as it
5236 // can take several dozens of milliseconds to complete
5237 boolean loaded = onLoadSoundEffects();
5238 if (msg.obj != null) {
5239 LoadSoundEffectReply reply = (LoadSoundEffectReply)msg.obj;
5240 synchronized (reply) {
5241 reply.mStatus = loaded ? 0 : -1;
5242 reply.notify();
5243 }
5244 }
Eric Laurent117b7bb2011-01-16 17:07:27 -08005245 break;
5246
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005247 case MSG_PLAY_SOUND_EFFECT:
Eric Laurent5d3eb44a2013-03-21 15:35:10 -07005248 onPlaySoundEffect(msg.arg1, msg.arg2);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005249 break;
Jean-Michel Trivi4c637b92010-04-12 18:44:10 -07005250
Eric Laurentfa640152011-03-12 15:59:51 -08005251 case MSG_SET_FORCE_USE:
Jean-Michel Trivi58850372018-09-14 16:01:28 -07005252 {
5253 final String eventSource = (String) msg.obj;
5254 final int useCase = msg.arg1;
5255 final int config = msg.arg2;
5256 if (useCase == AudioSystem.FOR_MEDIA) {
5257 Log.wtf(TAG, "Invalid force use FOR_MEDIA in AudioService from "
5258 + eventSource);
5259 break;
Paul McLean10804eb2015-01-28 11:16:35 -08005260 }
Jean-Michel Trivi58850372018-09-14 16:01:28 -07005261 sForceUseLogger.log(
5262 new AudioServiceEvents.ForceUseEvent(useCase, config, eventSource));
5263 AudioSystem.setForceUse(useCase, config);
5264 }
Aniket Kumar Lataa8439e22019-01-11 03:59:00 -08005265 break;
5266
Jean-Michel Trivi92ed7bf2017-06-26 19:32:38 -07005267 case MSG_DISABLE_AUDIO_FOR_UID:
5268 mPlaybackMonitor.disableAudioForUid( msg.arg1 == 1 /* disable */,
5269 msg.arg2 /* uid */);
5270 mAudioEventWakeLock.release();
5271 break;
5272
Eric Laurentc34dcc12012-09-10 13:51:52 -07005273 case MSG_CHECK_MUSIC_ACTIVE:
John Spurlock90874332015-03-10 16:00:54 -04005274 onCheckMusicActive((String) msg.obj);
Eric Laurentc34dcc12012-09-10 13:51:52 -07005275 break;
Eric Laurent5bfaeae2012-09-21 18:44:48 -07005276
Eric Laurentd640bd32012-09-28 18:01:48 -07005277 case MSG_CONFIGURE_SAFE_MEDIA_VOLUME_FORCED:
5278 case MSG_CONFIGURE_SAFE_MEDIA_VOLUME:
John Spurlock90874332015-03-10 16:00:54 -04005279 onConfigureSafeVolume((msg.what == MSG_CONFIGURE_SAFE_MEDIA_VOLUME_FORCED),
5280 (String) msg.obj);
Eric Laurentd640bd32012-09-28 18:01:48 -07005281 break;
Eric Laurent05274f32012-11-29 12:48:18 -08005282 case MSG_PERSIST_SAFE_VOLUME_STATE:
5283 onPersistSafeVolumeState(msg.arg1);
5284 break;
Jean-Michel Trivia578c482012-12-28 11:19:49 -08005285
Eric Laurent4a5eeb92014-05-06 10:49:04 -07005286 case MSG_SYSTEM_READY:
5287 onSystemReady();
5288 break;
John Spurlockaa5ee4d2014-07-25 13:05:12 -04005289
Eric Laurent0867bed2015-05-20 14:49:08 -07005290 case MSG_INDICATE_SYSTEM_READY:
5291 onIndicateSystemReady();
5292 break;
5293
Jean-Michel Trivi1ab43f62017-04-27 15:37:34 -07005294 case MSG_ACCESSORY_PLUG_MEDIA_UNMUTE:
5295 onAccessoryPlugMediaUnmute(msg.arg1);
5296 break;
5297
John Spurlockaa5ee4d2014-07-25 13:05:12 -04005298 case MSG_PERSIST_MUSIC_ACTIVE_MS:
5299 final int musicActiveMs = msg.arg1;
5300 Settings.Secure.putIntForUser(mContentResolver,
5301 Settings.Secure.UNSAFE_VOLUME_MUSIC_ACTIVE_MS, musicActiveMs,
5302 UserHandle.USER_CURRENT);
5303 break;
Eric Laurentc0232482016-03-15 18:19:23 -07005304
RoboErik5452e252015-02-06 15:33:53 -08005305 case MSG_UNMUTE_STREAM:
5306 onUnmuteStream(msg.arg1, msg.arg2);
5307 break;
Eric Laurentc0232482016-03-15 18:19:23 -07005308
Jean-Michel Trivi5a561092015-04-23 18:48:08 -07005309 case MSG_DYN_POLICY_MIX_STATE_UPDATE:
5310 onDynPolicyMixStateUpdate((String) msg.obj, msg.arg1);
5311 break;
Jean-Michel Trivi7ed71472018-02-02 16:52:09 -08005312
5313 case MSG_NOTIFY_VOL_EVENT:
5314 onNotifyVolumeEvent((IAudioPolicyCallback) msg.obj, msg.arg1);
5315 break;
jiabin39940752018-04-02 18:18:45 -07005316
5317 case MSG_ENABLE_SURROUND_FORMATS:
5318 onEnableSurroundFormats((ArrayList<Integer>) msg.obj);
5319 break;
Jean-Michel Trivica49d312019-02-14 15:55:39 -08005320
5321 case MSG_UPDATE_RINGER_MODE:
5322 onUpdateRingerModeServiceInt();
5323 break;
Jean-Michel Trivi5bbcd442019-04-18 12:07:34 -07005324
5325 case MSG_SET_DEVICE_STREAM_VOLUME:
5326 onSetVolumeIndexOnDevice((DeviceVolumeUpdate) msg.obj);
5327 break;
5328
5329 case MSG_OBSERVE_DEVICES_FOR_ALL_STREAMS:
5330 onObserveDevicesForAllStreams();
5331 break;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005332 }
5333 }
5334 }
5335
Jason Parekhb1096152009-03-24 17:48:25 -07005336 private class SettingsObserver extends ContentObserver {
Eric Laurenta553c252009-07-17 12:17:14 -07005337
Jason Parekhb1096152009-03-24 17:48:25 -07005338 SettingsObserver() {
5339 super(new Handler());
Beverlyd6964762018-02-16 14:07:03 -05005340 mContentResolver.registerContentObserver(Settings.Global.getUriFor(
5341 Settings.Global.ZEN_MODE), false, this);
5342 mContentResolver.registerContentObserver(Settings.Global.getUriFor(
5343 Settings.Global.ZEN_MODE_CONFIG_ETAG), false, this);
Jason Parekhb1096152009-03-24 17:48:25 -07005344 mContentResolver.registerContentObserver(Settings.System.getUriFor(
5345 Settings.System.MODE_RINGER_STREAMS_AFFECTED), false, this);
Eric Laurent7ee1e4f2012-10-26 18:11:21 -07005346 mContentResolver.registerContentObserver(Settings.Global.getUriFor(
5347 Settings.Global.DOCK_AUDIO_MEDIA_ENABLED), false, this);
Andy Hung7b98e9a2016-02-25 18:34:50 -08005348 mContentResolver.registerContentObserver(Settings.System.getUriFor(
5349 Settings.System.MASTER_MONO), false, this);
Edward Savage-Jones35c292f2017-01-13 09:04:34 +01005350 mContentResolver.registerContentObserver(Settings.System.getUriFor(
5351 Settings.System.MASTER_BALANCE), false, this);
Phil Burked43bf52016-03-01 17:01:35 -08005352
5353 mEncodedSurroundMode = Settings.Global.getInt(
5354 mContentResolver, Settings.Global.ENCODED_SURROUND_OUTPUT,
5355 Settings.Global.ENCODED_SURROUND_OUTPUT_AUTO);
5356 mContentResolver.registerContentObserver(Settings.Global.getUriFor(
5357 Settings.Global.ENCODED_SURROUND_OUTPUT), false, this);
jiabin39940752018-04-02 18:18:45 -07005358
5359 mEnabledSurroundFormats = Settings.Global.getString(
5360 mContentResolver, Settings.Global.ENCODED_SURROUND_OUTPUT_ENABLED_FORMATS);
5361 mContentResolver.registerContentObserver(Settings.Global.getUriFor(
5362 Settings.Global.ENCODED_SURROUND_OUTPUT_ENABLED_FORMATS), false, this);
Eric Laurent1c9c1d52018-10-17 10:06:46 -07005363
5364 mContentResolver.registerContentObserver(Settings.Secure.getUriFor(
5365 Settings.Secure.VOICE_INTERACTION_SERVICE), false, this);
Jason Parekhb1096152009-03-24 17:48:25 -07005366 }
5367
5368 @Override
5369 public void onChange(boolean selfChange) {
5370 super.onChange(selfChange);
Glenn Kastenba195eb2011-12-13 09:30:40 -08005371 // FIXME This synchronized is not necessary if mSettingsLock only protects mRingerMode.
Beverlyd6964762018-02-16 14:07:03 -05005372 // However there appear to be some missing locks around mRingerAndZenModeMutedStreams
Glenn Kastenba195eb2011-12-13 09:30:40 -08005373 // and mRingerModeAffectedStreams, so will leave this synchronized for now.
Beverlyd6964762018-02-16 14:07:03 -05005374 // mRingerAndZenModeMutedStreams and mMuteAffectedStreams are safe (only accessed once).
Eric Laurenta553c252009-07-17 12:17:14 -07005375 synchronized (mSettingsLock) {
Beverlyd6964762018-02-16 14:07:03 -05005376 if (updateRingerAndZenModeAffectedStreams()) {
Eric Laurenta553c252009-07-17 12:17:14 -07005377 /*
5378 * Ensure all stream types that should be affected by ringer mode
5379 * are in the proper state.
5380 */
John Spurlock661f2cf2014-11-17 10:29:10 -05005381 setRingerModeInt(getRingerModeInternal(), false);
Eric Laurenta553c252009-07-17 12:17:14 -07005382 }
Eric Laurent7ee1e4f2012-10-26 18:11:21 -07005383 readDockAudioSettings(mContentResolver);
Andy Hung7b98e9a2016-02-25 18:34:50 -08005384 updateMasterMono(mContentResolver);
Edward Savage-Jones35c292f2017-01-13 09:04:34 +01005385 updateMasterBalance(mContentResolver);
Phil Burked43bf52016-03-01 17:01:35 -08005386 updateEncodedSurroundOutput();
jiabin39940752018-04-02 18:18:45 -07005387 sendEnabledSurroundFormats(mContentResolver, mSurroundModeChanged);
Eric Laurent1c9c1d52018-10-17 10:06:46 -07005388 updateAssistantUId(false);
Phil Burked43bf52016-03-01 17:01:35 -08005389 }
5390 }
5391
5392 private void updateEncodedSurroundOutput() {
5393 int newSurroundMode = Settings.Global.getInt(
5394 mContentResolver, Settings.Global.ENCODED_SURROUND_OUTPUT,
5395 Settings.Global.ENCODED_SURROUND_OUTPUT_AUTO);
5396 // Did it change?
5397 if (mEncodedSurroundMode != newSurroundMode) {
5398 // Send to AudioPolicyManager
Jean-Michel Trivi011f39e2017-08-19 18:08:06 -07005399 sendEncodedSurroundMode(newSurroundMode, "SettingsObserver");
Jean-Michel Trivi58850372018-09-14 16:01:28 -07005400 mDeviceBroker.toggleHdmiIfConnected_Async();
Phil Burked43bf52016-03-01 17:01:35 -08005401 mEncodedSurroundMode = newSurroundMode;
jiabin39940752018-04-02 18:18:45 -07005402 mSurroundModeChanged = true;
5403 } else {
5404 mSurroundModeChanged = false;
Eric Laurenta553c252009-07-17 12:17:14 -07005405 }
Jason Parekhb1096152009-03-24 17:48:25 -07005406 }
Jason Parekhb1096152009-03-24 17:48:25 -07005407 }
Eric Laurenta553c252009-07-17 12:17:14 -07005408
John Du5a0cf7a2013-07-19 11:30:34 -07005409 public void avrcpSupportsAbsoluteVolume(String address, boolean support) {
5410 // address is not used for now, but may be used when multiple a2dp devices are supported
Jean-Michel Trivi58850372018-09-14 16:01:28 -07005411 mDeviceBroker.setAvrcpAbsoluteVolumeSupported(support);
5412 sendMsg(mAudioHandler, MSG_SET_DEVICE_VOLUME, SENDMSG_QUEUE,
Eric Laurent3e6fb632018-05-21 09:28:46 -07005413 AudioSystem.DEVICE_OUT_BLUETOOTH_A2DP, 0,
5414 mStreamStates[AudioSystem.STREAM_MUSIC], 0);
Eric Laurentb1fbaac2012-05-29 09:24:28 -07005415 }
5416
Jean-Michel Trivi7db2d8f2018-03-06 10:30:59 -08005417 /**
5418 * @return true if there is currently a registered dynamic mixing policy that affects media
5419 */
Jean-Michel Trivi58850372018-09-14 16:01:28 -07005420 /*package*/ boolean hasMediaDynamicPolicy() {
Jean-Michel Trivi7db2d8f2018-03-06 10:30:59 -08005421 synchronized (mAudioPolicies) {
5422 if (mAudioPolicies.isEmpty()) {
5423 return false;
5424 }
5425 final Collection<AudioPolicyProxy> appColl = mAudioPolicies.values();
5426 for (AudioPolicyProxy app : appColl) {
5427 if (app.hasMixAffectingUsage(AudioAttributes.USAGE_MEDIA)) {
5428 return true;
5429 }
5430 }
5431 return false;
5432 }
5433 }
5434
Jean-Michel Trivi58850372018-09-14 16:01:28 -07005435 /*package*/ void checkMusicActive(int deviceType, String caller) {
5436 if ((deviceType & mSafeMediaVolumeDevices) != 0) {
5437 sendMsg(mAudioHandler,
5438 MSG_CHECK_MUSIC_ACTIVE,
5439 SENDMSG_REPLACE,
5440 0,
5441 0,
5442 caller,
5443 MUSIC_ACTIVE_POLL_PERIOD_MS);
Dianne Hackborn632ca412012-06-14 19:34:10 -07005444 }
Eric Laurenteab40d12017-06-09 12:45:21 -07005445 }
5446
Eric Laurenta553c252009-07-17 12:17:14 -07005447 /**
5448 * Receiver for misc intent broadcasts the Phone app cares about.
5449 */
5450 private class AudioServiceBroadcastReceiver extends BroadcastReceiver {
5451 @Override
5452 public void onReceive(Context context, Intent intent) {
Jean-Michel Trivi58850372018-09-14 16:01:28 -07005453 final String action = intent.getAction();
Eric Laurentae4506e2014-05-29 16:04:32 -07005454 int outDevice;
5455 int inDevice;
Eric Laurent59f48272012-04-05 19:42:21 -07005456 int state;
Eric Laurenta553c252009-07-17 12:17:14 -07005457
Jean-Michel Trivi758559e2010-03-09 09:26:08 -08005458 if (action.equals(Intent.ACTION_DOCK_EVENT)) {
5459 int dockState = intent.getIntExtra(Intent.EXTRA_DOCK_STATE,
5460 Intent.EXTRA_DOCK_STATE_UNDOCKED);
5461 int config;
5462 switch (dockState) {
5463 case Intent.EXTRA_DOCK_STATE_DESK:
5464 config = AudioSystem.FORCE_BT_DESK_DOCK;
5465 break;
5466 case Intent.EXTRA_DOCK_STATE_CAR:
5467 config = AudioSystem.FORCE_BT_CAR_DOCK;
5468 break;
Praveen Bharathi21e941b2010-10-06 15:23:14 -05005469 case Intent.EXTRA_DOCK_STATE_LE_DESK:
Eric Laurent08ed1b92012-11-05 14:54:12 -08005470 config = AudioSystem.FORCE_ANALOG_DOCK;
Praveen Bharathi21e941b2010-10-06 15:23:14 -05005471 break;
5472 case Intent.EXTRA_DOCK_STATE_HE_DESK:
5473 config = AudioSystem.FORCE_DIGITAL_DOCK;
5474 break;
Jean-Michel Trivi758559e2010-03-09 09:26:08 -08005475 case Intent.EXTRA_DOCK_STATE_UNDOCKED:
5476 default:
5477 config = AudioSystem.FORCE_NONE;
5478 }
Eric Laurent08ed1b92012-11-05 14:54:12 -08005479 // Low end docks have a menu to enable or disable audio
5480 // (see mDockAudioMediaEnabled)
Jean-Michel Trivi58850372018-09-14 16:01:28 -07005481 if (!((dockState == Intent.EXTRA_DOCK_STATE_LE_DESK)
5482 || ((dockState == Intent.EXTRA_DOCK_STATE_UNDOCKED)
5483 && (mDockState == Intent.EXTRA_DOCK_STATE_LE_DESK)))) {
5484 mDeviceBroker.setForceUse_Async(AudioSystem.FOR_DOCK, config,
5485 "ACTION_DOCK_EVENT intent");
Eric Laurent08ed1b92012-11-05 14:54:12 -08005486 }
5487 mDockState = dockState;
Jean-Michel Trivi58850372018-09-14 16:01:28 -07005488 } else if (action.equals(BluetoothHeadset.ACTION_ACTIVE_DEVICE_CHANGED)
5489 || action.equals(BluetoothHeadset.ACTION_AUDIO_STATE_CHANGED)) {
5490 mDeviceBroker.receiveBtEvent(intent);
Eric Laurent950e8cb2011-10-13 08:57:54 -07005491 } else if (action.equals(Intent.ACTION_SCREEN_ON)) {
Jon Eklund318f0fe2014-01-23 17:53:48 -06005492 if (mMonitorRotation) {
Jean-Michel Trivi24806db2015-10-01 15:00:59 -07005493 RotationHelper.enable();
Jon Eklund318f0fe2014-01-23 17:53:48 -06005494 }
Eric Laurent950e8cb2011-10-13 08:57:54 -07005495 AudioSystem.setParameters("screen_state=on");
5496 } else if (action.equals(Intent.ACTION_SCREEN_OFF)) {
Jon Eklund318f0fe2014-01-23 17:53:48 -06005497 if (mMonitorRotation) {
5498 //reduce wakeups (save current) by only listening when display is on
Jean-Michel Trivi24806db2015-10-01 15:00:59 -07005499 RotationHelper.disable();
Jon Eklund318f0fe2014-01-23 17:53:48 -06005500 }
Eric Laurent950e8cb2011-10-13 08:57:54 -07005501 AudioSystem.setParameters("screen_state=off");
Dianne Hackborn961cae92013-03-20 14:59:43 -07005502 } else if (action.equals(Intent.ACTION_CONFIGURATION_CHANGED)) {
Jean-Michel Trivif26f0172012-04-25 16:23:20 -07005503 handleConfigurationChanged(context);
Eric Laurentbc0fab1f2012-09-19 11:24:41 -07005504 } else if (action.equals(Intent.ACTION_USER_SWITCHED)) {
Yasuhiro Matsuda4ced7192015-07-10 22:08:44 +09005505 if (mUserSwitchedReceived) {
5506 // attempt to stop music playback for background user except on first user
5507 // switch (i.e. first boot)
Jean-Michel Trivib9465152019-02-06 15:20:19 -08005508 mDeviceBroker.postBroadcastBecomingNoisy();
Yasuhiro Matsuda4ced7192015-07-10 22:08:44 +09005509 }
5510 mUserSwitchedReceived = true;
Jean-Michel Trivif4a8eb22012-10-29 12:42:55 -07005511 // the current audio focus owner is no longer valid
Jean-Michel Trivifa9a6982013-06-27 16:22:58 -07005512 mMediaFocusControl.discardAudioFocusOwner();
Jean-Michel Trivif4a8eb22012-10-29 12:42:55 -07005513
Eric Laurent5bfaeae2012-09-21 18:44:48 -07005514 // load volume settings for new user
Eric Laurentbc0fab1f2012-09-19 11:24:41 -07005515 readAudioSettings(true /*userSwitch*/);
5516 // preserve STREAM_MUSIC volume from one user to the next.
5517 sendMsg(mAudioHandler,
5518 MSG_SET_ALL_VOLUMES,
5519 SENDMSG_QUEUE,
5520 0,
5521 0,
5522 mStreamStates[AudioSystem.STREAM_MUSIC], 0);
Fyodor Kupolovb5013302015-04-17 17:59:14 -07005523 } else if (action.equals(Intent.ACTION_USER_BACKGROUND)) {
5524 // Disable audio recording for the background user/profile
5525 int userId = intent.getIntExtra(Intent.EXTRA_USER_HANDLE, -1);
5526 if (userId >= 0) {
5527 // TODO Kill recording streams instead of killing processes holding permission
5528 UserInfo userInfo = UserManagerService.getInstance().getUserInfo(userId);
5529 killBackgroundUserProcessesWithRecordAudioPermission(userInfo);
5530 }
Makoto Onukiac65e1e2015-11-20 15:33:17 -08005531 UserManagerService.getInstance().setUserRestriction(
Fyodor Kupolovb5013302015-04-17 17:59:14 -07005532 UserManager.DISALLOW_RECORD_AUDIO, true, userId);
5533 } else if (action.equals(Intent.ACTION_USER_FOREGROUND)) {
5534 // Enable audio recording for foreground user/profile
5535 int userId = intent.getIntExtra(Intent.EXTRA_USER_HANDLE, -1);
Makoto Onukiac65e1e2015-11-20 15:33:17 -08005536 UserManagerService.getInstance().setUserRestriction(
Fyodor Kupolovb5013302015-04-17 17:59:14 -07005537 UserManager.DISALLOW_RECORD_AUDIO, false, userId);
Eric Laurentb70b78a2016-01-13 19:16:04 -08005538 } else if (action.equals(BluetoothAdapter.ACTION_STATE_CHANGED)) {
5539 state = intent.getIntExtra(BluetoothAdapter.EXTRA_STATE, -1);
5540 if (state == BluetoothAdapter.STATE_OFF ||
5541 state == BluetoothAdapter.STATE_TURNING_OFF) {
Jean-Michel Trivi58850372018-09-14 16:01:28 -07005542 mDeviceBroker.disconnectAllBluetoothProfiles();
Eric Laurentb70b78a2016-01-13 19:16:04 -08005543 }
Marco Nelissenfb6df0b2017-02-15 15:25:24 -08005544 } else if (action.equals(AudioEffect.ACTION_OPEN_AUDIO_EFFECT_CONTROL_SESSION) ||
5545 action.equals(AudioEffect.ACTION_CLOSE_AUDIO_EFFECT_CONTROL_SESSION)) {
5546 handleAudioEffectBroadcast(context, intent);
Jean-Michel Trivib2251822019-02-06 07:32:06 -08005547 } else if (action.equals(Intent.ACTION_PACKAGES_SUSPENDED)) {
5548 final int[] suspendedUids = intent.getIntArrayExtra(Intent.EXTRA_CHANGED_UID_LIST);
5549 final String[] suspendedPackages =
5550 intent.getStringArrayExtra(Intent.EXTRA_CHANGED_PACKAGE_LIST);
5551 if (suspendedPackages == null || suspendedUids == null
5552 || suspendedPackages.length != suspendedUids.length) {
5553 return;
5554 }
5555 for (int i = 0; i < suspendedUids.length; i++) {
5556 if (!TextUtils.isEmpty(suspendedPackages[i])) {
5557 mMediaFocusControl.noFocusForSuspendedApp(
5558 suspendedPackages[i], suspendedUids[i]);
5559 }
5560 }
Eric Laurenta553c252009-07-17 12:17:14 -07005561 }
5562 }
Paul McLeanc837a452014-04-09 09:04:43 -07005563 } // end class AudioServiceBroadcastReceiver
Jean-Michel Trivid5176cf2010-01-28 11:56:42 -08005564
Makoto Onukid45a4a22015-11-02 17:17:38 -08005565 private class AudioServiceUserRestrictionsListener implements UserRestrictionsListener {
5566
5567 @Override
5568 public void onUserRestrictionsChanged(int userId, Bundle newRestrictions,
5569 Bundle prevRestrictions) {
5570 // Update mic mute state.
5571 {
5572 final boolean wasRestricted =
5573 prevRestrictions.getBoolean(UserManager.DISALLOW_UNMUTE_MICROPHONE);
5574 final boolean isRestricted =
5575 newRestrictions.getBoolean(UserManager.DISALLOW_UNMUTE_MICROPHONE);
5576 if (wasRestricted != isRestricted) {
5577 setMicrophoneMuteNoCallerCheck(isRestricted, userId);
5578 }
5579 }
5580
5581 // Update speaker mute state.
5582 {
5583 final boolean wasRestricted =
Tony Makc1205112016-07-22 16:02:59 +01005584 prevRestrictions.getBoolean(UserManager.DISALLOW_ADJUST_VOLUME)
Esteban Talavera492b4722017-02-13 14:59:45 +00005585 || prevRestrictions.getBoolean(UserManager.DISALLOW_UNMUTE_DEVICE);
Makoto Onukid45a4a22015-11-02 17:17:38 -08005586 final boolean isRestricted =
Tony Makc1205112016-07-22 16:02:59 +01005587 newRestrictions.getBoolean(UserManager.DISALLOW_ADJUST_VOLUME)
Esteban Talavera492b4722017-02-13 14:59:45 +00005588 || newRestrictions.getBoolean(UserManager.DISALLOW_UNMUTE_DEVICE);
Makoto Onukid45a4a22015-11-02 17:17:38 -08005589 if (wasRestricted != isRestricted) {
5590 setMasterMuteInternalNoCallerCheck(isRestricted, /* flags =*/ 0, userId);
5591 }
5592 }
5593 }
5594 } // end class AudioServiceUserRestrictionsListener
5595
Marco Nelissenfb6df0b2017-02-15 15:25:24 -08005596 private void handleAudioEffectBroadcast(Context context, Intent intent) {
5597 String target = intent.getPackage();
5598 if (target != null) {
5599 Log.w(TAG, "effect broadcast already targeted to " + target);
5600 return;
5601 }
5602 intent.addFlags(Intent.FLAG_INCLUDE_STOPPED_PACKAGES);
5603 // TODO this should target a user-selected panel
5604 List<ResolveInfo> ril = context.getPackageManager().queryBroadcastReceivers(
5605 intent, 0 /* flags */);
5606 if (ril != null && ril.size() != 0) {
5607 ResolveInfo ri = ril.get(0);
5608 if (ri != null && ri.activityInfo != null && ri.activityInfo.packageName != null) {
5609 intent.setPackage(ri.activityInfo.packageName);
5610 context.sendBroadcastAsUser(intent, UserHandle.ALL);
5611 return;
5612 }
5613 }
5614 Log.w(TAG, "couldn't find receiver package for effect intent");
5615 }
5616
Fyodor Kupolovb5013302015-04-17 17:59:14 -07005617 private void killBackgroundUserProcessesWithRecordAudioPermission(UserInfo oldUser) {
5618 PackageManager pm = mContext.getPackageManager();
5619 // Find the home activity of the user. It should not be killed to avoid expensive restart,
5620 // when the user switches back. For managed profiles, we should kill all recording apps
5621 ComponentName homeActivityName = null;
5622 if (!oldUser.isManagedProfile()) {
Wale Ogunwale6767eae2018-05-03 15:52:51 -07005623 homeActivityName = LocalServices.getService(
5624 ActivityTaskManagerInternal.class).getHomeActivityForUser(oldUser.id);
Fyodor Kupolovb5013302015-04-17 17:59:14 -07005625 }
5626 final String[] permissions = { Manifest.permission.RECORD_AUDIO };
5627 List<PackageInfo> packages;
5628 try {
5629 packages = AppGlobals.getPackageManager()
5630 .getPackagesHoldingPermissions(permissions, 0, oldUser.id).getList();
5631 } catch (RemoteException e) {
5632 throw new AndroidRuntimeException(e);
5633 }
5634 for (int j = packages.size() - 1; j >= 0; j--) {
5635 PackageInfo pkg = packages.get(j);
Fyodor Kupolovbcb6c1e2015-05-11 12:05:15 -07005636 // Skip system processes
5637 if (UserHandle.getAppId(pkg.applicationInfo.uid) < FIRST_APPLICATION_UID) {
5638 continue;
5639 }
Amith Yamasanic1cbaab2015-07-21 11:46:14 -07005640 // Skip packages that have permission to interact across users
5641 if (pm.checkPermission(Manifest.permission.INTERACT_ACROSS_USERS, pkg.packageName)
5642 == PackageManager.PERMISSION_GRANTED) {
5643 continue;
5644 }
Fyodor Kupolovb5013302015-04-17 17:59:14 -07005645 if (homeActivityName != null
5646 && pkg.packageName.equals(homeActivityName.getPackageName())
5647 && pkg.applicationInfo.isSystemApp()) {
5648 continue;
5649 }
5650 try {
Svetoslavaa41add2015-08-06 15:03:55 -07005651 final int uid = pkg.applicationInfo.uid;
Sudheer Shankadc589ac2016-11-10 15:30:17 -08005652 ActivityManager.getService().killUid(UserHandle.getAppId(uid),
Svetoslavaa41add2015-08-06 15:03:55 -07005653 UserHandle.getUserId(uid),
Fyodor Kupolovb5013302015-04-17 17:59:14 -07005654 "killBackgroundUserProcessesWithAudioRecordPermission");
5655 } catch (RemoteException e) {
5656 Log.w(TAG, "Error calling killUid", e);
5657 }
5658 }
5659 }
5660
Jean-Michel Trivi3114ce32012-06-11 15:03:52 -07005661
Jean-Michel Trivifa9a6982013-06-27 16:22:58 -07005662 //==========================================================================================
5663 // Audio Focus
5664 //==========================================================================================
Jean-Michel Trivi9228af62018-01-05 17:06:17 -08005665 /**
5666 * Returns whether a focus request is eligible to force ducking.
5667 * Will return true if:
5668 * - the AudioAttributes have a usage of USAGE_ASSISTANCE_ACCESSIBILITY,
5669 * - the focus request is AUDIOFOCUS_GAIN_TRANSIENT_MAY_DUCK,
5670 * - the associated Bundle has KEY_ACCESSIBILITY_FORCE_FOCUS_DUCKING set to true,
5671 * - the uid of the requester is a known accessibility service or root.
5672 * @param aa AudioAttributes of the focus request
5673 * @param uid uid of the focus requester
5674 * @return true if ducking is to be forced
5675 */
5676 private boolean forceFocusDuckingForAccessibility(@Nullable AudioAttributes aa,
5677 int request, int uid) {
5678 if (aa == null || aa.getUsage() != AudioAttributes.USAGE_ASSISTANCE_ACCESSIBILITY
5679 || request != AudioManager.AUDIOFOCUS_GAIN_TRANSIENT_MAY_DUCK) {
5680 return false;
5681 }
5682 final Bundle extraInfo = aa.getBundle();
5683 if (extraInfo == null ||
5684 !extraInfo.getBoolean(AudioFocusRequest.KEY_ACCESSIBILITY_FORCE_FOCUS_DUCKING)) {
5685 return false;
5686 }
5687 if (uid == 0) {
5688 return true;
5689 }
5690 synchronized (mAccessibilityServiceUidsLock) {
5691 if (mAccessibilityServiceUids != null) {
5692 int callingUid = Binder.getCallingUid();
5693 for (int i = 0; i < mAccessibilityServiceUids.length; i++) {
5694 if (mAccessibilityServiceUids[i] == callingUid) {
5695 return true;
5696 }
5697 }
5698 }
5699 }
5700 return false;
5701 }
5702
Jean-Michel Trivifd6ad742014-11-10 14:38:30 -08005703 public int requestAudioFocus(AudioAttributes aa, int durationHint, IBinder cb,
Jean-Michel Trivi958876f2014-11-16 15:40:22 -08005704 IAudioFocusDispatcher fd, String clientId, String callingPackageName, int flags,
Jean-Michel Trivi461922f2017-04-25 15:23:17 -07005705 IAudioPolicyCallback pcb, int sdk) {
Jean-Michel Trivi958876f2014-11-16 15:40:22 -08005706 // permission checks
5707 if ((flags & AudioManager.AUDIOFOCUS_FLAG_LOCK) == AudioManager.AUDIOFOCUS_FLAG_LOCK) {
John Spurlock61560172015-02-06 19:46:04 -05005708 if (AudioSystem.IN_VOICE_COMM_FOCUS_ID.equals(clientId)) {
Jean-Michel Trivi958876f2014-11-16 15:40:22 -08005709 if (PackageManager.PERMISSION_GRANTED != mContext.checkCallingOrSelfPermission(
5710 android.Manifest.permission.MODIFY_PHONE_STATE)) {
5711 Log.e(TAG, "Invalid permission to (un)lock audio focus", new Exception());
5712 return AudioManager.AUDIOFOCUS_REQUEST_FAILED;
5713 }
5714 } else {
5715 // only a registered audio policy can be used to lock focus
5716 synchronized (mAudioPolicies) {
Jean-Michel Trivi0212be52014-11-24 14:43:10 -08005717 if (!mAudioPolicies.containsKey(pcb.asBinder())) {
5718 Log.e(TAG, "Invalid unregistered AudioPolicy to (un)lock audio focus");
Jean-Michel Trivi958876f2014-11-16 15:40:22 -08005719 return AudioManager.AUDIOFOCUS_REQUEST_FAILED;
5720 }
5721 }
5722 }
5723 }
5724
Jean-Michel Trivib2251822019-02-06 07:32:06 -08005725 if (callingPackageName == null || clientId == null || aa == null) {
5726 Log.e(TAG, "Invalid null parameter to request audio focus");
5727 return AudioManager.AUDIOFOCUS_REQUEST_FAILED;
5728 }
5729
Jean-Michel Trivifd6ad742014-11-10 14:38:30 -08005730 return mMediaFocusControl.requestAudioFocus(aa, durationHint, cb, fd,
Jean-Michel Trivi9228af62018-01-05 17:06:17 -08005731 clientId, callingPackageName, flags, sdk,
5732 forceFocusDuckingForAccessibility(aa, durationHint, Binder.getCallingUid()));
Jean-Michel Trivifa9a6982013-06-27 16:22:58 -07005733 }
5734
Jean-Michel Trivi126cf032017-04-02 23:19:02 -07005735 public int abandonAudioFocus(IAudioFocusDispatcher fd, String clientId, AudioAttributes aa,
5736 String callingPackageName) {
5737 return mMediaFocusControl.abandonAudioFocus(fd, clientId, aa, callingPackageName);
Jean-Michel Trivifa9a6982013-06-27 16:22:58 -07005738 }
5739
5740 public void unregisterAudioFocusClient(String clientId) {
5741 mMediaFocusControl.unregisterAudioFocusClient(clientId);
Jean-Michel Trivi3114ce32012-06-11 15:03:52 -07005742 }
5743
Jean-Michel Trivi23805662013-07-31 14:19:18 -07005744 public int getCurrentAudioFocus() {
5745 return mMediaFocusControl.getCurrentAudioFocus();
5746 }
5747
Jean-Michel Trivi99489cc2017-01-25 19:08:49 -08005748 public int getFocusRampTimeMs(int focusGain, AudioAttributes attr) {
5749 return mMediaFocusControl.getFocusRampTimeMs(focusGain, attr);
5750 }
5751
Jean-Michel Trivic1adecd2019-04-13 17:11:50 -07005752 /*package*/ boolean hasAudioFocusUsers() {
5753 return mMediaFocusControl.hasAudioFocusUsers();
5754 }
5755
Jean-Michel Trivi126cf032017-04-02 23:19:02 -07005756 //==========================================================================================
John Spurlock5e783732015-02-19 10:28:59 -05005757 private boolean readCameraSoundForced() {
5758 return SystemProperties.getBoolean("audio.camerasound.force", false) ||
5759 mContext.getResources().getBoolean(
5760 com.android.internal.R.bool.config_camera_sound_forced);
5761 }
5762
Jean-Michel Trivif26f0172012-04-25 16:23:20 -07005763 //==========================================================================================
5764 // Device orientation
5765 //==========================================================================================
5766 /**
Mikhail Naganovb668bc62018-02-13 13:46:38 -08005767 * Handles device configuration changes that may map to a change in rotation.
5768 * Monitoring rotation is optional, and is defined by the definition and value
5769 * of the "ro.audio.monitorRotation" system property.
Jean-Michel Trivif26f0172012-04-25 16:23:20 -07005770 */
5771 private void handleConfigurationChanged(Context context) {
5772 try {
Mikhail Naganovb668bc62018-02-13 13:46:38 -08005773 // reading new configuration "safely" (i.e. under try catch) in case anything
5774 // goes wrong.
Eric Laurentd640bd32012-09-28 18:01:48 -07005775 Configuration config = context.getResources().getConfiguration();
Eric Laurentd640bd32012-09-28 18:01:48 -07005776 sendMsg(mAudioHandler,
5777 MSG_CONFIGURE_SAFE_MEDIA_VOLUME,
5778 SENDMSG_REPLACE,
5779 0,
5780 0,
John Spurlock90874332015-03-10 16:00:54 -04005781 TAG,
Eric Laurentd640bd32012-09-28 18:01:48 -07005782 0);
Eric Laurentdd45d012012-10-08 09:04:34 -07005783
John Spurlock5e783732015-02-19 10:28:59 -05005784 boolean cameraSoundForced = readCameraSoundForced();
Eric Laurentdd45d012012-10-08 09:04:34 -07005785 synchronized (mSettingsLock) {
Jean-Michel Trivi8719a1d2017-11-06 11:52:51 -08005786 final boolean cameraSoundForcedChanged = (cameraSoundForced != mCameraSoundForced);
5787 mCameraSoundForced = cameraSoundForced;
Eric Laurent8fa4d6f2014-10-30 14:13:03 -07005788 if (cameraSoundForcedChanged) {
Muyuan Li1ed6df62016-06-18 11:16:52 -07005789 if (!mIsSingleVolume) {
Jean-Michel Trivi085346a2018-02-14 10:48:51 -08005790 synchronized (VolumeStreamState.class) {
5791 VolumeStreamState s = mStreamStates[AudioSystem.STREAM_SYSTEM_ENFORCED];
5792 if (cameraSoundForced) {
5793 s.setAllIndexesToMax();
5794 mRingerModeAffectedStreams &=
5795 ~(1 << AudioSystem.STREAM_SYSTEM_ENFORCED);
5796 } else {
5797 s.setAllIndexes(mStreamStates[AudioSystem.STREAM_SYSTEM], TAG);
5798 mRingerModeAffectedStreams |=
5799 (1 << AudioSystem.STREAM_SYSTEM_ENFORCED);
5800 }
Eric Laurent8fa4d6f2014-10-30 14:13:03 -07005801 }
5802 // take new state into account for streams muted by ringer mode
John Spurlock661f2cf2014-11-17 10:29:10 -05005803 setRingerModeInt(getRingerModeInternal(), false);
Eric Laurent8fa4d6f2014-10-30 14:13:03 -07005804 }
Jean-Michel Trivi58850372018-09-14 16:01:28 -07005805 mDeviceBroker.setForceUse_Async(AudioSystem.FOR_SYSTEM,
Eric Laurent8fa4d6f2014-10-30 14:13:03 -07005806 cameraSoundForced ?
5807 AudioSystem.FORCE_SYSTEM_ENFORCED : AudioSystem.FORCE_NONE,
Jean-Michel Trivi58850372018-09-14 16:01:28 -07005808 "handleConfigurationChanged");
Eric Laurent8fa4d6f2014-10-30 14:13:03 -07005809 sendMsg(mAudioHandler,
5810 MSG_SET_ALL_VOLUMES,
5811 SENDMSG_QUEUE,
5812 0,
5813 0,
5814 mStreamStates[AudioSystem.STREAM_SYSTEM_ENFORCED], 0);
Jean-Michel Trivi58850372018-09-14 16:01:28 -07005815
Eric Laurent8fa4d6f2014-10-30 14:13:03 -07005816 }
Eric Laurentdd45d012012-10-08 09:04:34 -07005817 }
John Spurlock3346a802014-05-20 16:25:37 -04005818 mVolumeController.setLayoutDirection(config.getLayoutDirection());
Jean-Michel Trivif26f0172012-04-25 16:23:20 -07005819 } catch (Exception e) {
Jean-Michel Trivibb6f8712013-05-23 15:02:41 -07005820 Log.e(TAG, "Error handling configuration change: ", e);
Jean-Michel Trivif26f0172012-04-25 16:23:20 -07005821 }
5822 }
5823
Jean-Michel Trivid5176cf2010-01-28 11:56:42 -08005824 @Override
Jeff Sharkey098d5802012-04-26 17:30:34 -07005825 public void setRingtonePlayer(IRingtonePlayer player) {
5826 mContext.enforceCallingOrSelfPermission(REMOTE_AUDIO_PLAYBACK, null);
5827 mRingtonePlayer = player;
5828 }
5829
5830 @Override
5831 public IRingtonePlayer getRingtonePlayer() {
5832 return mRingtonePlayer;
5833 }
5834
5835 @Override
Dianne Hackborn632ca412012-06-14 19:34:10 -07005836 public AudioRoutesInfo startWatchingRoutes(IAudioRoutesObserver observer) {
Jean-Michel Trivi58850372018-09-14 16:01:28 -07005837 return mDeviceBroker.startWatchingRoutes(observer);
Dianne Hackborn632ca412012-06-14 19:34:10 -07005838 }
5839
Eric Laurentc34dcc12012-09-10 13:51:52 -07005840
5841 //==========================================================================================
5842 // Safe media volume management.
5843 // MUSIC stream volume level is limited when headphones are connected according to safety
5844 // regulation. When the user attempts to raise the volume above the limit, a warning is
5845 // displayed and the user has to acknowlegde before the volume is actually changed.
5846 // The volume index corresponding to the limit is stored in config_safe_media_volume_index
5847 // property. Platforms with a different limit must set this property accordingly in their
5848 // overlay.
5849 //==========================================================================================
5850
Eric Laurentd640bd32012-09-28 18:01:48 -07005851 // mSafeMediaVolumeState indicates whether the media volume is limited over headphones.
5852 // It is SAFE_MEDIA_VOLUME_NOT_CONFIGURED at boot time until a network service is connected
5853 // or the configure time is elapsed. It is then set to SAFE_MEDIA_VOLUME_ACTIVE or
5854 // SAFE_MEDIA_VOLUME_DISABLED according to country option. If not SAFE_MEDIA_VOLUME_DISABLED, it
5855 // can be set to SAFE_MEDIA_VOLUME_INACTIVE by calling AudioService.disableSafeMediaVolume()
5856 // (when user opts out).
John Spurlock35134602014-07-24 18:10:48 -04005857 private static final int SAFE_MEDIA_VOLUME_NOT_CONFIGURED = 0;
5858 private static final int SAFE_MEDIA_VOLUME_DISABLED = 1;
5859 private static final int SAFE_MEDIA_VOLUME_INACTIVE = 2; // confirmed
5860 private static final int SAFE_MEDIA_VOLUME_ACTIVE = 3; // unconfirmed
hyomin.ohd0446dc2018-10-18 13:58:27 +09005861 private int mSafeMediaVolumeState;
5862 private final Object mSafeMediaVolumeStateLock = new Object();
Eric Laurentd640bd32012-09-28 18:01:48 -07005863
5864 private int mMcc = 0;
Eric Laurentc34dcc12012-09-10 13:51:52 -07005865 // mSafeMediaVolumeIndex is the cached value of config_safe_media_volume_index property
Eric Laurentd640bd32012-09-28 18:01:48 -07005866 private int mSafeMediaVolumeIndex;
John Muir8b8bddd2018-02-16 14:29:14 -08005867 // mSafeUsbMediaVolumeDbfs is the cached value of the config_safe_media_volume_usb_mB
5868 // property, divided by 100.0.
5869 private float mSafeUsbMediaVolumeDbfs;
Eric Laurentb378a13a2017-07-11 14:08:11 -07005870 // mSafeUsbMediaVolumeIndex is used for USB Headsets and is the music volume UI index
John Muir8b8bddd2018-02-16 14:29:14 -08005871 // corresponding to a gain of mSafeUsbMediaVolumeDbfs (defaulting to -37dB) in audio
5872 // flinger mixer.
Eric Laurent0e5deb32017-09-01 15:12:42 -07005873 // We remove -22 dBs from the theoretical -15dB to account for the EQ + bass boost
5874 // amplification when both effects are on with all band gains at maximum.
Eric Laurentb378a13a2017-07-11 14:08:11 -07005875 // This level corresponds to a loudness of 85 dB SPL for the warning to be displayed when
5876 // the headset is compliant to EN 60950 with a max loudness of 100dB SPL.
Eric Laurenteab40d12017-06-09 12:45:21 -07005877 private int mSafeUsbMediaVolumeIndex;
Eric Laurentc34dcc12012-09-10 13:51:52 -07005878 // mSafeMediaVolumeDevices lists the devices for which safe media volume is enforced,
Jean-Michel Trivi58850372018-09-14 16:01:28 -07005879 /*package*/ final int mSafeMediaVolumeDevices = AudioSystem.DEVICE_OUT_WIRED_HEADSET
5880 | AudioSystem.DEVICE_OUT_WIRED_HEADPHONE
5881 | AudioSystem.DEVICE_OUT_USB_HEADSET;
Eric Laurentc34dcc12012-09-10 13:51:52 -07005882 // mMusicActiveMs is the cumulative time of music activity since safe volume was disabled.
5883 // When this time reaches UNSAFE_VOLUME_MUSIC_ACTIVE_MS_MAX, the safe media volume is re-enabled
5884 // automatically. mMusicActiveMs is rounded to a multiple of MUSIC_ACTIVE_POLL_PERIOD_MS.
5885 private int mMusicActiveMs;
5886 private static final int UNSAFE_VOLUME_MUSIC_ACTIVE_MS_MAX = (20 * 3600 * 1000); // 20 hours
5887 private static final int MUSIC_ACTIVE_POLL_PERIOD_MS = 60000; // 1 minute polling interval
Eric Laurentd640bd32012-09-28 18:01:48 -07005888 private static final int SAFE_VOLUME_CONFIGURE_TIMEOUT_MS = 30000; // 30s after boot completed
Eric Laurentc34dcc12012-09-10 13:51:52 -07005889
Eric Laurenteab40d12017-06-09 12:45:21 -07005890 private int safeMediaVolumeIndex(int device) {
5891 if ((device & mSafeMediaVolumeDevices) == 0) {
5892 return MAX_STREAM_VOLUME[AudioSystem.STREAM_MUSIC];
5893 }
5894 if (device == AudioSystem.DEVICE_OUT_USB_HEADSET) {
5895 return mSafeUsbMediaVolumeIndex;
5896 } else {
5897 return mSafeMediaVolumeIndex;
5898 }
5899 }
5900
John Spurlock90874332015-03-10 16:00:54 -04005901 private void setSafeMediaVolumeEnabled(boolean on, String caller) {
hyomin.ohd0446dc2018-10-18 13:58:27 +09005902 synchronized (mSafeMediaVolumeStateLock) {
Eric Laurentd640bd32012-09-28 18:01:48 -07005903 if ((mSafeMediaVolumeState != SAFE_MEDIA_VOLUME_NOT_CONFIGURED) &&
5904 (mSafeMediaVolumeState != SAFE_MEDIA_VOLUME_DISABLED)) {
5905 if (on && (mSafeMediaVolumeState == SAFE_MEDIA_VOLUME_INACTIVE)) {
5906 mSafeMediaVolumeState = SAFE_MEDIA_VOLUME_ACTIVE;
John Spurlock90874332015-03-10 16:00:54 -04005907 enforceSafeMediaVolume(caller);
Eric Laurentd640bd32012-09-28 18:01:48 -07005908 } else if (!on && (mSafeMediaVolumeState == SAFE_MEDIA_VOLUME_ACTIVE)) {
5909 mSafeMediaVolumeState = SAFE_MEDIA_VOLUME_INACTIVE;
John Spurlockaa5ee4d2014-07-25 13:05:12 -04005910 mMusicActiveMs = 1; // nonzero = confirmed
5911 saveMusicActiveMs();
Eric Laurentd640bd32012-09-28 18:01:48 -07005912 sendMsg(mAudioHandler,
5913 MSG_CHECK_MUSIC_ACTIVE,
5914 SENDMSG_REPLACE,
5915 0,
5916 0,
John Spurlock90874332015-03-10 16:00:54 -04005917 caller,
Eric Laurentd640bd32012-09-28 18:01:48 -07005918 MUSIC_ACTIVE_POLL_PERIOD_MS);
5919 }
Eric Laurentc34dcc12012-09-10 13:51:52 -07005920 }
Eric Laurentc34dcc12012-09-10 13:51:52 -07005921 }
5922 }
5923
John Spurlock90874332015-03-10 16:00:54 -04005924 private void enforceSafeMediaVolume(String caller) {
Eric Laurentc34dcc12012-09-10 13:51:52 -07005925 VolumeStreamState streamState = mStreamStates[AudioSystem.STREAM_MUSIC];
Eric Laurentc34dcc12012-09-10 13:51:52 -07005926 int devices = mSafeMediaVolumeDevices;
5927 int i = 0;
5928
5929 while (devices != 0) {
5930 int device = 1 << i++;
5931 if ((device & devices) == 0) {
5932 continue;
5933 }
Eric Laurent42b041e2013-03-29 11:36:03 -07005934 int index = streamState.getIndex(device);
Eric Laurenteab40d12017-06-09 12:45:21 -07005935 if (index > safeMediaVolumeIndex(device)) {
5936 streamState.setIndex(safeMediaVolumeIndex(device), device, caller);
Eric Laurent42b041e2013-03-29 11:36:03 -07005937 sendMsg(mAudioHandler,
5938 MSG_SET_DEVICE_VOLUME,
5939 SENDMSG_QUEUE,
5940 device,
5941 0,
5942 streamState,
5943 0);
Eric Laurentc34dcc12012-09-10 13:51:52 -07005944 }
5945 devices &= ~device;
5946 }
5947 }
5948
5949 private boolean checkSafeMediaVolume(int streamType, int index, int device) {
hyomin.ohd0446dc2018-10-18 13:58:27 +09005950 synchronized (mSafeMediaVolumeStateLock) {
Eric Laurentd640bd32012-09-28 18:01:48 -07005951 if ((mSafeMediaVolumeState == SAFE_MEDIA_VOLUME_ACTIVE) &&
Eric Laurentc34dcc12012-09-10 13:51:52 -07005952 (mStreamVolumeAlias[streamType] == AudioSystem.STREAM_MUSIC) &&
5953 ((device & mSafeMediaVolumeDevices) != 0) &&
Eric Laurenteab40d12017-06-09 12:45:21 -07005954 (index > safeMediaVolumeIndex(device))) {
Eric Laurentc34dcc12012-09-10 13:51:52 -07005955 return false;
5956 }
5957 return true;
5958 }
5959 }
5960
John Spurlock3346a802014-05-20 16:25:37 -04005961 @Override
John Spurlock90874332015-03-10 16:00:54 -04005962 public void disableSafeMediaVolume(String callingPackage) {
John Spurlockcdb57ae2015-02-11 19:04:11 -05005963 enforceVolumeController("disable the safe media volume");
hyomin.ohd0446dc2018-10-18 13:58:27 +09005964 synchronized (mSafeMediaVolumeStateLock) {
John Spurlock90874332015-03-10 16:00:54 -04005965 setSafeMediaVolumeEnabled(false, callingPackage);
Eric Laurentfde16d52012-12-03 14:42:39 -08005966 if (mPendingVolumeCommand != null) {
5967 onSetStreamVolume(mPendingVolumeCommand.mStreamType,
5968 mPendingVolumeCommand.mIndex,
5969 mPendingVolumeCommand.mFlags,
John Spurlock90874332015-03-10 16:00:54 -04005970 mPendingVolumeCommand.mDevice,
5971 callingPackage);
Eric Laurentfde16d52012-12-03 14:42:39 -08005972 mPendingVolumeCommand = null;
5973 }
Eric Laurentc34dcc12012-09-10 13:51:52 -07005974 }
5975 }
5976
Jungshik Jang41d97462014-06-30 22:26:29 +09005977 //==========================================================================================
Jean-Michel Trivi90dbfdf2019-04-10 14:11:40 -07005978 // Hdmi CEC:
5979 // - System audio mode:
5980 // If Hdmi Cec's system audio mode is on, audio service should send the volume change
5981 // to HdmiControlService so that the audio receiver can handle it.
5982 // - CEC sink:
5983 // OUT_HDMI becomes a "full volume device", i.e. output is always at maximum level
5984 // and volume changes won't be taken into account on this device. Volume adjustments
5985 // are transformed into key events for the HDMI playback client.
Jungshik Jang41d97462014-06-30 22:26:29 +09005986 //==========================================================================================
5987
Eric Laurent212532b2014-07-21 15:43:18 -07005988 private class MyDisplayStatusCallback implements HdmiPlaybackClient.DisplayStatusCallback {
5989 public void onComplete(int status) {
Shubangc480a712018-06-11 18:02:42 -07005990 synchronized (mHdmiClientLock) {
5991 if (mHdmiManager != null) {
Eric Laurent212532b2014-07-21 15:43:18 -07005992 mHdmiCecSink = (status != HdmiControlManager.POWER_STATUS_UNKNOWN);
5993 // Television devices without CEC service apply software volume on HDMI output
Jean-Michel Trivi90dbfdf2019-04-10 14:11:40 -07005994 if (mHdmiCecSink) {
5995 if (DEBUG_VOL) {
5996 Log.d(TAG, "CEC sink: setting HDMI as full vol device");
5997 }
5998 mFullVolumeDevices |= AudioSystem.DEVICE_OUT_HDMI;
5999 } else {
6000 if (DEBUG_VOL) {
6001 Log.d(TAG, "TV, no CEC: setting HDMI as regular vol device");
6002 }
6003 // Android TV devices without CEC service apply software volume on
6004 // HDMI output
6005 mFullVolumeDevices &= ~AudioSystem.DEVICE_OUT_HDMI;
Eric Laurent212532b2014-07-21 15:43:18 -07006006 }
6007 checkAllFixedVolumeDevices();
6008 }
6009 }
6010 }
Shubangc480a712018-06-11 18:02:42 -07006011 }
6012
6013 private final Object mHdmiClientLock = new Object();
Eric Laurent212532b2014-07-21 15:43:18 -07006014
Jungshik Jang41d97462014-06-30 22:26:29 +09006015 // If HDMI-CEC system audio is supported
6016 private boolean mHdmiSystemAudioSupported = false;
6017 // Set only when device is tv.
Shubangc480a712018-06-11 18:02:42 -07006018 @GuardedBy("mHdmiClientLock")
Jungshik Jang41d97462014-06-30 22:26:29 +09006019 private HdmiTvClient mHdmiTvClient;
Eric Laurent0b03f992014-11-18 18:08:02 -08006020 // true if the device has system feature PackageManager.FEATURE_LEANBACK.
Eric Laurent212532b2014-07-21 15:43:18 -07006021 // cached HdmiControlManager interface
Shubangc480a712018-06-11 18:02:42 -07006022 @GuardedBy("mHdmiClientLock")
Eric Laurent212532b2014-07-21 15:43:18 -07006023 private HdmiControlManager mHdmiManager;
6024 // Set only when device is a set-top box.
Shubangc480a712018-06-11 18:02:42 -07006025 @GuardedBy("mHdmiClientLock")
Eric Laurent212532b2014-07-21 15:43:18 -07006026 private HdmiPlaybackClient mHdmiPlaybackClient;
6027 // true if we are a set-top box, an HDMI sink is connected and it supports CEC.
6028 private boolean mHdmiCecSink;
Shubangc480a712018-06-11 18:02:42 -07006029 // Set only when device is an audio system.
6030 @GuardedBy("mHdmiClientLock")
6031 private HdmiAudioSystemClient mHdmiAudioSystemClient;
Eric Laurent212532b2014-07-21 15:43:18 -07006032
6033 private MyDisplayStatusCallback mHdmiDisplayStatusCallback = new MyDisplayStatusCallback();
Jungshik Jang41d97462014-06-30 22:26:29 +09006034
6035 @Override
Jungshik Jang12307ca2014-07-15 19:27:56 +09006036 public int setHdmiSystemAudioSupported(boolean on) {
Eric Laurent212532b2014-07-21 15:43:18 -07006037 int device = AudioSystem.DEVICE_NONE;
Shubangc480a712018-06-11 18:02:42 -07006038 synchronized (mHdmiClientLock) {
6039 if (mHdmiManager != null) {
Shubangde728822018-07-16 16:46:51 -07006040 if (mHdmiTvClient == null && mHdmiAudioSystemClient == null) {
6041 Log.w(TAG, "Only Hdmi-Cec enabled TV or audio system device supports"
6042 + "system audio mode.");
Eric Laurent212532b2014-07-21 15:43:18 -07006043 return device;
6044 }
Shubangc480a712018-06-11 18:02:42 -07006045 if (mHdmiSystemAudioSupported != on) {
6046 mHdmiSystemAudioSupported = on;
6047 final int config = on ? AudioSystem.FORCE_HDMI_SYSTEM_AUDIO_ENFORCED :
6048 AudioSystem.FORCE_NONE;
Jean-Michel Trivi58850372018-09-14 16:01:28 -07006049 mDeviceBroker.setForceUse_Async(AudioSystem.FOR_HDMI_SYSTEM_AUDIO, config,
6050 "setHdmiSystemAudioSupported");
Eric Laurent212532b2014-07-21 15:43:18 -07006051 }
Shubangc480a712018-06-11 18:02:42 -07006052 device = getDevicesForStream(AudioSystem.STREAM_MUSIC);
Jungshik Jang6f34f5a2014-07-08 21:17:29 +09006053 }
Jungshik Jang6f34f5a2014-07-08 21:17:29 +09006054 }
Eric Laurent212532b2014-07-21 15:43:18 -07006055 return device;
Jungshik Jang6f34f5a2014-07-08 21:17:29 +09006056 }
Jungshik Jang41d97462014-06-30 22:26:29 +09006057
Terry Heoe7d6d972014-09-04 21:05:28 +09006058 @Override
6059 public boolean isHdmiSystemAudioSupported() {
6060 return mHdmiSystemAudioSupported;
6061 }
6062
Eric Laurentdd45d012012-10-08 09:04:34 -07006063 //==========================================================================================
Jean-Michel Triviac487672016-11-11 10:05:18 -08006064 // Accessibility
6065
Jean-Michel Trivicfa55532017-01-18 11:17:51 -08006066 private void initA11yMonitoring() {
6067 final AccessibilityManager accessibilityManager =
6068 (AccessibilityManager) mContext.getSystemService(Context.ACCESSIBILITY_SERVICE);
Jean-Michel Triviac487672016-11-11 10:05:18 -08006069 updateDefaultStreamOverrideDelay(accessibilityManager.isTouchExplorationEnabled());
Jean-Michel Trivi7592b982017-02-01 15:12:15 -08006070 updateA11yVolumeAlias(accessibilityManager.isAccessibilityVolumeStreamActive());
Phil Weaver26d709f2017-04-20 17:19:14 -07006071 accessibilityManager.addTouchExplorationStateChangeListener(this, null);
6072 accessibilityManager.addAccessibilityServicesStateChangeListener(this, null);
Jean-Michel Triviac487672016-11-11 10:05:18 -08006073 }
6074
6075 //---------------------------------------------------------------------------------
6076 // A11y: taking touch exploration into account for selecting the default
Jean-Michel Trivi873cc452014-09-11 17:25:09 -07006077 // stream override timeout when adjusting volume
Jean-Michel Triviac487672016-11-11 10:05:18 -08006078 //---------------------------------------------------------------------------------
Jean-Michel Trivi873cc452014-09-11 17:25:09 -07006079
Jean-Michel Triviac487672016-11-11 10:05:18 -08006080 // - STREAM_NOTIFICATION on tablets during this period after a notification stopped
Julia Reynoldsd9e96e22017-11-07 10:33:08 -05006081 // - STREAM_RING on phones during this period after a notification stopped
6082 // - STREAM_MUSIC otherwise
6083
Jean-Michel Triviac487672016-11-11 10:05:18 -08006084 private static final int DEFAULT_STREAM_TYPE_OVERRIDE_DELAY_MS = 0;
6085 private static final int TOUCH_EXPLORE_STREAM_TYPE_OVERRIDE_DELAY_MS = 1000;
Jean-Michel Trivi873cc452014-09-11 17:25:09 -07006086
Jean-Michel Triviac487672016-11-11 10:05:18 -08006087 private static int sStreamOverrideDelayMs;
Jean-Michel Trivi873cc452014-09-11 17:25:09 -07006088
Jean-Michel Triviac487672016-11-11 10:05:18 -08006089 @Override
6090 public void onTouchExplorationStateChanged(boolean enabled) {
6091 updateDefaultStreamOverrideDelay(enabled);
6092 }
6093
6094 private void updateDefaultStreamOverrideDelay(boolean touchExploreEnabled) {
6095 if (touchExploreEnabled) {
6096 sStreamOverrideDelayMs = TOUCH_EXPLORE_STREAM_TYPE_OVERRIDE_DELAY_MS;
6097 } else {
6098 sStreamOverrideDelayMs = DEFAULT_STREAM_TYPE_OVERRIDE_DELAY_MS;
Jean-Michel Trivi873cc452014-09-11 17:25:09 -07006099 }
Jean-Michel Triviac487672016-11-11 10:05:18 -08006100 if (DEBUG_VOL) Log.d(TAG, "Touch exploration enabled=" + touchExploreEnabled
6101 + " stream override delay is now " + sStreamOverrideDelayMs + " ms");
6102 }
Jean-Michel Trivi873cc452014-09-11 17:25:09 -07006103
Jean-Michel Triviac487672016-11-11 10:05:18 -08006104 //---------------------------------------------------------------------------------
6105 // A11y: taking a11y state into account for the handling of a11y prompts volume
6106 //---------------------------------------------------------------------------------
Jean-Michel Trivi873cc452014-09-11 17:25:09 -07006107
Jean-Michel Triviac487672016-11-11 10:05:18 -08006108 private static boolean sIndependentA11yVolume = false;
6109
Jean-Michel Trivicfa55532017-01-18 11:17:51 -08006110 // implementation of AccessibilityServicesStateChangeListener
6111 @Override
Phil Weaver4cab9302017-03-30 15:27:39 -07006112 public void onAccessibilityServicesStateChanged(AccessibilityManager accessibilityManager) {
Jean-Michel Trivicfa55532017-01-18 11:17:51 -08006113 updateA11yVolumeAlias(accessibilityManager.isAccessibilityVolumeStreamActive());
6114 }
6115
6116 private void updateA11yVolumeAlias(boolean a11VolEnabled) {
6117 if (DEBUG_VOL) Log.d(TAG, "Accessibility volume enabled = " + a11VolEnabled);
6118 if (sIndependentA11yVolume != a11VolEnabled) {
6119 sIndependentA11yVolume = a11VolEnabled;
6120 // update the volume mapping scheme
6121 updateStreamVolumeAlias(true /*updateVolumes*/, TAG);
6122 // update the volume controller behavior
6123 mVolumeController.setA11yMode(sIndependentA11yVolume ?
6124 VolumePolicy.A11Y_MODE_INDEPENDENT_A11Y_VOLUME :
6125 VolumePolicy.A11Y_MODE_MEDIA_A11Y_VOLUME);
Jean-Michel Trivia53b7052017-04-12 18:27:01 -07006126 mVolumeController.postVolumeChanged(AudioManager.STREAM_ACCESSIBILITY, 0);
Jean-Michel Trivicfa55532017-01-18 11:17:51 -08006127 }
Jean-Michel Trivi873cc452014-09-11 17:25:09 -07006128 }
6129
6130 //==========================================================================================
Eric Laurentdd45d012012-10-08 09:04:34 -07006131 // Camera shutter sound policy.
6132 // config_camera_sound_forced configuration option in config.xml defines if the camera shutter
6133 // sound is forced (sound even if the device is in silent mode) or not. This option is false by
6134 // default and can be overridden by country specific overlay in values-mccXXX/config.xml.
6135 //==========================================================================================
6136
6137 // cached value of com.android.internal.R.bool.config_camera_sound_forced
Jean-Michel Trivi8719a1d2017-11-06 11:52:51 -08006138 @GuardedBy("mSettingsLock")
6139 private boolean mCameraSoundForced;
Eric Laurentdd45d012012-10-08 09:04:34 -07006140
6141 // called by android.hardware.Camera to populate CameraInfo.canDisableShutterSound
6142 public boolean isCameraSoundForced() {
Jean-Michel Trivi8719a1d2017-11-06 11:52:51 -08006143 synchronized (mSettingsLock) {
Eric Laurentdd45d012012-10-08 09:04:34 -07006144 return mCameraSoundForced;
6145 }
6146 }
6147
Jean-Michel Trivi011f39e2017-08-19 18:08:06 -07006148 //==========================================================================================
6149 // AudioService logging and dumpsys
6150 //==========================================================================================
Jean-Michel Trivi3bf75782018-07-02 10:48:04 -07006151 static final int LOG_NB_EVENTS_PHONE_STATE = 20;
6152 static final int LOG_NB_EVENTS_DEVICE_CONNECTION = 30;
6153 static final int LOG_NB_EVENTS_FORCE_USE = 20;
6154 static final int LOG_NB_EVENTS_VOLUME = 40;
6155 static final int LOG_NB_EVENTS_DYN_POLICY = 10;
Jean-Michel Trivi011f39e2017-08-19 18:08:06 -07006156
6157 final private AudioEventLogger mModeLogger = new AudioEventLogger(LOG_NB_EVENTS_PHONE_STATE,
6158 "phone state (logged after successfull call to AudioSystem.setPhoneState(int))");
6159
Jean-Michel Trivi3bf75782018-07-02 10:48:04 -07006160 // logs for wired + A2DP device connections:
6161 // - wired: logged before onSetWiredDeviceConnectionState() is executed
6162 // - A2DP: logged at reception of method call
Jean-Michel Trivi58850372018-09-14 16:01:28 -07006163 /*package*/ static final AudioEventLogger sDeviceLogger = new AudioEventLogger(
Jean-Michel Trivi44abe2c2019-02-26 18:12:54 -08006164 LOG_NB_EVENTS_DEVICE_CONNECTION, "wired/A2DP/hearing aid device connection");
Jean-Michel Trivi011f39e2017-08-19 18:08:06 -07006165
Jean-Michel Trivi58850372018-09-14 16:01:28 -07006166 static final AudioEventLogger sForceUseLogger = new AudioEventLogger(
Jean-Michel Trivi011f39e2017-08-19 18:08:06 -07006167 LOG_NB_EVENTS_FORCE_USE,
6168 "force use (logged before setForceUse() is executed)");
6169
Jean-Michel Trivi58850372018-09-14 16:01:28 -07006170 static final AudioEventLogger sVolumeLogger = new AudioEventLogger(LOG_NB_EVENTS_VOLUME,
Jean-Michel Trivicf170362017-08-24 17:24:57 -07006171 "volume changes (logged when command received by AudioService)");
6172
Jean-Michel Trivi12a86762018-04-24 16:57:49 -07006173 final private AudioEventLogger mDynPolicyLogger = new AudioEventLogger(LOG_NB_EVENTS_DYN_POLICY,
6174 "dynamic policy events (logged when command received by AudioService)");
6175
Eric Laurentdd45d012012-10-08 09:04:34 -07006176 private static final String[] RINGER_MODE_NAMES = new String[] {
6177 "SILENT",
6178 "VIBRATE",
6179 "NORMAL"
6180 };
6181
6182 private void dumpRingerMode(PrintWriter pw) {
6183 pw.println("\nRinger mode: ");
John Spurlock661f2cf2014-11-17 10:29:10 -05006184 pw.println("- mode (internal) = " + RINGER_MODE_NAMES[mRingerMode]);
6185 pw.println("- mode (external) = " + RINGER_MODE_NAMES[mRingerModeExternal]);
John Spurlock50ced3f2015-05-11 16:00:09 -04006186 dumpRingerModeStreams(pw, "affected", mRingerModeAffectedStreams);
Beverlyd6964762018-02-16 14:07:03 -05006187 dumpRingerModeStreams(pw, "muted", mRingerAndZenModeMutedStreams);
John Spurlock661f2cf2014-11-17 10:29:10 -05006188 pw.print("- delegate = "); pw.println(mRingerModeDelegate);
Eric Laurentdd45d012012-10-08 09:04:34 -07006189 }
6190
John Spurlock50ced3f2015-05-11 16:00:09 -04006191 private void dumpRingerModeStreams(PrintWriter pw, String type, int streams) {
6192 pw.print("- ringer mode "); pw.print(type); pw.print(" streams = 0x");
6193 pw.print(Integer.toHexString(streams));
6194 if (streams != 0) {
6195 pw.print(" (");
6196 boolean first = true;
6197 for (int i = 0; i < AudioSystem.STREAM_NAMES.length; i++) {
6198 final int stream = (1 << i);
6199 if ((streams & stream) != 0) {
6200 if (!first) pw.print(',');
6201 pw.print(AudioSystem.STREAM_NAMES[i]);
6202 streams &= ~stream;
6203 first = false;
6204 }
6205 }
6206 if (streams != 0) {
6207 if (!first) pw.print(',');
6208 pw.print(streams);
6209 }
6210 pw.print(')');
6211 }
6212 pw.println();
6213 }
6214
Dianne Hackborn632ca412012-06-14 19:34:10 -07006215 @Override
Jean-Michel Trivid5176cf2010-01-28 11:56:42 -08006216 protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
Jeff Sharkeyfe9a53b2017-03-31 14:08:23 -06006217 if (!DumpUtils.checkDumpPermission(mContext, TAG, pw)) return;
Jeff Sharkeyeb4cc4922012-04-26 18:17:29 -07006218
Jean-Michel Trivifa9a6982013-06-27 16:22:58 -07006219 mMediaFocusControl.dump(pw);
Eric Laurentbffc3d12012-05-07 17:43:49 -07006220 dumpStreamStates(pw);
Eric Laurentdd45d012012-10-08 09:04:34 -07006221 dumpRingerMode(pw);
Dianne Hackborn632ca412012-06-14 19:34:10 -07006222 pw.println("\nAudio routes:");
Jean-Michel Trivi58850372018-09-14 16:01:28 -07006223 pw.print(" mMainType=0x"); pw.println(Integer.toHexString(
6224 mDeviceBroker.getCurAudioRoutes().mainType));
6225 pw.print(" mBluetoothName="); pw.println(mDeviceBroker.getCurAudioRoutes().bluetoothName);
John Spurlock35134602014-07-24 18:10:48 -04006226
6227 pw.println("\nOther state:");
John Spurlock3346a802014-05-20 16:25:37 -04006228 pw.print(" mVolumeController="); pw.println(mVolumeController);
John Spurlock35134602014-07-24 18:10:48 -04006229 pw.print(" mSafeMediaVolumeState=");
6230 pw.println(safeMediaVolumeStateToString(mSafeMediaVolumeState));
6231 pw.print(" mSafeMediaVolumeIndex="); pw.println(mSafeMediaVolumeIndex);
Eric Laurenteab40d12017-06-09 12:45:21 -07006232 pw.print(" mSafeUsbMediaVolumeIndex="); pw.println(mSafeUsbMediaVolumeIndex);
John Muir8b8bddd2018-02-16 14:29:14 -08006233 pw.print(" mSafeUsbMediaVolumeDbfs="); pw.println(mSafeUsbMediaVolumeDbfs);
Jean-Michel Trivi7592b982017-02-01 15:12:15 -08006234 pw.print(" sIndependentA11yVolume="); pw.println(sIndependentA11yVolume);
John Spurlock35134602014-07-24 18:10:48 -04006235 pw.print(" mPendingVolumeCommand="); pw.println(mPendingVolumeCommand);
6236 pw.print(" mMusicActiveMs="); pw.println(mMusicActiveMs);
John Spurlockaa5ee4d2014-07-25 13:05:12 -04006237 pw.print(" mMcc="); pw.println(mMcc);
John Spurlock5e783732015-02-19 10:28:59 -05006238 pw.print(" mCameraSoundForced="); pw.println(mCameraSoundForced);
John Spurlock661f2cf2014-11-17 10:29:10 -05006239 pw.print(" mHasVibrator="); pw.println(mHasVibrator);
John Spurlocka48d7792015-03-03 17:35:57 -05006240 pw.print(" mVolumePolicy="); pw.println(mVolumePolicy);
Jean-Michel Trivi58850372018-09-14 16:01:28 -07006241 pw.print(" mAvrcpAbsVolSupported=");
6242 pw.println(mDeviceBroker.isAvrcpAbsoluteVolumeSupported());
Amya9e71692019-03-14 17:49:19 -07006243 pw.print(" mIsSingleVolume="); pw.println(mIsSingleVolume);
6244 pw.print(" mUseFixedVolume="); pw.println(mUseFixedVolume);
6245 pw.print(" mFixedVolumeDevices=0x"); pw.println(Integer.toHexString(mFixedVolumeDevices));
6246 pw.print(" mHdmiCecSink="); pw.println(mHdmiCecSink);
6247 pw.print(" mHdmiAudioSystemClient="); pw.println(mHdmiAudioSystemClient);
6248 pw.print(" mHdmiPlaybackClient="); pw.println(mHdmiPlaybackClient);
6249 pw.print(" mHdmiTvClient="); pw.println(mHdmiTvClient);
6250 pw.print(" mHdmiSystemAudioSupported="); pw.println(mHdmiSystemAudioSupported);
Jean-Michel Trivi1b3541d2014-11-25 12:53:41 -08006251
6252 dumpAudioPolicies(pw);
Jean-Michel Trivi12a86762018-04-24 16:57:49 -07006253 mDynPolicyLogger.dump(pw);
Jean-Michel Trivi292a6a42016-12-01 08:32:15 -08006254
6255 mPlaybackMonitor.dump(pw);
Jean-Michel Trivi66ffacf2017-02-04 17:25:31 -08006256
6257 mRecordMonitor.dump(pw);
Jean-Michel Trivi011f39e2017-08-19 18:08:06 -07006258
Jean-Michel Trivicf170362017-08-24 17:24:57 -07006259 pw.println("\n");
Jean-Michel Trivi011f39e2017-08-19 18:08:06 -07006260 pw.println("\nEvent logs:");
6261 mModeLogger.dump(pw);
6262 pw.println("\n");
Jean-Michel Trivi58850372018-09-14 16:01:28 -07006263 sDeviceLogger.dump(pw);
Jean-Michel Trivi011f39e2017-08-19 18:08:06 -07006264 pw.println("\n");
Jean-Michel Trivi58850372018-09-14 16:01:28 -07006265 sForceUseLogger.dump(pw);
Jean-Michel Trivicf170362017-08-24 17:24:57 -07006266 pw.println("\n");
Jean-Michel Trivi58850372018-09-14 16:01:28 -07006267 sVolumeLogger.dump(pw);
John Spurlock35134602014-07-24 18:10:48 -04006268 }
6269
hyomin.ohd0446dc2018-10-18 13:58:27 +09006270 private static String safeMediaVolumeStateToString(int state) {
John Spurlock35134602014-07-24 18:10:48 -04006271 switch(state) {
6272 case SAFE_MEDIA_VOLUME_NOT_CONFIGURED: return "SAFE_MEDIA_VOLUME_NOT_CONFIGURED";
6273 case SAFE_MEDIA_VOLUME_DISABLED: return "SAFE_MEDIA_VOLUME_DISABLED";
6274 case SAFE_MEDIA_VOLUME_INACTIVE: return "SAFE_MEDIA_VOLUME_INACTIVE";
6275 case SAFE_MEDIA_VOLUME_ACTIVE: return "SAFE_MEDIA_VOLUME_ACTIVE";
6276 }
6277 return null;
Jean-Michel Trivid5176cf2010-01-28 11:56:42 -08006278 }
Glenn Kastenfd116ad2013-07-12 17:10:39 -07006279
6280 // Inform AudioFlinger of our device's low RAM attribute
6281 private static void readAndSetLowRamDevice()
6282 {
Andy Hung79583582018-01-23 13:58:02 -08006283 boolean isLowRamDevice = ActivityManager.isLowRamDeviceStatic();
6284 long totalMemory = 1024 * 1024 * 1024; // 1GB is the default if ActivityManager fails.
6285
6286 try {
6287 final ActivityManager.MemoryInfo info = new ActivityManager.MemoryInfo();
6288 ActivityManager.getService().getMemoryInfo(info);
6289 totalMemory = info.totalMem;
6290 } catch (RemoteException e) {
6291 Log.w(TAG, "Cannot obtain MemoryInfo from ActivityManager, assume low memory device");
6292 isLowRamDevice = true;
6293 }
6294
6295 final int status = AudioSystem.setLowRamDevice(isLowRamDevice, totalMemory);
Glenn Kastenfd116ad2013-07-12 17:10:39 -07006296 if (status != 0) {
6297 Log.w(TAG, "AudioFlinger informed of device's low RAM attribute; status " + status);
6298 }
6299 }
John Spurlock3346a802014-05-20 16:25:37 -04006300
John Spurlockcdb57ae2015-02-11 19:04:11 -05006301 private void enforceVolumeController(String action) {
John Spurlock3346a802014-05-20 16:25:37 -04006302 mContext.enforceCallingOrSelfPermission(android.Manifest.permission.STATUS_BAR_SERVICE,
6303 "Only SystemUI can " + action);
6304 }
6305
6306 @Override
6307 public void setVolumeController(final IVolumeController controller) {
John Spurlockcdb57ae2015-02-11 19:04:11 -05006308 enforceVolumeController("set the volume controller");
John Spurlock3346a802014-05-20 16:25:37 -04006309
6310 // return early if things are not actually changing
6311 if (mVolumeController.isSameBinder(controller)) {
6312 return;
6313 }
6314
6315 // dismiss the old volume controller
6316 mVolumeController.postDismiss();
6317 if (controller != null) {
6318 // we are about to register a new controller, listen for its death
6319 try {
6320 controller.asBinder().linkToDeath(new DeathRecipient() {
6321 @Override
6322 public void binderDied() {
6323 if (mVolumeController.isSameBinder(controller)) {
6324 Log.w(TAG, "Current remote volume controller died, unregistering");
6325 setVolumeController(null);
6326 }
6327 }
6328 }, 0);
6329 } catch (RemoteException e) {
6330 // noop
6331 }
6332 }
6333 mVolumeController.setController(controller);
John Spurlock33f4e042014-07-11 13:10:58 -04006334 if (DEBUG_VOL) Log.d(TAG, "Volume controller: " + mVolumeController);
6335 }
6336
6337 @Override
6338 public void notifyVolumeControllerVisible(final IVolumeController controller, boolean visible) {
John Spurlockcdb57ae2015-02-11 19:04:11 -05006339 enforceVolumeController("notify about volume controller visibility");
John Spurlock33f4e042014-07-11 13:10:58 -04006340
6341 // return early if the controller is not current
6342 if (!mVolumeController.isSameBinder(controller)) {
6343 return;
6344 }
6345
6346 mVolumeController.setVisible(visible);
6347 if (DEBUG_VOL) Log.d(TAG, "Volume controller visible: " + visible);
John Spurlock3346a802014-05-20 16:25:37 -04006348 }
RoboErikd09bd0c2014-06-24 17:45:19 -07006349
John Spurlocka48d7792015-03-03 17:35:57 -05006350 @Override
6351 public void setVolumePolicy(VolumePolicy policy) {
6352 enforceVolumeController("set volume policy");
John Spurlockb02c7442015-04-14 09:32:25 -04006353 if (policy != null && !policy.equals(mVolumePolicy)) {
John Spurlocka48d7792015-03-03 17:35:57 -05006354 mVolumePolicy = policy;
John Spurlockb02c7442015-04-14 09:32:25 -04006355 if (DEBUG_VOL) Log.d(TAG, "Volume policy changed: " + mVolumePolicy);
John Spurlocka48d7792015-03-03 17:35:57 -05006356 }
6357 }
6358
RoboErikd09bd0c2014-06-24 17:45:19 -07006359 public static class VolumeController {
6360 private static final String TAG = "VolumeController";
6361
6362 private IVolumeController mController;
John Spurlock33f4e042014-07-11 13:10:58 -04006363 private boolean mVisible;
6364 private long mNextLongPress;
6365 private int mLongPressTimeout;
RoboErikd09bd0c2014-06-24 17:45:19 -07006366
6367 public void setController(IVolumeController controller) {
6368 mController = controller;
John Spurlock33f4e042014-07-11 13:10:58 -04006369 mVisible = false;
6370 }
6371
6372 public void loadSettings(ContentResolver cr) {
6373 mLongPressTimeout = Settings.Secure.getIntForUser(cr,
6374 Settings.Secure.LONG_PRESS_TIMEOUT, 500, UserHandle.USER_CURRENT);
6375 }
6376
RoboErik4197cb62015-01-21 15:45:32 -08006377 public boolean suppressAdjustment(int resolvedStream, int flags, boolean isMute) {
6378 if (isMute) {
6379 return false;
6380 }
John Spurlock33f4e042014-07-11 13:10:58 -04006381 boolean suppress = false;
Julia Reynoldseb0ce472018-05-04 15:34:55 -04006382 if (resolvedStream == DEFAULT_VOL_STREAM_NO_PLAYBACK && mController != null) {
John Spurlock33f4e042014-07-11 13:10:58 -04006383 final long now = SystemClock.uptimeMillis();
6384 if ((flags & AudioManager.FLAG_SHOW_UI) != 0 && !mVisible) {
6385 // ui will become visible
6386 if (mNextLongPress < now) {
6387 mNextLongPress = now + mLongPressTimeout;
6388 }
6389 suppress = true;
6390 } else if (mNextLongPress > 0) { // in a long-press
6391 if (now > mNextLongPress) {
6392 // long press triggered, no more suppression
6393 mNextLongPress = 0;
6394 } else {
6395 // keep suppressing until the long press triggers
6396 suppress = true;
6397 }
6398 }
6399 }
6400 return suppress;
6401 }
6402
6403 public void setVisible(boolean visible) {
6404 mVisible = visible;
RoboErikd09bd0c2014-06-24 17:45:19 -07006405 }
6406
6407 public boolean isSameBinder(IVolumeController controller) {
6408 return Objects.equals(asBinder(), binder(controller));
6409 }
6410
6411 public IBinder asBinder() {
6412 return binder(mController);
6413 }
6414
6415 private static IBinder binder(IVolumeController controller) {
6416 return controller == null ? null : controller.asBinder();
6417 }
6418
6419 @Override
6420 public String toString() {
John Spurlock33f4e042014-07-11 13:10:58 -04006421 return "VolumeController(" + asBinder() + ",mVisible=" + mVisible + ")";
RoboErikd09bd0c2014-06-24 17:45:19 -07006422 }
6423
6424 public void postDisplaySafeVolumeWarning(int flags) {
6425 if (mController == null)
6426 return;
6427 try {
6428 mController.displaySafeVolumeWarning(flags);
6429 } catch (RemoteException e) {
6430 Log.w(TAG, "Error calling displaySafeVolumeWarning", e);
6431 }
6432 }
6433
6434 public void postVolumeChanged(int streamType, int flags) {
6435 if (mController == null)
6436 return;
6437 try {
6438 mController.volumeChanged(streamType, flags);
6439 } catch (RemoteException e) {
6440 Log.w(TAG, "Error calling volumeChanged", e);
6441 }
6442 }
6443
RoboErikd09bd0c2014-06-24 17:45:19 -07006444 public void postMasterMuteChanged(int flags) {
6445 if (mController == null)
6446 return;
6447 try {
6448 mController.masterMuteChanged(flags);
6449 } catch (RemoteException e) {
6450 Log.w(TAG, "Error calling masterMuteChanged", e);
6451 }
6452 }
6453
6454 public void setLayoutDirection(int layoutDirection) {
6455 if (mController == null)
6456 return;
6457 try {
6458 mController.setLayoutDirection(layoutDirection);
6459 } catch (RemoteException e) {
6460 Log.w(TAG, "Error calling setLayoutDirection", e);
6461 }
6462 }
6463
6464 public void postDismiss() {
6465 if (mController == null)
6466 return;
6467 try {
6468 mController.dismiss();
6469 } catch (RemoteException e) {
6470 Log.w(TAG, "Error calling dismiss", e);
6471 }
6472 }
Jean-Michel Triviac487672016-11-11 10:05:18 -08006473
6474 public void setA11yMode(int a11yMode) {
6475 if (mController == null)
6476 return;
6477 try {
6478 mController.setA11yMode(a11yMode);
6479 } catch (RemoteException e) {
6480 Log.w(TAG, "Error calling setA11Mode", e);
6481 }
6482 }
RoboErikd09bd0c2014-06-24 17:45:19 -07006483 }
Jean-Michel Trivia8b6bd82014-07-01 09:48:46 -07006484
RoboErik0dac35a2014-08-12 15:48:49 -07006485 /**
6486 * Interface for system components to get some extra functionality through
6487 * LocalServices.
6488 */
6489 final class AudioServiceInternal extends AudioManagerInternal {
John Spurlock661f2cf2014-11-17 10:29:10 -05006490 @Override
6491 public void setRingerModeDelegate(RingerModeDelegate delegate) {
6492 mRingerModeDelegate = delegate;
6493 if (mRingerModeDelegate != null) {
Jean-Michel Trivi8719a1d2017-11-06 11:52:51 -08006494 synchronized (mSettingsLock) {
Beverlyd6964762018-02-16 14:07:03 -05006495 updateRingerAndZenModeAffectedStreams();
Jean-Michel Trivi8719a1d2017-11-06 11:52:51 -08006496 }
John Spurlock661f2cf2014-11-17 10:29:10 -05006497 setRingerModeInternal(getRingerModeInternal(), TAG + ".setRingerModeDelegate");
6498 }
6499 }
RoboErik272e1612014-09-05 11:39:29 -07006500
6501 @Override
6502 public void adjustSuggestedStreamVolumeForUid(int streamType, int direction, int flags,
6503 String callingPackage, int uid) {
6504 // direction and stream type swap here because the public
6505 // adjustSuggested has a different order than the other methods.
John Spurlock90874332015-03-10 16:00:54 -04006506 adjustSuggestedStreamVolume(direction, streamType, flags, callingPackage,
6507 callingPackage, uid);
RoboErik272e1612014-09-05 11:39:29 -07006508 }
6509
RoboErik0dac35a2014-08-12 15:48:49 -07006510 @Override
6511 public void adjustStreamVolumeForUid(int streamType, int direction, int flags,
6512 String callingPackage, int uid) {
Jean-Michel Trivi8505b232019-04-13 16:52:27 -07006513 if (direction != AudioManager.ADJUST_SAME) {
6514 sVolumeLogger.log(new VolumeEvent(VolumeEvent.VOL_ADJUST_VOL_UID, streamType,
6515 direction/*val1*/, flags/*val2*/, new StringBuilder(callingPackage)
6516 .append(" uid:").append(uid).toString()));
6517 }
John Spurlock90874332015-03-10 16:00:54 -04006518 adjustStreamVolume(streamType, direction, flags, callingPackage,
6519 callingPackage, uid);
RoboErik0dac35a2014-08-12 15:48:49 -07006520 }
6521
6522 @Override
6523 public void setStreamVolumeForUid(int streamType, int direction, int flags,
6524 String callingPackage, int uid) {
John Spurlock90874332015-03-10 16:00:54 -04006525 setStreamVolume(streamType, direction, flags, callingPackage, callingPackage, uid);
RoboErik0dac35a2014-08-12 15:48:49 -07006526 }
RoboErik519c7742014-11-18 10:59:09 -08006527
6528 @Override
John Spurlock661f2cf2014-11-17 10:29:10 -05006529 public int getRingerModeInternal() {
6530 return AudioService.this.getRingerModeInternal();
6531 }
6532
6533 @Override
6534 public void setRingerModeInternal(int ringerMode, String caller) {
6535 AudioService.this.setRingerModeInternal(ringerMode, caller);
6536 }
John Spurlockcdb57ae2015-02-11 19:04:11 -05006537
6538 @Override
Mike Digman55272862018-02-20 14:35:17 -08006539 public void silenceRingerModeInternal(String caller) {
6540 AudioService.this.silenceRingerModeInternal(caller);
6541 }
6542
6543 @Override
John Spurlock50ced3f2015-05-11 16:00:09 -04006544 public void updateRingerModeAffectedStreamsInternal() {
6545 synchronized (mSettingsLock) {
Beverlyd6964762018-02-16 14:07:03 -05006546 if (updateRingerAndZenModeAffectedStreams()) {
John Spurlock50ced3f2015-05-11 16:00:09 -04006547 setRingerModeInt(getRingerModeInternal(), false);
6548 }
6549 }
6550 }
Phil Weaverf1a9aff2017-03-23 17:21:29 -07006551
6552 @Override
6553 public void setAccessibilityServiceUids(IntArray uids) {
6554 synchronized (mAccessibilityServiceUidsLock) {
6555 if (uids.size() == 0) {
6556 mAccessibilityServiceUids = null;
6557 } else {
6558 boolean changed = (mAccessibilityServiceUids == null)
6559 || (mAccessibilityServiceUids.length != uids.size());
6560 if (!changed) {
6561 for (int i = 0; i < mAccessibilityServiceUids.length; i++) {
6562 if (uids.get(i) != mAccessibilityServiceUids[i]) {
6563 changed = true;
6564 break;
6565 }
6566 }
6567 }
6568 if (changed) {
6569 mAccessibilityServiceUids = uids.toArray();
6570 }
6571 }
Eric Laurent1c9c1d52018-10-17 10:06:46 -07006572 AudioSystem.setA11yServicesUids(mAccessibilityServiceUids);
Phil Weaverf1a9aff2017-03-23 17:21:29 -07006573 }
6574 }
RoboErik0dac35a2014-08-12 15:48:49 -07006575 }
6576
Jean-Michel Trivia8b6bd82014-07-01 09:48:46 -07006577 //==========================================================================================
6578 // Audio policy management
6579 //==========================================================================================
Jean-Michel Trivi0212be52014-11-24 14:43:10 -08006580 public String registerAudioPolicy(AudioPolicyConfig policyConfig, IAudioPolicyCallback pcb,
Jean-Michel Triviee7d2452019-03-19 12:29:27 -07006581 boolean hasFocusListener, boolean isFocusPolicy, boolean isTestFocusPolicy,
6582 boolean isVolumeController, IMediaProjection projection) {
Jean-Michel Trivi5a561092015-04-23 18:48:08 -07006583 AudioSystem.setDynamicPolicyCallback(mDynPolicyCallback);
6584
Kevin Rocard2fe8b8b2019-02-20 11:25:23 -08006585 if (!isPolicyRegisterAllowed(policyConfig, projection)) {
6586 Slog.w(TAG, "Permission denied to register audio policy for pid "
6587 + Binder.getCallingPid() + " / uid " + Binder.getCallingUid()
6588 + ", need MODIFY_AUDIO_ROUTING or MediaProjection that can project audio");
Jean-Michel Trivi8fdb0d42014-07-16 19:08:37 -07006589 return null;
Jean-Michel Trivia8b6bd82014-07-01 09:48:46 -07006590 }
Jean-Michel Trivi0212be52014-11-24 14:43:10 -08006591
Jean-Michel Trivi12a86762018-04-24 16:57:49 -07006592 mDynPolicyLogger.log((new AudioEventLogger.StringEvent("registerAudioPolicy for "
6593 + pcb.asBinder() + " with config:" + policyConfig)).printLog(TAG));
Kevin Rocard2fe8b8b2019-02-20 11:25:23 -08006594
6595 String regId = null;
Jean-Michel Trivia8b6bd82014-07-01 09:48:46 -07006596 synchronized (mAudioPolicies) {
Jean-Michel Trivia8b6bd82014-07-01 09:48:46 -07006597 try {
Jean-Michel Trivi0212be52014-11-24 14:43:10 -08006598 if (mAudioPolicies.containsKey(pcb.asBinder())) {
Jean-Michel Trivi1b3541d2014-11-25 12:53:41 -08006599 Slog.e(TAG, "Cannot re-register policy");
6600 return null;
6601 }
Jean-Michel Trivi126cf032017-04-02 23:19:02 -07006602 AudioPolicyProxy app = new AudioPolicyProxy(policyConfig, pcb, hasFocusListener,
Jean-Michel Triviee7d2452019-03-19 12:29:27 -07006603 isFocusPolicy, isTestFocusPolicy, isVolumeController);
Jean-Michel Trivi0212be52014-11-24 14:43:10 -08006604 pcb.asBinder().linkToDeath(app, 0/*flags*/);
6605 regId = app.getRegistrationId();
6606 mAudioPolicies.put(pcb.asBinder(), app);
Jean-Michel Trivia8b6bd82014-07-01 09:48:46 -07006607 } catch (RemoteException e) {
6608 // audio policy owner has already died!
Jean-Michel Trivi0212be52014-11-24 14:43:10 -08006609 Slog.w(TAG, "Audio policy registration failed, could not link to " + pcb +
Jean-Michel Trivia8b6bd82014-07-01 09:48:46 -07006610 " binder death", e);
Jean-Michel Trivi8fdb0d42014-07-16 19:08:37 -07006611 return null;
Jean-Michel Trivia8b6bd82014-07-01 09:48:46 -07006612 }
6613 }
Jean-Michel Trivi8fdb0d42014-07-16 19:08:37 -07006614 return regId;
Jean-Michel Trivia8b6bd82014-07-01 09:48:46 -07006615 }
Jean-Michel Trivi8fdb0d42014-07-16 19:08:37 -07006616
Kevin Rocard2fe8b8b2019-02-20 11:25:23 -08006617 /**
6618 * Apps with MODIFY_AUDIO_ROUTING can register any policy.
6619 * Apps with an audio capable MediaProjection are allowed to register a RENDER|LOOPBACK policy
6620 * as those policy do not modify the audio routing.
6621 */
6622 private boolean isPolicyRegisterAllowed(AudioPolicyConfig policyConfig,
6623 IMediaProjection projection) {
6624
6625 boolean isLoopbackRenderPolicy = policyConfig.getMixes().stream().allMatch(
6626 mix -> mix.getRouteFlags() == (mix.ROUTE_FLAG_RENDER | mix.ROUTE_FLAG_LOOP_BACK));
6627
Kevin Rocarda3a4bbb2019-03-07 18:29:48 -08006628 if (isLoopbackRenderPolicy) {
6629 boolean allowPrivilegedPlaybackCapture = policyConfig.getMixes().stream().anyMatch(
6630 mix -> mix.getRule().allowPrivilegedPlaybackCapture());
6631 if (allowPrivilegedPlaybackCapture
6632 && !(hasPermission(android.Manifest.permission.CAPTURE_AUDIO_OUTPUT)
6633 || hasPermission(android.Manifest.permission.CAPTURE_MEDIA_OUTPUT))) {
6634 // Opt-out can not be bypassed without a system permission
6635 return false;
6636 }
6637
6638 if (canProjectAudio(projection)) {
6639 // Policy that do not modify the audio routing only need an audio projection
6640 return true;
6641 }
Kevin Rocard2fe8b8b2019-02-20 11:25:23 -08006642 }
6643
6644 boolean hasPermissionModifyAudioRouting =
6645 (PackageManager.PERMISSION_GRANTED == mContext.checkCallingPermission(
6646 android.Manifest.permission.MODIFY_AUDIO_ROUTING));
6647 if (hasPermissionModifyAudioRouting) {
6648 return true;
6649 }
6650 return false;
6651 }
Kevin Rocarda3a4bbb2019-03-07 18:29:48 -08006652 private boolean hasPermission(String permission) {
6653 return PackageManager.PERMISSION_GRANTED == mContext.checkCallingPermission(permission);
6654 }
Kevin Rocard2fe8b8b2019-02-20 11:25:23 -08006655
6656 /** @return true if projection is a valid MediaProjection that can project audio. */
6657 private boolean canProjectAudio(IMediaProjection projection) {
6658 if (projection == null) {
6659 return false;
6660 }
6661
6662 IMediaProjectionManager projectionService = getProjectionService();
6663 if (projectionService == null) {
6664 Log.e(TAG, "Can't get service IMediaProjectionManager");
6665 return false;
6666 }
6667
6668 try {
6669 if (!projectionService.isValidMediaProjection(projection)) {
6670 Log.w(TAG, "App passed invalid MediaProjection token");
6671 return false;
6672 }
6673 } catch (RemoteException e) {
6674 Log.e(TAG, "Can't call .isValidMediaProjection() on IMediaProjectionManager"
6675 + projectionService.asBinder(), e);
6676 return false;
6677 }
6678
6679 try {
6680 if (!projection.canProjectAudio()) {
6681 Log.w(TAG, "App passed MediaProjection that can not project audio");
6682 return false;
6683 }
6684 } catch (RemoteException e) {
6685 Log.e(TAG, "Can't call .canProjectAudio() on valid IMediaProjection"
6686 + projection.asBinder(), e);
6687 return false;
6688 }
6689
6690 return true;
6691 }
6692
6693 private IMediaProjectionManager getProjectionService() {
6694 if (mProjectionService == null) {
6695 IBinder b = ServiceManager.getService(Context.MEDIA_PROJECTION_SERVICE);
6696 mProjectionService = IMediaProjectionManager.Stub.asInterface(b);
6697 }
6698 return mProjectionService;
6699 }
6700
Jean-Michel Trivicada3722019-03-02 16:14:12 -08006701 /**
6702 * See {@link AudioManager#unregisterAudioPolicyAsync(AudioPolicy)}
6703 * Declared oneway
6704 * @param pcb nullable because on service interface
6705 */
6706 public void unregisterAudioPolicyAsync(@Nullable IAudioPolicyCallback pcb) {
6707 unregisterAudioPolicy(pcb);
6708 }
6709
6710 /**
6711 * See {@link AudioManager#unregisterAudioPolicy(AudioPolicy)}
6712 * @param pcb nullable because on service interface
6713 */
6714 public void unregisterAudioPolicy(@Nullable IAudioPolicyCallback pcb) {
6715 if (pcb == null) {
6716 return;
6717 }
6718 unregisterAudioPolicyInt(pcb);
6719 }
6720
6721
6722 private void unregisterAudioPolicyInt(@NonNull IAudioPolicyCallback pcb) {
Jean-Michel Trivi12a86762018-04-24 16:57:49 -07006723 mDynPolicyLogger.log((new AudioEventLogger.StringEvent("unregisterAudioPolicyAsync for "
6724 + pcb.asBinder()).printLog(TAG)));
Jean-Michel Trivia8b6bd82014-07-01 09:48:46 -07006725 synchronized (mAudioPolicies) {
Jean-Michel Trivi0212be52014-11-24 14:43:10 -08006726 AudioPolicyProxy app = mAudioPolicies.remove(pcb.asBinder());
Jean-Michel Trivia8b6bd82014-07-01 09:48:46 -07006727 if (app == null) {
6728 Slog.w(TAG, "Trying to unregister unknown audio policy for pid "
6729 + Binder.getCallingPid() + " / uid " + Binder.getCallingUid());
Jean-Michel Trivi1b3541d2014-11-25 12:53:41 -08006730 return;
Jean-Michel Trivia8b6bd82014-07-01 09:48:46 -07006731 } else {
Jean-Michel Trivi0212be52014-11-24 14:43:10 -08006732 pcb.asBinder().unlinkToDeath(app, 0/*flags*/);
Jean-Michel Trivia8b6bd82014-07-01 09:48:46 -07006733 }
Jean-Michel Trivi0212be52014-11-24 14:43:10 -08006734 app.release();
Jean-Michel Trivia8b6bd82014-07-01 09:48:46 -07006735 }
Jean-Michel Trivi8fdb0d42014-07-16 19:08:37 -07006736 // TODO implement clearing mix attribute matching info in native audio policy
Jean-Michel Trivia8b6bd82014-07-01 09:48:46 -07006737 }
6738
Jean-Michel Triviaf576a02018-02-14 08:57:46 -08006739 /**
6740 * Checks whether caller has MODIFY_AUDIO_ROUTING permission, and the policy is registered.
6741 * @param errorMsg log warning if permission check failed.
6742 * @return null if the operation on the audio mixes should be cancelled.
6743 */
6744 @GuardedBy("mAudioPolicies")
6745 private AudioPolicyProxy checkUpdateForPolicy(IAudioPolicyCallback pcb, String errorMsg) {
6746 // permission check
6747 final boolean hasPermissionForPolicy =
Jean-Michel Trivi0212be52014-11-24 14:43:10 -08006748 (PackageManager.PERMISSION_GRANTED == mContext.checkCallingPermission(
6749 android.Manifest.permission.MODIFY_AUDIO_ROUTING));
6750 if (!hasPermissionForPolicy) {
Jean-Michel Triviaf576a02018-02-14 08:57:46 -08006751 Slog.w(TAG, errorMsg + " for pid " +
Jean-Michel Trivi0212be52014-11-24 14:43:10 -08006752 + Binder.getCallingPid() + " / uid "
6753 + Binder.getCallingUid() + ", need MODIFY_AUDIO_ROUTING");
Jean-Michel Triviaf576a02018-02-14 08:57:46 -08006754 return null;
Jean-Michel Trivi0212be52014-11-24 14:43:10 -08006755 }
Jean-Michel Triviaf576a02018-02-14 08:57:46 -08006756 // policy registered?
6757 final AudioPolicyProxy app = mAudioPolicies.get(pcb.asBinder());
6758 if (app == null) {
6759 Slog.w(TAG, errorMsg + " for pid " +
6760 + Binder.getCallingPid() + " / uid "
6761 + Binder.getCallingUid() + ", unregistered policy");
6762 return null;
6763 }
6764 return app;
6765 }
Jean-Michel Trivi0212be52014-11-24 14:43:10 -08006766
Jean-Michel Triviaf576a02018-02-14 08:57:46 -08006767 public int addMixForPolicy(AudioPolicyConfig policyConfig, IAudioPolicyCallback pcb) {
6768 if (DEBUG_AP) { Log.d(TAG, "addMixForPolicy for " + pcb.asBinder()
6769 + " with config:" + policyConfig); }
Jean-Michel Trivi0212be52014-11-24 14:43:10 -08006770 synchronized (mAudioPolicies) {
Jean-Michel Triviaf576a02018-02-14 08:57:46 -08006771 final AudioPolicyProxy app =
6772 checkUpdateForPolicy(pcb, "Cannot add AudioMix in audio policy");
6773 if (app == null){
6774 return AudioManager.ERROR;
6775 }
6776 app.addMixes(policyConfig.getMixes());
6777 }
6778 return AudioManager.SUCCESS;
6779 }
6780
6781 public int removeMixForPolicy(AudioPolicyConfig policyConfig, IAudioPolicyCallback pcb) {
6782 if (DEBUG_AP) { Log.d(TAG, "removeMixForPolicy for " + pcb.asBinder()
6783 + " with config:" + policyConfig); }
6784 synchronized (mAudioPolicies) {
6785 final AudioPolicyProxy app =
6786 checkUpdateForPolicy(pcb, "Cannot add AudioMix in audio policy");
6787 if (app == null) {
6788 return AudioManager.ERROR;
6789 }
6790 app.removeMixes(policyConfig.getMixes());
6791 }
6792 return AudioManager.SUCCESS;
6793 }
6794
Jean-Michel Trivid6f65de2018-12-18 18:49:14 -08006795 /** see AudioPolicy.setUidDeviceAffinity() */
6796 public int setUidDeviceAffinity(IAudioPolicyCallback pcb, int uid,
Jean-Michel Trivif93107f2019-01-08 09:38:25 -08006797 @NonNull int[] deviceTypes, @NonNull String[] deviceAddresses) {
6798 if (DEBUG_AP) {
6799 Log.d(TAG, "setUidDeviceAffinity for " + pcb.asBinder() + " uid:" + uid);
6800 }
Jean-Michel Trivid6f65de2018-12-18 18:49:14 -08006801 synchronized (mAudioPolicies) {
6802 final AudioPolicyProxy app =
6803 checkUpdateForPolicy(pcb, "Cannot change device affinity in audio policy");
6804 if (app == null) {
6805 return AudioManager.ERROR;
6806 }
6807 if (!app.hasMixRoutedToDevices(deviceTypes, deviceAddresses)) {
6808 return AudioManager.ERROR;
6809 }
Jean-Michel Trivif93107f2019-01-08 09:38:25 -08006810 return app.setUidDeviceAffinities(uid, deviceTypes, deviceAddresses);
Jean-Michel Trivid6f65de2018-12-18 18:49:14 -08006811 }
Jean-Michel Trivid6f65de2018-12-18 18:49:14 -08006812 }
6813
6814 /** see AudioPolicy.removeUidDeviceAffinity() */
6815 public int removeUidDeviceAffinity(IAudioPolicyCallback pcb, int uid) {
Jean-Michel Trivif93107f2019-01-08 09:38:25 -08006816 if (DEBUG_AP) {
6817 Log.d(TAG, "removeUidDeviceAffinity for " + pcb.asBinder() + " uid:" + uid);
6818 }
Jean-Michel Trivid6f65de2018-12-18 18:49:14 -08006819 synchronized (mAudioPolicies) {
6820 final AudioPolicyProxy app =
6821 checkUpdateForPolicy(pcb, "Cannot remove device affinity in audio policy");
6822 if (app == null) {
6823 return AudioManager.ERROR;
6824 }
Jean-Michel Trivif93107f2019-01-08 09:38:25 -08006825 return app.removeUidDeviceAffinities(uid);
Jean-Michel Trivid6f65de2018-12-18 18:49:14 -08006826 }
Jean-Michel Trivid6f65de2018-12-18 18:49:14 -08006827 }
6828
Jean-Michel Triviaf576a02018-02-14 08:57:46 -08006829 public int setFocusPropertiesForPolicy(int duckingBehavior, IAudioPolicyCallback pcb) {
6830 if (DEBUG_AP) Log.d(TAG, "setFocusPropertiesForPolicy() duck behavior=" + duckingBehavior
6831 + " policy " + pcb.asBinder());
6832 synchronized (mAudioPolicies) {
6833 final AudioPolicyProxy app =
6834 checkUpdateForPolicy(pcb, "Cannot change audio policy focus properties");
6835 if (app == null){
6836 return AudioManager.ERROR;
6837 }
Jean-Michel Trivi0212be52014-11-24 14:43:10 -08006838 if (!mAudioPolicies.containsKey(pcb.asBinder())) {
6839 Slog.e(TAG, "Cannot change audio policy focus properties, unregistered policy");
6840 return AudioManager.ERROR;
6841 }
Jean-Michel Trivi0212be52014-11-24 14:43:10 -08006842 if (duckingBehavior == AudioPolicy.FOCUS_POLICY_DUCKING_IN_POLICY) {
6843 // is there already one policy managing ducking?
Eric Laurent0867bed2015-05-20 14:49:08 -07006844 for (AudioPolicyProxy policy : mAudioPolicies.values()) {
Jean-Michel Trivi0212be52014-11-24 14:43:10 -08006845 if (policy.mFocusDuckBehavior == AudioPolicy.FOCUS_POLICY_DUCKING_IN_POLICY) {
6846 Slog.e(TAG, "Cannot change audio policy ducking behavior, already handled");
6847 return AudioManager.ERROR;
6848 }
6849 }
6850 }
6851 app.mFocusDuckBehavior = duckingBehavior;
6852 mMediaFocusControl.setDuckingInExtPolicyAvailable(
6853 duckingBehavior == AudioPolicy.FOCUS_POLICY_DUCKING_IN_POLICY);
6854 }
6855 return AudioManager.SUCCESS;
6856 }
6857
Jean-Michel Trivi0c88f492019-04-12 15:43:56 -07006858 /** see AudioManager.hasRegisteredDynamicPolicy */
6859 public boolean hasRegisteredDynamicPolicy() {
6860 synchronized (mAudioPolicies) {
6861 return !mAudioPolicies.isEmpty();
6862 }
6863 }
6864
Jean-Michel Trivi610aa9b2018-01-27 15:42:42 -08006865 private final Object mExtVolumeControllerLock = new Object();
6866 private IAudioPolicyCallback mExtVolumeController;
6867 private void setExtVolumeController(IAudioPolicyCallback apc) {
6868 if (!mContext.getResources().getBoolean(
6869 com.android.internal.R.bool.config_handleVolumeKeysInWindowManager)) {
6870 Log.e(TAG, "Cannot set external volume controller: device not set for volume keys" +
6871 " handled in PhoneWindowManager");
6872 return;
6873 }
6874 synchronized (mExtVolumeControllerLock) {
6875 if (mExtVolumeController != null && !mExtVolumeController.asBinder().pingBinder()) {
6876 Log.e(TAG, "Cannot set external volume controller: existing controller");
6877 }
6878 mExtVolumeController = apc;
6879 }
6880 }
6881
Jean-Michel Trivi1b3541d2014-11-25 12:53:41 -08006882 private void dumpAudioPolicies(PrintWriter pw) {
6883 pw.println("\nAudio policies:");
6884 synchronized (mAudioPolicies) {
Eric Laurent0867bed2015-05-20 14:49:08 -07006885 for (AudioPolicyProxy policy : mAudioPolicies.values()) {
Jean-Michel Trivi1b3541d2014-11-25 12:53:41 -08006886 pw.println(policy.toLogFriendlyString());
6887 }
6888 }
6889 }
6890
Jean-Michel Trivi958876f2014-11-16 15:40:22 -08006891 //======================
Jean-Michel Trivid3c71f02015-12-07 11:59:31 -08006892 // Audio policy callbacks from AudioSystem for dynamic policies
Jean-Michel Trivi5a561092015-04-23 18:48:08 -07006893 //======================
6894 private final AudioSystem.DynamicPolicyCallback mDynPolicyCallback =
6895 new AudioSystem.DynamicPolicyCallback() {
6896 public void onDynamicPolicyMixStateUpdate(String regId, int state) {
6897 if (!TextUtils.isEmpty(regId)) {
6898 sendMsg(mAudioHandler, MSG_DYN_POLICY_MIX_STATE_UPDATE, SENDMSG_QUEUE,
6899 state /*arg1*/, 0 /*arg2 ignored*/, regId /*obj*/, 0 /*delay*/);
6900 }
6901 }
6902 };
6903
6904 private void onDynPolicyMixStateUpdate(String regId, int state) {
6905 if (DEBUG_AP) Log.d(TAG, "onDynamicPolicyMixStateUpdate("+ regId + ", " + state +")");
6906 synchronized (mAudioPolicies) {
6907 for (AudioPolicyProxy policy : mAudioPolicies.values()) {
6908 for (AudioMix mix : policy.getMixes()) {
6909 if (mix.getRegistration().equals(regId)) {
6910 try {
6911 policy.mPolicyCallback.notifyMixStateUpdate(regId, state);
6912 } catch (RemoteException e) {
6913 Log.e(TAG, "Can't call notifyMixStateUpdate() on IAudioPolicyCallback "
6914 + policy.mPolicyCallback.asBinder(), e);
6915 }
6916 return;
6917 }
6918 }
6919 }
6920 }
Jean-Michel Trivid3c71f02015-12-07 11:59:31 -08006921 }
Jean-Michel Trivi5a561092015-04-23 18:48:08 -07006922
Jean-Michel Trivid3c71f02015-12-07 11:59:31 -08006923 //======================
6924 // Audio policy callbacks from AudioSystem for recording configuration updates
6925 //======================
Jean-Michel Trivi66ffacf2017-02-04 17:25:31 -08006926 private final RecordingActivityMonitor mRecordMonitor;
Jean-Michel Trivid3c71f02015-12-07 11:59:31 -08006927
6928 public void registerRecordingCallback(IRecordingConfigDispatcher rcdb) {
Jean-Michel Trivi66ffacf2017-02-04 17:25:31 -08006929 final boolean isPrivileged =
6930 (PackageManager.PERMISSION_GRANTED == mContext.checkCallingPermission(
6931 android.Manifest.permission.MODIFY_AUDIO_ROUTING));
6932 mRecordMonitor.registerRecordingCallback(rcdb, isPrivileged);
Jean-Michel Trivid3c71f02015-12-07 11:59:31 -08006933 }
6934
6935 public void unregisterRecordingCallback(IRecordingConfigDispatcher rcdb) {
6936 mRecordMonitor.unregisterRecordingCallback(rcdb);
6937 }
6938
Jean-Michel Trivif04fab12016-05-19 10:42:35 -07006939 public List<AudioRecordingConfiguration> getActiveRecordingConfigurations() {
Jean-Michel Trivi66ffacf2017-02-04 17:25:31 -08006940 final boolean isPrivileged =
6941 (PackageManager.PERMISSION_GRANTED == mContext.checkCallingPermission(
6942 android.Manifest.permission.MODIFY_AUDIO_ROUTING));
6943 return mRecordMonitor.getActiveRecordingConfigurations(isPrivileged);
Jean-Michel Trivi5a561092015-04-23 18:48:08 -07006944 }
6945
Mikhail Naganova00883d2019-04-18 12:36:27 -07006946 //======================
6947 // Audio recording state notification from clients
6948 //======================
6949 /**
6950 * Track a recorder provided by the client
6951 */
6952 public int trackRecorder(IBinder recorder) {
6953 return mRecordMonitor.trackRecorder(recorder);
6954 }
6955
6956 /**
6957 * Receive an event from the client about a tracked recorder
6958 */
6959 public void recorderEvent(int riid, int event) {
6960 mRecordMonitor.recorderEvent(riid, event);
6961 }
6962
Robin Lee7af9a742017-02-20 14:47:30 +00006963 public void disableRingtoneSync(final int userId) {
Andre Lago7bdc6d82016-09-22 18:00:41 +01006964 final int callingUserId = UserHandle.getCallingUserId();
Robin Lee7af9a742017-02-20 14:47:30 +00006965 if (callingUserId != userId) {
6966 mContext.enforceCallingOrSelfPermission(Manifest.permission.INTERACT_ACROSS_USERS_FULL,
6967 "disable sound settings syncing for another profile");
6968 }
Andre Lago7bdc6d82016-09-22 18:00:41 +01006969 final long token = Binder.clearCallingIdentity();
6970 try {
Robin Lee7af9a742017-02-20 14:47:30 +00006971 // Disable the sync setting so the profile uses its own sound settings.
6972 Settings.Secure.putIntForUser(mContentResolver, Settings.Secure.SYNC_PARENT_SOUNDS,
6973 0 /* false */, userId);
Andre Lago7bdc6d82016-09-22 18:00:41 +01006974 } finally {
6975 Binder.restoreCallingIdentity(token);
6976 }
6977 }
6978
Jean-Michel Trivi5a561092015-04-23 18:48:08 -07006979 //======================
Jean-Michel Trivi46e310b2017-01-04 15:58:02 -08006980 // Audio playback notification
Jean-Michel Trivi292a6a42016-12-01 08:32:15 -08006981 //======================
Eric Laurente5a351c2017-09-27 20:11:51 -07006982 private final PlaybackActivityMonitor mPlaybackMonitor;
Jean-Michel Trivi292a6a42016-12-01 08:32:15 -08006983
6984 public void registerPlaybackCallback(IPlaybackConfigDispatcher pcdb) {
Jean-Michel Trivi44a8f532017-01-02 14:36:43 -08006985 final boolean isPrivileged =
Jaewan Kim92dea332017-02-02 11:52:08 +09006986 (PackageManager.PERMISSION_GRANTED == mContext.checkCallingOrSelfPermission(
Jean-Michel Trivi292a6a42016-12-01 08:32:15 -08006987 android.Manifest.permission.MODIFY_AUDIO_ROUTING));
6988 mPlaybackMonitor.registerPlaybackCallback(pcdb, isPrivileged);
6989 }
6990
6991 public void unregisterPlaybackCallback(IPlaybackConfigDispatcher pcdb) {
6992 mPlaybackMonitor.unregisterPlaybackCallback(pcdb);
6993 }
6994
6995 public List<AudioPlaybackConfiguration> getActivePlaybackConfigurations() {
Jean-Michel Trivi44a8f532017-01-02 14:36:43 -08006996 final boolean isPrivileged =
Jaewan Kim92dea332017-02-02 11:52:08 +09006997 (PackageManager.PERMISSION_GRANTED == mContext.checkCallingOrSelfPermission(
Jean-Michel Trivi44a8f532017-01-02 14:36:43 -08006998 android.Manifest.permission.MODIFY_AUDIO_ROUTING));
6999 return mPlaybackMonitor.getActivePlaybackConfigurations(isPrivileged);
Jean-Michel Trivi292a6a42016-12-01 08:32:15 -08007000 }
7001
Jean-Michel Trivi44a8f532017-01-02 14:36:43 -08007002 public int trackPlayer(PlayerBase.PlayerIdCard pic) {
7003 return mPlaybackMonitor.trackPlayer(pic);
Jean-Michel Trivi292a6a42016-12-01 08:32:15 -08007004 }
7005
7006 public void playerAttributes(int piid, AudioAttributes attr) {
Jean-Michel Trivi46e310b2017-01-04 15:58:02 -08007007 mPlaybackMonitor.playerAttributes(piid, attr, Binder.getCallingUid());
Jean-Michel Trivi292a6a42016-12-01 08:32:15 -08007008 }
7009
7010 public void playerEvent(int piid, int event) {
Jean-Michel Trivi46e310b2017-01-04 15:58:02 -08007011 mPlaybackMonitor.playerEvent(piid, event, Binder.getCallingUid());
Jean-Michel Trivi292a6a42016-12-01 08:32:15 -08007012 }
7013
Jean-Michel Trivi3120059d2017-08-28 12:40:55 -07007014 public void playerHasOpPlayAudio(int piid, boolean hasOpPlayAudio) {
7015 mPlaybackMonitor.playerHasOpPlayAudio(piid, hasOpPlayAudio, Binder.getCallingUid());
7016 }
7017
Jean-Michel Trivi292a6a42016-12-01 08:32:15 -08007018 public void releasePlayer(int piid) {
Jean-Michel Trivi46e310b2017-01-04 15:58:02 -08007019 mPlaybackMonitor.releasePlayer(piid, Binder.getCallingUid());
Jean-Michel Trivi292a6a42016-12-01 08:32:15 -08007020 }
7021
7022 //======================
Jean-Michel Trivi58850372018-09-14 16:01:28 -07007023 // Audio device management
7024 //======================
7025 private final AudioDeviceBroker mDeviceBroker;
7026
7027 //======================
Jean-Michel Trivi958876f2014-11-16 15:40:22 -08007028 // Audio policy proxy
7029 //======================
Jean-Michel Trivid6f65de2018-12-18 18:49:14 -08007030 private static final class AudioDeviceArray {
7031 final @NonNull int[] mDeviceTypes;
7032 final @NonNull String[] mDeviceAddresses;
7033 AudioDeviceArray(@NonNull int[] types, @NonNull String[] addresses) {
7034 mDeviceTypes = types;
7035 mDeviceAddresses = addresses;
7036 }
7037 }
7038
Jean-Michel Trivi8fdb0d42014-07-16 19:08:37 -07007039 /**
Jean-Michel Trivi1b3541d2014-11-25 12:53:41 -08007040 * This internal class inherits from AudioPolicyConfig, each instance contains all the
7041 * mixes of an AudioPolicy and their configurations.
Jean-Michel Trivi8fdb0d42014-07-16 19:08:37 -07007042 */
7043 public class AudioPolicyProxy extends AudioPolicyConfig implements IBinder.DeathRecipient {
Jean-Michel Trivia8b6bd82014-07-01 09:48:46 -07007044 private static final String TAG = "AudioPolicyProxy";
Jean-Michel Trivi610aa9b2018-01-27 15:42:42 -08007045 final IAudioPolicyCallback mPolicyCallback;
7046 final boolean mHasFocusListener;
7047 final boolean mIsVolumeController;
Jean-Michel Trivid6f65de2018-12-18 18:49:14 -08007048 final HashMap<Integer, AudioDeviceArray> mUidDeviceAffinities =
7049 new HashMap<Integer, AudioDeviceArray>();
Jean-Michel Trivi0212be52014-11-24 14:43:10 -08007050 /**
7051 * Audio focus ducking behavior for an audio policy.
7052 * This variable reflects the value that was successfully set in
7053 * {@link AudioService#setFocusPropertiesForPolicy(int, IAudioPolicyCallback)}. This
7054 * implies that a value of FOCUS_POLICY_DUCKING_IN_POLICY means the corresponding policy
7055 * is handling ducking for audio focus.
7056 */
7057 int mFocusDuckBehavior = AudioPolicy.FOCUS_POLICY_DUCKING_DEFAULT;
Jean-Michel Trivi126cf032017-04-02 23:19:02 -07007058 boolean mIsFocusPolicy = false;
Jean-Michel Triviee7d2452019-03-19 12:29:27 -07007059 boolean mIsTestFocusPolicy = false;
Jean-Michel Trivi0212be52014-11-24 14:43:10 -08007060
7061 AudioPolicyProxy(AudioPolicyConfig config, IAudioPolicyCallback token,
Jean-Michel Triviee7d2452019-03-19 12:29:27 -07007062 boolean hasFocusListener, boolean isFocusPolicy, boolean isTestFocusPolicy,
7063 boolean isVolumeController) {
Jean-Michel Trivi8fdb0d42014-07-16 19:08:37 -07007064 super(config);
Jean-Michel Trivi1b3541d2014-11-25 12:53:41 -08007065 setRegistration(new String(config.hashCode() + ":ap:" + mAudioPolicyCounter++));
Jean-Michel Trivi5a561092015-04-23 18:48:08 -07007066 mPolicyCallback = token;
Jean-Michel Trivi0212be52014-11-24 14:43:10 -08007067 mHasFocusListener = hasFocusListener;
Jean-Michel Trivi610aa9b2018-01-27 15:42:42 -08007068 mIsVolumeController = isVolumeController;
Jean-Michel Trivi0212be52014-11-24 14:43:10 -08007069 if (mHasFocusListener) {
Jean-Michel Trivi5a561092015-04-23 18:48:08 -07007070 mMediaFocusControl.addFocusFollower(mPolicyCallback);
Jean-Michel Trivi126cf032017-04-02 23:19:02 -07007071 // can only ever be true if there is a focus listener
7072 if (isFocusPolicy) {
7073 mIsFocusPolicy = true;
Jean-Michel Triviee7d2452019-03-19 12:29:27 -07007074 mIsTestFocusPolicy = isTestFocusPolicy;
7075 mMediaFocusControl.setFocusPolicy(mPolicyCallback, mIsTestFocusPolicy);
Jean-Michel Trivi126cf032017-04-02 23:19:02 -07007076 }
Jean-Michel Trivi0212be52014-11-24 14:43:10 -08007077 }
Jean-Michel Trivi610aa9b2018-01-27 15:42:42 -08007078 if (mIsVolumeController) {
7079 setExtVolumeController(mPolicyCallback);
7080 }
Eric Laurent7f5eb9f2014-12-01 19:36:30 -08007081 connectMixes();
Jean-Michel Trivia8b6bd82014-07-01 09:48:46 -07007082 }
7083
7084 public void binderDied() {
7085 synchronized (mAudioPolicies) {
Jean-Michel Trivi5a561092015-04-23 18:48:08 -07007086 Log.i(TAG, "audio policy " + mPolicyCallback + " died");
Jean-Michel Trivi0212be52014-11-24 14:43:10 -08007087 release();
Jean-Michel Trivi5a561092015-04-23 18:48:08 -07007088 mAudioPolicies.remove(mPolicyCallback.asBinder());
Jean-Michel Trivi8fdb0d42014-07-16 19:08:37 -07007089 }
Jean-Michel Trivi610aa9b2018-01-27 15:42:42 -08007090 if (mIsVolumeController) {
7091 synchronized (mExtVolumeControllerLock) {
7092 mExtVolumeController = null;
7093 }
7094 }
Jean-Michel Trivi8fdb0d42014-07-16 19:08:37 -07007095 }
7096
Jean-Michel Trivi0212be52014-11-24 14:43:10 -08007097 String getRegistrationId() {
Jean-Michel Trivi1b3541d2014-11-25 12:53:41 -08007098 return getRegistration();
Jean-Michel Trivi8fdb0d42014-07-16 19:08:37 -07007099 }
7100
Jean-Michel Trivi0212be52014-11-24 14:43:10 -08007101 void release() {
Jean-Michel Trivi126cf032017-04-02 23:19:02 -07007102 if (mIsFocusPolicy) {
Jean-Michel Triviee7d2452019-03-19 12:29:27 -07007103 mMediaFocusControl.unsetFocusPolicy(mPolicyCallback, mIsTestFocusPolicy);
Jean-Michel Trivi126cf032017-04-02 23:19:02 -07007104 }
Jean-Michel Trivi0212be52014-11-24 14:43:10 -08007105 if (mFocusDuckBehavior == AudioPolicy.FOCUS_POLICY_DUCKING_IN_POLICY) {
7106 mMediaFocusControl.setDuckingInExtPolicyAvailable(false);
7107 }
7108 if (mHasFocusListener) {
Jean-Michel Trivi5a561092015-04-23 18:48:08 -07007109 mMediaFocusControl.removeFocusFollower(mPolicyCallback);
Jean-Michel Trivi0212be52014-11-24 14:43:10 -08007110 }
Eric Laurent66b69672018-01-26 18:30:51 -08007111 final long identity = Binder.clearCallingIdentity();
Eric Laurent7f5eb9f2014-12-01 19:36:30 -08007112 AudioSystem.registerPolicyMixes(mMixes, false);
Eric Laurent66b69672018-01-26 18:30:51 -08007113 Binder.restoreCallingIdentity(identity);
Jean-Michel Trivi8fdb0d42014-07-16 19:08:37 -07007114 }
7115
Jean-Michel Trivi7db2d8f2018-03-06 10:30:59 -08007116 boolean hasMixAffectingUsage(int usage) {
7117 for (AudioMix mix : mMixes) {
7118 if (mix.isAffectingUsage(usage)) {
7119 return true;
7120 }
7121 }
7122 return false;
7123 }
7124
Jean-Michel Trivid6f65de2018-12-18 18:49:14 -08007125 // Verify all the devices in the array are served by mixes defined in this policy
7126 boolean hasMixRoutedToDevices(@NonNull int[] deviceTypes,
7127 @NonNull String[] deviceAddresses) {
7128 for (int i = 0; i < deviceTypes.length; i++) {
7129 boolean hasDevice = false;
7130 for (AudioMix mix : mMixes) {
7131 // this will check both that the mix has ROUTE_FLAG_RENDER and the device
7132 // is reached by this mix
7133 if (mix.isRoutedToDevice(deviceTypes[i], deviceAddresses[i])) {
7134 hasDevice = true;
7135 break;
7136 }
7137 }
7138 if (!hasDevice) {
7139 return false;
7140 }
7141 }
7142 return true;
7143 }
7144
Jean-Michel Triviaf576a02018-02-14 08:57:46 -08007145 void addMixes(@NonNull ArrayList<AudioMix> mixes) {
7146 // TODO optimize to not have to unregister the mixes already in place
7147 synchronized (mMixes) {
7148 AudioSystem.registerPolicyMixes(mMixes, false);
7149 this.add(mixes);
7150 AudioSystem.registerPolicyMixes(mMixes, true);
7151 }
7152 }
7153
7154 void removeMixes(@NonNull ArrayList<AudioMix> mixes) {
7155 // TODO optimize to not have to unregister the mixes already in place
7156 synchronized (mMixes) {
7157 AudioSystem.registerPolicyMixes(mMixes, false);
7158 this.remove(mixes);
7159 AudioSystem.registerPolicyMixes(mMixes, true);
7160 }
7161 }
7162
Eric Laurent7f5eb9f2014-12-01 19:36:30 -08007163 void connectMixes() {
Eric Laurent66b69672018-01-26 18:30:51 -08007164 final long identity = Binder.clearCallingIdentity();
Eric Laurent7f5eb9f2014-12-01 19:36:30 -08007165 AudioSystem.registerPolicyMixes(mMixes, true);
Eric Laurent66b69672018-01-26 18:30:51 -08007166 Binder.restoreCallingIdentity(identity);
Jean-Michel Trivia8b6bd82014-07-01 09:48:46 -07007167 }
Jean-Michel Trivid6f65de2018-12-18 18:49:14 -08007168
Jean-Michel Trivif93107f2019-01-08 09:38:25 -08007169 int setUidDeviceAffinities(int uid, @NonNull int[] types, @NonNull String[] addresses) {
Jean-Michel Trivid6f65de2018-12-18 18:49:14 -08007170 final Integer Uid = new Integer(uid);
Jean-Michel Trivif93107f2019-01-08 09:38:25 -08007171 int res;
Jean-Michel Trivid6f65de2018-12-18 18:49:14 -08007172 if (mUidDeviceAffinities.remove(Uid) != null) {
7173 final long identity = Binder.clearCallingIdentity();
Jean-Michel Trivif93107f2019-01-08 09:38:25 -08007174 res = AudioSystem.removeUidDeviceAffinities(uid);
Jean-Michel Trivid6f65de2018-12-18 18:49:14 -08007175 Binder.restoreCallingIdentity(identity);
Jean-Michel Trivif93107f2019-01-08 09:38:25 -08007176 if (res != AudioSystem.SUCCESS) {
7177 Log.e(TAG, "AudioSystem. removeUidDeviceAffinities(" + uid + ") failed, "
7178 + " cannot call AudioSystem.setUidDeviceAffinities");
7179 return AudioManager.ERROR;
7180 }
Jean-Michel Trivid6f65de2018-12-18 18:49:14 -08007181 }
7182 final long identity = Binder.clearCallingIdentity();
Jean-Michel Trivif93107f2019-01-08 09:38:25 -08007183 res = AudioSystem.setUidDeviceAffinities(uid, types, addresses);
Jean-Michel Trivid6f65de2018-12-18 18:49:14 -08007184 Binder.restoreCallingIdentity(identity);
7185 if (res == AudioSystem.SUCCESS) {
7186 mUidDeviceAffinities.put(Uid, new AudioDeviceArray(types, addresses));
Jean-Michel Trivif93107f2019-01-08 09:38:25 -08007187 return AudioManager.SUCCESS;
Jean-Michel Trivid6f65de2018-12-18 18:49:14 -08007188 }
Jean-Michel Trivif93107f2019-01-08 09:38:25 -08007189 Log.e(TAG, "AudioSystem. setUidDeviceAffinities(" + uid + ") failed");
7190 return AudioManager.ERROR;
Jean-Michel Trivid6f65de2018-12-18 18:49:14 -08007191 }
7192
Jean-Michel Trivif93107f2019-01-08 09:38:25 -08007193 int removeUidDeviceAffinities(int uid) {
Jean-Michel Trivid6f65de2018-12-18 18:49:14 -08007194 if (mUidDeviceAffinities.remove(new Integer(uid)) != null) {
7195 final long identity = Binder.clearCallingIdentity();
Jean-Michel Trivif93107f2019-01-08 09:38:25 -08007196 final int res = AudioSystem.removeUidDeviceAffinities(uid);
Jean-Michel Trivid6f65de2018-12-18 18:49:14 -08007197 Binder.restoreCallingIdentity(identity);
Jean-Michel Trivif93107f2019-01-08 09:38:25 -08007198 if (res == AudioSystem.SUCCESS) {
7199 return AudioManager.SUCCESS;
7200 }
Jean-Michel Trivid6f65de2018-12-18 18:49:14 -08007201 }
Jean-Michel Trivif93107f2019-01-08 09:38:25 -08007202 Log.e(TAG, "AudioSystem. removeUidDeviceAffinities failed");
7203 return AudioManager.ERROR;
Jean-Michel Trivid6f65de2018-12-18 18:49:14 -08007204 }
Jean-Michel Trivia8b6bd82014-07-01 09:48:46 -07007205 };
7206
Jean-Michel Trivi126cf032017-04-02 23:19:02 -07007207 //======================
7208 // Audio policy: focus
7209 //======================
7210 /** */
7211 public int dispatchFocusChange(AudioFocusInfo afi, int focusChange, IAudioPolicyCallback pcb) {
Jean-Michel Trivie2d8aae2018-01-30 15:09:47 -08007212 if (afi == null) {
7213 throw new IllegalArgumentException("Illegal null AudioFocusInfo");
7214 }
7215 if (pcb == null) {
7216 throw new IllegalArgumentException("Illegal null AudioPolicy callback");
7217 }
Jean-Michel Trivi126cf032017-04-02 23:19:02 -07007218 synchronized (mAudioPolicies) {
7219 if (!mAudioPolicies.containsKey(pcb.asBinder())) {
7220 throw new IllegalStateException("Unregistered AudioPolicy for focus dispatch");
7221 }
7222 return mMediaFocusControl.dispatchFocusChange(afi, focusChange);
7223 }
7224 }
7225
Jean-Michel Trivie2d8aae2018-01-30 15:09:47 -08007226 public void setFocusRequestResultFromExtPolicy(AudioFocusInfo afi, int requestResult,
7227 IAudioPolicyCallback pcb) {
7228 if (afi == null) {
7229 throw new IllegalArgumentException("Illegal null AudioFocusInfo");
7230 }
7231 if (pcb == null) {
7232 throw new IllegalArgumentException("Illegal null AudioPolicy callback");
7233 }
7234 synchronized (mAudioPolicies) {
7235 if (!mAudioPolicies.containsKey(pcb.asBinder())) {
7236 throw new IllegalStateException("Unregistered AudioPolicy for external focus");
7237 }
7238 mMediaFocusControl.setFocusRequestResultFromExtPolicy(afi, requestResult);
7239 }
7240 }
7241
7242
Jean-Michel Trivi126cf032017-04-02 23:19:02 -07007243 //======================
Eric Laurent1d3cdce2018-01-20 10:31:21 -08007244 // Audioserver state displatch
7245 //======================
7246 private class AsdProxy implements IBinder.DeathRecipient {
7247 private final IAudioServerStateDispatcher mAsd;
7248
7249 AsdProxy(IAudioServerStateDispatcher asd) {
7250 mAsd = asd;
7251 }
7252
7253 public void binderDied() {
7254 synchronized (mAudioServerStateListeners) {
7255 mAudioServerStateListeners.remove(mAsd.asBinder());
7256 }
7257 }
7258
7259 IAudioServerStateDispatcher callback() {
7260 return mAsd;
7261 }
7262 }
7263
7264 private HashMap<IBinder, AsdProxy> mAudioServerStateListeners =
7265 new HashMap<IBinder, AsdProxy>();
7266
7267 private void checkMonitorAudioServerStatePermission() {
7268 if (!(mContext.checkCallingOrSelfPermission(
7269 android.Manifest.permission.MODIFY_PHONE_STATE) ==
7270 PackageManager.PERMISSION_GRANTED ||
7271 mContext.checkCallingOrSelfPermission(
7272 android.Manifest.permission.MODIFY_AUDIO_ROUTING) ==
7273 PackageManager.PERMISSION_GRANTED)) {
7274 throw new SecurityException("Not allowed to monitor audioserver state");
7275 }
7276 }
7277
7278 public void registerAudioServerStateDispatcher(IAudioServerStateDispatcher asd) {
7279 checkMonitorAudioServerStatePermission();
7280 synchronized (mAudioServerStateListeners) {
7281 if (mAudioServerStateListeners.containsKey(asd.asBinder())) {
7282 Slog.w(TAG, "Cannot re-register audio server state dispatcher");
7283 return;
7284 }
7285 AsdProxy asdp = new AsdProxy(asd);
7286 try {
7287 asd.asBinder().linkToDeath(asdp, 0/*flags*/);
7288 } catch (RemoteException e) {
7289
7290 }
7291 mAudioServerStateListeners.put(asd.asBinder(), asdp);
7292 }
7293 }
7294
7295 public void unregisterAudioServerStateDispatcher(IAudioServerStateDispatcher asd) {
7296 checkMonitorAudioServerStatePermission();
7297 synchronized (mAudioServerStateListeners) {
7298 AsdProxy asdp = mAudioServerStateListeners.remove(asd.asBinder());
7299 if (asdp == null) {
7300 Slog.w(TAG, "Trying to unregister unknown audioserver state dispatcher for pid "
7301 + Binder.getCallingPid() + " / uid " + Binder.getCallingUid());
7302 return;
7303 } else {
7304 asd.asBinder().unlinkToDeath(asdp, 0/*flags*/);
7305 }
7306 }
7307 }
7308
7309 public boolean isAudioServerRunning() {
7310 checkMonitorAudioServerStatePermission();
7311 return (AudioSystem.checkAudioFlinger() == AudioSystem.AUDIO_STATUS_OK);
7312 }
7313
7314 //======================
Jean-Michel Trivi126cf032017-04-02 23:19:02 -07007315 // misc
7316 //======================
Jean-Michel Triviaf576a02018-02-14 08:57:46 -08007317 private final HashMap<IBinder, AudioPolicyProxy> mAudioPolicies =
Jean-Michel Trivia8b6bd82014-07-01 09:48:46 -07007318 new HashMap<IBinder, AudioPolicyProxy>();
Jean-Michel Triviaf576a02018-02-14 08:57:46 -08007319 @GuardedBy("mAudioPolicies")
7320 private int mAudioPolicyCounter = 0;
Phil Burkac0f7042016-02-24 12:19:08 -08007321}