blob: de63d0ef8edf71620b921033686c9d6d5ed3142a [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;
Jean-Michel Trivi0212be52014-11-24 14:43:10 -080091import android.media.audiopolicy.IAudioPolicyCallback;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080092import android.os.Binder;
Eric Laurentc18c9132013-04-12 17:24:56 -070093import android.os.Build;
Makoto Onukid45a4a22015-11-02 17:17:38 -080094import android.os.Bundle;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080095import android.os.Environment;
96import android.os.Handler;
97import android.os.IBinder;
98import android.os.Looper;
99import android.os.Message;
Jean-Michel Trivic6802222012-04-30 11:15:03 -0700100import android.os.PowerManager;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800101import android.os.RemoteException;
John Spurlock33f4e042014-07-11 13:10:58 -0400102import android.os.SystemClock;
Jaikumar Ganesh82aa7f02010-09-27 17:05:10 -0700103import android.os.SystemProperties;
Dianne Hackborn5ac72a22012-08-29 18:32:08 -0700104import android.os.UserHandle;
Fyodor Kupolovb5013302015-04-17 17:59:14 -0700105import android.os.UserManager;
Makoto Onukid45a4a22015-11-02 17:17:38 -0800106import android.os.UserManagerInternal;
107import android.os.UserManagerInternal.UserRestrictionsListener;
Mike Digman55272862018-02-20 14:35:17 -0800108import android.os.VibrationEffect;
Eric Laurentbffc3d12012-05-07 17:43:49 -0700109import android.os.Vibrator;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800110import android.provider.Settings;
111import android.provider.Settings.System;
Beverly925cde82018-01-23 09:31:23 -0500112import android.service.notification.ZenModeConfig;
Tyler Gunnef9f6f92014-09-12 22:16:17 -0700113import android.telecom.TelecomManager;
Dianne Hackborn632ca412012-06-14 19:34:10 -0700114import android.text.TextUtils;
Fyodor Kupolovb5013302015-04-17 17:59:14 -0700115import android.util.AndroidRuntimeException;
Phil Weaverf1a9aff2017-03-23 17:21:29 -0700116import android.util.IntArray;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800117import android.util.Log;
John Spurlockaa5ee4d2014-07-25 13:05:12 -0400118import android.util.MathUtils;
Jean-Michel Trivia8b6bd82014-07-01 09:48:46 -0700119import android.util.Slog;
John Spurlock2bb02ec2015-03-02 13:13:06 -0500120import android.util.SparseIntArray;
Jean-Michel Trivid327f212010-03-16 21:44:33 -0700121import android.view.KeyEvent;
Jean-Michel Trivi873cc452014-09-11 17:25:09 -0700122import android.view.accessibility.AccessibilityManager;
Mike Digman55272862018-02-20 14:35:17 -0800123import android.widget.Toast;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800124
Jean-Michel Trivi8719a1d2017-11-06 11:52:51 -0800125import com.android.internal.annotations.GuardedBy;
Jeff Sharkeyfe9a53b2017-03-31 14:08:23 -0600126import com.android.internal.util.DumpUtils;
Eric Laurente78fced2013-03-15 16:03:47 -0700127import com.android.internal.util.XmlUtils;
John Spurlock90874332015-03-10 16:00:54 -0400128import com.android.server.EventLogTags;
RoboErik0dac35a2014-08-12 15:48:49 -0700129import com.android.server.LocalServices;
Makoto Onukie1aef852015-10-15 17:28:35 -0700130import com.android.server.SystemService;
Beverly925cde82018-01-23 09:31:23 -0500131import com.android.server.audio.AudioServiceEvents.PhoneStateEvent;
132import com.android.server.audio.AudioServiceEvents.VolumeEvent;
Fyodor Kupolovb5013302015-04-17 17:59:14 -0700133import com.android.server.pm.UserManagerService;
Wale Ogunwale9e4f3e02018-05-17 09:35:39 -0700134import com.android.server.wm.ActivityTaskManagerInternal;
Eric Laurente78fced2013-03-15 16:03:47 -0700135
136import org.xmlpull.v1.XmlPullParserException;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800137
Jaekyun Seokc31033f2018-01-15 14:53:17 +0900138import java.io.File;
Jean-Michel Trivid5176cf2010-01-28 11:56:42 -0800139import java.io.FileDescriptor;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800140import java.io.IOException;
Jean-Michel Trivid5176cf2010-01-28 11:56:42 -0800141import java.io.PrintWriter;
Jean-Michel Trivi58850372018-09-14 16:01:28 -0700142import java.lang.annotation.Retention;
143import java.lang.annotation.RetentionPolicy;
Eric Laurente78fced2013-03-15 16:03:47 -0700144import java.lang.reflect.Field;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800145import java.util.ArrayList;
Jean-Michel Trivi7db2d8f2018-03-06 10:30:59 -0800146import java.util.Collection;
Eric Laurentc42ac9d2009-07-29 08:53:03 -0700147import java.util.HashMap;
148import java.util.Iterator;
Jaikumar Ganesh5a1e4cf2010-10-18 17:05:09 -0700149import java.util.List;
Jaikumar Ganesh82aa7f02010-09-27 17:05:10 -0700150import java.util.NoSuchElementException;
RoboErikd09bd0c2014-06-24 17:45:19 -0700151import java.util.Objects;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800152
153/**
154 * The implementation of the volume manager service.
155 * <p>
156 * This implementation focuses on delivering a responsive UI. Most methods are
157 * asynchronous to external calls. For example, the task of setting a volume
158 * will update our internal state, but in a separate thread will set the system
159 * volume and later persist to the database. Similarly, setting the ringer mode
160 * will update the state and broadcast a change and in a separate thread later
161 * persist the ringer mode.
162 *
163 * @hide
164 */
Jean-Michel Triviac487672016-11-11 10:05:18 -0800165public class AudioService extends IAudioService.Stub
166 implements AccessibilityManager.TouchExplorationStateChangeListener,
Jean-Michel Trivicfa55532017-01-18 11:17:51 -0800167 AccessibilityManager.AccessibilityServicesStateChangeListener {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800168
Jean-Michel Trivi58850372018-09-14 16:01:28 -0700169 private static final String TAG = "AS.AudioService";
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800170
Jean-Michel Trivi339567d2014-07-29 09:53:34 -0700171 /** Debug audio mode */
Jean-Michel Trivi58850372018-09-14 16:01:28 -0700172 protected static final boolean DEBUG_MODE = false;
Jean-Michel Trivi8fdb0d42014-07-16 19:08:37 -0700173
174 /** Debug audio policy feature */
Jean-Michel Trivi58850372018-09-14 16:01:28 -0700175 protected static final boolean DEBUG_AP = false;
Jean-Michel Trivi8fdb0d42014-07-16 19:08:37 -0700176
Jean-Michel Trivi3114ce32012-06-11 15:03:52 -0700177 /** Debug volumes */
Jean-Michel Trivi58850372018-09-14 16:01:28 -0700178 protected static final boolean DEBUG_VOL = false;
Jean-Michel Trivi18e7bce2011-08-26 12:11:36 -0700179
Paul McLean394a8e12015-03-03 10:29:19 -0700180 /** debug calls to devices APIs */
Jean-Michel Trivi58850372018-09-14 16:01:28 -0700181 protected static final boolean DEBUG_DEVICES = false;
182
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800183 /** How long to delay before persisting a change in volume/ringer mode. */
RoboErik45edba12012-03-27 17:54:36 -0700184 private static final int PERSIST_DELAY = 500;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800185
RoboErik5452e252015-02-06 15:33:53 -0800186 /** How long to delay after a volume down event before unmuting a stream */
187 private static final int UNMUTE_STREAM_DELAY = 350;
188
John Spurlock3346a802014-05-20 16:25:37 -0400189 /**
John Spurlocka11b4af2014-06-01 11:52:23 -0400190 * Only used in the result from {@link #checkForRingerModeChange(int, int, int)}
191 */
192 private static final int FLAG_ADJUST_VOLUME = 1;
193
Dianne Hackbornba50b97c2013-04-30 15:04:46 -0700194 private final Context mContext;
195 private final ContentResolver mContentResolver;
196 private final AppOpsManager mAppOps;
Eric Laurent212532b2014-07-21 15:43:18 -0700197
Eric Laurent212532b2014-07-21 15:43:18 -0700198 // the platform type affects volume and silent mode behavior
199 private final int mPlatformType;
200
Muyuan Li1ed6df62016-06-18 11:16:52 -0700201 // indicates whether the system maps all streams to a single stream.
202 private final boolean mIsSingleVolume;
203
Eric Laurent212532b2014-07-21 15:43:18 -0700204 private boolean isPlatformVoice() {
John Spurlock61560172015-02-06 19:46:04 -0500205 return mPlatformType == AudioSystem.PLATFORM_VOICE;
Eric Laurent212532b2014-07-21 15:43:18 -0700206 }
207
Jean-Michel Trivi58850372018-09-14 16:01:28 -0700208 /*package*/ boolean isPlatformTelevision() {
John Spurlock61560172015-02-06 19:46:04 -0500209 return mPlatformType == AudioSystem.PLATFORM_TELEVISION;
Eric Laurent212532b2014-07-21 15:43:18 -0700210 }
Jean-Michel Trivid5176cf2010-01-28 11:56:42 -0800211
Jean-Michel Trivi58850372018-09-14 16:01:28 -0700212 /*package*/ boolean isPlatformAutomotive() {
Hongwei Wangdaba1242018-05-29 14:36:16 -0700213 return mContext.getPackageManager().hasSystemFeature(PackageManager.FEATURE_AUTOMOTIVE);
214 }
215
John Spurlock3346a802014-05-20 16:25:37 -0400216 /** The controller for the volume UI. */
217 private final VolumeController mVolumeController = new VolumeController();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800218
219 // sendMsg() flags
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800220 /** If the msg is already queued, replace it with this one. */
221 private static final int SENDMSG_REPLACE = 0;
222 /** If the msg is already queued, ignore this one and leave the old. */
223 private static final int SENDMSG_NOOP = 1;
224 /** If the msg is already queued, queue this one and leave the old. */
225 private static final int SENDMSG_QUEUE = 2;
226
Jean-Michel Trivi3114ce32012-06-11 15:03:52 -0700227 // AudioHandler messages
Eric Laurent9bc8358d2011-11-18 16:43:31 -0800228 private static final int MSG_SET_DEVICE_VOLUME = 0;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800229 private static final int MSG_PERSIST_VOLUME = 1;
230 private static final int MSG_PERSIST_RINGER_MODE = 3;
Andy Hunged0ea402015-10-30 14:11:46 -0700231 private static final int MSG_AUDIO_SERVER_DIED = 4;
Eric Laurentdfb881f2013-07-18 14:41:39 -0700232 private static final int MSG_PLAY_SOUND_EFFECT = 5;
Eric Laurentdfb881f2013-07-18 14:41:39 -0700233 private static final int MSG_LOAD_SOUND_EFFECTS = 7;
234 private static final int MSG_SET_FORCE_USE = 8;
235 private static final int MSG_BT_HEADSET_CNCT_FAILED = 9;
236 private static final int MSG_SET_ALL_VOLUMES = 10;
Jean-Michel Trivi58850372018-09-14 16:01:28 -0700237 private static final int MSG_CHECK_MUSIC_ACTIVE = 11;
238 private static final int MSG_CONFIGURE_SAFE_MEDIA_VOLUME = 12;
239 private static final int MSG_CONFIGURE_SAFE_MEDIA_VOLUME_FORCED = 13;
240 private static final int MSG_PERSIST_SAFE_VOLUME_STATE = 14;
241 private static final int MSG_UNLOAD_SOUND_EFFECTS = 15;
242 private static final int MSG_SYSTEM_READY = 16;
243 private static final int MSG_PERSIST_MUSIC_ACTIVE_MS = 17;
244 private static final int MSG_UNMUTE_STREAM = 18;
245 private static final int MSG_DYN_POLICY_MIX_STATE_UPDATE = 19;
246 private static final int MSG_INDICATE_SYSTEM_READY = 20;
247 private static final int MSG_ACCESSORY_PLUG_MEDIA_UNMUTE = 21;
248 private static final int MSG_NOTIFY_VOL_EVENT = 22;
249 private static final int MSG_DISPATCH_AUDIO_SERVER_STATE = 23;
250 private static final int MSG_ENABLE_SURROUND_FORMATS = 24;
Jean-Michel Trivi3114ce32012-06-11 15:03:52 -0700251 // start of messages handled under wakelock
252 // these messages can only be queued, i.e. sent with queueMsgUnderWakeLock(),
Jean-Michel Trivie12c39b2012-06-06 10:51:58 -0700253 // and not with sendMsg(..., ..., SENDMSG_QUEUE, ...)
Jean-Michel Trivi58850372018-09-14 16:01:28 -0700254 private static final int MSG_DISABLE_AUDIO_FOR_UID = 100;
Jean-Michel Trivi3114ce32012-06-11 15:03:52 -0700255 // end of messages handled under wakelock
Eric Laurentafbb0472011-12-15 09:04:23 -0800256
Eric Laurent0867bed2015-05-20 14:49:08 -0700257 // retry delay in case of failure to indicate system ready to AudioFlinger
258 private static final int INDICATE_SYSTEM_READY_RETRY_DELAY_MS = 1000;
259
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800260 /** @see AudioSystemThread */
261 private AudioSystemThread mAudioSystemThread;
262 /** @see AudioHandler */
263 private AudioHandler mAudioHandler;
264 /** @see VolumeStreamState */
265 private VolumeStreamState[] mStreamStates;
Jean-Michel Trivi58850372018-09-14 16:01:28 -0700266
267 /*package*/ VolumeStreamState getStreamState(int stream) {
268 return mStreamStates[stream];
269 }
270
Jason Parekhb1096152009-03-24 17:48:25 -0700271 private SettingsObserver mSettingsObserver;
Eric Laurenta553c252009-07-17 12:17:14 -0700272
Jean-Michel Trivifa9a6982013-06-27 16:22:58 -0700273 private int mMode = AudioSystem.MODE_NORMAL;
Glenn Kastenba195eb2011-12-13 09:30:40 -0800274 // protects mRingerMode
275 private final Object mSettingsLock = new Object();
Eric Laurent45c90ce2012-04-24 18:44:22 -0700276
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800277 private SoundPool mSoundPool;
Glenn Kasten30c918c2011-11-10 17:56:41 -0800278 private final Object mSoundEffectsLock = new Object();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800279 private static final int NUM_SOUNDPOOL_CHANNELS = 4;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800280
281 /* Sound effect file names */
282 private static final String SOUND_EFFECTS_PATH = "/media/audio/ui/";
Eric Laurente78fced2013-03-15 16:03:47 -0700283 private static final List<String> SOUND_EFFECT_FILES = new ArrayList<String>();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800284
285 /* Sound effect file name mapping sound effect id (AudioManager.FX_xxx) to
286 * file index in SOUND_EFFECT_FILES[] (first column) and indicating if effect
287 * uses soundpool (second column) */
Eric Laurente78fced2013-03-15 16:03:47 -0700288 private final int[][] SOUND_EFFECT_FILES_MAP = new int[AudioManager.NUM_SOUND_EFFECTS][2];
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800289
John Spurlockb6e19e32015-03-10 21:33:44 -0400290 /** Maximum volume index values for audio streams */
Chinyue Chen6affe932018-01-24 14:51:43 +0800291 protected static int[] MAX_STREAM_VOLUME = new int[] {
Eric Laurent6ee99522009-08-25 06:30:59 -0700292 5, // STREAM_VOICE_CALL
293 7, // STREAM_SYSTEM
294 7, // STREAM_RING
295 15, // STREAM_MUSIC
296 7, // STREAM_ALARM
297 7, // STREAM_NOTIFICATION
298 15, // STREAM_BLUETOOTH_SCO
299 7, // STREAM_SYSTEM_ENFORCED
300 15, // STREAM_DTMF
Jean-Michel Trivi3f0945a2016-11-11 10:05:18 -0800301 15, // STREAM_TTS
302 15 // STREAM_ACCESSIBILITY
Jared Suttles59820132009-08-13 21:50:52 -0500303 };
Eric Laurent91377de2014-10-10 15:24:04 -0700304
John Spurlockb6e19e32015-03-10 21:33:44 -0400305 /** Minimum volume index values for audio streams */
Chinyue Chen6affe932018-01-24 14:51:43 +0800306 protected static int[] MIN_STREAM_VOLUME = new int[] {
John Spurlockb6e19e32015-03-10 21:33:44 -0400307 1, // STREAM_VOICE_CALL
308 0, // STREAM_SYSTEM
309 0, // STREAM_RING
310 0, // STREAM_MUSIC
Jean-Michel Trivie05eef82018-03-08 18:56:34 -0800311 1, // STREAM_ALARM
John Spurlockb6e19e32015-03-10 21:33:44 -0400312 0, // STREAM_NOTIFICATION
Eric Laurente4381ec2015-10-29 17:52:48 -0700313 0, // STREAM_BLUETOOTH_SCO
John Spurlockb6e19e32015-03-10 21:33:44 -0400314 0, // STREAM_SYSTEM_ENFORCED
315 0, // STREAM_DTMF
Jean-Michel Trivi3f0945a2016-11-11 10:05:18 -0800316 0, // STREAM_TTS
Jean-Michel Trivie05eef82018-03-08 18:56:34 -0800317 1 // STREAM_ACCESSIBILITY
John Spurlockb6e19e32015-03-10 21:33:44 -0400318 };
319
Eric Laurent6d517662012-04-23 18:42:39 -0700320 /* mStreamVolumeAlias[] indicates for each stream if it uses the volume settings
Eric Laurenta553c252009-07-17 12:17:14 -0700321 * of another stream: This avoids multiplying the volume settings for hidden
322 * stream types that follow other stream behavior for volume settings
Eric Laurent6d517662012-04-23 18:42:39 -0700323 * NOTE: do not create loops in aliases!
324 * Some streams alias to different streams according to device category (phone or tablet) or
Eric Laurent24e0d9b2013-10-03 18:15:07 -0700325 * use case (in call vs off call...). See updateStreamVolumeAlias() for more details.
Eric Laurent212532b2014-07-21 15:43:18 -0700326 * mStreamVolumeAlias contains STREAM_VOLUME_ALIAS_VOICE aliases for a voice capable device
327 * (phone), STREAM_VOLUME_ALIAS_TELEVISION for a television or set-top box and
328 * STREAM_VOLUME_ALIAS_DEFAULT for other devices (e.g. tablets).*/
329 private final int[] STREAM_VOLUME_ALIAS_VOICE = new int[] {
Eric Laurent6d517662012-04-23 18:42:39 -0700330 AudioSystem.STREAM_VOICE_CALL, // STREAM_VOICE_CALL
331 AudioSystem.STREAM_RING, // STREAM_SYSTEM
332 AudioSystem.STREAM_RING, // STREAM_RING
333 AudioSystem.STREAM_MUSIC, // STREAM_MUSIC
334 AudioSystem.STREAM_ALARM, // STREAM_ALARM
335 AudioSystem.STREAM_RING, // STREAM_NOTIFICATION
336 AudioSystem.STREAM_BLUETOOTH_SCO, // STREAM_BLUETOOTH_SCO
337 AudioSystem.STREAM_RING, // STREAM_SYSTEM_ENFORCED
338 AudioSystem.STREAM_RING, // STREAM_DTMF
Jean-Michel Trivi3f0945a2016-11-11 10:05:18 -0800339 AudioSystem.STREAM_MUSIC, // STREAM_TTS
340 AudioSystem.STREAM_MUSIC // STREAM_ACCESSIBILITY
Eric Laurenta553c252009-07-17 12:17:14 -0700341 };
Eric Laurent212532b2014-07-21 15:43:18 -0700342 private final int[] STREAM_VOLUME_ALIAS_TELEVISION = new int[] {
343 AudioSystem.STREAM_MUSIC, // STREAM_VOICE_CALL
344 AudioSystem.STREAM_MUSIC, // STREAM_SYSTEM
345 AudioSystem.STREAM_MUSIC, // STREAM_RING
346 AudioSystem.STREAM_MUSIC, // STREAM_MUSIC
347 AudioSystem.STREAM_MUSIC, // STREAM_ALARM
348 AudioSystem.STREAM_MUSIC, // STREAM_NOTIFICATION
349 AudioSystem.STREAM_MUSIC, // STREAM_BLUETOOTH_SCO
350 AudioSystem.STREAM_MUSIC, // STREAM_SYSTEM_ENFORCED
351 AudioSystem.STREAM_MUSIC, // STREAM_DTMF
Jean-Michel Trivi3f0945a2016-11-11 10:05:18 -0800352 AudioSystem.STREAM_MUSIC, // STREAM_TTS
353 AudioSystem.STREAM_MUSIC // STREAM_ACCESSIBILITY
Eric Laurent212532b2014-07-21 15:43:18 -0700354 };
355 private final int[] STREAM_VOLUME_ALIAS_DEFAULT = new int[] {
Eric Laurent6d517662012-04-23 18:42:39 -0700356 AudioSystem.STREAM_VOICE_CALL, // STREAM_VOICE_CALL
John Spurlock4f0f1202014-08-05 13:28:33 -0400357 AudioSystem.STREAM_RING, // STREAM_SYSTEM
Eric Laurent6d517662012-04-23 18:42:39 -0700358 AudioSystem.STREAM_RING, // STREAM_RING
359 AudioSystem.STREAM_MUSIC, // STREAM_MUSIC
360 AudioSystem.STREAM_ALARM, // STREAM_ALARM
361 AudioSystem.STREAM_RING, // STREAM_NOTIFICATION
362 AudioSystem.STREAM_BLUETOOTH_SCO, // STREAM_BLUETOOTH_SCO
John Spurlock4f0f1202014-08-05 13:28:33 -0400363 AudioSystem.STREAM_RING, // STREAM_SYSTEM_ENFORCED
364 AudioSystem.STREAM_RING, // STREAM_DTMF
Jean-Michel Trivi3f0945a2016-11-11 10:05:18 -0800365 AudioSystem.STREAM_MUSIC, // STREAM_TTS
366 AudioSystem.STREAM_MUSIC // STREAM_ACCESSIBILITY
Eric Laurent6d517662012-04-23 18:42:39 -0700367 };
Yue Li949865b2017-05-24 17:25:28 -0700368 protected static int[] mStreamVolumeAlias;
Eric Laurenta553c252009-07-17 12:17:14 -0700369
Dianne Hackbornba50b97c2013-04-30 15:04:46 -0700370 /**
371 * Map AudioSystem.STREAM_* constants to app ops. This should be used
372 * after mapping through mStreamVolumeAlias.
373 */
John Spurlock59dc9c12015-03-02 11:20:15 -0500374 private static final int[] STREAM_VOLUME_OPS = new int[] {
Dianne Hackbornba50b97c2013-04-30 15:04:46 -0700375 AppOpsManager.OP_AUDIO_VOICE_VOLUME, // STREAM_VOICE_CALL
376 AppOpsManager.OP_AUDIO_MEDIA_VOLUME, // STREAM_SYSTEM
377 AppOpsManager.OP_AUDIO_RING_VOLUME, // STREAM_RING
378 AppOpsManager.OP_AUDIO_MEDIA_VOLUME, // STREAM_MUSIC
379 AppOpsManager.OP_AUDIO_ALARM_VOLUME, // STREAM_ALARM
380 AppOpsManager.OP_AUDIO_NOTIFICATION_VOLUME, // STREAM_NOTIFICATION
381 AppOpsManager.OP_AUDIO_BLUETOOTH_VOLUME, // STREAM_BLUETOOTH_SCO
382 AppOpsManager.OP_AUDIO_MEDIA_VOLUME, // STREAM_SYSTEM_ENFORCED
383 AppOpsManager.OP_AUDIO_MEDIA_VOLUME, // STREAM_DTMF
384 AppOpsManager.OP_AUDIO_MEDIA_VOLUME, // STREAM_TTS
Jean-Michel Trivi3f0945a2016-11-11 10:05:18 -0800385 AppOpsManager.OP_AUDIO_ACCESSIBILITY_VOLUME, // STREAM_ACCESSIBILITY
Dianne Hackbornba50b97c2013-04-30 15:04:46 -0700386 };
387
Eric Laurent83a017b2013-03-19 18:15:31 -0700388 private final boolean mUseFixedVolume;
389
Julia Reynoldseb0ce472018-05-04 15:34:55 -0400390 /**
391 * Default stream type used for volume control in the absence of playback
392 * e.g. user on homescreen, no app playing anything, presses hardware volume buttons, this
393 * stream type is controlled.
394 */
Eric Laurent07584202019-01-24 18:33:49 -0800395 protected static final int DEFAULT_VOL_STREAM_NO_PLAYBACK = AudioSystem.STREAM_MUSIC;
Julia Reynoldseb0ce472018-05-04 15:34:55 -0400396
Glenn Kasten30c918c2011-11-10 17:56:41 -0800397 private final AudioSystem.ErrorCallback mAudioSystemCallback = new AudioSystem.ErrorCallback() {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800398 public void onError(int error) {
399 switch (error) {
400 case AudioSystem.AUDIO_STATUS_SERVER_DIED:
Eric Laurent07584202019-01-24 18:33:49 -0800401 mRecordMonitor.clear();
402
Andy Hunged0ea402015-10-30 14:11:46 -0700403 sendMsg(mAudioHandler, MSG_AUDIO_SERVER_DIED,
Eric Laurentdfb881f2013-07-18 14:41:39 -0700404 SENDMSG_NOOP, 0, 0, null, 0);
Eric Laurent1d3cdce2018-01-20 10:31:21 -0800405 sendMsg(mAudioHandler, MSG_DISPATCH_AUDIO_SERVER_STATE,
406 SENDMSG_QUEUE, 0, 0, null, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800407 break;
408 default:
409 break;
410 }
Eric Laurentdfb881f2013-07-18 14:41:39 -0700411 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800412 };
413
414 /**
415 * Current ringer mode from one of {@link AudioManager#RINGER_MODE_NORMAL},
416 * {@link AudioManager#RINGER_MODE_SILENT}, or
417 * {@link AudioManager#RINGER_MODE_VIBRATE}.
418 */
Jean-Michel Trivi8719a1d2017-11-06 11:52:51 -0800419 @GuardedBy("mSettingsLock")
John Spurlock661f2cf2014-11-17 10:29:10 -0500420 private int mRingerMode; // internal ringer mode, affects muting of underlying streams
Jean-Michel Trivi8719a1d2017-11-06 11:52:51 -0800421 @GuardedBy("mSettingsLock")
John Spurlock661f2cf2014-11-17 10:29:10 -0500422 private int mRingerModeExternal = -1; // reported ringer mode to outside clients (AudioManager)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800423
Eric Laurent9bcf4012009-06-12 06:09:28 -0700424 /** @see System#MODE_RINGER_STREAMS_AFFECTED */
Eric Laurent24e0d9b2013-10-03 18:15:07 -0700425 private int mRingerModeAffectedStreams = 0;
Eric Laurent9bcf4012009-06-12 06:09:28 -0700426
Beverlyd6964762018-02-16 14:07:03 -0500427 private int mZenModeAffectedStreams = 0;
428
429 // Streams currently muted by ringer mode and dnd
430 private int mRingerAndZenModeMutedStreams;
Eric Laurent5b4e6542010-03-19 20:02:21 -0700431
John Spurlock3ce37252015-02-17 13:20:45 -0500432 /** Streams that can be muted. Do not resolve to aliases when checking.
433 * @see System#MUTE_STREAMS_AFFECTED */
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800434 private int mMuteAffectedStreams;
435
436 /**
Eric Laurentbffc3d12012-05-07 17:43:49 -0700437 * NOTE: setVibrateSetting(), getVibrateSetting(), shouldVibrate() are deprecated.
438 * mVibrateSetting is just maintained during deprecation period but vibration policy is
439 * now only controlled by mHasVibrator and mRingerMode
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800440 */
441 private int mVibrateSetting;
442
Eric Laurentbffc3d12012-05-07 17:43:49 -0700443 // Is there a vibrator
444 private final boolean mHasVibrator;
Mike Digman55272862018-02-20 14:35:17 -0800445 // Used to play vibrations
446 private Vibrator mVibrator;
447 private static final AudioAttributes VIBRATION_ATTRIBUTES = new AudioAttributes.Builder()
448 .setContentType(AudioAttributes.CONTENT_TYPE_SONIFICATION)
449 .setUsage(AudioAttributes.USAGE_ASSISTANCE_SONIFICATION)
450 .build();
Eric Laurentbffc3d12012-05-07 17:43:49 -0700451
Eric Laurenta553c252009-07-17 12:17:14 -0700452 // Broadcast receiver for device connections intent broadcasts
453 private final BroadcastReceiver mReceiver = new AudioServiceBroadcastReceiver();
454
Makoto Onukid45a4a22015-11-02 17:17:38 -0800455 /** Interface for UserManagerService. */
456 private final UserManagerInternal mUserManagerInternal;
Sudheer Shankafc46e9b2016-10-21 17:55:27 -0700457 private final ActivityManagerInternal mActivityManagerInternal;
Makoto Onukid45a4a22015-11-02 17:17:38 -0800458
459 private final UserRestrictionsListener mUserRestrictionsListener =
460 new AudioServiceUserRestrictionsListener();
461
Eric Laurent9272b4b2010-01-23 17:12:59 -0800462 // List of binder death handlers for setMode() client processes.
463 // The last process to have called setMode() is at the top of the list.
Jean-Michel Trivi58850372018-09-14 16:01:28 -0700464 // package-private so it can be accessed in AudioDeviceBroker.getSetModeDeathHandlers
465 //TODO candidate to be moved to separate class that handles synchronization
466 @GuardedBy("mDeviceBroker.mSetModeLock")
467 /*package*/ final ArrayList<SetModeDeathHandler> mSetModeDeathHandlers =
468 new ArrayList<SetModeDeathHandler>();
Eric Laurent62ef7672010-11-24 10:58:32 -0800469
Eric Laurenta60e2122010-12-28 16:49:07 -0800470 // true if boot sequence has been completed
Eric Laurent4a5eeb92014-05-06 10:49:04 -0700471 private boolean mSystemReady;
Yasuhiro Matsuda4ced7192015-07-10 22:08:44 +0900472 // true if Intent.ACTION_USER_SWITCHED has ever been received
473 private boolean mUserSwitchedReceived;
Eric Laurenta60e2122010-12-28 16:49:07 -0800474 // listener for SoundPool sample load completion indication
475 private SoundPoolCallback mSoundPoolCallBack;
476 // thread for SoundPool listener
477 private SoundPoolListenerThread mSoundPoolListenerThread;
478 // message looper for SoundPool listener
479 private Looper mSoundPoolLooper = null;
Jean-Michel Trivic55b3932012-06-05 11:57:59 -0700480 // volume applied to sound played with playSoundEffect()
Jean-Michel Trivif2b0c112012-07-09 11:59:11 -0700481 private static int sSoundEffectVolumeDb;
Eric Laurent25101b02011-02-02 09:33:30 -0800482 // previous volume adjustment direction received by checkForRingerModeChange()
483 private int mPrevVolDirection = AudioManager.ADJUST_SAME;
Eric Laurent45c90ce2012-04-24 18:44:22 -0700484 // mVolumeControlStream is set by VolumePanel to temporarily force the stream type which volume
485 // is controlled by Vol keys.
Jean-Michel Trivia7880d42017-04-15 12:41:05 -0700486 private int mVolumeControlStream = -1;
487 // interpretation of whether the volume stream has been selected by the user by clicking on a
488 // volume slider to change which volume is controlled by the volume keys. Is false
489 // when mVolumeControlStream is -1.
490 private boolean mUserSelectedVolumeControlStream = false;
Eric Laurent45c90ce2012-04-24 18:44:22 -0700491 private final Object mForceControlStreamLock = new Object();
492 // VolumePanel is currently the only client of forceVolumeControlStream() and runs in system
493 // server process so in theory it is not necessary to monitor the client death.
494 // However it is good to be ready for future evolutions.
495 private ForceControlStreamClient mForceControlStreamClient = null;
Jeff Sharkey098d5802012-04-26 17:30:34 -0700496 // Used to play ringtones outside system_server
497 private volatile IRingtonePlayer mRingtonePlayer;
Eric Laurent9bc8358d2011-11-18 16:43:31 -0800498
Eric Laurent4bbcc652012-09-24 14:26:30 -0700499 // Devices for which the volume is fixed and VolumePanel slider should be disabled
Eric Laurent212532b2014-07-21 15:43:18 -0700500 int mFixedVolumeDevices = AudioSystem.DEVICE_OUT_HDMI |
Eric Laurent4bbcc652012-09-24 14:26:30 -0700501 AudioSystem.DEVICE_OUT_DGTL_DOCK_HEADSET |
Eric Laurent212532b2014-07-21 15:43:18 -0700502 AudioSystem.DEVICE_OUT_ANLG_DOCK_HEADSET |
503 AudioSystem.DEVICE_OUT_HDMI_ARC |
504 AudioSystem.DEVICE_OUT_SPDIF |
505 AudioSystem.DEVICE_OUT_AUX_LINE;
Jakub Pawlowskic274fb22018-04-04 10:15:12 -0700506 int mFullVolumeDevices = 0;
Eric Laurent4bbcc652012-09-24 14:26:30 -0700507
Jean-Michel Trivibb6f8712013-05-23 15:02:41 -0700508 private final boolean mMonitorRotation;
Eric Laurentd640bd32012-09-28 18:01:48 -0700509
Eric Laurent7ee1e4f2012-10-26 18:11:21 -0700510 private boolean mDockAudioMediaEnabled = true;
511
Eric Laurent08ed1b92012-11-05 14:54:12 -0800512 private int mDockState = Intent.EXTRA_DOCK_STATE_UNDOCKED;
513
Eric Laurentfde16d52012-12-03 14:42:39 -0800514 // Used when safe volume warning message display is requested by setStreamVolume(). In this
515 // case, the new requested volume, stream type and device are stored in mPendingVolumeCommand
516 // and used later when/if disableSafeMediaVolume() is called.
517 private StreamVolumeCommand mPendingVolumeCommand;
518
Jean-Michel Trivifa9a6982013-06-27 16:22:58 -0700519 private PowerManager.WakeLock mAudioEventWakeLock;
520
521 private final MediaFocusControl mMediaFocusControl;
522
Tomoharu Kasaharaf0fecb12018-09-06 20:04:38 +0900523 // Pre-scale for Bluetooth Absolute Volume
524 private float[] mPrescaleAbsoluteVolume = new float[] {
525 0.5f, // Pre-scale for index 1
526 0.7f, // Pre-scale for index 2
527 0.85f, // Pre-scale for index 3
528 };
529
Julia Reynolds48034f82016-03-09 10:15:16 -0500530 private NotificationManager mNm;
John Spurlock661f2cf2014-11-17 10:29:10 -0500531 private AudioManagerInternal.RingerModeDelegate mRingerModeDelegate;
John Spurlocka48d7792015-03-03 17:35:57 -0500532 private VolumePolicy mVolumePolicy = VolumePolicy.DEFAULT;
John Spurlock07e72432015-03-13 11:46:52 -0400533 private long mLoweredFromNormalToVibrateTime;
John Spurlock661f2cf2014-11-17 10:29:10 -0500534
Phil Weaverf1a9aff2017-03-23 17:21:29 -0700535 // Array of Uids of valid accessibility services to check if caller is one of them
536 private int[] mAccessibilityServiceUids;
537 private final Object mAccessibilityServiceUidsLock = new Object();
538
jiabin39940752018-04-02 18:18:45 -0700539 private int mEncodedSurroundMode;
540 private String mEnabledSurroundFormats;
541 private boolean mSurroundModeChanged;
542
Eric Laurent1c9c1d52018-10-17 10:06:46 -0700543 @GuardedBy("mSettingsLock")
544 private int mAssistantUid;
545
Paul McLean10804eb2015-01-28 11:16:35 -0800546 // Defines the format for the connection "address" for ALSA devices
547 public static String makeAlsaAddressString(int card, int device) {
548 return "card=" + card + ";device=" + device + ";";
549 }
550
Makoto Onukie1aef852015-10-15 17:28:35 -0700551 public static final class Lifecycle extends SystemService {
552 private AudioService mService;
553
554 public Lifecycle(Context context) {
555 super(context);
556 mService = new AudioService(context);
557 }
558
559 @Override
560 public void onStart() {
561 publishBinderService(Context.AUDIO_SERVICE, mService);
562 }
563
564 @Override
565 public void onBootPhase(int phase) {
566 if (phase == SystemService.PHASE_ACTIVITY_MANAGER_READY) {
567 mService.systemReady();
568 }
569 }
570 }
571
Dianne Hackborn3e99f652017-07-05 16:33:56 -0700572 final private IUidObserver mUidObserver = new IUidObserver.Stub() {
573 @Override public void onUidStateChanged(int uid, int procState, long procStateSeq) {
574 }
575
576 @Override public void onUidGone(int uid, boolean disabled) {
577 // Once the uid is no longer running, no need to keep trying to disable its audio.
578 disableAudioForUid(false, uid);
579 }
580
581 @Override public void onUidActive(int uid) throws RemoteException {
582 }
583
584 @Override public void onUidIdle(int uid, boolean disabled) {
585 }
586
587 @Override public void onUidCachedChanged(int uid, boolean cached) {
588 disableAudioForUid(cached, uid);
589 }
590
591 private void disableAudioForUid(boolean disable, int uid) {
592 queueMsgUnderWakeLock(mAudioHandler, MSG_DISABLE_AUDIO_FOR_UID,
593 disable ? 1 : 0 /* arg1 */, uid /* arg2 */,
594 null /* obj */, 0 /* delay */);
595 }
596 };
597
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800598 ///////////////////////////////////////////////////////////////////////////
599 // Construction
600 ///////////////////////////////////////////////////////////////////////////
601
602 /** @hide */
603 public AudioService(Context context) {
604 mContext = context;
605 mContentResolver = context.getContentResolver();
Dianne Hackbornba50b97c2013-04-30 15:04:46 -0700606 mAppOps = (AppOpsManager)context.getSystemService(Context.APP_OPS_SERVICE);
Eric Laurent212532b2014-07-21 15:43:18 -0700607
John Spurlock61560172015-02-06 19:46:04 -0500608 mPlatformType = AudioSystem.getPlatformType(context);
Jared Suttles59820132009-08-13 21:50:52 -0500609
Muyuan Li1ed6df62016-06-18 11:16:52 -0700610 mIsSingleVolume = AudioSystem.isSingleVolume(context);
611
Makoto Onukid45a4a22015-11-02 17:17:38 -0800612 mUserManagerInternal = LocalServices.getService(UserManagerInternal.class);
Sudheer Shankafc46e9b2016-10-21 17:55:27 -0700613 mActivityManagerInternal = LocalServices.getService(ActivityManagerInternal.class);
Makoto Onukid45a4a22015-11-02 17:17:38 -0800614
Jean-Michel Trivic6802222012-04-30 11:15:03 -0700615 PowerManager pm = (PowerManager)context.getSystemService(Context.POWER_SERVICE);
Jean-Michel Trivifa9a6982013-06-27 16:22:58 -0700616 mAudioEventWakeLock = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "handleAudioEvent");
Jean-Michel Trivic6802222012-04-30 11:15:03 -0700617
Mike Digman55272862018-02-20 14:35:17 -0800618 mVibrator = (Vibrator) context.getSystemService(Context.VIBRATOR_SERVICE);
619 mHasVibrator = mVibrator == null ? false : mVibrator.hasVibrator();
Eric Laurentbffc3d12012-05-07 17:43:49 -0700620
John Spurlockb6e19e32015-03-10 21:33:44 -0400621 // Initialize volume
Eric Laurent403bd342017-07-11 16:21:44 -0700622 int maxCallVolume = SystemProperties.getInt("ro.config.vc_call_vol_steps", -1);
623 if (maxCallVolume != -1) {
624 MAX_STREAM_VOLUME[AudioSystem.STREAM_VOICE_CALL] = maxCallVolume;
Shuhei Miyazaki89091ba2018-01-11 18:17:04 +0900625 }
626
627 int defaultCallVolume = SystemProperties.getInt("ro.config.vc_call_vol_default", -1);
628 if (defaultCallVolume != -1 &&
629 defaultCallVolume <= MAX_STREAM_VOLUME[AudioSystem.STREAM_VOICE_CALL] &&
630 defaultCallVolume >= MIN_STREAM_VOLUME[AudioSystem.STREAM_VOICE_CALL]) {
631 AudioSystem.DEFAULT_STREAM_VOLUME[AudioSystem.STREAM_VOICE_CALL] = defaultCallVolume;
632 } else {
Eric Laurent403bd342017-07-11 16:21:44 -0700633 AudioSystem.DEFAULT_STREAM_VOLUME[AudioSystem.STREAM_VOICE_CALL] =
634 (maxCallVolume * 3) / 4;
Eric Laurent91377de2014-10-10 15:24:04 -0700635 }
Eric Laurent403bd342017-07-11 16:21:44 -0700636
637 int maxMusicVolume = SystemProperties.getInt("ro.config.media_vol_steps", -1);
638 if (maxMusicVolume != -1) {
639 MAX_STREAM_VOLUME[AudioSystem.STREAM_MUSIC] = maxMusicVolume;
640 }
641
642 int defaultMusicVolume = SystemProperties.getInt("ro.config.media_vol_default", -1);
643 if (defaultMusicVolume != -1 &&
Shuhei Miyazaki89091ba2018-01-11 18:17:04 +0900644 defaultMusicVolume <= MAX_STREAM_VOLUME[AudioSystem.STREAM_MUSIC] &&
645 defaultMusicVolume >= MIN_STREAM_VOLUME[AudioSystem.STREAM_MUSIC]) {
Eric Laurent403bd342017-07-11 16:21:44 -0700646 AudioSystem.DEFAULT_STREAM_VOLUME[AudioSystem.STREAM_MUSIC] = defaultMusicVolume;
647 } else {
Hank Freund45926dc2015-12-11 10:50:45 -0800648 if (isPlatformTelevision()) {
Eric Laurent403bd342017-07-11 16:21:44 -0700649 AudioSystem.DEFAULT_STREAM_VOLUME[AudioSystem.STREAM_MUSIC] =
650 MAX_STREAM_VOLUME[AudioSystem.STREAM_MUSIC] / 4;
Hank Freund45926dc2015-12-11 10:50:45 -0800651 } else {
Eric Laurent403bd342017-07-11 16:21:44 -0700652 AudioSystem.DEFAULT_STREAM_VOLUME[AudioSystem.STREAM_MUSIC] =
653 MAX_STREAM_VOLUME[AudioSystem.STREAM_MUSIC] / 3;
Hank Freund45926dc2015-12-11 10:50:45 -0800654 }
Eric Laurent91377de2014-10-10 15:24:04 -0700655 }
Jared Suttles59820132009-08-13 21:50:52 -0500656
Chris Kuiper09b6c212018-01-03 22:22:13 -0800657 int maxAlarmVolume = SystemProperties.getInt("ro.config.alarm_vol_steps", -1);
658 if (maxAlarmVolume != -1) {
659 MAX_STREAM_VOLUME[AudioSystem.STREAM_ALARM] = maxAlarmVolume;
660 }
661
662 int defaultAlarmVolume = SystemProperties.getInt("ro.config.alarm_vol_default", -1);
663 if (defaultAlarmVolume != -1 &&
664 defaultAlarmVolume <= MAX_STREAM_VOLUME[AudioSystem.STREAM_ALARM]) {
665 AudioSystem.DEFAULT_STREAM_VOLUME[AudioSystem.STREAM_ALARM] = defaultAlarmVolume;
666 } else {
667 // Default is 6 out of 7 (default maximum), so scale accordingly.
668 AudioSystem.DEFAULT_STREAM_VOLUME[AudioSystem.STREAM_ALARM] =
669 6 * MAX_STREAM_VOLUME[AudioSystem.STREAM_ALARM] / 7;
670 }
671
672 int maxSystemVolume = SystemProperties.getInt("ro.config.system_vol_steps", -1);
673 if (maxSystemVolume != -1) {
674 MAX_STREAM_VOLUME[AudioSystem.STREAM_SYSTEM] = maxSystemVolume;
675 }
676
677 int defaultSystemVolume = SystemProperties.getInt("ro.config.system_vol_default", -1);
678 if (defaultSystemVolume != -1 &&
679 defaultSystemVolume <= MAX_STREAM_VOLUME[AudioSystem.STREAM_SYSTEM]) {
680 AudioSystem.DEFAULT_STREAM_VOLUME[AudioSystem.STREAM_SYSTEM] = defaultSystemVolume;
681 } else {
682 // Default is to use maximum.
683 AudioSystem.DEFAULT_STREAM_VOLUME[AudioSystem.STREAM_SYSTEM] =
684 MAX_STREAM_VOLUME[AudioSystem.STREAM_SYSTEM];
685 }
686
Jean-Michel Trivif2b0c112012-07-09 11:59:11 -0700687 sSoundEffectVolumeDb = context.getResources().getInteger(
Jean-Michel Trivic55b3932012-06-05 11:57:59 -0700688 com.android.internal.R.integer.config_soundEffectVolumeDb);
Eric Laurent25101b02011-02-02 09:33:30 -0800689
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800690 createAudioSystemThread();
Eric Laurentdd45d012012-10-08 09:04:34 -0700691
Eric Laurentdfb881f2013-07-18 14:41:39 -0700692 AudioSystem.setErrorCallback(mAudioSystemCallback);
693
John Spurlock5e783732015-02-19 10:28:59 -0500694 boolean cameraSoundForced = readCameraSoundForced();
Eric Laurentdd45d012012-10-08 09:04:34 -0700695 mCameraSoundForced = new Boolean(cameraSoundForced);
696 sendMsg(mAudioHandler,
697 MSG_SET_FORCE_USE,
698 SENDMSG_QUEUE,
699 AudioSystem.FOR_SYSTEM,
700 cameraSoundForced ?
701 AudioSystem.FORCE_SYSTEM_ENFORCED : AudioSystem.FORCE_NONE,
Jean-Michel Trivi011f39e2017-08-19 18:08:06 -0700702 new String("AudioService ctor"),
Eric Laurentdd45d012012-10-08 09:04:34 -0700703 0);
704
hyomin.ohd0446dc2018-10-18 13:58:27 +0900705 mSafeMediaVolumeState = Settings.Global.getInt(mContentResolver,
706 Settings.Global.AUDIO_SAFE_VOLUME_STATE,
707 SAFE_MEDIA_VOLUME_NOT_CONFIGURED);
Eric Laurent05274f32012-11-29 12:48:18 -0800708 // The default safe volume index read here will be replaced by the actual value when
709 // the mcc is read by onConfigureSafeVolume()
710 mSafeMediaVolumeIndex = mContext.getResources().getInteger(
711 com.android.internal.R.integer.config_safe_media_volume_index) * 10;
712
Eric Laurent83a017b2013-03-19 18:15:31 -0700713 mUseFixedVolume = mContext.getResources().getBoolean(
714 com.android.internal.R.bool.config_useFixedVolume);
715
Jean-Michel Trivi58850372018-09-14 16:01:28 -0700716 mDeviceBroker = new AudioDeviceBroker(mContext, this);
717
Eric Laurent24e0d9b2013-10-03 18:15:07 -0700718 // must be called before readPersistedSettings() which needs a valid mStreamVolumeAlias[]
719 // array initialized by updateStreamVolumeAlias()
John Spurlock90874332015-03-10 16:00:54 -0400720 updateStreamVolumeAlias(false /*updateVolumes*/, TAG);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800721 readPersistedSettings();
Eric Laurentc0232482016-03-15 18:19:23 -0700722 readUserRestrictions();
Eric Laurentc1d41662011-07-19 11:21:13 -0700723 mSettingsObserver = new SettingsObserver();
Eric Laurenta553c252009-07-17 12:17:14 -0700724 createStreamStates();
Eric Laurent9f103de2011-09-08 15:04:23 -0700725
Eric Laurentb378a13a2017-07-11 14:08:11 -0700726 // mSafeUsbMediaVolumeIndex must be initialized after createStreamStates() because it
727 // relies on audio policy having correct ranges for volume indexes.
728 mSafeUsbMediaVolumeIndex = getSafeUsbMediaVolumeIndex();
729
Eric Laurente5a351c2017-09-27 20:11:51 -0700730 mPlaybackMonitor =
731 new PlaybackActivityMonitor(context, MAX_STREAM_VOLUME[AudioSystem.STREAM_ALARM]);
732
Jean-Michel Trivi99489cc2017-01-25 19:08:49 -0800733 mMediaFocusControl = new MediaFocusControl(mContext, mPlaybackMonitor);
John Spurlockb6e19e32015-03-10 21:33:44 -0400734
Jean-Michel Trivi66ffacf2017-02-04 17:25:31 -0800735 mRecordMonitor = new RecordingActivityMonitor(mContext);
736
Glenn Kastenfd116ad2013-07-12 17:10:39 -0700737 readAndSetLowRamDevice();
Eric Laurent3891c4c2010-04-20 09:40:57 -0700738
739 // Call setRingerModeInt() to apply correct mute
740 // state on streams affected by ringer mode.
Beverlyd6964762018-02-16 14:07:03 -0500741 mRingerAndZenModeMutedStreams = 0;
John Spurlock661f2cf2014-11-17 10:29:10 -0500742 setRingerModeInt(getRingerModeInternal(), false);
Eric Laurent3891c4c2010-04-20 09:40:57 -0700743
Eric Laurenta553c252009-07-17 12:17:14 -0700744 // Register for device connection intent broadcasts.
745 IntentFilter intentFilter =
Eric Laurentb1fbaac2012-05-29 09:24:28 -0700746 new IntentFilter(BluetoothHeadset.ACTION_AUDIO_STATE_CHANGED);
Jack He8dd33942018-01-17 15:45:12 -0800747 intentFilter.addAction(BluetoothHeadset.ACTION_ACTIVE_DEVICE_CHANGED);
Jaikumar Ganesh82aa7f02010-09-27 17:05:10 -0700748 intentFilter.addAction(Intent.ACTION_DOCK_EVENT);
Eric Laurent950e8cb2011-10-13 08:57:54 -0700749 intentFilter.addAction(Intent.ACTION_SCREEN_ON);
750 intentFilter.addAction(Intent.ACTION_SCREEN_OFF);
Eric Laurentbc0fab1f2012-09-19 11:24:41 -0700751 intentFilter.addAction(Intent.ACTION_USER_SWITCHED);
Fyodor Kupolovb5013302015-04-17 17:59:14 -0700752 intentFilter.addAction(Intent.ACTION_USER_BACKGROUND);
753 intentFilter.addAction(Intent.ACTION_USER_FOREGROUND);
Paul McLeanc837a452014-04-09 09:04:43 -0700754 intentFilter.addAction(UsbManager.ACTION_USB_DEVICE_ATTACHED);
Eric Laurentb70b78a2016-01-13 19:16:04 -0800755 intentFilter.addAction(BluetoothAdapter.ACTION_STATE_CHANGED);
Jean-Michel Trivif26f0172012-04-25 16:23:20 -0700756
Eric Laurentd640bd32012-09-28 18:01:48 -0700757 intentFilter.addAction(Intent.ACTION_CONFIGURATION_CHANGED);
Jean-Michel Trivibb6f8712013-05-23 15:02:41 -0700758 mMonitorRotation = SystemProperties.getBoolean("ro.audio.monitorRotation", false);
759 if (mMonitorRotation) {
Jean-Michel Trivi24806db2015-10-01 15:00:59 -0700760 RotationHelper.init(mContext, mAudioHandler);
Jean-Michel Trivibb6f8712013-05-23 15:02:41 -0700761 }
Jean-Michel Trivif26f0172012-04-25 16:23:20 -0700762
Marco Nelissenfb6df0b2017-02-15 15:25:24 -0800763 intentFilter.addAction(AudioEffect.ACTION_OPEN_AUDIO_EFFECT_CONTROL_SESSION);
764 intentFilter.addAction(AudioEffect.ACTION_CLOSE_AUDIO_EFFECT_CONTROL_SESSION);
765
Fyodor Kupolovb5013302015-04-17 17:59:14 -0700766 context.registerReceiverAsUser(mReceiver, UserHandle.ALL, intentFilter, null, null);
Jared Suttles59820132009-08-13 21:50:52 -0500767
RoboErik0dac35a2014-08-12 15:48:49 -0700768 LocalServices.addService(AudioManagerInternal.class, new AudioServiceInternal());
Makoto Onukid45a4a22015-11-02 17:17:38 -0800769
770 mUserManagerInternal.addUserRestrictionsListener(mUserRestrictionsListener);
Jean-Michel Trivid3c71f02015-12-07 11:59:31 -0800771
772 mRecordMonitor.initMonitor();
Tomoharu Kasaharaf0fecb12018-09-06 20:04:38 +0900773
774 final float[] preScale = new float[3];
775 preScale[0] = mContext.getResources().getFraction(
776 com.android.internal.R.fraction.config_prescaleAbsoluteVolume_index1,
777 1, 1);
778 preScale[1] = mContext.getResources().getFraction(
779 com.android.internal.R.fraction.config_prescaleAbsoluteVolume_index2,
780 1, 1);
781 preScale[2] = mContext.getResources().getFraction(
782 com.android.internal.R.fraction.config_prescaleAbsoluteVolume_index3,
783 1, 1);
784 for (int i = 0; i < preScale.length; i++) {
785 if (0.0f <= preScale[i] && preScale[i] <= 1.0f) {
786 mPrescaleAbsoluteVolume[i] = preScale[i];
787 }
788 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800789 }
790
Eric Laurent4a5eeb92014-05-06 10:49:04 -0700791 public void systemReady() {
792 sendMsg(mAudioHandler, MSG_SYSTEM_READY, SENDMSG_QUEUE,
793 0, 0, null, 0);
Dianne Hackborn3e3600e2017-08-31 11:15:26 -0700794 if (false) {
795 // This is turned off for now, because it is racy and thus causes apps to break.
796 // Currently banning a uid means that if an app tries to start playing an audio
797 // stream, that will be preventing, and unbanning it will not allow that stream
798 // to resume. However these changes in uid state are racy with what the app is doing,
799 // so that after taking a process out of the cached state we can't guarantee that
800 // we will unban the uid before the app actually tries to start playing audio.
801 // (To do that, the activity manager would need to wait until it knows for sure
802 // that the ban has been removed, before telling the app to do whatever it is
803 // supposed to do that caused it to go out of the cached state.)
804 try {
805 ActivityManager.getService().registerUidObserver(mUidObserver,
806 ActivityManager.UID_OBSERVER_CACHED | ActivityManager.UID_OBSERVER_GONE,
807 ActivityManager.PROCESS_STATE_UNKNOWN, null);
808 } catch (RemoteException e) {
809 // ignored; both services live in system_server
810 }
Dianne Hackborn3e99f652017-07-05 16:33:56 -0700811 }
Eric Laurent4a5eeb92014-05-06 10:49:04 -0700812 }
813
814 public void onSystemReady() {
815 mSystemReady = true;
816 sendMsg(mAudioHandler, MSG_LOAD_SOUND_EFFECTS, SENDMSG_QUEUE,
817 0, 0, null, 0);
818
Jean-Michel Trivi58850372018-09-14 16:01:28 -0700819 mDeviceBroker.onSystemReady();
Eric Laurent4a5eeb92014-05-06 10:49:04 -0700820
Jeff Sharkey73ea0ae2016-08-10 17:30:38 -0600821 if (mContext.getPackageManager().hasSystemFeature(PackageManager.FEATURE_HDMI_CEC)) {
Shubangc480a712018-06-11 18:02:42 -0700822 synchronized (mHdmiClientLock) {
823 mHdmiManager = mContext.getSystemService(HdmiControlManager.class);
Eric Laurent212532b2014-07-21 15:43:18 -0700824 mHdmiTvClient = mHdmiManager.getTvClient();
Jungshik Jangc9ff9682014-09-15 17:41:06 +0900825 if (mHdmiTvClient != null) {
826 mFixedVolumeDevices &= ~AudioSystem.DEVICE_ALL_HDMI_SYSTEM_AUDIO_AND_SPEAKER;
827 }
Eric Laurent212532b2014-07-21 15:43:18 -0700828 mHdmiPlaybackClient = mHdmiManager.getPlaybackClient();
829 mHdmiCecSink = false;
Shubangc480a712018-06-11 18:02:42 -0700830 mHdmiAudioSystemClient = mHdmiManager.getAudioSystemClient();
Eric Laurent212532b2014-07-21 15:43:18 -0700831 }
832 }
Wonsik Kim7f4342e2014-07-20 23:04:59 +0900833
Julia Reynolds48034f82016-03-09 10:15:16 -0500834 mNm = (NotificationManager) mContext.getSystemService(Context.NOTIFICATION_SERVICE);
835
Eric Laurent4a5eeb92014-05-06 10:49:04 -0700836 sendMsg(mAudioHandler,
837 MSG_CONFIGURE_SAFE_MEDIA_VOLUME_FORCED,
838 SENDMSG_REPLACE,
839 0,
840 0,
John Spurlock90874332015-03-10 16:00:54 -0400841 TAG,
Eric Laurent03332ab2017-02-09 18:29:15 -0800842 SystemProperties.getBoolean("audio.safemedia.bypass", false) ?
843 0 : SAFE_VOLUME_CONFIGURE_TIMEOUT_MS);
Jean-Michel Trivi873cc452014-09-11 17:25:09 -0700844
Jean-Michel Trivicfa55532017-01-18 11:17:51 -0800845 initA11yMonitoring();
Eric Laurent0867bed2015-05-20 14:49:08 -0700846 onIndicateSystemReady();
847 }
848
849 void onIndicateSystemReady() {
850 if (AudioSystem.systemReady() == AudioSystem.SUCCESS) {
851 return;
852 }
853 sendMsg(mAudioHandler,
854 MSG_INDICATE_SYSTEM_READY,
855 SENDMSG_REPLACE,
856 0,
857 0,
858 null,
859 INDICATE_SYSTEM_READY_RETRY_DELAY_MS);
860 }
861
Andy Hunged0ea402015-10-30 14:11:46 -0700862 public void onAudioServerDied() {
Eric Laurent0867bed2015-05-20 14:49:08 -0700863 if (!mSystemReady ||
864 (AudioSystem.checkAudioFlinger() != AudioSystem.AUDIO_STATUS_OK)) {
Andy Hunged0ea402015-10-30 14:11:46 -0700865 Log.e(TAG, "Audioserver died.");
866 sendMsg(mAudioHandler, MSG_AUDIO_SERVER_DIED, SENDMSG_NOOP, 0, 0,
Eric Laurent0867bed2015-05-20 14:49:08 -0700867 null, 500);
868 return;
869 }
Andy Hunged0ea402015-10-30 14:11:46 -0700870 Log.e(TAG, "Audioserver started.");
Eric Laurent0867bed2015-05-20 14:49:08 -0700871
872 // indicate to audio HAL that we start the reconfiguration phase after a media
873 // server crash
874 // Note that we only execute this when the media server
875 // process restarts after a crash, not the first time it is started.
876 AudioSystem.setParameters("restarting=true");
877
878 readAndSetLowRamDevice();
879
Jean-Michel Trivi58850372018-09-14 16:01:28 -0700880 // Restore device connection states, BT state
881 mDeviceBroker.onAudioServerDied();
882
Eric Laurent0867bed2015-05-20 14:49:08 -0700883 // Restore call state
Jean-Michel Trivi011f39e2017-08-19 18:08:06 -0700884 if (AudioSystem.setPhoneState(mMode) == AudioSystem.AUDIO_STATUS_OK) {
885 mModeLogger.log(new AudioEventLogger.StringEvent(
886 "onAudioServerDied causes setPhoneState(" + AudioSystem.modeToString(mMode) + ")"));
887 }
Eric Laurent0867bed2015-05-20 14:49:08 -0700888
Jean-Michel Trivi8719a1d2017-11-06 11:52:51 -0800889 final int forSys;
890 synchronized (mSettingsLock) {
891 forSys = mCameraSoundForced ?
892 AudioSystem.FORCE_SYSTEM_ENFORCED : AudioSystem.FORCE_NONE;
893 }
Jean-Michel Trivi58850372018-09-14 16:01:28 -0700894
895 mDeviceBroker.setForceUse_Async(AudioSystem.FOR_SYSTEM, forSys, "onAudioServerDied");
Eric Laurent0867bed2015-05-20 14:49:08 -0700896
897 // Restore stream volumes
898 int numStreamTypes = AudioSystem.getNumStreamTypes();
899 for (int streamType = numStreamTypes - 1; streamType >= 0; streamType--) {
900 VolumeStreamState streamState = mStreamStates[streamType];
Eric Laurente4381ec2015-10-29 17:52:48 -0700901 AudioSystem.initStreamVolume(
902 streamType, streamState.mIndexMin / 10, streamState.mIndexMax / 10);
Eric Laurent0867bed2015-05-20 14:49:08 -0700903
904 streamState.applyAllVolumes();
905 }
906
Andy Hungf04b84d2015-12-18 17:33:27 -0800907 // Restore mono mode
Andy Hung7b98e9a2016-02-25 18:34:50 -0800908 updateMasterMono(mContentResolver);
Andy Hungf04b84d2015-12-18 17:33:27 -0800909
Edward Savage-Jones35c292f2017-01-13 09:04:34 +0100910 // Restore audio balance
911 updateMasterBalance(mContentResolver);
912
Eric Laurent0867bed2015-05-20 14:49:08 -0700913 // Restore ringer mode
914 setRingerModeInt(getRingerModeInternal(), false);
915
Mikhail Naganovb668bc62018-02-13 13:46:38 -0800916 // Reset device rotation (if monitored for this device)
Eric Laurent0867bed2015-05-20 14:49:08 -0700917 if (mMonitorRotation) {
Jean-Michel Trivi24806db2015-10-01 15:00:59 -0700918 RotationHelper.updateOrientation();
Eric Laurent0867bed2015-05-20 14:49:08 -0700919 }
920
Eric Laurent0867bed2015-05-20 14:49:08 -0700921 synchronized (mSettingsLock) {
Jean-Michel Trivi011f39e2017-08-19 18:08:06 -0700922 final int forDock = mDockAudioMediaEnabled ?
923 AudioSystem.FORCE_ANALOG_DOCK : AudioSystem.FORCE_NONE;
Jean-Michel Trivi58850372018-09-14 16:01:28 -0700924 mDeviceBroker.setForceUse_Async(AudioSystem.FOR_DOCK, forDock, "onAudioServerDied");
Jean-Michel Trivi011f39e2017-08-19 18:08:06 -0700925 sendEncodedSurroundMode(mContentResolver, "onAudioServerDied");
jiabin39940752018-04-02 18:18:45 -0700926 sendEnabledSurroundFormats(mContentResolver, true);
Eric Laurent1c9c1d52018-10-17 10:06:46 -0700927 updateAssistantUId(true);
928 }
929 synchronized (mAccessibilityServiceUidsLock) {
930 AudioSystem.setA11yServicesUids(mAccessibilityServiceUids);
Eric Laurent0867bed2015-05-20 14:49:08 -0700931 }
Shubangc480a712018-06-11 18:02:42 -0700932 synchronized (mHdmiClientLock) {
933 if (mHdmiManager != null && mHdmiTvClient != null) {
934 setHdmiSystemAudioSupported(mHdmiSystemAudioSupported);
Eric Laurent0867bed2015-05-20 14:49:08 -0700935 }
936 }
937
938 synchronized (mAudioPolicies) {
939 for (AudioPolicyProxy policy : mAudioPolicies.values()) {
940 policy.connectMixes();
941 }
942 }
943
944 onIndicateSystemReady();
945 // indicate the end of reconfiguration phase to audio HAL
946 AudioSystem.setParameters("restarting=false");
Eric Laurent1d3cdce2018-01-20 10:31:21 -0800947
948 sendMsg(mAudioHandler, MSG_DISPATCH_AUDIO_SERVER_STATE,
949 SENDMSG_QUEUE, 1, 0, null, 0);
950 }
951
952 private void onDispatchAudioServerStateChange(boolean state) {
953 synchronized (mAudioServerStateListeners) {
954 for (AsdProxy asdp : mAudioServerStateListeners.values()) {
955 try {
956 asdp.callback().dispatchAudioServerStateChange(state);
957 } catch (RemoteException e) {
958 Log.w(TAG, "Could not call dispatchAudioServerStateChange()", e);
959 }
960 }
961 }
Eric Laurent4a5eeb92014-05-06 10:49:04 -0700962 }
963
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800964 private void createAudioSystemThread() {
965 mAudioSystemThread = new AudioSystemThread();
966 mAudioSystemThread.start();
967 waitForAudioHandlerCreation();
968 }
969
970 /** Waits for the volume handler to be created by the other thread. */
971 private void waitForAudioHandlerCreation() {
972 synchronized(this) {
973 while (mAudioHandler == null) {
974 try {
975 // Wait for mAudioHandler to be set by the other thread
976 wait();
977 } catch (InterruptedException e) {
978 Log.e(TAG, "Interrupted while waiting on volume handler.");
979 }
980 }
981 }
982 }
983
Eric Laurent24482012012-05-10 09:41:17 -0700984 private void checkAllAliasStreamVolumes() {
Jean-Michel Trivi085346a2018-02-14 10:48:51 -0800985 synchronized (mSettingsLock) {
986 synchronized (VolumeStreamState.class) {
987 int numStreamTypes = AudioSystem.getNumStreamTypes();
988 for (int streamType = 0; streamType < numStreamTypes; streamType++) {
989 mStreamStates[streamType]
990 .setAllIndexes(mStreamStates[mStreamVolumeAlias[streamType]], TAG);
991 // apply stream volume
992 if (!mStreamStates[streamType].mIsMuted) {
993 mStreamStates[streamType].applyAllVolumes();
994 }
Eric Laurent8fa4d6f2014-10-30 14:13:03 -0700995 }
Eric Laurent24482012012-05-10 09:41:17 -0700996 }
997 }
998 }
999
Jean-Michel Trivi58850372018-09-14 16:01:28 -07001000 /**
1001 * Called from AudioDeviceBroker when DEVICE_OUT_HDMI is connected or disconnected.
1002 */
1003 /*package*/ void checkVolumeCecOnHdmiConnection(int state, String caller) {
1004 if (state != 0) {
1005 // DEVICE_OUT_HDMI is now connected
1006 if ((AudioSystem.DEVICE_OUT_HDMI & mSafeMediaVolumeDevices) != 0) {
1007 sendMsg(mAudioHandler,
1008 MSG_CHECK_MUSIC_ACTIVE,
1009 SENDMSG_REPLACE,
1010 0,
1011 0,
1012 caller,
1013 MUSIC_ACTIVE_POLL_PERIOD_MS);
1014 }
1015
1016 if (isPlatformTelevision()) {
1017 mFixedVolumeDevices |= AudioSystem.DEVICE_OUT_HDMI;
1018 checkAllFixedVolumeDevices();
1019 synchronized (mHdmiClientLock) {
1020 if (mHdmiManager != null && mHdmiPlaybackClient != null) {
1021 mHdmiCecSink = false;
1022 mHdmiPlaybackClient.queryDisplayStatus(mHdmiDisplayStatusCallback);
1023 }
1024 }
1025 }
1026 sendEnabledSurroundFormats(mContentResolver, true);
1027 } else {
1028 // DEVICE_OUT_HDMI disconnected
1029 if (isPlatformTelevision()) {
1030 synchronized (mHdmiClientLock) {
1031 if (mHdmiManager != null) {
1032 mHdmiCecSink = false;
1033 }
1034 }
1035 }
1036 }
1037 }
1038
Eric Laurent212532b2014-07-21 15:43:18 -07001039 private void checkAllFixedVolumeDevices()
1040 {
1041 int numStreamTypes = AudioSystem.getNumStreamTypes();
1042 for (int streamType = 0; streamType < numStreamTypes; streamType++) {
1043 mStreamStates[streamType].checkFixedVolumeDevices();
1044 }
1045 }
1046
Jean-Michel Triviba5270b2014-10-01 17:49:29 -07001047 private void checkAllFixedVolumeDevices(int streamType) {
1048 mStreamStates[streamType].checkFixedVolumeDevices();
1049 }
1050
John Spurlockb6e19e32015-03-10 21:33:44 -04001051 private void checkMuteAffectedStreams() {
1052 // any stream with a min level > 0 is not muteable by definition
Tomoharu Kasaharaa0d0c542019-01-18 20:04:38 +09001053 // STREAM_VOICE_CALL and STREAM_BLUETOOTH_SCO can be muted by applications
1054 // that has the the MODIFY_PHONE_STATE permission.
John Spurlockb6e19e32015-03-10 21:33:44 -04001055 for (int i = 0; i < mStreamStates.length; i++) {
1056 final VolumeStreamState vss = mStreamStates[i];
Nadav Bar6b7751d2017-12-24 16:03:08 +02001057 if (vss.mIndexMin > 0 &&
Tomoharu Kasaharaa0d0c542019-01-18 20:04:38 +09001058 (vss.mStreamType != AudioSystem.STREAM_VOICE_CALL &&
1059 vss.mStreamType != AudioSystem.STREAM_BLUETOOTH_SCO)) {
John Spurlockb6e19e32015-03-10 21:33:44 -04001060 mMuteAffectedStreams &= ~(1 << vss.mStreamType);
1061 }
1062 }
1063 }
1064
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001065 private void createStreamStates() {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001066 int numStreamTypes = AudioSystem.getNumStreamTypes();
1067 VolumeStreamState[] streams = mStreamStates = new VolumeStreamState[numStreamTypes];
1068
1069 for (int i = 0; i < numStreamTypes; i++) {
Jean-Michel Trivia53b7052017-04-12 18:27:01 -07001070 streams[i] =
1071 new VolumeStreamState(System.VOLUME_SETTINGS_INT[mStreamVolumeAlias[i]], i);
Eric Laurenta553c252009-07-17 12:17:14 -07001072 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001073
Eric Laurent212532b2014-07-21 15:43:18 -07001074 checkAllFixedVolumeDevices();
Eric Laurent24482012012-05-10 09:41:17 -07001075 checkAllAliasStreamVolumes();
John Spurlockb6e19e32015-03-10 21:33:44 -04001076 checkMuteAffectedStreams();
Eric Laurent403bd342017-07-11 16:21:44 -07001077 updateDefaultVolumes();
1078 }
1079
1080 // Update default indexes from aliased streams. Must be called after mStreamStates is created
1081 private void updateDefaultVolumes() {
1082 for (int stream = 0; stream < mStreamStates.length; stream++) {
1083 if (stream != mStreamVolumeAlias[stream]) {
1084 AudioSystem.DEFAULT_STREAM_VOLUME[stream] = rescaleIndex(
1085 AudioSystem.DEFAULT_STREAM_VOLUME[mStreamVolumeAlias[stream]],
1086 mStreamVolumeAlias[stream],
1087 stream);
1088 }
1089 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001090 }
1091
Eric Laurentbffc3d12012-05-07 17:43:49 -07001092 private void dumpStreamStates(PrintWriter pw) {
1093 pw.println("\nStream volumes (device: index)");
1094 int numStreamTypes = AudioSystem.getNumStreamTypes();
1095 for (int i = 0; i < numStreamTypes; i++) {
John Spurlock61560172015-02-06 19:46:04 -05001096 pw.println("- " + AudioSystem.STREAM_NAMES[i] + ":");
Eric Laurentbffc3d12012-05-07 17:43:49 -07001097 mStreamStates[i].dump(pw);
1098 pw.println("");
1099 }
Eric Laurentdd45d012012-10-08 09:04:34 -07001100 pw.print("\n- mute affected streams = 0x");
1101 pw.println(Integer.toHexString(mMuteAffectedStreams));
Eric Laurentbffc3d12012-05-07 17:43:49 -07001102 }
1103
John Spurlock90874332015-03-10 16:00:54 -04001104 private void updateStreamVolumeAlias(boolean updateVolumes, String caller) {
Eric Laurent6d517662012-04-23 18:42:39 -07001105 int dtmfStreamAlias;
Jean-Michel Triviac487672016-11-11 10:05:18 -08001106 final int a11yStreamAlias = sIndependentA11yVolume ?
1107 AudioSystem.STREAM_ACCESSIBILITY : AudioSystem.STREAM_MUSIC;
Eric Laurent212532b2014-07-21 15:43:18 -07001108
Muyuan Li1ed6df62016-06-18 11:16:52 -07001109 if (mIsSingleVolume) {
Eric Laurent212532b2014-07-21 15:43:18 -07001110 mStreamVolumeAlias = STREAM_VOLUME_ALIAS_TELEVISION;
1111 dtmfStreamAlias = AudioSystem.STREAM_MUSIC;
Muyuan Li1ed6df62016-06-18 11:16:52 -07001112 } else {
1113 switch (mPlatformType) {
1114 case AudioSystem.PLATFORM_VOICE:
1115 mStreamVolumeAlias = STREAM_VOLUME_ALIAS_VOICE;
1116 dtmfStreamAlias = AudioSystem.STREAM_RING;
1117 break;
1118 default:
1119 mStreamVolumeAlias = STREAM_VOLUME_ALIAS_DEFAULT;
1120 dtmfStreamAlias = AudioSystem.STREAM_MUSIC;
1121 }
Eric Laurent6d517662012-04-23 18:42:39 -07001122 }
Eric Laurent212532b2014-07-21 15:43:18 -07001123
Muyuan Li1ed6df62016-06-18 11:16:52 -07001124 if (mIsSingleVolume) {
Eric Laurent212532b2014-07-21 15:43:18 -07001125 mRingerModeAffectedStreams = 0;
Eric Laurent24e0d9b2013-10-03 18:15:07 -07001126 } else {
Eric Laurent212532b2014-07-21 15:43:18 -07001127 if (isInCommunication()) {
1128 dtmfStreamAlias = AudioSystem.STREAM_VOICE_CALL;
1129 mRingerModeAffectedStreams &= ~(1 << AudioSystem.STREAM_DTMF);
1130 } else {
1131 mRingerModeAffectedStreams |= (1 << AudioSystem.STREAM_DTMF);
1132 }
Eric Laurent6d517662012-04-23 18:42:39 -07001133 }
Eric Laurent212532b2014-07-21 15:43:18 -07001134
Eric Laurent6d517662012-04-23 18:42:39 -07001135 mStreamVolumeAlias[AudioSystem.STREAM_DTMF] = dtmfStreamAlias;
Jean-Michel Trivi170a0ee2017-04-14 18:13:26 -07001136 mStreamVolumeAlias[AudioSystem.STREAM_ACCESSIBILITY] = a11yStreamAlias;
Jean-Michel Triviac487672016-11-11 10:05:18 -08001137
Eric Laurent403bd342017-07-11 16:21:44 -07001138 if (updateVolumes && mStreamStates != null) {
1139 updateDefaultVolumes();
1140
Jean-Michel Trivi085346a2018-02-14 10:48:51 -08001141 synchronized (mSettingsLock) {
1142 synchronized (VolumeStreamState.class) {
1143 mStreamStates[AudioSystem.STREAM_DTMF]
1144 .setAllIndexes(mStreamStates[dtmfStreamAlias], caller);
1145 mStreamStates[AudioSystem.STREAM_ACCESSIBILITY].mVolumeIndexSettingName =
1146 System.VOLUME_SETTINGS_INT[a11yStreamAlias];
1147 mStreamStates[AudioSystem.STREAM_ACCESSIBILITY].setAllIndexes(
1148 mStreamStates[a11yStreamAlias], caller);
Jean-Michel Trivie05eef82018-03-08 18:56:34 -08001149 mStreamStates[AudioSystem.STREAM_ACCESSIBILITY].refreshRange(
1150 mStreamVolumeAlias[AudioSystem.STREAM_ACCESSIBILITY]);
Jean-Michel Trivi085346a2018-02-14 10:48:51 -08001151 }
1152 }
Jean-Michel Trivi170a0ee2017-04-14 18:13:26 -07001153 if (sIndependentA11yVolume) {
1154 // restore the a11y values from the settings
1155 mStreamStates[AudioSystem.STREAM_ACCESSIBILITY].readSettings();
1156 }
1157
Eric Laurent24e0d9b2013-10-03 18:15:07 -07001158 // apply stream mute states according to new value of mRingerModeAffectedStreams
John Spurlock661f2cf2014-11-17 10:29:10 -05001159 setRingerModeInt(getRingerModeInternal(), false);
Eric Laurent6d517662012-04-23 18:42:39 -07001160 sendMsg(mAudioHandler,
1161 MSG_SET_ALL_VOLUMES,
1162 SENDMSG_QUEUE,
1163 0,
1164 0,
1165 mStreamStates[AudioSystem.STREAM_DTMF], 0);
Jean-Michel Triviac487672016-11-11 10:05:18 -08001166 sendMsg(mAudioHandler,
1167 MSG_SET_ALL_VOLUMES,
1168 SENDMSG_QUEUE,
1169 0,
1170 0,
1171 mStreamStates[AudioSystem.STREAM_ACCESSIBILITY], 0);
Eric Laurent6d517662012-04-23 18:42:39 -07001172 }
1173 }
1174
Eric Laurent7ee1e4f2012-10-26 18:11:21 -07001175 private void readDockAudioSettings(ContentResolver cr)
1176 {
1177 mDockAudioMediaEnabled = Settings.Global.getInt(
Eric Laurent5ba0ffa02012-10-29 12:31:09 -07001178 cr, Settings.Global.DOCK_AUDIO_MEDIA_ENABLED, 0) == 1;
Eric Laurent7ee1e4f2012-10-26 18:11:21 -07001179
Eric Laurent7ee1e4f2012-10-26 18:11:21 -07001180 sendMsg(mAudioHandler,
1181 MSG_SET_FORCE_USE,
1182 SENDMSG_QUEUE,
1183 AudioSystem.FOR_DOCK,
1184 mDockAudioMediaEnabled ?
1185 AudioSystem.FORCE_ANALOG_DOCK : AudioSystem.FORCE_NONE,
Jean-Michel Trivi011f39e2017-08-19 18:08:06 -07001186 new String("readDockAudioSettings"),
Eric Laurent7ee1e4f2012-10-26 18:11:21 -07001187 0);
1188 }
1189
Phil Burkac0f7042016-02-24 12:19:08 -08001190
Andy Hung7b98e9a2016-02-25 18:34:50 -08001191 private void updateMasterMono(ContentResolver cr)
1192 {
1193 final boolean masterMono = System.getIntForUser(
1194 cr, System.MASTER_MONO, 0 /* default */, UserHandle.USER_CURRENT) == 1;
1195 if (DEBUG_VOL) {
1196 Log.d(TAG, String.format("Master mono %b", masterMono));
1197 }
1198 AudioSystem.setMasterMono(masterMono);
1199 }
1200
Edward Savage-Jones35c292f2017-01-13 09:04:34 +01001201 private void updateMasterBalance(ContentResolver cr) {
1202 final float masterBalance = System.getFloatForUser(
1203 cr, System.MASTER_BALANCE, 0.f /* default */, UserHandle.USER_CURRENT);
1204 if (DEBUG_VOL) {
1205 Log.d(TAG, String.format("Master balance %f", masterBalance));
1206 }
1207 if (AudioSystem.setMasterBalance(masterBalance) != 0) {
1208 Log.e(TAG, String.format("setMasterBalance failed for %f", masterBalance));
1209 }
1210 }
1211
Jean-Michel Trivi011f39e2017-08-19 18:08:06 -07001212 private void sendEncodedSurroundMode(ContentResolver cr, String eventSource)
Phil Burkac0f7042016-02-24 12:19:08 -08001213 {
Jean-Michel Trivi58850372018-09-14 16:01:28 -07001214 final int encodedSurroundMode = Settings.Global.getInt(
Phil Burkac0f7042016-02-24 12:19:08 -08001215 cr, Settings.Global.ENCODED_SURROUND_OUTPUT,
1216 Settings.Global.ENCODED_SURROUND_OUTPUT_AUTO);
Jean-Michel Trivi011f39e2017-08-19 18:08:06 -07001217 sendEncodedSurroundMode(encodedSurroundMode, eventSource);
Phil Burkac0f7042016-02-24 12:19:08 -08001218 }
1219
Jean-Michel Trivi011f39e2017-08-19 18:08:06 -07001220 private void sendEncodedSurroundMode(int encodedSurroundMode, String eventSource)
Phil Burkac0f7042016-02-24 12:19:08 -08001221 {
1222 // initialize to guaranteed bad value
1223 int forceSetting = AudioSystem.NUM_FORCE_CONFIG;
1224 switch (encodedSurroundMode) {
1225 case Settings.Global.ENCODED_SURROUND_OUTPUT_AUTO:
1226 forceSetting = AudioSystem.FORCE_NONE;
1227 break;
1228 case Settings.Global.ENCODED_SURROUND_OUTPUT_NEVER:
1229 forceSetting = AudioSystem.FORCE_ENCODED_SURROUND_NEVER;
1230 break;
1231 case Settings.Global.ENCODED_SURROUND_OUTPUT_ALWAYS:
1232 forceSetting = AudioSystem.FORCE_ENCODED_SURROUND_ALWAYS;
1233 break;
jiabin39940752018-04-02 18:18:45 -07001234 case Settings.Global.ENCODED_SURROUND_OUTPUT_MANUAL:
1235 forceSetting = AudioSystem.FORCE_ENCODED_SURROUND_MANUAL;
1236 break;
Phil Burkac0f7042016-02-24 12:19:08 -08001237 default:
1238 Log.e(TAG, "updateSurroundSoundSettings: illegal value "
1239 + encodedSurroundMode);
1240 break;
1241 }
1242 if (forceSetting != AudioSystem.NUM_FORCE_CONFIG) {
Jean-Michel Trivi58850372018-09-14 16:01:28 -07001243 mDeviceBroker.setForceUse_Async(AudioSystem.FOR_ENCODED_SURROUND, forceSetting,
1244 eventSource);
Phil Burkac0f7042016-02-24 12:19:08 -08001245 }
1246 }
1247
jiabin39940752018-04-02 18:18:45 -07001248 private void sendEnabledSurroundFormats(ContentResolver cr, boolean forceUpdate) {
1249 if (mEncodedSurroundMode != Settings.Global.ENCODED_SURROUND_OUTPUT_MANUAL) {
1250 // Manually enable surround formats only when the setting is in manual mode.
1251 return;
1252 }
1253 String enabledSurroundFormats = Settings.Global.getString(
1254 cr, Settings.Global.ENCODED_SURROUND_OUTPUT_ENABLED_FORMATS);
jiabin6db5f862018-05-17 10:33:09 -07001255 if (enabledSurroundFormats == null) {
1256 // Never allow enabledSurroundFormats as a null, which could happen when
1257 // ENCODED_SURROUND_OUTPUT_ENABLED_FORMATS is not appear in settings DB.
1258 enabledSurroundFormats = "";
1259 }
jiabin39940752018-04-02 18:18:45 -07001260 if (!forceUpdate && TextUtils.equals(enabledSurroundFormats, mEnabledSurroundFormats)) {
1261 // Update enabled surround formats to AudioPolicyManager only when forceUpdate
1262 // is true or enabled surround formats changed.
1263 return;
1264 }
1265
1266 mEnabledSurroundFormats = enabledSurroundFormats;
1267 String[] surroundFormats = TextUtils.split(enabledSurroundFormats, ",");
1268 ArrayList<Integer> formats = new ArrayList<>();
1269 for (String format : surroundFormats) {
1270 try {
1271 int audioFormat = Integer.valueOf(format);
1272 boolean isSurroundFormat = false;
1273 for (int sf : AudioFormat.SURROUND_SOUND_ENCODING) {
1274 if (sf == audioFormat) {
1275 isSurroundFormat = true;
1276 break;
1277 }
1278 }
1279 if (isSurroundFormat && !formats.contains(audioFormat)) {
1280 formats.add(audioFormat);
1281 }
1282 } catch (Exception e) {
1283 Log.e(TAG, "Invalid enabled surround format:" + format);
1284 }
1285 }
1286 // Set filtered surround formats to settings DB in case
1287 // there are invalid surround formats in original settings.
1288 Settings.Global.putString(mContext.getContentResolver(),
1289 Settings.Global.ENCODED_SURROUND_OUTPUT_ENABLED_FORMATS,
1290 TextUtils.join(",", formats));
1291 sendMsg(mAudioHandler, MSG_ENABLE_SURROUND_FORMATS, SENDMSG_QUEUE, 0, 0, formats, 0);
1292 }
1293
1294 private void onEnableSurroundFormats(ArrayList<Integer> enabledSurroundFormats) {
1295 // Set surround format enabled accordingly.
1296 for (int surroundFormat : AudioFormat.SURROUND_SOUND_ENCODING) {
1297 boolean enabled = enabledSurroundFormats.contains(surroundFormat);
1298 int ret = AudioSystem.setSurroundFormatEnabled(surroundFormat, enabled);
1299 Log.i(TAG, "enable surround format:" + surroundFormat + " " + enabled + " " + ret);
1300 }
1301 }
1302
Eric Laurent1c9c1d52018-10-17 10:06:46 -07001303 @GuardedBy("mSettingsLock")
1304 private void updateAssistantUId(boolean forceUpdate) {
1305 int assistantUid = 0;
1306
1307 // Consider assistants in the following order of priority:
1308 // 1) voice interaction service
1309 // 2) assistant
1310 String assistantName = Settings.Secure.getStringForUser(
1311 mContentResolver,
1312 Settings.Secure.VOICE_INTERACTION_SERVICE, UserHandle.USER_CURRENT);
1313 if (TextUtils.isEmpty(assistantName)) {
1314 assistantName = Settings.Secure.getStringForUser(
1315 mContentResolver,
1316 Settings.Secure.ASSISTANT, UserHandle.USER_CURRENT);
1317 }
1318 if (!TextUtils.isEmpty(assistantName)) {
1319 String packageName = ComponentName.unflattenFromString(assistantName).getPackageName();
1320 if (!TextUtils.isEmpty(packageName)) {
1321 try {
1322 assistantUid = mContext.getPackageManager().getPackageUid(packageName, 0);
1323 } catch (PackageManager.NameNotFoundException e) {
1324 Log.e(TAG,
1325 "updateAssistantUId() could not find UID for package: " + packageName);
1326 }
1327 }
1328 }
1329
1330 if (assistantUid != mAssistantUid || forceUpdate) {
1331 AudioSystem.setAssistantUid(assistantUid);
1332 mAssistantUid = assistantUid;
1333 }
1334 }
1335
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001336 private void readPersistedSettings() {
1337 final ContentResolver cr = mContentResolver;
1338
Eric Laurentbffc3d12012-05-07 17:43:49 -07001339 int ringerModeFromSettings =
Jeff Sharkey8d9a1f62012-10-18 15:38:14 -07001340 Settings.Global.getInt(
1341 cr, Settings.Global.MODE_RINGER, AudioManager.RINGER_MODE_NORMAL);
Eric Laurentbffc3d12012-05-07 17:43:49 -07001342 int ringerMode = ringerModeFromSettings;
Eric Laurent72668b22011-07-19 16:04:27 -07001343 // sanity check in case the settings are restored from a device with incompatible
1344 // ringer modes
John Spurlock97559372014-10-24 16:27:36 -04001345 if (!isValidRingerMode(ringerMode)) {
Glenn Kastenba195eb2011-12-13 09:30:40 -08001346 ringerMode = AudioManager.RINGER_MODE_NORMAL;
Eric Laurentbffc3d12012-05-07 17:43:49 -07001347 }
1348 if ((ringerMode == AudioManager.RINGER_MODE_VIBRATE) && !mHasVibrator) {
1349 ringerMode = AudioManager.RINGER_MODE_SILENT;
1350 }
1351 if (ringerMode != ringerModeFromSettings) {
Jeff Sharkey8d9a1f62012-10-18 15:38:14 -07001352 Settings.Global.putInt(cr, Settings.Global.MODE_RINGER, ringerMode);
Glenn Kastenba195eb2011-12-13 09:30:40 -08001353 }
Muyuan Li1ed6df62016-06-18 11:16:52 -07001354 if (mUseFixedVolume || mIsSingleVolume) {
Eric Laurent83a017b2013-03-19 18:15:31 -07001355 ringerMode = AudioManager.RINGER_MODE_NORMAL;
1356 }
Glenn Kastenba195eb2011-12-13 09:30:40 -08001357 synchronized(mSettingsLock) {
1358 mRingerMode = ringerMode;
John Spurlock661f2cf2014-11-17 10:29:10 -05001359 if (mRingerModeExternal == -1) {
1360 mRingerModeExternal = mRingerMode;
1361 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001362
Eric Laurentdd45d012012-10-08 09:04:34 -07001363 // System.VIBRATE_ON is not used any more but defaults for mVibrateSetting
1364 // are still needed while setVibrateSetting() and getVibrateSetting() are being
1365 // deprecated.
John Spurlock61560172015-02-06 19:46:04 -05001366 mVibrateSetting = AudioSystem.getValueForVibrateSetting(0,
Eric Laurentdd45d012012-10-08 09:04:34 -07001367 AudioManager.VIBRATE_TYPE_NOTIFICATION,
1368 mHasVibrator ? AudioManager.VIBRATE_SETTING_ONLY_SILENT
1369 : AudioManager.VIBRATE_SETTING_OFF);
John Spurlock61560172015-02-06 19:46:04 -05001370 mVibrateSetting = AudioSystem.getValueForVibrateSetting(mVibrateSetting,
Eric Laurentdd45d012012-10-08 09:04:34 -07001371 AudioManager.VIBRATE_TYPE_RINGER,
1372 mHasVibrator ? AudioManager.VIBRATE_SETTING_ONLY_SILENT
1373 : AudioManager.VIBRATE_SETTING_OFF);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001374
Beverlyd6964762018-02-16 14:07:03 -05001375 updateRingerAndZenModeAffectedStreams();
Eric Laurent7ee1e4f2012-10-26 18:11:21 -07001376 readDockAudioSettings(cr);
Jean-Michel Trivi011f39e2017-08-19 18:08:06 -07001377 sendEncodedSurroundMode(cr, "readPersistedSettings");
jiabin39940752018-04-02 18:18:45 -07001378 sendEnabledSurroundFormats(cr, true);
Eric Laurent1c9c1d52018-10-17 10:06:46 -07001379 updateAssistantUId(true);
Eric Laurent402f7f22011-02-04 12:30:32 -08001380 }
Eric Laurentc1d41662011-07-19 11:21:13 -07001381
Eric Laurentbc0fab1f2012-09-19 11:24:41 -07001382 mMuteAffectedStreams = System.getIntForUser(cr,
John Spurlock61560172015-02-06 19:46:04 -05001383 System.MUTE_STREAMS_AFFECTED, AudioSystem.DEFAULT_MUTE_STREAMS_AFFECTED,
John Spurlock24c05182015-02-05 12:30:36 -05001384 UserHandle.USER_CURRENT);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001385
Andy Hung7b98e9a2016-02-25 18:34:50 -08001386 updateMasterMono(cr);
Andy Hungf04b84d2015-12-18 17:33:27 -08001387
Edward Savage-Jones35c292f2017-01-13 09:04:34 +01001388 updateMasterBalance(cr);
1389
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001390 // Each stream will read its own persisted settings
1391
John Spurlockbcc10872014-11-28 15:29:21 -05001392 // Broadcast the sticky intents
1393 broadcastRingerMode(AudioManager.RINGER_MODE_CHANGED_ACTION, mRingerModeExternal);
1394 broadcastRingerMode(AudioManager.INTERNAL_RINGER_MODE_CHANGED_ACTION, mRingerMode);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001395
1396 // Broadcast vibrate settings
1397 broadcastVibrateSetting(AudioManager.VIBRATE_TYPE_RINGER);
1398 broadcastVibrateSetting(AudioManager.VIBRATE_TYPE_NOTIFICATION);
Jean-Michel Trivid589fea2011-04-15 11:28:10 -07001399
John Spurlock33f4e042014-07-11 13:10:58 -04001400 // Load settings for the volume controller
1401 mVolumeController.loadSettings(cr);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001402 }
1403
Eric Laurentc0232482016-03-15 18:19:23 -07001404 private void readUserRestrictions() {
1405 final int currentUser = getCurrentUserId();
1406
1407 // Check the current user restriction.
Tony Makc1205112016-07-22 16:02:59 +01001408 boolean masterMute =
1409 mUserManagerInternal.getUserRestriction(currentUser,
Esteban Talavera492b4722017-02-13 14:59:45 +00001410 UserManager.DISALLOW_UNMUTE_DEVICE)
Tony Makc1205112016-07-22 16:02:59 +01001411 || mUserManagerInternal.getUserRestriction(currentUser,
1412 UserManager.DISALLOW_ADJUST_VOLUME);
Eric Laurentc0232482016-03-15 18:19:23 -07001413 if (mUseFixedVolume) {
1414 masterMute = false;
1415 AudioSystem.setMasterVolume(1.0f);
1416 }
1417 if (DEBUG_VOL) {
1418 Log.d(TAG, String.format("Master mute %s, user=%d", masterMute, currentUser));
1419 }
1420 setSystemAudioMute(masterMute);
1421 AudioSystem.setMasterMute(masterMute);
1422 broadcastMasterMuteStatus(masterMute);
1423
1424 boolean microphoneMute = mUserManagerInternal.getUserRestriction(
1425 currentUser, UserManager.DISALLOW_UNMUTE_MICROPHONE);
1426 if (DEBUG_VOL) {
1427 Log.d(TAG, String.format("Mic mute %s, user=%d", microphoneMute, currentUser));
1428 }
1429 AudioSystem.muteMicrophone(microphoneMute);
1430 }
1431
Eric Laurenta553c252009-07-17 12:17:14 -07001432 private int rescaleIndex(int index, int srcStream, int dstStream) {
Jean-Michel Trivie05eef82018-03-08 18:56:34 -08001433 final int rescaled =
1434 (index * mStreamStates[dstStream].getMaxIndex()
1435 + mStreamStates[srcStream].getMaxIndex() / 2)
1436 / mStreamStates[srcStream].getMaxIndex();
1437 if (rescaled < mStreamStates[dstStream].getMinIndex()) {
1438 return mStreamStates[dstStream].getMinIndex();
1439 } else {
1440 return rescaled;
1441 }
Eric Laurenta553c252009-07-17 12:17:14 -07001442 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001443
1444 ///////////////////////////////////////////////////////////////////////////
1445 // IPC methods
1446 ///////////////////////////////////////////////////////////////////////////
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001447 /** @see AudioManager#adjustVolume(int, int) */
Dianne Hackbornba50b97c2013-04-30 15:04:46 -07001448 public void adjustSuggestedStreamVolume(int direction, int suggestedStreamType, int flags,
John Spurlock90874332015-03-10 16:00:54 -04001449 String callingPackage, String caller) {
Jean-Michel Trivi610aa9b2018-01-27 15:42:42 -08001450 final IAudioPolicyCallback extVolCtlr;
1451 synchronized (mExtVolumeControllerLock) {
1452 extVolCtlr = mExtVolumeController;
1453 }
1454 if (extVolCtlr != null) {
Jean-Michel Trivi7ed71472018-02-02 16:52:09 -08001455 sendMsg(mAudioHandler, MSG_NOTIFY_VOL_EVENT, SENDMSG_QUEUE,
1456 direction, 0 /*ignored*/,
1457 extVolCtlr, 0 /*delay*/);
Jean-Michel Trivi610aa9b2018-01-27 15:42:42 -08001458 } else {
1459 adjustSuggestedStreamVolume(direction, suggestedStreamType, flags, callingPackage,
1460 caller, Binder.getCallingUid());
1461 }
RoboErik272e1612014-09-05 11:39:29 -07001462 }
1463
1464 private void adjustSuggestedStreamVolume(int direction, int suggestedStreamType, int flags,
John Spurlock90874332015-03-10 16:00:54 -04001465 String callingPackage, String caller, int uid) {
1466 if (DEBUG_VOL) Log.d(TAG, "adjustSuggestedStreamVolume() stream=" + suggestedStreamType
Jean-Michel Trivia7880d42017-04-15 12:41:05 -07001467 + ", flags=" + flags + ", caller=" + caller
1468 + ", volControlStream=" + mVolumeControlStream
1469 + ", userSelect=" + mUserSelectedVolumeControlStream);
Jean-Michel Trivi58850372018-09-14 16:01:28 -07001470 sVolumeLogger.log(new VolumeEvent(VolumeEvent.VOL_ADJUST_SUGG_VOL, suggestedStreamType,
Jean-Michel Trivicf170362017-08-24 17:24:57 -07001471 direction/*val1*/, flags/*val2*/, new StringBuilder(callingPackage)
1472 .append("/").append(caller).append(" uid:").append(uid).toString()));
Jean-Michel Trivia7880d42017-04-15 12:41:05 -07001473 final int streamType;
jiabin8fd5d5e2018-03-23 14:09:28 -07001474 synchronized (mForceControlStreamLock) {
1475 // Request lock in case mVolumeControlStream is changed by other thread.
1476 if (mUserSelectedVolumeControlStream) { // implies mVolumeControlStream != -1
Jean-Michel Trivia7880d42017-04-15 12:41:05 -07001477 streamType = mVolumeControlStream;
jiabin8fd5d5e2018-03-23 14:09:28 -07001478 } else {
1479 final int maybeActiveStreamType = getActiveStreamType(suggestedStreamType);
1480 final boolean activeForReal;
1481 if (maybeActiveStreamType == AudioSystem.STREAM_RING
1482 || maybeActiveStreamType == AudioSystem.STREAM_NOTIFICATION) {
1483 activeForReal = wasStreamActiveRecently(maybeActiveStreamType, 0);
1484 } else {
1485 activeForReal = AudioSystem.isStreamActive(maybeActiveStreamType, 0);
1486 }
1487 if (activeForReal || mVolumeControlStream == -1) {
1488 streamType = maybeActiveStreamType;
1489 } else {
1490 streamType = mVolumeControlStream;
1491 }
Jean-Michel Trivia7880d42017-04-15 12:41:05 -07001492 }
Eric Laurent402f7f22011-02-04 12:30:32 -08001493 }
Jean-Michel Trivia7880d42017-04-15 12:41:05 -07001494
1495 final boolean isMute = isMuteAdjust(direction);
1496
John Spurlock0a376af2015-03-26 16:24:12 -04001497 ensureValidStreamType(streamType);
John Spurlock33f4e042014-07-11 13:10:58 -04001498 final int resolvedStream = mStreamVolumeAlias[streamType];
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001499
RoboErik2811dd32014-08-12 09:48:13 -07001500 // Play sounds on STREAM_RING only.
1501 if ((flags & AudioManager.FLAG_PLAY_SOUND) != 0 &&
John Spurlock33f4e042014-07-11 13:10:58 -04001502 resolvedStream != AudioSystem.STREAM_RING) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001503 flags &= ~AudioManager.FLAG_PLAY_SOUND;
1504 }
1505
John Spurlock33f4e042014-07-11 13:10:58 -04001506 // For notifications/ring, show the ui before making any adjustments
RoboErik4197cb62015-01-21 15:45:32 -08001507 // Don't suppress mute/unmute requests
Stanley Changb77e13d2018-08-28 08:16:03 +08001508 // Don't suppress adjustments for single volume device
1509 if (mVolumeController.suppressAdjustment(resolvedStream, flags, isMute)
1510 && !mIsSingleVolume) {
John Spurlock33f4e042014-07-11 13:10:58 -04001511 direction = 0;
1512 flags &= ~AudioManager.FLAG_PLAY_SOUND;
1513 flags &= ~AudioManager.FLAG_VIBRATE;
1514 if (DEBUG_VOL) Log.d(TAG, "Volume controller suppressed adjustment");
1515 }
1516
John Spurlock90874332015-03-10 16:00:54 -04001517 adjustStreamVolume(streamType, direction, flags, callingPackage, caller, uid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001518 }
1519
1520 /** @see AudioManager#adjustStreamVolume(int, int, int) */
Dianne Hackbornba50b97c2013-04-30 15:04:46 -07001521 public void adjustStreamVolume(int streamType, int direction, int flags,
1522 String callingPackage) {
Phil Weaverf1a9aff2017-03-23 17:21:29 -07001523 if ((streamType == AudioManager.STREAM_ACCESSIBILITY) && !canChangeAccessibilityVolume()) {
Jean-Michel Triviab2d9312017-03-13 15:33:39 -07001524 Log.w(TAG, "Trying to call adjustStreamVolume() for a11y without"
Phil Weaverf1a9aff2017-03-23 17:21:29 -07001525 + "CHANGE_ACCESSIBILITY_VOLUME / callingPackage=" + callingPackage);
Jean-Michel Triviab2d9312017-03-13 15:33:39 -07001526 return;
1527 }
Jean-Michel Trivi58850372018-09-14 16:01:28 -07001528 sVolumeLogger.log(new VolumeEvent(VolumeEvent.VOL_ADJUST_STREAM_VOL, streamType,
Jean-Michel Trivicf170362017-08-24 17:24:57 -07001529 direction/*val1*/, flags/*val2*/, callingPackage));
John Spurlock90874332015-03-10 16:00:54 -04001530 adjustStreamVolume(streamType, direction, flags, callingPackage, callingPackage,
1531 Binder.getCallingUid());
RoboErik0dac35a2014-08-12 15:48:49 -07001532 }
1533
Chinyue Chen6affe932018-01-24 14:51:43 +08001534 protected void adjustStreamVolume(int streamType, int direction, int flags,
John Spurlock90874332015-03-10 16:00:54 -04001535 String callingPackage, String caller, int uid) {
Eric Laurent83a017b2013-03-19 18:15:31 -07001536 if (mUseFixedVolume) {
1537 return;
1538 }
John Spurlock90874332015-03-10 16:00:54 -04001539 if (DEBUG_VOL) Log.d(TAG, "adjustStreamVolume() stream=" + streamType + ", dir=" + direction
1540 + ", flags=" + flags + ", caller=" + caller);
Jean-Michel Trivi3114ce32012-06-11 15:03:52 -07001541
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001542 ensureValidDirection(direction);
1543 ensureValidStreamType(streamType);
1544
RoboErik4197cb62015-01-21 15:45:32 -08001545 boolean isMuteAdjust = isMuteAdjust(direction);
1546
John Spurlock3ce37252015-02-17 13:20:45 -05001547 if (isMuteAdjust && !isStreamAffectedByMute(streamType)) {
1548 return;
1549 }
1550
Tomoharu Kasaharaa0d0c542019-01-18 20:04:38 +09001551 // If adjust is mute and the stream is STREAM_VOICE_CALL or STREAM_BLUETOOTH_SCO, make sure
Nadav Bar6b7751d2017-12-24 16:03:08 +02001552 // that the calling app have the MODIFY_PHONE_STATE permission.
1553 if (isMuteAdjust &&
Tomoharu Kasaharaa0d0c542019-01-18 20:04:38 +09001554 (streamType == AudioSystem.STREAM_VOICE_CALL ||
1555 streamType == AudioSystem.STREAM_BLUETOOTH_SCO) &&
Nadav Bar6b7751d2017-12-24 16:03:08 +02001556 mContext.checkCallingOrSelfPermission(
1557 android.Manifest.permission.MODIFY_PHONE_STATE)
1558 != PackageManager.PERMISSION_GRANTED) {
1559 Log.w(TAG, "MODIFY_PHONE_STATE Permission Denial: adjustStreamVolume from pid="
1560 + Binder.getCallingPid() + ", uid=" + Binder.getCallingUid());
1561 return;
1562 }
1563
Eric Laurent96a33d12011-11-08 10:31:57 -08001564 // use stream type alias here so that streams with same alias have the same behavior,
1565 // including with regard to silent mode control (e.g the use of STREAM_RING below and in
1566 // checkForRingerModeChange() in place of STREAM_RING or STREAM_NOTIFICATION)
Eric Laurent6d517662012-04-23 18:42:39 -07001567 int streamTypeAlias = mStreamVolumeAlias[streamType];
RoboErik4197cb62015-01-21 15:45:32 -08001568
Eric Laurentb024c302011-10-14 17:19:27 -07001569 VolumeStreamState streamState = mStreamStates[streamTypeAlias];
Eric Laurent9bc8358d2011-11-18 16:43:31 -08001570
1571 final int device = getDeviceForStream(streamTypeAlias);
Eric Laurent3ef75492012-11-28 12:12:23 -08001572
Eric Laurent42b041e2013-03-29 11:36:03 -07001573 int aliasIndex = streamState.getIndex(device);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001574 boolean adjustVolume = true;
Eric Laurent3ef75492012-11-28 12:12:23 -08001575 int step;
Eric Laurent24482012012-05-10 09:41:17 -07001576
Matthew Xiec9d1d5f2013-09-12 00:32:22 -07001577 // skip a2dp absolute volume control request when the device
1578 // is not an a2dp device
1579 if ((device & AudioSystem.DEVICE_OUT_ALL_A2DP) == 0 &&
1580 (flags & AudioManager.FLAG_BLUETOOTH_ABS_VOLUME) != 0) {
1581 return;
1582 }
1583
Kenny Guy70e0c582015-06-30 19:18:28 +01001584 // If we are being called by the system (e.g. hardware keys) check for current user
1585 // so we handle user restrictions correctly.
1586 if (uid == android.os.Process.SYSTEM_UID) {
1587 uid = UserHandle.getUid(getCurrentUserId(), UserHandle.getAppId(uid));
1588 }
John Spurlock59dc9c12015-03-02 11:20:15 -05001589 if (mAppOps.noteOp(STREAM_VOLUME_OPS[streamTypeAlias], uid, callingPackage)
RoboErik0dac35a2014-08-12 15:48:49 -07001590 != AppOpsManager.MODE_ALLOWED) {
Dianne Hackbornba50b97c2013-04-30 15:04:46 -07001591 return;
1592 }
1593
Eric Laurentfde16d52012-12-03 14:42:39 -08001594 // reset any pending volume command
hyomin.ohd0446dc2018-10-18 13:58:27 +09001595 synchronized (mSafeMediaVolumeStateLock) {
Eric Laurentfde16d52012-12-03 14:42:39 -08001596 mPendingVolumeCommand = null;
1597 }
1598
Eric Laurent3ef75492012-11-28 12:12:23 -08001599 flags &= ~AudioManager.FLAG_FIXED_VOLUME;
1600 if ((streamTypeAlias == AudioSystem.STREAM_MUSIC) &&
1601 ((device & mFixedVolumeDevices) != 0)) {
1602 flags |= AudioManager.FLAG_FIXED_VOLUME;
1603
1604 // Always toggle between max safe volume and 0 for fixed volume devices where safe
1605 // volume is enforced, and max and 0 for the others.
1606 // This is simulated by stepping by the full allowed volume range
1607 if (mSafeMediaVolumeState == SAFE_MEDIA_VOLUME_ACTIVE &&
1608 (device & mSafeMediaVolumeDevices) != 0) {
Eric Laurenteab40d12017-06-09 12:45:21 -07001609 step = safeMediaVolumeIndex(device);
Eric Laurent3ef75492012-11-28 12:12:23 -08001610 } else {
1611 step = streamState.getMaxIndex();
1612 }
1613 if (aliasIndex != 0) {
1614 aliasIndex = step;
1615 }
1616 } else {
1617 // convert one UI step (+/-1) into a number of internal units on the stream alias
1618 step = rescaleIndex(10, streamType, streamTypeAlias);
1619 }
1620
Eric Laurent42b041e2013-03-29 11:36:03 -07001621 // If either the client forces allowing ringer modes for this adjustment,
1622 // or the stream type is one that is affected by ringer modes
1623 if (((flags & AudioManager.FLAG_ALLOW_RINGER_MODES) != 0) ||
John Spurlockee5ad722015-03-03 16:17:21 -05001624 (streamTypeAlias == getUiSoundsStreamType())) {
John Spurlock661f2cf2014-11-17 10:29:10 -05001625 int ringerMode = getRingerModeInternal();
Eric Laurent42b041e2013-03-29 11:36:03 -07001626 // do not vibrate if already in vibrate mode
1627 if (ringerMode == AudioManager.RINGER_MODE_VIBRATE) {
1628 flags &= ~AudioManager.FLAG_VIBRATE;
Eric Laurent3ef75492012-11-28 12:12:23 -08001629 }
RoboErik5452e252015-02-06 15:33:53 -08001630 // Check if the ringer mode handles this adjustment. If it does we don't
1631 // need to adjust the volume further.
John Spurlock50ced3f2015-05-11 16:00:09 -04001632 final int result = checkForRingerModeChange(aliasIndex, direction, step,
Julia Reynoldsed783792016-04-08 15:27:35 -04001633 streamState.mIsMuted, callingPackage, flags);
John Spurlocka11b4af2014-06-01 11:52:23 -04001634 adjustVolume = (result & FLAG_ADJUST_VOLUME) != 0;
1635 // If suppressing a volume adjustment in silent mode, display the UI hint
1636 if ((result & AudioManager.FLAG_SHOW_SILENT_HINT) != 0) {
1637 flags |= AudioManager.FLAG_SHOW_SILENT_HINT;
1638 }
John Spurlock661f2cf2014-11-17 10:29:10 -05001639 // If suppressing a volume down adjustment in vibrate mode, display the UI hint
1640 if ((result & AudioManager.FLAG_SHOW_VIBRATE_HINT) != 0) {
1641 flags |= AudioManager.FLAG_SHOW_VIBRATE_HINT;
1642 }
Eric Laurent42b041e2013-03-29 11:36:03 -07001643 }
Beverlyd6964762018-02-16 14:07:03 -05001644
1645 // If the ringer mode or zen is muting the stream, do not change stream unless
1646 // it'll cause us to exit dnd
Julia Reynoldsed783792016-04-08 15:27:35 -04001647 if (!volumeAdjustmentAllowedByDnd(streamTypeAlias, flags)) {
John Spurlock50ced3f2015-05-11 16:00:09 -04001648 adjustVolume = false;
1649 }
Eric Laurent42b041e2013-03-29 11:36:03 -07001650 int oldIndex = mStreamStates[streamType].getIndex(device);
Eric Laurent3ef75492012-11-28 12:12:23 -08001651
Eric Laurent42b041e2013-03-29 11:36:03 -07001652 if (adjustVolume && (direction != AudioManager.ADJUST_SAME)) {
RoboErik5452e252015-02-06 15:33:53 -08001653 mAudioHandler.removeMessages(MSG_UNMUTE_STREAM);
Matthew Xiec9d1d5f2013-09-12 00:32:22 -07001654
RoboErik4197cb62015-01-21 15:45:32 -08001655 if (isMuteAdjust) {
1656 boolean state;
1657 if (direction == AudioManager.ADJUST_TOGGLE_MUTE) {
1658 state = !streamState.mIsMuted;
1659 } else {
1660 state = direction == AudioManager.ADJUST_MUTE;
1661 }
1662 if (streamTypeAlias == AudioSystem.STREAM_MUSIC) {
1663 setSystemAudioMute(state);
1664 }
1665 for (int stream = 0; stream < mStreamStates.length; stream++) {
1666 if (streamTypeAlias == mStreamVolumeAlias[stream]) {
Sungmin Choi841ed0a2015-07-26 23:09:49 -07001667 if (!(readCameraSoundForced()
1668 && (mStreamStates[stream].getStreamType()
1669 == AudioSystem.STREAM_SYSTEM_ENFORCED))) {
1670 mStreamStates[stream].mute(state);
1671 }
RoboErik4197cb62015-01-21 15:45:32 -08001672 }
1673 }
1674 } else if ((direction == AudioManager.ADJUST_RAISE) &&
Eric Laurent42b041e2013-03-29 11:36:03 -07001675 !checkSafeMediaVolume(streamTypeAlias, aliasIndex + step, device)) {
RoboErik4197cb62015-01-21 15:45:32 -08001676 Log.e(TAG, "adjustStreamVolume() safe volume index = " + oldIndex);
John Spurlock3346a802014-05-20 16:25:37 -04001677 mVolumeController.postDisplaySafeVolumeWarning(flags);
John Spurlock90874332015-03-10 16:00:54 -04001678 } else if (streamState.adjustIndex(direction * step, device, caller)
1679 || streamState.mIsMuted) {
RoboErik4197cb62015-01-21 15:45:32 -08001680 // Post message to set system volume (it in turn will post a
1681 // message to persist).
1682 if (streamState.mIsMuted) {
1683 // Unmute the stream if it was previously muted
RoboErik5452e252015-02-06 15:33:53 -08001684 if (direction == AudioManager.ADJUST_RAISE) {
1685 // unmute immediately for volume up
1686 streamState.mute(false);
1687 } else if (direction == AudioManager.ADJUST_LOWER) {
Muyuan Li1ed6df62016-06-18 11:16:52 -07001688 if (mIsSingleVolume) {
John Spurlocka48d7792015-03-03 17:35:57 -05001689 sendMsg(mAudioHandler, MSG_UNMUTE_STREAM, SENDMSG_QUEUE,
1690 streamTypeAlias, flags, null, UNMUTE_STREAM_DELAY);
1691 }
RoboErik5452e252015-02-06 15:33:53 -08001692 }
RoboErik4197cb62015-01-21 15:45:32 -08001693 }
Eric Laurent42b041e2013-03-29 11:36:03 -07001694 sendMsg(mAudioHandler,
1695 MSG_SET_DEVICE_VOLUME,
1696 SENDMSG_QUEUE,
1697 device,
1698 0,
1699 streamState,
1700 0);
Eric Laurent4bbcc652012-09-24 14:26:30 -07001701 }
Jungshik Jang41d97462014-06-30 22:26:29 +09001702
Jungshik Jang41d97462014-06-30 22:26:29 +09001703 int newIndex = mStreamStates[streamType].getIndex(device);
Ajay Panickere3946c82018-02-26 16:04:15 -08001704
1705 // Check if volume update should be send to AVRCP
1706 if (streamTypeAlias == AudioSystem.STREAM_MUSIC &&
1707 (device & AudioSystem.DEVICE_OUT_ALL_A2DP) != 0 &&
1708 (flags & AudioManager.FLAG_BLUETOOTH_ABS_VOLUME) == 0) {
Jean-Michel Trivi58850372018-09-14 16:01:28 -07001709 if (DEBUG_VOL) {
1710 Log.d(TAG, "adjustSreamVolume: postSetAvrcpAbsoluteVolumeIndex index="
1711 + newIndex + "stream=" + streamType);
Ajay Panickere3946c82018-02-26 16:04:15 -08001712 }
Jean-Michel Trivi734819a2019-02-04 15:44:28 -08001713 mDeviceBroker.postSetAvrcpAbsoluteVolumeIndex(newIndex / 10);
Ajay Panickere3946c82018-02-26 16:04:15 -08001714 }
1715
Jakub Pawlowskif9570f32018-02-21 17:15:12 -08001716 // Check if volume update should be send to Hearing Aid
1717 if ((device & AudioSystem.DEVICE_OUT_HEARING_AID) != 0) {
Jean-Michel Trivi58850372018-09-14 16:01:28 -07001718 Log.i(TAG, "adjustSreamVolume postSetHearingAidVolumeIndex index=" + newIndex
1719 + " stream=" + streamType);
1720 mDeviceBroker.postSetHearingAidVolumeIndex(newIndex, streamType);
Jakub Pawlowskif9570f32018-02-21 17:15:12 -08001721 }
1722
Ajay Panickere3946c82018-02-26 16:04:15 -08001723 // Check if volume update should be sent to Hdmi system audio.
Jinsuk Kim336cdb42014-11-29 06:27:00 +09001724 if (streamTypeAlias == AudioSystem.STREAM_MUSIC) {
1725 setSystemAudioVolume(oldIndex, newIndex, getStreamMaxVolume(streamType), flags);
1726 }
Shubangc480a712018-06-11 18:02:42 -07001727 synchronized (mHdmiClientLock) {
1728 if (mHdmiManager != null) {
Eric Laurent212532b2014-07-21 15:43:18 -07001729 // mHdmiCecSink true => mHdmiPlaybackClient != null
1730 if (mHdmiCecSink &&
1731 streamTypeAlias == AudioSystem.STREAM_MUSIC &&
1732 oldIndex != newIndex) {
Shubangc480a712018-06-11 18:02:42 -07001733 int keyCode = (direction == -1) ? KeyEvent.KEYCODE_VOLUME_DOWN :
1734 KeyEvent.KEYCODE_VOLUME_UP;
1735 final long ident = Binder.clearCallingIdentity();
1736 try {
1737 mHdmiPlaybackClient.sendKeyEvent(keyCode, true);
1738 mHdmiPlaybackClient.sendKeyEvent(keyCode, false);
1739 } finally {
1740 Binder.restoreCallingIdentity(ident);
Eric Laurent212532b2014-07-21 15:43:18 -07001741 }
Jungshik Jang41d97462014-06-30 22:26:29 +09001742 }
Shubangc480a712018-06-11 18:02:42 -07001743
1744 if (mHdmiAudioSystemClient != null &&
Shubangde728822018-07-16 16:46:51 -07001745 mHdmiSystemAudioSupported &&
Shubangc480a712018-06-11 18:02:42 -07001746 streamTypeAlias == AudioSystem.STREAM_MUSIC &&
1747 (oldIndex != newIndex || isMuteAdjust)) {
Shubangde728822018-07-16 16:46:51 -07001748 final long identity = Binder.clearCallingIdentity();
Shubangc480a712018-06-11 18:02:42 -07001749 mHdmiAudioSystemClient.sendReportAudioStatusCecCommand(
1750 isMuteAdjust, getStreamVolume(AudioSystem.STREAM_MUSIC),
1751 getStreamMaxVolume(AudioSystem.STREAM_MUSIC),
1752 isStreamMute(AudioSystem.STREAM_MUSIC));
Shubangde728822018-07-16 16:46:51 -07001753 Binder.restoreCallingIdentity(identity);
Shubangc480a712018-06-11 18:02:42 -07001754 }
Jungshik Jang41d97462014-06-30 22:26:29 +09001755 }
1756 }
Eric Laurent4bbcc652012-09-24 14:26:30 -07001757 }
Eric Laurent42b041e2013-03-29 11:36:03 -07001758 int index = mStreamStates[streamType].getIndex(device);
Eric Laurent25101b02011-02-02 09:33:30 -08001759 sendVolumeUpdate(streamType, oldIndex, index, flags);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001760 }
1761
RoboErik5452e252015-02-06 15:33:53 -08001762 // Called after a delay when volume down is pressed while muted
1763 private void onUnmuteStream(int stream, int flags) {
1764 VolumeStreamState streamState = mStreamStates[stream];
1765 streamState.mute(false);
1766
1767 final int device = getDeviceForStream(stream);
1768 final int index = mStreamStates[stream].getIndex(device);
1769 sendVolumeUpdate(stream, index, index, flags);
1770 }
1771
Jinsuk Kim336cdb42014-11-29 06:27:00 +09001772 private void setSystemAudioVolume(int oldVolume, int newVolume, int maxVolume, int flags) {
Jinsuk Kim336cdb42014-11-29 06:27:00 +09001773 // Sets the audio volume of AVR when we are in system audio mode. The new volume info
1774 // is tranformed to HDMI-CEC commands and passed through CEC bus.
Shubangc480a712018-06-11 18:02:42 -07001775 synchronized (mHdmiClientLock) {
1776 if (mHdmiManager == null
1777 || mHdmiTvClient == null
1778 || oldVolume == newVolume
1779 || (flags & AudioManager.FLAG_HDMI_SYSTEM_AUDIO_VOLUME) != 0
1780 || !mHdmiSystemAudioSupported) return;
1781 final long token = Binder.clearCallingIdentity();
1782 try {
1783 mHdmiTvClient.setSystemAudioVolume(oldVolume, newVolume, maxVolume);
1784 } finally {
1785 Binder.restoreCallingIdentity(token);
Jinsuk Kim336cdb42014-11-29 06:27:00 +09001786 }
1787 }
1788 }
1789
Eric Laurentfde16d52012-12-03 14:42:39 -08001790 // StreamVolumeCommand contains the information needed to defer the process of
1791 // setStreamVolume() in case the user has to acknowledge the safe volume warning message.
1792 class StreamVolumeCommand {
1793 public final int mStreamType;
1794 public final int mIndex;
1795 public final int mFlags;
1796 public final int mDevice;
Eric Laurent9ce379a2010-02-16 06:00:26 -08001797
Eric Laurentfde16d52012-12-03 14:42:39 -08001798 StreamVolumeCommand(int streamType, int index, int flags, int device) {
1799 mStreamType = streamType;
1800 mIndex = index;
1801 mFlags = flags;
1802 mDevice = device;
Eric Laurentb024c302011-10-14 17:19:27 -07001803 }
John Spurlock35134602014-07-24 18:10:48 -04001804
1805 @Override
1806 public String toString() {
1807 return new StringBuilder().append("{streamType=").append(mStreamType).append(",index=")
1808 .append(mIndex).append(",flags=").append(mFlags).append(",device=")
1809 .append(mDevice).append('}').toString();
1810 }
Eric Laurentfde16d52012-12-03 14:42:39 -08001811 };
Eric Laurent3ef75492012-11-28 12:12:23 -08001812
Julia Reynolds48034f82016-03-09 10:15:16 -05001813 private int getNewRingerMode(int stream, int index, int flags) {
Zak Cohen47798292017-11-30 12:34:20 -08001814 // setRingerMode does nothing if the device is single volume,so the value would be unchanged
1815 if (mIsSingleVolume) {
1816 return getRingerModeExternal();
1817 }
1818
John Spurlockee5ad722015-03-03 16:17:21 -05001819 // setting volume on ui sounds stream type also controls silent mode
Eric Laurent3ef75492012-11-28 12:12:23 -08001820 if (((flags & AudioManager.FLAG_ALLOW_RINGER_MODES) != 0) ||
John Spurlock75ae23c2015-06-02 16:26:43 -04001821 (stream == getUiSoundsStreamType())) {
Eric Laurent3ef75492012-11-28 12:12:23 -08001822 int newRingerMode;
1823 if (index == 0) {
1824 newRingerMode = mHasVibrator ? AudioManager.RINGER_MODE_VIBRATE
John Spurlocka48d7792015-03-03 17:35:57 -05001825 : mVolumePolicy.volumeDownToEnterSilent ? AudioManager.RINGER_MODE_SILENT
Julia Reynolds48034f82016-03-09 10:15:16 -05001826 : AudioManager.RINGER_MODE_NORMAL;
Eric Laurent3ef75492012-11-28 12:12:23 -08001827 } else {
1828 newRingerMode = AudioManager.RINGER_MODE_NORMAL;
1829 }
Julia Reynolds48034f82016-03-09 10:15:16 -05001830 return newRingerMode;
1831 }
1832 return getRingerModeExternal();
1833 }
1834
1835 private boolean isAndroidNPlus(String caller) {
1836 try {
1837 final ApplicationInfo applicationInfo =
1838 mContext.getPackageManager().getApplicationInfoAsUser(
1839 caller, 0, UserHandle.getUserId(Binder.getCallingUid()));
1840 if (applicationInfo.targetSdkVersion >= Build.VERSION_CODES.N) {
1841 return true;
1842 }
1843 return false;
1844 } catch (PackageManager.NameNotFoundException e) {
1845 return true;
1846 }
1847 }
1848
1849 private boolean wouldToggleZenMode(int newMode) {
1850 if (getRingerModeExternal() == AudioManager.RINGER_MODE_SILENT
1851 && newMode != AudioManager.RINGER_MODE_SILENT) {
1852 return true;
1853 } else if (getRingerModeExternal() != AudioManager.RINGER_MODE_SILENT
1854 && newMode == AudioManager.RINGER_MODE_SILENT) {
1855 return true;
1856 }
1857 return false;
1858 }
1859
1860 private void onSetStreamVolume(int streamType, int index, int flags, int device,
1861 String caller) {
1862 final int stream = mStreamVolumeAlias[streamType];
1863 setStreamVolumeInt(stream, index, device, false, caller);
1864 // setting volume on ui sounds stream type also controls silent mode
1865 if (((flags & AudioManager.FLAG_ALLOW_RINGER_MODES) != 0) ||
1866 (stream == getUiSoundsStreamType())) {
1867 setRingerMode(getNewRingerMode(stream, index, flags),
1868 TAG + ".onSetStreamVolume", false /*external*/);
Eric Laurent3ef75492012-11-28 12:12:23 -08001869 }
John Spurlock75ae23c2015-06-02 16:26:43 -04001870 // setting non-zero volume for a muted stream unmutes the stream and vice versa
1871 mStreamStates[stream].mute(index == 0);
Eric Laurentfde16d52012-12-03 14:42:39 -08001872 }
1873
1874 /** @see AudioManager#setStreamVolume(int, int, int) */
Dianne Hackbornba50b97c2013-04-30 15:04:46 -07001875 public void setStreamVolume(int streamType, int index, int flags, String callingPackage) {
Phil Weaverf1a9aff2017-03-23 17:21:29 -07001876 if ((streamType == AudioManager.STREAM_ACCESSIBILITY) && !canChangeAccessibilityVolume()) {
Jean-Michel Triviab2d9312017-03-13 15:33:39 -07001877 Log.w(TAG, "Trying to call setStreamVolume() for a11y without"
Phil Weaverf1a9aff2017-03-23 17:21:29 -07001878 + " CHANGE_ACCESSIBILITY_VOLUME callingPackage=" + callingPackage);
Jean-Michel Triviab2d9312017-03-13 15:33:39 -07001879 return;
1880 }
Tomoharu Kasaharaa0d0c542019-01-18 20:04:38 +09001881 if ((streamType == AudioManager.STREAM_VOICE_CALL ||
1882 streamType == AudioManager.STREAM_BLUETOOTH_SCO) &&
Nadav Bar6b7751d2017-12-24 16:03:08 +02001883 (index == 0) &&
1884 (mContext.checkCallingOrSelfPermission(
1885 android.Manifest.permission.MODIFY_PHONE_STATE)
1886 != PackageManager.PERMISSION_GRANTED)) {
Tomoharu Kasaharaa0d0c542019-01-18 20:04:38 +09001887 Log.w(TAG, "Trying to call setStreamVolume() for STREAM_VOICE_CALL or"
1888 + " STREAM_BLUETOOTH_SCO and index 0 without"
Nadav Bar6b7751d2017-12-24 16:03:08 +02001889 + " MODIFY_PHONE_STATE callingPackage=" + callingPackage);
1890 return;
1891 }
Jean-Michel Trivi58850372018-09-14 16:01:28 -07001892 sVolumeLogger.log(new VolumeEvent(VolumeEvent.VOL_SET_STREAM_VOL, streamType,
Jean-Michel Trivicf170362017-08-24 17:24:57 -07001893 index/*val1*/, flags/*val2*/, callingPackage));
John Spurlock90874332015-03-10 16:00:54 -04001894 setStreamVolume(streamType, index, flags, callingPackage, callingPackage,
1895 Binder.getCallingUid());
RoboErik0dac35a2014-08-12 15:48:49 -07001896 }
1897
Phil Weaverf1a9aff2017-03-23 17:21:29 -07001898 private boolean canChangeAccessibilityVolume() {
1899 synchronized (mAccessibilityServiceUidsLock) {
1900 if (PackageManager.PERMISSION_GRANTED == mContext.checkCallingOrSelfPermission(
1901 android.Manifest.permission.CHANGE_ACCESSIBILITY_VOLUME)) {
1902 return true;
1903 }
1904 if (mAccessibilityServiceUids != null) {
1905 int callingUid = Binder.getCallingUid();
1906 for (int i = 0; i < mAccessibilityServiceUids.length; i++) {
1907 if (mAccessibilityServiceUids[i] == callingUid) {
1908 return true;
1909 }
1910 }
1911 }
1912 return false;
1913 }
1914 }
1915
RoboErik0dac35a2014-08-12 15:48:49 -07001916 private void setStreamVolume(int streamType, int index, int flags, String callingPackage,
John Spurlock90874332015-03-10 16:00:54 -04001917 String caller, int uid) {
Jean-Michel Triviac487672016-11-11 10:05:18 -08001918 if (DEBUG_VOL) {
1919 Log.d(TAG, "setStreamVolume(stream=" + streamType+", index=" + index
1920 + ", calling=" + callingPackage + ")");
1921 }
Eric Laurent83a017b2013-03-19 18:15:31 -07001922 if (mUseFixedVolume) {
1923 return;
1924 }
1925
Eric Laurentfde16d52012-12-03 14:42:39 -08001926 ensureValidStreamType(streamType);
Dianne Hackbornba50b97c2013-04-30 15:04:46 -07001927 int streamTypeAlias = mStreamVolumeAlias[streamType];
1928 VolumeStreamState streamState = mStreamStates[streamTypeAlias];
Eric Laurentfde16d52012-12-03 14:42:39 -08001929
1930 final int device = getDeviceForStream(streamType);
1931 int oldIndex;
1932
Matthew Xiec9d1d5f2013-09-12 00:32:22 -07001933 // skip a2dp absolute volume control request when the device
1934 // is not an a2dp device
1935 if ((device & AudioSystem.DEVICE_OUT_ALL_A2DP) == 0 &&
1936 (flags & AudioManager.FLAG_BLUETOOTH_ABS_VOLUME) != 0) {
1937 return;
1938 }
Kenny Guy70e0c582015-06-30 19:18:28 +01001939 // If we are being called by the system (e.g. hardware keys) check for current user
1940 // so we handle user restrictions correctly.
1941 if (uid == android.os.Process.SYSTEM_UID) {
1942 uid = UserHandle.getUid(getCurrentUserId(), UserHandle.getAppId(uid));
1943 }
John Spurlock59dc9c12015-03-02 11:20:15 -05001944 if (mAppOps.noteOp(STREAM_VOLUME_OPS[streamTypeAlias], uid, callingPackage)
RoboErik0dac35a2014-08-12 15:48:49 -07001945 != AppOpsManager.MODE_ALLOWED) {
Dianne Hackbornba50b97c2013-04-30 15:04:46 -07001946 return;
1947 }
1948
Julia Reynolds48034f82016-03-09 10:15:16 -05001949 if (isAndroidNPlus(callingPackage)
1950 && wouldToggleZenMode(getNewRingerMode(streamTypeAlias, index, flags))
1951 && !mNm.isNotificationPolicyAccessGrantedForPackage(callingPackage)) {
1952 throw new SecurityException("Not allowed to change Do Not Disturb state");
1953 }
1954
Julia Reynoldsed783792016-04-08 15:27:35 -04001955 if (!volumeAdjustmentAllowedByDnd(streamTypeAlias, flags)) {
1956 return;
1957 }
1958
hyomin.ohd0446dc2018-10-18 13:58:27 +09001959 synchronized (mSafeMediaVolumeStateLock) {
Eric Laurentfde16d52012-12-03 14:42:39 -08001960 // reset any pending volume command
1961 mPendingVolumeCommand = null;
1962
Eric Laurent42b041e2013-03-29 11:36:03 -07001963 oldIndex = streamState.getIndex(device);
Eric Laurentfde16d52012-12-03 14:42:39 -08001964
Dianne Hackbornba50b97c2013-04-30 15:04:46 -07001965 index = rescaleIndex(index * 10, streamType, streamTypeAlias);
Eric Laurentfde16d52012-12-03 14:42:39 -08001966
Jean-Michel Trivi58850372018-09-14 16:01:28 -07001967 if (streamTypeAlias == AudioSystem.STREAM_MUSIC
1968 && (device & AudioSystem.DEVICE_OUT_ALL_A2DP) != 0
1969 && (flags & AudioManager.FLAG_BLUETOOTH_ABS_VOLUME) == 0) {
1970 if (DEBUG_VOL) {
1971 Log.d(TAG, "setStreamVolume postSetAvrcpAbsoluteVolumeIndex index=" + index
1972 + "stream=" + streamType);
John Du5a0cf7a2013-07-19 11:30:34 -07001973 }
Jean-Michel Trivi58850372018-09-14 16:01:28 -07001974 mDeviceBroker.postSetAvrcpAbsoluteVolumeIndex(index / 10);
John Du5a0cf7a2013-07-19 11:30:34 -07001975 }
1976
Jakub Pawlowskif9570f32018-02-21 17:15:12 -08001977 if ((device & AudioSystem.DEVICE_OUT_HEARING_AID) != 0) {
Jean-Michel Trivi58850372018-09-14 16:01:28 -07001978 Log.i(TAG, "setStreamVolume postSetHearingAidVolumeIndex index=" + index
1979 + " stream=" + streamType);
1980 mDeviceBroker.postSetHearingAidVolumeIndex(index, streamType);
Jakub Pawlowskif9570f32018-02-21 17:15:12 -08001981 }
1982
Jinsuk Kim336cdb42014-11-29 06:27:00 +09001983 if (streamTypeAlias == AudioSystem.STREAM_MUSIC) {
1984 setSystemAudioVolume(oldIndex, index, getStreamMaxVolume(streamType), flags);
Jungshik Jang41d97462014-06-30 22:26:29 +09001985 }
1986
Eric Laurentfde16d52012-12-03 14:42:39 -08001987 flags &= ~AudioManager.FLAG_FIXED_VOLUME;
Dianne Hackbornba50b97c2013-04-30 15:04:46 -07001988 if ((streamTypeAlias == AudioSystem.STREAM_MUSIC) &&
Eric Laurentfde16d52012-12-03 14:42:39 -08001989 ((device & mFixedVolumeDevices) != 0)) {
1990 flags |= AudioManager.FLAG_FIXED_VOLUME;
1991
1992 // volume is either 0 or max allowed for fixed volume devices
1993 if (index != 0) {
1994 if (mSafeMediaVolumeState == SAFE_MEDIA_VOLUME_ACTIVE &&
1995 (device & mSafeMediaVolumeDevices) != 0) {
Eric Laurenteab40d12017-06-09 12:45:21 -07001996 index = safeMediaVolumeIndex(device);
Eric Laurentfde16d52012-12-03 14:42:39 -08001997 } else {
1998 index = streamState.getMaxIndex();
1999 }
2000 }
2001 }
2002
Dianne Hackbornba50b97c2013-04-30 15:04:46 -07002003 if (!checkSafeMediaVolume(streamTypeAlias, index, device)) {
John Spurlock3346a802014-05-20 16:25:37 -04002004 mVolumeController.postDisplaySafeVolumeWarning(flags);
Eric Laurentfde16d52012-12-03 14:42:39 -08002005 mPendingVolumeCommand = new StreamVolumeCommand(
2006 streamType, index, flags, device);
2007 } else {
John Spurlock90874332015-03-10 16:00:54 -04002008 onSetStreamVolume(streamType, index, flags, device, caller);
Eric Laurent42b041e2013-03-29 11:36:03 -07002009 index = mStreamStates[streamType].getIndex(device);
Eric Laurentfde16d52012-12-03 14:42:39 -08002010 }
2011 }
Shubangc480a712018-06-11 18:02:42 -07002012 synchronized (mHdmiClientLock) {
2013 if (mHdmiManager != null &&
2014 mHdmiAudioSystemClient != null &&
Shubangde728822018-07-16 16:46:51 -07002015 mHdmiSystemAudioSupported &&
Shubangc480a712018-06-11 18:02:42 -07002016 streamTypeAlias == AudioSystem.STREAM_MUSIC &&
2017 (oldIndex != index)) {
Shubangde728822018-07-16 16:46:51 -07002018 final long identity = Binder.clearCallingIdentity();
Shubangc480a712018-06-11 18:02:42 -07002019 mHdmiAudioSystemClient.sendReportAudioStatusCecCommand(
2020 false, getStreamVolume(AudioSystem.STREAM_MUSIC),
2021 getStreamMaxVolume(AudioSystem.STREAM_MUSIC),
2022 isStreamMute(AudioSystem.STREAM_MUSIC));
Shubangde728822018-07-16 16:46:51 -07002023 Binder.restoreCallingIdentity(identity);
Shubangc480a712018-06-11 18:02:42 -07002024 }
2025 }
Eric Laurent25101b02011-02-02 09:33:30 -08002026 sendVolumeUpdate(streamType, oldIndex, index, flags);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002027 }
2028
Beverlyd6964762018-02-16 14:07:03 -05002029 // No ringer or zen muted stream volumes can be changed unless it'll exit dnd
Julia Reynoldsed783792016-04-08 15:27:35 -04002030 private boolean volumeAdjustmentAllowedByDnd(int streamTypeAlias, int flags) {
Beverlyd6964762018-02-16 14:07:03 -05002031 switch (mNm.getZenMode()) {
2032 case Settings.Global.ZEN_MODE_OFF:
2033 return true;
2034 case Settings.Global.ZEN_MODE_NO_INTERRUPTIONS:
2035 case Settings.Global.ZEN_MODE_ALARMS:
2036 case Settings.Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS:
2037 return !isStreamMutedByRingerOrZenMode(streamTypeAlias)
2038 || streamTypeAlias == getUiSoundsStreamType()
2039 || (flags & AudioManager.FLAG_ALLOW_RINGER_MODES) != 0;
Julia Reynoldsed783792016-04-08 15:27:35 -04002040 }
Beverlyd6964762018-02-16 14:07:03 -05002041
Julia Reynoldsed783792016-04-08 15:27:35 -04002042 return true;
2043 }
2044
Eric Laurent45c90ce2012-04-24 18:44:22 -07002045 /** @see AudioManager#forceVolumeControlStream(int) */
2046 public void forceVolumeControlStream(int streamType, IBinder cb) {
Jean-Michel Trivi60eddfd2018-03-09 15:31:12 -08002047 if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.MODIFY_PHONE_STATE)
2048 != PackageManager.PERMISSION_GRANTED) {
2049 return;
2050 }
Jean-Michel Trivia7880d42017-04-15 12:41:05 -07002051 if (DEBUG_VOL) { Log.d(TAG, String.format("forceVolumeControlStream(%d)", streamType)); }
Eric Laurent45c90ce2012-04-24 18:44:22 -07002052 synchronized(mForceControlStreamLock) {
Jean-Michel Trivia7880d42017-04-15 12:41:05 -07002053 if (mVolumeControlStream != -1 && streamType != -1) {
2054 mUserSelectedVolumeControlStream = true;
2055 }
Eric Laurent45c90ce2012-04-24 18:44:22 -07002056 mVolumeControlStream = streamType;
2057 if (mVolumeControlStream == -1) {
2058 if (mForceControlStreamClient != null) {
2059 mForceControlStreamClient.release();
2060 mForceControlStreamClient = null;
2061 }
Jean-Michel Trivia7880d42017-04-15 12:41:05 -07002062 mUserSelectedVolumeControlStream = false;
Eric Laurent45c90ce2012-04-24 18:44:22 -07002063 } else {
jianzhou21fb09f2018-02-28 14:03:15 +08002064 if (null == mForceControlStreamClient) {
2065 mForceControlStreamClient = new ForceControlStreamClient(cb);
2066 } else {
2067 if (mForceControlStreamClient.getBinder() == cb) {
2068 Log.d(TAG, "forceVolumeControlStream cb:" + cb + " is already linked.");
2069 } else {
2070 mForceControlStreamClient.release();
2071 mForceControlStreamClient = new ForceControlStreamClient(cb);
2072 }
2073 }
Eric Laurent45c90ce2012-04-24 18:44:22 -07002074 }
2075 }
2076 }
2077
2078 private class ForceControlStreamClient implements IBinder.DeathRecipient {
2079 private IBinder mCb; // To be notified of client's death
2080
2081 ForceControlStreamClient(IBinder cb) {
2082 if (cb != null) {
2083 try {
2084 cb.linkToDeath(this, 0);
2085 } catch (RemoteException e) {
2086 // Client has died!
2087 Log.w(TAG, "ForceControlStreamClient() could not link to "+cb+" binder death");
2088 cb = null;
2089 }
2090 }
2091 mCb = cb;
2092 }
2093
2094 public void binderDied() {
2095 synchronized(mForceControlStreamLock) {
2096 Log.w(TAG, "SCO client died");
2097 if (mForceControlStreamClient != this) {
2098 Log.w(TAG, "unregistered control stream client died");
2099 } else {
2100 mForceControlStreamClient = null;
2101 mVolumeControlStream = -1;
Jean-Michel Trivia7880d42017-04-15 12:41:05 -07002102 mUserSelectedVolumeControlStream = false;
Eric Laurent45c90ce2012-04-24 18:44:22 -07002103 }
2104 }
2105 }
2106
2107 public void release() {
2108 if (mCb != null) {
2109 mCb.unlinkToDeath(this, 0);
2110 mCb = null;
2111 }
2112 }
jianzhou21fb09f2018-02-28 14:03:15 +08002113
2114 public IBinder getBinder() {
2115 return mCb;
2116 }
Eric Laurent45c90ce2012-04-24 18:44:22 -07002117 }
2118
Dianne Hackborn5ac72a22012-08-29 18:32:08 -07002119 private void sendBroadcastToAll(Intent intent) {
Christopher Tate267603f2015-01-20 14:21:21 -08002120 intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);
John Spurlock86490862015-02-25 11:22:52 -05002121 intent.addFlags(Intent.FLAG_RECEIVER_FOREGROUND);
Dianne Hackborn5ac72a22012-08-29 18:32:08 -07002122 final long ident = Binder.clearCallingIdentity();
2123 try {
2124 mContext.sendBroadcastAsUser(intent, UserHandle.ALL);
2125 } finally {
2126 Binder.restoreCallingIdentity(ident);
2127 }
2128 }
2129
2130 private void sendStickyBroadcastToAll(Intent intent) {
John Spurlock86490862015-02-25 11:22:52 -05002131 intent.addFlags(Intent.FLAG_RECEIVER_FOREGROUND);
Dianne Hackborn5ac72a22012-08-29 18:32:08 -07002132 final long ident = Binder.clearCallingIdentity();
2133 try {
2134 mContext.sendStickyBroadcastAsUser(intent, UserHandle.ALL);
2135 } finally {
2136 Binder.restoreCallingIdentity(ident);
2137 }
2138 }
2139
Kenny Guy70e0c582015-06-30 19:18:28 +01002140 private int getCurrentUserId() {
2141 final long ident = Binder.clearCallingIdentity();
2142 try {
Sudheer Shankadc589ac2016-11-10 15:30:17 -08002143 UserInfo currentUser = ActivityManager.getService().getCurrentUser();
Kenny Guy70e0c582015-06-30 19:18:28 +01002144 return currentUser.id;
2145 } catch (RemoteException e) {
2146 // Activity manager not running, nothing we can do assume user 0.
2147 } finally {
2148 Binder.restoreCallingIdentity(ident);
2149 }
Xiaohui Chen7c696362015-09-16 09:56:14 -07002150 return UserHandle.USER_SYSTEM;
Kenny Guy70e0c582015-06-30 19:18:28 +01002151 }
2152
Eric Laurent25101b02011-02-02 09:33:30 -08002153 // UI update and Broadcast Intent
Yue Li949865b2017-05-24 17:25:28 -07002154 protected void sendVolumeUpdate(int streamType, int oldIndex, int index, int flags) {
John Spurlock72966d62015-06-18 15:45:07 -04002155 streamType = mStreamVolumeAlias[streamType];
Eric Laurent25101b02011-02-02 09:33:30 -08002156
Jinsuk Kim336cdb42014-11-29 06:27:00 +09002157 if (streamType == AudioSystem.STREAM_MUSIC) {
2158 flags = updateFlagsForSystemAudio(flags);
Jungshik Jang1a6be6e2014-09-16 11:04:54 +09002159 }
John Spurlock3346a802014-05-20 16:25:37 -04002160 mVolumeController.postVolumeChanged(streamType, flags);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002161 }
2162
Jinsuk Kim336cdb42014-11-29 06:27:00 +09002163 // If Hdmi-CEC system audio mode is on, we show volume bar only when TV
2164 // receives volume notification from Audio Receiver.
2165 private int updateFlagsForSystemAudio(int flags) {
Shubangc480a712018-06-11 18:02:42 -07002166 synchronized (mHdmiClientLock) {
2167 if (mHdmiTvClient != null) {
Jinsuk Kim336cdb42014-11-29 06:27:00 +09002168 if (mHdmiSystemAudioSupported &&
2169 ((flags & AudioManager.FLAG_HDMI_SYSTEM_AUDIO_VOLUME) == 0)) {
2170 flags &= ~AudioManager.FLAG_SHOW_UI;
2171 }
2172 }
2173 }
2174 return flags;
2175 }
2176
Mike Lockwood0dc37cc2011-12-01 16:14:19 -05002177 // UI update and Broadcast Intent
Mike Lockwood0dc37cc2011-12-01 16:14:19 -05002178 private void sendMasterMuteUpdate(boolean muted, int flags) {
Jinsuk Kim336cdb42014-11-29 06:27:00 +09002179 mVolumeController.postMasterMuteChanged(updateFlagsForSystemAudio(flags));
Justin Koh57978ed2012-04-03 17:37:58 -07002180 broadcastMasterMuteStatus(muted);
2181 }
Mike Lockwood0dc37cc2011-12-01 16:14:19 -05002182
Justin Koh57978ed2012-04-03 17:37:58 -07002183 private void broadcastMasterMuteStatus(boolean muted) {
Mike Lockwood0dc37cc2011-12-01 16:14:19 -05002184 Intent intent = new Intent(AudioManager.MASTER_MUTE_CHANGED_ACTION);
2185 intent.putExtra(AudioManager.EXTRA_MASTER_VOLUME_MUTED, muted);
Justin Koh57978ed2012-04-03 17:37:58 -07002186 intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT
2187 | Intent.FLAG_RECEIVER_REPLACE_PENDING);
Dianne Hackborn5ac72a22012-08-29 18:32:08 -07002188 sendStickyBroadcastToAll(intent);
Mike Lockwood0dc37cc2011-12-01 16:14:19 -05002189 }
2190
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002191 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002192 * Sets the stream state's index, and posts a message to set system volume.
2193 * This will not call out to the UI. Assumes a valid stream type.
2194 *
2195 * @param streamType Type of the stream
2196 * @param index Desired volume index of the stream
Eric Laurent9bc8358d2011-11-18 16:43:31 -08002197 * @param device the device whose volume must be changed
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002198 * @param force If true, set the volume even if the desired volume is same
2199 * as the current volume.
2200 */
Eric Laurent9bc8358d2011-11-18 16:43:31 -08002201 private void setStreamVolumeInt(int streamType,
2202 int index,
2203 int device,
John Spurlock90874332015-03-10 16:00:54 -04002204 boolean force,
2205 String caller) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002206 VolumeStreamState streamState = mStreamStates[streamType];
Eric Laurent5b4e6542010-03-19 20:02:21 -07002207
John Spurlock90874332015-03-10 16:00:54 -04002208 if (streamState.setIndex(index, device, caller) || force) {
Eric Laurent42b041e2013-03-29 11:36:03 -07002209 // Post message to set system volume (it in turn will post a message
2210 // to persist).
2211 sendMsg(mAudioHandler,
2212 MSG_SET_DEVICE_VOLUME,
2213 SENDMSG_QUEUE,
2214 device,
2215 0,
2216 streamState,
2217 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002218 }
2219 }
2220
Jinsuk Kim336cdb42014-11-29 06:27:00 +09002221 private void setSystemAudioMute(boolean state) {
Shubangc480a712018-06-11 18:02:42 -07002222 synchronized (mHdmiClientLock) {
2223 if (mHdmiManager == null || mHdmiTvClient == null || !mHdmiSystemAudioSupported) return;
2224 final long token = Binder.clearCallingIdentity();
2225 try {
2226 mHdmiTvClient.setSystemAudioMute(state);
2227 } finally {
2228 Binder.restoreCallingIdentity(token);
Jinsuk Kim336cdb42014-11-29 06:27:00 +09002229 }
2230 }
2231 }
2232
Eric Laurent25101b02011-02-02 09:33:30 -08002233 /** get stream mute state. */
2234 public boolean isStreamMute(int streamType) {
RoboErik7c82ced2014-12-04 17:39:08 -08002235 if (streamType == AudioManager.USE_DEFAULT_STREAM_TYPE) {
2236 streamType = getActiveStreamType(streamType);
2237 }
Eric Laurent8fa4d6f2014-10-30 14:13:03 -07002238 synchronized (VolumeStreamState.class) {
jiabin93d32ef2017-07-11 13:50:02 -07002239 ensureValidStreamType(streamType);
RoboErik4197cb62015-01-21 15:45:32 -08002240 return mStreamStates[streamType].mIsMuted;
Eric Laurent8fa4d6f2014-10-30 14:13:03 -07002241 }
Eric Laurent25101b02011-02-02 09:33:30 -08002242 }
2243
Jean-Michel Triviba5270b2014-10-01 17:49:29 -07002244 private class RmtSbmxFullVolDeathHandler implements IBinder.DeathRecipient {
2245 private IBinder mICallback; // To be notified of client's death
2246
2247 RmtSbmxFullVolDeathHandler(IBinder cb) {
2248 mICallback = cb;
2249 try {
2250 cb.linkToDeath(this, 0/*flags*/);
2251 } catch (RemoteException e) {
2252 Log.e(TAG, "can't link to death", e);
2253 }
2254 }
2255
2256 boolean isHandlerFor(IBinder cb) {
2257 return mICallback.equals(cb);
2258 }
2259
2260 void forget() {
2261 try {
2262 mICallback.unlinkToDeath(this, 0/*flags*/);
2263 } catch (NoSuchElementException e) {
2264 Log.e(TAG, "error unlinking to death", e);
2265 }
2266 }
2267
2268 public void binderDied() {
2269 Log.w(TAG, "Recorder with remote submix at full volume died " + mICallback);
2270 forceRemoteSubmixFullVolume(false, mICallback);
2271 }
2272 }
2273
2274 /**
2275 * call must be synchronized on mRmtSbmxFullVolDeathHandlers
2276 * @return true if there is a registered death handler, false otherwise */
2277 private boolean discardRmtSbmxFullVolDeathHandlerFor(IBinder cb) {
2278 Iterator<RmtSbmxFullVolDeathHandler> it = mRmtSbmxFullVolDeathHandlers.iterator();
2279 while (it.hasNext()) {
2280 final RmtSbmxFullVolDeathHandler handler = it.next();
2281 if (handler.isHandlerFor(cb)) {
2282 handler.forget();
2283 mRmtSbmxFullVolDeathHandlers.remove(handler);
2284 return true;
2285 }
2286 }
2287 return false;
2288 }
2289
2290 /** call synchronized on mRmtSbmxFullVolDeathHandlers */
2291 private boolean hasRmtSbmxFullVolDeathHandlerFor(IBinder cb) {
2292 Iterator<RmtSbmxFullVolDeathHandler> it = mRmtSbmxFullVolDeathHandlers.iterator();
2293 while (it.hasNext()) {
2294 if (it.next().isHandlerFor(cb)) {
2295 return true;
2296 }
2297 }
2298 return false;
2299 }
2300
2301 private int mRmtSbmxFullVolRefCount = 0;
2302 private ArrayList<RmtSbmxFullVolDeathHandler> mRmtSbmxFullVolDeathHandlers =
2303 new ArrayList<RmtSbmxFullVolDeathHandler>();
2304
2305 public void forceRemoteSubmixFullVolume(boolean startForcing, IBinder cb) {
2306 if (cb == null) {
2307 return;
2308 }
2309 if ((PackageManager.PERMISSION_GRANTED != mContext.checkCallingOrSelfPermission(
2310 android.Manifest.permission.CAPTURE_AUDIO_OUTPUT))) {
2311 Log.w(TAG, "Trying to call forceRemoteSubmixFullVolume() without CAPTURE_AUDIO_OUTPUT");
2312 return;
2313 }
2314 synchronized(mRmtSbmxFullVolDeathHandlers) {
2315 boolean applyRequired = false;
2316 if (startForcing) {
2317 if (!hasRmtSbmxFullVolDeathHandlerFor(cb)) {
2318 mRmtSbmxFullVolDeathHandlers.add(new RmtSbmxFullVolDeathHandler(cb));
2319 if (mRmtSbmxFullVolRefCount == 0) {
2320 mFullVolumeDevices |= AudioSystem.DEVICE_OUT_REMOTE_SUBMIX;
2321 mFixedVolumeDevices |= AudioSystem.DEVICE_OUT_REMOTE_SUBMIX;
2322 applyRequired = true;
2323 }
2324 mRmtSbmxFullVolRefCount++;
2325 }
2326 } else {
2327 if (discardRmtSbmxFullVolDeathHandlerFor(cb) && (mRmtSbmxFullVolRefCount > 0)) {
2328 mRmtSbmxFullVolRefCount--;
2329 if (mRmtSbmxFullVolRefCount == 0) {
2330 mFullVolumeDevices &= ~AudioSystem.DEVICE_OUT_REMOTE_SUBMIX;
2331 mFixedVolumeDevices &= ~AudioSystem.DEVICE_OUT_REMOTE_SUBMIX;
2332 applyRequired = true;
2333 }
2334 }
2335 }
2336 if (applyRequired) {
2337 // Assumes only STREAM_MUSIC going through DEVICE_OUT_REMOTE_SUBMIX
2338 checkAllFixedVolumeDevices(AudioSystem.STREAM_MUSIC);
2339 mStreamStates[AudioSystem.STREAM_MUSIC].applyAllVolumes();
2340 }
2341 }
2342 }
2343
Kenny Guy70e0c582015-06-30 19:18:28 +01002344 private void setMasterMuteInternal(boolean mute, int flags, String callingPackage, int uid,
2345 int userId) {
2346 // If we are being called by the system check for user we are going to change
2347 // so we handle user restrictions correctly.
2348 if (uid == android.os.Process.SYSTEM_UID) {
2349 uid = UserHandle.getUid(userId, UserHandle.getAppId(uid));
2350 }
Makoto Onuki4f160732015-10-27 17:15:38 -07002351 // If OP_AUDIO_MASTER_VOLUME is set, disallow unmuting.
2352 if (!mute && mAppOps.noteOp(AppOpsManager.OP_AUDIO_MASTER_VOLUME, uid, callingPackage)
RoboErik7c82ced2014-12-04 17:39:08 -08002353 != AppOpsManager.MODE_ALLOWED) {
Julia Reynolds4a21b252014-06-04 11:11:43 -04002354 return;
2355 }
Kenny Guy70e0c582015-06-30 19:18:28 +01002356 if (userId != UserHandle.getCallingUserId() &&
2357 mContext.checkCallingOrSelfPermission(
2358 android.Manifest.permission.INTERACT_ACROSS_USERS_FULL)
2359 != PackageManager.PERMISSION_GRANTED) {
2360 return;
2361 }
Makoto Onukid45a4a22015-11-02 17:17:38 -08002362 setMasterMuteInternalNoCallerCheck(mute, flags, userId);
2363 }
2364
2365 private void setMasterMuteInternalNoCallerCheck(boolean mute, int flags, int userId) {
2366 if (DEBUG_VOL) {
2367 Log.d(TAG, String.format("Master mute %s, %d, user=%d", mute, flags, userId));
2368 }
Hongwei Wangdaba1242018-05-29 14:36:16 -07002369 if (!isPlatformAutomotive() && mUseFixedVolume) {
2370 // If using fixed volume, we don't mute.
2371 // TODO: remove the isPlatformAutomotive check here.
2372 // The isPlatformAutomotive check is added for safety but may not be necessary.
2373 return;
Makoto Onukid45a4a22015-11-02 17:17:38 -08002374 }
Kenny Guy70e0c582015-06-30 19:18:28 +01002375 if (getCurrentUserId() == userId) {
2376 if (mute != AudioSystem.getMasterMute()) {
2377 setSystemAudioMute(mute);
2378 AudioSystem.setMasterMute(mute);
Kenny Guy70e0c582015-06-30 19:18:28 +01002379 sendMasterMuteUpdate(mute, flags);
RoboErik7c82ced2014-12-04 17:39:08 -08002380
Kenny Guy70e0c582015-06-30 19:18:28 +01002381 Intent intent = new Intent(AudioManager.MASTER_MUTE_CHANGED_ACTION);
2382 intent.putExtra(AudioManager.EXTRA_MASTER_VOLUME_MUTED, mute);
2383 sendBroadcastToAll(intent);
2384 }
Jason Simmons1ce5b262012-02-02 13:00:17 -08002385 }
Mike Lockwoodce952c82011-11-14 10:47:42 -08002386 }
2387
2388 /** get master mute state. */
2389 public boolean isMasterMute() {
Mike Lockwood3194ea92011-12-07 11:47:31 -08002390 return AudioSystem.getMasterMute();
Mike Lockwoodce952c82011-11-14 10:47:42 -08002391 }
2392
Kenny Guy70e0c582015-06-30 19:18:28 +01002393 public void setMasterMute(boolean mute, int flags, String callingPackage, int userId) {
2394 setMasterMuteInternal(mute, flags, callingPackage, Binder.getCallingUid(),
2395 userId);
John Spurlockee5ad722015-03-03 16:17:21 -05002396 }
2397
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002398 /** @see AudioManager#getStreamVolume(int) */
2399 public int getStreamVolume(int streamType) {
2400 ensureValidStreamType(streamType);
Eric Laurent9bc8358d2011-11-18 16:43:31 -08002401 int device = getDeviceForStream(streamType);
Eric Laurent8fa4d6f2014-10-30 14:13:03 -07002402 synchronized (VolumeStreamState.class) {
2403 int index = mStreamStates[streamType].getIndex(device);
Eric Laurent4bbcc652012-09-24 14:26:30 -07002404
Eric Laurent8fa4d6f2014-10-30 14:13:03 -07002405 // by convention getStreamVolume() returns 0 when a stream is muted.
RoboErik4197cb62015-01-21 15:45:32 -08002406 if (mStreamStates[streamType].mIsMuted) {
Eric Laurent8fa4d6f2014-10-30 14:13:03 -07002407 index = 0;
2408 }
2409 if (index != 0 && (mStreamVolumeAlias[streamType] == AudioSystem.STREAM_MUSIC) &&
2410 (device & mFixedVolumeDevices) != 0) {
2411 index = mStreamStates[streamType].getMaxIndex();
2412 }
2413 return (index + 5) / 10;
Eric Laurent42b041e2013-03-29 11:36:03 -07002414 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002415 }
2416
2417 /** @see AudioManager#getStreamMaxVolume(int) */
2418 public int getStreamMaxVolume(int streamType) {
2419 ensureValidStreamType(streamType);
Eric Laurenta553c252009-07-17 12:17:14 -07002420 return (mStreamStates[streamType].getMaxIndex() + 5) / 10;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002421 }
2422
Jean-Michel Trivi8e7aca32017-11-28 18:12:38 -08002423 /** @see AudioManager#getStreamMinVolumeInt(int) */
John Spurlockb6e19e32015-03-10 21:33:44 -04002424 public int getStreamMinVolume(int streamType) {
2425 ensureValidStreamType(streamType);
2426 return (mStreamStates[streamType].getMinIndex() + 5) / 10;
2427 }
2428
Eric Laurent25101b02011-02-02 09:33:30 -08002429 /** Get last audible volume before stream was muted. */
2430 public int getLastAudibleStreamVolume(int streamType) {
2431 ensureValidStreamType(streamType);
Eric Laurent9bc8358d2011-11-18 16:43:31 -08002432 int device = getDeviceForStream(streamType);
Eric Laurent42b041e2013-03-29 11:36:03 -07002433 return (mStreamStates[streamType].getIndex(device) + 5) / 10;
Eric Laurent25101b02011-02-02 09:33:30 -08002434 }
2435
John Spurlockee5ad722015-03-03 16:17:21 -05002436 /** @see AudioManager#getUiSoundsStreamType() */
2437 public int getUiSoundsStreamType() {
John Spurlock4f0f1202014-08-05 13:28:33 -04002438 return mStreamVolumeAlias[AudioSystem.STREAM_SYSTEM];
Eric Laurent6d517662012-04-23 18:42:39 -07002439 }
2440
Makoto Onukid45a4a22015-11-02 17:17:38 -08002441 /** @see AudioManager#setMicrophoneMute(boolean) */
2442 @Override
Kenny Guy70e0c582015-06-30 19:18:28 +01002443 public void setMicrophoneMute(boolean on, String callingPackage, int userId) {
2444 // If we are being called by the system check for user we are going to change
2445 // so we handle user restrictions correctly.
2446 int uid = Binder.getCallingUid();
2447 if (uid == android.os.Process.SYSTEM_UID) {
2448 uid = UserHandle.getUid(userId, UserHandle.getAppId(uid));
2449 }
Makoto Onuki4f160732015-10-27 17:15:38 -07002450 // If OP_MUTE_MICROPHONE is set, disallow unmuting.
2451 if (!on && mAppOps.noteOp(AppOpsManager.OP_MUTE_MICROPHONE, uid, callingPackage)
Kenny Guy70e0c582015-06-30 19:18:28 +01002452 != AppOpsManager.MODE_ALLOWED) {
Emily Bernier22c921a2014-05-28 11:01:32 -04002453 return;
2454 }
Jean-Michel Trivi4a4fea02014-08-29 18:14:09 -07002455 if (!checkAudioSettingsPermission("setMicrophoneMute()")) {
2456 return;
2457 }
Kenny Guy70e0c582015-06-30 19:18:28 +01002458 if (userId != UserHandle.getCallingUserId() &&
2459 mContext.checkCallingOrSelfPermission(
2460 android.Manifest.permission.INTERACT_ACROSS_USERS_FULL)
2461 != PackageManager.PERMISSION_GRANTED) {
2462 return;
2463 }
Makoto Onukid45a4a22015-11-02 17:17:38 -08002464 setMicrophoneMuteNoCallerCheck(on, userId);
2465 }
Emily Bernier22c921a2014-05-28 11:01:32 -04002466
Makoto Onukid45a4a22015-11-02 17:17:38 -08002467 private void setMicrophoneMuteNoCallerCheck(boolean on, int userId) {
2468 if (DEBUG_VOL) {
2469 Log.d(TAG, String.format("Mic mute %s, user=%d", on, userId));
2470 }
Jean-Michel Trivi7be17d22017-12-21 18:09:21 -08002471 // only mute for the current user
Kenny Guy70e0c582015-06-30 19:18:28 +01002472 if (getCurrentUserId() == userId) {
Jean-Michel Trivi7be17d22017-12-21 18:09:21 -08002473 final boolean currentMute = AudioSystem.isMicrophoneMuted();
Eric Laurent66b69672018-01-26 18:30:51 -08002474 final long identity = Binder.clearCallingIdentity();
Kenny Guy70e0c582015-06-30 19:18:28 +01002475 AudioSystem.muteMicrophone(on);
Eric Laurent66b69672018-01-26 18:30:51 -08002476 Binder.restoreCallingIdentity(identity);
Jean-Michel Trivi7be17d22017-12-21 18:09:21 -08002477 if (on != currentMute) {
2478 mContext.sendBroadcast(new Intent(AudioManager.ACTION_MICROPHONE_MUTE_CHANGED)
2479 .setFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY));
2480 }
Kenny Guy70e0c582015-06-30 19:18:28 +01002481 }
Emily Bernier22c921a2014-05-28 11:01:32 -04002482 }
2483
John Spurlock661f2cf2014-11-17 10:29:10 -05002484 @Override
2485 public int getRingerModeExternal() {
2486 synchronized(mSettingsLock) {
2487 return mRingerModeExternal;
2488 }
2489 }
2490
2491 @Override
2492 public int getRingerModeInternal() {
Glenn Kastenba195eb2011-12-13 09:30:40 -08002493 synchronized(mSettingsLock) {
2494 return mRingerMode;
2495 }
2496 }
2497
2498 private void ensureValidRingerMode(int ringerMode) {
John Spurlock97559372014-10-24 16:27:36 -04002499 if (!isValidRingerMode(ringerMode)) {
Glenn Kastenba195eb2011-12-13 09:30:40 -08002500 throw new IllegalArgumentException("Bad ringer mode " + ringerMode);
2501 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002502 }
2503
John Spurlock97559372014-10-24 16:27:36 -04002504 /** @see AudioManager#isValidRingerMode(int) */
2505 public boolean isValidRingerMode(int ringerMode) {
2506 return ringerMode >= 0 && ringerMode <= AudioManager.RINGER_MODE_MAX;
2507 }
2508
John Spurlock661f2cf2014-11-17 10:29:10 -05002509 public void setRingerModeExternal(int ringerMode, String caller) {
Julia Reynolds48034f82016-03-09 10:15:16 -05002510 if (isAndroidNPlus(caller) && wouldToggleZenMode(ringerMode)
2511 && !mNm.isNotificationPolicyAccessGrantedForPackage(caller)) {
2512 throw new SecurityException("Not allowed to change Do Not Disturb state");
2513 }
2514
John Spurlockaf88a192014-12-23 16:14:44 -05002515 setRingerMode(ringerMode, caller, true /*external*/);
John Spurlock661f2cf2014-11-17 10:29:10 -05002516 }
2517
2518 public void setRingerModeInternal(int ringerMode, String caller) {
John Spurlockcdb57ae2015-02-11 19:04:11 -05002519 enforceVolumeController("setRingerModeInternal");
John Spurlockaf88a192014-12-23 16:14:44 -05002520 setRingerMode(ringerMode, caller, false /*external*/);
John Spurlock661f2cf2014-11-17 10:29:10 -05002521 }
2522
Mike Digman55272862018-02-20 14:35:17 -08002523 public void silenceRingerModeInternal(String reason) {
2524 VibrationEffect effect = null;
2525 int ringerMode = AudioManager.RINGER_MODE_SILENT;
2526 int toastText = 0;
2527
2528 int silenceRingerSetting = Settings.Secure.VOLUME_HUSH_OFF;
2529 if (mContext.getResources()
2530 .getBoolean(com.android.internal.R.bool.config_volumeHushGestureEnabled)) {
2531 silenceRingerSetting = Settings.Secure.getIntForUser(mContentResolver,
2532 Settings.Secure.VOLUME_HUSH_GESTURE, VOLUME_HUSH_OFF,
2533 UserHandle.USER_CURRENT);
2534 }
2535
2536 switch(silenceRingerSetting) {
2537 case VOLUME_HUSH_MUTE:
2538 effect = VibrationEffect.get(VibrationEffect.EFFECT_DOUBLE_CLICK);
2539 ringerMode = AudioManager.RINGER_MODE_SILENT;
2540 toastText = com.android.internal.R.string.volume_dialog_ringer_guidance_silent;
2541 break;
2542 case VOLUME_HUSH_VIBRATE:
2543 effect = VibrationEffect.get(VibrationEffect.EFFECT_HEAVY_CLICK);
2544 ringerMode = AudioManager.RINGER_MODE_VIBRATE;
2545 toastText = com.android.internal.R.string.volume_dialog_ringer_guidance_vibrate;
2546 break;
2547 }
Alexey Kuzmine1f06b82018-06-20 17:48:43 +01002548 maybeVibrate(effect, reason);
Mike Digman55272862018-02-20 14:35:17 -08002549 setRingerModeInternal(ringerMode, reason);
2550 Toast.makeText(mContext, toastText, Toast.LENGTH_SHORT).show();
2551 }
2552
Alexey Kuzmine1f06b82018-06-20 17:48:43 +01002553 private boolean maybeVibrate(VibrationEffect effect, String reason) {
Mike Digman55272862018-02-20 14:35:17 -08002554 if (!mHasVibrator) {
2555 return false;
2556 }
2557 final boolean hapticsDisabled = Settings.System.getIntForUser(mContext.getContentResolver(),
2558 Settings.System.HAPTIC_FEEDBACK_ENABLED, 0, UserHandle.USER_CURRENT) == 0;
2559 if (hapticsDisabled) {
2560 return false;
2561 }
2562
2563 if (effect == null) {
2564 return false;
2565 }
Alexey Kuzmine1f06b82018-06-20 17:48:43 +01002566 mVibrator.vibrate(Binder.getCallingUid(), mContext.getOpPackageName(), effect,
2567 reason, VIBRATION_ATTRIBUTES);
Mike Digman55272862018-02-20 14:35:17 -08002568 return true;
2569 }
2570
John Spurlock661f2cf2014-11-17 10:29:10 -05002571 private void setRingerMode(int ringerMode, String caller, boolean external) {
Muyuan Li1ed6df62016-06-18 11:16:52 -07002572 if (mUseFixedVolume || mIsSingleVolume) {
Eric Laurent83a017b2013-03-19 18:15:31 -07002573 return;
2574 }
John Spurlock661f2cf2014-11-17 10:29:10 -05002575 if (caller == null || caller.length() == 0) {
2576 throw new IllegalArgumentException("Bad caller: " + caller);
2577 }
John Spurlock97559372014-10-24 16:27:36 -04002578 ensureValidRingerMode(ringerMode);
Eric Laurent24482012012-05-10 09:41:17 -07002579 if ((ringerMode == AudioManager.RINGER_MODE_VIBRATE) && !mHasVibrator) {
2580 ringerMode = AudioManager.RINGER_MODE_SILENT;
2581 }
John Spurlockaf88a192014-12-23 16:14:44 -05002582 final long identity = Binder.clearCallingIdentity();
2583 try {
2584 synchronized (mSettingsLock) {
2585 final int ringerModeInternal = getRingerModeInternal();
2586 final int ringerModeExternal = getRingerModeExternal();
2587 if (external) {
2588 setRingerModeExt(ringerMode);
2589 if (mRingerModeDelegate != null) {
2590 ringerMode = mRingerModeDelegate.onSetRingerModeExternal(ringerModeExternal,
John Spurlocka48d7792015-03-03 17:35:57 -05002591 ringerMode, caller, ringerModeInternal, mVolumePolicy);
John Spurlockaf88a192014-12-23 16:14:44 -05002592 }
2593 if (ringerMode != ringerModeInternal) {
2594 setRingerModeInt(ringerMode, true /*persist*/);
2595 }
2596 } else /*internal*/ {
2597 if (ringerMode != ringerModeInternal) {
2598 setRingerModeInt(ringerMode, true /*persist*/);
2599 }
2600 if (mRingerModeDelegate != null) {
2601 ringerMode = mRingerModeDelegate.onSetRingerModeInternal(ringerModeInternal,
John Spurlocka48d7792015-03-03 17:35:57 -05002602 ringerMode, caller, ringerModeExternal, mVolumePolicy);
John Spurlockaf88a192014-12-23 16:14:44 -05002603 }
2604 setRingerModeExt(ringerMode);
John Spurlock57627792014-12-11 11:29:54 -05002605 }
John Spurlock661f2cf2014-11-17 10:29:10 -05002606 }
John Spurlockaf88a192014-12-23 16:14:44 -05002607 } finally {
2608 Binder.restoreCallingIdentity(identity);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002609 }
2610 }
2611
John Spurlock661f2cf2014-11-17 10:29:10 -05002612 private void setRingerModeExt(int ringerMode) {
2613 synchronized(mSettingsLock) {
2614 if (ringerMode == mRingerModeExternal) return;
2615 mRingerModeExternal = ringerMode;
John Spurlocke5b42d92014-10-15 12:03:48 -04002616 }
John Spurlock661f2cf2014-11-17 10:29:10 -05002617 // Send sticky broadcast
John Spurlockbcc10872014-11-28 15:29:21 -05002618 broadcastRingerMode(AudioManager.RINGER_MODE_CHANGED_ACTION, ringerMode);
John Spurlocke5b42d92014-10-15 12:03:48 -04002619 }
2620
Jean-Michel Trivic106d9f2018-06-07 12:28:27 -07002621 @GuardedBy("mSettingsLock")
John Spurlock50ced3f2015-05-11 16:00:09 -04002622 private void muteRingerModeStreams() {
Beverlyd6964762018-02-16 14:07:03 -05002623 // Mute stream if not previously muted by ringer mode and (ringer mode
2624 // is not RINGER_MODE_NORMAL OR stream is zen muted) and stream is affected by ringer mode.
2625 // Unmute stream if previously muted by ringer/zen mode and ringer mode
Eric Laurent5b4e6542010-03-19 20:02:21 -07002626 // is RINGER_MODE_NORMAL or stream is not affected by ringer mode.
Jason Parekhb1096152009-03-24 17:48:25 -07002627 int numStreamTypes = AudioSystem.getNumStreamTypes();
Beverly925cde82018-01-23 09:31:23 -05002628
2629 if (mNm == null) {
2630 mNm = (NotificationManager) mContext.getSystemService(Context.NOTIFICATION_SERVICE);
2631 }
2632
Jack He6dd78c12018-02-12 21:00:24 -08002633 final int ringerMode = mRingerMode; // Read ringer mode as reading primitives is atomic
2634 final boolean ringerModeMute = ringerMode == AudioManager.RINGER_MODE_VIBRATE
2635 || ringerMode == AudioManager.RINGER_MODE_SILENT;
2636 final boolean shouldRingSco = ringerMode == AudioManager.RINGER_MODE_VIBRATE
2637 && isBluetoothScoOn();
2638 // Ask audio policy engine to force use Bluetooth SCO channel if needed
2639 final String eventSource = "muteRingerModeStreams() from u/pid:" + Binder.getCallingUid()
2640 + "/" + Binder.getCallingPid();
2641 sendMsg(mAudioHandler, MSG_SET_FORCE_USE, SENDMSG_QUEUE, AudioSystem.FOR_VIBRATE_RINGING,
2642 shouldRingSco ? AudioSystem.FORCE_BT_SCO : AudioSystem.FORCE_NONE, eventSource, 0);
Beverly925cde82018-01-23 09:31:23 -05002643
Eric Laurent5b4e6542010-03-19 20:02:21 -07002644 for (int streamType = numStreamTypes - 1; streamType >= 0; streamType--) {
Beverlyd6964762018-02-16 14:07:03 -05002645 final boolean isMuted = isStreamMutedByRingerOrZenMode(streamType);
Jack He6dd78c12018-02-12 21:00:24 -08002646 final boolean muteAllowedBySco =
2647 !(shouldRingSco && streamType == AudioSystem.STREAM_RING);
Beverlyd6964762018-02-16 14:07:03 -05002648 final boolean shouldZenMute = shouldZenMuteStream(streamType);
2649 final boolean shouldMute = shouldZenMute || (ringerModeMute
Jack He6dd78c12018-02-12 21:00:24 -08002650 && isStreamAffectedByRingerMode(streamType) && muteAllowedBySco);
John Spurlock661f2cf2014-11-17 10:29:10 -05002651 if (isMuted == shouldMute) continue;
2652 if (!shouldMute) {
2653 // unmute
2654 // ring and notifications volume should never be 0 when not silenced
John Spurlockd9c75db2015-04-28 11:19:13 -04002655 if (mStreamVolumeAlias[streamType] == AudioSystem.STREAM_RING) {
John Spurlock661f2cf2014-11-17 10:29:10 -05002656 synchronized (VolumeStreamState.class) {
John Spurlocka48d7792015-03-03 17:35:57 -05002657 final VolumeStreamState vss = mStreamStates[streamType];
2658 for (int i = 0; i < vss.mIndexMap.size(); i++) {
2659 int device = vss.mIndexMap.keyAt(i);
2660 int value = vss.mIndexMap.valueAt(i);
John Spurlock2bb02ec2015-03-02 13:13:06 -05002661 if (value == 0) {
John Spurlocka48d7792015-03-03 17:35:57 -05002662 vss.setIndex(10, device, TAG);
Eric Laurent9bc8358d2011-11-18 16:43:31 -08002663 }
2664 }
Eric Laurent9e0d25f2015-02-12 17:28:53 -08002665 // Persist volume for stream ring when it is changed here
2666 final int device = getDeviceForStream(streamType);
2667 sendMsg(mAudioHandler,
2668 MSG_PERSIST_VOLUME,
2669 SENDMSG_QUEUE,
2670 device,
2671 0,
2672 mStreamStates[streamType],
2673 PERSIST_DELAY);
Eric Laurentb024c302011-10-14 17:19:27 -07002674 }
Eric Laurent9bcf4012009-06-12 06:09:28 -07002675 }
RoboErik4197cb62015-01-21 15:45:32 -08002676 mStreamStates[streamType].mute(false);
Beverlyd6964762018-02-16 14:07:03 -05002677 mRingerAndZenModeMutedStreams &= ~(1 << streamType);
Eric Laurent5b4e6542010-03-19 20:02:21 -07002678 } else {
John Spurlock661f2cf2014-11-17 10:29:10 -05002679 // mute
RoboErik4197cb62015-01-21 15:45:32 -08002680 mStreamStates[streamType].mute(true);
Beverlyd6964762018-02-16 14:07:03 -05002681 mRingerAndZenModeMutedStreams |= (1 << streamType);
Jason Parekhb1096152009-03-24 17:48:25 -07002682 }
2683 }
John Spurlock50ced3f2015-05-11 16:00:09 -04002684 }
2685
Beverly925cde82018-01-23 09:31:23 -05002686 private boolean isAlarm(int streamType) {
2687 return streamType == AudioSystem.STREAM_ALARM;
2688 }
2689
2690 private boolean isNotificationOrRinger(int streamType) {
2691 return streamType == AudioSystem.STREAM_NOTIFICATION
2692 || streamType == AudioSystem.STREAM_RING;
2693 }
2694
2695 private boolean isMedia(int streamType) {
Beverlyd6964762018-02-16 14:07:03 -05002696 return streamType == AudioSystem.STREAM_MUSIC;
2697 }
2698
2699
2700 private boolean isSystem(int streamType) {
2701 return streamType == AudioSystem.STREAM_SYSTEM;
Beverly925cde82018-01-23 09:31:23 -05002702 }
2703
John Spurlock50ced3f2015-05-11 16:00:09 -04002704 private void setRingerModeInt(int ringerMode, boolean persist) {
2705 final boolean change;
2706 synchronized(mSettingsLock) {
2707 change = mRingerMode != ringerMode;
2708 mRingerMode = ringerMode;
Jean-Michel Trivic106d9f2018-06-07 12:28:27 -07002709 muteRingerModeStreams();
John Spurlock50ced3f2015-05-11 16:00:09 -04002710 }
2711
Jason Parekhb1096152009-03-24 17:48:25 -07002712 // Post a persist ringer mode msg
Eric Laurent4050c932009-07-08 02:52:14 -07002713 if (persist) {
Eric Laurentafbb0472011-12-15 09:04:23 -08002714 sendMsg(mAudioHandler, MSG_PERSIST_RINGER_MODE,
Eric Laurent4050c932009-07-08 02:52:14 -07002715 SENDMSG_REPLACE, 0, 0, null, PERSIST_DELAY);
2716 }
John Spurlockbcc10872014-11-28 15:29:21 -05002717 if (change) {
2718 // Send sticky broadcast
2719 broadcastRingerMode(AudioManager.INTERNAL_RINGER_MODE_CHANGED_ACTION, ringerMode);
2720 }
Jason Parekhb1096152009-03-24 17:48:25 -07002721 }
2722
Jean-Michel Trivi58850372018-09-14 16:01:28 -07002723 /*package*/ void setUpdateRingerModeServiceInt() {
2724 setRingerModeInt(getRingerModeInternal(), false);
2725 }
2726
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002727 /** @see AudioManager#shouldVibrate(int) */
2728 public boolean shouldVibrate(int vibrateType) {
Eric Laurentbffc3d12012-05-07 17:43:49 -07002729 if (!mHasVibrator) return false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002730
2731 switch (getVibrateSetting(vibrateType)) {
2732
2733 case AudioManager.VIBRATE_SETTING_ON:
John Spurlock57627792014-12-11 11:29:54 -05002734 return getRingerModeExternal() != AudioManager.RINGER_MODE_SILENT;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002735
2736 case AudioManager.VIBRATE_SETTING_ONLY_SILENT:
John Spurlock57627792014-12-11 11:29:54 -05002737 return getRingerModeExternal() == AudioManager.RINGER_MODE_VIBRATE;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002738
2739 case AudioManager.VIBRATE_SETTING_OFF:
Daniel Sandlerbcac4962010-04-12 13:23:57 -04002740 // return false, even for incoming calls
2741 return false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002742
2743 default:
2744 return false;
2745 }
2746 }
2747
2748 /** @see AudioManager#getVibrateSetting(int) */
2749 public int getVibrateSetting(int vibrateType) {
Eric Laurentbffc3d12012-05-07 17:43:49 -07002750 if (!mHasVibrator) return AudioManager.VIBRATE_SETTING_OFF;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002751 return (mVibrateSetting >> (vibrateType * 2)) & 3;
2752 }
2753
2754 /** @see AudioManager#setVibrateSetting(int, int) */
2755 public void setVibrateSetting(int vibrateType, int vibrateSetting) {
2756
Eric Laurentbffc3d12012-05-07 17:43:49 -07002757 if (!mHasVibrator) return;
2758
John Spurlock61560172015-02-06 19:46:04 -05002759 mVibrateSetting = AudioSystem.getValueForVibrateSetting(mVibrateSetting, vibrateType,
2760 vibrateSetting);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002761
2762 // Broadcast change
2763 broadcastVibrateSetting(vibrateType);
2764
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002765 }
2766
Jean-Michel Trivi58850372018-09-14 16:01:28 -07002767 /*package*/ class SetModeDeathHandler implements IBinder.DeathRecipient {
Eric Laurent9272b4b2010-01-23 17:12:59 -08002768 private IBinder mCb; // To be notified of client's death
Marco Nelissenf1ddd512011-08-10 14:15:44 -07002769 private int mPid;
Eric Laurent9272b4b2010-01-23 17:12:59 -08002770 private int mMode = AudioSystem.MODE_NORMAL; // Current mode set by this client
2771
Eric Laurent9f103de2011-09-08 15:04:23 -07002772 SetModeDeathHandler(IBinder cb, int pid) {
Eric Laurent9272b4b2010-01-23 17:12:59 -08002773 mCb = cb;
Eric Laurent9f103de2011-09-08 15:04:23 -07002774 mPid = pid;
Eric Laurent9272b4b2010-01-23 17:12:59 -08002775 }
2776
2777 public void binderDied() {
Jack He89f97982018-05-02 19:10:56 -07002778 int oldModeOwnerPid = 0;
Eric Laurentd7454be2011-09-14 08:45:58 -07002779 int newModeOwnerPid = 0;
Jean-Michel Trivi58850372018-09-14 16:01:28 -07002780 synchronized (mDeviceBroker.mSetModeLock) {
Eric Laurent9272b4b2010-01-23 17:12:59 -08002781 Log.w(TAG, "setMode() client died");
Jack He89f97982018-05-02 19:10:56 -07002782 if (!mSetModeDeathHandlers.isEmpty()) {
2783 oldModeOwnerPid = mSetModeDeathHandlers.get(0).getPid();
2784 }
Eric Laurent9272b4b2010-01-23 17:12:59 -08002785 int index = mSetModeDeathHandlers.indexOf(this);
2786 if (index < 0) {
2787 Log.w(TAG, "unregistered setMode() client died");
2788 } else {
John Spurlock90874332015-03-10 16:00:54 -04002789 newModeOwnerPid = setModeInt(AudioSystem.MODE_NORMAL, mCb, mPid, TAG);
Eric Laurent9272b4b2010-01-23 17:12:59 -08002790 }
2791 }
Eric Laurent9f103de2011-09-08 15:04:23 -07002792 // when entering RINGTONE, IN_CALL or IN_COMMUNICATION mode, clear all
Jack He89f97982018-05-02 19:10:56 -07002793 // SCO connections not started by the application changing the mode when pid changes
2794 if ((newModeOwnerPid != oldModeOwnerPid) && (newModeOwnerPid != 0)) {
Jean-Michel Trivi58850372018-09-14 16:01:28 -07002795 mDeviceBroker.postDisconnectBluetoothSco(newModeOwnerPid);
Eric Laurent9f103de2011-09-08 15:04:23 -07002796 }
Eric Laurent9272b4b2010-01-23 17:12:59 -08002797 }
2798
Marco Nelissenf1ddd512011-08-10 14:15:44 -07002799 public int getPid() {
2800 return mPid;
2801 }
2802
Eric Laurent9272b4b2010-01-23 17:12:59 -08002803 public void setMode(int mode) {
2804 mMode = mode;
2805 }
2806
2807 public int getMode() {
2808 return mMode;
2809 }
2810
2811 public IBinder getBinder() {
2812 return mCb;
2813 }
2814 }
2815
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002816 /** @see AudioManager#setMode(int) */
John Spurlock90874332015-03-10 16:00:54 -04002817 public void setMode(int mode, IBinder cb, String callingPackage) {
2818 if (DEBUG_MODE) { Log.v(TAG, "setMode(mode=" + mode + ", callingPackage=" + callingPackage + ")"); }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002819 if (!checkAudioSettingsPermission("setMode()")) {
2820 return;
2821 }
Eric Laurenta553c252009-07-17 12:17:14 -07002822
Jean-Michel Triviccd654e2014-09-03 17:48:47 -07002823 if ( (mode == AudioSystem.MODE_IN_CALL) &&
2824 (mContext.checkCallingOrSelfPermission(
2825 android.Manifest.permission.MODIFY_PHONE_STATE)
2826 != PackageManager.PERMISSION_GRANTED)) {
2827 Log.w(TAG, "MODIFY_PHONE_STATE Permission Denial: setMode(MODE_IN_CALL) from pid="
2828 + Binder.getCallingPid() + ", uid=" + Binder.getCallingUid());
2829 return;
2830 }
2831
Jean-Michel Trivi8f677d62010-11-15 12:11:32 -08002832 if (mode < AudioSystem.MODE_CURRENT || mode >= AudioSystem.NUM_MODES) {
Eric Laurenta553c252009-07-17 12:17:14 -07002833 return;
2834 }
2835
Jack He89f97982018-05-02 19:10:56 -07002836 int oldModeOwnerPid = 0;
Eric Laurentd7454be2011-09-14 08:45:58 -07002837 int newModeOwnerPid = 0;
Jean-Michel Trivi58850372018-09-14 16:01:28 -07002838 synchronized (mDeviceBroker.mSetModeLock) {
Jack He89f97982018-05-02 19:10:56 -07002839 if (!mSetModeDeathHandlers.isEmpty()) {
2840 oldModeOwnerPid = mSetModeDeathHandlers.get(0).getPid();
2841 }
Eric Laurenta553c252009-07-17 12:17:14 -07002842 if (mode == AudioSystem.MODE_CURRENT) {
2843 mode = mMode;
2844 }
John Spurlock90874332015-03-10 16:00:54 -04002845 newModeOwnerPid = setModeInt(mode, cb, Binder.getCallingPid(), callingPackage);
Eric Laurent9f103de2011-09-08 15:04:23 -07002846 }
2847 // when entering RINGTONE, IN_CALL or IN_COMMUNICATION mode, clear all
Jack He89f97982018-05-02 19:10:56 -07002848 // SCO connections not started by the application changing the mode when pid changes
2849 if ((newModeOwnerPid != oldModeOwnerPid) && (newModeOwnerPid != 0)) {
Jean-Michel Trivi58850372018-09-14 16:01:28 -07002850 mDeviceBroker.postDisconnectBluetoothSco(newModeOwnerPid);
Eric Laurent9f103de2011-09-08 15:04:23 -07002851 }
2852 }
Jean-Michel Trivi2ade5762010-12-11 13:18:30 -08002853
Jean-Michel Trivi58850372018-09-14 16:01:28 -07002854 // must be called synchronized on mSetModeLock
Eric Laurentd7454be2011-09-14 08:45:58 -07002855 // setModeInt() returns a valid PID if the audio mode was successfully set to
Eric Laurent9f103de2011-09-08 15:04:23 -07002856 // any mode other than NORMAL.
John Spurlock90874332015-03-10 16:00:54 -04002857 private int setModeInt(int mode, IBinder cb, int pid, String caller) {
2858 if (DEBUG_MODE) { Log.v(TAG, "setModeInt(mode=" + mode + ", pid=" + pid + ", caller="
2859 + caller + ")"); }
Eric Laurentd7454be2011-09-14 08:45:58 -07002860 int newModeOwnerPid = 0;
Eric Laurent9f103de2011-09-08 15:04:23 -07002861 if (cb == null) {
2862 Log.e(TAG, "setModeInt() called with null binder");
Eric Laurentd7454be2011-09-14 08:45:58 -07002863 return newModeOwnerPid;
Eric Laurent9f103de2011-09-08 15:04:23 -07002864 }
Jean-Michel Trivi2ade5762010-12-11 13:18:30 -08002865
Eric Laurent9f103de2011-09-08 15:04:23 -07002866 SetModeDeathHandler hdlr = null;
2867 Iterator iter = mSetModeDeathHandlers.iterator();
2868 while (iter.hasNext()) {
2869 SetModeDeathHandler h = (SetModeDeathHandler)iter.next();
2870 if (h.getPid() == pid) {
2871 hdlr = h;
2872 // Remove from client list so that it is re-inserted at top of list
2873 iter.remove();
2874 hdlr.getBinder().unlinkToDeath(hdlr, 0);
2875 break;
2876 }
2877 }
2878 int status = AudioSystem.AUDIO_STATUS_OK;
Eric Laurent6afa6502017-09-28 15:18:19 -07002879 int actualMode;
Eric Laurent9f103de2011-09-08 15:04:23 -07002880 do {
Eric Laurent6afa6502017-09-28 15:18:19 -07002881 actualMode = mode;
Eric Laurent9f103de2011-09-08 15:04:23 -07002882 if (mode == AudioSystem.MODE_NORMAL) {
2883 // get new mode from client at top the list if any
2884 if (!mSetModeDeathHandlers.isEmpty()) {
2885 hdlr = mSetModeDeathHandlers.get(0);
2886 cb = hdlr.getBinder();
Eric Laurent6afa6502017-09-28 15:18:19 -07002887 actualMode = hdlr.getMode();
Jean-Michel Trivi339567d2014-07-29 09:53:34 -07002888 if (DEBUG_MODE) {
2889 Log.w(TAG, " using mode=" + mode + " instead due to death hdlr at pid="
2890 + hdlr.mPid);
2891 }
Eric Laurentb9c9d262009-05-06 08:13:20 -07002892 }
Eric Laurent9f103de2011-09-08 15:04:23 -07002893 } else {
2894 if (hdlr == null) {
2895 hdlr = new SetModeDeathHandler(cb, pid);
2896 }
2897 // Register for client death notification
2898 try {
2899 cb.linkToDeath(hdlr, 0);
2900 } catch (RemoteException e) {
2901 // Client has died!
2902 Log.w(TAG, "setMode() could not link to "+cb+" binder death");
2903 }
2904
2905 // Last client to call setMode() is always at top of client list
2906 // as required by SetModeDeathHandler.binderDied()
2907 mSetModeDeathHandlers.add(0, hdlr);
2908 hdlr.setMode(mode);
2909 }
2910
Eric Laurent6afa6502017-09-28 15:18:19 -07002911 if (actualMode != mMode) {
Eric Laurent66b69672018-01-26 18:30:51 -08002912 final long identity = Binder.clearCallingIdentity();
Eric Laurent6afa6502017-09-28 15:18:19 -07002913 status = AudioSystem.setPhoneState(actualMode);
Eric Laurent66b69672018-01-26 18:30:51 -08002914 Binder.restoreCallingIdentity(identity);
Eric Laurent9f103de2011-09-08 15:04:23 -07002915 if (status == AudioSystem.AUDIO_STATUS_OK) {
Eric Laurent6afa6502017-09-28 15:18:19 -07002916 if (DEBUG_MODE) { Log.v(TAG, " mode successfully set to " + actualMode); }
2917 mMode = actualMode;
Eric Laurent9f103de2011-09-08 15:04:23 -07002918 } else {
2919 if (hdlr != null) {
2920 mSetModeDeathHandlers.remove(hdlr);
2921 cb.unlinkToDeath(hdlr, 0);
2922 }
2923 // force reading new top of mSetModeDeathHandlers stack
Jean-Michel Trivi339567d2014-07-29 09:53:34 -07002924 if (DEBUG_MODE) { Log.w(TAG, " mode set to MODE_NORMAL after phoneState pb"); }
Eric Laurent9f103de2011-09-08 15:04:23 -07002925 mode = AudioSystem.MODE_NORMAL;
2926 }
2927 } else {
2928 status = AudioSystem.AUDIO_STATUS_OK;
2929 }
2930 } while (status != AudioSystem.AUDIO_STATUS_OK && !mSetModeDeathHandlers.isEmpty());
2931
2932 if (status == AudioSystem.AUDIO_STATUS_OK) {
Eric Laurent6afa6502017-09-28 15:18:19 -07002933 if (actualMode != AudioSystem.MODE_NORMAL) {
Eric Laurentd7454be2011-09-14 08:45:58 -07002934 if (mSetModeDeathHandlers.isEmpty()) {
2935 Log.e(TAG, "setMode() different from MODE_NORMAL with empty mode client stack");
2936 } else {
2937 newModeOwnerPid = mSetModeDeathHandlers.get(0).getPid();
2938 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002939 }
Eric Laurent6afa6502017-09-28 15:18:19 -07002940 // Note: newModeOwnerPid is always 0 when actualMode is MODE_NORMAL
2941 mModeLogger.log(
2942 new PhoneStateEvent(caller, pid, mode, newModeOwnerPid, actualMode));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002943 int streamType = getActiveStreamType(AudioManager.USE_DEFAULT_STREAM_TYPE);
Eric Laurent9bc8358d2011-11-18 16:43:31 -08002944 int device = getDeviceForStream(streamType);
Eric Laurent42b041e2013-03-29 11:36:03 -07002945 int index = mStreamStates[mStreamVolumeAlias[streamType]].getIndex(device);
John Spurlock90874332015-03-10 16:00:54 -04002946 setStreamVolumeInt(mStreamVolumeAlias[streamType], index, device, true, caller);
Eric Laurent6d517662012-04-23 18:42:39 -07002947
John Spurlock90874332015-03-10 16:00:54 -04002948 updateStreamVolumeAlias(true /*updateVolumes*/, caller);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002949 }
Eric Laurentd7454be2011-09-14 08:45:58 -07002950 return newModeOwnerPid;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002951 }
2952
2953 /** @see AudioManager#getMode() */
2954 public int getMode() {
2955 return mMode;
2956 }
2957
Eric Laurente78fced2013-03-15 16:03:47 -07002958 //==========================================================================================
2959 // Sound Effects
2960 //==========================================================================================
2961
2962 private static final String TAG_AUDIO_ASSETS = "audio_assets";
2963 private static final String ATTR_VERSION = "version";
2964 private static final String TAG_GROUP = "group";
2965 private static final String ATTR_GROUP_NAME = "name";
2966 private static final String TAG_ASSET = "asset";
2967 private static final String ATTR_ASSET_ID = "id";
2968 private static final String ATTR_ASSET_FILE = "file";
2969
2970 private static final String ASSET_FILE_VERSION = "1.0";
2971 private static final String GROUP_TOUCH_SOUNDS = "touch_sounds";
2972
Glenn Kasten167d1a22013-07-23 16:24:41 -07002973 private static final int SOUND_EFFECTS_LOAD_TIMEOUT_MS = 5000;
Eric Laurent5d3eb44a2013-03-21 15:35:10 -07002974
2975 class LoadSoundEffectReply {
2976 public int mStatus = 1;
2977 };
2978
Eric Laurente78fced2013-03-15 16:03:47 -07002979 private void loadTouchSoundAssetDefaults() {
2980 SOUND_EFFECT_FILES.add("Effect_Tick.ogg");
2981 for (int i = 0; i < AudioManager.NUM_SOUND_EFFECTS; i++) {
2982 SOUND_EFFECT_FILES_MAP[i][0] = 0;
2983 SOUND_EFFECT_FILES_MAP[i][1] = -1;
2984 }
2985 }
2986
2987 private void loadTouchSoundAssets() {
2988 XmlResourceParser parser = null;
2989
Eric Laurent5d3eb44a2013-03-21 15:35:10 -07002990 // only load assets once.
2991 if (!SOUND_EFFECT_FILES.isEmpty()) {
2992 return;
2993 }
2994
Eric Laurente78fced2013-03-15 16:03:47 -07002995 loadTouchSoundAssetDefaults();
2996
2997 try {
2998 parser = mContext.getResources().getXml(com.android.internal.R.xml.audio_assets);
2999
3000 XmlUtils.beginDocument(parser, TAG_AUDIO_ASSETS);
3001 String version = parser.getAttributeValue(null, ATTR_VERSION);
3002 boolean inTouchSoundsGroup = false;
3003
3004 if (ASSET_FILE_VERSION.equals(version)) {
3005 while (true) {
3006 XmlUtils.nextElement(parser);
3007 String element = parser.getName();
3008 if (element == null) {
3009 break;
3010 }
3011 if (element.equals(TAG_GROUP)) {
3012 String name = parser.getAttributeValue(null, ATTR_GROUP_NAME);
3013 if (GROUP_TOUCH_SOUNDS.equals(name)) {
3014 inTouchSoundsGroup = true;
3015 break;
3016 }
3017 }
3018 }
3019 while (inTouchSoundsGroup) {
3020 XmlUtils.nextElement(parser);
3021 String element = parser.getName();
3022 if (element == null) {
3023 break;
3024 }
3025 if (element.equals(TAG_ASSET)) {
3026 String id = parser.getAttributeValue(null, ATTR_ASSET_ID);
3027 String file = parser.getAttributeValue(null, ATTR_ASSET_FILE);
3028 int fx;
3029
3030 try {
3031 Field field = AudioManager.class.getField(id);
3032 fx = field.getInt(null);
3033 } catch (Exception e) {
3034 Log.w(TAG, "Invalid touch sound ID: "+id);
3035 continue;
3036 }
3037
3038 int i = SOUND_EFFECT_FILES.indexOf(file);
3039 if (i == -1) {
3040 i = SOUND_EFFECT_FILES.size();
3041 SOUND_EFFECT_FILES.add(file);
3042 }
3043 SOUND_EFFECT_FILES_MAP[fx][0] = i;
3044 } else {
3045 break;
3046 }
3047 }
3048 }
3049 } catch (Resources.NotFoundException e) {
3050 Log.w(TAG, "audio assets file not found", e);
3051 } catch (XmlPullParserException e) {
3052 Log.w(TAG, "XML parser exception reading touch sound assets", e);
3053 } catch (IOException e) {
3054 Log.w(TAG, "I/O exception reading touch sound assets", e);
3055 } finally {
3056 if (parser != null) {
3057 parser.close();
3058 }
3059 }
3060 }
3061
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003062 /** @see AudioManager#playSoundEffect(int) */
3063 public void playSoundEffect(int effectType) {
Eric Laurent5d3eb44a2013-03-21 15:35:10 -07003064 playSoundEffectVolume(effectType, -1.0f);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003065 }
3066
3067 /** @see AudioManager#playSoundEffect(int, float) */
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003068 public void playSoundEffectVolume(int effectType, float volume) {
Beverlyd6964762018-02-16 14:07:03 -05003069 // do not try to play the sound effect if the system stream is muted
3070 if (isStreamMutedByRingerOrZenMode(STREAM_SYSTEM)) {
3071 return;
3072 }
3073
Natalie Silvanovich559c76d2014-05-01 10:16:24 -07003074 if (effectType >= AudioManager.NUM_SOUND_EFFECTS || effectType < 0) {
3075 Log.w(TAG, "AudioService effectType value " + effectType + " out of range");
3076 return;
3077 }
3078
Eric Laurent5d3eb44a2013-03-21 15:35:10 -07003079 sendMsg(mAudioHandler, MSG_PLAY_SOUND_EFFECT, SENDMSG_QUEUE,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003080 effectType, (int) (volume * 1000), null, 0);
3081 }
3082
3083 /**
3084 * Loads samples into the soundpool.
Glenn Kasten5c17a822011-11-30 09:41:01 -08003085 * This method must be called at first when sound effects are enabled
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003086 */
3087 public boolean loadSoundEffects() {
Eric Laurent5d3eb44a2013-03-21 15:35:10 -07003088 int attempts = 3;
3089 LoadSoundEffectReply reply = new LoadSoundEffectReply();
Eric Laurenta60e2122010-12-28 16:49:07 -08003090
Eric Laurent5d3eb44a2013-03-21 15:35:10 -07003091 synchronized (reply) {
3092 sendMsg(mAudioHandler, MSG_LOAD_SOUND_EFFECTS, SENDMSG_QUEUE, 0, 0, reply, 0);
3093 while ((reply.mStatus == 1) && (attempts-- > 0)) {
Eric Laurent117b7bb2011-01-16 17:07:27 -08003094 try {
Glenn Kasten167d1a22013-07-23 16:24:41 -07003095 reply.wait(SOUND_EFFECTS_LOAD_TIMEOUT_MS);
Eric Laurent5d3eb44a2013-03-21 15:35:10 -07003096 } catch (InterruptedException e) {
3097 Log.w(TAG, "loadSoundEffects Interrupted while waiting sound pool loaded.");
Eric Laurent117b7bb2011-01-16 17:07:27 -08003098 }
Eric Laurenta60e2122010-12-28 16:49:07 -08003099 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003100 }
Eric Laurent5d3eb44a2013-03-21 15:35:10 -07003101 return (reply.mStatus == 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003102 }
3103
3104 /**
3105 * Unloads samples from the sound pool.
3106 * This method can be called to free some memory when
3107 * sound effects are disabled.
3108 */
3109 public void unloadSoundEffects() {
Eric Laurent5d3eb44a2013-03-21 15:35:10 -07003110 sendMsg(mAudioHandler, MSG_UNLOAD_SOUND_EFFECTS, SENDMSG_QUEUE, 0, 0, null, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003111 }
3112
Eric Laurenta60e2122010-12-28 16:49:07 -08003113 class SoundPoolListenerThread extends Thread {
3114 public SoundPoolListenerThread() {
3115 super("SoundPoolListenerThread");
3116 }
3117
3118 @Override
3119 public void run() {
3120
3121 Looper.prepare();
3122 mSoundPoolLooper = Looper.myLooper();
3123
3124 synchronized (mSoundEffectsLock) {
3125 if (mSoundPool != null) {
3126 mSoundPoolCallBack = new SoundPoolCallback();
3127 mSoundPool.setOnLoadCompleteListener(mSoundPoolCallBack);
3128 }
3129 mSoundEffectsLock.notify();
3130 }
3131 Looper.loop();
3132 }
3133 }
3134
3135 private final class SoundPoolCallback implements
3136 android.media.SoundPool.OnLoadCompleteListener {
3137
Eric Laurent5d3eb44a2013-03-21 15:35:10 -07003138 int mStatus = 1; // 1 means neither error nor last sample loaded yet
3139 List<Integer> mSamples = new ArrayList<Integer>();
Eric Laurenta60e2122010-12-28 16:49:07 -08003140
3141 public int status() {
3142 return mStatus;
3143 }
3144
Eric Laurent5d3eb44a2013-03-21 15:35:10 -07003145 public void setSamples(int[] samples) {
3146 for (int i = 0; i < samples.length; i++) {
3147 // do not wait ack for samples rejected upfront by SoundPool
3148 if (samples[i] > 0) {
3149 mSamples.add(samples[i]);
3150 }
3151 }
Eric Laurenta60e2122010-12-28 16:49:07 -08003152 }
3153
3154 public void onLoadComplete(SoundPool soundPool, int sampleId, int status) {
3155 synchronized (mSoundEffectsLock) {
Eric Laurent5d3eb44a2013-03-21 15:35:10 -07003156 int i = mSamples.indexOf(sampleId);
3157 if (i >= 0) {
3158 mSamples.remove(i);
Eric Laurenta60e2122010-12-28 16:49:07 -08003159 }
Eric Laurent5d3eb44a2013-03-21 15:35:10 -07003160 if ((status != 0) || mSamples. isEmpty()) {
3161 mStatus = status;
Eric Laurenta60e2122010-12-28 16:49:07 -08003162 mSoundEffectsLock.notify();
3163 }
3164 }
3165 }
3166 }
3167
Eric Laurent4050c932009-07-08 02:52:14 -07003168 /** @see AudioManager#reloadAudioSettings() */
3169 public void reloadAudioSettings() {
Eric Laurentbc0fab1f2012-09-19 11:24:41 -07003170 readAudioSettings(false /*userSwitch*/);
3171 }
3172
3173 private void readAudioSettings(boolean userSwitch) {
Eric Laurent4050c932009-07-08 02:52:14 -07003174 // restore ringer mode, ringer mode affected streams, mute affected streams and vibrate settings
3175 readPersistedSettings();
Eric Laurentc0232482016-03-15 18:19:23 -07003176 readUserRestrictions();
Eric Laurent4050c932009-07-08 02:52:14 -07003177
3178 // restore volume settings
3179 int numStreamTypes = AudioSystem.getNumStreamTypes();
3180 for (int streamType = 0; streamType < numStreamTypes; streamType++) {
3181 VolumeStreamState streamState = mStreamStates[streamType];
3182
Eric Laurentbc0fab1f2012-09-19 11:24:41 -07003183 if (userSwitch && mStreamVolumeAlias[streamType] == AudioSystem.STREAM_MUSIC) {
3184 continue;
3185 }
3186
Eric Laurent8fa4d6f2014-10-30 14:13:03 -07003187 streamState.readSettings();
3188 synchronized (VolumeStreamState.class) {
Eric Laurent3172d5e2012-05-09 11:38:16 -07003189 // unmute stream that was muted but is not affect by mute anymore
RoboErik4197cb62015-01-21 15:45:32 -08003190 if (streamState.mIsMuted && ((!isStreamAffectedByMute(streamType) &&
Beverlyd6964762018-02-16 14:07:03 -05003191 !isStreamMutedByRingerOrZenMode(streamType)) || mUseFixedVolume)) {
RoboErik4197cb62015-01-21 15:45:32 -08003192 streamState.mIsMuted = false;
Eric Laurent4050c932009-07-08 02:52:14 -07003193 }
Eric Laurent4050c932009-07-08 02:52:14 -07003194 }
3195 }
3196
Eric Laurent33902db2012-10-07 16:15:07 -07003197 // apply new ringer mode before checking volume for alias streams so that streams
3198 // muted by ringer mode have the correct volume
John Spurlock661f2cf2014-11-17 10:29:10 -05003199 setRingerModeInt(getRingerModeInternal(), false);
Eric Laurent33902db2012-10-07 16:15:07 -07003200
Eric Laurent212532b2014-07-21 15:43:18 -07003201 checkAllFixedVolumeDevices();
Eric Laurent24482012012-05-10 09:41:17 -07003202 checkAllAliasStreamVolumes();
John Spurlockb6e19e32015-03-10 21:33:44 -04003203 checkMuteAffectedStreams();
Eric Laurent24482012012-05-10 09:41:17 -07003204
hyomin.ohd0446dc2018-10-18 13:58:27 +09003205 synchronized (mSafeMediaVolumeStateLock) {
John Spurlockaa5ee4d2014-07-25 13:05:12 -04003206 mMusicActiveMs = MathUtils.constrain(Settings.Secure.getIntForUser(mContentResolver,
3207 Settings.Secure.UNSAFE_VOLUME_MUSIC_ACTIVE_MS, 0, UserHandle.USER_CURRENT),
3208 0, UNSAFE_VOLUME_MUSIC_ACTIVE_MS_MAX);
Eric Laurentd640bd32012-09-28 18:01:48 -07003209 if (mSafeMediaVolumeState == SAFE_MEDIA_VOLUME_ACTIVE) {
John Spurlock90874332015-03-10 16:00:54 -04003210 enforceSafeMediaVolume(TAG);
Eric Laurentf1a457d2012-09-20 16:27:23 -07003211 }
Eric Laurentc34dcc12012-09-10 13:51:52 -07003212 }
Eric Laurent4050c932009-07-08 02:52:14 -07003213 }
3214
Dianne Hackborn961cae92013-03-20 14:59:43 -07003215 /** @see AudioManager#setSpeakerphoneOn(boolean) */
Eric Laurentc42ac9d2009-07-29 08:53:03 -07003216 public void setSpeakerphoneOn(boolean on){
Eric Laurentdc1d17a2009-09-10 00:48:21 -07003217 if (!checkAudioSettingsPermission("setSpeakerphoneOn()")) {
3218 return;
3219 }
Jean-Michel Trivi011f39e2017-08-19 18:08:06 -07003220 // for logging only
3221 final String eventSource = new StringBuilder("setSpeakerphoneOn(").append(on)
3222 .append(") from u/pid:").append(Binder.getCallingUid()).append("/")
3223 .append(Binder.getCallingPid()).toString();
Jean-Michel Trivi58850372018-09-14 16:01:28 -07003224 mDeviceBroker.setSpeakerphoneOn(on, eventSource);
Eric Laurentc42ac9d2009-07-29 08:53:03 -07003225 }
3226
3227 /** @see AudioManager#isSpeakerphoneOn() */
3228 public boolean isSpeakerphoneOn() {
Jean-Michel Trivi58850372018-09-14 16:01:28 -07003229 return mDeviceBroker.isSpeakerphoneOn();
Eric Laurentc42ac9d2009-07-29 08:53:03 -07003230 }
3231
Dianne Hackborn961cae92013-03-20 14:59:43 -07003232 /** @see AudioManager#setBluetoothScoOn(boolean) */
Eric Laurent48221252015-09-24 18:41:48 -07003233 public void setBluetoothScoOn(boolean on) {
Eric Laurentdc1d17a2009-09-10 00:48:21 -07003234 if (!checkAudioSettingsPermission("setBluetoothScoOn()")) {
3235 return;
3236 }
Sharad Sangle1d188442017-05-09 16:05:40 +05303237
3238 // Only enable calls from system components
Vitor Albuquerquec3bb48c2018-03-07 10:39:59 -03003239 if (UserHandle.getCallingAppId() >= FIRST_APPLICATION_UID) {
Jean-Michel Trivi58850372018-09-14 16:01:28 -07003240 mDeviceBroker.setBluetoothScoOnByApp(on);
Sharad Sangle1d188442017-05-09 16:05:40 +05303241 return;
3242 }
3243
Jean-Michel Trivi011f39e2017-08-19 18:08:06 -07003244 // for logging only
3245 final String eventSource = new StringBuilder("setBluetoothScoOn(").append(on)
3246 .append(") from u/pid:").append(Binder.getCallingUid()).append("/")
3247 .append(Binder.getCallingPid()).toString();
Jean-Michel Trivi58850372018-09-14 16:01:28 -07003248
3249 mDeviceBroker.setBluetoothScoOn(on, eventSource);
Eric Laurent48221252015-09-24 18:41:48 -07003250 }
Johan Gustavsson7337bee2013-03-01 15:53:30 +01003251
Jean-Michel Trivi58850372018-09-14 16:01:28 -07003252 /** @see AudioManager#isBluetoothScoOn()
3253 * Note that it doesn't report internal state, but state seen by apps (which may have
3254 * called setBluetoothScoOn() */
Eric Laurentc42ac9d2009-07-29 08:53:03 -07003255 public boolean isBluetoothScoOn() {
Jean-Michel Trivi58850372018-09-14 16:01:28 -07003256 return mDeviceBroker.isBluetoothScoOnForApp();
Eric Laurentc42ac9d2009-07-29 08:53:03 -07003257 }
3258
Jean-Michel Trivi58850372018-09-14 16:01:28 -07003259 // TODO investigate internal users due to deprecation of SDK API
Sungsoocf09fe62016-09-28 16:21:48 +09003260 /** @see AudioManager#setBluetoothA2dpOn(boolean) */
Eric Laurent78472112012-05-21 08:57:21 -07003261 public void setBluetoothA2dpOn(boolean on) {
Jean-Michel Trivi011f39e2017-08-19 18:08:06 -07003262 // for logging only
3263 final String eventSource = new StringBuilder("setBluetoothA2dpOn(").append(on)
3264 .append(") from u/pid:").append(Binder.getCallingUid()).append("/")
3265 .append(Binder.getCallingPid()).toString();
Jean-Michel Trivi58850372018-09-14 16:01:28 -07003266 mDeviceBroker.setBluetoothA2dpOn_Async(on, eventSource);
Eric Laurent78472112012-05-21 08:57:21 -07003267 }
3268
Sungsoocf09fe62016-09-28 16:21:48 +09003269 /** @see AudioManager#isBluetoothA2dpOn() */
Eric Laurent78472112012-05-21 08:57:21 -07003270 public boolean isBluetoothA2dpOn() {
Jean-Michel Trivi58850372018-09-14 16:01:28 -07003271 return mDeviceBroker.isBluetoothA2dpOn();
Eric Laurent78472112012-05-21 08:57:21 -07003272 }
3273
Eric Laurent3def1ee2010-03-17 23:26:26 -07003274 /** @see AudioManager#startBluetoothSco() */
Eric Laurent83900752014-05-15 15:14:22 -07003275 public void startBluetoothSco(IBinder cb, int targetSdkVersion) {
Jean-Michel Trivi58850372018-09-14 16:01:28 -07003276 final int scoAudioMode =
Eric Laurent83900752014-05-15 15:14:22 -07003277 (targetSdkVersion < Build.VERSION_CODES.JELLY_BEAN_MR2) ?
Jean-Michel Trivi58850372018-09-14 16:01:28 -07003278 BtHelper.SCO_MODE_VIRTUAL_CALL : BtHelper.SCO_MODE_UNDEFINED;
3279 final String eventSource = new StringBuilder("startBluetoothSco()")
3280 .append(") from u/pid:").append(Binder.getCallingUid()).append("/")
3281 .append(Binder.getCallingPid()).toString();
3282 startBluetoothScoInt(cb, scoAudioMode, eventSource);
Eric Laurent83900752014-05-15 15:14:22 -07003283 }
3284
3285 /** @see AudioManager#startBluetoothScoVirtualCall() */
3286 public void startBluetoothScoVirtualCall(IBinder cb) {
Jean-Michel Trivi58850372018-09-14 16:01:28 -07003287 final String eventSource = new StringBuilder("startBluetoothScoVirtualCall()")
3288 .append(") from u/pid:").append(Binder.getCallingUid()).append("/")
3289 .append(Binder.getCallingPid()).toString();
3290 startBluetoothScoInt(cb, BtHelper.SCO_MODE_VIRTUAL_CALL, eventSource);
Eric Laurent83900752014-05-15 15:14:22 -07003291 }
3292
Jean-Michel Trivi58850372018-09-14 16:01:28 -07003293 void startBluetoothScoInt(IBinder cb, int scoAudioMode, @NonNull String eventSource) {
Eric Laurentdc03c612011-04-01 10:59:41 -07003294 if (!checkAudioSettingsPermission("startBluetoothSco()") ||
Eric Laurent4a5eeb92014-05-06 10:49:04 -07003295 !mSystemReady) {
Eric Laurent3def1ee2010-03-17 23:26:26 -07003296 return;
3297 }
Jean-Michel Trivi58850372018-09-14 16:01:28 -07003298 mDeviceBroker.startBluetoothScoForClient_Sync(cb, scoAudioMode, eventSource);
Eric Laurent3def1ee2010-03-17 23:26:26 -07003299 }
3300
3301 /** @see AudioManager#stopBluetoothSco() */
3302 public void stopBluetoothSco(IBinder cb){
Eric Laurentdc03c612011-04-01 10:59:41 -07003303 if (!checkAudioSettingsPermission("stopBluetoothSco()") ||
Eric Laurent4a5eeb92014-05-06 10:49:04 -07003304 !mSystemReady) {
Eric Laurent3def1ee2010-03-17 23:26:26 -07003305 return;
3306 }
Jean-Michel Trivi58850372018-09-14 16:01:28 -07003307 final String eventSource = new StringBuilder("stopBluetoothSco()")
3308 .append(") from u/pid:").append(Binder.getCallingUid()).append("/")
3309 .append(Binder.getCallingPid()).toString();
3310 mDeviceBroker.stopBluetoothScoForClient_Sync(cb, eventSource);
Eric Laurent3def1ee2010-03-17 23:26:26 -07003311 }
3312
Eric Laurent78472112012-05-21 08:57:21 -07003313
Jean-Michel Trivi58850372018-09-14 16:01:28 -07003314 /*package*/ ContentResolver getContentResolver() {
3315 return mContentResolver;
Jakub Pawlowskif9570f32018-02-21 17:15:12 -08003316 }
3317
John Spurlock90874332015-03-10 16:00:54 -04003318 private void onCheckMusicActive(String caller) {
hyomin.ohd0446dc2018-10-18 13:58:27 +09003319 synchronized (mSafeMediaVolumeStateLock) {
Eric Laurentd640bd32012-09-28 18:01:48 -07003320 if (mSafeMediaVolumeState == SAFE_MEDIA_VOLUME_INACTIVE) {
Eric Laurentc34dcc12012-09-10 13:51:52 -07003321 int device = getDeviceForStream(AudioSystem.STREAM_MUSIC);
3322
3323 if ((device & mSafeMediaVolumeDevices) != 0) {
3324 sendMsg(mAudioHandler,
3325 MSG_CHECK_MUSIC_ACTIVE,
3326 SENDMSG_REPLACE,
Eric Laurentf1a457d2012-09-20 16:27:23 -07003327 0,
Eric Laurentc34dcc12012-09-10 13:51:52 -07003328 0,
John Spurlock90874332015-03-10 16:00:54 -04003329 caller,
Eric Laurentc34dcc12012-09-10 13:51:52 -07003330 MUSIC_ACTIVE_POLL_PERIOD_MS);
Eric Laurent42b041e2013-03-29 11:36:03 -07003331 int index = mStreamStates[AudioSystem.STREAM_MUSIC].getIndex(device);
Jean-Michel Trivi58850372018-09-14 16:01:28 -07003332 if (AudioSystem.isStreamActive(AudioSystem.STREAM_MUSIC, 0)
3333 && (index > safeMediaVolumeIndex(device))) {
Eric Laurentc34dcc12012-09-10 13:51:52 -07003334 // Approximate cumulative active music time
3335 mMusicActiveMs += MUSIC_ACTIVE_POLL_PERIOD_MS;
3336 if (mMusicActiveMs > UNSAFE_VOLUME_MUSIC_ACTIVE_MS_MAX) {
John Spurlock90874332015-03-10 16:00:54 -04003337 setSafeMediaVolumeEnabled(true, caller);
Eric Laurentc34dcc12012-09-10 13:51:52 -07003338 mMusicActiveMs = 0;
Eric Laurentc34dcc12012-09-10 13:51:52 -07003339 }
John Spurlockaa5ee4d2014-07-25 13:05:12 -04003340 saveMusicActiveMs();
Eric Laurentc34dcc12012-09-10 13:51:52 -07003341 }
3342 }
3343 }
3344 }
3345 }
3346
John Spurlockaa5ee4d2014-07-25 13:05:12 -04003347 private void saveMusicActiveMs() {
3348 mAudioHandler.obtainMessage(MSG_PERSIST_MUSIC_ACTIVE_MS, mMusicActiveMs, 0).sendToTarget();
3349 }
3350
Jean-Michel Trivi58850372018-09-14 16:01:28 -07003351 private int getSafeUsbMediaVolumeIndex() {
Eric Laurenteab40d12017-06-09 12:45:21 -07003352 // determine UI volume index corresponding to the wanted safe gain in dBFS
3353 int min = MIN_STREAM_VOLUME[AudioSystem.STREAM_MUSIC];
3354 int max = MAX_STREAM_VOLUME[AudioSystem.STREAM_MUSIC];
3355
John Muir8b8bddd2018-02-16 14:29:14 -08003356 mSafeUsbMediaVolumeDbfs = mContext.getResources().getInteger(
3357 com.android.internal.R.integer.config_safe_media_volume_usb_mB) / 100.0f;
3358
Jean-Michel Trivi58850372018-09-14 16:01:28 -07003359 while (Math.abs(max - min) > 1) {
Eric Laurenteab40d12017-06-09 12:45:21 -07003360 int index = (max + min) / 2;
3361 float gainDB = AudioSystem.getStreamVolumeDB(
3362 AudioSystem.STREAM_MUSIC, index, AudioSystem.DEVICE_OUT_USB_HEADSET);
Eric Laurentb378a13a2017-07-11 14:08:11 -07003363 if (Float.isNaN(gainDB)) {
Eric Laurenteab40d12017-06-09 12:45:21 -07003364 //keep last min in case of read error
3365 break;
John Muir8b8bddd2018-02-16 14:29:14 -08003366 } else if (gainDB == mSafeUsbMediaVolumeDbfs) {
Eric Laurenteab40d12017-06-09 12:45:21 -07003367 min = index;
3368 break;
John Muir8b8bddd2018-02-16 14:29:14 -08003369 } else if (gainDB < mSafeUsbMediaVolumeDbfs) {
Eric Laurenteab40d12017-06-09 12:45:21 -07003370 min = index;
3371 } else {
3372 max = index;
3373 }
3374 }
3375 return min * 10;
3376 }
3377
John Spurlock90874332015-03-10 16:00:54 -04003378 private void onConfigureSafeVolume(boolean force, String caller) {
hyomin.ohd0446dc2018-10-18 13:58:27 +09003379 synchronized (mSafeMediaVolumeStateLock) {
Eric Laurentd640bd32012-09-28 18:01:48 -07003380 int mcc = mContext.getResources().getConfiguration().mcc;
3381 if ((mMcc != mcc) || ((mMcc == 0) && force)) {
3382 mSafeMediaVolumeIndex = mContext.getResources().getInteger(
3383 com.android.internal.R.integer.config_safe_media_volume_index) * 10;
Eric Laurenteab40d12017-06-09 12:45:21 -07003384
3385 mSafeUsbMediaVolumeIndex = getSafeUsbMediaVolumeIndex();
3386
John Spurlock35134602014-07-24 18:10:48 -04003387 boolean safeMediaVolumeEnabled =
3388 SystemProperties.getBoolean("audio.safemedia.force", false)
3389 || mContext.getResources().getBoolean(
3390 com.android.internal.R.bool.config_safe_media_volume_enabled);
Eric Laurent05274f32012-11-29 12:48:18 -08003391
Ricardo Garcia3a30a762015-06-23 15:54:45 -07003392 boolean safeMediaVolumeBypass =
3393 SystemProperties.getBoolean("audio.safemedia.bypass", false);
3394
Eric Laurent05274f32012-11-29 12:48:18 -08003395 // The persisted state is either "disabled" or "active": this is the state applied
3396 // next time we boot and cannot be "inactive"
3397 int persistedState;
Ricardo Garcia3a30a762015-06-23 15:54:45 -07003398 if (safeMediaVolumeEnabled && !safeMediaVolumeBypass) {
Eric Laurent05274f32012-11-29 12:48:18 -08003399 persistedState = SAFE_MEDIA_VOLUME_ACTIVE;
3400 // The state can already be "inactive" here if the user has forced it before
3401 // the 30 seconds timeout for forced configuration. In this case we don't reset
3402 // it to "active".
3403 if (mSafeMediaVolumeState != SAFE_MEDIA_VOLUME_INACTIVE) {
John Spurlockaa5ee4d2014-07-25 13:05:12 -04003404 if (mMusicActiveMs == 0) {
3405 mSafeMediaVolumeState = SAFE_MEDIA_VOLUME_ACTIVE;
John Spurlock90874332015-03-10 16:00:54 -04003406 enforceSafeMediaVolume(caller);
John Spurlockaa5ee4d2014-07-25 13:05:12 -04003407 } else {
3408 // We have existing playback time recorded, already confirmed.
3409 mSafeMediaVolumeState = SAFE_MEDIA_VOLUME_INACTIVE;
3410 }
Eric Laurent05274f32012-11-29 12:48:18 -08003411 }
Eric Laurentd640bd32012-09-28 18:01:48 -07003412 } else {
Eric Laurent05274f32012-11-29 12:48:18 -08003413 persistedState = SAFE_MEDIA_VOLUME_DISABLED;
Eric Laurentd640bd32012-09-28 18:01:48 -07003414 mSafeMediaVolumeState = SAFE_MEDIA_VOLUME_DISABLED;
3415 }
3416 mMcc = mcc;
Eric Laurent05274f32012-11-29 12:48:18 -08003417 sendMsg(mAudioHandler,
3418 MSG_PERSIST_SAFE_VOLUME_STATE,
3419 SENDMSG_QUEUE,
3420 persistedState,
3421 0,
3422 null,
3423 0);
Eric Laurentd640bd32012-09-28 18:01:48 -07003424 }
3425 }
3426 }
3427
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003428 ///////////////////////////////////////////////////////////////////////////
3429 // Internal methods
3430 ///////////////////////////////////////////////////////////////////////////
3431
3432 /**
3433 * Checks if the adjustment should change ringer mode instead of just
3434 * adjusting volume. If so, this will set the proper ringer mode and volume
3435 * indices on the stream states.
3436 */
Julia Reynoldsed783792016-04-08 15:27:35 -04003437 private int checkForRingerModeChange(int oldIndex, int direction, int step, boolean isMuted,
3438 String caller, int flags) {
John Spurlocka11b4af2014-06-01 11:52:23 -04003439 int result = FLAG_ADJUST_VOLUME;
Zak Cohen47798292017-11-30 12:34:20 -08003440 if (isPlatformTelevision() || mIsSingleVolume) {
Hank Freund21003f62015-12-08 09:05:46 -08003441 return result;
3442 }
3443
John Spurlock661f2cf2014-11-17 10:29:10 -05003444 int ringerMode = getRingerModeInternal();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003445
Eric Laurentbffc3d12012-05-07 17:43:49 -07003446 switch (ringerMode) {
3447 case RINGER_MODE_NORMAL:
3448 if (direction == AudioManager.ADJUST_LOWER) {
3449 if (mHasVibrator) {
Eric Laurent24482012012-05-10 09:41:17 -07003450 // "step" is the delta in internal index units corresponding to a
3451 // change of 1 in UI index units.
3452 // Because of rounding when rescaling from one stream index range to its alias
3453 // index range, we cannot simply test oldIndex == step:
3454 // (step <= oldIndex < 2 * step) is equivalent to: (old UI index == 1)
3455 if (step <= oldIndex && oldIndex < 2 * step) {
Eric Laurentbffc3d12012-05-07 17:43:49 -07003456 ringerMode = RINGER_MODE_VIBRATE;
John Spurlock07e72432015-03-13 11:46:52 -04003457 mLoweredFromNormalToVibrateTime = SystemClock.uptimeMillis();
Eric Laurentbffc3d12012-05-07 17:43:49 -07003458 }
3459 } else {
John Spurlockd9c75db2015-04-28 11:19:13 -04003460 if (oldIndex == step && mVolumePolicy.volumeDownToEnterSilent) {
Eric Laurentbffc3d12012-05-07 17:43:49 -07003461 ringerMode = RINGER_MODE_SILENT;
3462 }
Eric Laurent3d4c06f2011-08-15 19:58:28 -07003463 }
Muyuan Li1ed6df62016-06-18 11:16:52 -07003464 } else if (mIsSingleVolume && (direction == AudioManager.ADJUST_TOGGLE_MUTE
John Spurlocka48d7792015-03-03 17:35:57 -05003465 || direction == AudioManager.ADJUST_MUTE)) {
RoboErik5452e252015-02-06 15:33:53 -08003466 if (mHasVibrator) {
3467 ringerMode = RINGER_MODE_VIBRATE;
3468 } else {
3469 ringerMode = RINGER_MODE_SILENT;
3470 }
3471 // Setting the ringer mode will toggle mute
3472 result &= ~FLAG_ADJUST_VOLUME;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003473 }
Eric Laurentbffc3d12012-05-07 17:43:49 -07003474 break;
3475 case RINGER_MODE_VIBRATE:
3476 if (!mHasVibrator) {
3477 Log.e(TAG, "checkForRingerModeChange() current ringer mode is vibrate" +
3478 "but no vibrator is present");
3479 break;
3480 }
Amith Yamasanic696a532011-10-28 17:02:37 -07003481 if ((direction == AudioManager.ADJUST_LOWER)) {
RoboErik5452e252015-02-06 15:33:53 -08003482 // This is the case we were muted with the volume turned up
Muyuan Li1ed6df62016-06-18 11:16:52 -07003483 if (mIsSingleVolume && oldIndex >= 2 * step && isMuted) {
RoboErik5452e252015-02-06 15:33:53 -08003484 ringerMode = RINGER_MODE_NORMAL;
3485 } else if (mPrevVolDirection != AudioManager.ADJUST_LOWER) {
John Spurlocka48d7792015-03-03 17:35:57 -05003486 if (mVolumePolicy.volumeDownToEnterSilent) {
John Spurlock07e72432015-03-13 11:46:52 -04003487 final long diff = SystemClock.uptimeMillis()
3488 - mLoweredFromNormalToVibrateTime;
John Spurlockd9c75db2015-04-28 11:19:13 -04003489 if (diff > mVolumePolicy.vibrateToSilentDebounce
3490 && mRingerModeDelegate.canVolumeDownEnterSilent()) {
John Spurlock07e72432015-03-13 11:46:52 -04003491 ringerMode = RINGER_MODE_SILENT;
3492 }
John Spurlock795a5142014-12-08 14:09:35 -05003493 } else {
3494 result |= AudioManager.FLAG_SHOW_VIBRATE_HINT;
3495 }
Amith Yamasanic696a532011-10-28 17:02:37 -07003496 }
RoboErik5452e252015-02-06 15:33:53 -08003497 } else if (direction == AudioManager.ADJUST_RAISE
3498 || direction == AudioManager.ADJUST_TOGGLE_MUTE
3499 || direction == AudioManager.ADJUST_UNMUTE) {
Eric Laurentbffc3d12012-05-07 17:43:49 -07003500 ringerMode = RINGER_MODE_NORMAL;
Amith Yamasanic696a532011-10-28 17:02:37 -07003501 }
John Spurlocka11b4af2014-06-01 11:52:23 -04003502 result &= ~FLAG_ADJUST_VOLUME;
Eric Laurentbffc3d12012-05-07 17:43:49 -07003503 break;
3504 case RINGER_MODE_SILENT:
Muyuan Li1ed6df62016-06-18 11:16:52 -07003505 if (mIsSingleVolume && direction == AudioManager.ADJUST_LOWER && oldIndex >= 2 * step && isMuted) {
RoboErik5452e252015-02-06 15:33:53 -08003506 // This is the case we were muted with the volume turned up
3507 ringerMode = RINGER_MODE_NORMAL;
3508 } else if (direction == AudioManager.ADJUST_RAISE
3509 || direction == AudioManager.ADJUST_TOGGLE_MUTE
3510 || direction == AudioManager.ADJUST_UNMUTE) {
John Spurlocka48d7792015-03-03 17:35:57 -05003511 if (!mVolumePolicy.volumeUpToExitSilent) {
John Spurlocka11b4af2014-06-01 11:52:23 -04003512 result |= AudioManager.FLAG_SHOW_SILENT_HINT;
Eric Laurentbffc3d12012-05-07 17:43:49 -07003513 } else {
RoboErik5452e252015-02-06 15:33:53 -08003514 if (mHasVibrator && direction == AudioManager.ADJUST_RAISE) {
John Spurlocka11b4af2014-06-01 11:52:23 -04003515 ringerMode = RINGER_MODE_VIBRATE;
3516 } else {
RoboErik5452e252015-02-06 15:33:53 -08003517 // If we don't have a vibrator or they were toggling mute
3518 // go straight back to normal.
John Spurlocka11b4af2014-06-01 11:52:23 -04003519 ringerMode = RINGER_MODE_NORMAL;
3520 }
Eric Laurentbffc3d12012-05-07 17:43:49 -07003521 }
Daniel Sandler6329bf72010-02-26 15:17:44 -05003522 }
John Spurlocka11b4af2014-06-01 11:52:23 -04003523 result &= ~FLAG_ADJUST_VOLUME;
Eric Laurentbffc3d12012-05-07 17:43:49 -07003524 break;
3525 default:
3526 Log.e(TAG, "checkForRingerModeChange() wrong ringer mode: "+ringerMode);
3527 break;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003528 }
3529
Julia Reynoldsed783792016-04-08 15:27:35 -04003530 if (isAndroidNPlus(caller) && wouldToggleZenMode(ringerMode)
3531 && !mNm.isNotificationPolicyAccessGrantedForPackage(caller)
3532 && (flags & AudioManager.FLAG_FROM_KEY) == 0) {
3533 throw new SecurityException("Not allowed to change Do Not Disturb state");
3534 }
3535
John Spurlock661f2cf2014-11-17 10:29:10 -05003536 setRingerMode(ringerMode, TAG + ".checkForRingerModeChange", false /*external*/);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003537
Eric Laurent25101b02011-02-02 09:33:30 -08003538 mPrevVolDirection = direction;
3539
John Spurlocka11b4af2014-06-01 11:52:23 -04003540 return result;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003541 }
3542
John Spurlock3346a802014-05-20 16:25:37 -04003543 @Override
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003544 public boolean isStreamAffectedByRingerMode(int streamType) {
Eric Laurent9bcf4012009-06-12 06:09:28 -07003545 return (mRingerModeAffectedStreams & (1 << streamType)) != 0;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003546 }
3547
Beverlyd6964762018-02-16 14:07:03 -05003548 private boolean shouldZenMuteStream(int streamType) {
3549 if (mNm.getZenMode() != Settings.Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS) {
3550 return false;
3551 }
3552
Beverlyff2df9b2018-10-10 16:54:10 -04003553 NotificationManager.Policy zenPolicy = mNm.getConsolidatedNotificationPolicy();
Beverlyd6964762018-02-16 14:07:03 -05003554 final boolean muteAlarms = (zenPolicy.priorityCategories
3555 & NotificationManager.Policy.PRIORITY_CATEGORY_ALARMS) == 0;
3556 final boolean muteMedia = (zenPolicy.priorityCategories
3557 & NotificationManager.Policy.PRIORITY_CATEGORY_MEDIA) == 0;
3558 final boolean muteSystem = (zenPolicy.priorityCategories
3559 & NotificationManager.Policy.PRIORITY_CATEGORY_SYSTEM) == 0;
3560 final boolean muteNotificationAndRing = ZenModeConfig
Beverlyff2df9b2018-10-10 16:54:10 -04003561 .areAllPriorityOnlyNotificationZenSoundsMuted(
3562 mNm.getConsolidatedNotificationPolicy());
Beverlyd6964762018-02-16 14:07:03 -05003563 return muteAlarms && isAlarm(streamType)
3564 || muteMedia && isMedia(streamType)
3565 || muteSystem && isSystem(streamType)
3566 || muteNotificationAndRing && isNotificationOrRinger(streamType);
3567 }
3568
3569 private boolean isStreamMutedByRingerOrZenMode(int streamType) {
3570 return (mRingerAndZenModeMutedStreams & (1 << streamType)) != 0;
3571 }
3572
3573 /**
3574 * DND total silence: media and alarms streams are tied to the muted ringer
3575 * {@link ZenModeHelper.RingerModeDelegate#getRingerModeAffectedStreams(int)}
3576 * DND alarms only: notification, ringer + system muted (by default tied to muted ringer mode)
3577 * DND priority only: alarms, media, system streams can be muted separate from ringer based on
3578 * zenPolicy (this method determines which streams)
3579 * @return true if changed, else false
3580 */
3581 private boolean updateZenModeAffectedStreams() {
3582 int zenModeAffectedStreams = 0;
3583 if (mSystemReady && mNm.getZenMode() == Settings.Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS) {
Beverlyff2df9b2018-10-10 16:54:10 -04003584 NotificationManager.Policy zenPolicy = mNm.getConsolidatedNotificationPolicy();
Beverlyd6964762018-02-16 14:07:03 -05003585 if ((zenPolicy.priorityCategories
3586 & NotificationManager.Policy.PRIORITY_CATEGORY_ALARMS) == 0) {
3587 zenModeAffectedStreams |= 1 << AudioManager.STREAM_ALARM;
3588 }
3589
3590 if ((zenPolicy.priorityCategories
3591 & NotificationManager.Policy.PRIORITY_CATEGORY_MEDIA) == 0) {
3592 zenModeAffectedStreams |= 1 << AudioManager.STREAM_MUSIC;
3593 }
3594
3595 if ((zenPolicy.priorityCategories
3596 & NotificationManager.Policy.PRIORITY_CATEGORY_SYSTEM) == 0) {
3597 zenModeAffectedStreams |= 1 << AudioManager.STREAM_SYSTEM;
3598 }
3599 }
3600
3601 if (mZenModeAffectedStreams != zenModeAffectedStreams) {
3602 mZenModeAffectedStreams = zenModeAffectedStreams;
3603 return true;
3604 }
3605
3606 return false;
Eric Laurent5b4e6542010-03-19 20:02:21 -07003607 }
3608
Jean-Michel Trivi8719a1d2017-11-06 11:52:51 -08003609 @GuardedBy("mSettingsLock")
Beverlyd6964762018-02-16 14:07:03 -05003610 private boolean updateRingerAndZenModeAffectedStreams() {
3611 boolean updatedZenModeAffectedStreams = updateZenModeAffectedStreams();
John Spurlock50ced3f2015-05-11 16:00:09 -04003612 int ringerModeAffectedStreams = Settings.System.getIntForUser(mContentResolver,
Eric Laurent24e0d9b2013-10-03 18:15:07 -07003613 Settings.System.MODE_RINGER_STREAMS_AFFECTED,
3614 ((1 << AudioSystem.STREAM_RING)|(1 << AudioSystem.STREAM_NOTIFICATION)|
3615 (1 << AudioSystem.STREAM_SYSTEM)|(1 << AudioSystem.STREAM_SYSTEM_ENFORCED)),
3616 UserHandle.USER_CURRENT);
3617
Muyuan Li1ed6df62016-06-18 11:16:52 -07003618 if (mIsSingleVolume) {
John Spurlock50ced3f2015-05-11 16:00:09 -04003619 ringerModeAffectedStreams = 0;
3620 } else if (mRingerModeDelegate != null) {
3621 ringerModeAffectedStreams = mRingerModeDelegate
3622 .getRingerModeAffectedStreams(ringerModeAffectedStreams);
Eric Laurent24e0d9b2013-10-03 18:15:07 -07003623 }
Jean-Michel Trivi8719a1d2017-11-06 11:52:51 -08003624 if (mCameraSoundForced) {
3625 ringerModeAffectedStreams &= ~(1 << AudioSystem.STREAM_SYSTEM_ENFORCED);
3626 } else {
3627 ringerModeAffectedStreams |= (1 << AudioSystem.STREAM_SYSTEM_ENFORCED);
Eric Laurent24e0d9b2013-10-03 18:15:07 -07003628 }
3629 if (mStreamVolumeAlias[AudioSystem.STREAM_DTMF] == AudioSystem.STREAM_RING) {
3630 ringerModeAffectedStreams |= (1 << AudioSystem.STREAM_DTMF);
3631 } else {
3632 ringerModeAffectedStreams &= ~(1 << AudioSystem.STREAM_DTMF);
3633 }
3634
3635 if (ringerModeAffectedStreams != mRingerModeAffectedStreams) {
3636 Settings.System.putIntForUser(mContentResolver,
3637 Settings.System.MODE_RINGER_STREAMS_AFFECTED,
3638 ringerModeAffectedStreams,
3639 UserHandle.USER_CURRENT);
3640 mRingerModeAffectedStreams = ringerModeAffectedStreams;
3641 return true;
3642 }
Beverlyd6964762018-02-16 14:07:03 -05003643 return updatedZenModeAffectedStreams;
Eric Laurent24e0d9b2013-10-03 18:15:07 -07003644 }
3645
John Spurlocka9dfbe8b2015-02-17 11:01:51 -05003646 @Override
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003647 public boolean isStreamAffectedByMute(int streamType) {
3648 return (mMuteAffectedStreams & (1 << streamType)) != 0;
3649 }
3650
3651 private void ensureValidDirection(int direction) {
RoboErik4197cb62015-01-21 15:45:32 -08003652 switch (direction) {
3653 case AudioManager.ADJUST_LOWER:
3654 case AudioManager.ADJUST_RAISE:
3655 case AudioManager.ADJUST_SAME:
3656 case AudioManager.ADJUST_MUTE:
3657 case AudioManager.ADJUST_UNMUTE:
3658 case AudioManager.ADJUST_TOGGLE_MUTE:
3659 break;
3660 default:
3661 throw new IllegalArgumentException("Bad direction " + direction);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003662 }
3663 }
3664
3665 private void ensureValidStreamType(int streamType) {
3666 if (streamType < 0 || streamType >= mStreamStates.length) {
3667 throw new IllegalArgumentException("Bad stream type " + streamType);
3668 }
3669 }
3670
RoboErik4197cb62015-01-21 15:45:32 -08003671 private boolean isMuteAdjust(int adjust) {
3672 return adjust == AudioManager.ADJUST_MUTE || adjust == AudioManager.ADJUST_UNMUTE
3673 || adjust == AudioManager.ADJUST_TOGGLE_MUTE;
3674 }
3675
Jean-Michel Trivi58850372018-09-14 16:01:28 -07003676 /*package*/ boolean isInCommunication() {
Nancy Chen0eb1e402014-08-21 22:52:29 -07003677 boolean IsInCall = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003678
Tyler Gunnef9f6f92014-09-12 22:16:17 -07003679 TelecomManager telecomManager =
3680 (TelecomManager) mContext.getSystemService(Context.TELECOM_SERVICE);
Eric Laurent38edfda2014-12-18 17:38:04 -08003681
3682 final long ident = Binder.clearCallingIdentity();
Tyler Gunnef9f6f92014-09-12 22:16:17 -07003683 IsInCall = telecomManager.isInCall();
Eric Laurent38edfda2014-12-18 17:38:04 -08003684 Binder.restoreCallingIdentity(ident);
Santos Cordon9eb45932014-06-27 12:28:43 -07003685
Eric Laurentda1af762017-12-15 16:54:35 -08003686 return (IsInCall || getMode() == AudioManager.MODE_IN_COMMUNICATION ||
3687 getMode() == AudioManager.MODE_IN_CALL);
Eric Laurent6d517662012-04-23 18:42:39 -07003688 }
Eric Laurent25101b02011-02-02 09:33:30 -08003689
Jean-Michel Trivifca1e602013-10-10 18:12:59 -07003690 /**
3691 * For code clarity for getActiveStreamType(int)
Julia Reynoldsd9e96e22017-11-07 10:33:08 -05003692 * @param delay_ms max time since last stream activity to consider
3693 * @return true if stream is active in streams handled by AudioFlinger now or
Jean-Michel Trivifca1e602013-10-10 18:12:59 -07003694 * in the last "delay_ms" ms.
3695 */
Julia Reynoldsd9e96e22017-11-07 10:33:08 -05003696 private boolean wasStreamActiveRecently(int stream, int delay_ms) {
3697 return AudioSystem.isStreamActive(stream, delay_ms)
3698 || AudioSystem.isStreamActiveRemotely(stream, delay_ms);
Jean-Michel Trivifca1e602013-10-10 18:12:59 -07003699 }
3700
Eric Laurent6d517662012-04-23 18:42:39 -07003701 private int getActiveStreamType(int suggestedStreamType) {
Muyuan Li1ed6df62016-06-18 11:16:52 -07003702 if (mIsSingleVolume
3703 && suggestedStreamType == AudioManager.USE_DEFAULT_STREAM_TYPE) {
3704 return AudioSystem.STREAM_MUSIC;
3705 }
3706
Eric Laurent212532b2014-07-21 15:43:18 -07003707 switch (mPlatformType) {
John Spurlock61560172015-02-06 19:46:04 -05003708 case AudioSystem.PLATFORM_VOICE:
Eric Laurent6d517662012-04-23 18:42:39 -07003709 if (isInCommunication()) {
Eric Laurent25101b02011-02-02 09:33:30 -08003710 if (AudioSystem.getForceUse(AudioSystem.FOR_COMMUNICATION)
3711 == AudioSystem.FORCE_BT_SCO) {
3712 // Log.v(TAG, "getActiveStreamType: Forcing STREAM_BLUETOOTH_SCO...");
3713 return AudioSystem.STREAM_BLUETOOTH_SCO;
3714 } else {
3715 // Log.v(TAG, "getActiveStreamType: Forcing STREAM_VOICE_CALL...");
3716 return AudioSystem.STREAM_VOICE_CALL;
3717 }
Eric Laurent25101b02011-02-02 09:33:30 -08003718 } else if (suggestedStreamType == AudioManager.USE_DEFAULT_STREAM_TYPE) {
Julia Reynoldsd9e96e22017-11-07 10:33:08 -05003719 if (wasStreamActiveRecently(AudioSystem.STREAM_RING, sStreamOverrideDelayMs)) {
Jean-Michel Trivi3114ce32012-06-11 15:03:52 -07003720 if (DEBUG_VOL)
Julia Reynoldsd9e96e22017-11-07 10:33:08 -05003721 Log.v(TAG, "getActiveStreamType: Forcing STREAM_RING stream active");
3722 return AudioSystem.STREAM_RING;
3723 } else if (wasStreamActiveRecently(
3724 AudioSystem.STREAM_NOTIFICATION, sStreamOverrideDelayMs)) {
3725 if (DEBUG_VOL)
3726 Log.v(TAG, "getActiveStreamType: Forcing STREAM_NOTIFICATION stream active");
3727 return AudioSystem.STREAM_NOTIFICATION;
3728 } else {
Julia Reynoldseb0ce472018-05-04 15:34:55 -04003729 if (DEBUG_VOL) {
3730 Log.v(TAG, "getActiveStreamType: Forcing DEFAULT_VOL_STREAM_NO_PLAYBACK("
3731 + DEFAULT_VOL_STREAM_NO_PLAYBACK + ") b/c default");
3732 }
3733 return DEFAULT_VOL_STREAM_NO_PLAYBACK;
Jean-Michel Trivi3114ce32012-06-11 15:03:52 -07003734 }
Julia Reynoldsd9e96e22017-11-07 10:33:08 -05003735 } else if (
3736 wasStreamActiveRecently(AudioSystem.STREAM_NOTIFICATION, sStreamOverrideDelayMs)) {
Jean-Michel Trivi3114ce32012-06-11 15:03:52 -07003737 if (DEBUG_VOL)
Julia Reynoldsd9e96e22017-11-07 10:33:08 -05003738 Log.v(TAG, "getActiveStreamType: Forcing STREAM_NOTIFICATION stream active");
3739 return AudioSystem.STREAM_NOTIFICATION;
3740 } else if (wasStreamActiveRecently(AudioSystem.STREAM_RING, sStreamOverrideDelayMs)) {
3741 if (DEBUG_VOL)
3742 Log.v(TAG, "getActiveStreamType: Forcing STREAM_RING stream active");
3743 return AudioSystem.STREAM_RING;
Eric Laurent25101b02011-02-02 09:33:30 -08003744 }
Eric Laurent212532b2014-07-21 15:43:18 -07003745 default:
Eric Laurent6d517662012-04-23 18:42:39 -07003746 if (isInCommunication()) {
Eric Laurent25101b02011-02-02 09:33:30 -08003747 if (AudioSystem.getForceUse(AudioSystem.FOR_COMMUNICATION)
3748 == AudioSystem.FORCE_BT_SCO) {
Jean-Michel Trivi3114ce32012-06-11 15:03:52 -07003749 if (DEBUG_VOL) Log.v(TAG, "getActiveStreamType: Forcing STREAM_BLUETOOTH_SCO");
Eric Laurent25101b02011-02-02 09:33:30 -08003750 return AudioSystem.STREAM_BLUETOOTH_SCO;
3751 } else {
Jean-Michel Trivi3114ce32012-06-11 15:03:52 -07003752 if (DEBUG_VOL) Log.v(TAG, "getActiveStreamType: Forcing STREAM_VOICE_CALL");
Eric Laurent25101b02011-02-02 09:33:30 -08003753 return AudioSystem.STREAM_VOICE_CALL;
3754 }
Julia Reynoldsd9e96e22017-11-07 10:33:08 -05003755 } else if (AudioSystem.isStreamActive(
3756 AudioSystem.STREAM_NOTIFICATION, sStreamOverrideDelayMs)) {
Jean-Michel Trivi3114ce32012-06-11 15:03:52 -07003757 if (DEBUG_VOL) Log.v(TAG, "getActiveStreamType: Forcing STREAM_NOTIFICATION");
Eric Laurent25101b02011-02-02 09:33:30 -08003758 return AudioSystem.STREAM_NOTIFICATION;
Julia Reynoldsd9e96e22017-11-07 10:33:08 -05003759 } else if (AudioSystem.isStreamActive(
3760 AudioSystem.STREAM_RING, sStreamOverrideDelayMs)) {
3761 if (DEBUG_VOL) Log.v(TAG, "getActiveStreamType: Forcing STREAM_RING");
3762 return AudioSystem.STREAM_RING;
Jean-Michel Trivi3114ce32012-06-11 15:03:52 -07003763 } else if (suggestedStreamType == AudioManager.USE_DEFAULT_STREAM_TYPE) {
Julia Reynoldsd9e96e22017-11-07 10:33:08 -05003764 if (AudioSystem.isStreamActive(
3765 AudioSystem.STREAM_NOTIFICATION, sStreamOverrideDelayMs)) {
3766 if (DEBUG_VOL) Log.v(TAG, "getActiveStreamType: Forcing STREAM_NOTIFICATION");
John Spurlockeb1d88d2014-07-19 14:49:19 -04003767 return AudioSystem.STREAM_NOTIFICATION;
Julia Reynoldsd9e96e22017-11-07 10:33:08 -05003768 } else if (AudioSystem.isStreamActive(
3769 AudioSystem.STREAM_RING, sStreamOverrideDelayMs)) {
3770 if (DEBUG_VOL) Log.v(TAG, "getActiveStreamType: Forcing STREAM_RING");
3771 return AudioSystem.STREAM_RING;
3772 } else {
Julia Reynoldseb0ce472018-05-04 15:34:55 -04003773 if (DEBUG_VOL) {
3774 Log.v(TAG, "getActiveStreamType: Forcing DEFAULT_VOL_STREAM_NO_PLAYBACK("
3775 + DEFAULT_VOL_STREAM_NO_PLAYBACK + ") b/c default");
3776 }
3777 return DEFAULT_VOL_STREAM_NO_PLAYBACK;
Jean-Michel Trivi3114ce32012-06-11 15:03:52 -07003778 }
Joe Onoratoc7fcba42011-01-05 16:53:11 -08003779 }
Eric Laurent212532b2014-07-21 15:43:18 -07003780 break;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003781 }
Eric Laurent212532b2014-07-21 15:43:18 -07003782 if (DEBUG_VOL) Log.v(TAG, "getActiveStreamType: Returning suggested type "
3783 + suggestedStreamType);
3784 return suggestedStreamType;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003785 }
3786
John Spurlockbcc10872014-11-28 15:29:21 -05003787 private void broadcastRingerMode(String action, int ringerMode) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003788 // Send sticky broadcast
John Spurlockbcc10872014-11-28 15:29:21 -05003789 Intent broadcast = new Intent(action);
Glenn Kastenba195eb2011-12-13 09:30:40 -08003790 broadcast.putExtra(AudioManager.EXTRA_RINGER_MODE, ringerMode);
Dianne Hackborn1c633fc2009-12-08 19:45:14 -08003791 broadcast.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT
3792 | Intent.FLAG_RECEIVER_REPLACE_PENDING);
Dianne Hackborn5ac72a22012-08-29 18:32:08 -07003793 sendStickyBroadcastToAll(broadcast);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003794 }
3795
3796 private void broadcastVibrateSetting(int vibrateType) {
3797 // Send broadcast
Sudheer Shankafc46e9b2016-10-21 17:55:27 -07003798 if (mActivityManagerInternal.isSystemReady()) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003799 Intent broadcast = new Intent(AudioManager.VIBRATE_SETTING_CHANGED_ACTION);
3800 broadcast.putExtra(AudioManager.EXTRA_VIBRATE_TYPE, vibrateType);
3801 broadcast.putExtra(AudioManager.EXTRA_VIBRATE_SETTING, getVibrateSetting(vibrateType));
Dianne Hackborn5ac72a22012-08-29 18:32:08 -07003802 sendBroadcastToAll(broadcast);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003803 }
3804 }
3805
3806 // Message helper methods
Jean-Michel Trivi2d8dab52012-05-30 18:13:59 -07003807 /**
3808 * Queue a message on the given handler's message queue, after acquiring the service wake lock.
3809 * Note that the wake lock needs to be released after the message has been handled.
3810 */
3811 private void queueMsgUnderWakeLock(Handler handler, int msg,
3812 int arg1, int arg2, Object obj, int delay) {
Eric Laurenta4dfbdc52013-10-01 11:53:51 -07003813 final long ident = Binder.clearCallingIdentity();
3814 // Always acquire the wake lock as AudioService because it is released by the
3815 // message handler.
Jean-Michel Trivifa9a6982013-06-27 16:22:58 -07003816 mAudioEventWakeLock.acquire();
Eric Laurenta4dfbdc52013-10-01 11:53:51 -07003817 Binder.restoreCallingIdentity(ident);
Jean-Michel Trivi2d8dab52012-05-30 18:13:59 -07003818 sendMsg(handler, msg, SENDMSG_QUEUE, arg1, arg2, obj, delay);
3819 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003820
Eric Laurentafbb0472011-12-15 09:04:23 -08003821 private static void sendMsg(Handler handler, int msg,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003822 int existingMsgPolicy, int arg1, int arg2, Object obj, int delay) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003823 if (existingMsgPolicy == SENDMSG_REPLACE) {
3824 handler.removeMessages(msg);
3825 } else if (existingMsgPolicy == SENDMSG_NOOP && handler.hasMessages(msg)) {
3826 return;
3827 }
Eric Laurent3c4636c2018-06-13 19:36:42 -07003828
Jean-Michel Trivi58850372018-09-14 16:01:28 -07003829 final long time = SystemClock.uptimeMillis() + delay;
3830 handler.sendMessageAtTime(handler.obtainMessage(msg, arg1, arg2, obj), time);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003831 }
3832
3833 boolean checkAudioSettingsPermission(String method) {
Jean-Michel Triviccd654e2014-09-03 17:48:47 -07003834 if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.MODIFY_AUDIO_SETTINGS)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003835 == PackageManager.PERMISSION_GRANTED) {
3836 return true;
3837 }
3838 String msg = "Audio Settings Permission Denial: " + method + " from pid="
3839 + Binder.getCallingPid()
3840 + ", uid=" + Binder.getCallingUid();
3841 Log.w(TAG, msg);
3842 return false;
3843 }
3844
Jean-Michel Trivi58850372018-09-14 16:01:28 -07003845 /*package*/ int getDeviceForStream(int stream) {
John Spurlock8a52c442015-03-26 14:23:58 -04003846 int device = getDevicesForStream(stream);
Eric Laurent9bc8358d2011-11-18 16:43:31 -08003847 if ((device & (device - 1)) != 0) {
3848 // Multiple device selection is either:
3849 // - speaker + one other device: give priority to speaker in this case.
3850 // - one A2DP device + another device: happens with duplicated output. In this case
3851 // retain the device on the A2DP output as the other must not correspond to an active
3852 // selection if not the speaker.
Jungshik Jangc9ff9682014-09-15 17:41:06 +09003853 // - HDMI-CEC system audio mode only output: give priority to available item in order.
Eric Laurent9bc8358d2011-11-18 16:43:31 -08003854 if ((device & AudioSystem.DEVICE_OUT_SPEAKER) != 0) {
3855 device = AudioSystem.DEVICE_OUT_SPEAKER;
Jungshik Jangc9ff9682014-09-15 17:41:06 +09003856 } else if ((device & AudioSystem.DEVICE_OUT_HDMI_ARC) != 0) {
3857 device = AudioSystem.DEVICE_OUT_HDMI_ARC;
3858 } else if ((device & AudioSystem.DEVICE_OUT_SPDIF) != 0) {
3859 device = AudioSystem.DEVICE_OUT_SPDIF;
3860 } else if ((device & AudioSystem.DEVICE_OUT_AUX_LINE) != 0) {
3861 device = AudioSystem.DEVICE_OUT_AUX_LINE;
Eric Laurent9bc8358d2011-11-18 16:43:31 -08003862 } else {
3863 device &= AudioSystem.DEVICE_OUT_ALL_A2DP;
3864 }
3865 }
3866 return device;
3867 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003868
John Spurlock8a52c442015-03-26 14:23:58 -04003869 private int getDevicesForStream(int stream) {
3870 return getDevicesForStream(stream, true /*checkOthers*/);
3871 }
3872
3873 private int getDevicesForStream(int stream, boolean checkOthers) {
3874 ensureValidStreamType(stream);
3875 synchronized (VolumeStreamState.class) {
3876 return mStreamStates[stream].observeDevicesForStream_syncVSS(checkOthers);
3877 }
3878 }
3879
3880 private void observeDevicesForStreams(int skipStream) {
3881 synchronized (VolumeStreamState.class) {
3882 for (int stream = 0; stream < mStreamStates.length; stream++) {
3883 if (stream != skipStream) {
3884 mStreamStates[stream].observeDevicesForStream_syncVSS(false /*checkOthers*/);
3885 }
3886 }
3887 }
3888 }
3889
Jean-Michel Trivi58850372018-09-14 16:01:28 -07003890
3891 /*package*/ void observeDevicesForAllStreams() {
3892 observeDevicesForStreams(-1);
Aniket Kumar Lata9fbc2052019-01-11 02:02:33 -08003893 }
3894
Jean-Michel Trivi58850372018-09-14 16:01:28 -07003895 /*package*/ static final int CONNECTION_STATE_DISCONNECTED = 0;
3896 /*package*/ static final int CONNECTION_STATE_CONNECTED = 1;
3897 /**
3898 * The states that can be used with AudioService.setWiredDeviceConnectionState()
3899 * Attention: those values differ from those in BluetoothProfile, follow annotations to
3900 * distinguish between @ConnectionState and @BtProfileConnectionState
Paul McLean10804eb2015-01-28 11:16:35 -08003901 */
Jean-Michel Trivi58850372018-09-14 16:01:28 -07003902 @IntDef({
3903 CONNECTION_STATE_DISCONNECTED,
3904 CONNECTION_STATE_CONNECTED,
3905 })
3906 @Retention(RetentionPolicy.SOURCE)
3907 public @interface ConnectionState {}
Paul McLean10804eb2015-01-28 11:16:35 -08003908
Jean-Michel Trivi58850372018-09-14 16:01:28 -07003909 /**
3910 * see AudioManager.setWiredDeviceConnectionState()
3911 */
3912 public void setWiredDeviceConnectionState(int type,
3913 @ConnectionState int state, String address, String name,
John Spurlock90874332015-03-10 16:00:54 -04003914 String caller) {
Jean-Michel Trivi58850372018-09-14 16:01:28 -07003915 if (state != CONNECTION_STATE_CONNECTED
3916 && state != CONNECTION_STATE_DISCONNECTED) {
3917 throw new IllegalArgumentException("Invalid state " + state);
Eric Laurentb1fbaac2012-05-29 09:24:28 -07003918 }
Jean-Michel Trivi58850372018-09-14 16:01:28 -07003919 mDeviceBroker.setWiredDeviceConnectionState(type, state, address, name, caller);
Eric Laurentb1fbaac2012-05-29 09:24:28 -07003920 }
3921
Jean-Michel Trivi58850372018-09-14 16:01:28 -07003922 /**
3923 * @hide
3924 * The states that can be used with AudioService.setBluetoothHearingAidDeviceConnectionState()
3925 * and AudioService.setBluetoothA2dpDeviceConnectionStateSuppressNoisyIntent()
3926 */
3927 @IntDef({
3928 BluetoothProfile.STATE_DISCONNECTED,
3929 BluetoothProfile.STATE_CONNECTED,
3930 })
3931 @Retention(RetentionPolicy.SOURCE)
3932 public @interface BtProfileConnectionState {}
3933
Jakub Pawlowskif9570f32018-02-21 17:15:12 -08003934 public int setBluetoothHearingAidDeviceConnectionState(
Jean-Michel Trivi58850372018-09-14 16:01:28 -07003935 @NonNull BluetoothDevice device, @BtProfileConnectionState int state,
3936 boolean suppressNoisyIntent, int musicDevice)
Jakub Pawlowskif9570f32018-02-21 17:15:12 -08003937 {
Jean-Michel Trivi58850372018-09-14 16:01:28 -07003938 if (device == null) {
3939 throw new IllegalArgumentException("Illegal null device");
Jakub Pawlowskif9570f32018-02-21 17:15:12 -08003940 }
Jean-Michel Trivi58850372018-09-14 16:01:28 -07003941 if (state != BluetoothProfile.STATE_CONNECTED
3942 && state != BluetoothProfile.STATE_DISCONNECTED) {
3943 throw new IllegalArgumentException("Illegal BluetoothProfile state for device "
3944 + " (dis)connection, got " + state);
3945 }
3946 return mDeviceBroker.setBluetoothHearingAidDeviceConnectionState(
3947 device, state, suppressNoisyIntent, musicDevice, "AudioService");
Jakub Pawlowski10c90612018-02-21 13:28:46 -08003948 }
3949
Jean-Michel Trivi58850372018-09-14 16:01:28 -07003950 /**
3951 * See AudioManager.setBluetoothA2dpDeviceConnectionStateSuppressNoisyIntent()
3952 */
3953 public int setBluetoothA2dpDeviceConnectionStateSuppressNoisyIntent(
3954 @NonNull BluetoothDevice device, @AudioService.BtProfileConnectionState int state,
3955 int profile, boolean suppressNoisyIntent, int a2dpVolume) {
3956 if (device == null) {
3957 throw new IllegalArgumentException("Illegal null device");
3958 }
3959 if (state != BluetoothProfile.STATE_CONNECTED
3960 && state != BluetoothProfile.STATE_DISCONNECTED) {
3961 throw new IllegalArgumentException("Illegal BluetoothProfile state for device "
3962 + " (dis)connection, got " + state);
3963 }
3964 return mDeviceBroker.setBluetoothA2dpDeviceConnectionStateSuppressNoisyIntent(device, state,
3965 profile, suppressNoisyIntent, a2dpVolume);
Pavlin Radoslavov82e06462018-01-19 18:20:04 -08003966 }
3967
Jean-Michel Trivi58850372018-09-14 16:01:28 -07003968 /**
3969 * See AudioManager.handleBluetoothA2dpDeviceConfigChange()
3970 * @param device
3971 */
Pavlin Radoslavov44a4ef02016-12-21 12:05:51 -08003972 public void handleBluetoothA2dpDeviceConfigChange(BluetoothDevice device)
3973 {
Jean-Michel Trivi58850372018-09-14 16:01:28 -07003974 if (device == null) {
3975 throw new IllegalArgumentException("Illegal null device");
Pavlin Radoslavov44a4ef02016-12-21 12:05:51 -08003976 }
Jean-Michel Trivi58850372018-09-14 16:01:28 -07003977 mDeviceBroker.postBluetoothA2dpDeviceConfigChange(device);
Pavlin Radoslavov44a4ef02016-12-21 12:05:51 -08003978 }
3979
Aniket Kumar Lataa8439e22019-01-11 03:59:00 -08003980 /**
3981 * @see AudioManager#handleBluetoothA2dpActiveDeviceChange(BluetoothDevice, int, int,
3982 * boolean, int)
3983 */
3984 public int handleBluetoothA2dpActiveDeviceChange(
3985 BluetoothDevice device, int state, int profile, boolean suppressNoisyIntent,
3986 int a2dpVolume) {
Jean-Michel Trivi58850372018-09-14 16:01:28 -07003987 if (device == null) {
3988 throw new IllegalArgumentException("Illegal null device");
3989 }
Aniket Kumar Lataa8439e22019-01-11 03:59:00 -08003990 if (profile != BluetoothProfile.A2DP && profile != BluetoothProfile.A2DP_SINK) {
3991 throw new IllegalArgumentException("invalid profile " + profile);
3992 }
Jean-Michel Trivi58850372018-09-14 16:01:28 -07003993 if (state != BluetoothProfile.STATE_CONNECTED
3994 && state != BluetoothProfile.STATE_DISCONNECTED) {
3995 throw new IllegalArgumentException("Invalid state " + state);
Aniket Kumar Lataa8439e22019-01-11 03:59:00 -08003996 }
Jean-Michel Trivi58850372018-09-14 16:01:28 -07003997 return mDeviceBroker.handleBluetoothA2dpActiveDeviceChange(device, state, profile,
3998 suppressNoisyIntent, a2dpVolume);
Aniket Kumar Lataa8439e22019-01-11 03:59:00 -08003999 }
4000
Jean-Michel Trivi1ab43f62017-04-27 15:37:34 -07004001 private static final int DEVICE_MEDIA_UNMUTED_ON_PLUG =
4002 AudioSystem.DEVICE_OUT_WIRED_HEADSET | AudioSystem.DEVICE_OUT_WIRED_HEADPHONE |
4003 AudioSystem.DEVICE_OUT_LINE |
4004 AudioSystem.DEVICE_OUT_ALL_A2DP |
4005 AudioSystem.DEVICE_OUT_ALL_USB |
4006 AudioSystem.DEVICE_OUT_HDMI;
4007
Jean-Michel Trivi58850372018-09-14 16:01:28 -07004008 /*package*/ void postAccessoryPlugMediaUnmute(int newDevice) {
4009 sendMsg(mAudioHandler, MSG_ACCESSORY_PLUG_MEDIA_UNMUTE, SENDMSG_QUEUE,
4010 newDevice, 0, null, 0);
4011 }
4012
Jean-Michel Trivi1ab43f62017-04-27 15:37:34 -07004013 private void onAccessoryPlugMediaUnmute(int newDevice) {
4014 if (DEBUG_VOL) {
4015 Log.i(TAG, String.format("onAccessoryPlugMediaUnmute newDevice=%d [%s]",
4016 newDevice, AudioSystem.getOutputDeviceName(newDevice)));
4017 }
Jean-Michel Trivi58850372018-09-14 16:01:28 -07004018
4019 if (mNm.getZenMode() != Settings.Global.ZEN_MODE_NO_INTERRUPTIONS
4020 && (newDevice & DEVICE_MEDIA_UNMUTED_ON_PLUG) != 0
4021 && mStreamStates[AudioSystem.STREAM_MUSIC].mIsMuted
4022 && mStreamStates[AudioSystem.STREAM_MUSIC].getIndex(newDevice) != 0
4023 && (newDevice & AudioSystem.getDevicesForStream(AudioSystem.STREAM_MUSIC)) != 0) {
4024 if (DEBUG_VOL) {
4025 Log.i(TAG, String.format(" onAccessoryPlugMediaUnmute unmuting device=%d [%s]",
4026 newDevice, AudioSystem.getOutputDeviceName(newDevice)));
Jean-Michel Trivi1ab43f62017-04-27 15:37:34 -07004027 }
Jean-Michel Trivi58850372018-09-14 16:01:28 -07004028 mStreamStates[AudioSystem.STREAM_MUSIC].mute(false);
Jean-Michel Trivi1ab43f62017-04-27 15:37:34 -07004029 }
4030 }
4031
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004032 ///////////////////////////////////////////////////////////////////////////
4033 // Inner classes
4034 ///////////////////////////////////////////////////////////////////////////
4035
Eric Laurent8fa4d6f2014-10-30 14:13:03 -07004036 // NOTE: Locking order for synchronized objects related to volume or ringer mode management:
4037 // 1 mScoclient OR mSafeMediaVolumeState
Jean-Michel Trivi58850372018-09-14 16:01:28 -07004038 // 2 mSetModeLock
Eric Laurent8fa4d6f2014-10-30 14:13:03 -07004039 // 3 mSettingsLock
4040 // 4 VolumeStreamState.class
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004041 public class VolumeStreamState {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004042 private final int mStreamType;
Jean-Michel Trivie05eef82018-03-08 18:56:34 -08004043 private int mIndexMin;
4044 private int mIndexMax;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004045
RoboErik4197cb62015-01-21 15:45:32 -08004046 private boolean mIsMuted;
Jean-Michel Trivi11a74a72009-10-27 17:39:30 -07004047 private String mVolumeIndexSettingName;
John Spurlock8a52c442015-03-26 14:23:58 -04004048 private int mObservedDevices;
John Spurlockb6e19e32015-03-10 21:33:44 -04004049
John Spurlock2bb02ec2015-03-02 13:13:06 -05004050 private final SparseIntArray mIndexMap = new SparseIntArray(8);
John Spurlockf63860c2015-02-19 09:46:27 -05004051 private final Intent mVolumeChanged;
John Spurlock8a52c442015-03-26 14:23:58 -04004052 private final Intent mStreamDevicesChanged;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004053
Eric Laurenta553c252009-07-17 12:17:14 -07004054 private VolumeStreamState(String settingName, int streamType) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004055
Eric Laurent9bc8358d2011-11-18 16:43:31 -08004056 mVolumeIndexSettingName = settingName;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004057
4058 mStreamType = streamType;
John Spurlockb6e19e32015-03-10 21:33:44 -04004059 mIndexMin = MIN_STREAM_VOLUME[streamType] * 10;
4060 mIndexMax = MAX_STREAM_VOLUME[streamType] * 10;
4061 AudioSystem.initStreamVolume(streamType, mIndexMin / 10, mIndexMax / 10);
Eric Laurent9bc8358d2011-11-18 16:43:31 -08004062
Eric Laurent33902db2012-10-07 16:15:07 -07004063 readSettings();
John Spurlockf63860c2015-02-19 09:46:27 -05004064 mVolumeChanged = new Intent(AudioManager.VOLUME_CHANGED_ACTION);
4065 mVolumeChanged.putExtra(AudioManager.EXTRA_VOLUME_STREAM_TYPE, mStreamType);
John Spurlock8a52c442015-03-26 14:23:58 -04004066 mStreamDevicesChanged = new Intent(AudioManager.STREAM_DEVICES_CHANGED_ACTION);
4067 mStreamDevicesChanged.putExtra(AudioManager.EXTRA_VOLUME_STREAM_TYPE, mStreamType);
4068 }
4069
4070 public int observeDevicesForStream_syncVSS(boolean checkOthers) {
4071 final int devices = AudioSystem.getDevicesForStream(mStreamType);
4072 if (devices == mObservedDevices) {
4073 return devices;
4074 }
4075 final int prevDevices = mObservedDevices;
4076 mObservedDevices = devices;
4077 if (checkOthers) {
4078 // one stream's devices have changed, check the others
4079 observeDevicesForStreams(mStreamType);
4080 }
4081 // log base stream changes to the event log
4082 if (mStreamVolumeAlias[mStreamType] == mStreamType) {
4083 EventLogTags.writeStreamDevicesChanged(mStreamType, prevDevices, devices);
4084 }
4085 sendBroadcastToAll(mStreamDevicesChanged
4086 .putExtra(AudioManager.EXTRA_PREV_VOLUME_STREAM_DEVICES, prevDevices)
4087 .putExtra(AudioManager.EXTRA_VOLUME_STREAM_DEVICES, devices));
4088 return devices;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004089 }
4090
Jean-Michel Trivia53b7052017-04-12 18:27:01 -07004091 public @Nullable String getSettingNameForDevice(int device) {
4092 if (!hasValidSettingsName()) {
4093 return null;
Eric Laurent9bc8358d2011-11-18 16:43:31 -08004094 }
Jean-Michel Trivia53b7052017-04-12 18:27:01 -07004095 final String suffix = AudioSystem.getOutputDeviceName(device);
4096 if (suffix.isEmpty()) {
4097 return mVolumeIndexSettingName;
4098 }
4099 return mVolumeIndexSettingName + "_" + suffix;
4100 }
4101
4102 private boolean hasValidSettingsName() {
4103 return (mVolumeIndexSettingName != null && !mVolumeIndexSettingName.isEmpty());
Jean-Michel Trivi11a74a72009-10-27 17:39:30 -07004104 }
4105
Eric Laurentfdbee862014-05-12 15:26:12 -07004106 public void readSettings() {
Jean-Michel Trivi8719a1d2017-11-06 11:52:51 -08004107 synchronized (mSettingsLock) {
4108 synchronized (VolumeStreamState.class) {
4109 // force maximum volume on all streams if fixed volume property is set
4110 if (mUseFixedVolume) {
4111 mIndexMap.put(AudioSystem.DEVICE_OUT_DEFAULT, mIndexMax);
4112 return;
4113 }
4114 // do not read system stream volume from settings: this stream is always aliased
4115 // to another stream type and its volume is never persisted. Values in settings can
4116 // only be stale values
4117 if ((mStreamType == AudioSystem.STREAM_SYSTEM) ||
4118 (mStreamType == AudioSystem.STREAM_SYSTEM_ENFORCED)) {
4119 int index = 10 * AudioSystem.DEFAULT_STREAM_VOLUME[mStreamType];
Eric Laurentfdbee862014-05-12 15:26:12 -07004120 if (mCameraSoundForced) {
4121 index = mIndexMax;
4122 }
Jean-Michel Trivi8719a1d2017-11-06 11:52:51 -08004123 mIndexMap.put(AudioSystem.DEVICE_OUT_DEFAULT, index);
4124 return;
Eric Laurentdd45d012012-10-08 09:04:34 -07004125 }
Eric Laurent9bc8358d2011-11-18 16:43:31 -08004126 }
Jean-Michel Trivi8719a1d2017-11-06 11:52:51 -08004127 }
4128 synchronized (VolumeStreamState.class) {
Eric Laurentfdbee862014-05-12 15:26:12 -07004129 int remainingDevices = AudioSystem.DEVICE_OUT_ALL;
4130
4131 for (int i = 0; remainingDevices != 0; i++) {
4132 int device = (1 << i);
4133 if ((device & remainingDevices) == 0) {
4134 continue;
4135 }
4136 remainingDevices &= ~device;
4137
4138 // retrieve current volume for device
Eric Laurentfdbee862014-05-12 15:26:12 -07004139 // if no volume stored for current stream and device, use default volume if default
4140 // device, continue otherwise
4141 int defaultIndex = (device == AudioSystem.DEVICE_OUT_DEFAULT) ?
John Spurlock61560172015-02-06 19:46:04 -05004142 AudioSystem.DEFAULT_STREAM_VOLUME[mStreamType] : -1;
Jean-Michel Trivia53b7052017-04-12 18:27:01 -07004143 int index;
4144 if (!hasValidSettingsName()) {
4145 index = defaultIndex;
4146 } else {
4147 String name = getSettingNameForDevice(device);
4148 index = Settings.System.getIntForUser(
4149 mContentResolver, name, defaultIndex, UserHandle.USER_CURRENT);
4150 }
Eric Laurentfdbee862014-05-12 15:26:12 -07004151 if (index == -1) {
4152 continue;
4153 }
4154
John Spurlock2bb02ec2015-03-02 13:13:06 -05004155 mIndexMap.put(device, getValidIndex(10 * index));
Eric Laurentdd45d012012-10-08 09:04:34 -07004156 }
Eric Laurent9bc8358d2011-11-18 16:43:31 -08004157 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004158 }
4159
Liejun Tao39fb5672016-03-09 15:52:13 -06004160 private int getAbsoluteVolumeIndex(int index) {
4161 /* Special handling for Bluetooth Absolute Volume scenario
4162 * If we send full audio gain, some accessories are too loud even at its lowest
4163 * volume. We are not able to enumerate all such accessories, so here is the
4164 * workaround from phone side.
4165 * Pre-scale volume at lowest volume steps 1 2 and 3.
4166 * For volume step 0, set audio gain to 0 as some accessories won't mute on their end.
4167 */
4168 if (index == 0) {
4169 // 0% for volume 0
4170 index = 0;
Tomoharu Kasaharaf0fecb12018-09-06 20:04:38 +09004171 } else if (index > 0 && index <= 3) {
4172 // Pre-scale for volume steps 1 2 and 3
4173 index = (int) (mIndexMax * mPrescaleAbsoluteVolume[index - 1]) / 10;
Liejun Tao39fb5672016-03-09 15:52:13 -06004174 } else {
4175 // otherwise, full gain
Tomoharu Kasaharaf0fecb12018-09-06 20:04:38 +09004176 index = (mIndexMax + 5) / 10;
Liejun Tao39fb5672016-03-09 15:52:13 -06004177 }
4178 return index;
4179 }
4180
Eric Laurent8fa4d6f2014-10-30 14:13:03 -07004181 // must be called while synchronized VolumeStreamState.class
Jean-Michel Trivi58850372018-09-14 16:01:28 -07004182 /*package*/ void applyDeviceVolume_syncVSS(int device, boolean isAvrcpAbsVolSupported) {
Eric Laurent42b041e2013-03-29 11:36:03 -07004183 int index;
RoboErik4197cb62015-01-21 15:45:32 -08004184 if (mIsMuted) {
Eric Laurent42b041e2013-03-29 11:36:03 -07004185 index = 0;
Jean-Michel Trivi58850372018-09-14 16:01:28 -07004186 } else if ((device & AudioSystem.DEVICE_OUT_ALL_A2DP) != 0 && isAvrcpAbsVolSupported) {
Liejun Tao39fb5672016-03-09 15:52:13 -06004187 index = getAbsoluteVolumeIndex((getIndex(device) + 5)/10);
Liejun Tao4565a472016-01-20 17:52:20 -06004188 } else if ((device & mFullVolumeDevices) != 0) {
Matthew Xiec9d1d5f2013-09-12 00:32:22 -07004189 index = (mIndexMax + 5)/10;
Jakub Pawlowskic274fb22018-04-04 10:15:12 -07004190 } else if ((device & AudioSystem.DEVICE_OUT_HEARING_AID) != 0) {
4191 index = (mIndexMax + 5)/10;
Eric Laurentcd772d02013-10-30 18:31:07 -07004192 } else {
Eric Laurent42b041e2013-03-29 11:36:03 -07004193 index = (getIndex(device) + 5)/10;
4194 }
Jean-Michel Trivi58850372018-09-14 16:01:28 -07004195 AudioSystem.setStreamVolumeIndexAS(mStreamType, index, device);
Eric Laurent9bc8358d2011-11-18 16:43:31 -08004196 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004197
Eric Laurentfdbee862014-05-12 15:26:12 -07004198 public void applyAllVolumes() {
Jean-Michel Trivi58850372018-09-14 16:01:28 -07004199 final boolean isAvrcpAbsVolSupported = mDeviceBroker.isAvrcpAbsoluteVolumeSupported();
Eric Laurentfdbee862014-05-12 15:26:12 -07004200 synchronized (VolumeStreamState.class) {
Eric Laurentd9ac2be2016-04-07 14:04:23 -07004201 // apply device specific volumes first
Eric Laurentfdbee862014-05-12 15:26:12 -07004202 int index;
John Spurlock2bb02ec2015-03-02 13:13:06 -05004203 for (int i = 0; i < mIndexMap.size(); i++) {
Eric Laurentd9ac2be2016-04-07 14:04:23 -07004204 final int device = mIndexMap.keyAt(i);
Eric Laurentfdbee862014-05-12 15:26:12 -07004205 if (device != AudioSystem.DEVICE_OUT_DEFAULT) {
RoboErik4197cb62015-01-21 15:45:32 -08004206 if (mIsMuted) {
Eric Laurentfdbee862014-05-12 15:26:12 -07004207 index = 0;
Liejun Tao39fb5672016-03-09 15:52:13 -06004208 } else if ((device & AudioSystem.DEVICE_OUT_ALL_A2DP) != 0 &&
Jean-Michel Trivi58850372018-09-14 16:01:28 -07004209 isAvrcpAbsVolSupported) {
Liejun Tao39fb5672016-03-09 15:52:13 -06004210 index = getAbsoluteVolumeIndex((getIndex(device) + 5)/10);
4211 } else if ((device & mFullVolumeDevices) != 0) {
Eric Laurentfdbee862014-05-12 15:26:12 -07004212 index = (mIndexMax + 5)/10;
Jakub Pawlowskic274fb22018-04-04 10:15:12 -07004213 } else if ((device & AudioSystem.DEVICE_OUT_HEARING_AID) != 0) {
4214 index = (mIndexMax + 5)/10;
Eric Laurentfdbee862014-05-12 15:26:12 -07004215 } else {
John Spurlock2bb02ec2015-03-02 13:13:06 -05004216 index = (mIndexMap.valueAt(i) + 5)/10;
Eric Laurentfdbee862014-05-12 15:26:12 -07004217 }
Jean-Michel Trivi58850372018-09-14 16:01:28 -07004218 AudioSystem.setStreamVolumeIndexAS(mStreamType, index, device);
Eric Laurent42b041e2013-03-29 11:36:03 -07004219 }
Eric Laurent9bc8358d2011-11-18 16:43:31 -08004220 }
Eric Laurentd9ac2be2016-04-07 14:04:23 -07004221 // apply default volume last: by convention , default device volume will be used
4222 // by audio policy manager if no explicit volume is present for a given device type
4223 if (mIsMuted) {
4224 index = 0;
4225 } else {
4226 index = (getIndex(AudioSystem.DEVICE_OUT_DEFAULT) + 5)/10;
4227 }
Jean-Michel Trivi58850372018-09-14 16:01:28 -07004228 AudioSystem.setStreamVolumeIndexAS(
Eric Laurentd9ac2be2016-04-07 14:04:23 -07004229 mStreamType, index, AudioSystem.DEVICE_OUT_DEFAULT);
Eric Laurent9bc8358d2011-11-18 16:43:31 -08004230 }
4231 }
4232
John Spurlock90874332015-03-10 16:00:54 -04004233 public boolean adjustIndex(int deltaIndex, int device, String caller) {
4234 return setIndex(getIndex(device) + deltaIndex, device, caller);
Eric Laurent9bc8358d2011-11-18 16:43:31 -08004235 }
4236
John Spurlock90874332015-03-10 16:00:54 -04004237 public boolean setIndex(int index, int device, String caller) {
Jack He6dd78c12018-02-12 21:00:24 -08004238 boolean changed;
John Spurlockf63860c2015-02-19 09:46:27 -05004239 int oldIndex;
Jean-Michel Trivi8719a1d2017-11-06 11:52:51 -08004240 synchronized (mSettingsLock) {
4241 synchronized (VolumeStreamState.class) {
4242 oldIndex = getIndex(device);
4243 index = getValidIndex(index);
Eric Laurentfdbee862014-05-12 15:26:12 -07004244 if ((mStreamType == AudioSystem.STREAM_SYSTEM_ENFORCED) && mCameraSoundForced) {
4245 index = mIndexMax;
Eric Laurenta553c252009-07-17 12:17:14 -07004246 }
Jean-Michel Trivi8719a1d2017-11-06 11:52:51 -08004247 mIndexMap.put(device, index);
Eric Laurentfdbee862014-05-12 15:26:12 -07004248
Jean-Michel Trivi8719a1d2017-11-06 11:52:51 -08004249 changed = oldIndex != index;
4250 // Apply change to all streams using this one as alias if:
4251 // - the index actually changed OR
4252 // - there is no volume index stored for this device on alias stream.
4253 // If changing volume of current device, also change volume of current
4254 // device on aliased stream
Jack He6dd78c12018-02-12 21:00:24 -08004255 final boolean isCurrentDevice = (device == getDeviceForStream(mStreamType));
Jean-Michel Trivi8719a1d2017-11-06 11:52:51 -08004256 final int numStreamTypes = AudioSystem.getNumStreamTypes();
4257 for (int streamType = numStreamTypes - 1; streamType >= 0; streamType--) {
4258 final VolumeStreamState aliasStreamState = mStreamStates[streamType];
4259 if (streamType != mStreamType &&
4260 mStreamVolumeAlias[streamType] == mStreamType &&
4261 (changed || !aliasStreamState.hasIndexForDevice(device))) {
4262 final int scaledIndex = rescaleIndex(index, mStreamType, streamType);
4263 aliasStreamState.setIndex(scaledIndex, device, caller);
Jack He6dd78c12018-02-12 21:00:24 -08004264 if (isCurrentDevice) {
Jean-Michel Trivi8719a1d2017-11-06 11:52:51 -08004265 aliasStreamState.setIndex(scaledIndex,
4266 getDeviceForStream(streamType), caller);
4267 }
Eric Laurentfdbee862014-05-12 15:26:12 -07004268 }
4269 }
Jack He6dd78c12018-02-12 21:00:24 -08004270 // Mirror changes in SPEAKER ringtone volume on SCO when
4271 if (changed && mStreamType == AudioSystem.STREAM_RING
4272 && device == AudioSystem.DEVICE_OUT_SPEAKER) {
4273 for (int i = 0; i < mIndexMap.size(); i++) {
4274 int otherDevice = mIndexMap.keyAt(i);
4275 if ((otherDevice & AudioSystem.DEVICE_OUT_ALL_SCO) != 0) {
4276 mIndexMap.put(otherDevice, index);
4277 }
4278 }
4279 }
Eric Laurentfdbee862014-05-12 15:26:12 -07004280 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004281 }
John Spurlockf63860c2015-02-19 09:46:27 -05004282 if (changed) {
4283 oldIndex = (oldIndex + 5) / 10;
4284 index = (index + 5) / 10;
John Spurlock90874332015-03-10 16:00:54 -04004285 // log base stream changes to the event log
4286 if (mStreamVolumeAlias[mStreamType] == mStreamType) {
4287 if (caller == null) {
4288 Log.w(TAG, "No caller for volume_changed event", new Throwable());
4289 }
4290 EventLogTags.writeVolumeChanged(mStreamType, oldIndex, index, mIndexMax / 10,
4291 caller);
4292 }
4293 // fire changed intents for all streams
John Spurlockf63860c2015-02-19 09:46:27 -05004294 mVolumeChanged.putExtra(AudioManager.EXTRA_VOLUME_STREAM_VALUE, index);
4295 mVolumeChanged.putExtra(AudioManager.EXTRA_PREV_VOLUME_STREAM_VALUE, oldIndex);
Jean-Michel Trivi560877d2015-06-25 17:38:35 -07004296 mVolumeChanged.putExtra(AudioManager.EXTRA_VOLUME_STREAM_TYPE_ALIAS,
4297 mStreamVolumeAlias[mStreamType]);
John Spurlockf63860c2015-02-19 09:46:27 -05004298 sendBroadcastToAll(mVolumeChanged);
4299 }
4300 return changed;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004301 }
4302
Eric Laurentfdbee862014-05-12 15:26:12 -07004303 public int getIndex(int device) {
4304 synchronized (VolumeStreamState.class) {
John Spurlock2bb02ec2015-03-02 13:13:06 -05004305 int index = mIndexMap.get(device, -1);
4306 if (index == -1) {
Eric Laurentfdbee862014-05-12 15:26:12 -07004307 // there is always an entry for AudioSystem.DEVICE_OUT_DEFAULT
John Spurlock2bb02ec2015-03-02 13:13:06 -05004308 index = mIndexMap.get(AudioSystem.DEVICE_OUT_DEFAULT);
Eric Laurentfdbee862014-05-12 15:26:12 -07004309 }
John Spurlock2bb02ec2015-03-02 13:13:06 -05004310 return index;
Eric Laurent9bc8358d2011-11-18 16:43:31 -08004311 }
Eric Laurent5b4e6542010-03-19 20:02:21 -07004312 }
4313
Eric Laurent3fb608e2016-11-03 16:27:40 -07004314 public boolean hasIndexForDevice(int device) {
4315 synchronized (VolumeStreamState.class) {
4316 return (mIndexMap.get(device, -1) != -1);
4317 }
4318 }
4319
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004320 public int getMaxIndex() {
Eric Laurenta553c252009-07-17 12:17:14 -07004321 return mIndexMax;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004322 }
4323
John Spurlockb6e19e32015-03-10 21:33:44 -04004324 public int getMinIndex() {
4325 return mIndexMin;
4326 }
4327
Jean-Michel Trivi170a0ee2017-04-14 18:13:26 -07004328 /**
Jean-Michel Trivie05eef82018-03-08 18:56:34 -08004329 * Updates the min/max index values from another stream. Use this when changing the alias
4330 * for the current stream type.
4331 * @param sourceStreamType
4332 */
4333 // must be sync'd on mSettingsLock before VolumeStreamState.class
4334 @GuardedBy("VolumeStreamState.class")
4335 public void refreshRange(int sourceStreamType) {
4336 mIndexMin = MIN_STREAM_VOLUME[sourceStreamType] * 10;
4337 mIndexMax = MAX_STREAM_VOLUME[sourceStreamType] * 10;
4338 // verify all current volumes are within bounds
4339 for (int i = 0 ; i < mIndexMap.size(); i++) {
4340 final int device = mIndexMap.keyAt(i);
4341 final int index = mIndexMap.valueAt(i);
4342 mIndexMap.put(device, getValidIndex(index));
4343 }
4344 }
4345
4346 /**
Jean-Michel Trivi170a0ee2017-04-14 18:13:26 -07004347 * Copies all device/index pairs from the given VolumeStreamState after initializing
4348 * them with the volume for DEVICE_OUT_DEFAULT. No-op if the source VolumeStreamState
4349 * has the same stream type as this instance.
4350 * @param srcStream
4351 * @param caller
4352 */
Jean-Michel Trivi085346a2018-02-14 10:48:51 -08004353 // must be sync'd on mSettingsLock before VolumeStreamState.class
4354 @GuardedBy("VolumeStreamState.class")
John Spurlock90874332015-03-10 16:00:54 -04004355 public void setAllIndexes(VolumeStreamState srcStream, String caller) {
Jean-Michel Trivi170a0ee2017-04-14 18:13:26 -07004356 if (mStreamType == srcStream.mStreamType) {
4357 return;
4358 }
Jean-Michel Trivi085346a2018-02-14 10:48:51 -08004359 int srcStreamType = srcStream.getStreamType();
4360 // apply default device volume from source stream to all devices first in case
4361 // some devices are present in this stream state but not in source stream state
4362 int index = srcStream.getIndex(AudioSystem.DEVICE_OUT_DEFAULT);
4363 index = rescaleIndex(index, srcStreamType, mStreamType);
4364 for (int i = 0; i < mIndexMap.size(); i++) {
4365 mIndexMap.put(mIndexMap.keyAt(i), index);
4366 }
4367 // Now apply actual volume for devices in source stream state
4368 SparseIntArray srcMap = srcStream.mIndexMap;
4369 for (int i = 0; i < srcMap.size(); i++) {
4370 int device = srcMap.keyAt(i);
4371 index = srcMap.valueAt(i);
4372 index = rescaleIndex(index, srcStreamType, mStreamType);
Eric Laurent33902db2012-10-07 16:15:07 -07004373
Jean-Michel Trivi085346a2018-02-14 10:48:51 -08004374 setIndex(index, device, caller);
Eric Laurent6d517662012-04-23 18:42:39 -07004375 }
4376 }
4377
Jean-Michel Trivi085346a2018-02-14 10:48:51 -08004378 // must be sync'd on mSettingsLock before VolumeStreamState.class
4379 @GuardedBy("VolumeStreamState.class")
Eric Laurentfdbee862014-05-12 15:26:12 -07004380 public void setAllIndexesToMax() {
Jean-Michel Trivi085346a2018-02-14 10:48:51 -08004381 for (int i = 0; i < mIndexMap.size(); i++) {
4382 mIndexMap.put(mIndexMap.keyAt(i), mIndexMax);
Eric Laurentdd45d012012-10-08 09:04:34 -07004383 }
Eric Laurentdd45d012012-10-08 09:04:34 -07004384 }
4385
RoboErik4197cb62015-01-21 15:45:32 -08004386 public void mute(boolean state) {
John Spurlock22b9ee12015-02-18 22:51:44 -05004387 boolean changed = false;
Eric Laurentfdbee862014-05-12 15:26:12 -07004388 synchronized (VolumeStreamState.class) {
RoboErik4197cb62015-01-21 15:45:32 -08004389 if (state != mIsMuted) {
John Spurlock22b9ee12015-02-18 22:51:44 -05004390 changed = true;
RoboErik4197cb62015-01-21 15:45:32 -08004391 mIsMuted = state;
John Spurlock22b9ee12015-02-18 22:51:44 -05004392
RoboErik4197cb62015-01-21 15:45:32 -08004393 // Set the new mute volume. This propagates the values to
4394 // the audio system, otherwise the volume won't be changed
4395 // at the lower level.
4396 sendMsg(mAudioHandler,
4397 MSG_SET_ALL_VOLUMES,
4398 SENDMSG_QUEUE,
4399 0,
4400 0,
4401 this, 0);
Eric Laurentfdbee862014-05-12 15:26:12 -07004402 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004403 }
John Spurlock22b9ee12015-02-18 22:51:44 -05004404 if (changed) {
4405 // Stream mute changed, fire the intent.
4406 Intent intent = new Intent(AudioManager.STREAM_MUTE_CHANGED_ACTION);
4407 intent.putExtra(AudioManager.EXTRA_VOLUME_STREAM_TYPE, mStreamType);
4408 intent.putExtra(AudioManager.EXTRA_STREAM_VOLUME_MUTED, state);
4409 sendBroadcastToAll(intent);
4410 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004411 }
4412
Eric Laurent6d517662012-04-23 18:42:39 -07004413 public int getStreamType() {
4414 return mStreamType;
4415 }
4416
Eric Laurent212532b2014-07-21 15:43:18 -07004417 public void checkFixedVolumeDevices() {
Jean-Michel Trivi58850372018-09-14 16:01:28 -07004418 final boolean isAvrcpAbsVolSupported = mDeviceBroker.isAvrcpAbsoluteVolumeSupported();
Eric Laurent212532b2014-07-21 15:43:18 -07004419 synchronized (VolumeStreamState.class) {
4420 // ignore settings for fixed volume devices: volume should always be at max or 0
4421 if (mStreamVolumeAlias[mStreamType] == AudioSystem.STREAM_MUSIC) {
John Spurlock2bb02ec2015-03-02 13:13:06 -05004422 for (int i = 0; i < mIndexMap.size(); i++) {
4423 int device = mIndexMap.keyAt(i);
4424 int index = mIndexMap.valueAt(i);
Jean-Michel Triviba5270b2014-10-01 17:49:29 -07004425 if (((device & mFullVolumeDevices) != 0)
4426 || (((device & mFixedVolumeDevices) != 0) && index != 0)) {
John Spurlock2bb02ec2015-03-02 13:13:06 -05004427 mIndexMap.put(device, mIndexMax);
Eric Laurent212532b2014-07-21 15:43:18 -07004428 }
Jean-Michel Trivi58850372018-09-14 16:01:28 -07004429 applyDeviceVolume_syncVSS(device, isAvrcpAbsVolSupported);
Eric Laurent212532b2014-07-21 15:43:18 -07004430 }
4431 }
4432 }
4433 }
4434
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004435 private int getValidIndex(int index) {
John Spurlockb6e19e32015-03-10 21:33:44 -04004436 if (index < mIndexMin) {
4437 return mIndexMin;
John Spurlockee5ad722015-03-03 16:17:21 -05004438 } else if (mUseFixedVolume || index > mIndexMax) {
Eric Laurenta553c252009-07-17 12:17:14 -07004439 return mIndexMax;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004440 }
4441
4442 return index;
4443 }
4444
Eric Laurentbffc3d12012-05-07 17:43:49 -07004445 private void dump(PrintWriter pw) {
RoboErik4197cb62015-01-21 15:45:32 -08004446 pw.print(" Muted: ");
4447 pw.println(mIsMuted);
John Spurlockb6e19e32015-03-10 21:33:44 -04004448 pw.print(" Min: ");
4449 pw.println((mIndexMin + 5) / 10);
John Spurlock2b29bc42014-08-26 16:40:35 -04004450 pw.print(" Max: ");
4451 pw.println((mIndexMax + 5) / 10);
Eric Laurentbffc3d12012-05-07 17:43:49 -07004452 pw.print(" Current: ");
John Spurlock2bb02ec2015-03-02 13:13:06 -05004453 for (int i = 0; i < mIndexMap.size(); i++) {
4454 if (i > 0) {
4455 pw.print(", ");
4456 }
4457 final int device = mIndexMap.keyAt(i);
John Spurlock2b29bc42014-08-26 16:40:35 -04004458 pw.print(Integer.toHexString(device));
4459 final String deviceName = device == AudioSystem.DEVICE_OUT_DEFAULT ? "default"
4460 : AudioSystem.getOutputDeviceName(device);
4461 if (!deviceName.isEmpty()) {
4462 pw.print(" (");
4463 pw.print(deviceName);
4464 pw.print(")");
4465 }
4466 pw.print(": ");
John Spurlock2bb02ec2015-03-02 13:13:06 -05004467 final int index = (mIndexMap.valueAt(i) + 5) / 10;
John Spurlock2b29bc42014-08-26 16:40:35 -04004468 pw.print(index);
Eric Laurentbffc3d12012-05-07 17:43:49 -07004469 }
John Spurlockb32fc972015-03-05 13:58:00 -05004470 pw.println();
4471 pw.print(" Devices: ");
John Spurlock8a52c442015-03-26 14:23:58 -04004472 final int devices = getDevicesForStream(mStreamType);
John Spurlockb32fc972015-03-05 13:58:00 -05004473 int device, i = 0, n = 0;
John Spurlock1ff1e6e2015-03-09 14:21:20 -04004474 // iterate all devices from 1 to DEVICE_OUT_DEFAULT exclusive
4475 // (the default device is not returned by getDevicesForStream)
4476 while ((device = 1 << i) != AudioSystem.DEVICE_OUT_DEFAULT) {
John Spurlockb32fc972015-03-05 13:58:00 -05004477 if ((devices & device) != 0) {
4478 if (n++ > 0) {
4479 pw.print(", ");
4480 }
4481 pw.print(AudioSystem.getOutputDeviceName(device));
4482 }
4483 i++;
4484 }
Eric Laurentbffc3d12012-05-07 17:43:49 -07004485 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004486 }
4487
4488 /** Thread that handles native AudioSystem control. */
4489 private class AudioSystemThread extends Thread {
4490 AudioSystemThread() {
4491 super("AudioService");
4492 }
4493
4494 @Override
4495 public void run() {
4496 // Set this thread up so the handler will work on it
4497 Looper.prepare();
4498
4499 synchronized(AudioService.this) {
4500 mAudioHandler = new AudioHandler();
4501
4502 // Notify that the handler has been created
4503 AudioService.this.notify();
4504 }
4505
4506 // Listen for volume change requests that are set by VolumePanel
4507 Looper.loop();
4508 }
4509 }
4510
Jean-Michel Trivi58850372018-09-14 16:01:28 -07004511 /*package*/ void setDeviceVolume(VolumeStreamState streamState, int device) {
4512
4513 final boolean isAvrcpAbsVolSupported = mDeviceBroker.isAvrcpAbsoluteVolumeSupported();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004514
Eric Laurent3e6fb632018-05-21 09:28:46 -07004515 synchronized (VolumeStreamState.class) {
4516 // Apply volume
Jean-Michel Trivi58850372018-09-14 16:01:28 -07004517 streamState.applyDeviceVolume_syncVSS(device, isAvrcpAbsVolSupported);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004518
Eric Laurent3e6fb632018-05-21 09:28:46 -07004519 // Apply change to all streams using this one as alias
4520 int numStreamTypes = AudioSystem.getNumStreamTypes();
4521 for (int streamType = numStreamTypes - 1; streamType >= 0; streamType--) {
4522 if (streamType != streamState.mStreamType &&
4523 mStreamVolumeAlias[streamType] == streamState.mStreamType) {
4524 // Make sure volume is also maxed out on A2DP device for aliased stream
4525 // that may have a different device selected
4526 int streamDevice = getDeviceForStream(streamType);
Jean-Michel Trivi58850372018-09-14 16:01:28 -07004527 if ((device != streamDevice) && isAvrcpAbsVolSupported
4528 && ((device & AudioSystem.DEVICE_OUT_ALL_A2DP) != 0)) {
4529 mStreamStates[streamType].applyDeviceVolume_syncVSS(device,
4530 isAvrcpAbsVolSupported);
Eric Laurentcd772d02013-10-30 18:31:07 -07004531 }
Jean-Michel Trivi58850372018-09-14 16:01:28 -07004532 mStreamStates[streamType].applyDeviceVolume_syncVSS(streamDevice,
4533 isAvrcpAbsVolSupported);
Eric Laurenta553c252009-07-17 12:17:14 -07004534 }
4535 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004536 }
Eric Laurent3e6fb632018-05-21 09:28:46 -07004537 // Post a persist volume msg
4538 sendMsg(mAudioHandler,
4539 MSG_PERSIST_VOLUME,
4540 SENDMSG_QUEUE,
4541 device,
4542 0,
4543 streamState,
4544 PERSIST_DELAY);
4545
4546 }
4547
4548 /** Handles internal volume messages in separate volume thread. */
4549 private class AudioHandler extends Handler {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004550
Eric Laurent9bc8358d2011-11-18 16:43:31 -08004551 private void setAllVolumes(VolumeStreamState streamState) {
4552
4553 // Apply volume
4554 streamState.applyAllVolumes();
4555
4556 // Apply change to all streams using this one as alias
4557 int numStreamTypes = AudioSystem.getNumStreamTypes();
4558 for (int streamType = numStreamTypes - 1; streamType >= 0; streamType--) {
4559 if (streamType != streamState.mStreamType &&
Eric Laurent6d517662012-04-23 18:42:39 -07004560 mStreamVolumeAlias[streamType] == streamState.mStreamType) {
Eric Laurent9bc8358d2011-11-18 16:43:31 -08004561 mStreamStates[streamType].applyAllVolumes();
4562 }
4563 }
4564 }
4565
Eric Laurent42b041e2013-03-29 11:36:03 -07004566 private void persistVolume(VolumeStreamState streamState, int device) {
Eric Laurent83a017b2013-03-19 18:15:31 -07004567 if (mUseFixedVolume) {
4568 return;
4569 }
Muyuan Li1ed6df62016-06-18 11:16:52 -07004570 if (mIsSingleVolume && (streamState.mStreamType != AudioSystem.STREAM_MUSIC)) {
Eric Laurent212532b2014-07-21 15:43:18 -07004571 return;
4572 }
Jean-Michel Trivia53b7052017-04-12 18:27:01 -07004573 if (streamState.hasValidSettingsName()) {
4574 System.putIntForUser(mContentResolver,
4575 streamState.getSettingNameForDevice(device),
4576 (streamState.getIndex(device) + 5)/ 10,
4577 UserHandle.USER_CURRENT);
4578 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004579 }
4580
Glenn Kastenba195eb2011-12-13 09:30:40 -08004581 private void persistRingerMode(int ringerMode) {
Eric Laurent83a017b2013-03-19 18:15:31 -07004582 if (mUseFixedVolume) {
4583 return;
4584 }
Jeff Sharkey8d9a1f62012-10-18 15:38:14 -07004585 Settings.Global.putInt(mContentResolver, Settings.Global.MODE_RINGER, ringerMode);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004586 }
4587
Jaekyun Seokc31033f2018-01-15 14:53:17 +09004588 private String getSoundEffectFilePath(int effectType) {
4589 String filePath = Environment.getProductDirectory() + SOUND_EFFECTS_PATH
4590 + SOUND_EFFECT_FILES.get(SOUND_EFFECT_FILES_MAP[effectType][0]);
4591 if (!new File(filePath).isFile()) {
4592 filePath = Environment.getRootDirectory() + SOUND_EFFECTS_PATH
4593 + SOUND_EFFECT_FILES.get(SOUND_EFFECT_FILES_MAP[effectType][0]);
4594 }
4595 return filePath;
4596 }
4597
Eric Laurent5d3eb44a2013-03-21 15:35:10 -07004598 private boolean onLoadSoundEffects() {
4599 int status;
4600
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004601 synchronized (mSoundEffectsLock) {
Eric Laurent4a5eeb92014-05-06 10:49:04 -07004602 if (!mSystemReady) {
Eric Laurent5d3eb44a2013-03-21 15:35:10 -07004603 Log.w(TAG, "onLoadSoundEffects() called before boot complete");
4604 return false;
4605 }
4606
4607 if (mSoundPool != null) {
4608 return true;
4609 }
4610
4611 loadTouchSoundAssets();
4612
Jean-Michel Trivi55a30c42014-07-20 17:56:11 -07004613 mSoundPool = new SoundPool.Builder()
4614 .setMaxStreams(NUM_SOUNDPOOL_CHANNELS)
4615 .setAudioAttributes(new AudioAttributes.Builder()
4616 .setUsage(AudioAttributes.USAGE_ASSISTANCE_SONIFICATION)
4617 .setContentType(AudioAttributes.CONTENT_TYPE_SONIFICATION)
4618 .build())
4619 .build();
Eric Laurent5d3eb44a2013-03-21 15:35:10 -07004620 mSoundPoolCallBack = null;
4621 mSoundPoolListenerThread = new SoundPoolListenerThread();
4622 mSoundPoolListenerThread.start();
4623 int attempts = 3;
4624 while ((mSoundPoolCallBack == null) && (attempts-- > 0)) {
4625 try {
4626 // Wait for mSoundPoolCallBack to be set by the other thread
Glenn Kasten167d1a22013-07-23 16:24:41 -07004627 mSoundEffectsLock.wait(SOUND_EFFECTS_LOAD_TIMEOUT_MS);
Eric Laurent5d3eb44a2013-03-21 15:35:10 -07004628 } catch (InterruptedException e) {
4629 Log.w(TAG, "Interrupted while waiting sound pool listener thread.");
4630 }
4631 }
4632
4633 if (mSoundPoolCallBack == null) {
4634 Log.w(TAG, "onLoadSoundEffects() SoundPool listener or thread creation error");
4635 if (mSoundPoolLooper != null) {
4636 mSoundPoolLooper.quit();
4637 mSoundPoolLooper = null;
4638 }
4639 mSoundPoolListenerThread = null;
4640 mSoundPool.release();
4641 mSoundPool = null;
4642 return false;
4643 }
4644 /*
4645 * poolId table: The value -1 in this table indicates that corresponding
4646 * file (same index in SOUND_EFFECT_FILES[] has not been loaded.
4647 * Once loaded, the value in poolId is the sample ID and the same
4648 * sample can be reused for another effect using the same file.
4649 */
4650 int[] poolId = new int[SOUND_EFFECT_FILES.size()];
4651 for (int fileIdx = 0; fileIdx < SOUND_EFFECT_FILES.size(); fileIdx++) {
4652 poolId[fileIdx] = -1;
4653 }
4654 /*
4655 * Effects whose value in SOUND_EFFECT_FILES_MAP[effect][1] is -1 must be loaded.
4656 * If load succeeds, value in SOUND_EFFECT_FILES_MAP[effect][1] is > 0:
4657 * this indicates we have a valid sample loaded for this effect.
4658 */
4659
4660 int numSamples = 0;
4661 for (int effect = 0; effect < AudioManager.NUM_SOUND_EFFECTS; effect++) {
4662 // Do not load sample if this effect uses the MediaPlayer
4663 if (SOUND_EFFECT_FILES_MAP[effect][1] == 0) {
4664 continue;
4665 }
4666 if (poolId[SOUND_EFFECT_FILES_MAP[effect][0]] == -1) {
Jaekyun Seokc31033f2018-01-15 14:53:17 +09004667 String filePath = getSoundEffectFilePath(effect);
Eric Laurent5d3eb44a2013-03-21 15:35:10 -07004668 int sampleId = mSoundPool.load(filePath, 0);
4669 if (sampleId <= 0) {
4670 Log.w(TAG, "Soundpool could not load file: "+filePath);
4671 } else {
4672 SOUND_EFFECT_FILES_MAP[effect][1] = sampleId;
4673 poolId[SOUND_EFFECT_FILES_MAP[effect][0]] = sampleId;
4674 numSamples++;
4675 }
4676 } else {
4677 SOUND_EFFECT_FILES_MAP[effect][1] =
4678 poolId[SOUND_EFFECT_FILES_MAP[effect][0]];
4679 }
4680 }
4681 // wait for all samples to be loaded
4682 if (numSamples > 0) {
4683 mSoundPoolCallBack.setSamples(poolId);
4684
4685 attempts = 3;
4686 status = 1;
4687 while ((status == 1) && (attempts-- > 0)) {
4688 try {
Glenn Kasten167d1a22013-07-23 16:24:41 -07004689 mSoundEffectsLock.wait(SOUND_EFFECTS_LOAD_TIMEOUT_MS);
Eric Laurent5d3eb44a2013-03-21 15:35:10 -07004690 status = mSoundPoolCallBack.status();
4691 } catch (InterruptedException e) {
4692 Log.w(TAG, "Interrupted while waiting sound pool callback.");
4693 }
4694 }
4695 } else {
4696 status = -1;
4697 }
4698
4699 if (mSoundPoolLooper != null) {
4700 mSoundPoolLooper.quit();
4701 mSoundPoolLooper = null;
4702 }
4703 mSoundPoolListenerThread = null;
4704 if (status != 0) {
4705 Log.w(TAG,
4706 "onLoadSoundEffects(), Error "+status+ " while loading samples");
4707 for (int effect = 0; effect < AudioManager.NUM_SOUND_EFFECTS; effect++) {
4708 if (SOUND_EFFECT_FILES_MAP[effect][1] > 0) {
4709 SOUND_EFFECT_FILES_MAP[effect][1] = -1;
4710 }
4711 }
4712
4713 mSoundPool.release();
4714 mSoundPool = null;
4715 }
4716 }
4717 return (status == 0);
4718 }
4719
4720 /**
4721 * Unloads samples from the sound pool.
4722 * This method can be called to free some memory when
4723 * sound effects are disabled.
4724 */
4725 private void onUnloadSoundEffects() {
4726 synchronized (mSoundEffectsLock) {
4727 if (mSoundPool == null) {
4728 return;
4729 }
4730
4731 int[] poolId = new int[SOUND_EFFECT_FILES.size()];
4732 for (int fileIdx = 0; fileIdx < SOUND_EFFECT_FILES.size(); fileIdx++) {
4733 poolId[fileIdx] = 0;
4734 }
4735
4736 for (int effect = 0; effect < AudioManager.NUM_SOUND_EFFECTS; effect++) {
4737 if (SOUND_EFFECT_FILES_MAP[effect][1] <= 0) {
4738 continue;
4739 }
4740 if (poolId[SOUND_EFFECT_FILES_MAP[effect][0]] == 0) {
4741 mSoundPool.unload(SOUND_EFFECT_FILES_MAP[effect][1]);
4742 SOUND_EFFECT_FILES_MAP[effect][1] = -1;
4743 poolId[SOUND_EFFECT_FILES_MAP[effect][0]] = -1;
4744 }
4745 }
4746 mSoundPool.release();
4747 mSoundPool = null;
4748 }
4749 }
4750
4751 private void onPlaySoundEffect(int effectType, int volume) {
4752 synchronized (mSoundEffectsLock) {
4753
4754 onLoadSoundEffects();
4755
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004756 if (mSoundPool == null) {
4757 return;
4758 }
Eric Laurenta2ef57d2009-09-28 04:46:10 -07004759 float volFloat;
Eric Laurent25101b02011-02-02 09:33:30 -08004760 // use default if volume is not specified by caller
Eric Laurenta2ef57d2009-09-28 04:46:10 -07004761 if (volume < 0) {
Jean-Michel Trivif2b0c112012-07-09 11:59:11 -07004762 volFloat = (float)Math.pow(10, (float)sSoundEffectVolumeDb/20);
Eric Laurenta2ef57d2009-09-28 04:46:10 -07004763 } else {
RoboErik8a2cfc32014-05-16 11:19:38 -07004764 volFloat = volume / 1000.0f;
Eric Laurenta2ef57d2009-09-28 04:46:10 -07004765 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004766
4767 if (SOUND_EFFECT_FILES_MAP[effectType][1] > 0) {
Eric Laurent5d3eb44a2013-03-21 15:35:10 -07004768 mSoundPool.play(SOUND_EFFECT_FILES_MAP[effectType][1],
4769 volFloat, volFloat, 0, 0, 1.0f);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004770 } else {
4771 MediaPlayer mediaPlayer = new MediaPlayer();
Glenn Kasten62b9aec2011-11-07 11:10:16 -08004772 try {
Jaekyun Seokc31033f2018-01-15 14:53:17 +09004773 String filePath = getSoundEffectFilePath(effectType);
Glenn Kasten62b9aec2011-11-07 11:10:16 -08004774 mediaPlayer.setDataSource(filePath);
4775 mediaPlayer.setAudioStreamType(AudioSystem.STREAM_SYSTEM);
4776 mediaPlayer.prepare();
Glenn Kasten068225d2012-02-27 16:21:04 -08004777 mediaPlayer.setVolume(volFloat);
Glenn Kasten62b9aec2011-11-07 11:10:16 -08004778 mediaPlayer.setOnCompletionListener(new OnCompletionListener() {
4779 public void onCompletion(MediaPlayer mp) {
4780 cleanupPlayer(mp);
4781 }
4782 });
4783 mediaPlayer.setOnErrorListener(new OnErrorListener() {
4784 public boolean onError(MediaPlayer mp, int what, int extra) {
4785 cleanupPlayer(mp);
4786 return true;
4787 }
4788 });
4789 mediaPlayer.start();
4790 } catch (IOException ex) {
4791 Log.w(TAG, "MediaPlayer IOException: "+ex);
4792 } catch (IllegalArgumentException ex) {
4793 Log.w(TAG, "MediaPlayer IllegalArgumentException: "+ex);
4794 } catch (IllegalStateException ex) {
4795 Log.w(TAG, "MediaPlayer IllegalStateException: "+ex);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004796 }
4797 }
4798 }
4799 }
4800
4801 private void cleanupPlayer(MediaPlayer mp) {
4802 if (mp != null) {
4803 try {
4804 mp.stop();
4805 mp.release();
4806 } catch (IllegalStateException ex) {
4807 Log.w(TAG, "MediaPlayer IllegalStateException: "+ex);
4808 }
4809 }
4810 }
4811
Eric Laurent05274f32012-11-29 12:48:18 -08004812 private void onPersistSafeVolumeState(int state) {
4813 Settings.Global.putInt(mContentResolver,
4814 Settings.Global.AUDIO_SAFE_VOLUME_STATE,
4815 state);
4816 }
4817
Jean-Michel Trivi7ed71472018-02-02 16:52:09 -08004818 private void onNotifyVolumeEvent(@NonNull IAudioPolicyCallback apc,
4819 @AudioManager.VolumeAdjustment int direction) {
4820 try {
4821 apc.notifyVolumeAdjust(direction);
4822 } catch(Exception e) {
4823 // nothing we can do about this. Do not log error, too much potential for spam
4824 }
4825 }
4826
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004827 @Override
4828 public void handleMessage(Message msg) {
Eric Laurentafbb0472011-12-15 09:04:23 -08004829 switch (msg.what) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004830
Eric Laurent9bc8358d2011-11-18 16:43:31 -08004831 case MSG_SET_DEVICE_VOLUME:
4832 setDeviceVolume((VolumeStreamState) msg.obj, msg.arg1);
4833 break;
4834
4835 case MSG_SET_ALL_VOLUMES:
4836 setAllVolumes((VolumeStreamState) msg.obj);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004837 break;
4838
4839 case MSG_PERSIST_VOLUME:
Eric Laurent42b041e2013-03-29 11:36:03 -07004840 persistVolume((VolumeStreamState) msg.obj, msg.arg1);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004841 break;
4842
4843 case MSG_PERSIST_RINGER_MODE:
Glenn Kastenba195eb2011-12-13 09:30:40 -08004844 // note that the value persisted is the current ringer mode, not the
4845 // value of ringer mode as of the time the request was made to persist
John Spurlock661f2cf2014-11-17 10:29:10 -05004846 persistRingerMode(getRingerModeInternal());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004847 break;
4848
Andy Hunged0ea402015-10-30 14:11:46 -07004849 case MSG_AUDIO_SERVER_DIED:
4850 onAudioServerDied();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004851 break;
4852
Eric Laurent1d3cdce2018-01-20 10:31:21 -08004853 case MSG_DISPATCH_AUDIO_SERVER_STATE:
4854 onDispatchAudioServerStateChange(msg.arg1 == 1);
4855 break;
4856
Eric Laurent5d3eb44a2013-03-21 15:35:10 -07004857 case MSG_UNLOAD_SOUND_EFFECTS:
4858 onUnloadSoundEffects();
4859 break;
4860
Eric Laurent117b7bb2011-01-16 17:07:27 -08004861 case MSG_LOAD_SOUND_EFFECTS:
Eric Laurent5d3eb44a2013-03-21 15:35:10 -07004862 //FIXME: onLoadSoundEffects() should be executed in a separate thread as it
4863 // can take several dozens of milliseconds to complete
4864 boolean loaded = onLoadSoundEffects();
4865 if (msg.obj != null) {
4866 LoadSoundEffectReply reply = (LoadSoundEffectReply)msg.obj;
4867 synchronized (reply) {
4868 reply.mStatus = loaded ? 0 : -1;
4869 reply.notify();
4870 }
4871 }
Eric Laurent117b7bb2011-01-16 17:07:27 -08004872 break;
4873
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004874 case MSG_PLAY_SOUND_EFFECT:
Eric Laurent5d3eb44a2013-03-21 15:35:10 -07004875 onPlaySoundEffect(msg.arg1, msg.arg2);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004876 break;
Jean-Michel Trivi4c637b92010-04-12 18:44:10 -07004877
Eric Laurentfa640152011-03-12 15:59:51 -08004878 case MSG_SET_FORCE_USE:
Jean-Michel Trivi58850372018-09-14 16:01:28 -07004879 {
4880 final String eventSource = (String) msg.obj;
4881 final int useCase = msg.arg1;
4882 final int config = msg.arg2;
4883 if (useCase == AudioSystem.FOR_MEDIA) {
4884 Log.wtf(TAG, "Invalid force use FOR_MEDIA in AudioService from "
4885 + eventSource);
4886 break;
Paul McLean10804eb2015-01-28 11:16:35 -08004887 }
Jean-Michel Trivi58850372018-09-14 16:01:28 -07004888 sForceUseLogger.log(
4889 new AudioServiceEvents.ForceUseEvent(useCase, config, eventSource));
4890 AudioSystem.setForceUse(useCase, config);
4891 }
Aniket Kumar Lataa8439e22019-01-11 03:59:00 -08004892 break;
4893
Jean-Michel Trivi92ed7bf2017-06-26 19:32:38 -07004894 case MSG_DISABLE_AUDIO_FOR_UID:
4895 mPlaybackMonitor.disableAudioForUid( msg.arg1 == 1 /* disable */,
4896 msg.arg2 /* uid */);
4897 mAudioEventWakeLock.release();
4898 break;
4899
Eric Laurentc34dcc12012-09-10 13:51:52 -07004900 case MSG_CHECK_MUSIC_ACTIVE:
John Spurlock90874332015-03-10 16:00:54 -04004901 onCheckMusicActive((String) msg.obj);
Eric Laurentc34dcc12012-09-10 13:51:52 -07004902 break;
Eric Laurent5bfaeae2012-09-21 18:44:48 -07004903
Eric Laurentd640bd32012-09-28 18:01:48 -07004904 case MSG_CONFIGURE_SAFE_MEDIA_VOLUME_FORCED:
4905 case MSG_CONFIGURE_SAFE_MEDIA_VOLUME:
John Spurlock90874332015-03-10 16:00:54 -04004906 onConfigureSafeVolume((msg.what == MSG_CONFIGURE_SAFE_MEDIA_VOLUME_FORCED),
4907 (String) msg.obj);
Eric Laurentd640bd32012-09-28 18:01:48 -07004908 break;
Eric Laurent05274f32012-11-29 12:48:18 -08004909 case MSG_PERSIST_SAFE_VOLUME_STATE:
4910 onPersistSafeVolumeState(msg.arg1);
4911 break;
Jean-Michel Trivia578c482012-12-28 11:19:49 -08004912
Eric Laurent4a5eeb92014-05-06 10:49:04 -07004913 case MSG_SYSTEM_READY:
4914 onSystemReady();
4915 break;
John Spurlockaa5ee4d2014-07-25 13:05:12 -04004916
Eric Laurent0867bed2015-05-20 14:49:08 -07004917 case MSG_INDICATE_SYSTEM_READY:
4918 onIndicateSystemReady();
4919 break;
4920
Jean-Michel Trivi1ab43f62017-04-27 15:37:34 -07004921 case MSG_ACCESSORY_PLUG_MEDIA_UNMUTE:
4922 onAccessoryPlugMediaUnmute(msg.arg1);
4923 break;
4924
John Spurlockaa5ee4d2014-07-25 13:05:12 -04004925 case MSG_PERSIST_MUSIC_ACTIVE_MS:
4926 final int musicActiveMs = msg.arg1;
4927 Settings.Secure.putIntForUser(mContentResolver,
4928 Settings.Secure.UNSAFE_VOLUME_MUSIC_ACTIVE_MS, musicActiveMs,
4929 UserHandle.USER_CURRENT);
4930 break;
Eric Laurentc0232482016-03-15 18:19:23 -07004931
RoboErik5452e252015-02-06 15:33:53 -08004932 case MSG_UNMUTE_STREAM:
4933 onUnmuteStream(msg.arg1, msg.arg2);
4934 break;
Eric Laurentc0232482016-03-15 18:19:23 -07004935
Jean-Michel Trivi5a561092015-04-23 18:48:08 -07004936 case MSG_DYN_POLICY_MIX_STATE_UPDATE:
4937 onDynPolicyMixStateUpdate((String) msg.obj, msg.arg1);
4938 break;
Jean-Michel Trivi7ed71472018-02-02 16:52:09 -08004939
4940 case MSG_NOTIFY_VOL_EVENT:
4941 onNotifyVolumeEvent((IAudioPolicyCallback) msg.obj, msg.arg1);
4942 break;
jiabin39940752018-04-02 18:18:45 -07004943
4944 case MSG_ENABLE_SURROUND_FORMATS:
4945 onEnableSurroundFormats((ArrayList<Integer>) msg.obj);
4946 break;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004947 }
4948 }
4949 }
4950
Jason Parekhb1096152009-03-24 17:48:25 -07004951 private class SettingsObserver extends ContentObserver {
Eric Laurenta553c252009-07-17 12:17:14 -07004952
Jason Parekhb1096152009-03-24 17:48:25 -07004953 SettingsObserver() {
4954 super(new Handler());
Beverlyd6964762018-02-16 14:07:03 -05004955 mContentResolver.registerContentObserver(Settings.Global.getUriFor(
4956 Settings.Global.ZEN_MODE), false, this);
4957 mContentResolver.registerContentObserver(Settings.Global.getUriFor(
4958 Settings.Global.ZEN_MODE_CONFIG_ETAG), false, this);
Jason Parekhb1096152009-03-24 17:48:25 -07004959 mContentResolver.registerContentObserver(Settings.System.getUriFor(
4960 Settings.System.MODE_RINGER_STREAMS_AFFECTED), false, this);
Eric Laurent7ee1e4f2012-10-26 18:11:21 -07004961 mContentResolver.registerContentObserver(Settings.Global.getUriFor(
4962 Settings.Global.DOCK_AUDIO_MEDIA_ENABLED), false, this);
Andy Hung7b98e9a2016-02-25 18:34:50 -08004963 mContentResolver.registerContentObserver(Settings.System.getUriFor(
4964 Settings.System.MASTER_MONO), false, this);
Edward Savage-Jones35c292f2017-01-13 09:04:34 +01004965 mContentResolver.registerContentObserver(Settings.System.getUriFor(
4966 Settings.System.MASTER_BALANCE), false, this);
Phil Burked43bf52016-03-01 17:01:35 -08004967
4968 mEncodedSurroundMode = Settings.Global.getInt(
4969 mContentResolver, Settings.Global.ENCODED_SURROUND_OUTPUT,
4970 Settings.Global.ENCODED_SURROUND_OUTPUT_AUTO);
4971 mContentResolver.registerContentObserver(Settings.Global.getUriFor(
4972 Settings.Global.ENCODED_SURROUND_OUTPUT), false, this);
jiabin39940752018-04-02 18:18:45 -07004973
4974 mEnabledSurroundFormats = Settings.Global.getString(
4975 mContentResolver, Settings.Global.ENCODED_SURROUND_OUTPUT_ENABLED_FORMATS);
4976 mContentResolver.registerContentObserver(Settings.Global.getUriFor(
4977 Settings.Global.ENCODED_SURROUND_OUTPUT_ENABLED_FORMATS), false, this);
Eric Laurent1c9c1d52018-10-17 10:06:46 -07004978
4979 mContentResolver.registerContentObserver(Settings.Secure.getUriFor(
4980 Settings.Secure.VOICE_INTERACTION_SERVICE), false, this);
Jason Parekhb1096152009-03-24 17:48:25 -07004981 }
4982
4983 @Override
4984 public void onChange(boolean selfChange) {
4985 super.onChange(selfChange);
Glenn Kastenba195eb2011-12-13 09:30:40 -08004986 // FIXME This synchronized is not necessary if mSettingsLock only protects mRingerMode.
Beverlyd6964762018-02-16 14:07:03 -05004987 // However there appear to be some missing locks around mRingerAndZenModeMutedStreams
Glenn Kastenba195eb2011-12-13 09:30:40 -08004988 // and mRingerModeAffectedStreams, so will leave this synchronized for now.
Beverlyd6964762018-02-16 14:07:03 -05004989 // mRingerAndZenModeMutedStreams and mMuteAffectedStreams are safe (only accessed once).
Eric Laurenta553c252009-07-17 12:17:14 -07004990 synchronized (mSettingsLock) {
Beverlyd6964762018-02-16 14:07:03 -05004991 if (updateRingerAndZenModeAffectedStreams()) {
Eric Laurenta553c252009-07-17 12:17:14 -07004992 /*
4993 * Ensure all stream types that should be affected by ringer mode
4994 * are in the proper state.
4995 */
John Spurlock661f2cf2014-11-17 10:29:10 -05004996 setRingerModeInt(getRingerModeInternal(), false);
Eric Laurenta553c252009-07-17 12:17:14 -07004997 }
Eric Laurent7ee1e4f2012-10-26 18:11:21 -07004998 readDockAudioSettings(mContentResolver);
Andy Hung7b98e9a2016-02-25 18:34:50 -08004999 updateMasterMono(mContentResolver);
Edward Savage-Jones35c292f2017-01-13 09:04:34 +01005000 updateMasterBalance(mContentResolver);
Phil Burked43bf52016-03-01 17:01:35 -08005001 updateEncodedSurroundOutput();
jiabin39940752018-04-02 18:18:45 -07005002 sendEnabledSurroundFormats(mContentResolver, mSurroundModeChanged);
Eric Laurent1c9c1d52018-10-17 10:06:46 -07005003 updateAssistantUId(false);
Phil Burked43bf52016-03-01 17:01:35 -08005004 }
5005 }
5006
5007 private void updateEncodedSurroundOutput() {
5008 int newSurroundMode = Settings.Global.getInt(
5009 mContentResolver, Settings.Global.ENCODED_SURROUND_OUTPUT,
5010 Settings.Global.ENCODED_SURROUND_OUTPUT_AUTO);
5011 // Did it change?
5012 if (mEncodedSurroundMode != newSurroundMode) {
5013 // Send to AudioPolicyManager
Jean-Michel Trivi011f39e2017-08-19 18:08:06 -07005014 sendEncodedSurroundMode(newSurroundMode, "SettingsObserver");
Jean-Michel Trivi58850372018-09-14 16:01:28 -07005015 mDeviceBroker.toggleHdmiIfConnected_Async();
Phil Burked43bf52016-03-01 17:01:35 -08005016 mEncodedSurroundMode = newSurroundMode;
jiabin39940752018-04-02 18:18:45 -07005017 mSurroundModeChanged = true;
5018 } else {
5019 mSurroundModeChanged = false;
Eric Laurenta553c252009-07-17 12:17:14 -07005020 }
Jason Parekhb1096152009-03-24 17:48:25 -07005021 }
Jason Parekhb1096152009-03-24 17:48:25 -07005022 }
Eric Laurenta553c252009-07-17 12:17:14 -07005023
John Du5a0cf7a2013-07-19 11:30:34 -07005024 public void avrcpSupportsAbsoluteVolume(String address, boolean support) {
5025 // address is not used for now, but may be used when multiple a2dp devices are supported
Jean-Michel Trivi58850372018-09-14 16:01:28 -07005026 mDeviceBroker.setAvrcpAbsoluteVolumeSupported(support);
5027 sendMsg(mAudioHandler, MSG_SET_DEVICE_VOLUME, SENDMSG_QUEUE,
Eric Laurent3e6fb632018-05-21 09:28:46 -07005028 AudioSystem.DEVICE_OUT_BLUETOOTH_A2DP, 0,
5029 mStreamStates[AudioSystem.STREAM_MUSIC], 0);
Eric Laurentb1fbaac2012-05-29 09:24:28 -07005030 }
5031
Jean-Michel Trivi7db2d8f2018-03-06 10:30:59 -08005032 /**
5033 * @return true if there is currently a registered dynamic mixing policy that affects media
5034 */
Jean-Michel Trivi58850372018-09-14 16:01:28 -07005035 /*package*/ boolean hasMediaDynamicPolicy() {
Jean-Michel Trivi7db2d8f2018-03-06 10:30:59 -08005036 synchronized (mAudioPolicies) {
5037 if (mAudioPolicies.isEmpty()) {
5038 return false;
5039 }
5040 final Collection<AudioPolicyProxy> appColl = mAudioPolicies.values();
5041 for (AudioPolicyProxy app : appColl) {
5042 if (app.hasMixAffectingUsage(AudioAttributes.USAGE_MEDIA)) {
5043 return true;
5044 }
5045 }
5046 return false;
5047 }
5048 }
5049
Jean-Michel Trivi58850372018-09-14 16:01:28 -07005050 /*package*/ void checkMusicActive(int deviceType, String caller) {
5051 if ((deviceType & mSafeMediaVolumeDevices) != 0) {
5052 sendMsg(mAudioHandler,
5053 MSG_CHECK_MUSIC_ACTIVE,
5054 SENDMSG_REPLACE,
5055 0,
5056 0,
5057 caller,
5058 MUSIC_ACTIVE_POLL_PERIOD_MS);
Dianne Hackborn632ca412012-06-14 19:34:10 -07005059 }
Eric Laurenteab40d12017-06-09 12:45:21 -07005060 }
5061
Eric Laurenta553c252009-07-17 12:17:14 -07005062 /**
5063 * Receiver for misc intent broadcasts the Phone app cares about.
5064 */
5065 private class AudioServiceBroadcastReceiver extends BroadcastReceiver {
5066 @Override
5067 public void onReceive(Context context, Intent intent) {
Jean-Michel Trivi58850372018-09-14 16:01:28 -07005068 final String action = intent.getAction();
Eric Laurentae4506e2014-05-29 16:04:32 -07005069 int outDevice;
5070 int inDevice;
Eric Laurent59f48272012-04-05 19:42:21 -07005071 int state;
Eric Laurenta553c252009-07-17 12:17:14 -07005072
Jean-Michel Trivi758559e2010-03-09 09:26:08 -08005073 if (action.equals(Intent.ACTION_DOCK_EVENT)) {
5074 int dockState = intent.getIntExtra(Intent.EXTRA_DOCK_STATE,
5075 Intent.EXTRA_DOCK_STATE_UNDOCKED);
5076 int config;
5077 switch (dockState) {
5078 case Intent.EXTRA_DOCK_STATE_DESK:
5079 config = AudioSystem.FORCE_BT_DESK_DOCK;
5080 break;
5081 case Intent.EXTRA_DOCK_STATE_CAR:
5082 config = AudioSystem.FORCE_BT_CAR_DOCK;
5083 break;
Praveen Bharathi21e941b2010-10-06 15:23:14 -05005084 case Intent.EXTRA_DOCK_STATE_LE_DESK:
Eric Laurent08ed1b92012-11-05 14:54:12 -08005085 config = AudioSystem.FORCE_ANALOG_DOCK;
Praveen Bharathi21e941b2010-10-06 15:23:14 -05005086 break;
5087 case Intent.EXTRA_DOCK_STATE_HE_DESK:
5088 config = AudioSystem.FORCE_DIGITAL_DOCK;
5089 break;
Jean-Michel Trivi758559e2010-03-09 09:26:08 -08005090 case Intent.EXTRA_DOCK_STATE_UNDOCKED:
5091 default:
5092 config = AudioSystem.FORCE_NONE;
5093 }
Eric Laurent08ed1b92012-11-05 14:54:12 -08005094 // Low end docks have a menu to enable or disable audio
5095 // (see mDockAudioMediaEnabled)
Jean-Michel Trivi58850372018-09-14 16:01:28 -07005096 if (!((dockState == Intent.EXTRA_DOCK_STATE_LE_DESK)
5097 || ((dockState == Intent.EXTRA_DOCK_STATE_UNDOCKED)
5098 && (mDockState == Intent.EXTRA_DOCK_STATE_LE_DESK)))) {
5099 mDeviceBroker.setForceUse_Async(AudioSystem.FOR_DOCK, config,
5100 "ACTION_DOCK_EVENT intent");
Eric Laurent08ed1b92012-11-05 14:54:12 -08005101 }
5102 mDockState = dockState;
Jean-Michel Trivi58850372018-09-14 16:01:28 -07005103 } else if (action.equals(BluetoothHeadset.ACTION_ACTIVE_DEVICE_CHANGED)
5104 || action.equals(BluetoothHeadset.ACTION_AUDIO_STATE_CHANGED)) {
5105 mDeviceBroker.receiveBtEvent(intent);
Eric Laurent950e8cb2011-10-13 08:57:54 -07005106 } else if (action.equals(Intent.ACTION_SCREEN_ON)) {
Jon Eklund318f0fe2014-01-23 17:53:48 -06005107 if (mMonitorRotation) {
Jean-Michel Trivi24806db2015-10-01 15:00:59 -07005108 RotationHelper.enable();
Jon Eklund318f0fe2014-01-23 17:53:48 -06005109 }
Eric Laurent950e8cb2011-10-13 08:57:54 -07005110 AudioSystem.setParameters("screen_state=on");
5111 } else if (action.equals(Intent.ACTION_SCREEN_OFF)) {
Jon Eklund318f0fe2014-01-23 17:53:48 -06005112 if (mMonitorRotation) {
5113 //reduce wakeups (save current) by only listening when display is on
Jean-Michel Trivi24806db2015-10-01 15:00:59 -07005114 RotationHelper.disable();
Jon Eklund318f0fe2014-01-23 17:53:48 -06005115 }
Eric Laurent950e8cb2011-10-13 08:57:54 -07005116 AudioSystem.setParameters("screen_state=off");
Dianne Hackborn961cae92013-03-20 14:59:43 -07005117 } else if (action.equals(Intent.ACTION_CONFIGURATION_CHANGED)) {
Jean-Michel Trivif26f0172012-04-25 16:23:20 -07005118 handleConfigurationChanged(context);
Eric Laurentbc0fab1f2012-09-19 11:24:41 -07005119 } else if (action.equals(Intent.ACTION_USER_SWITCHED)) {
Yasuhiro Matsuda4ced7192015-07-10 22:08:44 +09005120 if (mUserSwitchedReceived) {
5121 // attempt to stop music playback for background user except on first user
5122 // switch (i.e. first boot)
Jean-Michel Trivi58850372018-09-14 16:01:28 -07005123 mDeviceBroker.broadcastBecomingNoisy();
Yasuhiro Matsuda4ced7192015-07-10 22:08:44 +09005124 }
5125 mUserSwitchedReceived = true;
Jean-Michel Trivif4a8eb22012-10-29 12:42:55 -07005126 // the current audio focus owner is no longer valid
Jean-Michel Trivifa9a6982013-06-27 16:22:58 -07005127 mMediaFocusControl.discardAudioFocusOwner();
Jean-Michel Trivif4a8eb22012-10-29 12:42:55 -07005128
Eric Laurent5bfaeae2012-09-21 18:44:48 -07005129 // load volume settings for new user
Eric Laurentbc0fab1f2012-09-19 11:24:41 -07005130 readAudioSettings(true /*userSwitch*/);
5131 // preserve STREAM_MUSIC volume from one user to the next.
5132 sendMsg(mAudioHandler,
5133 MSG_SET_ALL_VOLUMES,
5134 SENDMSG_QUEUE,
5135 0,
5136 0,
5137 mStreamStates[AudioSystem.STREAM_MUSIC], 0);
Fyodor Kupolovb5013302015-04-17 17:59:14 -07005138 } else if (action.equals(Intent.ACTION_USER_BACKGROUND)) {
5139 // Disable audio recording for the background user/profile
5140 int userId = intent.getIntExtra(Intent.EXTRA_USER_HANDLE, -1);
5141 if (userId >= 0) {
5142 // TODO Kill recording streams instead of killing processes holding permission
5143 UserInfo userInfo = UserManagerService.getInstance().getUserInfo(userId);
5144 killBackgroundUserProcessesWithRecordAudioPermission(userInfo);
5145 }
Makoto Onukiac65e1e2015-11-20 15:33:17 -08005146 UserManagerService.getInstance().setUserRestriction(
Fyodor Kupolovb5013302015-04-17 17:59:14 -07005147 UserManager.DISALLOW_RECORD_AUDIO, true, userId);
5148 } else if (action.equals(Intent.ACTION_USER_FOREGROUND)) {
5149 // Enable audio recording for foreground user/profile
5150 int userId = intent.getIntExtra(Intent.EXTRA_USER_HANDLE, -1);
Makoto Onukiac65e1e2015-11-20 15:33:17 -08005151 UserManagerService.getInstance().setUserRestriction(
Fyodor Kupolovb5013302015-04-17 17:59:14 -07005152 UserManager.DISALLOW_RECORD_AUDIO, false, userId);
Eric Laurentb70b78a2016-01-13 19:16:04 -08005153 } else if (action.equals(BluetoothAdapter.ACTION_STATE_CHANGED)) {
5154 state = intent.getIntExtra(BluetoothAdapter.EXTRA_STATE, -1);
5155 if (state == BluetoothAdapter.STATE_OFF ||
5156 state == BluetoothAdapter.STATE_TURNING_OFF) {
Jean-Michel Trivi58850372018-09-14 16:01:28 -07005157 mDeviceBroker.disconnectAllBluetoothProfiles();
Eric Laurentb70b78a2016-01-13 19:16:04 -08005158 }
Marco Nelissenfb6df0b2017-02-15 15:25:24 -08005159 } else if (action.equals(AudioEffect.ACTION_OPEN_AUDIO_EFFECT_CONTROL_SESSION) ||
5160 action.equals(AudioEffect.ACTION_CLOSE_AUDIO_EFFECT_CONTROL_SESSION)) {
5161 handleAudioEffectBroadcast(context, intent);
Eric Laurenta553c252009-07-17 12:17:14 -07005162 }
5163 }
Paul McLeanc837a452014-04-09 09:04:43 -07005164 } // end class AudioServiceBroadcastReceiver
Jean-Michel Trivid5176cf2010-01-28 11:56:42 -08005165
Makoto Onukid45a4a22015-11-02 17:17:38 -08005166 private class AudioServiceUserRestrictionsListener implements UserRestrictionsListener {
5167
5168 @Override
5169 public void onUserRestrictionsChanged(int userId, Bundle newRestrictions,
5170 Bundle prevRestrictions) {
5171 // Update mic mute state.
5172 {
5173 final boolean wasRestricted =
5174 prevRestrictions.getBoolean(UserManager.DISALLOW_UNMUTE_MICROPHONE);
5175 final boolean isRestricted =
5176 newRestrictions.getBoolean(UserManager.DISALLOW_UNMUTE_MICROPHONE);
5177 if (wasRestricted != isRestricted) {
5178 setMicrophoneMuteNoCallerCheck(isRestricted, userId);
5179 }
5180 }
5181
5182 // Update speaker mute state.
5183 {
5184 final boolean wasRestricted =
Tony Makc1205112016-07-22 16:02:59 +01005185 prevRestrictions.getBoolean(UserManager.DISALLOW_ADJUST_VOLUME)
Esteban Talavera492b4722017-02-13 14:59:45 +00005186 || prevRestrictions.getBoolean(UserManager.DISALLOW_UNMUTE_DEVICE);
Makoto Onukid45a4a22015-11-02 17:17:38 -08005187 final boolean isRestricted =
Tony Makc1205112016-07-22 16:02:59 +01005188 newRestrictions.getBoolean(UserManager.DISALLOW_ADJUST_VOLUME)
Esteban Talavera492b4722017-02-13 14:59:45 +00005189 || newRestrictions.getBoolean(UserManager.DISALLOW_UNMUTE_DEVICE);
Makoto Onukid45a4a22015-11-02 17:17:38 -08005190 if (wasRestricted != isRestricted) {
5191 setMasterMuteInternalNoCallerCheck(isRestricted, /* flags =*/ 0, userId);
5192 }
5193 }
5194 }
5195 } // end class AudioServiceUserRestrictionsListener
5196
Marco Nelissenfb6df0b2017-02-15 15:25:24 -08005197 private void handleAudioEffectBroadcast(Context context, Intent intent) {
5198 String target = intent.getPackage();
5199 if (target != null) {
5200 Log.w(TAG, "effect broadcast already targeted to " + target);
5201 return;
5202 }
5203 intent.addFlags(Intent.FLAG_INCLUDE_STOPPED_PACKAGES);
5204 // TODO this should target a user-selected panel
5205 List<ResolveInfo> ril = context.getPackageManager().queryBroadcastReceivers(
5206 intent, 0 /* flags */);
5207 if (ril != null && ril.size() != 0) {
5208 ResolveInfo ri = ril.get(0);
5209 if (ri != null && ri.activityInfo != null && ri.activityInfo.packageName != null) {
5210 intent.setPackage(ri.activityInfo.packageName);
5211 context.sendBroadcastAsUser(intent, UserHandle.ALL);
5212 return;
5213 }
5214 }
5215 Log.w(TAG, "couldn't find receiver package for effect intent");
5216 }
5217
Fyodor Kupolovb5013302015-04-17 17:59:14 -07005218 private void killBackgroundUserProcessesWithRecordAudioPermission(UserInfo oldUser) {
5219 PackageManager pm = mContext.getPackageManager();
5220 // Find the home activity of the user. It should not be killed to avoid expensive restart,
5221 // when the user switches back. For managed profiles, we should kill all recording apps
5222 ComponentName homeActivityName = null;
5223 if (!oldUser.isManagedProfile()) {
Wale Ogunwale6767eae2018-05-03 15:52:51 -07005224 homeActivityName = LocalServices.getService(
5225 ActivityTaskManagerInternal.class).getHomeActivityForUser(oldUser.id);
Fyodor Kupolovb5013302015-04-17 17:59:14 -07005226 }
5227 final String[] permissions = { Manifest.permission.RECORD_AUDIO };
5228 List<PackageInfo> packages;
5229 try {
5230 packages = AppGlobals.getPackageManager()
5231 .getPackagesHoldingPermissions(permissions, 0, oldUser.id).getList();
5232 } catch (RemoteException e) {
5233 throw new AndroidRuntimeException(e);
5234 }
5235 for (int j = packages.size() - 1; j >= 0; j--) {
5236 PackageInfo pkg = packages.get(j);
Fyodor Kupolovbcb6c1e2015-05-11 12:05:15 -07005237 // Skip system processes
5238 if (UserHandle.getAppId(pkg.applicationInfo.uid) < FIRST_APPLICATION_UID) {
5239 continue;
5240 }
Amith Yamasanic1cbaab2015-07-21 11:46:14 -07005241 // Skip packages that have permission to interact across users
5242 if (pm.checkPermission(Manifest.permission.INTERACT_ACROSS_USERS, pkg.packageName)
5243 == PackageManager.PERMISSION_GRANTED) {
5244 continue;
5245 }
Fyodor Kupolovb5013302015-04-17 17:59:14 -07005246 if (homeActivityName != null
5247 && pkg.packageName.equals(homeActivityName.getPackageName())
5248 && pkg.applicationInfo.isSystemApp()) {
5249 continue;
5250 }
5251 try {
Svetoslavaa41add2015-08-06 15:03:55 -07005252 final int uid = pkg.applicationInfo.uid;
Sudheer Shankadc589ac2016-11-10 15:30:17 -08005253 ActivityManager.getService().killUid(UserHandle.getAppId(uid),
Svetoslavaa41add2015-08-06 15:03:55 -07005254 UserHandle.getUserId(uid),
Fyodor Kupolovb5013302015-04-17 17:59:14 -07005255 "killBackgroundUserProcessesWithAudioRecordPermission");
5256 } catch (RemoteException e) {
5257 Log.w(TAG, "Error calling killUid", e);
5258 }
5259 }
5260 }
5261
Jean-Michel Trivi3114ce32012-06-11 15:03:52 -07005262
Jean-Michel Trivifa9a6982013-06-27 16:22:58 -07005263 //==========================================================================================
5264 // Audio Focus
5265 //==========================================================================================
Jean-Michel Trivi9228af62018-01-05 17:06:17 -08005266 /**
5267 * Returns whether a focus request is eligible to force ducking.
5268 * Will return true if:
5269 * - the AudioAttributes have a usage of USAGE_ASSISTANCE_ACCESSIBILITY,
5270 * - the focus request is AUDIOFOCUS_GAIN_TRANSIENT_MAY_DUCK,
5271 * - the associated Bundle has KEY_ACCESSIBILITY_FORCE_FOCUS_DUCKING set to true,
5272 * - the uid of the requester is a known accessibility service or root.
5273 * @param aa AudioAttributes of the focus request
5274 * @param uid uid of the focus requester
5275 * @return true if ducking is to be forced
5276 */
5277 private boolean forceFocusDuckingForAccessibility(@Nullable AudioAttributes aa,
5278 int request, int uid) {
5279 if (aa == null || aa.getUsage() != AudioAttributes.USAGE_ASSISTANCE_ACCESSIBILITY
5280 || request != AudioManager.AUDIOFOCUS_GAIN_TRANSIENT_MAY_DUCK) {
5281 return false;
5282 }
5283 final Bundle extraInfo = aa.getBundle();
5284 if (extraInfo == null ||
5285 !extraInfo.getBoolean(AudioFocusRequest.KEY_ACCESSIBILITY_FORCE_FOCUS_DUCKING)) {
5286 return false;
5287 }
5288 if (uid == 0) {
5289 return true;
5290 }
5291 synchronized (mAccessibilityServiceUidsLock) {
5292 if (mAccessibilityServiceUids != null) {
5293 int callingUid = Binder.getCallingUid();
5294 for (int i = 0; i < mAccessibilityServiceUids.length; i++) {
5295 if (mAccessibilityServiceUids[i] == callingUid) {
5296 return true;
5297 }
5298 }
5299 }
5300 }
5301 return false;
5302 }
5303
Jean-Michel Trivifd6ad742014-11-10 14:38:30 -08005304 public int requestAudioFocus(AudioAttributes aa, int durationHint, IBinder cb,
Jean-Michel Trivi958876f2014-11-16 15:40:22 -08005305 IAudioFocusDispatcher fd, String clientId, String callingPackageName, int flags,
Jean-Michel Trivi461922f2017-04-25 15:23:17 -07005306 IAudioPolicyCallback pcb, int sdk) {
Jean-Michel Trivi958876f2014-11-16 15:40:22 -08005307 // permission checks
5308 if ((flags & AudioManager.AUDIOFOCUS_FLAG_LOCK) == AudioManager.AUDIOFOCUS_FLAG_LOCK) {
John Spurlock61560172015-02-06 19:46:04 -05005309 if (AudioSystem.IN_VOICE_COMM_FOCUS_ID.equals(clientId)) {
Jean-Michel Trivi958876f2014-11-16 15:40:22 -08005310 if (PackageManager.PERMISSION_GRANTED != mContext.checkCallingOrSelfPermission(
5311 android.Manifest.permission.MODIFY_PHONE_STATE)) {
5312 Log.e(TAG, "Invalid permission to (un)lock audio focus", new Exception());
5313 return AudioManager.AUDIOFOCUS_REQUEST_FAILED;
5314 }
5315 } else {
5316 // only a registered audio policy can be used to lock focus
5317 synchronized (mAudioPolicies) {
Jean-Michel Trivi0212be52014-11-24 14:43:10 -08005318 if (!mAudioPolicies.containsKey(pcb.asBinder())) {
5319 Log.e(TAG, "Invalid unregistered AudioPolicy to (un)lock audio focus");
Jean-Michel Trivi958876f2014-11-16 15:40:22 -08005320 return AudioManager.AUDIOFOCUS_REQUEST_FAILED;
5321 }
5322 }
5323 }
5324 }
5325
Jean-Michel Trivifd6ad742014-11-10 14:38:30 -08005326 return mMediaFocusControl.requestAudioFocus(aa, durationHint, cb, fd,
Jean-Michel Trivi9228af62018-01-05 17:06:17 -08005327 clientId, callingPackageName, flags, sdk,
5328 forceFocusDuckingForAccessibility(aa, durationHint, Binder.getCallingUid()));
Jean-Michel Trivifa9a6982013-06-27 16:22:58 -07005329 }
5330
Jean-Michel Trivi126cf032017-04-02 23:19:02 -07005331 public int abandonAudioFocus(IAudioFocusDispatcher fd, String clientId, AudioAttributes aa,
5332 String callingPackageName) {
5333 return mMediaFocusControl.abandonAudioFocus(fd, clientId, aa, callingPackageName);
Jean-Michel Trivifa9a6982013-06-27 16:22:58 -07005334 }
5335
5336 public void unregisterAudioFocusClient(String clientId) {
5337 mMediaFocusControl.unregisterAudioFocusClient(clientId);
Jean-Michel Trivi3114ce32012-06-11 15:03:52 -07005338 }
5339
Jean-Michel Trivi23805662013-07-31 14:19:18 -07005340 public int getCurrentAudioFocus() {
5341 return mMediaFocusControl.getCurrentAudioFocus();
5342 }
5343
Jean-Michel Trivi99489cc2017-01-25 19:08:49 -08005344 public int getFocusRampTimeMs(int focusGain, AudioAttributes attr) {
5345 return mMediaFocusControl.getFocusRampTimeMs(focusGain, attr);
5346 }
5347
Jean-Michel Trivi126cf032017-04-02 23:19:02 -07005348 //==========================================================================================
John Spurlock5e783732015-02-19 10:28:59 -05005349 private boolean readCameraSoundForced() {
5350 return SystemProperties.getBoolean("audio.camerasound.force", false) ||
5351 mContext.getResources().getBoolean(
5352 com.android.internal.R.bool.config_camera_sound_forced);
5353 }
5354
Jean-Michel Trivif26f0172012-04-25 16:23:20 -07005355 //==========================================================================================
5356 // Device orientation
5357 //==========================================================================================
5358 /**
Mikhail Naganovb668bc62018-02-13 13:46:38 -08005359 * Handles device configuration changes that may map to a change in rotation.
5360 * Monitoring rotation is optional, and is defined by the definition and value
5361 * of the "ro.audio.monitorRotation" system property.
Jean-Michel Trivif26f0172012-04-25 16:23:20 -07005362 */
5363 private void handleConfigurationChanged(Context context) {
5364 try {
Mikhail Naganovb668bc62018-02-13 13:46:38 -08005365 // reading new configuration "safely" (i.e. under try catch) in case anything
5366 // goes wrong.
Eric Laurentd640bd32012-09-28 18:01:48 -07005367 Configuration config = context.getResources().getConfiguration();
Eric Laurentd640bd32012-09-28 18:01:48 -07005368 sendMsg(mAudioHandler,
5369 MSG_CONFIGURE_SAFE_MEDIA_VOLUME,
5370 SENDMSG_REPLACE,
5371 0,
5372 0,
John Spurlock90874332015-03-10 16:00:54 -04005373 TAG,
Eric Laurentd640bd32012-09-28 18:01:48 -07005374 0);
Eric Laurentdd45d012012-10-08 09:04:34 -07005375
John Spurlock5e783732015-02-19 10:28:59 -05005376 boolean cameraSoundForced = readCameraSoundForced();
Eric Laurentdd45d012012-10-08 09:04:34 -07005377 synchronized (mSettingsLock) {
Jean-Michel Trivi8719a1d2017-11-06 11:52:51 -08005378 final boolean cameraSoundForcedChanged = (cameraSoundForced != mCameraSoundForced);
5379 mCameraSoundForced = cameraSoundForced;
Eric Laurent8fa4d6f2014-10-30 14:13:03 -07005380 if (cameraSoundForcedChanged) {
Muyuan Li1ed6df62016-06-18 11:16:52 -07005381 if (!mIsSingleVolume) {
Jean-Michel Trivi085346a2018-02-14 10:48:51 -08005382 synchronized (VolumeStreamState.class) {
5383 VolumeStreamState s = mStreamStates[AudioSystem.STREAM_SYSTEM_ENFORCED];
5384 if (cameraSoundForced) {
5385 s.setAllIndexesToMax();
5386 mRingerModeAffectedStreams &=
5387 ~(1 << AudioSystem.STREAM_SYSTEM_ENFORCED);
5388 } else {
5389 s.setAllIndexes(mStreamStates[AudioSystem.STREAM_SYSTEM], TAG);
5390 mRingerModeAffectedStreams |=
5391 (1 << AudioSystem.STREAM_SYSTEM_ENFORCED);
5392 }
Eric Laurent8fa4d6f2014-10-30 14:13:03 -07005393 }
5394 // take new state into account for streams muted by ringer mode
John Spurlock661f2cf2014-11-17 10:29:10 -05005395 setRingerModeInt(getRingerModeInternal(), false);
Eric Laurent8fa4d6f2014-10-30 14:13:03 -07005396 }
Jean-Michel Trivi58850372018-09-14 16:01:28 -07005397 mDeviceBroker.setForceUse_Async(AudioSystem.FOR_SYSTEM,
Eric Laurent8fa4d6f2014-10-30 14:13:03 -07005398 cameraSoundForced ?
5399 AudioSystem.FORCE_SYSTEM_ENFORCED : AudioSystem.FORCE_NONE,
Jean-Michel Trivi58850372018-09-14 16:01:28 -07005400 "handleConfigurationChanged");
Eric Laurent8fa4d6f2014-10-30 14:13:03 -07005401 sendMsg(mAudioHandler,
5402 MSG_SET_ALL_VOLUMES,
5403 SENDMSG_QUEUE,
5404 0,
5405 0,
5406 mStreamStates[AudioSystem.STREAM_SYSTEM_ENFORCED], 0);
Jean-Michel Trivi58850372018-09-14 16:01:28 -07005407
Eric Laurent8fa4d6f2014-10-30 14:13:03 -07005408 }
Eric Laurentdd45d012012-10-08 09:04:34 -07005409 }
John Spurlock3346a802014-05-20 16:25:37 -04005410 mVolumeController.setLayoutDirection(config.getLayoutDirection());
Jean-Michel Trivif26f0172012-04-25 16:23:20 -07005411 } catch (Exception e) {
Jean-Michel Trivibb6f8712013-05-23 15:02:41 -07005412 Log.e(TAG, "Error handling configuration change: ", e);
Jean-Michel Trivif26f0172012-04-25 16:23:20 -07005413 }
5414 }
5415
Jean-Michel Trivid5176cf2010-01-28 11:56:42 -08005416 @Override
Jeff Sharkey098d5802012-04-26 17:30:34 -07005417 public void setRingtonePlayer(IRingtonePlayer player) {
5418 mContext.enforceCallingOrSelfPermission(REMOTE_AUDIO_PLAYBACK, null);
5419 mRingtonePlayer = player;
5420 }
5421
5422 @Override
5423 public IRingtonePlayer getRingtonePlayer() {
5424 return mRingtonePlayer;
5425 }
5426
5427 @Override
Dianne Hackborn632ca412012-06-14 19:34:10 -07005428 public AudioRoutesInfo startWatchingRoutes(IAudioRoutesObserver observer) {
Jean-Michel Trivi58850372018-09-14 16:01:28 -07005429 return mDeviceBroker.startWatchingRoutes(observer);
Dianne Hackborn632ca412012-06-14 19:34:10 -07005430 }
5431
Eric Laurentc34dcc12012-09-10 13:51:52 -07005432
5433 //==========================================================================================
5434 // Safe media volume management.
5435 // MUSIC stream volume level is limited when headphones are connected according to safety
5436 // regulation. When the user attempts to raise the volume above the limit, a warning is
5437 // displayed and the user has to acknowlegde before the volume is actually changed.
5438 // The volume index corresponding to the limit is stored in config_safe_media_volume_index
5439 // property. Platforms with a different limit must set this property accordingly in their
5440 // overlay.
5441 //==========================================================================================
5442
Eric Laurentd640bd32012-09-28 18:01:48 -07005443 // mSafeMediaVolumeState indicates whether the media volume is limited over headphones.
5444 // It is SAFE_MEDIA_VOLUME_NOT_CONFIGURED at boot time until a network service is connected
5445 // or the configure time is elapsed. It is then set to SAFE_MEDIA_VOLUME_ACTIVE or
5446 // SAFE_MEDIA_VOLUME_DISABLED according to country option. If not SAFE_MEDIA_VOLUME_DISABLED, it
5447 // can be set to SAFE_MEDIA_VOLUME_INACTIVE by calling AudioService.disableSafeMediaVolume()
5448 // (when user opts out).
John Spurlock35134602014-07-24 18:10:48 -04005449 private static final int SAFE_MEDIA_VOLUME_NOT_CONFIGURED = 0;
5450 private static final int SAFE_MEDIA_VOLUME_DISABLED = 1;
5451 private static final int SAFE_MEDIA_VOLUME_INACTIVE = 2; // confirmed
5452 private static final int SAFE_MEDIA_VOLUME_ACTIVE = 3; // unconfirmed
hyomin.ohd0446dc2018-10-18 13:58:27 +09005453 private int mSafeMediaVolumeState;
5454 private final Object mSafeMediaVolumeStateLock = new Object();
Eric Laurentd640bd32012-09-28 18:01:48 -07005455
5456 private int mMcc = 0;
Eric Laurentc34dcc12012-09-10 13:51:52 -07005457 // mSafeMediaVolumeIndex is the cached value of config_safe_media_volume_index property
Eric Laurentd640bd32012-09-28 18:01:48 -07005458 private int mSafeMediaVolumeIndex;
John Muir8b8bddd2018-02-16 14:29:14 -08005459 // mSafeUsbMediaVolumeDbfs is the cached value of the config_safe_media_volume_usb_mB
5460 // property, divided by 100.0.
5461 private float mSafeUsbMediaVolumeDbfs;
Eric Laurentb378a13a2017-07-11 14:08:11 -07005462 // mSafeUsbMediaVolumeIndex is used for USB Headsets and is the music volume UI index
John Muir8b8bddd2018-02-16 14:29:14 -08005463 // corresponding to a gain of mSafeUsbMediaVolumeDbfs (defaulting to -37dB) in audio
5464 // flinger mixer.
Eric Laurent0e5deb32017-09-01 15:12:42 -07005465 // We remove -22 dBs from the theoretical -15dB to account for the EQ + bass boost
5466 // amplification when both effects are on with all band gains at maximum.
Eric Laurentb378a13a2017-07-11 14:08:11 -07005467 // This level corresponds to a loudness of 85 dB SPL for the warning to be displayed when
5468 // the headset is compliant to EN 60950 with a max loudness of 100dB SPL.
Eric Laurenteab40d12017-06-09 12:45:21 -07005469 private int mSafeUsbMediaVolumeIndex;
Eric Laurentc34dcc12012-09-10 13:51:52 -07005470 // mSafeMediaVolumeDevices lists the devices for which safe media volume is enforced,
Jean-Michel Trivi58850372018-09-14 16:01:28 -07005471 /*package*/ final int mSafeMediaVolumeDevices = AudioSystem.DEVICE_OUT_WIRED_HEADSET
5472 | AudioSystem.DEVICE_OUT_WIRED_HEADPHONE
5473 | AudioSystem.DEVICE_OUT_USB_HEADSET;
Eric Laurentc34dcc12012-09-10 13:51:52 -07005474 // mMusicActiveMs is the cumulative time of music activity since safe volume was disabled.
5475 // When this time reaches UNSAFE_VOLUME_MUSIC_ACTIVE_MS_MAX, the safe media volume is re-enabled
5476 // automatically. mMusicActiveMs is rounded to a multiple of MUSIC_ACTIVE_POLL_PERIOD_MS.
5477 private int mMusicActiveMs;
5478 private static final int UNSAFE_VOLUME_MUSIC_ACTIVE_MS_MAX = (20 * 3600 * 1000); // 20 hours
5479 private static final int MUSIC_ACTIVE_POLL_PERIOD_MS = 60000; // 1 minute polling interval
Eric Laurentd640bd32012-09-28 18:01:48 -07005480 private static final int SAFE_VOLUME_CONFIGURE_TIMEOUT_MS = 30000; // 30s after boot completed
Eric Laurentc34dcc12012-09-10 13:51:52 -07005481
Eric Laurenteab40d12017-06-09 12:45:21 -07005482 private int safeMediaVolumeIndex(int device) {
5483 if ((device & mSafeMediaVolumeDevices) == 0) {
5484 return MAX_STREAM_VOLUME[AudioSystem.STREAM_MUSIC];
5485 }
5486 if (device == AudioSystem.DEVICE_OUT_USB_HEADSET) {
5487 return mSafeUsbMediaVolumeIndex;
5488 } else {
5489 return mSafeMediaVolumeIndex;
5490 }
5491 }
5492
John Spurlock90874332015-03-10 16:00:54 -04005493 private void setSafeMediaVolumeEnabled(boolean on, String caller) {
hyomin.ohd0446dc2018-10-18 13:58:27 +09005494 synchronized (mSafeMediaVolumeStateLock) {
Eric Laurentd640bd32012-09-28 18:01:48 -07005495 if ((mSafeMediaVolumeState != SAFE_MEDIA_VOLUME_NOT_CONFIGURED) &&
5496 (mSafeMediaVolumeState != SAFE_MEDIA_VOLUME_DISABLED)) {
5497 if (on && (mSafeMediaVolumeState == SAFE_MEDIA_VOLUME_INACTIVE)) {
5498 mSafeMediaVolumeState = SAFE_MEDIA_VOLUME_ACTIVE;
John Spurlock90874332015-03-10 16:00:54 -04005499 enforceSafeMediaVolume(caller);
Eric Laurentd640bd32012-09-28 18:01:48 -07005500 } else if (!on && (mSafeMediaVolumeState == SAFE_MEDIA_VOLUME_ACTIVE)) {
5501 mSafeMediaVolumeState = SAFE_MEDIA_VOLUME_INACTIVE;
John Spurlockaa5ee4d2014-07-25 13:05:12 -04005502 mMusicActiveMs = 1; // nonzero = confirmed
5503 saveMusicActiveMs();
Eric Laurentd640bd32012-09-28 18:01:48 -07005504 sendMsg(mAudioHandler,
5505 MSG_CHECK_MUSIC_ACTIVE,
5506 SENDMSG_REPLACE,
5507 0,
5508 0,
John Spurlock90874332015-03-10 16:00:54 -04005509 caller,
Eric Laurentd640bd32012-09-28 18:01:48 -07005510 MUSIC_ACTIVE_POLL_PERIOD_MS);
5511 }
Eric Laurentc34dcc12012-09-10 13:51:52 -07005512 }
Eric Laurentc34dcc12012-09-10 13:51:52 -07005513 }
5514 }
5515
John Spurlock90874332015-03-10 16:00:54 -04005516 private void enforceSafeMediaVolume(String caller) {
Eric Laurentc34dcc12012-09-10 13:51:52 -07005517 VolumeStreamState streamState = mStreamStates[AudioSystem.STREAM_MUSIC];
Eric Laurentc34dcc12012-09-10 13:51:52 -07005518 int devices = mSafeMediaVolumeDevices;
5519 int i = 0;
5520
5521 while (devices != 0) {
5522 int device = 1 << i++;
5523 if ((device & devices) == 0) {
5524 continue;
5525 }
Eric Laurent42b041e2013-03-29 11:36:03 -07005526 int index = streamState.getIndex(device);
Eric Laurenteab40d12017-06-09 12:45:21 -07005527 if (index > safeMediaVolumeIndex(device)) {
5528 streamState.setIndex(safeMediaVolumeIndex(device), device, caller);
Eric Laurent42b041e2013-03-29 11:36:03 -07005529 sendMsg(mAudioHandler,
5530 MSG_SET_DEVICE_VOLUME,
5531 SENDMSG_QUEUE,
5532 device,
5533 0,
5534 streamState,
5535 0);
Eric Laurentc34dcc12012-09-10 13:51:52 -07005536 }
5537 devices &= ~device;
5538 }
5539 }
5540
5541 private boolean checkSafeMediaVolume(int streamType, int index, int device) {
hyomin.ohd0446dc2018-10-18 13:58:27 +09005542 synchronized (mSafeMediaVolumeStateLock) {
Eric Laurentd640bd32012-09-28 18:01:48 -07005543 if ((mSafeMediaVolumeState == SAFE_MEDIA_VOLUME_ACTIVE) &&
Eric Laurentc34dcc12012-09-10 13:51:52 -07005544 (mStreamVolumeAlias[streamType] == AudioSystem.STREAM_MUSIC) &&
5545 ((device & mSafeMediaVolumeDevices) != 0) &&
Eric Laurenteab40d12017-06-09 12:45:21 -07005546 (index > safeMediaVolumeIndex(device))) {
Eric Laurentc34dcc12012-09-10 13:51:52 -07005547 return false;
5548 }
5549 return true;
5550 }
5551 }
5552
John Spurlock3346a802014-05-20 16:25:37 -04005553 @Override
John Spurlock90874332015-03-10 16:00:54 -04005554 public void disableSafeMediaVolume(String callingPackage) {
John Spurlockcdb57ae2015-02-11 19:04:11 -05005555 enforceVolumeController("disable the safe media volume");
hyomin.ohd0446dc2018-10-18 13:58:27 +09005556 synchronized (mSafeMediaVolumeStateLock) {
John Spurlock90874332015-03-10 16:00:54 -04005557 setSafeMediaVolumeEnabled(false, callingPackage);
Eric Laurentfde16d52012-12-03 14:42:39 -08005558 if (mPendingVolumeCommand != null) {
5559 onSetStreamVolume(mPendingVolumeCommand.mStreamType,
5560 mPendingVolumeCommand.mIndex,
5561 mPendingVolumeCommand.mFlags,
John Spurlock90874332015-03-10 16:00:54 -04005562 mPendingVolumeCommand.mDevice,
5563 callingPackage);
Eric Laurentfde16d52012-12-03 14:42:39 -08005564 mPendingVolumeCommand = null;
5565 }
Eric Laurentc34dcc12012-09-10 13:51:52 -07005566 }
5567 }
5568
Jungshik Jang41d97462014-06-30 22:26:29 +09005569 //==========================================================================================
5570 // Hdmi Cec system audio mode.
John Spurlockbc82b122015-03-02 16:12:38 -05005571 // If Hdmi Cec's system audio mode is on, audio service should send the volume change
5572 // to HdmiControlService so that the audio receiver can handle it.
Jungshik Jang41d97462014-06-30 22:26:29 +09005573 //==========================================================================================
5574
Eric Laurent212532b2014-07-21 15:43:18 -07005575 private class MyDisplayStatusCallback implements HdmiPlaybackClient.DisplayStatusCallback {
5576 public void onComplete(int status) {
Shubangc480a712018-06-11 18:02:42 -07005577 synchronized (mHdmiClientLock) {
5578 if (mHdmiManager != null) {
Eric Laurent212532b2014-07-21 15:43:18 -07005579 mHdmiCecSink = (status != HdmiControlManager.POWER_STATUS_UNKNOWN);
5580 // Television devices without CEC service apply software volume on HDMI output
5581 if (isPlatformTelevision() && !mHdmiCecSink) {
5582 mFixedVolumeDevices &= ~AudioSystem.DEVICE_OUT_HDMI;
5583 }
5584 checkAllFixedVolumeDevices();
5585 }
5586 }
5587 }
Shubangc480a712018-06-11 18:02:42 -07005588 }
5589
5590 private final Object mHdmiClientLock = new Object();
Eric Laurent212532b2014-07-21 15:43:18 -07005591
Jungshik Jang41d97462014-06-30 22:26:29 +09005592 // If HDMI-CEC system audio is supported
5593 private boolean mHdmiSystemAudioSupported = false;
5594 // Set only when device is tv.
Shubangc480a712018-06-11 18:02:42 -07005595 @GuardedBy("mHdmiClientLock")
Jungshik Jang41d97462014-06-30 22:26:29 +09005596 private HdmiTvClient mHdmiTvClient;
Eric Laurent0b03f992014-11-18 18:08:02 -08005597 // true if the device has system feature PackageManager.FEATURE_LEANBACK.
Eric Laurent212532b2014-07-21 15:43:18 -07005598 // cached HdmiControlManager interface
Shubangc480a712018-06-11 18:02:42 -07005599 @GuardedBy("mHdmiClientLock")
Eric Laurent212532b2014-07-21 15:43:18 -07005600 private HdmiControlManager mHdmiManager;
5601 // Set only when device is a set-top box.
Shubangc480a712018-06-11 18:02:42 -07005602 @GuardedBy("mHdmiClientLock")
Eric Laurent212532b2014-07-21 15:43:18 -07005603 private HdmiPlaybackClient mHdmiPlaybackClient;
5604 // true if we are a set-top box, an HDMI sink is connected and it supports CEC.
5605 private boolean mHdmiCecSink;
Shubangc480a712018-06-11 18:02:42 -07005606 // Set only when device is an audio system.
5607 @GuardedBy("mHdmiClientLock")
5608 private HdmiAudioSystemClient mHdmiAudioSystemClient;
Eric Laurent212532b2014-07-21 15:43:18 -07005609
5610 private MyDisplayStatusCallback mHdmiDisplayStatusCallback = new MyDisplayStatusCallback();
Jungshik Jang41d97462014-06-30 22:26:29 +09005611
5612 @Override
Jungshik Jang12307ca2014-07-15 19:27:56 +09005613 public int setHdmiSystemAudioSupported(boolean on) {
Eric Laurent212532b2014-07-21 15:43:18 -07005614 int device = AudioSystem.DEVICE_NONE;
Shubangc480a712018-06-11 18:02:42 -07005615 synchronized (mHdmiClientLock) {
5616 if (mHdmiManager != null) {
Shubangde728822018-07-16 16:46:51 -07005617 if (mHdmiTvClient == null && mHdmiAudioSystemClient == null) {
5618 Log.w(TAG, "Only Hdmi-Cec enabled TV or audio system device supports"
5619 + "system audio mode.");
Eric Laurent212532b2014-07-21 15:43:18 -07005620 return device;
5621 }
Shubangc480a712018-06-11 18:02:42 -07005622 if (mHdmiSystemAudioSupported != on) {
5623 mHdmiSystemAudioSupported = on;
5624 final int config = on ? AudioSystem.FORCE_HDMI_SYSTEM_AUDIO_ENFORCED :
5625 AudioSystem.FORCE_NONE;
Jean-Michel Trivi58850372018-09-14 16:01:28 -07005626 mDeviceBroker.setForceUse_Async(AudioSystem.FOR_HDMI_SYSTEM_AUDIO, config,
5627 "setHdmiSystemAudioSupported");
Eric Laurent212532b2014-07-21 15:43:18 -07005628 }
Shubangc480a712018-06-11 18:02:42 -07005629 device = getDevicesForStream(AudioSystem.STREAM_MUSIC);
Jungshik Jang6f34f5a2014-07-08 21:17:29 +09005630 }
Jungshik Jang6f34f5a2014-07-08 21:17:29 +09005631 }
Eric Laurent212532b2014-07-21 15:43:18 -07005632 return device;
Jungshik Jang6f34f5a2014-07-08 21:17:29 +09005633 }
Jungshik Jang41d97462014-06-30 22:26:29 +09005634
Terry Heoe7d6d972014-09-04 21:05:28 +09005635 @Override
5636 public boolean isHdmiSystemAudioSupported() {
5637 return mHdmiSystemAudioSupported;
5638 }
5639
Eric Laurentdd45d012012-10-08 09:04:34 -07005640 //==========================================================================================
Jean-Michel Triviac487672016-11-11 10:05:18 -08005641 // Accessibility
5642
Jean-Michel Trivicfa55532017-01-18 11:17:51 -08005643 private void initA11yMonitoring() {
5644 final AccessibilityManager accessibilityManager =
5645 (AccessibilityManager) mContext.getSystemService(Context.ACCESSIBILITY_SERVICE);
Jean-Michel Triviac487672016-11-11 10:05:18 -08005646 updateDefaultStreamOverrideDelay(accessibilityManager.isTouchExplorationEnabled());
Jean-Michel Trivi7592b982017-02-01 15:12:15 -08005647 updateA11yVolumeAlias(accessibilityManager.isAccessibilityVolumeStreamActive());
Phil Weaver26d709f2017-04-20 17:19:14 -07005648 accessibilityManager.addTouchExplorationStateChangeListener(this, null);
5649 accessibilityManager.addAccessibilityServicesStateChangeListener(this, null);
Jean-Michel Triviac487672016-11-11 10:05:18 -08005650 }
5651
5652 //---------------------------------------------------------------------------------
5653 // A11y: taking touch exploration into account for selecting the default
Jean-Michel Trivi873cc452014-09-11 17:25:09 -07005654 // stream override timeout when adjusting volume
Jean-Michel Triviac487672016-11-11 10:05:18 -08005655 //---------------------------------------------------------------------------------
Jean-Michel Trivi873cc452014-09-11 17:25:09 -07005656
Jean-Michel Triviac487672016-11-11 10:05:18 -08005657 // - STREAM_NOTIFICATION on tablets during this period after a notification stopped
Julia Reynoldsd9e96e22017-11-07 10:33:08 -05005658 // - STREAM_RING on phones during this period after a notification stopped
5659 // - STREAM_MUSIC otherwise
5660
Jean-Michel Triviac487672016-11-11 10:05:18 -08005661 private static final int DEFAULT_STREAM_TYPE_OVERRIDE_DELAY_MS = 0;
5662 private static final int TOUCH_EXPLORE_STREAM_TYPE_OVERRIDE_DELAY_MS = 1000;
Jean-Michel Trivi873cc452014-09-11 17:25:09 -07005663
Jean-Michel Triviac487672016-11-11 10:05:18 -08005664 private static int sStreamOverrideDelayMs;
Jean-Michel Trivi873cc452014-09-11 17:25:09 -07005665
Jean-Michel Triviac487672016-11-11 10:05:18 -08005666 @Override
5667 public void onTouchExplorationStateChanged(boolean enabled) {
5668 updateDefaultStreamOverrideDelay(enabled);
5669 }
5670
5671 private void updateDefaultStreamOverrideDelay(boolean touchExploreEnabled) {
5672 if (touchExploreEnabled) {
5673 sStreamOverrideDelayMs = TOUCH_EXPLORE_STREAM_TYPE_OVERRIDE_DELAY_MS;
5674 } else {
5675 sStreamOverrideDelayMs = DEFAULT_STREAM_TYPE_OVERRIDE_DELAY_MS;
Jean-Michel Trivi873cc452014-09-11 17:25:09 -07005676 }
Jean-Michel Triviac487672016-11-11 10:05:18 -08005677 if (DEBUG_VOL) Log.d(TAG, "Touch exploration enabled=" + touchExploreEnabled
5678 + " stream override delay is now " + sStreamOverrideDelayMs + " ms");
5679 }
Jean-Michel Trivi873cc452014-09-11 17:25:09 -07005680
Jean-Michel Triviac487672016-11-11 10:05:18 -08005681 //---------------------------------------------------------------------------------
5682 // A11y: taking a11y state into account for the handling of a11y prompts volume
5683 //---------------------------------------------------------------------------------
Jean-Michel Trivi873cc452014-09-11 17:25:09 -07005684
Jean-Michel Triviac487672016-11-11 10:05:18 -08005685 private static boolean sIndependentA11yVolume = false;
5686
Jean-Michel Trivicfa55532017-01-18 11:17:51 -08005687 // implementation of AccessibilityServicesStateChangeListener
5688 @Override
Phil Weaver4cab9302017-03-30 15:27:39 -07005689 public void onAccessibilityServicesStateChanged(AccessibilityManager accessibilityManager) {
Jean-Michel Trivicfa55532017-01-18 11:17:51 -08005690 updateA11yVolumeAlias(accessibilityManager.isAccessibilityVolumeStreamActive());
5691 }
5692
5693 private void updateA11yVolumeAlias(boolean a11VolEnabled) {
5694 if (DEBUG_VOL) Log.d(TAG, "Accessibility volume enabled = " + a11VolEnabled);
5695 if (sIndependentA11yVolume != a11VolEnabled) {
5696 sIndependentA11yVolume = a11VolEnabled;
5697 // update the volume mapping scheme
5698 updateStreamVolumeAlias(true /*updateVolumes*/, TAG);
5699 // update the volume controller behavior
5700 mVolumeController.setA11yMode(sIndependentA11yVolume ?
5701 VolumePolicy.A11Y_MODE_INDEPENDENT_A11Y_VOLUME :
5702 VolumePolicy.A11Y_MODE_MEDIA_A11Y_VOLUME);
Jean-Michel Trivia53b7052017-04-12 18:27:01 -07005703 mVolumeController.postVolumeChanged(AudioManager.STREAM_ACCESSIBILITY, 0);
Jean-Michel Trivicfa55532017-01-18 11:17:51 -08005704 }
Jean-Michel Trivi873cc452014-09-11 17:25:09 -07005705 }
5706
5707 //==========================================================================================
Eric Laurentdd45d012012-10-08 09:04:34 -07005708 // Camera shutter sound policy.
5709 // config_camera_sound_forced configuration option in config.xml defines if the camera shutter
5710 // sound is forced (sound even if the device is in silent mode) or not. This option is false by
5711 // default and can be overridden by country specific overlay in values-mccXXX/config.xml.
5712 //==========================================================================================
5713
5714 // cached value of com.android.internal.R.bool.config_camera_sound_forced
Jean-Michel Trivi8719a1d2017-11-06 11:52:51 -08005715 @GuardedBy("mSettingsLock")
5716 private boolean mCameraSoundForced;
Eric Laurentdd45d012012-10-08 09:04:34 -07005717
5718 // called by android.hardware.Camera to populate CameraInfo.canDisableShutterSound
5719 public boolean isCameraSoundForced() {
Jean-Michel Trivi8719a1d2017-11-06 11:52:51 -08005720 synchronized (mSettingsLock) {
Eric Laurentdd45d012012-10-08 09:04:34 -07005721 return mCameraSoundForced;
5722 }
5723 }
5724
Jean-Michel Trivi011f39e2017-08-19 18:08:06 -07005725 //==========================================================================================
5726 // AudioService logging and dumpsys
5727 //==========================================================================================
Jean-Michel Trivi3bf75782018-07-02 10:48:04 -07005728 static final int LOG_NB_EVENTS_PHONE_STATE = 20;
5729 static final int LOG_NB_EVENTS_DEVICE_CONNECTION = 30;
5730 static final int LOG_NB_EVENTS_FORCE_USE = 20;
5731 static final int LOG_NB_EVENTS_VOLUME = 40;
5732 static final int LOG_NB_EVENTS_DYN_POLICY = 10;
Jean-Michel Trivi011f39e2017-08-19 18:08:06 -07005733
5734 final private AudioEventLogger mModeLogger = new AudioEventLogger(LOG_NB_EVENTS_PHONE_STATE,
5735 "phone state (logged after successfull call to AudioSystem.setPhoneState(int))");
5736
Jean-Michel Trivi3bf75782018-07-02 10:48:04 -07005737 // logs for wired + A2DP device connections:
5738 // - wired: logged before onSetWiredDeviceConnectionState() is executed
5739 // - A2DP: logged at reception of method call
Jean-Michel Trivi58850372018-09-14 16:01:28 -07005740 /*package*/ static final AudioEventLogger sDeviceLogger = new AudioEventLogger(
5741 LOG_NB_EVENTS_DEVICE_CONNECTION, "wired/A2DP/hearing aid device connection BLABLI");
Jean-Michel Trivi011f39e2017-08-19 18:08:06 -07005742
Jean-Michel Trivi58850372018-09-14 16:01:28 -07005743 static final AudioEventLogger sForceUseLogger = new AudioEventLogger(
Jean-Michel Trivi011f39e2017-08-19 18:08:06 -07005744 LOG_NB_EVENTS_FORCE_USE,
5745 "force use (logged before setForceUse() is executed)");
5746
Jean-Michel Trivi58850372018-09-14 16:01:28 -07005747 static final AudioEventLogger sVolumeLogger = new AudioEventLogger(LOG_NB_EVENTS_VOLUME,
Jean-Michel Trivicf170362017-08-24 17:24:57 -07005748 "volume changes (logged when command received by AudioService)");
5749
Jean-Michel Trivi12a86762018-04-24 16:57:49 -07005750 final private AudioEventLogger mDynPolicyLogger = new AudioEventLogger(LOG_NB_EVENTS_DYN_POLICY,
5751 "dynamic policy events (logged when command received by AudioService)");
5752
Eric Laurentdd45d012012-10-08 09:04:34 -07005753 private static final String[] RINGER_MODE_NAMES = new String[] {
5754 "SILENT",
5755 "VIBRATE",
5756 "NORMAL"
5757 };
5758
5759 private void dumpRingerMode(PrintWriter pw) {
5760 pw.println("\nRinger mode: ");
John Spurlock661f2cf2014-11-17 10:29:10 -05005761 pw.println("- mode (internal) = " + RINGER_MODE_NAMES[mRingerMode]);
5762 pw.println("- mode (external) = " + RINGER_MODE_NAMES[mRingerModeExternal]);
John Spurlock50ced3f2015-05-11 16:00:09 -04005763 dumpRingerModeStreams(pw, "affected", mRingerModeAffectedStreams);
Beverlyd6964762018-02-16 14:07:03 -05005764 dumpRingerModeStreams(pw, "muted", mRingerAndZenModeMutedStreams);
John Spurlock661f2cf2014-11-17 10:29:10 -05005765 pw.print("- delegate = "); pw.println(mRingerModeDelegate);
Eric Laurentdd45d012012-10-08 09:04:34 -07005766 }
5767
John Spurlock50ced3f2015-05-11 16:00:09 -04005768 private void dumpRingerModeStreams(PrintWriter pw, String type, int streams) {
5769 pw.print("- ringer mode "); pw.print(type); pw.print(" streams = 0x");
5770 pw.print(Integer.toHexString(streams));
5771 if (streams != 0) {
5772 pw.print(" (");
5773 boolean first = true;
5774 for (int i = 0; i < AudioSystem.STREAM_NAMES.length; i++) {
5775 final int stream = (1 << i);
5776 if ((streams & stream) != 0) {
5777 if (!first) pw.print(',');
5778 pw.print(AudioSystem.STREAM_NAMES[i]);
5779 streams &= ~stream;
5780 first = false;
5781 }
5782 }
5783 if (streams != 0) {
5784 if (!first) pw.print(',');
5785 pw.print(streams);
5786 }
5787 pw.print(')');
5788 }
5789 pw.println();
5790 }
5791
Dianne Hackborn632ca412012-06-14 19:34:10 -07005792 @Override
Jean-Michel Trivid5176cf2010-01-28 11:56:42 -08005793 protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
Jeff Sharkeyfe9a53b2017-03-31 14:08:23 -06005794 if (!DumpUtils.checkDumpPermission(mContext, TAG, pw)) return;
Jeff Sharkeyeb4cc4922012-04-26 18:17:29 -07005795
Jean-Michel Trivifa9a6982013-06-27 16:22:58 -07005796 mMediaFocusControl.dump(pw);
Eric Laurentbffc3d12012-05-07 17:43:49 -07005797 dumpStreamStates(pw);
Eric Laurentdd45d012012-10-08 09:04:34 -07005798 dumpRingerMode(pw);
Dianne Hackborn632ca412012-06-14 19:34:10 -07005799 pw.println("\nAudio routes:");
Jean-Michel Trivi58850372018-09-14 16:01:28 -07005800 pw.print(" mMainType=0x"); pw.println(Integer.toHexString(
5801 mDeviceBroker.getCurAudioRoutes().mainType));
5802 pw.print(" mBluetoothName="); pw.println(mDeviceBroker.getCurAudioRoutes().bluetoothName);
John Spurlock35134602014-07-24 18:10:48 -04005803
5804 pw.println("\nOther state:");
John Spurlock3346a802014-05-20 16:25:37 -04005805 pw.print(" mVolumeController="); pw.println(mVolumeController);
John Spurlock35134602014-07-24 18:10:48 -04005806 pw.print(" mSafeMediaVolumeState=");
5807 pw.println(safeMediaVolumeStateToString(mSafeMediaVolumeState));
5808 pw.print(" mSafeMediaVolumeIndex="); pw.println(mSafeMediaVolumeIndex);
Eric Laurenteab40d12017-06-09 12:45:21 -07005809 pw.print(" mSafeUsbMediaVolumeIndex="); pw.println(mSafeUsbMediaVolumeIndex);
John Muir8b8bddd2018-02-16 14:29:14 -08005810 pw.print(" mSafeUsbMediaVolumeDbfs="); pw.println(mSafeUsbMediaVolumeDbfs);
Jean-Michel Trivi7592b982017-02-01 15:12:15 -08005811 pw.print(" sIndependentA11yVolume="); pw.println(sIndependentA11yVolume);
John Spurlock35134602014-07-24 18:10:48 -04005812 pw.print(" mPendingVolumeCommand="); pw.println(mPendingVolumeCommand);
5813 pw.print(" mMusicActiveMs="); pw.println(mMusicActiveMs);
John Spurlockaa5ee4d2014-07-25 13:05:12 -04005814 pw.print(" mMcc="); pw.println(mMcc);
John Spurlock5e783732015-02-19 10:28:59 -05005815 pw.print(" mCameraSoundForced="); pw.println(mCameraSoundForced);
John Spurlock661f2cf2014-11-17 10:29:10 -05005816 pw.print(" mHasVibrator="); pw.println(mHasVibrator);
John Spurlocka48d7792015-03-03 17:35:57 -05005817 pw.print(" mVolumePolicy="); pw.println(mVolumePolicy);
Jean-Michel Trivi58850372018-09-14 16:01:28 -07005818 pw.print(" mAvrcpAbsVolSupported=");
5819 pw.println(mDeviceBroker.isAvrcpAbsoluteVolumeSupported());
Jean-Michel Trivi1b3541d2014-11-25 12:53:41 -08005820
5821 dumpAudioPolicies(pw);
Jean-Michel Trivi12a86762018-04-24 16:57:49 -07005822 mDynPolicyLogger.dump(pw);
Jean-Michel Trivi292a6a42016-12-01 08:32:15 -08005823
5824 mPlaybackMonitor.dump(pw);
Jean-Michel Trivi66ffacf2017-02-04 17:25:31 -08005825
5826 mRecordMonitor.dump(pw);
Jean-Michel Trivi011f39e2017-08-19 18:08:06 -07005827
Jean-Michel Trivicf170362017-08-24 17:24:57 -07005828 pw.println("\n");
Jean-Michel Trivi011f39e2017-08-19 18:08:06 -07005829 pw.println("\nEvent logs:");
5830 mModeLogger.dump(pw);
5831 pw.println("\n");
Jean-Michel Trivi58850372018-09-14 16:01:28 -07005832 sDeviceLogger.dump(pw);
Jean-Michel Trivi011f39e2017-08-19 18:08:06 -07005833 pw.println("\n");
Jean-Michel Trivi58850372018-09-14 16:01:28 -07005834 sForceUseLogger.dump(pw);
Jean-Michel Trivicf170362017-08-24 17:24:57 -07005835 pw.println("\n");
Jean-Michel Trivi58850372018-09-14 16:01:28 -07005836 sVolumeLogger.dump(pw);
John Spurlock35134602014-07-24 18:10:48 -04005837 }
5838
hyomin.ohd0446dc2018-10-18 13:58:27 +09005839 private static String safeMediaVolumeStateToString(int state) {
John Spurlock35134602014-07-24 18:10:48 -04005840 switch(state) {
5841 case SAFE_MEDIA_VOLUME_NOT_CONFIGURED: return "SAFE_MEDIA_VOLUME_NOT_CONFIGURED";
5842 case SAFE_MEDIA_VOLUME_DISABLED: return "SAFE_MEDIA_VOLUME_DISABLED";
5843 case SAFE_MEDIA_VOLUME_INACTIVE: return "SAFE_MEDIA_VOLUME_INACTIVE";
5844 case SAFE_MEDIA_VOLUME_ACTIVE: return "SAFE_MEDIA_VOLUME_ACTIVE";
5845 }
5846 return null;
Jean-Michel Trivid5176cf2010-01-28 11:56:42 -08005847 }
Glenn Kastenfd116ad2013-07-12 17:10:39 -07005848
5849 // Inform AudioFlinger of our device's low RAM attribute
5850 private static void readAndSetLowRamDevice()
5851 {
Andy Hung79583582018-01-23 13:58:02 -08005852 boolean isLowRamDevice = ActivityManager.isLowRamDeviceStatic();
5853 long totalMemory = 1024 * 1024 * 1024; // 1GB is the default if ActivityManager fails.
5854
5855 try {
5856 final ActivityManager.MemoryInfo info = new ActivityManager.MemoryInfo();
5857 ActivityManager.getService().getMemoryInfo(info);
5858 totalMemory = info.totalMem;
5859 } catch (RemoteException e) {
5860 Log.w(TAG, "Cannot obtain MemoryInfo from ActivityManager, assume low memory device");
5861 isLowRamDevice = true;
5862 }
5863
5864 final int status = AudioSystem.setLowRamDevice(isLowRamDevice, totalMemory);
Glenn Kastenfd116ad2013-07-12 17:10:39 -07005865 if (status != 0) {
5866 Log.w(TAG, "AudioFlinger informed of device's low RAM attribute; status " + status);
5867 }
5868 }
John Spurlock3346a802014-05-20 16:25:37 -04005869
John Spurlockcdb57ae2015-02-11 19:04:11 -05005870 private void enforceVolumeController(String action) {
John Spurlock3346a802014-05-20 16:25:37 -04005871 mContext.enforceCallingOrSelfPermission(android.Manifest.permission.STATUS_BAR_SERVICE,
5872 "Only SystemUI can " + action);
5873 }
5874
5875 @Override
5876 public void setVolumeController(final IVolumeController controller) {
John Spurlockcdb57ae2015-02-11 19:04:11 -05005877 enforceVolumeController("set the volume controller");
John Spurlock3346a802014-05-20 16:25:37 -04005878
5879 // return early if things are not actually changing
5880 if (mVolumeController.isSameBinder(controller)) {
5881 return;
5882 }
5883
5884 // dismiss the old volume controller
5885 mVolumeController.postDismiss();
5886 if (controller != null) {
5887 // we are about to register a new controller, listen for its death
5888 try {
5889 controller.asBinder().linkToDeath(new DeathRecipient() {
5890 @Override
5891 public void binderDied() {
5892 if (mVolumeController.isSameBinder(controller)) {
5893 Log.w(TAG, "Current remote volume controller died, unregistering");
5894 setVolumeController(null);
5895 }
5896 }
5897 }, 0);
5898 } catch (RemoteException e) {
5899 // noop
5900 }
5901 }
5902 mVolumeController.setController(controller);
John Spurlock33f4e042014-07-11 13:10:58 -04005903 if (DEBUG_VOL) Log.d(TAG, "Volume controller: " + mVolumeController);
5904 }
5905
5906 @Override
5907 public void notifyVolumeControllerVisible(final IVolumeController controller, boolean visible) {
John Spurlockcdb57ae2015-02-11 19:04:11 -05005908 enforceVolumeController("notify about volume controller visibility");
John Spurlock33f4e042014-07-11 13:10:58 -04005909
5910 // return early if the controller is not current
5911 if (!mVolumeController.isSameBinder(controller)) {
5912 return;
5913 }
5914
5915 mVolumeController.setVisible(visible);
5916 if (DEBUG_VOL) Log.d(TAG, "Volume controller visible: " + visible);
John Spurlock3346a802014-05-20 16:25:37 -04005917 }
RoboErikd09bd0c2014-06-24 17:45:19 -07005918
John Spurlocka48d7792015-03-03 17:35:57 -05005919 @Override
5920 public void setVolumePolicy(VolumePolicy policy) {
5921 enforceVolumeController("set volume policy");
John Spurlockb02c7442015-04-14 09:32:25 -04005922 if (policy != null && !policy.equals(mVolumePolicy)) {
John Spurlocka48d7792015-03-03 17:35:57 -05005923 mVolumePolicy = policy;
John Spurlockb02c7442015-04-14 09:32:25 -04005924 if (DEBUG_VOL) Log.d(TAG, "Volume policy changed: " + mVolumePolicy);
John Spurlocka48d7792015-03-03 17:35:57 -05005925 }
5926 }
5927
RoboErikd09bd0c2014-06-24 17:45:19 -07005928 public static class VolumeController {
5929 private static final String TAG = "VolumeController";
5930
5931 private IVolumeController mController;
John Spurlock33f4e042014-07-11 13:10:58 -04005932 private boolean mVisible;
5933 private long mNextLongPress;
5934 private int mLongPressTimeout;
RoboErikd09bd0c2014-06-24 17:45:19 -07005935
5936 public void setController(IVolumeController controller) {
5937 mController = controller;
John Spurlock33f4e042014-07-11 13:10:58 -04005938 mVisible = false;
5939 }
5940
5941 public void loadSettings(ContentResolver cr) {
5942 mLongPressTimeout = Settings.Secure.getIntForUser(cr,
5943 Settings.Secure.LONG_PRESS_TIMEOUT, 500, UserHandle.USER_CURRENT);
5944 }
5945
RoboErik4197cb62015-01-21 15:45:32 -08005946 public boolean suppressAdjustment(int resolvedStream, int flags, boolean isMute) {
5947 if (isMute) {
5948 return false;
5949 }
John Spurlock33f4e042014-07-11 13:10:58 -04005950 boolean suppress = false;
Julia Reynoldseb0ce472018-05-04 15:34:55 -04005951 if (resolvedStream == DEFAULT_VOL_STREAM_NO_PLAYBACK && mController != null) {
John Spurlock33f4e042014-07-11 13:10:58 -04005952 final long now = SystemClock.uptimeMillis();
5953 if ((flags & AudioManager.FLAG_SHOW_UI) != 0 && !mVisible) {
5954 // ui will become visible
5955 if (mNextLongPress < now) {
5956 mNextLongPress = now + mLongPressTimeout;
5957 }
5958 suppress = true;
5959 } else if (mNextLongPress > 0) { // in a long-press
5960 if (now > mNextLongPress) {
5961 // long press triggered, no more suppression
5962 mNextLongPress = 0;
5963 } else {
5964 // keep suppressing until the long press triggers
5965 suppress = true;
5966 }
5967 }
5968 }
5969 return suppress;
5970 }
5971
5972 public void setVisible(boolean visible) {
5973 mVisible = visible;
RoboErikd09bd0c2014-06-24 17:45:19 -07005974 }
5975
5976 public boolean isSameBinder(IVolumeController controller) {
5977 return Objects.equals(asBinder(), binder(controller));
5978 }
5979
5980 public IBinder asBinder() {
5981 return binder(mController);
5982 }
5983
5984 private static IBinder binder(IVolumeController controller) {
5985 return controller == null ? null : controller.asBinder();
5986 }
5987
5988 @Override
5989 public String toString() {
John Spurlock33f4e042014-07-11 13:10:58 -04005990 return "VolumeController(" + asBinder() + ",mVisible=" + mVisible + ")";
RoboErikd09bd0c2014-06-24 17:45:19 -07005991 }
5992
5993 public void postDisplaySafeVolumeWarning(int flags) {
5994 if (mController == null)
5995 return;
5996 try {
5997 mController.displaySafeVolumeWarning(flags);
5998 } catch (RemoteException e) {
5999 Log.w(TAG, "Error calling displaySafeVolumeWarning", e);
6000 }
6001 }
6002
6003 public void postVolumeChanged(int streamType, int flags) {
6004 if (mController == null)
6005 return;
6006 try {
6007 mController.volumeChanged(streamType, flags);
6008 } catch (RemoteException e) {
6009 Log.w(TAG, "Error calling volumeChanged", e);
6010 }
6011 }
6012
RoboErikd09bd0c2014-06-24 17:45:19 -07006013 public void postMasterMuteChanged(int flags) {
6014 if (mController == null)
6015 return;
6016 try {
6017 mController.masterMuteChanged(flags);
6018 } catch (RemoteException e) {
6019 Log.w(TAG, "Error calling masterMuteChanged", e);
6020 }
6021 }
6022
6023 public void setLayoutDirection(int layoutDirection) {
6024 if (mController == null)
6025 return;
6026 try {
6027 mController.setLayoutDirection(layoutDirection);
6028 } catch (RemoteException e) {
6029 Log.w(TAG, "Error calling setLayoutDirection", e);
6030 }
6031 }
6032
6033 public void postDismiss() {
6034 if (mController == null)
6035 return;
6036 try {
6037 mController.dismiss();
6038 } catch (RemoteException e) {
6039 Log.w(TAG, "Error calling dismiss", e);
6040 }
6041 }
Jean-Michel Triviac487672016-11-11 10:05:18 -08006042
6043 public void setA11yMode(int a11yMode) {
6044 if (mController == null)
6045 return;
6046 try {
6047 mController.setA11yMode(a11yMode);
6048 } catch (RemoteException e) {
6049 Log.w(TAG, "Error calling setA11Mode", e);
6050 }
6051 }
RoboErikd09bd0c2014-06-24 17:45:19 -07006052 }
Jean-Michel Trivia8b6bd82014-07-01 09:48:46 -07006053
RoboErik0dac35a2014-08-12 15:48:49 -07006054 /**
6055 * Interface for system components to get some extra functionality through
6056 * LocalServices.
6057 */
6058 final class AudioServiceInternal extends AudioManagerInternal {
John Spurlock661f2cf2014-11-17 10:29:10 -05006059 @Override
6060 public void setRingerModeDelegate(RingerModeDelegate delegate) {
6061 mRingerModeDelegate = delegate;
6062 if (mRingerModeDelegate != null) {
Jean-Michel Trivi8719a1d2017-11-06 11:52:51 -08006063 synchronized (mSettingsLock) {
Beverlyd6964762018-02-16 14:07:03 -05006064 updateRingerAndZenModeAffectedStreams();
Jean-Michel Trivi8719a1d2017-11-06 11:52:51 -08006065 }
John Spurlock661f2cf2014-11-17 10:29:10 -05006066 setRingerModeInternal(getRingerModeInternal(), TAG + ".setRingerModeDelegate");
6067 }
6068 }
RoboErik272e1612014-09-05 11:39:29 -07006069
6070 @Override
6071 public void adjustSuggestedStreamVolumeForUid(int streamType, int direction, int flags,
6072 String callingPackage, int uid) {
6073 // direction and stream type swap here because the public
6074 // adjustSuggested has a different order than the other methods.
John Spurlock90874332015-03-10 16:00:54 -04006075 adjustSuggestedStreamVolume(direction, streamType, flags, callingPackage,
6076 callingPackage, uid);
RoboErik272e1612014-09-05 11:39:29 -07006077 }
6078
RoboErik0dac35a2014-08-12 15:48:49 -07006079 @Override
6080 public void adjustStreamVolumeForUid(int streamType, int direction, int flags,
6081 String callingPackage, int uid) {
John Spurlock90874332015-03-10 16:00:54 -04006082 adjustStreamVolume(streamType, direction, flags, callingPackage,
6083 callingPackage, uid);
RoboErik0dac35a2014-08-12 15:48:49 -07006084 }
6085
6086 @Override
6087 public void setStreamVolumeForUid(int streamType, int direction, int flags,
6088 String callingPackage, int uid) {
John Spurlock90874332015-03-10 16:00:54 -04006089 setStreamVolume(streamType, direction, flags, callingPackage, callingPackage, uid);
RoboErik0dac35a2014-08-12 15:48:49 -07006090 }
RoboErik519c7742014-11-18 10:59:09 -08006091
6092 @Override
John Spurlock661f2cf2014-11-17 10:29:10 -05006093 public int getRingerModeInternal() {
6094 return AudioService.this.getRingerModeInternal();
6095 }
6096
6097 @Override
6098 public void setRingerModeInternal(int ringerMode, String caller) {
6099 AudioService.this.setRingerModeInternal(ringerMode, caller);
6100 }
John Spurlockcdb57ae2015-02-11 19:04:11 -05006101
6102 @Override
Mike Digman55272862018-02-20 14:35:17 -08006103 public void silenceRingerModeInternal(String caller) {
6104 AudioService.this.silenceRingerModeInternal(caller);
6105 }
6106
6107 @Override
John Spurlock50ced3f2015-05-11 16:00:09 -04006108 public void updateRingerModeAffectedStreamsInternal() {
6109 synchronized (mSettingsLock) {
Beverlyd6964762018-02-16 14:07:03 -05006110 if (updateRingerAndZenModeAffectedStreams()) {
John Spurlock50ced3f2015-05-11 16:00:09 -04006111 setRingerModeInt(getRingerModeInternal(), false);
6112 }
6113 }
6114 }
Phil Weaverf1a9aff2017-03-23 17:21:29 -07006115
6116 @Override
6117 public void setAccessibilityServiceUids(IntArray uids) {
6118 synchronized (mAccessibilityServiceUidsLock) {
6119 if (uids.size() == 0) {
6120 mAccessibilityServiceUids = null;
6121 } else {
6122 boolean changed = (mAccessibilityServiceUids == null)
6123 || (mAccessibilityServiceUids.length != uids.size());
6124 if (!changed) {
6125 for (int i = 0; i < mAccessibilityServiceUids.length; i++) {
6126 if (uids.get(i) != mAccessibilityServiceUids[i]) {
6127 changed = true;
6128 break;
6129 }
6130 }
6131 }
6132 if (changed) {
6133 mAccessibilityServiceUids = uids.toArray();
6134 }
6135 }
Eric Laurent1c9c1d52018-10-17 10:06:46 -07006136 AudioSystem.setA11yServicesUids(mAccessibilityServiceUids);
Phil Weaverf1a9aff2017-03-23 17:21:29 -07006137 }
6138 }
RoboErik0dac35a2014-08-12 15:48:49 -07006139 }
6140
Jean-Michel Trivia8b6bd82014-07-01 09:48:46 -07006141 //==========================================================================================
6142 // Audio policy management
6143 //==========================================================================================
Jean-Michel Trivi0212be52014-11-24 14:43:10 -08006144 public String registerAudioPolicy(AudioPolicyConfig policyConfig, IAudioPolicyCallback pcb,
Jean-Michel Trivi610aa9b2018-01-27 15:42:42 -08006145 boolean hasFocusListener, boolean isFocusPolicy, boolean isVolumeController) {
Jean-Michel Trivi5a561092015-04-23 18:48:08 -07006146 AudioSystem.setDynamicPolicyCallback(mDynPolicyCallback);
6147
Jean-Michel Trivi8fdb0d42014-07-16 19:08:37 -07006148 String regId = null;
Jean-Michel Trivi0212be52014-11-24 14:43:10 -08006149 // error handling
Jean-Michel Trivia8b6bd82014-07-01 09:48:46 -07006150 boolean hasPermissionForPolicy =
Jean-Michel Trivi0212be52014-11-24 14:43:10 -08006151 (PackageManager.PERMISSION_GRANTED == mContext.checkCallingPermission(
Jean-Michel Trivia8b6bd82014-07-01 09:48:46 -07006152 android.Manifest.permission.MODIFY_AUDIO_ROUTING));
6153 if (!hasPermissionForPolicy) {
6154 Slog.w(TAG, "Can't register audio policy for pid " + Binder.getCallingPid() + " / uid "
6155 + Binder.getCallingUid() + ", need MODIFY_AUDIO_ROUTING");
Jean-Michel Trivi8fdb0d42014-07-16 19:08:37 -07006156 return null;
Jean-Michel Trivia8b6bd82014-07-01 09:48:46 -07006157 }
Jean-Michel Trivi0212be52014-11-24 14:43:10 -08006158
Jean-Michel Trivi12a86762018-04-24 16:57:49 -07006159 mDynPolicyLogger.log((new AudioEventLogger.StringEvent("registerAudioPolicy for "
6160 + pcb.asBinder() + " with config:" + policyConfig)).printLog(TAG));
Jean-Michel Trivia8b6bd82014-07-01 09:48:46 -07006161 synchronized (mAudioPolicies) {
Jean-Michel Trivia8b6bd82014-07-01 09:48:46 -07006162 try {
Jean-Michel Trivi0212be52014-11-24 14:43:10 -08006163 if (mAudioPolicies.containsKey(pcb.asBinder())) {
Jean-Michel Trivi1b3541d2014-11-25 12:53:41 -08006164 Slog.e(TAG, "Cannot re-register policy");
6165 return null;
6166 }
Jean-Michel Trivi126cf032017-04-02 23:19:02 -07006167 AudioPolicyProxy app = new AudioPolicyProxy(policyConfig, pcb, hasFocusListener,
Jean-Michel Trivi610aa9b2018-01-27 15:42:42 -08006168 isFocusPolicy, isVolumeController);
Jean-Michel Trivi0212be52014-11-24 14:43:10 -08006169 pcb.asBinder().linkToDeath(app, 0/*flags*/);
6170 regId = app.getRegistrationId();
6171 mAudioPolicies.put(pcb.asBinder(), app);
Jean-Michel Trivia8b6bd82014-07-01 09:48:46 -07006172 } catch (RemoteException e) {
6173 // audio policy owner has already died!
Jean-Michel Trivi0212be52014-11-24 14:43:10 -08006174 Slog.w(TAG, "Audio policy registration failed, could not link to " + pcb +
Jean-Michel Trivia8b6bd82014-07-01 09:48:46 -07006175 " binder death", e);
Jean-Michel Trivi8fdb0d42014-07-16 19:08:37 -07006176 return null;
Jean-Michel Trivia8b6bd82014-07-01 09:48:46 -07006177 }
6178 }
Jean-Michel Trivi8fdb0d42014-07-16 19:08:37 -07006179 return regId;
Jean-Michel Trivia8b6bd82014-07-01 09:48:46 -07006180 }
Jean-Michel Trivi8fdb0d42014-07-16 19:08:37 -07006181
Jean-Michel Trivi0212be52014-11-24 14:43:10 -08006182 public void unregisterAudioPolicyAsync(IAudioPolicyCallback pcb) {
Jean-Michel Trivi12a86762018-04-24 16:57:49 -07006183 mDynPolicyLogger.log((new AudioEventLogger.StringEvent("unregisterAudioPolicyAsync for "
6184 + pcb.asBinder()).printLog(TAG)));
Jean-Michel Trivia8b6bd82014-07-01 09:48:46 -07006185 synchronized (mAudioPolicies) {
Jean-Michel Trivi0212be52014-11-24 14:43:10 -08006186 AudioPolicyProxy app = mAudioPolicies.remove(pcb.asBinder());
Jean-Michel Trivia8b6bd82014-07-01 09:48:46 -07006187 if (app == null) {
6188 Slog.w(TAG, "Trying to unregister unknown audio policy for pid "
6189 + Binder.getCallingPid() + " / uid " + Binder.getCallingUid());
Jean-Michel Trivi1b3541d2014-11-25 12:53:41 -08006190 return;
Jean-Michel Trivia8b6bd82014-07-01 09:48:46 -07006191 } else {
Jean-Michel Trivi0212be52014-11-24 14:43:10 -08006192 pcb.asBinder().unlinkToDeath(app, 0/*flags*/);
Jean-Michel Trivia8b6bd82014-07-01 09:48:46 -07006193 }
Jean-Michel Trivi0212be52014-11-24 14:43:10 -08006194 app.release();
Jean-Michel Trivia8b6bd82014-07-01 09:48:46 -07006195 }
Jean-Michel Trivi8fdb0d42014-07-16 19:08:37 -07006196 // TODO implement clearing mix attribute matching info in native audio policy
Jean-Michel Trivia8b6bd82014-07-01 09:48:46 -07006197 }
6198
Jean-Michel Triviaf576a02018-02-14 08:57:46 -08006199 /**
6200 * Checks whether caller has MODIFY_AUDIO_ROUTING permission, and the policy is registered.
6201 * @param errorMsg log warning if permission check failed.
6202 * @return null if the operation on the audio mixes should be cancelled.
6203 */
6204 @GuardedBy("mAudioPolicies")
6205 private AudioPolicyProxy checkUpdateForPolicy(IAudioPolicyCallback pcb, String errorMsg) {
6206 // permission check
6207 final boolean hasPermissionForPolicy =
Jean-Michel Trivi0212be52014-11-24 14:43:10 -08006208 (PackageManager.PERMISSION_GRANTED == mContext.checkCallingPermission(
6209 android.Manifest.permission.MODIFY_AUDIO_ROUTING));
6210 if (!hasPermissionForPolicy) {
Jean-Michel Triviaf576a02018-02-14 08:57:46 -08006211 Slog.w(TAG, errorMsg + " for pid " +
Jean-Michel Trivi0212be52014-11-24 14:43:10 -08006212 + Binder.getCallingPid() + " / uid "
6213 + Binder.getCallingUid() + ", need MODIFY_AUDIO_ROUTING");
Jean-Michel Triviaf576a02018-02-14 08:57:46 -08006214 return null;
Jean-Michel Trivi0212be52014-11-24 14:43:10 -08006215 }
Jean-Michel Triviaf576a02018-02-14 08:57:46 -08006216 // policy registered?
6217 final AudioPolicyProxy app = mAudioPolicies.get(pcb.asBinder());
6218 if (app == null) {
6219 Slog.w(TAG, errorMsg + " for pid " +
6220 + Binder.getCallingPid() + " / uid "
6221 + Binder.getCallingUid() + ", unregistered policy");
6222 return null;
6223 }
6224 return app;
6225 }
Jean-Michel Trivi0212be52014-11-24 14:43:10 -08006226
Jean-Michel Triviaf576a02018-02-14 08:57:46 -08006227 public int addMixForPolicy(AudioPolicyConfig policyConfig, IAudioPolicyCallback pcb) {
6228 if (DEBUG_AP) { Log.d(TAG, "addMixForPolicy for " + pcb.asBinder()
6229 + " with config:" + policyConfig); }
Jean-Michel Trivi0212be52014-11-24 14:43:10 -08006230 synchronized (mAudioPolicies) {
Jean-Michel Triviaf576a02018-02-14 08:57:46 -08006231 final AudioPolicyProxy app =
6232 checkUpdateForPolicy(pcb, "Cannot add AudioMix in audio policy");
6233 if (app == null){
6234 return AudioManager.ERROR;
6235 }
6236 app.addMixes(policyConfig.getMixes());
6237 }
6238 return AudioManager.SUCCESS;
6239 }
6240
6241 public int removeMixForPolicy(AudioPolicyConfig policyConfig, IAudioPolicyCallback pcb) {
6242 if (DEBUG_AP) { Log.d(TAG, "removeMixForPolicy for " + pcb.asBinder()
6243 + " with config:" + policyConfig); }
6244 synchronized (mAudioPolicies) {
6245 final AudioPolicyProxy app =
6246 checkUpdateForPolicy(pcb, "Cannot add AudioMix in audio policy");
6247 if (app == null) {
6248 return AudioManager.ERROR;
6249 }
6250 app.removeMixes(policyConfig.getMixes());
6251 }
6252 return AudioManager.SUCCESS;
6253 }
6254
Jean-Michel Trivid6f65de2018-12-18 18:49:14 -08006255 /** see AudioPolicy.setUidDeviceAffinity() */
6256 public int setUidDeviceAffinity(IAudioPolicyCallback pcb, int uid,
Jean-Michel Trivif93107f2019-01-08 09:38:25 -08006257 @NonNull int[] deviceTypes, @NonNull String[] deviceAddresses) {
6258 if (DEBUG_AP) {
6259 Log.d(TAG, "setUidDeviceAffinity for " + pcb.asBinder() + " uid:" + uid);
6260 }
Jean-Michel Trivid6f65de2018-12-18 18:49:14 -08006261 synchronized (mAudioPolicies) {
6262 final AudioPolicyProxy app =
6263 checkUpdateForPolicy(pcb, "Cannot change device affinity in audio policy");
6264 if (app == null) {
6265 return AudioManager.ERROR;
6266 }
6267 if (!app.hasMixRoutedToDevices(deviceTypes, deviceAddresses)) {
6268 return AudioManager.ERROR;
6269 }
Jean-Michel Trivif93107f2019-01-08 09:38:25 -08006270 return app.setUidDeviceAffinities(uid, deviceTypes, deviceAddresses);
Jean-Michel Trivid6f65de2018-12-18 18:49:14 -08006271 }
Jean-Michel Trivid6f65de2018-12-18 18:49:14 -08006272 }
6273
6274 /** see AudioPolicy.removeUidDeviceAffinity() */
6275 public int removeUidDeviceAffinity(IAudioPolicyCallback pcb, int uid) {
Jean-Michel Trivif93107f2019-01-08 09:38:25 -08006276 if (DEBUG_AP) {
6277 Log.d(TAG, "removeUidDeviceAffinity for " + pcb.asBinder() + " uid:" + uid);
6278 }
Jean-Michel Trivid6f65de2018-12-18 18:49:14 -08006279 synchronized (mAudioPolicies) {
6280 final AudioPolicyProxy app =
6281 checkUpdateForPolicy(pcb, "Cannot remove device affinity in audio policy");
6282 if (app == null) {
6283 return AudioManager.ERROR;
6284 }
Jean-Michel Trivif93107f2019-01-08 09:38:25 -08006285 return app.removeUidDeviceAffinities(uid);
Jean-Michel Trivid6f65de2018-12-18 18:49:14 -08006286 }
Jean-Michel Trivid6f65de2018-12-18 18:49:14 -08006287 }
6288
Jean-Michel Triviaf576a02018-02-14 08:57:46 -08006289 public int setFocusPropertiesForPolicy(int duckingBehavior, IAudioPolicyCallback pcb) {
6290 if (DEBUG_AP) Log.d(TAG, "setFocusPropertiesForPolicy() duck behavior=" + duckingBehavior
6291 + " policy " + pcb.asBinder());
6292 synchronized (mAudioPolicies) {
6293 final AudioPolicyProxy app =
6294 checkUpdateForPolicy(pcb, "Cannot change audio policy focus properties");
6295 if (app == null){
6296 return AudioManager.ERROR;
6297 }
Jean-Michel Trivi0212be52014-11-24 14:43:10 -08006298 if (!mAudioPolicies.containsKey(pcb.asBinder())) {
6299 Slog.e(TAG, "Cannot change audio policy focus properties, unregistered policy");
6300 return AudioManager.ERROR;
6301 }
Jean-Michel Trivi0212be52014-11-24 14:43:10 -08006302 if (duckingBehavior == AudioPolicy.FOCUS_POLICY_DUCKING_IN_POLICY) {
6303 // is there already one policy managing ducking?
Eric Laurent0867bed2015-05-20 14:49:08 -07006304 for (AudioPolicyProxy policy : mAudioPolicies.values()) {
Jean-Michel Trivi0212be52014-11-24 14:43:10 -08006305 if (policy.mFocusDuckBehavior == AudioPolicy.FOCUS_POLICY_DUCKING_IN_POLICY) {
6306 Slog.e(TAG, "Cannot change audio policy ducking behavior, already handled");
6307 return AudioManager.ERROR;
6308 }
6309 }
6310 }
6311 app.mFocusDuckBehavior = duckingBehavior;
6312 mMediaFocusControl.setDuckingInExtPolicyAvailable(
6313 duckingBehavior == AudioPolicy.FOCUS_POLICY_DUCKING_IN_POLICY);
6314 }
6315 return AudioManager.SUCCESS;
6316 }
6317
Jean-Michel Trivi610aa9b2018-01-27 15:42:42 -08006318 private final Object mExtVolumeControllerLock = new Object();
6319 private IAudioPolicyCallback mExtVolumeController;
6320 private void setExtVolumeController(IAudioPolicyCallback apc) {
6321 if (!mContext.getResources().getBoolean(
6322 com.android.internal.R.bool.config_handleVolumeKeysInWindowManager)) {
6323 Log.e(TAG, "Cannot set external volume controller: device not set for volume keys" +
6324 " handled in PhoneWindowManager");
6325 return;
6326 }
6327 synchronized (mExtVolumeControllerLock) {
6328 if (mExtVolumeController != null && !mExtVolumeController.asBinder().pingBinder()) {
6329 Log.e(TAG, "Cannot set external volume controller: existing controller");
6330 }
6331 mExtVolumeController = apc;
6332 }
6333 }
6334
Jean-Michel Trivi1b3541d2014-11-25 12:53:41 -08006335 private void dumpAudioPolicies(PrintWriter pw) {
6336 pw.println("\nAudio policies:");
6337 synchronized (mAudioPolicies) {
Eric Laurent0867bed2015-05-20 14:49:08 -07006338 for (AudioPolicyProxy policy : mAudioPolicies.values()) {
Jean-Michel Trivi1b3541d2014-11-25 12:53:41 -08006339 pw.println(policy.toLogFriendlyString());
6340 }
6341 }
6342 }
6343
Jean-Michel Trivi958876f2014-11-16 15:40:22 -08006344 //======================
Jean-Michel Trivid3c71f02015-12-07 11:59:31 -08006345 // Audio policy callbacks from AudioSystem for dynamic policies
Jean-Michel Trivi5a561092015-04-23 18:48:08 -07006346 //======================
6347 private final AudioSystem.DynamicPolicyCallback mDynPolicyCallback =
6348 new AudioSystem.DynamicPolicyCallback() {
6349 public void onDynamicPolicyMixStateUpdate(String regId, int state) {
6350 if (!TextUtils.isEmpty(regId)) {
6351 sendMsg(mAudioHandler, MSG_DYN_POLICY_MIX_STATE_UPDATE, SENDMSG_QUEUE,
6352 state /*arg1*/, 0 /*arg2 ignored*/, regId /*obj*/, 0 /*delay*/);
6353 }
6354 }
6355 };
6356
6357 private void onDynPolicyMixStateUpdate(String regId, int state) {
6358 if (DEBUG_AP) Log.d(TAG, "onDynamicPolicyMixStateUpdate("+ regId + ", " + state +")");
6359 synchronized (mAudioPolicies) {
6360 for (AudioPolicyProxy policy : mAudioPolicies.values()) {
6361 for (AudioMix mix : policy.getMixes()) {
6362 if (mix.getRegistration().equals(regId)) {
6363 try {
6364 policy.mPolicyCallback.notifyMixStateUpdate(regId, state);
6365 } catch (RemoteException e) {
6366 Log.e(TAG, "Can't call notifyMixStateUpdate() on IAudioPolicyCallback "
6367 + policy.mPolicyCallback.asBinder(), e);
6368 }
6369 return;
6370 }
6371 }
6372 }
6373 }
Jean-Michel Trivid3c71f02015-12-07 11:59:31 -08006374 }
Jean-Michel Trivi5a561092015-04-23 18:48:08 -07006375
Jean-Michel Trivid3c71f02015-12-07 11:59:31 -08006376 //======================
6377 // Audio policy callbacks from AudioSystem for recording configuration updates
6378 //======================
Jean-Michel Trivi66ffacf2017-02-04 17:25:31 -08006379 private final RecordingActivityMonitor mRecordMonitor;
Jean-Michel Trivid3c71f02015-12-07 11:59:31 -08006380
6381 public void registerRecordingCallback(IRecordingConfigDispatcher rcdb) {
Jean-Michel Trivi66ffacf2017-02-04 17:25:31 -08006382 final boolean isPrivileged =
6383 (PackageManager.PERMISSION_GRANTED == mContext.checkCallingPermission(
6384 android.Manifest.permission.MODIFY_AUDIO_ROUTING));
6385 mRecordMonitor.registerRecordingCallback(rcdb, isPrivileged);
Jean-Michel Trivid3c71f02015-12-07 11:59:31 -08006386 }
6387
6388 public void unregisterRecordingCallback(IRecordingConfigDispatcher rcdb) {
6389 mRecordMonitor.unregisterRecordingCallback(rcdb);
6390 }
6391
Jean-Michel Trivif04fab12016-05-19 10:42:35 -07006392 public List<AudioRecordingConfiguration> getActiveRecordingConfigurations() {
Jean-Michel Trivi66ffacf2017-02-04 17:25:31 -08006393 final boolean isPrivileged =
6394 (PackageManager.PERMISSION_GRANTED == mContext.checkCallingPermission(
6395 android.Manifest.permission.MODIFY_AUDIO_ROUTING));
6396 return mRecordMonitor.getActiveRecordingConfigurations(isPrivileged);
Jean-Michel Trivi5a561092015-04-23 18:48:08 -07006397 }
6398
Robin Lee7af9a742017-02-20 14:47:30 +00006399 public void disableRingtoneSync(final int userId) {
Andre Lago7bdc6d82016-09-22 18:00:41 +01006400 final int callingUserId = UserHandle.getCallingUserId();
Robin Lee7af9a742017-02-20 14:47:30 +00006401 if (callingUserId != userId) {
6402 mContext.enforceCallingOrSelfPermission(Manifest.permission.INTERACT_ACROSS_USERS_FULL,
6403 "disable sound settings syncing for another profile");
6404 }
Andre Lago7bdc6d82016-09-22 18:00:41 +01006405 final long token = Binder.clearCallingIdentity();
6406 try {
Robin Lee7af9a742017-02-20 14:47:30 +00006407 // Disable the sync setting so the profile uses its own sound settings.
6408 Settings.Secure.putIntForUser(mContentResolver, Settings.Secure.SYNC_PARENT_SOUNDS,
6409 0 /* false */, userId);
Andre Lago7bdc6d82016-09-22 18:00:41 +01006410 } finally {
6411 Binder.restoreCallingIdentity(token);
6412 }
6413 }
6414
Jean-Michel Trivi5a561092015-04-23 18:48:08 -07006415 //======================
Jean-Michel Trivi46e310b2017-01-04 15:58:02 -08006416 // Audio playback notification
Jean-Michel Trivi292a6a42016-12-01 08:32:15 -08006417 //======================
Eric Laurente5a351c2017-09-27 20:11:51 -07006418 private final PlaybackActivityMonitor mPlaybackMonitor;
Jean-Michel Trivi292a6a42016-12-01 08:32:15 -08006419
6420 public void registerPlaybackCallback(IPlaybackConfigDispatcher pcdb) {
Jean-Michel Trivi44a8f532017-01-02 14:36:43 -08006421 final boolean isPrivileged =
Jaewan Kim92dea332017-02-02 11:52:08 +09006422 (PackageManager.PERMISSION_GRANTED == mContext.checkCallingOrSelfPermission(
Jean-Michel Trivi292a6a42016-12-01 08:32:15 -08006423 android.Manifest.permission.MODIFY_AUDIO_ROUTING));
6424 mPlaybackMonitor.registerPlaybackCallback(pcdb, isPrivileged);
6425 }
6426
6427 public void unregisterPlaybackCallback(IPlaybackConfigDispatcher pcdb) {
6428 mPlaybackMonitor.unregisterPlaybackCallback(pcdb);
6429 }
6430
6431 public List<AudioPlaybackConfiguration> getActivePlaybackConfigurations() {
Jean-Michel Trivi44a8f532017-01-02 14:36:43 -08006432 final boolean isPrivileged =
Jaewan Kim92dea332017-02-02 11:52:08 +09006433 (PackageManager.PERMISSION_GRANTED == mContext.checkCallingOrSelfPermission(
Jean-Michel Trivi44a8f532017-01-02 14:36:43 -08006434 android.Manifest.permission.MODIFY_AUDIO_ROUTING));
6435 return mPlaybackMonitor.getActivePlaybackConfigurations(isPrivileged);
Jean-Michel Trivi292a6a42016-12-01 08:32:15 -08006436 }
6437
Jean-Michel Trivi44a8f532017-01-02 14:36:43 -08006438 public int trackPlayer(PlayerBase.PlayerIdCard pic) {
6439 return mPlaybackMonitor.trackPlayer(pic);
Jean-Michel Trivi292a6a42016-12-01 08:32:15 -08006440 }
6441
6442 public void playerAttributes(int piid, AudioAttributes attr) {
Jean-Michel Trivi46e310b2017-01-04 15:58:02 -08006443 mPlaybackMonitor.playerAttributes(piid, attr, Binder.getCallingUid());
Jean-Michel Trivi292a6a42016-12-01 08:32:15 -08006444 }
6445
6446 public void playerEvent(int piid, int event) {
Jean-Michel Trivi46e310b2017-01-04 15:58:02 -08006447 mPlaybackMonitor.playerEvent(piid, event, Binder.getCallingUid());
Jean-Michel Trivi292a6a42016-12-01 08:32:15 -08006448 }
6449
Jean-Michel Trivi3120059d2017-08-28 12:40:55 -07006450 public void playerHasOpPlayAudio(int piid, boolean hasOpPlayAudio) {
6451 mPlaybackMonitor.playerHasOpPlayAudio(piid, hasOpPlayAudio, Binder.getCallingUid());
6452 }
6453
Jean-Michel Trivi292a6a42016-12-01 08:32:15 -08006454 public void releasePlayer(int piid) {
Jean-Michel Trivi46e310b2017-01-04 15:58:02 -08006455 mPlaybackMonitor.releasePlayer(piid, Binder.getCallingUid());
Jean-Michel Trivi292a6a42016-12-01 08:32:15 -08006456 }
6457
6458 //======================
Jean-Michel Trivi58850372018-09-14 16:01:28 -07006459 // Audio device management
6460 //======================
6461 private final AudioDeviceBroker mDeviceBroker;
6462
6463 //======================
Jean-Michel Trivi958876f2014-11-16 15:40:22 -08006464 // Audio policy proxy
6465 //======================
Jean-Michel Trivid6f65de2018-12-18 18:49:14 -08006466 private static final class AudioDeviceArray {
6467 final @NonNull int[] mDeviceTypes;
6468 final @NonNull String[] mDeviceAddresses;
6469 AudioDeviceArray(@NonNull int[] types, @NonNull String[] addresses) {
6470 mDeviceTypes = types;
6471 mDeviceAddresses = addresses;
6472 }
6473 }
6474
Jean-Michel Trivi8fdb0d42014-07-16 19:08:37 -07006475 /**
Jean-Michel Trivi1b3541d2014-11-25 12:53:41 -08006476 * This internal class inherits from AudioPolicyConfig, each instance contains all the
6477 * mixes of an AudioPolicy and their configurations.
Jean-Michel Trivi8fdb0d42014-07-16 19:08:37 -07006478 */
6479 public class AudioPolicyProxy extends AudioPolicyConfig implements IBinder.DeathRecipient {
Jean-Michel Trivia8b6bd82014-07-01 09:48:46 -07006480 private static final String TAG = "AudioPolicyProxy";
Jean-Michel Trivi610aa9b2018-01-27 15:42:42 -08006481 final IAudioPolicyCallback mPolicyCallback;
6482 final boolean mHasFocusListener;
6483 final boolean mIsVolumeController;
Jean-Michel Trivid6f65de2018-12-18 18:49:14 -08006484 final HashMap<Integer, AudioDeviceArray> mUidDeviceAffinities =
6485 new HashMap<Integer, AudioDeviceArray>();
Jean-Michel Trivi0212be52014-11-24 14:43:10 -08006486 /**
6487 * Audio focus ducking behavior for an audio policy.
6488 * This variable reflects the value that was successfully set in
6489 * {@link AudioService#setFocusPropertiesForPolicy(int, IAudioPolicyCallback)}. This
6490 * implies that a value of FOCUS_POLICY_DUCKING_IN_POLICY means the corresponding policy
6491 * is handling ducking for audio focus.
6492 */
6493 int mFocusDuckBehavior = AudioPolicy.FOCUS_POLICY_DUCKING_DEFAULT;
Jean-Michel Trivi126cf032017-04-02 23:19:02 -07006494 boolean mIsFocusPolicy = false;
Jean-Michel Trivi0212be52014-11-24 14:43:10 -08006495
6496 AudioPolicyProxy(AudioPolicyConfig config, IAudioPolicyCallback token,
Jean-Michel Trivi610aa9b2018-01-27 15:42:42 -08006497 boolean hasFocusListener, boolean isFocusPolicy, boolean isVolumeController) {
Jean-Michel Trivi8fdb0d42014-07-16 19:08:37 -07006498 super(config);
Jean-Michel Trivi1b3541d2014-11-25 12:53:41 -08006499 setRegistration(new String(config.hashCode() + ":ap:" + mAudioPolicyCounter++));
Jean-Michel Trivi5a561092015-04-23 18:48:08 -07006500 mPolicyCallback = token;
Jean-Michel Trivi0212be52014-11-24 14:43:10 -08006501 mHasFocusListener = hasFocusListener;
Jean-Michel Trivi610aa9b2018-01-27 15:42:42 -08006502 mIsVolumeController = isVolumeController;
Jean-Michel Trivi0212be52014-11-24 14:43:10 -08006503 if (mHasFocusListener) {
Jean-Michel Trivi5a561092015-04-23 18:48:08 -07006504 mMediaFocusControl.addFocusFollower(mPolicyCallback);
Jean-Michel Trivi126cf032017-04-02 23:19:02 -07006505 // can only ever be true if there is a focus listener
6506 if (isFocusPolicy) {
6507 mIsFocusPolicy = true;
6508 mMediaFocusControl.setFocusPolicy(mPolicyCallback);
6509 }
Jean-Michel Trivi0212be52014-11-24 14:43:10 -08006510 }
Jean-Michel Trivi610aa9b2018-01-27 15:42:42 -08006511 if (mIsVolumeController) {
6512 setExtVolumeController(mPolicyCallback);
6513 }
Eric Laurent7f5eb9f2014-12-01 19:36:30 -08006514 connectMixes();
Jean-Michel Trivia8b6bd82014-07-01 09:48:46 -07006515 }
6516
6517 public void binderDied() {
6518 synchronized (mAudioPolicies) {
Jean-Michel Trivi5a561092015-04-23 18:48:08 -07006519 Log.i(TAG, "audio policy " + mPolicyCallback + " died");
Jean-Michel Trivi0212be52014-11-24 14:43:10 -08006520 release();
Jean-Michel Trivi5a561092015-04-23 18:48:08 -07006521 mAudioPolicies.remove(mPolicyCallback.asBinder());
Jean-Michel Trivi8fdb0d42014-07-16 19:08:37 -07006522 }
Jean-Michel Trivi610aa9b2018-01-27 15:42:42 -08006523 if (mIsVolumeController) {
6524 synchronized (mExtVolumeControllerLock) {
6525 mExtVolumeController = null;
6526 }
6527 }
Jean-Michel Trivi8fdb0d42014-07-16 19:08:37 -07006528 }
6529
Jean-Michel Trivi0212be52014-11-24 14:43:10 -08006530 String getRegistrationId() {
Jean-Michel Trivi1b3541d2014-11-25 12:53:41 -08006531 return getRegistration();
Jean-Michel Trivi8fdb0d42014-07-16 19:08:37 -07006532 }
6533
Jean-Michel Trivi0212be52014-11-24 14:43:10 -08006534 void release() {
Jean-Michel Trivi126cf032017-04-02 23:19:02 -07006535 if (mIsFocusPolicy) {
6536 mMediaFocusControl.unsetFocusPolicy(mPolicyCallback);
6537 }
Jean-Michel Trivi0212be52014-11-24 14:43:10 -08006538 if (mFocusDuckBehavior == AudioPolicy.FOCUS_POLICY_DUCKING_IN_POLICY) {
6539 mMediaFocusControl.setDuckingInExtPolicyAvailable(false);
6540 }
6541 if (mHasFocusListener) {
Jean-Michel Trivi5a561092015-04-23 18:48:08 -07006542 mMediaFocusControl.removeFocusFollower(mPolicyCallback);
Jean-Michel Trivi0212be52014-11-24 14:43:10 -08006543 }
Eric Laurent66b69672018-01-26 18:30:51 -08006544 final long identity = Binder.clearCallingIdentity();
Eric Laurent7f5eb9f2014-12-01 19:36:30 -08006545 AudioSystem.registerPolicyMixes(mMixes, false);
Eric Laurent66b69672018-01-26 18:30:51 -08006546 Binder.restoreCallingIdentity(identity);
Jean-Michel Trivi8fdb0d42014-07-16 19:08:37 -07006547 }
6548
Jean-Michel Trivi7db2d8f2018-03-06 10:30:59 -08006549 boolean hasMixAffectingUsage(int usage) {
6550 for (AudioMix mix : mMixes) {
6551 if (mix.isAffectingUsage(usage)) {
6552 return true;
6553 }
6554 }
6555 return false;
6556 }
6557
Jean-Michel Trivid6f65de2018-12-18 18:49:14 -08006558 // Verify all the devices in the array are served by mixes defined in this policy
6559 boolean hasMixRoutedToDevices(@NonNull int[] deviceTypes,
6560 @NonNull String[] deviceAddresses) {
6561 for (int i = 0; i < deviceTypes.length; i++) {
6562 boolean hasDevice = false;
6563 for (AudioMix mix : mMixes) {
6564 // this will check both that the mix has ROUTE_FLAG_RENDER and the device
6565 // is reached by this mix
6566 if (mix.isRoutedToDevice(deviceTypes[i], deviceAddresses[i])) {
6567 hasDevice = true;
6568 break;
6569 }
6570 }
6571 if (!hasDevice) {
6572 return false;
6573 }
6574 }
6575 return true;
6576 }
6577
Jean-Michel Triviaf576a02018-02-14 08:57:46 -08006578 void addMixes(@NonNull ArrayList<AudioMix> mixes) {
6579 // TODO optimize to not have to unregister the mixes already in place
6580 synchronized (mMixes) {
6581 AudioSystem.registerPolicyMixes(mMixes, false);
6582 this.add(mixes);
6583 AudioSystem.registerPolicyMixes(mMixes, true);
6584 }
6585 }
6586
6587 void removeMixes(@NonNull ArrayList<AudioMix> mixes) {
6588 // TODO optimize to not have to unregister the mixes already in place
6589 synchronized (mMixes) {
6590 AudioSystem.registerPolicyMixes(mMixes, false);
6591 this.remove(mixes);
6592 AudioSystem.registerPolicyMixes(mMixes, true);
6593 }
6594 }
6595
Eric Laurent7f5eb9f2014-12-01 19:36:30 -08006596 void connectMixes() {
Eric Laurent66b69672018-01-26 18:30:51 -08006597 final long identity = Binder.clearCallingIdentity();
Eric Laurent7f5eb9f2014-12-01 19:36:30 -08006598 AudioSystem.registerPolicyMixes(mMixes, true);
Eric Laurent66b69672018-01-26 18:30:51 -08006599 Binder.restoreCallingIdentity(identity);
Jean-Michel Trivia8b6bd82014-07-01 09:48:46 -07006600 }
Jean-Michel Trivid6f65de2018-12-18 18:49:14 -08006601
Jean-Michel Trivif93107f2019-01-08 09:38:25 -08006602 int setUidDeviceAffinities(int uid, @NonNull int[] types, @NonNull String[] addresses) {
Jean-Michel Trivid6f65de2018-12-18 18:49:14 -08006603 final Integer Uid = new Integer(uid);
Jean-Michel Trivif93107f2019-01-08 09:38:25 -08006604 int res;
Jean-Michel Trivid6f65de2018-12-18 18:49:14 -08006605 if (mUidDeviceAffinities.remove(Uid) != null) {
6606 final long identity = Binder.clearCallingIdentity();
Jean-Michel Trivif93107f2019-01-08 09:38:25 -08006607 res = AudioSystem.removeUidDeviceAffinities(uid);
Jean-Michel Trivid6f65de2018-12-18 18:49:14 -08006608 Binder.restoreCallingIdentity(identity);
Jean-Michel Trivif93107f2019-01-08 09:38:25 -08006609 if (res != AudioSystem.SUCCESS) {
6610 Log.e(TAG, "AudioSystem. removeUidDeviceAffinities(" + uid + ") failed, "
6611 + " cannot call AudioSystem.setUidDeviceAffinities");
6612 return AudioManager.ERROR;
6613 }
Jean-Michel Trivid6f65de2018-12-18 18:49:14 -08006614 }
6615 final long identity = Binder.clearCallingIdentity();
Jean-Michel Trivif93107f2019-01-08 09:38:25 -08006616 res = AudioSystem.setUidDeviceAffinities(uid, types, addresses);
Jean-Michel Trivid6f65de2018-12-18 18:49:14 -08006617 Binder.restoreCallingIdentity(identity);
6618 if (res == AudioSystem.SUCCESS) {
6619 mUidDeviceAffinities.put(Uid, new AudioDeviceArray(types, addresses));
Jean-Michel Trivif93107f2019-01-08 09:38:25 -08006620 return AudioManager.SUCCESS;
Jean-Michel Trivid6f65de2018-12-18 18:49:14 -08006621 }
Jean-Michel Trivif93107f2019-01-08 09:38:25 -08006622 Log.e(TAG, "AudioSystem. setUidDeviceAffinities(" + uid + ") failed");
6623 return AudioManager.ERROR;
Jean-Michel Trivid6f65de2018-12-18 18:49:14 -08006624 }
6625
Jean-Michel Trivif93107f2019-01-08 09:38:25 -08006626 int removeUidDeviceAffinities(int uid) {
Jean-Michel Trivid6f65de2018-12-18 18:49:14 -08006627 if (mUidDeviceAffinities.remove(new Integer(uid)) != null) {
6628 final long identity = Binder.clearCallingIdentity();
Jean-Michel Trivif93107f2019-01-08 09:38:25 -08006629 final int res = AudioSystem.removeUidDeviceAffinities(uid);
Jean-Michel Trivid6f65de2018-12-18 18:49:14 -08006630 Binder.restoreCallingIdentity(identity);
Jean-Michel Trivif93107f2019-01-08 09:38:25 -08006631 if (res == AudioSystem.SUCCESS) {
6632 return AudioManager.SUCCESS;
6633 }
Jean-Michel Trivid6f65de2018-12-18 18:49:14 -08006634 }
Jean-Michel Trivif93107f2019-01-08 09:38:25 -08006635 Log.e(TAG, "AudioSystem. removeUidDeviceAffinities failed");
6636 return AudioManager.ERROR;
Jean-Michel Trivid6f65de2018-12-18 18:49:14 -08006637 }
Jean-Michel Trivia8b6bd82014-07-01 09:48:46 -07006638 };
6639
Jean-Michel Trivi126cf032017-04-02 23:19:02 -07006640 //======================
6641 // Audio policy: focus
6642 //======================
6643 /** */
6644 public int dispatchFocusChange(AudioFocusInfo afi, int focusChange, IAudioPolicyCallback pcb) {
Jean-Michel Trivie2d8aae2018-01-30 15:09:47 -08006645 if (afi == null) {
6646 throw new IllegalArgumentException("Illegal null AudioFocusInfo");
6647 }
6648 if (pcb == null) {
6649 throw new IllegalArgumentException("Illegal null AudioPolicy callback");
6650 }
Jean-Michel Trivi126cf032017-04-02 23:19:02 -07006651 synchronized (mAudioPolicies) {
6652 if (!mAudioPolicies.containsKey(pcb.asBinder())) {
6653 throw new IllegalStateException("Unregistered AudioPolicy for focus dispatch");
6654 }
6655 return mMediaFocusControl.dispatchFocusChange(afi, focusChange);
6656 }
6657 }
6658
Jean-Michel Trivie2d8aae2018-01-30 15:09:47 -08006659 public void setFocusRequestResultFromExtPolicy(AudioFocusInfo afi, int requestResult,
6660 IAudioPolicyCallback pcb) {
6661 if (afi == null) {
6662 throw new IllegalArgumentException("Illegal null AudioFocusInfo");
6663 }
6664 if (pcb == null) {
6665 throw new IllegalArgumentException("Illegal null AudioPolicy callback");
6666 }
6667 synchronized (mAudioPolicies) {
6668 if (!mAudioPolicies.containsKey(pcb.asBinder())) {
6669 throw new IllegalStateException("Unregistered AudioPolicy for external focus");
6670 }
6671 mMediaFocusControl.setFocusRequestResultFromExtPolicy(afi, requestResult);
6672 }
6673 }
6674
6675
Jean-Michel Trivi126cf032017-04-02 23:19:02 -07006676 //======================
Eric Laurent1d3cdce2018-01-20 10:31:21 -08006677 // Audioserver state displatch
6678 //======================
6679 private class AsdProxy implements IBinder.DeathRecipient {
6680 private final IAudioServerStateDispatcher mAsd;
6681
6682 AsdProxy(IAudioServerStateDispatcher asd) {
6683 mAsd = asd;
6684 }
6685
6686 public void binderDied() {
6687 synchronized (mAudioServerStateListeners) {
6688 mAudioServerStateListeners.remove(mAsd.asBinder());
6689 }
6690 }
6691
6692 IAudioServerStateDispatcher callback() {
6693 return mAsd;
6694 }
6695 }
6696
6697 private HashMap<IBinder, AsdProxy> mAudioServerStateListeners =
6698 new HashMap<IBinder, AsdProxy>();
6699
6700 private void checkMonitorAudioServerStatePermission() {
6701 if (!(mContext.checkCallingOrSelfPermission(
6702 android.Manifest.permission.MODIFY_PHONE_STATE) ==
6703 PackageManager.PERMISSION_GRANTED ||
6704 mContext.checkCallingOrSelfPermission(
6705 android.Manifest.permission.MODIFY_AUDIO_ROUTING) ==
6706 PackageManager.PERMISSION_GRANTED)) {
6707 throw new SecurityException("Not allowed to monitor audioserver state");
6708 }
6709 }
6710
6711 public void registerAudioServerStateDispatcher(IAudioServerStateDispatcher asd) {
6712 checkMonitorAudioServerStatePermission();
6713 synchronized (mAudioServerStateListeners) {
6714 if (mAudioServerStateListeners.containsKey(asd.asBinder())) {
6715 Slog.w(TAG, "Cannot re-register audio server state dispatcher");
6716 return;
6717 }
6718 AsdProxy asdp = new AsdProxy(asd);
6719 try {
6720 asd.asBinder().linkToDeath(asdp, 0/*flags*/);
6721 } catch (RemoteException e) {
6722
6723 }
6724 mAudioServerStateListeners.put(asd.asBinder(), asdp);
6725 }
6726 }
6727
6728 public void unregisterAudioServerStateDispatcher(IAudioServerStateDispatcher asd) {
6729 checkMonitorAudioServerStatePermission();
6730 synchronized (mAudioServerStateListeners) {
6731 AsdProxy asdp = mAudioServerStateListeners.remove(asd.asBinder());
6732 if (asdp == null) {
6733 Slog.w(TAG, "Trying to unregister unknown audioserver state dispatcher for pid "
6734 + Binder.getCallingPid() + " / uid " + Binder.getCallingUid());
6735 return;
6736 } else {
6737 asd.asBinder().unlinkToDeath(asdp, 0/*flags*/);
6738 }
6739 }
6740 }
6741
6742 public boolean isAudioServerRunning() {
6743 checkMonitorAudioServerStatePermission();
6744 return (AudioSystem.checkAudioFlinger() == AudioSystem.AUDIO_STATUS_OK);
6745 }
6746
6747 //======================
Jean-Michel Trivi126cf032017-04-02 23:19:02 -07006748 // misc
6749 //======================
Jean-Michel Triviaf576a02018-02-14 08:57:46 -08006750 private final HashMap<IBinder, AudioPolicyProxy> mAudioPolicies =
Jean-Michel Trivia8b6bd82014-07-01 09:48:46 -07006751 new HashMap<IBinder, AudioPolicyProxy>();
Jean-Michel Triviaf576a02018-02-14 08:57:46 -08006752 @GuardedBy("mAudioPolicies")
6753 private int mAudioPolicyCounter = 0;
Phil Burkac0f7042016-02-24 12:19:08 -08006754}