blob: 1723163a132da0e1742e577ec3e6b5c86cafc1f4 [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 }
789
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800790 }
791
Eric Laurent4a5eeb92014-05-06 10:49:04 -0700792 public void systemReady() {
793 sendMsg(mAudioHandler, MSG_SYSTEM_READY, SENDMSG_QUEUE,
794 0, 0, null, 0);
Dianne Hackborn3e3600e2017-08-31 11:15:26 -0700795 if (false) {
796 // This is turned off for now, because it is racy and thus causes apps to break.
797 // Currently banning a uid means that if an app tries to start playing an audio
798 // stream, that will be preventing, and unbanning it will not allow that stream
799 // to resume. However these changes in uid state are racy with what the app is doing,
800 // so that after taking a process out of the cached state we can't guarantee that
801 // we will unban the uid before the app actually tries to start playing audio.
802 // (To do that, the activity manager would need to wait until it knows for sure
803 // that the ban has been removed, before telling the app to do whatever it is
804 // supposed to do that caused it to go out of the cached state.)
805 try {
806 ActivityManager.getService().registerUidObserver(mUidObserver,
807 ActivityManager.UID_OBSERVER_CACHED | ActivityManager.UID_OBSERVER_GONE,
808 ActivityManager.PROCESS_STATE_UNKNOWN, null);
809 } catch (RemoteException e) {
810 // ignored; both services live in system_server
811 }
Dianne Hackborn3e99f652017-07-05 16:33:56 -0700812 }
Eric Laurent4a5eeb92014-05-06 10:49:04 -0700813 }
814
815 public void onSystemReady() {
816 mSystemReady = true;
817 sendMsg(mAudioHandler, MSG_LOAD_SOUND_EFFECTS, SENDMSG_QUEUE,
818 0, 0, null, 0);
819
Jean-Michel Trivi58850372018-09-14 16:01:28 -0700820 mDeviceBroker.onSystemReady();
Eric Laurent4a5eeb92014-05-06 10:49:04 -0700821
Jeff Sharkey73ea0ae2016-08-10 17:30:38 -0600822 if (mContext.getPackageManager().hasSystemFeature(PackageManager.FEATURE_HDMI_CEC)) {
Shubangc480a712018-06-11 18:02:42 -0700823 synchronized (mHdmiClientLock) {
824 mHdmiManager = mContext.getSystemService(HdmiControlManager.class);
Eric Laurent212532b2014-07-21 15:43:18 -0700825 mHdmiTvClient = mHdmiManager.getTvClient();
Jungshik Jangc9ff9682014-09-15 17:41:06 +0900826 if (mHdmiTvClient != null) {
827 mFixedVolumeDevices &= ~AudioSystem.DEVICE_ALL_HDMI_SYSTEM_AUDIO_AND_SPEAKER;
828 }
Eric Laurent212532b2014-07-21 15:43:18 -0700829 mHdmiPlaybackClient = mHdmiManager.getPlaybackClient();
830 mHdmiCecSink = false;
Shubangc480a712018-06-11 18:02:42 -0700831 mHdmiAudioSystemClient = mHdmiManager.getAudioSystemClient();
Eric Laurent212532b2014-07-21 15:43:18 -0700832 }
833 }
Wonsik Kim7f4342e2014-07-20 23:04:59 +0900834
Julia Reynolds48034f82016-03-09 10:15:16 -0500835 mNm = (NotificationManager) mContext.getSystemService(Context.NOTIFICATION_SERVICE);
836
Eric Laurent4a5eeb92014-05-06 10:49:04 -0700837 sendMsg(mAudioHandler,
838 MSG_CONFIGURE_SAFE_MEDIA_VOLUME_FORCED,
839 SENDMSG_REPLACE,
840 0,
841 0,
John Spurlock90874332015-03-10 16:00:54 -0400842 TAG,
Eric Laurent03332ab2017-02-09 18:29:15 -0800843 SystemProperties.getBoolean("audio.safemedia.bypass", false) ?
844 0 : SAFE_VOLUME_CONFIGURE_TIMEOUT_MS);
Jean-Michel Trivi873cc452014-09-11 17:25:09 -0700845
Jean-Michel Trivicfa55532017-01-18 11:17:51 -0800846 initA11yMonitoring();
Eric Laurent0867bed2015-05-20 14:49:08 -0700847 onIndicateSystemReady();
848 }
849
850 void onIndicateSystemReady() {
851 if (AudioSystem.systemReady() == AudioSystem.SUCCESS) {
852 return;
853 }
854 sendMsg(mAudioHandler,
855 MSG_INDICATE_SYSTEM_READY,
856 SENDMSG_REPLACE,
857 0,
858 0,
859 null,
860 INDICATE_SYSTEM_READY_RETRY_DELAY_MS);
861 }
862
Andy Hunged0ea402015-10-30 14:11:46 -0700863 public void onAudioServerDied() {
Eric Laurent0867bed2015-05-20 14:49:08 -0700864 if (!mSystemReady ||
865 (AudioSystem.checkAudioFlinger() != AudioSystem.AUDIO_STATUS_OK)) {
Andy Hunged0ea402015-10-30 14:11:46 -0700866 Log.e(TAG, "Audioserver died.");
867 sendMsg(mAudioHandler, MSG_AUDIO_SERVER_DIED, SENDMSG_NOOP, 0, 0,
Eric Laurent0867bed2015-05-20 14:49:08 -0700868 null, 500);
869 return;
870 }
Andy Hunged0ea402015-10-30 14:11:46 -0700871 Log.e(TAG, "Audioserver started.");
Eric Laurent0867bed2015-05-20 14:49:08 -0700872
873 // indicate to audio HAL that we start the reconfiguration phase after a media
874 // server crash
875 // Note that we only execute this when the media server
876 // process restarts after a crash, not the first time it is started.
877 AudioSystem.setParameters("restarting=true");
878
879 readAndSetLowRamDevice();
880
Jean-Michel Trivi58850372018-09-14 16:01:28 -0700881 // Restore device connection states, BT state
882 mDeviceBroker.onAudioServerDied();
883
Eric Laurent0867bed2015-05-20 14:49:08 -0700884 // Restore call state
Jean-Michel Trivi011f39e2017-08-19 18:08:06 -0700885 if (AudioSystem.setPhoneState(mMode) == AudioSystem.AUDIO_STATUS_OK) {
886 mModeLogger.log(new AudioEventLogger.StringEvent(
887 "onAudioServerDied causes setPhoneState(" + AudioSystem.modeToString(mMode) + ")"));
888 }
Eric Laurent0867bed2015-05-20 14:49:08 -0700889
Jean-Michel Trivi8719a1d2017-11-06 11:52:51 -0800890 final int forSys;
891 synchronized (mSettingsLock) {
892 forSys = mCameraSoundForced ?
893 AudioSystem.FORCE_SYSTEM_ENFORCED : AudioSystem.FORCE_NONE;
894 }
Jean-Michel Trivi58850372018-09-14 16:01:28 -0700895
896 mDeviceBroker.setForceUse_Async(AudioSystem.FOR_SYSTEM, forSys, "onAudioServerDied");
Eric Laurent0867bed2015-05-20 14:49:08 -0700897
898 // Restore stream volumes
899 int numStreamTypes = AudioSystem.getNumStreamTypes();
900 for (int streamType = numStreamTypes - 1; streamType >= 0; streamType--) {
901 VolumeStreamState streamState = mStreamStates[streamType];
Eric Laurente4381ec2015-10-29 17:52:48 -0700902 AudioSystem.initStreamVolume(
903 streamType, streamState.mIndexMin / 10, streamState.mIndexMax / 10);
Eric Laurent0867bed2015-05-20 14:49:08 -0700904
905 streamState.applyAllVolumes();
906 }
907
Andy Hungf04b84d2015-12-18 17:33:27 -0800908 // Restore mono mode
Andy Hung7b98e9a2016-02-25 18:34:50 -0800909 updateMasterMono(mContentResolver);
Andy Hungf04b84d2015-12-18 17:33:27 -0800910
Eric Laurent0867bed2015-05-20 14:49:08 -0700911 // Restore ringer mode
912 setRingerModeInt(getRingerModeInternal(), false);
913
Mikhail Naganovb668bc62018-02-13 13:46:38 -0800914 // Reset device rotation (if monitored for this device)
Eric Laurent0867bed2015-05-20 14:49:08 -0700915 if (mMonitorRotation) {
Jean-Michel Trivi24806db2015-10-01 15:00:59 -0700916 RotationHelper.updateOrientation();
Eric Laurent0867bed2015-05-20 14:49:08 -0700917 }
918
Eric Laurent0867bed2015-05-20 14:49:08 -0700919 synchronized (mSettingsLock) {
Jean-Michel Trivi011f39e2017-08-19 18:08:06 -0700920 final int forDock = mDockAudioMediaEnabled ?
921 AudioSystem.FORCE_ANALOG_DOCK : AudioSystem.FORCE_NONE;
Jean-Michel Trivi58850372018-09-14 16:01:28 -0700922 mDeviceBroker.setForceUse_Async(AudioSystem.FOR_DOCK, forDock, "onAudioServerDied");
Jean-Michel Trivi011f39e2017-08-19 18:08:06 -0700923 sendEncodedSurroundMode(mContentResolver, "onAudioServerDied");
jiabin39940752018-04-02 18:18:45 -0700924 sendEnabledSurroundFormats(mContentResolver, true);
Eric Laurent1c9c1d52018-10-17 10:06:46 -0700925 updateAssistantUId(true);
926 }
927 synchronized (mAccessibilityServiceUidsLock) {
928 AudioSystem.setA11yServicesUids(mAccessibilityServiceUids);
Eric Laurent0867bed2015-05-20 14:49:08 -0700929 }
Shubangc480a712018-06-11 18:02:42 -0700930 synchronized (mHdmiClientLock) {
931 if (mHdmiManager != null && mHdmiTvClient != null) {
932 setHdmiSystemAudioSupported(mHdmiSystemAudioSupported);
Eric Laurent0867bed2015-05-20 14:49:08 -0700933 }
934 }
935
936 synchronized (mAudioPolicies) {
937 for (AudioPolicyProxy policy : mAudioPolicies.values()) {
938 policy.connectMixes();
939 }
940 }
941
942 onIndicateSystemReady();
943 // indicate the end of reconfiguration phase to audio HAL
944 AudioSystem.setParameters("restarting=false");
Eric Laurent1d3cdce2018-01-20 10:31:21 -0800945
946 sendMsg(mAudioHandler, MSG_DISPATCH_AUDIO_SERVER_STATE,
947 SENDMSG_QUEUE, 1, 0, null, 0);
948 }
949
950 private void onDispatchAudioServerStateChange(boolean state) {
951 synchronized (mAudioServerStateListeners) {
952 for (AsdProxy asdp : mAudioServerStateListeners.values()) {
953 try {
954 asdp.callback().dispatchAudioServerStateChange(state);
955 } catch (RemoteException e) {
956 Log.w(TAG, "Could not call dispatchAudioServerStateChange()", e);
957 }
958 }
959 }
Eric Laurent4a5eeb92014-05-06 10:49:04 -0700960 }
961
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800962 private void createAudioSystemThread() {
963 mAudioSystemThread = new AudioSystemThread();
964 mAudioSystemThread.start();
965 waitForAudioHandlerCreation();
966 }
967
968 /** Waits for the volume handler to be created by the other thread. */
969 private void waitForAudioHandlerCreation() {
970 synchronized(this) {
971 while (mAudioHandler == null) {
972 try {
973 // Wait for mAudioHandler to be set by the other thread
974 wait();
975 } catch (InterruptedException e) {
976 Log.e(TAG, "Interrupted while waiting on volume handler.");
977 }
978 }
979 }
980 }
981
Eric Laurent24482012012-05-10 09:41:17 -0700982 private void checkAllAliasStreamVolumes() {
Jean-Michel Trivi085346a2018-02-14 10:48:51 -0800983 synchronized (mSettingsLock) {
984 synchronized (VolumeStreamState.class) {
985 int numStreamTypes = AudioSystem.getNumStreamTypes();
986 for (int streamType = 0; streamType < numStreamTypes; streamType++) {
987 mStreamStates[streamType]
988 .setAllIndexes(mStreamStates[mStreamVolumeAlias[streamType]], TAG);
989 // apply stream volume
990 if (!mStreamStates[streamType].mIsMuted) {
991 mStreamStates[streamType].applyAllVolumes();
992 }
Eric Laurent8fa4d6f2014-10-30 14:13:03 -0700993 }
Eric Laurent24482012012-05-10 09:41:17 -0700994 }
995 }
996 }
997
Jean-Michel Trivi58850372018-09-14 16:01:28 -0700998 /**
999 * Called from AudioDeviceBroker when DEVICE_OUT_HDMI is connected or disconnected.
1000 */
1001 /*package*/ void checkVolumeCecOnHdmiConnection(int state, String caller) {
1002 if (state != 0) {
1003 // DEVICE_OUT_HDMI is now connected
1004 if ((AudioSystem.DEVICE_OUT_HDMI & mSafeMediaVolumeDevices) != 0) {
1005 sendMsg(mAudioHandler,
1006 MSG_CHECK_MUSIC_ACTIVE,
1007 SENDMSG_REPLACE,
1008 0,
1009 0,
1010 caller,
1011 MUSIC_ACTIVE_POLL_PERIOD_MS);
1012 }
1013
1014 if (isPlatformTelevision()) {
1015 mFixedVolumeDevices |= AudioSystem.DEVICE_OUT_HDMI;
1016 checkAllFixedVolumeDevices();
1017 synchronized (mHdmiClientLock) {
1018 if (mHdmiManager != null && mHdmiPlaybackClient != null) {
1019 mHdmiCecSink = false;
1020 mHdmiPlaybackClient.queryDisplayStatus(mHdmiDisplayStatusCallback);
1021 }
1022 }
1023 }
1024 sendEnabledSurroundFormats(mContentResolver, true);
1025 } else {
1026 // DEVICE_OUT_HDMI disconnected
1027 if (isPlatformTelevision()) {
1028 synchronized (mHdmiClientLock) {
1029 if (mHdmiManager != null) {
1030 mHdmiCecSink = false;
1031 }
1032 }
1033 }
1034 }
1035 }
1036
Eric Laurent212532b2014-07-21 15:43:18 -07001037 private void checkAllFixedVolumeDevices()
1038 {
1039 int numStreamTypes = AudioSystem.getNumStreamTypes();
1040 for (int streamType = 0; streamType < numStreamTypes; streamType++) {
1041 mStreamStates[streamType].checkFixedVolumeDevices();
1042 }
1043 }
1044
Jean-Michel Triviba5270b2014-10-01 17:49:29 -07001045 private void checkAllFixedVolumeDevices(int streamType) {
1046 mStreamStates[streamType].checkFixedVolumeDevices();
1047 }
1048
John Spurlockb6e19e32015-03-10 21:33:44 -04001049 private void checkMuteAffectedStreams() {
1050 // any stream with a min level > 0 is not muteable by definition
Tomoharu Kasaharaa0d0c542019-01-18 20:04:38 +09001051 // STREAM_VOICE_CALL and STREAM_BLUETOOTH_SCO can be muted by applications
1052 // that has the the MODIFY_PHONE_STATE permission.
John Spurlockb6e19e32015-03-10 21:33:44 -04001053 for (int i = 0; i < mStreamStates.length; i++) {
1054 final VolumeStreamState vss = mStreamStates[i];
Nadav Bar6b7751d2017-12-24 16:03:08 +02001055 if (vss.mIndexMin > 0 &&
Tomoharu Kasaharaa0d0c542019-01-18 20:04:38 +09001056 (vss.mStreamType != AudioSystem.STREAM_VOICE_CALL &&
1057 vss.mStreamType != AudioSystem.STREAM_BLUETOOTH_SCO)) {
John Spurlockb6e19e32015-03-10 21:33:44 -04001058 mMuteAffectedStreams &= ~(1 << vss.mStreamType);
1059 }
1060 }
1061 }
1062
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001063 private void createStreamStates() {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001064 int numStreamTypes = AudioSystem.getNumStreamTypes();
1065 VolumeStreamState[] streams = mStreamStates = new VolumeStreamState[numStreamTypes];
1066
1067 for (int i = 0; i < numStreamTypes; i++) {
Jean-Michel Trivia53b7052017-04-12 18:27:01 -07001068 streams[i] =
1069 new VolumeStreamState(System.VOLUME_SETTINGS_INT[mStreamVolumeAlias[i]], i);
Eric Laurenta553c252009-07-17 12:17:14 -07001070 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001071
Eric Laurent212532b2014-07-21 15:43:18 -07001072 checkAllFixedVolumeDevices();
Eric Laurent24482012012-05-10 09:41:17 -07001073 checkAllAliasStreamVolumes();
John Spurlockb6e19e32015-03-10 21:33:44 -04001074 checkMuteAffectedStreams();
Eric Laurent403bd342017-07-11 16:21:44 -07001075 updateDefaultVolumes();
1076 }
1077
1078 // Update default indexes from aliased streams. Must be called after mStreamStates is created
1079 private void updateDefaultVolumes() {
1080 for (int stream = 0; stream < mStreamStates.length; stream++) {
1081 if (stream != mStreamVolumeAlias[stream]) {
1082 AudioSystem.DEFAULT_STREAM_VOLUME[stream] = rescaleIndex(
1083 AudioSystem.DEFAULT_STREAM_VOLUME[mStreamVolumeAlias[stream]],
1084 mStreamVolumeAlias[stream],
1085 stream);
1086 }
1087 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001088 }
1089
Eric Laurentbffc3d12012-05-07 17:43:49 -07001090 private void dumpStreamStates(PrintWriter pw) {
1091 pw.println("\nStream volumes (device: index)");
1092 int numStreamTypes = AudioSystem.getNumStreamTypes();
1093 for (int i = 0; i < numStreamTypes; i++) {
John Spurlock61560172015-02-06 19:46:04 -05001094 pw.println("- " + AudioSystem.STREAM_NAMES[i] + ":");
Eric Laurentbffc3d12012-05-07 17:43:49 -07001095 mStreamStates[i].dump(pw);
1096 pw.println("");
1097 }
Eric Laurentdd45d012012-10-08 09:04:34 -07001098 pw.print("\n- mute affected streams = 0x");
1099 pw.println(Integer.toHexString(mMuteAffectedStreams));
Eric Laurentbffc3d12012-05-07 17:43:49 -07001100 }
1101
John Spurlock90874332015-03-10 16:00:54 -04001102 private void updateStreamVolumeAlias(boolean updateVolumes, String caller) {
Eric Laurent6d517662012-04-23 18:42:39 -07001103 int dtmfStreamAlias;
Jean-Michel Triviac487672016-11-11 10:05:18 -08001104 final int a11yStreamAlias = sIndependentA11yVolume ?
1105 AudioSystem.STREAM_ACCESSIBILITY : AudioSystem.STREAM_MUSIC;
Eric Laurent212532b2014-07-21 15:43:18 -07001106
Muyuan Li1ed6df62016-06-18 11:16:52 -07001107 if (mIsSingleVolume) {
Eric Laurent212532b2014-07-21 15:43:18 -07001108 mStreamVolumeAlias = STREAM_VOLUME_ALIAS_TELEVISION;
1109 dtmfStreamAlias = AudioSystem.STREAM_MUSIC;
Muyuan Li1ed6df62016-06-18 11:16:52 -07001110 } else {
1111 switch (mPlatformType) {
1112 case AudioSystem.PLATFORM_VOICE:
1113 mStreamVolumeAlias = STREAM_VOLUME_ALIAS_VOICE;
1114 dtmfStreamAlias = AudioSystem.STREAM_RING;
1115 break;
1116 default:
1117 mStreamVolumeAlias = STREAM_VOLUME_ALIAS_DEFAULT;
1118 dtmfStreamAlias = AudioSystem.STREAM_MUSIC;
1119 }
Eric Laurent6d517662012-04-23 18:42:39 -07001120 }
Eric Laurent212532b2014-07-21 15:43:18 -07001121
Muyuan Li1ed6df62016-06-18 11:16:52 -07001122 if (mIsSingleVolume) {
Eric Laurent212532b2014-07-21 15:43:18 -07001123 mRingerModeAffectedStreams = 0;
Eric Laurent24e0d9b2013-10-03 18:15:07 -07001124 } else {
Eric Laurent212532b2014-07-21 15:43:18 -07001125 if (isInCommunication()) {
1126 dtmfStreamAlias = AudioSystem.STREAM_VOICE_CALL;
1127 mRingerModeAffectedStreams &= ~(1 << AudioSystem.STREAM_DTMF);
1128 } else {
1129 mRingerModeAffectedStreams |= (1 << AudioSystem.STREAM_DTMF);
1130 }
Eric Laurent6d517662012-04-23 18:42:39 -07001131 }
Eric Laurent212532b2014-07-21 15:43:18 -07001132
Eric Laurent6d517662012-04-23 18:42:39 -07001133 mStreamVolumeAlias[AudioSystem.STREAM_DTMF] = dtmfStreamAlias;
Jean-Michel Trivi170a0ee2017-04-14 18:13:26 -07001134 mStreamVolumeAlias[AudioSystem.STREAM_ACCESSIBILITY] = a11yStreamAlias;
Jean-Michel Triviac487672016-11-11 10:05:18 -08001135
Eric Laurent403bd342017-07-11 16:21:44 -07001136 if (updateVolumes && mStreamStates != null) {
1137 updateDefaultVolumes();
1138
Jean-Michel Trivi085346a2018-02-14 10:48:51 -08001139 synchronized (mSettingsLock) {
1140 synchronized (VolumeStreamState.class) {
1141 mStreamStates[AudioSystem.STREAM_DTMF]
1142 .setAllIndexes(mStreamStates[dtmfStreamAlias], caller);
1143 mStreamStates[AudioSystem.STREAM_ACCESSIBILITY].mVolumeIndexSettingName =
1144 System.VOLUME_SETTINGS_INT[a11yStreamAlias];
1145 mStreamStates[AudioSystem.STREAM_ACCESSIBILITY].setAllIndexes(
1146 mStreamStates[a11yStreamAlias], caller);
Jean-Michel Trivie05eef82018-03-08 18:56:34 -08001147 mStreamStates[AudioSystem.STREAM_ACCESSIBILITY].refreshRange(
1148 mStreamVolumeAlias[AudioSystem.STREAM_ACCESSIBILITY]);
Jean-Michel Trivi085346a2018-02-14 10:48:51 -08001149 }
1150 }
Jean-Michel Trivi170a0ee2017-04-14 18:13:26 -07001151 if (sIndependentA11yVolume) {
1152 // restore the a11y values from the settings
1153 mStreamStates[AudioSystem.STREAM_ACCESSIBILITY].readSettings();
1154 }
1155
Eric Laurent24e0d9b2013-10-03 18:15:07 -07001156 // apply stream mute states according to new value of mRingerModeAffectedStreams
John Spurlock661f2cf2014-11-17 10:29:10 -05001157 setRingerModeInt(getRingerModeInternal(), false);
Eric Laurent6d517662012-04-23 18:42:39 -07001158 sendMsg(mAudioHandler,
1159 MSG_SET_ALL_VOLUMES,
1160 SENDMSG_QUEUE,
1161 0,
1162 0,
1163 mStreamStates[AudioSystem.STREAM_DTMF], 0);
Jean-Michel Triviac487672016-11-11 10:05:18 -08001164 sendMsg(mAudioHandler,
1165 MSG_SET_ALL_VOLUMES,
1166 SENDMSG_QUEUE,
1167 0,
1168 0,
1169 mStreamStates[AudioSystem.STREAM_ACCESSIBILITY], 0);
Eric Laurent6d517662012-04-23 18:42:39 -07001170 }
1171 }
1172
Eric Laurent7ee1e4f2012-10-26 18:11:21 -07001173 private void readDockAudioSettings(ContentResolver cr)
1174 {
1175 mDockAudioMediaEnabled = Settings.Global.getInt(
Eric Laurent5ba0ffa02012-10-29 12:31:09 -07001176 cr, Settings.Global.DOCK_AUDIO_MEDIA_ENABLED, 0) == 1;
Eric Laurent7ee1e4f2012-10-26 18:11:21 -07001177
Eric Laurent7ee1e4f2012-10-26 18:11:21 -07001178 sendMsg(mAudioHandler,
1179 MSG_SET_FORCE_USE,
1180 SENDMSG_QUEUE,
1181 AudioSystem.FOR_DOCK,
1182 mDockAudioMediaEnabled ?
1183 AudioSystem.FORCE_ANALOG_DOCK : AudioSystem.FORCE_NONE,
Jean-Michel Trivi011f39e2017-08-19 18:08:06 -07001184 new String("readDockAudioSettings"),
Eric Laurent7ee1e4f2012-10-26 18:11:21 -07001185 0);
1186 }
1187
Phil Burkac0f7042016-02-24 12:19:08 -08001188
Andy Hung7b98e9a2016-02-25 18:34:50 -08001189 private void updateMasterMono(ContentResolver cr)
1190 {
1191 final boolean masterMono = System.getIntForUser(
1192 cr, System.MASTER_MONO, 0 /* default */, UserHandle.USER_CURRENT) == 1;
1193 if (DEBUG_VOL) {
1194 Log.d(TAG, String.format("Master mono %b", masterMono));
1195 }
1196 AudioSystem.setMasterMono(masterMono);
1197 }
1198
Jean-Michel Trivi011f39e2017-08-19 18:08:06 -07001199 private void sendEncodedSurroundMode(ContentResolver cr, String eventSource)
Phil Burkac0f7042016-02-24 12:19:08 -08001200 {
Jean-Michel Trivi58850372018-09-14 16:01:28 -07001201 final int encodedSurroundMode = Settings.Global.getInt(
Phil Burkac0f7042016-02-24 12:19:08 -08001202 cr, Settings.Global.ENCODED_SURROUND_OUTPUT,
1203 Settings.Global.ENCODED_SURROUND_OUTPUT_AUTO);
Jean-Michel Trivi011f39e2017-08-19 18:08:06 -07001204 sendEncodedSurroundMode(encodedSurroundMode, eventSource);
Phil Burkac0f7042016-02-24 12:19:08 -08001205 }
1206
Jean-Michel Trivi011f39e2017-08-19 18:08:06 -07001207 private void sendEncodedSurroundMode(int encodedSurroundMode, String eventSource)
Phil Burkac0f7042016-02-24 12:19:08 -08001208 {
1209 // initialize to guaranteed bad value
1210 int forceSetting = AudioSystem.NUM_FORCE_CONFIG;
1211 switch (encodedSurroundMode) {
1212 case Settings.Global.ENCODED_SURROUND_OUTPUT_AUTO:
1213 forceSetting = AudioSystem.FORCE_NONE;
1214 break;
1215 case Settings.Global.ENCODED_SURROUND_OUTPUT_NEVER:
1216 forceSetting = AudioSystem.FORCE_ENCODED_SURROUND_NEVER;
1217 break;
1218 case Settings.Global.ENCODED_SURROUND_OUTPUT_ALWAYS:
1219 forceSetting = AudioSystem.FORCE_ENCODED_SURROUND_ALWAYS;
1220 break;
jiabin39940752018-04-02 18:18:45 -07001221 case Settings.Global.ENCODED_SURROUND_OUTPUT_MANUAL:
1222 forceSetting = AudioSystem.FORCE_ENCODED_SURROUND_MANUAL;
1223 break;
Phil Burkac0f7042016-02-24 12:19:08 -08001224 default:
1225 Log.e(TAG, "updateSurroundSoundSettings: illegal value "
1226 + encodedSurroundMode);
1227 break;
1228 }
1229 if (forceSetting != AudioSystem.NUM_FORCE_CONFIG) {
Jean-Michel Trivi58850372018-09-14 16:01:28 -07001230 mDeviceBroker.setForceUse_Async(AudioSystem.FOR_ENCODED_SURROUND, forceSetting,
1231 eventSource);
Phil Burkac0f7042016-02-24 12:19:08 -08001232 }
1233 }
1234
jiabin39940752018-04-02 18:18:45 -07001235 private void sendEnabledSurroundFormats(ContentResolver cr, boolean forceUpdate) {
1236 if (mEncodedSurroundMode != Settings.Global.ENCODED_SURROUND_OUTPUT_MANUAL) {
1237 // Manually enable surround formats only when the setting is in manual mode.
1238 return;
1239 }
1240 String enabledSurroundFormats = Settings.Global.getString(
1241 cr, Settings.Global.ENCODED_SURROUND_OUTPUT_ENABLED_FORMATS);
jiabin6db5f862018-05-17 10:33:09 -07001242 if (enabledSurroundFormats == null) {
1243 // Never allow enabledSurroundFormats as a null, which could happen when
1244 // ENCODED_SURROUND_OUTPUT_ENABLED_FORMATS is not appear in settings DB.
1245 enabledSurroundFormats = "";
1246 }
jiabin39940752018-04-02 18:18:45 -07001247 if (!forceUpdate && TextUtils.equals(enabledSurroundFormats, mEnabledSurroundFormats)) {
1248 // Update enabled surround formats to AudioPolicyManager only when forceUpdate
1249 // is true or enabled surround formats changed.
1250 return;
1251 }
1252
1253 mEnabledSurroundFormats = enabledSurroundFormats;
1254 String[] surroundFormats = TextUtils.split(enabledSurroundFormats, ",");
1255 ArrayList<Integer> formats = new ArrayList<>();
1256 for (String format : surroundFormats) {
1257 try {
1258 int audioFormat = Integer.valueOf(format);
1259 boolean isSurroundFormat = false;
1260 for (int sf : AudioFormat.SURROUND_SOUND_ENCODING) {
1261 if (sf == audioFormat) {
1262 isSurroundFormat = true;
1263 break;
1264 }
1265 }
1266 if (isSurroundFormat && !formats.contains(audioFormat)) {
1267 formats.add(audioFormat);
1268 }
1269 } catch (Exception e) {
1270 Log.e(TAG, "Invalid enabled surround format:" + format);
1271 }
1272 }
1273 // Set filtered surround formats to settings DB in case
1274 // there are invalid surround formats in original settings.
1275 Settings.Global.putString(mContext.getContentResolver(),
1276 Settings.Global.ENCODED_SURROUND_OUTPUT_ENABLED_FORMATS,
1277 TextUtils.join(",", formats));
1278 sendMsg(mAudioHandler, MSG_ENABLE_SURROUND_FORMATS, SENDMSG_QUEUE, 0, 0, formats, 0);
1279 }
1280
1281 private void onEnableSurroundFormats(ArrayList<Integer> enabledSurroundFormats) {
1282 // Set surround format enabled accordingly.
1283 for (int surroundFormat : AudioFormat.SURROUND_SOUND_ENCODING) {
1284 boolean enabled = enabledSurroundFormats.contains(surroundFormat);
1285 int ret = AudioSystem.setSurroundFormatEnabled(surroundFormat, enabled);
1286 Log.i(TAG, "enable surround format:" + surroundFormat + " " + enabled + " " + ret);
1287 }
1288 }
1289
Eric Laurent1c9c1d52018-10-17 10:06:46 -07001290 @GuardedBy("mSettingsLock")
1291 private void updateAssistantUId(boolean forceUpdate) {
1292 int assistantUid = 0;
1293
1294 // Consider assistants in the following order of priority:
1295 // 1) voice interaction service
1296 // 2) assistant
1297 String assistantName = Settings.Secure.getStringForUser(
1298 mContentResolver,
1299 Settings.Secure.VOICE_INTERACTION_SERVICE, UserHandle.USER_CURRENT);
1300 if (TextUtils.isEmpty(assistantName)) {
1301 assistantName = Settings.Secure.getStringForUser(
1302 mContentResolver,
1303 Settings.Secure.ASSISTANT, UserHandle.USER_CURRENT);
1304 }
1305 if (!TextUtils.isEmpty(assistantName)) {
1306 String packageName = ComponentName.unflattenFromString(assistantName).getPackageName();
1307 if (!TextUtils.isEmpty(packageName)) {
1308 try {
1309 assistantUid = mContext.getPackageManager().getPackageUid(packageName, 0);
1310 } catch (PackageManager.NameNotFoundException e) {
1311 Log.e(TAG,
1312 "updateAssistantUId() could not find UID for package: " + packageName);
1313 }
1314 }
1315 }
1316
1317 if (assistantUid != mAssistantUid || forceUpdate) {
1318 AudioSystem.setAssistantUid(assistantUid);
1319 mAssistantUid = assistantUid;
1320 }
1321 }
1322
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001323 private void readPersistedSettings() {
1324 final ContentResolver cr = mContentResolver;
1325
Eric Laurentbffc3d12012-05-07 17:43:49 -07001326 int ringerModeFromSettings =
Jeff Sharkey8d9a1f62012-10-18 15:38:14 -07001327 Settings.Global.getInt(
1328 cr, Settings.Global.MODE_RINGER, AudioManager.RINGER_MODE_NORMAL);
Eric Laurentbffc3d12012-05-07 17:43:49 -07001329 int ringerMode = ringerModeFromSettings;
Eric Laurent72668b22011-07-19 16:04:27 -07001330 // sanity check in case the settings are restored from a device with incompatible
1331 // ringer modes
John Spurlock97559372014-10-24 16:27:36 -04001332 if (!isValidRingerMode(ringerMode)) {
Glenn Kastenba195eb2011-12-13 09:30:40 -08001333 ringerMode = AudioManager.RINGER_MODE_NORMAL;
Eric Laurentbffc3d12012-05-07 17:43:49 -07001334 }
1335 if ((ringerMode == AudioManager.RINGER_MODE_VIBRATE) && !mHasVibrator) {
1336 ringerMode = AudioManager.RINGER_MODE_SILENT;
1337 }
1338 if (ringerMode != ringerModeFromSettings) {
Jeff Sharkey8d9a1f62012-10-18 15:38:14 -07001339 Settings.Global.putInt(cr, Settings.Global.MODE_RINGER, ringerMode);
Glenn Kastenba195eb2011-12-13 09:30:40 -08001340 }
Muyuan Li1ed6df62016-06-18 11:16:52 -07001341 if (mUseFixedVolume || mIsSingleVolume) {
Eric Laurent83a017b2013-03-19 18:15:31 -07001342 ringerMode = AudioManager.RINGER_MODE_NORMAL;
1343 }
Glenn Kastenba195eb2011-12-13 09:30:40 -08001344 synchronized(mSettingsLock) {
1345 mRingerMode = ringerMode;
John Spurlock661f2cf2014-11-17 10:29:10 -05001346 if (mRingerModeExternal == -1) {
1347 mRingerModeExternal = mRingerMode;
1348 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001349
Eric Laurentdd45d012012-10-08 09:04:34 -07001350 // System.VIBRATE_ON is not used any more but defaults for mVibrateSetting
1351 // are still needed while setVibrateSetting() and getVibrateSetting() are being
1352 // deprecated.
John Spurlock61560172015-02-06 19:46:04 -05001353 mVibrateSetting = AudioSystem.getValueForVibrateSetting(0,
Eric Laurentdd45d012012-10-08 09:04:34 -07001354 AudioManager.VIBRATE_TYPE_NOTIFICATION,
1355 mHasVibrator ? AudioManager.VIBRATE_SETTING_ONLY_SILENT
1356 : AudioManager.VIBRATE_SETTING_OFF);
John Spurlock61560172015-02-06 19:46:04 -05001357 mVibrateSetting = AudioSystem.getValueForVibrateSetting(mVibrateSetting,
Eric Laurentdd45d012012-10-08 09:04:34 -07001358 AudioManager.VIBRATE_TYPE_RINGER,
1359 mHasVibrator ? AudioManager.VIBRATE_SETTING_ONLY_SILENT
1360 : AudioManager.VIBRATE_SETTING_OFF);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001361
Beverlyd6964762018-02-16 14:07:03 -05001362 updateRingerAndZenModeAffectedStreams();
Eric Laurent7ee1e4f2012-10-26 18:11:21 -07001363 readDockAudioSettings(cr);
Jean-Michel Trivi011f39e2017-08-19 18:08:06 -07001364 sendEncodedSurroundMode(cr, "readPersistedSettings");
jiabin39940752018-04-02 18:18:45 -07001365 sendEnabledSurroundFormats(cr, true);
Eric Laurent1c9c1d52018-10-17 10:06:46 -07001366 updateAssistantUId(true);
Eric Laurent402f7f22011-02-04 12:30:32 -08001367 }
Eric Laurentc1d41662011-07-19 11:21:13 -07001368
Eric Laurentbc0fab1f2012-09-19 11:24:41 -07001369 mMuteAffectedStreams = System.getIntForUser(cr,
John Spurlock61560172015-02-06 19:46:04 -05001370 System.MUTE_STREAMS_AFFECTED, AudioSystem.DEFAULT_MUTE_STREAMS_AFFECTED,
John Spurlock24c05182015-02-05 12:30:36 -05001371 UserHandle.USER_CURRENT);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001372
Andy Hung7b98e9a2016-02-25 18:34:50 -08001373 updateMasterMono(cr);
Andy Hungf04b84d2015-12-18 17:33:27 -08001374
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001375 // Each stream will read its own persisted settings
1376
John Spurlockbcc10872014-11-28 15:29:21 -05001377 // Broadcast the sticky intents
1378 broadcastRingerMode(AudioManager.RINGER_MODE_CHANGED_ACTION, mRingerModeExternal);
1379 broadcastRingerMode(AudioManager.INTERNAL_RINGER_MODE_CHANGED_ACTION, mRingerMode);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001380
1381 // Broadcast vibrate settings
1382 broadcastVibrateSetting(AudioManager.VIBRATE_TYPE_RINGER);
1383 broadcastVibrateSetting(AudioManager.VIBRATE_TYPE_NOTIFICATION);
Jean-Michel Trivid589fea2011-04-15 11:28:10 -07001384
John Spurlock33f4e042014-07-11 13:10:58 -04001385 // Load settings for the volume controller
1386 mVolumeController.loadSettings(cr);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001387 }
1388
Eric Laurentc0232482016-03-15 18:19:23 -07001389 private void readUserRestrictions() {
1390 final int currentUser = getCurrentUserId();
1391
1392 // Check the current user restriction.
Tony Makc1205112016-07-22 16:02:59 +01001393 boolean masterMute =
1394 mUserManagerInternal.getUserRestriction(currentUser,
Esteban Talavera492b4722017-02-13 14:59:45 +00001395 UserManager.DISALLOW_UNMUTE_DEVICE)
Tony Makc1205112016-07-22 16:02:59 +01001396 || mUserManagerInternal.getUserRestriction(currentUser,
1397 UserManager.DISALLOW_ADJUST_VOLUME);
Eric Laurentc0232482016-03-15 18:19:23 -07001398 if (mUseFixedVolume) {
1399 masterMute = false;
1400 AudioSystem.setMasterVolume(1.0f);
1401 }
1402 if (DEBUG_VOL) {
1403 Log.d(TAG, String.format("Master mute %s, user=%d", masterMute, currentUser));
1404 }
1405 setSystemAudioMute(masterMute);
1406 AudioSystem.setMasterMute(masterMute);
1407 broadcastMasterMuteStatus(masterMute);
1408
1409 boolean microphoneMute = mUserManagerInternal.getUserRestriction(
1410 currentUser, UserManager.DISALLOW_UNMUTE_MICROPHONE);
1411 if (DEBUG_VOL) {
1412 Log.d(TAG, String.format("Mic mute %s, user=%d", microphoneMute, currentUser));
1413 }
1414 AudioSystem.muteMicrophone(microphoneMute);
1415 }
1416
Eric Laurenta553c252009-07-17 12:17:14 -07001417 private int rescaleIndex(int index, int srcStream, int dstStream) {
Jean-Michel Trivie05eef82018-03-08 18:56:34 -08001418 final int rescaled =
1419 (index * mStreamStates[dstStream].getMaxIndex()
1420 + mStreamStates[srcStream].getMaxIndex() / 2)
1421 / mStreamStates[srcStream].getMaxIndex();
1422 if (rescaled < mStreamStates[dstStream].getMinIndex()) {
1423 return mStreamStates[dstStream].getMinIndex();
1424 } else {
1425 return rescaled;
1426 }
Eric Laurenta553c252009-07-17 12:17:14 -07001427 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001428
1429 ///////////////////////////////////////////////////////////////////////////
1430 // IPC methods
1431 ///////////////////////////////////////////////////////////////////////////
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001432 /** @see AudioManager#adjustVolume(int, int) */
Dianne Hackbornba50b97c2013-04-30 15:04:46 -07001433 public void adjustSuggestedStreamVolume(int direction, int suggestedStreamType, int flags,
John Spurlock90874332015-03-10 16:00:54 -04001434 String callingPackage, String caller) {
Jean-Michel Trivi610aa9b2018-01-27 15:42:42 -08001435 final IAudioPolicyCallback extVolCtlr;
1436 synchronized (mExtVolumeControllerLock) {
1437 extVolCtlr = mExtVolumeController;
1438 }
1439 if (extVolCtlr != null) {
Jean-Michel Trivi7ed71472018-02-02 16:52:09 -08001440 sendMsg(mAudioHandler, MSG_NOTIFY_VOL_EVENT, SENDMSG_QUEUE,
1441 direction, 0 /*ignored*/,
1442 extVolCtlr, 0 /*delay*/);
Jean-Michel Trivi610aa9b2018-01-27 15:42:42 -08001443 } else {
1444 adjustSuggestedStreamVolume(direction, suggestedStreamType, flags, callingPackage,
1445 caller, Binder.getCallingUid());
1446 }
RoboErik272e1612014-09-05 11:39:29 -07001447 }
1448
1449 private void adjustSuggestedStreamVolume(int direction, int suggestedStreamType, int flags,
John Spurlock90874332015-03-10 16:00:54 -04001450 String callingPackage, String caller, int uid) {
1451 if (DEBUG_VOL) Log.d(TAG, "adjustSuggestedStreamVolume() stream=" + suggestedStreamType
Jean-Michel Trivia7880d42017-04-15 12:41:05 -07001452 + ", flags=" + flags + ", caller=" + caller
1453 + ", volControlStream=" + mVolumeControlStream
1454 + ", userSelect=" + mUserSelectedVolumeControlStream);
Jean-Michel Trivi58850372018-09-14 16:01:28 -07001455 sVolumeLogger.log(new VolumeEvent(VolumeEvent.VOL_ADJUST_SUGG_VOL, suggestedStreamType,
Jean-Michel Trivicf170362017-08-24 17:24:57 -07001456 direction/*val1*/, flags/*val2*/, new StringBuilder(callingPackage)
1457 .append("/").append(caller).append(" uid:").append(uid).toString()));
Jean-Michel Trivia7880d42017-04-15 12:41:05 -07001458 final int streamType;
jiabin8fd5d5e2018-03-23 14:09:28 -07001459 synchronized (mForceControlStreamLock) {
1460 // Request lock in case mVolumeControlStream is changed by other thread.
1461 if (mUserSelectedVolumeControlStream) { // implies mVolumeControlStream != -1
Jean-Michel Trivia7880d42017-04-15 12:41:05 -07001462 streamType = mVolumeControlStream;
jiabin8fd5d5e2018-03-23 14:09:28 -07001463 } else {
1464 final int maybeActiveStreamType = getActiveStreamType(suggestedStreamType);
1465 final boolean activeForReal;
1466 if (maybeActiveStreamType == AudioSystem.STREAM_RING
1467 || maybeActiveStreamType == AudioSystem.STREAM_NOTIFICATION) {
1468 activeForReal = wasStreamActiveRecently(maybeActiveStreamType, 0);
1469 } else {
1470 activeForReal = AudioSystem.isStreamActive(maybeActiveStreamType, 0);
1471 }
1472 if (activeForReal || mVolumeControlStream == -1) {
1473 streamType = maybeActiveStreamType;
1474 } else {
1475 streamType = mVolumeControlStream;
1476 }
Jean-Michel Trivia7880d42017-04-15 12:41:05 -07001477 }
Eric Laurent402f7f22011-02-04 12:30:32 -08001478 }
Jean-Michel Trivia7880d42017-04-15 12:41:05 -07001479
1480 final boolean isMute = isMuteAdjust(direction);
1481
John Spurlock0a376af2015-03-26 16:24:12 -04001482 ensureValidStreamType(streamType);
John Spurlock33f4e042014-07-11 13:10:58 -04001483 final int resolvedStream = mStreamVolumeAlias[streamType];
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001484
RoboErik2811dd32014-08-12 09:48:13 -07001485 // Play sounds on STREAM_RING only.
1486 if ((flags & AudioManager.FLAG_PLAY_SOUND) != 0 &&
John Spurlock33f4e042014-07-11 13:10:58 -04001487 resolvedStream != AudioSystem.STREAM_RING) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001488 flags &= ~AudioManager.FLAG_PLAY_SOUND;
1489 }
1490
John Spurlock33f4e042014-07-11 13:10:58 -04001491 // For notifications/ring, show the ui before making any adjustments
RoboErik4197cb62015-01-21 15:45:32 -08001492 // Don't suppress mute/unmute requests
Stanley Changb77e13d2018-08-28 08:16:03 +08001493 // Don't suppress adjustments for single volume device
1494 if (mVolumeController.suppressAdjustment(resolvedStream, flags, isMute)
1495 && !mIsSingleVolume) {
John Spurlock33f4e042014-07-11 13:10:58 -04001496 direction = 0;
1497 flags &= ~AudioManager.FLAG_PLAY_SOUND;
1498 flags &= ~AudioManager.FLAG_VIBRATE;
1499 if (DEBUG_VOL) Log.d(TAG, "Volume controller suppressed adjustment");
1500 }
1501
John Spurlock90874332015-03-10 16:00:54 -04001502 adjustStreamVolume(streamType, direction, flags, callingPackage, caller, uid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001503 }
1504
1505 /** @see AudioManager#adjustStreamVolume(int, int, int) */
Dianne Hackbornba50b97c2013-04-30 15:04:46 -07001506 public void adjustStreamVolume(int streamType, int direction, int flags,
1507 String callingPackage) {
Phil Weaverf1a9aff2017-03-23 17:21:29 -07001508 if ((streamType == AudioManager.STREAM_ACCESSIBILITY) && !canChangeAccessibilityVolume()) {
Jean-Michel Triviab2d9312017-03-13 15:33:39 -07001509 Log.w(TAG, "Trying to call adjustStreamVolume() for a11y without"
Phil Weaverf1a9aff2017-03-23 17:21:29 -07001510 + "CHANGE_ACCESSIBILITY_VOLUME / callingPackage=" + callingPackage);
Jean-Michel Triviab2d9312017-03-13 15:33:39 -07001511 return;
1512 }
Jean-Michel Trivi58850372018-09-14 16:01:28 -07001513 sVolumeLogger.log(new VolumeEvent(VolumeEvent.VOL_ADJUST_STREAM_VOL, streamType,
Jean-Michel Trivicf170362017-08-24 17:24:57 -07001514 direction/*val1*/, flags/*val2*/, callingPackage));
John Spurlock90874332015-03-10 16:00:54 -04001515 adjustStreamVolume(streamType, direction, flags, callingPackage, callingPackage,
1516 Binder.getCallingUid());
RoboErik0dac35a2014-08-12 15:48:49 -07001517 }
1518
Chinyue Chen6affe932018-01-24 14:51:43 +08001519 protected void adjustStreamVolume(int streamType, int direction, int flags,
John Spurlock90874332015-03-10 16:00:54 -04001520 String callingPackage, String caller, int uid) {
Eric Laurent83a017b2013-03-19 18:15:31 -07001521 if (mUseFixedVolume) {
1522 return;
1523 }
John Spurlock90874332015-03-10 16:00:54 -04001524 if (DEBUG_VOL) Log.d(TAG, "adjustStreamVolume() stream=" + streamType + ", dir=" + direction
1525 + ", flags=" + flags + ", caller=" + caller);
Jean-Michel Trivi3114ce32012-06-11 15:03:52 -07001526
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001527 ensureValidDirection(direction);
1528 ensureValidStreamType(streamType);
1529
RoboErik4197cb62015-01-21 15:45:32 -08001530 boolean isMuteAdjust = isMuteAdjust(direction);
1531
John Spurlock3ce37252015-02-17 13:20:45 -05001532 if (isMuteAdjust && !isStreamAffectedByMute(streamType)) {
1533 return;
1534 }
1535
Tomoharu Kasaharaa0d0c542019-01-18 20:04:38 +09001536 // If adjust is mute and the stream is STREAM_VOICE_CALL or STREAM_BLUETOOTH_SCO, make sure
Nadav Bar6b7751d2017-12-24 16:03:08 +02001537 // that the calling app have the MODIFY_PHONE_STATE permission.
1538 if (isMuteAdjust &&
Tomoharu Kasaharaa0d0c542019-01-18 20:04:38 +09001539 (streamType == AudioSystem.STREAM_VOICE_CALL ||
1540 streamType == AudioSystem.STREAM_BLUETOOTH_SCO) &&
Nadav Bar6b7751d2017-12-24 16:03:08 +02001541 mContext.checkCallingOrSelfPermission(
1542 android.Manifest.permission.MODIFY_PHONE_STATE)
1543 != PackageManager.PERMISSION_GRANTED) {
1544 Log.w(TAG, "MODIFY_PHONE_STATE Permission Denial: adjustStreamVolume from pid="
1545 + Binder.getCallingPid() + ", uid=" + Binder.getCallingUid());
1546 return;
1547 }
1548
Eric Laurent96a33d12011-11-08 10:31:57 -08001549 // use stream type alias here so that streams with same alias have the same behavior,
1550 // including with regard to silent mode control (e.g the use of STREAM_RING below and in
1551 // checkForRingerModeChange() in place of STREAM_RING or STREAM_NOTIFICATION)
Eric Laurent6d517662012-04-23 18:42:39 -07001552 int streamTypeAlias = mStreamVolumeAlias[streamType];
RoboErik4197cb62015-01-21 15:45:32 -08001553
Eric Laurentb024c302011-10-14 17:19:27 -07001554 VolumeStreamState streamState = mStreamStates[streamTypeAlias];
Eric Laurent9bc8358d2011-11-18 16:43:31 -08001555
1556 final int device = getDeviceForStream(streamTypeAlias);
Eric Laurent3ef75492012-11-28 12:12:23 -08001557
Eric Laurent42b041e2013-03-29 11:36:03 -07001558 int aliasIndex = streamState.getIndex(device);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001559 boolean adjustVolume = true;
Eric Laurent3ef75492012-11-28 12:12:23 -08001560 int step;
Eric Laurent24482012012-05-10 09:41:17 -07001561
Matthew Xiec9d1d5f2013-09-12 00:32:22 -07001562 // skip a2dp absolute volume control request when the device
1563 // is not an a2dp device
1564 if ((device & AudioSystem.DEVICE_OUT_ALL_A2DP) == 0 &&
1565 (flags & AudioManager.FLAG_BLUETOOTH_ABS_VOLUME) != 0) {
1566 return;
1567 }
1568
Kenny Guy70e0c582015-06-30 19:18:28 +01001569 // If we are being called by the system (e.g. hardware keys) check for current user
1570 // so we handle user restrictions correctly.
1571 if (uid == android.os.Process.SYSTEM_UID) {
1572 uid = UserHandle.getUid(getCurrentUserId(), UserHandle.getAppId(uid));
1573 }
John Spurlock59dc9c12015-03-02 11:20:15 -05001574 if (mAppOps.noteOp(STREAM_VOLUME_OPS[streamTypeAlias], uid, callingPackage)
RoboErik0dac35a2014-08-12 15:48:49 -07001575 != AppOpsManager.MODE_ALLOWED) {
Dianne Hackbornba50b97c2013-04-30 15:04:46 -07001576 return;
1577 }
1578
Eric Laurentfde16d52012-12-03 14:42:39 -08001579 // reset any pending volume command
hyomin.ohd0446dc2018-10-18 13:58:27 +09001580 synchronized (mSafeMediaVolumeStateLock) {
Eric Laurentfde16d52012-12-03 14:42:39 -08001581 mPendingVolumeCommand = null;
1582 }
1583
Eric Laurent3ef75492012-11-28 12:12:23 -08001584 flags &= ~AudioManager.FLAG_FIXED_VOLUME;
1585 if ((streamTypeAlias == AudioSystem.STREAM_MUSIC) &&
1586 ((device & mFixedVolumeDevices) != 0)) {
1587 flags |= AudioManager.FLAG_FIXED_VOLUME;
1588
1589 // Always toggle between max safe volume and 0 for fixed volume devices where safe
1590 // volume is enforced, and max and 0 for the others.
1591 // This is simulated by stepping by the full allowed volume range
1592 if (mSafeMediaVolumeState == SAFE_MEDIA_VOLUME_ACTIVE &&
1593 (device & mSafeMediaVolumeDevices) != 0) {
Eric Laurenteab40d12017-06-09 12:45:21 -07001594 step = safeMediaVolumeIndex(device);
Eric Laurent3ef75492012-11-28 12:12:23 -08001595 } else {
1596 step = streamState.getMaxIndex();
1597 }
1598 if (aliasIndex != 0) {
1599 aliasIndex = step;
1600 }
1601 } else {
1602 // convert one UI step (+/-1) into a number of internal units on the stream alias
1603 step = rescaleIndex(10, streamType, streamTypeAlias);
1604 }
1605
Eric Laurent42b041e2013-03-29 11:36:03 -07001606 // If either the client forces allowing ringer modes for this adjustment,
1607 // or the stream type is one that is affected by ringer modes
1608 if (((flags & AudioManager.FLAG_ALLOW_RINGER_MODES) != 0) ||
John Spurlockee5ad722015-03-03 16:17:21 -05001609 (streamTypeAlias == getUiSoundsStreamType())) {
John Spurlock661f2cf2014-11-17 10:29:10 -05001610 int ringerMode = getRingerModeInternal();
Eric Laurent42b041e2013-03-29 11:36:03 -07001611 // do not vibrate if already in vibrate mode
1612 if (ringerMode == AudioManager.RINGER_MODE_VIBRATE) {
1613 flags &= ~AudioManager.FLAG_VIBRATE;
Eric Laurent3ef75492012-11-28 12:12:23 -08001614 }
RoboErik5452e252015-02-06 15:33:53 -08001615 // Check if the ringer mode handles this adjustment. If it does we don't
1616 // need to adjust the volume further.
John Spurlock50ced3f2015-05-11 16:00:09 -04001617 final int result = checkForRingerModeChange(aliasIndex, direction, step,
Julia Reynoldsed783792016-04-08 15:27:35 -04001618 streamState.mIsMuted, callingPackage, flags);
John Spurlocka11b4af2014-06-01 11:52:23 -04001619 adjustVolume = (result & FLAG_ADJUST_VOLUME) != 0;
1620 // If suppressing a volume adjustment in silent mode, display the UI hint
1621 if ((result & AudioManager.FLAG_SHOW_SILENT_HINT) != 0) {
1622 flags |= AudioManager.FLAG_SHOW_SILENT_HINT;
1623 }
John Spurlock661f2cf2014-11-17 10:29:10 -05001624 // If suppressing a volume down adjustment in vibrate mode, display the UI hint
1625 if ((result & AudioManager.FLAG_SHOW_VIBRATE_HINT) != 0) {
1626 flags |= AudioManager.FLAG_SHOW_VIBRATE_HINT;
1627 }
Eric Laurent42b041e2013-03-29 11:36:03 -07001628 }
Beverlyd6964762018-02-16 14:07:03 -05001629
1630 // If the ringer mode or zen is muting the stream, do not change stream unless
1631 // it'll cause us to exit dnd
Julia Reynoldsed783792016-04-08 15:27:35 -04001632 if (!volumeAdjustmentAllowedByDnd(streamTypeAlias, flags)) {
John Spurlock50ced3f2015-05-11 16:00:09 -04001633 adjustVolume = false;
1634 }
Eric Laurent42b041e2013-03-29 11:36:03 -07001635 int oldIndex = mStreamStates[streamType].getIndex(device);
Eric Laurent3ef75492012-11-28 12:12:23 -08001636
Eric Laurent42b041e2013-03-29 11:36:03 -07001637 if (adjustVolume && (direction != AudioManager.ADJUST_SAME)) {
RoboErik5452e252015-02-06 15:33:53 -08001638 mAudioHandler.removeMessages(MSG_UNMUTE_STREAM);
Matthew Xiec9d1d5f2013-09-12 00:32:22 -07001639
RoboErik4197cb62015-01-21 15:45:32 -08001640 if (isMuteAdjust) {
1641 boolean state;
1642 if (direction == AudioManager.ADJUST_TOGGLE_MUTE) {
1643 state = !streamState.mIsMuted;
1644 } else {
1645 state = direction == AudioManager.ADJUST_MUTE;
1646 }
1647 if (streamTypeAlias == AudioSystem.STREAM_MUSIC) {
1648 setSystemAudioMute(state);
1649 }
1650 for (int stream = 0; stream < mStreamStates.length; stream++) {
1651 if (streamTypeAlias == mStreamVolumeAlias[stream]) {
Sungmin Choi841ed0a2015-07-26 23:09:49 -07001652 if (!(readCameraSoundForced()
1653 && (mStreamStates[stream].getStreamType()
1654 == AudioSystem.STREAM_SYSTEM_ENFORCED))) {
1655 mStreamStates[stream].mute(state);
1656 }
RoboErik4197cb62015-01-21 15:45:32 -08001657 }
1658 }
1659 } else if ((direction == AudioManager.ADJUST_RAISE) &&
Eric Laurent42b041e2013-03-29 11:36:03 -07001660 !checkSafeMediaVolume(streamTypeAlias, aliasIndex + step, device)) {
RoboErik4197cb62015-01-21 15:45:32 -08001661 Log.e(TAG, "adjustStreamVolume() safe volume index = " + oldIndex);
John Spurlock3346a802014-05-20 16:25:37 -04001662 mVolumeController.postDisplaySafeVolumeWarning(flags);
John Spurlock90874332015-03-10 16:00:54 -04001663 } else if (streamState.adjustIndex(direction * step, device, caller)
1664 || streamState.mIsMuted) {
RoboErik4197cb62015-01-21 15:45:32 -08001665 // Post message to set system volume (it in turn will post a
1666 // message to persist).
1667 if (streamState.mIsMuted) {
1668 // Unmute the stream if it was previously muted
RoboErik5452e252015-02-06 15:33:53 -08001669 if (direction == AudioManager.ADJUST_RAISE) {
1670 // unmute immediately for volume up
1671 streamState.mute(false);
1672 } else if (direction == AudioManager.ADJUST_LOWER) {
Muyuan Li1ed6df62016-06-18 11:16:52 -07001673 if (mIsSingleVolume) {
John Spurlocka48d7792015-03-03 17:35:57 -05001674 sendMsg(mAudioHandler, MSG_UNMUTE_STREAM, SENDMSG_QUEUE,
1675 streamTypeAlias, flags, null, UNMUTE_STREAM_DELAY);
1676 }
RoboErik5452e252015-02-06 15:33:53 -08001677 }
RoboErik4197cb62015-01-21 15:45:32 -08001678 }
Eric Laurent42b041e2013-03-29 11:36:03 -07001679 sendMsg(mAudioHandler,
1680 MSG_SET_DEVICE_VOLUME,
1681 SENDMSG_QUEUE,
1682 device,
1683 0,
1684 streamState,
1685 0);
Eric Laurent4bbcc652012-09-24 14:26:30 -07001686 }
Jungshik Jang41d97462014-06-30 22:26:29 +09001687
Jungshik Jang41d97462014-06-30 22:26:29 +09001688 int newIndex = mStreamStates[streamType].getIndex(device);
Ajay Panickere3946c82018-02-26 16:04:15 -08001689
1690 // Check if volume update should be send to AVRCP
1691 if (streamTypeAlias == AudioSystem.STREAM_MUSIC &&
1692 (device & AudioSystem.DEVICE_OUT_ALL_A2DP) != 0 &&
1693 (flags & AudioManager.FLAG_BLUETOOTH_ABS_VOLUME) == 0) {
Jean-Michel Trivi58850372018-09-14 16:01:28 -07001694 if (DEBUG_VOL) {
1695 Log.d(TAG, "adjustSreamVolume: postSetAvrcpAbsoluteVolumeIndex index="
1696 + newIndex + "stream=" + streamType);
Ajay Panickere3946c82018-02-26 16:04:15 -08001697 }
Jean-Michel Trivi58850372018-09-14 16:01:28 -07001698 mDeviceBroker.postSetAvrcpAbsoluteVolumeIndex(newIndex);
Ajay Panickere3946c82018-02-26 16:04:15 -08001699 }
1700
Jakub Pawlowskif9570f32018-02-21 17:15:12 -08001701 // Check if volume update should be send to Hearing Aid
1702 if ((device & AudioSystem.DEVICE_OUT_HEARING_AID) != 0) {
Jean-Michel Trivi58850372018-09-14 16:01:28 -07001703 Log.i(TAG, "adjustSreamVolume postSetHearingAidVolumeIndex index=" + newIndex
1704 + " stream=" + streamType);
1705 mDeviceBroker.postSetHearingAidVolumeIndex(newIndex, streamType);
Jakub Pawlowskif9570f32018-02-21 17:15:12 -08001706 }
1707
Ajay Panickere3946c82018-02-26 16:04:15 -08001708 // Check if volume update should be sent to Hdmi system audio.
Jinsuk Kim336cdb42014-11-29 06:27:00 +09001709 if (streamTypeAlias == AudioSystem.STREAM_MUSIC) {
1710 setSystemAudioVolume(oldIndex, newIndex, getStreamMaxVolume(streamType), flags);
1711 }
Shubangc480a712018-06-11 18:02:42 -07001712 synchronized (mHdmiClientLock) {
1713 if (mHdmiManager != null) {
Eric Laurent212532b2014-07-21 15:43:18 -07001714 // mHdmiCecSink true => mHdmiPlaybackClient != null
1715 if (mHdmiCecSink &&
1716 streamTypeAlias == AudioSystem.STREAM_MUSIC &&
1717 oldIndex != newIndex) {
Shubangc480a712018-06-11 18:02:42 -07001718 int keyCode = (direction == -1) ? KeyEvent.KEYCODE_VOLUME_DOWN :
1719 KeyEvent.KEYCODE_VOLUME_UP;
1720 final long ident = Binder.clearCallingIdentity();
1721 try {
1722 mHdmiPlaybackClient.sendKeyEvent(keyCode, true);
1723 mHdmiPlaybackClient.sendKeyEvent(keyCode, false);
1724 } finally {
1725 Binder.restoreCallingIdentity(ident);
Eric Laurent212532b2014-07-21 15:43:18 -07001726 }
Jungshik Jang41d97462014-06-30 22:26:29 +09001727 }
Shubangc480a712018-06-11 18:02:42 -07001728
1729 if (mHdmiAudioSystemClient != null &&
Shubangde728822018-07-16 16:46:51 -07001730 mHdmiSystemAudioSupported &&
Shubangc480a712018-06-11 18:02:42 -07001731 streamTypeAlias == AudioSystem.STREAM_MUSIC &&
1732 (oldIndex != newIndex || isMuteAdjust)) {
Shubangde728822018-07-16 16:46:51 -07001733 final long identity = Binder.clearCallingIdentity();
Shubangc480a712018-06-11 18:02:42 -07001734 mHdmiAudioSystemClient.sendReportAudioStatusCecCommand(
1735 isMuteAdjust, getStreamVolume(AudioSystem.STREAM_MUSIC),
1736 getStreamMaxVolume(AudioSystem.STREAM_MUSIC),
1737 isStreamMute(AudioSystem.STREAM_MUSIC));
Shubangde728822018-07-16 16:46:51 -07001738 Binder.restoreCallingIdentity(identity);
Shubangc480a712018-06-11 18:02:42 -07001739 }
Jungshik Jang41d97462014-06-30 22:26:29 +09001740 }
1741 }
Eric Laurent4bbcc652012-09-24 14:26:30 -07001742 }
Eric Laurent42b041e2013-03-29 11:36:03 -07001743 int index = mStreamStates[streamType].getIndex(device);
Eric Laurent25101b02011-02-02 09:33:30 -08001744 sendVolumeUpdate(streamType, oldIndex, index, flags);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001745 }
1746
RoboErik5452e252015-02-06 15:33:53 -08001747 // Called after a delay when volume down is pressed while muted
1748 private void onUnmuteStream(int stream, int flags) {
1749 VolumeStreamState streamState = mStreamStates[stream];
1750 streamState.mute(false);
1751
1752 final int device = getDeviceForStream(stream);
1753 final int index = mStreamStates[stream].getIndex(device);
1754 sendVolumeUpdate(stream, index, index, flags);
1755 }
1756
Jinsuk Kim336cdb42014-11-29 06:27:00 +09001757 private void setSystemAudioVolume(int oldVolume, int newVolume, int maxVolume, int flags) {
Jinsuk Kim336cdb42014-11-29 06:27:00 +09001758 // Sets the audio volume of AVR when we are in system audio mode. The new volume info
1759 // is tranformed to HDMI-CEC commands and passed through CEC bus.
Shubangc480a712018-06-11 18:02:42 -07001760 synchronized (mHdmiClientLock) {
1761 if (mHdmiManager == null
1762 || mHdmiTvClient == null
1763 || oldVolume == newVolume
1764 || (flags & AudioManager.FLAG_HDMI_SYSTEM_AUDIO_VOLUME) != 0
1765 || !mHdmiSystemAudioSupported) return;
1766 final long token = Binder.clearCallingIdentity();
1767 try {
1768 mHdmiTvClient.setSystemAudioVolume(oldVolume, newVolume, maxVolume);
1769 } finally {
1770 Binder.restoreCallingIdentity(token);
Jinsuk Kim336cdb42014-11-29 06:27:00 +09001771 }
1772 }
1773 }
1774
Eric Laurentfde16d52012-12-03 14:42:39 -08001775 // StreamVolumeCommand contains the information needed to defer the process of
1776 // setStreamVolume() in case the user has to acknowledge the safe volume warning message.
1777 class StreamVolumeCommand {
1778 public final int mStreamType;
1779 public final int mIndex;
1780 public final int mFlags;
1781 public final int mDevice;
Eric Laurent9ce379a2010-02-16 06:00:26 -08001782
Eric Laurentfde16d52012-12-03 14:42:39 -08001783 StreamVolumeCommand(int streamType, int index, int flags, int device) {
1784 mStreamType = streamType;
1785 mIndex = index;
1786 mFlags = flags;
1787 mDevice = device;
Eric Laurentb024c302011-10-14 17:19:27 -07001788 }
John Spurlock35134602014-07-24 18:10:48 -04001789
1790 @Override
1791 public String toString() {
1792 return new StringBuilder().append("{streamType=").append(mStreamType).append(",index=")
1793 .append(mIndex).append(",flags=").append(mFlags).append(",device=")
1794 .append(mDevice).append('}').toString();
1795 }
Eric Laurentfde16d52012-12-03 14:42:39 -08001796 };
Eric Laurent3ef75492012-11-28 12:12:23 -08001797
Julia Reynolds48034f82016-03-09 10:15:16 -05001798 private int getNewRingerMode(int stream, int index, int flags) {
Zak Cohen47798292017-11-30 12:34:20 -08001799 // setRingerMode does nothing if the device is single volume,so the value would be unchanged
1800 if (mIsSingleVolume) {
1801 return getRingerModeExternal();
1802 }
1803
John Spurlockee5ad722015-03-03 16:17:21 -05001804 // setting volume on ui sounds stream type also controls silent mode
Eric Laurent3ef75492012-11-28 12:12:23 -08001805 if (((flags & AudioManager.FLAG_ALLOW_RINGER_MODES) != 0) ||
John Spurlock75ae23c2015-06-02 16:26:43 -04001806 (stream == getUiSoundsStreamType())) {
Eric Laurent3ef75492012-11-28 12:12:23 -08001807 int newRingerMode;
1808 if (index == 0) {
1809 newRingerMode = mHasVibrator ? AudioManager.RINGER_MODE_VIBRATE
John Spurlocka48d7792015-03-03 17:35:57 -05001810 : mVolumePolicy.volumeDownToEnterSilent ? AudioManager.RINGER_MODE_SILENT
Julia Reynolds48034f82016-03-09 10:15:16 -05001811 : AudioManager.RINGER_MODE_NORMAL;
Eric Laurent3ef75492012-11-28 12:12:23 -08001812 } else {
1813 newRingerMode = AudioManager.RINGER_MODE_NORMAL;
1814 }
Julia Reynolds48034f82016-03-09 10:15:16 -05001815 return newRingerMode;
1816 }
1817 return getRingerModeExternal();
1818 }
1819
1820 private boolean isAndroidNPlus(String caller) {
1821 try {
1822 final ApplicationInfo applicationInfo =
1823 mContext.getPackageManager().getApplicationInfoAsUser(
1824 caller, 0, UserHandle.getUserId(Binder.getCallingUid()));
1825 if (applicationInfo.targetSdkVersion >= Build.VERSION_CODES.N) {
1826 return true;
1827 }
1828 return false;
1829 } catch (PackageManager.NameNotFoundException e) {
1830 return true;
1831 }
1832 }
1833
1834 private boolean wouldToggleZenMode(int newMode) {
1835 if (getRingerModeExternal() == AudioManager.RINGER_MODE_SILENT
1836 && newMode != AudioManager.RINGER_MODE_SILENT) {
1837 return true;
1838 } else if (getRingerModeExternal() != AudioManager.RINGER_MODE_SILENT
1839 && newMode == AudioManager.RINGER_MODE_SILENT) {
1840 return true;
1841 }
1842 return false;
1843 }
1844
1845 private void onSetStreamVolume(int streamType, int index, int flags, int device,
1846 String caller) {
1847 final int stream = mStreamVolumeAlias[streamType];
1848 setStreamVolumeInt(stream, index, device, false, caller);
1849 // setting volume on ui sounds stream type also controls silent mode
1850 if (((flags & AudioManager.FLAG_ALLOW_RINGER_MODES) != 0) ||
1851 (stream == getUiSoundsStreamType())) {
1852 setRingerMode(getNewRingerMode(stream, index, flags),
1853 TAG + ".onSetStreamVolume", false /*external*/);
Eric Laurent3ef75492012-11-28 12:12:23 -08001854 }
John Spurlock75ae23c2015-06-02 16:26:43 -04001855 // setting non-zero volume for a muted stream unmutes the stream and vice versa
1856 mStreamStates[stream].mute(index == 0);
Eric Laurentfde16d52012-12-03 14:42:39 -08001857 }
1858
1859 /** @see AudioManager#setStreamVolume(int, int, int) */
Dianne Hackbornba50b97c2013-04-30 15:04:46 -07001860 public void setStreamVolume(int streamType, int index, int flags, String callingPackage) {
Phil Weaverf1a9aff2017-03-23 17:21:29 -07001861 if ((streamType == AudioManager.STREAM_ACCESSIBILITY) && !canChangeAccessibilityVolume()) {
Jean-Michel Triviab2d9312017-03-13 15:33:39 -07001862 Log.w(TAG, "Trying to call setStreamVolume() for a11y without"
Phil Weaverf1a9aff2017-03-23 17:21:29 -07001863 + " CHANGE_ACCESSIBILITY_VOLUME callingPackage=" + callingPackage);
Jean-Michel Triviab2d9312017-03-13 15:33:39 -07001864 return;
1865 }
Tomoharu Kasaharaa0d0c542019-01-18 20:04:38 +09001866 if ((streamType == AudioManager.STREAM_VOICE_CALL ||
1867 streamType == AudioManager.STREAM_BLUETOOTH_SCO) &&
Nadav Bar6b7751d2017-12-24 16:03:08 +02001868 (index == 0) &&
1869 (mContext.checkCallingOrSelfPermission(
1870 android.Manifest.permission.MODIFY_PHONE_STATE)
1871 != PackageManager.PERMISSION_GRANTED)) {
Tomoharu Kasaharaa0d0c542019-01-18 20:04:38 +09001872 Log.w(TAG, "Trying to call setStreamVolume() for STREAM_VOICE_CALL or"
1873 + " STREAM_BLUETOOTH_SCO and index 0 without"
Nadav Bar6b7751d2017-12-24 16:03:08 +02001874 + " MODIFY_PHONE_STATE callingPackage=" + callingPackage);
1875 return;
1876 }
Jean-Michel Trivi58850372018-09-14 16:01:28 -07001877 sVolumeLogger.log(new VolumeEvent(VolumeEvent.VOL_SET_STREAM_VOL, streamType,
Jean-Michel Trivicf170362017-08-24 17:24:57 -07001878 index/*val1*/, flags/*val2*/, callingPackage));
John Spurlock90874332015-03-10 16:00:54 -04001879 setStreamVolume(streamType, index, flags, callingPackage, callingPackage,
1880 Binder.getCallingUid());
RoboErik0dac35a2014-08-12 15:48:49 -07001881 }
1882
Phil Weaverf1a9aff2017-03-23 17:21:29 -07001883 private boolean canChangeAccessibilityVolume() {
1884 synchronized (mAccessibilityServiceUidsLock) {
1885 if (PackageManager.PERMISSION_GRANTED == mContext.checkCallingOrSelfPermission(
1886 android.Manifest.permission.CHANGE_ACCESSIBILITY_VOLUME)) {
1887 return true;
1888 }
1889 if (mAccessibilityServiceUids != null) {
1890 int callingUid = Binder.getCallingUid();
1891 for (int i = 0; i < mAccessibilityServiceUids.length; i++) {
1892 if (mAccessibilityServiceUids[i] == callingUid) {
1893 return true;
1894 }
1895 }
1896 }
1897 return false;
1898 }
1899 }
1900
RoboErik0dac35a2014-08-12 15:48:49 -07001901 private void setStreamVolume(int streamType, int index, int flags, String callingPackage,
John Spurlock90874332015-03-10 16:00:54 -04001902 String caller, int uid) {
Jean-Michel Triviac487672016-11-11 10:05:18 -08001903 if (DEBUG_VOL) {
1904 Log.d(TAG, "setStreamVolume(stream=" + streamType+", index=" + index
1905 + ", calling=" + callingPackage + ")");
1906 }
Eric Laurent83a017b2013-03-19 18:15:31 -07001907 if (mUseFixedVolume) {
1908 return;
1909 }
1910
Eric Laurentfde16d52012-12-03 14:42:39 -08001911 ensureValidStreamType(streamType);
Dianne Hackbornba50b97c2013-04-30 15:04:46 -07001912 int streamTypeAlias = mStreamVolumeAlias[streamType];
1913 VolumeStreamState streamState = mStreamStates[streamTypeAlias];
Eric Laurentfde16d52012-12-03 14:42:39 -08001914
1915 final int device = getDeviceForStream(streamType);
1916 int oldIndex;
1917
Matthew Xiec9d1d5f2013-09-12 00:32:22 -07001918 // skip a2dp absolute volume control request when the device
1919 // is not an a2dp device
1920 if ((device & AudioSystem.DEVICE_OUT_ALL_A2DP) == 0 &&
1921 (flags & AudioManager.FLAG_BLUETOOTH_ABS_VOLUME) != 0) {
1922 return;
1923 }
Kenny Guy70e0c582015-06-30 19:18:28 +01001924 // If we are being called by the system (e.g. hardware keys) check for current user
1925 // so we handle user restrictions correctly.
1926 if (uid == android.os.Process.SYSTEM_UID) {
1927 uid = UserHandle.getUid(getCurrentUserId(), UserHandle.getAppId(uid));
1928 }
John Spurlock59dc9c12015-03-02 11:20:15 -05001929 if (mAppOps.noteOp(STREAM_VOLUME_OPS[streamTypeAlias], uid, callingPackage)
RoboErik0dac35a2014-08-12 15:48:49 -07001930 != AppOpsManager.MODE_ALLOWED) {
Dianne Hackbornba50b97c2013-04-30 15:04:46 -07001931 return;
1932 }
1933
Julia Reynolds48034f82016-03-09 10:15:16 -05001934 if (isAndroidNPlus(callingPackage)
1935 && wouldToggleZenMode(getNewRingerMode(streamTypeAlias, index, flags))
1936 && !mNm.isNotificationPolicyAccessGrantedForPackage(callingPackage)) {
1937 throw new SecurityException("Not allowed to change Do Not Disturb state");
1938 }
1939
Julia Reynoldsed783792016-04-08 15:27:35 -04001940 if (!volumeAdjustmentAllowedByDnd(streamTypeAlias, flags)) {
1941 return;
1942 }
1943
hyomin.ohd0446dc2018-10-18 13:58:27 +09001944 synchronized (mSafeMediaVolumeStateLock) {
Eric Laurentfde16d52012-12-03 14:42:39 -08001945 // reset any pending volume command
1946 mPendingVolumeCommand = null;
1947
Eric Laurent42b041e2013-03-29 11:36:03 -07001948 oldIndex = streamState.getIndex(device);
Eric Laurentfde16d52012-12-03 14:42:39 -08001949
Dianne Hackbornba50b97c2013-04-30 15:04:46 -07001950 index = rescaleIndex(index * 10, streamType, streamTypeAlias);
Eric Laurentfde16d52012-12-03 14:42:39 -08001951
Jean-Michel Trivi58850372018-09-14 16:01:28 -07001952 if (streamTypeAlias == AudioSystem.STREAM_MUSIC
1953 && (device & AudioSystem.DEVICE_OUT_ALL_A2DP) != 0
1954 && (flags & AudioManager.FLAG_BLUETOOTH_ABS_VOLUME) == 0) {
1955 if (DEBUG_VOL) {
1956 Log.d(TAG, "setStreamVolume postSetAvrcpAbsoluteVolumeIndex index=" + index
1957 + "stream=" + streamType);
John Du5a0cf7a2013-07-19 11:30:34 -07001958 }
Jean-Michel Trivi58850372018-09-14 16:01:28 -07001959 mDeviceBroker.postSetAvrcpAbsoluteVolumeIndex(index / 10);
John Du5a0cf7a2013-07-19 11:30:34 -07001960 }
1961
Jakub Pawlowskif9570f32018-02-21 17:15:12 -08001962 if ((device & AudioSystem.DEVICE_OUT_HEARING_AID) != 0) {
Jean-Michel Trivi58850372018-09-14 16:01:28 -07001963 Log.i(TAG, "setStreamVolume postSetHearingAidVolumeIndex index=" + index
1964 + " stream=" + streamType);
1965 mDeviceBroker.postSetHearingAidVolumeIndex(index, streamType);
Jakub Pawlowskif9570f32018-02-21 17:15:12 -08001966 }
1967
Jinsuk Kim336cdb42014-11-29 06:27:00 +09001968 if (streamTypeAlias == AudioSystem.STREAM_MUSIC) {
1969 setSystemAudioVolume(oldIndex, index, getStreamMaxVolume(streamType), flags);
Jungshik Jang41d97462014-06-30 22:26:29 +09001970 }
1971
Eric Laurentfde16d52012-12-03 14:42:39 -08001972 flags &= ~AudioManager.FLAG_FIXED_VOLUME;
Dianne Hackbornba50b97c2013-04-30 15:04:46 -07001973 if ((streamTypeAlias == AudioSystem.STREAM_MUSIC) &&
Eric Laurentfde16d52012-12-03 14:42:39 -08001974 ((device & mFixedVolumeDevices) != 0)) {
1975 flags |= AudioManager.FLAG_FIXED_VOLUME;
1976
1977 // volume is either 0 or max allowed for fixed volume devices
1978 if (index != 0) {
1979 if (mSafeMediaVolumeState == SAFE_MEDIA_VOLUME_ACTIVE &&
1980 (device & mSafeMediaVolumeDevices) != 0) {
Eric Laurenteab40d12017-06-09 12:45:21 -07001981 index = safeMediaVolumeIndex(device);
Eric Laurentfde16d52012-12-03 14:42:39 -08001982 } else {
1983 index = streamState.getMaxIndex();
1984 }
1985 }
1986 }
1987
Dianne Hackbornba50b97c2013-04-30 15:04:46 -07001988 if (!checkSafeMediaVolume(streamTypeAlias, index, device)) {
John Spurlock3346a802014-05-20 16:25:37 -04001989 mVolumeController.postDisplaySafeVolumeWarning(flags);
Eric Laurentfde16d52012-12-03 14:42:39 -08001990 mPendingVolumeCommand = new StreamVolumeCommand(
1991 streamType, index, flags, device);
1992 } else {
John Spurlock90874332015-03-10 16:00:54 -04001993 onSetStreamVolume(streamType, index, flags, device, caller);
Eric Laurent42b041e2013-03-29 11:36:03 -07001994 index = mStreamStates[streamType].getIndex(device);
Eric Laurentfde16d52012-12-03 14:42:39 -08001995 }
1996 }
Shubangc480a712018-06-11 18:02:42 -07001997 synchronized (mHdmiClientLock) {
1998 if (mHdmiManager != null &&
1999 mHdmiAudioSystemClient != null &&
Shubangde728822018-07-16 16:46:51 -07002000 mHdmiSystemAudioSupported &&
Shubangc480a712018-06-11 18:02:42 -07002001 streamTypeAlias == AudioSystem.STREAM_MUSIC &&
2002 (oldIndex != index)) {
Shubangde728822018-07-16 16:46:51 -07002003 final long identity = Binder.clearCallingIdentity();
Shubangc480a712018-06-11 18:02:42 -07002004 mHdmiAudioSystemClient.sendReportAudioStatusCecCommand(
2005 false, getStreamVolume(AudioSystem.STREAM_MUSIC),
2006 getStreamMaxVolume(AudioSystem.STREAM_MUSIC),
2007 isStreamMute(AudioSystem.STREAM_MUSIC));
Shubangde728822018-07-16 16:46:51 -07002008 Binder.restoreCallingIdentity(identity);
Shubangc480a712018-06-11 18:02:42 -07002009 }
2010 }
Eric Laurent25101b02011-02-02 09:33:30 -08002011 sendVolumeUpdate(streamType, oldIndex, index, flags);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002012 }
2013
Beverlyd6964762018-02-16 14:07:03 -05002014 // No ringer or zen muted stream volumes can be changed unless it'll exit dnd
Julia Reynoldsed783792016-04-08 15:27:35 -04002015 private boolean volumeAdjustmentAllowedByDnd(int streamTypeAlias, int flags) {
Beverlyd6964762018-02-16 14:07:03 -05002016 switch (mNm.getZenMode()) {
2017 case Settings.Global.ZEN_MODE_OFF:
2018 return true;
2019 case Settings.Global.ZEN_MODE_NO_INTERRUPTIONS:
2020 case Settings.Global.ZEN_MODE_ALARMS:
2021 case Settings.Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS:
2022 return !isStreamMutedByRingerOrZenMode(streamTypeAlias)
2023 || streamTypeAlias == getUiSoundsStreamType()
2024 || (flags & AudioManager.FLAG_ALLOW_RINGER_MODES) != 0;
Julia Reynoldsed783792016-04-08 15:27:35 -04002025 }
Beverlyd6964762018-02-16 14:07:03 -05002026
Julia Reynoldsed783792016-04-08 15:27:35 -04002027 return true;
2028 }
2029
Eric Laurent45c90ce2012-04-24 18:44:22 -07002030 /** @see AudioManager#forceVolumeControlStream(int) */
2031 public void forceVolumeControlStream(int streamType, IBinder cb) {
Jean-Michel Trivi60eddfd2018-03-09 15:31:12 -08002032 if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.MODIFY_PHONE_STATE)
2033 != PackageManager.PERMISSION_GRANTED) {
2034 return;
2035 }
Jean-Michel Trivia7880d42017-04-15 12:41:05 -07002036 if (DEBUG_VOL) { Log.d(TAG, String.format("forceVolumeControlStream(%d)", streamType)); }
Eric Laurent45c90ce2012-04-24 18:44:22 -07002037 synchronized(mForceControlStreamLock) {
Jean-Michel Trivia7880d42017-04-15 12:41:05 -07002038 if (mVolumeControlStream != -1 && streamType != -1) {
2039 mUserSelectedVolumeControlStream = true;
2040 }
Eric Laurent45c90ce2012-04-24 18:44:22 -07002041 mVolumeControlStream = streamType;
2042 if (mVolumeControlStream == -1) {
2043 if (mForceControlStreamClient != null) {
2044 mForceControlStreamClient.release();
2045 mForceControlStreamClient = null;
2046 }
Jean-Michel Trivia7880d42017-04-15 12:41:05 -07002047 mUserSelectedVolumeControlStream = false;
Eric Laurent45c90ce2012-04-24 18:44:22 -07002048 } else {
jianzhou21fb09f2018-02-28 14:03:15 +08002049 if (null == mForceControlStreamClient) {
2050 mForceControlStreamClient = new ForceControlStreamClient(cb);
2051 } else {
2052 if (mForceControlStreamClient.getBinder() == cb) {
2053 Log.d(TAG, "forceVolumeControlStream cb:" + cb + " is already linked.");
2054 } else {
2055 mForceControlStreamClient.release();
2056 mForceControlStreamClient = new ForceControlStreamClient(cb);
2057 }
2058 }
Eric Laurent45c90ce2012-04-24 18:44:22 -07002059 }
2060 }
2061 }
2062
2063 private class ForceControlStreamClient implements IBinder.DeathRecipient {
2064 private IBinder mCb; // To be notified of client's death
2065
2066 ForceControlStreamClient(IBinder cb) {
2067 if (cb != null) {
2068 try {
2069 cb.linkToDeath(this, 0);
2070 } catch (RemoteException e) {
2071 // Client has died!
2072 Log.w(TAG, "ForceControlStreamClient() could not link to "+cb+" binder death");
2073 cb = null;
2074 }
2075 }
2076 mCb = cb;
2077 }
2078
2079 public void binderDied() {
2080 synchronized(mForceControlStreamLock) {
2081 Log.w(TAG, "SCO client died");
2082 if (mForceControlStreamClient != this) {
2083 Log.w(TAG, "unregistered control stream client died");
2084 } else {
2085 mForceControlStreamClient = null;
2086 mVolumeControlStream = -1;
Jean-Michel Trivia7880d42017-04-15 12:41:05 -07002087 mUserSelectedVolumeControlStream = false;
Eric Laurent45c90ce2012-04-24 18:44:22 -07002088 }
2089 }
2090 }
2091
2092 public void release() {
2093 if (mCb != null) {
2094 mCb.unlinkToDeath(this, 0);
2095 mCb = null;
2096 }
2097 }
jianzhou21fb09f2018-02-28 14:03:15 +08002098
2099 public IBinder getBinder() {
2100 return mCb;
2101 }
Eric Laurent45c90ce2012-04-24 18:44:22 -07002102 }
2103
Dianne Hackborn5ac72a22012-08-29 18:32:08 -07002104 private void sendBroadcastToAll(Intent intent) {
Christopher Tate267603f2015-01-20 14:21:21 -08002105 intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);
John Spurlock86490862015-02-25 11:22:52 -05002106 intent.addFlags(Intent.FLAG_RECEIVER_FOREGROUND);
Dianne Hackborn5ac72a22012-08-29 18:32:08 -07002107 final long ident = Binder.clearCallingIdentity();
2108 try {
2109 mContext.sendBroadcastAsUser(intent, UserHandle.ALL);
2110 } finally {
2111 Binder.restoreCallingIdentity(ident);
2112 }
2113 }
2114
2115 private void sendStickyBroadcastToAll(Intent intent) {
John Spurlock86490862015-02-25 11:22:52 -05002116 intent.addFlags(Intent.FLAG_RECEIVER_FOREGROUND);
Dianne Hackborn5ac72a22012-08-29 18:32:08 -07002117 final long ident = Binder.clearCallingIdentity();
2118 try {
2119 mContext.sendStickyBroadcastAsUser(intent, UserHandle.ALL);
2120 } finally {
2121 Binder.restoreCallingIdentity(ident);
2122 }
2123 }
2124
Kenny Guy70e0c582015-06-30 19:18:28 +01002125 private int getCurrentUserId() {
2126 final long ident = Binder.clearCallingIdentity();
2127 try {
Sudheer Shankadc589ac2016-11-10 15:30:17 -08002128 UserInfo currentUser = ActivityManager.getService().getCurrentUser();
Kenny Guy70e0c582015-06-30 19:18:28 +01002129 return currentUser.id;
2130 } catch (RemoteException e) {
2131 // Activity manager not running, nothing we can do assume user 0.
2132 } finally {
2133 Binder.restoreCallingIdentity(ident);
2134 }
Xiaohui Chen7c696362015-09-16 09:56:14 -07002135 return UserHandle.USER_SYSTEM;
Kenny Guy70e0c582015-06-30 19:18:28 +01002136 }
2137
Eric Laurent25101b02011-02-02 09:33:30 -08002138 // UI update and Broadcast Intent
Yue Li949865b2017-05-24 17:25:28 -07002139 protected void sendVolumeUpdate(int streamType, int oldIndex, int index, int flags) {
John Spurlock72966d62015-06-18 15:45:07 -04002140 streamType = mStreamVolumeAlias[streamType];
Eric Laurent25101b02011-02-02 09:33:30 -08002141
Jinsuk Kim336cdb42014-11-29 06:27:00 +09002142 if (streamType == AudioSystem.STREAM_MUSIC) {
2143 flags = updateFlagsForSystemAudio(flags);
Jungshik Jang1a6be6e2014-09-16 11:04:54 +09002144 }
John Spurlock3346a802014-05-20 16:25:37 -04002145 mVolumeController.postVolumeChanged(streamType, flags);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002146 }
2147
Jinsuk Kim336cdb42014-11-29 06:27:00 +09002148 // If Hdmi-CEC system audio mode is on, we show volume bar only when TV
2149 // receives volume notification from Audio Receiver.
2150 private int updateFlagsForSystemAudio(int flags) {
Shubangc480a712018-06-11 18:02:42 -07002151 synchronized (mHdmiClientLock) {
2152 if (mHdmiTvClient != null) {
Jinsuk Kim336cdb42014-11-29 06:27:00 +09002153 if (mHdmiSystemAudioSupported &&
2154 ((flags & AudioManager.FLAG_HDMI_SYSTEM_AUDIO_VOLUME) == 0)) {
2155 flags &= ~AudioManager.FLAG_SHOW_UI;
2156 }
2157 }
2158 }
2159 return flags;
2160 }
2161
Mike Lockwood0dc37cc2011-12-01 16:14:19 -05002162 // UI update and Broadcast Intent
Mike Lockwood0dc37cc2011-12-01 16:14:19 -05002163 private void sendMasterMuteUpdate(boolean muted, int flags) {
Jinsuk Kim336cdb42014-11-29 06:27:00 +09002164 mVolumeController.postMasterMuteChanged(updateFlagsForSystemAudio(flags));
Justin Koh57978ed2012-04-03 17:37:58 -07002165 broadcastMasterMuteStatus(muted);
2166 }
Mike Lockwood0dc37cc2011-12-01 16:14:19 -05002167
Justin Koh57978ed2012-04-03 17:37:58 -07002168 private void broadcastMasterMuteStatus(boolean muted) {
Mike Lockwood0dc37cc2011-12-01 16:14:19 -05002169 Intent intent = new Intent(AudioManager.MASTER_MUTE_CHANGED_ACTION);
2170 intent.putExtra(AudioManager.EXTRA_MASTER_VOLUME_MUTED, muted);
Justin Koh57978ed2012-04-03 17:37:58 -07002171 intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT
2172 | Intent.FLAG_RECEIVER_REPLACE_PENDING);
Dianne Hackborn5ac72a22012-08-29 18:32:08 -07002173 sendStickyBroadcastToAll(intent);
Mike Lockwood0dc37cc2011-12-01 16:14:19 -05002174 }
2175
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002176 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002177 * Sets the stream state's index, and posts a message to set system volume.
2178 * This will not call out to the UI. Assumes a valid stream type.
2179 *
2180 * @param streamType Type of the stream
2181 * @param index Desired volume index of the stream
Eric Laurent9bc8358d2011-11-18 16:43:31 -08002182 * @param device the device whose volume must be changed
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002183 * @param force If true, set the volume even if the desired volume is same
2184 * as the current volume.
2185 */
Eric Laurent9bc8358d2011-11-18 16:43:31 -08002186 private void setStreamVolumeInt(int streamType,
2187 int index,
2188 int device,
John Spurlock90874332015-03-10 16:00:54 -04002189 boolean force,
2190 String caller) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002191 VolumeStreamState streamState = mStreamStates[streamType];
Eric Laurent5b4e6542010-03-19 20:02:21 -07002192
John Spurlock90874332015-03-10 16:00:54 -04002193 if (streamState.setIndex(index, device, caller) || force) {
Eric Laurent42b041e2013-03-29 11:36:03 -07002194 // Post message to set system volume (it in turn will post a message
2195 // to persist).
2196 sendMsg(mAudioHandler,
2197 MSG_SET_DEVICE_VOLUME,
2198 SENDMSG_QUEUE,
2199 device,
2200 0,
2201 streamState,
2202 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002203 }
2204 }
2205
Jinsuk Kim336cdb42014-11-29 06:27:00 +09002206 private void setSystemAudioMute(boolean state) {
Shubangc480a712018-06-11 18:02:42 -07002207 synchronized (mHdmiClientLock) {
2208 if (mHdmiManager == null || mHdmiTvClient == null || !mHdmiSystemAudioSupported) return;
2209 final long token = Binder.clearCallingIdentity();
2210 try {
2211 mHdmiTvClient.setSystemAudioMute(state);
2212 } finally {
2213 Binder.restoreCallingIdentity(token);
Jinsuk Kim336cdb42014-11-29 06:27:00 +09002214 }
2215 }
2216 }
2217
Eric Laurent25101b02011-02-02 09:33:30 -08002218 /** get stream mute state. */
2219 public boolean isStreamMute(int streamType) {
RoboErik7c82ced2014-12-04 17:39:08 -08002220 if (streamType == AudioManager.USE_DEFAULT_STREAM_TYPE) {
2221 streamType = getActiveStreamType(streamType);
2222 }
Eric Laurent8fa4d6f2014-10-30 14:13:03 -07002223 synchronized (VolumeStreamState.class) {
jiabin93d32ef2017-07-11 13:50:02 -07002224 ensureValidStreamType(streamType);
RoboErik4197cb62015-01-21 15:45:32 -08002225 return mStreamStates[streamType].mIsMuted;
Eric Laurent8fa4d6f2014-10-30 14:13:03 -07002226 }
Eric Laurent25101b02011-02-02 09:33:30 -08002227 }
2228
Jean-Michel Triviba5270b2014-10-01 17:49:29 -07002229 private class RmtSbmxFullVolDeathHandler implements IBinder.DeathRecipient {
2230 private IBinder mICallback; // To be notified of client's death
2231
2232 RmtSbmxFullVolDeathHandler(IBinder cb) {
2233 mICallback = cb;
2234 try {
2235 cb.linkToDeath(this, 0/*flags*/);
2236 } catch (RemoteException e) {
2237 Log.e(TAG, "can't link to death", e);
2238 }
2239 }
2240
2241 boolean isHandlerFor(IBinder cb) {
2242 return mICallback.equals(cb);
2243 }
2244
2245 void forget() {
2246 try {
2247 mICallback.unlinkToDeath(this, 0/*flags*/);
2248 } catch (NoSuchElementException e) {
2249 Log.e(TAG, "error unlinking to death", e);
2250 }
2251 }
2252
2253 public void binderDied() {
2254 Log.w(TAG, "Recorder with remote submix at full volume died " + mICallback);
2255 forceRemoteSubmixFullVolume(false, mICallback);
2256 }
2257 }
2258
2259 /**
2260 * call must be synchronized on mRmtSbmxFullVolDeathHandlers
2261 * @return true if there is a registered death handler, false otherwise */
2262 private boolean discardRmtSbmxFullVolDeathHandlerFor(IBinder cb) {
2263 Iterator<RmtSbmxFullVolDeathHandler> it = mRmtSbmxFullVolDeathHandlers.iterator();
2264 while (it.hasNext()) {
2265 final RmtSbmxFullVolDeathHandler handler = it.next();
2266 if (handler.isHandlerFor(cb)) {
2267 handler.forget();
2268 mRmtSbmxFullVolDeathHandlers.remove(handler);
2269 return true;
2270 }
2271 }
2272 return false;
2273 }
2274
2275 /** call synchronized on mRmtSbmxFullVolDeathHandlers */
2276 private boolean hasRmtSbmxFullVolDeathHandlerFor(IBinder cb) {
2277 Iterator<RmtSbmxFullVolDeathHandler> it = mRmtSbmxFullVolDeathHandlers.iterator();
2278 while (it.hasNext()) {
2279 if (it.next().isHandlerFor(cb)) {
2280 return true;
2281 }
2282 }
2283 return false;
2284 }
2285
2286 private int mRmtSbmxFullVolRefCount = 0;
2287 private ArrayList<RmtSbmxFullVolDeathHandler> mRmtSbmxFullVolDeathHandlers =
2288 new ArrayList<RmtSbmxFullVolDeathHandler>();
2289
2290 public void forceRemoteSubmixFullVolume(boolean startForcing, IBinder cb) {
2291 if (cb == null) {
2292 return;
2293 }
2294 if ((PackageManager.PERMISSION_GRANTED != mContext.checkCallingOrSelfPermission(
2295 android.Manifest.permission.CAPTURE_AUDIO_OUTPUT))) {
2296 Log.w(TAG, "Trying to call forceRemoteSubmixFullVolume() without CAPTURE_AUDIO_OUTPUT");
2297 return;
2298 }
2299 synchronized(mRmtSbmxFullVolDeathHandlers) {
2300 boolean applyRequired = false;
2301 if (startForcing) {
2302 if (!hasRmtSbmxFullVolDeathHandlerFor(cb)) {
2303 mRmtSbmxFullVolDeathHandlers.add(new RmtSbmxFullVolDeathHandler(cb));
2304 if (mRmtSbmxFullVolRefCount == 0) {
2305 mFullVolumeDevices |= AudioSystem.DEVICE_OUT_REMOTE_SUBMIX;
2306 mFixedVolumeDevices |= AudioSystem.DEVICE_OUT_REMOTE_SUBMIX;
2307 applyRequired = true;
2308 }
2309 mRmtSbmxFullVolRefCount++;
2310 }
2311 } else {
2312 if (discardRmtSbmxFullVolDeathHandlerFor(cb) && (mRmtSbmxFullVolRefCount > 0)) {
2313 mRmtSbmxFullVolRefCount--;
2314 if (mRmtSbmxFullVolRefCount == 0) {
2315 mFullVolumeDevices &= ~AudioSystem.DEVICE_OUT_REMOTE_SUBMIX;
2316 mFixedVolumeDevices &= ~AudioSystem.DEVICE_OUT_REMOTE_SUBMIX;
2317 applyRequired = true;
2318 }
2319 }
2320 }
2321 if (applyRequired) {
2322 // Assumes only STREAM_MUSIC going through DEVICE_OUT_REMOTE_SUBMIX
2323 checkAllFixedVolumeDevices(AudioSystem.STREAM_MUSIC);
2324 mStreamStates[AudioSystem.STREAM_MUSIC].applyAllVolumes();
2325 }
2326 }
2327 }
2328
Kenny Guy70e0c582015-06-30 19:18:28 +01002329 private void setMasterMuteInternal(boolean mute, int flags, String callingPackage, int uid,
2330 int userId) {
2331 // If we are being called by the system check for user we are going to change
2332 // so we handle user restrictions correctly.
2333 if (uid == android.os.Process.SYSTEM_UID) {
2334 uid = UserHandle.getUid(userId, UserHandle.getAppId(uid));
2335 }
Makoto Onuki4f160732015-10-27 17:15:38 -07002336 // If OP_AUDIO_MASTER_VOLUME is set, disallow unmuting.
2337 if (!mute && mAppOps.noteOp(AppOpsManager.OP_AUDIO_MASTER_VOLUME, uid, callingPackage)
RoboErik7c82ced2014-12-04 17:39:08 -08002338 != AppOpsManager.MODE_ALLOWED) {
Julia Reynolds4a21b252014-06-04 11:11:43 -04002339 return;
2340 }
Kenny Guy70e0c582015-06-30 19:18:28 +01002341 if (userId != UserHandle.getCallingUserId() &&
2342 mContext.checkCallingOrSelfPermission(
2343 android.Manifest.permission.INTERACT_ACROSS_USERS_FULL)
2344 != PackageManager.PERMISSION_GRANTED) {
2345 return;
2346 }
Makoto Onukid45a4a22015-11-02 17:17:38 -08002347 setMasterMuteInternalNoCallerCheck(mute, flags, userId);
2348 }
2349
2350 private void setMasterMuteInternalNoCallerCheck(boolean mute, int flags, int userId) {
2351 if (DEBUG_VOL) {
2352 Log.d(TAG, String.format("Master mute %s, %d, user=%d", mute, flags, userId));
2353 }
Hongwei Wangdaba1242018-05-29 14:36:16 -07002354 if (!isPlatformAutomotive() && mUseFixedVolume) {
2355 // If using fixed volume, we don't mute.
2356 // TODO: remove the isPlatformAutomotive check here.
2357 // The isPlatformAutomotive check is added for safety but may not be necessary.
2358 return;
Makoto Onukid45a4a22015-11-02 17:17:38 -08002359 }
Kenny Guy70e0c582015-06-30 19:18:28 +01002360 if (getCurrentUserId() == userId) {
2361 if (mute != AudioSystem.getMasterMute()) {
2362 setSystemAudioMute(mute);
2363 AudioSystem.setMasterMute(mute);
Kenny Guy70e0c582015-06-30 19:18:28 +01002364 sendMasterMuteUpdate(mute, flags);
RoboErik7c82ced2014-12-04 17:39:08 -08002365
Kenny Guy70e0c582015-06-30 19:18:28 +01002366 Intent intent = new Intent(AudioManager.MASTER_MUTE_CHANGED_ACTION);
2367 intent.putExtra(AudioManager.EXTRA_MASTER_VOLUME_MUTED, mute);
2368 sendBroadcastToAll(intent);
2369 }
Jason Simmons1ce5b262012-02-02 13:00:17 -08002370 }
Mike Lockwoodce952c82011-11-14 10:47:42 -08002371 }
2372
2373 /** get master mute state. */
2374 public boolean isMasterMute() {
Mike Lockwood3194ea92011-12-07 11:47:31 -08002375 return AudioSystem.getMasterMute();
Mike Lockwoodce952c82011-11-14 10:47:42 -08002376 }
2377
Kenny Guy70e0c582015-06-30 19:18:28 +01002378 public void setMasterMute(boolean mute, int flags, String callingPackage, int userId) {
2379 setMasterMuteInternal(mute, flags, callingPackage, Binder.getCallingUid(),
2380 userId);
John Spurlockee5ad722015-03-03 16:17:21 -05002381 }
2382
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002383 /** @see AudioManager#getStreamVolume(int) */
2384 public int getStreamVolume(int streamType) {
2385 ensureValidStreamType(streamType);
Eric Laurent9bc8358d2011-11-18 16:43:31 -08002386 int device = getDeviceForStream(streamType);
Eric Laurent8fa4d6f2014-10-30 14:13:03 -07002387 synchronized (VolumeStreamState.class) {
2388 int index = mStreamStates[streamType].getIndex(device);
Eric Laurent4bbcc652012-09-24 14:26:30 -07002389
Eric Laurent8fa4d6f2014-10-30 14:13:03 -07002390 // by convention getStreamVolume() returns 0 when a stream is muted.
RoboErik4197cb62015-01-21 15:45:32 -08002391 if (mStreamStates[streamType].mIsMuted) {
Eric Laurent8fa4d6f2014-10-30 14:13:03 -07002392 index = 0;
2393 }
2394 if (index != 0 && (mStreamVolumeAlias[streamType] == AudioSystem.STREAM_MUSIC) &&
2395 (device & mFixedVolumeDevices) != 0) {
2396 index = mStreamStates[streamType].getMaxIndex();
2397 }
2398 return (index + 5) / 10;
Eric Laurent42b041e2013-03-29 11:36:03 -07002399 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002400 }
2401
2402 /** @see AudioManager#getStreamMaxVolume(int) */
2403 public int getStreamMaxVolume(int streamType) {
2404 ensureValidStreamType(streamType);
Eric Laurenta553c252009-07-17 12:17:14 -07002405 return (mStreamStates[streamType].getMaxIndex() + 5) / 10;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002406 }
2407
Jean-Michel Trivi8e7aca32017-11-28 18:12:38 -08002408 /** @see AudioManager#getStreamMinVolumeInt(int) */
John Spurlockb6e19e32015-03-10 21:33:44 -04002409 public int getStreamMinVolume(int streamType) {
2410 ensureValidStreamType(streamType);
2411 return (mStreamStates[streamType].getMinIndex() + 5) / 10;
2412 }
2413
Eric Laurent25101b02011-02-02 09:33:30 -08002414 /** Get last audible volume before stream was muted. */
2415 public int getLastAudibleStreamVolume(int streamType) {
2416 ensureValidStreamType(streamType);
Eric Laurent9bc8358d2011-11-18 16:43:31 -08002417 int device = getDeviceForStream(streamType);
Eric Laurent42b041e2013-03-29 11:36:03 -07002418 return (mStreamStates[streamType].getIndex(device) + 5) / 10;
Eric Laurent25101b02011-02-02 09:33:30 -08002419 }
2420
John Spurlockee5ad722015-03-03 16:17:21 -05002421 /** @see AudioManager#getUiSoundsStreamType() */
2422 public int getUiSoundsStreamType() {
John Spurlock4f0f1202014-08-05 13:28:33 -04002423 return mStreamVolumeAlias[AudioSystem.STREAM_SYSTEM];
Eric Laurent6d517662012-04-23 18:42:39 -07002424 }
2425
Makoto Onukid45a4a22015-11-02 17:17:38 -08002426 /** @see AudioManager#setMicrophoneMute(boolean) */
2427 @Override
Kenny Guy70e0c582015-06-30 19:18:28 +01002428 public void setMicrophoneMute(boolean on, String callingPackage, int userId) {
2429 // If we are being called by the system check for user we are going to change
2430 // so we handle user restrictions correctly.
2431 int uid = Binder.getCallingUid();
2432 if (uid == android.os.Process.SYSTEM_UID) {
2433 uid = UserHandle.getUid(userId, UserHandle.getAppId(uid));
2434 }
Makoto Onuki4f160732015-10-27 17:15:38 -07002435 // If OP_MUTE_MICROPHONE is set, disallow unmuting.
2436 if (!on && mAppOps.noteOp(AppOpsManager.OP_MUTE_MICROPHONE, uid, callingPackage)
Kenny Guy70e0c582015-06-30 19:18:28 +01002437 != AppOpsManager.MODE_ALLOWED) {
Emily Bernier22c921a2014-05-28 11:01:32 -04002438 return;
2439 }
Jean-Michel Trivi4a4fea02014-08-29 18:14:09 -07002440 if (!checkAudioSettingsPermission("setMicrophoneMute()")) {
2441 return;
2442 }
Kenny Guy70e0c582015-06-30 19:18:28 +01002443 if (userId != UserHandle.getCallingUserId() &&
2444 mContext.checkCallingOrSelfPermission(
2445 android.Manifest.permission.INTERACT_ACROSS_USERS_FULL)
2446 != PackageManager.PERMISSION_GRANTED) {
2447 return;
2448 }
Makoto Onukid45a4a22015-11-02 17:17:38 -08002449 setMicrophoneMuteNoCallerCheck(on, userId);
2450 }
Emily Bernier22c921a2014-05-28 11:01:32 -04002451
Makoto Onukid45a4a22015-11-02 17:17:38 -08002452 private void setMicrophoneMuteNoCallerCheck(boolean on, int userId) {
2453 if (DEBUG_VOL) {
2454 Log.d(TAG, String.format("Mic mute %s, user=%d", on, userId));
2455 }
Jean-Michel Trivi7be17d22017-12-21 18:09:21 -08002456 // only mute for the current user
Kenny Guy70e0c582015-06-30 19:18:28 +01002457 if (getCurrentUserId() == userId) {
Jean-Michel Trivi7be17d22017-12-21 18:09:21 -08002458 final boolean currentMute = AudioSystem.isMicrophoneMuted();
Eric Laurent66b69672018-01-26 18:30:51 -08002459 final long identity = Binder.clearCallingIdentity();
Kenny Guy70e0c582015-06-30 19:18:28 +01002460 AudioSystem.muteMicrophone(on);
Eric Laurent66b69672018-01-26 18:30:51 -08002461 Binder.restoreCallingIdentity(identity);
Jean-Michel Trivi7be17d22017-12-21 18:09:21 -08002462 if (on != currentMute) {
2463 mContext.sendBroadcast(new Intent(AudioManager.ACTION_MICROPHONE_MUTE_CHANGED)
2464 .setFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY));
2465 }
Kenny Guy70e0c582015-06-30 19:18:28 +01002466 }
Emily Bernier22c921a2014-05-28 11:01:32 -04002467 }
2468
John Spurlock661f2cf2014-11-17 10:29:10 -05002469 @Override
2470 public int getRingerModeExternal() {
2471 synchronized(mSettingsLock) {
2472 return mRingerModeExternal;
2473 }
2474 }
2475
2476 @Override
2477 public int getRingerModeInternal() {
Glenn Kastenba195eb2011-12-13 09:30:40 -08002478 synchronized(mSettingsLock) {
2479 return mRingerMode;
2480 }
2481 }
2482
2483 private void ensureValidRingerMode(int ringerMode) {
John Spurlock97559372014-10-24 16:27:36 -04002484 if (!isValidRingerMode(ringerMode)) {
Glenn Kastenba195eb2011-12-13 09:30:40 -08002485 throw new IllegalArgumentException("Bad ringer mode " + ringerMode);
2486 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002487 }
2488
John Spurlock97559372014-10-24 16:27:36 -04002489 /** @see AudioManager#isValidRingerMode(int) */
2490 public boolean isValidRingerMode(int ringerMode) {
2491 return ringerMode >= 0 && ringerMode <= AudioManager.RINGER_MODE_MAX;
2492 }
2493
John Spurlock661f2cf2014-11-17 10:29:10 -05002494 public void setRingerModeExternal(int ringerMode, String caller) {
Julia Reynolds48034f82016-03-09 10:15:16 -05002495 if (isAndroidNPlus(caller) && wouldToggleZenMode(ringerMode)
2496 && !mNm.isNotificationPolicyAccessGrantedForPackage(caller)) {
2497 throw new SecurityException("Not allowed to change Do Not Disturb state");
2498 }
2499
John Spurlockaf88a192014-12-23 16:14:44 -05002500 setRingerMode(ringerMode, caller, true /*external*/);
John Spurlock661f2cf2014-11-17 10:29:10 -05002501 }
2502
2503 public void setRingerModeInternal(int ringerMode, String caller) {
John Spurlockcdb57ae2015-02-11 19:04:11 -05002504 enforceVolumeController("setRingerModeInternal");
John Spurlockaf88a192014-12-23 16:14:44 -05002505 setRingerMode(ringerMode, caller, false /*external*/);
John Spurlock661f2cf2014-11-17 10:29:10 -05002506 }
2507
Mike Digman55272862018-02-20 14:35:17 -08002508 public void silenceRingerModeInternal(String reason) {
2509 VibrationEffect effect = null;
2510 int ringerMode = AudioManager.RINGER_MODE_SILENT;
2511 int toastText = 0;
2512
2513 int silenceRingerSetting = Settings.Secure.VOLUME_HUSH_OFF;
2514 if (mContext.getResources()
2515 .getBoolean(com.android.internal.R.bool.config_volumeHushGestureEnabled)) {
2516 silenceRingerSetting = Settings.Secure.getIntForUser(mContentResolver,
2517 Settings.Secure.VOLUME_HUSH_GESTURE, VOLUME_HUSH_OFF,
2518 UserHandle.USER_CURRENT);
2519 }
2520
2521 switch(silenceRingerSetting) {
2522 case VOLUME_HUSH_MUTE:
2523 effect = VibrationEffect.get(VibrationEffect.EFFECT_DOUBLE_CLICK);
2524 ringerMode = AudioManager.RINGER_MODE_SILENT;
2525 toastText = com.android.internal.R.string.volume_dialog_ringer_guidance_silent;
2526 break;
2527 case VOLUME_HUSH_VIBRATE:
2528 effect = VibrationEffect.get(VibrationEffect.EFFECT_HEAVY_CLICK);
2529 ringerMode = AudioManager.RINGER_MODE_VIBRATE;
2530 toastText = com.android.internal.R.string.volume_dialog_ringer_guidance_vibrate;
2531 break;
2532 }
Alexey Kuzmine1f06b82018-06-20 17:48:43 +01002533 maybeVibrate(effect, reason);
Mike Digman55272862018-02-20 14:35:17 -08002534 setRingerModeInternal(ringerMode, reason);
2535 Toast.makeText(mContext, toastText, Toast.LENGTH_SHORT).show();
2536 }
2537
Alexey Kuzmine1f06b82018-06-20 17:48:43 +01002538 private boolean maybeVibrate(VibrationEffect effect, String reason) {
Mike Digman55272862018-02-20 14:35:17 -08002539 if (!mHasVibrator) {
2540 return false;
2541 }
2542 final boolean hapticsDisabled = Settings.System.getIntForUser(mContext.getContentResolver(),
2543 Settings.System.HAPTIC_FEEDBACK_ENABLED, 0, UserHandle.USER_CURRENT) == 0;
2544 if (hapticsDisabled) {
2545 return false;
2546 }
2547
2548 if (effect == null) {
2549 return false;
2550 }
Alexey Kuzmine1f06b82018-06-20 17:48:43 +01002551 mVibrator.vibrate(Binder.getCallingUid(), mContext.getOpPackageName(), effect,
2552 reason, VIBRATION_ATTRIBUTES);
Mike Digman55272862018-02-20 14:35:17 -08002553 return true;
2554 }
2555
John Spurlock661f2cf2014-11-17 10:29:10 -05002556 private void setRingerMode(int ringerMode, String caller, boolean external) {
Muyuan Li1ed6df62016-06-18 11:16:52 -07002557 if (mUseFixedVolume || mIsSingleVolume) {
Eric Laurent83a017b2013-03-19 18:15:31 -07002558 return;
2559 }
John Spurlock661f2cf2014-11-17 10:29:10 -05002560 if (caller == null || caller.length() == 0) {
2561 throw new IllegalArgumentException("Bad caller: " + caller);
2562 }
John Spurlock97559372014-10-24 16:27:36 -04002563 ensureValidRingerMode(ringerMode);
Eric Laurent24482012012-05-10 09:41:17 -07002564 if ((ringerMode == AudioManager.RINGER_MODE_VIBRATE) && !mHasVibrator) {
2565 ringerMode = AudioManager.RINGER_MODE_SILENT;
2566 }
John Spurlockaf88a192014-12-23 16:14:44 -05002567 final long identity = Binder.clearCallingIdentity();
2568 try {
2569 synchronized (mSettingsLock) {
2570 final int ringerModeInternal = getRingerModeInternal();
2571 final int ringerModeExternal = getRingerModeExternal();
2572 if (external) {
2573 setRingerModeExt(ringerMode);
2574 if (mRingerModeDelegate != null) {
2575 ringerMode = mRingerModeDelegate.onSetRingerModeExternal(ringerModeExternal,
John Spurlocka48d7792015-03-03 17:35:57 -05002576 ringerMode, caller, ringerModeInternal, mVolumePolicy);
John Spurlockaf88a192014-12-23 16:14:44 -05002577 }
2578 if (ringerMode != ringerModeInternal) {
2579 setRingerModeInt(ringerMode, true /*persist*/);
2580 }
2581 } else /*internal*/ {
2582 if (ringerMode != ringerModeInternal) {
2583 setRingerModeInt(ringerMode, true /*persist*/);
2584 }
2585 if (mRingerModeDelegate != null) {
2586 ringerMode = mRingerModeDelegate.onSetRingerModeInternal(ringerModeInternal,
John Spurlocka48d7792015-03-03 17:35:57 -05002587 ringerMode, caller, ringerModeExternal, mVolumePolicy);
John Spurlockaf88a192014-12-23 16:14:44 -05002588 }
2589 setRingerModeExt(ringerMode);
John Spurlock57627792014-12-11 11:29:54 -05002590 }
John Spurlock661f2cf2014-11-17 10:29:10 -05002591 }
John Spurlockaf88a192014-12-23 16:14:44 -05002592 } finally {
2593 Binder.restoreCallingIdentity(identity);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002594 }
2595 }
2596
John Spurlock661f2cf2014-11-17 10:29:10 -05002597 private void setRingerModeExt(int ringerMode) {
2598 synchronized(mSettingsLock) {
2599 if (ringerMode == mRingerModeExternal) return;
2600 mRingerModeExternal = ringerMode;
John Spurlocke5b42d92014-10-15 12:03:48 -04002601 }
John Spurlock661f2cf2014-11-17 10:29:10 -05002602 // Send sticky broadcast
John Spurlockbcc10872014-11-28 15:29:21 -05002603 broadcastRingerMode(AudioManager.RINGER_MODE_CHANGED_ACTION, ringerMode);
John Spurlocke5b42d92014-10-15 12:03:48 -04002604 }
2605
Jean-Michel Trivic106d9f2018-06-07 12:28:27 -07002606 @GuardedBy("mSettingsLock")
John Spurlock50ced3f2015-05-11 16:00:09 -04002607 private void muteRingerModeStreams() {
Beverlyd6964762018-02-16 14:07:03 -05002608 // Mute stream if not previously muted by ringer mode and (ringer mode
2609 // is not RINGER_MODE_NORMAL OR stream is zen muted) and stream is affected by ringer mode.
2610 // Unmute stream if previously muted by ringer/zen mode and ringer mode
Eric Laurent5b4e6542010-03-19 20:02:21 -07002611 // is RINGER_MODE_NORMAL or stream is not affected by ringer mode.
Jason Parekhb1096152009-03-24 17:48:25 -07002612 int numStreamTypes = AudioSystem.getNumStreamTypes();
Beverly925cde82018-01-23 09:31:23 -05002613
2614 if (mNm == null) {
2615 mNm = (NotificationManager) mContext.getSystemService(Context.NOTIFICATION_SERVICE);
2616 }
2617
Jack He6dd78c12018-02-12 21:00:24 -08002618 final int ringerMode = mRingerMode; // Read ringer mode as reading primitives is atomic
2619 final boolean ringerModeMute = ringerMode == AudioManager.RINGER_MODE_VIBRATE
2620 || ringerMode == AudioManager.RINGER_MODE_SILENT;
2621 final boolean shouldRingSco = ringerMode == AudioManager.RINGER_MODE_VIBRATE
2622 && isBluetoothScoOn();
2623 // Ask audio policy engine to force use Bluetooth SCO channel if needed
2624 final String eventSource = "muteRingerModeStreams() from u/pid:" + Binder.getCallingUid()
2625 + "/" + Binder.getCallingPid();
2626 sendMsg(mAudioHandler, MSG_SET_FORCE_USE, SENDMSG_QUEUE, AudioSystem.FOR_VIBRATE_RINGING,
2627 shouldRingSco ? AudioSystem.FORCE_BT_SCO : AudioSystem.FORCE_NONE, eventSource, 0);
Beverly925cde82018-01-23 09:31:23 -05002628
Eric Laurent5b4e6542010-03-19 20:02:21 -07002629 for (int streamType = numStreamTypes - 1; streamType >= 0; streamType--) {
Beverlyd6964762018-02-16 14:07:03 -05002630 final boolean isMuted = isStreamMutedByRingerOrZenMode(streamType);
Jack He6dd78c12018-02-12 21:00:24 -08002631 final boolean muteAllowedBySco =
2632 !(shouldRingSco && streamType == AudioSystem.STREAM_RING);
Beverlyd6964762018-02-16 14:07:03 -05002633 final boolean shouldZenMute = shouldZenMuteStream(streamType);
2634 final boolean shouldMute = shouldZenMute || (ringerModeMute
Jack He6dd78c12018-02-12 21:00:24 -08002635 && isStreamAffectedByRingerMode(streamType) && muteAllowedBySco);
John Spurlock661f2cf2014-11-17 10:29:10 -05002636 if (isMuted == shouldMute) continue;
2637 if (!shouldMute) {
2638 // unmute
2639 // ring and notifications volume should never be 0 when not silenced
John Spurlockd9c75db2015-04-28 11:19:13 -04002640 if (mStreamVolumeAlias[streamType] == AudioSystem.STREAM_RING) {
John Spurlock661f2cf2014-11-17 10:29:10 -05002641 synchronized (VolumeStreamState.class) {
John Spurlocka48d7792015-03-03 17:35:57 -05002642 final VolumeStreamState vss = mStreamStates[streamType];
2643 for (int i = 0; i < vss.mIndexMap.size(); i++) {
2644 int device = vss.mIndexMap.keyAt(i);
2645 int value = vss.mIndexMap.valueAt(i);
John Spurlock2bb02ec2015-03-02 13:13:06 -05002646 if (value == 0) {
John Spurlocka48d7792015-03-03 17:35:57 -05002647 vss.setIndex(10, device, TAG);
Eric Laurent9bc8358d2011-11-18 16:43:31 -08002648 }
2649 }
Eric Laurent9e0d25f2015-02-12 17:28:53 -08002650 // Persist volume for stream ring when it is changed here
2651 final int device = getDeviceForStream(streamType);
2652 sendMsg(mAudioHandler,
2653 MSG_PERSIST_VOLUME,
2654 SENDMSG_QUEUE,
2655 device,
2656 0,
2657 mStreamStates[streamType],
2658 PERSIST_DELAY);
Eric Laurentb024c302011-10-14 17:19:27 -07002659 }
Eric Laurent9bcf4012009-06-12 06:09:28 -07002660 }
RoboErik4197cb62015-01-21 15:45:32 -08002661 mStreamStates[streamType].mute(false);
Beverlyd6964762018-02-16 14:07:03 -05002662 mRingerAndZenModeMutedStreams &= ~(1 << streamType);
Eric Laurent5b4e6542010-03-19 20:02:21 -07002663 } else {
John Spurlock661f2cf2014-11-17 10:29:10 -05002664 // mute
RoboErik4197cb62015-01-21 15:45:32 -08002665 mStreamStates[streamType].mute(true);
Beverlyd6964762018-02-16 14:07:03 -05002666 mRingerAndZenModeMutedStreams |= (1 << streamType);
Jason Parekhb1096152009-03-24 17:48:25 -07002667 }
2668 }
John Spurlock50ced3f2015-05-11 16:00:09 -04002669 }
2670
Beverly925cde82018-01-23 09:31:23 -05002671 private boolean isAlarm(int streamType) {
2672 return streamType == AudioSystem.STREAM_ALARM;
2673 }
2674
2675 private boolean isNotificationOrRinger(int streamType) {
2676 return streamType == AudioSystem.STREAM_NOTIFICATION
2677 || streamType == AudioSystem.STREAM_RING;
2678 }
2679
2680 private boolean isMedia(int streamType) {
Beverlyd6964762018-02-16 14:07:03 -05002681 return streamType == AudioSystem.STREAM_MUSIC;
2682 }
2683
2684
2685 private boolean isSystem(int streamType) {
2686 return streamType == AudioSystem.STREAM_SYSTEM;
Beverly925cde82018-01-23 09:31:23 -05002687 }
2688
John Spurlock50ced3f2015-05-11 16:00:09 -04002689 private void setRingerModeInt(int ringerMode, boolean persist) {
2690 final boolean change;
2691 synchronized(mSettingsLock) {
2692 change = mRingerMode != ringerMode;
2693 mRingerMode = ringerMode;
Jean-Michel Trivic106d9f2018-06-07 12:28:27 -07002694 muteRingerModeStreams();
John Spurlock50ced3f2015-05-11 16:00:09 -04002695 }
2696
Jason Parekhb1096152009-03-24 17:48:25 -07002697 // Post a persist ringer mode msg
Eric Laurent4050c932009-07-08 02:52:14 -07002698 if (persist) {
Eric Laurentafbb0472011-12-15 09:04:23 -08002699 sendMsg(mAudioHandler, MSG_PERSIST_RINGER_MODE,
Eric Laurent4050c932009-07-08 02:52:14 -07002700 SENDMSG_REPLACE, 0, 0, null, PERSIST_DELAY);
2701 }
John Spurlockbcc10872014-11-28 15:29:21 -05002702 if (change) {
2703 // Send sticky broadcast
2704 broadcastRingerMode(AudioManager.INTERNAL_RINGER_MODE_CHANGED_ACTION, ringerMode);
2705 }
Jason Parekhb1096152009-03-24 17:48:25 -07002706 }
2707
Jean-Michel Trivi58850372018-09-14 16:01:28 -07002708 /*package*/ void setUpdateRingerModeServiceInt() {
2709 setRingerModeInt(getRingerModeInternal(), false);
2710 }
2711
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002712 /** @see AudioManager#shouldVibrate(int) */
2713 public boolean shouldVibrate(int vibrateType) {
Eric Laurentbffc3d12012-05-07 17:43:49 -07002714 if (!mHasVibrator) return false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002715
2716 switch (getVibrateSetting(vibrateType)) {
2717
2718 case AudioManager.VIBRATE_SETTING_ON:
John Spurlock57627792014-12-11 11:29:54 -05002719 return getRingerModeExternal() != AudioManager.RINGER_MODE_SILENT;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002720
2721 case AudioManager.VIBRATE_SETTING_ONLY_SILENT:
John Spurlock57627792014-12-11 11:29:54 -05002722 return getRingerModeExternal() == AudioManager.RINGER_MODE_VIBRATE;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002723
2724 case AudioManager.VIBRATE_SETTING_OFF:
Daniel Sandlerbcac4962010-04-12 13:23:57 -04002725 // return false, even for incoming calls
2726 return false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002727
2728 default:
2729 return false;
2730 }
2731 }
2732
2733 /** @see AudioManager#getVibrateSetting(int) */
2734 public int getVibrateSetting(int vibrateType) {
Eric Laurentbffc3d12012-05-07 17:43:49 -07002735 if (!mHasVibrator) return AudioManager.VIBRATE_SETTING_OFF;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002736 return (mVibrateSetting >> (vibrateType * 2)) & 3;
2737 }
2738
2739 /** @see AudioManager#setVibrateSetting(int, int) */
2740 public void setVibrateSetting(int vibrateType, int vibrateSetting) {
2741
Eric Laurentbffc3d12012-05-07 17:43:49 -07002742 if (!mHasVibrator) return;
2743
John Spurlock61560172015-02-06 19:46:04 -05002744 mVibrateSetting = AudioSystem.getValueForVibrateSetting(mVibrateSetting, vibrateType,
2745 vibrateSetting);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002746
2747 // Broadcast change
2748 broadcastVibrateSetting(vibrateType);
2749
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002750 }
2751
Jean-Michel Trivi58850372018-09-14 16:01:28 -07002752 /*package*/ class SetModeDeathHandler implements IBinder.DeathRecipient {
Eric Laurent9272b4b2010-01-23 17:12:59 -08002753 private IBinder mCb; // To be notified of client's death
Marco Nelissenf1ddd512011-08-10 14:15:44 -07002754 private int mPid;
Eric Laurent9272b4b2010-01-23 17:12:59 -08002755 private int mMode = AudioSystem.MODE_NORMAL; // Current mode set by this client
2756
Eric Laurent9f103de2011-09-08 15:04:23 -07002757 SetModeDeathHandler(IBinder cb, int pid) {
Eric Laurent9272b4b2010-01-23 17:12:59 -08002758 mCb = cb;
Eric Laurent9f103de2011-09-08 15:04:23 -07002759 mPid = pid;
Eric Laurent9272b4b2010-01-23 17:12:59 -08002760 }
2761
2762 public void binderDied() {
Jack He89f97982018-05-02 19:10:56 -07002763 int oldModeOwnerPid = 0;
Eric Laurentd7454be2011-09-14 08:45:58 -07002764 int newModeOwnerPid = 0;
Jean-Michel Trivi58850372018-09-14 16:01:28 -07002765 synchronized (mDeviceBroker.mSetModeLock) {
Eric Laurent9272b4b2010-01-23 17:12:59 -08002766 Log.w(TAG, "setMode() client died");
Jack He89f97982018-05-02 19:10:56 -07002767 if (!mSetModeDeathHandlers.isEmpty()) {
2768 oldModeOwnerPid = mSetModeDeathHandlers.get(0).getPid();
2769 }
Eric Laurent9272b4b2010-01-23 17:12:59 -08002770 int index = mSetModeDeathHandlers.indexOf(this);
2771 if (index < 0) {
2772 Log.w(TAG, "unregistered setMode() client died");
2773 } else {
John Spurlock90874332015-03-10 16:00:54 -04002774 newModeOwnerPid = setModeInt(AudioSystem.MODE_NORMAL, mCb, mPid, TAG);
Eric Laurent9272b4b2010-01-23 17:12:59 -08002775 }
2776 }
Eric Laurent9f103de2011-09-08 15:04:23 -07002777 // when entering RINGTONE, IN_CALL or IN_COMMUNICATION mode, clear all
Jack He89f97982018-05-02 19:10:56 -07002778 // SCO connections not started by the application changing the mode when pid changes
2779 if ((newModeOwnerPid != oldModeOwnerPid) && (newModeOwnerPid != 0)) {
Jean-Michel Trivi58850372018-09-14 16:01:28 -07002780 mDeviceBroker.postDisconnectBluetoothSco(newModeOwnerPid);
Eric Laurent9f103de2011-09-08 15:04:23 -07002781 }
Eric Laurent9272b4b2010-01-23 17:12:59 -08002782 }
2783
Marco Nelissenf1ddd512011-08-10 14:15:44 -07002784 public int getPid() {
2785 return mPid;
2786 }
2787
Eric Laurent9272b4b2010-01-23 17:12:59 -08002788 public void setMode(int mode) {
2789 mMode = mode;
2790 }
2791
2792 public int getMode() {
2793 return mMode;
2794 }
2795
2796 public IBinder getBinder() {
2797 return mCb;
2798 }
2799 }
2800
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002801 /** @see AudioManager#setMode(int) */
John Spurlock90874332015-03-10 16:00:54 -04002802 public void setMode(int mode, IBinder cb, String callingPackage) {
2803 if (DEBUG_MODE) { Log.v(TAG, "setMode(mode=" + mode + ", callingPackage=" + callingPackage + ")"); }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002804 if (!checkAudioSettingsPermission("setMode()")) {
2805 return;
2806 }
Eric Laurenta553c252009-07-17 12:17:14 -07002807
Jean-Michel Triviccd654e2014-09-03 17:48:47 -07002808 if ( (mode == AudioSystem.MODE_IN_CALL) &&
2809 (mContext.checkCallingOrSelfPermission(
2810 android.Manifest.permission.MODIFY_PHONE_STATE)
2811 != PackageManager.PERMISSION_GRANTED)) {
2812 Log.w(TAG, "MODIFY_PHONE_STATE Permission Denial: setMode(MODE_IN_CALL) from pid="
2813 + Binder.getCallingPid() + ", uid=" + Binder.getCallingUid());
2814 return;
2815 }
2816
Jean-Michel Trivi8f677d62010-11-15 12:11:32 -08002817 if (mode < AudioSystem.MODE_CURRENT || mode >= AudioSystem.NUM_MODES) {
Eric Laurenta553c252009-07-17 12:17:14 -07002818 return;
2819 }
2820
Jack He89f97982018-05-02 19:10:56 -07002821 int oldModeOwnerPid = 0;
Eric Laurentd7454be2011-09-14 08:45:58 -07002822 int newModeOwnerPid = 0;
Jean-Michel Trivi58850372018-09-14 16:01:28 -07002823 synchronized (mDeviceBroker.mSetModeLock) {
Jack He89f97982018-05-02 19:10:56 -07002824 if (!mSetModeDeathHandlers.isEmpty()) {
2825 oldModeOwnerPid = mSetModeDeathHandlers.get(0).getPid();
2826 }
Eric Laurenta553c252009-07-17 12:17:14 -07002827 if (mode == AudioSystem.MODE_CURRENT) {
2828 mode = mMode;
2829 }
John Spurlock90874332015-03-10 16:00:54 -04002830 newModeOwnerPid = setModeInt(mode, cb, Binder.getCallingPid(), callingPackage);
Eric Laurent9f103de2011-09-08 15:04:23 -07002831 }
2832 // when entering RINGTONE, IN_CALL or IN_COMMUNICATION mode, clear all
Jack He89f97982018-05-02 19:10:56 -07002833 // SCO connections not started by the application changing the mode when pid changes
2834 if ((newModeOwnerPid != oldModeOwnerPid) && (newModeOwnerPid != 0)) {
Jean-Michel Trivi58850372018-09-14 16:01:28 -07002835 mDeviceBroker.postDisconnectBluetoothSco(newModeOwnerPid);
Eric Laurent9f103de2011-09-08 15:04:23 -07002836 }
2837 }
Jean-Michel Trivi2ade5762010-12-11 13:18:30 -08002838
Jean-Michel Trivi58850372018-09-14 16:01:28 -07002839 // must be called synchronized on mSetModeLock
Eric Laurentd7454be2011-09-14 08:45:58 -07002840 // setModeInt() returns a valid PID if the audio mode was successfully set to
Eric Laurent9f103de2011-09-08 15:04:23 -07002841 // any mode other than NORMAL.
John Spurlock90874332015-03-10 16:00:54 -04002842 private int setModeInt(int mode, IBinder cb, int pid, String caller) {
2843 if (DEBUG_MODE) { Log.v(TAG, "setModeInt(mode=" + mode + ", pid=" + pid + ", caller="
2844 + caller + ")"); }
Eric Laurentd7454be2011-09-14 08:45:58 -07002845 int newModeOwnerPid = 0;
Eric Laurent9f103de2011-09-08 15:04:23 -07002846 if (cb == null) {
2847 Log.e(TAG, "setModeInt() called with null binder");
Eric Laurentd7454be2011-09-14 08:45:58 -07002848 return newModeOwnerPid;
Eric Laurent9f103de2011-09-08 15:04:23 -07002849 }
Jean-Michel Trivi2ade5762010-12-11 13:18:30 -08002850
Eric Laurent9f103de2011-09-08 15:04:23 -07002851 SetModeDeathHandler hdlr = null;
2852 Iterator iter = mSetModeDeathHandlers.iterator();
2853 while (iter.hasNext()) {
2854 SetModeDeathHandler h = (SetModeDeathHandler)iter.next();
2855 if (h.getPid() == pid) {
2856 hdlr = h;
2857 // Remove from client list so that it is re-inserted at top of list
2858 iter.remove();
2859 hdlr.getBinder().unlinkToDeath(hdlr, 0);
2860 break;
2861 }
2862 }
2863 int status = AudioSystem.AUDIO_STATUS_OK;
Eric Laurent6afa6502017-09-28 15:18:19 -07002864 int actualMode;
Eric Laurent9f103de2011-09-08 15:04:23 -07002865 do {
Eric Laurent6afa6502017-09-28 15:18:19 -07002866 actualMode = mode;
Eric Laurent9f103de2011-09-08 15:04:23 -07002867 if (mode == AudioSystem.MODE_NORMAL) {
2868 // get new mode from client at top the list if any
2869 if (!mSetModeDeathHandlers.isEmpty()) {
2870 hdlr = mSetModeDeathHandlers.get(0);
2871 cb = hdlr.getBinder();
Eric Laurent6afa6502017-09-28 15:18:19 -07002872 actualMode = hdlr.getMode();
Jean-Michel Trivi339567d2014-07-29 09:53:34 -07002873 if (DEBUG_MODE) {
2874 Log.w(TAG, " using mode=" + mode + " instead due to death hdlr at pid="
2875 + hdlr.mPid);
2876 }
Eric Laurentb9c9d262009-05-06 08:13:20 -07002877 }
Eric Laurent9f103de2011-09-08 15:04:23 -07002878 } else {
2879 if (hdlr == null) {
2880 hdlr = new SetModeDeathHandler(cb, pid);
2881 }
2882 // Register for client death notification
2883 try {
2884 cb.linkToDeath(hdlr, 0);
2885 } catch (RemoteException e) {
2886 // Client has died!
2887 Log.w(TAG, "setMode() could not link to "+cb+" binder death");
2888 }
2889
2890 // Last client to call setMode() is always at top of client list
2891 // as required by SetModeDeathHandler.binderDied()
2892 mSetModeDeathHandlers.add(0, hdlr);
2893 hdlr.setMode(mode);
2894 }
2895
Eric Laurent6afa6502017-09-28 15:18:19 -07002896 if (actualMode != mMode) {
Eric Laurent66b69672018-01-26 18:30:51 -08002897 final long identity = Binder.clearCallingIdentity();
Eric Laurent6afa6502017-09-28 15:18:19 -07002898 status = AudioSystem.setPhoneState(actualMode);
Eric Laurent66b69672018-01-26 18:30:51 -08002899 Binder.restoreCallingIdentity(identity);
Eric Laurent9f103de2011-09-08 15:04:23 -07002900 if (status == AudioSystem.AUDIO_STATUS_OK) {
Eric Laurent6afa6502017-09-28 15:18:19 -07002901 if (DEBUG_MODE) { Log.v(TAG, " mode successfully set to " + actualMode); }
2902 mMode = actualMode;
Eric Laurent9f103de2011-09-08 15:04:23 -07002903 } else {
2904 if (hdlr != null) {
2905 mSetModeDeathHandlers.remove(hdlr);
2906 cb.unlinkToDeath(hdlr, 0);
2907 }
2908 // force reading new top of mSetModeDeathHandlers stack
Jean-Michel Trivi339567d2014-07-29 09:53:34 -07002909 if (DEBUG_MODE) { Log.w(TAG, " mode set to MODE_NORMAL after phoneState pb"); }
Eric Laurent9f103de2011-09-08 15:04:23 -07002910 mode = AudioSystem.MODE_NORMAL;
2911 }
2912 } else {
2913 status = AudioSystem.AUDIO_STATUS_OK;
2914 }
2915 } while (status != AudioSystem.AUDIO_STATUS_OK && !mSetModeDeathHandlers.isEmpty());
2916
2917 if (status == AudioSystem.AUDIO_STATUS_OK) {
Eric Laurent6afa6502017-09-28 15:18:19 -07002918 if (actualMode != AudioSystem.MODE_NORMAL) {
Eric Laurentd7454be2011-09-14 08:45:58 -07002919 if (mSetModeDeathHandlers.isEmpty()) {
2920 Log.e(TAG, "setMode() different from MODE_NORMAL with empty mode client stack");
2921 } else {
2922 newModeOwnerPid = mSetModeDeathHandlers.get(0).getPid();
2923 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002924 }
Eric Laurent6afa6502017-09-28 15:18:19 -07002925 // Note: newModeOwnerPid is always 0 when actualMode is MODE_NORMAL
2926 mModeLogger.log(
2927 new PhoneStateEvent(caller, pid, mode, newModeOwnerPid, actualMode));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002928 int streamType = getActiveStreamType(AudioManager.USE_DEFAULT_STREAM_TYPE);
Eric Laurent9bc8358d2011-11-18 16:43:31 -08002929 int device = getDeviceForStream(streamType);
Eric Laurent42b041e2013-03-29 11:36:03 -07002930 int index = mStreamStates[mStreamVolumeAlias[streamType]].getIndex(device);
John Spurlock90874332015-03-10 16:00:54 -04002931 setStreamVolumeInt(mStreamVolumeAlias[streamType], index, device, true, caller);
Eric Laurent6d517662012-04-23 18:42:39 -07002932
John Spurlock90874332015-03-10 16:00:54 -04002933 updateStreamVolumeAlias(true /*updateVolumes*/, caller);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002934 }
Eric Laurentd7454be2011-09-14 08:45:58 -07002935 return newModeOwnerPid;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002936 }
2937
2938 /** @see AudioManager#getMode() */
2939 public int getMode() {
2940 return mMode;
2941 }
2942
Eric Laurente78fced2013-03-15 16:03:47 -07002943 //==========================================================================================
2944 // Sound Effects
2945 //==========================================================================================
2946
2947 private static final String TAG_AUDIO_ASSETS = "audio_assets";
2948 private static final String ATTR_VERSION = "version";
2949 private static final String TAG_GROUP = "group";
2950 private static final String ATTR_GROUP_NAME = "name";
2951 private static final String TAG_ASSET = "asset";
2952 private static final String ATTR_ASSET_ID = "id";
2953 private static final String ATTR_ASSET_FILE = "file";
2954
2955 private static final String ASSET_FILE_VERSION = "1.0";
2956 private static final String GROUP_TOUCH_SOUNDS = "touch_sounds";
2957
Glenn Kasten167d1a22013-07-23 16:24:41 -07002958 private static final int SOUND_EFFECTS_LOAD_TIMEOUT_MS = 5000;
Eric Laurent5d3eb44a2013-03-21 15:35:10 -07002959
2960 class LoadSoundEffectReply {
2961 public int mStatus = 1;
2962 };
2963
Eric Laurente78fced2013-03-15 16:03:47 -07002964 private void loadTouchSoundAssetDefaults() {
2965 SOUND_EFFECT_FILES.add("Effect_Tick.ogg");
2966 for (int i = 0; i < AudioManager.NUM_SOUND_EFFECTS; i++) {
2967 SOUND_EFFECT_FILES_MAP[i][0] = 0;
2968 SOUND_EFFECT_FILES_MAP[i][1] = -1;
2969 }
2970 }
2971
2972 private void loadTouchSoundAssets() {
2973 XmlResourceParser parser = null;
2974
Eric Laurent5d3eb44a2013-03-21 15:35:10 -07002975 // only load assets once.
2976 if (!SOUND_EFFECT_FILES.isEmpty()) {
2977 return;
2978 }
2979
Eric Laurente78fced2013-03-15 16:03:47 -07002980 loadTouchSoundAssetDefaults();
2981
2982 try {
2983 parser = mContext.getResources().getXml(com.android.internal.R.xml.audio_assets);
2984
2985 XmlUtils.beginDocument(parser, TAG_AUDIO_ASSETS);
2986 String version = parser.getAttributeValue(null, ATTR_VERSION);
2987 boolean inTouchSoundsGroup = false;
2988
2989 if (ASSET_FILE_VERSION.equals(version)) {
2990 while (true) {
2991 XmlUtils.nextElement(parser);
2992 String element = parser.getName();
2993 if (element == null) {
2994 break;
2995 }
2996 if (element.equals(TAG_GROUP)) {
2997 String name = parser.getAttributeValue(null, ATTR_GROUP_NAME);
2998 if (GROUP_TOUCH_SOUNDS.equals(name)) {
2999 inTouchSoundsGroup = true;
3000 break;
3001 }
3002 }
3003 }
3004 while (inTouchSoundsGroup) {
3005 XmlUtils.nextElement(parser);
3006 String element = parser.getName();
3007 if (element == null) {
3008 break;
3009 }
3010 if (element.equals(TAG_ASSET)) {
3011 String id = parser.getAttributeValue(null, ATTR_ASSET_ID);
3012 String file = parser.getAttributeValue(null, ATTR_ASSET_FILE);
3013 int fx;
3014
3015 try {
3016 Field field = AudioManager.class.getField(id);
3017 fx = field.getInt(null);
3018 } catch (Exception e) {
3019 Log.w(TAG, "Invalid touch sound ID: "+id);
3020 continue;
3021 }
3022
3023 int i = SOUND_EFFECT_FILES.indexOf(file);
3024 if (i == -1) {
3025 i = SOUND_EFFECT_FILES.size();
3026 SOUND_EFFECT_FILES.add(file);
3027 }
3028 SOUND_EFFECT_FILES_MAP[fx][0] = i;
3029 } else {
3030 break;
3031 }
3032 }
3033 }
3034 } catch (Resources.NotFoundException e) {
3035 Log.w(TAG, "audio assets file not found", e);
3036 } catch (XmlPullParserException e) {
3037 Log.w(TAG, "XML parser exception reading touch sound assets", e);
3038 } catch (IOException e) {
3039 Log.w(TAG, "I/O exception reading touch sound assets", e);
3040 } finally {
3041 if (parser != null) {
3042 parser.close();
3043 }
3044 }
3045 }
3046
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003047 /** @see AudioManager#playSoundEffect(int) */
3048 public void playSoundEffect(int effectType) {
Eric Laurent5d3eb44a2013-03-21 15:35:10 -07003049 playSoundEffectVolume(effectType, -1.0f);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003050 }
3051
3052 /** @see AudioManager#playSoundEffect(int, float) */
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003053 public void playSoundEffectVolume(int effectType, float volume) {
Beverlyd6964762018-02-16 14:07:03 -05003054 // do not try to play the sound effect if the system stream is muted
3055 if (isStreamMutedByRingerOrZenMode(STREAM_SYSTEM)) {
3056 return;
3057 }
3058
Natalie Silvanovich559c76d2014-05-01 10:16:24 -07003059 if (effectType >= AudioManager.NUM_SOUND_EFFECTS || effectType < 0) {
3060 Log.w(TAG, "AudioService effectType value " + effectType + " out of range");
3061 return;
3062 }
3063
Eric Laurent5d3eb44a2013-03-21 15:35:10 -07003064 sendMsg(mAudioHandler, MSG_PLAY_SOUND_EFFECT, SENDMSG_QUEUE,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003065 effectType, (int) (volume * 1000), null, 0);
3066 }
3067
3068 /**
3069 * Loads samples into the soundpool.
Glenn Kasten5c17a822011-11-30 09:41:01 -08003070 * This method must be called at first when sound effects are enabled
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003071 */
3072 public boolean loadSoundEffects() {
Eric Laurent5d3eb44a2013-03-21 15:35:10 -07003073 int attempts = 3;
3074 LoadSoundEffectReply reply = new LoadSoundEffectReply();
Eric Laurenta60e2122010-12-28 16:49:07 -08003075
Eric Laurent5d3eb44a2013-03-21 15:35:10 -07003076 synchronized (reply) {
3077 sendMsg(mAudioHandler, MSG_LOAD_SOUND_EFFECTS, SENDMSG_QUEUE, 0, 0, reply, 0);
3078 while ((reply.mStatus == 1) && (attempts-- > 0)) {
Eric Laurent117b7bb2011-01-16 17:07:27 -08003079 try {
Glenn Kasten167d1a22013-07-23 16:24:41 -07003080 reply.wait(SOUND_EFFECTS_LOAD_TIMEOUT_MS);
Eric Laurent5d3eb44a2013-03-21 15:35:10 -07003081 } catch (InterruptedException e) {
3082 Log.w(TAG, "loadSoundEffects Interrupted while waiting sound pool loaded.");
Eric Laurent117b7bb2011-01-16 17:07:27 -08003083 }
Eric Laurenta60e2122010-12-28 16:49:07 -08003084 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003085 }
Eric Laurent5d3eb44a2013-03-21 15:35:10 -07003086 return (reply.mStatus == 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003087 }
3088
3089 /**
3090 * Unloads samples from the sound pool.
3091 * This method can be called to free some memory when
3092 * sound effects are disabled.
3093 */
3094 public void unloadSoundEffects() {
Eric Laurent5d3eb44a2013-03-21 15:35:10 -07003095 sendMsg(mAudioHandler, MSG_UNLOAD_SOUND_EFFECTS, SENDMSG_QUEUE, 0, 0, null, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003096 }
3097
Eric Laurenta60e2122010-12-28 16:49:07 -08003098 class SoundPoolListenerThread extends Thread {
3099 public SoundPoolListenerThread() {
3100 super("SoundPoolListenerThread");
3101 }
3102
3103 @Override
3104 public void run() {
3105
3106 Looper.prepare();
3107 mSoundPoolLooper = Looper.myLooper();
3108
3109 synchronized (mSoundEffectsLock) {
3110 if (mSoundPool != null) {
3111 mSoundPoolCallBack = new SoundPoolCallback();
3112 mSoundPool.setOnLoadCompleteListener(mSoundPoolCallBack);
3113 }
3114 mSoundEffectsLock.notify();
3115 }
3116 Looper.loop();
3117 }
3118 }
3119
3120 private final class SoundPoolCallback implements
3121 android.media.SoundPool.OnLoadCompleteListener {
3122
Eric Laurent5d3eb44a2013-03-21 15:35:10 -07003123 int mStatus = 1; // 1 means neither error nor last sample loaded yet
3124 List<Integer> mSamples = new ArrayList<Integer>();
Eric Laurenta60e2122010-12-28 16:49:07 -08003125
3126 public int status() {
3127 return mStatus;
3128 }
3129
Eric Laurent5d3eb44a2013-03-21 15:35:10 -07003130 public void setSamples(int[] samples) {
3131 for (int i = 0; i < samples.length; i++) {
3132 // do not wait ack for samples rejected upfront by SoundPool
3133 if (samples[i] > 0) {
3134 mSamples.add(samples[i]);
3135 }
3136 }
Eric Laurenta60e2122010-12-28 16:49:07 -08003137 }
3138
3139 public void onLoadComplete(SoundPool soundPool, int sampleId, int status) {
3140 synchronized (mSoundEffectsLock) {
Eric Laurent5d3eb44a2013-03-21 15:35:10 -07003141 int i = mSamples.indexOf(sampleId);
3142 if (i >= 0) {
3143 mSamples.remove(i);
Eric Laurenta60e2122010-12-28 16:49:07 -08003144 }
Eric Laurent5d3eb44a2013-03-21 15:35:10 -07003145 if ((status != 0) || mSamples. isEmpty()) {
3146 mStatus = status;
Eric Laurenta60e2122010-12-28 16:49:07 -08003147 mSoundEffectsLock.notify();
3148 }
3149 }
3150 }
3151 }
3152
Eric Laurent4050c932009-07-08 02:52:14 -07003153 /** @see AudioManager#reloadAudioSettings() */
3154 public void reloadAudioSettings() {
Eric Laurentbc0fab1f2012-09-19 11:24:41 -07003155 readAudioSettings(false /*userSwitch*/);
3156 }
3157
3158 private void readAudioSettings(boolean userSwitch) {
Eric Laurent4050c932009-07-08 02:52:14 -07003159 // restore ringer mode, ringer mode affected streams, mute affected streams and vibrate settings
3160 readPersistedSettings();
Eric Laurentc0232482016-03-15 18:19:23 -07003161 readUserRestrictions();
Eric Laurent4050c932009-07-08 02:52:14 -07003162
3163 // restore volume settings
3164 int numStreamTypes = AudioSystem.getNumStreamTypes();
3165 for (int streamType = 0; streamType < numStreamTypes; streamType++) {
3166 VolumeStreamState streamState = mStreamStates[streamType];
3167
Eric Laurentbc0fab1f2012-09-19 11:24:41 -07003168 if (userSwitch && mStreamVolumeAlias[streamType] == AudioSystem.STREAM_MUSIC) {
3169 continue;
3170 }
3171
Eric Laurent8fa4d6f2014-10-30 14:13:03 -07003172 streamState.readSettings();
3173 synchronized (VolumeStreamState.class) {
Eric Laurent3172d5e2012-05-09 11:38:16 -07003174 // unmute stream that was muted but is not affect by mute anymore
RoboErik4197cb62015-01-21 15:45:32 -08003175 if (streamState.mIsMuted && ((!isStreamAffectedByMute(streamType) &&
Beverlyd6964762018-02-16 14:07:03 -05003176 !isStreamMutedByRingerOrZenMode(streamType)) || mUseFixedVolume)) {
RoboErik4197cb62015-01-21 15:45:32 -08003177 streamState.mIsMuted = false;
Eric Laurent4050c932009-07-08 02:52:14 -07003178 }
Eric Laurent4050c932009-07-08 02:52:14 -07003179 }
3180 }
3181
Eric Laurent33902db2012-10-07 16:15:07 -07003182 // apply new ringer mode before checking volume for alias streams so that streams
3183 // muted by ringer mode have the correct volume
John Spurlock661f2cf2014-11-17 10:29:10 -05003184 setRingerModeInt(getRingerModeInternal(), false);
Eric Laurent33902db2012-10-07 16:15:07 -07003185
Eric Laurent212532b2014-07-21 15:43:18 -07003186 checkAllFixedVolumeDevices();
Eric Laurent24482012012-05-10 09:41:17 -07003187 checkAllAliasStreamVolumes();
John Spurlockb6e19e32015-03-10 21:33:44 -04003188 checkMuteAffectedStreams();
Eric Laurent24482012012-05-10 09:41:17 -07003189
hyomin.ohd0446dc2018-10-18 13:58:27 +09003190 synchronized (mSafeMediaVolumeStateLock) {
John Spurlockaa5ee4d2014-07-25 13:05:12 -04003191 mMusicActiveMs = MathUtils.constrain(Settings.Secure.getIntForUser(mContentResolver,
3192 Settings.Secure.UNSAFE_VOLUME_MUSIC_ACTIVE_MS, 0, UserHandle.USER_CURRENT),
3193 0, UNSAFE_VOLUME_MUSIC_ACTIVE_MS_MAX);
Eric Laurentd640bd32012-09-28 18:01:48 -07003194 if (mSafeMediaVolumeState == SAFE_MEDIA_VOLUME_ACTIVE) {
John Spurlock90874332015-03-10 16:00:54 -04003195 enforceSafeMediaVolume(TAG);
Eric Laurentf1a457d2012-09-20 16:27:23 -07003196 }
Eric Laurentc34dcc12012-09-10 13:51:52 -07003197 }
Eric Laurent4050c932009-07-08 02:52:14 -07003198 }
3199
Dianne Hackborn961cae92013-03-20 14:59:43 -07003200 /** @see AudioManager#setSpeakerphoneOn(boolean) */
Eric Laurentc42ac9d2009-07-29 08:53:03 -07003201 public void setSpeakerphoneOn(boolean on){
Eric Laurentdc1d17a2009-09-10 00:48:21 -07003202 if (!checkAudioSettingsPermission("setSpeakerphoneOn()")) {
3203 return;
3204 }
Jean-Michel Trivi011f39e2017-08-19 18:08:06 -07003205 // for logging only
3206 final String eventSource = new StringBuilder("setSpeakerphoneOn(").append(on)
3207 .append(") from u/pid:").append(Binder.getCallingUid()).append("/")
3208 .append(Binder.getCallingPid()).toString();
Jean-Michel Trivi58850372018-09-14 16:01:28 -07003209 mDeviceBroker.setSpeakerphoneOn(on, eventSource);
Eric Laurentc42ac9d2009-07-29 08:53:03 -07003210 }
3211
3212 /** @see AudioManager#isSpeakerphoneOn() */
3213 public boolean isSpeakerphoneOn() {
Jean-Michel Trivi58850372018-09-14 16:01:28 -07003214 return mDeviceBroker.isSpeakerphoneOn();
Eric Laurentc42ac9d2009-07-29 08:53:03 -07003215 }
3216
Dianne Hackborn961cae92013-03-20 14:59:43 -07003217 /** @see AudioManager#setBluetoothScoOn(boolean) */
Eric Laurent48221252015-09-24 18:41:48 -07003218 public void setBluetoothScoOn(boolean on) {
Eric Laurentdc1d17a2009-09-10 00:48:21 -07003219 if (!checkAudioSettingsPermission("setBluetoothScoOn()")) {
3220 return;
3221 }
Sharad Sangle1d188442017-05-09 16:05:40 +05303222
3223 // Only enable calls from system components
Vitor Albuquerquec3bb48c2018-03-07 10:39:59 -03003224 if (UserHandle.getCallingAppId() >= FIRST_APPLICATION_UID) {
Jean-Michel Trivi58850372018-09-14 16:01:28 -07003225 mDeviceBroker.setBluetoothScoOnByApp(on);
Sharad Sangle1d188442017-05-09 16:05:40 +05303226 return;
3227 }
3228
Jean-Michel Trivi011f39e2017-08-19 18:08:06 -07003229 // for logging only
3230 final String eventSource = new StringBuilder("setBluetoothScoOn(").append(on)
3231 .append(") from u/pid:").append(Binder.getCallingUid()).append("/")
3232 .append(Binder.getCallingPid()).toString();
Jean-Michel Trivi58850372018-09-14 16:01:28 -07003233
3234 mDeviceBroker.setBluetoothScoOn(on, eventSource);
Eric Laurent48221252015-09-24 18:41:48 -07003235 }
Johan Gustavsson7337bee2013-03-01 15:53:30 +01003236
Jean-Michel Trivi58850372018-09-14 16:01:28 -07003237 /** @see AudioManager#isBluetoothScoOn()
3238 * Note that it doesn't report internal state, but state seen by apps (which may have
3239 * called setBluetoothScoOn() */
Eric Laurentc42ac9d2009-07-29 08:53:03 -07003240 public boolean isBluetoothScoOn() {
Jean-Michel Trivi58850372018-09-14 16:01:28 -07003241 return mDeviceBroker.isBluetoothScoOnForApp();
Eric Laurentc42ac9d2009-07-29 08:53:03 -07003242 }
3243
Jean-Michel Trivi58850372018-09-14 16:01:28 -07003244 // TODO investigate internal users due to deprecation of SDK API
Sungsoocf09fe62016-09-28 16:21:48 +09003245 /** @see AudioManager#setBluetoothA2dpOn(boolean) */
Eric Laurent78472112012-05-21 08:57:21 -07003246 public void setBluetoothA2dpOn(boolean on) {
Jean-Michel Trivi011f39e2017-08-19 18:08:06 -07003247 // for logging only
3248 final String eventSource = new StringBuilder("setBluetoothA2dpOn(").append(on)
3249 .append(") from u/pid:").append(Binder.getCallingUid()).append("/")
3250 .append(Binder.getCallingPid()).toString();
Jean-Michel Trivi58850372018-09-14 16:01:28 -07003251 mDeviceBroker.setBluetoothA2dpOn_Async(on, eventSource);
Eric Laurent78472112012-05-21 08:57:21 -07003252 }
3253
Sungsoocf09fe62016-09-28 16:21:48 +09003254 /** @see AudioManager#isBluetoothA2dpOn() */
Eric Laurent78472112012-05-21 08:57:21 -07003255 public boolean isBluetoothA2dpOn() {
Jean-Michel Trivi58850372018-09-14 16:01:28 -07003256 return mDeviceBroker.isBluetoothA2dpOn();
Eric Laurent78472112012-05-21 08:57:21 -07003257 }
3258
Eric Laurent3def1ee2010-03-17 23:26:26 -07003259 /** @see AudioManager#startBluetoothSco() */
Eric Laurent83900752014-05-15 15:14:22 -07003260 public void startBluetoothSco(IBinder cb, int targetSdkVersion) {
Jean-Michel Trivi58850372018-09-14 16:01:28 -07003261 final int scoAudioMode =
Eric Laurent83900752014-05-15 15:14:22 -07003262 (targetSdkVersion < Build.VERSION_CODES.JELLY_BEAN_MR2) ?
Jean-Michel Trivi58850372018-09-14 16:01:28 -07003263 BtHelper.SCO_MODE_VIRTUAL_CALL : BtHelper.SCO_MODE_UNDEFINED;
3264 final String eventSource = new StringBuilder("startBluetoothSco()")
3265 .append(") from u/pid:").append(Binder.getCallingUid()).append("/")
3266 .append(Binder.getCallingPid()).toString();
3267 startBluetoothScoInt(cb, scoAudioMode, eventSource);
Eric Laurent83900752014-05-15 15:14:22 -07003268 }
3269
3270 /** @see AudioManager#startBluetoothScoVirtualCall() */
3271 public void startBluetoothScoVirtualCall(IBinder cb) {
Jean-Michel Trivi58850372018-09-14 16:01:28 -07003272 final String eventSource = new StringBuilder("startBluetoothScoVirtualCall()")
3273 .append(") from u/pid:").append(Binder.getCallingUid()).append("/")
3274 .append(Binder.getCallingPid()).toString();
3275 startBluetoothScoInt(cb, BtHelper.SCO_MODE_VIRTUAL_CALL, eventSource);
Eric Laurent83900752014-05-15 15:14:22 -07003276 }
3277
Jean-Michel Trivi58850372018-09-14 16:01:28 -07003278 void startBluetoothScoInt(IBinder cb, int scoAudioMode, @NonNull String eventSource) {
Eric Laurentdc03c612011-04-01 10:59:41 -07003279 if (!checkAudioSettingsPermission("startBluetoothSco()") ||
Eric Laurent4a5eeb92014-05-06 10:49:04 -07003280 !mSystemReady) {
Eric Laurent3def1ee2010-03-17 23:26:26 -07003281 return;
3282 }
Jean-Michel Trivi58850372018-09-14 16:01:28 -07003283 mDeviceBroker.startBluetoothScoForClient_Sync(cb, scoAudioMode, eventSource);
Eric Laurent3def1ee2010-03-17 23:26:26 -07003284 }
3285
3286 /** @see AudioManager#stopBluetoothSco() */
3287 public void stopBluetoothSco(IBinder cb){
Eric Laurentdc03c612011-04-01 10:59:41 -07003288 if (!checkAudioSettingsPermission("stopBluetoothSco()") ||
Eric Laurent4a5eeb92014-05-06 10:49:04 -07003289 !mSystemReady) {
Eric Laurent3def1ee2010-03-17 23:26:26 -07003290 return;
3291 }
Jean-Michel Trivi58850372018-09-14 16:01:28 -07003292 final String eventSource = new StringBuilder("stopBluetoothSco()")
3293 .append(") from u/pid:").append(Binder.getCallingUid()).append("/")
3294 .append(Binder.getCallingPid()).toString();
3295 mDeviceBroker.stopBluetoothScoForClient_Sync(cb, eventSource);
Eric Laurent3def1ee2010-03-17 23:26:26 -07003296 }
3297
Eric Laurent78472112012-05-21 08:57:21 -07003298
Jean-Michel Trivi58850372018-09-14 16:01:28 -07003299 /*package*/ ContentResolver getContentResolver() {
3300 return mContentResolver;
Jakub Pawlowskif9570f32018-02-21 17:15:12 -08003301 }
3302
John Spurlock90874332015-03-10 16:00:54 -04003303 private void onCheckMusicActive(String caller) {
hyomin.ohd0446dc2018-10-18 13:58:27 +09003304 synchronized (mSafeMediaVolumeStateLock) {
Eric Laurentd640bd32012-09-28 18:01:48 -07003305 if (mSafeMediaVolumeState == SAFE_MEDIA_VOLUME_INACTIVE) {
Eric Laurentc34dcc12012-09-10 13:51:52 -07003306 int device = getDeviceForStream(AudioSystem.STREAM_MUSIC);
3307
3308 if ((device & mSafeMediaVolumeDevices) != 0) {
3309 sendMsg(mAudioHandler,
3310 MSG_CHECK_MUSIC_ACTIVE,
3311 SENDMSG_REPLACE,
Eric Laurentf1a457d2012-09-20 16:27:23 -07003312 0,
Eric Laurentc34dcc12012-09-10 13:51:52 -07003313 0,
John Spurlock90874332015-03-10 16:00:54 -04003314 caller,
Eric Laurentc34dcc12012-09-10 13:51:52 -07003315 MUSIC_ACTIVE_POLL_PERIOD_MS);
Eric Laurent42b041e2013-03-29 11:36:03 -07003316 int index = mStreamStates[AudioSystem.STREAM_MUSIC].getIndex(device);
Jean-Michel Trivi58850372018-09-14 16:01:28 -07003317 if (AudioSystem.isStreamActive(AudioSystem.STREAM_MUSIC, 0)
3318 && (index > safeMediaVolumeIndex(device))) {
Eric Laurentc34dcc12012-09-10 13:51:52 -07003319 // Approximate cumulative active music time
3320 mMusicActiveMs += MUSIC_ACTIVE_POLL_PERIOD_MS;
3321 if (mMusicActiveMs > UNSAFE_VOLUME_MUSIC_ACTIVE_MS_MAX) {
John Spurlock90874332015-03-10 16:00:54 -04003322 setSafeMediaVolumeEnabled(true, caller);
Eric Laurentc34dcc12012-09-10 13:51:52 -07003323 mMusicActiveMs = 0;
Eric Laurentc34dcc12012-09-10 13:51:52 -07003324 }
John Spurlockaa5ee4d2014-07-25 13:05:12 -04003325 saveMusicActiveMs();
Eric Laurentc34dcc12012-09-10 13:51:52 -07003326 }
3327 }
3328 }
3329 }
3330 }
3331
John Spurlockaa5ee4d2014-07-25 13:05:12 -04003332 private void saveMusicActiveMs() {
3333 mAudioHandler.obtainMessage(MSG_PERSIST_MUSIC_ACTIVE_MS, mMusicActiveMs, 0).sendToTarget();
3334 }
3335
Jean-Michel Trivi58850372018-09-14 16:01:28 -07003336 private int getSafeUsbMediaVolumeIndex() {
Eric Laurenteab40d12017-06-09 12:45:21 -07003337 // determine UI volume index corresponding to the wanted safe gain in dBFS
3338 int min = MIN_STREAM_VOLUME[AudioSystem.STREAM_MUSIC];
3339 int max = MAX_STREAM_VOLUME[AudioSystem.STREAM_MUSIC];
3340
John Muir8b8bddd2018-02-16 14:29:14 -08003341 mSafeUsbMediaVolumeDbfs = mContext.getResources().getInteger(
3342 com.android.internal.R.integer.config_safe_media_volume_usb_mB) / 100.0f;
3343
Jean-Michel Trivi58850372018-09-14 16:01:28 -07003344 while (Math.abs(max - min) > 1) {
Eric Laurenteab40d12017-06-09 12:45:21 -07003345 int index = (max + min) / 2;
3346 float gainDB = AudioSystem.getStreamVolumeDB(
3347 AudioSystem.STREAM_MUSIC, index, AudioSystem.DEVICE_OUT_USB_HEADSET);
Eric Laurentb378a13a2017-07-11 14:08:11 -07003348 if (Float.isNaN(gainDB)) {
Eric Laurenteab40d12017-06-09 12:45:21 -07003349 //keep last min in case of read error
3350 break;
John Muir8b8bddd2018-02-16 14:29:14 -08003351 } else if (gainDB == mSafeUsbMediaVolumeDbfs) {
Eric Laurenteab40d12017-06-09 12:45:21 -07003352 min = index;
3353 break;
John Muir8b8bddd2018-02-16 14:29:14 -08003354 } else if (gainDB < mSafeUsbMediaVolumeDbfs) {
Eric Laurenteab40d12017-06-09 12:45:21 -07003355 min = index;
3356 } else {
3357 max = index;
3358 }
3359 }
3360 return min * 10;
3361 }
3362
John Spurlock90874332015-03-10 16:00:54 -04003363 private void onConfigureSafeVolume(boolean force, String caller) {
hyomin.ohd0446dc2018-10-18 13:58:27 +09003364 synchronized (mSafeMediaVolumeStateLock) {
Eric Laurentd640bd32012-09-28 18:01:48 -07003365 int mcc = mContext.getResources().getConfiguration().mcc;
3366 if ((mMcc != mcc) || ((mMcc == 0) && force)) {
3367 mSafeMediaVolumeIndex = mContext.getResources().getInteger(
3368 com.android.internal.R.integer.config_safe_media_volume_index) * 10;
Eric Laurenteab40d12017-06-09 12:45:21 -07003369
3370 mSafeUsbMediaVolumeIndex = getSafeUsbMediaVolumeIndex();
3371
John Spurlock35134602014-07-24 18:10:48 -04003372 boolean safeMediaVolumeEnabled =
3373 SystemProperties.getBoolean("audio.safemedia.force", false)
3374 || mContext.getResources().getBoolean(
3375 com.android.internal.R.bool.config_safe_media_volume_enabled);
Eric Laurent05274f32012-11-29 12:48:18 -08003376
Ricardo Garcia3a30a762015-06-23 15:54:45 -07003377 boolean safeMediaVolumeBypass =
3378 SystemProperties.getBoolean("audio.safemedia.bypass", false);
3379
Eric Laurent05274f32012-11-29 12:48:18 -08003380 // The persisted state is either "disabled" or "active": this is the state applied
3381 // next time we boot and cannot be "inactive"
3382 int persistedState;
Ricardo Garcia3a30a762015-06-23 15:54:45 -07003383 if (safeMediaVolumeEnabled && !safeMediaVolumeBypass) {
Eric Laurent05274f32012-11-29 12:48:18 -08003384 persistedState = SAFE_MEDIA_VOLUME_ACTIVE;
3385 // The state can already be "inactive" here if the user has forced it before
3386 // the 30 seconds timeout for forced configuration. In this case we don't reset
3387 // it to "active".
3388 if (mSafeMediaVolumeState != SAFE_MEDIA_VOLUME_INACTIVE) {
John Spurlockaa5ee4d2014-07-25 13:05:12 -04003389 if (mMusicActiveMs == 0) {
3390 mSafeMediaVolumeState = SAFE_MEDIA_VOLUME_ACTIVE;
John Spurlock90874332015-03-10 16:00:54 -04003391 enforceSafeMediaVolume(caller);
John Spurlockaa5ee4d2014-07-25 13:05:12 -04003392 } else {
3393 // We have existing playback time recorded, already confirmed.
3394 mSafeMediaVolumeState = SAFE_MEDIA_VOLUME_INACTIVE;
3395 }
Eric Laurent05274f32012-11-29 12:48:18 -08003396 }
Eric Laurentd640bd32012-09-28 18:01:48 -07003397 } else {
Eric Laurent05274f32012-11-29 12:48:18 -08003398 persistedState = SAFE_MEDIA_VOLUME_DISABLED;
Eric Laurentd640bd32012-09-28 18:01:48 -07003399 mSafeMediaVolumeState = SAFE_MEDIA_VOLUME_DISABLED;
3400 }
3401 mMcc = mcc;
Eric Laurent05274f32012-11-29 12:48:18 -08003402 sendMsg(mAudioHandler,
3403 MSG_PERSIST_SAFE_VOLUME_STATE,
3404 SENDMSG_QUEUE,
3405 persistedState,
3406 0,
3407 null,
3408 0);
Eric Laurentd640bd32012-09-28 18:01:48 -07003409 }
3410 }
3411 }
3412
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003413 ///////////////////////////////////////////////////////////////////////////
3414 // Internal methods
3415 ///////////////////////////////////////////////////////////////////////////
3416
3417 /**
3418 * Checks if the adjustment should change ringer mode instead of just
3419 * adjusting volume. If so, this will set the proper ringer mode and volume
3420 * indices on the stream states.
3421 */
Julia Reynoldsed783792016-04-08 15:27:35 -04003422 private int checkForRingerModeChange(int oldIndex, int direction, int step, boolean isMuted,
3423 String caller, int flags) {
John Spurlocka11b4af2014-06-01 11:52:23 -04003424 int result = FLAG_ADJUST_VOLUME;
Zak Cohen47798292017-11-30 12:34:20 -08003425 if (isPlatformTelevision() || mIsSingleVolume) {
Hank Freund21003f62015-12-08 09:05:46 -08003426 return result;
3427 }
3428
John Spurlock661f2cf2014-11-17 10:29:10 -05003429 int ringerMode = getRingerModeInternal();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003430
Eric Laurentbffc3d12012-05-07 17:43:49 -07003431 switch (ringerMode) {
3432 case RINGER_MODE_NORMAL:
3433 if (direction == AudioManager.ADJUST_LOWER) {
3434 if (mHasVibrator) {
Eric Laurent24482012012-05-10 09:41:17 -07003435 // "step" is the delta in internal index units corresponding to a
3436 // change of 1 in UI index units.
3437 // Because of rounding when rescaling from one stream index range to its alias
3438 // index range, we cannot simply test oldIndex == step:
3439 // (step <= oldIndex < 2 * step) is equivalent to: (old UI index == 1)
3440 if (step <= oldIndex && oldIndex < 2 * step) {
Eric Laurentbffc3d12012-05-07 17:43:49 -07003441 ringerMode = RINGER_MODE_VIBRATE;
John Spurlock07e72432015-03-13 11:46:52 -04003442 mLoweredFromNormalToVibrateTime = SystemClock.uptimeMillis();
Eric Laurentbffc3d12012-05-07 17:43:49 -07003443 }
3444 } else {
John Spurlockd9c75db2015-04-28 11:19:13 -04003445 if (oldIndex == step && mVolumePolicy.volumeDownToEnterSilent) {
Eric Laurentbffc3d12012-05-07 17:43:49 -07003446 ringerMode = RINGER_MODE_SILENT;
3447 }
Eric Laurent3d4c06f2011-08-15 19:58:28 -07003448 }
Muyuan Li1ed6df62016-06-18 11:16:52 -07003449 } else if (mIsSingleVolume && (direction == AudioManager.ADJUST_TOGGLE_MUTE
John Spurlocka48d7792015-03-03 17:35:57 -05003450 || direction == AudioManager.ADJUST_MUTE)) {
RoboErik5452e252015-02-06 15:33:53 -08003451 if (mHasVibrator) {
3452 ringerMode = RINGER_MODE_VIBRATE;
3453 } else {
3454 ringerMode = RINGER_MODE_SILENT;
3455 }
3456 // Setting the ringer mode will toggle mute
3457 result &= ~FLAG_ADJUST_VOLUME;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003458 }
Eric Laurentbffc3d12012-05-07 17:43:49 -07003459 break;
3460 case RINGER_MODE_VIBRATE:
3461 if (!mHasVibrator) {
3462 Log.e(TAG, "checkForRingerModeChange() current ringer mode is vibrate" +
3463 "but no vibrator is present");
3464 break;
3465 }
Amith Yamasanic696a532011-10-28 17:02:37 -07003466 if ((direction == AudioManager.ADJUST_LOWER)) {
RoboErik5452e252015-02-06 15:33:53 -08003467 // This is the case we were muted with the volume turned up
Muyuan Li1ed6df62016-06-18 11:16:52 -07003468 if (mIsSingleVolume && oldIndex >= 2 * step && isMuted) {
RoboErik5452e252015-02-06 15:33:53 -08003469 ringerMode = RINGER_MODE_NORMAL;
3470 } else if (mPrevVolDirection != AudioManager.ADJUST_LOWER) {
John Spurlocka48d7792015-03-03 17:35:57 -05003471 if (mVolumePolicy.volumeDownToEnterSilent) {
John Spurlock07e72432015-03-13 11:46:52 -04003472 final long diff = SystemClock.uptimeMillis()
3473 - mLoweredFromNormalToVibrateTime;
John Spurlockd9c75db2015-04-28 11:19:13 -04003474 if (diff > mVolumePolicy.vibrateToSilentDebounce
3475 && mRingerModeDelegate.canVolumeDownEnterSilent()) {
John Spurlock07e72432015-03-13 11:46:52 -04003476 ringerMode = RINGER_MODE_SILENT;
3477 }
John Spurlock795a5142014-12-08 14:09:35 -05003478 } else {
3479 result |= AudioManager.FLAG_SHOW_VIBRATE_HINT;
3480 }
Amith Yamasanic696a532011-10-28 17:02:37 -07003481 }
RoboErik5452e252015-02-06 15:33:53 -08003482 } else if (direction == AudioManager.ADJUST_RAISE
3483 || direction == AudioManager.ADJUST_TOGGLE_MUTE
3484 || direction == AudioManager.ADJUST_UNMUTE) {
Eric Laurentbffc3d12012-05-07 17:43:49 -07003485 ringerMode = RINGER_MODE_NORMAL;
Amith Yamasanic696a532011-10-28 17:02:37 -07003486 }
John Spurlocka11b4af2014-06-01 11:52:23 -04003487 result &= ~FLAG_ADJUST_VOLUME;
Eric Laurentbffc3d12012-05-07 17:43:49 -07003488 break;
3489 case RINGER_MODE_SILENT:
Muyuan Li1ed6df62016-06-18 11:16:52 -07003490 if (mIsSingleVolume && direction == AudioManager.ADJUST_LOWER && oldIndex >= 2 * step && isMuted) {
RoboErik5452e252015-02-06 15:33:53 -08003491 // This is the case we were muted with the volume turned up
3492 ringerMode = RINGER_MODE_NORMAL;
3493 } else if (direction == AudioManager.ADJUST_RAISE
3494 || direction == AudioManager.ADJUST_TOGGLE_MUTE
3495 || direction == AudioManager.ADJUST_UNMUTE) {
John Spurlocka48d7792015-03-03 17:35:57 -05003496 if (!mVolumePolicy.volumeUpToExitSilent) {
John Spurlocka11b4af2014-06-01 11:52:23 -04003497 result |= AudioManager.FLAG_SHOW_SILENT_HINT;
Eric Laurentbffc3d12012-05-07 17:43:49 -07003498 } else {
RoboErik5452e252015-02-06 15:33:53 -08003499 if (mHasVibrator && direction == AudioManager.ADJUST_RAISE) {
John Spurlocka11b4af2014-06-01 11:52:23 -04003500 ringerMode = RINGER_MODE_VIBRATE;
3501 } else {
RoboErik5452e252015-02-06 15:33:53 -08003502 // If we don't have a vibrator or they were toggling mute
3503 // go straight back to normal.
John Spurlocka11b4af2014-06-01 11:52:23 -04003504 ringerMode = RINGER_MODE_NORMAL;
3505 }
Eric Laurentbffc3d12012-05-07 17:43:49 -07003506 }
Daniel Sandler6329bf72010-02-26 15:17:44 -05003507 }
John Spurlocka11b4af2014-06-01 11:52:23 -04003508 result &= ~FLAG_ADJUST_VOLUME;
Eric Laurentbffc3d12012-05-07 17:43:49 -07003509 break;
3510 default:
3511 Log.e(TAG, "checkForRingerModeChange() wrong ringer mode: "+ringerMode);
3512 break;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003513 }
3514
Julia Reynoldsed783792016-04-08 15:27:35 -04003515 if (isAndroidNPlus(caller) && wouldToggleZenMode(ringerMode)
3516 && !mNm.isNotificationPolicyAccessGrantedForPackage(caller)
3517 && (flags & AudioManager.FLAG_FROM_KEY) == 0) {
3518 throw new SecurityException("Not allowed to change Do Not Disturb state");
3519 }
3520
John Spurlock661f2cf2014-11-17 10:29:10 -05003521 setRingerMode(ringerMode, TAG + ".checkForRingerModeChange", false /*external*/);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003522
Eric Laurent25101b02011-02-02 09:33:30 -08003523 mPrevVolDirection = direction;
3524
John Spurlocka11b4af2014-06-01 11:52:23 -04003525 return result;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003526 }
3527
John Spurlock3346a802014-05-20 16:25:37 -04003528 @Override
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003529 public boolean isStreamAffectedByRingerMode(int streamType) {
Eric Laurent9bcf4012009-06-12 06:09:28 -07003530 return (mRingerModeAffectedStreams & (1 << streamType)) != 0;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003531 }
3532
Beverlyd6964762018-02-16 14:07:03 -05003533 private boolean shouldZenMuteStream(int streamType) {
3534 if (mNm.getZenMode() != Settings.Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS) {
3535 return false;
3536 }
3537
Beverlyff2df9b2018-10-10 16:54:10 -04003538 NotificationManager.Policy zenPolicy = mNm.getConsolidatedNotificationPolicy();
Beverlyd6964762018-02-16 14:07:03 -05003539 final boolean muteAlarms = (zenPolicy.priorityCategories
3540 & NotificationManager.Policy.PRIORITY_CATEGORY_ALARMS) == 0;
3541 final boolean muteMedia = (zenPolicy.priorityCategories
3542 & NotificationManager.Policy.PRIORITY_CATEGORY_MEDIA) == 0;
3543 final boolean muteSystem = (zenPolicy.priorityCategories
3544 & NotificationManager.Policy.PRIORITY_CATEGORY_SYSTEM) == 0;
3545 final boolean muteNotificationAndRing = ZenModeConfig
Beverlyff2df9b2018-10-10 16:54:10 -04003546 .areAllPriorityOnlyNotificationZenSoundsMuted(
3547 mNm.getConsolidatedNotificationPolicy());
Beverlyd6964762018-02-16 14:07:03 -05003548 return muteAlarms && isAlarm(streamType)
3549 || muteMedia && isMedia(streamType)
3550 || muteSystem && isSystem(streamType)
3551 || muteNotificationAndRing && isNotificationOrRinger(streamType);
3552 }
3553
3554 private boolean isStreamMutedByRingerOrZenMode(int streamType) {
3555 return (mRingerAndZenModeMutedStreams & (1 << streamType)) != 0;
3556 }
3557
3558 /**
3559 * DND total silence: media and alarms streams are tied to the muted ringer
3560 * {@link ZenModeHelper.RingerModeDelegate#getRingerModeAffectedStreams(int)}
3561 * DND alarms only: notification, ringer + system muted (by default tied to muted ringer mode)
3562 * DND priority only: alarms, media, system streams can be muted separate from ringer based on
3563 * zenPolicy (this method determines which streams)
3564 * @return true if changed, else false
3565 */
3566 private boolean updateZenModeAffectedStreams() {
3567 int zenModeAffectedStreams = 0;
3568 if (mSystemReady && mNm.getZenMode() == Settings.Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS) {
Beverlyff2df9b2018-10-10 16:54:10 -04003569 NotificationManager.Policy zenPolicy = mNm.getConsolidatedNotificationPolicy();
Beverlyd6964762018-02-16 14:07:03 -05003570 if ((zenPolicy.priorityCategories
3571 & NotificationManager.Policy.PRIORITY_CATEGORY_ALARMS) == 0) {
3572 zenModeAffectedStreams |= 1 << AudioManager.STREAM_ALARM;
3573 }
3574
3575 if ((zenPolicy.priorityCategories
3576 & NotificationManager.Policy.PRIORITY_CATEGORY_MEDIA) == 0) {
3577 zenModeAffectedStreams |= 1 << AudioManager.STREAM_MUSIC;
3578 }
3579
3580 if ((zenPolicy.priorityCategories
3581 & NotificationManager.Policy.PRIORITY_CATEGORY_SYSTEM) == 0) {
3582 zenModeAffectedStreams |= 1 << AudioManager.STREAM_SYSTEM;
3583 }
3584 }
3585
3586 if (mZenModeAffectedStreams != zenModeAffectedStreams) {
3587 mZenModeAffectedStreams = zenModeAffectedStreams;
3588 return true;
3589 }
3590
3591 return false;
Eric Laurent5b4e6542010-03-19 20:02:21 -07003592 }
3593
Jean-Michel Trivi8719a1d2017-11-06 11:52:51 -08003594 @GuardedBy("mSettingsLock")
Beverlyd6964762018-02-16 14:07:03 -05003595 private boolean updateRingerAndZenModeAffectedStreams() {
3596 boolean updatedZenModeAffectedStreams = updateZenModeAffectedStreams();
John Spurlock50ced3f2015-05-11 16:00:09 -04003597 int ringerModeAffectedStreams = Settings.System.getIntForUser(mContentResolver,
Eric Laurent24e0d9b2013-10-03 18:15:07 -07003598 Settings.System.MODE_RINGER_STREAMS_AFFECTED,
3599 ((1 << AudioSystem.STREAM_RING)|(1 << AudioSystem.STREAM_NOTIFICATION)|
3600 (1 << AudioSystem.STREAM_SYSTEM)|(1 << AudioSystem.STREAM_SYSTEM_ENFORCED)),
3601 UserHandle.USER_CURRENT);
3602
Muyuan Li1ed6df62016-06-18 11:16:52 -07003603 if (mIsSingleVolume) {
John Spurlock50ced3f2015-05-11 16:00:09 -04003604 ringerModeAffectedStreams = 0;
3605 } else if (mRingerModeDelegate != null) {
3606 ringerModeAffectedStreams = mRingerModeDelegate
3607 .getRingerModeAffectedStreams(ringerModeAffectedStreams);
Eric Laurent24e0d9b2013-10-03 18:15:07 -07003608 }
Jean-Michel Trivi8719a1d2017-11-06 11:52:51 -08003609 if (mCameraSoundForced) {
3610 ringerModeAffectedStreams &= ~(1 << AudioSystem.STREAM_SYSTEM_ENFORCED);
3611 } else {
3612 ringerModeAffectedStreams |= (1 << AudioSystem.STREAM_SYSTEM_ENFORCED);
Eric Laurent24e0d9b2013-10-03 18:15:07 -07003613 }
3614 if (mStreamVolumeAlias[AudioSystem.STREAM_DTMF] == AudioSystem.STREAM_RING) {
3615 ringerModeAffectedStreams |= (1 << AudioSystem.STREAM_DTMF);
3616 } else {
3617 ringerModeAffectedStreams &= ~(1 << AudioSystem.STREAM_DTMF);
3618 }
3619
3620 if (ringerModeAffectedStreams != mRingerModeAffectedStreams) {
3621 Settings.System.putIntForUser(mContentResolver,
3622 Settings.System.MODE_RINGER_STREAMS_AFFECTED,
3623 ringerModeAffectedStreams,
3624 UserHandle.USER_CURRENT);
3625 mRingerModeAffectedStreams = ringerModeAffectedStreams;
3626 return true;
3627 }
Beverlyd6964762018-02-16 14:07:03 -05003628 return updatedZenModeAffectedStreams;
Eric Laurent24e0d9b2013-10-03 18:15:07 -07003629 }
3630
John Spurlocka9dfbe8b2015-02-17 11:01:51 -05003631 @Override
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003632 public boolean isStreamAffectedByMute(int streamType) {
3633 return (mMuteAffectedStreams & (1 << streamType)) != 0;
3634 }
3635
3636 private void ensureValidDirection(int direction) {
RoboErik4197cb62015-01-21 15:45:32 -08003637 switch (direction) {
3638 case AudioManager.ADJUST_LOWER:
3639 case AudioManager.ADJUST_RAISE:
3640 case AudioManager.ADJUST_SAME:
3641 case AudioManager.ADJUST_MUTE:
3642 case AudioManager.ADJUST_UNMUTE:
3643 case AudioManager.ADJUST_TOGGLE_MUTE:
3644 break;
3645 default:
3646 throw new IllegalArgumentException("Bad direction " + direction);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003647 }
3648 }
3649
3650 private void ensureValidStreamType(int streamType) {
3651 if (streamType < 0 || streamType >= mStreamStates.length) {
3652 throw new IllegalArgumentException("Bad stream type " + streamType);
3653 }
3654 }
3655
RoboErik4197cb62015-01-21 15:45:32 -08003656 private boolean isMuteAdjust(int adjust) {
3657 return adjust == AudioManager.ADJUST_MUTE || adjust == AudioManager.ADJUST_UNMUTE
3658 || adjust == AudioManager.ADJUST_TOGGLE_MUTE;
3659 }
3660
Jean-Michel Trivi58850372018-09-14 16:01:28 -07003661 /*package*/ boolean isInCommunication() {
Nancy Chen0eb1e402014-08-21 22:52:29 -07003662 boolean IsInCall = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003663
Tyler Gunnef9f6f92014-09-12 22:16:17 -07003664 TelecomManager telecomManager =
3665 (TelecomManager) mContext.getSystemService(Context.TELECOM_SERVICE);
Eric Laurent38edfda2014-12-18 17:38:04 -08003666
3667 final long ident = Binder.clearCallingIdentity();
Tyler Gunnef9f6f92014-09-12 22:16:17 -07003668 IsInCall = telecomManager.isInCall();
Eric Laurent38edfda2014-12-18 17:38:04 -08003669 Binder.restoreCallingIdentity(ident);
Santos Cordon9eb45932014-06-27 12:28:43 -07003670
Eric Laurentda1af762017-12-15 16:54:35 -08003671 return (IsInCall || getMode() == AudioManager.MODE_IN_COMMUNICATION ||
3672 getMode() == AudioManager.MODE_IN_CALL);
Eric Laurent6d517662012-04-23 18:42:39 -07003673 }
Eric Laurent25101b02011-02-02 09:33:30 -08003674
Jean-Michel Trivifca1e602013-10-10 18:12:59 -07003675 /**
3676 * For code clarity for getActiveStreamType(int)
Julia Reynoldsd9e96e22017-11-07 10:33:08 -05003677 * @param delay_ms max time since last stream activity to consider
3678 * @return true if stream is active in streams handled by AudioFlinger now or
Jean-Michel Trivifca1e602013-10-10 18:12:59 -07003679 * in the last "delay_ms" ms.
3680 */
Julia Reynoldsd9e96e22017-11-07 10:33:08 -05003681 private boolean wasStreamActiveRecently(int stream, int delay_ms) {
3682 return AudioSystem.isStreamActive(stream, delay_ms)
3683 || AudioSystem.isStreamActiveRemotely(stream, delay_ms);
Jean-Michel Trivifca1e602013-10-10 18:12:59 -07003684 }
3685
Eric Laurent6d517662012-04-23 18:42:39 -07003686 private int getActiveStreamType(int suggestedStreamType) {
Muyuan Li1ed6df62016-06-18 11:16:52 -07003687 if (mIsSingleVolume
3688 && suggestedStreamType == AudioManager.USE_DEFAULT_STREAM_TYPE) {
3689 return AudioSystem.STREAM_MUSIC;
3690 }
3691
Eric Laurent212532b2014-07-21 15:43:18 -07003692 switch (mPlatformType) {
John Spurlock61560172015-02-06 19:46:04 -05003693 case AudioSystem.PLATFORM_VOICE:
Eric Laurent6d517662012-04-23 18:42:39 -07003694 if (isInCommunication()) {
Eric Laurent25101b02011-02-02 09:33:30 -08003695 if (AudioSystem.getForceUse(AudioSystem.FOR_COMMUNICATION)
3696 == AudioSystem.FORCE_BT_SCO) {
3697 // Log.v(TAG, "getActiveStreamType: Forcing STREAM_BLUETOOTH_SCO...");
3698 return AudioSystem.STREAM_BLUETOOTH_SCO;
3699 } else {
3700 // Log.v(TAG, "getActiveStreamType: Forcing STREAM_VOICE_CALL...");
3701 return AudioSystem.STREAM_VOICE_CALL;
3702 }
Eric Laurent25101b02011-02-02 09:33:30 -08003703 } else if (suggestedStreamType == AudioManager.USE_DEFAULT_STREAM_TYPE) {
Julia Reynoldsd9e96e22017-11-07 10:33:08 -05003704 if (wasStreamActiveRecently(AudioSystem.STREAM_RING, sStreamOverrideDelayMs)) {
Jean-Michel Trivi3114ce32012-06-11 15:03:52 -07003705 if (DEBUG_VOL)
Julia Reynoldsd9e96e22017-11-07 10:33:08 -05003706 Log.v(TAG, "getActiveStreamType: Forcing STREAM_RING stream active");
3707 return AudioSystem.STREAM_RING;
3708 } else if (wasStreamActiveRecently(
3709 AudioSystem.STREAM_NOTIFICATION, sStreamOverrideDelayMs)) {
3710 if (DEBUG_VOL)
3711 Log.v(TAG, "getActiveStreamType: Forcing STREAM_NOTIFICATION stream active");
3712 return AudioSystem.STREAM_NOTIFICATION;
3713 } else {
Julia Reynoldseb0ce472018-05-04 15:34:55 -04003714 if (DEBUG_VOL) {
3715 Log.v(TAG, "getActiveStreamType: Forcing DEFAULT_VOL_STREAM_NO_PLAYBACK("
3716 + DEFAULT_VOL_STREAM_NO_PLAYBACK + ") b/c default");
3717 }
3718 return DEFAULT_VOL_STREAM_NO_PLAYBACK;
Jean-Michel Trivi3114ce32012-06-11 15:03:52 -07003719 }
Julia Reynoldsd9e96e22017-11-07 10:33:08 -05003720 } else if (
3721 wasStreamActiveRecently(AudioSystem.STREAM_NOTIFICATION, sStreamOverrideDelayMs)) {
Jean-Michel Trivi3114ce32012-06-11 15:03:52 -07003722 if (DEBUG_VOL)
Julia Reynoldsd9e96e22017-11-07 10:33:08 -05003723 Log.v(TAG, "getActiveStreamType: Forcing STREAM_NOTIFICATION stream active");
3724 return AudioSystem.STREAM_NOTIFICATION;
3725 } else if (wasStreamActiveRecently(AudioSystem.STREAM_RING, sStreamOverrideDelayMs)) {
3726 if (DEBUG_VOL)
3727 Log.v(TAG, "getActiveStreamType: Forcing STREAM_RING stream active");
3728 return AudioSystem.STREAM_RING;
Eric Laurent25101b02011-02-02 09:33:30 -08003729 }
Eric Laurent212532b2014-07-21 15:43:18 -07003730 default:
Eric Laurent6d517662012-04-23 18:42:39 -07003731 if (isInCommunication()) {
Eric Laurent25101b02011-02-02 09:33:30 -08003732 if (AudioSystem.getForceUse(AudioSystem.FOR_COMMUNICATION)
3733 == AudioSystem.FORCE_BT_SCO) {
Jean-Michel Trivi3114ce32012-06-11 15:03:52 -07003734 if (DEBUG_VOL) Log.v(TAG, "getActiveStreamType: Forcing STREAM_BLUETOOTH_SCO");
Eric Laurent25101b02011-02-02 09:33:30 -08003735 return AudioSystem.STREAM_BLUETOOTH_SCO;
3736 } else {
Jean-Michel Trivi3114ce32012-06-11 15:03:52 -07003737 if (DEBUG_VOL) Log.v(TAG, "getActiveStreamType: Forcing STREAM_VOICE_CALL");
Eric Laurent25101b02011-02-02 09:33:30 -08003738 return AudioSystem.STREAM_VOICE_CALL;
3739 }
Julia Reynoldsd9e96e22017-11-07 10:33:08 -05003740 } else if (AudioSystem.isStreamActive(
3741 AudioSystem.STREAM_NOTIFICATION, sStreamOverrideDelayMs)) {
Jean-Michel Trivi3114ce32012-06-11 15:03:52 -07003742 if (DEBUG_VOL) Log.v(TAG, "getActiveStreamType: Forcing STREAM_NOTIFICATION");
Eric Laurent25101b02011-02-02 09:33:30 -08003743 return AudioSystem.STREAM_NOTIFICATION;
Julia Reynoldsd9e96e22017-11-07 10:33:08 -05003744 } else if (AudioSystem.isStreamActive(
3745 AudioSystem.STREAM_RING, sStreamOverrideDelayMs)) {
3746 if (DEBUG_VOL) Log.v(TAG, "getActiveStreamType: Forcing STREAM_RING");
3747 return AudioSystem.STREAM_RING;
Jean-Michel Trivi3114ce32012-06-11 15:03:52 -07003748 } else if (suggestedStreamType == AudioManager.USE_DEFAULT_STREAM_TYPE) {
Julia Reynoldsd9e96e22017-11-07 10:33:08 -05003749 if (AudioSystem.isStreamActive(
3750 AudioSystem.STREAM_NOTIFICATION, sStreamOverrideDelayMs)) {
3751 if (DEBUG_VOL) Log.v(TAG, "getActiveStreamType: Forcing STREAM_NOTIFICATION");
John Spurlockeb1d88d2014-07-19 14:49:19 -04003752 return AudioSystem.STREAM_NOTIFICATION;
Julia Reynoldsd9e96e22017-11-07 10:33:08 -05003753 } else if (AudioSystem.isStreamActive(
3754 AudioSystem.STREAM_RING, sStreamOverrideDelayMs)) {
3755 if (DEBUG_VOL) Log.v(TAG, "getActiveStreamType: Forcing STREAM_RING");
3756 return AudioSystem.STREAM_RING;
3757 } else {
Julia Reynoldseb0ce472018-05-04 15:34:55 -04003758 if (DEBUG_VOL) {
3759 Log.v(TAG, "getActiveStreamType: Forcing DEFAULT_VOL_STREAM_NO_PLAYBACK("
3760 + DEFAULT_VOL_STREAM_NO_PLAYBACK + ") b/c default");
3761 }
3762 return DEFAULT_VOL_STREAM_NO_PLAYBACK;
Jean-Michel Trivi3114ce32012-06-11 15:03:52 -07003763 }
Joe Onoratoc7fcba42011-01-05 16:53:11 -08003764 }
Eric Laurent212532b2014-07-21 15:43:18 -07003765 break;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003766 }
Eric Laurent212532b2014-07-21 15:43:18 -07003767 if (DEBUG_VOL) Log.v(TAG, "getActiveStreamType: Returning suggested type "
3768 + suggestedStreamType);
3769 return suggestedStreamType;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003770 }
3771
John Spurlockbcc10872014-11-28 15:29:21 -05003772 private void broadcastRingerMode(String action, int ringerMode) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003773 // Send sticky broadcast
John Spurlockbcc10872014-11-28 15:29:21 -05003774 Intent broadcast = new Intent(action);
Glenn Kastenba195eb2011-12-13 09:30:40 -08003775 broadcast.putExtra(AudioManager.EXTRA_RINGER_MODE, ringerMode);
Dianne Hackborn1c633fc2009-12-08 19:45:14 -08003776 broadcast.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT
3777 | Intent.FLAG_RECEIVER_REPLACE_PENDING);
Dianne Hackborn5ac72a22012-08-29 18:32:08 -07003778 sendStickyBroadcastToAll(broadcast);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003779 }
3780
3781 private void broadcastVibrateSetting(int vibrateType) {
3782 // Send broadcast
Sudheer Shankafc46e9b2016-10-21 17:55:27 -07003783 if (mActivityManagerInternal.isSystemReady()) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003784 Intent broadcast = new Intent(AudioManager.VIBRATE_SETTING_CHANGED_ACTION);
3785 broadcast.putExtra(AudioManager.EXTRA_VIBRATE_TYPE, vibrateType);
3786 broadcast.putExtra(AudioManager.EXTRA_VIBRATE_SETTING, getVibrateSetting(vibrateType));
Dianne Hackborn5ac72a22012-08-29 18:32:08 -07003787 sendBroadcastToAll(broadcast);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003788 }
3789 }
3790
3791 // Message helper methods
Jean-Michel Trivi2d8dab52012-05-30 18:13:59 -07003792 /**
3793 * Queue a message on the given handler's message queue, after acquiring the service wake lock.
3794 * Note that the wake lock needs to be released after the message has been handled.
3795 */
3796 private void queueMsgUnderWakeLock(Handler handler, int msg,
3797 int arg1, int arg2, Object obj, int delay) {
Eric Laurenta4dfbdc52013-10-01 11:53:51 -07003798 final long ident = Binder.clearCallingIdentity();
3799 // Always acquire the wake lock as AudioService because it is released by the
3800 // message handler.
Jean-Michel Trivifa9a6982013-06-27 16:22:58 -07003801 mAudioEventWakeLock.acquire();
Eric Laurenta4dfbdc52013-10-01 11:53:51 -07003802 Binder.restoreCallingIdentity(ident);
Jean-Michel Trivi2d8dab52012-05-30 18:13:59 -07003803 sendMsg(handler, msg, SENDMSG_QUEUE, arg1, arg2, obj, delay);
3804 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003805
Eric Laurentafbb0472011-12-15 09:04:23 -08003806 private static void sendMsg(Handler handler, int msg,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003807 int existingMsgPolicy, int arg1, int arg2, Object obj, int delay) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003808
3809 if (existingMsgPolicy == SENDMSG_REPLACE) {
3810 handler.removeMessages(msg);
3811 } else if (existingMsgPolicy == SENDMSG_NOOP && handler.hasMessages(msg)) {
3812 return;
3813 }
Eric Laurent3c4636c2018-06-13 19:36:42 -07003814
Jean-Michel Trivi58850372018-09-14 16:01:28 -07003815 final long time = SystemClock.uptimeMillis() + delay;
3816 handler.sendMessageAtTime(handler.obtainMessage(msg, arg1, arg2, obj), time);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003817 }
3818
3819 boolean checkAudioSettingsPermission(String method) {
Jean-Michel Triviccd654e2014-09-03 17:48:47 -07003820 if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.MODIFY_AUDIO_SETTINGS)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003821 == PackageManager.PERMISSION_GRANTED) {
3822 return true;
3823 }
3824 String msg = "Audio Settings Permission Denial: " + method + " from pid="
3825 + Binder.getCallingPid()
3826 + ", uid=" + Binder.getCallingUid();
3827 Log.w(TAG, msg);
3828 return false;
3829 }
3830
Jean-Michel Trivi58850372018-09-14 16:01:28 -07003831 /*package*/ int getDeviceForStream(int stream) {
John Spurlock8a52c442015-03-26 14:23:58 -04003832 int device = getDevicesForStream(stream);
Eric Laurent9bc8358d2011-11-18 16:43:31 -08003833 if ((device & (device - 1)) != 0) {
3834 // Multiple device selection is either:
3835 // - speaker + one other device: give priority to speaker in this case.
3836 // - one A2DP device + another device: happens with duplicated output. In this case
3837 // retain the device on the A2DP output as the other must not correspond to an active
3838 // selection if not the speaker.
Jungshik Jangc9ff9682014-09-15 17:41:06 +09003839 // - HDMI-CEC system audio mode only output: give priority to available item in order.
Eric Laurent9bc8358d2011-11-18 16:43:31 -08003840 if ((device & AudioSystem.DEVICE_OUT_SPEAKER) != 0) {
3841 device = AudioSystem.DEVICE_OUT_SPEAKER;
Jungshik Jangc9ff9682014-09-15 17:41:06 +09003842 } else if ((device & AudioSystem.DEVICE_OUT_HDMI_ARC) != 0) {
3843 device = AudioSystem.DEVICE_OUT_HDMI_ARC;
3844 } else if ((device & AudioSystem.DEVICE_OUT_SPDIF) != 0) {
3845 device = AudioSystem.DEVICE_OUT_SPDIF;
3846 } else if ((device & AudioSystem.DEVICE_OUT_AUX_LINE) != 0) {
3847 device = AudioSystem.DEVICE_OUT_AUX_LINE;
Eric Laurent9bc8358d2011-11-18 16:43:31 -08003848 } else {
3849 device &= AudioSystem.DEVICE_OUT_ALL_A2DP;
3850 }
3851 }
3852 return device;
3853 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003854
John Spurlock8a52c442015-03-26 14:23:58 -04003855 private int getDevicesForStream(int stream) {
3856 return getDevicesForStream(stream, true /*checkOthers*/);
3857 }
3858
3859 private int getDevicesForStream(int stream, boolean checkOthers) {
3860 ensureValidStreamType(stream);
3861 synchronized (VolumeStreamState.class) {
3862 return mStreamStates[stream].observeDevicesForStream_syncVSS(checkOthers);
3863 }
3864 }
3865
3866 private void observeDevicesForStreams(int skipStream) {
3867 synchronized (VolumeStreamState.class) {
3868 for (int stream = 0; stream < mStreamStates.length; stream++) {
3869 if (stream != skipStream) {
3870 mStreamStates[stream].observeDevicesForStream_syncVSS(false /*checkOthers*/);
3871 }
3872 }
3873 }
3874 }
3875
Jean-Michel Trivi58850372018-09-14 16:01:28 -07003876
3877 /*package*/ void observeDevicesForAllStreams() {
3878 observeDevicesForStreams(-1);
Aniket Kumar Lata9fbc2052019-01-11 02:02:33 -08003879 }
3880
Jean-Michel Trivi58850372018-09-14 16:01:28 -07003881 /*package*/ static final int CONNECTION_STATE_DISCONNECTED = 0;
3882 /*package*/ static final int CONNECTION_STATE_CONNECTED = 1;
3883 /**
3884 * The states that can be used with AudioService.setWiredDeviceConnectionState()
3885 * Attention: those values differ from those in BluetoothProfile, follow annotations to
3886 * distinguish between @ConnectionState and @BtProfileConnectionState
Paul McLean10804eb2015-01-28 11:16:35 -08003887 */
Jean-Michel Trivi58850372018-09-14 16:01:28 -07003888 @IntDef({
3889 CONNECTION_STATE_DISCONNECTED,
3890 CONNECTION_STATE_CONNECTED,
3891 })
3892 @Retention(RetentionPolicy.SOURCE)
3893 public @interface ConnectionState {}
Paul McLean10804eb2015-01-28 11:16:35 -08003894
Jean-Michel Trivi58850372018-09-14 16:01:28 -07003895 /**
3896 * see AudioManager.setWiredDeviceConnectionState()
3897 */
3898 public void setWiredDeviceConnectionState(int type,
3899 @ConnectionState int state, String address, String name,
John Spurlock90874332015-03-10 16:00:54 -04003900 String caller) {
Jean-Michel Trivi58850372018-09-14 16:01:28 -07003901 if (state != CONNECTION_STATE_CONNECTED
3902 && state != CONNECTION_STATE_DISCONNECTED) {
3903 throw new IllegalArgumentException("Invalid state " + state);
Eric Laurentb1fbaac2012-05-29 09:24:28 -07003904 }
Jean-Michel Trivi58850372018-09-14 16:01:28 -07003905 mDeviceBroker.setWiredDeviceConnectionState(type, state, address, name, caller);
Eric Laurentb1fbaac2012-05-29 09:24:28 -07003906 }
3907
Jean-Michel Trivi58850372018-09-14 16:01:28 -07003908 /**
3909 * @hide
3910 * The states that can be used with AudioService.setBluetoothHearingAidDeviceConnectionState()
3911 * and AudioService.setBluetoothA2dpDeviceConnectionStateSuppressNoisyIntent()
3912 */
3913 @IntDef({
3914 BluetoothProfile.STATE_DISCONNECTED,
3915 BluetoothProfile.STATE_CONNECTED,
3916 })
3917 @Retention(RetentionPolicy.SOURCE)
3918 public @interface BtProfileConnectionState {}
3919
Jakub Pawlowskif9570f32018-02-21 17:15:12 -08003920 public int setBluetoothHearingAidDeviceConnectionState(
Jean-Michel Trivi58850372018-09-14 16:01:28 -07003921 @NonNull BluetoothDevice device, @BtProfileConnectionState int state,
3922 boolean suppressNoisyIntent, int musicDevice)
Jakub Pawlowskif9570f32018-02-21 17:15:12 -08003923 {
Jean-Michel Trivi58850372018-09-14 16:01:28 -07003924 if (device == null) {
3925 throw new IllegalArgumentException("Illegal null device");
Jakub Pawlowskif9570f32018-02-21 17:15:12 -08003926 }
Jean-Michel Trivi58850372018-09-14 16:01:28 -07003927 if (state != BluetoothProfile.STATE_CONNECTED
3928 && state != BluetoothProfile.STATE_DISCONNECTED) {
3929 throw new IllegalArgumentException("Illegal BluetoothProfile state for device "
3930 + " (dis)connection, got " + state);
3931 }
3932 return mDeviceBroker.setBluetoothHearingAidDeviceConnectionState(
3933 device, state, suppressNoisyIntent, musicDevice, "AudioService");
Jakub Pawlowski10c90612018-02-21 13:28:46 -08003934 }
3935
Jean-Michel Trivi58850372018-09-14 16:01:28 -07003936 /**
3937 * See AudioManager.setBluetoothA2dpDeviceConnectionStateSuppressNoisyIntent()
3938 */
3939 public int setBluetoothA2dpDeviceConnectionStateSuppressNoisyIntent(
3940 @NonNull BluetoothDevice device, @AudioService.BtProfileConnectionState int state,
3941 int profile, boolean suppressNoisyIntent, int a2dpVolume) {
3942 if (device == null) {
3943 throw new IllegalArgumentException("Illegal null device");
3944 }
3945 if (state != BluetoothProfile.STATE_CONNECTED
3946 && state != BluetoothProfile.STATE_DISCONNECTED) {
3947 throw new IllegalArgumentException("Illegal BluetoothProfile state for device "
3948 + " (dis)connection, got " + state);
3949 }
3950 return mDeviceBroker.setBluetoothA2dpDeviceConnectionStateSuppressNoisyIntent(device, state,
3951 profile, suppressNoisyIntent, a2dpVolume);
Pavlin Radoslavov82e06462018-01-19 18:20:04 -08003952 }
3953
Jean-Michel Trivi58850372018-09-14 16:01:28 -07003954 /**
3955 * See AudioManager.handleBluetoothA2dpDeviceConfigChange()
3956 * @param device
3957 */
Pavlin Radoslavov44a4ef02016-12-21 12:05:51 -08003958 public void handleBluetoothA2dpDeviceConfigChange(BluetoothDevice device)
3959 {
Jean-Michel Trivi58850372018-09-14 16:01:28 -07003960 if (device == null) {
3961 throw new IllegalArgumentException("Illegal null device");
Pavlin Radoslavov44a4ef02016-12-21 12:05:51 -08003962 }
Jean-Michel Trivi58850372018-09-14 16:01:28 -07003963 mDeviceBroker.postBluetoothA2dpDeviceConfigChange(device);
Pavlin Radoslavov44a4ef02016-12-21 12:05:51 -08003964 }
3965
Aniket Kumar Lataa8439e22019-01-11 03:59:00 -08003966 /**
3967 * @see AudioManager#handleBluetoothA2dpActiveDeviceChange(BluetoothDevice, int, int,
3968 * boolean, int)
3969 */
3970 public int handleBluetoothA2dpActiveDeviceChange(
3971 BluetoothDevice device, int state, int profile, boolean suppressNoisyIntent,
3972 int a2dpVolume) {
Jean-Michel Trivi58850372018-09-14 16:01:28 -07003973 if (device == null) {
3974 throw new IllegalArgumentException("Illegal null device");
3975 }
Aniket Kumar Lataa8439e22019-01-11 03:59:00 -08003976 if (profile != BluetoothProfile.A2DP && profile != BluetoothProfile.A2DP_SINK) {
3977 throw new IllegalArgumentException("invalid profile " + profile);
3978 }
Jean-Michel Trivi58850372018-09-14 16:01:28 -07003979 if (state != BluetoothProfile.STATE_CONNECTED
3980 && state != BluetoothProfile.STATE_DISCONNECTED) {
3981 throw new IllegalArgumentException("Invalid state " + state);
Aniket Kumar Lataa8439e22019-01-11 03:59:00 -08003982 }
Jean-Michel Trivi58850372018-09-14 16:01:28 -07003983 return mDeviceBroker.handleBluetoothA2dpActiveDeviceChange(device, state, profile,
3984 suppressNoisyIntent, a2dpVolume);
Aniket Kumar Lataa8439e22019-01-11 03:59:00 -08003985 }
3986
Jean-Michel Trivi1ab43f62017-04-27 15:37:34 -07003987 private static final int DEVICE_MEDIA_UNMUTED_ON_PLUG =
3988 AudioSystem.DEVICE_OUT_WIRED_HEADSET | AudioSystem.DEVICE_OUT_WIRED_HEADPHONE |
3989 AudioSystem.DEVICE_OUT_LINE |
3990 AudioSystem.DEVICE_OUT_ALL_A2DP |
3991 AudioSystem.DEVICE_OUT_ALL_USB |
3992 AudioSystem.DEVICE_OUT_HDMI;
3993
Jean-Michel Trivi58850372018-09-14 16:01:28 -07003994 /*package*/ void postAccessoryPlugMediaUnmute(int newDevice) {
3995 sendMsg(mAudioHandler, MSG_ACCESSORY_PLUG_MEDIA_UNMUTE, SENDMSG_QUEUE,
3996 newDevice, 0, null, 0);
3997 }
3998
Jean-Michel Trivi1ab43f62017-04-27 15:37:34 -07003999 private void onAccessoryPlugMediaUnmute(int newDevice) {
4000 if (DEBUG_VOL) {
4001 Log.i(TAG, String.format("onAccessoryPlugMediaUnmute newDevice=%d [%s]",
4002 newDevice, AudioSystem.getOutputDeviceName(newDevice)));
4003 }
Jean-Michel Trivi58850372018-09-14 16:01:28 -07004004
4005 if (mNm.getZenMode() != Settings.Global.ZEN_MODE_NO_INTERRUPTIONS
4006 && (newDevice & DEVICE_MEDIA_UNMUTED_ON_PLUG) != 0
4007 && mStreamStates[AudioSystem.STREAM_MUSIC].mIsMuted
4008 && mStreamStates[AudioSystem.STREAM_MUSIC].getIndex(newDevice) != 0
4009 && (newDevice & AudioSystem.getDevicesForStream(AudioSystem.STREAM_MUSIC)) != 0) {
4010 if (DEBUG_VOL) {
4011 Log.i(TAG, String.format(" onAccessoryPlugMediaUnmute unmuting device=%d [%s]",
4012 newDevice, AudioSystem.getOutputDeviceName(newDevice)));
Jean-Michel Trivi1ab43f62017-04-27 15:37:34 -07004013 }
Jean-Michel Trivi58850372018-09-14 16:01:28 -07004014 mStreamStates[AudioSystem.STREAM_MUSIC].mute(false);
Jean-Michel Trivi1ab43f62017-04-27 15:37:34 -07004015 }
4016 }
4017
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004018 ///////////////////////////////////////////////////////////////////////////
4019 // Inner classes
4020 ///////////////////////////////////////////////////////////////////////////
4021
Eric Laurent8fa4d6f2014-10-30 14:13:03 -07004022 // NOTE: Locking order for synchronized objects related to volume or ringer mode management:
4023 // 1 mScoclient OR mSafeMediaVolumeState
Jean-Michel Trivi58850372018-09-14 16:01:28 -07004024 // 2 mSetModeLock
Eric Laurent8fa4d6f2014-10-30 14:13:03 -07004025 // 3 mSettingsLock
4026 // 4 VolumeStreamState.class
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004027 public class VolumeStreamState {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004028 private final int mStreamType;
Jean-Michel Trivie05eef82018-03-08 18:56:34 -08004029 private int mIndexMin;
4030 private int mIndexMax;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004031
RoboErik4197cb62015-01-21 15:45:32 -08004032 private boolean mIsMuted;
Jean-Michel Trivi11a74a72009-10-27 17:39:30 -07004033 private String mVolumeIndexSettingName;
John Spurlock8a52c442015-03-26 14:23:58 -04004034 private int mObservedDevices;
John Spurlockb6e19e32015-03-10 21:33:44 -04004035
John Spurlock2bb02ec2015-03-02 13:13:06 -05004036 private final SparseIntArray mIndexMap = new SparseIntArray(8);
John Spurlockf63860c2015-02-19 09:46:27 -05004037 private final Intent mVolumeChanged;
John Spurlock8a52c442015-03-26 14:23:58 -04004038 private final Intent mStreamDevicesChanged;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004039
Eric Laurenta553c252009-07-17 12:17:14 -07004040 private VolumeStreamState(String settingName, int streamType) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004041
Eric Laurent9bc8358d2011-11-18 16:43:31 -08004042 mVolumeIndexSettingName = settingName;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004043
4044 mStreamType = streamType;
John Spurlockb6e19e32015-03-10 21:33:44 -04004045 mIndexMin = MIN_STREAM_VOLUME[streamType] * 10;
4046 mIndexMax = MAX_STREAM_VOLUME[streamType] * 10;
4047 AudioSystem.initStreamVolume(streamType, mIndexMin / 10, mIndexMax / 10);
Eric Laurent9bc8358d2011-11-18 16:43:31 -08004048
Eric Laurent33902db2012-10-07 16:15:07 -07004049 readSettings();
John Spurlockf63860c2015-02-19 09:46:27 -05004050 mVolumeChanged = new Intent(AudioManager.VOLUME_CHANGED_ACTION);
4051 mVolumeChanged.putExtra(AudioManager.EXTRA_VOLUME_STREAM_TYPE, mStreamType);
John Spurlock8a52c442015-03-26 14:23:58 -04004052 mStreamDevicesChanged = new Intent(AudioManager.STREAM_DEVICES_CHANGED_ACTION);
4053 mStreamDevicesChanged.putExtra(AudioManager.EXTRA_VOLUME_STREAM_TYPE, mStreamType);
4054 }
4055
4056 public int observeDevicesForStream_syncVSS(boolean checkOthers) {
4057 final int devices = AudioSystem.getDevicesForStream(mStreamType);
4058 if (devices == mObservedDevices) {
4059 return devices;
4060 }
4061 final int prevDevices = mObservedDevices;
4062 mObservedDevices = devices;
4063 if (checkOthers) {
4064 // one stream's devices have changed, check the others
4065 observeDevicesForStreams(mStreamType);
4066 }
4067 // log base stream changes to the event log
4068 if (mStreamVolumeAlias[mStreamType] == mStreamType) {
4069 EventLogTags.writeStreamDevicesChanged(mStreamType, prevDevices, devices);
4070 }
4071 sendBroadcastToAll(mStreamDevicesChanged
4072 .putExtra(AudioManager.EXTRA_PREV_VOLUME_STREAM_DEVICES, prevDevices)
4073 .putExtra(AudioManager.EXTRA_VOLUME_STREAM_DEVICES, devices));
4074 return devices;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004075 }
4076
Jean-Michel Trivia53b7052017-04-12 18:27:01 -07004077 public @Nullable String getSettingNameForDevice(int device) {
4078 if (!hasValidSettingsName()) {
4079 return null;
Eric Laurent9bc8358d2011-11-18 16:43:31 -08004080 }
Jean-Michel Trivia53b7052017-04-12 18:27:01 -07004081 final String suffix = AudioSystem.getOutputDeviceName(device);
4082 if (suffix.isEmpty()) {
4083 return mVolumeIndexSettingName;
4084 }
4085 return mVolumeIndexSettingName + "_" + suffix;
4086 }
4087
4088 private boolean hasValidSettingsName() {
4089 return (mVolumeIndexSettingName != null && !mVolumeIndexSettingName.isEmpty());
Jean-Michel Trivi11a74a72009-10-27 17:39:30 -07004090 }
4091
Eric Laurentfdbee862014-05-12 15:26:12 -07004092 public void readSettings() {
Jean-Michel Trivi8719a1d2017-11-06 11:52:51 -08004093 synchronized (mSettingsLock) {
4094 synchronized (VolumeStreamState.class) {
4095 // force maximum volume on all streams if fixed volume property is set
4096 if (mUseFixedVolume) {
4097 mIndexMap.put(AudioSystem.DEVICE_OUT_DEFAULT, mIndexMax);
4098 return;
4099 }
4100 // do not read system stream volume from settings: this stream is always aliased
4101 // to another stream type and its volume is never persisted. Values in settings can
4102 // only be stale values
4103 if ((mStreamType == AudioSystem.STREAM_SYSTEM) ||
4104 (mStreamType == AudioSystem.STREAM_SYSTEM_ENFORCED)) {
4105 int index = 10 * AudioSystem.DEFAULT_STREAM_VOLUME[mStreamType];
Eric Laurentfdbee862014-05-12 15:26:12 -07004106 if (mCameraSoundForced) {
4107 index = mIndexMax;
4108 }
Jean-Michel Trivi8719a1d2017-11-06 11:52:51 -08004109 mIndexMap.put(AudioSystem.DEVICE_OUT_DEFAULT, index);
4110 return;
Eric Laurentdd45d012012-10-08 09:04:34 -07004111 }
Eric Laurent9bc8358d2011-11-18 16:43:31 -08004112 }
Jean-Michel Trivi8719a1d2017-11-06 11:52:51 -08004113 }
4114 synchronized (VolumeStreamState.class) {
Eric Laurentfdbee862014-05-12 15:26:12 -07004115 int remainingDevices = AudioSystem.DEVICE_OUT_ALL;
4116
4117 for (int i = 0; remainingDevices != 0; i++) {
4118 int device = (1 << i);
4119 if ((device & remainingDevices) == 0) {
4120 continue;
4121 }
4122 remainingDevices &= ~device;
4123
4124 // retrieve current volume for device
Eric Laurentfdbee862014-05-12 15:26:12 -07004125 // if no volume stored for current stream and device, use default volume if default
4126 // device, continue otherwise
4127 int defaultIndex = (device == AudioSystem.DEVICE_OUT_DEFAULT) ?
John Spurlock61560172015-02-06 19:46:04 -05004128 AudioSystem.DEFAULT_STREAM_VOLUME[mStreamType] : -1;
Jean-Michel Trivia53b7052017-04-12 18:27:01 -07004129 int index;
4130 if (!hasValidSettingsName()) {
4131 index = defaultIndex;
4132 } else {
4133 String name = getSettingNameForDevice(device);
4134 index = Settings.System.getIntForUser(
4135 mContentResolver, name, defaultIndex, UserHandle.USER_CURRENT);
4136 }
Eric Laurentfdbee862014-05-12 15:26:12 -07004137 if (index == -1) {
4138 continue;
4139 }
4140
John Spurlock2bb02ec2015-03-02 13:13:06 -05004141 mIndexMap.put(device, getValidIndex(10 * index));
Eric Laurentdd45d012012-10-08 09:04:34 -07004142 }
Eric Laurent9bc8358d2011-11-18 16:43:31 -08004143 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004144 }
4145
Liejun Tao39fb5672016-03-09 15:52:13 -06004146 private int getAbsoluteVolumeIndex(int index) {
4147 /* Special handling for Bluetooth Absolute Volume scenario
4148 * If we send full audio gain, some accessories are too loud even at its lowest
4149 * volume. We are not able to enumerate all such accessories, so here is the
4150 * workaround from phone side.
4151 * Pre-scale volume at lowest volume steps 1 2 and 3.
4152 * For volume step 0, set audio gain to 0 as some accessories won't mute on their end.
4153 */
4154 if (index == 0) {
4155 // 0% for volume 0
4156 index = 0;
Tomoharu Kasaharaf0fecb12018-09-06 20:04:38 +09004157 } else if (index > 0 && index <= 3) {
4158 // Pre-scale for volume steps 1 2 and 3
4159 index = (int) (mIndexMax * mPrescaleAbsoluteVolume[index - 1]) / 10;
Liejun Tao39fb5672016-03-09 15:52:13 -06004160 } else {
4161 // otherwise, full gain
Tomoharu Kasaharaf0fecb12018-09-06 20:04:38 +09004162 index = (mIndexMax + 5) / 10;
Liejun Tao39fb5672016-03-09 15:52:13 -06004163 }
4164 return index;
4165 }
4166
Eric Laurent8fa4d6f2014-10-30 14:13:03 -07004167 // must be called while synchronized VolumeStreamState.class
Jean-Michel Trivi58850372018-09-14 16:01:28 -07004168 /*package*/ void applyDeviceVolume_syncVSS(int device, boolean isAvrcpAbsVolSupported) {
Eric Laurent42b041e2013-03-29 11:36:03 -07004169 int index;
RoboErik4197cb62015-01-21 15:45:32 -08004170 if (mIsMuted) {
Eric Laurent42b041e2013-03-29 11:36:03 -07004171 index = 0;
Jean-Michel Trivi58850372018-09-14 16:01:28 -07004172 } else if ((device & AudioSystem.DEVICE_OUT_ALL_A2DP) != 0 && isAvrcpAbsVolSupported) {
Liejun Tao39fb5672016-03-09 15:52:13 -06004173 index = getAbsoluteVolumeIndex((getIndex(device) + 5)/10);
Liejun Tao4565a472016-01-20 17:52:20 -06004174 } else if ((device & mFullVolumeDevices) != 0) {
Matthew Xiec9d1d5f2013-09-12 00:32:22 -07004175 index = (mIndexMax + 5)/10;
Jakub Pawlowskic274fb22018-04-04 10:15:12 -07004176 } else if ((device & AudioSystem.DEVICE_OUT_HEARING_AID) != 0) {
4177 index = (mIndexMax + 5)/10;
Eric Laurentcd772d02013-10-30 18:31:07 -07004178 } else {
Eric Laurent42b041e2013-03-29 11:36:03 -07004179 index = (getIndex(device) + 5)/10;
4180 }
Jean-Michel Trivi58850372018-09-14 16:01:28 -07004181 AudioSystem.setStreamVolumeIndexAS(mStreamType, index, device);
Eric Laurent9bc8358d2011-11-18 16:43:31 -08004182 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004183
Eric Laurentfdbee862014-05-12 15:26:12 -07004184 public void applyAllVolumes() {
Jean-Michel Trivi58850372018-09-14 16:01:28 -07004185 final boolean isAvrcpAbsVolSupported = mDeviceBroker.isAvrcpAbsoluteVolumeSupported();
Eric Laurentfdbee862014-05-12 15:26:12 -07004186 synchronized (VolumeStreamState.class) {
Eric Laurentd9ac2be2016-04-07 14:04:23 -07004187 // apply device specific volumes first
Eric Laurentfdbee862014-05-12 15:26:12 -07004188 int index;
John Spurlock2bb02ec2015-03-02 13:13:06 -05004189 for (int i = 0; i < mIndexMap.size(); i++) {
Eric Laurentd9ac2be2016-04-07 14:04:23 -07004190 final int device = mIndexMap.keyAt(i);
Eric Laurentfdbee862014-05-12 15:26:12 -07004191 if (device != AudioSystem.DEVICE_OUT_DEFAULT) {
RoboErik4197cb62015-01-21 15:45:32 -08004192 if (mIsMuted) {
Eric Laurentfdbee862014-05-12 15:26:12 -07004193 index = 0;
Liejun Tao39fb5672016-03-09 15:52:13 -06004194 } else if ((device & AudioSystem.DEVICE_OUT_ALL_A2DP) != 0 &&
Jean-Michel Trivi58850372018-09-14 16:01:28 -07004195 isAvrcpAbsVolSupported) {
Liejun Tao39fb5672016-03-09 15:52:13 -06004196 index = getAbsoluteVolumeIndex((getIndex(device) + 5)/10);
4197 } else if ((device & mFullVolumeDevices) != 0) {
Eric Laurentfdbee862014-05-12 15:26:12 -07004198 index = (mIndexMax + 5)/10;
Jakub Pawlowskic274fb22018-04-04 10:15:12 -07004199 } else if ((device & AudioSystem.DEVICE_OUT_HEARING_AID) != 0) {
4200 index = (mIndexMax + 5)/10;
Eric Laurentfdbee862014-05-12 15:26:12 -07004201 } else {
John Spurlock2bb02ec2015-03-02 13:13:06 -05004202 index = (mIndexMap.valueAt(i) + 5)/10;
Eric Laurentfdbee862014-05-12 15:26:12 -07004203 }
Jean-Michel Trivi58850372018-09-14 16:01:28 -07004204 AudioSystem.setStreamVolumeIndexAS(mStreamType, index, device);
Eric Laurent42b041e2013-03-29 11:36:03 -07004205 }
Eric Laurent9bc8358d2011-11-18 16:43:31 -08004206 }
Eric Laurentd9ac2be2016-04-07 14:04:23 -07004207 // apply default volume last: by convention , default device volume will be used
4208 // by audio policy manager if no explicit volume is present for a given device type
4209 if (mIsMuted) {
4210 index = 0;
4211 } else {
4212 index = (getIndex(AudioSystem.DEVICE_OUT_DEFAULT) + 5)/10;
4213 }
Jean-Michel Trivi58850372018-09-14 16:01:28 -07004214 AudioSystem.setStreamVolumeIndexAS(
Eric Laurentd9ac2be2016-04-07 14:04:23 -07004215 mStreamType, index, AudioSystem.DEVICE_OUT_DEFAULT);
Eric Laurent9bc8358d2011-11-18 16:43:31 -08004216 }
4217 }
4218
John Spurlock90874332015-03-10 16:00:54 -04004219 public boolean adjustIndex(int deltaIndex, int device, String caller) {
4220 return setIndex(getIndex(device) + deltaIndex, device, caller);
Eric Laurent9bc8358d2011-11-18 16:43:31 -08004221 }
4222
John Spurlock90874332015-03-10 16:00:54 -04004223 public boolean setIndex(int index, int device, String caller) {
Jack He6dd78c12018-02-12 21:00:24 -08004224 boolean changed;
John Spurlockf63860c2015-02-19 09:46:27 -05004225 int oldIndex;
Jean-Michel Trivi8719a1d2017-11-06 11:52:51 -08004226 synchronized (mSettingsLock) {
4227 synchronized (VolumeStreamState.class) {
4228 oldIndex = getIndex(device);
4229 index = getValidIndex(index);
Eric Laurentfdbee862014-05-12 15:26:12 -07004230 if ((mStreamType == AudioSystem.STREAM_SYSTEM_ENFORCED) && mCameraSoundForced) {
4231 index = mIndexMax;
Eric Laurenta553c252009-07-17 12:17:14 -07004232 }
Jean-Michel Trivi8719a1d2017-11-06 11:52:51 -08004233 mIndexMap.put(device, index);
Eric Laurentfdbee862014-05-12 15:26:12 -07004234
Jean-Michel Trivi8719a1d2017-11-06 11:52:51 -08004235 changed = oldIndex != index;
4236 // Apply change to all streams using this one as alias if:
4237 // - the index actually changed OR
4238 // - there is no volume index stored for this device on alias stream.
4239 // If changing volume of current device, also change volume of current
4240 // device on aliased stream
Jack He6dd78c12018-02-12 21:00:24 -08004241 final boolean isCurrentDevice = (device == getDeviceForStream(mStreamType));
Jean-Michel Trivi8719a1d2017-11-06 11:52:51 -08004242 final int numStreamTypes = AudioSystem.getNumStreamTypes();
4243 for (int streamType = numStreamTypes - 1; streamType >= 0; streamType--) {
4244 final VolumeStreamState aliasStreamState = mStreamStates[streamType];
4245 if (streamType != mStreamType &&
4246 mStreamVolumeAlias[streamType] == mStreamType &&
4247 (changed || !aliasStreamState.hasIndexForDevice(device))) {
4248 final int scaledIndex = rescaleIndex(index, mStreamType, streamType);
4249 aliasStreamState.setIndex(scaledIndex, device, caller);
Jack He6dd78c12018-02-12 21:00:24 -08004250 if (isCurrentDevice) {
Jean-Michel Trivi8719a1d2017-11-06 11:52:51 -08004251 aliasStreamState.setIndex(scaledIndex,
4252 getDeviceForStream(streamType), caller);
4253 }
Eric Laurentfdbee862014-05-12 15:26:12 -07004254 }
4255 }
Jack He6dd78c12018-02-12 21:00:24 -08004256 // Mirror changes in SPEAKER ringtone volume on SCO when
4257 if (changed && mStreamType == AudioSystem.STREAM_RING
4258 && device == AudioSystem.DEVICE_OUT_SPEAKER) {
4259 for (int i = 0; i < mIndexMap.size(); i++) {
4260 int otherDevice = mIndexMap.keyAt(i);
4261 if ((otherDevice & AudioSystem.DEVICE_OUT_ALL_SCO) != 0) {
4262 mIndexMap.put(otherDevice, index);
4263 }
4264 }
4265 }
Eric Laurentfdbee862014-05-12 15:26:12 -07004266 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004267 }
John Spurlockf63860c2015-02-19 09:46:27 -05004268 if (changed) {
4269 oldIndex = (oldIndex + 5) / 10;
4270 index = (index + 5) / 10;
John Spurlock90874332015-03-10 16:00:54 -04004271 // log base stream changes to the event log
4272 if (mStreamVolumeAlias[mStreamType] == mStreamType) {
4273 if (caller == null) {
4274 Log.w(TAG, "No caller for volume_changed event", new Throwable());
4275 }
4276 EventLogTags.writeVolumeChanged(mStreamType, oldIndex, index, mIndexMax / 10,
4277 caller);
4278 }
4279 // fire changed intents for all streams
John Spurlockf63860c2015-02-19 09:46:27 -05004280 mVolumeChanged.putExtra(AudioManager.EXTRA_VOLUME_STREAM_VALUE, index);
4281 mVolumeChanged.putExtra(AudioManager.EXTRA_PREV_VOLUME_STREAM_VALUE, oldIndex);
Jean-Michel Trivi560877d2015-06-25 17:38:35 -07004282 mVolumeChanged.putExtra(AudioManager.EXTRA_VOLUME_STREAM_TYPE_ALIAS,
4283 mStreamVolumeAlias[mStreamType]);
John Spurlockf63860c2015-02-19 09:46:27 -05004284 sendBroadcastToAll(mVolumeChanged);
4285 }
4286 return changed;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004287 }
4288
Eric Laurentfdbee862014-05-12 15:26:12 -07004289 public int getIndex(int device) {
4290 synchronized (VolumeStreamState.class) {
John Spurlock2bb02ec2015-03-02 13:13:06 -05004291 int index = mIndexMap.get(device, -1);
4292 if (index == -1) {
Eric Laurentfdbee862014-05-12 15:26:12 -07004293 // there is always an entry for AudioSystem.DEVICE_OUT_DEFAULT
John Spurlock2bb02ec2015-03-02 13:13:06 -05004294 index = mIndexMap.get(AudioSystem.DEVICE_OUT_DEFAULT);
Eric Laurentfdbee862014-05-12 15:26:12 -07004295 }
John Spurlock2bb02ec2015-03-02 13:13:06 -05004296 return index;
Eric Laurent9bc8358d2011-11-18 16:43:31 -08004297 }
Eric Laurent5b4e6542010-03-19 20:02:21 -07004298 }
4299
Eric Laurent3fb608e2016-11-03 16:27:40 -07004300 public boolean hasIndexForDevice(int device) {
4301 synchronized (VolumeStreamState.class) {
4302 return (mIndexMap.get(device, -1) != -1);
4303 }
4304 }
4305
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004306 public int getMaxIndex() {
Eric Laurenta553c252009-07-17 12:17:14 -07004307 return mIndexMax;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004308 }
4309
John Spurlockb6e19e32015-03-10 21:33:44 -04004310 public int getMinIndex() {
4311 return mIndexMin;
4312 }
4313
Jean-Michel Trivi170a0ee2017-04-14 18:13:26 -07004314 /**
Jean-Michel Trivie05eef82018-03-08 18:56:34 -08004315 * Updates the min/max index values from another stream. Use this when changing the alias
4316 * for the current stream type.
4317 * @param sourceStreamType
4318 */
4319 // must be sync'd on mSettingsLock before VolumeStreamState.class
4320 @GuardedBy("VolumeStreamState.class")
4321 public void refreshRange(int sourceStreamType) {
4322 mIndexMin = MIN_STREAM_VOLUME[sourceStreamType] * 10;
4323 mIndexMax = MAX_STREAM_VOLUME[sourceStreamType] * 10;
4324 // verify all current volumes are within bounds
4325 for (int i = 0 ; i < mIndexMap.size(); i++) {
4326 final int device = mIndexMap.keyAt(i);
4327 final int index = mIndexMap.valueAt(i);
4328 mIndexMap.put(device, getValidIndex(index));
4329 }
4330 }
4331
4332 /**
Jean-Michel Trivi170a0ee2017-04-14 18:13:26 -07004333 * Copies all device/index pairs from the given VolumeStreamState after initializing
4334 * them with the volume for DEVICE_OUT_DEFAULT. No-op if the source VolumeStreamState
4335 * has the same stream type as this instance.
4336 * @param srcStream
4337 * @param caller
4338 */
Jean-Michel Trivi085346a2018-02-14 10:48:51 -08004339 // must be sync'd on mSettingsLock before VolumeStreamState.class
4340 @GuardedBy("VolumeStreamState.class")
John Spurlock90874332015-03-10 16:00:54 -04004341 public void setAllIndexes(VolumeStreamState srcStream, String caller) {
Jean-Michel Trivi170a0ee2017-04-14 18:13:26 -07004342 if (mStreamType == srcStream.mStreamType) {
4343 return;
4344 }
Jean-Michel Trivi085346a2018-02-14 10:48:51 -08004345 int srcStreamType = srcStream.getStreamType();
4346 // apply default device volume from source stream to all devices first in case
4347 // some devices are present in this stream state but not in source stream state
4348 int index = srcStream.getIndex(AudioSystem.DEVICE_OUT_DEFAULT);
4349 index = rescaleIndex(index, srcStreamType, mStreamType);
4350 for (int i = 0; i < mIndexMap.size(); i++) {
4351 mIndexMap.put(mIndexMap.keyAt(i), index);
4352 }
4353 // Now apply actual volume for devices in source stream state
4354 SparseIntArray srcMap = srcStream.mIndexMap;
4355 for (int i = 0; i < srcMap.size(); i++) {
4356 int device = srcMap.keyAt(i);
4357 index = srcMap.valueAt(i);
4358 index = rescaleIndex(index, srcStreamType, mStreamType);
Eric Laurent33902db2012-10-07 16:15:07 -07004359
Jean-Michel Trivi085346a2018-02-14 10:48:51 -08004360 setIndex(index, device, caller);
Eric Laurent6d517662012-04-23 18:42:39 -07004361 }
4362 }
4363
Jean-Michel Trivi085346a2018-02-14 10:48:51 -08004364 // must be sync'd on mSettingsLock before VolumeStreamState.class
4365 @GuardedBy("VolumeStreamState.class")
Eric Laurentfdbee862014-05-12 15:26:12 -07004366 public void setAllIndexesToMax() {
Jean-Michel Trivi085346a2018-02-14 10:48:51 -08004367 for (int i = 0; i < mIndexMap.size(); i++) {
4368 mIndexMap.put(mIndexMap.keyAt(i), mIndexMax);
Eric Laurentdd45d012012-10-08 09:04:34 -07004369 }
Eric Laurentdd45d012012-10-08 09:04:34 -07004370 }
4371
RoboErik4197cb62015-01-21 15:45:32 -08004372 public void mute(boolean state) {
John Spurlock22b9ee12015-02-18 22:51:44 -05004373 boolean changed = false;
Eric Laurentfdbee862014-05-12 15:26:12 -07004374 synchronized (VolumeStreamState.class) {
RoboErik4197cb62015-01-21 15:45:32 -08004375 if (state != mIsMuted) {
John Spurlock22b9ee12015-02-18 22:51:44 -05004376 changed = true;
RoboErik4197cb62015-01-21 15:45:32 -08004377 mIsMuted = state;
John Spurlock22b9ee12015-02-18 22:51:44 -05004378
RoboErik4197cb62015-01-21 15:45:32 -08004379 // Set the new mute volume. This propagates the values to
4380 // the audio system, otherwise the volume won't be changed
4381 // at the lower level.
4382 sendMsg(mAudioHandler,
4383 MSG_SET_ALL_VOLUMES,
4384 SENDMSG_QUEUE,
4385 0,
4386 0,
4387 this, 0);
Eric Laurentfdbee862014-05-12 15:26:12 -07004388 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004389 }
John Spurlock22b9ee12015-02-18 22:51:44 -05004390 if (changed) {
4391 // Stream mute changed, fire the intent.
4392 Intent intent = new Intent(AudioManager.STREAM_MUTE_CHANGED_ACTION);
4393 intent.putExtra(AudioManager.EXTRA_VOLUME_STREAM_TYPE, mStreamType);
4394 intent.putExtra(AudioManager.EXTRA_STREAM_VOLUME_MUTED, state);
4395 sendBroadcastToAll(intent);
4396 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004397 }
4398
Eric Laurent6d517662012-04-23 18:42:39 -07004399 public int getStreamType() {
4400 return mStreamType;
4401 }
4402
Eric Laurent212532b2014-07-21 15:43:18 -07004403 public void checkFixedVolumeDevices() {
Jean-Michel Trivi58850372018-09-14 16:01:28 -07004404 final boolean isAvrcpAbsVolSupported = mDeviceBroker.isAvrcpAbsoluteVolumeSupported();
Eric Laurent212532b2014-07-21 15:43:18 -07004405 synchronized (VolumeStreamState.class) {
4406 // ignore settings for fixed volume devices: volume should always be at max or 0
4407 if (mStreamVolumeAlias[mStreamType] == AudioSystem.STREAM_MUSIC) {
John Spurlock2bb02ec2015-03-02 13:13:06 -05004408 for (int i = 0; i < mIndexMap.size(); i++) {
4409 int device = mIndexMap.keyAt(i);
4410 int index = mIndexMap.valueAt(i);
Jean-Michel Triviba5270b2014-10-01 17:49:29 -07004411 if (((device & mFullVolumeDevices) != 0)
4412 || (((device & mFixedVolumeDevices) != 0) && index != 0)) {
John Spurlock2bb02ec2015-03-02 13:13:06 -05004413 mIndexMap.put(device, mIndexMax);
Eric Laurent212532b2014-07-21 15:43:18 -07004414 }
Jean-Michel Trivi58850372018-09-14 16:01:28 -07004415 applyDeviceVolume_syncVSS(device, isAvrcpAbsVolSupported);
Eric Laurent212532b2014-07-21 15:43:18 -07004416 }
4417 }
4418 }
4419 }
4420
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004421 private int getValidIndex(int index) {
John Spurlockb6e19e32015-03-10 21:33:44 -04004422 if (index < mIndexMin) {
4423 return mIndexMin;
John Spurlockee5ad722015-03-03 16:17:21 -05004424 } else if (mUseFixedVolume || index > mIndexMax) {
Eric Laurenta553c252009-07-17 12:17:14 -07004425 return mIndexMax;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004426 }
4427
4428 return index;
4429 }
4430
Eric Laurentbffc3d12012-05-07 17:43:49 -07004431 private void dump(PrintWriter pw) {
RoboErik4197cb62015-01-21 15:45:32 -08004432 pw.print(" Muted: ");
4433 pw.println(mIsMuted);
John Spurlockb6e19e32015-03-10 21:33:44 -04004434 pw.print(" Min: ");
4435 pw.println((mIndexMin + 5) / 10);
John Spurlock2b29bc42014-08-26 16:40:35 -04004436 pw.print(" Max: ");
4437 pw.println((mIndexMax + 5) / 10);
Eric Laurentbffc3d12012-05-07 17:43:49 -07004438 pw.print(" Current: ");
John Spurlock2bb02ec2015-03-02 13:13:06 -05004439 for (int i = 0; i < mIndexMap.size(); i++) {
4440 if (i > 0) {
4441 pw.print(", ");
4442 }
4443 final int device = mIndexMap.keyAt(i);
John Spurlock2b29bc42014-08-26 16:40:35 -04004444 pw.print(Integer.toHexString(device));
4445 final String deviceName = device == AudioSystem.DEVICE_OUT_DEFAULT ? "default"
4446 : AudioSystem.getOutputDeviceName(device);
4447 if (!deviceName.isEmpty()) {
4448 pw.print(" (");
4449 pw.print(deviceName);
4450 pw.print(")");
4451 }
4452 pw.print(": ");
John Spurlock2bb02ec2015-03-02 13:13:06 -05004453 final int index = (mIndexMap.valueAt(i) + 5) / 10;
John Spurlock2b29bc42014-08-26 16:40:35 -04004454 pw.print(index);
Eric Laurentbffc3d12012-05-07 17:43:49 -07004455 }
John Spurlockb32fc972015-03-05 13:58:00 -05004456 pw.println();
4457 pw.print(" Devices: ");
John Spurlock8a52c442015-03-26 14:23:58 -04004458 final int devices = getDevicesForStream(mStreamType);
John Spurlockb32fc972015-03-05 13:58:00 -05004459 int device, i = 0, n = 0;
John Spurlock1ff1e6e2015-03-09 14:21:20 -04004460 // iterate all devices from 1 to DEVICE_OUT_DEFAULT exclusive
4461 // (the default device is not returned by getDevicesForStream)
4462 while ((device = 1 << i) != AudioSystem.DEVICE_OUT_DEFAULT) {
John Spurlockb32fc972015-03-05 13:58:00 -05004463 if ((devices & device) != 0) {
4464 if (n++ > 0) {
4465 pw.print(", ");
4466 }
4467 pw.print(AudioSystem.getOutputDeviceName(device));
4468 }
4469 i++;
4470 }
Eric Laurentbffc3d12012-05-07 17:43:49 -07004471 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004472 }
4473
4474 /** Thread that handles native AudioSystem control. */
4475 private class AudioSystemThread extends Thread {
4476 AudioSystemThread() {
4477 super("AudioService");
4478 }
4479
4480 @Override
4481 public void run() {
4482 // Set this thread up so the handler will work on it
4483 Looper.prepare();
4484
4485 synchronized(AudioService.this) {
4486 mAudioHandler = new AudioHandler();
4487
4488 // Notify that the handler has been created
4489 AudioService.this.notify();
4490 }
4491
4492 // Listen for volume change requests that are set by VolumePanel
4493 Looper.loop();
4494 }
4495 }
4496
Jean-Michel Trivi58850372018-09-14 16:01:28 -07004497 /*package*/ void setDeviceVolume(VolumeStreamState streamState, int device) {
4498
4499 final boolean isAvrcpAbsVolSupported = mDeviceBroker.isAvrcpAbsoluteVolumeSupported();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004500
Eric Laurent3e6fb632018-05-21 09:28:46 -07004501 synchronized (VolumeStreamState.class) {
4502 // Apply volume
Jean-Michel Trivi58850372018-09-14 16:01:28 -07004503 streamState.applyDeviceVolume_syncVSS(device, isAvrcpAbsVolSupported);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004504
Eric Laurent3e6fb632018-05-21 09:28:46 -07004505 // Apply change to all streams using this one as alias
4506 int numStreamTypes = AudioSystem.getNumStreamTypes();
4507 for (int streamType = numStreamTypes - 1; streamType >= 0; streamType--) {
4508 if (streamType != streamState.mStreamType &&
4509 mStreamVolumeAlias[streamType] == streamState.mStreamType) {
4510 // Make sure volume is also maxed out on A2DP device for aliased stream
4511 // that may have a different device selected
4512 int streamDevice = getDeviceForStream(streamType);
Jean-Michel Trivi58850372018-09-14 16:01:28 -07004513 if ((device != streamDevice) && isAvrcpAbsVolSupported
4514 && ((device & AudioSystem.DEVICE_OUT_ALL_A2DP) != 0)) {
4515 mStreamStates[streamType].applyDeviceVolume_syncVSS(device,
4516 isAvrcpAbsVolSupported);
Eric Laurentcd772d02013-10-30 18:31:07 -07004517 }
Jean-Michel Trivi58850372018-09-14 16:01:28 -07004518 mStreamStates[streamType].applyDeviceVolume_syncVSS(streamDevice,
4519 isAvrcpAbsVolSupported);
Eric Laurenta553c252009-07-17 12:17:14 -07004520 }
4521 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004522 }
Eric Laurent3e6fb632018-05-21 09:28:46 -07004523 // Post a persist volume msg
4524 sendMsg(mAudioHandler,
4525 MSG_PERSIST_VOLUME,
4526 SENDMSG_QUEUE,
4527 device,
4528 0,
4529 streamState,
4530 PERSIST_DELAY);
4531
4532 }
4533
4534 /** Handles internal volume messages in separate volume thread. */
4535 private class AudioHandler extends Handler {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004536
Eric Laurent9bc8358d2011-11-18 16:43:31 -08004537 private void setAllVolumes(VolumeStreamState streamState) {
4538
4539 // Apply volume
4540 streamState.applyAllVolumes();
4541
4542 // Apply change to all streams using this one as alias
4543 int numStreamTypes = AudioSystem.getNumStreamTypes();
4544 for (int streamType = numStreamTypes - 1; streamType >= 0; streamType--) {
4545 if (streamType != streamState.mStreamType &&
Eric Laurent6d517662012-04-23 18:42:39 -07004546 mStreamVolumeAlias[streamType] == streamState.mStreamType) {
Eric Laurent9bc8358d2011-11-18 16:43:31 -08004547 mStreamStates[streamType].applyAllVolumes();
4548 }
4549 }
4550 }
4551
Eric Laurent42b041e2013-03-29 11:36:03 -07004552 private void persistVolume(VolumeStreamState streamState, int device) {
Eric Laurent83a017b2013-03-19 18:15:31 -07004553 if (mUseFixedVolume) {
4554 return;
4555 }
Muyuan Li1ed6df62016-06-18 11:16:52 -07004556 if (mIsSingleVolume && (streamState.mStreamType != AudioSystem.STREAM_MUSIC)) {
Eric Laurent212532b2014-07-21 15:43:18 -07004557 return;
4558 }
Jean-Michel Trivia53b7052017-04-12 18:27:01 -07004559 if (streamState.hasValidSettingsName()) {
4560 System.putIntForUser(mContentResolver,
4561 streamState.getSettingNameForDevice(device),
4562 (streamState.getIndex(device) + 5)/ 10,
4563 UserHandle.USER_CURRENT);
4564 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004565 }
4566
Glenn Kastenba195eb2011-12-13 09:30:40 -08004567 private void persistRingerMode(int ringerMode) {
Eric Laurent83a017b2013-03-19 18:15:31 -07004568 if (mUseFixedVolume) {
4569 return;
4570 }
Jeff Sharkey8d9a1f62012-10-18 15:38:14 -07004571 Settings.Global.putInt(mContentResolver, Settings.Global.MODE_RINGER, ringerMode);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004572 }
4573
Jaekyun Seokc31033f2018-01-15 14:53:17 +09004574 private String getSoundEffectFilePath(int effectType) {
4575 String filePath = Environment.getProductDirectory() + SOUND_EFFECTS_PATH
4576 + SOUND_EFFECT_FILES.get(SOUND_EFFECT_FILES_MAP[effectType][0]);
4577 if (!new File(filePath).isFile()) {
4578 filePath = Environment.getRootDirectory() + SOUND_EFFECTS_PATH
4579 + SOUND_EFFECT_FILES.get(SOUND_EFFECT_FILES_MAP[effectType][0]);
4580 }
4581 return filePath;
4582 }
4583
Eric Laurent5d3eb44a2013-03-21 15:35:10 -07004584 private boolean onLoadSoundEffects() {
4585 int status;
4586
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004587 synchronized (mSoundEffectsLock) {
Eric Laurent4a5eeb92014-05-06 10:49:04 -07004588 if (!mSystemReady) {
Eric Laurent5d3eb44a2013-03-21 15:35:10 -07004589 Log.w(TAG, "onLoadSoundEffects() called before boot complete");
4590 return false;
4591 }
4592
4593 if (mSoundPool != null) {
4594 return true;
4595 }
4596
4597 loadTouchSoundAssets();
4598
Jean-Michel Trivi55a30c42014-07-20 17:56:11 -07004599 mSoundPool = new SoundPool.Builder()
4600 .setMaxStreams(NUM_SOUNDPOOL_CHANNELS)
4601 .setAudioAttributes(new AudioAttributes.Builder()
4602 .setUsage(AudioAttributes.USAGE_ASSISTANCE_SONIFICATION)
4603 .setContentType(AudioAttributes.CONTENT_TYPE_SONIFICATION)
4604 .build())
4605 .build();
Eric Laurent5d3eb44a2013-03-21 15:35:10 -07004606 mSoundPoolCallBack = null;
4607 mSoundPoolListenerThread = new SoundPoolListenerThread();
4608 mSoundPoolListenerThread.start();
4609 int attempts = 3;
4610 while ((mSoundPoolCallBack == null) && (attempts-- > 0)) {
4611 try {
4612 // Wait for mSoundPoolCallBack to be set by the other thread
Glenn Kasten167d1a22013-07-23 16:24:41 -07004613 mSoundEffectsLock.wait(SOUND_EFFECTS_LOAD_TIMEOUT_MS);
Eric Laurent5d3eb44a2013-03-21 15:35:10 -07004614 } catch (InterruptedException e) {
4615 Log.w(TAG, "Interrupted while waiting sound pool listener thread.");
4616 }
4617 }
4618
4619 if (mSoundPoolCallBack == null) {
4620 Log.w(TAG, "onLoadSoundEffects() SoundPool listener or thread creation error");
4621 if (mSoundPoolLooper != null) {
4622 mSoundPoolLooper.quit();
4623 mSoundPoolLooper = null;
4624 }
4625 mSoundPoolListenerThread = null;
4626 mSoundPool.release();
4627 mSoundPool = null;
4628 return false;
4629 }
4630 /*
4631 * poolId table: The value -1 in this table indicates that corresponding
4632 * file (same index in SOUND_EFFECT_FILES[] has not been loaded.
4633 * Once loaded, the value in poolId is the sample ID and the same
4634 * sample can be reused for another effect using the same file.
4635 */
4636 int[] poolId = new int[SOUND_EFFECT_FILES.size()];
4637 for (int fileIdx = 0; fileIdx < SOUND_EFFECT_FILES.size(); fileIdx++) {
4638 poolId[fileIdx] = -1;
4639 }
4640 /*
4641 * Effects whose value in SOUND_EFFECT_FILES_MAP[effect][1] is -1 must be loaded.
4642 * If load succeeds, value in SOUND_EFFECT_FILES_MAP[effect][1] is > 0:
4643 * this indicates we have a valid sample loaded for this effect.
4644 */
4645
4646 int numSamples = 0;
4647 for (int effect = 0; effect < AudioManager.NUM_SOUND_EFFECTS; effect++) {
4648 // Do not load sample if this effect uses the MediaPlayer
4649 if (SOUND_EFFECT_FILES_MAP[effect][1] == 0) {
4650 continue;
4651 }
4652 if (poolId[SOUND_EFFECT_FILES_MAP[effect][0]] == -1) {
Jaekyun Seokc31033f2018-01-15 14:53:17 +09004653 String filePath = getSoundEffectFilePath(effect);
Eric Laurent5d3eb44a2013-03-21 15:35:10 -07004654 int sampleId = mSoundPool.load(filePath, 0);
4655 if (sampleId <= 0) {
4656 Log.w(TAG, "Soundpool could not load file: "+filePath);
4657 } else {
4658 SOUND_EFFECT_FILES_MAP[effect][1] = sampleId;
4659 poolId[SOUND_EFFECT_FILES_MAP[effect][0]] = sampleId;
4660 numSamples++;
4661 }
4662 } else {
4663 SOUND_EFFECT_FILES_MAP[effect][1] =
4664 poolId[SOUND_EFFECT_FILES_MAP[effect][0]];
4665 }
4666 }
4667 // wait for all samples to be loaded
4668 if (numSamples > 0) {
4669 mSoundPoolCallBack.setSamples(poolId);
4670
4671 attempts = 3;
4672 status = 1;
4673 while ((status == 1) && (attempts-- > 0)) {
4674 try {
Glenn Kasten167d1a22013-07-23 16:24:41 -07004675 mSoundEffectsLock.wait(SOUND_EFFECTS_LOAD_TIMEOUT_MS);
Eric Laurent5d3eb44a2013-03-21 15:35:10 -07004676 status = mSoundPoolCallBack.status();
4677 } catch (InterruptedException e) {
4678 Log.w(TAG, "Interrupted while waiting sound pool callback.");
4679 }
4680 }
4681 } else {
4682 status = -1;
4683 }
4684
4685 if (mSoundPoolLooper != null) {
4686 mSoundPoolLooper.quit();
4687 mSoundPoolLooper = null;
4688 }
4689 mSoundPoolListenerThread = null;
4690 if (status != 0) {
4691 Log.w(TAG,
4692 "onLoadSoundEffects(), Error "+status+ " while loading samples");
4693 for (int effect = 0; effect < AudioManager.NUM_SOUND_EFFECTS; effect++) {
4694 if (SOUND_EFFECT_FILES_MAP[effect][1] > 0) {
4695 SOUND_EFFECT_FILES_MAP[effect][1] = -1;
4696 }
4697 }
4698
4699 mSoundPool.release();
4700 mSoundPool = null;
4701 }
4702 }
4703 return (status == 0);
4704 }
4705
4706 /**
4707 * Unloads samples from the sound pool.
4708 * This method can be called to free some memory when
4709 * sound effects are disabled.
4710 */
4711 private void onUnloadSoundEffects() {
4712 synchronized (mSoundEffectsLock) {
4713 if (mSoundPool == null) {
4714 return;
4715 }
4716
4717 int[] poolId = new int[SOUND_EFFECT_FILES.size()];
4718 for (int fileIdx = 0; fileIdx < SOUND_EFFECT_FILES.size(); fileIdx++) {
4719 poolId[fileIdx] = 0;
4720 }
4721
4722 for (int effect = 0; effect < AudioManager.NUM_SOUND_EFFECTS; effect++) {
4723 if (SOUND_EFFECT_FILES_MAP[effect][1] <= 0) {
4724 continue;
4725 }
4726 if (poolId[SOUND_EFFECT_FILES_MAP[effect][0]] == 0) {
4727 mSoundPool.unload(SOUND_EFFECT_FILES_MAP[effect][1]);
4728 SOUND_EFFECT_FILES_MAP[effect][1] = -1;
4729 poolId[SOUND_EFFECT_FILES_MAP[effect][0]] = -1;
4730 }
4731 }
4732 mSoundPool.release();
4733 mSoundPool = null;
4734 }
4735 }
4736
4737 private void onPlaySoundEffect(int effectType, int volume) {
4738 synchronized (mSoundEffectsLock) {
4739
4740 onLoadSoundEffects();
4741
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004742 if (mSoundPool == null) {
4743 return;
4744 }
Eric Laurenta2ef57d2009-09-28 04:46:10 -07004745 float volFloat;
Eric Laurent25101b02011-02-02 09:33:30 -08004746 // use default if volume is not specified by caller
Eric Laurenta2ef57d2009-09-28 04:46:10 -07004747 if (volume < 0) {
Jean-Michel Trivif2b0c112012-07-09 11:59:11 -07004748 volFloat = (float)Math.pow(10, (float)sSoundEffectVolumeDb/20);
Eric Laurenta2ef57d2009-09-28 04:46:10 -07004749 } else {
RoboErik8a2cfc32014-05-16 11:19:38 -07004750 volFloat = volume / 1000.0f;
Eric Laurenta2ef57d2009-09-28 04:46:10 -07004751 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004752
4753 if (SOUND_EFFECT_FILES_MAP[effectType][1] > 0) {
Eric Laurent5d3eb44a2013-03-21 15:35:10 -07004754 mSoundPool.play(SOUND_EFFECT_FILES_MAP[effectType][1],
4755 volFloat, volFloat, 0, 0, 1.0f);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004756 } else {
4757 MediaPlayer mediaPlayer = new MediaPlayer();
Glenn Kasten62b9aec2011-11-07 11:10:16 -08004758 try {
Jaekyun Seokc31033f2018-01-15 14:53:17 +09004759 String filePath = getSoundEffectFilePath(effectType);
Glenn Kasten62b9aec2011-11-07 11:10:16 -08004760 mediaPlayer.setDataSource(filePath);
4761 mediaPlayer.setAudioStreamType(AudioSystem.STREAM_SYSTEM);
4762 mediaPlayer.prepare();
Glenn Kasten068225d2012-02-27 16:21:04 -08004763 mediaPlayer.setVolume(volFloat);
Glenn Kasten62b9aec2011-11-07 11:10:16 -08004764 mediaPlayer.setOnCompletionListener(new OnCompletionListener() {
4765 public void onCompletion(MediaPlayer mp) {
4766 cleanupPlayer(mp);
4767 }
4768 });
4769 mediaPlayer.setOnErrorListener(new OnErrorListener() {
4770 public boolean onError(MediaPlayer mp, int what, int extra) {
4771 cleanupPlayer(mp);
4772 return true;
4773 }
4774 });
4775 mediaPlayer.start();
4776 } catch (IOException ex) {
4777 Log.w(TAG, "MediaPlayer IOException: "+ex);
4778 } catch (IllegalArgumentException ex) {
4779 Log.w(TAG, "MediaPlayer IllegalArgumentException: "+ex);
4780 } catch (IllegalStateException ex) {
4781 Log.w(TAG, "MediaPlayer IllegalStateException: "+ex);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004782 }
4783 }
4784 }
4785 }
4786
4787 private void cleanupPlayer(MediaPlayer mp) {
4788 if (mp != null) {
4789 try {
4790 mp.stop();
4791 mp.release();
4792 } catch (IllegalStateException ex) {
4793 Log.w(TAG, "MediaPlayer IllegalStateException: "+ex);
4794 }
4795 }
4796 }
4797
Eric Laurent05274f32012-11-29 12:48:18 -08004798 private void onPersistSafeVolumeState(int state) {
4799 Settings.Global.putInt(mContentResolver,
4800 Settings.Global.AUDIO_SAFE_VOLUME_STATE,
4801 state);
4802 }
4803
Jean-Michel Trivi7ed71472018-02-02 16:52:09 -08004804 private void onNotifyVolumeEvent(@NonNull IAudioPolicyCallback apc,
4805 @AudioManager.VolumeAdjustment int direction) {
4806 try {
4807 apc.notifyVolumeAdjust(direction);
4808 } catch(Exception e) {
4809 // nothing we can do about this. Do not log error, too much potential for spam
4810 }
4811 }
4812
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004813 @Override
4814 public void handleMessage(Message msg) {
Eric Laurentafbb0472011-12-15 09:04:23 -08004815 switch (msg.what) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004816
Eric Laurent9bc8358d2011-11-18 16:43:31 -08004817 case MSG_SET_DEVICE_VOLUME:
4818 setDeviceVolume((VolumeStreamState) msg.obj, msg.arg1);
4819 break;
4820
4821 case MSG_SET_ALL_VOLUMES:
4822 setAllVolumes((VolumeStreamState) msg.obj);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004823 break;
4824
4825 case MSG_PERSIST_VOLUME:
Eric Laurent42b041e2013-03-29 11:36:03 -07004826 persistVolume((VolumeStreamState) msg.obj, msg.arg1);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004827 break;
4828
4829 case MSG_PERSIST_RINGER_MODE:
Glenn Kastenba195eb2011-12-13 09:30:40 -08004830 // note that the value persisted is the current ringer mode, not the
4831 // value of ringer mode as of the time the request was made to persist
John Spurlock661f2cf2014-11-17 10:29:10 -05004832 persistRingerMode(getRingerModeInternal());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004833 break;
4834
Andy Hunged0ea402015-10-30 14:11:46 -07004835 case MSG_AUDIO_SERVER_DIED:
4836 onAudioServerDied();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004837 break;
4838
Eric Laurent1d3cdce2018-01-20 10:31:21 -08004839 case MSG_DISPATCH_AUDIO_SERVER_STATE:
4840 onDispatchAudioServerStateChange(msg.arg1 == 1);
4841 break;
4842
Eric Laurent5d3eb44a2013-03-21 15:35:10 -07004843 case MSG_UNLOAD_SOUND_EFFECTS:
4844 onUnloadSoundEffects();
4845 break;
4846
Eric Laurent117b7bb2011-01-16 17:07:27 -08004847 case MSG_LOAD_SOUND_EFFECTS:
Eric Laurent5d3eb44a2013-03-21 15:35:10 -07004848 //FIXME: onLoadSoundEffects() should be executed in a separate thread as it
4849 // can take several dozens of milliseconds to complete
4850 boolean loaded = onLoadSoundEffects();
4851 if (msg.obj != null) {
4852 LoadSoundEffectReply reply = (LoadSoundEffectReply)msg.obj;
4853 synchronized (reply) {
4854 reply.mStatus = loaded ? 0 : -1;
4855 reply.notify();
4856 }
4857 }
Eric Laurent117b7bb2011-01-16 17:07:27 -08004858 break;
4859
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004860 case MSG_PLAY_SOUND_EFFECT:
Eric Laurent5d3eb44a2013-03-21 15:35:10 -07004861 onPlaySoundEffect(msg.arg1, msg.arg2);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004862 break;
Jean-Michel Trivi4c637b92010-04-12 18:44:10 -07004863
Eric Laurentfa640152011-03-12 15:59:51 -08004864 case MSG_SET_FORCE_USE:
Jean-Michel Trivi58850372018-09-14 16:01:28 -07004865 {
4866 final String eventSource = (String) msg.obj;
4867 final int useCase = msg.arg1;
4868 final int config = msg.arg2;
4869 if (useCase == AudioSystem.FOR_MEDIA) {
4870 Log.wtf(TAG, "Invalid force use FOR_MEDIA in AudioService from "
4871 + eventSource);
4872 break;
Paul McLean10804eb2015-01-28 11:16:35 -08004873 }
Jean-Michel Trivi58850372018-09-14 16:01:28 -07004874 sForceUseLogger.log(
4875 new AudioServiceEvents.ForceUseEvent(useCase, config, eventSource));
4876 AudioSystem.setForceUse(useCase, config);
4877 }
Aniket Kumar Lataa8439e22019-01-11 03:59:00 -08004878 break;
4879
Jean-Michel Trivi92ed7bf2017-06-26 19:32:38 -07004880 case MSG_DISABLE_AUDIO_FOR_UID:
4881 mPlaybackMonitor.disableAudioForUid( msg.arg1 == 1 /* disable */,
4882 msg.arg2 /* uid */);
4883 mAudioEventWakeLock.release();
4884 break;
4885
Eric Laurentc34dcc12012-09-10 13:51:52 -07004886 case MSG_CHECK_MUSIC_ACTIVE:
John Spurlock90874332015-03-10 16:00:54 -04004887 onCheckMusicActive((String) msg.obj);
Eric Laurentc34dcc12012-09-10 13:51:52 -07004888 break;
Eric Laurent5bfaeae2012-09-21 18:44:48 -07004889
Eric Laurentd640bd32012-09-28 18:01:48 -07004890 case MSG_CONFIGURE_SAFE_MEDIA_VOLUME_FORCED:
4891 case MSG_CONFIGURE_SAFE_MEDIA_VOLUME:
John Spurlock90874332015-03-10 16:00:54 -04004892 onConfigureSafeVolume((msg.what == MSG_CONFIGURE_SAFE_MEDIA_VOLUME_FORCED),
4893 (String) msg.obj);
Eric Laurentd640bd32012-09-28 18:01:48 -07004894 break;
Eric Laurent05274f32012-11-29 12:48:18 -08004895 case MSG_PERSIST_SAFE_VOLUME_STATE:
4896 onPersistSafeVolumeState(msg.arg1);
4897 break;
Jean-Michel Trivia578c482012-12-28 11:19:49 -08004898
Eric Laurent4a5eeb92014-05-06 10:49:04 -07004899 case MSG_SYSTEM_READY:
4900 onSystemReady();
4901 break;
John Spurlockaa5ee4d2014-07-25 13:05:12 -04004902
Eric Laurent0867bed2015-05-20 14:49:08 -07004903 case MSG_INDICATE_SYSTEM_READY:
4904 onIndicateSystemReady();
4905 break;
4906
Jean-Michel Trivi1ab43f62017-04-27 15:37:34 -07004907 case MSG_ACCESSORY_PLUG_MEDIA_UNMUTE:
4908 onAccessoryPlugMediaUnmute(msg.arg1);
4909 break;
4910
John Spurlockaa5ee4d2014-07-25 13:05:12 -04004911 case MSG_PERSIST_MUSIC_ACTIVE_MS:
4912 final int musicActiveMs = msg.arg1;
4913 Settings.Secure.putIntForUser(mContentResolver,
4914 Settings.Secure.UNSAFE_VOLUME_MUSIC_ACTIVE_MS, musicActiveMs,
4915 UserHandle.USER_CURRENT);
4916 break;
Eric Laurentc0232482016-03-15 18:19:23 -07004917
RoboErik5452e252015-02-06 15:33:53 -08004918 case MSG_UNMUTE_STREAM:
4919 onUnmuteStream(msg.arg1, msg.arg2);
4920 break;
Eric Laurentc0232482016-03-15 18:19:23 -07004921
Jean-Michel Trivi5a561092015-04-23 18:48:08 -07004922 case MSG_DYN_POLICY_MIX_STATE_UPDATE:
4923 onDynPolicyMixStateUpdate((String) msg.obj, msg.arg1);
4924 break;
Jean-Michel Trivi7ed71472018-02-02 16:52:09 -08004925
4926 case MSG_NOTIFY_VOL_EVENT:
4927 onNotifyVolumeEvent((IAudioPolicyCallback) msg.obj, msg.arg1);
4928 break;
jiabin39940752018-04-02 18:18:45 -07004929
4930 case MSG_ENABLE_SURROUND_FORMATS:
4931 onEnableSurroundFormats((ArrayList<Integer>) msg.obj);
4932 break;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004933 }
4934 }
4935 }
4936
Jason Parekhb1096152009-03-24 17:48:25 -07004937 private class SettingsObserver extends ContentObserver {
Eric Laurenta553c252009-07-17 12:17:14 -07004938
Jason Parekhb1096152009-03-24 17:48:25 -07004939 SettingsObserver() {
4940 super(new Handler());
Beverlyd6964762018-02-16 14:07:03 -05004941 mContentResolver.registerContentObserver(Settings.Global.getUriFor(
4942 Settings.Global.ZEN_MODE), false, this);
4943 mContentResolver.registerContentObserver(Settings.Global.getUriFor(
4944 Settings.Global.ZEN_MODE_CONFIG_ETAG), false, this);
Jason Parekhb1096152009-03-24 17:48:25 -07004945 mContentResolver.registerContentObserver(Settings.System.getUriFor(
4946 Settings.System.MODE_RINGER_STREAMS_AFFECTED), false, this);
Eric Laurent7ee1e4f2012-10-26 18:11:21 -07004947 mContentResolver.registerContentObserver(Settings.Global.getUriFor(
4948 Settings.Global.DOCK_AUDIO_MEDIA_ENABLED), false, this);
Andy Hung7b98e9a2016-02-25 18:34:50 -08004949 mContentResolver.registerContentObserver(Settings.System.getUriFor(
4950 Settings.System.MASTER_MONO), false, this);
Phil Burked43bf52016-03-01 17:01:35 -08004951
4952 mEncodedSurroundMode = Settings.Global.getInt(
4953 mContentResolver, Settings.Global.ENCODED_SURROUND_OUTPUT,
4954 Settings.Global.ENCODED_SURROUND_OUTPUT_AUTO);
4955 mContentResolver.registerContentObserver(Settings.Global.getUriFor(
4956 Settings.Global.ENCODED_SURROUND_OUTPUT), false, this);
jiabin39940752018-04-02 18:18:45 -07004957
4958 mEnabledSurroundFormats = Settings.Global.getString(
4959 mContentResolver, Settings.Global.ENCODED_SURROUND_OUTPUT_ENABLED_FORMATS);
4960 mContentResolver.registerContentObserver(Settings.Global.getUriFor(
4961 Settings.Global.ENCODED_SURROUND_OUTPUT_ENABLED_FORMATS), false, this);
Eric Laurent1c9c1d52018-10-17 10:06:46 -07004962
4963 mContentResolver.registerContentObserver(Settings.Secure.getUriFor(
4964 Settings.Secure.VOICE_INTERACTION_SERVICE), false, this);
Jason Parekhb1096152009-03-24 17:48:25 -07004965 }
4966
4967 @Override
4968 public void onChange(boolean selfChange) {
4969 super.onChange(selfChange);
Glenn Kastenba195eb2011-12-13 09:30:40 -08004970 // FIXME This synchronized is not necessary if mSettingsLock only protects mRingerMode.
Beverlyd6964762018-02-16 14:07:03 -05004971 // However there appear to be some missing locks around mRingerAndZenModeMutedStreams
Glenn Kastenba195eb2011-12-13 09:30:40 -08004972 // and mRingerModeAffectedStreams, so will leave this synchronized for now.
Beverlyd6964762018-02-16 14:07:03 -05004973 // mRingerAndZenModeMutedStreams and mMuteAffectedStreams are safe (only accessed once).
Eric Laurenta553c252009-07-17 12:17:14 -07004974 synchronized (mSettingsLock) {
Beverlyd6964762018-02-16 14:07:03 -05004975 if (updateRingerAndZenModeAffectedStreams()) {
Eric Laurenta553c252009-07-17 12:17:14 -07004976 /*
4977 * Ensure all stream types that should be affected by ringer mode
4978 * are in the proper state.
4979 */
John Spurlock661f2cf2014-11-17 10:29:10 -05004980 setRingerModeInt(getRingerModeInternal(), false);
Eric Laurenta553c252009-07-17 12:17:14 -07004981 }
Eric Laurent7ee1e4f2012-10-26 18:11:21 -07004982 readDockAudioSettings(mContentResolver);
Andy Hung7b98e9a2016-02-25 18:34:50 -08004983 updateMasterMono(mContentResolver);
Phil Burked43bf52016-03-01 17:01:35 -08004984 updateEncodedSurroundOutput();
jiabin39940752018-04-02 18:18:45 -07004985 sendEnabledSurroundFormats(mContentResolver, mSurroundModeChanged);
Eric Laurent1c9c1d52018-10-17 10:06:46 -07004986 updateAssistantUId(false);
Phil Burked43bf52016-03-01 17:01:35 -08004987 }
4988 }
4989
4990 private void updateEncodedSurroundOutput() {
4991 int newSurroundMode = Settings.Global.getInt(
4992 mContentResolver, Settings.Global.ENCODED_SURROUND_OUTPUT,
4993 Settings.Global.ENCODED_SURROUND_OUTPUT_AUTO);
4994 // Did it change?
4995 if (mEncodedSurroundMode != newSurroundMode) {
4996 // Send to AudioPolicyManager
Jean-Michel Trivi011f39e2017-08-19 18:08:06 -07004997 sendEncodedSurroundMode(newSurroundMode, "SettingsObserver");
Jean-Michel Trivi58850372018-09-14 16:01:28 -07004998 mDeviceBroker.toggleHdmiIfConnected_Async();
Phil Burked43bf52016-03-01 17:01:35 -08004999 mEncodedSurroundMode = newSurroundMode;
jiabin39940752018-04-02 18:18:45 -07005000 mSurroundModeChanged = true;
5001 } else {
5002 mSurroundModeChanged = false;
Eric Laurenta553c252009-07-17 12:17:14 -07005003 }
Jason Parekhb1096152009-03-24 17:48:25 -07005004 }
Jason Parekhb1096152009-03-24 17:48:25 -07005005 }
Eric Laurenta553c252009-07-17 12:17:14 -07005006
John Du5a0cf7a2013-07-19 11:30:34 -07005007 public void avrcpSupportsAbsoluteVolume(String address, boolean support) {
5008 // address is not used for now, but may be used when multiple a2dp devices are supported
Jean-Michel Trivi58850372018-09-14 16:01:28 -07005009 mDeviceBroker.setAvrcpAbsoluteVolumeSupported(support);
5010 sendMsg(mAudioHandler, MSG_SET_DEVICE_VOLUME, SENDMSG_QUEUE,
Eric Laurent3e6fb632018-05-21 09:28:46 -07005011 AudioSystem.DEVICE_OUT_BLUETOOTH_A2DP, 0,
5012 mStreamStates[AudioSystem.STREAM_MUSIC], 0);
Eric Laurentb1fbaac2012-05-29 09:24:28 -07005013 }
5014
Jean-Michel Trivi7db2d8f2018-03-06 10:30:59 -08005015 /**
5016 * @return true if there is currently a registered dynamic mixing policy that affects media
5017 */
Jean-Michel Trivi58850372018-09-14 16:01:28 -07005018 /*package*/ boolean hasMediaDynamicPolicy() {
Jean-Michel Trivi7db2d8f2018-03-06 10:30:59 -08005019 synchronized (mAudioPolicies) {
5020 if (mAudioPolicies.isEmpty()) {
5021 return false;
5022 }
5023 final Collection<AudioPolicyProxy> appColl = mAudioPolicies.values();
5024 for (AudioPolicyProxy app : appColl) {
5025 if (app.hasMixAffectingUsage(AudioAttributes.USAGE_MEDIA)) {
5026 return true;
5027 }
5028 }
5029 return false;
5030 }
5031 }
5032
Jean-Michel Trivi58850372018-09-14 16:01:28 -07005033 /*package*/ void checkMusicActive(int deviceType, String caller) {
5034 if ((deviceType & mSafeMediaVolumeDevices) != 0) {
5035 sendMsg(mAudioHandler,
5036 MSG_CHECK_MUSIC_ACTIVE,
5037 SENDMSG_REPLACE,
5038 0,
5039 0,
5040 caller,
5041 MUSIC_ACTIVE_POLL_PERIOD_MS);
Dianne Hackborn632ca412012-06-14 19:34:10 -07005042 }
Eric Laurenteab40d12017-06-09 12:45:21 -07005043 }
5044
Eric Laurenta553c252009-07-17 12:17:14 -07005045 /**
5046 * Receiver for misc intent broadcasts the Phone app cares about.
5047 */
5048 private class AudioServiceBroadcastReceiver extends BroadcastReceiver {
5049 @Override
5050 public void onReceive(Context context, Intent intent) {
Jean-Michel Trivi58850372018-09-14 16:01:28 -07005051 final String action = intent.getAction();
Eric Laurentae4506e2014-05-29 16:04:32 -07005052 int outDevice;
5053 int inDevice;
Eric Laurent59f48272012-04-05 19:42:21 -07005054 int state;
Eric Laurenta553c252009-07-17 12:17:14 -07005055
Jean-Michel Trivi758559e2010-03-09 09:26:08 -08005056 if (action.equals(Intent.ACTION_DOCK_EVENT)) {
5057 int dockState = intent.getIntExtra(Intent.EXTRA_DOCK_STATE,
5058 Intent.EXTRA_DOCK_STATE_UNDOCKED);
5059 int config;
5060 switch (dockState) {
5061 case Intent.EXTRA_DOCK_STATE_DESK:
5062 config = AudioSystem.FORCE_BT_DESK_DOCK;
5063 break;
5064 case Intent.EXTRA_DOCK_STATE_CAR:
5065 config = AudioSystem.FORCE_BT_CAR_DOCK;
5066 break;
Praveen Bharathi21e941b2010-10-06 15:23:14 -05005067 case Intent.EXTRA_DOCK_STATE_LE_DESK:
Eric Laurent08ed1b92012-11-05 14:54:12 -08005068 config = AudioSystem.FORCE_ANALOG_DOCK;
Praveen Bharathi21e941b2010-10-06 15:23:14 -05005069 break;
5070 case Intent.EXTRA_DOCK_STATE_HE_DESK:
5071 config = AudioSystem.FORCE_DIGITAL_DOCK;
5072 break;
Jean-Michel Trivi758559e2010-03-09 09:26:08 -08005073 case Intent.EXTRA_DOCK_STATE_UNDOCKED:
5074 default:
5075 config = AudioSystem.FORCE_NONE;
5076 }
Eric Laurent08ed1b92012-11-05 14:54:12 -08005077 // Low end docks have a menu to enable or disable audio
5078 // (see mDockAudioMediaEnabled)
Jean-Michel Trivi58850372018-09-14 16:01:28 -07005079 if (!((dockState == Intent.EXTRA_DOCK_STATE_LE_DESK)
5080 || ((dockState == Intent.EXTRA_DOCK_STATE_UNDOCKED)
5081 && (mDockState == Intent.EXTRA_DOCK_STATE_LE_DESK)))) {
5082 mDeviceBroker.setForceUse_Async(AudioSystem.FOR_DOCK, config,
5083 "ACTION_DOCK_EVENT intent");
Eric Laurent08ed1b92012-11-05 14:54:12 -08005084 }
5085 mDockState = dockState;
Jean-Michel Trivi58850372018-09-14 16:01:28 -07005086 } else if (action.equals(BluetoothHeadset.ACTION_ACTIVE_DEVICE_CHANGED)
5087 || action.equals(BluetoothHeadset.ACTION_AUDIO_STATE_CHANGED)) {
5088 mDeviceBroker.receiveBtEvent(intent);
Eric Laurent950e8cb2011-10-13 08:57:54 -07005089 } else if (action.equals(Intent.ACTION_SCREEN_ON)) {
Jon Eklund318f0fe2014-01-23 17:53:48 -06005090 if (mMonitorRotation) {
Jean-Michel Trivi24806db2015-10-01 15:00:59 -07005091 RotationHelper.enable();
Jon Eklund318f0fe2014-01-23 17:53:48 -06005092 }
Eric Laurent950e8cb2011-10-13 08:57:54 -07005093 AudioSystem.setParameters("screen_state=on");
5094 } else if (action.equals(Intent.ACTION_SCREEN_OFF)) {
Jon Eklund318f0fe2014-01-23 17:53:48 -06005095 if (mMonitorRotation) {
5096 //reduce wakeups (save current) by only listening when display is on
Jean-Michel Trivi24806db2015-10-01 15:00:59 -07005097 RotationHelper.disable();
Jon Eklund318f0fe2014-01-23 17:53:48 -06005098 }
Eric Laurent950e8cb2011-10-13 08:57:54 -07005099 AudioSystem.setParameters("screen_state=off");
Dianne Hackborn961cae92013-03-20 14:59:43 -07005100 } else if (action.equals(Intent.ACTION_CONFIGURATION_CHANGED)) {
Jean-Michel Trivif26f0172012-04-25 16:23:20 -07005101 handleConfigurationChanged(context);
Eric Laurentbc0fab1f2012-09-19 11:24:41 -07005102 } else if (action.equals(Intent.ACTION_USER_SWITCHED)) {
Yasuhiro Matsuda4ced7192015-07-10 22:08:44 +09005103 if (mUserSwitchedReceived) {
5104 // attempt to stop music playback for background user except on first user
5105 // switch (i.e. first boot)
Jean-Michel Trivi58850372018-09-14 16:01:28 -07005106 mDeviceBroker.broadcastBecomingNoisy();
Yasuhiro Matsuda4ced7192015-07-10 22:08:44 +09005107 }
5108 mUserSwitchedReceived = true;
Jean-Michel Trivif4a8eb22012-10-29 12:42:55 -07005109 // the current audio focus owner is no longer valid
Jean-Michel Trivifa9a6982013-06-27 16:22:58 -07005110 mMediaFocusControl.discardAudioFocusOwner();
Jean-Michel Trivif4a8eb22012-10-29 12:42:55 -07005111
Eric Laurent5bfaeae2012-09-21 18:44:48 -07005112 // load volume settings for new user
Eric Laurentbc0fab1f2012-09-19 11:24:41 -07005113 readAudioSettings(true /*userSwitch*/);
5114 // preserve STREAM_MUSIC volume from one user to the next.
5115 sendMsg(mAudioHandler,
5116 MSG_SET_ALL_VOLUMES,
5117 SENDMSG_QUEUE,
5118 0,
5119 0,
5120 mStreamStates[AudioSystem.STREAM_MUSIC], 0);
Fyodor Kupolovb5013302015-04-17 17:59:14 -07005121 } else if (action.equals(Intent.ACTION_USER_BACKGROUND)) {
5122 // Disable audio recording for the background user/profile
5123 int userId = intent.getIntExtra(Intent.EXTRA_USER_HANDLE, -1);
5124 if (userId >= 0) {
5125 // TODO Kill recording streams instead of killing processes holding permission
5126 UserInfo userInfo = UserManagerService.getInstance().getUserInfo(userId);
5127 killBackgroundUserProcessesWithRecordAudioPermission(userInfo);
5128 }
Makoto Onukiac65e1e2015-11-20 15:33:17 -08005129 UserManagerService.getInstance().setUserRestriction(
Fyodor Kupolovb5013302015-04-17 17:59:14 -07005130 UserManager.DISALLOW_RECORD_AUDIO, true, userId);
5131 } else if (action.equals(Intent.ACTION_USER_FOREGROUND)) {
5132 // Enable audio recording for foreground user/profile
5133 int userId = intent.getIntExtra(Intent.EXTRA_USER_HANDLE, -1);
Makoto Onukiac65e1e2015-11-20 15:33:17 -08005134 UserManagerService.getInstance().setUserRestriction(
Fyodor Kupolovb5013302015-04-17 17:59:14 -07005135 UserManager.DISALLOW_RECORD_AUDIO, false, userId);
Eric Laurentb70b78a2016-01-13 19:16:04 -08005136 } else if (action.equals(BluetoothAdapter.ACTION_STATE_CHANGED)) {
5137 state = intent.getIntExtra(BluetoothAdapter.EXTRA_STATE, -1);
5138 if (state == BluetoothAdapter.STATE_OFF ||
5139 state == BluetoothAdapter.STATE_TURNING_OFF) {
Jean-Michel Trivi58850372018-09-14 16:01:28 -07005140 mDeviceBroker.disconnectAllBluetoothProfiles();
Eric Laurentb70b78a2016-01-13 19:16:04 -08005141 }
Marco Nelissenfb6df0b2017-02-15 15:25:24 -08005142 } else if (action.equals(AudioEffect.ACTION_OPEN_AUDIO_EFFECT_CONTROL_SESSION) ||
5143 action.equals(AudioEffect.ACTION_CLOSE_AUDIO_EFFECT_CONTROL_SESSION)) {
5144 handleAudioEffectBroadcast(context, intent);
Eric Laurenta553c252009-07-17 12:17:14 -07005145 }
5146 }
Paul McLeanc837a452014-04-09 09:04:43 -07005147 } // end class AudioServiceBroadcastReceiver
Jean-Michel Trivid5176cf2010-01-28 11:56:42 -08005148
Makoto Onukid45a4a22015-11-02 17:17:38 -08005149 private class AudioServiceUserRestrictionsListener implements UserRestrictionsListener {
5150
5151 @Override
5152 public void onUserRestrictionsChanged(int userId, Bundle newRestrictions,
5153 Bundle prevRestrictions) {
5154 // Update mic mute state.
5155 {
5156 final boolean wasRestricted =
5157 prevRestrictions.getBoolean(UserManager.DISALLOW_UNMUTE_MICROPHONE);
5158 final boolean isRestricted =
5159 newRestrictions.getBoolean(UserManager.DISALLOW_UNMUTE_MICROPHONE);
5160 if (wasRestricted != isRestricted) {
5161 setMicrophoneMuteNoCallerCheck(isRestricted, userId);
5162 }
5163 }
5164
5165 // Update speaker mute state.
5166 {
5167 final boolean wasRestricted =
Tony Makc1205112016-07-22 16:02:59 +01005168 prevRestrictions.getBoolean(UserManager.DISALLOW_ADJUST_VOLUME)
Esteban Talavera492b4722017-02-13 14:59:45 +00005169 || prevRestrictions.getBoolean(UserManager.DISALLOW_UNMUTE_DEVICE);
Makoto Onukid45a4a22015-11-02 17:17:38 -08005170 final boolean isRestricted =
Tony Makc1205112016-07-22 16:02:59 +01005171 newRestrictions.getBoolean(UserManager.DISALLOW_ADJUST_VOLUME)
Esteban Talavera492b4722017-02-13 14:59:45 +00005172 || newRestrictions.getBoolean(UserManager.DISALLOW_UNMUTE_DEVICE);
Makoto Onukid45a4a22015-11-02 17:17:38 -08005173 if (wasRestricted != isRestricted) {
5174 setMasterMuteInternalNoCallerCheck(isRestricted, /* flags =*/ 0, userId);
5175 }
5176 }
5177 }
5178 } // end class AudioServiceUserRestrictionsListener
5179
Marco Nelissenfb6df0b2017-02-15 15:25:24 -08005180 private void handleAudioEffectBroadcast(Context context, Intent intent) {
5181 String target = intent.getPackage();
5182 if (target != null) {
5183 Log.w(TAG, "effect broadcast already targeted to " + target);
5184 return;
5185 }
5186 intent.addFlags(Intent.FLAG_INCLUDE_STOPPED_PACKAGES);
5187 // TODO this should target a user-selected panel
5188 List<ResolveInfo> ril = context.getPackageManager().queryBroadcastReceivers(
5189 intent, 0 /* flags */);
5190 if (ril != null && ril.size() != 0) {
5191 ResolveInfo ri = ril.get(0);
5192 if (ri != null && ri.activityInfo != null && ri.activityInfo.packageName != null) {
5193 intent.setPackage(ri.activityInfo.packageName);
5194 context.sendBroadcastAsUser(intent, UserHandle.ALL);
5195 return;
5196 }
5197 }
5198 Log.w(TAG, "couldn't find receiver package for effect intent");
5199 }
5200
Fyodor Kupolovb5013302015-04-17 17:59:14 -07005201 private void killBackgroundUserProcessesWithRecordAudioPermission(UserInfo oldUser) {
5202 PackageManager pm = mContext.getPackageManager();
5203 // Find the home activity of the user. It should not be killed to avoid expensive restart,
5204 // when the user switches back. For managed profiles, we should kill all recording apps
5205 ComponentName homeActivityName = null;
5206 if (!oldUser.isManagedProfile()) {
Wale Ogunwale6767eae2018-05-03 15:52:51 -07005207 homeActivityName = LocalServices.getService(
5208 ActivityTaskManagerInternal.class).getHomeActivityForUser(oldUser.id);
Fyodor Kupolovb5013302015-04-17 17:59:14 -07005209 }
5210 final String[] permissions = { Manifest.permission.RECORD_AUDIO };
5211 List<PackageInfo> packages;
5212 try {
5213 packages = AppGlobals.getPackageManager()
5214 .getPackagesHoldingPermissions(permissions, 0, oldUser.id).getList();
5215 } catch (RemoteException e) {
5216 throw new AndroidRuntimeException(e);
5217 }
5218 for (int j = packages.size() - 1; j >= 0; j--) {
5219 PackageInfo pkg = packages.get(j);
Fyodor Kupolovbcb6c1e2015-05-11 12:05:15 -07005220 // Skip system processes
5221 if (UserHandle.getAppId(pkg.applicationInfo.uid) < FIRST_APPLICATION_UID) {
5222 continue;
5223 }
Amith Yamasanic1cbaab2015-07-21 11:46:14 -07005224 // Skip packages that have permission to interact across users
5225 if (pm.checkPermission(Manifest.permission.INTERACT_ACROSS_USERS, pkg.packageName)
5226 == PackageManager.PERMISSION_GRANTED) {
5227 continue;
5228 }
Fyodor Kupolovb5013302015-04-17 17:59:14 -07005229 if (homeActivityName != null
5230 && pkg.packageName.equals(homeActivityName.getPackageName())
5231 && pkg.applicationInfo.isSystemApp()) {
5232 continue;
5233 }
5234 try {
Svetoslavaa41add2015-08-06 15:03:55 -07005235 final int uid = pkg.applicationInfo.uid;
Sudheer Shankadc589ac2016-11-10 15:30:17 -08005236 ActivityManager.getService().killUid(UserHandle.getAppId(uid),
Svetoslavaa41add2015-08-06 15:03:55 -07005237 UserHandle.getUserId(uid),
Fyodor Kupolovb5013302015-04-17 17:59:14 -07005238 "killBackgroundUserProcessesWithAudioRecordPermission");
5239 } catch (RemoteException e) {
5240 Log.w(TAG, "Error calling killUid", e);
5241 }
5242 }
5243 }
5244
Jean-Michel Trivi3114ce32012-06-11 15:03:52 -07005245
Jean-Michel Trivifa9a6982013-06-27 16:22:58 -07005246 //==========================================================================================
5247 // Audio Focus
5248 //==========================================================================================
Jean-Michel Trivi9228af62018-01-05 17:06:17 -08005249 /**
5250 * Returns whether a focus request is eligible to force ducking.
5251 * Will return true if:
5252 * - the AudioAttributes have a usage of USAGE_ASSISTANCE_ACCESSIBILITY,
5253 * - the focus request is AUDIOFOCUS_GAIN_TRANSIENT_MAY_DUCK,
5254 * - the associated Bundle has KEY_ACCESSIBILITY_FORCE_FOCUS_DUCKING set to true,
5255 * - the uid of the requester is a known accessibility service or root.
5256 * @param aa AudioAttributes of the focus request
5257 * @param uid uid of the focus requester
5258 * @return true if ducking is to be forced
5259 */
5260 private boolean forceFocusDuckingForAccessibility(@Nullable AudioAttributes aa,
5261 int request, int uid) {
5262 if (aa == null || aa.getUsage() != AudioAttributes.USAGE_ASSISTANCE_ACCESSIBILITY
5263 || request != AudioManager.AUDIOFOCUS_GAIN_TRANSIENT_MAY_DUCK) {
5264 return false;
5265 }
5266 final Bundle extraInfo = aa.getBundle();
5267 if (extraInfo == null ||
5268 !extraInfo.getBoolean(AudioFocusRequest.KEY_ACCESSIBILITY_FORCE_FOCUS_DUCKING)) {
5269 return false;
5270 }
5271 if (uid == 0) {
5272 return true;
5273 }
5274 synchronized (mAccessibilityServiceUidsLock) {
5275 if (mAccessibilityServiceUids != null) {
5276 int callingUid = Binder.getCallingUid();
5277 for (int i = 0; i < mAccessibilityServiceUids.length; i++) {
5278 if (mAccessibilityServiceUids[i] == callingUid) {
5279 return true;
5280 }
5281 }
5282 }
5283 }
5284 return false;
5285 }
5286
Jean-Michel Trivifd6ad742014-11-10 14:38:30 -08005287 public int requestAudioFocus(AudioAttributes aa, int durationHint, IBinder cb,
Jean-Michel Trivi958876f2014-11-16 15:40:22 -08005288 IAudioFocusDispatcher fd, String clientId, String callingPackageName, int flags,
Jean-Michel Trivi461922f2017-04-25 15:23:17 -07005289 IAudioPolicyCallback pcb, int sdk) {
Jean-Michel Trivi958876f2014-11-16 15:40:22 -08005290 // permission checks
5291 if ((flags & AudioManager.AUDIOFOCUS_FLAG_LOCK) == AudioManager.AUDIOFOCUS_FLAG_LOCK) {
John Spurlock61560172015-02-06 19:46:04 -05005292 if (AudioSystem.IN_VOICE_COMM_FOCUS_ID.equals(clientId)) {
Jean-Michel Trivi958876f2014-11-16 15:40:22 -08005293 if (PackageManager.PERMISSION_GRANTED != mContext.checkCallingOrSelfPermission(
5294 android.Manifest.permission.MODIFY_PHONE_STATE)) {
5295 Log.e(TAG, "Invalid permission to (un)lock audio focus", new Exception());
5296 return AudioManager.AUDIOFOCUS_REQUEST_FAILED;
5297 }
5298 } else {
5299 // only a registered audio policy can be used to lock focus
5300 synchronized (mAudioPolicies) {
Jean-Michel Trivi0212be52014-11-24 14:43:10 -08005301 if (!mAudioPolicies.containsKey(pcb.asBinder())) {
5302 Log.e(TAG, "Invalid unregistered AudioPolicy to (un)lock audio focus");
Jean-Michel Trivi958876f2014-11-16 15:40:22 -08005303 return AudioManager.AUDIOFOCUS_REQUEST_FAILED;
5304 }
5305 }
5306 }
5307 }
5308
Jean-Michel Trivifd6ad742014-11-10 14:38:30 -08005309 return mMediaFocusControl.requestAudioFocus(aa, durationHint, cb, fd,
Jean-Michel Trivi9228af62018-01-05 17:06:17 -08005310 clientId, callingPackageName, flags, sdk,
5311 forceFocusDuckingForAccessibility(aa, durationHint, Binder.getCallingUid()));
Jean-Michel Trivifa9a6982013-06-27 16:22:58 -07005312 }
5313
Jean-Michel Trivi126cf032017-04-02 23:19:02 -07005314 public int abandonAudioFocus(IAudioFocusDispatcher fd, String clientId, AudioAttributes aa,
5315 String callingPackageName) {
5316 return mMediaFocusControl.abandonAudioFocus(fd, clientId, aa, callingPackageName);
Jean-Michel Trivifa9a6982013-06-27 16:22:58 -07005317 }
5318
5319 public void unregisterAudioFocusClient(String clientId) {
5320 mMediaFocusControl.unregisterAudioFocusClient(clientId);
Jean-Michel Trivi3114ce32012-06-11 15:03:52 -07005321 }
5322
Jean-Michel Trivi23805662013-07-31 14:19:18 -07005323 public int getCurrentAudioFocus() {
5324 return mMediaFocusControl.getCurrentAudioFocus();
5325 }
5326
Jean-Michel Trivi99489cc2017-01-25 19:08:49 -08005327 public int getFocusRampTimeMs(int focusGain, AudioAttributes attr) {
5328 return mMediaFocusControl.getFocusRampTimeMs(focusGain, attr);
5329 }
5330
Jean-Michel Trivi126cf032017-04-02 23:19:02 -07005331 //==========================================================================================
John Spurlock5e783732015-02-19 10:28:59 -05005332 private boolean readCameraSoundForced() {
5333 return SystemProperties.getBoolean("audio.camerasound.force", false) ||
5334 mContext.getResources().getBoolean(
5335 com.android.internal.R.bool.config_camera_sound_forced);
5336 }
5337
Jean-Michel Trivif26f0172012-04-25 16:23:20 -07005338 //==========================================================================================
5339 // Device orientation
5340 //==========================================================================================
5341 /**
Mikhail Naganovb668bc62018-02-13 13:46:38 -08005342 * Handles device configuration changes that may map to a change in rotation.
5343 * Monitoring rotation is optional, and is defined by the definition and value
5344 * of the "ro.audio.monitorRotation" system property.
Jean-Michel Trivif26f0172012-04-25 16:23:20 -07005345 */
5346 private void handleConfigurationChanged(Context context) {
5347 try {
Mikhail Naganovb668bc62018-02-13 13:46:38 -08005348 // reading new configuration "safely" (i.e. under try catch) in case anything
5349 // goes wrong.
Eric Laurentd640bd32012-09-28 18:01:48 -07005350 Configuration config = context.getResources().getConfiguration();
Eric Laurentd640bd32012-09-28 18:01:48 -07005351 sendMsg(mAudioHandler,
5352 MSG_CONFIGURE_SAFE_MEDIA_VOLUME,
5353 SENDMSG_REPLACE,
5354 0,
5355 0,
John Spurlock90874332015-03-10 16:00:54 -04005356 TAG,
Eric Laurentd640bd32012-09-28 18:01:48 -07005357 0);
Eric Laurentdd45d012012-10-08 09:04:34 -07005358
John Spurlock5e783732015-02-19 10:28:59 -05005359 boolean cameraSoundForced = readCameraSoundForced();
Eric Laurentdd45d012012-10-08 09:04:34 -07005360 synchronized (mSettingsLock) {
Jean-Michel Trivi8719a1d2017-11-06 11:52:51 -08005361 final boolean cameraSoundForcedChanged = (cameraSoundForced != mCameraSoundForced);
5362 mCameraSoundForced = cameraSoundForced;
Eric Laurent8fa4d6f2014-10-30 14:13:03 -07005363 if (cameraSoundForcedChanged) {
Muyuan Li1ed6df62016-06-18 11:16:52 -07005364 if (!mIsSingleVolume) {
Jean-Michel Trivi085346a2018-02-14 10:48:51 -08005365 synchronized (VolumeStreamState.class) {
5366 VolumeStreamState s = mStreamStates[AudioSystem.STREAM_SYSTEM_ENFORCED];
5367 if (cameraSoundForced) {
5368 s.setAllIndexesToMax();
5369 mRingerModeAffectedStreams &=
5370 ~(1 << AudioSystem.STREAM_SYSTEM_ENFORCED);
5371 } else {
5372 s.setAllIndexes(mStreamStates[AudioSystem.STREAM_SYSTEM], TAG);
5373 mRingerModeAffectedStreams |=
5374 (1 << AudioSystem.STREAM_SYSTEM_ENFORCED);
5375 }
Eric Laurent8fa4d6f2014-10-30 14:13:03 -07005376 }
5377 // take new state into account for streams muted by ringer mode
John Spurlock661f2cf2014-11-17 10:29:10 -05005378 setRingerModeInt(getRingerModeInternal(), false);
Eric Laurent8fa4d6f2014-10-30 14:13:03 -07005379 }
Jean-Michel Trivi58850372018-09-14 16:01:28 -07005380 mDeviceBroker.setForceUse_Async(AudioSystem.FOR_SYSTEM,
Eric Laurent8fa4d6f2014-10-30 14:13:03 -07005381 cameraSoundForced ?
5382 AudioSystem.FORCE_SYSTEM_ENFORCED : AudioSystem.FORCE_NONE,
Jean-Michel Trivi58850372018-09-14 16:01:28 -07005383 "handleConfigurationChanged");
Eric Laurent8fa4d6f2014-10-30 14:13:03 -07005384 sendMsg(mAudioHandler,
5385 MSG_SET_ALL_VOLUMES,
5386 SENDMSG_QUEUE,
5387 0,
5388 0,
5389 mStreamStates[AudioSystem.STREAM_SYSTEM_ENFORCED], 0);
Jean-Michel Trivi58850372018-09-14 16:01:28 -07005390
Eric Laurent8fa4d6f2014-10-30 14:13:03 -07005391 }
Eric Laurentdd45d012012-10-08 09:04:34 -07005392 }
John Spurlock3346a802014-05-20 16:25:37 -04005393 mVolumeController.setLayoutDirection(config.getLayoutDirection());
Jean-Michel Trivif26f0172012-04-25 16:23:20 -07005394 } catch (Exception e) {
Jean-Michel Trivibb6f8712013-05-23 15:02:41 -07005395 Log.e(TAG, "Error handling configuration change: ", e);
Jean-Michel Trivif26f0172012-04-25 16:23:20 -07005396 }
5397 }
5398
Jean-Michel Trivid5176cf2010-01-28 11:56:42 -08005399 @Override
Jeff Sharkey098d5802012-04-26 17:30:34 -07005400 public void setRingtonePlayer(IRingtonePlayer player) {
5401 mContext.enforceCallingOrSelfPermission(REMOTE_AUDIO_PLAYBACK, null);
5402 mRingtonePlayer = player;
5403 }
5404
5405 @Override
5406 public IRingtonePlayer getRingtonePlayer() {
5407 return mRingtonePlayer;
5408 }
5409
5410 @Override
Dianne Hackborn632ca412012-06-14 19:34:10 -07005411 public AudioRoutesInfo startWatchingRoutes(IAudioRoutesObserver observer) {
Jean-Michel Trivi58850372018-09-14 16:01:28 -07005412 return mDeviceBroker.startWatchingRoutes(observer);
Dianne Hackborn632ca412012-06-14 19:34:10 -07005413 }
5414
Eric Laurentc34dcc12012-09-10 13:51:52 -07005415
5416 //==========================================================================================
5417 // Safe media volume management.
5418 // MUSIC stream volume level is limited when headphones are connected according to safety
5419 // regulation. When the user attempts to raise the volume above the limit, a warning is
5420 // displayed and the user has to acknowlegde before the volume is actually changed.
5421 // The volume index corresponding to the limit is stored in config_safe_media_volume_index
5422 // property. Platforms with a different limit must set this property accordingly in their
5423 // overlay.
5424 //==========================================================================================
5425
Eric Laurentd640bd32012-09-28 18:01:48 -07005426 // mSafeMediaVolumeState indicates whether the media volume is limited over headphones.
5427 // It is SAFE_MEDIA_VOLUME_NOT_CONFIGURED at boot time until a network service is connected
5428 // or the configure time is elapsed. It is then set to SAFE_MEDIA_VOLUME_ACTIVE or
5429 // SAFE_MEDIA_VOLUME_DISABLED according to country option. If not SAFE_MEDIA_VOLUME_DISABLED, it
5430 // can be set to SAFE_MEDIA_VOLUME_INACTIVE by calling AudioService.disableSafeMediaVolume()
5431 // (when user opts out).
John Spurlock35134602014-07-24 18:10:48 -04005432 private static final int SAFE_MEDIA_VOLUME_NOT_CONFIGURED = 0;
5433 private static final int SAFE_MEDIA_VOLUME_DISABLED = 1;
5434 private static final int SAFE_MEDIA_VOLUME_INACTIVE = 2; // confirmed
5435 private static final int SAFE_MEDIA_VOLUME_ACTIVE = 3; // unconfirmed
hyomin.ohd0446dc2018-10-18 13:58:27 +09005436 private int mSafeMediaVolumeState;
5437 private final Object mSafeMediaVolumeStateLock = new Object();
Eric Laurentd640bd32012-09-28 18:01:48 -07005438
5439 private int mMcc = 0;
Eric Laurentc34dcc12012-09-10 13:51:52 -07005440 // mSafeMediaVolumeIndex is the cached value of config_safe_media_volume_index property
Eric Laurentd640bd32012-09-28 18:01:48 -07005441 private int mSafeMediaVolumeIndex;
John Muir8b8bddd2018-02-16 14:29:14 -08005442 // mSafeUsbMediaVolumeDbfs is the cached value of the config_safe_media_volume_usb_mB
5443 // property, divided by 100.0.
5444 private float mSafeUsbMediaVolumeDbfs;
Eric Laurentb378a13a2017-07-11 14:08:11 -07005445 // mSafeUsbMediaVolumeIndex is used for USB Headsets and is the music volume UI index
John Muir8b8bddd2018-02-16 14:29:14 -08005446 // corresponding to a gain of mSafeUsbMediaVolumeDbfs (defaulting to -37dB) in audio
5447 // flinger mixer.
Eric Laurent0e5deb32017-09-01 15:12:42 -07005448 // We remove -22 dBs from the theoretical -15dB to account for the EQ + bass boost
5449 // amplification when both effects are on with all band gains at maximum.
Eric Laurentb378a13a2017-07-11 14:08:11 -07005450 // This level corresponds to a loudness of 85 dB SPL for the warning to be displayed when
5451 // the headset is compliant to EN 60950 with a max loudness of 100dB SPL.
Eric Laurenteab40d12017-06-09 12:45:21 -07005452 private int mSafeUsbMediaVolumeIndex;
Eric Laurentc34dcc12012-09-10 13:51:52 -07005453 // mSafeMediaVolumeDevices lists the devices for which safe media volume is enforced,
Jean-Michel Trivi58850372018-09-14 16:01:28 -07005454 /*package*/ final int mSafeMediaVolumeDevices = AudioSystem.DEVICE_OUT_WIRED_HEADSET
5455 | AudioSystem.DEVICE_OUT_WIRED_HEADPHONE
5456 | AudioSystem.DEVICE_OUT_USB_HEADSET;
Eric Laurentc34dcc12012-09-10 13:51:52 -07005457 // mMusicActiveMs is the cumulative time of music activity since safe volume was disabled.
5458 // When this time reaches UNSAFE_VOLUME_MUSIC_ACTIVE_MS_MAX, the safe media volume is re-enabled
5459 // automatically. mMusicActiveMs is rounded to a multiple of MUSIC_ACTIVE_POLL_PERIOD_MS.
5460 private int mMusicActiveMs;
5461 private static final int UNSAFE_VOLUME_MUSIC_ACTIVE_MS_MAX = (20 * 3600 * 1000); // 20 hours
5462 private static final int MUSIC_ACTIVE_POLL_PERIOD_MS = 60000; // 1 minute polling interval
Eric Laurentd640bd32012-09-28 18:01:48 -07005463 private static final int SAFE_VOLUME_CONFIGURE_TIMEOUT_MS = 30000; // 30s after boot completed
Eric Laurentc34dcc12012-09-10 13:51:52 -07005464
Eric Laurenteab40d12017-06-09 12:45:21 -07005465 private int safeMediaVolumeIndex(int device) {
5466 if ((device & mSafeMediaVolumeDevices) == 0) {
5467 return MAX_STREAM_VOLUME[AudioSystem.STREAM_MUSIC];
5468 }
5469 if (device == AudioSystem.DEVICE_OUT_USB_HEADSET) {
5470 return mSafeUsbMediaVolumeIndex;
5471 } else {
5472 return mSafeMediaVolumeIndex;
5473 }
5474 }
5475
John Spurlock90874332015-03-10 16:00:54 -04005476 private void setSafeMediaVolumeEnabled(boolean on, String caller) {
hyomin.ohd0446dc2018-10-18 13:58:27 +09005477 synchronized (mSafeMediaVolumeStateLock) {
Eric Laurentd640bd32012-09-28 18:01:48 -07005478 if ((mSafeMediaVolumeState != SAFE_MEDIA_VOLUME_NOT_CONFIGURED) &&
5479 (mSafeMediaVolumeState != SAFE_MEDIA_VOLUME_DISABLED)) {
5480 if (on && (mSafeMediaVolumeState == SAFE_MEDIA_VOLUME_INACTIVE)) {
5481 mSafeMediaVolumeState = SAFE_MEDIA_VOLUME_ACTIVE;
John Spurlock90874332015-03-10 16:00:54 -04005482 enforceSafeMediaVolume(caller);
Eric Laurentd640bd32012-09-28 18:01:48 -07005483 } else if (!on && (mSafeMediaVolumeState == SAFE_MEDIA_VOLUME_ACTIVE)) {
5484 mSafeMediaVolumeState = SAFE_MEDIA_VOLUME_INACTIVE;
John Spurlockaa5ee4d2014-07-25 13:05:12 -04005485 mMusicActiveMs = 1; // nonzero = confirmed
5486 saveMusicActiveMs();
Eric Laurentd640bd32012-09-28 18:01:48 -07005487 sendMsg(mAudioHandler,
5488 MSG_CHECK_MUSIC_ACTIVE,
5489 SENDMSG_REPLACE,
5490 0,
5491 0,
John Spurlock90874332015-03-10 16:00:54 -04005492 caller,
Eric Laurentd640bd32012-09-28 18:01:48 -07005493 MUSIC_ACTIVE_POLL_PERIOD_MS);
5494 }
Eric Laurentc34dcc12012-09-10 13:51:52 -07005495 }
Eric Laurentc34dcc12012-09-10 13:51:52 -07005496 }
5497 }
5498
John Spurlock90874332015-03-10 16:00:54 -04005499 private void enforceSafeMediaVolume(String caller) {
Eric Laurentc34dcc12012-09-10 13:51:52 -07005500 VolumeStreamState streamState = mStreamStates[AudioSystem.STREAM_MUSIC];
Eric Laurentc34dcc12012-09-10 13:51:52 -07005501 int devices = mSafeMediaVolumeDevices;
5502 int i = 0;
5503
5504 while (devices != 0) {
5505 int device = 1 << i++;
5506 if ((device & devices) == 0) {
5507 continue;
5508 }
Eric Laurent42b041e2013-03-29 11:36:03 -07005509 int index = streamState.getIndex(device);
Eric Laurenteab40d12017-06-09 12:45:21 -07005510 if (index > safeMediaVolumeIndex(device)) {
5511 streamState.setIndex(safeMediaVolumeIndex(device), device, caller);
Eric Laurent42b041e2013-03-29 11:36:03 -07005512 sendMsg(mAudioHandler,
5513 MSG_SET_DEVICE_VOLUME,
5514 SENDMSG_QUEUE,
5515 device,
5516 0,
5517 streamState,
5518 0);
Eric Laurentc34dcc12012-09-10 13:51:52 -07005519 }
5520 devices &= ~device;
5521 }
5522 }
5523
5524 private boolean checkSafeMediaVolume(int streamType, int index, int device) {
hyomin.ohd0446dc2018-10-18 13:58:27 +09005525 synchronized (mSafeMediaVolumeStateLock) {
Eric Laurentd640bd32012-09-28 18:01:48 -07005526 if ((mSafeMediaVolumeState == SAFE_MEDIA_VOLUME_ACTIVE) &&
Eric Laurentc34dcc12012-09-10 13:51:52 -07005527 (mStreamVolumeAlias[streamType] == AudioSystem.STREAM_MUSIC) &&
5528 ((device & mSafeMediaVolumeDevices) != 0) &&
Eric Laurenteab40d12017-06-09 12:45:21 -07005529 (index > safeMediaVolumeIndex(device))) {
Eric Laurentc34dcc12012-09-10 13:51:52 -07005530 return false;
5531 }
5532 return true;
5533 }
5534 }
5535
John Spurlock3346a802014-05-20 16:25:37 -04005536 @Override
John Spurlock90874332015-03-10 16:00:54 -04005537 public void disableSafeMediaVolume(String callingPackage) {
John Spurlockcdb57ae2015-02-11 19:04:11 -05005538 enforceVolumeController("disable the safe media volume");
hyomin.ohd0446dc2018-10-18 13:58:27 +09005539 synchronized (mSafeMediaVolumeStateLock) {
John Spurlock90874332015-03-10 16:00:54 -04005540 setSafeMediaVolumeEnabled(false, callingPackage);
Eric Laurentfde16d52012-12-03 14:42:39 -08005541 if (mPendingVolumeCommand != null) {
5542 onSetStreamVolume(mPendingVolumeCommand.mStreamType,
5543 mPendingVolumeCommand.mIndex,
5544 mPendingVolumeCommand.mFlags,
John Spurlock90874332015-03-10 16:00:54 -04005545 mPendingVolumeCommand.mDevice,
5546 callingPackage);
Eric Laurentfde16d52012-12-03 14:42:39 -08005547 mPendingVolumeCommand = null;
5548 }
Eric Laurentc34dcc12012-09-10 13:51:52 -07005549 }
5550 }
5551
Jungshik Jang41d97462014-06-30 22:26:29 +09005552 //==========================================================================================
5553 // Hdmi Cec system audio mode.
John Spurlockbc82b122015-03-02 16:12:38 -05005554 // If Hdmi Cec's system audio mode is on, audio service should send the volume change
5555 // to HdmiControlService so that the audio receiver can handle it.
Jungshik Jang41d97462014-06-30 22:26:29 +09005556 //==========================================================================================
5557
Eric Laurent212532b2014-07-21 15:43:18 -07005558 private class MyDisplayStatusCallback implements HdmiPlaybackClient.DisplayStatusCallback {
5559 public void onComplete(int status) {
Shubangc480a712018-06-11 18:02:42 -07005560 synchronized (mHdmiClientLock) {
5561 if (mHdmiManager != null) {
Eric Laurent212532b2014-07-21 15:43:18 -07005562 mHdmiCecSink = (status != HdmiControlManager.POWER_STATUS_UNKNOWN);
5563 // Television devices without CEC service apply software volume on HDMI output
5564 if (isPlatformTelevision() && !mHdmiCecSink) {
5565 mFixedVolumeDevices &= ~AudioSystem.DEVICE_OUT_HDMI;
5566 }
5567 checkAllFixedVolumeDevices();
5568 }
5569 }
5570 }
Shubangc480a712018-06-11 18:02:42 -07005571 }
5572
5573 private final Object mHdmiClientLock = new Object();
Eric Laurent212532b2014-07-21 15:43:18 -07005574
Jungshik Jang41d97462014-06-30 22:26:29 +09005575 // If HDMI-CEC system audio is supported
5576 private boolean mHdmiSystemAudioSupported = false;
5577 // Set only when device is tv.
Shubangc480a712018-06-11 18:02:42 -07005578 @GuardedBy("mHdmiClientLock")
Jungshik Jang41d97462014-06-30 22:26:29 +09005579 private HdmiTvClient mHdmiTvClient;
Eric Laurent0b03f992014-11-18 18:08:02 -08005580 // true if the device has system feature PackageManager.FEATURE_LEANBACK.
Eric Laurent212532b2014-07-21 15:43:18 -07005581 // cached HdmiControlManager interface
Shubangc480a712018-06-11 18:02:42 -07005582 @GuardedBy("mHdmiClientLock")
Eric Laurent212532b2014-07-21 15:43:18 -07005583 private HdmiControlManager mHdmiManager;
5584 // Set only when device is a set-top box.
Shubangc480a712018-06-11 18:02:42 -07005585 @GuardedBy("mHdmiClientLock")
Eric Laurent212532b2014-07-21 15:43:18 -07005586 private HdmiPlaybackClient mHdmiPlaybackClient;
5587 // true if we are a set-top box, an HDMI sink is connected and it supports CEC.
5588 private boolean mHdmiCecSink;
Shubangc480a712018-06-11 18:02:42 -07005589 // Set only when device is an audio system.
5590 @GuardedBy("mHdmiClientLock")
5591 private HdmiAudioSystemClient mHdmiAudioSystemClient;
Eric Laurent212532b2014-07-21 15:43:18 -07005592
5593 private MyDisplayStatusCallback mHdmiDisplayStatusCallback = new MyDisplayStatusCallback();
Jungshik Jang41d97462014-06-30 22:26:29 +09005594
5595 @Override
Jungshik Jang12307ca2014-07-15 19:27:56 +09005596 public int setHdmiSystemAudioSupported(boolean on) {
Eric Laurent212532b2014-07-21 15:43:18 -07005597 int device = AudioSystem.DEVICE_NONE;
Shubangc480a712018-06-11 18:02:42 -07005598 synchronized (mHdmiClientLock) {
5599 if (mHdmiManager != null) {
Shubangde728822018-07-16 16:46:51 -07005600 if (mHdmiTvClient == null && mHdmiAudioSystemClient == null) {
5601 Log.w(TAG, "Only Hdmi-Cec enabled TV or audio system device supports"
5602 + "system audio mode.");
Eric Laurent212532b2014-07-21 15:43:18 -07005603 return device;
5604 }
Shubangc480a712018-06-11 18:02:42 -07005605 if (mHdmiSystemAudioSupported != on) {
5606 mHdmiSystemAudioSupported = on;
5607 final int config = on ? AudioSystem.FORCE_HDMI_SYSTEM_AUDIO_ENFORCED :
5608 AudioSystem.FORCE_NONE;
Jean-Michel Trivi58850372018-09-14 16:01:28 -07005609 mDeviceBroker.setForceUse_Async(AudioSystem.FOR_HDMI_SYSTEM_AUDIO, config,
5610 "setHdmiSystemAudioSupported");
Eric Laurent212532b2014-07-21 15:43:18 -07005611 }
Shubangc480a712018-06-11 18:02:42 -07005612 device = getDevicesForStream(AudioSystem.STREAM_MUSIC);
Jungshik Jang6f34f5a2014-07-08 21:17:29 +09005613 }
Jungshik Jang6f34f5a2014-07-08 21:17:29 +09005614 }
Eric Laurent212532b2014-07-21 15:43:18 -07005615 return device;
Jungshik Jang6f34f5a2014-07-08 21:17:29 +09005616 }
Jungshik Jang41d97462014-06-30 22:26:29 +09005617
Terry Heoe7d6d972014-09-04 21:05:28 +09005618 @Override
5619 public boolean isHdmiSystemAudioSupported() {
5620 return mHdmiSystemAudioSupported;
5621 }
5622
Eric Laurentdd45d012012-10-08 09:04:34 -07005623 //==========================================================================================
Jean-Michel Triviac487672016-11-11 10:05:18 -08005624 // Accessibility
5625
Jean-Michel Trivicfa55532017-01-18 11:17:51 -08005626 private void initA11yMonitoring() {
5627 final AccessibilityManager accessibilityManager =
5628 (AccessibilityManager) mContext.getSystemService(Context.ACCESSIBILITY_SERVICE);
Jean-Michel Triviac487672016-11-11 10:05:18 -08005629 updateDefaultStreamOverrideDelay(accessibilityManager.isTouchExplorationEnabled());
Jean-Michel Trivi7592b982017-02-01 15:12:15 -08005630 updateA11yVolumeAlias(accessibilityManager.isAccessibilityVolumeStreamActive());
Phil Weaver26d709f2017-04-20 17:19:14 -07005631 accessibilityManager.addTouchExplorationStateChangeListener(this, null);
5632 accessibilityManager.addAccessibilityServicesStateChangeListener(this, null);
Jean-Michel Triviac487672016-11-11 10:05:18 -08005633 }
5634
5635 //---------------------------------------------------------------------------------
5636 // A11y: taking touch exploration into account for selecting the default
Jean-Michel Trivi873cc452014-09-11 17:25:09 -07005637 // stream override timeout when adjusting volume
Jean-Michel Triviac487672016-11-11 10:05:18 -08005638 //---------------------------------------------------------------------------------
Jean-Michel Trivi873cc452014-09-11 17:25:09 -07005639
Jean-Michel Triviac487672016-11-11 10:05:18 -08005640 // - STREAM_NOTIFICATION on tablets during this period after a notification stopped
Julia Reynoldsd9e96e22017-11-07 10:33:08 -05005641 // - STREAM_RING on phones during this period after a notification stopped
5642 // - STREAM_MUSIC otherwise
5643
Jean-Michel Triviac487672016-11-11 10:05:18 -08005644 private static final int DEFAULT_STREAM_TYPE_OVERRIDE_DELAY_MS = 0;
5645 private static final int TOUCH_EXPLORE_STREAM_TYPE_OVERRIDE_DELAY_MS = 1000;
Jean-Michel Trivi873cc452014-09-11 17:25:09 -07005646
Jean-Michel Triviac487672016-11-11 10:05:18 -08005647 private static int sStreamOverrideDelayMs;
Jean-Michel Trivi873cc452014-09-11 17:25:09 -07005648
Jean-Michel Triviac487672016-11-11 10:05:18 -08005649 @Override
5650 public void onTouchExplorationStateChanged(boolean enabled) {
5651 updateDefaultStreamOverrideDelay(enabled);
5652 }
5653
5654 private void updateDefaultStreamOverrideDelay(boolean touchExploreEnabled) {
5655 if (touchExploreEnabled) {
5656 sStreamOverrideDelayMs = TOUCH_EXPLORE_STREAM_TYPE_OVERRIDE_DELAY_MS;
5657 } else {
5658 sStreamOverrideDelayMs = DEFAULT_STREAM_TYPE_OVERRIDE_DELAY_MS;
Jean-Michel Trivi873cc452014-09-11 17:25:09 -07005659 }
Jean-Michel Triviac487672016-11-11 10:05:18 -08005660 if (DEBUG_VOL) Log.d(TAG, "Touch exploration enabled=" + touchExploreEnabled
5661 + " stream override delay is now " + sStreamOverrideDelayMs + " ms");
5662 }
Jean-Michel Trivi873cc452014-09-11 17:25:09 -07005663
Jean-Michel Triviac487672016-11-11 10:05:18 -08005664 //---------------------------------------------------------------------------------
5665 // A11y: taking a11y state into account for the handling of a11y prompts volume
5666 //---------------------------------------------------------------------------------
Jean-Michel Trivi873cc452014-09-11 17:25:09 -07005667
Jean-Michel Triviac487672016-11-11 10:05:18 -08005668 private static boolean sIndependentA11yVolume = false;
5669
Jean-Michel Trivicfa55532017-01-18 11:17:51 -08005670 // implementation of AccessibilityServicesStateChangeListener
5671 @Override
Phil Weaver4cab9302017-03-30 15:27:39 -07005672 public void onAccessibilityServicesStateChanged(AccessibilityManager accessibilityManager) {
Jean-Michel Trivicfa55532017-01-18 11:17:51 -08005673 updateA11yVolumeAlias(accessibilityManager.isAccessibilityVolumeStreamActive());
5674 }
5675
5676 private void updateA11yVolumeAlias(boolean a11VolEnabled) {
5677 if (DEBUG_VOL) Log.d(TAG, "Accessibility volume enabled = " + a11VolEnabled);
5678 if (sIndependentA11yVolume != a11VolEnabled) {
5679 sIndependentA11yVolume = a11VolEnabled;
5680 // update the volume mapping scheme
5681 updateStreamVolumeAlias(true /*updateVolumes*/, TAG);
5682 // update the volume controller behavior
5683 mVolumeController.setA11yMode(sIndependentA11yVolume ?
5684 VolumePolicy.A11Y_MODE_INDEPENDENT_A11Y_VOLUME :
5685 VolumePolicy.A11Y_MODE_MEDIA_A11Y_VOLUME);
Jean-Michel Trivia53b7052017-04-12 18:27:01 -07005686 mVolumeController.postVolumeChanged(AudioManager.STREAM_ACCESSIBILITY, 0);
Jean-Michel Trivicfa55532017-01-18 11:17:51 -08005687 }
Jean-Michel Trivi873cc452014-09-11 17:25:09 -07005688 }
5689
5690 //==========================================================================================
Eric Laurentdd45d012012-10-08 09:04:34 -07005691 // Camera shutter sound policy.
5692 // config_camera_sound_forced configuration option in config.xml defines if the camera shutter
5693 // sound is forced (sound even if the device is in silent mode) or not. This option is false by
5694 // default and can be overridden by country specific overlay in values-mccXXX/config.xml.
5695 //==========================================================================================
5696
5697 // cached value of com.android.internal.R.bool.config_camera_sound_forced
Jean-Michel Trivi8719a1d2017-11-06 11:52:51 -08005698 @GuardedBy("mSettingsLock")
5699 private boolean mCameraSoundForced;
Eric Laurentdd45d012012-10-08 09:04:34 -07005700
5701 // called by android.hardware.Camera to populate CameraInfo.canDisableShutterSound
5702 public boolean isCameraSoundForced() {
Jean-Michel Trivi8719a1d2017-11-06 11:52:51 -08005703 synchronized (mSettingsLock) {
Eric Laurentdd45d012012-10-08 09:04:34 -07005704 return mCameraSoundForced;
5705 }
5706 }
5707
Jean-Michel Trivi011f39e2017-08-19 18:08:06 -07005708 //==========================================================================================
5709 // AudioService logging and dumpsys
5710 //==========================================================================================
Jean-Michel Trivi3bf75782018-07-02 10:48:04 -07005711 static final int LOG_NB_EVENTS_PHONE_STATE = 20;
5712 static final int LOG_NB_EVENTS_DEVICE_CONNECTION = 30;
5713 static final int LOG_NB_EVENTS_FORCE_USE = 20;
5714 static final int LOG_NB_EVENTS_VOLUME = 40;
5715 static final int LOG_NB_EVENTS_DYN_POLICY = 10;
Jean-Michel Trivi011f39e2017-08-19 18:08:06 -07005716
5717 final private AudioEventLogger mModeLogger = new AudioEventLogger(LOG_NB_EVENTS_PHONE_STATE,
5718 "phone state (logged after successfull call to AudioSystem.setPhoneState(int))");
5719
Jean-Michel Trivi3bf75782018-07-02 10:48:04 -07005720 // logs for wired + A2DP device connections:
5721 // - wired: logged before onSetWiredDeviceConnectionState() is executed
5722 // - A2DP: logged at reception of method call
Jean-Michel Trivi58850372018-09-14 16:01:28 -07005723 /*package*/ static final AudioEventLogger sDeviceLogger = new AudioEventLogger(
5724 LOG_NB_EVENTS_DEVICE_CONNECTION, "wired/A2DP/hearing aid device connection BLABLI");
Jean-Michel Trivi011f39e2017-08-19 18:08:06 -07005725
Jean-Michel Trivi58850372018-09-14 16:01:28 -07005726 static final AudioEventLogger sForceUseLogger = new AudioEventLogger(
Jean-Michel Trivi011f39e2017-08-19 18:08:06 -07005727 LOG_NB_EVENTS_FORCE_USE,
5728 "force use (logged before setForceUse() is executed)");
5729
Jean-Michel Trivi58850372018-09-14 16:01:28 -07005730 static final AudioEventLogger sVolumeLogger = new AudioEventLogger(LOG_NB_EVENTS_VOLUME,
Jean-Michel Trivicf170362017-08-24 17:24:57 -07005731 "volume changes (logged when command received by AudioService)");
5732
Jean-Michel Trivi12a86762018-04-24 16:57:49 -07005733 final private AudioEventLogger mDynPolicyLogger = new AudioEventLogger(LOG_NB_EVENTS_DYN_POLICY,
5734 "dynamic policy events (logged when command received by AudioService)");
5735
Eric Laurentdd45d012012-10-08 09:04:34 -07005736 private static final String[] RINGER_MODE_NAMES = new String[] {
5737 "SILENT",
5738 "VIBRATE",
5739 "NORMAL"
5740 };
5741
5742 private void dumpRingerMode(PrintWriter pw) {
5743 pw.println("\nRinger mode: ");
John Spurlock661f2cf2014-11-17 10:29:10 -05005744 pw.println("- mode (internal) = " + RINGER_MODE_NAMES[mRingerMode]);
5745 pw.println("- mode (external) = " + RINGER_MODE_NAMES[mRingerModeExternal]);
John Spurlock50ced3f2015-05-11 16:00:09 -04005746 dumpRingerModeStreams(pw, "affected", mRingerModeAffectedStreams);
Beverlyd6964762018-02-16 14:07:03 -05005747 dumpRingerModeStreams(pw, "muted", mRingerAndZenModeMutedStreams);
John Spurlock661f2cf2014-11-17 10:29:10 -05005748 pw.print("- delegate = "); pw.println(mRingerModeDelegate);
Eric Laurentdd45d012012-10-08 09:04:34 -07005749 }
5750
John Spurlock50ced3f2015-05-11 16:00:09 -04005751 private void dumpRingerModeStreams(PrintWriter pw, String type, int streams) {
5752 pw.print("- ringer mode "); pw.print(type); pw.print(" streams = 0x");
5753 pw.print(Integer.toHexString(streams));
5754 if (streams != 0) {
5755 pw.print(" (");
5756 boolean first = true;
5757 for (int i = 0; i < AudioSystem.STREAM_NAMES.length; i++) {
5758 final int stream = (1 << i);
5759 if ((streams & stream) != 0) {
5760 if (!first) pw.print(',');
5761 pw.print(AudioSystem.STREAM_NAMES[i]);
5762 streams &= ~stream;
5763 first = false;
5764 }
5765 }
5766 if (streams != 0) {
5767 if (!first) pw.print(',');
5768 pw.print(streams);
5769 }
5770 pw.print(')');
5771 }
5772 pw.println();
5773 }
5774
Dianne Hackborn632ca412012-06-14 19:34:10 -07005775 @Override
Jean-Michel Trivid5176cf2010-01-28 11:56:42 -08005776 protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
Jeff Sharkeyfe9a53b2017-03-31 14:08:23 -06005777 if (!DumpUtils.checkDumpPermission(mContext, TAG, pw)) return;
Jeff Sharkeyeb4cc4922012-04-26 18:17:29 -07005778
Jean-Michel Trivifa9a6982013-06-27 16:22:58 -07005779 mMediaFocusControl.dump(pw);
Eric Laurentbffc3d12012-05-07 17:43:49 -07005780 dumpStreamStates(pw);
Eric Laurentdd45d012012-10-08 09:04:34 -07005781 dumpRingerMode(pw);
Dianne Hackborn632ca412012-06-14 19:34:10 -07005782 pw.println("\nAudio routes:");
Jean-Michel Trivi58850372018-09-14 16:01:28 -07005783 pw.print(" mMainType=0x"); pw.println(Integer.toHexString(
5784 mDeviceBroker.getCurAudioRoutes().mainType));
5785 pw.print(" mBluetoothName="); pw.println(mDeviceBroker.getCurAudioRoutes().bluetoothName);
John Spurlock35134602014-07-24 18:10:48 -04005786
5787 pw.println("\nOther state:");
John Spurlock3346a802014-05-20 16:25:37 -04005788 pw.print(" mVolumeController="); pw.println(mVolumeController);
John Spurlock35134602014-07-24 18:10:48 -04005789 pw.print(" mSafeMediaVolumeState=");
5790 pw.println(safeMediaVolumeStateToString(mSafeMediaVolumeState));
5791 pw.print(" mSafeMediaVolumeIndex="); pw.println(mSafeMediaVolumeIndex);
Eric Laurenteab40d12017-06-09 12:45:21 -07005792 pw.print(" mSafeUsbMediaVolumeIndex="); pw.println(mSafeUsbMediaVolumeIndex);
John Muir8b8bddd2018-02-16 14:29:14 -08005793 pw.print(" mSafeUsbMediaVolumeDbfs="); pw.println(mSafeUsbMediaVolumeDbfs);
Jean-Michel Trivi7592b982017-02-01 15:12:15 -08005794 pw.print(" sIndependentA11yVolume="); pw.println(sIndependentA11yVolume);
John Spurlock35134602014-07-24 18:10:48 -04005795 pw.print(" mPendingVolumeCommand="); pw.println(mPendingVolumeCommand);
5796 pw.print(" mMusicActiveMs="); pw.println(mMusicActiveMs);
John Spurlockaa5ee4d2014-07-25 13:05:12 -04005797 pw.print(" mMcc="); pw.println(mMcc);
John Spurlock5e783732015-02-19 10:28:59 -05005798 pw.print(" mCameraSoundForced="); pw.println(mCameraSoundForced);
John Spurlock661f2cf2014-11-17 10:29:10 -05005799 pw.print(" mHasVibrator="); pw.println(mHasVibrator);
John Spurlocka48d7792015-03-03 17:35:57 -05005800 pw.print(" mVolumePolicy="); pw.println(mVolumePolicy);
Jean-Michel Trivi58850372018-09-14 16:01:28 -07005801 pw.print(" mAvrcpAbsVolSupported=");
5802 pw.println(mDeviceBroker.isAvrcpAbsoluteVolumeSupported());
Jean-Michel Trivi1b3541d2014-11-25 12:53:41 -08005803
5804 dumpAudioPolicies(pw);
Jean-Michel Trivi12a86762018-04-24 16:57:49 -07005805 mDynPolicyLogger.dump(pw);
Jean-Michel Trivi292a6a42016-12-01 08:32:15 -08005806
5807 mPlaybackMonitor.dump(pw);
Jean-Michel Trivi66ffacf2017-02-04 17:25:31 -08005808
5809 mRecordMonitor.dump(pw);
Jean-Michel Trivi011f39e2017-08-19 18:08:06 -07005810
Jean-Michel Trivicf170362017-08-24 17:24:57 -07005811 pw.println("\n");
Jean-Michel Trivi011f39e2017-08-19 18:08:06 -07005812 pw.println("\nEvent logs:");
5813 mModeLogger.dump(pw);
5814 pw.println("\n");
Jean-Michel Trivi58850372018-09-14 16:01:28 -07005815 sDeviceLogger.dump(pw);
Jean-Michel Trivi011f39e2017-08-19 18:08:06 -07005816 pw.println("\n");
Jean-Michel Trivi58850372018-09-14 16:01:28 -07005817 sForceUseLogger.dump(pw);
Jean-Michel Trivicf170362017-08-24 17:24:57 -07005818 pw.println("\n");
Jean-Michel Trivi58850372018-09-14 16:01:28 -07005819 sVolumeLogger.dump(pw);
John Spurlock35134602014-07-24 18:10:48 -04005820 }
5821
hyomin.ohd0446dc2018-10-18 13:58:27 +09005822 private static String safeMediaVolumeStateToString(int state) {
John Spurlock35134602014-07-24 18:10:48 -04005823 switch(state) {
5824 case SAFE_MEDIA_VOLUME_NOT_CONFIGURED: return "SAFE_MEDIA_VOLUME_NOT_CONFIGURED";
5825 case SAFE_MEDIA_VOLUME_DISABLED: return "SAFE_MEDIA_VOLUME_DISABLED";
5826 case SAFE_MEDIA_VOLUME_INACTIVE: return "SAFE_MEDIA_VOLUME_INACTIVE";
5827 case SAFE_MEDIA_VOLUME_ACTIVE: return "SAFE_MEDIA_VOLUME_ACTIVE";
5828 }
5829 return null;
Jean-Michel Trivid5176cf2010-01-28 11:56:42 -08005830 }
Glenn Kastenfd116ad2013-07-12 17:10:39 -07005831
5832 // Inform AudioFlinger of our device's low RAM attribute
5833 private static void readAndSetLowRamDevice()
5834 {
Andy Hung79583582018-01-23 13:58:02 -08005835 boolean isLowRamDevice = ActivityManager.isLowRamDeviceStatic();
5836 long totalMemory = 1024 * 1024 * 1024; // 1GB is the default if ActivityManager fails.
5837
5838 try {
5839 final ActivityManager.MemoryInfo info = new ActivityManager.MemoryInfo();
5840 ActivityManager.getService().getMemoryInfo(info);
5841 totalMemory = info.totalMem;
5842 } catch (RemoteException e) {
5843 Log.w(TAG, "Cannot obtain MemoryInfo from ActivityManager, assume low memory device");
5844 isLowRamDevice = true;
5845 }
5846
5847 final int status = AudioSystem.setLowRamDevice(isLowRamDevice, totalMemory);
Glenn Kastenfd116ad2013-07-12 17:10:39 -07005848 if (status != 0) {
5849 Log.w(TAG, "AudioFlinger informed of device's low RAM attribute; status " + status);
5850 }
5851 }
John Spurlock3346a802014-05-20 16:25:37 -04005852
John Spurlockcdb57ae2015-02-11 19:04:11 -05005853 private void enforceVolumeController(String action) {
John Spurlock3346a802014-05-20 16:25:37 -04005854 mContext.enforceCallingOrSelfPermission(android.Manifest.permission.STATUS_BAR_SERVICE,
5855 "Only SystemUI can " + action);
5856 }
5857
5858 @Override
5859 public void setVolumeController(final IVolumeController controller) {
John Spurlockcdb57ae2015-02-11 19:04:11 -05005860 enforceVolumeController("set the volume controller");
John Spurlock3346a802014-05-20 16:25:37 -04005861
5862 // return early if things are not actually changing
5863 if (mVolumeController.isSameBinder(controller)) {
5864 return;
5865 }
5866
5867 // dismiss the old volume controller
5868 mVolumeController.postDismiss();
5869 if (controller != null) {
5870 // we are about to register a new controller, listen for its death
5871 try {
5872 controller.asBinder().linkToDeath(new DeathRecipient() {
5873 @Override
5874 public void binderDied() {
5875 if (mVolumeController.isSameBinder(controller)) {
5876 Log.w(TAG, "Current remote volume controller died, unregistering");
5877 setVolumeController(null);
5878 }
5879 }
5880 }, 0);
5881 } catch (RemoteException e) {
5882 // noop
5883 }
5884 }
5885 mVolumeController.setController(controller);
John Spurlock33f4e042014-07-11 13:10:58 -04005886 if (DEBUG_VOL) Log.d(TAG, "Volume controller: " + mVolumeController);
5887 }
5888
5889 @Override
5890 public void notifyVolumeControllerVisible(final IVolumeController controller, boolean visible) {
John Spurlockcdb57ae2015-02-11 19:04:11 -05005891 enforceVolumeController("notify about volume controller visibility");
John Spurlock33f4e042014-07-11 13:10:58 -04005892
5893 // return early if the controller is not current
5894 if (!mVolumeController.isSameBinder(controller)) {
5895 return;
5896 }
5897
5898 mVolumeController.setVisible(visible);
5899 if (DEBUG_VOL) Log.d(TAG, "Volume controller visible: " + visible);
John Spurlock3346a802014-05-20 16:25:37 -04005900 }
RoboErikd09bd0c2014-06-24 17:45:19 -07005901
John Spurlocka48d7792015-03-03 17:35:57 -05005902 @Override
5903 public void setVolumePolicy(VolumePolicy policy) {
5904 enforceVolumeController("set volume policy");
John Spurlockb02c7442015-04-14 09:32:25 -04005905 if (policy != null && !policy.equals(mVolumePolicy)) {
John Spurlocka48d7792015-03-03 17:35:57 -05005906 mVolumePolicy = policy;
John Spurlockb02c7442015-04-14 09:32:25 -04005907 if (DEBUG_VOL) Log.d(TAG, "Volume policy changed: " + mVolumePolicy);
John Spurlocka48d7792015-03-03 17:35:57 -05005908 }
5909 }
5910
RoboErikd09bd0c2014-06-24 17:45:19 -07005911 public static class VolumeController {
5912 private static final String TAG = "VolumeController";
5913
5914 private IVolumeController mController;
John Spurlock33f4e042014-07-11 13:10:58 -04005915 private boolean mVisible;
5916 private long mNextLongPress;
5917 private int mLongPressTimeout;
RoboErikd09bd0c2014-06-24 17:45:19 -07005918
5919 public void setController(IVolumeController controller) {
5920 mController = controller;
John Spurlock33f4e042014-07-11 13:10:58 -04005921 mVisible = false;
5922 }
5923
5924 public void loadSettings(ContentResolver cr) {
5925 mLongPressTimeout = Settings.Secure.getIntForUser(cr,
5926 Settings.Secure.LONG_PRESS_TIMEOUT, 500, UserHandle.USER_CURRENT);
5927 }
5928
RoboErik4197cb62015-01-21 15:45:32 -08005929 public boolean suppressAdjustment(int resolvedStream, int flags, boolean isMute) {
5930 if (isMute) {
5931 return false;
5932 }
John Spurlock33f4e042014-07-11 13:10:58 -04005933 boolean suppress = false;
Julia Reynoldseb0ce472018-05-04 15:34:55 -04005934 if (resolvedStream == DEFAULT_VOL_STREAM_NO_PLAYBACK && mController != null) {
John Spurlock33f4e042014-07-11 13:10:58 -04005935 final long now = SystemClock.uptimeMillis();
5936 if ((flags & AudioManager.FLAG_SHOW_UI) != 0 && !mVisible) {
5937 // ui will become visible
5938 if (mNextLongPress < now) {
5939 mNextLongPress = now + mLongPressTimeout;
5940 }
5941 suppress = true;
5942 } else if (mNextLongPress > 0) { // in a long-press
5943 if (now > mNextLongPress) {
5944 // long press triggered, no more suppression
5945 mNextLongPress = 0;
5946 } else {
5947 // keep suppressing until the long press triggers
5948 suppress = true;
5949 }
5950 }
5951 }
5952 return suppress;
5953 }
5954
5955 public void setVisible(boolean visible) {
5956 mVisible = visible;
RoboErikd09bd0c2014-06-24 17:45:19 -07005957 }
5958
5959 public boolean isSameBinder(IVolumeController controller) {
5960 return Objects.equals(asBinder(), binder(controller));
5961 }
5962
5963 public IBinder asBinder() {
5964 return binder(mController);
5965 }
5966
5967 private static IBinder binder(IVolumeController controller) {
5968 return controller == null ? null : controller.asBinder();
5969 }
5970
5971 @Override
5972 public String toString() {
John Spurlock33f4e042014-07-11 13:10:58 -04005973 return "VolumeController(" + asBinder() + ",mVisible=" + mVisible + ")";
RoboErikd09bd0c2014-06-24 17:45:19 -07005974 }
5975
5976 public void postDisplaySafeVolumeWarning(int flags) {
5977 if (mController == null)
5978 return;
5979 try {
5980 mController.displaySafeVolumeWarning(flags);
5981 } catch (RemoteException e) {
5982 Log.w(TAG, "Error calling displaySafeVolumeWarning", e);
5983 }
5984 }
5985
5986 public void postVolumeChanged(int streamType, int flags) {
5987 if (mController == null)
5988 return;
5989 try {
5990 mController.volumeChanged(streamType, flags);
5991 } catch (RemoteException e) {
5992 Log.w(TAG, "Error calling volumeChanged", e);
5993 }
5994 }
5995
RoboErikd09bd0c2014-06-24 17:45:19 -07005996 public void postMasterMuteChanged(int flags) {
5997 if (mController == null)
5998 return;
5999 try {
6000 mController.masterMuteChanged(flags);
6001 } catch (RemoteException e) {
6002 Log.w(TAG, "Error calling masterMuteChanged", e);
6003 }
6004 }
6005
6006 public void setLayoutDirection(int layoutDirection) {
6007 if (mController == null)
6008 return;
6009 try {
6010 mController.setLayoutDirection(layoutDirection);
6011 } catch (RemoteException e) {
6012 Log.w(TAG, "Error calling setLayoutDirection", e);
6013 }
6014 }
6015
6016 public void postDismiss() {
6017 if (mController == null)
6018 return;
6019 try {
6020 mController.dismiss();
6021 } catch (RemoteException e) {
6022 Log.w(TAG, "Error calling dismiss", e);
6023 }
6024 }
Jean-Michel Triviac487672016-11-11 10:05:18 -08006025
6026 public void setA11yMode(int a11yMode) {
6027 if (mController == null)
6028 return;
6029 try {
6030 mController.setA11yMode(a11yMode);
6031 } catch (RemoteException e) {
6032 Log.w(TAG, "Error calling setA11Mode", e);
6033 }
6034 }
RoboErikd09bd0c2014-06-24 17:45:19 -07006035 }
Jean-Michel Trivia8b6bd82014-07-01 09:48:46 -07006036
RoboErik0dac35a2014-08-12 15:48:49 -07006037 /**
6038 * Interface for system components to get some extra functionality through
6039 * LocalServices.
6040 */
6041 final class AudioServiceInternal extends AudioManagerInternal {
John Spurlock661f2cf2014-11-17 10:29:10 -05006042 @Override
6043 public void setRingerModeDelegate(RingerModeDelegate delegate) {
6044 mRingerModeDelegate = delegate;
6045 if (mRingerModeDelegate != null) {
Jean-Michel Trivi8719a1d2017-11-06 11:52:51 -08006046 synchronized (mSettingsLock) {
Beverlyd6964762018-02-16 14:07:03 -05006047 updateRingerAndZenModeAffectedStreams();
Jean-Michel Trivi8719a1d2017-11-06 11:52:51 -08006048 }
John Spurlock661f2cf2014-11-17 10:29:10 -05006049 setRingerModeInternal(getRingerModeInternal(), TAG + ".setRingerModeDelegate");
6050 }
6051 }
RoboErik272e1612014-09-05 11:39:29 -07006052
6053 @Override
6054 public void adjustSuggestedStreamVolumeForUid(int streamType, int direction, int flags,
6055 String callingPackage, int uid) {
6056 // direction and stream type swap here because the public
6057 // adjustSuggested has a different order than the other methods.
John Spurlock90874332015-03-10 16:00:54 -04006058 adjustSuggestedStreamVolume(direction, streamType, flags, callingPackage,
6059 callingPackage, uid);
RoboErik272e1612014-09-05 11:39:29 -07006060 }
6061
RoboErik0dac35a2014-08-12 15:48:49 -07006062 @Override
6063 public void adjustStreamVolumeForUid(int streamType, int direction, int flags,
6064 String callingPackage, int uid) {
John Spurlock90874332015-03-10 16:00:54 -04006065 adjustStreamVolume(streamType, direction, flags, callingPackage,
6066 callingPackage, uid);
RoboErik0dac35a2014-08-12 15:48:49 -07006067 }
6068
6069 @Override
6070 public void setStreamVolumeForUid(int streamType, int direction, int flags,
6071 String callingPackage, int uid) {
John Spurlock90874332015-03-10 16:00:54 -04006072 setStreamVolume(streamType, direction, flags, callingPackage, callingPackage, uid);
RoboErik0dac35a2014-08-12 15:48:49 -07006073 }
RoboErik519c7742014-11-18 10:59:09 -08006074
6075 @Override
John Spurlock661f2cf2014-11-17 10:29:10 -05006076 public int getRingerModeInternal() {
6077 return AudioService.this.getRingerModeInternal();
6078 }
6079
6080 @Override
6081 public void setRingerModeInternal(int ringerMode, String caller) {
6082 AudioService.this.setRingerModeInternal(ringerMode, caller);
6083 }
John Spurlockcdb57ae2015-02-11 19:04:11 -05006084
6085 @Override
Mike Digman55272862018-02-20 14:35:17 -08006086 public void silenceRingerModeInternal(String caller) {
6087 AudioService.this.silenceRingerModeInternal(caller);
6088 }
6089
6090 @Override
John Spurlock50ced3f2015-05-11 16:00:09 -04006091 public void updateRingerModeAffectedStreamsInternal() {
6092 synchronized (mSettingsLock) {
Beverlyd6964762018-02-16 14:07:03 -05006093 if (updateRingerAndZenModeAffectedStreams()) {
John Spurlock50ced3f2015-05-11 16:00:09 -04006094 setRingerModeInt(getRingerModeInternal(), false);
6095 }
6096 }
6097 }
Phil Weaverf1a9aff2017-03-23 17:21:29 -07006098
6099 @Override
6100 public void setAccessibilityServiceUids(IntArray uids) {
6101 synchronized (mAccessibilityServiceUidsLock) {
6102 if (uids.size() == 0) {
6103 mAccessibilityServiceUids = null;
6104 } else {
6105 boolean changed = (mAccessibilityServiceUids == null)
6106 || (mAccessibilityServiceUids.length != uids.size());
6107 if (!changed) {
6108 for (int i = 0; i < mAccessibilityServiceUids.length; i++) {
6109 if (uids.get(i) != mAccessibilityServiceUids[i]) {
6110 changed = true;
6111 break;
6112 }
6113 }
6114 }
6115 if (changed) {
6116 mAccessibilityServiceUids = uids.toArray();
6117 }
6118 }
Eric Laurent1c9c1d52018-10-17 10:06:46 -07006119 AudioSystem.setA11yServicesUids(mAccessibilityServiceUids);
Phil Weaverf1a9aff2017-03-23 17:21:29 -07006120 }
6121 }
RoboErik0dac35a2014-08-12 15:48:49 -07006122 }
6123
Jean-Michel Trivia8b6bd82014-07-01 09:48:46 -07006124 //==========================================================================================
6125 // Audio policy management
6126 //==========================================================================================
Jean-Michel Trivi0212be52014-11-24 14:43:10 -08006127 public String registerAudioPolicy(AudioPolicyConfig policyConfig, IAudioPolicyCallback pcb,
Jean-Michel Trivi610aa9b2018-01-27 15:42:42 -08006128 boolean hasFocusListener, boolean isFocusPolicy, boolean isVolumeController) {
Jean-Michel Trivi5a561092015-04-23 18:48:08 -07006129 AudioSystem.setDynamicPolicyCallback(mDynPolicyCallback);
6130
Jean-Michel Trivi8fdb0d42014-07-16 19:08:37 -07006131 String regId = null;
Jean-Michel Trivi0212be52014-11-24 14:43:10 -08006132 // error handling
Jean-Michel Trivia8b6bd82014-07-01 09:48:46 -07006133 boolean hasPermissionForPolicy =
Jean-Michel Trivi0212be52014-11-24 14:43:10 -08006134 (PackageManager.PERMISSION_GRANTED == mContext.checkCallingPermission(
Jean-Michel Trivia8b6bd82014-07-01 09:48:46 -07006135 android.Manifest.permission.MODIFY_AUDIO_ROUTING));
6136 if (!hasPermissionForPolicy) {
6137 Slog.w(TAG, "Can't register audio policy for pid " + Binder.getCallingPid() + " / uid "
6138 + Binder.getCallingUid() + ", need MODIFY_AUDIO_ROUTING");
Jean-Michel Trivi8fdb0d42014-07-16 19:08:37 -07006139 return null;
Jean-Michel Trivia8b6bd82014-07-01 09:48:46 -07006140 }
Jean-Michel Trivi0212be52014-11-24 14:43:10 -08006141
Jean-Michel Trivi12a86762018-04-24 16:57:49 -07006142 mDynPolicyLogger.log((new AudioEventLogger.StringEvent("registerAudioPolicy for "
6143 + pcb.asBinder() + " with config:" + policyConfig)).printLog(TAG));
Jean-Michel Trivia8b6bd82014-07-01 09:48:46 -07006144 synchronized (mAudioPolicies) {
Jean-Michel Trivia8b6bd82014-07-01 09:48:46 -07006145 try {
Jean-Michel Trivi0212be52014-11-24 14:43:10 -08006146 if (mAudioPolicies.containsKey(pcb.asBinder())) {
Jean-Michel Trivi1b3541d2014-11-25 12:53:41 -08006147 Slog.e(TAG, "Cannot re-register policy");
6148 return null;
6149 }
Jean-Michel Trivi126cf032017-04-02 23:19:02 -07006150 AudioPolicyProxy app = new AudioPolicyProxy(policyConfig, pcb, hasFocusListener,
Jean-Michel Trivi610aa9b2018-01-27 15:42:42 -08006151 isFocusPolicy, isVolumeController);
Jean-Michel Trivi0212be52014-11-24 14:43:10 -08006152 pcb.asBinder().linkToDeath(app, 0/*flags*/);
6153 regId = app.getRegistrationId();
6154 mAudioPolicies.put(pcb.asBinder(), app);
Jean-Michel Trivia8b6bd82014-07-01 09:48:46 -07006155 } catch (RemoteException e) {
6156 // audio policy owner has already died!
Jean-Michel Trivi0212be52014-11-24 14:43:10 -08006157 Slog.w(TAG, "Audio policy registration failed, could not link to " + pcb +
Jean-Michel Trivia8b6bd82014-07-01 09:48:46 -07006158 " binder death", e);
Jean-Michel Trivi8fdb0d42014-07-16 19:08:37 -07006159 return null;
Jean-Michel Trivia8b6bd82014-07-01 09:48:46 -07006160 }
6161 }
Jean-Michel Trivi8fdb0d42014-07-16 19:08:37 -07006162 return regId;
Jean-Michel Trivia8b6bd82014-07-01 09:48:46 -07006163 }
Jean-Michel Trivi8fdb0d42014-07-16 19:08:37 -07006164
Jean-Michel Trivi0212be52014-11-24 14:43:10 -08006165 public void unregisterAudioPolicyAsync(IAudioPolicyCallback pcb) {
Jean-Michel Trivi12a86762018-04-24 16:57:49 -07006166 mDynPolicyLogger.log((new AudioEventLogger.StringEvent("unregisterAudioPolicyAsync for "
6167 + pcb.asBinder()).printLog(TAG)));
Jean-Michel Trivia8b6bd82014-07-01 09:48:46 -07006168 synchronized (mAudioPolicies) {
Jean-Michel Trivi0212be52014-11-24 14:43:10 -08006169 AudioPolicyProxy app = mAudioPolicies.remove(pcb.asBinder());
Jean-Michel Trivia8b6bd82014-07-01 09:48:46 -07006170 if (app == null) {
6171 Slog.w(TAG, "Trying to unregister unknown audio policy for pid "
6172 + Binder.getCallingPid() + " / uid " + Binder.getCallingUid());
Jean-Michel Trivi1b3541d2014-11-25 12:53:41 -08006173 return;
Jean-Michel Trivia8b6bd82014-07-01 09:48:46 -07006174 } else {
Jean-Michel Trivi0212be52014-11-24 14:43:10 -08006175 pcb.asBinder().unlinkToDeath(app, 0/*flags*/);
Jean-Michel Trivia8b6bd82014-07-01 09:48:46 -07006176 }
Jean-Michel Trivi0212be52014-11-24 14:43:10 -08006177 app.release();
Jean-Michel Trivia8b6bd82014-07-01 09:48:46 -07006178 }
Jean-Michel Trivi8fdb0d42014-07-16 19:08:37 -07006179 // TODO implement clearing mix attribute matching info in native audio policy
Jean-Michel Trivia8b6bd82014-07-01 09:48:46 -07006180 }
6181
Jean-Michel Triviaf576a02018-02-14 08:57:46 -08006182 /**
6183 * Checks whether caller has MODIFY_AUDIO_ROUTING permission, and the policy is registered.
6184 * @param errorMsg log warning if permission check failed.
6185 * @return null if the operation on the audio mixes should be cancelled.
6186 */
6187 @GuardedBy("mAudioPolicies")
6188 private AudioPolicyProxy checkUpdateForPolicy(IAudioPolicyCallback pcb, String errorMsg) {
6189 // permission check
6190 final boolean hasPermissionForPolicy =
Jean-Michel Trivi0212be52014-11-24 14:43:10 -08006191 (PackageManager.PERMISSION_GRANTED == mContext.checkCallingPermission(
6192 android.Manifest.permission.MODIFY_AUDIO_ROUTING));
6193 if (!hasPermissionForPolicy) {
Jean-Michel Triviaf576a02018-02-14 08:57:46 -08006194 Slog.w(TAG, errorMsg + " for pid " +
Jean-Michel Trivi0212be52014-11-24 14:43:10 -08006195 + Binder.getCallingPid() + " / uid "
6196 + Binder.getCallingUid() + ", need MODIFY_AUDIO_ROUTING");
Jean-Michel Triviaf576a02018-02-14 08:57:46 -08006197 return null;
Jean-Michel Trivi0212be52014-11-24 14:43:10 -08006198 }
Jean-Michel Triviaf576a02018-02-14 08:57:46 -08006199 // policy registered?
6200 final AudioPolicyProxy app = mAudioPolicies.get(pcb.asBinder());
6201 if (app == null) {
6202 Slog.w(TAG, errorMsg + " for pid " +
6203 + Binder.getCallingPid() + " / uid "
6204 + Binder.getCallingUid() + ", unregistered policy");
6205 return null;
6206 }
6207 return app;
6208 }
Jean-Michel Trivi0212be52014-11-24 14:43:10 -08006209
Jean-Michel Triviaf576a02018-02-14 08:57:46 -08006210 public int addMixForPolicy(AudioPolicyConfig policyConfig, IAudioPolicyCallback pcb) {
6211 if (DEBUG_AP) { Log.d(TAG, "addMixForPolicy for " + pcb.asBinder()
6212 + " with config:" + policyConfig); }
Jean-Michel Trivi0212be52014-11-24 14:43:10 -08006213 synchronized (mAudioPolicies) {
Jean-Michel Triviaf576a02018-02-14 08:57:46 -08006214 final AudioPolicyProxy app =
6215 checkUpdateForPolicy(pcb, "Cannot add AudioMix in audio policy");
6216 if (app == null){
6217 return AudioManager.ERROR;
6218 }
6219 app.addMixes(policyConfig.getMixes());
6220 }
6221 return AudioManager.SUCCESS;
6222 }
6223
6224 public int removeMixForPolicy(AudioPolicyConfig policyConfig, IAudioPolicyCallback pcb) {
6225 if (DEBUG_AP) { Log.d(TAG, "removeMixForPolicy for " + pcb.asBinder()
6226 + " with config:" + policyConfig); }
6227 synchronized (mAudioPolicies) {
6228 final AudioPolicyProxy app =
6229 checkUpdateForPolicy(pcb, "Cannot add AudioMix in audio policy");
6230 if (app == null) {
6231 return AudioManager.ERROR;
6232 }
6233 app.removeMixes(policyConfig.getMixes());
6234 }
6235 return AudioManager.SUCCESS;
6236 }
6237
Jean-Michel Trivid6f65de2018-12-18 18:49:14 -08006238 /** see AudioPolicy.setUidDeviceAffinity() */
6239 public int setUidDeviceAffinity(IAudioPolicyCallback pcb, int uid,
Jean-Michel Trivif93107f2019-01-08 09:38:25 -08006240 @NonNull int[] deviceTypes, @NonNull String[] deviceAddresses) {
6241 if (DEBUG_AP) {
6242 Log.d(TAG, "setUidDeviceAffinity for " + pcb.asBinder() + " uid:" + uid);
6243 }
Jean-Michel Trivid6f65de2018-12-18 18:49:14 -08006244 synchronized (mAudioPolicies) {
6245 final AudioPolicyProxy app =
6246 checkUpdateForPolicy(pcb, "Cannot change device affinity in audio policy");
6247 if (app == null) {
6248 return AudioManager.ERROR;
6249 }
6250 if (!app.hasMixRoutedToDevices(deviceTypes, deviceAddresses)) {
6251 return AudioManager.ERROR;
6252 }
Jean-Michel Trivif93107f2019-01-08 09:38:25 -08006253 return app.setUidDeviceAffinities(uid, deviceTypes, deviceAddresses);
Jean-Michel Trivid6f65de2018-12-18 18:49:14 -08006254 }
Jean-Michel Trivid6f65de2018-12-18 18:49:14 -08006255 }
6256
6257 /** see AudioPolicy.removeUidDeviceAffinity() */
6258 public int removeUidDeviceAffinity(IAudioPolicyCallback pcb, int uid) {
Jean-Michel Trivif93107f2019-01-08 09:38:25 -08006259 if (DEBUG_AP) {
6260 Log.d(TAG, "removeUidDeviceAffinity for " + pcb.asBinder() + " uid:" + uid);
6261 }
Jean-Michel Trivid6f65de2018-12-18 18:49:14 -08006262 synchronized (mAudioPolicies) {
6263 final AudioPolicyProxy app =
6264 checkUpdateForPolicy(pcb, "Cannot remove device affinity in audio policy");
6265 if (app == null) {
6266 return AudioManager.ERROR;
6267 }
Jean-Michel Trivif93107f2019-01-08 09:38:25 -08006268 return app.removeUidDeviceAffinities(uid);
Jean-Michel Trivid6f65de2018-12-18 18:49:14 -08006269 }
Jean-Michel Trivid6f65de2018-12-18 18:49:14 -08006270 }
6271
Jean-Michel Triviaf576a02018-02-14 08:57:46 -08006272 public int setFocusPropertiesForPolicy(int duckingBehavior, IAudioPolicyCallback pcb) {
6273 if (DEBUG_AP) Log.d(TAG, "setFocusPropertiesForPolicy() duck behavior=" + duckingBehavior
6274 + " policy " + pcb.asBinder());
6275 synchronized (mAudioPolicies) {
6276 final AudioPolicyProxy app =
6277 checkUpdateForPolicy(pcb, "Cannot change audio policy focus properties");
6278 if (app == null){
6279 return AudioManager.ERROR;
6280 }
Jean-Michel Trivi0212be52014-11-24 14:43:10 -08006281 if (!mAudioPolicies.containsKey(pcb.asBinder())) {
6282 Slog.e(TAG, "Cannot change audio policy focus properties, unregistered policy");
6283 return AudioManager.ERROR;
6284 }
Jean-Michel Trivi0212be52014-11-24 14:43:10 -08006285 if (duckingBehavior == AudioPolicy.FOCUS_POLICY_DUCKING_IN_POLICY) {
6286 // is there already one policy managing ducking?
Eric Laurent0867bed2015-05-20 14:49:08 -07006287 for (AudioPolicyProxy policy : mAudioPolicies.values()) {
Jean-Michel Trivi0212be52014-11-24 14:43:10 -08006288 if (policy.mFocusDuckBehavior == AudioPolicy.FOCUS_POLICY_DUCKING_IN_POLICY) {
6289 Slog.e(TAG, "Cannot change audio policy ducking behavior, already handled");
6290 return AudioManager.ERROR;
6291 }
6292 }
6293 }
6294 app.mFocusDuckBehavior = duckingBehavior;
6295 mMediaFocusControl.setDuckingInExtPolicyAvailable(
6296 duckingBehavior == AudioPolicy.FOCUS_POLICY_DUCKING_IN_POLICY);
6297 }
6298 return AudioManager.SUCCESS;
6299 }
6300
Jean-Michel Trivi610aa9b2018-01-27 15:42:42 -08006301 private final Object mExtVolumeControllerLock = new Object();
6302 private IAudioPolicyCallback mExtVolumeController;
6303 private void setExtVolumeController(IAudioPolicyCallback apc) {
6304 if (!mContext.getResources().getBoolean(
6305 com.android.internal.R.bool.config_handleVolumeKeysInWindowManager)) {
6306 Log.e(TAG, "Cannot set external volume controller: device not set for volume keys" +
6307 " handled in PhoneWindowManager");
6308 return;
6309 }
6310 synchronized (mExtVolumeControllerLock) {
6311 if (mExtVolumeController != null && !mExtVolumeController.asBinder().pingBinder()) {
6312 Log.e(TAG, "Cannot set external volume controller: existing controller");
6313 }
6314 mExtVolumeController = apc;
6315 }
6316 }
6317
Jean-Michel Trivi1b3541d2014-11-25 12:53:41 -08006318 private void dumpAudioPolicies(PrintWriter pw) {
6319 pw.println("\nAudio policies:");
6320 synchronized (mAudioPolicies) {
Eric Laurent0867bed2015-05-20 14:49:08 -07006321 for (AudioPolicyProxy policy : mAudioPolicies.values()) {
Jean-Michel Trivi1b3541d2014-11-25 12:53:41 -08006322 pw.println(policy.toLogFriendlyString());
6323 }
6324 }
6325 }
6326
Jean-Michel Trivi958876f2014-11-16 15:40:22 -08006327 //======================
Jean-Michel Trivid3c71f02015-12-07 11:59:31 -08006328 // Audio policy callbacks from AudioSystem for dynamic policies
Jean-Michel Trivi5a561092015-04-23 18:48:08 -07006329 //======================
6330 private final AudioSystem.DynamicPolicyCallback mDynPolicyCallback =
6331 new AudioSystem.DynamicPolicyCallback() {
6332 public void onDynamicPolicyMixStateUpdate(String regId, int state) {
6333 if (!TextUtils.isEmpty(regId)) {
6334 sendMsg(mAudioHandler, MSG_DYN_POLICY_MIX_STATE_UPDATE, SENDMSG_QUEUE,
6335 state /*arg1*/, 0 /*arg2 ignored*/, regId /*obj*/, 0 /*delay*/);
6336 }
6337 }
6338 };
6339
6340 private void onDynPolicyMixStateUpdate(String regId, int state) {
6341 if (DEBUG_AP) Log.d(TAG, "onDynamicPolicyMixStateUpdate("+ regId + ", " + state +")");
6342 synchronized (mAudioPolicies) {
6343 for (AudioPolicyProxy policy : mAudioPolicies.values()) {
6344 for (AudioMix mix : policy.getMixes()) {
6345 if (mix.getRegistration().equals(regId)) {
6346 try {
6347 policy.mPolicyCallback.notifyMixStateUpdate(regId, state);
6348 } catch (RemoteException e) {
6349 Log.e(TAG, "Can't call notifyMixStateUpdate() on IAudioPolicyCallback "
6350 + policy.mPolicyCallback.asBinder(), e);
6351 }
6352 return;
6353 }
6354 }
6355 }
6356 }
Jean-Michel Trivid3c71f02015-12-07 11:59:31 -08006357 }
Jean-Michel Trivi5a561092015-04-23 18:48:08 -07006358
Jean-Michel Trivid3c71f02015-12-07 11:59:31 -08006359 //======================
6360 // Audio policy callbacks from AudioSystem for recording configuration updates
6361 //======================
Jean-Michel Trivi66ffacf2017-02-04 17:25:31 -08006362 private final RecordingActivityMonitor mRecordMonitor;
Jean-Michel Trivid3c71f02015-12-07 11:59:31 -08006363
6364 public void registerRecordingCallback(IRecordingConfigDispatcher rcdb) {
Jean-Michel Trivi66ffacf2017-02-04 17:25:31 -08006365 final boolean isPrivileged =
6366 (PackageManager.PERMISSION_GRANTED == mContext.checkCallingPermission(
6367 android.Manifest.permission.MODIFY_AUDIO_ROUTING));
6368 mRecordMonitor.registerRecordingCallback(rcdb, isPrivileged);
Jean-Michel Trivid3c71f02015-12-07 11:59:31 -08006369 }
6370
6371 public void unregisterRecordingCallback(IRecordingConfigDispatcher rcdb) {
6372 mRecordMonitor.unregisterRecordingCallback(rcdb);
6373 }
6374
Jean-Michel Trivif04fab12016-05-19 10:42:35 -07006375 public List<AudioRecordingConfiguration> getActiveRecordingConfigurations() {
Jean-Michel Trivi66ffacf2017-02-04 17:25:31 -08006376 final boolean isPrivileged =
6377 (PackageManager.PERMISSION_GRANTED == mContext.checkCallingPermission(
6378 android.Manifest.permission.MODIFY_AUDIO_ROUTING));
6379 return mRecordMonitor.getActiveRecordingConfigurations(isPrivileged);
Jean-Michel Trivi5a561092015-04-23 18:48:08 -07006380 }
6381
Robin Lee7af9a742017-02-20 14:47:30 +00006382 public void disableRingtoneSync(final int userId) {
Andre Lago7bdc6d82016-09-22 18:00:41 +01006383 final int callingUserId = UserHandle.getCallingUserId();
Robin Lee7af9a742017-02-20 14:47:30 +00006384 if (callingUserId != userId) {
6385 mContext.enforceCallingOrSelfPermission(Manifest.permission.INTERACT_ACROSS_USERS_FULL,
6386 "disable sound settings syncing for another profile");
6387 }
Andre Lago7bdc6d82016-09-22 18:00:41 +01006388 final long token = Binder.clearCallingIdentity();
6389 try {
Robin Lee7af9a742017-02-20 14:47:30 +00006390 // Disable the sync setting so the profile uses its own sound settings.
6391 Settings.Secure.putIntForUser(mContentResolver, Settings.Secure.SYNC_PARENT_SOUNDS,
6392 0 /* false */, userId);
Andre Lago7bdc6d82016-09-22 18:00:41 +01006393 } finally {
6394 Binder.restoreCallingIdentity(token);
6395 }
6396 }
6397
Jean-Michel Trivi5a561092015-04-23 18:48:08 -07006398 //======================
Jean-Michel Trivi46e310b2017-01-04 15:58:02 -08006399 // Audio playback notification
Jean-Michel Trivi292a6a42016-12-01 08:32:15 -08006400 //======================
Eric Laurente5a351c2017-09-27 20:11:51 -07006401 private final PlaybackActivityMonitor mPlaybackMonitor;
Jean-Michel Trivi292a6a42016-12-01 08:32:15 -08006402
6403 public void registerPlaybackCallback(IPlaybackConfigDispatcher pcdb) {
Jean-Michel Trivi44a8f532017-01-02 14:36:43 -08006404 final boolean isPrivileged =
Jaewan Kim92dea332017-02-02 11:52:08 +09006405 (PackageManager.PERMISSION_GRANTED == mContext.checkCallingOrSelfPermission(
Jean-Michel Trivi292a6a42016-12-01 08:32:15 -08006406 android.Manifest.permission.MODIFY_AUDIO_ROUTING));
6407 mPlaybackMonitor.registerPlaybackCallback(pcdb, isPrivileged);
6408 }
6409
6410 public void unregisterPlaybackCallback(IPlaybackConfigDispatcher pcdb) {
6411 mPlaybackMonitor.unregisterPlaybackCallback(pcdb);
6412 }
6413
6414 public List<AudioPlaybackConfiguration> getActivePlaybackConfigurations() {
Jean-Michel Trivi44a8f532017-01-02 14:36:43 -08006415 final boolean isPrivileged =
Jaewan Kim92dea332017-02-02 11:52:08 +09006416 (PackageManager.PERMISSION_GRANTED == mContext.checkCallingOrSelfPermission(
Jean-Michel Trivi44a8f532017-01-02 14:36:43 -08006417 android.Manifest.permission.MODIFY_AUDIO_ROUTING));
6418 return mPlaybackMonitor.getActivePlaybackConfigurations(isPrivileged);
Jean-Michel Trivi292a6a42016-12-01 08:32:15 -08006419 }
6420
Jean-Michel Trivi44a8f532017-01-02 14:36:43 -08006421 public int trackPlayer(PlayerBase.PlayerIdCard pic) {
6422 return mPlaybackMonitor.trackPlayer(pic);
Jean-Michel Trivi292a6a42016-12-01 08:32:15 -08006423 }
6424
6425 public void playerAttributes(int piid, AudioAttributes attr) {
Jean-Michel Trivi46e310b2017-01-04 15:58:02 -08006426 mPlaybackMonitor.playerAttributes(piid, attr, Binder.getCallingUid());
Jean-Michel Trivi292a6a42016-12-01 08:32:15 -08006427 }
6428
6429 public void playerEvent(int piid, int event) {
Jean-Michel Trivi46e310b2017-01-04 15:58:02 -08006430 mPlaybackMonitor.playerEvent(piid, event, Binder.getCallingUid());
Jean-Michel Trivi292a6a42016-12-01 08:32:15 -08006431 }
6432
Jean-Michel Trivi3120059d2017-08-28 12:40:55 -07006433 public void playerHasOpPlayAudio(int piid, boolean hasOpPlayAudio) {
6434 mPlaybackMonitor.playerHasOpPlayAudio(piid, hasOpPlayAudio, Binder.getCallingUid());
6435 }
6436
Jean-Michel Trivi292a6a42016-12-01 08:32:15 -08006437 public void releasePlayer(int piid) {
Jean-Michel Trivi46e310b2017-01-04 15:58:02 -08006438 mPlaybackMonitor.releasePlayer(piid, Binder.getCallingUid());
Jean-Michel Trivi292a6a42016-12-01 08:32:15 -08006439 }
6440
6441 //======================
Jean-Michel Trivi58850372018-09-14 16:01:28 -07006442 // Audio device management
6443 //======================
6444 private final AudioDeviceBroker mDeviceBroker;
6445
6446 //======================
Jean-Michel Trivi958876f2014-11-16 15:40:22 -08006447 // Audio policy proxy
6448 //======================
Jean-Michel Trivid6f65de2018-12-18 18:49:14 -08006449 private static final class AudioDeviceArray {
6450 final @NonNull int[] mDeviceTypes;
6451 final @NonNull String[] mDeviceAddresses;
6452 AudioDeviceArray(@NonNull int[] types, @NonNull String[] addresses) {
6453 mDeviceTypes = types;
6454 mDeviceAddresses = addresses;
6455 }
6456 }
6457
Jean-Michel Trivi8fdb0d42014-07-16 19:08:37 -07006458 /**
Jean-Michel Trivi1b3541d2014-11-25 12:53:41 -08006459 * This internal class inherits from AudioPolicyConfig, each instance contains all the
6460 * mixes of an AudioPolicy and their configurations.
Jean-Michel Trivi8fdb0d42014-07-16 19:08:37 -07006461 */
6462 public class AudioPolicyProxy extends AudioPolicyConfig implements IBinder.DeathRecipient {
Jean-Michel Trivia8b6bd82014-07-01 09:48:46 -07006463 private static final String TAG = "AudioPolicyProxy";
Jean-Michel Trivi610aa9b2018-01-27 15:42:42 -08006464 final IAudioPolicyCallback mPolicyCallback;
6465 final boolean mHasFocusListener;
6466 final boolean mIsVolumeController;
Jean-Michel Trivid6f65de2018-12-18 18:49:14 -08006467 final HashMap<Integer, AudioDeviceArray> mUidDeviceAffinities =
6468 new HashMap<Integer, AudioDeviceArray>();
Jean-Michel Trivi0212be52014-11-24 14:43:10 -08006469 /**
6470 * Audio focus ducking behavior for an audio policy.
6471 * This variable reflects the value that was successfully set in
6472 * {@link AudioService#setFocusPropertiesForPolicy(int, IAudioPolicyCallback)}. This
6473 * implies that a value of FOCUS_POLICY_DUCKING_IN_POLICY means the corresponding policy
6474 * is handling ducking for audio focus.
6475 */
6476 int mFocusDuckBehavior = AudioPolicy.FOCUS_POLICY_DUCKING_DEFAULT;
Jean-Michel Trivi126cf032017-04-02 23:19:02 -07006477 boolean mIsFocusPolicy = false;
Jean-Michel Trivi0212be52014-11-24 14:43:10 -08006478
6479 AudioPolicyProxy(AudioPolicyConfig config, IAudioPolicyCallback token,
Jean-Michel Trivi610aa9b2018-01-27 15:42:42 -08006480 boolean hasFocusListener, boolean isFocusPolicy, boolean isVolumeController) {
Jean-Michel Trivi8fdb0d42014-07-16 19:08:37 -07006481 super(config);
Jean-Michel Trivi1b3541d2014-11-25 12:53:41 -08006482 setRegistration(new String(config.hashCode() + ":ap:" + mAudioPolicyCounter++));
Jean-Michel Trivi5a561092015-04-23 18:48:08 -07006483 mPolicyCallback = token;
Jean-Michel Trivi0212be52014-11-24 14:43:10 -08006484 mHasFocusListener = hasFocusListener;
Jean-Michel Trivi610aa9b2018-01-27 15:42:42 -08006485 mIsVolumeController = isVolumeController;
Jean-Michel Trivi0212be52014-11-24 14:43:10 -08006486 if (mHasFocusListener) {
Jean-Michel Trivi5a561092015-04-23 18:48:08 -07006487 mMediaFocusControl.addFocusFollower(mPolicyCallback);
Jean-Michel Trivi126cf032017-04-02 23:19:02 -07006488 // can only ever be true if there is a focus listener
6489 if (isFocusPolicy) {
6490 mIsFocusPolicy = true;
6491 mMediaFocusControl.setFocusPolicy(mPolicyCallback);
6492 }
Jean-Michel Trivi0212be52014-11-24 14:43:10 -08006493 }
Jean-Michel Trivi610aa9b2018-01-27 15:42:42 -08006494 if (mIsVolumeController) {
6495 setExtVolumeController(mPolicyCallback);
6496 }
Eric Laurent7f5eb9f2014-12-01 19:36:30 -08006497 connectMixes();
Jean-Michel Trivia8b6bd82014-07-01 09:48:46 -07006498 }
6499
6500 public void binderDied() {
6501 synchronized (mAudioPolicies) {
Jean-Michel Trivi5a561092015-04-23 18:48:08 -07006502 Log.i(TAG, "audio policy " + mPolicyCallback + " died");
Jean-Michel Trivi0212be52014-11-24 14:43:10 -08006503 release();
Jean-Michel Trivi5a561092015-04-23 18:48:08 -07006504 mAudioPolicies.remove(mPolicyCallback.asBinder());
Jean-Michel Trivi8fdb0d42014-07-16 19:08:37 -07006505 }
Jean-Michel Trivi610aa9b2018-01-27 15:42:42 -08006506 if (mIsVolumeController) {
6507 synchronized (mExtVolumeControllerLock) {
6508 mExtVolumeController = null;
6509 }
6510 }
Jean-Michel Trivi8fdb0d42014-07-16 19:08:37 -07006511 }
6512
Jean-Michel Trivi0212be52014-11-24 14:43:10 -08006513 String getRegistrationId() {
Jean-Michel Trivi1b3541d2014-11-25 12:53:41 -08006514 return getRegistration();
Jean-Michel Trivi8fdb0d42014-07-16 19:08:37 -07006515 }
6516
Jean-Michel Trivi0212be52014-11-24 14:43:10 -08006517 void release() {
Jean-Michel Trivi126cf032017-04-02 23:19:02 -07006518 if (mIsFocusPolicy) {
6519 mMediaFocusControl.unsetFocusPolicy(mPolicyCallback);
6520 }
Jean-Michel Trivi0212be52014-11-24 14:43:10 -08006521 if (mFocusDuckBehavior == AudioPolicy.FOCUS_POLICY_DUCKING_IN_POLICY) {
6522 mMediaFocusControl.setDuckingInExtPolicyAvailable(false);
6523 }
6524 if (mHasFocusListener) {
Jean-Michel Trivi5a561092015-04-23 18:48:08 -07006525 mMediaFocusControl.removeFocusFollower(mPolicyCallback);
Jean-Michel Trivi0212be52014-11-24 14:43:10 -08006526 }
Eric Laurent66b69672018-01-26 18:30:51 -08006527 final long identity = Binder.clearCallingIdentity();
Eric Laurent7f5eb9f2014-12-01 19:36:30 -08006528 AudioSystem.registerPolicyMixes(mMixes, false);
Eric Laurent66b69672018-01-26 18:30:51 -08006529 Binder.restoreCallingIdentity(identity);
Jean-Michel Trivi8fdb0d42014-07-16 19:08:37 -07006530 }
6531
Jean-Michel Trivi7db2d8f2018-03-06 10:30:59 -08006532 boolean hasMixAffectingUsage(int usage) {
6533 for (AudioMix mix : mMixes) {
6534 if (mix.isAffectingUsage(usage)) {
6535 return true;
6536 }
6537 }
6538 return false;
6539 }
6540
Jean-Michel Trivid6f65de2018-12-18 18:49:14 -08006541 // Verify all the devices in the array are served by mixes defined in this policy
6542 boolean hasMixRoutedToDevices(@NonNull int[] deviceTypes,
6543 @NonNull String[] deviceAddresses) {
6544 for (int i = 0; i < deviceTypes.length; i++) {
6545 boolean hasDevice = false;
6546 for (AudioMix mix : mMixes) {
6547 // this will check both that the mix has ROUTE_FLAG_RENDER and the device
6548 // is reached by this mix
6549 if (mix.isRoutedToDevice(deviceTypes[i], deviceAddresses[i])) {
6550 hasDevice = true;
6551 break;
6552 }
6553 }
6554 if (!hasDevice) {
6555 return false;
6556 }
6557 }
6558 return true;
6559 }
6560
Jean-Michel Triviaf576a02018-02-14 08:57:46 -08006561 void addMixes(@NonNull ArrayList<AudioMix> mixes) {
6562 // TODO optimize to not have to unregister the mixes already in place
6563 synchronized (mMixes) {
6564 AudioSystem.registerPolicyMixes(mMixes, false);
6565 this.add(mixes);
6566 AudioSystem.registerPolicyMixes(mMixes, true);
6567 }
6568 }
6569
6570 void removeMixes(@NonNull ArrayList<AudioMix> mixes) {
6571 // TODO optimize to not have to unregister the mixes already in place
6572 synchronized (mMixes) {
6573 AudioSystem.registerPolicyMixes(mMixes, false);
6574 this.remove(mixes);
6575 AudioSystem.registerPolicyMixes(mMixes, true);
6576 }
6577 }
6578
Eric Laurent7f5eb9f2014-12-01 19:36:30 -08006579 void connectMixes() {
Eric Laurent66b69672018-01-26 18:30:51 -08006580 final long identity = Binder.clearCallingIdentity();
Eric Laurent7f5eb9f2014-12-01 19:36:30 -08006581 AudioSystem.registerPolicyMixes(mMixes, true);
Eric Laurent66b69672018-01-26 18:30:51 -08006582 Binder.restoreCallingIdentity(identity);
Jean-Michel Trivia8b6bd82014-07-01 09:48:46 -07006583 }
Jean-Michel Trivid6f65de2018-12-18 18:49:14 -08006584
Jean-Michel Trivif93107f2019-01-08 09:38:25 -08006585 int setUidDeviceAffinities(int uid, @NonNull int[] types, @NonNull String[] addresses) {
Jean-Michel Trivid6f65de2018-12-18 18:49:14 -08006586 final Integer Uid = new Integer(uid);
Jean-Michel Trivif93107f2019-01-08 09:38:25 -08006587 int res;
Jean-Michel Trivid6f65de2018-12-18 18:49:14 -08006588 if (mUidDeviceAffinities.remove(Uid) != null) {
6589 final long identity = Binder.clearCallingIdentity();
Jean-Michel Trivif93107f2019-01-08 09:38:25 -08006590 res = AudioSystem.removeUidDeviceAffinities(uid);
Jean-Michel Trivid6f65de2018-12-18 18:49:14 -08006591 Binder.restoreCallingIdentity(identity);
Jean-Michel Trivif93107f2019-01-08 09:38:25 -08006592 if (res != AudioSystem.SUCCESS) {
6593 Log.e(TAG, "AudioSystem. removeUidDeviceAffinities(" + uid + ") failed, "
6594 + " cannot call AudioSystem.setUidDeviceAffinities");
6595 return AudioManager.ERROR;
6596 }
Jean-Michel Trivid6f65de2018-12-18 18:49:14 -08006597 }
6598 final long identity = Binder.clearCallingIdentity();
Jean-Michel Trivif93107f2019-01-08 09:38:25 -08006599 res = AudioSystem.setUidDeviceAffinities(uid, types, addresses);
Jean-Michel Trivid6f65de2018-12-18 18:49:14 -08006600 Binder.restoreCallingIdentity(identity);
6601 if (res == AudioSystem.SUCCESS) {
6602 mUidDeviceAffinities.put(Uid, new AudioDeviceArray(types, addresses));
Jean-Michel Trivif93107f2019-01-08 09:38:25 -08006603 return AudioManager.SUCCESS;
Jean-Michel Trivid6f65de2018-12-18 18:49:14 -08006604 }
Jean-Michel Trivif93107f2019-01-08 09:38:25 -08006605 Log.e(TAG, "AudioSystem. setUidDeviceAffinities(" + uid + ") failed");
6606 return AudioManager.ERROR;
Jean-Michel Trivid6f65de2018-12-18 18:49:14 -08006607 }
6608
Jean-Michel Trivif93107f2019-01-08 09:38:25 -08006609 int removeUidDeviceAffinities(int uid) {
Jean-Michel Trivid6f65de2018-12-18 18:49:14 -08006610 if (mUidDeviceAffinities.remove(new Integer(uid)) != null) {
6611 final long identity = Binder.clearCallingIdentity();
Jean-Michel Trivif93107f2019-01-08 09:38:25 -08006612 final int res = AudioSystem.removeUidDeviceAffinities(uid);
Jean-Michel Trivid6f65de2018-12-18 18:49:14 -08006613 Binder.restoreCallingIdentity(identity);
Jean-Michel Trivif93107f2019-01-08 09:38:25 -08006614 if (res == AudioSystem.SUCCESS) {
6615 return AudioManager.SUCCESS;
6616 }
Jean-Michel Trivid6f65de2018-12-18 18:49:14 -08006617 }
Jean-Michel Trivif93107f2019-01-08 09:38:25 -08006618 Log.e(TAG, "AudioSystem. removeUidDeviceAffinities failed");
6619 return AudioManager.ERROR;
Jean-Michel Trivid6f65de2018-12-18 18:49:14 -08006620 }
Jean-Michel Trivia8b6bd82014-07-01 09:48:46 -07006621 };
6622
Jean-Michel Trivi126cf032017-04-02 23:19:02 -07006623 //======================
6624 // Audio policy: focus
6625 //======================
6626 /** */
6627 public int dispatchFocusChange(AudioFocusInfo afi, int focusChange, IAudioPolicyCallback pcb) {
Jean-Michel Trivie2d8aae2018-01-30 15:09:47 -08006628 if (afi == null) {
6629 throw new IllegalArgumentException("Illegal null AudioFocusInfo");
6630 }
6631 if (pcb == null) {
6632 throw new IllegalArgumentException("Illegal null AudioPolicy callback");
6633 }
Jean-Michel Trivi126cf032017-04-02 23:19:02 -07006634 synchronized (mAudioPolicies) {
6635 if (!mAudioPolicies.containsKey(pcb.asBinder())) {
6636 throw new IllegalStateException("Unregistered AudioPolicy for focus dispatch");
6637 }
6638 return mMediaFocusControl.dispatchFocusChange(afi, focusChange);
6639 }
6640 }
6641
Jean-Michel Trivie2d8aae2018-01-30 15:09:47 -08006642 public void setFocusRequestResultFromExtPolicy(AudioFocusInfo afi, int requestResult,
6643 IAudioPolicyCallback pcb) {
6644 if (afi == null) {
6645 throw new IllegalArgumentException("Illegal null AudioFocusInfo");
6646 }
6647 if (pcb == null) {
6648 throw new IllegalArgumentException("Illegal null AudioPolicy callback");
6649 }
6650 synchronized (mAudioPolicies) {
6651 if (!mAudioPolicies.containsKey(pcb.asBinder())) {
6652 throw new IllegalStateException("Unregistered AudioPolicy for external focus");
6653 }
6654 mMediaFocusControl.setFocusRequestResultFromExtPolicy(afi, requestResult);
6655 }
6656 }
6657
6658
Jean-Michel Trivi126cf032017-04-02 23:19:02 -07006659 //======================
Eric Laurent1d3cdce2018-01-20 10:31:21 -08006660 // Audioserver state displatch
6661 //======================
6662 private class AsdProxy implements IBinder.DeathRecipient {
6663 private final IAudioServerStateDispatcher mAsd;
6664
6665 AsdProxy(IAudioServerStateDispatcher asd) {
6666 mAsd = asd;
6667 }
6668
6669 public void binderDied() {
6670 synchronized (mAudioServerStateListeners) {
6671 mAudioServerStateListeners.remove(mAsd.asBinder());
6672 }
6673 }
6674
6675 IAudioServerStateDispatcher callback() {
6676 return mAsd;
6677 }
6678 }
6679
6680 private HashMap<IBinder, AsdProxy> mAudioServerStateListeners =
6681 new HashMap<IBinder, AsdProxy>();
6682
6683 private void checkMonitorAudioServerStatePermission() {
6684 if (!(mContext.checkCallingOrSelfPermission(
6685 android.Manifest.permission.MODIFY_PHONE_STATE) ==
6686 PackageManager.PERMISSION_GRANTED ||
6687 mContext.checkCallingOrSelfPermission(
6688 android.Manifest.permission.MODIFY_AUDIO_ROUTING) ==
6689 PackageManager.PERMISSION_GRANTED)) {
6690 throw new SecurityException("Not allowed to monitor audioserver state");
6691 }
6692 }
6693
6694 public void registerAudioServerStateDispatcher(IAudioServerStateDispatcher asd) {
6695 checkMonitorAudioServerStatePermission();
6696 synchronized (mAudioServerStateListeners) {
6697 if (mAudioServerStateListeners.containsKey(asd.asBinder())) {
6698 Slog.w(TAG, "Cannot re-register audio server state dispatcher");
6699 return;
6700 }
6701 AsdProxy asdp = new AsdProxy(asd);
6702 try {
6703 asd.asBinder().linkToDeath(asdp, 0/*flags*/);
6704 } catch (RemoteException e) {
6705
6706 }
6707 mAudioServerStateListeners.put(asd.asBinder(), asdp);
6708 }
6709 }
6710
6711 public void unregisterAudioServerStateDispatcher(IAudioServerStateDispatcher asd) {
6712 checkMonitorAudioServerStatePermission();
6713 synchronized (mAudioServerStateListeners) {
6714 AsdProxy asdp = mAudioServerStateListeners.remove(asd.asBinder());
6715 if (asdp == null) {
6716 Slog.w(TAG, "Trying to unregister unknown audioserver state dispatcher for pid "
6717 + Binder.getCallingPid() + " / uid " + Binder.getCallingUid());
6718 return;
6719 } else {
6720 asd.asBinder().unlinkToDeath(asdp, 0/*flags*/);
6721 }
6722 }
6723 }
6724
6725 public boolean isAudioServerRunning() {
6726 checkMonitorAudioServerStatePermission();
6727 return (AudioSystem.checkAudioFlinger() == AudioSystem.AUDIO_STATUS_OK);
6728 }
6729
6730 //======================
Jean-Michel Trivi126cf032017-04-02 23:19:02 -07006731 // misc
6732 //======================
Jean-Michel Triviaf576a02018-02-14 08:57:46 -08006733 private final HashMap<IBinder, AudioPolicyProxy> mAudioPolicies =
Jean-Michel Trivia8b6bd82014-07-01 09:48:46 -07006734 new HashMap<IBinder, AudioPolicyProxy>();
Jean-Michel Triviaf576a02018-02-14 08:57:46 -08006735 @GuardedBy("mAudioPolicies")
6736 private int mAudioPolicyCounter = 0;
Phil Burkac0f7042016-02-24 12:19:08 -08006737}