blob: 5d802a76ae95cafdc90c2404cb7505ce2d862ba3 [file] [log] [blame]
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001/*
2 * Copyright (C) 2006 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
John Spurlock61560172015-02-06 19:46:04 -050017package com.android.server.audio;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080018
Jeff Sharkey098d5802012-04-26 17:30:34 -070019import static android.Manifest.permission.REMOTE_AUDIO_PLAYBACK;
Amith Yamasanic696a532011-10-28 17:02:37 -070020import static android.media.AudioManager.RINGER_MODE_NORMAL;
21import static android.media.AudioManager.RINGER_MODE_SILENT;
22import static android.media.AudioManager.RINGER_MODE_VIBRATE;
Beverlyd6964762018-02-16 14:07:03 -050023import static android.media.AudioManager.STREAM_SYSTEM;
Fyodor Kupolovbcb6c1e2015-05-11 12:05:15 -070024import static android.os.Process.FIRST_APPLICATION_UID;
Mike Digman55272862018-02-20 14:35:17 -080025import static android.provider.Settings.Secure.VOLUME_HUSH_MUTE;
26import static android.provider.Settings.Secure.VOLUME_HUSH_OFF;
27import static android.provider.Settings.Secure.VOLUME_HUSH_VIBRATE;
Amith Yamasanic696a532011-10-28 17:02:37 -070028
Fyodor Kupolovb5013302015-04-17 17:59:14 -070029import android.Manifest;
Jean-Michel Trivi58850372018-09-14 16:01:28 -070030import android.annotation.IntDef;
Jean-Michel Trivi7ed71472018-02-02 16:52:09 -080031import android.annotation.NonNull;
Jean-Michel Trivia53b7052017-04-12 18:27:01 -070032import android.annotation.Nullable;
Glenn Kastenfd116ad2013-07-12 17:10:39 -070033import android.app.ActivityManager;
Fyodor Kupolovb5013302015-04-17 17:59:14 -070034import android.app.ActivityManagerInternal;
Fyodor Kupolovb5013302015-04-17 17:59:14 -070035import android.app.AppGlobals;
Dianne Hackbornba50b97c2013-04-30 15:04:46 -070036import android.app.AppOpsManager;
Dianne Hackborn3e99f652017-07-05 16:33:56 -070037import android.app.IUidObserver;
Julia Reynolds48034f82016-03-09 10:15:16 -050038import android.app.NotificationManager;
Jaikumar Ganesh82aa7f02010-09-27 17:05:10 -070039import android.bluetooth.BluetoothAdapter;
Jaikumar Ganesh82aa7f02010-09-27 17:05:10 -070040import android.bluetooth.BluetoothDevice;
41import android.bluetooth.BluetoothHeadset;
42import android.bluetooth.BluetoothProfile;
Nick Pellybd022f42009-08-14 18:33:38 -070043import android.content.BroadcastReceiver;
Jean-Michel Trivid327f212010-03-16 21:44:33 -070044import android.content.ComponentName;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080045import android.content.ContentResolver;
46import android.content.Context;
47import android.content.Intent;
Eric Laurenta553c252009-07-17 12:17:14 -070048import android.content.IntentFilter;
Julia Reynolds48034f82016-03-09 10:15:16 -050049import android.content.pm.ApplicationInfo;
Fyodor Kupolovb5013302015-04-17 17:59:14 -070050import android.content.pm.PackageInfo;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080051import android.content.pm.PackageManager;
Marco Nelissenfb6df0b2017-02-15 15:25:24 -080052import android.content.pm.ResolveInfo;
Fyodor Kupolovb5013302015-04-17 17:59:14 -070053import android.content.pm.UserInfo;
Jean-Michel Trivif26f0172012-04-25 16:23:20 -070054import android.content.res.Configuration;
Eric Laurente78fced2013-03-15 16:03:47 -070055import android.content.res.Resources;
56import android.content.res.XmlResourceParser;
Jason Parekhb1096152009-03-24 17:48:25 -070057import android.database.ContentObserver;
Shubangc480a712018-06-11 18:02:42 -070058import android.hardware.hdmi.HdmiAudioSystemClient;
Jungshik Jang41d97462014-06-30 22:26:29 +090059import android.hardware.hdmi.HdmiControlManager;
Eric Laurent212532b2014-07-21 15:43:18 -070060import android.hardware.hdmi.HdmiPlaybackClient;
Jungshik Jang41d97462014-06-30 22:26:29 +090061import android.hardware.hdmi.HdmiTvClient;
Paul McLeanc837a452014-04-09 09:04:43 -070062import android.hardware.usb.UsbManager;
John Spurlock61560172015-02-06 19:46:04 -050063import android.media.AudioAttributes;
Jean-Michel Trivi126cf032017-04-02 23:19:02 -070064import android.media.AudioFocusInfo;
Jean-Michel Trivi9228af62018-01-05 17:06:17 -080065import android.media.AudioFocusRequest;
John Spurlock61560172015-02-06 19:46:04 -050066import android.media.AudioFormat;
67import android.media.AudioManager;
68import android.media.AudioManagerInternal;
Jean-Michel Trivi292a6a42016-12-01 08:32:15 -080069import android.media.AudioPlaybackConfiguration;
Jean-Michel Trivi598c0c92016-03-07 14:13:03 -080070import android.media.AudioRecordingConfiguration;
John Spurlock61560172015-02-06 19:46:04 -050071import android.media.AudioRoutesInfo;
Beverly925cde82018-01-23 09:31:23 -050072import android.media.AudioSystem;
John Spurlock61560172015-02-06 19:46:04 -050073import android.media.IAudioFocusDispatcher;
74import android.media.IAudioRoutesObserver;
Eric Laurent1d3cdce2018-01-20 10:31:21 -080075import android.media.IAudioServerStateDispatcher;
John Spurlock61560172015-02-06 19:46:04 -050076import android.media.IAudioService;
Jean-Michel Trivi292a6a42016-12-01 08:32:15 -080077import android.media.IPlaybackConfigDispatcher;
Jean-Michel Trivid3c71f02015-12-07 11:59:31 -080078import android.media.IRecordingConfigDispatcher;
John Spurlock61560172015-02-06 19:46:04 -050079import android.media.IRingtonePlayer;
80import android.media.IVolumeController;
81import android.media.MediaPlayer;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080082import android.media.MediaPlayer.OnCompletionListener;
83import android.media.MediaPlayer.OnErrorListener;
Jean-Michel Trivi292a6a42016-12-01 08:32:15 -080084import android.media.PlayerBase;
Beverly925cde82018-01-23 09:31:23 -050085import android.media.SoundPool;
86import android.media.VolumePolicy;
87import android.media.audiofx.AudioEffect;
Jean-Michel Trivi5a561092015-04-23 18:48:08 -070088import android.media.audiopolicy.AudioMix;
Jean-Michel Trivi958876f2014-11-16 15:40:22 -080089import android.media.audiopolicy.AudioPolicy;
Jean-Michel Trivia8b6bd82014-07-01 09:48:46 -070090import android.media.audiopolicy.AudioPolicyConfig;
François Gaffie0699fec2018-07-09 14:35:10 +020091import android.media.audiopolicy.AudioProductStrategies;
Jean-Michel Trivi0212be52014-11-24 14:43:10 -080092import android.media.audiopolicy.IAudioPolicyCallback;
Kevin Rocard2fe8b8b2019-02-20 11:25:23 -080093import android.media.projection.IMediaProjection;
94import android.media.projection.IMediaProjectionManager;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080095import android.os.Binder;
Eric Laurentc18c9132013-04-12 17:24:56 -070096import android.os.Build;
Makoto Onukid45a4a22015-11-02 17:17:38 -080097import android.os.Bundle;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080098import android.os.Environment;
99import android.os.Handler;
100import android.os.IBinder;
101import android.os.Looper;
102import android.os.Message;
Jean-Michel Trivic6802222012-04-30 11:15:03 -0700103import android.os.PowerManager;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800104import android.os.RemoteException;
Kevin Rocard2fe8b8b2019-02-20 11:25:23 -0800105import android.os.ServiceManager;
John Spurlock33f4e042014-07-11 13:10:58 -0400106import android.os.SystemClock;
Jaikumar Ganesh82aa7f02010-09-27 17:05:10 -0700107import android.os.SystemProperties;
Dianne Hackborn5ac72a22012-08-29 18:32:08 -0700108import android.os.UserHandle;
Fyodor Kupolovb5013302015-04-17 17:59:14 -0700109import android.os.UserManager;
Makoto Onukid45a4a22015-11-02 17:17:38 -0800110import android.os.UserManagerInternal;
111import android.os.UserManagerInternal.UserRestrictionsListener;
Mike Digman55272862018-02-20 14:35:17 -0800112import android.os.VibrationEffect;
Eric Laurentbffc3d12012-05-07 17:43:49 -0700113import android.os.Vibrator;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800114import android.provider.Settings;
115import android.provider.Settings.System;
Beverly925cde82018-01-23 09:31:23 -0500116import android.service.notification.ZenModeConfig;
Tyler Gunnef9f6f92014-09-12 22:16:17 -0700117import android.telecom.TelecomManager;
Dianne Hackborn632ca412012-06-14 19:34:10 -0700118import android.text.TextUtils;
Fyodor Kupolovb5013302015-04-17 17:59:14 -0700119import android.util.AndroidRuntimeException;
Phil Weaverf1a9aff2017-03-23 17:21:29 -0700120import android.util.IntArray;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800121import android.util.Log;
John Spurlockaa5ee4d2014-07-25 13:05:12 -0400122import android.util.MathUtils;
Jean-Michel Trivia8b6bd82014-07-01 09:48:46 -0700123import android.util.Slog;
John Spurlock2bb02ec2015-03-02 13:13:06 -0500124import android.util.SparseIntArray;
Jean-Michel Trivid327f212010-03-16 21:44:33 -0700125import android.view.KeyEvent;
Jean-Michel Trivi873cc452014-09-11 17:25:09 -0700126import android.view.accessibility.AccessibilityManager;
Mike Digman55272862018-02-20 14:35:17 -0800127import android.widget.Toast;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800128
Jean-Michel Trivi8719a1d2017-11-06 11:52:51 -0800129import com.android.internal.annotations.GuardedBy;
Jeff Sharkeyfe9a53b2017-03-31 14:08:23 -0600130import com.android.internal.util.DumpUtils;
Eric Laurente78fced2013-03-15 16:03:47 -0700131import com.android.internal.util.XmlUtils;
John Spurlock90874332015-03-10 16:00:54 -0400132import com.android.server.EventLogTags;
RoboErik0dac35a2014-08-12 15:48:49 -0700133import com.android.server.LocalServices;
Makoto Onukie1aef852015-10-15 17:28:35 -0700134import com.android.server.SystemService;
Beverly925cde82018-01-23 09:31:23 -0500135import com.android.server.audio.AudioServiceEvents.PhoneStateEvent;
136import com.android.server.audio.AudioServiceEvents.VolumeEvent;
Fyodor Kupolovb5013302015-04-17 17:59:14 -0700137import com.android.server.pm.UserManagerService;
Wale Ogunwale9e4f3e02018-05-17 09:35:39 -0700138import com.android.server.wm.ActivityTaskManagerInternal;
Eric Laurente78fced2013-03-15 16:03:47 -0700139
140import org.xmlpull.v1.XmlPullParserException;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800141
Jaekyun Seokc31033f2018-01-15 14:53:17 +0900142import java.io.File;
Jean-Michel Trivid5176cf2010-01-28 11:56:42 -0800143import java.io.FileDescriptor;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800144import java.io.IOException;
Jean-Michel Trivid5176cf2010-01-28 11:56:42 -0800145import java.io.PrintWriter;
Jean-Michel Trivi58850372018-09-14 16:01:28 -0700146import java.lang.annotation.Retention;
147import java.lang.annotation.RetentionPolicy;
Eric Laurente78fced2013-03-15 16:03:47 -0700148import java.lang.reflect.Field;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800149import java.util.ArrayList;
Jean-Michel Trivi7db2d8f2018-03-06 10:30:59 -0800150import java.util.Collection;
Eric Laurentc42ac9d2009-07-29 08:53:03 -0700151import java.util.HashMap;
152import java.util.Iterator;
Jaikumar Ganesh5a1e4cf2010-10-18 17:05:09 -0700153import java.util.List;
Jaikumar Ganesh82aa7f02010-09-27 17:05:10 -0700154import java.util.NoSuchElementException;
RoboErikd09bd0c2014-06-24 17:45:19 -0700155import java.util.Objects;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800156
157/**
158 * The implementation of the volume manager service.
159 * <p>
160 * This implementation focuses on delivering a responsive UI. Most methods are
161 * asynchronous to external calls. For example, the task of setting a volume
162 * will update our internal state, but in a separate thread will set the system
163 * volume and later persist to the database. Similarly, setting the ringer mode
164 * will update the state and broadcast a change and in a separate thread later
165 * persist the ringer mode.
166 *
167 * @hide
168 */
Jean-Michel Triviac487672016-11-11 10:05:18 -0800169public class AudioService extends IAudioService.Stub
170 implements AccessibilityManager.TouchExplorationStateChangeListener,
Jean-Michel Trivicfa55532017-01-18 11:17:51 -0800171 AccessibilityManager.AccessibilityServicesStateChangeListener {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800172
Jean-Michel Trivi58850372018-09-14 16:01:28 -0700173 private static final String TAG = "AS.AudioService";
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800174
Jean-Michel Trivi339567d2014-07-29 09:53:34 -0700175 /** Debug audio mode */
Jean-Michel Trivi58850372018-09-14 16:01:28 -0700176 protected static final boolean DEBUG_MODE = false;
Jean-Michel Trivi8fdb0d42014-07-16 19:08:37 -0700177
178 /** Debug audio policy feature */
Jean-Michel Trivi58850372018-09-14 16:01:28 -0700179 protected static final boolean DEBUG_AP = false;
Jean-Michel Trivi8fdb0d42014-07-16 19:08:37 -0700180
Jean-Michel Trivi3114ce32012-06-11 15:03:52 -0700181 /** Debug volumes */
Jean-Michel Trivi58850372018-09-14 16:01:28 -0700182 protected static final boolean DEBUG_VOL = false;
Jean-Michel Trivi18e7bce2011-08-26 12:11:36 -0700183
Paul McLean394a8e12015-03-03 10:29:19 -0700184 /** debug calls to devices APIs */
Jean-Michel Trivi58850372018-09-14 16:01:28 -0700185 protected static final boolean DEBUG_DEVICES = false;
186
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800187 /** How long to delay before persisting a change in volume/ringer mode. */
RoboErik45edba12012-03-27 17:54:36 -0700188 private static final int PERSIST_DELAY = 500;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800189
RoboErik5452e252015-02-06 15:33:53 -0800190 /** How long to delay after a volume down event before unmuting a stream */
191 private static final int UNMUTE_STREAM_DELAY = 350;
192
John Spurlock3346a802014-05-20 16:25:37 -0400193 /**
John Spurlocka11b4af2014-06-01 11:52:23 -0400194 * Only used in the result from {@link #checkForRingerModeChange(int, int, int)}
195 */
196 private static final int FLAG_ADJUST_VOLUME = 1;
197
Dianne Hackbornba50b97c2013-04-30 15:04:46 -0700198 private final Context mContext;
199 private final ContentResolver mContentResolver;
200 private final AppOpsManager mAppOps;
Eric Laurent212532b2014-07-21 15:43:18 -0700201
Eric Laurent212532b2014-07-21 15:43:18 -0700202 // the platform type affects volume and silent mode behavior
203 private final int mPlatformType;
204
Muyuan Li1ed6df62016-06-18 11:16:52 -0700205 // indicates whether the system maps all streams to a single stream.
206 private final boolean mIsSingleVolume;
207
Eric Laurent212532b2014-07-21 15:43:18 -0700208 private boolean isPlatformVoice() {
John Spurlock61560172015-02-06 19:46:04 -0500209 return mPlatformType == AudioSystem.PLATFORM_VOICE;
Eric Laurent212532b2014-07-21 15:43:18 -0700210 }
211
Jean-Michel Trivi58850372018-09-14 16:01:28 -0700212 /*package*/ boolean isPlatformTelevision() {
John Spurlock61560172015-02-06 19:46:04 -0500213 return mPlatformType == AudioSystem.PLATFORM_TELEVISION;
Eric Laurent212532b2014-07-21 15:43:18 -0700214 }
Jean-Michel Trivid5176cf2010-01-28 11:56:42 -0800215
Jean-Michel Trivi58850372018-09-14 16:01:28 -0700216 /*package*/ boolean isPlatformAutomotive() {
Hongwei Wangdaba1242018-05-29 14:36:16 -0700217 return mContext.getPackageManager().hasSystemFeature(PackageManager.FEATURE_AUTOMOTIVE);
218 }
219
John Spurlock3346a802014-05-20 16:25:37 -0400220 /** The controller for the volume UI. */
221 private final VolumeController mVolumeController = new VolumeController();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800222
223 // sendMsg() flags
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800224 /** If the msg is already queued, replace it with this one. */
225 private static final int SENDMSG_REPLACE = 0;
226 /** If the msg is already queued, ignore this one and leave the old. */
227 private static final int SENDMSG_NOOP = 1;
228 /** If the msg is already queued, queue this one and leave the old. */
229 private static final int SENDMSG_QUEUE = 2;
230
Jean-Michel Trivi3114ce32012-06-11 15:03:52 -0700231 // AudioHandler messages
Eric Laurent9bc8358d2011-11-18 16:43:31 -0800232 private static final int MSG_SET_DEVICE_VOLUME = 0;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800233 private static final int MSG_PERSIST_VOLUME = 1;
234 private static final int MSG_PERSIST_RINGER_MODE = 3;
Andy Hunged0ea402015-10-30 14:11:46 -0700235 private static final int MSG_AUDIO_SERVER_DIED = 4;
Eric Laurentdfb881f2013-07-18 14:41:39 -0700236 private static final int MSG_PLAY_SOUND_EFFECT = 5;
Eric Laurentdfb881f2013-07-18 14:41:39 -0700237 private static final int MSG_LOAD_SOUND_EFFECTS = 7;
238 private static final int MSG_SET_FORCE_USE = 8;
239 private static final int MSG_BT_HEADSET_CNCT_FAILED = 9;
240 private static final int MSG_SET_ALL_VOLUMES = 10;
Jean-Michel Trivi58850372018-09-14 16:01:28 -0700241 private static final int MSG_CHECK_MUSIC_ACTIVE = 11;
242 private static final int MSG_CONFIGURE_SAFE_MEDIA_VOLUME = 12;
243 private static final int MSG_CONFIGURE_SAFE_MEDIA_VOLUME_FORCED = 13;
244 private static final int MSG_PERSIST_SAFE_VOLUME_STATE = 14;
245 private static final int MSG_UNLOAD_SOUND_EFFECTS = 15;
246 private static final int MSG_SYSTEM_READY = 16;
247 private static final int MSG_PERSIST_MUSIC_ACTIVE_MS = 17;
248 private static final int MSG_UNMUTE_STREAM = 18;
249 private static final int MSG_DYN_POLICY_MIX_STATE_UPDATE = 19;
250 private static final int MSG_INDICATE_SYSTEM_READY = 20;
251 private static final int MSG_ACCESSORY_PLUG_MEDIA_UNMUTE = 21;
252 private static final int MSG_NOTIFY_VOL_EVENT = 22;
253 private static final int MSG_DISPATCH_AUDIO_SERVER_STATE = 23;
254 private static final int MSG_ENABLE_SURROUND_FORMATS = 24;
Jean-Michel Trivica49d312019-02-14 15:55:39 -0800255 private static final int MSG_UPDATE_RINGER_MODE = 25;
Jean-Michel Trivi3114ce32012-06-11 15:03:52 -0700256 // start of messages handled under wakelock
257 // these messages can only be queued, i.e. sent with queueMsgUnderWakeLock(),
Jean-Michel Trivie12c39b2012-06-06 10:51:58 -0700258 // and not with sendMsg(..., ..., SENDMSG_QUEUE, ...)
Jean-Michel Trivi58850372018-09-14 16:01:28 -0700259 private static final int MSG_DISABLE_AUDIO_FOR_UID = 100;
Jean-Michel Trivi3114ce32012-06-11 15:03:52 -0700260 // end of messages handled under wakelock
Eric Laurentafbb0472011-12-15 09:04:23 -0800261
Eric Laurent0867bed2015-05-20 14:49:08 -0700262 // retry delay in case of failure to indicate system ready to AudioFlinger
263 private static final int INDICATE_SYSTEM_READY_RETRY_DELAY_MS = 1000;
264
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800265 /** @see AudioSystemThread */
266 private AudioSystemThread mAudioSystemThread;
267 /** @see AudioHandler */
268 private AudioHandler mAudioHandler;
269 /** @see VolumeStreamState */
270 private VolumeStreamState[] mStreamStates;
Jean-Michel Trivi58850372018-09-14 16:01:28 -0700271
272 /*package*/ VolumeStreamState getStreamState(int stream) {
273 return mStreamStates[stream];
274 }
275
Jason Parekhb1096152009-03-24 17:48:25 -0700276 private SettingsObserver mSettingsObserver;
Eric Laurenta553c252009-07-17 12:17:14 -0700277
François Gaffie0699fec2018-07-09 14:35:10 +0200278 /** @see AudioProductStrategies */
279 private static AudioProductStrategies sAudioProductStrategies;
280
Jean-Michel Trivifa9a6982013-06-27 16:22:58 -0700281 private int mMode = AudioSystem.MODE_NORMAL;
Glenn Kastenba195eb2011-12-13 09:30:40 -0800282 // protects mRingerMode
283 private final Object mSettingsLock = new Object();
Eric Laurent45c90ce2012-04-24 18:44:22 -0700284
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800285 private SoundPool mSoundPool;
Glenn Kasten30c918c2011-11-10 17:56:41 -0800286 private final Object mSoundEffectsLock = new Object();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800287 private static final int NUM_SOUNDPOOL_CHANNELS = 4;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800288
289 /* Sound effect file names */
290 private static final String SOUND_EFFECTS_PATH = "/media/audio/ui/";
Eric Laurente78fced2013-03-15 16:03:47 -0700291 private static final List<String> SOUND_EFFECT_FILES = new ArrayList<String>();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800292
293 /* Sound effect file name mapping sound effect id (AudioManager.FX_xxx) to
294 * file index in SOUND_EFFECT_FILES[] (first column) and indicating if effect
295 * uses soundpool (second column) */
Eric Laurente78fced2013-03-15 16:03:47 -0700296 private final int[][] SOUND_EFFECT_FILES_MAP = new int[AudioManager.NUM_SOUND_EFFECTS][2];
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800297
John Spurlockb6e19e32015-03-10 21:33:44 -0400298 /** Maximum volume index values for audio streams */
Chinyue Chen6affe932018-01-24 14:51:43 +0800299 protected static int[] MAX_STREAM_VOLUME = new int[] {
Eric Laurent6ee99522009-08-25 06:30:59 -0700300 5, // STREAM_VOICE_CALL
301 7, // STREAM_SYSTEM
302 7, // STREAM_RING
303 15, // STREAM_MUSIC
304 7, // STREAM_ALARM
305 7, // STREAM_NOTIFICATION
306 15, // STREAM_BLUETOOTH_SCO
307 7, // STREAM_SYSTEM_ENFORCED
308 15, // STREAM_DTMF
Jean-Michel Trivi3f0945a2016-11-11 10:05:18 -0800309 15, // STREAM_TTS
310 15 // STREAM_ACCESSIBILITY
Jared Suttles59820132009-08-13 21:50:52 -0500311 };
Eric Laurent91377de2014-10-10 15:24:04 -0700312
John Spurlockb6e19e32015-03-10 21:33:44 -0400313 /** Minimum volume index values for audio streams */
Chinyue Chen6affe932018-01-24 14:51:43 +0800314 protected static int[] MIN_STREAM_VOLUME = new int[] {
John Spurlockb6e19e32015-03-10 21:33:44 -0400315 1, // STREAM_VOICE_CALL
316 0, // STREAM_SYSTEM
317 0, // STREAM_RING
318 0, // STREAM_MUSIC
Jean-Michel Trivie05eef82018-03-08 18:56:34 -0800319 1, // STREAM_ALARM
John Spurlockb6e19e32015-03-10 21:33:44 -0400320 0, // STREAM_NOTIFICATION
Eric Laurente4381ec2015-10-29 17:52:48 -0700321 0, // STREAM_BLUETOOTH_SCO
John Spurlockb6e19e32015-03-10 21:33:44 -0400322 0, // STREAM_SYSTEM_ENFORCED
323 0, // STREAM_DTMF
Jean-Michel Trivi3f0945a2016-11-11 10:05:18 -0800324 0, // STREAM_TTS
Jean-Michel Trivie05eef82018-03-08 18:56:34 -0800325 1 // STREAM_ACCESSIBILITY
John Spurlockb6e19e32015-03-10 21:33:44 -0400326 };
327
Eric Laurent6d517662012-04-23 18:42:39 -0700328 /* mStreamVolumeAlias[] indicates for each stream if it uses the volume settings
Eric Laurenta553c252009-07-17 12:17:14 -0700329 * of another stream: This avoids multiplying the volume settings for hidden
330 * stream types that follow other stream behavior for volume settings
Eric Laurent6d517662012-04-23 18:42:39 -0700331 * NOTE: do not create loops in aliases!
332 * Some streams alias to different streams according to device category (phone or tablet) or
Eric Laurent24e0d9b2013-10-03 18:15:07 -0700333 * use case (in call vs off call...). See updateStreamVolumeAlias() for more details.
Eric Laurent212532b2014-07-21 15:43:18 -0700334 * mStreamVolumeAlias contains STREAM_VOLUME_ALIAS_VOICE aliases for a voice capable device
335 * (phone), STREAM_VOLUME_ALIAS_TELEVISION for a television or set-top box and
336 * STREAM_VOLUME_ALIAS_DEFAULT for other devices (e.g. tablets).*/
337 private final int[] STREAM_VOLUME_ALIAS_VOICE = new int[] {
Eric Laurent6d517662012-04-23 18:42:39 -0700338 AudioSystem.STREAM_VOICE_CALL, // STREAM_VOICE_CALL
339 AudioSystem.STREAM_RING, // STREAM_SYSTEM
340 AudioSystem.STREAM_RING, // STREAM_RING
341 AudioSystem.STREAM_MUSIC, // STREAM_MUSIC
342 AudioSystem.STREAM_ALARM, // STREAM_ALARM
343 AudioSystem.STREAM_RING, // STREAM_NOTIFICATION
344 AudioSystem.STREAM_BLUETOOTH_SCO, // STREAM_BLUETOOTH_SCO
345 AudioSystem.STREAM_RING, // STREAM_SYSTEM_ENFORCED
346 AudioSystem.STREAM_RING, // STREAM_DTMF
Jean-Michel Trivi3f0945a2016-11-11 10:05:18 -0800347 AudioSystem.STREAM_MUSIC, // STREAM_TTS
348 AudioSystem.STREAM_MUSIC // STREAM_ACCESSIBILITY
Eric Laurenta553c252009-07-17 12:17:14 -0700349 };
Eric Laurent212532b2014-07-21 15:43:18 -0700350 private final int[] STREAM_VOLUME_ALIAS_TELEVISION = new int[] {
351 AudioSystem.STREAM_MUSIC, // STREAM_VOICE_CALL
352 AudioSystem.STREAM_MUSIC, // STREAM_SYSTEM
353 AudioSystem.STREAM_MUSIC, // STREAM_RING
354 AudioSystem.STREAM_MUSIC, // STREAM_MUSIC
355 AudioSystem.STREAM_MUSIC, // STREAM_ALARM
356 AudioSystem.STREAM_MUSIC, // STREAM_NOTIFICATION
357 AudioSystem.STREAM_MUSIC, // STREAM_BLUETOOTH_SCO
358 AudioSystem.STREAM_MUSIC, // STREAM_SYSTEM_ENFORCED
359 AudioSystem.STREAM_MUSIC, // STREAM_DTMF
Jean-Michel Trivi3f0945a2016-11-11 10:05:18 -0800360 AudioSystem.STREAM_MUSIC, // STREAM_TTS
361 AudioSystem.STREAM_MUSIC // STREAM_ACCESSIBILITY
Eric Laurent212532b2014-07-21 15:43:18 -0700362 };
363 private final int[] STREAM_VOLUME_ALIAS_DEFAULT = new int[] {
Eric Laurent6d517662012-04-23 18:42:39 -0700364 AudioSystem.STREAM_VOICE_CALL, // STREAM_VOICE_CALL
John Spurlock4f0f1202014-08-05 13:28:33 -0400365 AudioSystem.STREAM_RING, // STREAM_SYSTEM
Eric Laurent6d517662012-04-23 18:42:39 -0700366 AudioSystem.STREAM_RING, // STREAM_RING
367 AudioSystem.STREAM_MUSIC, // STREAM_MUSIC
368 AudioSystem.STREAM_ALARM, // STREAM_ALARM
369 AudioSystem.STREAM_RING, // STREAM_NOTIFICATION
370 AudioSystem.STREAM_BLUETOOTH_SCO, // STREAM_BLUETOOTH_SCO
John Spurlock4f0f1202014-08-05 13:28:33 -0400371 AudioSystem.STREAM_RING, // STREAM_SYSTEM_ENFORCED
372 AudioSystem.STREAM_RING, // STREAM_DTMF
Jean-Michel Trivi3f0945a2016-11-11 10:05:18 -0800373 AudioSystem.STREAM_MUSIC, // STREAM_TTS
374 AudioSystem.STREAM_MUSIC // STREAM_ACCESSIBILITY
Eric Laurent6d517662012-04-23 18:42:39 -0700375 };
Yue Li949865b2017-05-24 17:25:28 -0700376 protected static int[] mStreamVolumeAlias;
Eric Laurenta553c252009-07-17 12:17:14 -0700377
Dianne Hackbornba50b97c2013-04-30 15:04:46 -0700378 /**
379 * Map AudioSystem.STREAM_* constants to app ops. This should be used
380 * after mapping through mStreamVolumeAlias.
381 */
John Spurlock59dc9c12015-03-02 11:20:15 -0500382 private static final int[] STREAM_VOLUME_OPS = new int[] {
Dianne Hackbornba50b97c2013-04-30 15:04:46 -0700383 AppOpsManager.OP_AUDIO_VOICE_VOLUME, // STREAM_VOICE_CALL
384 AppOpsManager.OP_AUDIO_MEDIA_VOLUME, // STREAM_SYSTEM
385 AppOpsManager.OP_AUDIO_RING_VOLUME, // STREAM_RING
386 AppOpsManager.OP_AUDIO_MEDIA_VOLUME, // STREAM_MUSIC
387 AppOpsManager.OP_AUDIO_ALARM_VOLUME, // STREAM_ALARM
388 AppOpsManager.OP_AUDIO_NOTIFICATION_VOLUME, // STREAM_NOTIFICATION
389 AppOpsManager.OP_AUDIO_BLUETOOTH_VOLUME, // STREAM_BLUETOOTH_SCO
390 AppOpsManager.OP_AUDIO_MEDIA_VOLUME, // STREAM_SYSTEM_ENFORCED
391 AppOpsManager.OP_AUDIO_MEDIA_VOLUME, // STREAM_DTMF
392 AppOpsManager.OP_AUDIO_MEDIA_VOLUME, // STREAM_TTS
Jean-Michel Trivi3f0945a2016-11-11 10:05:18 -0800393 AppOpsManager.OP_AUDIO_ACCESSIBILITY_VOLUME, // STREAM_ACCESSIBILITY
Dianne Hackbornba50b97c2013-04-30 15:04:46 -0700394 };
395
Eric Laurent83a017b2013-03-19 18:15:31 -0700396 private final boolean mUseFixedVolume;
397
Julia Reynoldseb0ce472018-05-04 15:34:55 -0400398 /**
399 * Default stream type used for volume control in the absence of playback
400 * e.g. user on homescreen, no app playing anything, presses hardware volume buttons, this
401 * stream type is controlled.
402 */
Eric Laurent07584202019-01-24 18:33:49 -0800403 protected static final int DEFAULT_VOL_STREAM_NO_PLAYBACK = AudioSystem.STREAM_MUSIC;
Julia Reynoldseb0ce472018-05-04 15:34:55 -0400404
Glenn Kasten30c918c2011-11-10 17:56:41 -0800405 private final AudioSystem.ErrorCallback mAudioSystemCallback = new AudioSystem.ErrorCallback() {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800406 public void onError(int error) {
407 switch (error) {
408 case AudioSystem.AUDIO_STATUS_SERVER_DIED:
Eric Laurent07584202019-01-24 18:33:49 -0800409 mRecordMonitor.clear();
410
Andy Hunged0ea402015-10-30 14:11:46 -0700411 sendMsg(mAudioHandler, MSG_AUDIO_SERVER_DIED,
Eric Laurentdfb881f2013-07-18 14:41:39 -0700412 SENDMSG_NOOP, 0, 0, null, 0);
Eric Laurent1d3cdce2018-01-20 10:31:21 -0800413 sendMsg(mAudioHandler, MSG_DISPATCH_AUDIO_SERVER_STATE,
414 SENDMSG_QUEUE, 0, 0, null, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800415 break;
416 default:
417 break;
418 }
Eric Laurentdfb881f2013-07-18 14:41:39 -0700419 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800420 };
421
422 /**
423 * Current ringer mode from one of {@link AudioManager#RINGER_MODE_NORMAL},
424 * {@link AudioManager#RINGER_MODE_SILENT}, or
425 * {@link AudioManager#RINGER_MODE_VIBRATE}.
426 */
Jean-Michel Trivi8719a1d2017-11-06 11:52:51 -0800427 @GuardedBy("mSettingsLock")
John Spurlock661f2cf2014-11-17 10:29:10 -0500428 private int mRingerMode; // internal ringer mode, affects muting of underlying streams
Jean-Michel Trivi8719a1d2017-11-06 11:52:51 -0800429 @GuardedBy("mSettingsLock")
John Spurlock661f2cf2014-11-17 10:29:10 -0500430 private int mRingerModeExternal = -1; // reported ringer mode to outside clients (AudioManager)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800431
Eric Laurent9bcf4012009-06-12 06:09:28 -0700432 /** @see System#MODE_RINGER_STREAMS_AFFECTED */
Eric Laurent24e0d9b2013-10-03 18:15:07 -0700433 private int mRingerModeAffectedStreams = 0;
Eric Laurent9bcf4012009-06-12 06:09:28 -0700434
Beverlyd6964762018-02-16 14:07:03 -0500435 private int mZenModeAffectedStreams = 0;
436
437 // Streams currently muted by ringer mode and dnd
438 private int mRingerAndZenModeMutedStreams;
Eric Laurent5b4e6542010-03-19 20:02:21 -0700439
John Spurlock3ce37252015-02-17 13:20:45 -0500440 /** Streams that can be muted. Do not resolve to aliases when checking.
441 * @see System#MUTE_STREAMS_AFFECTED */
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800442 private int mMuteAffectedStreams;
443
444 /**
Eric Laurentbffc3d12012-05-07 17:43:49 -0700445 * NOTE: setVibrateSetting(), getVibrateSetting(), shouldVibrate() are deprecated.
446 * mVibrateSetting is just maintained during deprecation period but vibration policy is
447 * now only controlled by mHasVibrator and mRingerMode
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800448 */
449 private int mVibrateSetting;
450
Eric Laurentbffc3d12012-05-07 17:43:49 -0700451 // Is there a vibrator
452 private final boolean mHasVibrator;
Mike Digman55272862018-02-20 14:35:17 -0800453 // Used to play vibrations
454 private Vibrator mVibrator;
455 private static final AudioAttributes VIBRATION_ATTRIBUTES = new AudioAttributes.Builder()
456 .setContentType(AudioAttributes.CONTENT_TYPE_SONIFICATION)
457 .setUsage(AudioAttributes.USAGE_ASSISTANCE_SONIFICATION)
458 .build();
Eric Laurentbffc3d12012-05-07 17:43:49 -0700459
Eric Laurenta553c252009-07-17 12:17:14 -0700460 // Broadcast receiver for device connections intent broadcasts
461 private final BroadcastReceiver mReceiver = new AudioServiceBroadcastReceiver();
462
Kevin Rocard2fe8b8b2019-02-20 11:25:23 -0800463 private IMediaProjectionManager mProjectionService; // to validate projection token
464
Makoto Onukid45a4a22015-11-02 17:17:38 -0800465 /** Interface for UserManagerService. */
466 private final UserManagerInternal mUserManagerInternal;
Sudheer Shankafc46e9b2016-10-21 17:55:27 -0700467 private final ActivityManagerInternal mActivityManagerInternal;
Makoto Onukid45a4a22015-11-02 17:17:38 -0800468
469 private final UserRestrictionsListener mUserRestrictionsListener =
470 new AudioServiceUserRestrictionsListener();
471
Eric Laurent9272b4b2010-01-23 17:12:59 -0800472 // List of binder death handlers for setMode() client processes.
473 // The last process to have called setMode() is at the top of the list.
Jean-Michel Trivi58850372018-09-14 16:01:28 -0700474 // package-private so it can be accessed in AudioDeviceBroker.getSetModeDeathHandlers
475 //TODO candidate to be moved to separate class that handles synchronization
476 @GuardedBy("mDeviceBroker.mSetModeLock")
477 /*package*/ final ArrayList<SetModeDeathHandler> mSetModeDeathHandlers =
478 new ArrayList<SetModeDeathHandler>();
Eric Laurent62ef7672010-11-24 10:58:32 -0800479
Eric Laurenta60e2122010-12-28 16:49:07 -0800480 // true if boot sequence has been completed
Eric Laurent4a5eeb92014-05-06 10:49:04 -0700481 private boolean mSystemReady;
Yasuhiro Matsuda4ced7192015-07-10 22:08:44 +0900482 // true if Intent.ACTION_USER_SWITCHED has ever been received
483 private boolean mUserSwitchedReceived;
Eric Laurenta60e2122010-12-28 16:49:07 -0800484 // listener for SoundPool sample load completion indication
485 private SoundPoolCallback mSoundPoolCallBack;
486 // thread for SoundPool listener
487 private SoundPoolListenerThread mSoundPoolListenerThread;
488 // message looper for SoundPool listener
489 private Looper mSoundPoolLooper = null;
Jean-Michel Trivic55b3932012-06-05 11:57:59 -0700490 // volume applied to sound played with playSoundEffect()
Jean-Michel Trivif2b0c112012-07-09 11:59:11 -0700491 private static int sSoundEffectVolumeDb;
Eric Laurent25101b02011-02-02 09:33:30 -0800492 // previous volume adjustment direction received by checkForRingerModeChange()
493 private int mPrevVolDirection = AudioManager.ADJUST_SAME;
Eric Laurent45c90ce2012-04-24 18:44:22 -0700494 // mVolumeControlStream is set by VolumePanel to temporarily force the stream type which volume
495 // is controlled by Vol keys.
Jean-Michel Trivia7880d42017-04-15 12:41:05 -0700496 private int mVolumeControlStream = -1;
497 // interpretation of whether the volume stream has been selected by the user by clicking on a
498 // volume slider to change which volume is controlled by the volume keys. Is false
499 // when mVolumeControlStream is -1.
500 private boolean mUserSelectedVolumeControlStream = false;
Eric Laurent45c90ce2012-04-24 18:44:22 -0700501 private final Object mForceControlStreamLock = new Object();
502 // VolumePanel is currently the only client of forceVolumeControlStream() and runs in system
503 // server process so in theory it is not necessary to monitor the client death.
504 // However it is good to be ready for future evolutions.
505 private ForceControlStreamClient mForceControlStreamClient = null;
Jeff Sharkey098d5802012-04-26 17:30:34 -0700506 // Used to play ringtones outside system_server
507 private volatile IRingtonePlayer mRingtonePlayer;
Eric Laurent9bc8358d2011-11-18 16:43:31 -0800508
Eric Laurent4bbcc652012-09-24 14:26:30 -0700509 // Devices for which the volume is fixed and VolumePanel slider should be disabled
Eric Laurent212532b2014-07-21 15:43:18 -0700510 int mFixedVolumeDevices = AudioSystem.DEVICE_OUT_HDMI |
Eric Laurent4bbcc652012-09-24 14:26:30 -0700511 AudioSystem.DEVICE_OUT_DGTL_DOCK_HEADSET |
Eric Laurent212532b2014-07-21 15:43:18 -0700512 AudioSystem.DEVICE_OUT_ANLG_DOCK_HEADSET |
513 AudioSystem.DEVICE_OUT_HDMI_ARC |
514 AudioSystem.DEVICE_OUT_SPDIF |
515 AudioSystem.DEVICE_OUT_AUX_LINE;
Jakub Pawlowskic274fb22018-04-04 10:15:12 -0700516 int mFullVolumeDevices = 0;
Eric Laurent4bbcc652012-09-24 14:26:30 -0700517
Jean-Michel Trivibb6f8712013-05-23 15:02:41 -0700518 private final boolean mMonitorRotation;
Eric Laurentd640bd32012-09-28 18:01:48 -0700519
Eric Laurent7ee1e4f2012-10-26 18:11:21 -0700520 private boolean mDockAudioMediaEnabled = true;
521
Eric Laurent08ed1b92012-11-05 14:54:12 -0800522 private int mDockState = Intent.EXTRA_DOCK_STATE_UNDOCKED;
523
Eric Laurentfde16d52012-12-03 14:42:39 -0800524 // Used when safe volume warning message display is requested by setStreamVolume(). In this
525 // case, the new requested volume, stream type and device are stored in mPendingVolumeCommand
526 // and used later when/if disableSafeMediaVolume() is called.
527 private StreamVolumeCommand mPendingVolumeCommand;
528
Jean-Michel Trivifa9a6982013-06-27 16:22:58 -0700529 private PowerManager.WakeLock mAudioEventWakeLock;
530
531 private final MediaFocusControl mMediaFocusControl;
532
Tomoharu Kasaharaf0fecb12018-09-06 20:04:38 +0900533 // Pre-scale for Bluetooth Absolute Volume
534 private float[] mPrescaleAbsoluteVolume = new float[] {
535 0.5f, // Pre-scale for index 1
536 0.7f, // Pre-scale for index 2
537 0.85f, // Pre-scale for index 3
538 };
539
Julia Reynolds48034f82016-03-09 10:15:16 -0500540 private NotificationManager mNm;
John Spurlock661f2cf2014-11-17 10:29:10 -0500541 private AudioManagerInternal.RingerModeDelegate mRingerModeDelegate;
John Spurlocka48d7792015-03-03 17:35:57 -0500542 private VolumePolicy mVolumePolicy = VolumePolicy.DEFAULT;
John Spurlock07e72432015-03-13 11:46:52 -0400543 private long mLoweredFromNormalToVibrateTime;
John Spurlock661f2cf2014-11-17 10:29:10 -0500544
Phil Weaverf1a9aff2017-03-23 17:21:29 -0700545 // Array of Uids of valid accessibility services to check if caller is one of them
546 private int[] mAccessibilityServiceUids;
547 private final Object mAccessibilityServiceUidsLock = new Object();
548
jiabin39940752018-04-02 18:18:45 -0700549 private int mEncodedSurroundMode;
550 private String mEnabledSurroundFormats;
551 private boolean mSurroundModeChanged;
552
Eric Laurent1c9c1d52018-10-17 10:06:46 -0700553 @GuardedBy("mSettingsLock")
554 private int mAssistantUid;
555
Paul McLean10804eb2015-01-28 11:16:35 -0800556 // Defines the format for the connection "address" for ALSA devices
557 public static String makeAlsaAddressString(int card, int device) {
558 return "card=" + card + ";device=" + device + ";";
559 }
560
Makoto Onukie1aef852015-10-15 17:28:35 -0700561 public static final class Lifecycle extends SystemService {
562 private AudioService mService;
563
564 public Lifecycle(Context context) {
565 super(context);
566 mService = new AudioService(context);
567 }
568
569 @Override
570 public void onStart() {
571 publishBinderService(Context.AUDIO_SERVICE, mService);
572 }
573
574 @Override
575 public void onBootPhase(int phase) {
576 if (phase == SystemService.PHASE_ACTIVITY_MANAGER_READY) {
577 mService.systemReady();
578 }
579 }
580 }
581
Dianne Hackborn3e99f652017-07-05 16:33:56 -0700582 final private IUidObserver mUidObserver = new IUidObserver.Stub() {
583 @Override public void onUidStateChanged(int uid, int procState, long procStateSeq) {
584 }
585
586 @Override public void onUidGone(int uid, boolean disabled) {
587 // Once the uid is no longer running, no need to keep trying to disable its audio.
588 disableAudioForUid(false, uid);
589 }
590
591 @Override public void onUidActive(int uid) throws RemoteException {
592 }
593
594 @Override public void onUidIdle(int uid, boolean disabled) {
595 }
596
597 @Override public void onUidCachedChanged(int uid, boolean cached) {
598 disableAudioForUid(cached, uid);
599 }
600
601 private void disableAudioForUid(boolean disable, int uid) {
602 queueMsgUnderWakeLock(mAudioHandler, MSG_DISABLE_AUDIO_FOR_UID,
603 disable ? 1 : 0 /* arg1 */, uid /* arg2 */,
604 null /* obj */, 0 /* delay */);
605 }
606 };
607
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800608 ///////////////////////////////////////////////////////////////////////////
609 // Construction
610 ///////////////////////////////////////////////////////////////////////////
611
612 /** @hide */
613 public AudioService(Context context) {
614 mContext = context;
615 mContentResolver = context.getContentResolver();
Dianne Hackbornba50b97c2013-04-30 15:04:46 -0700616 mAppOps = (AppOpsManager)context.getSystemService(Context.APP_OPS_SERVICE);
Eric Laurent212532b2014-07-21 15:43:18 -0700617
John Spurlock61560172015-02-06 19:46:04 -0500618 mPlatformType = AudioSystem.getPlatformType(context);
Jared Suttles59820132009-08-13 21:50:52 -0500619
Muyuan Li1ed6df62016-06-18 11:16:52 -0700620 mIsSingleVolume = AudioSystem.isSingleVolume(context);
621
Makoto Onukid45a4a22015-11-02 17:17:38 -0800622 mUserManagerInternal = LocalServices.getService(UserManagerInternal.class);
Sudheer Shankafc46e9b2016-10-21 17:55:27 -0700623 mActivityManagerInternal = LocalServices.getService(ActivityManagerInternal.class);
Makoto Onukid45a4a22015-11-02 17:17:38 -0800624
Jean-Michel Trivic6802222012-04-30 11:15:03 -0700625 PowerManager pm = (PowerManager)context.getSystemService(Context.POWER_SERVICE);
Jean-Michel Trivifa9a6982013-06-27 16:22:58 -0700626 mAudioEventWakeLock = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "handleAudioEvent");
Jean-Michel Trivic6802222012-04-30 11:15:03 -0700627
Mike Digman55272862018-02-20 14:35:17 -0800628 mVibrator = (Vibrator) context.getSystemService(Context.VIBRATOR_SERVICE);
629 mHasVibrator = mVibrator == null ? false : mVibrator.hasVibrator();
Eric Laurentbffc3d12012-05-07 17:43:49 -0700630
François Gaffie0699fec2018-07-09 14:35:10 +0200631 sAudioProductStrategies = new AudioProductStrategies();
632
John Spurlockb6e19e32015-03-10 21:33:44 -0400633 // Initialize volume
Eric Laurent403bd342017-07-11 16:21:44 -0700634 int maxCallVolume = SystemProperties.getInt("ro.config.vc_call_vol_steps", -1);
635 if (maxCallVolume != -1) {
636 MAX_STREAM_VOLUME[AudioSystem.STREAM_VOICE_CALL] = maxCallVolume;
Shuhei Miyazaki89091ba2018-01-11 18:17:04 +0900637 }
638
639 int defaultCallVolume = SystemProperties.getInt("ro.config.vc_call_vol_default", -1);
640 if (defaultCallVolume != -1 &&
641 defaultCallVolume <= MAX_STREAM_VOLUME[AudioSystem.STREAM_VOICE_CALL] &&
642 defaultCallVolume >= MIN_STREAM_VOLUME[AudioSystem.STREAM_VOICE_CALL]) {
643 AudioSystem.DEFAULT_STREAM_VOLUME[AudioSystem.STREAM_VOICE_CALL] = defaultCallVolume;
644 } else {
Eric Laurent403bd342017-07-11 16:21:44 -0700645 AudioSystem.DEFAULT_STREAM_VOLUME[AudioSystem.STREAM_VOICE_CALL] =
646 (maxCallVolume * 3) / 4;
Eric Laurent91377de2014-10-10 15:24:04 -0700647 }
Eric Laurent403bd342017-07-11 16:21:44 -0700648
649 int maxMusicVolume = SystemProperties.getInt("ro.config.media_vol_steps", -1);
650 if (maxMusicVolume != -1) {
651 MAX_STREAM_VOLUME[AudioSystem.STREAM_MUSIC] = maxMusicVolume;
652 }
653
654 int defaultMusicVolume = SystemProperties.getInt("ro.config.media_vol_default", -1);
655 if (defaultMusicVolume != -1 &&
Shuhei Miyazaki89091ba2018-01-11 18:17:04 +0900656 defaultMusicVolume <= MAX_STREAM_VOLUME[AudioSystem.STREAM_MUSIC] &&
657 defaultMusicVolume >= MIN_STREAM_VOLUME[AudioSystem.STREAM_MUSIC]) {
Eric Laurent403bd342017-07-11 16:21:44 -0700658 AudioSystem.DEFAULT_STREAM_VOLUME[AudioSystem.STREAM_MUSIC] = defaultMusicVolume;
659 } else {
Hank Freund45926dc2015-12-11 10:50:45 -0800660 if (isPlatformTelevision()) {
Eric Laurent403bd342017-07-11 16:21:44 -0700661 AudioSystem.DEFAULT_STREAM_VOLUME[AudioSystem.STREAM_MUSIC] =
662 MAX_STREAM_VOLUME[AudioSystem.STREAM_MUSIC] / 4;
Hank Freund45926dc2015-12-11 10:50:45 -0800663 } else {
Eric Laurent403bd342017-07-11 16:21:44 -0700664 AudioSystem.DEFAULT_STREAM_VOLUME[AudioSystem.STREAM_MUSIC] =
665 MAX_STREAM_VOLUME[AudioSystem.STREAM_MUSIC] / 3;
Hank Freund45926dc2015-12-11 10:50:45 -0800666 }
Eric Laurent91377de2014-10-10 15:24:04 -0700667 }
Jared Suttles59820132009-08-13 21:50:52 -0500668
Chris Kuiper09b6c212018-01-03 22:22:13 -0800669 int maxAlarmVolume = SystemProperties.getInt("ro.config.alarm_vol_steps", -1);
670 if (maxAlarmVolume != -1) {
671 MAX_STREAM_VOLUME[AudioSystem.STREAM_ALARM] = maxAlarmVolume;
672 }
673
674 int defaultAlarmVolume = SystemProperties.getInt("ro.config.alarm_vol_default", -1);
675 if (defaultAlarmVolume != -1 &&
676 defaultAlarmVolume <= MAX_STREAM_VOLUME[AudioSystem.STREAM_ALARM]) {
677 AudioSystem.DEFAULT_STREAM_VOLUME[AudioSystem.STREAM_ALARM] = defaultAlarmVolume;
678 } else {
679 // Default is 6 out of 7 (default maximum), so scale accordingly.
680 AudioSystem.DEFAULT_STREAM_VOLUME[AudioSystem.STREAM_ALARM] =
681 6 * MAX_STREAM_VOLUME[AudioSystem.STREAM_ALARM] / 7;
682 }
683
684 int maxSystemVolume = SystemProperties.getInt("ro.config.system_vol_steps", -1);
685 if (maxSystemVolume != -1) {
686 MAX_STREAM_VOLUME[AudioSystem.STREAM_SYSTEM] = maxSystemVolume;
687 }
688
689 int defaultSystemVolume = SystemProperties.getInt("ro.config.system_vol_default", -1);
690 if (defaultSystemVolume != -1 &&
691 defaultSystemVolume <= MAX_STREAM_VOLUME[AudioSystem.STREAM_SYSTEM]) {
692 AudioSystem.DEFAULT_STREAM_VOLUME[AudioSystem.STREAM_SYSTEM] = defaultSystemVolume;
693 } else {
694 // Default is to use maximum.
695 AudioSystem.DEFAULT_STREAM_VOLUME[AudioSystem.STREAM_SYSTEM] =
696 MAX_STREAM_VOLUME[AudioSystem.STREAM_SYSTEM];
697 }
698
Jean-Michel Trivif2b0c112012-07-09 11:59:11 -0700699 sSoundEffectVolumeDb = context.getResources().getInteger(
Jean-Michel Trivic55b3932012-06-05 11:57:59 -0700700 com.android.internal.R.integer.config_soundEffectVolumeDb);
Eric Laurent25101b02011-02-02 09:33:30 -0800701
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800702 createAudioSystemThread();
Eric Laurentdd45d012012-10-08 09:04:34 -0700703
Eric Laurentdfb881f2013-07-18 14:41:39 -0700704 AudioSystem.setErrorCallback(mAudioSystemCallback);
705
John Spurlock5e783732015-02-19 10:28:59 -0500706 boolean cameraSoundForced = readCameraSoundForced();
Eric Laurentdd45d012012-10-08 09:04:34 -0700707 mCameraSoundForced = new Boolean(cameraSoundForced);
708 sendMsg(mAudioHandler,
709 MSG_SET_FORCE_USE,
710 SENDMSG_QUEUE,
711 AudioSystem.FOR_SYSTEM,
712 cameraSoundForced ?
713 AudioSystem.FORCE_SYSTEM_ENFORCED : AudioSystem.FORCE_NONE,
Jean-Michel Trivi011f39e2017-08-19 18:08:06 -0700714 new String("AudioService ctor"),
Eric Laurentdd45d012012-10-08 09:04:34 -0700715 0);
716
hyomin.ohd0446dc2018-10-18 13:58:27 +0900717 mSafeMediaVolumeState = Settings.Global.getInt(mContentResolver,
718 Settings.Global.AUDIO_SAFE_VOLUME_STATE,
719 SAFE_MEDIA_VOLUME_NOT_CONFIGURED);
Eric Laurent05274f32012-11-29 12:48:18 -0800720 // The default safe volume index read here will be replaced by the actual value when
721 // the mcc is read by onConfigureSafeVolume()
722 mSafeMediaVolumeIndex = mContext.getResources().getInteger(
723 com.android.internal.R.integer.config_safe_media_volume_index) * 10;
724
Eric Laurent83a017b2013-03-19 18:15:31 -0700725 mUseFixedVolume = mContext.getResources().getBoolean(
726 com.android.internal.R.bool.config_useFixedVolume);
727
Jean-Michel Trivi58850372018-09-14 16:01:28 -0700728 mDeviceBroker = new AudioDeviceBroker(mContext, this);
729
Eric Laurent24e0d9b2013-10-03 18:15:07 -0700730 // must be called before readPersistedSettings() which needs a valid mStreamVolumeAlias[]
731 // array initialized by updateStreamVolumeAlias()
John Spurlock90874332015-03-10 16:00:54 -0400732 updateStreamVolumeAlias(false /*updateVolumes*/, TAG);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800733 readPersistedSettings();
Eric Laurentc0232482016-03-15 18:19:23 -0700734 readUserRestrictions();
Eric Laurentc1d41662011-07-19 11:21:13 -0700735 mSettingsObserver = new SettingsObserver();
Eric Laurenta553c252009-07-17 12:17:14 -0700736 createStreamStates();
Eric Laurent9f103de2011-09-08 15:04:23 -0700737
Eric Laurentb378a13a2017-07-11 14:08:11 -0700738 // mSafeUsbMediaVolumeIndex must be initialized after createStreamStates() because it
739 // relies on audio policy having correct ranges for volume indexes.
740 mSafeUsbMediaVolumeIndex = getSafeUsbMediaVolumeIndex();
741
Eric Laurente5a351c2017-09-27 20:11:51 -0700742 mPlaybackMonitor =
743 new PlaybackActivityMonitor(context, MAX_STREAM_VOLUME[AudioSystem.STREAM_ALARM]);
744
Jean-Michel Trivi99489cc2017-01-25 19:08:49 -0800745 mMediaFocusControl = new MediaFocusControl(mContext, mPlaybackMonitor);
John Spurlockb6e19e32015-03-10 21:33:44 -0400746
Jean-Michel Trivi66ffacf2017-02-04 17:25:31 -0800747 mRecordMonitor = new RecordingActivityMonitor(mContext);
748
Glenn Kastenfd116ad2013-07-12 17:10:39 -0700749 readAndSetLowRamDevice();
Eric Laurent3891c4c2010-04-20 09:40:57 -0700750
751 // Call setRingerModeInt() to apply correct mute
752 // state on streams affected by ringer mode.
Beverlyd6964762018-02-16 14:07:03 -0500753 mRingerAndZenModeMutedStreams = 0;
John Spurlock661f2cf2014-11-17 10:29:10 -0500754 setRingerModeInt(getRingerModeInternal(), false);
Eric Laurent3891c4c2010-04-20 09:40:57 -0700755
Eric Laurenta553c252009-07-17 12:17:14 -0700756 // Register for device connection intent broadcasts.
757 IntentFilter intentFilter =
Eric Laurentb1fbaac2012-05-29 09:24:28 -0700758 new IntentFilter(BluetoothHeadset.ACTION_AUDIO_STATE_CHANGED);
Jack He8dd33942018-01-17 15:45:12 -0800759 intentFilter.addAction(BluetoothHeadset.ACTION_ACTIVE_DEVICE_CHANGED);
Jaikumar Ganesh82aa7f02010-09-27 17:05:10 -0700760 intentFilter.addAction(Intent.ACTION_DOCK_EVENT);
Eric Laurent950e8cb2011-10-13 08:57:54 -0700761 intentFilter.addAction(Intent.ACTION_SCREEN_ON);
762 intentFilter.addAction(Intent.ACTION_SCREEN_OFF);
Eric Laurentbc0fab1f2012-09-19 11:24:41 -0700763 intentFilter.addAction(Intent.ACTION_USER_SWITCHED);
Fyodor Kupolovb5013302015-04-17 17:59:14 -0700764 intentFilter.addAction(Intent.ACTION_USER_BACKGROUND);
765 intentFilter.addAction(Intent.ACTION_USER_FOREGROUND);
Paul McLeanc837a452014-04-09 09:04:43 -0700766 intentFilter.addAction(UsbManager.ACTION_USB_DEVICE_ATTACHED);
Eric Laurentb70b78a2016-01-13 19:16:04 -0800767 intentFilter.addAction(BluetoothAdapter.ACTION_STATE_CHANGED);
Jean-Michel Trivib2251822019-02-06 07:32:06 -0800768 intentFilter.addAction(Intent.ACTION_PACKAGES_SUSPENDED);
Jean-Michel Trivif26f0172012-04-25 16:23:20 -0700769
Eric Laurentd640bd32012-09-28 18:01:48 -0700770 intentFilter.addAction(Intent.ACTION_CONFIGURATION_CHANGED);
Jean-Michel Trivibb6f8712013-05-23 15:02:41 -0700771 mMonitorRotation = SystemProperties.getBoolean("ro.audio.monitorRotation", false);
772 if (mMonitorRotation) {
Jean-Michel Trivi24806db2015-10-01 15:00:59 -0700773 RotationHelper.init(mContext, mAudioHandler);
Jean-Michel Trivibb6f8712013-05-23 15:02:41 -0700774 }
Jean-Michel Trivif26f0172012-04-25 16:23:20 -0700775
Marco Nelissenfb6df0b2017-02-15 15:25:24 -0800776 intentFilter.addAction(AudioEffect.ACTION_OPEN_AUDIO_EFFECT_CONTROL_SESSION);
777 intentFilter.addAction(AudioEffect.ACTION_CLOSE_AUDIO_EFFECT_CONTROL_SESSION);
778
Fyodor Kupolovb5013302015-04-17 17:59:14 -0700779 context.registerReceiverAsUser(mReceiver, UserHandle.ALL, intentFilter, null, null);
Jared Suttles59820132009-08-13 21:50:52 -0500780
RoboErik0dac35a2014-08-12 15:48:49 -0700781 LocalServices.addService(AudioManagerInternal.class, new AudioServiceInternal());
Makoto Onukid45a4a22015-11-02 17:17:38 -0800782
783 mUserManagerInternal.addUserRestrictionsListener(mUserRestrictionsListener);
Jean-Michel Trivid3c71f02015-12-07 11:59:31 -0800784
785 mRecordMonitor.initMonitor();
Tomoharu Kasaharaf0fecb12018-09-06 20:04:38 +0900786
787 final float[] preScale = new float[3];
788 preScale[0] = mContext.getResources().getFraction(
789 com.android.internal.R.fraction.config_prescaleAbsoluteVolume_index1,
790 1, 1);
791 preScale[1] = mContext.getResources().getFraction(
792 com.android.internal.R.fraction.config_prescaleAbsoluteVolume_index2,
793 1, 1);
794 preScale[2] = mContext.getResources().getFraction(
795 com.android.internal.R.fraction.config_prescaleAbsoluteVolume_index3,
796 1, 1);
797 for (int i = 0; i < preScale.length; i++) {
798 if (0.0f <= preScale[i] && preScale[i] <= 1.0f) {
799 mPrescaleAbsoluteVolume[i] = preScale[i];
800 }
801 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800802 }
803
Eric Laurent4a5eeb92014-05-06 10:49:04 -0700804 public void systemReady() {
805 sendMsg(mAudioHandler, MSG_SYSTEM_READY, SENDMSG_QUEUE,
806 0, 0, null, 0);
Dianne Hackborn3e3600e2017-08-31 11:15:26 -0700807 if (false) {
808 // This is turned off for now, because it is racy and thus causes apps to break.
809 // Currently banning a uid means that if an app tries to start playing an audio
810 // stream, that will be preventing, and unbanning it will not allow that stream
811 // to resume. However these changes in uid state are racy with what the app is doing,
812 // so that after taking a process out of the cached state we can't guarantee that
813 // we will unban the uid before the app actually tries to start playing audio.
814 // (To do that, the activity manager would need to wait until it knows for sure
815 // that the ban has been removed, before telling the app to do whatever it is
816 // supposed to do that caused it to go out of the cached state.)
817 try {
818 ActivityManager.getService().registerUidObserver(mUidObserver,
819 ActivityManager.UID_OBSERVER_CACHED | ActivityManager.UID_OBSERVER_GONE,
820 ActivityManager.PROCESS_STATE_UNKNOWN, null);
821 } catch (RemoteException e) {
822 // ignored; both services live in system_server
823 }
Dianne Hackborn3e99f652017-07-05 16:33:56 -0700824 }
Eric Laurent4a5eeb92014-05-06 10:49:04 -0700825 }
826
827 public void onSystemReady() {
828 mSystemReady = true;
829 sendMsg(mAudioHandler, MSG_LOAD_SOUND_EFFECTS, SENDMSG_QUEUE,
830 0, 0, null, 0);
831
Jean-Michel Trivi58850372018-09-14 16:01:28 -0700832 mDeviceBroker.onSystemReady();
Eric Laurent4a5eeb92014-05-06 10:49:04 -0700833
Jeff Sharkey73ea0ae2016-08-10 17:30:38 -0600834 if (mContext.getPackageManager().hasSystemFeature(PackageManager.FEATURE_HDMI_CEC)) {
Shubangc480a712018-06-11 18:02:42 -0700835 synchronized (mHdmiClientLock) {
836 mHdmiManager = mContext.getSystemService(HdmiControlManager.class);
Eric Laurent212532b2014-07-21 15:43:18 -0700837 mHdmiTvClient = mHdmiManager.getTvClient();
Jungshik Jangc9ff9682014-09-15 17:41:06 +0900838 if (mHdmiTvClient != null) {
839 mFixedVolumeDevices &= ~AudioSystem.DEVICE_ALL_HDMI_SYSTEM_AUDIO_AND_SPEAKER;
840 }
Eric Laurent212532b2014-07-21 15:43:18 -0700841 mHdmiPlaybackClient = mHdmiManager.getPlaybackClient();
842 mHdmiCecSink = false;
Shubangc480a712018-06-11 18:02:42 -0700843 mHdmiAudioSystemClient = mHdmiManager.getAudioSystemClient();
Eric Laurent212532b2014-07-21 15:43:18 -0700844 }
845 }
Wonsik Kim7f4342e2014-07-20 23:04:59 +0900846
Julia Reynolds48034f82016-03-09 10:15:16 -0500847 mNm = (NotificationManager) mContext.getSystemService(Context.NOTIFICATION_SERVICE);
848
Eric Laurent4a5eeb92014-05-06 10:49:04 -0700849 sendMsg(mAudioHandler,
850 MSG_CONFIGURE_SAFE_MEDIA_VOLUME_FORCED,
851 SENDMSG_REPLACE,
852 0,
853 0,
John Spurlock90874332015-03-10 16:00:54 -0400854 TAG,
Eric Laurent03332ab2017-02-09 18:29:15 -0800855 SystemProperties.getBoolean("audio.safemedia.bypass", false) ?
856 0 : SAFE_VOLUME_CONFIGURE_TIMEOUT_MS);
Jean-Michel Trivi873cc452014-09-11 17:25:09 -0700857
Jean-Michel Trivicfa55532017-01-18 11:17:51 -0800858 initA11yMonitoring();
Eric Laurent0867bed2015-05-20 14:49:08 -0700859 onIndicateSystemReady();
860 }
861
862 void onIndicateSystemReady() {
863 if (AudioSystem.systemReady() == AudioSystem.SUCCESS) {
864 return;
865 }
866 sendMsg(mAudioHandler,
867 MSG_INDICATE_SYSTEM_READY,
868 SENDMSG_REPLACE,
869 0,
870 0,
871 null,
872 INDICATE_SYSTEM_READY_RETRY_DELAY_MS);
873 }
874
Andy Hunged0ea402015-10-30 14:11:46 -0700875 public void onAudioServerDied() {
Eric Laurent0867bed2015-05-20 14:49:08 -0700876 if (!mSystemReady ||
877 (AudioSystem.checkAudioFlinger() != AudioSystem.AUDIO_STATUS_OK)) {
Andy Hunged0ea402015-10-30 14:11:46 -0700878 Log.e(TAG, "Audioserver died.");
879 sendMsg(mAudioHandler, MSG_AUDIO_SERVER_DIED, SENDMSG_NOOP, 0, 0,
Eric Laurent0867bed2015-05-20 14:49:08 -0700880 null, 500);
881 return;
882 }
Andy Hunged0ea402015-10-30 14:11:46 -0700883 Log.e(TAG, "Audioserver started.");
Eric Laurent0867bed2015-05-20 14:49:08 -0700884
885 // indicate to audio HAL that we start the reconfiguration phase after a media
886 // server crash
887 // Note that we only execute this when the media server
888 // process restarts after a crash, not the first time it is started.
889 AudioSystem.setParameters("restarting=true");
890
891 readAndSetLowRamDevice();
892
Jean-Michel Trivi58850372018-09-14 16:01:28 -0700893 // Restore device connection states, BT state
894 mDeviceBroker.onAudioServerDied();
895
Eric Laurent0867bed2015-05-20 14:49:08 -0700896 // Restore call state
Jean-Michel Trivi011f39e2017-08-19 18:08:06 -0700897 if (AudioSystem.setPhoneState(mMode) == AudioSystem.AUDIO_STATUS_OK) {
898 mModeLogger.log(new AudioEventLogger.StringEvent(
899 "onAudioServerDied causes setPhoneState(" + AudioSystem.modeToString(mMode) + ")"));
900 }
Eric Laurent0867bed2015-05-20 14:49:08 -0700901
Jean-Michel Trivi8719a1d2017-11-06 11:52:51 -0800902 final int forSys;
903 synchronized (mSettingsLock) {
904 forSys = mCameraSoundForced ?
905 AudioSystem.FORCE_SYSTEM_ENFORCED : AudioSystem.FORCE_NONE;
906 }
Jean-Michel Trivi58850372018-09-14 16:01:28 -0700907
908 mDeviceBroker.setForceUse_Async(AudioSystem.FOR_SYSTEM, forSys, "onAudioServerDied");
Eric Laurent0867bed2015-05-20 14:49:08 -0700909
910 // Restore stream volumes
911 int numStreamTypes = AudioSystem.getNumStreamTypes();
912 for (int streamType = numStreamTypes - 1; streamType >= 0; streamType--) {
913 VolumeStreamState streamState = mStreamStates[streamType];
Eric Laurente4381ec2015-10-29 17:52:48 -0700914 AudioSystem.initStreamVolume(
915 streamType, streamState.mIndexMin / 10, streamState.mIndexMax / 10);
Eric Laurent0867bed2015-05-20 14:49:08 -0700916
917 streamState.applyAllVolumes();
918 }
919
Andy Hungf04b84d2015-12-18 17:33:27 -0800920 // Restore mono mode
Andy Hung7b98e9a2016-02-25 18:34:50 -0800921 updateMasterMono(mContentResolver);
Andy Hungf04b84d2015-12-18 17:33:27 -0800922
Edward Savage-Jones35c292f2017-01-13 09:04:34 +0100923 // Restore audio balance
924 updateMasterBalance(mContentResolver);
925
Eric Laurent0867bed2015-05-20 14:49:08 -0700926 // Restore ringer mode
927 setRingerModeInt(getRingerModeInternal(), false);
928
Mikhail Naganovb668bc62018-02-13 13:46:38 -0800929 // Reset device rotation (if monitored for this device)
Eric Laurent0867bed2015-05-20 14:49:08 -0700930 if (mMonitorRotation) {
Jean-Michel Trivi24806db2015-10-01 15:00:59 -0700931 RotationHelper.updateOrientation();
Eric Laurent0867bed2015-05-20 14:49:08 -0700932 }
933
Eric Laurent0867bed2015-05-20 14:49:08 -0700934 synchronized (mSettingsLock) {
Jean-Michel Trivi011f39e2017-08-19 18:08:06 -0700935 final int forDock = mDockAudioMediaEnabled ?
936 AudioSystem.FORCE_ANALOG_DOCK : AudioSystem.FORCE_NONE;
Jean-Michel Trivi58850372018-09-14 16:01:28 -0700937 mDeviceBroker.setForceUse_Async(AudioSystem.FOR_DOCK, forDock, "onAudioServerDied");
Jean-Michel Trivi011f39e2017-08-19 18:08:06 -0700938 sendEncodedSurroundMode(mContentResolver, "onAudioServerDied");
jiabin39940752018-04-02 18:18:45 -0700939 sendEnabledSurroundFormats(mContentResolver, true);
Eric Laurent1c9c1d52018-10-17 10:06:46 -0700940 updateAssistantUId(true);
941 }
942 synchronized (mAccessibilityServiceUidsLock) {
943 AudioSystem.setA11yServicesUids(mAccessibilityServiceUids);
Eric Laurent0867bed2015-05-20 14:49:08 -0700944 }
Shubangc480a712018-06-11 18:02:42 -0700945 synchronized (mHdmiClientLock) {
946 if (mHdmiManager != null && mHdmiTvClient != null) {
947 setHdmiSystemAudioSupported(mHdmiSystemAudioSupported);
Eric Laurent0867bed2015-05-20 14:49:08 -0700948 }
949 }
950
951 synchronized (mAudioPolicies) {
952 for (AudioPolicyProxy policy : mAudioPolicies.values()) {
953 policy.connectMixes();
954 }
955 }
956
957 onIndicateSystemReady();
958 // indicate the end of reconfiguration phase to audio HAL
959 AudioSystem.setParameters("restarting=false");
Eric Laurent1d3cdce2018-01-20 10:31:21 -0800960
961 sendMsg(mAudioHandler, MSG_DISPATCH_AUDIO_SERVER_STATE,
962 SENDMSG_QUEUE, 1, 0, null, 0);
963 }
964
965 private void onDispatchAudioServerStateChange(boolean state) {
966 synchronized (mAudioServerStateListeners) {
967 for (AsdProxy asdp : mAudioServerStateListeners.values()) {
968 try {
969 asdp.callback().dispatchAudioServerStateChange(state);
970 } catch (RemoteException e) {
971 Log.w(TAG, "Could not call dispatchAudioServerStateChange()", e);
972 }
973 }
974 }
Eric Laurent4a5eeb92014-05-06 10:49:04 -0700975 }
976
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800977 private void createAudioSystemThread() {
978 mAudioSystemThread = new AudioSystemThread();
979 mAudioSystemThread.start();
980 waitForAudioHandlerCreation();
981 }
982
983 /** Waits for the volume handler to be created by the other thread. */
984 private void waitForAudioHandlerCreation() {
985 synchronized(this) {
986 while (mAudioHandler == null) {
987 try {
988 // Wait for mAudioHandler to be set by the other thread
989 wait();
990 } catch (InterruptedException e) {
991 Log.e(TAG, "Interrupted while waiting on volume handler.");
992 }
993 }
994 }
995 }
996
François Gaffie0699fec2018-07-09 14:35:10 +0200997 /**
998 * @return the {@link android.media.audiopolicy.AudioProductStrategies} discovered from the
999 * platform configuration file.
1000 */
1001 public @NonNull AudioProductStrategies getAudioProductStrategies() {
1002 return sAudioProductStrategies;
1003 }
1004
Eric Laurent24482012012-05-10 09:41:17 -07001005 private void checkAllAliasStreamVolumes() {
Jean-Michel Trivi085346a2018-02-14 10:48:51 -08001006 synchronized (mSettingsLock) {
1007 synchronized (VolumeStreamState.class) {
1008 int numStreamTypes = AudioSystem.getNumStreamTypes();
1009 for (int streamType = 0; streamType < numStreamTypes; streamType++) {
1010 mStreamStates[streamType]
1011 .setAllIndexes(mStreamStates[mStreamVolumeAlias[streamType]], TAG);
1012 // apply stream volume
1013 if (!mStreamStates[streamType].mIsMuted) {
1014 mStreamStates[streamType].applyAllVolumes();
1015 }
Eric Laurent8fa4d6f2014-10-30 14:13:03 -07001016 }
Eric Laurent24482012012-05-10 09:41:17 -07001017 }
1018 }
1019 }
1020
Jean-Michel Trivi58850372018-09-14 16:01:28 -07001021 /**
1022 * Called from AudioDeviceBroker when DEVICE_OUT_HDMI is connected or disconnected.
1023 */
1024 /*package*/ void checkVolumeCecOnHdmiConnection(int state, String caller) {
1025 if (state != 0) {
1026 // DEVICE_OUT_HDMI is now connected
1027 if ((AudioSystem.DEVICE_OUT_HDMI & mSafeMediaVolumeDevices) != 0) {
1028 sendMsg(mAudioHandler,
1029 MSG_CHECK_MUSIC_ACTIVE,
1030 SENDMSG_REPLACE,
1031 0,
1032 0,
1033 caller,
1034 MUSIC_ACTIVE_POLL_PERIOD_MS);
1035 }
1036
1037 if (isPlatformTelevision()) {
1038 mFixedVolumeDevices |= AudioSystem.DEVICE_OUT_HDMI;
1039 checkAllFixedVolumeDevices();
1040 synchronized (mHdmiClientLock) {
1041 if (mHdmiManager != null && mHdmiPlaybackClient != null) {
1042 mHdmiCecSink = false;
1043 mHdmiPlaybackClient.queryDisplayStatus(mHdmiDisplayStatusCallback);
1044 }
1045 }
1046 }
1047 sendEnabledSurroundFormats(mContentResolver, true);
1048 } else {
1049 // DEVICE_OUT_HDMI disconnected
1050 if (isPlatformTelevision()) {
1051 synchronized (mHdmiClientLock) {
1052 if (mHdmiManager != null) {
1053 mHdmiCecSink = false;
1054 }
1055 }
1056 }
1057 }
1058 }
1059
Eric Laurent212532b2014-07-21 15:43:18 -07001060 private void checkAllFixedVolumeDevices()
1061 {
1062 int numStreamTypes = AudioSystem.getNumStreamTypes();
1063 for (int streamType = 0; streamType < numStreamTypes; streamType++) {
1064 mStreamStates[streamType].checkFixedVolumeDevices();
1065 }
1066 }
1067
Jean-Michel Triviba5270b2014-10-01 17:49:29 -07001068 private void checkAllFixedVolumeDevices(int streamType) {
1069 mStreamStates[streamType].checkFixedVolumeDevices();
1070 }
1071
John Spurlockb6e19e32015-03-10 21:33:44 -04001072 private void checkMuteAffectedStreams() {
1073 // any stream with a min level > 0 is not muteable by definition
Tomoharu Kasaharaa0d0c542019-01-18 20:04:38 +09001074 // STREAM_VOICE_CALL and STREAM_BLUETOOTH_SCO can be muted by applications
1075 // that has the the MODIFY_PHONE_STATE permission.
John Spurlockb6e19e32015-03-10 21:33:44 -04001076 for (int i = 0; i < mStreamStates.length; i++) {
1077 final VolumeStreamState vss = mStreamStates[i];
Nadav Bar6b7751d2017-12-24 16:03:08 +02001078 if (vss.mIndexMin > 0 &&
Tomoharu Kasaharaa0d0c542019-01-18 20:04:38 +09001079 (vss.mStreamType != AudioSystem.STREAM_VOICE_CALL &&
1080 vss.mStreamType != AudioSystem.STREAM_BLUETOOTH_SCO)) {
John Spurlockb6e19e32015-03-10 21:33:44 -04001081 mMuteAffectedStreams &= ~(1 << vss.mStreamType);
1082 }
1083 }
1084 }
1085
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001086 private void createStreamStates() {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001087 int numStreamTypes = AudioSystem.getNumStreamTypes();
1088 VolumeStreamState[] streams = mStreamStates = new VolumeStreamState[numStreamTypes];
1089
1090 for (int i = 0; i < numStreamTypes; i++) {
Jean-Michel Trivia53b7052017-04-12 18:27:01 -07001091 streams[i] =
1092 new VolumeStreamState(System.VOLUME_SETTINGS_INT[mStreamVolumeAlias[i]], i);
Eric Laurenta553c252009-07-17 12:17:14 -07001093 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001094
Eric Laurent212532b2014-07-21 15:43:18 -07001095 checkAllFixedVolumeDevices();
Eric Laurent24482012012-05-10 09:41:17 -07001096 checkAllAliasStreamVolumes();
John Spurlockb6e19e32015-03-10 21:33:44 -04001097 checkMuteAffectedStreams();
Eric Laurent403bd342017-07-11 16:21:44 -07001098 updateDefaultVolumes();
1099 }
1100
1101 // Update default indexes from aliased streams. Must be called after mStreamStates is created
1102 private void updateDefaultVolumes() {
1103 for (int stream = 0; stream < mStreamStates.length; stream++) {
1104 if (stream != mStreamVolumeAlias[stream]) {
1105 AudioSystem.DEFAULT_STREAM_VOLUME[stream] = rescaleIndex(
1106 AudioSystem.DEFAULT_STREAM_VOLUME[mStreamVolumeAlias[stream]],
1107 mStreamVolumeAlias[stream],
1108 stream);
1109 }
1110 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001111 }
1112
Eric Laurentbffc3d12012-05-07 17:43:49 -07001113 private void dumpStreamStates(PrintWriter pw) {
1114 pw.println("\nStream volumes (device: index)");
1115 int numStreamTypes = AudioSystem.getNumStreamTypes();
1116 for (int i = 0; i < numStreamTypes; i++) {
John Spurlock61560172015-02-06 19:46:04 -05001117 pw.println("- " + AudioSystem.STREAM_NAMES[i] + ":");
Eric Laurentbffc3d12012-05-07 17:43:49 -07001118 mStreamStates[i].dump(pw);
1119 pw.println("");
1120 }
Eric Laurentdd45d012012-10-08 09:04:34 -07001121 pw.print("\n- mute affected streams = 0x");
1122 pw.println(Integer.toHexString(mMuteAffectedStreams));
Eric Laurentbffc3d12012-05-07 17:43:49 -07001123 }
1124
John Spurlock90874332015-03-10 16:00:54 -04001125 private void updateStreamVolumeAlias(boolean updateVolumes, String caller) {
Eric Laurent6d517662012-04-23 18:42:39 -07001126 int dtmfStreamAlias;
Jean-Michel Triviac487672016-11-11 10:05:18 -08001127 final int a11yStreamAlias = sIndependentA11yVolume ?
1128 AudioSystem.STREAM_ACCESSIBILITY : AudioSystem.STREAM_MUSIC;
Eric Laurent212532b2014-07-21 15:43:18 -07001129
Muyuan Li1ed6df62016-06-18 11:16:52 -07001130 if (mIsSingleVolume) {
Eric Laurent212532b2014-07-21 15:43:18 -07001131 mStreamVolumeAlias = STREAM_VOLUME_ALIAS_TELEVISION;
1132 dtmfStreamAlias = AudioSystem.STREAM_MUSIC;
Muyuan Li1ed6df62016-06-18 11:16:52 -07001133 } else {
1134 switch (mPlatformType) {
1135 case AudioSystem.PLATFORM_VOICE:
1136 mStreamVolumeAlias = STREAM_VOLUME_ALIAS_VOICE;
1137 dtmfStreamAlias = AudioSystem.STREAM_RING;
1138 break;
1139 default:
1140 mStreamVolumeAlias = STREAM_VOLUME_ALIAS_DEFAULT;
1141 dtmfStreamAlias = AudioSystem.STREAM_MUSIC;
1142 }
Eric Laurent6d517662012-04-23 18:42:39 -07001143 }
Eric Laurent212532b2014-07-21 15:43:18 -07001144
Muyuan Li1ed6df62016-06-18 11:16:52 -07001145 if (mIsSingleVolume) {
Eric Laurent212532b2014-07-21 15:43:18 -07001146 mRingerModeAffectedStreams = 0;
Eric Laurent24e0d9b2013-10-03 18:15:07 -07001147 } else {
Eric Laurent212532b2014-07-21 15:43:18 -07001148 if (isInCommunication()) {
1149 dtmfStreamAlias = AudioSystem.STREAM_VOICE_CALL;
1150 mRingerModeAffectedStreams &= ~(1 << AudioSystem.STREAM_DTMF);
1151 } else {
1152 mRingerModeAffectedStreams |= (1 << AudioSystem.STREAM_DTMF);
1153 }
Eric Laurent6d517662012-04-23 18:42:39 -07001154 }
Eric Laurent212532b2014-07-21 15:43:18 -07001155
Eric Laurent6d517662012-04-23 18:42:39 -07001156 mStreamVolumeAlias[AudioSystem.STREAM_DTMF] = dtmfStreamAlias;
Jean-Michel Trivi170a0ee2017-04-14 18:13:26 -07001157 mStreamVolumeAlias[AudioSystem.STREAM_ACCESSIBILITY] = a11yStreamAlias;
Jean-Michel Triviac487672016-11-11 10:05:18 -08001158
Eric Laurent403bd342017-07-11 16:21:44 -07001159 if (updateVolumes && mStreamStates != null) {
1160 updateDefaultVolumes();
1161
Jean-Michel Trivi085346a2018-02-14 10:48:51 -08001162 synchronized (mSettingsLock) {
1163 synchronized (VolumeStreamState.class) {
1164 mStreamStates[AudioSystem.STREAM_DTMF]
1165 .setAllIndexes(mStreamStates[dtmfStreamAlias], caller);
1166 mStreamStates[AudioSystem.STREAM_ACCESSIBILITY].mVolumeIndexSettingName =
1167 System.VOLUME_SETTINGS_INT[a11yStreamAlias];
1168 mStreamStates[AudioSystem.STREAM_ACCESSIBILITY].setAllIndexes(
1169 mStreamStates[a11yStreamAlias], caller);
Jean-Michel Trivie05eef82018-03-08 18:56:34 -08001170 mStreamStates[AudioSystem.STREAM_ACCESSIBILITY].refreshRange(
1171 mStreamVolumeAlias[AudioSystem.STREAM_ACCESSIBILITY]);
Jean-Michel Trivi085346a2018-02-14 10:48:51 -08001172 }
1173 }
Jean-Michel Trivi170a0ee2017-04-14 18:13:26 -07001174 if (sIndependentA11yVolume) {
1175 // restore the a11y values from the settings
1176 mStreamStates[AudioSystem.STREAM_ACCESSIBILITY].readSettings();
1177 }
1178
Eric Laurent24e0d9b2013-10-03 18:15:07 -07001179 // apply stream mute states according to new value of mRingerModeAffectedStreams
John Spurlock661f2cf2014-11-17 10:29:10 -05001180 setRingerModeInt(getRingerModeInternal(), false);
Eric Laurent6d517662012-04-23 18:42:39 -07001181 sendMsg(mAudioHandler,
1182 MSG_SET_ALL_VOLUMES,
1183 SENDMSG_QUEUE,
1184 0,
1185 0,
1186 mStreamStates[AudioSystem.STREAM_DTMF], 0);
Jean-Michel Triviac487672016-11-11 10:05:18 -08001187 sendMsg(mAudioHandler,
1188 MSG_SET_ALL_VOLUMES,
1189 SENDMSG_QUEUE,
1190 0,
1191 0,
1192 mStreamStates[AudioSystem.STREAM_ACCESSIBILITY], 0);
Eric Laurent6d517662012-04-23 18:42:39 -07001193 }
1194 }
1195
Eric Laurent7ee1e4f2012-10-26 18:11:21 -07001196 private void readDockAudioSettings(ContentResolver cr)
1197 {
1198 mDockAudioMediaEnabled = Settings.Global.getInt(
Eric Laurent5ba0ffa02012-10-29 12:31:09 -07001199 cr, Settings.Global.DOCK_AUDIO_MEDIA_ENABLED, 0) == 1;
Eric Laurent7ee1e4f2012-10-26 18:11:21 -07001200
Eric Laurent7ee1e4f2012-10-26 18:11:21 -07001201 sendMsg(mAudioHandler,
1202 MSG_SET_FORCE_USE,
1203 SENDMSG_QUEUE,
1204 AudioSystem.FOR_DOCK,
1205 mDockAudioMediaEnabled ?
1206 AudioSystem.FORCE_ANALOG_DOCK : AudioSystem.FORCE_NONE,
Jean-Michel Trivi011f39e2017-08-19 18:08:06 -07001207 new String("readDockAudioSettings"),
Eric Laurent7ee1e4f2012-10-26 18:11:21 -07001208 0);
1209 }
1210
Phil Burkac0f7042016-02-24 12:19:08 -08001211
Andy Hung7b98e9a2016-02-25 18:34:50 -08001212 private void updateMasterMono(ContentResolver cr)
1213 {
1214 final boolean masterMono = System.getIntForUser(
1215 cr, System.MASTER_MONO, 0 /* default */, UserHandle.USER_CURRENT) == 1;
1216 if (DEBUG_VOL) {
1217 Log.d(TAG, String.format("Master mono %b", masterMono));
1218 }
1219 AudioSystem.setMasterMono(masterMono);
1220 }
1221
Edward Savage-Jones35c292f2017-01-13 09:04:34 +01001222 private void updateMasterBalance(ContentResolver cr) {
1223 final float masterBalance = System.getFloatForUser(
1224 cr, System.MASTER_BALANCE, 0.f /* default */, UserHandle.USER_CURRENT);
1225 if (DEBUG_VOL) {
1226 Log.d(TAG, String.format("Master balance %f", masterBalance));
1227 }
1228 if (AudioSystem.setMasterBalance(masterBalance) != 0) {
1229 Log.e(TAG, String.format("setMasterBalance failed for %f", masterBalance));
1230 }
1231 }
1232
Jean-Michel Trivi011f39e2017-08-19 18:08:06 -07001233 private void sendEncodedSurroundMode(ContentResolver cr, String eventSource)
Phil Burkac0f7042016-02-24 12:19:08 -08001234 {
Jean-Michel Trivi58850372018-09-14 16:01:28 -07001235 final int encodedSurroundMode = Settings.Global.getInt(
Phil Burkac0f7042016-02-24 12:19:08 -08001236 cr, Settings.Global.ENCODED_SURROUND_OUTPUT,
1237 Settings.Global.ENCODED_SURROUND_OUTPUT_AUTO);
Jean-Michel Trivi011f39e2017-08-19 18:08:06 -07001238 sendEncodedSurroundMode(encodedSurroundMode, eventSource);
Phil Burkac0f7042016-02-24 12:19:08 -08001239 }
1240
Jean-Michel Trivi011f39e2017-08-19 18:08:06 -07001241 private void sendEncodedSurroundMode(int encodedSurroundMode, String eventSource)
Phil Burkac0f7042016-02-24 12:19:08 -08001242 {
1243 // initialize to guaranteed bad value
1244 int forceSetting = AudioSystem.NUM_FORCE_CONFIG;
1245 switch (encodedSurroundMode) {
1246 case Settings.Global.ENCODED_SURROUND_OUTPUT_AUTO:
1247 forceSetting = AudioSystem.FORCE_NONE;
1248 break;
1249 case Settings.Global.ENCODED_SURROUND_OUTPUT_NEVER:
1250 forceSetting = AudioSystem.FORCE_ENCODED_SURROUND_NEVER;
1251 break;
1252 case Settings.Global.ENCODED_SURROUND_OUTPUT_ALWAYS:
1253 forceSetting = AudioSystem.FORCE_ENCODED_SURROUND_ALWAYS;
1254 break;
jiabin39940752018-04-02 18:18:45 -07001255 case Settings.Global.ENCODED_SURROUND_OUTPUT_MANUAL:
1256 forceSetting = AudioSystem.FORCE_ENCODED_SURROUND_MANUAL;
1257 break;
Phil Burkac0f7042016-02-24 12:19:08 -08001258 default:
1259 Log.e(TAG, "updateSurroundSoundSettings: illegal value "
1260 + encodedSurroundMode);
1261 break;
1262 }
1263 if (forceSetting != AudioSystem.NUM_FORCE_CONFIG) {
Jean-Michel Trivi58850372018-09-14 16:01:28 -07001264 mDeviceBroker.setForceUse_Async(AudioSystem.FOR_ENCODED_SURROUND, forceSetting,
1265 eventSource);
Phil Burkac0f7042016-02-24 12:19:08 -08001266 }
1267 }
1268
jiabin39940752018-04-02 18:18:45 -07001269 private void sendEnabledSurroundFormats(ContentResolver cr, boolean forceUpdate) {
1270 if (mEncodedSurroundMode != Settings.Global.ENCODED_SURROUND_OUTPUT_MANUAL) {
1271 // Manually enable surround formats only when the setting is in manual mode.
1272 return;
1273 }
1274 String enabledSurroundFormats = Settings.Global.getString(
1275 cr, Settings.Global.ENCODED_SURROUND_OUTPUT_ENABLED_FORMATS);
jiabin6db5f862018-05-17 10:33:09 -07001276 if (enabledSurroundFormats == null) {
1277 // Never allow enabledSurroundFormats as a null, which could happen when
1278 // ENCODED_SURROUND_OUTPUT_ENABLED_FORMATS is not appear in settings DB.
1279 enabledSurroundFormats = "";
1280 }
jiabin39940752018-04-02 18:18:45 -07001281 if (!forceUpdate && TextUtils.equals(enabledSurroundFormats, mEnabledSurroundFormats)) {
1282 // Update enabled surround formats to AudioPolicyManager only when forceUpdate
1283 // is true or enabled surround formats changed.
1284 return;
1285 }
1286
1287 mEnabledSurroundFormats = enabledSurroundFormats;
1288 String[] surroundFormats = TextUtils.split(enabledSurroundFormats, ",");
1289 ArrayList<Integer> formats = new ArrayList<>();
1290 for (String format : surroundFormats) {
1291 try {
1292 int audioFormat = Integer.valueOf(format);
1293 boolean isSurroundFormat = false;
1294 for (int sf : AudioFormat.SURROUND_SOUND_ENCODING) {
1295 if (sf == audioFormat) {
1296 isSurroundFormat = true;
1297 break;
1298 }
1299 }
1300 if (isSurroundFormat && !formats.contains(audioFormat)) {
1301 formats.add(audioFormat);
1302 }
1303 } catch (Exception e) {
1304 Log.e(TAG, "Invalid enabled surround format:" + format);
1305 }
1306 }
1307 // Set filtered surround formats to settings DB in case
1308 // there are invalid surround formats in original settings.
1309 Settings.Global.putString(mContext.getContentResolver(),
1310 Settings.Global.ENCODED_SURROUND_OUTPUT_ENABLED_FORMATS,
1311 TextUtils.join(",", formats));
1312 sendMsg(mAudioHandler, MSG_ENABLE_SURROUND_FORMATS, SENDMSG_QUEUE, 0, 0, formats, 0);
1313 }
1314
1315 private void onEnableSurroundFormats(ArrayList<Integer> enabledSurroundFormats) {
1316 // Set surround format enabled accordingly.
1317 for (int surroundFormat : AudioFormat.SURROUND_SOUND_ENCODING) {
1318 boolean enabled = enabledSurroundFormats.contains(surroundFormat);
1319 int ret = AudioSystem.setSurroundFormatEnabled(surroundFormat, enabled);
1320 Log.i(TAG, "enable surround format:" + surroundFormat + " " + enabled + " " + ret);
1321 }
1322 }
1323
Eric Laurent1c9c1d52018-10-17 10:06:46 -07001324 @GuardedBy("mSettingsLock")
1325 private void updateAssistantUId(boolean forceUpdate) {
1326 int assistantUid = 0;
1327
1328 // Consider assistants in the following order of priority:
1329 // 1) voice interaction service
1330 // 2) assistant
1331 String assistantName = Settings.Secure.getStringForUser(
1332 mContentResolver,
1333 Settings.Secure.VOICE_INTERACTION_SERVICE, UserHandle.USER_CURRENT);
1334 if (TextUtils.isEmpty(assistantName)) {
1335 assistantName = Settings.Secure.getStringForUser(
1336 mContentResolver,
1337 Settings.Secure.ASSISTANT, UserHandle.USER_CURRENT);
1338 }
1339 if (!TextUtils.isEmpty(assistantName)) {
1340 String packageName = ComponentName.unflattenFromString(assistantName).getPackageName();
1341 if (!TextUtils.isEmpty(packageName)) {
1342 try {
1343 assistantUid = mContext.getPackageManager().getPackageUid(packageName, 0);
1344 } catch (PackageManager.NameNotFoundException e) {
1345 Log.e(TAG,
1346 "updateAssistantUId() could not find UID for package: " + packageName);
1347 }
1348 }
1349 }
1350
1351 if (assistantUid != mAssistantUid || forceUpdate) {
1352 AudioSystem.setAssistantUid(assistantUid);
1353 mAssistantUid = assistantUid;
1354 }
1355 }
1356
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001357 private void readPersistedSettings() {
1358 final ContentResolver cr = mContentResolver;
1359
Eric Laurentbffc3d12012-05-07 17:43:49 -07001360 int ringerModeFromSettings =
Jeff Sharkey8d9a1f62012-10-18 15:38:14 -07001361 Settings.Global.getInt(
1362 cr, Settings.Global.MODE_RINGER, AudioManager.RINGER_MODE_NORMAL);
Eric Laurentbffc3d12012-05-07 17:43:49 -07001363 int ringerMode = ringerModeFromSettings;
Eric Laurent72668b22011-07-19 16:04:27 -07001364 // sanity check in case the settings are restored from a device with incompatible
1365 // ringer modes
John Spurlock97559372014-10-24 16:27:36 -04001366 if (!isValidRingerMode(ringerMode)) {
Glenn Kastenba195eb2011-12-13 09:30:40 -08001367 ringerMode = AudioManager.RINGER_MODE_NORMAL;
Eric Laurentbffc3d12012-05-07 17:43:49 -07001368 }
1369 if ((ringerMode == AudioManager.RINGER_MODE_VIBRATE) && !mHasVibrator) {
1370 ringerMode = AudioManager.RINGER_MODE_SILENT;
1371 }
1372 if (ringerMode != ringerModeFromSettings) {
Jeff Sharkey8d9a1f62012-10-18 15:38:14 -07001373 Settings.Global.putInt(cr, Settings.Global.MODE_RINGER, ringerMode);
Glenn Kastenba195eb2011-12-13 09:30:40 -08001374 }
Muyuan Li1ed6df62016-06-18 11:16:52 -07001375 if (mUseFixedVolume || mIsSingleVolume) {
Eric Laurent83a017b2013-03-19 18:15:31 -07001376 ringerMode = AudioManager.RINGER_MODE_NORMAL;
1377 }
Glenn Kastenba195eb2011-12-13 09:30:40 -08001378 synchronized(mSettingsLock) {
1379 mRingerMode = ringerMode;
John Spurlock661f2cf2014-11-17 10:29:10 -05001380 if (mRingerModeExternal == -1) {
1381 mRingerModeExternal = mRingerMode;
1382 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001383
Eric Laurentdd45d012012-10-08 09:04:34 -07001384 // System.VIBRATE_ON is not used any more but defaults for mVibrateSetting
1385 // are still needed while setVibrateSetting() and getVibrateSetting() are being
1386 // deprecated.
John Spurlock61560172015-02-06 19:46:04 -05001387 mVibrateSetting = AudioSystem.getValueForVibrateSetting(0,
Eric Laurentdd45d012012-10-08 09:04:34 -07001388 AudioManager.VIBRATE_TYPE_NOTIFICATION,
1389 mHasVibrator ? AudioManager.VIBRATE_SETTING_ONLY_SILENT
1390 : AudioManager.VIBRATE_SETTING_OFF);
John Spurlock61560172015-02-06 19:46:04 -05001391 mVibrateSetting = AudioSystem.getValueForVibrateSetting(mVibrateSetting,
Eric Laurentdd45d012012-10-08 09:04:34 -07001392 AudioManager.VIBRATE_TYPE_RINGER,
1393 mHasVibrator ? AudioManager.VIBRATE_SETTING_ONLY_SILENT
1394 : AudioManager.VIBRATE_SETTING_OFF);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001395
Beverlyd6964762018-02-16 14:07:03 -05001396 updateRingerAndZenModeAffectedStreams();
Eric Laurent7ee1e4f2012-10-26 18:11:21 -07001397 readDockAudioSettings(cr);
Jean-Michel Trivi011f39e2017-08-19 18:08:06 -07001398 sendEncodedSurroundMode(cr, "readPersistedSettings");
jiabin39940752018-04-02 18:18:45 -07001399 sendEnabledSurroundFormats(cr, true);
Eric Laurent1c9c1d52018-10-17 10:06:46 -07001400 updateAssistantUId(true);
Eric Laurent402f7f22011-02-04 12:30:32 -08001401 }
Eric Laurentc1d41662011-07-19 11:21:13 -07001402
Eric Laurentbc0fab1f2012-09-19 11:24:41 -07001403 mMuteAffectedStreams = System.getIntForUser(cr,
John Spurlock61560172015-02-06 19:46:04 -05001404 System.MUTE_STREAMS_AFFECTED, AudioSystem.DEFAULT_MUTE_STREAMS_AFFECTED,
John Spurlock24c05182015-02-05 12:30:36 -05001405 UserHandle.USER_CURRENT);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001406
Andy Hung7b98e9a2016-02-25 18:34:50 -08001407 updateMasterMono(cr);
Andy Hungf04b84d2015-12-18 17:33:27 -08001408
Edward Savage-Jones35c292f2017-01-13 09:04:34 +01001409 updateMasterBalance(cr);
1410
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001411 // Each stream will read its own persisted settings
1412
John Spurlockbcc10872014-11-28 15:29:21 -05001413 // Broadcast the sticky intents
1414 broadcastRingerMode(AudioManager.RINGER_MODE_CHANGED_ACTION, mRingerModeExternal);
1415 broadcastRingerMode(AudioManager.INTERNAL_RINGER_MODE_CHANGED_ACTION, mRingerMode);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001416
1417 // Broadcast vibrate settings
1418 broadcastVibrateSetting(AudioManager.VIBRATE_TYPE_RINGER);
1419 broadcastVibrateSetting(AudioManager.VIBRATE_TYPE_NOTIFICATION);
Jean-Michel Trivid589fea2011-04-15 11:28:10 -07001420
John Spurlock33f4e042014-07-11 13:10:58 -04001421 // Load settings for the volume controller
1422 mVolumeController.loadSettings(cr);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001423 }
1424
Eric Laurentc0232482016-03-15 18:19:23 -07001425 private void readUserRestrictions() {
1426 final int currentUser = getCurrentUserId();
1427
1428 // Check the current user restriction.
Tony Makc1205112016-07-22 16:02:59 +01001429 boolean masterMute =
1430 mUserManagerInternal.getUserRestriction(currentUser,
Esteban Talavera492b4722017-02-13 14:59:45 +00001431 UserManager.DISALLOW_UNMUTE_DEVICE)
Tony Makc1205112016-07-22 16:02:59 +01001432 || mUserManagerInternal.getUserRestriction(currentUser,
1433 UserManager.DISALLOW_ADJUST_VOLUME);
Eric Laurentc0232482016-03-15 18:19:23 -07001434 if (mUseFixedVolume) {
1435 masterMute = false;
1436 AudioSystem.setMasterVolume(1.0f);
1437 }
1438 if (DEBUG_VOL) {
1439 Log.d(TAG, String.format("Master mute %s, user=%d", masterMute, currentUser));
1440 }
1441 setSystemAudioMute(masterMute);
1442 AudioSystem.setMasterMute(masterMute);
1443 broadcastMasterMuteStatus(masterMute);
1444
1445 boolean microphoneMute = mUserManagerInternal.getUserRestriction(
1446 currentUser, UserManager.DISALLOW_UNMUTE_MICROPHONE);
1447 if (DEBUG_VOL) {
1448 Log.d(TAG, String.format("Mic mute %s, user=%d", microphoneMute, currentUser));
1449 }
1450 AudioSystem.muteMicrophone(microphoneMute);
1451 }
1452
Eric Laurenta553c252009-07-17 12:17:14 -07001453 private int rescaleIndex(int index, int srcStream, int dstStream) {
Jean-Michel Trivie05eef82018-03-08 18:56:34 -08001454 final int rescaled =
1455 (index * mStreamStates[dstStream].getMaxIndex()
1456 + mStreamStates[srcStream].getMaxIndex() / 2)
1457 / mStreamStates[srcStream].getMaxIndex();
1458 if (rescaled < mStreamStates[dstStream].getMinIndex()) {
1459 return mStreamStates[dstStream].getMinIndex();
1460 } else {
1461 return rescaled;
1462 }
Eric Laurenta553c252009-07-17 12:17:14 -07001463 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001464
1465 ///////////////////////////////////////////////////////////////////////////
1466 // IPC methods
1467 ///////////////////////////////////////////////////////////////////////////
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001468 /** @see AudioManager#adjustVolume(int, int) */
Dianne Hackbornba50b97c2013-04-30 15:04:46 -07001469 public void adjustSuggestedStreamVolume(int direction, int suggestedStreamType, int flags,
John Spurlock90874332015-03-10 16:00:54 -04001470 String callingPackage, String caller) {
Jean-Michel Trivi610aa9b2018-01-27 15:42:42 -08001471 final IAudioPolicyCallback extVolCtlr;
1472 synchronized (mExtVolumeControllerLock) {
1473 extVolCtlr = mExtVolumeController;
1474 }
1475 if (extVolCtlr != null) {
Jean-Michel Trivi7ed71472018-02-02 16:52:09 -08001476 sendMsg(mAudioHandler, MSG_NOTIFY_VOL_EVENT, SENDMSG_QUEUE,
1477 direction, 0 /*ignored*/,
1478 extVolCtlr, 0 /*delay*/);
Jean-Michel Trivi610aa9b2018-01-27 15:42:42 -08001479 } else {
1480 adjustSuggestedStreamVolume(direction, suggestedStreamType, flags, callingPackage,
1481 caller, Binder.getCallingUid());
1482 }
RoboErik272e1612014-09-05 11:39:29 -07001483 }
1484
1485 private void adjustSuggestedStreamVolume(int direction, int suggestedStreamType, int flags,
John Spurlock90874332015-03-10 16:00:54 -04001486 String callingPackage, String caller, int uid) {
1487 if (DEBUG_VOL) Log.d(TAG, "adjustSuggestedStreamVolume() stream=" + suggestedStreamType
Jean-Michel Trivia7880d42017-04-15 12:41:05 -07001488 + ", flags=" + flags + ", caller=" + caller
1489 + ", volControlStream=" + mVolumeControlStream
1490 + ", userSelect=" + mUserSelectedVolumeControlStream);
Jean-Michel Trivi58850372018-09-14 16:01:28 -07001491 sVolumeLogger.log(new VolumeEvent(VolumeEvent.VOL_ADJUST_SUGG_VOL, suggestedStreamType,
Jean-Michel Trivicf170362017-08-24 17:24:57 -07001492 direction/*val1*/, flags/*val2*/, new StringBuilder(callingPackage)
1493 .append("/").append(caller).append(" uid:").append(uid).toString()));
Jean-Michel Trivia7880d42017-04-15 12:41:05 -07001494 final int streamType;
jiabin8fd5d5e2018-03-23 14:09:28 -07001495 synchronized (mForceControlStreamLock) {
1496 // Request lock in case mVolumeControlStream is changed by other thread.
1497 if (mUserSelectedVolumeControlStream) { // implies mVolumeControlStream != -1
Jean-Michel Trivia7880d42017-04-15 12:41:05 -07001498 streamType = mVolumeControlStream;
jiabin8fd5d5e2018-03-23 14:09:28 -07001499 } else {
1500 final int maybeActiveStreamType = getActiveStreamType(suggestedStreamType);
1501 final boolean activeForReal;
1502 if (maybeActiveStreamType == AudioSystem.STREAM_RING
1503 || maybeActiveStreamType == AudioSystem.STREAM_NOTIFICATION) {
1504 activeForReal = wasStreamActiveRecently(maybeActiveStreamType, 0);
1505 } else {
1506 activeForReal = AudioSystem.isStreamActive(maybeActiveStreamType, 0);
1507 }
1508 if (activeForReal || mVolumeControlStream == -1) {
1509 streamType = maybeActiveStreamType;
1510 } else {
1511 streamType = mVolumeControlStream;
1512 }
Jean-Michel Trivia7880d42017-04-15 12:41:05 -07001513 }
Eric Laurent402f7f22011-02-04 12:30:32 -08001514 }
Jean-Michel Trivia7880d42017-04-15 12:41:05 -07001515
1516 final boolean isMute = isMuteAdjust(direction);
1517
John Spurlock0a376af2015-03-26 16:24:12 -04001518 ensureValidStreamType(streamType);
John Spurlock33f4e042014-07-11 13:10:58 -04001519 final int resolvedStream = mStreamVolumeAlias[streamType];
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001520
RoboErik2811dd32014-08-12 09:48:13 -07001521 // Play sounds on STREAM_RING only.
1522 if ((flags & AudioManager.FLAG_PLAY_SOUND) != 0 &&
John Spurlock33f4e042014-07-11 13:10:58 -04001523 resolvedStream != AudioSystem.STREAM_RING) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001524 flags &= ~AudioManager.FLAG_PLAY_SOUND;
1525 }
1526
John Spurlock33f4e042014-07-11 13:10:58 -04001527 // For notifications/ring, show the ui before making any adjustments
RoboErik4197cb62015-01-21 15:45:32 -08001528 // Don't suppress mute/unmute requests
Stanley Changb77e13d2018-08-28 08:16:03 +08001529 // Don't suppress adjustments for single volume device
1530 if (mVolumeController.suppressAdjustment(resolvedStream, flags, isMute)
1531 && !mIsSingleVolume) {
John Spurlock33f4e042014-07-11 13:10:58 -04001532 direction = 0;
1533 flags &= ~AudioManager.FLAG_PLAY_SOUND;
1534 flags &= ~AudioManager.FLAG_VIBRATE;
1535 if (DEBUG_VOL) Log.d(TAG, "Volume controller suppressed adjustment");
1536 }
1537
John Spurlock90874332015-03-10 16:00:54 -04001538 adjustStreamVolume(streamType, direction, flags, callingPackage, caller, uid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001539 }
1540
1541 /** @see AudioManager#adjustStreamVolume(int, int, int) */
Dianne Hackbornba50b97c2013-04-30 15:04:46 -07001542 public void adjustStreamVolume(int streamType, int direction, int flags,
1543 String callingPackage) {
Phil Weaverf1a9aff2017-03-23 17:21:29 -07001544 if ((streamType == AudioManager.STREAM_ACCESSIBILITY) && !canChangeAccessibilityVolume()) {
Jean-Michel Triviab2d9312017-03-13 15:33:39 -07001545 Log.w(TAG, "Trying to call adjustStreamVolume() for a11y without"
Phil Weaverf1a9aff2017-03-23 17:21:29 -07001546 + "CHANGE_ACCESSIBILITY_VOLUME / callingPackage=" + callingPackage);
Jean-Michel Triviab2d9312017-03-13 15:33:39 -07001547 return;
1548 }
Jean-Michel Trivi58850372018-09-14 16:01:28 -07001549 sVolumeLogger.log(new VolumeEvent(VolumeEvent.VOL_ADJUST_STREAM_VOL, streamType,
Jean-Michel Trivicf170362017-08-24 17:24:57 -07001550 direction/*val1*/, flags/*val2*/, callingPackage));
John Spurlock90874332015-03-10 16:00:54 -04001551 adjustStreamVolume(streamType, direction, flags, callingPackage, callingPackage,
1552 Binder.getCallingUid());
RoboErik0dac35a2014-08-12 15:48:49 -07001553 }
1554
Chinyue Chen6affe932018-01-24 14:51:43 +08001555 protected void adjustStreamVolume(int streamType, int direction, int flags,
John Spurlock90874332015-03-10 16:00:54 -04001556 String callingPackage, String caller, int uid) {
Eric Laurent83a017b2013-03-19 18:15:31 -07001557 if (mUseFixedVolume) {
1558 return;
1559 }
John Spurlock90874332015-03-10 16:00:54 -04001560 if (DEBUG_VOL) Log.d(TAG, "adjustStreamVolume() stream=" + streamType + ", dir=" + direction
1561 + ", flags=" + flags + ", caller=" + caller);
Jean-Michel Trivi3114ce32012-06-11 15:03:52 -07001562
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001563 ensureValidDirection(direction);
1564 ensureValidStreamType(streamType);
1565
RoboErik4197cb62015-01-21 15:45:32 -08001566 boolean isMuteAdjust = isMuteAdjust(direction);
1567
John Spurlock3ce37252015-02-17 13:20:45 -05001568 if (isMuteAdjust && !isStreamAffectedByMute(streamType)) {
1569 return;
1570 }
1571
Tomoharu Kasaharaa0d0c542019-01-18 20:04:38 +09001572 // If adjust is mute and the stream is STREAM_VOICE_CALL or STREAM_BLUETOOTH_SCO, make sure
Nadav Bar6b7751d2017-12-24 16:03:08 +02001573 // that the calling app have the MODIFY_PHONE_STATE permission.
1574 if (isMuteAdjust &&
Tomoharu Kasaharaa0d0c542019-01-18 20:04:38 +09001575 (streamType == AudioSystem.STREAM_VOICE_CALL ||
1576 streamType == AudioSystem.STREAM_BLUETOOTH_SCO) &&
Nadav Bar6b7751d2017-12-24 16:03:08 +02001577 mContext.checkCallingOrSelfPermission(
1578 android.Manifest.permission.MODIFY_PHONE_STATE)
1579 != PackageManager.PERMISSION_GRANTED) {
1580 Log.w(TAG, "MODIFY_PHONE_STATE Permission Denial: adjustStreamVolume from pid="
1581 + Binder.getCallingPid() + ", uid=" + Binder.getCallingUid());
1582 return;
1583 }
1584
Eric Laurent96a33d12011-11-08 10:31:57 -08001585 // use stream type alias here so that streams with same alias have the same behavior,
1586 // including with regard to silent mode control (e.g the use of STREAM_RING below and in
1587 // checkForRingerModeChange() in place of STREAM_RING or STREAM_NOTIFICATION)
Eric Laurent6d517662012-04-23 18:42:39 -07001588 int streamTypeAlias = mStreamVolumeAlias[streamType];
RoboErik4197cb62015-01-21 15:45:32 -08001589
Eric Laurentb024c302011-10-14 17:19:27 -07001590 VolumeStreamState streamState = mStreamStates[streamTypeAlias];
Eric Laurent9bc8358d2011-11-18 16:43:31 -08001591
1592 final int device = getDeviceForStream(streamTypeAlias);
Eric Laurent3ef75492012-11-28 12:12:23 -08001593
Eric Laurent42b041e2013-03-29 11:36:03 -07001594 int aliasIndex = streamState.getIndex(device);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001595 boolean adjustVolume = true;
Eric Laurent3ef75492012-11-28 12:12:23 -08001596 int step;
Eric Laurent24482012012-05-10 09:41:17 -07001597
Matthew Xiec9d1d5f2013-09-12 00:32:22 -07001598 // skip a2dp absolute volume control request when the device
1599 // is not an a2dp device
1600 if ((device & AudioSystem.DEVICE_OUT_ALL_A2DP) == 0 &&
1601 (flags & AudioManager.FLAG_BLUETOOTH_ABS_VOLUME) != 0) {
1602 return;
1603 }
1604
Kenny Guy70e0c582015-06-30 19:18:28 +01001605 // If we are being called by the system (e.g. hardware keys) check for current user
1606 // so we handle user restrictions correctly.
1607 if (uid == android.os.Process.SYSTEM_UID) {
1608 uid = UserHandle.getUid(getCurrentUserId(), UserHandle.getAppId(uid));
1609 }
John Spurlock59dc9c12015-03-02 11:20:15 -05001610 if (mAppOps.noteOp(STREAM_VOLUME_OPS[streamTypeAlias], uid, callingPackage)
RoboErik0dac35a2014-08-12 15:48:49 -07001611 != AppOpsManager.MODE_ALLOWED) {
Dianne Hackbornba50b97c2013-04-30 15:04:46 -07001612 return;
1613 }
1614
Eric Laurentfde16d52012-12-03 14:42:39 -08001615 // reset any pending volume command
hyomin.ohd0446dc2018-10-18 13:58:27 +09001616 synchronized (mSafeMediaVolumeStateLock) {
Eric Laurentfde16d52012-12-03 14:42:39 -08001617 mPendingVolumeCommand = null;
1618 }
1619
Eric Laurent3ef75492012-11-28 12:12:23 -08001620 flags &= ~AudioManager.FLAG_FIXED_VOLUME;
1621 if ((streamTypeAlias == AudioSystem.STREAM_MUSIC) &&
1622 ((device & mFixedVolumeDevices) != 0)) {
1623 flags |= AudioManager.FLAG_FIXED_VOLUME;
1624
1625 // Always toggle between max safe volume and 0 for fixed volume devices where safe
1626 // volume is enforced, and max and 0 for the others.
1627 // This is simulated by stepping by the full allowed volume range
1628 if (mSafeMediaVolumeState == SAFE_MEDIA_VOLUME_ACTIVE &&
1629 (device & mSafeMediaVolumeDevices) != 0) {
Eric Laurenteab40d12017-06-09 12:45:21 -07001630 step = safeMediaVolumeIndex(device);
Eric Laurent3ef75492012-11-28 12:12:23 -08001631 } else {
1632 step = streamState.getMaxIndex();
1633 }
1634 if (aliasIndex != 0) {
1635 aliasIndex = step;
1636 }
1637 } else {
1638 // convert one UI step (+/-1) into a number of internal units on the stream alias
1639 step = rescaleIndex(10, streamType, streamTypeAlias);
1640 }
1641
Eric Laurent42b041e2013-03-29 11:36:03 -07001642 // If either the client forces allowing ringer modes for this adjustment,
1643 // or the stream type is one that is affected by ringer modes
1644 if (((flags & AudioManager.FLAG_ALLOW_RINGER_MODES) != 0) ||
John Spurlockee5ad722015-03-03 16:17:21 -05001645 (streamTypeAlias == getUiSoundsStreamType())) {
John Spurlock661f2cf2014-11-17 10:29:10 -05001646 int ringerMode = getRingerModeInternal();
Eric Laurent42b041e2013-03-29 11:36:03 -07001647 // do not vibrate if already in vibrate mode
1648 if (ringerMode == AudioManager.RINGER_MODE_VIBRATE) {
1649 flags &= ~AudioManager.FLAG_VIBRATE;
Eric Laurent3ef75492012-11-28 12:12:23 -08001650 }
RoboErik5452e252015-02-06 15:33:53 -08001651 // Check if the ringer mode handles this adjustment. If it does we don't
1652 // need to adjust the volume further.
John Spurlock50ced3f2015-05-11 16:00:09 -04001653 final int result = checkForRingerModeChange(aliasIndex, direction, step,
Julia Reynoldsed783792016-04-08 15:27:35 -04001654 streamState.mIsMuted, callingPackage, flags);
John Spurlocka11b4af2014-06-01 11:52:23 -04001655 adjustVolume = (result & FLAG_ADJUST_VOLUME) != 0;
1656 // If suppressing a volume adjustment in silent mode, display the UI hint
1657 if ((result & AudioManager.FLAG_SHOW_SILENT_HINT) != 0) {
1658 flags |= AudioManager.FLAG_SHOW_SILENT_HINT;
1659 }
John Spurlock661f2cf2014-11-17 10:29:10 -05001660 // If suppressing a volume down adjustment in vibrate mode, display the UI hint
1661 if ((result & AudioManager.FLAG_SHOW_VIBRATE_HINT) != 0) {
1662 flags |= AudioManager.FLAG_SHOW_VIBRATE_HINT;
1663 }
Eric Laurent42b041e2013-03-29 11:36:03 -07001664 }
Beverlyd6964762018-02-16 14:07:03 -05001665
1666 // If the ringer mode or zen is muting the stream, do not change stream unless
1667 // it'll cause us to exit dnd
Julia Reynoldsed783792016-04-08 15:27:35 -04001668 if (!volumeAdjustmentAllowedByDnd(streamTypeAlias, flags)) {
John Spurlock50ced3f2015-05-11 16:00:09 -04001669 adjustVolume = false;
1670 }
Eric Laurent42b041e2013-03-29 11:36:03 -07001671 int oldIndex = mStreamStates[streamType].getIndex(device);
Eric Laurent3ef75492012-11-28 12:12:23 -08001672
Eric Laurent42b041e2013-03-29 11:36:03 -07001673 if (adjustVolume && (direction != AudioManager.ADJUST_SAME)) {
RoboErik5452e252015-02-06 15:33:53 -08001674 mAudioHandler.removeMessages(MSG_UNMUTE_STREAM);
Matthew Xiec9d1d5f2013-09-12 00:32:22 -07001675
RoboErik4197cb62015-01-21 15:45:32 -08001676 if (isMuteAdjust) {
1677 boolean state;
1678 if (direction == AudioManager.ADJUST_TOGGLE_MUTE) {
1679 state = !streamState.mIsMuted;
1680 } else {
1681 state = direction == AudioManager.ADJUST_MUTE;
1682 }
1683 if (streamTypeAlias == AudioSystem.STREAM_MUSIC) {
1684 setSystemAudioMute(state);
1685 }
1686 for (int stream = 0; stream < mStreamStates.length; stream++) {
1687 if (streamTypeAlias == mStreamVolumeAlias[stream]) {
Sungmin Choi841ed0a2015-07-26 23:09:49 -07001688 if (!(readCameraSoundForced()
1689 && (mStreamStates[stream].getStreamType()
1690 == AudioSystem.STREAM_SYSTEM_ENFORCED))) {
1691 mStreamStates[stream].mute(state);
1692 }
RoboErik4197cb62015-01-21 15:45:32 -08001693 }
1694 }
1695 } else if ((direction == AudioManager.ADJUST_RAISE) &&
Eric Laurent42b041e2013-03-29 11:36:03 -07001696 !checkSafeMediaVolume(streamTypeAlias, aliasIndex + step, device)) {
RoboErik4197cb62015-01-21 15:45:32 -08001697 Log.e(TAG, "adjustStreamVolume() safe volume index = " + oldIndex);
John Spurlock3346a802014-05-20 16:25:37 -04001698 mVolumeController.postDisplaySafeVolumeWarning(flags);
John Spurlock90874332015-03-10 16:00:54 -04001699 } else if (streamState.adjustIndex(direction * step, device, caller)
1700 || streamState.mIsMuted) {
RoboErik4197cb62015-01-21 15:45:32 -08001701 // Post message to set system volume (it in turn will post a
1702 // message to persist).
1703 if (streamState.mIsMuted) {
1704 // Unmute the stream if it was previously muted
RoboErik5452e252015-02-06 15:33:53 -08001705 if (direction == AudioManager.ADJUST_RAISE) {
1706 // unmute immediately for volume up
1707 streamState.mute(false);
1708 } else if (direction == AudioManager.ADJUST_LOWER) {
Muyuan Li1ed6df62016-06-18 11:16:52 -07001709 if (mIsSingleVolume) {
John Spurlocka48d7792015-03-03 17:35:57 -05001710 sendMsg(mAudioHandler, MSG_UNMUTE_STREAM, SENDMSG_QUEUE,
1711 streamTypeAlias, flags, null, UNMUTE_STREAM_DELAY);
1712 }
RoboErik5452e252015-02-06 15:33:53 -08001713 }
RoboErik4197cb62015-01-21 15:45:32 -08001714 }
Eric Laurent42b041e2013-03-29 11:36:03 -07001715 sendMsg(mAudioHandler,
1716 MSG_SET_DEVICE_VOLUME,
1717 SENDMSG_QUEUE,
1718 device,
1719 0,
1720 streamState,
1721 0);
Eric Laurent4bbcc652012-09-24 14:26:30 -07001722 }
Jungshik Jang41d97462014-06-30 22:26:29 +09001723
Jungshik Jang41d97462014-06-30 22:26:29 +09001724 int newIndex = mStreamStates[streamType].getIndex(device);
Ajay Panickere3946c82018-02-26 16:04:15 -08001725
1726 // Check if volume update should be send to AVRCP
1727 if (streamTypeAlias == AudioSystem.STREAM_MUSIC &&
1728 (device & AudioSystem.DEVICE_OUT_ALL_A2DP) != 0 &&
1729 (flags & AudioManager.FLAG_BLUETOOTH_ABS_VOLUME) == 0) {
Jean-Michel Trivi58850372018-09-14 16:01:28 -07001730 if (DEBUG_VOL) {
1731 Log.d(TAG, "adjustSreamVolume: postSetAvrcpAbsoluteVolumeIndex index="
1732 + newIndex + "stream=" + streamType);
Ajay Panickere3946c82018-02-26 16:04:15 -08001733 }
Jean-Michel Trivi734819a2019-02-04 15:44:28 -08001734 mDeviceBroker.postSetAvrcpAbsoluteVolumeIndex(newIndex / 10);
Ajay Panickere3946c82018-02-26 16:04:15 -08001735 }
1736
Jakub Pawlowskif9570f32018-02-21 17:15:12 -08001737 // Check if volume update should be send to Hearing Aid
1738 if ((device & AudioSystem.DEVICE_OUT_HEARING_AID) != 0) {
Jean-Michel Trivi58850372018-09-14 16:01:28 -07001739 Log.i(TAG, "adjustSreamVolume postSetHearingAidVolumeIndex index=" + newIndex
1740 + " stream=" + streamType);
1741 mDeviceBroker.postSetHearingAidVolumeIndex(newIndex, streamType);
Jakub Pawlowskif9570f32018-02-21 17:15:12 -08001742 }
1743
Ajay Panickere3946c82018-02-26 16:04:15 -08001744 // Check if volume update should be sent to Hdmi system audio.
Jinsuk Kim336cdb42014-11-29 06:27:00 +09001745 if (streamTypeAlias == AudioSystem.STREAM_MUSIC) {
1746 setSystemAudioVolume(oldIndex, newIndex, getStreamMaxVolume(streamType), flags);
1747 }
Shubangc480a712018-06-11 18:02:42 -07001748 synchronized (mHdmiClientLock) {
1749 if (mHdmiManager != null) {
Eric Laurent212532b2014-07-21 15:43:18 -07001750 // mHdmiCecSink true => mHdmiPlaybackClient != null
1751 if (mHdmiCecSink &&
1752 streamTypeAlias == AudioSystem.STREAM_MUSIC &&
1753 oldIndex != newIndex) {
Shubangc480a712018-06-11 18:02:42 -07001754 int keyCode = (direction == -1) ? KeyEvent.KEYCODE_VOLUME_DOWN :
1755 KeyEvent.KEYCODE_VOLUME_UP;
1756 final long ident = Binder.clearCallingIdentity();
1757 try {
1758 mHdmiPlaybackClient.sendKeyEvent(keyCode, true);
1759 mHdmiPlaybackClient.sendKeyEvent(keyCode, false);
1760 } finally {
1761 Binder.restoreCallingIdentity(ident);
Eric Laurent212532b2014-07-21 15:43:18 -07001762 }
Jungshik Jang41d97462014-06-30 22:26:29 +09001763 }
Shubangc480a712018-06-11 18:02:42 -07001764
1765 if (mHdmiAudioSystemClient != null &&
Shubangde728822018-07-16 16:46:51 -07001766 mHdmiSystemAudioSupported &&
Shubangc480a712018-06-11 18:02:42 -07001767 streamTypeAlias == AudioSystem.STREAM_MUSIC &&
1768 (oldIndex != newIndex || isMuteAdjust)) {
Shubangde728822018-07-16 16:46:51 -07001769 final long identity = Binder.clearCallingIdentity();
Shubangc480a712018-06-11 18:02:42 -07001770 mHdmiAudioSystemClient.sendReportAudioStatusCecCommand(
1771 isMuteAdjust, getStreamVolume(AudioSystem.STREAM_MUSIC),
1772 getStreamMaxVolume(AudioSystem.STREAM_MUSIC),
1773 isStreamMute(AudioSystem.STREAM_MUSIC));
Shubangde728822018-07-16 16:46:51 -07001774 Binder.restoreCallingIdentity(identity);
Shubangc480a712018-06-11 18:02:42 -07001775 }
Jungshik Jang41d97462014-06-30 22:26:29 +09001776 }
1777 }
Eric Laurent4bbcc652012-09-24 14:26:30 -07001778 }
Eric Laurent42b041e2013-03-29 11:36:03 -07001779 int index = mStreamStates[streamType].getIndex(device);
Eric Laurent25101b02011-02-02 09:33:30 -08001780 sendVolumeUpdate(streamType, oldIndex, index, flags);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001781 }
1782
RoboErik5452e252015-02-06 15:33:53 -08001783 // Called after a delay when volume down is pressed while muted
1784 private void onUnmuteStream(int stream, int flags) {
1785 VolumeStreamState streamState = mStreamStates[stream];
1786 streamState.mute(false);
1787
1788 final int device = getDeviceForStream(stream);
1789 final int index = mStreamStates[stream].getIndex(device);
1790 sendVolumeUpdate(stream, index, index, flags);
1791 }
1792
Jinsuk Kim336cdb42014-11-29 06:27:00 +09001793 private void setSystemAudioVolume(int oldVolume, int newVolume, int maxVolume, int flags) {
Jinsuk Kim336cdb42014-11-29 06:27:00 +09001794 // Sets the audio volume of AVR when we are in system audio mode. The new volume info
1795 // is tranformed to HDMI-CEC commands and passed through CEC bus.
Shubangc480a712018-06-11 18:02:42 -07001796 synchronized (mHdmiClientLock) {
1797 if (mHdmiManager == null
1798 || mHdmiTvClient == null
1799 || oldVolume == newVolume
1800 || (flags & AudioManager.FLAG_HDMI_SYSTEM_AUDIO_VOLUME) != 0
1801 || !mHdmiSystemAudioSupported) return;
1802 final long token = Binder.clearCallingIdentity();
1803 try {
1804 mHdmiTvClient.setSystemAudioVolume(oldVolume, newVolume, maxVolume);
1805 } finally {
1806 Binder.restoreCallingIdentity(token);
Jinsuk Kim336cdb42014-11-29 06:27:00 +09001807 }
1808 }
1809 }
1810
Eric Laurentfde16d52012-12-03 14:42:39 -08001811 // StreamVolumeCommand contains the information needed to defer the process of
1812 // setStreamVolume() in case the user has to acknowledge the safe volume warning message.
1813 class StreamVolumeCommand {
1814 public final int mStreamType;
1815 public final int mIndex;
1816 public final int mFlags;
1817 public final int mDevice;
Eric Laurent9ce379a2010-02-16 06:00:26 -08001818
Eric Laurentfde16d52012-12-03 14:42:39 -08001819 StreamVolumeCommand(int streamType, int index, int flags, int device) {
1820 mStreamType = streamType;
1821 mIndex = index;
1822 mFlags = flags;
1823 mDevice = device;
Eric Laurentb024c302011-10-14 17:19:27 -07001824 }
John Spurlock35134602014-07-24 18:10:48 -04001825
1826 @Override
1827 public String toString() {
1828 return new StringBuilder().append("{streamType=").append(mStreamType).append(",index=")
1829 .append(mIndex).append(",flags=").append(mFlags).append(",device=")
1830 .append(mDevice).append('}').toString();
1831 }
Eric Laurentfde16d52012-12-03 14:42:39 -08001832 };
Eric Laurent3ef75492012-11-28 12:12:23 -08001833
Julia Reynolds48034f82016-03-09 10:15:16 -05001834 private int getNewRingerMode(int stream, int index, int flags) {
Zak Cohen47798292017-11-30 12:34:20 -08001835 // setRingerMode does nothing if the device is single volume,so the value would be unchanged
1836 if (mIsSingleVolume) {
1837 return getRingerModeExternal();
1838 }
1839
John Spurlockee5ad722015-03-03 16:17:21 -05001840 // setting volume on ui sounds stream type also controls silent mode
Eric Laurent3ef75492012-11-28 12:12:23 -08001841 if (((flags & AudioManager.FLAG_ALLOW_RINGER_MODES) != 0) ||
John Spurlock75ae23c2015-06-02 16:26:43 -04001842 (stream == getUiSoundsStreamType())) {
Eric Laurent3ef75492012-11-28 12:12:23 -08001843 int newRingerMode;
1844 if (index == 0) {
1845 newRingerMode = mHasVibrator ? AudioManager.RINGER_MODE_VIBRATE
John Spurlocka48d7792015-03-03 17:35:57 -05001846 : mVolumePolicy.volumeDownToEnterSilent ? AudioManager.RINGER_MODE_SILENT
Julia Reynolds48034f82016-03-09 10:15:16 -05001847 : AudioManager.RINGER_MODE_NORMAL;
Eric Laurent3ef75492012-11-28 12:12:23 -08001848 } else {
1849 newRingerMode = AudioManager.RINGER_MODE_NORMAL;
1850 }
Julia Reynolds48034f82016-03-09 10:15:16 -05001851 return newRingerMode;
1852 }
1853 return getRingerModeExternal();
1854 }
1855
1856 private boolean isAndroidNPlus(String caller) {
1857 try {
1858 final ApplicationInfo applicationInfo =
1859 mContext.getPackageManager().getApplicationInfoAsUser(
1860 caller, 0, UserHandle.getUserId(Binder.getCallingUid()));
1861 if (applicationInfo.targetSdkVersion >= Build.VERSION_CODES.N) {
1862 return true;
1863 }
1864 return false;
1865 } catch (PackageManager.NameNotFoundException e) {
1866 return true;
1867 }
1868 }
1869
1870 private boolean wouldToggleZenMode(int newMode) {
1871 if (getRingerModeExternal() == AudioManager.RINGER_MODE_SILENT
1872 && newMode != AudioManager.RINGER_MODE_SILENT) {
1873 return true;
1874 } else if (getRingerModeExternal() != AudioManager.RINGER_MODE_SILENT
1875 && newMode == AudioManager.RINGER_MODE_SILENT) {
1876 return true;
1877 }
1878 return false;
1879 }
1880
1881 private void onSetStreamVolume(int streamType, int index, int flags, int device,
1882 String caller) {
1883 final int stream = mStreamVolumeAlias[streamType];
1884 setStreamVolumeInt(stream, index, device, false, caller);
1885 // setting volume on ui sounds stream type also controls silent mode
1886 if (((flags & AudioManager.FLAG_ALLOW_RINGER_MODES) != 0) ||
1887 (stream == getUiSoundsStreamType())) {
1888 setRingerMode(getNewRingerMode(stream, index, flags),
1889 TAG + ".onSetStreamVolume", false /*external*/);
Eric Laurent3ef75492012-11-28 12:12:23 -08001890 }
John Spurlock75ae23c2015-06-02 16:26:43 -04001891 // setting non-zero volume for a muted stream unmutes the stream and vice versa
1892 mStreamStates[stream].mute(index == 0);
Eric Laurentfde16d52012-12-03 14:42:39 -08001893 }
1894
1895 /** @see AudioManager#setStreamVolume(int, int, int) */
Dianne Hackbornba50b97c2013-04-30 15:04:46 -07001896 public void setStreamVolume(int streamType, int index, int flags, String callingPackage) {
Phil Weaverf1a9aff2017-03-23 17:21:29 -07001897 if ((streamType == AudioManager.STREAM_ACCESSIBILITY) && !canChangeAccessibilityVolume()) {
Jean-Michel Triviab2d9312017-03-13 15:33:39 -07001898 Log.w(TAG, "Trying to call setStreamVolume() for a11y without"
Phil Weaverf1a9aff2017-03-23 17:21:29 -07001899 + " CHANGE_ACCESSIBILITY_VOLUME callingPackage=" + callingPackage);
Jean-Michel Triviab2d9312017-03-13 15:33:39 -07001900 return;
1901 }
Tomoharu Kasaharaa0d0c542019-01-18 20:04:38 +09001902 if ((streamType == AudioManager.STREAM_VOICE_CALL ||
1903 streamType == AudioManager.STREAM_BLUETOOTH_SCO) &&
Nadav Bar6b7751d2017-12-24 16:03:08 +02001904 (index == 0) &&
1905 (mContext.checkCallingOrSelfPermission(
1906 android.Manifest.permission.MODIFY_PHONE_STATE)
1907 != PackageManager.PERMISSION_GRANTED)) {
Tomoharu Kasaharaa0d0c542019-01-18 20:04:38 +09001908 Log.w(TAG, "Trying to call setStreamVolume() for STREAM_VOICE_CALL or"
1909 + " STREAM_BLUETOOTH_SCO and index 0 without"
Nadav Bar6b7751d2017-12-24 16:03:08 +02001910 + " MODIFY_PHONE_STATE callingPackage=" + callingPackage);
1911 return;
1912 }
Jean-Michel Trivi58850372018-09-14 16:01:28 -07001913 sVolumeLogger.log(new VolumeEvent(VolumeEvent.VOL_SET_STREAM_VOL, streamType,
Jean-Michel Trivicf170362017-08-24 17:24:57 -07001914 index/*val1*/, flags/*val2*/, callingPackage));
John Spurlock90874332015-03-10 16:00:54 -04001915 setStreamVolume(streamType, index, flags, callingPackage, callingPackage,
1916 Binder.getCallingUid());
RoboErik0dac35a2014-08-12 15:48:49 -07001917 }
1918
Phil Weaverf1a9aff2017-03-23 17:21:29 -07001919 private boolean canChangeAccessibilityVolume() {
1920 synchronized (mAccessibilityServiceUidsLock) {
1921 if (PackageManager.PERMISSION_GRANTED == mContext.checkCallingOrSelfPermission(
1922 android.Manifest.permission.CHANGE_ACCESSIBILITY_VOLUME)) {
1923 return true;
1924 }
1925 if (mAccessibilityServiceUids != null) {
1926 int callingUid = Binder.getCallingUid();
1927 for (int i = 0; i < mAccessibilityServiceUids.length; i++) {
1928 if (mAccessibilityServiceUids[i] == callingUid) {
1929 return true;
1930 }
1931 }
1932 }
1933 return false;
1934 }
1935 }
1936
RoboErik0dac35a2014-08-12 15:48:49 -07001937 private void setStreamVolume(int streamType, int index, int flags, String callingPackage,
John Spurlock90874332015-03-10 16:00:54 -04001938 String caller, int uid) {
Jean-Michel Triviac487672016-11-11 10:05:18 -08001939 if (DEBUG_VOL) {
1940 Log.d(TAG, "setStreamVolume(stream=" + streamType+", index=" + index
1941 + ", calling=" + callingPackage + ")");
1942 }
Eric Laurent83a017b2013-03-19 18:15:31 -07001943 if (mUseFixedVolume) {
1944 return;
1945 }
1946
Eric Laurentfde16d52012-12-03 14:42:39 -08001947 ensureValidStreamType(streamType);
Dianne Hackbornba50b97c2013-04-30 15:04:46 -07001948 int streamTypeAlias = mStreamVolumeAlias[streamType];
1949 VolumeStreamState streamState = mStreamStates[streamTypeAlias];
Eric Laurentfde16d52012-12-03 14:42:39 -08001950
1951 final int device = getDeviceForStream(streamType);
1952 int oldIndex;
1953
Matthew Xiec9d1d5f2013-09-12 00:32:22 -07001954 // skip a2dp absolute volume control request when the device
1955 // is not an a2dp device
1956 if ((device & AudioSystem.DEVICE_OUT_ALL_A2DP) == 0 &&
1957 (flags & AudioManager.FLAG_BLUETOOTH_ABS_VOLUME) != 0) {
1958 return;
1959 }
Kenny Guy70e0c582015-06-30 19:18:28 +01001960 // If we are being called by the system (e.g. hardware keys) check for current user
1961 // so we handle user restrictions correctly.
1962 if (uid == android.os.Process.SYSTEM_UID) {
1963 uid = UserHandle.getUid(getCurrentUserId(), UserHandle.getAppId(uid));
1964 }
John Spurlock59dc9c12015-03-02 11:20:15 -05001965 if (mAppOps.noteOp(STREAM_VOLUME_OPS[streamTypeAlias], uid, callingPackage)
RoboErik0dac35a2014-08-12 15:48:49 -07001966 != AppOpsManager.MODE_ALLOWED) {
Dianne Hackbornba50b97c2013-04-30 15:04:46 -07001967 return;
1968 }
1969
Julia Reynolds48034f82016-03-09 10:15:16 -05001970 if (isAndroidNPlus(callingPackage)
1971 && wouldToggleZenMode(getNewRingerMode(streamTypeAlias, index, flags))
1972 && !mNm.isNotificationPolicyAccessGrantedForPackage(callingPackage)) {
1973 throw new SecurityException("Not allowed to change Do Not Disturb state");
1974 }
1975
Julia Reynoldsed783792016-04-08 15:27:35 -04001976 if (!volumeAdjustmentAllowedByDnd(streamTypeAlias, flags)) {
1977 return;
1978 }
1979
hyomin.ohd0446dc2018-10-18 13:58:27 +09001980 synchronized (mSafeMediaVolumeStateLock) {
Eric Laurentfde16d52012-12-03 14:42:39 -08001981 // reset any pending volume command
1982 mPendingVolumeCommand = null;
1983
Eric Laurent42b041e2013-03-29 11:36:03 -07001984 oldIndex = streamState.getIndex(device);
Eric Laurentfde16d52012-12-03 14:42:39 -08001985
Dianne Hackbornba50b97c2013-04-30 15:04:46 -07001986 index = rescaleIndex(index * 10, streamType, streamTypeAlias);
Eric Laurentfde16d52012-12-03 14:42:39 -08001987
Jean-Michel Trivi58850372018-09-14 16:01:28 -07001988 if (streamTypeAlias == AudioSystem.STREAM_MUSIC
1989 && (device & AudioSystem.DEVICE_OUT_ALL_A2DP) != 0
1990 && (flags & AudioManager.FLAG_BLUETOOTH_ABS_VOLUME) == 0) {
1991 if (DEBUG_VOL) {
1992 Log.d(TAG, "setStreamVolume postSetAvrcpAbsoluteVolumeIndex index=" + index
1993 + "stream=" + streamType);
John Du5a0cf7a2013-07-19 11:30:34 -07001994 }
Jean-Michel Trivi58850372018-09-14 16:01:28 -07001995 mDeviceBroker.postSetAvrcpAbsoluteVolumeIndex(index / 10);
John Du5a0cf7a2013-07-19 11:30:34 -07001996 }
1997
Jakub Pawlowskif9570f32018-02-21 17:15:12 -08001998 if ((device & AudioSystem.DEVICE_OUT_HEARING_AID) != 0) {
Jean-Michel Trivi58850372018-09-14 16:01:28 -07001999 Log.i(TAG, "setStreamVolume postSetHearingAidVolumeIndex index=" + index
2000 + " stream=" + streamType);
2001 mDeviceBroker.postSetHearingAidVolumeIndex(index, streamType);
Jakub Pawlowskif9570f32018-02-21 17:15:12 -08002002 }
2003
Jinsuk Kim336cdb42014-11-29 06:27:00 +09002004 if (streamTypeAlias == AudioSystem.STREAM_MUSIC) {
2005 setSystemAudioVolume(oldIndex, index, getStreamMaxVolume(streamType), flags);
Jungshik Jang41d97462014-06-30 22:26:29 +09002006 }
2007
Eric Laurentfde16d52012-12-03 14:42:39 -08002008 flags &= ~AudioManager.FLAG_FIXED_VOLUME;
Dianne Hackbornba50b97c2013-04-30 15:04:46 -07002009 if ((streamTypeAlias == AudioSystem.STREAM_MUSIC) &&
Eric Laurentfde16d52012-12-03 14:42:39 -08002010 ((device & mFixedVolumeDevices) != 0)) {
2011 flags |= AudioManager.FLAG_FIXED_VOLUME;
2012
2013 // volume is either 0 or max allowed for fixed volume devices
2014 if (index != 0) {
2015 if (mSafeMediaVolumeState == SAFE_MEDIA_VOLUME_ACTIVE &&
2016 (device & mSafeMediaVolumeDevices) != 0) {
Eric Laurenteab40d12017-06-09 12:45:21 -07002017 index = safeMediaVolumeIndex(device);
Eric Laurentfde16d52012-12-03 14:42:39 -08002018 } else {
2019 index = streamState.getMaxIndex();
2020 }
2021 }
2022 }
2023
Dianne Hackbornba50b97c2013-04-30 15:04:46 -07002024 if (!checkSafeMediaVolume(streamTypeAlias, index, device)) {
John Spurlock3346a802014-05-20 16:25:37 -04002025 mVolumeController.postDisplaySafeVolumeWarning(flags);
Eric Laurentfde16d52012-12-03 14:42:39 -08002026 mPendingVolumeCommand = new StreamVolumeCommand(
2027 streamType, index, flags, device);
2028 } else {
John Spurlock90874332015-03-10 16:00:54 -04002029 onSetStreamVolume(streamType, index, flags, device, caller);
Eric Laurent42b041e2013-03-29 11:36:03 -07002030 index = mStreamStates[streamType].getIndex(device);
Eric Laurentfde16d52012-12-03 14:42:39 -08002031 }
2032 }
Shubangc480a712018-06-11 18:02:42 -07002033 synchronized (mHdmiClientLock) {
2034 if (mHdmiManager != null &&
2035 mHdmiAudioSystemClient != null &&
Shubangde728822018-07-16 16:46:51 -07002036 mHdmiSystemAudioSupported &&
Shubangc480a712018-06-11 18:02:42 -07002037 streamTypeAlias == AudioSystem.STREAM_MUSIC &&
2038 (oldIndex != index)) {
Shubangde728822018-07-16 16:46:51 -07002039 final long identity = Binder.clearCallingIdentity();
Shubangc480a712018-06-11 18:02:42 -07002040 mHdmiAudioSystemClient.sendReportAudioStatusCecCommand(
2041 false, getStreamVolume(AudioSystem.STREAM_MUSIC),
2042 getStreamMaxVolume(AudioSystem.STREAM_MUSIC),
2043 isStreamMute(AudioSystem.STREAM_MUSIC));
Shubangde728822018-07-16 16:46:51 -07002044 Binder.restoreCallingIdentity(identity);
Shubangc480a712018-06-11 18:02:42 -07002045 }
2046 }
Eric Laurent25101b02011-02-02 09:33:30 -08002047 sendVolumeUpdate(streamType, oldIndex, index, flags);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002048 }
2049
Beverlyd6964762018-02-16 14:07:03 -05002050 // No ringer or zen muted stream volumes can be changed unless it'll exit dnd
Julia Reynoldsed783792016-04-08 15:27:35 -04002051 private boolean volumeAdjustmentAllowedByDnd(int streamTypeAlias, int flags) {
Beverlyd6964762018-02-16 14:07:03 -05002052 switch (mNm.getZenMode()) {
2053 case Settings.Global.ZEN_MODE_OFF:
2054 return true;
2055 case Settings.Global.ZEN_MODE_NO_INTERRUPTIONS:
2056 case Settings.Global.ZEN_MODE_ALARMS:
2057 case Settings.Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS:
2058 return !isStreamMutedByRingerOrZenMode(streamTypeAlias)
2059 || streamTypeAlias == getUiSoundsStreamType()
2060 || (flags & AudioManager.FLAG_ALLOW_RINGER_MODES) != 0;
Julia Reynoldsed783792016-04-08 15:27:35 -04002061 }
Beverlyd6964762018-02-16 14:07:03 -05002062
Julia Reynoldsed783792016-04-08 15:27:35 -04002063 return true;
2064 }
2065
Eric Laurent45c90ce2012-04-24 18:44:22 -07002066 /** @see AudioManager#forceVolumeControlStream(int) */
2067 public void forceVolumeControlStream(int streamType, IBinder cb) {
Jean-Michel Trivi60eddfd2018-03-09 15:31:12 -08002068 if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.MODIFY_PHONE_STATE)
2069 != PackageManager.PERMISSION_GRANTED) {
2070 return;
2071 }
Jean-Michel Trivia7880d42017-04-15 12:41:05 -07002072 if (DEBUG_VOL) { Log.d(TAG, String.format("forceVolumeControlStream(%d)", streamType)); }
Eric Laurent45c90ce2012-04-24 18:44:22 -07002073 synchronized(mForceControlStreamLock) {
Jean-Michel Trivia7880d42017-04-15 12:41:05 -07002074 if (mVolumeControlStream != -1 && streamType != -1) {
2075 mUserSelectedVolumeControlStream = true;
2076 }
Eric Laurent45c90ce2012-04-24 18:44:22 -07002077 mVolumeControlStream = streamType;
2078 if (mVolumeControlStream == -1) {
2079 if (mForceControlStreamClient != null) {
2080 mForceControlStreamClient.release();
2081 mForceControlStreamClient = null;
2082 }
Jean-Michel Trivia7880d42017-04-15 12:41:05 -07002083 mUserSelectedVolumeControlStream = false;
Eric Laurent45c90ce2012-04-24 18:44:22 -07002084 } else {
jianzhou21fb09f2018-02-28 14:03:15 +08002085 if (null == mForceControlStreamClient) {
2086 mForceControlStreamClient = new ForceControlStreamClient(cb);
2087 } else {
2088 if (mForceControlStreamClient.getBinder() == cb) {
2089 Log.d(TAG, "forceVolumeControlStream cb:" + cb + " is already linked.");
2090 } else {
2091 mForceControlStreamClient.release();
2092 mForceControlStreamClient = new ForceControlStreamClient(cb);
2093 }
2094 }
Eric Laurent45c90ce2012-04-24 18:44:22 -07002095 }
2096 }
2097 }
2098
2099 private class ForceControlStreamClient implements IBinder.DeathRecipient {
2100 private IBinder mCb; // To be notified of client's death
2101
2102 ForceControlStreamClient(IBinder cb) {
2103 if (cb != null) {
2104 try {
2105 cb.linkToDeath(this, 0);
2106 } catch (RemoteException e) {
2107 // Client has died!
2108 Log.w(TAG, "ForceControlStreamClient() could not link to "+cb+" binder death");
2109 cb = null;
2110 }
2111 }
2112 mCb = cb;
2113 }
2114
2115 public void binderDied() {
2116 synchronized(mForceControlStreamLock) {
2117 Log.w(TAG, "SCO client died");
2118 if (mForceControlStreamClient != this) {
2119 Log.w(TAG, "unregistered control stream client died");
2120 } else {
2121 mForceControlStreamClient = null;
2122 mVolumeControlStream = -1;
Jean-Michel Trivia7880d42017-04-15 12:41:05 -07002123 mUserSelectedVolumeControlStream = false;
Eric Laurent45c90ce2012-04-24 18:44:22 -07002124 }
2125 }
2126 }
2127
2128 public void release() {
2129 if (mCb != null) {
2130 mCb.unlinkToDeath(this, 0);
2131 mCb = null;
2132 }
2133 }
jianzhou21fb09f2018-02-28 14:03:15 +08002134
2135 public IBinder getBinder() {
2136 return mCb;
2137 }
Eric Laurent45c90ce2012-04-24 18:44:22 -07002138 }
2139
Dianne Hackborn5ac72a22012-08-29 18:32:08 -07002140 private void sendBroadcastToAll(Intent intent) {
Christopher Tate267603f2015-01-20 14:21:21 -08002141 intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);
John Spurlock86490862015-02-25 11:22:52 -05002142 intent.addFlags(Intent.FLAG_RECEIVER_FOREGROUND);
Dianne Hackborn5ac72a22012-08-29 18:32:08 -07002143 final long ident = Binder.clearCallingIdentity();
2144 try {
2145 mContext.sendBroadcastAsUser(intent, UserHandle.ALL);
2146 } finally {
2147 Binder.restoreCallingIdentity(ident);
2148 }
2149 }
2150
2151 private void sendStickyBroadcastToAll(Intent intent) {
John Spurlock86490862015-02-25 11:22:52 -05002152 intent.addFlags(Intent.FLAG_RECEIVER_FOREGROUND);
Dianne Hackborn5ac72a22012-08-29 18:32:08 -07002153 final long ident = Binder.clearCallingIdentity();
2154 try {
2155 mContext.sendStickyBroadcastAsUser(intent, UserHandle.ALL);
2156 } finally {
2157 Binder.restoreCallingIdentity(ident);
2158 }
2159 }
2160
Kenny Guy70e0c582015-06-30 19:18:28 +01002161 private int getCurrentUserId() {
2162 final long ident = Binder.clearCallingIdentity();
2163 try {
Sudheer Shankadc589ac2016-11-10 15:30:17 -08002164 UserInfo currentUser = ActivityManager.getService().getCurrentUser();
Kenny Guy70e0c582015-06-30 19:18:28 +01002165 return currentUser.id;
2166 } catch (RemoteException e) {
2167 // Activity manager not running, nothing we can do assume user 0.
2168 } finally {
2169 Binder.restoreCallingIdentity(ident);
2170 }
Xiaohui Chen7c696362015-09-16 09:56:14 -07002171 return UserHandle.USER_SYSTEM;
Kenny Guy70e0c582015-06-30 19:18:28 +01002172 }
2173
Eric Laurent25101b02011-02-02 09:33:30 -08002174 // UI update and Broadcast Intent
Yue Li949865b2017-05-24 17:25:28 -07002175 protected void sendVolumeUpdate(int streamType, int oldIndex, int index, int flags) {
John Spurlock72966d62015-06-18 15:45:07 -04002176 streamType = mStreamVolumeAlias[streamType];
Eric Laurent25101b02011-02-02 09:33:30 -08002177
Jinsuk Kim336cdb42014-11-29 06:27:00 +09002178 if (streamType == AudioSystem.STREAM_MUSIC) {
2179 flags = updateFlagsForSystemAudio(flags);
Jungshik Jang1a6be6e2014-09-16 11:04:54 +09002180 }
John Spurlock3346a802014-05-20 16:25:37 -04002181 mVolumeController.postVolumeChanged(streamType, flags);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002182 }
2183
Jinsuk Kim336cdb42014-11-29 06:27:00 +09002184 // If Hdmi-CEC system audio mode is on, we show volume bar only when TV
2185 // receives volume notification from Audio Receiver.
2186 private int updateFlagsForSystemAudio(int flags) {
Shubangc480a712018-06-11 18:02:42 -07002187 synchronized (mHdmiClientLock) {
2188 if (mHdmiTvClient != null) {
Jinsuk Kim336cdb42014-11-29 06:27:00 +09002189 if (mHdmiSystemAudioSupported &&
2190 ((flags & AudioManager.FLAG_HDMI_SYSTEM_AUDIO_VOLUME) == 0)) {
2191 flags &= ~AudioManager.FLAG_SHOW_UI;
2192 }
2193 }
2194 }
2195 return flags;
2196 }
2197
Mike Lockwood0dc37cc2011-12-01 16:14:19 -05002198 // UI update and Broadcast Intent
Mike Lockwood0dc37cc2011-12-01 16:14:19 -05002199 private void sendMasterMuteUpdate(boolean muted, int flags) {
Jinsuk Kim336cdb42014-11-29 06:27:00 +09002200 mVolumeController.postMasterMuteChanged(updateFlagsForSystemAudio(flags));
Justin Koh57978ed2012-04-03 17:37:58 -07002201 broadcastMasterMuteStatus(muted);
2202 }
Mike Lockwood0dc37cc2011-12-01 16:14:19 -05002203
Justin Koh57978ed2012-04-03 17:37:58 -07002204 private void broadcastMasterMuteStatus(boolean muted) {
Mike Lockwood0dc37cc2011-12-01 16:14:19 -05002205 Intent intent = new Intent(AudioManager.MASTER_MUTE_CHANGED_ACTION);
2206 intent.putExtra(AudioManager.EXTRA_MASTER_VOLUME_MUTED, muted);
Justin Koh57978ed2012-04-03 17:37:58 -07002207 intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT
2208 | Intent.FLAG_RECEIVER_REPLACE_PENDING);
Dianne Hackborn5ac72a22012-08-29 18:32:08 -07002209 sendStickyBroadcastToAll(intent);
Mike Lockwood0dc37cc2011-12-01 16:14:19 -05002210 }
2211
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002212 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002213 * Sets the stream state's index, and posts a message to set system volume.
2214 * This will not call out to the UI. Assumes a valid stream type.
2215 *
2216 * @param streamType Type of the stream
2217 * @param index Desired volume index of the stream
Eric Laurent9bc8358d2011-11-18 16:43:31 -08002218 * @param device the device whose volume must be changed
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002219 * @param force If true, set the volume even if the desired volume is same
2220 * as the current volume.
2221 */
Eric Laurent9bc8358d2011-11-18 16:43:31 -08002222 private void setStreamVolumeInt(int streamType,
2223 int index,
2224 int device,
John Spurlock90874332015-03-10 16:00:54 -04002225 boolean force,
2226 String caller) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002227 VolumeStreamState streamState = mStreamStates[streamType];
Eric Laurent5b4e6542010-03-19 20:02:21 -07002228
John Spurlock90874332015-03-10 16:00:54 -04002229 if (streamState.setIndex(index, device, caller) || force) {
Eric Laurent42b041e2013-03-29 11:36:03 -07002230 // Post message to set system volume (it in turn will post a message
2231 // to persist).
2232 sendMsg(mAudioHandler,
2233 MSG_SET_DEVICE_VOLUME,
2234 SENDMSG_QUEUE,
2235 device,
2236 0,
2237 streamState,
2238 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002239 }
2240 }
2241
Jinsuk Kim336cdb42014-11-29 06:27:00 +09002242 private void setSystemAudioMute(boolean state) {
Shubangc480a712018-06-11 18:02:42 -07002243 synchronized (mHdmiClientLock) {
2244 if (mHdmiManager == null || mHdmiTvClient == null || !mHdmiSystemAudioSupported) return;
2245 final long token = Binder.clearCallingIdentity();
2246 try {
2247 mHdmiTvClient.setSystemAudioMute(state);
2248 } finally {
2249 Binder.restoreCallingIdentity(token);
Jinsuk Kim336cdb42014-11-29 06:27:00 +09002250 }
2251 }
2252 }
2253
Eric Laurent25101b02011-02-02 09:33:30 -08002254 /** get stream mute state. */
2255 public boolean isStreamMute(int streamType) {
RoboErik7c82ced2014-12-04 17:39:08 -08002256 if (streamType == AudioManager.USE_DEFAULT_STREAM_TYPE) {
2257 streamType = getActiveStreamType(streamType);
2258 }
Eric Laurent8fa4d6f2014-10-30 14:13:03 -07002259 synchronized (VolumeStreamState.class) {
jiabin93d32ef2017-07-11 13:50:02 -07002260 ensureValidStreamType(streamType);
RoboErik4197cb62015-01-21 15:45:32 -08002261 return mStreamStates[streamType].mIsMuted;
Eric Laurent8fa4d6f2014-10-30 14:13:03 -07002262 }
Eric Laurent25101b02011-02-02 09:33:30 -08002263 }
2264
Jean-Michel Triviba5270b2014-10-01 17:49:29 -07002265 private class RmtSbmxFullVolDeathHandler implements IBinder.DeathRecipient {
2266 private IBinder mICallback; // To be notified of client's death
2267
2268 RmtSbmxFullVolDeathHandler(IBinder cb) {
2269 mICallback = cb;
2270 try {
2271 cb.linkToDeath(this, 0/*flags*/);
2272 } catch (RemoteException e) {
2273 Log.e(TAG, "can't link to death", e);
2274 }
2275 }
2276
2277 boolean isHandlerFor(IBinder cb) {
2278 return mICallback.equals(cb);
2279 }
2280
2281 void forget() {
2282 try {
2283 mICallback.unlinkToDeath(this, 0/*flags*/);
2284 } catch (NoSuchElementException e) {
2285 Log.e(TAG, "error unlinking to death", e);
2286 }
2287 }
2288
2289 public void binderDied() {
2290 Log.w(TAG, "Recorder with remote submix at full volume died " + mICallback);
2291 forceRemoteSubmixFullVolume(false, mICallback);
2292 }
2293 }
2294
2295 /**
2296 * call must be synchronized on mRmtSbmxFullVolDeathHandlers
2297 * @return true if there is a registered death handler, false otherwise */
2298 private boolean discardRmtSbmxFullVolDeathHandlerFor(IBinder cb) {
2299 Iterator<RmtSbmxFullVolDeathHandler> it = mRmtSbmxFullVolDeathHandlers.iterator();
2300 while (it.hasNext()) {
2301 final RmtSbmxFullVolDeathHandler handler = it.next();
2302 if (handler.isHandlerFor(cb)) {
2303 handler.forget();
2304 mRmtSbmxFullVolDeathHandlers.remove(handler);
2305 return true;
2306 }
2307 }
2308 return false;
2309 }
2310
2311 /** call synchronized on mRmtSbmxFullVolDeathHandlers */
2312 private boolean hasRmtSbmxFullVolDeathHandlerFor(IBinder cb) {
2313 Iterator<RmtSbmxFullVolDeathHandler> it = mRmtSbmxFullVolDeathHandlers.iterator();
2314 while (it.hasNext()) {
2315 if (it.next().isHandlerFor(cb)) {
2316 return true;
2317 }
2318 }
2319 return false;
2320 }
2321
2322 private int mRmtSbmxFullVolRefCount = 0;
2323 private ArrayList<RmtSbmxFullVolDeathHandler> mRmtSbmxFullVolDeathHandlers =
2324 new ArrayList<RmtSbmxFullVolDeathHandler>();
2325
2326 public void forceRemoteSubmixFullVolume(boolean startForcing, IBinder cb) {
2327 if (cb == null) {
2328 return;
2329 }
2330 if ((PackageManager.PERMISSION_GRANTED != mContext.checkCallingOrSelfPermission(
2331 android.Manifest.permission.CAPTURE_AUDIO_OUTPUT))) {
2332 Log.w(TAG, "Trying to call forceRemoteSubmixFullVolume() without CAPTURE_AUDIO_OUTPUT");
2333 return;
2334 }
2335 synchronized(mRmtSbmxFullVolDeathHandlers) {
2336 boolean applyRequired = false;
2337 if (startForcing) {
2338 if (!hasRmtSbmxFullVolDeathHandlerFor(cb)) {
2339 mRmtSbmxFullVolDeathHandlers.add(new RmtSbmxFullVolDeathHandler(cb));
2340 if (mRmtSbmxFullVolRefCount == 0) {
2341 mFullVolumeDevices |= AudioSystem.DEVICE_OUT_REMOTE_SUBMIX;
2342 mFixedVolumeDevices |= AudioSystem.DEVICE_OUT_REMOTE_SUBMIX;
2343 applyRequired = true;
2344 }
2345 mRmtSbmxFullVolRefCount++;
2346 }
2347 } else {
2348 if (discardRmtSbmxFullVolDeathHandlerFor(cb) && (mRmtSbmxFullVolRefCount > 0)) {
2349 mRmtSbmxFullVolRefCount--;
2350 if (mRmtSbmxFullVolRefCount == 0) {
2351 mFullVolumeDevices &= ~AudioSystem.DEVICE_OUT_REMOTE_SUBMIX;
2352 mFixedVolumeDevices &= ~AudioSystem.DEVICE_OUT_REMOTE_SUBMIX;
2353 applyRequired = true;
2354 }
2355 }
2356 }
2357 if (applyRequired) {
2358 // Assumes only STREAM_MUSIC going through DEVICE_OUT_REMOTE_SUBMIX
2359 checkAllFixedVolumeDevices(AudioSystem.STREAM_MUSIC);
2360 mStreamStates[AudioSystem.STREAM_MUSIC].applyAllVolumes();
2361 }
2362 }
2363 }
2364
Kenny Guy70e0c582015-06-30 19:18:28 +01002365 private void setMasterMuteInternal(boolean mute, int flags, String callingPackage, int uid,
2366 int userId) {
2367 // If we are being called by the system check for user we are going to change
2368 // so we handle user restrictions correctly.
2369 if (uid == android.os.Process.SYSTEM_UID) {
2370 uid = UserHandle.getUid(userId, UserHandle.getAppId(uid));
2371 }
Makoto Onuki4f160732015-10-27 17:15:38 -07002372 // If OP_AUDIO_MASTER_VOLUME is set, disallow unmuting.
2373 if (!mute && mAppOps.noteOp(AppOpsManager.OP_AUDIO_MASTER_VOLUME, uid, callingPackage)
RoboErik7c82ced2014-12-04 17:39:08 -08002374 != AppOpsManager.MODE_ALLOWED) {
Julia Reynolds4a21b252014-06-04 11:11:43 -04002375 return;
2376 }
Kenny Guy70e0c582015-06-30 19:18:28 +01002377 if (userId != UserHandle.getCallingUserId() &&
2378 mContext.checkCallingOrSelfPermission(
2379 android.Manifest.permission.INTERACT_ACROSS_USERS_FULL)
2380 != PackageManager.PERMISSION_GRANTED) {
2381 return;
2382 }
Makoto Onukid45a4a22015-11-02 17:17:38 -08002383 setMasterMuteInternalNoCallerCheck(mute, flags, userId);
2384 }
2385
2386 private void setMasterMuteInternalNoCallerCheck(boolean mute, int flags, int userId) {
2387 if (DEBUG_VOL) {
2388 Log.d(TAG, String.format("Master mute %s, %d, user=%d", mute, flags, userId));
2389 }
Hongwei Wangdaba1242018-05-29 14:36:16 -07002390 if (!isPlatformAutomotive() && mUseFixedVolume) {
2391 // If using fixed volume, we don't mute.
2392 // TODO: remove the isPlatformAutomotive check here.
2393 // The isPlatformAutomotive check is added for safety but may not be necessary.
2394 return;
Makoto Onukid45a4a22015-11-02 17:17:38 -08002395 }
Kenny Guy70e0c582015-06-30 19:18:28 +01002396 if (getCurrentUserId() == userId) {
2397 if (mute != AudioSystem.getMasterMute()) {
2398 setSystemAudioMute(mute);
2399 AudioSystem.setMasterMute(mute);
Kenny Guy70e0c582015-06-30 19:18:28 +01002400 sendMasterMuteUpdate(mute, flags);
RoboErik7c82ced2014-12-04 17:39:08 -08002401
Kenny Guy70e0c582015-06-30 19:18:28 +01002402 Intent intent = new Intent(AudioManager.MASTER_MUTE_CHANGED_ACTION);
2403 intent.putExtra(AudioManager.EXTRA_MASTER_VOLUME_MUTED, mute);
2404 sendBroadcastToAll(intent);
2405 }
Jason Simmons1ce5b262012-02-02 13:00:17 -08002406 }
Mike Lockwoodce952c82011-11-14 10:47:42 -08002407 }
2408
2409 /** get master mute state. */
2410 public boolean isMasterMute() {
Mike Lockwood3194ea92011-12-07 11:47:31 -08002411 return AudioSystem.getMasterMute();
Mike Lockwoodce952c82011-11-14 10:47:42 -08002412 }
2413
Kenny Guy70e0c582015-06-30 19:18:28 +01002414 public void setMasterMute(boolean mute, int flags, String callingPackage, int userId) {
2415 setMasterMuteInternal(mute, flags, callingPackage, Binder.getCallingUid(),
2416 userId);
John Spurlockee5ad722015-03-03 16:17:21 -05002417 }
2418
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002419 /** @see AudioManager#getStreamVolume(int) */
2420 public int getStreamVolume(int streamType) {
2421 ensureValidStreamType(streamType);
Eric Laurent9bc8358d2011-11-18 16:43:31 -08002422 int device = getDeviceForStream(streamType);
Eric Laurent8fa4d6f2014-10-30 14:13:03 -07002423 synchronized (VolumeStreamState.class) {
2424 int index = mStreamStates[streamType].getIndex(device);
Eric Laurent4bbcc652012-09-24 14:26:30 -07002425
Eric Laurent8fa4d6f2014-10-30 14:13:03 -07002426 // by convention getStreamVolume() returns 0 when a stream is muted.
RoboErik4197cb62015-01-21 15:45:32 -08002427 if (mStreamStates[streamType].mIsMuted) {
Eric Laurent8fa4d6f2014-10-30 14:13:03 -07002428 index = 0;
2429 }
2430 if (index != 0 && (mStreamVolumeAlias[streamType] == AudioSystem.STREAM_MUSIC) &&
2431 (device & mFixedVolumeDevices) != 0) {
2432 index = mStreamStates[streamType].getMaxIndex();
2433 }
2434 return (index + 5) / 10;
Eric Laurent42b041e2013-03-29 11:36:03 -07002435 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002436 }
2437
2438 /** @see AudioManager#getStreamMaxVolume(int) */
2439 public int getStreamMaxVolume(int streamType) {
2440 ensureValidStreamType(streamType);
Eric Laurenta553c252009-07-17 12:17:14 -07002441 return (mStreamStates[streamType].getMaxIndex() + 5) / 10;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002442 }
2443
Jean-Michel Trivi8e7aca32017-11-28 18:12:38 -08002444 /** @see AudioManager#getStreamMinVolumeInt(int) */
John Spurlockb6e19e32015-03-10 21:33:44 -04002445 public int getStreamMinVolume(int streamType) {
2446 ensureValidStreamType(streamType);
2447 return (mStreamStates[streamType].getMinIndex() + 5) / 10;
2448 }
2449
Eric Laurent25101b02011-02-02 09:33:30 -08002450 /** Get last audible volume before stream was muted. */
2451 public int getLastAudibleStreamVolume(int streamType) {
2452 ensureValidStreamType(streamType);
Eric Laurent9bc8358d2011-11-18 16:43:31 -08002453 int device = getDeviceForStream(streamType);
Eric Laurent42b041e2013-03-29 11:36:03 -07002454 return (mStreamStates[streamType].getIndex(device) + 5) / 10;
Eric Laurent25101b02011-02-02 09:33:30 -08002455 }
2456
John Spurlockee5ad722015-03-03 16:17:21 -05002457 /** @see AudioManager#getUiSoundsStreamType() */
2458 public int getUiSoundsStreamType() {
John Spurlock4f0f1202014-08-05 13:28:33 -04002459 return mStreamVolumeAlias[AudioSystem.STREAM_SYSTEM];
Eric Laurent6d517662012-04-23 18:42:39 -07002460 }
2461
Makoto Onukid45a4a22015-11-02 17:17:38 -08002462 /** @see AudioManager#setMicrophoneMute(boolean) */
2463 @Override
Kenny Guy70e0c582015-06-30 19:18:28 +01002464 public void setMicrophoneMute(boolean on, String callingPackage, int userId) {
2465 // If we are being called by the system check for user we are going to change
2466 // so we handle user restrictions correctly.
2467 int uid = Binder.getCallingUid();
2468 if (uid == android.os.Process.SYSTEM_UID) {
2469 uid = UserHandle.getUid(userId, UserHandle.getAppId(uid));
2470 }
Makoto Onuki4f160732015-10-27 17:15:38 -07002471 // If OP_MUTE_MICROPHONE is set, disallow unmuting.
2472 if (!on && mAppOps.noteOp(AppOpsManager.OP_MUTE_MICROPHONE, uid, callingPackage)
Kenny Guy70e0c582015-06-30 19:18:28 +01002473 != AppOpsManager.MODE_ALLOWED) {
Emily Bernier22c921a2014-05-28 11:01:32 -04002474 return;
2475 }
Jean-Michel Trivi4a4fea02014-08-29 18:14:09 -07002476 if (!checkAudioSettingsPermission("setMicrophoneMute()")) {
2477 return;
2478 }
Kenny Guy70e0c582015-06-30 19:18:28 +01002479 if (userId != UserHandle.getCallingUserId() &&
2480 mContext.checkCallingOrSelfPermission(
2481 android.Manifest.permission.INTERACT_ACROSS_USERS_FULL)
2482 != PackageManager.PERMISSION_GRANTED) {
2483 return;
2484 }
Makoto Onukid45a4a22015-11-02 17:17:38 -08002485 setMicrophoneMuteNoCallerCheck(on, userId);
2486 }
Emily Bernier22c921a2014-05-28 11:01:32 -04002487
Makoto Onukid45a4a22015-11-02 17:17:38 -08002488 private void setMicrophoneMuteNoCallerCheck(boolean on, int userId) {
2489 if (DEBUG_VOL) {
2490 Log.d(TAG, String.format("Mic mute %s, user=%d", on, userId));
2491 }
Jean-Michel Trivi7be17d22017-12-21 18:09:21 -08002492 // only mute for the current user
Kenny Guy70e0c582015-06-30 19:18:28 +01002493 if (getCurrentUserId() == userId) {
Jean-Michel Trivi7be17d22017-12-21 18:09:21 -08002494 final boolean currentMute = AudioSystem.isMicrophoneMuted();
Eric Laurent66b69672018-01-26 18:30:51 -08002495 final long identity = Binder.clearCallingIdentity();
Kenny Guy70e0c582015-06-30 19:18:28 +01002496 AudioSystem.muteMicrophone(on);
Eric Laurent66b69672018-01-26 18:30:51 -08002497 Binder.restoreCallingIdentity(identity);
Jean-Michel Trivi7be17d22017-12-21 18:09:21 -08002498 if (on != currentMute) {
2499 mContext.sendBroadcast(new Intent(AudioManager.ACTION_MICROPHONE_MUTE_CHANGED)
2500 .setFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY));
2501 }
Kenny Guy70e0c582015-06-30 19:18:28 +01002502 }
Emily Bernier22c921a2014-05-28 11:01:32 -04002503 }
2504
John Spurlock661f2cf2014-11-17 10:29:10 -05002505 @Override
2506 public int getRingerModeExternal() {
2507 synchronized(mSettingsLock) {
2508 return mRingerModeExternal;
2509 }
2510 }
2511
2512 @Override
2513 public int getRingerModeInternal() {
Glenn Kastenba195eb2011-12-13 09:30:40 -08002514 synchronized(mSettingsLock) {
2515 return mRingerMode;
2516 }
2517 }
2518
2519 private void ensureValidRingerMode(int ringerMode) {
John Spurlock97559372014-10-24 16:27:36 -04002520 if (!isValidRingerMode(ringerMode)) {
Glenn Kastenba195eb2011-12-13 09:30:40 -08002521 throw new IllegalArgumentException("Bad ringer mode " + ringerMode);
2522 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002523 }
2524
John Spurlock97559372014-10-24 16:27:36 -04002525 /** @see AudioManager#isValidRingerMode(int) */
2526 public boolean isValidRingerMode(int ringerMode) {
2527 return ringerMode >= 0 && ringerMode <= AudioManager.RINGER_MODE_MAX;
2528 }
2529
John Spurlock661f2cf2014-11-17 10:29:10 -05002530 public void setRingerModeExternal(int ringerMode, String caller) {
Julia Reynolds48034f82016-03-09 10:15:16 -05002531 if (isAndroidNPlus(caller) && wouldToggleZenMode(ringerMode)
2532 && !mNm.isNotificationPolicyAccessGrantedForPackage(caller)) {
2533 throw new SecurityException("Not allowed to change Do Not Disturb state");
2534 }
2535
John Spurlockaf88a192014-12-23 16:14:44 -05002536 setRingerMode(ringerMode, caller, true /*external*/);
John Spurlock661f2cf2014-11-17 10:29:10 -05002537 }
2538
2539 public void setRingerModeInternal(int ringerMode, String caller) {
John Spurlockcdb57ae2015-02-11 19:04:11 -05002540 enforceVolumeController("setRingerModeInternal");
John Spurlockaf88a192014-12-23 16:14:44 -05002541 setRingerMode(ringerMode, caller, false /*external*/);
John Spurlock661f2cf2014-11-17 10:29:10 -05002542 }
2543
Mike Digman55272862018-02-20 14:35:17 -08002544 public void silenceRingerModeInternal(String reason) {
2545 VibrationEffect effect = null;
2546 int ringerMode = AudioManager.RINGER_MODE_SILENT;
2547 int toastText = 0;
2548
2549 int silenceRingerSetting = Settings.Secure.VOLUME_HUSH_OFF;
2550 if (mContext.getResources()
2551 .getBoolean(com.android.internal.R.bool.config_volumeHushGestureEnabled)) {
2552 silenceRingerSetting = Settings.Secure.getIntForUser(mContentResolver,
2553 Settings.Secure.VOLUME_HUSH_GESTURE, VOLUME_HUSH_OFF,
2554 UserHandle.USER_CURRENT);
2555 }
2556
2557 switch(silenceRingerSetting) {
2558 case VOLUME_HUSH_MUTE:
2559 effect = VibrationEffect.get(VibrationEffect.EFFECT_DOUBLE_CLICK);
2560 ringerMode = AudioManager.RINGER_MODE_SILENT;
2561 toastText = com.android.internal.R.string.volume_dialog_ringer_guidance_silent;
2562 break;
2563 case VOLUME_HUSH_VIBRATE:
2564 effect = VibrationEffect.get(VibrationEffect.EFFECT_HEAVY_CLICK);
2565 ringerMode = AudioManager.RINGER_MODE_VIBRATE;
2566 toastText = com.android.internal.R.string.volume_dialog_ringer_guidance_vibrate;
2567 break;
2568 }
Alexey Kuzmine1f06b82018-06-20 17:48:43 +01002569 maybeVibrate(effect, reason);
Mike Digman55272862018-02-20 14:35:17 -08002570 setRingerModeInternal(ringerMode, reason);
2571 Toast.makeText(mContext, toastText, Toast.LENGTH_SHORT).show();
2572 }
2573
Alexey Kuzmine1f06b82018-06-20 17:48:43 +01002574 private boolean maybeVibrate(VibrationEffect effect, String reason) {
Mike Digman55272862018-02-20 14:35:17 -08002575 if (!mHasVibrator) {
2576 return false;
2577 }
2578 final boolean hapticsDisabled = Settings.System.getIntForUser(mContext.getContentResolver(),
2579 Settings.System.HAPTIC_FEEDBACK_ENABLED, 0, UserHandle.USER_CURRENT) == 0;
2580 if (hapticsDisabled) {
2581 return false;
2582 }
2583
2584 if (effect == null) {
2585 return false;
2586 }
Alexey Kuzmine1f06b82018-06-20 17:48:43 +01002587 mVibrator.vibrate(Binder.getCallingUid(), mContext.getOpPackageName(), effect,
2588 reason, VIBRATION_ATTRIBUTES);
Mike Digman55272862018-02-20 14:35:17 -08002589 return true;
2590 }
2591
John Spurlock661f2cf2014-11-17 10:29:10 -05002592 private void setRingerMode(int ringerMode, String caller, boolean external) {
Muyuan Li1ed6df62016-06-18 11:16:52 -07002593 if (mUseFixedVolume || mIsSingleVolume) {
Eric Laurent83a017b2013-03-19 18:15:31 -07002594 return;
2595 }
John Spurlock661f2cf2014-11-17 10:29:10 -05002596 if (caller == null || caller.length() == 0) {
2597 throw new IllegalArgumentException("Bad caller: " + caller);
2598 }
John Spurlock97559372014-10-24 16:27:36 -04002599 ensureValidRingerMode(ringerMode);
Eric Laurent24482012012-05-10 09:41:17 -07002600 if ((ringerMode == AudioManager.RINGER_MODE_VIBRATE) && !mHasVibrator) {
2601 ringerMode = AudioManager.RINGER_MODE_SILENT;
2602 }
John Spurlockaf88a192014-12-23 16:14:44 -05002603 final long identity = Binder.clearCallingIdentity();
2604 try {
2605 synchronized (mSettingsLock) {
2606 final int ringerModeInternal = getRingerModeInternal();
2607 final int ringerModeExternal = getRingerModeExternal();
2608 if (external) {
2609 setRingerModeExt(ringerMode);
2610 if (mRingerModeDelegate != null) {
2611 ringerMode = mRingerModeDelegate.onSetRingerModeExternal(ringerModeExternal,
John Spurlocka48d7792015-03-03 17:35:57 -05002612 ringerMode, caller, ringerModeInternal, mVolumePolicy);
John Spurlockaf88a192014-12-23 16:14:44 -05002613 }
2614 if (ringerMode != ringerModeInternal) {
2615 setRingerModeInt(ringerMode, true /*persist*/);
2616 }
2617 } else /*internal*/ {
2618 if (ringerMode != ringerModeInternal) {
2619 setRingerModeInt(ringerMode, true /*persist*/);
2620 }
2621 if (mRingerModeDelegate != null) {
2622 ringerMode = mRingerModeDelegate.onSetRingerModeInternal(ringerModeInternal,
John Spurlocka48d7792015-03-03 17:35:57 -05002623 ringerMode, caller, ringerModeExternal, mVolumePolicy);
John Spurlockaf88a192014-12-23 16:14:44 -05002624 }
2625 setRingerModeExt(ringerMode);
John Spurlock57627792014-12-11 11:29:54 -05002626 }
John Spurlock661f2cf2014-11-17 10:29:10 -05002627 }
John Spurlockaf88a192014-12-23 16:14:44 -05002628 } finally {
2629 Binder.restoreCallingIdentity(identity);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002630 }
2631 }
2632
John Spurlock661f2cf2014-11-17 10:29:10 -05002633 private void setRingerModeExt(int ringerMode) {
2634 synchronized(mSettingsLock) {
2635 if (ringerMode == mRingerModeExternal) return;
2636 mRingerModeExternal = ringerMode;
John Spurlocke5b42d92014-10-15 12:03:48 -04002637 }
John Spurlock661f2cf2014-11-17 10:29:10 -05002638 // Send sticky broadcast
John Spurlockbcc10872014-11-28 15:29:21 -05002639 broadcastRingerMode(AudioManager.RINGER_MODE_CHANGED_ACTION, ringerMode);
John Spurlocke5b42d92014-10-15 12:03:48 -04002640 }
2641
Jean-Michel Trivic106d9f2018-06-07 12:28:27 -07002642 @GuardedBy("mSettingsLock")
John Spurlock50ced3f2015-05-11 16:00:09 -04002643 private void muteRingerModeStreams() {
Beverlyd6964762018-02-16 14:07:03 -05002644 // Mute stream if not previously muted by ringer mode and (ringer mode
2645 // is not RINGER_MODE_NORMAL OR stream is zen muted) and stream is affected by ringer mode.
2646 // Unmute stream if previously muted by ringer/zen mode and ringer mode
Eric Laurent5b4e6542010-03-19 20:02:21 -07002647 // is RINGER_MODE_NORMAL or stream is not affected by ringer mode.
Jason Parekhb1096152009-03-24 17:48:25 -07002648 int numStreamTypes = AudioSystem.getNumStreamTypes();
Beverly925cde82018-01-23 09:31:23 -05002649
2650 if (mNm == null) {
2651 mNm = (NotificationManager) mContext.getSystemService(Context.NOTIFICATION_SERVICE);
2652 }
2653
Jack He6dd78c12018-02-12 21:00:24 -08002654 final int ringerMode = mRingerMode; // Read ringer mode as reading primitives is atomic
2655 final boolean ringerModeMute = ringerMode == AudioManager.RINGER_MODE_VIBRATE
2656 || ringerMode == AudioManager.RINGER_MODE_SILENT;
2657 final boolean shouldRingSco = ringerMode == AudioManager.RINGER_MODE_VIBRATE
2658 && isBluetoothScoOn();
2659 // Ask audio policy engine to force use Bluetooth SCO channel if needed
2660 final String eventSource = "muteRingerModeStreams() from u/pid:" + Binder.getCallingUid()
2661 + "/" + Binder.getCallingPid();
2662 sendMsg(mAudioHandler, MSG_SET_FORCE_USE, SENDMSG_QUEUE, AudioSystem.FOR_VIBRATE_RINGING,
2663 shouldRingSco ? AudioSystem.FORCE_BT_SCO : AudioSystem.FORCE_NONE, eventSource, 0);
Beverly925cde82018-01-23 09:31:23 -05002664
Eric Laurent5b4e6542010-03-19 20:02:21 -07002665 for (int streamType = numStreamTypes - 1; streamType >= 0; streamType--) {
Beverlyd6964762018-02-16 14:07:03 -05002666 final boolean isMuted = isStreamMutedByRingerOrZenMode(streamType);
Jack He6dd78c12018-02-12 21:00:24 -08002667 final boolean muteAllowedBySco =
2668 !(shouldRingSco && streamType == AudioSystem.STREAM_RING);
Beverlyd6964762018-02-16 14:07:03 -05002669 final boolean shouldZenMute = shouldZenMuteStream(streamType);
2670 final boolean shouldMute = shouldZenMute || (ringerModeMute
Jack He6dd78c12018-02-12 21:00:24 -08002671 && isStreamAffectedByRingerMode(streamType) && muteAllowedBySco);
John Spurlock661f2cf2014-11-17 10:29:10 -05002672 if (isMuted == shouldMute) continue;
2673 if (!shouldMute) {
2674 // unmute
2675 // ring and notifications volume should never be 0 when not silenced
John Spurlockd9c75db2015-04-28 11:19:13 -04002676 if (mStreamVolumeAlias[streamType] == AudioSystem.STREAM_RING) {
John Spurlock661f2cf2014-11-17 10:29:10 -05002677 synchronized (VolumeStreamState.class) {
John Spurlocka48d7792015-03-03 17:35:57 -05002678 final VolumeStreamState vss = mStreamStates[streamType];
2679 for (int i = 0; i < vss.mIndexMap.size(); i++) {
2680 int device = vss.mIndexMap.keyAt(i);
2681 int value = vss.mIndexMap.valueAt(i);
John Spurlock2bb02ec2015-03-02 13:13:06 -05002682 if (value == 0) {
John Spurlocka48d7792015-03-03 17:35:57 -05002683 vss.setIndex(10, device, TAG);
Eric Laurent9bc8358d2011-11-18 16:43:31 -08002684 }
2685 }
Eric Laurent9e0d25f2015-02-12 17:28:53 -08002686 // Persist volume for stream ring when it is changed here
2687 final int device = getDeviceForStream(streamType);
2688 sendMsg(mAudioHandler,
2689 MSG_PERSIST_VOLUME,
2690 SENDMSG_QUEUE,
2691 device,
2692 0,
2693 mStreamStates[streamType],
2694 PERSIST_DELAY);
Eric Laurentb024c302011-10-14 17:19:27 -07002695 }
Eric Laurent9bcf4012009-06-12 06:09:28 -07002696 }
RoboErik4197cb62015-01-21 15:45:32 -08002697 mStreamStates[streamType].mute(false);
Beverlyd6964762018-02-16 14:07:03 -05002698 mRingerAndZenModeMutedStreams &= ~(1 << streamType);
Eric Laurent5b4e6542010-03-19 20:02:21 -07002699 } else {
John Spurlock661f2cf2014-11-17 10:29:10 -05002700 // mute
RoboErik4197cb62015-01-21 15:45:32 -08002701 mStreamStates[streamType].mute(true);
Beverlyd6964762018-02-16 14:07:03 -05002702 mRingerAndZenModeMutedStreams |= (1 << streamType);
Jason Parekhb1096152009-03-24 17:48:25 -07002703 }
2704 }
John Spurlock50ced3f2015-05-11 16:00:09 -04002705 }
2706
Beverly925cde82018-01-23 09:31:23 -05002707 private boolean isAlarm(int streamType) {
2708 return streamType == AudioSystem.STREAM_ALARM;
2709 }
2710
2711 private boolean isNotificationOrRinger(int streamType) {
2712 return streamType == AudioSystem.STREAM_NOTIFICATION
2713 || streamType == AudioSystem.STREAM_RING;
2714 }
2715
2716 private boolean isMedia(int streamType) {
Beverlyd6964762018-02-16 14:07:03 -05002717 return streamType == AudioSystem.STREAM_MUSIC;
2718 }
2719
2720
2721 private boolean isSystem(int streamType) {
2722 return streamType == AudioSystem.STREAM_SYSTEM;
Beverly925cde82018-01-23 09:31:23 -05002723 }
2724
John Spurlock50ced3f2015-05-11 16:00:09 -04002725 private void setRingerModeInt(int ringerMode, boolean persist) {
2726 final boolean change;
2727 synchronized(mSettingsLock) {
2728 change = mRingerMode != ringerMode;
2729 mRingerMode = ringerMode;
Jean-Michel Trivic106d9f2018-06-07 12:28:27 -07002730 muteRingerModeStreams();
John Spurlock50ced3f2015-05-11 16:00:09 -04002731 }
2732
Jason Parekhb1096152009-03-24 17:48:25 -07002733 // Post a persist ringer mode msg
Eric Laurent4050c932009-07-08 02:52:14 -07002734 if (persist) {
Eric Laurentafbb0472011-12-15 09:04:23 -08002735 sendMsg(mAudioHandler, MSG_PERSIST_RINGER_MODE,
Eric Laurent4050c932009-07-08 02:52:14 -07002736 SENDMSG_REPLACE, 0, 0, null, PERSIST_DELAY);
2737 }
John Spurlockbcc10872014-11-28 15:29:21 -05002738 if (change) {
2739 // Send sticky broadcast
2740 broadcastRingerMode(AudioManager.INTERNAL_RINGER_MODE_CHANGED_ACTION, ringerMode);
2741 }
Jason Parekhb1096152009-03-24 17:48:25 -07002742 }
2743
Jean-Michel Trivica49d312019-02-14 15:55:39 -08002744 /*package*/ void postUpdateRingerModeServiceInt() {
2745 sendMsg(mAudioHandler, MSG_UPDATE_RINGER_MODE, SENDMSG_QUEUE, 0, 0, null, 0);
2746 }
2747
2748 private void onUpdateRingerModeServiceInt() {
Jean-Michel Trivi58850372018-09-14 16:01:28 -07002749 setRingerModeInt(getRingerModeInternal(), false);
2750 }
2751
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002752 /** @see AudioManager#shouldVibrate(int) */
2753 public boolean shouldVibrate(int vibrateType) {
Eric Laurentbffc3d12012-05-07 17:43:49 -07002754 if (!mHasVibrator) return false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002755
2756 switch (getVibrateSetting(vibrateType)) {
2757
2758 case AudioManager.VIBRATE_SETTING_ON:
John Spurlock57627792014-12-11 11:29:54 -05002759 return getRingerModeExternal() != AudioManager.RINGER_MODE_SILENT;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002760
2761 case AudioManager.VIBRATE_SETTING_ONLY_SILENT:
John Spurlock57627792014-12-11 11:29:54 -05002762 return getRingerModeExternal() == AudioManager.RINGER_MODE_VIBRATE;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002763
2764 case AudioManager.VIBRATE_SETTING_OFF:
Daniel Sandlerbcac4962010-04-12 13:23:57 -04002765 // return false, even for incoming calls
2766 return false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002767
2768 default:
2769 return false;
2770 }
2771 }
2772
2773 /** @see AudioManager#getVibrateSetting(int) */
2774 public int getVibrateSetting(int vibrateType) {
Eric Laurentbffc3d12012-05-07 17:43:49 -07002775 if (!mHasVibrator) return AudioManager.VIBRATE_SETTING_OFF;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002776 return (mVibrateSetting >> (vibrateType * 2)) & 3;
2777 }
2778
2779 /** @see AudioManager#setVibrateSetting(int, int) */
2780 public void setVibrateSetting(int vibrateType, int vibrateSetting) {
2781
Eric Laurentbffc3d12012-05-07 17:43:49 -07002782 if (!mHasVibrator) return;
2783
John Spurlock61560172015-02-06 19:46:04 -05002784 mVibrateSetting = AudioSystem.getValueForVibrateSetting(mVibrateSetting, vibrateType,
2785 vibrateSetting);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002786
2787 // Broadcast change
2788 broadcastVibrateSetting(vibrateType);
2789
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002790 }
2791
Jean-Michel Trivi58850372018-09-14 16:01:28 -07002792 /*package*/ class SetModeDeathHandler implements IBinder.DeathRecipient {
Eric Laurent9272b4b2010-01-23 17:12:59 -08002793 private IBinder mCb; // To be notified of client's death
Marco Nelissenf1ddd512011-08-10 14:15:44 -07002794 private int mPid;
Eric Laurent9272b4b2010-01-23 17:12:59 -08002795 private int mMode = AudioSystem.MODE_NORMAL; // Current mode set by this client
2796
Eric Laurent9f103de2011-09-08 15:04:23 -07002797 SetModeDeathHandler(IBinder cb, int pid) {
Eric Laurent9272b4b2010-01-23 17:12:59 -08002798 mCb = cb;
Eric Laurent9f103de2011-09-08 15:04:23 -07002799 mPid = pid;
Eric Laurent9272b4b2010-01-23 17:12:59 -08002800 }
2801
2802 public void binderDied() {
Jack He89f97982018-05-02 19:10:56 -07002803 int oldModeOwnerPid = 0;
Eric Laurentd7454be2011-09-14 08:45:58 -07002804 int newModeOwnerPid = 0;
Jean-Michel Trivi58850372018-09-14 16:01:28 -07002805 synchronized (mDeviceBroker.mSetModeLock) {
Eric Laurent9272b4b2010-01-23 17:12:59 -08002806 Log.w(TAG, "setMode() client died");
Jack He89f97982018-05-02 19:10:56 -07002807 if (!mSetModeDeathHandlers.isEmpty()) {
2808 oldModeOwnerPid = mSetModeDeathHandlers.get(0).getPid();
2809 }
Eric Laurent9272b4b2010-01-23 17:12:59 -08002810 int index = mSetModeDeathHandlers.indexOf(this);
2811 if (index < 0) {
2812 Log.w(TAG, "unregistered setMode() client died");
2813 } else {
John Spurlock90874332015-03-10 16:00:54 -04002814 newModeOwnerPid = setModeInt(AudioSystem.MODE_NORMAL, mCb, mPid, TAG);
Eric Laurent9272b4b2010-01-23 17:12:59 -08002815 }
2816 }
Eric Laurent9f103de2011-09-08 15:04:23 -07002817 // when entering RINGTONE, IN_CALL or IN_COMMUNICATION mode, clear all
Jack He89f97982018-05-02 19:10:56 -07002818 // SCO connections not started by the application changing the mode when pid changes
2819 if ((newModeOwnerPid != oldModeOwnerPid) && (newModeOwnerPid != 0)) {
Jean-Michel Trivi58850372018-09-14 16:01:28 -07002820 mDeviceBroker.postDisconnectBluetoothSco(newModeOwnerPid);
Eric Laurent9f103de2011-09-08 15:04:23 -07002821 }
Eric Laurent9272b4b2010-01-23 17:12:59 -08002822 }
2823
Marco Nelissenf1ddd512011-08-10 14:15:44 -07002824 public int getPid() {
2825 return mPid;
2826 }
2827
Eric Laurent9272b4b2010-01-23 17:12:59 -08002828 public void setMode(int mode) {
2829 mMode = mode;
2830 }
2831
2832 public int getMode() {
2833 return mMode;
2834 }
2835
2836 public IBinder getBinder() {
2837 return mCb;
2838 }
2839 }
2840
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002841 /** @see AudioManager#setMode(int) */
John Spurlock90874332015-03-10 16:00:54 -04002842 public void setMode(int mode, IBinder cb, String callingPackage) {
2843 if (DEBUG_MODE) { Log.v(TAG, "setMode(mode=" + mode + ", callingPackage=" + callingPackage + ")"); }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002844 if (!checkAudioSettingsPermission("setMode()")) {
2845 return;
2846 }
Eric Laurenta553c252009-07-17 12:17:14 -07002847
Jean-Michel Triviccd654e2014-09-03 17:48:47 -07002848 if ( (mode == AudioSystem.MODE_IN_CALL) &&
2849 (mContext.checkCallingOrSelfPermission(
2850 android.Manifest.permission.MODIFY_PHONE_STATE)
2851 != PackageManager.PERMISSION_GRANTED)) {
2852 Log.w(TAG, "MODIFY_PHONE_STATE Permission Denial: setMode(MODE_IN_CALL) from pid="
2853 + Binder.getCallingPid() + ", uid=" + Binder.getCallingUid());
2854 return;
2855 }
2856
Jean-Michel Trivi8f677d62010-11-15 12:11:32 -08002857 if (mode < AudioSystem.MODE_CURRENT || mode >= AudioSystem.NUM_MODES) {
Eric Laurenta553c252009-07-17 12:17:14 -07002858 return;
2859 }
2860
Jack He89f97982018-05-02 19:10:56 -07002861 int oldModeOwnerPid = 0;
Eric Laurentd7454be2011-09-14 08:45:58 -07002862 int newModeOwnerPid = 0;
Jean-Michel Trivi58850372018-09-14 16:01:28 -07002863 synchronized (mDeviceBroker.mSetModeLock) {
Jack He89f97982018-05-02 19:10:56 -07002864 if (!mSetModeDeathHandlers.isEmpty()) {
2865 oldModeOwnerPid = mSetModeDeathHandlers.get(0).getPid();
2866 }
Eric Laurenta553c252009-07-17 12:17:14 -07002867 if (mode == AudioSystem.MODE_CURRENT) {
2868 mode = mMode;
2869 }
John Spurlock90874332015-03-10 16:00:54 -04002870 newModeOwnerPid = setModeInt(mode, cb, Binder.getCallingPid(), callingPackage);
Eric Laurent9f103de2011-09-08 15:04:23 -07002871 }
2872 // when entering RINGTONE, IN_CALL or IN_COMMUNICATION mode, clear all
Jack He89f97982018-05-02 19:10:56 -07002873 // SCO connections not started by the application changing the mode when pid changes
2874 if ((newModeOwnerPid != oldModeOwnerPid) && (newModeOwnerPid != 0)) {
Jean-Michel Trivi58850372018-09-14 16:01:28 -07002875 mDeviceBroker.postDisconnectBluetoothSco(newModeOwnerPid);
Eric Laurent9f103de2011-09-08 15:04:23 -07002876 }
2877 }
Jean-Michel Trivi2ade5762010-12-11 13:18:30 -08002878
Jean-Michel Trivi58850372018-09-14 16:01:28 -07002879 // must be called synchronized on mSetModeLock
Eric Laurentd7454be2011-09-14 08:45:58 -07002880 // setModeInt() returns a valid PID if the audio mode was successfully set to
Eric Laurent9f103de2011-09-08 15:04:23 -07002881 // any mode other than NORMAL.
John Spurlock90874332015-03-10 16:00:54 -04002882 private int setModeInt(int mode, IBinder cb, int pid, String caller) {
2883 if (DEBUG_MODE) { Log.v(TAG, "setModeInt(mode=" + mode + ", pid=" + pid + ", caller="
2884 + caller + ")"); }
Eric Laurentd7454be2011-09-14 08:45:58 -07002885 int newModeOwnerPid = 0;
Eric Laurent9f103de2011-09-08 15:04:23 -07002886 if (cb == null) {
2887 Log.e(TAG, "setModeInt() called with null binder");
Eric Laurentd7454be2011-09-14 08:45:58 -07002888 return newModeOwnerPid;
Eric Laurent9f103de2011-09-08 15:04:23 -07002889 }
Jean-Michel Trivi2ade5762010-12-11 13:18:30 -08002890
Eric Laurent9f103de2011-09-08 15:04:23 -07002891 SetModeDeathHandler hdlr = null;
2892 Iterator iter = mSetModeDeathHandlers.iterator();
2893 while (iter.hasNext()) {
2894 SetModeDeathHandler h = (SetModeDeathHandler)iter.next();
2895 if (h.getPid() == pid) {
2896 hdlr = h;
2897 // Remove from client list so that it is re-inserted at top of list
2898 iter.remove();
2899 hdlr.getBinder().unlinkToDeath(hdlr, 0);
2900 break;
2901 }
2902 }
2903 int status = AudioSystem.AUDIO_STATUS_OK;
Eric Laurent6afa6502017-09-28 15:18:19 -07002904 int actualMode;
Eric Laurent9f103de2011-09-08 15:04:23 -07002905 do {
Eric Laurent6afa6502017-09-28 15:18:19 -07002906 actualMode = mode;
Eric Laurent9f103de2011-09-08 15:04:23 -07002907 if (mode == AudioSystem.MODE_NORMAL) {
2908 // get new mode from client at top the list if any
2909 if (!mSetModeDeathHandlers.isEmpty()) {
2910 hdlr = mSetModeDeathHandlers.get(0);
2911 cb = hdlr.getBinder();
Eric Laurent6afa6502017-09-28 15:18:19 -07002912 actualMode = hdlr.getMode();
Jean-Michel Trivi339567d2014-07-29 09:53:34 -07002913 if (DEBUG_MODE) {
2914 Log.w(TAG, " using mode=" + mode + " instead due to death hdlr at pid="
2915 + hdlr.mPid);
2916 }
Eric Laurentb9c9d262009-05-06 08:13:20 -07002917 }
Eric Laurent9f103de2011-09-08 15:04:23 -07002918 } else {
2919 if (hdlr == null) {
2920 hdlr = new SetModeDeathHandler(cb, pid);
2921 }
2922 // Register for client death notification
2923 try {
2924 cb.linkToDeath(hdlr, 0);
2925 } catch (RemoteException e) {
2926 // Client has died!
2927 Log.w(TAG, "setMode() could not link to "+cb+" binder death");
2928 }
2929
2930 // Last client to call setMode() is always at top of client list
2931 // as required by SetModeDeathHandler.binderDied()
2932 mSetModeDeathHandlers.add(0, hdlr);
2933 hdlr.setMode(mode);
2934 }
2935
Eric Laurent6afa6502017-09-28 15:18:19 -07002936 if (actualMode != mMode) {
Eric Laurent66b69672018-01-26 18:30:51 -08002937 final long identity = Binder.clearCallingIdentity();
Eric Laurent6afa6502017-09-28 15:18:19 -07002938 status = AudioSystem.setPhoneState(actualMode);
Eric Laurent66b69672018-01-26 18:30:51 -08002939 Binder.restoreCallingIdentity(identity);
Eric Laurent9f103de2011-09-08 15:04:23 -07002940 if (status == AudioSystem.AUDIO_STATUS_OK) {
Eric Laurent6afa6502017-09-28 15:18:19 -07002941 if (DEBUG_MODE) { Log.v(TAG, " mode successfully set to " + actualMode); }
2942 mMode = actualMode;
Eric Laurent9f103de2011-09-08 15:04:23 -07002943 } else {
2944 if (hdlr != null) {
2945 mSetModeDeathHandlers.remove(hdlr);
2946 cb.unlinkToDeath(hdlr, 0);
2947 }
2948 // force reading new top of mSetModeDeathHandlers stack
Jean-Michel Trivi339567d2014-07-29 09:53:34 -07002949 if (DEBUG_MODE) { Log.w(TAG, " mode set to MODE_NORMAL after phoneState pb"); }
Eric Laurent9f103de2011-09-08 15:04:23 -07002950 mode = AudioSystem.MODE_NORMAL;
2951 }
2952 } else {
2953 status = AudioSystem.AUDIO_STATUS_OK;
2954 }
2955 } while (status != AudioSystem.AUDIO_STATUS_OK && !mSetModeDeathHandlers.isEmpty());
2956
2957 if (status == AudioSystem.AUDIO_STATUS_OK) {
Eric Laurent6afa6502017-09-28 15:18:19 -07002958 if (actualMode != AudioSystem.MODE_NORMAL) {
Eric Laurentd7454be2011-09-14 08:45:58 -07002959 if (mSetModeDeathHandlers.isEmpty()) {
2960 Log.e(TAG, "setMode() different from MODE_NORMAL with empty mode client stack");
2961 } else {
2962 newModeOwnerPid = mSetModeDeathHandlers.get(0).getPid();
2963 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002964 }
Eric Laurent6afa6502017-09-28 15:18:19 -07002965 // Note: newModeOwnerPid is always 0 when actualMode is MODE_NORMAL
2966 mModeLogger.log(
2967 new PhoneStateEvent(caller, pid, mode, newModeOwnerPid, actualMode));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002968 int streamType = getActiveStreamType(AudioManager.USE_DEFAULT_STREAM_TYPE);
Eric Laurent9bc8358d2011-11-18 16:43:31 -08002969 int device = getDeviceForStream(streamType);
Eric Laurent42b041e2013-03-29 11:36:03 -07002970 int index = mStreamStates[mStreamVolumeAlias[streamType]].getIndex(device);
John Spurlock90874332015-03-10 16:00:54 -04002971 setStreamVolumeInt(mStreamVolumeAlias[streamType], index, device, true, caller);
Eric Laurent6d517662012-04-23 18:42:39 -07002972
John Spurlock90874332015-03-10 16:00:54 -04002973 updateStreamVolumeAlias(true /*updateVolumes*/, caller);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002974 }
Eric Laurentd7454be2011-09-14 08:45:58 -07002975 return newModeOwnerPid;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002976 }
2977
2978 /** @see AudioManager#getMode() */
2979 public int getMode() {
2980 return mMode;
2981 }
2982
Eric Laurente78fced2013-03-15 16:03:47 -07002983 //==========================================================================================
2984 // Sound Effects
2985 //==========================================================================================
2986
2987 private static final String TAG_AUDIO_ASSETS = "audio_assets";
2988 private static final String ATTR_VERSION = "version";
2989 private static final String TAG_GROUP = "group";
2990 private static final String ATTR_GROUP_NAME = "name";
2991 private static final String TAG_ASSET = "asset";
2992 private static final String ATTR_ASSET_ID = "id";
2993 private static final String ATTR_ASSET_FILE = "file";
2994
2995 private static final String ASSET_FILE_VERSION = "1.0";
2996 private static final String GROUP_TOUCH_SOUNDS = "touch_sounds";
2997
Glenn Kasten167d1a22013-07-23 16:24:41 -07002998 private static final int SOUND_EFFECTS_LOAD_TIMEOUT_MS = 5000;
Eric Laurent5d3eb44a2013-03-21 15:35:10 -07002999
3000 class LoadSoundEffectReply {
3001 public int mStatus = 1;
3002 };
3003
Eric Laurente78fced2013-03-15 16:03:47 -07003004 private void loadTouchSoundAssetDefaults() {
3005 SOUND_EFFECT_FILES.add("Effect_Tick.ogg");
3006 for (int i = 0; i < AudioManager.NUM_SOUND_EFFECTS; i++) {
3007 SOUND_EFFECT_FILES_MAP[i][0] = 0;
3008 SOUND_EFFECT_FILES_MAP[i][1] = -1;
3009 }
3010 }
3011
3012 private void loadTouchSoundAssets() {
3013 XmlResourceParser parser = null;
3014
Eric Laurent5d3eb44a2013-03-21 15:35:10 -07003015 // only load assets once.
3016 if (!SOUND_EFFECT_FILES.isEmpty()) {
3017 return;
3018 }
3019
Eric Laurente78fced2013-03-15 16:03:47 -07003020 loadTouchSoundAssetDefaults();
3021
3022 try {
3023 parser = mContext.getResources().getXml(com.android.internal.R.xml.audio_assets);
3024
3025 XmlUtils.beginDocument(parser, TAG_AUDIO_ASSETS);
3026 String version = parser.getAttributeValue(null, ATTR_VERSION);
3027 boolean inTouchSoundsGroup = false;
3028
3029 if (ASSET_FILE_VERSION.equals(version)) {
3030 while (true) {
3031 XmlUtils.nextElement(parser);
3032 String element = parser.getName();
3033 if (element == null) {
3034 break;
3035 }
3036 if (element.equals(TAG_GROUP)) {
3037 String name = parser.getAttributeValue(null, ATTR_GROUP_NAME);
3038 if (GROUP_TOUCH_SOUNDS.equals(name)) {
3039 inTouchSoundsGroup = true;
3040 break;
3041 }
3042 }
3043 }
3044 while (inTouchSoundsGroup) {
3045 XmlUtils.nextElement(parser);
3046 String element = parser.getName();
3047 if (element == null) {
3048 break;
3049 }
3050 if (element.equals(TAG_ASSET)) {
3051 String id = parser.getAttributeValue(null, ATTR_ASSET_ID);
3052 String file = parser.getAttributeValue(null, ATTR_ASSET_FILE);
3053 int fx;
3054
3055 try {
3056 Field field = AudioManager.class.getField(id);
3057 fx = field.getInt(null);
3058 } catch (Exception e) {
3059 Log.w(TAG, "Invalid touch sound ID: "+id);
3060 continue;
3061 }
3062
3063 int i = SOUND_EFFECT_FILES.indexOf(file);
3064 if (i == -1) {
3065 i = SOUND_EFFECT_FILES.size();
3066 SOUND_EFFECT_FILES.add(file);
3067 }
3068 SOUND_EFFECT_FILES_MAP[fx][0] = i;
3069 } else {
3070 break;
3071 }
3072 }
3073 }
3074 } catch (Resources.NotFoundException e) {
3075 Log.w(TAG, "audio assets file not found", e);
3076 } catch (XmlPullParserException e) {
3077 Log.w(TAG, "XML parser exception reading touch sound assets", e);
3078 } catch (IOException e) {
3079 Log.w(TAG, "I/O exception reading touch sound assets", e);
3080 } finally {
3081 if (parser != null) {
3082 parser.close();
3083 }
3084 }
3085 }
3086
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003087 /** @see AudioManager#playSoundEffect(int) */
3088 public void playSoundEffect(int effectType) {
Eric Laurent5d3eb44a2013-03-21 15:35:10 -07003089 playSoundEffectVolume(effectType, -1.0f);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003090 }
3091
3092 /** @see AudioManager#playSoundEffect(int, float) */
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003093 public void playSoundEffectVolume(int effectType, float volume) {
Beverlyd6964762018-02-16 14:07:03 -05003094 // do not try to play the sound effect if the system stream is muted
3095 if (isStreamMutedByRingerOrZenMode(STREAM_SYSTEM)) {
3096 return;
3097 }
3098
Natalie Silvanovich559c76d2014-05-01 10:16:24 -07003099 if (effectType >= AudioManager.NUM_SOUND_EFFECTS || effectType < 0) {
3100 Log.w(TAG, "AudioService effectType value " + effectType + " out of range");
3101 return;
3102 }
3103
Eric Laurent5d3eb44a2013-03-21 15:35:10 -07003104 sendMsg(mAudioHandler, MSG_PLAY_SOUND_EFFECT, SENDMSG_QUEUE,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003105 effectType, (int) (volume * 1000), null, 0);
3106 }
3107
3108 /**
3109 * Loads samples into the soundpool.
Glenn Kasten5c17a822011-11-30 09:41:01 -08003110 * This method must be called at first when sound effects are enabled
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003111 */
3112 public boolean loadSoundEffects() {
Eric Laurent5d3eb44a2013-03-21 15:35:10 -07003113 int attempts = 3;
3114 LoadSoundEffectReply reply = new LoadSoundEffectReply();
Eric Laurenta60e2122010-12-28 16:49:07 -08003115
Eric Laurent5d3eb44a2013-03-21 15:35:10 -07003116 synchronized (reply) {
3117 sendMsg(mAudioHandler, MSG_LOAD_SOUND_EFFECTS, SENDMSG_QUEUE, 0, 0, reply, 0);
3118 while ((reply.mStatus == 1) && (attempts-- > 0)) {
Eric Laurent117b7bb2011-01-16 17:07:27 -08003119 try {
Glenn Kasten167d1a22013-07-23 16:24:41 -07003120 reply.wait(SOUND_EFFECTS_LOAD_TIMEOUT_MS);
Eric Laurent5d3eb44a2013-03-21 15:35:10 -07003121 } catch (InterruptedException e) {
3122 Log.w(TAG, "loadSoundEffects Interrupted while waiting sound pool loaded.");
Eric Laurent117b7bb2011-01-16 17:07:27 -08003123 }
Eric Laurenta60e2122010-12-28 16:49:07 -08003124 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003125 }
Eric Laurent5d3eb44a2013-03-21 15:35:10 -07003126 return (reply.mStatus == 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003127 }
3128
3129 /**
3130 * Unloads samples from the sound pool.
3131 * This method can be called to free some memory when
3132 * sound effects are disabled.
3133 */
3134 public void unloadSoundEffects() {
Eric Laurent5d3eb44a2013-03-21 15:35:10 -07003135 sendMsg(mAudioHandler, MSG_UNLOAD_SOUND_EFFECTS, SENDMSG_QUEUE, 0, 0, null, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003136 }
3137
Eric Laurenta60e2122010-12-28 16:49:07 -08003138 class SoundPoolListenerThread extends Thread {
3139 public SoundPoolListenerThread() {
3140 super("SoundPoolListenerThread");
3141 }
3142
3143 @Override
3144 public void run() {
3145
3146 Looper.prepare();
3147 mSoundPoolLooper = Looper.myLooper();
3148
3149 synchronized (mSoundEffectsLock) {
3150 if (mSoundPool != null) {
3151 mSoundPoolCallBack = new SoundPoolCallback();
3152 mSoundPool.setOnLoadCompleteListener(mSoundPoolCallBack);
3153 }
3154 mSoundEffectsLock.notify();
3155 }
3156 Looper.loop();
3157 }
3158 }
3159
3160 private final class SoundPoolCallback implements
3161 android.media.SoundPool.OnLoadCompleteListener {
3162
Eric Laurent5d3eb44a2013-03-21 15:35:10 -07003163 int mStatus = 1; // 1 means neither error nor last sample loaded yet
3164 List<Integer> mSamples = new ArrayList<Integer>();
Eric Laurenta60e2122010-12-28 16:49:07 -08003165
3166 public int status() {
3167 return mStatus;
3168 }
3169
Eric Laurent5d3eb44a2013-03-21 15:35:10 -07003170 public void setSamples(int[] samples) {
3171 for (int i = 0; i < samples.length; i++) {
3172 // do not wait ack for samples rejected upfront by SoundPool
3173 if (samples[i] > 0) {
3174 mSamples.add(samples[i]);
3175 }
3176 }
Eric Laurenta60e2122010-12-28 16:49:07 -08003177 }
3178
3179 public void onLoadComplete(SoundPool soundPool, int sampleId, int status) {
3180 synchronized (mSoundEffectsLock) {
Eric Laurent5d3eb44a2013-03-21 15:35:10 -07003181 int i = mSamples.indexOf(sampleId);
3182 if (i >= 0) {
3183 mSamples.remove(i);
Eric Laurenta60e2122010-12-28 16:49:07 -08003184 }
Eric Laurent5d3eb44a2013-03-21 15:35:10 -07003185 if ((status != 0) || mSamples. isEmpty()) {
3186 mStatus = status;
Eric Laurenta60e2122010-12-28 16:49:07 -08003187 mSoundEffectsLock.notify();
3188 }
3189 }
3190 }
3191 }
3192
Eric Laurent4050c932009-07-08 02:52:14 -07003193 /** @see AudioManager#reloadAudioSettings() */
3194 public void reloadAudioSettings() {
Eric Laurentbc0fab1f2012-09-19 11:24:41 -07003195 readAudioSettings(false /*userSwitch*/);
3196 }
3197
3198 private void readAudioSettings(boolean userSwitch) {
Eric Laurent4050c932009-07-08 02:52:14 -07003199 // restore ringer mode, ringer mode affected streams, mute affected streams and vibrate settings
3200 readPersistedSettings();
Eric Laurentc0232482016-03-15 18:19:23 -07003201 readUserRestrictions();
Eric Laurent4050c932009-07-08 02:52:14 -07003202
3203 // restore volume settings
3204 int numStreamTypes = AudioSystem.getNumStreamTypes();
3205 for (int streamType = 0; streamType < numStreamTypes; streamType++) {
3206 VolumeStreamState streamState = mStreamStates[streamType];
3207
Eric Laurentbc0fab1f2012-09-19 11:24:41 -07003208 if (userSwitch && mStreamVolumeAlias[streamType] == AudioSystem.STREAM_MUSIC) {
3209 continue;
3210 }
3211
Eric Laurent8fa4d6f2014-10-30 14:13:03 -07003212 streamState.readSettings();
3213 synchronized (VolumeStreamState.class) {
Eric Laurent3172d5e2012-05-09 11:38:16 -07003214 // unmute stream that was muted but is not affect by mute anymore
RoboErik4197cb62015-01-21 15:45:32 -08003215 if (streamState.mIsMuted && ((!isStreamAffectedByMute(streamType) &&
Beverlyd6964762018-02-16 14:07:03 -05003216 !isStreamMutedByRingerOrZenMode(streamType)) || mUseFixedVolume)) {
RoboErik4197cb62015-01-21 15:45:32 -08003217 streamState.mIsMuted = false;
Eric Laurent4050c932009-07-08 02:52:14 -07003218 }
Eric Laurent4050c932009-07-08 02:52:14 -07003219 }
3220 }
3221
Eric Laurent33902db2012-10-07 16:15:07 -07003222 // apply new ringer mode before checking volume for alias streams so that streams
3223 // muted by ringer mode have the correct volume
John Spurlock661f2cf2014-11-17 10:29:10 -05003224 setRingerModeInt(getRingerModeInternal(), false);
Eric Laurent33902db2012-10-07 16:15:07 -07003225
Eric Laurent212532b2014-07-21 15:43:18 -07003226 checkAllFixedVolumeDevices();
Eric Laurent24482012012-05-10 09:41:17 -07003227 checkAllAliasStreamVolumes();
John Spurlockb6e19e32015-03-10 21:33:44 -04003228 checkMuteAffectedStreams();
Eric Laurent24482012012-05-10 09:41:17 -07003229
hyomin.ohd0446dc2018-10-18 13:58:27 +09003230 synchronized (mSafeMediaVolumeStateLock) {
John Spurlockaa5ee4d2014-07-25 13:05:12 -04003231 mMusicActiveMs = MathUtils.constrain(Settings.Secure.getIntForUser(mContentResolver,
3232 Settings.Secure.UNSAFE_VOLUME_MUSIC_ACTIVE_MS, 0, UserHandle.USER_CURRENT),
3233 0, UNSAFE_VOLUME_MUSIC_ACTIVE_MS_MAX);
Eric Laurentd640bd32012-09-28 18:01:48 -07003234 if (mSafeMediaVolumeState == SAFE_MEDIA_VOLUME_ACTIVE) {
John Spurlock90874332015-03-10 16:00:54 -04003235 enforceSafeMediaVolume(TAG);
Eric Laurentf1a457d2012-09-20 16:27:23 -07003236 }
Eric Laurentc34dcc12012-09-10 13:51:52 -07003237 }
Eric Laurent4050c932009-07-08 02:52:14 -07003238 }
3239
Dianne Hackborn961cae92013-03-20 14:59:43 -07003240 /** @see AudioManager#setSpeakerphoneOn(boolean) */
Eric Laurentc42ac9d2009-07-29 08:53:03 -07003241 public void setSpeakerphoneOn(boolean on){
Eric Laurentdc1d17a2009-09-10 00:48:21 -07003242 if (!checkAudioSettingsPermission("setSpeakerphoneOn()")) {
3243 return;
3244 }
JW Kwon6e144772018-10-04 17:39:29 +09003245
3246 if (mContext.checkCallingOrSelfPermission(
3247 android.Manifest.permission.MODIFY_PHONE_STATE)
3248 != PackageManager.PERMISSION_GRANTED) {
3249 synchronized (mSetModeDeathHandlers) {
3250 for (SetModeDeathHandler h : mSetModeDeathHandlers) {
3251 if (h.getMode() == AudioSystem.MODE_IN_CALL) {
3252 Log.w(TAG, "getMode is call, Permission Denial: setSpeakerphoneOn from pid="
3253 + Binder.getCallingPid() + ", uid=" + Binder.getCallingUid());
3254 return;
3255 }
3256 }
3257 }
3258 }
3259
Jean-Michel Trivi011f39e2017-08-19 18:08:06 -07003260 // for logging only
3261 final String eventSource = new StringBuilder("setSpeakerphoneOn(").append(on)
3262 .append(") from u/pid:").append(Binder.getCallingUid()).append("/")
3263 .append(Binder.getCallingPid()).toString();
Jean-Michel Trivi58850372018-09-14 16:01:28 -07003264 mDeviceBroker.setSpeakerphoneOn(on, eventSource);
Eric Laurentc42ac9d2009-07-29 08:53:03 -07003265 }
3266
3267 /** @see AudioManager#isSpeakerphoneOn() */
3268 public boolean isSpeakerphoneOn() {
Jean-Michel Trivi58850372018-09-14 16:01:28 -07003269 return mDeviceBroker.isSpeakerphoneOn();
Eric Laurentc42ac9d2009-07-29 08:53:03 -07003270 }
3271
Dianne Hackborn961cae92013-03-20 14:59:43 -07003272 /** @see AudioManager#setBluetoothScoOn(boolean) */
Eric Laurent48221252015-09-24 18:41:48 -07003273 public void setBluetoothScoOn(boolean on) {
Eric Laurentdc1d17a2009-09-10 00:48:21 -07003274 if (!checkAudioSettingsPermission("setBluetoothScoOn()")) {
3275 return;
3276 }
Sharad Sangle1d188442017-05-09 16:05:40 +05303277
3278 // Only enable calls from system components
Vitor Albuquerquec3bb48c2018-03-07 10:39:59 -03003279 if (UserHandle.getCallingAppId() >= FIRST_APPLICATION_UID) {
Jean-Michel Trivi58850372018-09-14 16:01:28 -07003280 mDeviceBroker.setBluetoothScoOnByApp(on);
Sharad Sangle1d188442017-05-09 16:05:40 +05303281 return;
3282 }
3283
Jean-Michel Trivi011f39e2017-08-19 18:08:06 -07003284 // for logging only
3285 final String eventSource = new StringBuilder("setBluetoothScoOn(").append(on)
3286 .append(") from u/pid:").append(Binder.getCallingUid()).append("/")
3287 .append(Binder.getCallingPid()).toString();
Jean-Michel Trivi58850372018-09-14 16:01:28 -07003288
3289 mDeviceBroker.setBluetoothScoOn(on, eventSource);
Eric Laurent48221252015-09-24 18:41:48 -07003290 }
Johan Gustavsson7337bee2013-03-01 15:53:30 +01003291
Jean-Michel Trivi58850372018-09-14 16:01:28 -07003292 /** @see AudioManager#isBluetoothScoOn()
3293 * Note that it doesn't report internal state, but state seen by apps (which may have
3294 * called setBluetoothScoOn() */
Eric Laurentc42ac9d2009-07-29 08:53:03 -07003295 public boolean isBluetoothScoOn() {
Jean-Michel Trivi58850372018-09-14 16:01:28 -07003296 return mDeviceBroker.isBluetoothScoOnForApp();
Eric Laurentc42ac9d2009-07-29 08:53:03 -07003297 }
3298
Jean-Michel Trivi58850372018-09-14 16:01:28 -07003299 // TODO investigate internal users due to deprecation of SDK API
Sungsoocf09fe62016-09-28 16:21:48 +09003300 /** @see AudioManager#setBluetoothA2dpOn(boolean) */
Eric Laurent78472112012-05-21 08:57:21 -07003301 public void setBluetoothA2dpOn(boolean on) {
Jean-Michel Trivi011f39e2017-08-19 18:08:06 -07003302 // for logging only
3303 final String eventSource = new StringBuilder("setBluetoothA2dpOn(").append(on)
3304 .append(") from u/pid:").append(Binder.getCallingUid()).append("/")
3305 .append(Binder.getCallingPid()).toString();
Jean-Michel Trivi58850372018-09-14 16:01:28 -07003306 mDeviceBroker.setBluetoothA2dpOn_Async(on, eventSource);
Eric Laurent78472112012-05-21 08:57:21 -07003307 }
3308
Sungsoocf09fe62016-09-28 16:21:48 +09003309 /** @see AudioManager#isBluetoothA2dpOn() */
Eric Laurent78472112012-05-21 08:57:21 -07003310 public boolean isBluetoothA2dpOn() {
Jean-Michel Trivi58850372018-09-14 16:01:28 -07003311 return mDeviceBroker.isBluetoothA2dpOn();
Eric Laurent78472112012-05-21 08:57:21 -07003312 }
3313
Eric Laurent3def1ee2010-03-17 23:26:26 -07003314 /** @see AudioManager#startBluetoothSco() */
Eric Laurent83900752014-05-15 15:14:22 -07003315 public void startBluetoothSco(IBinder cb, int targetSdkVersion) {
Jean-Michel Trivi58850372018-09-14 16:01:28 -07003316 final int scoAudioMode =
Eric Laurent83900752014-05-15 15:14:22 -07003317 (targetSdkVersion < Build.VERSION_CODES.JELLY_BEAN_MR2) ?
Jean-Michel Trivi58850372018-09-14 16:01:28 -07003318 BtHelper.SCO_MODE_VIRTUAL_CALL : BtHelper.SCO_MODE_UNDEFINED;
3319 final String eventSource = new StringBuilder("startBluetoothSco()")
3320 .append(") from u/pid:").append(Binder.getCallingUid()).append("/")
3321 .append(Binder.getCallingPid()).toString();
3322 startBluetoothScoInt(cb, scoAudioMode, eventSource);
Eric Laurent83900752014-05-15 15:14:22 -07003323 }
3324
3325 /** @see AudioManager#startBluetoothScoVirtualCall() */
3326 public void startBluetoothScoVirtualCall(IBinder cb) {
Jean-Michel Trivi58850372018-09-14 16:01:28 -07003327 final String eventSource = new StringBuilder("startBluetoothScoVirtualCall()")
3328 .append(") from u/pid:").append(Binder.getCallingUid()).append("/")
3329 .append(Binder.getCallingPid()).toString();
3330 startBluetoothScoInt(cb, BtHelper.SCO_MODE_VIRTUAL_CALL, eventSource);
Eric Laurent83900752014-05-15 15:14:22 -07003331 }
3332
Jean-Michel Trivi58850372018-09-14 16:01:28 -07003333 void startBluetoothScoInt(IBinder cb, int scoAudioMode, @NonNull String eventSource) {
Eric Laurentdc03c612011-04-01 10:59:41 -07003334 if (!checkAudioSettingsPermission("startBluetoothSco()") ||
Eric Laurent4a5eeb92014-05-06 10:49:04 -07003335 !mSystemReady) {
Eric Laurent3def1ee2010-03-17 23:26:26 -07003336 return;
3337 }
Jean-Michel Trivi58850372018-09-14 16:01:28 -07003338 mDeviceBroker.startBluetoothScoForClient_Sync(cb, scoAudioMode, eventSource);
Eric Laurent3def1ee2010-03-17 23:26:26 -07003339 }
3340
3341 /** @see AudioManager#stopBluetoothSco() */
3342 public void stopBluetoothSco(IBinder cb){
Eric Laurentdc03c612011-04-01 10:59:41 -07003343 if (!checkAudioSettingsPermission("stopBluetoothSco()") ||
Eric Laurent4a5eeb92014-05-06 10:49:04 -07003344 !mSystemReady) {
Eric Laurent3def1ee2010-03-17 23:26:26 -07003345 return;
3346 }
Jean-Michel Trivi58850372018-09-14 16:01:28 -07003347 final String eventSource = new StringBuilder("stopBluetoothSco()")
3348 .append(") from u/pid:").append(Binder.getCallingUid()).append("/")
3349 .append(Binder.getCallingPid()).toString();
3350 mDeviceBroker.stopBluetoothScoForClient_Sync(cb, eventSource);
Eric Laurent3def1ee2010-03-17 23:26:26 -07003351 }
3352
Eric Laurent78472112012-05-21 08:57:21 -07003353
Jean-Michel Trivi58850372018-09-14 16:01:28 -07003354 /*package*/ ContentResolver getContentResolver() {
3355 return mContentResolver;
Jakub Pawlowskif9570f32018-02-21 17:15:12 -08003356 }
3357
John Spurlock90874332015-03-10 16:00:54 -04003358 private void onCheckMusicActive(String caller) {
hyomin.ohd0446dc2018-10-18 13:58:27 +09003359 synchronized (mSafeMediaVolumeStateLock) {
Eric Laurentd640bd32012-09-28 18:01:48 -07003360 if (mSafeMediaVolumeState == SAFE_MEDIA_VOLUME_INACTIVE) {
Eric Laurentc34dcc12012-09-10 13:51:52 -07003361 int device = getDeviceForStream(AudioSystem.STREAM_MUSIC);
3362
3363 if ((device & mSafeMediaVolumeDevices) != 0) {
3364 sendMsg(mAudioHandler,
3365 MSG_CHECK_MUSIC_ACTIVE,
3366 SENDMSG_REPLACE,
Eric Laurentf1a457d2012-09-20 16:27:23 -07003367 0,
Eric Laurentc34dcc12012-09-10 13:51:52 -07003368 0,
John Spurlock90874332015-03-10 16:00:54 -04003369 caller,
Eric Laurentc34dcc12012-09-10 13:51:52 -07003370 MUSIC_ACTIVE_POLL_PERIOD_MS);
Eric Laurent42b041e2013-03-29 11:36:03 -07003371 int index = mStreamStates[AudioSystem.STREAM_MUSIC].getIndex(device);
Jean-Michel Trivi58850372018-09-14 16:01:28 -07003372 if (AudioSystem.isStreamActive(AudioSystem.STREAM_MUSIC, 0)
3373 && (index > safeMediaVolumeIndex(device))) {
Eric Laurentc34dcc12012-09-10 13:51:52 -07003374 // Approximate cumulative active music time
3375 mMusicActiveMs += MUSIC_ACTIVE_POLL_PERIOD_MS;
3376 if (mMusicActiveMs > UNSAFE_VOLUME_MUSIC_ACTIVE_MS_MAX) {
John Spurlock90874332015-03-10 16:00:54 -04003377 setSafeMediaVolumeEnabled(true, caller);
Eric Laurentc34dcc12012-09-10 13:51:52 -07003378 mMusicActiveMs = 0;
Eric Laurentc34dcc12012-09-10 13:51:52 -07003379 }
John Spurlockaa5ee4d2014-07-25 13:05:12 -04003380 saveMusicActiveMs();
Eric Laurentc34dcc12012-09-10 13:51:52 -07003381 }
3382 }
3383 }
3384 }
3385 }
3386
John Spurlockaa5ee4d2014-07-25 13:05:12 -04003387 private void saveMusicActiveMs() {
3388 mAudioHandler.obtainMessage(MSG_PERSIST_MUSIC_ACTIVE_MS, mMusicActiveMs, 0).sendToTarget();
3389 }
3390
Jean-Michel Trivi58850372018-09-14 16:01:28 -07003391 private int getSafeUsbMediaVolumeIndex() {
Eric Laurenteab40d12017-06-09 12:45:21 -07003392 // determine UI volume index corresponding to the wanted safe gain in dBFS
3393 int min = MIN_STREAM_VOLUME[AudioSystem.STREAM_MUSIC];
3394 int max = MAX_STREAM_VOLUME[AudioSystem.STREAM_MUSIC];
3395
John Muir8b8bddd2018-02-16 14:29:14 -08003396 mSafeUsbMediaVolumeDbfs = mContext.getResources().getInteger(
3397 com.android.internal.R.integer.config_safe_media_volume_usb_mB) / 100.0f;
3398
Jean-Michel Trivi58850372018-09-14 16:01:28 -07003399 while (Math.abs(max - min) > 1) {
Eric Laurenteab40d12017-06-09 12:45:21 -07003400 int index = (max + min) / 2;
3401 float gainDB = AudioSystem.getStreamVolumeDB(
3402 AudioSystem.STREAM_MUSIC, index, AudioSystem.DEVICE_OUT_USB_HEADSET);
Eric Laurentb378a13a2017-07-11 14:08:11 -07003403 if (Float.isNaN(gainDB)) {
Eric Laurenteab40d12017-06-09 12:45:21 -07003404 //keep last min in case of read error
3405 break;
John Muir8b8bddd2018-02-16 14:29:14 -08003406 } else if (gainDB == mSafeUsbMediaVolumeDbfs) {
Eric Laurenteab40d12017-06-09 12:45:21 -07003407 min = index;
3408 break;
John Muir8b8bddd2018-02-16 14:29:14 -08003409 } else if (gainDB < mSafeUsbMediaVolumeDbfs) {
Eric Laurenteab40d12017-06-09 12:45:21 -07003410 min = index;
3411 } else {
3412 max = index;
3413 }
3414 }
3415 return min * 10;
3416 }
3417
John Spurlock90874332015-03-10 16:00:54 -04003418 private void onConfigureSafeVolume(boolean force, String caller) {
hyomin.ohd0446dc2018-10-18 13:58:27 +09003419 synchronized (mSafeMediaVolumeStateLock) {
Eric Laurentd640bd32012-09-28 18:01:48 -07003420 int mcc = mContext.getResources().getConfiguration().mcc;
3421 if ((mMcc != mcc) || ((mMcc == 0) && force)) {
3422 mSafeMediaVolumeIndex = mContext.getResources().getInteger(
3423 com.android.internal.R.integer.config_safe_media_volume_index) * 10;
Eric Laurenteab40d12017-06-09 12:45:21 -07003424
3425 mSafeUsbMediaVolumeIndex = getSafeUsbMediaVolumeIndex();
3426
John Spurlock35134602014-07-24 18:10:48 -04003427 boolean safeMediaVolumeEnabled =
3428 SystemProperties.getBoolean("audio.safemedia.force", false)
3429 || mContext.getResources().getBoolean(
3430 com.android.internal.R.bool.config_safe_media_volume_enabled);
Eric Laurent05274f32012-11-29 12:48:18 -08003431
Ricardo Garcia3a30a762015-06-23 15:54:45 -07003432 boolean safeMediaVolumeBypass =
3433 SystemProperties.getBoolean("audio.safemedia.bypass", false);
3434
Eric Laurent05274f32012-11-29 12:48:18 -08003435 // The persisted state is either "disabled" or "active": this is the state applied
3436 // next time we boot and cannot be "inactive"
3437 int persistedState;
Ricardo Garcia3a30a762015-06-23 15:54:45 -07003438 if (safeMediaVolumeEnabled && !safeMediaVolumeBypass) {
Eric Laurent05274f32012-11-29 12:48:18 -08003439 persistedState = SAFE_MEDIA_VOLUME_ACTIVE;
3440 // The state can already be "inactive" here if the user has forced it before
3441 // the 30 seconds timeout for forced configuration. In this case we don't reset
3442 // it to "active".
3443 if (mSafeMediaVolumeState != SAFE_MEDIA_VOLUME_INACTIVE) {
John Spurlockaa5ee4d2014-07-25 13:05:12 -04003444 if (mMusicActiveMs == 0) {
3445 mSafeMediaVolumeState = SAFE_MEDIA_VOLUME_ACTIVE;
John Spurlock90874332015-03-10 16:00:54 -04003446 enforceSafeMediaVolume(caller);
John Spurlockaa5ee4d2014-07-25 13:05:12 -04003447 } else {
3448 // We have existing playback time recorded, already confirmed.
3449 mSafeMediaVolumeState = SAFE_MEDIA_VOLUME_INACTIVE;
3450 }
Eric Laurent05274f32012-11-29 12:48:18 -08003451 }
Eric Laurentd640bd32012-09-28 18:01:48 -07003452 } else {
Eric Laurent05274f32012-11-29 12:48:18 -08003453 persistedState = SAFE_MEDIA_VOLUME_DISABLED;
Eric Laurentd640bd32012-09-28 18:01:48 -07003454 mSafeMediaVolumeState = SAFE_MEDIA_VOLUME_DISABLED;
3455 }
3456 mMcc = mcc;
Eric Laurent05274f32012-11-29 12:48:18 -08003457 sendMsg(mAudioHandler,
3458 MSG_PERSIST_SAFE_VOLUME_STATE,
3459 SENDMSG_QUEUE,
3460 persistedState,
3461 0,
3462 null,
3463 0);
Eric Laurentd640bd32012-09-28 18:01:48 -07003464 }
3465 }
3466 }
3467
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003468 ///////////////////////////////////////////////////////////////////////////
3469 // Internal methods
3470 ///////////////////////////////////////////////////////////////////////////
3471
3472 /**
3473 * Checks if the adjustment should change ringer mode instead of just
3474 * adjusting volume. If so, this will set the proper ringer mode and volume
3475 * indices on the stream states.
3476 */
Julia Reynoldsed783792016-04-08 15:27:35 -04003477 private int checkForRingerModeChange(int oldIndex, int direction, int step, boolean isMuted,
3478 String caller, int flags) {
John Spurlocka11b4af2014-06-01 11:52:23 -04003479 int result = FLAG_ADJUST_VOLUME;
Zak Cohen47798292017-11-30 12:34:20 -08003480 if (isPlatformTelevision() || mIsSingleVolume) {
Hank Freund21003f62015-12-08 09:05:46 -08003481 return result;
3482 }
3483
John Spurlock661f2cf2014-11-17 10:29:10 -05003484 int ringerMode = getRingerModeInternal();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003485
Eric Laurentbffc3d12012-05-07 17:43:49 -07003486 switch (ringerMode) {
3487 case RINGER_MODE_NORMAL:
3488 if (direction == AudioManager.ADJUST_LOWER) {
3489 if (mHasVibrator) {
Eric Laurent24482012012-05-10 09:41:17 -07003490 // "step" is the delta in internal index units corresponding to a
3491 // change of 1 in UI index units.
3492 // Because of rounding when rescaling from one stream index range to its alias
3493 // index range, we cannot simply test oldIndex == step:
3494 // (step <= oldIndex < 2 * step) is equivalent to: (old UI index == 1)
3495 if (step <= oldIndex && oldIndex < 2 * step) {
Eric Laurentbffc3d12012-05-07 17:43:49 -07003496 ringerMode = RINGER_MODE_VIBRATE;
John Spurlock07e72432015-03-13 11:46:52 -04003497 mLoweredFromNormalToVibrateTime = SystemClock.uptimeMillis();
Eric Laurentbffc3d12012-05-07 17:43:49 -07003498 }
3499 } else {
John Spurlockd9c75db2015-04-28 11:19:13 -04003500 if (oldIndex == step && mVolumePolicy.volumeDownToEnterSilent) {
Eric Laurentbffc3d12012-05-07 17:43:49 -07003501 ringerMode = RINGER_MODE_SILENT;
3502 }
Eric Laurent3d4c06f2011-08-15 19:58:28 -07003503 }
Muyuan Li1ed6df62016-06-18 11:16:52 -07003504 } else if (mIsSingleVolume && (direction == AudioManager.ADJUST_TOGGLE_MUTE
John Spurlocka48d7792015-03-03 17:35:57 -05003505 || direction == AudioManager.ADJUST_MUTE)) {
RoboErik5452e252015-02-06 15:33:53 -08003506 if (mHasVibrator) {
3507 ringerMode = RINGER_MODE_VIBRATE;
3508 } else {
3509 ringerMode = RINGER_MODE_SILENT;
3510 }
3511 // Setting the ringer mode will toggle mute
3512 result &= ~FLAG_ADJUST_VOLUME;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003513 }
Eric Laurentbffc3d12012-05-07 17:43:49 -07003514 break;
3515 case RINGER_MODE_VIBRATE:
3516 if (!mHasVibrator) {
3517 Log.e(TAG, "checkForRingerModeChange() current ringer mode is vibrate" +
3518 "but no vibrator is present");
3519 break;
3520 }
Amith Yamasanic696a532011-10-28 17:02:37 -07003521 if ((direction == AudioManager.ADJUST_LOWER)) {
RoboErik5452e252015-02-06 15:33:53 -08003522 // This is the case we were muted with the volume turned up
Muyuan Li1ed6df62016-06-18 11:16:52 -07003523 if (mIsSingleVolume && oldIndex >= 2 * step && isMuted) {
RoboErik5452e252015-02-06 15:33:53 -08003524 ringerMode = RINGER_MODE_NORMAL;
3525 } else if (mPrevVolDirection != AudioManager.ADJUST_LOWER) {
John Spurlocka48d7792015-03-03 17:35:57 -05003526 if (mVolumePolicy.volumeDownToEnterSilent) {
John Spurlock07e72432015-03-13 11:46:52 -04003527 final long diff = SystemClock.uptimeMillis()
3528 - mLoweredFromNormalToVibrateTime;
John Spurlockd9c75db2015-04-28 11:19:13 -04003529 if (diff > mVolumePolicy.vibrateToSilentDebounce
3530 && mRingerModeDelegate.canVolumeDownEnterSilent()) {
John Spurlock07e72432015-03-13 11:46:52 -04003531 ringerMode = RINGER_MODE_SILENT;
3532 }
John Spurlock795a5142014-12-08 14:09:35 -05003533 } else {
3534 result |= AudioManager.FLAG_SHOW_VIBRATE_HINT;
3535 }
Amith Yamasanic696a532011-10-28 17:02:37 -07003536 }
RoboErik5452e252015-02-06 15:33:53 -08003537 } else if (direction == AudioManager.ADJUST_RAISE
3538 || direction == AudioManager.ADJUST_TOGGLE_MUTE
3539 || direction == AudioManager.ADJUST_UNMUTE) {
Eric Laurentbffc3d12012-05-07 17:43:49 -07003540 ringerMode = RINGER_MODE_NORMAL;
Amith Yamasanic696a532011-10-28 17:02:37 -07003541 }
John Spurlocka11b4af2014-06-01 11:52:23 -04003542 result &= ~FLAG_ADJUST_VOLUME;
Eric Laurentbffc3d12012-05-07 17:43:49 -07003543 break;
3544 case RINGER_MODE_SILENT:
Muyuan Li1ed6df62016-06-18 11:16:52 -07003545 if (mIsSingleVolume && direction == AudioManager.ADJUST_LOWER && oldIndex >= 2 * step && isMuted) {
RoboErik5452e252015-02-06 15:33:53 -08003546 // This is the case we were muted with the volume turned up
3547 ringerMode = RINGER_MODE_NORMAL;
3548 } else if (direction == AudioManager.ADJUST_RAISE
3549 || direction == AudioManager.ADJUST_TOGGLE_MUTE
3550 || direction == AudioManager.ADJUST_UNMUTE) {
John Spurlocka48d7792015-03-03 17:35:57 -05003551 if (!mVolumePolicy.volumeUpToExitSilent) {
John Spurlocka11b4af2014-06-01 11:52:23 -04003552 result |= AudioManager.FLAG_SHOW_SILENT_HINT;
Eric Laurentbffc3d12012-05-07 17:43:49 -07003553 } else {
RoboErik5452e252015-02-06 15:33:53 -08003554 if (mHasVibrator && direction == AudioManager.ADJUST_RAISE) {
John Spurlocka11b4af2014-06-01 11:52:23 -04003555 ringerMode = RINGER_MODE_VIBRATE;
3556 } else {
RoboErik5452e252015-02-06 15:33:53 -08003557 // If we don't have a vibrator or they were toggling mute
3558 // go straight back to normal.
John Spurlocka11b4af2014-06-01 11:52:23 -04003559 ringerMode = RINGER_MODE_NORMAL;
3560 }
Eric Laurentbffc3d12012-05-07 17:43:49 -07003561 }
Daniel Sandler6329bf72010-02-26 15:17:44 -05003562 }
John Spurlocka11b4af2014-06-01 11:52:23 -04003563 result &= ~FLAG_ADJUST_VOLUME;
Eric Laurentbffc3d12012-05-07 17:43:49 -07003564 break;
3565 default:
3566 Log.e(TAG, "checkForRingerModeChange() wrong ringer mode: "+ringerMode);
3567 break;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003568 }
3569
Julia Reynoldsed783792016-04-08 15:27:35 -04003570 if (isAndroidNPlus(caller) && wouldToggleZenMode(ringerMode)
3571 && !mNm.isNotificationPolicyAccessGrantedForPackage(caller)
3572 && (flags & AudioManager.FLAG_FROM_KEY) == 0) {
3573 throw new SecurityException("Not allowed to change Do Not Disturb state");
3574 }
3575
John Spurlock661f2cf2014-11-17 10:29:10 -05003576 setRingerMode(ringerMode, TAG + ".checkForRingerModeChange", false /*external*/);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003577
Eric Laurent25101b02011-02-02 09:33:30 -08003578 mPrevVolDirection = direction;
3579
John Spurlocka11b4af2014-06-01 11:52:23 -04003580 return result;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003581 }
3582
John Spurlock3346a802014-05-20 16:25:37 -04003583 @Override
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003584 public boolean isStreamAffectedByRingerMode(int streamType) {
Eric Laurent9bcf4012009-06-12 06:09:28 -07003585 return (mRingerModeAffectedStreams & (1 << streamType)) != 0;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003586 }
3587
Beverlyd6964762018-02-16 14:07:03 -05003588 private boolean shouldZenMuteStream(int streamType) {
3589 if (mNm.getZenMode() != Settings.Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS) {
3590 return false;
3591 }
3592
Beverlyff2df9b2018-10-10 16:54:10 -04003593 NotificationManager.Policy zenPolicy = mNm.getConsolidatedNotificationPolicy();
Beverlyd6964762018-02-16 14:07:03 -05003594 final boolean muteAlarms = (zenPolicy.priorityCategories
3595 & NotificationManager.Policy.PRIORITY_CATEGORY_ALARMS) == 0;
3596 final boolean muteMedia = (zenPolicy.priorityCategories
3597 & NotificationManager.Policy.PRIORITY_CATEGORY_MEDIA) == 0;
3598 final boolean muteSystem = (zenPolicy.priorityCategories
3599 & NotificationManager.Policy.PRIORITY_CATEGORY_SYSTEM) == 0;
3600 final boolean muteNotificationAndRing = ZenModeConfig
Beverlyff2df9b2018-10-10 16:54:10 -04003601 .areAllPriorityOnlyNotificationZenSoundsMuted(
3602 mNm.getConsolidatedNotificationPolicy());
Beverlyd6964762018-02-16 14:07:03 -05003603 return muteAlarms && isAlarm(streamType)
3604 || muteMedia && isMedia(streamType)
3605 || muteSystem && isSystem(streamType)
3606 || muteNotificationAndRing && isNotificationOrRinger(streamType);
3607 }
3608
3609 private boolean isStreamMutedByRingerOrZenMode(int streamType) {
3610 return (mRingerAndZenModeMutedStreams & (1 << streamType)) != 0;
3611 }
3612
3613 /**
3614 * DND total silence: media and alarms streams are tied to the muted ringer
3615 * {@link ZenModeHelper.RingerModeDelegate#getRingerModeAffectedStreams(int)}
3616 * DND alarms only: notification, ringer + system muted (by default tied to muted ringer mode)
3617 * DND priority only: alarms, media, system streams can be muted separate from ringer based on
3618 * zenPolicy (this method determines which streams)
3619 * @return true if changed, else false
3620 */
3621 private boolean updateZenModeAffectedStreams() {
3622 int zenModeAffectedStreams = 0;
3623 if (mSystemReady && mNm.getZenMode() == Settings.Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS) {
Beverlyff2df9b2018-10-10 16:54:10 -04003624 NotificationManager.Policy zenPolicy = mNm.getConsolidatedNotificationPolicy();
Beverlyd6964762018-02-16 14:07:03 -05003625 if ((zenPolicy.priorityCategories
3626 & NotificationManager.Policy.PRIORITY_CATEGORY_ALARMS) == 0) {
3627 zenModeAffectedStreams |= 1 << AudioManager.STREAM_ALARM;
3628 }
3629
3630 if ((zenPolicy.priorityCategories
3631 & NotificationManager.Policy.PRIORITY_CATEGORY_MEDIA) == 0) {
3632 zenModeAffectedStreams |= 1 << AudioManager.STREAM_MUSIC;
3633 }
3634
3635 if ((zenPolicy.priorityCategories
3636 & NotificationManager.Policy.PRIORITY_CATEGORY_SYSTEM) == 0) {
3637 zenModeAffectedStreams |= 1 << AudioManager.STREAM_SYSTEM;
3638 }
3639 }
3640
3641 if (mZenModeAffectedStreams != zenModeAffectedStreams) {
3642 mZenModeAffectedStreams = zenModeAffectedStreams;
3643 return true;
3644 }
3645
3646 return false;
Eric Laurent5b4e6542010-03-19 20:02:21 -07003647 }
3648
Jean-Michel Trivi8719a1d2017-11-06 11:52:51 -08003649 @GuardedBy("mSettingsLock")
Beverlyd6964762018-02-16 14:07:03 -05003650 private boolean updateRingerAndZenModeAffectedStreams() {
3651 boolean updatedZenModeAffectedStreams = updateZenModeAffectedStreams();
John Spurlock50ced3f2015-05-11 16:00:09 -04003652 int ringerModeAffectedStreams = Settings.System.getIntForUser(mContentResolver,
Eric Laurent24e0d9b2013-10-03 18:15:07 -07003653 Settings.System.MODE_RINGER_STREAMS_AFFECTED,
3654 ((1 << AudioSystem.STREAM_RING)|(1 << AudioSystem.STREAM_NOTIFICATION)|
3655 (1 << AudioSystem.STREAM_SYSTEM)|(1 << AudioSystem.STREAM_SYSTEM_ENFORCED)),
3656 UserHandle.USER_CURRENT);
3657
Muyuan Li1ed6df62016-06-18 11:16:52 -07003658 if (mIsSingleVolume) {
John Spurlock50ced3f2015-05-11 16:00:09 -04003659 ringerModeAffectedStreams = 0;
3660 } else if (mRingerModeDelegate != null) {
3661 ringerModeAffectedStreams = mRingerModeDelegate
3662 .getRingerModeAffectedStreams(ringerModeAffectedStreams);
Eric Laurent24e0d9b2013-10-03 18:15:07 -07003663 }
Jean-Michel Trivi8719a1d2017-11-06 11:52:51 -08003664 if (mCameraSoundForced) {
3665 ringerModeAffectedStreams &= ~(1 << AudioSystem.STREAM_SYSTEM_ENFORCED);
3666 } else {
3667 ringerModeAffectedStreams |= (1 << AudioSystem.STREAM_SYSTEM_ENFORCED);
Eric Laurent24e0d9b2013-10-03 18:15:07 -07003668 }
3669 if (mStreamVolumeAlias[AudioSystem.STREAM_DTMF] == AudioSystem.STREAM_RING) {
3670 ringerModeAffectedStreams |= (1 << AudioSystem.STREAM_DTMF);
3671 } else {
3672 ringerModeAffectedStreams &= ~(1 << AudioSystem.STREAM_DTMF);
3673 }
3674
3675 if (ringerModeAffectedStreams != mRingerModeAffectedStreams) {
3676 Settings.System.putIntForUser(mContentResolver,
3677 Settings.System.MODE_RINGER_STREAMS_AFFECTED,
3678 ringerModeAffectedStreams,
3679 UserHandle.USER_CURRENT);
3680 mRingerModeAffectedStreams = ringerModeAffectedStreams;
3681 return true;
3682 }
Beverlyd6964762018-02-16 14:07:03 -05003683 return updatedZenModeAffectedStreams;
Eric Laurent24e0d9b2013-10-03 18:15:07 -07003684 }
3685
John Spurlocka9dfbe8b2015-02-17 11:01:51 -05003686 @Override
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003687 public boolean isStreamAffectedByMute(int streamType) {
3688 return (mMuteAffectedStreams & (1 << streamType)) != 0;
3689 }
3690
3691 private void ensureValidDirection(int direction) {
RoboErik4197cb62015-01-21 15:45:32 -08003692 switch (direction) {
3693 case AudioManager.ADJUST_LOWER:
3694 case AudioManager.ADJUST_RAISE:
3695 case AudioManager.ADJUST_SAME:
3696 case AudioManager.ADJUST_MUTE:
3697 case AudioManager.ADJUST_UNMUTE:
3698 case AudioManager.ADJUST_TOGGLE_MUTE:
3699 break;
3700 default:
3701 throw new IllegalArgumentException("Bad direction " + direction);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003702 }
3703 }
3704
3705 private void ensureValidStreamType(int streamType) {
3706 if (streamType < 0 || streamType >= mStreamStates.length) {
3707 throw new IllegalArgumentException("Bad stream type " + streamType);
3708 }
3709 }
3710
RoboErik4197cb62015-01-21 15:45:32 -08003711 private boolean isMuteAdjust(int adjust) {
3712 return adjust == AudioManager.ADJUST_MUTE || adjust == AudioManager.ADJUST_UNMUTE
3713 || adjust == AudioManager.ADJUST_TOGGLE_MUTE;
3714 }
3715
Jean-Michel Trivi58850372018-09-14 16:01:28 -07003716 /*package*/ boolean isInCommunication() {
Nancy Chen0eb1e402014-08-21 22:52:29 -07003717 boolean IsInCall = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003718
Tyler Gunnef9f6f92014-09-12 22:16:17 -07003719 TelecomManager telecomManager =
3720 (TelecomManager) mContext.getSystemService(Context.TELECOM_SERVICE);
Eric Laurent38edfda2014-12-18 17:38:04 -08003721
3722 final long ident = Binder.clearCallingIdentity();
Tyler Gunnef9f6f92014-09-12 22:16:17 -07003723 IsInCall = telecomManager.isInCall();
Eric Laurent38edfda2014-12-18 17:38:04 -08003724 Binder.restoreCallingIdentity(ident);
Santos Cordon9eb45932014-06-27 12:28:43 -07003725
Eric Laurentda1af762017-12-15 16:54:35 -08003726 return (IsInCall || getMode() == AudioManager.MODE_IN_COMMUNICATION ||
3727 getMode() == AudioManager.MODE_IN_CALL);
Eric Laurent6d517662012-04-23 18:42:39 -07003728 }
Eric Laurent25101b02011-02-02 09:33:30 -08003729
Jean-Michel Trivifca1e602013-10-10 18:12:59 -07003730 /**
3731 * For code clarity for getActiveStreamType(int)
Julia Reynoldsd9e96e22017-11-07 10:33:08 -05003732 * @param delay_ms max time since last stream activity to consider
3733 * @return true if stream is active in streams handled by AudioFlinger now or
Jean-Michel Trivifca1e602013-10-10 18:12:59 -07003734 * in the last "delay_ms" ms.
3735 */
Julia Reynoldsd9e96e22017-11-07 10:33:08 -05003736 private boolean wasStreamActiveRecently(int stream, int delay_ms) {
3737 return AudioSystem.isStreamActive(stream, delay_ms)
3738 || AudioSystem.isStreamActiveRemotely(stream, delay_ms);
Jean-Michel Trivifca1e602013-10-10 18:12:59 -07003739 }
3740
Eric Laurent6d517662012-04-23 18:42:39 -07003741 private int getActiveStreamType(int suggestedStreamType) {
Muyuan Li1ed6df62016-06-18 11:16:52 -07003742 if (mIsSingleVolume
3743 && suggestedStreamType == AudioManager.USE_DEFAULT_STREAM_TYPE) {
3744 return AudioSystem.STREAM_MUSIC;
3745 }
3746
Eric Laurent212532b2014-07-21 15:43:18 -07003747 switch (mPlatformType) {
John Spurlock61560172015-02-06 19:46:04 -05003748 case AudioSystem.PLATFORM_VOICE:
Eric Laurent6d517662012-04-23 18:42:39 -07003749 if (isInCommunication()) {
Eric Laurent25101b02011-02-02 09:33:30 -08003750 if (AudioSystem.getForceUse(AudioSystem.FOR_COMMUNICATION)
3751 == AudioSystem.FORCE_BT_SCO) {
3752 // Log.v(TAG, "getActiveStreamType: Forcing STREAM_BLUETOOTH_SCO...");
3753 return AudioSystem.STREAM_BLUETOOTH_SCO;
3754 } else {
3755 // Log.v(TAG, "getActiveStreamType: Forcing STREAM_VOICE_CALL...");
3756 return AudioSystem.STREAM_VOICE_CALL;
3757 }
Eric Laurent25101b02011-02-02 09:33:30 -08003758 } else if (suggestedStreamType == AudioManager.USE_DEFAULT_STREAM_TYPE) {
Julia Reynoldsd9e96e22017-11-07 10:33:08 -05003759 if (wasStreamActiveRecently(AudioSystem.STREAM_RING, sStreamOverrideDelayMs)) {
Jean-Michel Trivi3114ce32012-06-11 15:03:52 -07003760 if (DEBUG_VOL)
Julia Reynoldsd9e96e22017-11-07 10:33:08 -05003761 Log.v(TAG, "getActiveStreamType: Forcing STREAM_RING stream active");
3762 return AudioSystem.STREAM_RING;
3763 } else if (wasStreamActiveRecently(
3764 AudioSystem.STREAM_NOTIFICATION, sStreamOverrideDelayMs)) {
3765 if (DEBUG_VOL)
3766 Log.v(TAG, "getActiveStreamType: Forcing STREAM_NOTIFICATION stream active");
3767 return AudioSystem.STREAM_NOTIFICATION;
3768 } else {
Julia Reynoldseb0ce472018-05-04 15:34:55 -04003769 if (DEBUG_VOL) {
3770 Log.v(TAG, "getActiveStreamType: Forcing DEFAULT_VOL_STREAM_NO_PLAYBACK("
3771 + DEFAULT_VOL_STREAM_NO_PLAYBACK + ") b/c default");
3772 }
3773 return DEFAULT_VOL_STREAM_NO_PLAYBACK;
Jean-Michel Trivi3114ce32012-06-11 15:03:52 -07003774 }
Julia Reynoldsd9e96e22017-11-07 10:33:08 -05003775 } else if (
3776 wasStreamActiveRecently(AudioSystem.STREAM_NOTIFICATION, sStreamOverrideDelayMs)) {
Jean-Michel Trivi3114ce32012-06-11 15:03:52 -07003777 if (DEBUG_VOL)
Julia Reynoldsd9e96e22017-11-07 10:33:08 -05003778 Log.v(TAG, "getActiveStreamType: Forcing STREAM_NOTIFICATION stream active");
3779 return AudioSystem.STREAM_NOTIFICATION;
3780 } else if (wasStreamActiveRecently(AudioSystem.STREAM_RING, sStreamOverrideDelayMs)) {
3781 if (DEBUG_VOL)
3782 Log.v(TAG, "getActiveStreamType: Forcing STREAM_RING stream active");
3783 return AudioSystem.STREAM_RING;
Eric Laurent25101b02011-02-02 09:33:30 -08003784 }
Eric Laurent212532b2014-07-21 15:43:18 -07003785 default:
Eric Laurent6d517662012-04-23 18:42:39 -07003786 if (isInCommunication()) {
Eric Laurent25101b02011-02-02 09:33:30 -08003787 if (AudioSystem.getForceUse(AudioSystem.FOR_COMMUNICATION)
3788 == AudioSystem.FORCE_BT_SCO) {
Jean-Michel Trivi3114ce32012-06-11 15:03:52 -07003789 if (DEBUG_VOL) Log.v(TAG, "getActiveStreamType: Forcing STREAM_BLUETOOTH_SCO");
Eric Laurent25101b02011-02-02 09:33:30 -08003790 return AudioSystem.STREAM_BLUETOOTH_SCO;
3791 } else {
Jean-Michel Trivi3114ce32012-06-11 15:03:52 -07003792 if (DEBUG_VOL) Log.v(TAG, "getActiveStreamType: Forcing STREAM_VOICE_CALL");
Eric Laurent25101b02011-02-02 09:33:30 -08003793 return AudioSystem.STREAM_VOICE_CALL;
3794 }
Julia Reynoldsd9e96e22017-11-07 10:33:08 -05003795 } else if (AudioSystem.isStreamActive(
3796 AudioSystem.STREAM_NOTIFICATION, sStreamOverrideDelayMs)) {
Jean-Michel Trivi3114ce32012-06-11 15:03:52 -07003797 if (DEBUG_VOL) Log.v(TAG, "getActiveStreamType: Forcing STREAM_NOTIFICATION");
Eric Laurent25101b02011-02-02 09:33:30 -08003798 return AudioSystem.STREAM_NOTIFICATION;
Julia Reynoldsd9e96e22017-11-07 10:33:08 -05003799 } else if (AudioSystem.isStreamActive(
3800 AudioSystem.STREAM_RING, sStreamOverrideDelayMs)) {
3801 if (DEBUG_VOL) Log.v(TAG, "getActiveStreamType: Forcing STREAM_RING");
3802 return AudioSystem.STREAM_RING;
Jean-Michel Trivi3114ce32012-06-11 15:03:52 -07003803 } else if (suggestedStreamType == AudioManager.USE_DEFAULT_STREAM_TYPE) {
Julia Reynoldsd9e96e22017-11-07 10:33:08 -05003804 if (AudioSystem.isStreamActive(
3805 AudioSystem.STREAM_NOTIFICATION, sStreamOverrideDelayMs)) {
3806 if (DEBUG_VOL) Log.v(TAG, "getActiveStreamType: Forcing STREAM_NOTIFICATION");
John Spurlockeb1d88d2014-07-19 14:49:19 -04003807 return AudioSystem.STREAM_NOTIFICATION;
Julia Reynoldsd9e96e22017-11-07 10:33:08 -05003808 } else if (AudioSystem.isStreamActive(
3809 AudioSystem.STREAM_RING, sStreamOverrideDelayMs)) {
3810 if (DEBUG_VOL) Log.v(TAG, "getActiveStreamType: Forcing STREAM_RING");
3811 return AudioSystem.STREAM_RING;
3812 } else {
Julia Reynoldseb0ce472018-05-04 15:34:55 -04003813 if (DEBUG_VOL) {
3814 Log.v(TAG, "getActiveStreamType: Forcing DEFAULT_VOL_STREAM_NO_PLAYBACK("
3815 + DEFAULT_VOL_STREAM_NO_PLAYBACK + ") b/c default");
3816 }
3817 return DEFAULT_VOL_STREAM_NO_PLAYBACK;
Jean-Michel Trivi3114ce32012-06-11 15:03:52 -07003818 }
Joe Onoratoc7fcba42011-01-05 16:53:11 -08003819 }
Eric Laurent212532b2014-07-21 15:43:18 -07003820 break;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003821 }
Eric Laurent212532b2014-07-21 15:43:18 -07003822 if (DEBUG_VOL) Log.v(TAG, "getActiveStreamType: Returning suggested type "
3823 + suggestedStreamType);
3824 return suggestedStreamType;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003825 }
3826
John Spurlockbcc10872014-11-28 15:29:21 -05003827 private void broadcastRingerMode(String action, int ringerMode) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003828 // Send sticky broadcast
John Spurlockbcc10872014-11-28 15:29:21 -05003829 Intent broadcast = new Intent(action);
Glenn Kastenba195eb2011-12-13 09:30:40 -08003830 broadcast.putExtra(AudioManager.EXTRA_RINGER_MODE, ringerMode);
Dianne Hackborn1c633fc2009-12-08 19:45:14 -08003831 broadcast.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT
3832 | Intent.FLAG_RECEIVER_REPLACE_PENDING);
Dianne Hackborn5ac72a22012-08-29 18:32:08 -07003833 sendStickyBroadcastToAll(broadcast);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003834 }
3835
3836 private void broadcastVibrateSetting(int vibrateType) {
3837 // Send broadcast
Sudheer Shankafc46e9b2016-10-21 17:55:27 -07003838 if (mActivityManagerInternal.isSystemReady()) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003839 Intent broadcast = new Intent(AudioManager.VIBRATE_SETTING_CHANGED_ACTION);
3840 broadcast.putExtra(AudioManager.EXTRA_VIBRATE_TYPE, vibrateType);
3841 broadcast.putExtra(AudioManager.EXTRA_VIBRATE_SETTING, getVibrateSetting(vibrateType));
Dianne Hackborn5ac72a22012-08-29 18:32:08 -07003842 sendBroadcastToAll(broadcast);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003843 }
3844 }
3845
3846 // Message helper methods
Jean-Michel Trivi2d8dab52012-05-30 18:13:59 -07003847 /**
3848 * Queue a message on the given handler's message queue, after acquiring the service wake lock.
3849 * Note that the wake lock needs to be released after the message has been handled.
3850 */
3851 private void queueMsgUnderWakeLock(Handler handler, int msg,
3852 int arg1, int arg2, Object obj, int delay) {
Eric Laurenta4dfbdc52013-10-01 11:53:51 -07003853 final long ident = Binder.clearCallingIdentity();
3854 // Always acquire the wake lock as AudioService because it is released by the
3855 // message handler.
Jean-Michel Trivifa9a6982013-06-27 16:22:58 -07003856 mAudioEventWakeLock.acquire();
Eric Laurenta4dfbdc52013-10-01 11:53:51 -07003857 Binder.restoreCallingIdentity(ident);
Jean-Michel Trivi2d8dab52012-05-30 18:13:59 -07003858 sendMsg(handler, msg, SENDMSG_QUEUE, arg1, arg2, obj, delay);
3859 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003860
Eric Laurentafbb0472011-12-15 09:04:23 -08003861 private static void sendMsg(Handler handler, int msg,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003862 int existingMsgPolicy, int arg1, int arg2, Object obj, int delay) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003863 if (existingMsgPolicy == SENDMSG_REPLACE) {
3864 handler.removeMessages(msg);
3865 } else if (existingMsgPolicy == SENDMSG_NOOP && handler.hasMessages(msg)) {
3866 return;
3867 }
Eric Laurent3c4636c2018-06-13 19:36:42 -07003868
Jean-Michel Trivi58850372018-09-14 16:01:28 -07003869 final long time = SystemClock.uptimeMillis() + delay;
3870 handler.sendMessageAtTime(handler.obtainMessage(msg, arg1, arg2, obj), time);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003871 }
3872
3873 boolean checkAudioSettingsPermission(String method) {
Jean-Michel Triviccd654e2014-09-03 17:48:47 -07003874 if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.MODIFY_AUDIO_SETTINGS)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003875 == PackageManager.PERMISSION_GRANTED) {
3876 return true;
3877 }
3878 String msg = "Audio Settings Permission Denial: " + method + " from pid="
3879 + Binder.getCallingPid()
3880 + ", uid=" + Binder.getCallingUid();
3881 Log.w(TAG, msg);
3882 return false;
3883 }
3884
Jean-Michel Trivi58850372018-09-14 16:01:28 -07003885 /*package*/ int getDeviceForStream(int stream) {
John Spurlock8a52c442015-03-26 14:23:58 -04003886 int device = getDevicesForStream(stream);
Eric Laurent9bc8358d2011-11-18 16:43:31 -08003887 if ((device & (device - 1)) != 0) {
3888 // Multiple device selection is either:
3889 // - speaker + one other device: give priority to speaker in this case.
3890 // - one A2DP device + another device: happens with duplicated output. In this case
3891 // retain the device on the A2DP output as the other must not correspond to an active
3892 // selection if not the speaker.
Jungshik Jangc9ff9682014-09-15 17:41:06 +09003893 // - HDMI-CEC system audio mode only output: give priority to available item in order.
Eric Laurent9bc8358d2011-11-18 16:43:31 -08003894 if ((device & AudioSystem.DEVICE_OUT_SPEAKER) != 0) {
3895 device = AudioSystem.DEVICE_OUT_SPEAKER;
Jungshik Jangc9ff9682014-09-15 17:41:06 +09003896 } else if ((device & AudioSystem.DEVICE_OUT_HDMI_ARC) != 0) {
3897 device = AudioSystem.DEVICE_OUT_HDMI_ARC;
3898 } else if ((device & AudioSystem.DEVICE_OUT_SPDIF) != 0) {
3899 device = AudioSystem.DEVICE_OUT_SPDIF;
3900 } else if ((device & AudioSystem.DEVICE_OUT_AUX_LINE) != 0) {
3901 device = AudioSystem.DEVICE_OUT_AUX_LINE;
Eric Laurent9bc8358d2011-11-18 16:43:31 -08003902 } else {
3903 device &= AudioSystem.DEVICE_OUT_ALL_A2DP;
3904 }
3905 }
3906 return device;
3907 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003908
John Spurlock8a52c442015-03-26 14:23:58 -04003909 private int getDevicesForStream(int stream) {
3910 return getDevicesForStream(stream, true /*checkOthers*/);
3911 }
3912
3913 private int getDevicesForStream(int stream, boolean checkOthers) {
3914 ensureValidStreamType(stream);
3915 synchronized (VolumeStreamState.class) {
3916 return mStreamStates[stream].observeDevicesForStream_syncVSS(checkOthers);
3917 }
3918 }
3919
3920 private void observeDevicesForStreams(int skipStream) {
3921 synchronized (VolumeStreamState.class) {
3922 for (int stream = 0; stream < mStreamStates.length; stream++) {
3923 if (stream != skipStream) {
3924 mStreamStates[stream].observeDevicesForStream_syncVSS(false /*checkOthers*/);
3925 }
3926 }
3927 }
3928 }
3929
Jean-Michel Trivi58850372018-09-14 16:01:28 -07003930
3931 /*package*/ void observeDevicesForAllStreams() {
3932 observeDevicesForStreams(-1);
Aniket Kumar Lata9fbc2052019-01-11 02:02:33 -08003933 }
3934
Jean-Michel Trivi58850372018-09-14 16:01:28 -07003935 /*package*/ static final int CONNECTION_STATE_DISCONNECTED = 0;
3936 /*package*/ static final int CONNECTION_STATE_CONNECTED = 1;
3937 /**
3938 * The states that can be used with AudioService.setWiredDeviceConnectionState()
3939 * Attention: those values differ from those in BluetoothProfile, follow annotations to
3940 * distinguish between @ConnectionState and @BtProfileConnectionState
Paul McLean10804eb2015-01-28 11:16:35 -08003941 */
Jean-Michel Trivi58850372018-09-14 16:01:28 -07003942 @IntDef({
3943 CONNECTION_STATE_DISCONNECTED,
3944 CONNECTION_STATE_CONNECTED,
3945 })
3946 @Retention(RetentionPolicy.SOURCE)
3947 public @interface ConnectionState {}
Paul McLean10804eb2015-01-28 11:16:35 -08003948
Jean-Michel Trivi58850372018-09-14 16:01:28 -07003949 /**
3950 * see AudioManager.setWiredDeviceConnectionState()
3951 */
3952 public void setWiredDeviceConnectionState(int type,
3953 @ConnectionState int state, String address, String name,
John Spurlock90874332015-03-10 16:00:54 -04003954 String caller) {
Jean-Michel Trivi58850372018-09-14 16:01:28 -07003955 if (state != CONNECTION_STATE_CONNECTED
3956 && state != CONNECTION_STATE_DISCONNECTED) {
3957 throw new IllegalArgumentException("Invalid state " + state);
Eric Laurentb1fbaac2012-05-29 09:24:28 -07003958 }
Jean-Michel Trivi58850372018-09-14 16:01:28 -07003959 mDeviceBroker.setWiredDeviceConnectionState(type, state, address, name, caller);
Eric Laurentb1fbaac2012-05-29 09:24:28 -07003960 }
3961
Jean-Michel Trivi58850372018-09-14 16:01:28 -07003962 /**
3963 * @hide
3964 * The states that can be used with AudioService.setBluetoothHearingAidDeviceConnectionState()
3965 * and AudioService.setBluetoothA2dpDeviceConnectionStateSuppressNoisyIntent()
3966 */
3967 @IntDef({
3968 BluetoothProfile.STATE_DISCONNECTED,
3969 BluetoothProfile.STATE_CONNECTED,
3970 })
3971 @Retention(RetentionPolicy.SOURCE)
3972 public @interface BtProfileConnectionState {}
3973
Jakub Pawlowskif9570f32018-02-21 17:15:12 -08003974 public int setBluetoothHearingAidDeviceConnectionState(
Jean-Michel Trivi58850372018-09-14 16:01:28 -07003975 @NonNull BluetoothDevice device, @BtProfileConnectionState int state,
3976 boolean suppressNoisyIntent, int musicDevice)
Jakub Pawlowskif9570f32018-02-21 17:15:12 -08003977 {
Jean-Michel Trivi58850372018-09-14 16:01:28 -07003978 if (device == null) {
3979 throw new IllegalArgumentException("Illegal null device");
Jakub Pawlowskif9570f32018-02-21 17:15:12 -08003980 }
Jean-Michel Trivi58850372018-09-14 16:01:28 -07003981 if (state != BluetoothProfile.STATE_CONNECTED
3982 && state != BluetoothProfile.STATE_DISCONNECTED) {
3983 throw new IllegalArgumentException("Illegal BluetoothProfile state for device "
3984 + " (dis)connection, got " + state);
3985 }
3986 return mDeviceBroker.setBluetoothHearingAidDeviceConnectionState(
3987 device, state, suppressNoisyIntent, musicDevice, "AudioService");
Jakub Pawlowski10c90612018-02-21 13:28:46 -08003988 }
3989
Jean-Michel Trivi58850372018-09-14 16:01:28 -07003990 /**
3991 * See AudioManager.setBluetoothA2dpDeviceConnectionStateSuppressNoisyIntent()
3992 */
3993 public int setBluetoothA2dpDeviceConnectionStateSuppressNoisyIntent(
3994 @NonNull BluetoothDevice device, @AudioService.BtProfileConnectionState int state,
3995 int profile, boolean suppressNoisyIntent, int a2dpVolume) {
3996 if (device == null) {
3997 throw new IllegalArgumentException("Illegal null device");
3998 }
3999 if (state != BluetoothProfile.STATE_CONNECTED
4000 && state != BluetoothProfile.STATE_DISCONNECTED) {
4001 throw new IllegalArgumentException("Illegal BluetoothProfile state for device "
4002 + " (dis)connection, got " + state);
4003 }
4004 return mDeviceBroker.setBluetoothA2dpDeviceConnectionStateSuppressNoisyIntent(device, state,
4005 profile, suppressNoisyIntent, a2dpVolume);
Pavlin Radoslavov82e06462018-01-19 18:20:04 -08004006 }
4007
Jean-Michel Trivi58850372018-09-14 16:01:28 -07004008 /**
4009 * See AudioManager.handleBluetoothA2dpDeviceConfigChange()
4010 * @param device
4011 */
Pavlin Radoslavov44a4ef02016-12-21 12:05:51 -08004012 public void handleBluetoothA2dpDeviceConfigChange(BluetoothDevice device)
4013 {
Jean-Michel Trivi58850372018-09-14 16:01:28 -07004014 if (device == null) {
4015 throw new IllegalArgumentException("Illegal null device");
Pavlin Radoslavov44a4ef02016-12-21 12:05:51 -08004016 }
Jean-Michel Trivi58850372018-09-14 16:01:28 -07004017 mDeviceBroker.postBluetoothA2dpDeviceConfigChange(device);
Pavlin Radoslavov44a4ef02016-12-21 12:05:51 -08004018 }
4019
Aniket Kumar Lataa8439e22019-01-11 03:59:00 -08004020 /**
4021 * @see AudioManager#handleBluetoothA2dpActiveDeviceChange(BluetoothDevice, int, int,
4022 * boolean, int)
4023 */
4024 public int handleBluetoothA2dpActiveDeviceChange(
4025 BluetoothDevice device, int state, int profile, boolean suppressNoisyIntent,
4026 int a2dpVolume) {
Jean-Michel Trivi58850372018-09-14 16:01:28 -07004027 if (device == null) {
4028 throw new IllegalArgumentException("Illegal null device");
4029 }
Aniket Kumar Lataa8439e22019-01-11 03:59:00 -08004030 if (profile != BluetoothProfile.A2DP && profile != BluetoothProfile.A2DP_SINK) {
4031 throw new IllegalArgumentException("invalid profile " + profile);
4032 }
Jean-Michel Trivi58850372018-09-14 16:01:28 -07004033 if (state != BluetoothProfile.STATE_CONNECTED
4034 && state != BluetoothProfile.STATE_DISCONNECTED) {
4035 throw new IllegalArgumentException("Invalid state " + state);
Aniket Kumar Lataa8439e22019-01-11 03:59:00 -08004036 }
Jean-Michel Trivi58850372018-09-14 16:01:28 -07004037 return mDeviceBroker.handleBluetoothA2dpActiveDeviceChange(device, state, profile,
4038 suppressNoisyIntent, a2dpVolume);
Aniket Kumar Lataa8439e22019-01-11 03:59:00 -08004039 }
4040
Jean-Michel Trivi1ab43f62017-04-27 15:37:34 -07004041 private static final int DEVICE_MEDIA_UNMUTED_ON_PLUG =
4042 AudioSystem.DEVICE_OUT_WIRED_HEADSET | AudioSystem.DEVICE_OUT_WIRED_HEADPHONE |
4043 AudioSystem.DEVICE_OUT_LINE |
4044 AudioSystem.DEVICE_OUT_ALL_A2DP |
4045 AudioSystem.DEVICE_OUT_ALL_USB |
4046 AudioSystem.DEVICE_OUT_HDMI;
4047
Jean-Michel Trivi58850372018-09-14 16:01:28 -07004048 /*package*/ void postAccessoryPlugMediaUnmute(int newDevice) {
4049 sendMsg(mAudioHandler, MSG_ACCESSORY_PLUG_MEDIA_UNMUTE, SENDMSG_QUEUE,
4050 newDevice, 0, null, 0);
4051 }
4052
Jean-Michel Trivi1ab43f62017-04-27 15:37:34 -07004053 private void onAccessoryPlugMediaUnmute(int newDevice) {
4054 if (DEBUG_VOL) {
4055 Log.i(TAG, String.format("onAccessoryPlugMediaUnmute newDevice=%d [%s]",
4056 newDevice, AudioSystem.getOutputDeviceName(newDevice)));
4057 }
Jean-Michel Trivi58850372018-09-14 16:01:28 -07004058
4059 if (mNm.getZenMode() != Settings.Global.ZEN_MODE_NO_INTERRUPTIONS
4060 && (newDevice & DEVICE_MEDIA_UNMUTED_ON_PLUG) != 0
4061 && mStreamStates[AudioSystem.STREAM_MUSIC].mIsMuted
4062 && mStreamStates[AudioSystem.STREAM_MUSIC].getIndex(newDevice) != 0
4063 && (newDevice & AudioSystem.getDevicesForStream(AudioSystem.STREAM_MUSIC)) != 0) {
4064 if (DEBUG_VOL) {
4065 Log.i(TAG, String.format(" onAccessoryPlugMediaUnmute unmuting device=%d [%s]",
4066 newDevice, AudioSystem.getOutputDeviceName(newDevice)));
Jean-Michel Trivi1ab43f62017-04-27 15:37:34 -07004067 }
Jean-Michel Trivi58850372018-09-14 16:01:28 -07004068 mStreamStates[AudioSystem.STREAM_MUSIC].mute(false);
Jean-Michel Trivi1ab43f62017-04-27 15:37:34 -07004069 }
4070 }
4071
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004072 ///////////////////////////////////////////////////////////////////////////
4073 // Inner classes
4074 ///////////////////////////////////////////////////////////////////////////
4075
Eric Laurent8fa4d6f2014-10-30 14:13:03 -07004076 // NOTE: Locking order for synchronized objects related to volume or ringer mode management:
4077 // 1 mScoclient OR mSafeMediaVolumeState
Jean-Michel Trivi58850372018-09-14 16:01:28 -07004078 // 2 mSetModeLock
Eric Laurent8fa4d6f2014-10-30 14:13:03 -07004079 // 3 mSettingsLock
4080 // 4 VolumeStreamState.class
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004081 public class VolumeStreamState {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004082 private final int mStreamType;
Jean-Michel Trivie05eef82018-03-08 18:56:34 -08004083 private int mIndexMin;
4084 private int mIndexMax;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004085
RoboErik4197cb62015-01-21 15:45:32 -08004086 private boolean mIsMuted;
Jean-Michel Trivi11a74a72009-10-27 17:39:30 -07004087 private String mVolumeIndexSettingName;
John Spurlock8a52c442015-03-26 14:23:58 -04004088 private int mObservedDevices;
John Spurlockb6e19e32015-03-10 21:33:44 -04004089
John Spurlock2bb02ec2015-03-02 13:13:06 -05004090 private final SparseIntArray mIndexMap = new SparseIntArray(8);
John Spurlockf63860c2015-02-19 09:46:27 -05004091 private final Intent mVolumeChanged;
John Spurlock8a52c442015-03-26 14:23:58 -04004092 private final Intent mStreamDevicesChanged;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004093
Eric Laurenta553c252009-07-17 12:17:14 -07004094 private VolumeStreamState(String settingName, int streamType) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004095
Eric Laurent9bc8358d2011-11-18 16:43:31 -08004096 mVolumeIndexSettingName = settingName;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004097
4098 mStreamType = streamType;
John Spurlockb6e19e32015-03-10 21:33:44 -04004099 mIndexMin = MIN_STREAM_VOLUME[streamType] * 10;
4100 mIndexMax = MAX_STREAM_VOLUME[streamType] * 10;
4101 AudioSystem.initStreamVolume(streamType, mIndexMin / 10, mIndexMax / 10);
Eric Laurent9bc8358d2011-11-18 16:43:31 -08004102
Eric Laurent33902db2012-10-07 16:15:07 -07004103 readSettings();
John Spurlockf63860c2015-02-19 09:46:27 -05004104 mVolumeChanged = new Intent(AudioManager.VOLUME_CHANGED_ACTION);
4105 mVolumeChanged.putExtra(AudioManager.EXTRA_VOLUME_STREAM_TYPE, mStreamType);
John Spurlock8a52c442015-03-26 14:23:58 -04004106 mStreamDevicesChanged = new Intent(AudioManager.STREAM_DEVICES_CHANGED_ACTION);
4107 mStreamDevicesChanged.putExtra(AudioManager.EXTRA_VOLUME_STREAM_TYPE, mStreamType);
4108 }
4109
4110 public int observeDevicesForStream_syncVSS(boolean checkOthers) {
4111 final int devices = AudioSystem.getDevicesForStream(mStreamType);
4112 if (devices == mObservedDevices) {
4113 return devices;
4114 }
4115 final int prevDevices = mObservedDevices;
4116 mObservedDevices = devices;
4117 if (checkOthers) {
4118 // one stream's devices have changed, check the others
4119 observeDevicesForStreams(mStreamType);
4120 }
4121 // log base stream changes to the event log
4122 if (mStreamVolumeAlias[mStreamType] == mStreamType) {
4123 EventLogTags.writeStreamDevicesChanged(mStreamType, prevDevices, devices);
4124 }
4125 sendBroadcastToAll(mStreamDevicesChanged
4126 .putExtra(AudioManager.EXTRA_PREV_VOLUME_STREAM_DEVICES, prevDevices)
4127 .putExtra(AudioManager.EXTRA_VOLUME_STREAM_DEVICES, devices));
4128 return devices;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004129 }
4130
Jean-Michel Trivia53b7052017-04-12 18:27:01 -07004131 public @Nullable String getSettingNameForDevice(int device) {
4132 if (!hasValidSettingsName()) {
4133 return null;
Eric Laurent9bc8358d2011-11-18 16:43:31 -08004134 }
Jean-Michel Trivia53b7052017-04-12 18:27:01 -07004135 final String suffix = AudioSystem.getOutputDeviceName(device);
4136 if (suffix.isEmpty()) {
4137 return mVolumeIndexSettingName;
4138 }
4139 return mVolumeIndexSettingName + "_" + suffix;
4140 }
4141
4142 private boolean hasValidSettingsName() {
4143 return (mVolumeIndexSettingName != null && !mVolumeIndexSettingName.isEmpty());
Jean-Michel Trivi11a74a72009-10-27 17:39:30 -07004144 }
4145
Eric Laurentfdbee862014-05-12 15:26:12 -07004146 public void readSettings() {
Jean-Michel Trivi8719a1d2017-11-06 11:52:51 -08004147 synchronized (mSettingsLock) {
4148 synchronized (VolumeStreamState.class) {
4149 // force maximum volume on all streams if fixed volume property is set
4150 if (mUseFixedVolume) {
4151 mIndexMap.put(AudioSystem.DEVICE_OUT_DEFAULT, mIndexMax);
4152 return;
4153 }
4154 // do not read system stream volume from settings: this stream is always aliased
4155 // to another stream type and its volume is never persisted. Values in settings can
4156 // only be stale values
4157 if ((mStreamType == AudioSystem.STREAM_SYSTEM) ||
4158 (mStreamType == AudioSystem.STREAM_SYSTEM_ENFORCED)) {
4159 int index = 10 * AudioSystem.DEFAULT_STREAM_VOLUME[mStreamType];
Eric Laurentfdbee862014-05-12 15:26:12 -07004160 if (mCameraSoundForced) {
4161 index = mIndexMax;
4162 }
Jean-Michel Trivi8719a1d2017-11-06 11:52:51 -08004163 mIndexMap.put(AudioSystem.DEVICE_OUT_DEFAULT, index);
4164 return;
Eric Laurentdd45d012012-10-08 09:04:34 -07004165 }
Eric Laurent9bc8358d2011-11-18 16:43:31 -08004166 }
Jean-Michel Trivi8719a1d2017-11-06 11:52:51 -08004167 }
4168 synchronized (VolumeStreamState.class) {
Eric Laurentfdbee862014-05-12 15:26:12 -07004169 int remainingDevices = AudioSystem.DEVICE_OUT_ALL;
4170
4171 for (int i = 0; remainingDevices != 0; i++) {
4172 int device = (1 << i);
4173 if ((device & remainingDevices) == 0) {
4174 continue;
4175 }
4176 remainingDevices &= ~device;
4177
4178 // retrieve current volume for device
Eric Laurentfdbee862014-05-12 15:26:12 -07004179 // if no volume stored for current stream and device, use default volume if default
4180 // device, continue otherwise
4181 int defaultIndex = (device == AudioSystem.DEVICE_OUT_DEFAULT) ?
John Spurlock61560172015-02-06 19:46:04 -05004182 AudioSystem.DEFAULT_STREAM_VOLUME[mStreamType] : -1;
Jean-Michel Trivia53b7052017-04-12 18:27:01 -07004183 int index;
4184 if (!hasValidSettingsName()) {
4185 index = defaultIndex;
4186 } else {
4187 String name = getSettingNameForDevice(device);
4188 index = Settings.System.getIntForUser(
4189 mContentResolver, name, defaultIndex, UserHandle.USER_CURRENT);
4190 }
Eric Laurentfdbee862014-05-12 15:26:12 -07004191 if (index == -1) {
4192 continue;
4193 }
4194
John Spurlock2bb02ec2015-03-02 13:13:06 -05004195 mIndexMap.put(device, getValidIndex(10 * index));
Eric Laurentdd45d012012-10-08 09:04:34 -07004196 }
Eric Laurent9bc8358d2011-11-18 16:43:31 -08004197 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004198 }
4199
Liejun Tao39fb5672016-03-09 15:52:13 -06004200 private int getAbsoluteVolumeIndex(int index) {
4201 /* Special handling for Bluetooth Absolute Volume scenario
4202 * If we send full audio gain, some accessories are too loud even at its lowest
4203 * volume. We are not able to enumerate all such accessories, so here is the
4204 * workaround from phone side.
4205 * Pre-scale volume at lowest volume steps 1 2 and 3.
4206 * For volume step 0, set audio gain to 0 as some accessories won't mute on their end.
4207 */
4208 if (index == 0) {
4209 // 0% for volume 0
4210 index = 0;
Tomoharu Kasaharaf0fecb12018-09-06 20:04:38 +09004211 } else if (index > 0 && index <= 3) {
4212 // Pre-scale for volume steps 1 2 and 3
4213 index = (int) (mIndexMax * mPrescaleAbsoluteVolume[index - 1]) / 10;
Liejun Tao39fb5672016-03-09 15:52:13 -06004214 } else {
4215 // otherwise, full gain
Tomoharu Kasaharaf0fecb12018-09-06 20:04:38 +09004216 index = (mIndexMax + 5) / 10;
Liejun Tao39fb5672016-03-09 15:52:13 -06004217 }
4218 return index;
4219 }
4220
Eric Laurent8fa4d6f2014-10-30 14:13:03 -07004221 // must be called while synchronized VolumeStreamState.class
Jean-Michel Trivi58850372018-09-14 16:01:28 -07004222 /*package*/ void applyDeviceVolume_syncVSS(int device, boolean isAvrcpAbsVolSupported) {
Eric Laurent42b041e2013-03-29 11:36:03 -07004223 int index;
RoboErik4197cb62015-01-21 15:45:32 -08004224 if (mIsMuted) {
Eric Laurent42b041e2013-03-29 11:36:03 -07004225 index = 0;
Jean-Michel Trivi58850372018-09-14 16:01:28 -07004226 } else if ((device & AudioSystem.DEVICE_OUT_ALL_A2DP) != 0 && isAvrcpAbsVolSupported) {
Liejun Tao39fb5672016-03-09 15:52:13 -06004227 index = getAbsoluteVolumeIndex((getIndex(device) + 5)/10);
Liejun Tao4565a472016-01-20 17:52:20 -06004228 } else if ((device & mFullVolumeDevices) != 0) {
Matthew Xiec9d1d5f2013-09-12 00:32:22 -07004229 index = (mIndexMax + 5)/10;
Jakub Pawlowskic274fb22018-04-04 10:15:12 -07004230 } else if ((device & AudioSystem.DEVICE_OUT_HEARING_AID) != 0) {
4231 index = (mIndexMax + 5)/10;
Eric Laurentcd772d02013-10-30 18:31:07 -07004232 } else {
Eric Laurent42b041e2013-03-29 11:36:03 -07004233 index = (getIndex(device) + 5)/10;
4234 }
Jean-Michel Trivi58850372018-09-14 16:01:28 -07004235 AudioSystem.setStreamVolumeIndexAS(mStreamType, index, device);
Eric Laurent9bc8358d2011-11-18 16:43:31 -08004236 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004237
Eric Laurentfdbee862014-05-12 15:26:12 -07004238 public void applyAllVolumes() {
Jean-Michel Trivi58850372018-09-14 16:01:28 -07004239 final boolean isAvrcpAbsVolSupported = mDeviceBroker.isAvrcpAbsoluteVolumeSupported();
Eric Laurentfdbee862014-05-12 15:26:12 -07004240 synchronized (VolumeStreamState.class) {
Eric Laurentd9ac2be2016-04-07 14:04:23 -07004241 // apply device specific volumes first
Eric Laurentfdbee862014-05-12 15:26:12 -07004242 int index;
John Spurlock2bb02ec2015-03-02 13:13:06 -05004243 for (int i = 0; i < mIndexMap.size(); i++) {
Eric Laurentd9ac2be2016-04-07 14:04:23 -07004244 final int device = mIndexMap.keyAt(i);
Eric Laurentfdbee862014-05-12 15:26:12 -07004245 if (device != AudioSystem.DEVICE_OUT_DEFAULT) {
RoboErik4197cb62015-01-21 15:45:32 -08004246 if (mIsMuted) {
Eric Laurentfdbee862014-05-12 15:26:12 -07004247 index = 0;
Liejun Tao39fb5672016-03-09 15:52:13 -06004248 } else if ((device & AudioSystem.DEVICE_OUT_ALL_A2DP) != 0 &&
Jean-Michel Trivi58850372018-09-14 16:01:28 -07004249 isAvrcpAbsVolSupported) {
Liejun Tao39fb5672016-03-09 15:52:13 -06004250 index = getAbsoluteVolumeIndex((getIndex(device) + 5)/10);
4251 } else if ((device & mFullVolumeDevices) != 0) {
Eric Laurentfdbee862014-05-12 15:26:12 -07004252 index = (mIndexMax + 5)/10;
Jakub Pawlowskic274fb22018-04-04 10:15:12 -07004253 } else if ((device & AudioSystem.DEVICE_OUT_HEARING_AID) != 0) {
4254 index = (mIndexMax + 5)/10;
Eric Laurentfdbee862014-05-12 15:26:12 -07004255 } else {
John Spurlock2bb02ec2015-03-02 13:13:06 -05004256 index = (mIndexMap.valueAt(i) + 5)/10;
Eric Laurentfdbee862014-05-12 15:26:12 -07004257 }
Jean-Michel Trivi58850372018-09-14 16:01:28 -07004258 AudioSystem.setStreamVolumeIndexAS(mStreamType, index, device);
Eric Laurent42b041e2013-03-29 11:36:03 -07004259 }
Eric Laurent9bc8358d2011-11-18 16:43:31 -08004260 }
Eric Laurentd9ac2be2016-04-07 14:04:23 -07004261 // apply default volume last: by convention , default device volume will be used
4262 // by audio policy manager if no explicit volume is present for a given device type
4263 if (mIsMuted) {
4264 index = 0;
4265 } else {
4266 index = (getIndex(AudioSystem.DEVICE_OUT_DEFAULT) + 5)/10;
4267 }
Jean-Michel Trivi58850372018-09-14 16:01:28 -07004268 AudioSystem.setStreamVolumeIndexAS(
Eric Laurentd9ac2be2016-04-07 14:04:23 -07004269 mStreamType, index, AudioSystem.DEVICE_OUT_DEFAULT);
Eric Laurent9bc8358d2011-11-18 16:43:31 -08004270 }
4271 }
4272
John Spurlock90874332015-03-10 16:00:54 -04004273 public boolean adjustIndex(int deltaIndex, int device, String caller) {
4274 return setIndex(getIndex(device) + deltaIndex, device, caller);
Eric Laurent9bc8358d2011-11-18 16:43:31 -08004275 }
4276
John Spurlock90874332015-03-10 16:00:54 -04004277 public boolean setIndex(int index, int device, String caller) {
Jack He6dd78c12018-02-12 21:00:24 -08004278 boolean changed;
John Spurlockf63860c2015-02-19 09:46:27 -05004279 int oldIndex;
Jean-Michel Trivi8719a1d2017-11-06 11:52:51 -08004280 synchronized (mSettingsLock) {
4281 synchronized (VolumeStreamState.class) {
4282 oldIndex = getIndex(device);
4283 index = getValidIndex(index);
Eric Laurentfdbee862014-05-12 15:26:12 -07004284 if ((mStreamType == AudioSystem.STREAM_SYSTEM_ENFORCED) && mCameraSoundForced) {
4285 index = mIndexMax;
Eric Laurenta553c252009-07-17 12:17:14 -07004286 }
Jean-Michel Trivi8719a1d2017-11-06 11:52:51 -08004287 mIndexMap.put(device, index);
Eric Laurentfdbee862014-05-12 15:26:12 -07004288
Jean-Michel Trivi8719a1d2017-11-06 11:52:51 -08004289 changed = oldIndex != index;
4290 // Apply change to all streams using this one as alias if:
4291 // - the index actually changed OR
4292 // - there is no volume index stored for this device on alias stream.
4293 // If changing volume of current device, also change volume of current
4294 // device on aliased stream
Jack He6dd78c12018-02-12 21:00:24 -08004295 final boolean isCurrentDevice = (device == getDeviceForStream(mStreamType));
Jean-Michel Trivi8719a1d2017-11-06 11:52:51 -08004296 final int numStreamTypes = AudioSystem.getNumStreamTypes();
4297 for (int streamType = numStreamTypes - 1; streamType >= 0; streamType--) {
4298 final VolumeStreamState aliasStreamState = mStreamStates[streamType];
4299 if (streamType != mStreamType &&
4300 mStreamVolumeAlias[streamType] == mStreamType &&
4301 (changed || !aliasStreamState.hasIndexForDevice(device))) {
4302 final int scaledIndex = rescaleIndex(index, mStreamType, streamType);
4303 aliasStreamState.setIndex(scaledIndex, device, caller);
Jack He6dd78c12018-02-12 21:00:24 -08004304 if (isCurrentDevice) {
Jean-Michel Trivi8719a1d2017-11-06 11:52:51 -08004305 aliasStreamState.setIndex(scaledIndex,
4306 getDeviceForStream(streamType), caller);
4307 }
Eric Laurentfdbee862014-05-12 15:26:12 -07004308 }
4309 }
Jack He6dd78c12018-02-12 21:00:24 -08004310 // Mirror changes in SPEAKER ringtone volume on SCO when
4311 if (changed && mStreamType == AudioSystem.STREAM_RING
4312 && device == AudioSystem.DEVICE_OUT_SPEAKER) {
4313 for (int i = 0; i < mIndexMap.size(); i++) {
4314 int otherDevice = mIndexMap.keyAt(i);
4315 if ((otherDevice & AudioSystem.DEVICE_OUT_ALL_SCO) != 0) {
4316 mIndexMap.put(otherDevice, index);
4317 }
4318 }
4319 }
Eric Laurentfdbee862014-05-12 15:26:12 -07004320 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004321 }
John Spurlockf63860c2015-02-19 09:46:27 -05004322 if (changed) {
4323 oldIndex = (oldIndex + 5) / 10;
4324 index = (index + 5) / 10;
John Spurlock90874332015-03-10 16:00:54 -04004325 // log base stream changes to the event log
4326 if (mStreamVolumeAlias[mStreamType] == mStreamType) {
4327 if (caller == null) {
4328 Log.w(TAG, "No caller for volume_changed event", new Throwable());
4329 }
4330 EventLogTags.writeVolumeChanged(mStreamType, oldIndex, index, mIndexMax / 10,
4331 caller);
4332 }
4333 // fire changed intents for all streams
John Spurlockf63860c2015-02-19 09:46:27 -05004334 mVolumeChanged.putExtra(AudioManager.EXTRA_VOLUME_STREAM_VALUE, index);
4335 mVolumeChanged.putExtra(AudioManager.EXTRA_PREV_VOLUME_STREAM_VALUE, oldIndex);
Jean-Michel Trivi560877d2015-06-25 17:38:35 -07004336 mVolumeChanged.putExtra(AudioManager.EXTRA_VOLUME_STREAM_TYPE_ALIAS,
4337 mStreamVolumeAlias[mStreamType]);
John Spurlockf63860c2015-02-19 09:46:27 -05004338 sendBroadcastToAll(mVolumeChanged);
4339 }
4340 return changed;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004341 }
4342
Eric Laurentfdbee862014-05-12 15:26:12 -07004343 public int getIndex(int device) {
4344 synchronized (VolumeStreamState.class) {
John Spurlock2bb02ec2015-03-02 13:13:06 -05004345 int index = mIndexMap.get(device, -1);
4346 if (index == -1) {
Eric Laurentfdbee862014-05-12 15:26:12 -07004347 // there is always an entry for AudioSystem.DEVICE_OUT_DEFAULT
John Spurlock2bb02ec2015-03-02 13:13:06 -05004348 index = mIndexMap.get(AudioSystem.DEVICE_OUT_DEFAULT);
Eric Laurentfdbee862014-05-12 15:26:12 -07004349 }
John Spurlock2bb02ec2015-03-02 13:13:06 -05004350 return index;
Eric Laurent9bc8358d2011-11-18 16:43:31 -08004351 }
Eric Laurent5b4e6542010-03-19 20:02:21 -07004352 }
4353
Eric Laurent3fb608e2016-11-03 16:27:40 -07004354 public boolean hasIndexForDevice(int device) {
4355 synchronized (VolumeStreamState.class) {
4356 return (mIndexMap.get(device, -1) != -1);
4357 }
4358 }
4359
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004360 public int getMaxIndex() {
Eric Laurenta553c252009-07-17 12:17:14 -07004361 return mIndexMax;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004362 }
4363
John Spurlockb6e19e32015-03-10 21:33:44 -04004364 public int getMinIndex() {
4365 return mIndexMin;
4366 }
4367
Jean-Michel Trivi170a0ee2017-04-14 18:13:26 -07004368 /**
Jean-Michel Trivie05eef82018-03-08 18:56:34 -08004369 * Updates the min/max index values from another stream. Use this when changing the alias
4370 * for the current stream type.
4371 * @param sourceStreamType
4372 */
4373 // must be sync'd on mSettingsLock before VolumeStreamState.class
4374 @GuardedBy("VolumeStreamState.class")
4375 public void refreshRange(int sourceStreamType) {
4376 mIndexMin = MIN_STREAM_VOLUME[sourceStreamType] * 10;
4377 mIndexMax = MAX_STREAM_VOLUME[sourceStreamType] * 10;
4378 // verify all current volumes are within bounds
4379 for (int i = 0 ; i < mIndexMap.size(); i++) {
4380 final int device = mIndexMap.keyAt(i);
4381 final int index = mIndexMap.valueAt(i);
4382 mIndexMap.put(device, getValidIndex(index));
4383 }
4384 }
4385
4386 /**
Jean-Michel Trivi170a0ee2017-04-14 18:13:26 -07004387 * Copies all device/index pairs from the given VolumeStreamState after initializing
4388 * them with the volume for DEVICE_OUT_DEFAULT. No-op if the source VolumeStreamState
4389 * has the same stream type as this instance.
4390 * @param srcStream
4391 * @param caller
4392 */
Jean-Michel Trivi085346a2018-02-14 10:48:51 -08004393 // must be sync'd on mSettingsLock before VolumeStreamState.class
4394 @GuardedBy("VolumeStreamState.class")
John Spurlock90874332015-03-10 16:00:54 -04004395 public void setAllIndexes(VolumeStreamState srcStream, String caller) {
Jean-Michel Trivi170a0ee2017-04-14 18:13:26 -07004396 if (mStreamType == srcStream.mStreamType) {
4397 return;
4398 }
Jean-Michel Trivi085346a2018-02-14 10:48:51 -08004399 int srcStreamType = srcStream.getStreamType();
4400 // apply default device volume from source stream to all devices first in case
4401 // some devices are present in this stream state but not in source stream state
4402 int index = srcStream.getIndex(AudioSystem.DEVICE_OUT_DEFAULT);
4403 index = rescaleIndex(index, srcStreamType, mStreamType);
4404 for (int i = 0; i < mIndexMap.size(); i++) {
4405 mIndexMap.put(mIndexMap.keyAt(i), index);
4406 }
4407 // Now apply actual volume for devices in source stream state
4408 SparseIntArray srcMap = srcStream.mIndexMap;
4409 for (int i = 0; i < srcMap.size(); i++) {
4410 int device = srcMap.keyAt(i);
4411 index = srcMap.valueAt(i);
4412 index = rescaleIndex(index, srcStreamType, mStreamType);
Eric Laurent33902db2012-10-07 16:15:07 -07004413
Jean-Michel Trivi085346a2018-02-14 10:48:51 -08004414 setIndex(index, device, caller);
Eric Laurent6d517662012-04-23 18:42:39 -07004415 }
4416 }
4417
Jean-Michel Trivi085346a2018-02-14 10:48:51 -08004418 // must be sync'd on mSettingsLock before VolumeStreamState.class
4419 @GuardedBy("VolumeStreamState.class")
Eric Laurentfdbee862014-05-12 15:26:12 -07004420 public void setAllIndexesToMax() {
Jean-Michel Trivi085346a2018-02-14 10:48:51 -08004421 for (int i = 0; i < mIndexMap.size(); i++) {
4422 mIndexMap.put(mIndexMap.keyAt(i), mIndexMax);
Eric Laurentdd45d012012-10-08 09:04:34 -07004423 }
Eric Laurentdd45d012012-10-08 09:04:34 -07004424 }
4425
RoboErik4197cb62015-01-21 15:45:32 -08004426 public void mute(boolean state) {
John Spurlock22b9ee12015-02-18 22:51:44 -05004427 boolean changed = false;
Eric Laurentfdbee862014-05-12 15:26:12 -07004428 synchronized (VolumeStreamState.class) {
RoboErik4197cb62015-01-21 15:45:32 -08004429 if (state != mIsMuted) {
John Spurlock22b9ee12015-02-18 22:51:44 -05004430 changed = true;
RoboErik4197cb62015-01-21 15:45:32 -08004431 mIsMuted = state;
John Spurlock22b9ee12015-02-18 22:51:44 -05004432
RoboErik4197cb62015-01-21 15:45:32 -08004433 // Set the new mute volume. This propagates the values to
4434 // the audio system, otherwise the volume won't be changed
4435 // at the lower level.
4436 sendMsg(mAudioHandler,
4437 MSG_SET_ALL_VOLUMES,
4438 SENDMSG_QUEUE,
4439 0,
4440 0,
4441 this, 0);
Eric Laurentfdbee862014-05-12 15:26:12 -07004442 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004443 }
John Spurlock22b9ee12015-02-18 22:51:44 -05004444 if (changed) {
4445 // Stream mute changed, fire the intent.
4446 Intent intent = new Intent(AudioManager.STREAM_MUTE_CHANGED_ACTION);
4447 intent.putExtra(AudioManager.EXTRA_VOLUME_STREAM_TYPE, mStreamType);
4448 intent.putExtra(AudioManager.EXTRA_STREAM_VOLUME_MUTED, state);
4449 sendBroadcastToAll(intent);
4450 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004451 }
4452
Eric Laurent6d517662012-04-23 18:42:39 -07004453 public int getStreamType() {
4454 return mStreamType;
4455 }
4456
Eric Laurent212532b2014-07-21 15:43:18 -07004457 public void checkFixedVolumeDevices() {
Jean-Michel Trivi58850372018-09-14 16:01:28 -07004458 final boolean isAvrcpAbsVolSupported = mDeviceBroker.isAvrcpAbsoluteVolumeSupported();
Eric Laurent212532b2014-07-21 15:43:18 -07004459 synchronized (VolumeStreamState.class) {
4460 // ignore settings for fixed volume devices: volume should always be at max or 0
4461 if (mStreamVolumeAlias[mStreamType] == AudioSystem.STREAM_MUSIC) {
John Spurlock2bb02ec2015-03-02 13:13:06 -05004462 for (int i = 0; i < mIndexMap.size(); i++) {
4463 int device = mIndexMap.keyAt(i);
4464 int index = mIndexMap.valueAt(i);
Jean-Michel Triviba5270b2014-10-01 17:49:29 -07004465 if (((device & mFullVolumeDevices) != 0)
4466 || (((device & mFixedVolumeDevices) != 0) && index != 0)) {
John Spurlock2bb02ec2015-03-02 13:13:06 -05004467 mIndexMap.put(device, mIndexMax);
Eric Laurent212532b2014-07-21 15:43:18 -07004468 }
Jean-Michel Trivi58850372018-09-14 16:01:28 -07004469 applyDeviceVolume_syncVSS(device, isAvrcpAbsVolSupported);
Eric Laurent212532b2014-07-21 15:43:18 -07004470 }
4471 }
4472 }
4473 }
4474
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004475 private int getValidIndex(int index) {
John Spurlockb6e19e32015-03-10 21:33:44 -04004476 if (index < mIndexMin) {
4477 return mIndexMin;
John Spurlockee5ad722015-03-03 16:17:21 -05004478 } else if (mUseFixedVolume || index > mIndexMax) {
Eric Laurenta553c252009-07-17 12:17:14 -07004479 return mIndexMax;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004480 }
4481
4482 return index;
4483 }
4484
Eric Laurentbffc3d12012-05-07 17:43:49 -07004485 private void dump(PrintWriter pw) {
RoboErik4197cb62015-01-21 15:45:32 -08004486 pw.print(" Muted: ");
4487 pw.println(mIsMuted);
John Spurlockb6e19e32015-03-10 21:33:44 -04004488 pw.print(" Min: ");
4489 pw.println((mIndexMin + 5) / 10);
John Spurlock2b29bc42014-08-26 16:40:35 -04004490 pw.print(" Max: ");
4491 pw.println((mIndexMax + 5) / 10);
Eric Laurentbffc3d12012-05-07 17:43:49 -07004492 pw.print(" Current: ");
John Spurlock2bb02ec2015-03-02 13:13:06 -05004493 for (int i = 0; i < mIndexMap.size(); i++) {
4494 if (i > 0) {
4495 pw.print(", ");
4496 }
4497 final int device = mIndexMap.keyAt(i);
John Spurlock2b29bc42014-08-26 16:40:35 -04004498 pw.print(Integer.toHexString(device));
4499 final String deviceName = device == AudioSystem.DEVICE_OUT_DEFAULT ? "default"
4500 : AudioSystem.getOutputDeviceName(device);
4501 if (!deviceName.isEmpty()) {
4502 pw.print(" (");
4503 pw.print(deviceName);
4504 pw.print(")");
4505 }
4506 pw.print(": ");
John Spurlock2bb02ec2015-03-02 13:13:06 -05004507 final int index = (mIndexMap.valueAt(i) + 5) / 10;
John Spurlock2b29bc42014-08-26 16:40:35 -04004508 pw.print(index);
Eric Laurentbffc3d12012-05-07 17:43:49 -07004509 }
John Spurlockb32fc972015-03-05 13:58:00 -05004510 pw.println();
4511 pw.print(" Devices: ");
John Spurlock8a52c442015-03-26 14:23:58 -04004512 final int devices = getDevicesForStream(mStreamType);
John Spurlockb32fc972015-03-05 13:58:00 -05004513 int device, i = 0, n = 0;
John Spurlock1ff1e6e2015-03-09 14:21:20 -04004514 // iterate all devices from 1 to DEVICE_OUT_DEFAULT exclusive
4515 // (the default device is not returned by getDevicesForStream)
4516 while ((device = 1 << i) != AudioSystem.DEVICE_OUT_DEFAULT) {
John Spurlockb32fc972015-03-05 13:58:00 -05004517 if ((devices & device) != 0) {
4518 if (n++ > 0) {
4519 pw.print(", ");
4520 }
4521 pw.print(AudioSystem.getOutputDeviceName(device));
4522 }
4523 i++;
4524 }
Eric Laurentbffc3d12012-05-07 17:43:49 -07004525 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004526 }
4527
4528 /** Thread that handles native AudioSystem control. */
4529 private class AudioSystemThread extends Thread {
4530 AudioSystemThread() {
4531 super("AudioService");
4532 }
4533
4534 @Override
4535 public void run() {
4536 // Set this thread up so the handler will work on it
4537 Looper.prepare();
4538
4539 synchronized(AudioService.this) {
4540 mAudioHandler = new AudioHandler();
4541
4542 // Notify that the handler has been created
4543 AudioService.this.notify();
4544 }
4545
4546 // Listen for volume change requests that are set by VolumePanel
4547 Looper.loop();
4548 }
4549 }
4550
Jean-Michel Trivi58850372018-09-14 16:01:28 -07004551 /*package*/ void setDeviceVolume(VolumeStreamState streamState, int device) {
4552
4553 final boolean isAvrcpAbsVolSupported = mDeviceBroker.isAvrcpAbsoluteVolumeSupported();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004554
Eric Laurent3e6fb632018-05-21 09:28:46 -07004555 synchronized (VolumeStreamState.class) {
4556 // Apply volume
Jean-Michel Trivi58850372018-09-14 16:01:28 -07004557 streamState.applyDeviceVolume_syncVSS(device, isAvrcpAbsVolSupported);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004558
Eric Laurent3e6fb632018-05-21 09:28:46 -07004559 // Apply change to all streams using this one as alias
4560 int numStreamTypes = AudioSystem.getNumStreamTypes();
4561 for (int streamType = numStreamTypes - 1; streamType >= 0; streamType--) {
4562 if (streamType != streamState.mStreamType &&
4563 mStreamVolumeAlias[streamType] == streamState.mStreamType) {
4564 // Make sure volume is also maxed out on A2DP device for aliased stream
4565 // that may have a different device selected
4566 int streamDevice = getDeviceForStream(streamType);
Jean-Michel Trivi58850372018-09-14 16:01:28 -07004567 if ((device != streamDevice) && isAvrcpAbsVolSupported
4568 && ((device & AudioSystem.DEVICE_OUT_ALL_A2DP) != 0)) {
4569 mStreamStates[streamType].applyDeviceVolume_syncVSS(device,
4570 isAvrcpAbsVolSupported);
Eric Laurentcd772d02013-10-30 18:31:07 -07004571 }
Jean-Michel Trivi58850372018-09-14 16:01:28 -07004572 mStreamStates[streamType].applyDeviceVolume_syncVSS(streamDevice,
4573 isAvrcpAbsVolSupported);
Eric Laurenta553c252009-07-17 12:17:14 -07004574 }
4575 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004576 }
Eric Laurent3e6fb632018-05-21 09:28:46 -07004577 // Post a persist volume msg
4578 sendMsg(mAudioHandler,
4579 MSG_PERSIST_VOLUME,
4580 SENDMSG_QUEUE,
4581 device,
4582 0,
4583 streamState,
4584 PERSIST_DELAY);
4585
4586 }
4587
4588 /** Handles internal volume messages in separate volume thread. */
4589 private class AudioHandler extends Handler {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004590
Eric Laurent9bc8358d2011-11-18 16:43:31 -08004591 private void setAllVolumes(VolumeStreamState streamState) {
4592
4593 // Apply volume
4594 streamState.applyAllVolumes();
4595
4596 // Apply change to all streams using this one as alias
4597 int numStreamTypes = AudioSystem.getNumStreamTypes();
4598 for (int streamType = numStreamTypes - 1; streamType >= 0; streamType--) {
4599 if (streamType != streamState.mStreamType &&
Eric Laurent6d517662012-04-23 18:42:39 -07004600 mStreamVolumeAlias[streamType] == streamState.mStreamType) {
Eric Laurent9bc8358d2011-11-18 16:43:31 -08004601 mStreamStates[streamType].applyAllVolumes();
4602 }
4603 }
4604 }
4605
Eric Laurent42b041e2013-03-29 11:36:03 -07004606 private void persistVolume(VolumeStreamState streamState, int device) {
Eric Laurent83a017b2013-03-19 18:15:31 -07004607 if (mUseFixedVolume) {
4608 return;
4609 }
Muyuan Li1ed6df62016-06-18 11:16:52 -07004610 if (mIsSingleVolume && (streamState.mStreamType != AudioSystem.STREAM_MUSIC)) {
Eric Laurent212532b2014-07-21 15:43:18 -07004611 return;
4612 }
Jean-Michel Trivia53b7052017-04-12 18:27:01 -07004613 if (streamState.hasValidSettingsName()) {
4614 System.putIntForUser(mContentResolver,
4615 streamState.getSettingNameForDevice(device),
4616 (streamState.getIndex(device) + 5)/ 10,
4617 UserHandle.USER_CURRENT);
4618 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004619 }
4620
Glenn Kastenba195eb2011-12-13 09:30:40 -08004621 private void persistRingerMode(int ringerMode) {
Eric Laurent83a017b2013-03-19 18:15:31 -07004622 if (mUseFixedVolume) {
4623 return;
4624 }
Jeff Sharkey8d9a1f62012-10-18 15:38:14 -07004625 Settings.Global.putInt(mContentResolver, Settings.Global.MODE_RINGER, ringerMode);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004626 }
4627
Jaekyun Seokc31033f2018-01-15 14:53:17 +09004628 private String getSoundEffectFilePath(int effectType) {
4629 String filePath = Environment.getProductDirectory() + SOUND_EFFECTS_PATH
4630 + SOUND_EFFECT_FILES.get(SOUND_EFFECT_FILES_MAP[effectType][0]);
4631 if (!new File(filePath).isFile()) {
4632 filePath = Environment.getRootDirectory() + SOUND_EFFECTS_PATH
4633 + SOUND_EFFECT_FILES.get(SOUND_EFFECT_FILES_MAP[effectType][0]);
4634 }
4635 return filePath;
4636 }
4637
Eric Laurent5d3eb44a2013-03-21 15:35:10 -07004638 private boolean onLoadSoundEffects() {
4639 int status;
4640
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004641 synchronized (mSoundEffectsLock) {
Eric Laurent4a5eeb92014-05-06 10:49:04 -07004642 if (!mSystemReady) {
Eric Laurent5d3eb44a2013-03-21 15:35:10 -07004643 Log.w(TAG, "onLoadSoundEffects() called before boot complete");
4644 return false;
4645 }
4646
4647 if (mSoundPool != null) {
4648 return true;
4649 }
4650
4651 loadTouchSoundAssets();
4652
Jean-Michel Trivi55a30c42014-07-20 17:56:11 -07004653 mSoundPool = new SoundPool.Builder()
4654 .setMaxStreams(NUM_SOUNDPOOL_CHANNELS)
4655 .setAudioAttributes(new AudioAttributes.Builder()
4656 .setUsage(AudioAttributes.USAGE_ASSISTANCE_SONIFICATION)
4657 .setContentType(AudioAttributes.CONTENT_TYPE_SONIFICATION)
4658 .build())
4659 .build();
Eric Laurent5d3eb44a2013-03-21 15:35:10 -07004660 mSoundPoolCallBack = null;
4661 mSoundPoolListenerThread = new SoundPoolListenerThread();
4662 mSoundPoolListenerThread.start();
4663 int attempts = 3;
4664 while ((mSoundPoolCallBack == null) && (attempts-- > 0)) {
4665 try {
4666 // Wait for mSoundPoolCallBack to be set by the other thread
Glenn Kasten167d1a22013-07-23 16:24:41 -07004667 mSoundEffectsLock.wait(SOUND_EFFECTS_LOAD_TIMEOUT_MS);
Eric Laurent5d3eb44a2013-03-21 15:35:10 -07004668 } catch (InterruptedException e) {
4669 Log.w(TAG, "Interrupted while waiting sound pool listener thread.");
4670 }
4671 }
4672
4673 if (mSoundPoolCallBack == null) {
4674 Log.w(TAG, "onLoadSoundEffects() SoundPool listener or thread creation error");
4675 if (mSoundPoolLooper != null) {
4676 mSoundPoolLooper.quit();
4677 mSoundPoolLooper = null;
4678 }
4679 mSoundPoolListenerThread = null;
4680 mSoundPool.release();
4681 mSoundPool = null;
4682 return false;
4683 }
4684 /*
4685 * poolId table: The value -1 in this table indicates that corresponding
4686 * file (same index in SOUND_EFFECT_FILES[] has not been loaded.
4687 * Once loaded, the value in poolId is the sample ID and the same
4688 * sample can be reused for another effect using the same file.
4689 */
4690 int[] poolId = new int[SOUND_EFFECT_FILES.size()];
4691 for (int fileIdx = 0; fileIdx < SOUND_EFFECT_FILES.size(); fileIdx++) {
4692 poolId[fileIdx] = -1;
4693 }
4694 /*
4695 * Effects whose value in SOUND_EFFECT_FILES_MAP[effect][1] is -1 must be loaded.
4696 * If load succeeds, value in SOUND_EFFECT_FILES_MAP[effect][1] is > 0:
4697 * this indicates we have a valid sample loaded for this effect.
4698 */
4699
4700 int numSamples = 0;
4701 for (int effect = 0; effect < AudioManager.NUM_SOUND_EFFECTS; effect++) {
4702 // Do not load sample if this effect uses the MediaPlayer
4703 if (SOUND_EFFECT_FILES_MAP[effect][1] == 0) {
4704 continue;
4705 }
4706 if (poolId[SOUND_EFFECT_FILES_MAP[effect][0]] == -1) {
Jaekyun Seokc31033f2018-01-15 14:53:17 +09004707 String filePath = getSoundEffectFilePath(effect);
Eric Laurent5d3eb44a2013-03-21 15:35:10 -07004708 int sampleId = mSoundPool.load(filePath, 0);
4709 if (sampleId <= 0) {
4710 Log.w(TAG, "Soundpool could not load file: "+filePath);
4711 } else {
4712 SOUND_EFFECT_FILES_MAP[effect][1] = sampleId;
4713 poolId[SOUND_EFFECT_FILES_MAP[effect][0]] = sampleId;
4714 numSamples++;
4715 }
4716 } else {
4717 SOUND_EFFECT_FILES_MAP[effect][1] =
4718 poolId[SOUND_EFFECT_FILES_MAP[effect][0]];
4719 }
4720 }
4721 // wait for all samples to be loaded
4722 if (numSamples > 0) {
4723 mSoundPoolCallBack.setSamples(poolId);
4724
4725 attempts = 3;
4726 status = 1;
4727 while ((status == 1) && (attempts-- > 0)) {
4728 try {
Glenn Kasten167d1a22013-07-23 16:24:41 -07004729 mSoundEffectsLock.wait(SOUND_EFFECTS_LOAD_TIMEOUT_MS);
Eric Laurent5d3eb44a2013-03-21 15:35:10 -07004730 status = mSoundPoolCallBack.status();
4731 } catch (InterruptedException e) {
4732 Log.w(TAG, "Interrupted while waiting sound pool callback.");
4733 }
4734 }
4735 } else {
4736 status = -1;
4737 }
4738
4739 if (mSoundPoolLooper != null) {
4740 mSoundPoolLooper.quit();
4741 mSoundPoolLooper = null;
4742 }
4743 mSoundPoolListenerThread = null;
4744 if (status != 0) {
4745 Log.w(TAG,
4746 "onLoadSoundEffects(), Error "+status+ " while loading samples");
4747 for (int effect = 0; effect < AudioManager.NUM_SOUND_EFFECTS; effect++) {
4748 if (SOUND_EFFECT_FILES_MAP[effect][1] > 0) {
4749 SOUND_EFFECT_FILES_MAP[effect][1] = -1;
4750 }
4751 }
4752
4753 mSoundPool.release();
4754 mSoundPool = null;
4755 }
4756 }
4757 return (status == 0);
4758 }
4759
4760 /**
4761 * Unloads samples from the sound pool.
4762 * This method can be called to free some memory when
4763 * sound effects are disabled.
4764 */
4765 private void onUnloadSoundEffects() {
4766 synchronized (mSoundEffectsLock) {
4767 if (mSoundPool == null) {
4768 return;
4769 }
4770
4771 int[] poolId = new int[SOUND_EFFECT_FILES.size()];
4772 for (int fileIdx = 0; fileIdx < SOUND_EFFECT_FILES.size(); fileIdx++) {
4773 poolId[fileIdx] = 0;
4774 }
4775
4776 for (int effect = 0; effect < AudioManager.NUM_SOUND_EFFECTS; effect++) {
4777 if (SOUND_EFFECT_FILES_MAP[effect][1] <= 0) {
4778 continue;
4779 }
4780 if (poolId[SOUND_EFFECT_FILES_MAP[effect][0]] == 0) {
4781 mSoundPool.unload(SOUND_EFFECT_FILES_MAP[effect][1]);
4782 SOUND_EFFECT_FILES_MAP[effect][1] = -1;
4783 poolId[SOUND_EFFECT_FILES_MAP[effect][0]] = -1;
4784 }
4785 }
4786 mSoundPool.release();
4787 mSoundPool = null;
4788 }
4789 }
4790
4791 private void onPlaySoundEffect(int effectType, int volume) {
4792 synchronized (mSoundEffectsLock) {
4793
4794 onLoadSoundEffects();
4795
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004796 if (mSoundPool == null) {
4797 return;
4798 }
Eric Laurenta2ef57d2009-09-28 04:46:10 -07004799 float volFloat;
Eric Laurent25101b02011-02-02 09:33:30 -08004800 // use default if volume is not specified by caller
Eric Laurenta2ef57d2009-09-28 04:46:10 -07004801 if (volume < 0) {
Jean-Michel Trivif2b0c112012-07-09 11:59:11 -07004802 volFloat = (float)Math.pow(10, (float)sSoundEffectVolumeDb/20);
Eric Laurenta2ef57d2009-09-28 04:46:10 -07004803 } else {
RoboErik8a2cfc32014-05-16 11:19:38 -07004804 volFloat = volume / 1000.0f;
Eric Laurenta2ef57d2009-09-28 04:46:10 -07004805 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004806
4807 if (SOUND_EFFECT_FILES_MAP[effectType][1] > 0) {
Eric Laurent5d3eb44a2013-03-21 15:35:10 -07004808 mSoundPool.play(SOUND_EFFECT_FILES_MAP[effectType][1],
4809 volFloat, volFloat, 0, 0, 1.0f);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004810 } else {
4811 MediaPlayer mediaPlayer = new MediaPlayer();
Glenn Kasten62b9aec2011-11-07 11:10:16 -08004812 try {
Jaekyun Seokc31033f2018-01-15 14:53:17 +09004813 String filePath = getSoundEffectFilePath(effectType);
Glenn Kasten62b9aec2011-11-07 11:10:16 -08004814 mediaPlayer.setDataSource(filePath);
4815 mediaPlayer.setAudioStreamType(AudioSystem.STREAM_SYSTEM);
4816 mediaPlayer.prepare();
Glenn Kasten068225d2012-02-27 16:21:04 -08004817 mediaPlayer.setVolume(volFloat);
Glenn Kasten62b9aec2011-11-07 11:10:16 -08004818 mediaPlayer.setOnCompletionListener(new OnCompletionListener() {
4819 public void onCompletion(MediaPlayer mp) {
4820 cleanupPlayer(mp);
4821 }
4822 });
4823 mediaPlayer.setOnErrorListener(new OnErrorListener() {
4824 public boolean onError(MediaPlayer mp, int what, int extra) {
4825 cleanupPlayer(mp);
4826 return true;
4827 }
4828 });
4829 mediaPlayer.start();
4830 } catch (IOException ex) {
4831 Log.w(TAG, "MediaPlayer IOException: "+ex);
4832 } catch (IllegalArgumentException ex) {
4833 Log.w(TAG, "MediaPlayer IllegalArgumentException: "+ex);
4834 } catch (IllegalStateException ex) {
4835 Log.w(TAG, "MediaPlayer IllegalStateException: "+ex);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004836 }
4837 }
4838 }
4839 }
4840
4841 private void cleanupPlayer(MediaPlayer mp) {
4842 if (mp != null) {
4843 try {
4844 mp.stop();
4845 mp.release();
4846 } catch (IllegalStateException ex) {
4847 Log.w(TAG, "MediaPlayer IllegalStateException: "+ex);
4848 }
4849 }
4850 }
4851
Eric Laurent05274f32012-11-29 12:48:18 -08004852 private void onPersistSafeVolumeState(int state) {
4853 Settings.Global.putInt(mContentResolver,
4854 Settings.Global.AUDIO_SAFE_VOLUME_STATE,
4855 state);
4856 }
4857
Jean-Michel Trivi7ed71472018-02-02 16:52:09 -08004858 private void onNotifyVolumeEvent(@NonNull IAudioPolicyCallback apc,
4859 @AudioManager.VolumeAdjustment int direction) {
4860 try {
4861 apc.notifyVolumeAdjust(direction);
4862 } catch(Exception e) {
4863 // nothing we can do about this. Do not log error, too much potential for spam
4864 }
4865 }
4866
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004867 @Override
4868 public void handleMessage(Message msg) {
Eric Laurentafbb0472011-12-15 09:04:23 -08004869 switch (msg.what) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004870
Eric Laurent9bc8358d2011-11-18 16:43:31 -08004871 case MSG_SET_DEVICE_VOLUME:
4872 setDeviceVolume((VolumeStreamState) msg.obj, msg.arg1);
4873 break;
4874
4875 case MSG_SET_ALL_VOLUMES:
4876 setAllVolumes((VolumeStreamState) msg.obj);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004877 break;
4878
4879 case MSG_PERSIST_VOLUME:
Eric Laurent42b041e2013-03-29 11:36:03 -07004880 persistVolume((VolumeStreamState) msg.obj, msg.arg1);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004881 break;
4882
4883 case MSG_PERSIST_RINGER_MODE:
Glenn Kastenba195eb2011-12-13 09:30:40 -08004884 // note that the value persisted is the current ringer mode, not the
4885 // value of ringer mode as of the time the request was made to persist
John Spurlock661f2cf2014-11-17 10:29:10 -05004886 persistRingerMode(getRingerModeInternal());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004887 break;
4888
Andy Hunged0ea402015-10-30 14:11:46 -07004889 case MSG_AUDIO_SERVER_DIED:
4890 onAudioServerDied();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004891 break;
4892
Eric Laurent1d3cdce2018-01-20 10:31:21 -08004893 case MSG_DISPATCH_AUDIO_SERVER_STATE:
4894 onDispatchAudioServerStateChange(msg.arg1 == 1);
4895 break;
4896
Eric Laurent5d3eb44a2013-03-21 15:35:10 -07004897 case MSG_UNLOAD_SOUND_EFFECTS:
4898 onUnloadSoundEffects();
4899 break;
4900
Eric Laurent117b7bb2011-01-16 17:07:27 -08004901 case MSG_LOAD_SOUND_EFFECTS:
Eric Laurent5d3eb44a2013-03-21 15:35:10 -07004902 //FIXME: onLoadSoundEffects() should be executed in a separate thread as it
4903 // can take several dozens of milliseconds to complete
4904 boolean loaded = onLoadSoundEffects();
4905 if (msg.obj != null) {
4906 LoadSoundEffectReply reply = (LoadSoundEffectReply)msg.obj;
4907 synchronized (reply) {
4908 reply.mStatus = loaded ? 0 : -1;
4909 reply.notify();
4910 }
4911 }
Eric Laurent117b7bb2011-01-16 17:07:27 -08004912 break;
4913
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004914 case MSG_PLAY_SOUND_EFFECT:
Eric Laurent5d3eb44a2013-03-21 15:35:10 -07004915 onPlaySoundEffect(msg.arg1, msg.arg2);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004916 break;
Jean-Michel Trivi4c637b92010-04-12 18:44:10 -07004917
Eric Laurentfa640152011-03-12 15:59:51 -08004918 case MSG_SET_FORCE_USE:
Jean-Michel Trivi58850372018-09-14 16:01:28 -07004919 {
4920 final String eventSource = (String) msg.obj;
4921 final int useCase = msg.arg1;
4922 final int config = msg.arg2;
4923 if (useCase == AudioSystem.FOR_MEDIA) {
4924 Log.wtf(TAG, "Invalid force use FOR_MEDIA in AudioService from "
4925 + eventSource);
4926 break;
Paul McLean10804eb2015-01-28 11:16:35 -08004927 }
Jean-Michel Trivi58850372018-09-14 16:01:28 -07004928 sForceUseLogger.log(
4929 new AudioServiceEvents.ForceUseEvent(useCase, config, eventSource));
4930 AudioSystem.setForceUse(useCase, config);
4931 }
Aniket Kumar Lataa8439e22019-01-11 03:59:00 -08004932 break;
4933
Jean-Michel Trivi92ed7bf2017-06-26 19:32:38 -07004934 case MSG_DISABLE_AUDIO_FOR_UID:
4935 mPlaybackMonitor.disableAudioForUid( msg.arg1 == 1 /* disable */,
4936 msg.arg2 /* uid */);
4937 mAudioEventWakeLock.release();
4938 break;
4939
Eric Laurentc34dcc12012-09-10 13:51:52 -07004940 case MSG_CHECK_MUSIC_ACTIVE:
John Spurlock90874332015-03-10 16:00:54 -04004941 onCheckMusicActive((String) msg.obj);
Eric Laurentc34dcc12012-09-10 13:51:52 -07004942 break;
Eric Laurent5bfaeae2012-09-21 18:44:48 -07004943
Eric Laurentd640bd32012-09-28 18:01:48 -07004944 case MSG_CONFIGURE_SAFE_MEDIA_VOLUME_FORCED:
4945 case MSG_CONFIGURE_SAFE_MEDIA_VOLUME:
John Spurlock90874332015-03-10 16:00:54 -04004946 onConfigureSafeVolume((msg.what == MSG_CONFIGURE_SAFE_MEDIA_VOLUME_FORCED),
4947 (String) msg.obj);
Eric Laurentd640bd32012-09-28 18:01:48 -07004948 break;
Eric Laurent05274f32012-11-29 12:48:18 -08004949 case MSG_PERSIST_SAFE_VOLUME_STATE:
4950 onPersistSafeVolumeState(msg.arg1);
4951 break;
Jean-Michel Trivia578c482012-12-28 11:19:49 -08004952
Eric Laurent4a5eeb92014-05-06 10:49:04 -07004953 case MSG_SYSTEM_READY:
4954 onSystemReady();
4955 break;
John Spurlockaa5ee4d2014-07-25 13:05:12 -04004956
Eric Laurent0867bed2015-05-20 14:49:08 -07004957 case MSG_INDICATE_SYSTEM_READY:
4958 onIndicateSystemReady();
4959 break;
4960
Jean-Michel Trivi1ab43f62017-04-27 15:37:34 -07004961 case MSG_ACCESSORY_PLUG_MEDIA_UNMUTE:
4962 onAccessoryPlugMediaUnmute(msg.arg1);
4963 break;
4964
John Spurlockaa5ee4d2014-07-25 13:05:12 -04004965 case MSG_PERSIST_MUSIC_ACTIVE_MS:
4966 final int musicActiveMs = msg.arg1;
4967 Settings.Secure.putIntForUser(mContentResolver,
4968 Settings.Secure.UNSAFE_VOLUME_MUSIC_ACTIVE_MS, musicActiveMs,
4969 UserHandle.USER_CURRENT);
4970 break;
Eric Laurentc0232482016-03-15 18:19:23 -07004971
RoboErik5452e252015-02-06 15:33:53 -08004972 case MSG_UNMUTE_STREAM:
4973 onUnmuteStream(msg.arg1, msg.arg2);
4974 break;
Eric Laurentc0232482016-03-15 18:19:23 -07004975
Jean-Michel Trivi5a561092015-04-23 18:48:08 -07004976 case MSG_DYN_POLICY_MIX_STATE_UPDATE:
4977 onDynPolicyMixStateUpdate((String) msg.obj, msg.arg1);
4978 break;
Jean-Michel Trivi7ed71472018-02-02 16:52:09 -08004979
4980 case MSG_NOTIFY_VOL_EVENT:
4981 onNotifyVolumeEvent((IAudioPolicyCallback) msg.obj, msg.arg1);
4982 break;
jiabin39940752018-04-02 18:18:45 -07004983
4984 case MSG_ENABLE_SURROUND_FORMATS:
4985 onEnableSurroundFormats((ArrayList<Integer>) msg.obj);
4986 break;
Jean-Michel Trivica49d312019-02-14 15:55:39 -08004987
4988 case MSG_UPDATE_RINGER_MODE:
4989 onUpdateRingerModeServiceInt();
4990 break;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004991 }
4992 }
4993 }
4994
Jason Parekhb1096152009-03-24 17:48:25 -07004995 private class SettingsObserver extends ContentObserver {
Eric Laurenta553c252009-07-17 12:17:14 -07004996
Jason Parekhb1096152009-03-24 17:48:25 -07004997 SettingsObserver() {
4998 super(new Handler());
Beverlyd6964762018-02-16 14:07:03 -05004999 mContentResolver.registerContentObserver(Settings.Global.getUriFor(
5000 Settings.Global.ZEN_MODE), false, this);
5001 mContentResolver.registerContentObserver(Settings.Global.getUriFor(
5002 Settings.Global.ZEN_MODE_CONFIG_ETAG), false, this);
Jason Parekhb1096152009-03-24 17:48:25 -07005003 mContentResolver.registerContentObserver(Settings.System.getUriFor(
5004 Settings.System.MODE_RINGER_STREAMS_AFFECTED), false, this);
Eric Laurent7ee1e4f2012-10-26 18:11:21 -07005005 mContentResolver.registerContentObserver(Settings.Global.getUriFor(
5006 Settings.Global.DOCK_AUDIO_MEDIA_ENABLED), false, this);
Andy Hung7b98e9a2016-02-25 18:34:50 -08005007 mContentResolver.registerContentObserver(Settings.System.getUriFor(
5008 Settings.System.MASTER_MONO), false, this);
Edward Savage-Jones35c292f2017-01-13 09:04:34 +01005009 mContentResolver.registerContentObserver(Settings.System.getUriFor(
5010 Settings.System.MASTER_BALANCE), false, this);
Phil Burked43bf52016-03-01 17:01:35 -08005011
5012 mEncodedSurroundMode = Settings.Global.getInt(
5013 mContentResolver, Settings.Global.ENCODED_SURROUND_OUTPUT,
5014 Settings.Global.ENCODED_SURROUND_OUTPUT_AUTO);
5015 mContentResolver.registerContentObserver(Settings.Global.getUriFor(
5016 Settings.Global.ENCODED_SURROUND_OUTPUT), false, this);
jiabin39940752018-04-02 18:18:45 -07005017
5018 mEnabledSurroundFormats = Settings.Global.getString(
5019 mContentResolver, Settings.Global.ENCODED_SURROUND_OUTPUT_ENABLED_FORMATS);
5020 mContentResolver.registerContentObserver(Settings.Global.getUriFor(
5021 Settings.Global.ENCODED_SURROUND_OUTPUT_ENABLED_FORMATS), false, this);
Eric Laurent1c9c1d52018-10-17 10:06:46 -07005022
5023 mContentResolver.registerContentObserver(Settings.Secure.getUriFor(
5024 Settings.Secure.VOICE_INTERACTION_SERVICE), false, this);
Jason Parekhb1096152009-03-24 17:48:25 -07005025 }
5026
5027 @Override
5028 public void onChange(boolean selfChange) {
5029 super.onChange(selfChange);
Glenn Kastenba195eb2011-12-13 09:30:40 -08005030 // FIXME This synchronized is not necessary if mSettingsLock only protects mRingerMode.
Beverlyd6964762018-02-16 14:07:03 -05005031 // However there appear to be some missing locks around mRingerAndZenModeMutedStreams
Glenn Kastenba195eb2011-12-13 09:30:40 -08005032 // and mRingerModeAffectedStreams, so will leave this synchronized for now.
Beverlyd6964762018-02-16 14:07:03 -05005033 // mRingerAndZenModeMutedStreams and mMuteAffectedStreams are safe (only accessed once).
Eric Laurenta553c252009-07-17 12:17:14 -07005034 synchronized (mSettingsLock) {
Beverlyd6964762018-02-16 14:07:03 -05005035 if (updateRingerAndZenModeAffectedStreams()) {
Eric Laurenta553c252009-07-17 12:17:14 -07005036 /*
5037 * Ensure all stream types that should be affected by ringer mode
5038 * are in the proper state.
5039 */
John Spurlock661f2cf2014-11-17 10:29:10 -05005040 setRingerModeInt(getRingerModeInternal(), false);
Eric Laurenta553c252009-07-17 12:17:14 -07005041 }
Eric Laurent7ee1e4f2012-10-26 18:11:21 -07005042 readDockAudioSettings(mContentResolver);
Andy Hung7b98e9a2016-02-25 18:34:50 -08005043 updateMasterMono(mContentResolver);
Edward Savage-Jones35c292f2017-01-13 09:04:34 +01005044 updateMasterBalance(mContentResolver);
Phil Burked43bf52016-03-01 17:01:35 -08005045 updateEncodedSurroundOutput();
jiabin39940752018-04-02 18:18:45 -07005046 sendEnabledSurroundFormats(mContentResolver, mSurroundModeChanged);
Eric Laurent1c9c1d52018-10-17 10:06:46 -07005047 updateAssistantUId(false);
Phil Burked43bf52016-03-01 17:01:35 -08005048 }
5049 }
5050
5051 private void updateEncodedSurroundOutput() {
5052 int newSurroundMode = Settings.Global.getInt(
5053 mContentResolver, Settings.Global.ENCODED_SURROUND_OUTPUT,
5054 Settings.Global.ENCODED_SURROUND_OUTPUT_AUTO);
5055 // Did it change?
5056 if (mEncodedSurroundMode != newSurroundMode) {
5057 // Send to AudioPolicyManager
Jean-Michel Trivi011f39e2017-08-19 18:08:06 -07005058 sendEncodedSurroundMode(newSurroundMode, "SettingsObserver");
Jean-Michel Trivi58850372018-09-14 16:01:28 -07005059 mDeviceBroker.toggleHdmiIfConnected_Async();
Phil Burked43bf52016-03-01 17:01:35 -08005060 mEncodedSurroundMode = newSurroundMode;
jiabin39940752018-04-02 18:18:45 -07005061 mSurroundModeChanged = true;
5062 } else {
5063 mSurroundModeChanged = false;
Eric Laurenta553c252009-07-17 12:17:14 -07005064 }
Jason Parekhb1096152009-03-24 17:48:25 -07005065 }
Jason Parekhb1096152009-03-24 17:48:25 -07005066 }
Eric Laurenta553c252009-07-17 12:17:14 -07005067
John Du5a0cf7a2013-07-19 11:30:34 -07005068 public void avrcpSupportsAbsoluteVolume(String address, boolean support) {
5069 // address is not used for now, but may be used when multiple a2dp devices are supported
Jean-Michel Trivi58850372018-09-14 16:01:28 -07005070 mDeviceBroker.setAvrcpAbsoluteVolumeSupported(support);
5071 sendMsg(mAudioHandler, MSG_SET_DEVICE_VOLUME, SENDMSG_QUEUE,
Eric Laurent3e6fb632018-05-21 09:28:46 -07005072 AudioSystem.DEVICE_OUT_BLUETOOTH_A2DP, 0,
5073 mStreamStates[AudioSystem.STREAM_MUSIC], 0);
Eric Laurentb1fbaac2012-05-29 09:24:28 -07005074 }
5075
Jean-Michel Trivi7db2d8f2018-03-06 10:30:59 -08005076 /**
5077 * @return true if there is currently a registered dynamic mixing policy that affects media
5078 */
Jean-Michel Trivi58850372018-09-14 16:01:28 -07005079 /*package*/ boolean hasMediaDynamicPolicy() {
Jean-Michel Trivi7db2d8f2018-03-06 10:30:59 -08005080 synchronized (mAudioPolicies) {
5081 if (mAudioPolicies.isEmpty()) {
5082 return false;
5083 }
5084 final Collection<AudioPolicyProxy> appColl = mAudioPolicies.values();
5085 for (AudioPolicyProxy app : appColl) {
5086 if (app.hasMixAffectingUsage(AudioAttributes.USAGE_MEDIA)) {
5087 return true;
5088 }
5089 }
5090 return false;
5091 }
5092 }
5093
Jean-Michel Trivi58850372018-09-14 16:01:28 -07005094 /*package*/ void checkMusicActive(int deviceType, String caller) {
5095 if ((deviceType & mSafeMediaVolumeDevices) != 0) {
5096 sendMsg(mAudioHandler,
5097 MSG_CHECK_MUSIC_ACTIVE,
5098 SENDMSG_REPLACE,
5099 0,
5100 0,
5101 caller,
5102 MUSIC_ACTIVE_POLL_PERIOD_MS);
Dianne Hackborn632ca412012-06-14 19:34:10 -07005103 }
Eric Laurenteab40d12017-06-09 12:45:21 -07005104 }
5105
Eric Laurenta553c252009-07-17 12:17:14 -07005106 /**
5107 * Receiver for misc intent broadcasts the Phone app cares about.
5108 */
5109 private class AudioServiceBroadcastReceiver extends BroadcastReceiver {
5110 @Override
5111 public void onReceive(Context context, Intent intent) {
Jean-Michel Trivi58850372018-09-14 16:01:28 -07005112 final String action = intent.getAction();
Eric Laurentae4506e2014-05-29 16:04:32 -07005113 int outDevice;
5114 int inDevice;
Eric Laurent59f48272012-04-05 19:42:21 -07005115 int state;
Eric Laurenta553c252009-07-17 12:17:14 -07005116
Jean-Michel Trivi758559e2010-03-09 09:26:08 -08005117 if (action.equals(Intent.ACTION_DOCK_EVENT)) {
5118 int dockState = intent.getIntExtra(Intent.EXTRA_DOCK_STATE,
5119 Intent.EXTRA_DOCK_STATE_UNDOCKED);
5120 int config;
5121 switch (dockState) {
5122 case Intent.EXTRA_DOCK_STATE_DESK:
5123 config = AudioSystem.FORCE_BT_DESK_DOCK;
5124 break;
5125 case Intent.EXTRA_DOCK_STATE_CAR:
5126 config = AudioSystem.FORCE_BT_CAR_DOCK;
5127 break;
Praveen Bharathi21e941b2010-10-06 15:23:14 -05005128 case Intent.EXTRA_DOCK_STATE_LE_DESK:
Eric Laurent08ed1b92012-11-05 14:54:12 -08005129 config = AudioSystem.FORCE_ANALOG_DOCK;
Praveen Bharathi21e941b2010-10-06 15:23:14 -05005130 break;
5131 case Intent.EXTRA_DOCK_STATE_HE_DESK:
5132 config = AudioSystem.FORCE_DIGITAL_DOCK;
5133 break;
Jean-Michel Trivi758559e2010-03-09 09:26:08 -08005134 case Intent.EXTRA_DOCK_STATE_UNDOCKED:
5135 default:
5136 config = AudioSystem.FORCE_NONE;
5137 }
Eric Laurent08ed1b92012-11-05 14:54:12 -08005138 // Low end docks have a menu to enable or disable audio
5139 // (see mDockAudioMediaEnabled)
Jean-Michel Trivi58850372018-09-14 16:01:28 -07005140 if (!((dockState == Intent.EXTRA_DOCK_STATE_LE_DESK)
5141 || ((dockState == Intent.EXTRA_DOCK_STATE_UNDOCKED)
5142 && (mDockState == Intent.EXTRA_DOCK_STATE_LE_DESK)))) {
5143 mDeviceBroker.setForceUse_Async(AudioSystem.FOR_DOCK, config,
5144 "ACTION_DOCK_EVENT intent");
Eric Laurent08ed1b92012-11-05 14:54:12 -08005145 }
5146 mDockState = dockState;
Jean-Michel Trivi58850372018-09-14 16:01:28 -07005147 } else if (action.equals(BluetoothHeadset.ACTION_ACTIVE_DEVICE_CHANGED)
5148 || action.equals(BluetoothHeadset.ACTION_AUDIO_STATE_CHANGED)) {
5149 mDeviceBroker.receiveBtEvent(intent);
Eric Laurent950e8cb2011-10-13 08:57:54 -07005150 } else if (action.equals(Intent.ACTION_SCREEN_ON)) {
Jon Eklund318f0fe2014-01-23 17:53:48 -06005151 if (mMonitorRotation) {
Jean-Michel Trivi24806db2015-10-01 15:00:59 -07005152 RotationHelper.enable();
Jon Eklund318f0fe2014-01-23 17:53:48 -06005153 }
Eric Laurent950e8cb2011-10-13 08:57:54 -07005154 AudioSystem.setParameters("screen_state=on");
5155 } else if (action.equals(Intent.ACTION_SCREEN_OFF)) {
Jon Eklund318f0fe2014-01-23 17:53:48 -06005156 if (mMonitorRotation) {
5157 //reduce wakeups (save current) by only listening when display is on
Jean-Michel Trivi24806db2015-10-01 15:00:59 -07005158 RotationHelper.disable();
Jon Eklund318f0fe2014-01-23 17:53:48 -06005159 }
Eric Laurent950e8cb2011-10-13 08:57:54 -07005160 AudioSystem.setParameters("screen_state=off");
Dianne Hackborn961cae92013-03-20 14:59:43 -07005161 } else if (action.equals(Intent.ACTION_CONFIGURATION_CHANGED)) {
Jean-Michel Trivif26f0172012-04-25 16:23:20 -07005162 handleConfigurationChanged(context);
Eric Laurentbc0fab1f2012-09-19 11:24:41 -07005163 } else if (action.equals(Intent.ACTION_USER_SWITCHED)) {
Yasuhiro Matsuda4ced7192015-07-10 22:08:44 +09005164 if (mUserSwitchedReceived) {
5165 // attempt to stop music playback for background user except on first user
5166 // switch (i.e. first boot)
Jean-Michel Trivib9465152019-02-06 15:20:19 -08005167 mDeviceBroker.postBroadcastBecomingNoisy();
Yasuhiro Matsuda4ced7192015-07-10 22:08:44 +09005168 }
5169 mUserSwitchedReceived = true;
Jean-Michel Trivif4a8eb22012-10-29 12:42:55 -07005170 // the current audio focus owner is no longer valid
Jean-Michel Trivifa9a6982013-06-27 16:22:58 -07005171 mMediaFocusControl.discardAudioFocusOwner();
Jean-Michel Trivif4a8eb22012-10-29 12:42:55 -07005172
Eric Laurent5bfaeae2012-09-21 18:44:48 -07005173 // load volume settings for new user
Eric Laurentbc0fab1f2012-09-19 11:24:41 -07005174 readAudioSettings(true /*userSwitch*/);
5175 // preserve STREAM_MUSIC volume from one user to the next.
5176 sendMsg(mAudioHandler,
5177 MSG_SET_ALL_VOLUMES,
5178 SENDMSG_QUEUE,
5179 0,
5180 0,
5181 mStreamStates[AudioSystem.STREAM_MUSIC], 0);
Fyodor Kupolovb5013302015-04-17 17:59:14 -07005182 } else if (action.equals(Intent.ACTION_USER_BACKGROUND)) {
5183 // Disable audio recording for the background user/profile
5184 int userId = intent.getIntExtra(Intent.EXTRA_USER_HANDLE, -1);
5185 if (userId >= 0) {
5186 // TODO Kill recording streams instead of killing processes holding permission
5187 UserInfo userInfo = UserManagerService.getInstance().getUserInfo(userId);
5188 killBackgroundUserProcessesWithRecordAudioPermission(userInfo);
5189 }
Makoto Onukiac65e1e2015-11-20 15:33:17 -08005190 UserManagerService.getInstance().setUserRestriction(
Fyodor Kupolovb5013302015-04-17 17:59:14 -07005191 UserManager.DISALLOW_RECORD_AUDIO, true, userId);
5192 } else if (action.equals(Intent.ACTION_USER_FOREGROUND)) {
5193 // Enable audio recording for foreground user/profile
5194 int userId = intent.getIntExtra(Intent.EXTRA_USER_HANDLE, -1);
Makoto Onukiac65e1e2015-11-20 15:33:17 -08005195 UserManagerService.getInstance().setUserRestriction(
Fyodor Kupolovb5013302015-04-17 17:59:14 -07005196 UserManager.DISALLOW_RECORD_AUDIO, false, userId);
Eric Laurentb70b78a2016-01-13 19:16:04 -08005197 } else if (action.equals(BluetoothAdapter.ACTION_STATE_CHANGED)) {
5198 state = intent.getIntExtra(BluetoothAdapter.EXTRA_STATE, -1);
5199 if (state == BluetoothAdapter.STATE_OFF ||
5200 state == BluetoothAdapter.STATE_TURNING_OFF) {
Jean-Michel Trivi58850372018-09-14 16:01:28 -07005201 mDeviceBroker.disconnectAllBluetoothProfiles();
Eric Laurentb70b78a2016-01-13 19:16:04 -08005202 }
Marco Nelissenfb6df0b2017-02-15 15:25:24 -08005203 } else if (action.equals(AudioEffect.ACTION_OPEN_AUDIO_EFFECT_CONTROL_SESSION) ||
5204 action.equals(AudioEffect.ACTION_CLOSE_AUDIO_EFFECT_CONTROL_SESSION)) {
5205 handleAudioEffectBroadcast(context, intent);
Jean-Michel Trivib2251822019-02-06 07:32:06 -08005206 } else if (action.equals(Intent.ACTION_PACKAGES_SUSPENDED)) {
5207 final int[] suspendedUids = intent.getIntArrayExtra(Intent.EXTRA_CHANGED_UID_LIST);
5208 final String[] suspendedPackages =
5209 intent.getStringArrayExtra(Intent.EXTRA_CHANGED_PACKAGE_LIST);
5210 if (suspendedPackages == null || suspendedUids == null
5211 || suspendedPackages.length != suspendedUids.length) {
5212 return;
5213 }
5214 for (int i = 0; i < suspendedUids.length; i++) {
5215 if (!TextUtils.isEmpty(suspendedPackages[i])) {
5216 mMediaFocusControl.noFocusForSuspendedApp(
5217 suspendedPackages[i], suspendedUids[i]);
5218 }
5219 }
Eric Laurenta553c252009-07-17 12:17:14 -07005220 }
5221 }
Paul McLeanc837a452014-04-09 09:04:43 -07005222 } // end class AudioServiceBroadcastReceiver
Jean-Michel Trivid5176cf2010-01-28 11:56:42 -08005223
Makoto Onukid45a4a22015-11-02 17:17:38 -08005224 private class AudioServiceUserRestrictionsListener implements UserRestrictionsListener {
5225
5226 @Override
5227 public void onUserRestrictionsChanged(int userId, Bundle newRestrictions,
5228 Bundle prevRestrictions) {
5229 // Update mic mute state.
5230 {
5231 final boolean wasRestricted =
5232 prevRestrictions.getBoolean(UserManager.DISALLOW_UNMUTE_MICROPHONE);
5233 final boolean isRestricted =
5234 newRestrictions.getBoolean(UserManager.DISALLOW_UNMUTE_MICROPHONE);
5235 if (wasRestricted != isRestricted) {
5236 setMicrophoneMuteNoCallerCheck(isRestricted, userId);
5237 }
5238 }
5239
5240 // Update speaker mute state.
5241 {
5242 final boolean wasRestricted =
Tony Makc1205112016-07-22 16:02:59 +01005243 prevRestrictions.getBoolean(UserManager.DISALLOW_ADJUST_VOLUME)
Esteban Talavera492b4722017-02-13 14:59:45 +00005244 || prevRestrictions.getBoolean(UserManager.DISALLOW_UNMUTE_DEVICE);
Makoto Onukid45a4a22015-11-02 17:17:38 -08005245 final boolean isRestricted =
Tony Makc1205112016-07-22 16:02:59 +01005246 newRestrictions.getBoolean(UserManager.DISALLOW_ADJUST_VOLUME)
Esteban Talavera492b4722017-02-13 14:59:45 +00005247 || newRestrictions.getBoolean(UserManager.DISALLOW_UNMUTE_DEVICE);
Makoto Onukid45a4a22015-11-02 17:17:38 -08005248 if (wasRestricted != isRestricted) {
5249 setMasterMuteInternalNoCallerCheck(isRestricted, /* flags =*/ 0, userId);
5250 }
5251 }
5252 }
5253 } // end class AudioServiceUserRestrictionsListener
5254
Marco Nelissenfb6df0b2017-02-15 15:25:24 -08005255 private void handleAudioEffectBroadcast(Context context, Intent intent) {
5256 String target = intent.getPackage();
5257 if (target != null) {
5258 Log.w(TAG, "effect broadcast already targeted to " + target);
5259 return;
5260 }
5261 intent.addFlags(Intent.FLAG_INCLUDE_STOPPED_PACKAGES);
5262 // TODO this should target a user-selected panel
5263 List<ResolveInfo> ril = context.getPackageManager().queryBroadcastReceivers(
5264 intent, 0 /* flags */);
5265 if (ril != null && ril.size() != 0) {
5266 ResolveInfo ri = ril.get(0);
5267 if (ri != null && ri.activityInfo != null && ri.activityInfo.packageName != null) {
5268 intent.setPackage(ri.activityInfo.packageName);
5269 context.sendBroadcastAsUser(intent, UserHandle.ALL);
5270 return;
5271 }
5272 }
5273 Log.w(TAG, "couldn't find receiver package for effect intent");
5274 }
5275
Fyodor Kupolovb5013302015-04-17 17:59:14 -07005276 private void killBackgroundUserProcessesWithRecordAudioPermission(UserInfo oldUser) {
5277 PackageManager pm = mContext.getPackageManager();
5278 // Find the home activity of the user. It should not be killed to avoid expensive restart,
5279 // when the user switches back. For managed profiles, we should kill all recording apps
5280 ComponentName homeActivityName = null;
5281 if (!oldUser.isManagedProfile()) {
Wale Ogunwale6767eae2018-05-03 15:52:51 -07005282 homeActivityName = LocalServices.getService(
5283 ActivityTaskManagerInternal.class).getHomeActivityForUser(oldUser.id);
Fyodor Kupolovb5013302015-04-17 17:59:14 -07005284 }
5285 final String[] permissions = { Manifest.permission.RECORD_AUDIO };
5286 List<PackageInfo> packages;
5287 try {
5288 packages = AppGlobals.getPackageManager()
5289 .getPackagesHoldingPermissions(permissions, 0, oldUser.id).getList();
5290 } catch (RemoteException e) {
5291 throw new AndroidRuntimeException(e);
5292 }
5293 for (int j = packages.size() - 1; j >= 0; j--) {
5294 PackageInfo pkg = packages.get(j);
Fyodor Kupolovbcb6c1e2015-05-11 12:05:15 -07005295 // Skip system processes
5296 if (UserHandle.getAppId(pkg.applicationInfo.uid) < FIRST_APPLICATION_UID) {
5297 continue;
5298 }
Amith Yamasanic1cbaab2015-07-21 11:46:14 -07005299 // Skip packages that have permission to interact across users
5300 if (pm.checkPermission(Manifest.permission.INTERACT_ACROSS_USERS, pkg.packageName)
5301 == PackageManager.PERMISSION_GRANTED) {
5302 continue;
5303 }
Fyodor Kupolovb5013302015-04-17 17:59:14 -07005304 if (homeActivityName != null
5305 && pkg.packageName.equals(homeActivityName.getPackageName())
5306 && pkg.applicationInfo.isSystemApp()) {
5307 continue;
5308 }
5309 try {
Svetoslavaa41add2015-08-06 15:03:55 -07005310 final int uid = pkg.applicationInfo.uid;
Sudheer Shankadc589ac2016-11-10 15:30:17 -08005311 ActivityManager.getService().killUid(UserHandle.getAppId(uid),
Svetoslavaa41add2015-08-06 15:03:55 -07005312 UserHandle.getUserId(uid),
Fyodor Kupolovb5013302015-04-17 17:59:14 -07005313 "killBackgroundUserProcessesWithAudioRecordPermission");
5314 } catch (RemoteException e) {
5315 Log.w(TAG, "Error calling killUid", e);
5316 }
5317 }
5318 }
5319
Jean-Michel Trivi3114ce32012-06-11 15:03:52 -07005320
Jean-Michel Trivifa9a6982013-06-27 16:22:58 -07005321 //==========================================================================================
5322 // Audio Focus
5323 //==========================================================================================
Jean-Michel Trivi9228af62018-01-05 17:06:17 -08005324 /**
5325 * Returns whether a focus request is eligible to force ducking.
5326 * Will return true if:
5327 * - the AudioAttributes have a usage of USAGE_ASSISTANCE_ACCESSIBILITY,
5328 * - the focus request is AUDIOFOCUS_GAIN_TRANSIENT_MAY_DUCK,
5329 * - the associated Bundle has KEY_ACCESSIBILITY_FORCE_FOCUS_DUCKING set to true,
5330 * - the uid of the requester is a known accessibility service or root.
5331 * @param aa AudioAttributes of the focus request
5332 * @param uid uid of the focus requester
5333 * @return true if ducking is to be forced
5334 */
5335 private boolean forceFocusDuckingForAccessibility(@Nullable AudioAttributes aa,
5336 int request, int uid) {
5337 if (aa == null || aa.getUsage() != AudioAttributes.USAGE_ASSISTANCE_ACCESSIBILITY
5338 || request != AudioManager.AUDIOFOCUS_GAIN_TRANSIENT_MAY_DUCK) {
5339 return false;
5340 }
5341 final Bundle extraInfo = aa.getBundle();
5342 if (extraInfo == null ||
5343 !extraInfo.getBoolean(AudioFocusRequest.KEY_ACCESSIBILITY_FORCE_FOCUS_DUCKING)) {
5344 return false;
5345 }
5346 if (uid == 0) {
5347 return true;
5348 }
5349 synchronized (mAccessibilityServiceUidsLock) {
5350 if (mAccessibilityServiceUids != null) {
5351 int callingUid = Binder.getCallingUid();
5352 for (int i = 0; i < mAccessibilityServiceUids.length; i++) {
5353 if (mAccessibilityServiceUids[i] == callingUid) {
5354 return true;
5355 }
5356 }
5357 }
5358 }
5359 return false;
5360 }
5361
Jean-Michel Trivifd6ad742014-11-10 14:38:30 -08005362 public int requestAudioFocus(AudioAttributes aa, int durationHint, IBinder cb,
Jean-Michel Trivi958876f2014-11-16 15:40:22 -08005363 IAudioFocusDispatcher fd, String clientId, String callingPackageName, int flags,
Jean-Michel Trivi461922f2017-04-25 15:23:17 -07005364 IAudioPolicyCallback pcb, int sdk) {
Jean-Michel Trivi958876f2014-11-16 15:40:22 -08005365 // permission checks
5366 if ((flags & AudioManager.AUDIOFOCUS_FLAG_LOCK) == AudioManager.AUDIOFOCUS_FLAG_LOCK) {
John Spurlock61560172015-02-06 19:46:04 -05005367 if (AudioSystem.IN_VOICE_COMM_FOCUS_ID.equals(clientId)) {
Jean-Michel Trivi958876f2014-11-16 15:40:22 -08005368 if (PackageManager.PERMISSION_GRANTED != mContext.checkCallingOrSelfPermission(
5369 android.Manifest.permission.MODIFY_PHONE_STATE)) {
5370 Log.e(TAG, "Invalid permission to (un)lock audio focus", new Exception());
5371 return AudioManager.AUDIOFOCUS_REQUEST_FAILED;
5372 }
5373 } else {
5374 // only a registered audio policy can be used to lock focus
5375 synchronized (mAudioPolicies) {
Jean-Michel Trivi0212be52014-11-24 14:43:10 -08005376 if (!mAudioPolicies.containsKey(pcb.asBinder())) {
5377 Log.e(TAG, "Invalid unregistered AudioPolicy to (un)lock audio focus");
Jean-Michel Trivi958876f2014-11-16 15:40:22 -08005378 return AudioManager.AUDIOFOCUS_REQUEST_FAILED;
5379 }
5380 }
5381 }
5382 }
5383
Jean-Michel Trivib2251822019-02-06 07:32:06 -08005384 if (callingPackageName == null || clientId == null || aa == null) {
5385 Log.e(TAG, "Invalid null parameter to request audio focus");
5386 return AudioManager.AUDIOFOCUS_REQUEST_FAILED;
5387 }
5388
Jean-Michel Trivifd6ad742014-11-10 14:38:30 -08005389 return mMediaFocusControl.requestAudioFocus(aa, durationHint, cb, fd,
Jean-Michel Trivi9228af62018-01-05 17:06:17 -08005390 clientId, callingPackageName, flags, sdk,
5391 forceFocusDuckingForAccessibility(aa, durationHint, Binder.getCallingUid()));
Jean-Michel Trivifa9a6982013-06-27 16:22:58 -07005392 }
5393
Jean-Michel Trivi126cf032017-04-02 23:19:02 -07005394 public int abandonAudioFocus(IAudioFocusDispatcher fd, String clientId, AudioAttributes aa,
5395 String callingPackageName) {
5396 return mMediaFocusControl.abandonAudioFocus(fd, clientId, aa, callingPackageName);
Jean-Michel Trivifa9a6982013-06-27 16:22:58 -07005397 }
5398
5399 public void unregisterAudioFocusClient(String clientId) {
5400 mMediaFocusControl.unregisterAudioFocusClient(clientId);
Jean-Michel Trivi3114ce32012-06-11 15:03:52 -07005401 }
5402
Jean-Michel Trivi23805662013-07-31 14:19:18 -07005403 public int getCurrentAudioFocus() {
5404 return mMediaFocusControl.getCurrentAudioFocus();
5405 }
5406
Jean-Michel Trivi99489cc2017-01-25 19:08:49 -08005407 public int getFocusRampTimeMs(int focusGain, AudioAttributes attr) {
5408 return mMediaFocusControl.getFocusRampTimeMs(focusGain, attr);
5409 }
5410
Jean-Michel Trivi126cf032017-04-02 23:19:02 -07005411 //==========================================================================================
John Spurlock5e783732015-02-19 10:28:59 -05005412 private boolean readCameraSoundForced() {
5413 return SystemProperties.getBoolean("audio.camerasound.force", false) ||
5414 mContext.getResources().getBoolean(
5415 com.android.internal.R.bool.config_camera_sound_forced);
5416 }
5417
Jean-Michel Trivif26f0172012-04-25 16:23:20 -07005418 //==========================================================================================
5419 // Device orientation
5420 //==========================================================================================
5421 /**
Mikhail Naganovb668bc62018-02-13 13:46:38 -08005422 * Handles device configuration changes that may map to a change in rotation.
5423 * Monitoring rotation is optional, and is defined by the definition and value
5424 * of the "ro.audio.monitorRotation" system property.
Jean-Michel Trivif26f0172012-04-25 16:23:20 -07005425 */
5426 private void handleConfigurationChanged(Context context) {
5427 try {
Mikhail Naganovb668bc62018-02-13 13:46:38 -08005428 // reading new configuration "safely" (i.e. under try catch) in case anything
5429 // goes wrong.
Eric Laurentd640bd32012-09-28 18:01:48 -07005430 Configuration config = context.getResources().getConfiguration();
Eric Laurentd640bd32012-09-28 18:01:48 -07005431 sendMsg(mAudioHandler,
5432 MSG_CONFIGURE_SAFE_MEDIA_VOLUME,
5433 SENDMSG_REPLACE,
5434 0,
5435 0,
John Spurlock90874332015-03-10 16:00:54 -04005436 TAG,
Eric Laurentd640bd32012-09-28 18:01:48 -07005437 0);
Eric Laurentdd45d012012-10-08 09:04:34 -07005438
John Spurlock5e783732015-02-19 10:28:59 -05005439 boolean cameraSoundForced = readCameraSoundForced();
Eric Laurentdd45d012012-10-08 09:04:34 -07005440 synchronized (mSettingsLock) {
Jean-Michel Trivi8719a1d2017-11-06 11:52:51 -08005441 final boolean cameraSoundForcedChanged = (cameraSoundForced != mCameraSoundForced);
5442 mCameraSoundForced = cameraSoundForced;
Eric Laurent8fa4d6f2014-10-30 14:13:03 -07005443 if (cameraSoundForcedChanged) {
Muyuan Li1ed6df62016-06-18 11:16:52 -07005444 if (!mIsSingleVolume) {
Jean-Michel Trivi085346a2018-02-14 10:48:51 -08005445 synchronized (VolumeStreamState.class) {
5446 VolumeStreamState s = mStreamStates[AudioSystem.STREAM_SYSTEM_ENFORCED];
5447 if (cameraSoundForced) {
5448 s.setAllIndexesToMax();
5449 mRingerModeAffectedStreams &=
5450 ~(1 << AudioSystem.STREAM_SYSTEM_ENFORCED);
5451 } else {
5452 s.setAllIndexes(mStreamStates[AudioSystem.STREAM_SYSTEM], TAG);
5453 mRingerModeAffectedStreams |=
5454 (1 << AudioSystem.STREAM_SYSTEM_ENFORCED);
5455 }
Eric Laurent8fa4d6f2014-10-30 14:13:03 -07005456 }
5457 // take new state into account for streams muted by ringer mode
John Spurlock661f2cf2014-11-17 10:29:10 -05005458 setRingerModeInt(getRingerModeInternal(), false);
Eric Laurent8fa4d6f2014-10-30 14:13:03 -07005459 }
Jean-Michel Trivi58850372018-09-14 16:01:28 -07005460 mDeviceBroker.setForceUse_Async(AudioSystem.FOR_SYSTEM,
Eric Laurent8fa4d6f2014-10-30 14:13:03 -07005461 cameraSoundForced ?
5462 AudioSystem.FORCE_SYSTEM_ENFORCED : AudioSystem.FORCE_NONE,
Jean-Michel Trivi58850372018-09-14 16:01:28 -07005463 "handleConfigurationChanged");
Eric Laurent8fa4d6f2014-10-30 14:13:03 -07005464 sendMsg(mAudioHandler,
5465 MSG_SET_ALL_VOLUMES,
5466 SENDMSG_QUEUE,
5467 0,
5468 0,
5469 mStreamStates[AudioSystem.STREAM_SYSTEM_ENFORCED], 0);
Jean-Michel Trivi58850372018-09-14 16:01:28 -07005470
Eric Laurent8fa4d6f2014-10-30 14:13:03 -07005471 }
Eric Laurentdd45d012012-10-08 09:04:34 -07005472 }
John Spurlock3346a802014-05-20 16:25:37 -04005473 mVolumeController.setLayoutDirection(config.getLayoutDirection());
Jean-Michel Trivif26f0172012-04-25 16:23:20 -07005474 } catch (Exception e) {
Jean-Michel Trivibb6f8712013-05-23 15:02:41 -07005475 Log.e(TAG, "Error handling configuration change: ", e);
Jean-Michel Trivif26f0172012-04-25 16:23:20 -07005476 }
5477 }
5478
Jean-Michel Trivid5176cf2010-01-28 11:56:42 -08005479 @Override
Jeff Sharkey098d5802012-04-26 17:30:34 -07005480 public void setRingtonePlayer(IRingtonePlayer player) {
5481 mContext.enforceCallingOrSelfPermission(REMOTE_AUDIO_PLAYBACK, null);
5482 mRingtonePlayer = player;
5483 }
5484
5485 @Override
5486 public IRingtonePlayer getRingtonePlayer() {
5487 return mRingtonePlayer;
5488 }
5489
5490 @Override
Dianne Hackborn632ca412012-06-14 19:34:10 -07005491 public AudioRoutesInfo startWatchingRoutes(IAudioRoutesObserver observer) {
Jean-Michel Trivi58850372018-09-14 16:01:28 -07005492 return mDeviceBroker.startWatchingRoutes(observer);
Dianne Hackborn632ca412012-06-14 19:34:10 -07005493 }
5494
Eric Laurentc34dcc12012-09-10 13:51:52 -07005495
5496 //==========================================================================================
5497 // Safe media volume management.
5498 // MUSIC stream volume level is limited when headphones are connected according to safety
5499 // regulation. When the user attempts to raise the volume above the limit, a warning is
5500 // displayed and the user has to acknowlegde before the volume is actually changed.
5501 // The volume index corresponding to the limit is stored in config_safe_media_volume_index
5502 // property. Platforms with a different limit must set this property accordingly in their
5503 // overlay.
5504 //==========================================================================================
5505
Eric Laurentd640bd32012-09-28 18:01:48 -07005506 // mSafeMediaVolumeState indicates whether the media volume is limited over headphones.
5507 // It is SAFE_MEDIA_VOLUME_NOT_CONFIGURED at boot time until a network service is connected
5508 // or the configure time is elapsed. It is then set to SAFE_MEDIA_VOLUME_ACTIVE or
5509 // SAFE_MEDIA_VOLUME_DISABLED according to country option. If not SAFE_MEDIA_VOLUME_DISABLED, it
5510 // can be set to SAFE_MEDIA_VOLUME_INACTIVE by calling AudioService.disableSafeMediaVolume()
5511 // (when user opts out).
John Spurlock35134602014-07-24 18:10:48 -04005512 private static final int SAFE_MEDIA_VOLUME_NOT_CONFIGURED = 0;
5513 private static final int SAFE_MEDIA_VOLUME_DISABLED = 1;
5514 private static final int SAFE_MEDIA_VOLUME_INACTIVE = 2; // confirmed
5515 private static final int SAFE_MEDIA_VOLUME_ACTIVE = 3; // unconfirmed
hyomin.ohd0446dc2018-10-18 13:58:27 +09005516 private int mSafeMediaVolumeState;
5517 private final Object mSafeMediaVolumeStateLock = new Object();
Eric Laurentd640bd32012-09-28 18:01:48 -07005518
5519 private int mMcc = 0;
Eric Laurentc34dcc12012-09-10 13:51:52 -07005520 // mSafeMediaVolumeIndex is the cached value of config_safe_media_volume_index property
Eric Laurentd640bd32012-09-28 18:01:48 -07005521 private int mSafeMediaVolumeIndex;
John Muir8b8bddd2018-02-16 14:29:14 -08005522 // mSafeUsbMediaVolumeDbfs is the cached value of the config_safe_media_volume_usb_mB
5523 // property, divided by 100.0.
5524 private float mSafeUsbMediaVolumeDbfs;
Eric Laurentb378a13a2017-07-11 14:08:11 -07005525 // mSafeUsbMediaVolumeIndex is used for USB Headsets and is the music volume UI index
John Muir8b8bddd2018-02-16 14:29:14 -08005526 // corresponding to a gain of mSafeUsbMediaVolumeDbfs (defaulting to -37dB) in audio
5527 // flinger mixer.
Eric Laurent0e5deb32017-09-01 15:12:42 -07005528 // We remove -22 dBs from the theoretical -15dB to account for the EQ + bass boost
5529 // amplification when both effects are on with all band gains at maximum.
Eric Laurentb378a13a2017-07-11 14:08:11 -07005530 // This level corresponds to a loudness of 85 dB SPL for the warning to be displayed when
5531 // the headset is compliant to EN 60950 with a max loudness of 100dB SPL.
Eric Laurenteab40d12017-06-09 12:45:21 -07005532 private int mSafeUsbMediaVolumeIndex;
Eric Laurentc34dcc12012-09-10 13:51:52 -07005533 // mSafeMediaVolumeDevices lists the devices for which safe media volume is enforced,
Jean-Michel Trivi58850372018-09-14 16:01:28 -07005534 /*package*/ final int mSafeMediaVolumeDevices = AudioSystem.DEVICE_OUT_WIRED_HEADSET
5535 | AudioSystem.DEVICE_OUT_WIRED_HEADPHONE
5536 | AudioSystem.DEVICE_OUT_USB_HEADSET;
Eric Laurentc34dcc12012-09-10 13:51:52 -07005537 // mMusicActiveMs is the cumulative time of music activity since safe volume was disabled.
5538 // When this time reaches UNSAFE_VOLUME_MUSIC_ACTIVE_MS_MAX, the safe media volume is re-enabled
5539 // automatically. mMusicActiveMs is rounded to a multiple of MUSIC_ACTIVE_POLL_PERIOD_MS.
5540 private int mMusicActiveMs;
5541 private static final int UNSAFE_VOLUME_MUSIC_ACTIVE_MS_MAX = (20 * 3600 * 1000); // 20 hours
5542 private static final int MUSIC_ACTIVE_POLL_PERIOD_MS = 60000; // 1 minute polling interval
Eric Laurentd640bd32012-09-28 18:01:48 -07005543 private static final int SAFE_VOLUME_CONFIGURE_TIMEOUT_MS = 30000; // 30s after boot completed
Eric Laurentc34dcc12012-09-10 13:51:52 -07005544
Eric Laurenteab40d12017-06-09 12:45:21 -07005545 private int safeMediaVolumeIndex(int device) {
5546 if ((device & mSafeMediaVolumeDevices) == 0) {
5547 return MAX_STREAM_VOLUME[AudioSystem.STREAM_MUSIC];
5548 }
5549 if (device == AudioSystem.DEVICE_OUT_USB_HEADSET) {
5550 return mSafeUsbMediaVolumeIndex;
5551 } else {
5552 return mSafeMediaVolumeIndex;
5553 }
5554 }
5555
John Spurlock90874332015-03-10 16:00:54 -04005556 private void setSafeMediaVolumeEnabled(boolean on, String caller) {
hyomin.ohd0446dc2018-10-18 13:58:27 +09005557 synchronized (mSafeMediaVolumeStateLock) {
Eric Laurentd640bd32012-09-28 18:01:48 -07005558 if ((mSafeMediaVolumeState != SAFE_MEDIA_VOLUME_NOT_CONFIGURED) &&
5559 (mSafeMediaVolumeState != SAFE_MEDIA_VOLUME_DISABLED)) {
5560 if (on && (mSafeMediaVolumeState == SAFE_MEDIA_VOLUME_INACTIVE)) {
5561 mSafeMediaVolumeState = SAFE_MEDIA_VOLUME_ACTIVE;
John Spurlock90874332015-03-10 16:00:54 -04005562 enforceSafeMediaVolume(caller);
Eric Laurentd640bd32012-09-28 18:01:48 -07005563 } else if (!on && (mSafeMediaVolumeState == SAFE_MEDIA_VOLUME_ACTIVE)) {
5564 mSafeMediaVolumeState = SAFE_MEDIA_VOLUME_INACTIVE;
John Spurlockaa5ee4d2014-07-25 13:05:12 -04005565 mMusicActiveMs = 1; // nonzero = confirmed
5566 saveMusicActiveMs();
Eric Laurentd640bd32012-09-28 18:01:48 -07005567 sendMsg(mAudioHandler,
5568 MSG_CHECK_MUSIC_ACTIVE,
5569 SENDMSG_REPLACE,
5570 0,
5571 0,
John Spurlock90874332015-03-10 16:00:54 -04005572 caller,
Eric Laurentd640bd32012-09-28 18:01:48 -07005573 MUSIC_ACTIVE_POLL_PERIOD_MS);
5574 }
Eric Laurentc34dcc12012-09-10 13:51:52 -07005575 }
Eric Laurentc34dcc12012-09-10 13:51:52 -07005576 }
5577 }
5578
John Spurlock90874332015-03-10 16:00:54 -04005579 private void enforceSafeMediaVolume(String caller) {
Eric Laurentc34dcc12012-09-10 13:51:52 -07005580 VolumeStreamState streamState = mStreamStates[AudioSystem.STREAM_MUSIC];
Eric Laurentc34dcc12012-09-10 13:51:52 -07005581 int devices = mSafeMediaVolumeDevices;
5582 int i = 0;
5583
5584 while (devices != 0) {
5585 int device = 1 << i++;
5586 if ((device & devices) == 0) {
5587 continue;
5588 }
Eric Laurent42b041e2013-03-29 11:36:03 -07005589 int index = streamState.getIndex(device);
Eric Laurenteab40d12017-06-09 12:45:21 -07005590 if (index > safeMediaVolumeIndex(device)) {
5591 streamState.setIndex(safeMediaVolumeIndex(device), device, caller);
Eric Laurent42b041e2013-03-29 11:36:03 -07005592 sendMsg(mAudioHandler,
5593 MSG_SET_DEVICE_VOLUME,
5594 SENDMSG_QUEUE,
5595 device,
5596 0,
5597 streamState,
5598 0);
Eric Laurentc34dcc12012-09-10 13:51:52 -07005599 }
5600 devices &= ~device;
5601 }
5602 }
5603
5604 private boolean checkSafeMediaVolume(int streamType, int index, int device) {
hyomin.ohd0446dc2018-10-18 13:58:27 +09005605 synchronized (mSafeMediaVolumeStateLock) {
Eric Laurentd640bd32012-09-28 18:01:48 -07005606 if ((mSafeMediaVolumeState == SAFE_MEDIA_VOLUME_ACTIVE) &&
Eric Laurentc34dcc12012-09-10 13:51:52 -07005607 (mStreamVolumeAlias[streamType] == AudioSystem.STREAM_MUSIC) &&
5608 ((device & mSafeMediaVolumeDevices) != 0) &&
Eric Laurenteab40d12017-06-09 12:45:21 -07005609 (index > safeMediaVolumeIndex(device))) {
Eric Laurentc34dcc12012-09-10 13:51:52 -07005610 return false;
5611 }
5612 return true;
5613 }
5614 }
5615
John Spurlock3346a802014-05-20 16:25:37 -04005616 @Override
John Spurlock90874332015-03-10 16:00:54 -04005617 public void disableSafeMediaVolume(String callingPackage) {
John Spurlockcdb57ae2015-02-11 19:04:11 -05005618 enforceVolumeController("disable the safe media volume");
hyomin.ohd0446dc2018-10-18 13:58:27 +09005619 synchronized (mSafeMediaVolumeStateLock) {
John Spurlock90874332015-03-10 16:00:54 -04005620 setSafeMediaVolumeEnabled(false, callingPackage);
Eric Laurentfde16d52012-12-03 14:42:39 -08005621 if (mPendingVolumeCommand != null) {
5622 onSetStreamVolume(mPendingVolumeCommand.mStreamType,
5623 mPendingVolumeCommand.mIndex,
5624 mPendingVolumeCommand.mFlags,
John Spurlock90874332015-03-10 16:00:54 -04005625 mPendingVolumeCommand.mDevice,
5626 callingPackage);
Eric Laurentfde16d52012-12-03 14:42:39 -08005627 mPendingVolumeCommand = null;
5628 }
Eric Laurentc34dcc12012-09-10 13:51:52 -07005629 }
5630 }
5631
Jungshik Jang41d97462014-06-30 22:26:29 +09005632 //==========================================================================================
5633 // Hdmi Cec system audio mode.
John Spurlockbc82b122015-03-02 16:12:38 -05005634 // If Hdmi Cec's system audio mode is on, audio service should send the volume change
5635 // to HdmiControlService so that the audio receiver can handle it.
Jungshik Jang41d97462014-06-30 22:26:29 +09005636 //==========================================================================================
5637
Eric Laurent212532b2014-07-21 15:43:18 -07005638 private class MyDisplayStatusCallback implements HdmiPlaybackClient.DisplayStatusCallback {
5639 public void onComplete(int status) {
Shubangc480a712018-06-11 18:02:42 -07005640 synchronized (mHdmiClientLock) {
5641 if (mHdmiManager != null) {
Eric Laurent212532b2014-07-21 15:43:18 -07005642 mHdmiCecSink = (status != HdmiControlManager.POWER_STATUS_UNKNOWN);
5643 // Television devices without CEC service apply software volume on HDMI output
5644 if (isPlatformTelevision() && !mHdmiCecSink) {
5645 mFixedVolumeDevices &= ~AudioSystem.DEVICE_OUT_HDMI;
5646 }
5647 checkAllFixedVolumeDevices();
5648 }
5649 }
5650 }
Shubangc480a712018-06-11 18:02:42 -07005651 }
5652
5653 private final Object mHdmiClientLock = new Object();
Eric Laurent212532b2014-07-21 15:43:18 -07005654
Jungshik Jang41d97462014-06-30 22:26:29 +09005655 // If HDMI-CEC system audio is supported
5656 private boolean mHdmiSystemAudioSupported = false;
5657 // Set only when device is tv.
Shubangc480a712018-06-11 18:02:42 -07005658 @GuardedBy("mHdmiClientLock")
Jungshik Jang41d97462014-06-30 22:26:29 +09005659 private HdmiTvClient mHdmiTvClient;
Eric Laurent0b03f992014-11-18 18:08:02 -08005660 // true if the device has system feature PackageManager.FEATURE_LEANBACK.
Eric Laurent212532b2014-07-21 15:43:18 -07005661 // cached HdmiControlManager interface
Shubangc480a712018-06-11 18:02:42 -07005662 @GuardedBy("mHdmiClientLock")
Eric Laurent212532b2014-07-21 15:43:18 -07005663 private HdmiControlManager mHdmiManager;
5664 // Set only when device is a set-top box.
Shubangc480a712018-06-11 18:02:42 -07005665 @GuardedBy("mHdmiClientLock")
Eric Laurent212532b2014-07-21 15:43:18 -07005666 private HdmiPlaybackClient mHdmiPlaybackClient;
5667 // true if we are a set-top box, an HDMI sink is connected and it supports CEC.
5668 private boolean mHdmiCecSink;
Shubangc480a712018-06-11 18:02:42 -07005669 // Set only when device is an audio system.
5670 @GuardedBy("mHdmiClientLock")
5671 private HdmiAudioSystemClient mHdmiAudioSystemClient;
Eric Laurent212532b2014-07-21 15:43:18 -07005672
5673 private MyDisplayStatusCallback mHdmiDisplayStatusCallback = new MyDisplayStatusCallback();
Jungshik Jang41d97462014-06-30 22:26:29 +09005674
5675 @Override
Jungshik Jang12307ca2014-07-15 19:27:56 +09005676 public int setHdmiSystemAudioSupported(boolean on) {
Eric Laurent212532b2014-07-21 15:43:18 -07005677 int device = AudioSystem.DEVICE_NONE;
Shubangc480a712018-06-11 18:02:42 -07005678 synchronized (mHdmiClientLock) {
5679 if (mHdmiManager != null) {
Shubangde728822018-07-16 16:46:51 -07005680 if (mHdmiTvClient == null && mHdmiAudioSystemClient == null) {
5681 Log.w(TAG, "Only Hdmi-Cec enabled TV or audio system device supports"
5682 + "system audio mode.");
Eric Laurent212532b2014-07-21 15:43:18 -07005683 return device;
5684 }
Shubangc480a712018-06-11 18:02:42 -07005685 if (mHdmiSystemAudioSupported != on) {
5686 mHdmiSystemAudioSupported = on;
5687 final int config = on ? AudioSystem.FORCE_HDMI_SYSTEM_AUDIO_ENFORCED :
5688 AudioSystem.FORCE_NONE;
Jean-Michel Trivi58850372018-09-14 16:01:28 -07005689 mDeviceBroker.setForceUse_Async(AudioSystem.FOR_HDMI_SYSTEM_AUDIO, config,
5690 "setHdmiSystemAudioSupported");
Eric Laurent212532b2014-07-21 15:43:18 -07005691 }
Shubangc480a712018-06-11 18:02:42 -07005692 device = getDevicesForStream(AudioSystem.STREAM_MUSIC);
Jungshik Jang6f34f5a2014-07-08 21:17:29 +09005693 }
Jungshik Jang6f34f5a2014-07-08 21:17:29 +09005694 }
Eric Laurent212532b2014-07-21 15:43:18 -07005695 return device;
Jungshik Jang6f34f5a2014-07-08 21:17:29 +09005696 }
Jungshik Jang41d97462014-06-30 22:26:29 +09005697
Terry Heoe7d6d972014-09-04 21:05:28 +09005698 @Override
5699 public boolean isHdmiSystemAudioSupported() {
5700 return mHdmiSystemAudioSupported;
5701 }
5702
Eric Laurentdd45d012012-10-08 09:04:34 -07005703 //==========================================================================================
Jean-Michel Triviac487672016-11-11 10:05:18 -08005704 // Accessibility
5705
Jean-Michel Trivicfa55532017-01-18 11:17:51 -08005706 private void initA11yMonitoring() {
5707 final AccessibilityManager accessibilityManager =
5708 (AccessibilityManager) mContext.getSystemService(Context.ACCESSIBILITY_SERVICE);
Jean-Michel Triviac487672016-11-11 10:05:18 -08005709 updateDefaultStreamOverrideDelay(accessibilityManager.isTouchExplorationEnabled());
Jean-Michel Trivi7592b982017-02-01 15:12:15 -08005710 updateA11yVolumeAlias(accessibilityManager.isAccessibilityVolumeStreamActive());
Phil Weaver26d709f2017-04-20 17:19:14 -07005711 accessibilityManager.addTouchExplorationStateChangeListener(this, null);
5712 accessibilityManager.addAccessibilityServicesStateChangeListener(this, null);
Jean-Michel Triviac487672016-11-11 10:05:18 -08005713 }
5714
5715 //---------------------------------------------------------------------------------
5716 // A11y: taking touch exploration into account for selecting the default
Jean-Michel Trivi873cc452014-09-11 17:25:09 -07005717 // stream override timeout when adjusting volume
Jean-Michel Triviac487672016-11-11 10:05:18 -08005718 //---------------------------------------------------------------------------------
Jean-Michel Trivi873cc452014-09-11 17:25:09 -07005719
Jean-Michel Triviac487672016-11-11 10:05:18 -08005720 // - STREAM_NOTIFICATION on tablets during this period after a notification stopped
Julia Reynoldsd9e96e22017-11-07 10:33:08 -05005721 // - STREAM_RING on phones during this period after a notification stopped
5722 // - STREAM_MUSIC otherwise
5723
Jean-Michel Triviac487672016-11-11 10:05:18 -08005724 private static final int DEFAULT_STREAM_TYPE_OVERRIDE_DELAY_MS = 0;
5725 private static final int TOUCH_EXPLORE_STREAM_TYPE_OVERRIDE_DELAY_MS = 1000;
Jean-Michel Trivi873cc452014-09-11 17:25:09 -07005726
Jean-Michel Triviac487672016-11-11 10:05:18 -08005727 private static int sStreamOverrideDelayMs;
Jean-Michel Trivi873cc452014-09-11 17:25:09 -07005728
Jean-Michel Triviac487672016-11-11 10:05:18 -08005729 @Override
5730 public void onTouchExplorationStateChanged(boolean enabled) {
5731 updateDefaultStreamOverrideDelay(enabled);
5732 }
5733
5734 private void updateDefaultStreamOverrideDelay(boolean touchExploreEnabled) {
5735 if (touchExploreEnabled) {
5736 sStreamOverrideDelayMs = TOUCH_EXPLORE_STREAM_TYPE_OVERRIDE_DELAY_MS;
5737 } else {
5738 sStreamOverrideDelayMs = DEFAULT_STREAM_TYPE_OVERRIDE_DELAY_MS;
Jean-Michel Trivi873cc452014-09-11 17:25:09 -07005739 }
Jean-Michel Triviac487672016-11-11 10:05:18 -08005740 if (DEBUG_VOL) Log.d(TAG, "Touch exploration enabled=" + touchExploreEnabled
5741 + " stream override delay is now " + sStreamOverrideDelayMs + " ms");
5742 }
Jean-Michel Trivi873cc452014-09-11 17:25:09 -07005743
Jean-Michel Triviac487672016-11-11 10:05:18 -08005744 //---------------------------------------------------------------------------------
5745 // A11y: taking a11y state into account for the handling of a11y prompts volume
5746 //---------------------------------------------------------------------------------
Jean-Michel Trivi873cc452014-09-11 17:25:09 -07005747
Jean-Michel Triviac487672016-11-11 10:05:18 -08005748 private static boolean sIndependentA11yVolume = false;
5749
Jean-Michel Trivicfa55532017-01-18 11:17:51 -08005750 // implementation of AccessibilityServicesStateChangeListener
5751 @Override
Phil Weaver4cab9302017-03-30 15:27:39 -07005752 public void onAccessibilityServicesStateChanged(AccessibilityManager accessibilityManager) {
Jean-Michel Trivicfa55532017-01-18 11:17:51 -08005753 updateA11yVolumeAlias(accessibilityManager.isAccessibilityVolumeStreamActive());
5754 }
5755
5756 private void updateA11yVolumeAlias(boolean a11VolEnabled) {
5757 if (DEBUG_VOL) Log.d(TAG, "Accessibility volume enabled = " + a11VolEnabled);
5758 if (sIndependentA11yVolume != a11VolEnabled) {
5759 sIndependentA11yVolume = a11VolEnabled;
5760 // update the volume mapping scheme
5761 updateStreamVolumeAlias(true /*updateVolumes*/, TAG);
5762 // update the volume controller behavior
5763 mVolumeController.setA11yMode(sIndependentA11yVolume ?
5764 VolumePolicy.A11Y_MODE_INDEPENDENT_A11Y_VOLUME :
5765 VolumePolicy.A11Y_MODE_MEDIA_A11Y_VOLUME);
Jean-Michel Trivia53b7052017-04-12 18:27:01 -07005766 mVolumeController.postVolumeChanged(AudioManager.STREAM_ACCESSIBILITY, 0);
Jean-Michel Trivicfa55532017-01-18 11:17:51 -08005767 }
Jean-Michel Trivi873cc452014-09-11 17:25:09 -07005768 }
5769
5770 //==========================================================================================
Eric Laurentdd45d012012-10-08 09:04:34 -07005771 // Camera shutter sound policy.
5772 // config_camera_sound_forced configuration option in config.xml defines if the camera shutter
5773 // sound is forced (sound even if the device is in silent mode) or not. This option is false by
5774 // default and can be overridden by country specific overlay in values-mccXXX/config.xml.
5775 //==========================================================================================
5776
5777 // cached value of com.android.internal.R.bool.config_camera_sound_forced
Jean-Michel Trivi8719a1d2017-11-06 11:52:51 -08005778 @GuardedBy("mSettingsLock")
5779 private boolean mCameraSoundForced;
Eric Laurentdd45d012012-10-08 09:04:34 -07005780
5781 // called by android.hardware.Camera to populate CameraInfo.canDisableShutterSound
5782 public boolean isCameraSoundForced() {
Jean-Michel Trivi8719a1d2017-11-06 11:52:51 -08005783 synchronized (mSettingsLock) {
Eric Laurentdd45d012012-10-08 09:04:34 -07005784 return mCameraSoundForced;
5785 }
5786 }
5787
Jean-Michel Trivi011f39e2017-08-19 18:08:06 -07005788 //==========================================================================================
5789 // AudioService logging and dumpsys
5790 //==========================================================================================
Jean-Michel Trivi3bf75782018-07-02 10:48:04 -07005791 static final int LOG_NB_EVENTS_PHONE_STATE = 20;
5792 static final int LOG_NB_EVENTS_DEVICE_CONNECTION = 30;
5793 static final int LOG_NB_EVENTS_FORCE_USE = 20;
5794 static final int LOG_NB_EVENTS_VOLUME = 40;
5795 static final int LOG_NB_EVENTS_DYN_POLICY = 10;
Jean-Michel Trivi011f39e2017-08-19 18:08:06 -07005796
5797 final private AudioEventLogger mModeLogger = new AudioEventLogger(LOG_NB_EVENTS_PHONE_STATE,
5798 "phone state (logged after successfull call to AudioSystem.setPhoneState(int))");
5799
Jean-Michel Trivi3bf75782018-07-02 10:48:04 -07005800 // logs for wired + A2DP device connections:
5801 // - wired: logged before onSetWiredDeviceConnectionState() is executed
5802 // - A2DP: logged at reception of method call
Jean-Michel Trivi58850372018-09-14 16:01:28 -07005803 /*package*/ static final AudioEventLogger sDeviceLogger = new AudioEventLogger(
Jean-Michel Trivi44abe2c2019-02-26 18:12:54 -08005804 LOG_NB_EVENTS_DEVICE_CONNECTION, "wired/A2DP/hearing aid device connection");
Jean-Michel Trivi011f39e2017-08-19 18:08:06 -07005805
Jean-Michel Trivi58850372018-09-14 16:01:28 -07005806 static final AudioEventLogger sForceUseLogger = new AudioEventLogger(
Jean-Michel Trivi011f39e2017-08-19 18:08:06 -07005807 LOG_NB_EVENTS_FORCE_USE,
5808 "force use (logged before setForceUse() is executed)");
5809
Jean-Michel Trivi58850372018-09-14 16:01:28 -07005810 static final AudioEventLogger sVolumeLogger = new AudioEventLogger(LOG_NB_EVENTS_VOLUME,
Jean-Michel Trivicf170362017-08-24 17:24:57 -07005811 "volume changes (logged when command received by AudioService)");
5812
Jean-Michel Trivi12a86762018-04-24 16:57:49 -07005813 final private AudioEventLogger mDynPolicyLogger = new AudioEventLogger(LOG_NB_EVENTS_DYN_POLICY,
5814 "dynamic policy events (logged when command received by AudioService)");
5815
Eric Laurentdd45d012012-10-08 09:04:34 -07005816 private static final String[] RINGER_MODE_NAMES = new String[] {
5817 "SILENT",
5818 "VIBRATE",
5819 "NORMAL"
5820 };
5821
5822 private void dumpRingerMode(PrintWriter pw) {
5823 pw.println("\nRinger mode: ");
John Spurlock661f2cf2014-11-17 10:29:10 -05005824 pw.println("- mode (internal) = " + RINGER_MODE_NAMES[mRingerMode]);
5825 pw.println("- mode (external) = " + RINGER_MODE_NAMES[mRingerModeExternal]);
John Spurlock50ced3f2015-05-11 16:00:09 -04005826 dumpRingerModeStreams(pw, "affected", mRingerModeAffectedStreams);
Beverlyd6964762018-02-16 14:07:03 -05005827 dumpRingerModeStreams(pw, "muted", mRingerAndZenModeMutedStreams);
John Spurlock661f2cf2014-11-17 10:29:10 -05005828 pw.print("- delegate = "); pw.println(mRingerModeDelegate);
Eric Laurentdd45d012012-10-08 09:04:34 -07005829 }
5830
John Spurlock50ced3f2015-05-11 16:00:09 -04005831 private void dumpRingerModeStreams(PrintWriter pw, String type, int streams) {
5832 pw.print("- ringer mode "); pw.print(type); pw.print(" streams = 0x");
5833 pw.print(Integer.toHexString(streams));
5834 if (streams != 0) {
5835 pw.print(" (");
5836 boolean first = true;
5837 for (int i = 0; i < AudioSystem.STREAM_NAMES.length; i++) {
5838 final int stream = (1 << i);
5839 if ((streams & stream) != 0) {
5840 if (!first) pw.print(',');
5841 pw.print(AudioSystem.STREAM_NAMES[i]);
5842 streams &= ~stream;
5843 first = false;
5844 }
5845 }
5846 if (streams != 0) {
5847 if (!first) pw.print(',');
5848 pw.print(streams);
5849 }
5850 pw.print(')');
5851 }
5852 pw.println();
5853 }
5854
Dianne Hackborn632ca412012-06-14 19:34:10 -07005855 @Override
Jean-Michel Trivid5176cf2010-01-28 11:56:42 -08005856 protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
Jeff Sharkeyfe9a53b2017-03-31 14:08:23 -06005857 if (!DumpUtils.checkDumpPermission(mContext, TAG, pw)) return;
Jeff Sharkeyeb4cc4922012-04-26 18:17:29 -07005858
Jean-Michel Trivifa9a6982013-06-27 16:22:58 -07005859 mMediaFocusControl.dump(pw);
Eric Laurentbffc3d12012-05-07 17:43:49 -07005860 dumpStreamStates(pw);
Eric Laurentdd45d012012-10-08 09:04:34 -07005861 dumpRingerMode(pw);
Dianne Hackborn632ca412012-06-14 19:34:10 -07005862 pw.println("\nAudio routes:");
Jean-Michel Trivi58850372018-09-14 16:01:28 -07005863 pw.print(" mMainType=0x"); pw.println(Integer.toHexString(
5864 mDeviceBroker.getCurAudioRoutes().mainType));
5865 pw.print(" mBluetoothName="); pw.println(mDeviceBroker.getCurAudioRoutes().bluetoothName);
John Spurlock35134602014-07-24 18:10:48 -04005866
5867 pw.println("\nOther state:");
John Spurlock3346a802014-05-20 16:25:37 -04005868 pw.print(" mVolumeController="); pw.println(mVolumeController);
John Spurlock35134602014-07-24 18:10:48 -04005869 pw.print(" mSafeMediaVolumeState=");
5870 pw.println(safeMediaVolumeStateToString(mSafeMediaVolumeState));
5871 pw.print(" mSafeMediaVolumeIndex="); pw.println(mSafeMediaVolumeIndex);
Eric Laurenteab40d12017-06-09 12:45:21 -07005872 pw.print(" mSafeUsbMediaVolumeIndex="); pw.println(mSafeUsbMediaVolumeIndex);
John Muir8b8bddd2018-02-16 14:29:14 -08005873 pw.print(" mSafeUsbMediaVolumeDbfs="); pw.println(mSafeUsbMediaVolumeDbfs);
Jean-Michel Trivi7592b982017-02-01 15:12:15 -08005874 pw.print(" sIndependentA11yVolume="); pw.println(sIndependentA11yVolume);
John Spurlock35134602014-07-24 18:10:48 -04005875 pw.print(" mPendingVolumeCommand="); pw.println(mPendingVolumeCommand);
5876 pw.print(" mMusicActiveMs="); pw.println(mMusicActiveMs);
John Spurlockaa5ee4d2014-07-25 13:05:12 -04005877 pw.print(" mMcc="); pw.println(mMcc);
John Spurlock5e783732015-02-19 10:28:59 -05005878 pw.print(" mCameraSoundForced="); pw.println(mCameraSoundForced);
John Spurlock661f2cf2014-11-17 10:29:10 -05005879 pw.print(" mHasVibrator="); pw.println(mHasVibrator);
John Spurlocka48d7792015-03-03 17:35:57 -05005880 pw.print(" mVolumePolicy="); pw.println(mVolumePolicy);
Jean-Michel Trivi58850372018-09-14 16:01:28 -07005881 pw.print(" mAvrcpAbsVolSupported=");
5882 pw.println(mDeviceBroker.isAvrcpAbsoluteVolumeSupported());
Jean-Michel Trivi1b3541d2014-11-25 12:53:41 -08005883
5884 dumpAudioPolicies(pw);
Jean-Michel Trivi12a86762018-04-24 16:57:49 -07005885 mDynPolicyLogger.dump(pw);
Jean-Michel Trivi292a6a42016-12-01 08:32:15 -08005886
5887 mPlaybackMonitor.dump(pw);
Jean-Michel Trivi66ffacf2017-02-04 17:25:31 -08005888
5889 mRecordMonitor.dump(pw);
Jean-Michel Trivi011f39e2017-08-19 18:08:06 -07005890
Jean-Michel Trivicf170362017-08-24 17:24:57 -07005891 pw.println("\n");
Jean-Michel Trivi011f39e2017-08-19 18:08:06 -07005892 pw.println("\nEvent logs:");
5893 mModeLogger.dump(pw);
5894 pw.println("\n");
Jean-Michel Trivi58850372018-09-14 16:01:28 -07005895 sDeviceLogger.dump(pw);
Jean-Michel Trivi011f39e2017-08-19 18:08:06 -07005896 pw.println("\n");
Jean-Michel Trivi58850372018-09-14 16:01:28 -07005897 sForceUseLogger.dump(pw);
Jean-Michel Trivicf170362017-08-24 17:24:57 -07005898 pw.println("\n");
Jean-Michel Trivi58850372018-09-14 16:01:28 -07005899 sVolumeLogger.dump(pw);
John Spurlock35134602014-07-24 18:10:48 -04005900 }
5901
hyomin.ohd0446dc2018-10-18 13:58:27 +09005902 private static String safeMediaVolumeStateToString(int state) {
John Spurlock35134602014-07-24 18:10:48 -04005903 switch(state) {
5904 case SAFE_MEDIA_VOLUME_NOT_CONFIGURED: return "SAFE_MEDIA_VOLUME_NOT_CONFIGURED";
5905 case SAFE_MEDIA_VOLUME_DISABLED: return "SAFE_MEDIA_VOLUME_DISABLED";
5906 case SAFE_MEDIA_VOLUME_INACTIVE: return "SAFE_MEDIA_VOLUME_INACTIVE";
5907 case SAFE_MEDIA_VOLUME_ACTIVE: return "SAFE_MEDIA_VOLUME_ACTIVE";
5908 }
5909 return null;
Jean-Michel Trivid5176cf2010-01-28 11:56:42 -08005910 }
Glenn Kastenfd116ad2013-07-12 17:10:39 -07005911
5912 // Inform AudioFlinger of our device's low RAM attribute
5913 private static void readAndSetLowRamDevice()
5914 {
Andy Hung79583582018-01-23 13:58:02 -08005915 boolean isLowRamDevice = ActivityManager.isLowRamDeviceStatic();
5916 long totalMemory = 1024 * 1024 * 1024; // 1GB is the default if ActivityManager fails.
5917
5918 try {
5919 final ActivityManager.MemoryInfo info = new ActivityManager.MemoryInfo();
5920 ActivityManager.getService().getMemoryInfo(info);
5921 totalMemory = info.totalMem;
5922 } catch (RemoteException e) {
5923 Log.w(TAG, "Cannot obtain MemoryInfo from ActivityManager, assume low memory device");
5924 isLowRamDevice = true;
5925 }
5926
5927 final int status = AudioSystem.setLowRamDevice(isLowRamDevice, totalMemory);
Glenn Kastenfd116ad2013-07-12 17:10:39 -07005928 if (status != 0) {
5929 Log.w(TAG, "AudioFlinger informed of device's low RAM attribute; status " + status);
5930 }
5931 }
John Spurlock3346a802014-05-20 16:25:37 -04005932
John Spurlockcdb57ae2015-02-11 19:04:11 -05005933 private void enforceVolumeController(String action) {
John Spurlock3346a802014-05-20 16:25:37 -04005934 mContext.enforceCallingOrSelfPermission(android.Manifest.permission.STATUS_BAR_SERVICE,
5935 "Only SystemUI can " + action);
5936 }
5937
5938 @Override
5939 public void setVolumeController(final IVolumeController controller) {
John Spurlockcdb57ae2015-02-11 19:04:11 -05005940 enforceVolumeController("set the volume controller");
John Spurlock3346a802014-05-20 16:25:37 -04005941
5942 // return early if things are not actually changing
5943 if (mVolumeController.isSameBinder(controller)) {
5944 return;
5945 }
5946
5947 // dismiss the old volume controller
5948 mVolumeController.postDismiss();
5949 if (controller != null) {
5950 // we are about to register a new controller, listen for its death
5951 try {
5952 controller.asBinder().linkToDeath(new DeathRecipient() {
5953 @Override
5954 public void binderDied() {
5955 if (mVolumeController.isSameBinder(controller)) {
5956 Log.w(TAG, "Current remote volume controller died, unregistering");
5957 setVolumeController(null);
5958 }
5959 }
5960 }, 0);
5961 } catch (RemoteException e) {
5962 // noop
5963 }
5964 }
5965 mVolumeController.setController(controller);
John Spurlock33f4e042014-07-11 13:10:58 -04005966 if (DEBUG_VOL) Log.d(TAG, "Volume controller: " + mVolumeController);
5967 }
5968
5969 @Override
5970 public void notifyVolumeControllerVisible(final IVolumeController controller, boolean visible) {
John Spurlockcdb57ae2015-02-11 19:04:11 -05005971 enforceVolumeController("notify about volume controller visibility");
John Spurlock33f4e042014-07-11 13:10:58 -04005972
5973 // return early if the controller is not current
5974 if (!mVolumeController.isSameBinder(controller)) {
5975 return;
5976 }
5977
5978 mVolumeController.setVisible(visible);
5979 if (DEBUG_VOL) Log.d(TAG, "Volume controller visible: " + visible);
John Spurlock3346a802014-05-20 16:25:37 -04005980 }
RoboErikd09bd0c2014-06-24 17:45:19 -07005981
John Spurlocka48d7792015-03-03 17:35:57 -05005982 @Override
5983 public void setVolumePolicy(VolumePolicy policy) {
5984 enforceVolumeController("set volume policy");
John Spurlockb02c7442015-04-14 09:32:25 -04005985 if (policy != null && !policy.equals(mVolumePolicy)) {
John Spurlocka48d7792015-03-03 17:35:57 -05005986 mVolumePolicy = policy;
John Spurlockb02c7442015-04-14 09:32:25 -04005987 if (DEBUG_VOL) Log.d(TAG, "Volume policy changed: " + mVolumePolicy);
John Spurlocka48d7792015-03-03 17:35:57 -05005988 }
5989 }
5990
RoboErikd09bd0c2014-06-24 17:45:19 -07005991 public static class VolumeController {
5992 private static final String TAG = "VolumeController";
5993
5994 private IVolumeController mController;
John Spurlock33f4e042014-07-11 13:10:58 -04005995 private boolean mVisible;
5996 private long mNextLongPress;
5997 private int mLongPressTimeout;
RoboErikd09bd0c2014-06-24 17:45:19 -07005998
5999 public void setController(IVolumeController controller) {
6000 mController = controller;
John Spurlock33f4e042014-07-11 13:10:58 -04006001 mVisible = false;
6002 }
6003
6004 public void loadSettings(ContentResolver cr) {
6005 mLongPressTimeout = Settings.Secure.getIntForUser(cr,
6006 Settings.Secure.LONG_PRESS_TIMEOUT, 500, UserHandle.USER_CURRENT);
6007 }
6008
RoboErik4197cb62015-01-21 15:45:32 -08006009 public boolean suppressAdjustment(int resolvedStream, int flags, boolean isMute) {
6010 if (isMute) {
6011 return false;
6012 }
John Spurlock33f4e042014-07-11 13:10:58 -04006013 boolean suppress = false;
Julia Reynoldseb0ce472018-05-04 15:34:55 -04006014 if (resolvedStream == DEFAULT_VOL_STREAM_NO_PLAYBACK && mController != null) {
John Spurlock33f4e042014-07-11 13:10:58 -04006015 final long now = SystemClock.uptimeMillis();
6016 if ((flags & AudioManager.FLAG_SHOW_UI) != 0 && !mVisible) {
6017 // ui will become visible
6018 if (mNextLongPress < now) {
6019 mNextLongPress = now + mLongPressTimeout;
6020 }
6021 suppress = true;
6022 } else if (mNextLongPress > 0) { // in a long-press
6023 if (now > mNextLongPress) {
6024 // long press triggered, no more suppression
6025 mNextLongPress = 0;
6026 } else {
6027 // keep suppressing until the long press triggers
6028 suppress = true;
6029 }
6030 }
6031 }
6032 return suppress;
6033 }
6034
6035 public void setVisible(boolean visible) {
6036 mVisible = visible;
RoboErikd09bd0c2014-06-24 17:45:19 -07006037 }
6038
6039 public boolean isSameBinder(IVolumeController controller) {
6040 return Objects.equals(asBinder(), binder(controller));
6041 }
6042
6043 public IBinder asBinder() {
6044 return binder(mController);
6045 }
6046
6047 private static IBinder binder(IVolumeController controller) {
6048 return controller == null ? null : controller.asBinder();
6049 }
6050
6051 @Override
6052 public String toString() {
John Spurlock33f4e042014-07-11 13:10:58 -04006053 return "VolumeController(" + asBinder() + ",mVisible=" + mVisible + ")";
RoboErikd09bd0c2014-06-24 17:45:19 -07006054 }
6055
6056 public void postDisplaySafeVolumeWarning(int flags) {
6057 if (mController == null)
6058 return;
6059 try {
6060 mController.displaySafeVolumeWarning(flags);
6061 } catch (RemoteException e) {
6062 Log.w(TAG, "Error calling displaySafeVolumeWarning", e);
6063 }
6064 }
6065
6066 public void postVolumeChanged(int streamType, int flags) {
6067 if (mController == null)
6068 return;
6069 try {
6070 mController.volumeChanged(streamType, flags);
6071 } catch (RemoteException e) {
6072 Log.w(TAG, "Error calling volumeChanged", e);
6073 }
6074 }
6075
RoboErikd09bd0c2014-06-24 17:45:19 -07006076 public void postMasterMuteChanged(int flags) {
6077 if (mController == null)
6078 return;
6079 try {
6080 mController.masterMuteChanged(flags);
6081 } catch (RemoteException e) {
6082 Log.w(TAG, "Error calling masterMuteChanged", e);
6083 }
6084 }
6085
6086 public void setLayoutDirection(int layoutDirection) {
6087 if (mController == null)
6088 return;
6089 try {
6090 mController.setLayoutDirection(layoutDirection);
6091 } catch (RemoteException e) {
6092 Log.w(TAG, "Error calling setLayoutDirection", e);
6093 }
6094 }
6095
6096 public void postDismiss() {
6097 if (mController == null)
6098 return;
6099 try {
6100 mController.dismiss();
6101 } catch (RemoteException e) {
6102 Log.w(TAG, "Error calling dismiss", e);
6103 }
6104 }
Jean-Michel Triviac487672016-11-11 10:05:18 -08006105
6106 public void setA11yMode(int a11yMode) {
6107 if (mController == null)
6108 return;
6109 try {
6110 mController.setA11yMode(a11yMode);
6111 } catch (RemoteException e) {
6112 Log.w(TAG, "Error calling setA11Mode", e);
6113 }
6114 }
RoboErikd09bd0c2014-06-24 17:45:19 -07006115 }
Jean-Michel Trivia8b6bd82014-07-01 09:48:46 -07006116
RoboErik0dac35a2014-08-12 15:48:49 -07006117 /**
6118 * Interface for system components to get some extra functionality through
6119 * LocalServices.
6120 */
6121 final class AudioServiceInternal extends AudioManagerInternal {
John Spurlock661f2cf2014-11-17 10:29:10 -05006122 @Override
6123 public void setRingerModeDelegate(RingerModeDelegate delegate) {
6124 mRingerModeDelegate = delegate;
6125 if (mRingerModeDelegate != null) {
Jean-Michel Trivi8719a1d2017-11-06 11:52:51 -08006126 synchronized (mSettingsLock) {
Beverlyd6964762018-02-16 14:07:03 -05006127 updateRingerAndZenModeAffectedStreams();
Jean-Michel Trivi8719a1d2017-11-06 11:52:51 -08006128 }
John Spurlock661f2cf2014-11-17 10:29:10 -05006129 setRingerModeInternal(getRingerModeInternal(), TAG + ".setRingerModeDelegate");
6130 }
6131 }
RoboErik272e1612014-09-05 11:39:29 -07006132
6133 @Override
6134 public void adjustSuggestedStreamVolumeForUid(int streamType, int direction, int flags,
6135 String callingPackage, int uid) {
6136 // direction and stream type swap here because the public
6137 // adjustSuggested has a different order than the other methods.
John Spurlock90874332015-03-10 16:00:54 -04006138 adjustSuggestedStreamVolume(direction, streamType, flags, callingPackage,
6139 callingPackage, uid);
RoboErik272e1612014-09-05 11:39:29 -07006140 }
6141
RoboErik0dac35a2014-08-12 15:48:49 -07006142 @Override
6143 public void adjustStreamVolumeForUid(int streamType, int direction, int flags,
6144 String callingPackage, int uid) {
John Spurlock90874332015-03-10 16:00:54 -04006145 adjustStreamVolume(streamType, direction, flags, callingPackage,
6146 callingPackage, uid);
RoboErik0dac35a2014-08-12 15:48:49 -07006147 }
6148
6149 @Override
6150 public void setStreamVolumeForUid(int streamType, int direction, int flags,
6151 String callingPackage, int uid) {
John Spurlock90874332015-03-10 16:00:54 -04006152 setStreamVolume(streamType, direction, flags, callingPackage, callingPackage, uid);
RoboErik0dac35a2014-08-12 15:48:49 -07006153 }
RoboErik519c7742014-11-18 10:59:09 -08006154
6155 @Override
John Spurlock661f2cf2014-11-17 10:29:10 -05006156 public int getRingerModeInternal() {
6157 return AudioService.this.getRingerModeInternal();
6158 }
6159
6160 @Override
6161 public void setRingerModeInternal(int ringerMode, String caller) {
6162 AudioService.this.setRingerModeInternal(ringerMode, caller);
6163 }
John Spurlockcdb57ae2015-02-11 19:04:11 -05006164
6165 @Override
Mike Digman55272862018-02-20 14:35:17 -08006166 public void silenceRingerModeInternal(String caller) {
6167 AudioService.this.silenceRingerModeInternal(caller);
6168 }
6169
6170 @Override
John Spurlock50ced3f2015-05-11 16:00:09 -04006171 public void updateRingerModeAffectedStreamsInternal() {
6172 synchronized (mSettingsLock) {
Beverlyd6964762018-02-16 14:07:03 -05006173 if (updateRingerAndZenModeAffectedStreams()) {
John Spurlock50ced3f2015-05-11 16:00:09 -04006174 setRingerModeInt(getRingerModeInternal(), false);
6175 }
6176 }
6177 }
Phil Weaverf1a9aff2017-03-23 17:21:29 -07006178
6179 @Override
6180 public void setAccessibilityServiceUids(IntArray uids) {
6181 synchronized (mAccessibilityServiceUidsLock) {
6182 if (uids.size() == 0) {
6183 mAccessibilityServiceUids = null;
6184 } else {
6185 boolean changed = (mAccessibilityServiceUids == null)
6186 || (mAccessibilityServiceUids.length != uids.size());
6187 if (!changed) {
6188 for (int i = 0; i < mAccessibilityServiceUids.length; i++) {
6189 if (uids.get(i) != mAccessibilityServiceUids[i]) {
6190 changed = true;
6191 break;
6192 }
6193 }
6194 }
6195 if (changed) {
6196 mAccessibilityServiceUids = uids.toArray();
6197 }
6198 }
Eric Laurent1c9c1d52018-10-17 10:06:46 -07006199 AudioSystem.setA11yServicesUids(mAccessibilityServiceUids);
Phil Weaverf1a9aff2017-03-23 17:21:29 -07006200 }
6201 }
RoboErik0dac35a2014-08-12 15:48:49 -07006202 }
6203
Jean-Michel Trivia8b6bd82014-07-01 09:48:46 -07006204 //==========================================================================================
6205 // Audio policy management
6206 //==========================================================================================
Jean-Michel Trivi0212be52014-11-24 14:43:10 -08006207 public String registerAudioPolicy(AudioPolicyConfig policyConfig, IAudioPolicyCallback pcb,
Kevin Rocard2fe8b8b2019-02-20 11:25:23 -08006208 boolean hasFocusListener, boolean isFocusPolicy, boolean isVolumeController,
6209 IMediaProjection projection) {
Jean-Michel Trivi5a561092015-04-23 18:48:08 -07006210 AudioSystem.setDynamicPolicyCallback(mDynPolicyCallback);
6211
Kevin Rocard2fe8b8b2019-02-20 11:25:23 -08006212 if (!isPolicyRegisterAllowed(policyConfig, projection)) {
6213 Slog.w(TAG, "Permission denied to register audio policy for pid "
6214 + Binder.getCallingPid() + " / uid " + Binder.getCallingUid()
6215 + ", need MODIFY_AUDIO_ROUTING or MediaProjection that can project audio");
Jean-Michel Trivi8fdb0d42014-07-16 19:08:37 -07006216 return null;
Jean-Michel Trivia8b6bd82014-07-01 09:48:46 -07006217 }
Jean-Michel Trivi0212be52014-11-24 14:43:10 -08006218
Jean-Michel Trivi12a86762018-04-24 16:57:49 -07006219 mDynPolicyLogger.log((new AudioEventLogger.StringEvent("registerAudioPolicy for "
6220 + pcb.asBinder() + " with config:" + policyConfig)).printLog(TAG));
Kevin Rocard2fe8b8b2019-02-20 11:25:23 -08006221
6222 String regId = null;
Jean-Michel Trivia8b6bd82014-07-01 09:48:46 -07006223 synchronized (mAudioPolicies) {
Jean-Michel Trivia8b6bd82014-07-01 09:48:46 -07006224 try {
Jean-Michel Trivi0212be52014-11-24 14:43:10 -08006225 if (mAudioPolicies.containsKey(pcb.asBinder())) {
Jean-Michel Trivi1b3541d2014-11-25 12:53:41 -08006226 Slog.e(TAG, "Cannot re-register policy");
6227 return null;
6228 }
Jean-Michel Trivi126cf032017-04-02 23:19:02 -07006229 AudioPolicyProxy app = new AudioPolicyProxy(policyConfig, pcb, hasFocusListener,
Jean-Michel Trivi610aa9b2018-01-27 15:42:42 -08006230 isFocusPolicy, isVolumeController);
Jean-Michel Trivi0212be52014-11-24 14:43:10 -08006231 pcb.asBinder().linkToDeath(app, 0/*flags*/);
6232 regId = app.getRegistrationId();
6233 mAudioPolicies.put(pcb.asBinder(), app);
Jean-Michel Trivia8b6bd82014-07-01 09:48:46 -07006234 } catch (RemoteException e) {
6235 // audio policy owner has already died!
Jean-Michel Trivi0212be52014-11-24 14:43:10 -08006236 Slog.w(TAG, "Audio policy registration failed, could not link to " + pcb +
Jean-Michel Trivia8b6bd82014-07-01 09:48:46 -07006237 " binder death", e);
Jean-Michel Trivi8fdb0d42014-07-16 19:08:37 -07006238 return null;
Jean-Michel Trivia8b6bd82014-07-01 09:48:46 -07006239 }
6240 }
Jean-Michel Trivi8fdb0d42014-07-16 19:08:37 -07006241 return regId;
Jean-Michel Trivia8b6bd82014-07-01 09:48:46 -07006242 }
Jean-Michel Trivi8fdb0d42014-07-16 19:08:37 -07006243
Kevin Rocard2fe8b8b2019-02-20 11:25:23 -08006244 /**
6245 * Apps with MODIFY_AUDIO_ROUTING can register any policy.
6246 * Apps with an audio capable MediaProjection are allowed to register a RENDER|LOOPBACK policy
6247 * as those policy do not modify the audio routing.
6248 */
6249 private boolean isPolicyRegisterAllowed(AudioPolicyConfig policyConfig,
6250 IMediaProjection projection) {
6251
6252 boolean isLoopbackRenderPolicy = policyConfig.getMixes().stream().allMatch(
6253 mix -> mix.getRouteFlags() == (mix.ROUTE_FLAG_RENDER | mix.ROUTE_FLAG_LOOP_BACK));
6254
6255 // Policy that do not modify the audio routing only need an audio projection
6256 if (isLoopbackRenderPolicy && canProjectAudio(projection)) {
6257 return true;
6258 }
6259
6260 boolean hasPermissionModifyAudioRouting =
6261 (PackageManager.PERMISSION_GRANTED == mContext.checkCallingPermission(
6262 android.Manifest.permission.MODIFY_AUDIO_ROUTING));
6263 if (hasPermissionModifyAudioRouting) {
6264 return true;
6265 }
6266 return false;
6267 }
6268
6269 /** @return true if projection is a valid MediaProjection that can project audio. */
6270 private boolean canProjectAudio(IMediaProjection projection) {
6271 if (projection == null) {
6272 return false;
6273 }
6274
6275 IMediaProjectionManager projectionService = getProjectionService();
6276 if (projectionService == null) {
6277 Log.e(TAG, "Can't get service IMediaProjectionManager");
6278 return false;
6279 }
6280
6281 try {
6282 if (!projectionService.isValidMediaProjection(projection)) {
6283 Log.w(TAG, "App passed invalid MediaProjection token");
6284 return false;
6285 }
6286 } catch (RemoteException e) {
6287 Log.e(TAG, "Can't call .isValidMediaProjection() on IMediaProjectionManager"
6288 + projectionService.asBinder(), e);
6289 return false;
6290 }
6291
6292 try {
6293 if (!projection.canProjectAudio()) {
6294 Log.w(TAG, "App passed MediaProjection that can not project audio");
6295 return false;
6296 }
6297 } catch (RemoteException e) {
6298 Log.e(TAG, "Can't call .canProjectAudio() on valid IMediaProjection"
6299 + projection.asBinder(), e);
6300 return false;
6301 }
6302
6303 return true;
6304 }
6305
6306 private IMediaProjectionManager getProjectionService() {
6307 if (mProjectionService == null) {
6308 IBinder b = ServiceManager.getService(Context.MEDIA_PROJECTION_SERVICE);
6309 mProjectionService = IMediaProjectionManager.Stub.asInterface(b);
6310 }
6311 return mProjectionService;
6312 }
6313
Jean-Michel Trivi0212be52014-11-24 14:43:10 -08006314 public void unregisterAudioPolicyAsync(IAudioPolicyCallback pcb) {
Jean-Michel Trivi12a86762018-04-24 16:57:49 -07006315 mDynPolicyLogger.log((new AudioEventLogger.StringEvent("unregisterAudioPolicyAsync for "
6316 + pcb.asBinder()).printLog(TAG)));
Jean-Michel Trivia8b6bd82014-07-01 09:48:46 -07006317 synchronized (mAudioPolicies) {
Jean-Michel Trivi0212be52014-11-24 14:43:10 -08006318 AudioPolicyProxy app = mAudioPolicies.remove(pcb.asBinder());
Jean-Michel Trivia8b6bd82014-07-01 09:48:46 -07006319 if (app == null) {
6320 Slog.w(TAG, "Trying to unregister unknown audio policy for pid "
6321 + Binder.getCallingPid() + " / uid " + Binder.getCallingUid());
Jean-Michel Trivi1b3541d2014-11-25 12:53:41 -08006322 return;
Jean-Michel Trivia8b6bd82014-07-01 09:48:46 -07006323 } else {
Jean-Michel Trivi0212be52014-11-24 14:43:10 -08006324 pcb.asBinder().unlinkToDeath(app, 0/*flags*/);
Jean-Michel Trivia8b6bd82014-07-01 09:48:46 -07006325 }
Jean-Michel Trivi0212be52014-11-24 14:43:10 -08006326 app.release();
Jean-Michel Trivia8b6bd82014-07-01 09:48:46 -07006327 }
Jean-Michel Trivi8fdb0d42014-07-16 19:08:37 -07006328 // TODO implement clearing mix attribute matching info in native audio policy
Jean-Michel Trivia8b6bd82014-07-01 09:48:46 -07006329 }
6330
Jean-Michel Triviaf576a02018-02-14 08:57:46 -08006331 /**
6332 * Checks whether caller has MODIFY_AUDIO_ROUTING permission, and the policy is registered.
6333 * @param errorMsg log warning if permission check failed.
6334 * @return null if the operation on the audio mixes should be cancelled.
6335 */
6336 @GuardedBy("mAudioPolicies")
6337 private AudioPolicyProxy checkUpdateForPolicy(IAudioPolicyCallback pcb, String errorMsg) {
6338 // permission check
6339 final boolean hasPermissionForPolicy =
Jean-Michel Trivi0212be52014-11-24 14:43:10 -08006340 (PackageManager.PERMISSION_GRANTED == mContext.checkCallingPermission(
6341 android.Manifest.permission.MODIFY_AUDIO_ROUTING));
6342 if (!hasPermissionForPolicy) {
Jean-Michel Triviaf576a02018-02-14 08:57:46 -08006343 Slog.w(TAG, errorMsg + " for pid " +
Jean-Michel Trivi0212be52014-11-24 14:43:10 -08006344 + Binder.getCallingPid() + " / uid "
6345 + Binder.getCallingUid() + ", need MODIFY_AUDIO_ROUTING");
Jean-Michel Triviaf576a02018-02-14 08:57:46 -08006346 return null;
Jean-Michel Trivi0212be52014-11-24 14:43:10 -08006347 }
Jean-Michel Triviaf576a02018-02-14 08:57:46 -08006348 // policy registered?
6349 final AudioPolicyProxy app = mAudioPolicies.get(pcb.asBinder());
6350 if (app == null) {
6351 Slog.w(TAG, errorMsg + " for pid " +
6352 + Binder.getCallingPid() + " / uid "
6353 + Binder.getCallingUid() + ", unregistered policy");
6354 return null;
6355 }
6356 return app;
6357 }
Jean-Michel Trivi0212be52014-11-24 14:43:10 -08006358
Jean-Michel Triviaf576a02018-02-14 08:57:46 -08006359 public int addMixForPolicy(AudioPolicyConfig policyConfig, IAudioPolicyCallback pcb) {
6360 if (DEBUG_AP) { Log.d(TAG, "addMixForPolicy for " + pcb.asBinder()
6361 + " with config:" + policyConfig); }
Jean-Michel Trivi0212be52014-11-24 14:43:10 -08006362 synchronized (mAudioPolicies) {
Jean-Michel Triviaf576a02018-02-14 08:57:46 -08006363 final AudioPolicyProxy app =
6364 checkUpdateForPolicy(pcb, "Cannot add AudioMix in audio policy");
6365 if (app == null){
6366 return AudioManager.ERROR;
6367 }
6368 app.addMixes(policyConfig.getMixes());
6369 }
6370 return AudioManager.SUCCESS;
6371 }
6372
6373 public int removeMixForPolicy(AudioPolicyConfig policyConfig, IAudioPolicyCallback pcb) {
6374 if (DEBUG_AP) { Log.d(TAG, "removeMixForPolicy for " + pcb.asBinder()
6375 + " with config:" + policyConfig); }
6376 synchronized (mAudioPolicies) {
6377 final AudioPolicyProxy app =
6378 checkUpdateForPolicy(pcb, "Cannot add AudioMix in audio policy");
6379 if (app == null) {
6380 return AudioManager.ERROR;
6381 }
6382 app.removeMixes(policyConfig.getMixes());
6383 }
6384 return AudioManager.SUCCESS;
6385 }
6386
Jean-Michel Trivid6f65de2018-12-18 18:49:14 -08006387 /** see AudioPolicy.setUidDeviceAffinity() */
6388 public int setUidDeviceAffinity(IAudioPolicyCallback pcb, int uid,
Jean-Michel Trivif93107f2019-01-08 09:38:25 -08006389 @NonNull int[] deviceTypes, @NonNull String[] deviceAddresses) {
6390 if (DEBUG_AP) {
6391 Log.d(TAG, "setUidDeviceAffinity for " + pcb.asBinder() + " uid:" + uid);
6392 }
Jean-Michel Trivid6f65de2018-12-18 18:49:14 -08006393 synchronized (mAudioPolicies) {
6394 final AudioPolicyProxy app =
6395 checkUpdateForPolicy(pcb, "Cannot change device affinity in audio policy");
6396 if (app == null) {
6397 return AudioManager.ERROR;
6398 }
6399 if (!app.hasMixRoutedToDevices(deviceTypes, deviceAddresses)) {
6400 return AudioManager.ERROR;
6401 }
Jean-Michel Trivif93107f2019-01-08 09:38:25 -08006402 return app.setUidDeviceAffinities(uid, deviceTypes, deviceAddresses);
Jean-Michel Trivid6f65de2018-12-18 18:49:14 -08006403 }
Jean-Michel Trivid6f65de2018-12-18 18:49:14 -08006404 }
6405
6406 /** see AudioPolicy.removeUidDeviceAffinity() */
6407 public int removeUidDeviceAffinity(IAudioPolicyCallback pcb, int uid) {
Jean-Michel Trivif93107f2019-01-08 09:38:25 -08006408 if (DEBUG_AP) {
6409 Log.d(TAG, "removeUidDeviceAffinity for " + pcb.asBinder() + " uid:" + uid);
6410 }
Jean-Michel Trivid6f65de2018-12-18 18:49:14 -08006411 synchronized (mAudioPolicies) {
6412 final AudioPolicyProxy app =
6413 checkUpdateForPolicy(pcb, "Cannot remove device affinity in audio policy");
6414 if (app == null) {
6415 return AudioManager.ERROR;
6416 }
Jean-Michel Trivif93107f2019-01-08 09:38:25 -08006417 return app.removeUidDeviceAffinities(uid);
Jean-Michel Trivid6f65de2018-12-18 18:49:14 -08006418 }
Jean-Michel Trivid6f65de2018-12-18 18:49:14 -08006419 }
6420
Jean-Michel Triviaf576a02018-02-14 08:57:46 -08006421 public int setFocusPropertiesForPolicy(int duckingBehavior, IAudioPolicyCallback pcb) {
6422 if (DEBUG_AP) Log.d(TAG, "setFocusPropertiesForPolicy() duck behavior=" + duckingBehavior
6423 + " policy " + pcb.asBinder());
6424 synchronized (mAudioPolicies) {
6425 final AudioPolicyProxy app =
6426 checkUpdateForPolicy(pcb, "Cannot change audio policy focus properties");
6427 if (app == null){
6428 return AudioManager.ERROR;
6429 }
Jean-Michel Trivi0212be52014-11-24 14:43:10 -08006430 if (!mAudioPolicies.containsKey(pcb.asBinder())) {
6431 Slog.e(TAG, "Cannot change audio policy focus properties, unregistered policy");
6432 return AudioManager.ERROR;
6433 }
Jean-Michel Trivi0212be52014-11-24 14:43:10 -08006434 if (duckingBehavior == AudioPolicy.FOCUS_POLICY_DUCKING_IN_POLICY) {
6435 // is there already one policy managing ducking?
Eric Laurent0867bed2015-05-20 14:49:08 -07006436 for (AudioPolicyProxy policy : mAudioPolicies.values()) {
Jean-Michel Trivi0212be52014-11-24 14:43:10 -08006437 if (policy.mFocusDuckBehavior == AudioPolicy.FOCUS_POLICY_DUCKING_IN_POLICY) {
6438 Slog.e(TAG, "Cannot change audio policy ducking behavior, already handled");
6439 return AudioManager.ERROR;
6440 }
6441 }
6442 }
6443 app.mFocusDuckBehavior = duckingBehavior;
6444 mMediaFocusControl.setDuckingInExtPolicyAvailable(
6445 duckingBehavior == AudioPolicy.FOCUS_POLICY_DUCKING_IN_POLICY);
6446 }
6447 return AudioManager.SUCCESS;
6448 }
6449
Jean-Michel Trivi610aa9b2018-01-27 15:42:42 -08006450 private final Object mExtVolumeControllerLock = new Object();
6451 private IAudioPolicyCallback mExtVolumeController;
6452 private void setExtVolumeController(IAudioPolicyCallback apc) {
6453 if (!mContext.getResources().getBoolean(
6454 com.android.internal.R.bool.config_handleVolumeKeysInWindowManager)) {
6455 Log.e(TAG, "Cannot set external volume controller: device not set for volume keys" +
6456 " handled in PhoneWindowManager");
6457 return;
6458 }
6459 synchronized (mExtVolumeControllerLock) {
6460 if (mExtVolumeController != null && !mExtVolumeController.asBinder().pingBinder()) {
6461 Log.e(TAG, "Cannot set external volume controller: existing controller");
6462 }
6463 mExtVolumeController = apc;
6464 }
6465 }
6466
Jean-Michel Trivi1b3541d2014-11-25 12:53:41 -08006467 private void dumpAudioPolicies(PrintWriter pw) {
6468 pw.println("\nAudio policies:");
6469 synchronized (mAudioPolicies) {
Eric Laurent0867bed2015-05-20 14:49:08 -07006470 for (AudioPolicyProxy policy : mAudioPolicies.values()) {
Jean-Michel Trivi1b3541d2014-11-25 12:53:41 -08006471 pw.println(policy.toLogFriendlyString());
6472 }
6473 }
6474 }
6475
Jean-Michel Trivi958876f2014-11-16 15:40:22 -08006476 //======================
Jean-Michel Trivid3c71f02015-12-07 11:59:31 -08006477 // Audio policy callbacks from AudioSystem for dynamic policies
Jean-Michel Trivi5a561092015-04-23 18:48:08 -07006478 //======================
6479 private final AudioSystem.DynamicPolicyCallback mDynPolicyCallback =
6480 new AudioSystem.DynamicPolicyCallback() {
6481 public void onDynamicPolicyMixStateUpdate(String regId, int state) {
6482 if (!TextUtils.isEmpty(regId)) {
6483 sendMsg(mAudioHandler, MSG_DYN_POLICY_MIX_STATE_UPDATE, SENDMSG_QUEUE,
6484 state /*arg1*/, 0 /*arg2 ignored*/, regId /*obj*/, 0 /*delay*/);
6485 }
6486 }
6487 };
6488
6489 private void onDynPolicyMixStateUpdate(String regId, int state) {
6490 if (DEBUG_AP) Log.d(TAG, "onDynamicPolicyMixStateUpdate("+ regId + ", " + state +")");
6491 synchronized (mAudioPolicies) {
6492 for (AudioPolicyProxy policy : mAudioPolicies.values()) {
6493 for (AudioMix mix : policy.getMixes()) {
6494 if (mix.getRegistration().equals(regId)) {
6495 try {
6496 policy.mPolicyCallback.notifyMixStateUpdate(regId, state);
6497 } catch (RemoteException e) {
6498 Log.e(TAG, "Can't call notifyMixStateUpdate() on IAudioPolicyCallback "
6499 + policy.mPolicyCallback.asBinder(), e);
6500 }
6501 return;
6502 }
6503 }
6504 }
6505 }
Jean-Michel Trivid3c71f02015-12-07 11:59:31 -08006506 }
Jean-Michel Trivi5a561092015-04-23 18:48:08 -07006507
Jean-Michel Trivid3c71f02015-12-07 11:59:31 -08006508 //======================
6509 // Audio policy callbacks from AudioSystem for recording configuration updates
6510 //======================
Jean-Michel Trivi66ffacf2017-02-04 17:25:31 -08006511 private final RecordingActivityMonitor mRecordMonitor;
Jean-Michel Trivid3c71f02015-12-07 11:59:31 -08006512
6513 public void registerRecordingCallback(IRecordingConfigDispatcher rcdb) {
Jean-Michel Trivi66ffacf2017-02-04 17:25:31 -08006514 final boolean isPrivileged =
6515 (PackageManager.PERMISSION_GRANTED == mContext.checkCallingPermission(
6516 android.Manifest.permission.MODIFY_AUDIO_ROUTING));
6517 mRecordMonitor.registerRecordingCallback(rcdb, isPrivileged);
Jean-Michel Trivid3c71f02015-12-07 11:59:31 -08006518 }
6519
6520 public void unregisterRecordingCallback(IRecordingConfigDispatcher rcdb) {
6521 mRecordMonitor.unregisterRecordingCallback(rcdb);
6522 }
6523
Jean-Michel Trivif04fab12016-05-19 10:42:35 -07006524 public List<AudioRecordingConfiguration> getActiveRecordingConfigurations() {
Jean-Michel Trivi66ffacf2017-02-04 17:25:31 -08006525 final boolean isPrivileged =
6526 (PackageManager.PERMISSION_GRANTED == mContext.checkCallingPermission(
6527 android.Manifest.permission.MODIFY_AUDIO_ROUTING));
6528 return mRecordMonitor.getActiveRecordingConfigurations(isPrivileged);
Jean-Michel Trivi5a561092015-04-23 18:48:08 -07006529 }
6530
Robin Lee7af9a742017-02-20 14:47:30 +00006531 public void disableRingtoneSync(final int userId) {
Andre Lago7bdc6d82016-09-22 18:00:41 +01006532 final int callingUserId = UserHandle.getCallingUserId();
Robin Lee7af9a742017-02-20 14:47:30 +00006533 if (callingUserId != userId) {
6534 mContext.enforceCallingOrSelfPermission(Manifest.permission.INTERACT_ACROSS_USERS_FULL,
6535 "disable sound settings syncing for another profile");
6536 }
Andre Lago7bdc6d82016-09-22 18:00:41 +01006537 final long token = Binder.clearCallingIdentity();
6538 try {
Robin Lee7af9a742017-02-20 14:47:30 +00006539 // Disable the sync setting so the profile uses its own sound settings.
6540 Settings.Secure.putIntForUser(mContentResolver, Settings.Secure.SYNC_PARENT_SOUNDS,
6541 0 /* false */, userId);
Andre Lago7bdc6d82016-09-22 18:00:41 +01006542 } finally {
6543 Binder.restoreCallingIdentity(token);
6544 }
6545 }
6546
Jean-Michel Trivi5a561092015-04-23 18:48:08 -07006547 //======================
Jean-Michel Trivi46e310b2017-01-04 15:58:02 -08006548 // Audio playback notification
Jean-Michel Trivi292a6a42016-12-01 08:32:15 -08006549 //======================
Eric Laurente5a351c2017-09-27 20:11:51 -07006550 private final PlaybackActivityMonitor mPlaybackMonitor;
Jean-Michel Trivi292a6a42016-12-01 08:32:15 -08006551
6552 public void registerPlaybackCallback(IPlaybackConfigDispatcher pcdb) {
Jean-Michel Trivi44a8f532017-01-02 14:36:43 -08006553 final boolean isPrivileged =
Jaewan Kim92dea332017-02-02 11:52:08 +09006554 (PackageManager.PERMISSION_GRANTED == mContext.checkCallingOrSelfPermission(
Jean-Michel Trivi292a6a42016-12-01 08:32:15 -08006555 android.Manifest.permission.MODIFY_AUDIO_ROUTING));
6556 mPlaybackMonitor.registerPlaybackCallback(pcdb, isPrivileged);
6557 }
6558
6559 public void unregisterPlaybackCallback(IPlaybackConfigDispatcher pcdb) {
6560 mPlaybackMonitor.unregisterPlaybackCallback(pcdb);
6561 }
6562
6563 public List<AudioPlaybackConfiguration> getActivePlaybackConfigurations() {
Jean-Michel Trivi44a8f532017-01-02 14:36:43 -08006564 final boolean isPrivileged =
Jaewan Kim92dea332017-02-02 11:52:08 +09006565 (PackageManager.PERMISSION_GRANTED == mContext.checkCallingOrSelfPermission(
Jean-Michel Trivi44a8f532017-01-02 14:36:43 -08006566 android.Manifest.permission.MODIFY_AUDIO_ROUTING));
6567 return mPlaybackMonitor.getActivePlaybackConfigurations(isPrivileged);
Jean-Michel Trivi292a6a42016-12-01 08:32:15 -08006568 }
6569
Jean-Michel Trivi44a8f532017-01-02 14:36:43 -08006570 public int trackPlayer(PlayerBase.PlayerIdCard pic) {
6571 return mPlaybackMonitor.trackPlayer(pic);
Jean-Michel Trivi292a6a42016-12-01 08:32:15 -08006572 }
6573
6574 public void playerAttributes(int piid, AudioAttributes attr) {
Jean-Michel Trivi46e310b2017-01-04 15:58:02 -08006575 mPlaybackMonitor.playerAttributes(piid, attr, Binder.getCallingUid());
Jean-Michel Trivi292a6a42016-12-01 08:32:15 -08006576 }
6577
6578 public void playerEvent(int piid, int event) {
Jean-Michel Trivi46e310b2017-01-04 15:58:02 -08006579 mPlaybackMonitor.playerEvent(piid, event, Binder.getCallingUid());
Jean-Michel Trivi292a6a42016-12-01 08:32:15 -08006580 }
6581
Jean-Michel Trivi3120059d2017-08-28 12:40:55 -07006582 public void playerHasOpPlayAudio(int piid, boolean hasOpPlayAudio) {
6583 mPlaybackMonitor.playerHasOpPlayAudio(piid, hasOpPlayAudio, Binder.getCallingUid());
6584 }
6585
Jean-Michel Trivi292a6a42016-12-01 08:32:15 -08006586 public void releasePlayer(int piid) {
Jean-Michel Trivi46e310b2017-01-04 15:58:02 -08006587 mPlaybackMonitor.releasePlayer(piid, Binder.getCallingUid());
Jean-Michel Trivi292a6a42016-12-01 08:32:15 -08006588 }
6589
6590 //======================
Jean-Michel Trivi58850372018-09-14 16:01:28 -07006591 // Audio device management
6592 //======================
6593 private final AudioDeviceBroker mDeviceBroker;
6594
6595 //======================
Jean-Michel Trivi958876f2014-11-16 15:40:22 -08006596 // Audio policy proxy
6597 //======================
Jean-Michel Trivid6f65de2018-12-18 18:49:14 -08006598 private static final class AudioDeviceArray {
6599 final @NonNull int[] mDeviceTypes;
6600 final @NonNull String[] mDeviceAddresses;
6601 AudioDeviceArray(@NonNull int[] types, @NonNull String[] addresses) {
6602 mDeviceTypes = types;
6603 mDeviceAddresses = addresses;
6604 }
6605 }
6606
Jean-Michel Trivi8fdb0d42014-07-16 19:08:37 -07006607 /**
Jean-Michel Trivi1b3541d2014-11-25 12:53:41 -08006608 * This internal class inherits from AudioPolicyConfig, each instance contains all the
6609 * mixes of an AudioPolicy and their configurations.
Jean-Michel Trivi8fdb0d42014-07-16 19:08:37 -07006610 */
6611 public class AudioPolicyProxy extends AudioPolicyConfig implements IBinder.DeathRecipient {
Jean-Michel Trivia8b6bd82014-07-01 09:48:46 -07006612 private static final String TAG = "AudioPolicyProxy";
Jean-Michel Trivi610aa9b2018-01-27 15:42:42 -08006613 final IAudioPolicyCallback mPolicyCallback;
6614 final boolean mHasFocusListener;
6615 final boolean mIsVolumeController;
Jean-Michel Trivid6f65de2018-12-18 18:49:14 -08006616 final HashMap<Integer, AudioDeviceArray> mUidDeviceAffinities =
6617 new HashMap<Integer, AudioDeviceArray>();
Jean-Michel Trivi0212be52014-11-24 14:43:10 -08006618 /**
6619 * Audio focus ducking behavior for an audio policy.
6620 * This variable reflects the value that was successfully set in
6621 * {@link AudioService#setFocusPropertiesForPolicy(int, IAudioPolicyCallback)}. This
6622 * implies that a value of FOCUS_POLICY_DUCKING_IN_POLICY means the corresponding policy
6623 * is handling ducking for audio focus.
6624 */
6625 int mFocusDuckBehavior = AudioPolicy.FOCUS_POLICY_DUCKING_DEFAULT;
Jean-Michel Trivi126cf032017-04-02 23:19:02 -07006626 boolean mIsFocusPolicy = false;
Jean-Michel Trivi0212be52014-11-24 14:43:10 -08006627
6628 AudioPolicyProxy(AudioPolicyConfig config, IAudioPolicyCallback token,
Jean-Michel Trivi610aa9b2018-01-27 15:42:42 -08006629 boolean hasFocusListener, boolean isFocusPolicy, boolean isVolumeController) {
Jean-Michel Trivi8fdb0d42014-07-16 19:08:37 -07006630 super(config);
Jean-Michel Trivi1b3541d2014-11-25 12:53:41 -08006631 setRegistration(new String(config.hashCode() + ":ap:" + mAudioPolicyCounter++));
Jean-Michel Trivi5a561092015-04-23 18:48:08 -07006632 mPolicyCallback = token;
Jean-Michel Trivi0212be52014-11-24 14:43:10 -08006633 mHasFocusListener = hasFocusListener;
Jean-Michel Trivi610aa9b2018-01-27 15:42:42 -08006634 mIsVolumeController = isVolumeController;
Jean-Michel Trivi0212be52014-11-24 14:43:10 -08006635 if (mHasFocusListener) {
Jean-Michel Trivi5a561092015-04-23 18:48:08 -07006636 mMediaFocusControl.addFocusFollower(mPolicyCallback);
Jean-Michel Trivi126cf032017-04-02 23:19:02 -07006637 // can only ever be true if there is a focus listener
6638 if (isFocusPolicy) {
6639 mIsFocusPolicy = true;
6640 mMediaFocusControl.setFocusPolicy(mPolicyCallback);
6641 }
Jean-Michel Trivi0212be52014-11-24 14:43:10 -08006642 }
Jean-Michel Trivi610aa9b2018-01-27 15:42:42 -08006643 if (mIsVolumeController) {
6644 setExtVolumeController(mPolicyCallback);
6645 }
Eric Laurent7f5eb9f2014-12-01 19:36:30 -08006646 connectMixes();
Jean-Michel Trivia8b6bd82014-07-01 09:48:46 -07006647 }
6648
6649 public void binderDied() {
6650 synchronized (mAudioPolicies) {
Jean-Michel Trivi5a561092015-04-23 18:48:08 -07006651 Log.i(TAG, "audio policy " + mPolicyCallback + " died");
Jean-Michel Trivi0212be52014-11-24 14:43:10 -08006652 release();
Jean-Michel Trivi5a561092015-04-23 18:48:08 -07006653 mAudioPolicies.remove(mPolicyCallback.asBinder());
Jean-Michel Trivi8fdb0d42014-07-16 19:08:37 -07006654 }
Jean-Michel Trivi610aa9b2018-01-27 15:42:42 -08006655 if (mIsVolumeController) {
6656 synchronized (mExtVolumeControllerLock) {
6657 mExtVolumeController = null;
6658 }
6659 }
Jean-Michel Trivi8fdb0d42014-07-16 19:08:37 -07006660 }
6661
Jean-Michel Trivi0212be52014-11-24 14:43:10 -08006662 String getRegistrationId() {
Jean-Michel Trivi1b3541d2014-11-25 12:53:41 -08006663 return getRegistration();
Jean-Michel Trivi8fdb0d42014-07-16 19:08:37 -07006664 }
6665
Jean-Michel Trivi0212be52014-11-24 14:43:10 -08006666 void release() {
Jean-Michel Trivi126cf032017-04-02 23:19:02 -07006667 if (mIsFocusPolicy) {
6668 mMediaFocusControl.unsetFocusPolicy(mPolicyCallback);
6669 }
Jean-Michel Trivi0212be52014-11-24 14:43:10 -08006670 if (mFocusDuckBehavior == AudioPolicy.FOCUS_POLICY_DUCKING_IN_POLICY) {
6671 mMediaFocusControl.setDuckingInExtPolicyAvailable(false);
6672 }
6673 if (mHasFocusListener) {
Jean-Michel Trivi5a561092015-04-23 18:48:08 -07006674 mMediaFocusControl.removeFocusFollower(mPolicyCallback);
Jean-Michel Trivi0212be52014-11-24 14:43:10 -08006675 }
Eric Laurent66b69672018-01-26 18:30:51 -08006676 final long identity = Binder.clearCallingIdentity();
Eric Laurent7f5eb9f2014-12-01 19:36:30 -08006677 AudioSystem.registerPolicyMixes(mMixes, false);
Eric Laurent66b69672018-01-26 18:30:51 -08006678 Binder.restoreCallingIdentity(identity);
Jean-Michel Trivi8fdb0d42014-07-16 19:08:37 -07006679 }
6680
Jean-Michel Trivi7db2d8f2018-03-06 10:30:59 -08006681 boolean hasMixAffectingUsage(int usage) {
6682 for (AudioMix mix : mMixes) {
6683 if (mix.isAffectingUsage(usage)) {
6684 return true;
6685 }
6686 }
6687 return false;
6688 }
6689
Jean-Michel Trivid6f65de2018-12-18 18:49:14 -08006690 // Verify all the devices in the array are served by mixes defined in this policy
6691 boolean hasMixRoutedToDevices(@NonNull int[] deviceTypes,
6692 @NonNull String[] deviceAddresses) {
6693 for (int i = 0; i < deviceTypes.length; i++) {
6694 boolean hasDevice = false;
6695 for (AudioMix mix : mMixes) {
6696 // this will check both that the mix has ROUTE_FLAG_RENDER and the device
6697 // is reached by this mix
6698 if (mix.isRoutedToDevice(deviceTypes[i], deviceAddresses[i])) {
6699 hasDevice = true;
6700 break;
6701 }
6702 }
6703 if (!hasDevice) {
6704 return false;
6705 }
6706 }
6707 return true;
6708 }
6709
Jean-Michel Triviaf576a02018-02-14 08:57:46 -08006710 void addMixes(@NonNull ArrayList<AudioMix> mixes) {
6711 // TODO optimize to not have to unregister the mixes already in place
6712 synchronized (mMixes) {
6713 AudioSystem.registerPolicyMixes(mMixes, false);
6714 this.add(mixes);
6715 AudioSystem.registerPolicyMixes(mMixes, true);
6716 }
6717 }
6718
6719 void removeMixes(@NonNull ArrayList<AudioMix> mixes) {
6720 // TODO optimize to not have to unregister the mixes already in place
6721 synchronized (mMixes) {
6722 AudioSystem.registerPolicyMixes(mMixes, false);
6723 this.remove(mixes);
6724 AudioSystem.registerPolicyMixes(mMixes, true);
6725 }
6726 }
6727
Eric Laurent7f5eb9f2014-12-01 19:36:30 -08006728 void connectMixes() {
Eric Laurent66b69672018-01-26 18:30:51 -08006729 final long identity = Binder.clearCallingIdentity();
Eric Laurent7f5eb9f2014-12-01 19:36:30 -08006730 AudioSystem.registerPolicyMixes(mMixes, true);
Eric Laurent66b69672018-01-26 18:30:51 -08006731 Binder.restoreCallingIdentity(identity);
Jean-Michel Trivia8b6bd82014-07-01 09:48:46 -07006732 }
Jean-Michel Trivid6f65de2018-12-18 18:49:14 -08006733
Jean-Michel Trivif93107f2019-01-08 09:38:25 -08006734 int setUidDeviceAffinities(int uid, @NonNull int[] types, @NonNull String[] addresses) {
Jean-Michel Trivid6f65de2018-12-18 18:49:14 -08006735 final Integer Uid = new Integer(uid);
Jean-Michel Trivif93107f2019-01-08 09:38:25 -08006736 int res;
Jean-Michel Trivid6f65de2018-12-18 18:49:14 -08006737 if (mUidDeviceAffinities.remove(Uid) != null) {
6738 final long identity = Binder.clearCallingIdentity();
Jean-Michel Trivif93107f2019-01-08 09:38:25 -08006739 res = AudioSystem.removeUidDeviceAffinities(uid);
Jean-Michel Trivid6f65de2018-12-18 18:49:14 -08006740 Binder.restoreCallingIdentity(identity);
Jean-Michel Trivif93107f2019-01-08 09:38:25 -08006741 if (res != AudioSystem.SUCCESS) {
6742 Log.e(TAG, "AudioSystem. removeUidDeviceAffinities(" + uid + ") failed, "
6743 + " cannot call AudioSystem.setUidDeviceAffinities");
6744 return AudioManager.ERROR;
6745 }
Jean-Michel Trivid6f65de2018-12-18 18:49:14 -08006746 }
6747 final long identity = Binder.clearCallingIdentity();
Jean-Michel Trivif93107f2019-01-08 09:38:25 -08006748 res = AudioSystem.setUidDeviceAffinities(uid, types, addresses);
Jean-Michel Trivid6f65de2018-12-18 18:49:14 -08006749 Binder.restoreCallingIdentity(identity);
6750 if (res == AudioSystem.SUCCESS) {
6751 mUidDeviceAffinities.put(Uid, new AudioDeviceArray(types, addresses));
Jean-Michel Trivif93107f2019-01-08 09:38:25 -08006752 return AudioManager.SUCCESS;
Jean-Michel Trivid6f65de2018-12-18 18:49:14 -08006753 }
Jean-Michel Trivif93107f2019-01-08 09:38:25 -08006754 Log.e(TAG, "AudioSystem. setUidDeviceAffinities(" + uid + ") failed");
6755 return AudioManager.ERROR;
Jean-Michel Trivid6f65de2018-12-18 18:49:14 -08006756 }
6757
Jean-Michel Trivif93107f2019-01-08 09:38:25 -08006758 int removeUidDeviceAffinities(int uid) {
Jean-Michel Trivid6f65de2018-12-18 18:49:14 -08006759 if (mUidDeviceAffinities.remove(new Integer(uid)) != null) {
6760 final long identity = Binder.clearCallingIdentity();
Jean-Michel Trivif93107f2019-01-08 09:38:25 -08006761 final int res = AudioSystem.removeUidDeviceAffinities(uid);
Jean-Michel Trivid6f65de2018-12-18 18:49:14 -08006762 Binder.restoreCallingIdentity(identity);
Jean-Michel Trivif93107f2019-01-08 09:38:25 -08006763 if (res == AudioSystem.SUCCESS) {
6764 return AudioManager.SUCCESS;
6765 }
Jean-Michel Trivid6f65de2018-12-18 18:49:14 -08006766 }
Jean-Michel Trivif93107f2019-01-08 09:38:25 -08006767 Log.e(TAG, "AudioSystem. removeUidDeviceAffinities failed");
6768 return AudioManager.ERROR;
Jean-Michel Trivid6f65de2018-12-18 18:49:14 -08006769 }
Jean-Michel Trivia8b6bd82014-07-01 09:48:46 -07006770 };
6771
Jean-Michel Trivi126cf032017-04-02 23:19:02 -07006772 //======================
6773 // Audio policy: focus
6774 //======================
6775 /** */
6776 public int dispatchFocusChange(AudioFocusInfo afi, int focusChange, IAudioPolicyCallback pcb) {
Jean-Michel Trivie2d8aae2018-01-30 15:09:47 -08006777 if (afi == null) {
6778 throw new IllegalArgumentException("Illegal null AudioFocusInfo");
6779 }
6780 if (pcb == null) {
6781 throw new IllegalArgumentException("Illegal null AudioPolicy callback");
6782 }
Jean-Michel Trivi126cf032017-04-02 23:19:02 -07006783 synchronized (mAudioPolicies) {
6784 if (!mAudioPolicies.containsKey(pcb.asBinder())) {
6785 throw new IllegalStateException("Unregistered AudioPolicy for focus dispatch");
6786 }
6787 return mMediaFocusControl.dispatchFocusChange(afi, focusChange);
6788 }
6789 }
6790
Jean-Michel Trivie2d8aae2018-01-30 15:09:47 -08006791 public void setFocusRequestResultFromExtPolicy(AudioFocusInfo afi, int requestResult,
6792 IAudioPolicyCallback pcb) {
6793 if (afi == null) {
6794 throw new IllegalArgumentException("Illegal null AudioFocusInfo");
6795 }
6796 if (pcb == null) {
6797 throw new IllegalArgumentException("Illegal null AudioPolicy callback");
6798 }
6799 synchronized (mAudioPolicies) {
6800 if (!mAudioPolicies.containsKey(pcb.asBinder())) {
6801 throw new IllegalStateException("Unregistered AudioPolicy for external focus");
6802 }
6803 mMediaFocusControl.setFocusRequestResultFromExtPolicy(afi, requestResult);
6804 }
6805 }
6806
6807
Jean-Michel Trivi126cf032017-04-02 23:19:02 -07006808 //======================
Eric Laurent1d3cdce2018-01-20 10:31:21 -08006809 // Audioserver state displatch
6810 //======================
6811 private class AsdProxy implements IBinder.DeathRecipient {
6812 private final IAudioServerStateDispatcher mAsd;
6813
6814 AsdProxy(IAudioServerStateDispatcher asd) {
6815 mAsd = asd;
6816 }
6817
6818 public void binderDied() {
6819 synchronized (mAudioServerStateListeners) {
6820 mAudioServerStateListeners.remove(mAsd.asBinder());
6821 }
6822 }
6823
6824 IAudioServerStateDispatcher callback() {
6825 return mAsd;
6826 }
6827 }
6828
6829 private HashMap<IBinder, AsdProxy> mAudioServerStateListeners =
6830 new HashMap<IBinder, AsdProxy>();
6831
6832 private void checkMonitorAudioServerStatePermission() {
6833 if (!(mContext.checkCallingOrSelfPermission(
6834 android.Manifest.permission.MODIFY_PHONE_STATE) ==
6835 PackageManager.PERMISSION_GRANTED ||
6836 mContext.checkCallingOrSelfPermission(
6837 android.Manifest.permission.MODIFY_AUDIO_ROUTING) ==
6838 PackageManager.PERMISSION_GRANTED)) {
6839 throw new SecurityException("Not allowed to monitor audioserver state");
6840 }
6841 }
6842
6843 public void registerAudioServerStateDispatcher(IAudioServerStateDispatcher asd) {
6844 checkMonitorAudioServerStatePermission();
6845 synchronized (mAudioServerStateListeners) {
6846 if (mAudioServerStateListeners.containsKey(asd.asBinder())) {
6847 Slog.w(TAG, "Cannot re-register audio server state dispatcher");
6848 return;
6849 }
6850 AsdProxy asdp = new AsdProxy(asd);
6851 try {
6852 asd.asBinder().linkToDeath(asdp, 0/*flags*/);
6853 } catch (RemoteException e) {
6854
6855 }
6856 mAudioServerStateListeners.put(asd.asBinder(), asdp);
6857 }
6858 }
6859
6860 public void unregisterAudioServerStateDispatcher(IAudioServerStateDispatcher asd) {
6861 checkMonitorAudioServerStatePermission();
6862 synchronized (mAudioServerStateListeners) {
6863 AsdProxy asdp = mAudioServerStateListeners.remove(asd.asBinder());
6864 if (asdp == null) {
6865 Slog.w(TAG, "Trying to unregister unknown audioserver state dispatcher for pid "
6866 + Binder.getCallingPid() + " / uid " + Binder.getCallingUid());
6867 return;
6868 } else {
6869 asd.asBinder().unlinkToDeath(asdp, 0/*flags*/);
6870 }
6871 }
6872 }
6873
6874 public boolean isAudioServerRunning() {
6875 checkMonitorAudioServerStatePermission();
6876 return (AudioSystem.checkAudioFlinger() == AudioSystem.AUDIO_STATUS_OK);
6877 }
6878
6879 //======================
Jean-Michel Trivi126cf032017-04-02 23:19:02 -07006880 // misc
6881 //======================
Jean-Michel Triviaf576a02018-02-14 08:57:46 -08006882 private final HashMap<IBinder, AudioPolicyProxy> mAudioPolicies =
Jean-Michel Trivia8b6bd82014-07-01 09:48:46 -07006883 new HashMap<IBinder, AudioPolicyProxy>();
Jean-Michel Triviaf576a02018-02-14 08:57:46 -08006884 @GuardedBy("mAudioPolicies")
6885 private int mAudioPolicyCounter = 0;
Phil Burkac0f7042016-02-24 12:19:08 -08006886}