summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--services/core/java/com/android/server/audio/AudioService.java111
1 files changed, 71 insertions, 40 deletions
diff --git a/services/core/java/com/android/server/audio/AudioService.java b/services/core/java/com/android/server/audio/AudioService.java
index 182778113c36..745555cd895f 100644
--- a/services/core/java/com/android/server/audio/AudioService.java
+++ b/services/core/java/com/android/server/audio/AudioService.java
@@ -41,10 +41,12 @@ import android.annotation.SuppressLint;
import android.annotation.UserIdInt;
import android.app.ActivityManager;
import android.app.ActivityManagerInternal;
+import android.app.AlarmManager;
import android.app.AppGlobals;
import android.app.AppOpsManager;
import android.app.IUidObserver;
import android.app.NotificationManager;
+import android.app.PendingIntent;
import android.app.role.OnRoleHoldersChangedListener;
import android.app.role.RoleManager;
import android.bluetooth.BluetoothAdapter;
@@ -1185,6 +1187,8 @@ public class AudioService extends IAudioService.Stub
mSafeMediaVolumeIndex = mContext.getResources().getInteger(
com.android.internal.R.integer.config_safe_media_volume_index) * 10;
+ mAlarmManager = (AlarmManager) mContext.getSystemService(Context.ALARM_SERVICE);
+
mUseFixedVolume = mContext.getResources().getBoolean(
com.android.internal.R.bool.config_useFixedVolume);
@@ -1202,7 +1206,7 @@ public class AudioService extends IAudioService.Stub
mPlaybackMonitor =
new PlaybackActivityMonitor(context, MAX_STREAM_VOLUME[AudioSystem.STREAM_ALARM],
device -> onMuteAwaitConnectionTimeout(device));
- mPlaybackMonitor.registerPlaybackCallback(mVoicePlaybackActivityMonitor, true);
+ mPlaybackMonitor.registerPlaybackCallback(mPlaybackActivityMonitor, true);
mMediaFocusControl = new MediaFocusControl(mContext, mPlaybackMonitor);
@@ -1308,6 +1312,7 @@ public class AudioService extends IAudioService.Stub
intentFilter.addAction(AudioEffect.ACTION_OPEN_AUDIO_EFFECT_CONTROL_SESSION);
intentFilter.addAction(AudioEffect.ACTION_CLOSE_AUDIO_EFFECT_CONTROL_SESSION);
+ intentFilter.addAction(ACTION_CHECK_MUSIC_ACTIVE);
mContext.registerReceiverAsUser(mReceiver, UserHandle.ALL, intentFilter, null, null,
Context.RECEIVER_EXPORTED);
@@ -1927,13 +1932,7 @@ public class AudioService extends IAudioService.Stub
if (state == AudioService.CONNECTION_STATE_CONNECTED) {
// DEVICE_OUT_HDMI is now connected
if (mSafeMediaVolumeDevices.contains(AudioSystem.DEVICE_OUT_HDMI)) {
- sendMsg(mAudioHandler,
- MSG_CHECK_MUSIC_ACTIVE,
- SENDMSG_REPLACE,
- 0,
- 0,
- caller,
- MUSIC_ACTIVE_POLL_PERIOD_MS);
+ scheduleMusicActiveCheck();
}
if (isPlatformTelevision()) {
@@ -3822,8 +3821,9 @@ public class AudioService extends IAudioService.Stub
}
private AtomicBoolean mVoicePlaybackActive = new AtomicBoolean(false);
+ private AtomicBoolean mMediaPlaybackActive = new AtomicBoolean(false);
- private final IPlaybackConfigDispatcher mVoicePlaybackActivityMonitor =
+ private final IPlaybackConfigDispatcher mPlaybackActivityMonitor =
new IPlaybackConfigDispatcher.Stub() {
@Override
public void dispatchPlaybackConfigChange(List<AudioPlaybackConfiguration> configs,
@@ -3836,19 +3836,26 @@ public class AudioService extends IAudioService.Stub
private void onPlaybackConfigChange(List<AudioPlaybackConfiguration> configs) {
boolean voiceActive = false;
+ boolean mediaActive = false;
for (AudioPlaybackConfiguration config : configs) {
final int usage = config.getAudioAttributes().getUsage();
- if ((usage == AudioAttributes.USAGE_VOICE_COMMUNICATION
- || usage == AudioAttributes.USAGE_VOICE_COMMUNICATION_SIGNALLING)
- && config.getPlayerState() == AudioPlaybackConfiguration.PLAYER_STATE_STARTED) {
+ if (!config.isActive()) {
+ continue;
+ }
+ if (usage == AudioAttributes.USAGE_VOICE_COMMUNICATION
+ || usage == AudioAttributes.USAGE_VOICE_COMMUNICATION_SIGNALLING) {
voiceActive = true;
- break;
+ }
+ if (usage == AudioAttributes.USAGE_MEDIA || usage == AudioAttributes.USAGE_GAME) {
+ mediaActive = true;
}
}
if (mVoicePlaybackActive.getAndSet(voiceActive) != voiceActive) {
updateHearingAidVolumeOnVoiceActivityUpdate();
}
-
+ if (mMediaPlaybackActive.getAndSet(mediaActive) != mediaActive && mediaActive) {
+ scheduleMusicActiveCheck();
+ }
// Update playback active state for all apps in audio mode stack.
// When the audio mode owner becomes active, replace any delayed MSG_UPDATE_AUDIO_MODE
// and request an audio mode update immediately. Upon any other change, queue the message
@@ -6031,30 +6038,52 @@ public class AudioService extends IAudioService.Stub
return mContentResolver;
}
+ private void scheduleMusicActiveCheck() {
+ synchronized (mSafeMediaVolumeStateLock) {
+ cancelMusicActiveCheck();
+ mMusicActiveIntent = PendingIntent.getBroadcast(mContext,
+ REQUEST_CODE_CHECK_MUSIC_ACTIVE,
+ new Intent(ACTION_CHECK_MUSIC_ACTIVE),
+ PendingIntent.FLAG_UPDATE_CURRENT | PendingIntent.FLAG_IMMUTABLE);
+ mAlarmManager.setExactAndAllowWhileIdle(AlarmManager.ELAPSED_REALTIME_WAKEUP,
+ SystemClock.elapsedRealtime()
+ + MUSIC_ACTIVE_POLL_PERIOD_MS, mMusicActiveIntent);
+ }
+ }
+
+ private void cancelMusicActiveCheck() {
+ synchronized (mSafeMediaVolumeStateLock) {
+ if (mMusicActiveIntent != null) {
+ mAlarmManager.cancel(mMusicActiveIntent);
+ mMusicActiveIntent = null;
+ }
+ }
+ }
private void onCheckMusicActive(String caller) {
synchronized (mSafeMediaVolumeStateLock) {
if (mSafeMediaVolumeState == SAFE_MEDIA_VOLUME_INACTIVE) {
int device = getDeviceForStream(AudioSystem.STREAM_MUSIC);
-
- if (mSafeMediaVolumeDevices.contains(device)) {
- sendMsg(mAudioHandler,
- MSG_CHECK_MUSIC_ACTIVE,
- SENDMSG_REPLACE,
- 0,
- 0,
- caller,
- MUSIC_ACTIVE_POLL_PERIOD_MS);
+ if (mSafeMediaVolumeDevices.contains(device)
+ && mAudioSystem.isStreamActive(AudioSystem.STREAM_MUSIC, 0)) {
+ scheduleMusicActiveCheck();
int index = mStreamStates[AudioSystem.STREAM_MUSIC].getIndex(device);
- if (mAudioSystem.isStreamActive(AudioSystem.STREAM_MUSIC, 0)
- && (index > safeMediaVolumeIndex(device))) {
+ if (index > safeMediaVolumeIndex(device)) {
// Approximate cumulative active music time
- mMusicActiveMs += MUSIC_ACTIVE_POLL_PERIOD_MS;
+ long curTimeMs = SystemClock.elapsedRealtime();
+ if (mLastMusicActiveTimeMs != 0) {
+ mMusicActiveMs += (int) (curTimeMs - mLastMusicActiveTimeMs);
+ }
+ mLastMusicActiveTimeMs = curTimeMs;
+ Log.i(TAG, "onCheckMusicActive() mMusicActiveMs: " + mMusicActiveMs);
if (mMusicActiveMs > UNSAFE_VOLUME_MUSIC_ACTIVE_MS_MAX) {
setSafeMediaVolumeEnabled(true, caller);
mMusicActiveMs = 0;
}
saveMusicActiveMs();
}
+ } else {
+ cancelMusicActiveCheck();
+ mLastMusicActiveTimeMs = 0;
}
}
}
@@ -6123,6 +6152,7 @@ public class AudioService extends IAudioService.Stub
} else {
// We have existing playback time recorded, already confirmed.
mSafeMediaVolumeState = SAFE_MEDIA_VOLUME_INACTIVE;
+ mLastMusicActiveTimeMs = 0;
}
}
} else {
@@ -8632,13 +8662,7 @@ public class AudioService extends IAudioService.Stub
@VisibleForTesting
public void checkMusicActive(int deviceType, String caller) {
if (mSafeMediaVolumeDevices.contains(deviceType)) {
- sendMsg(mAudioHandler,
- MSG_CHECK_MUSIC_ACTIVE,
- SENDMSG_REPLACE,
- 0,
- 0,
- caller,
- MUSIC_ACTIVE_POLL_PERIOD_MS);
+ scheduleMusicActiveCheck();
}
}
@@ -8763,6 +8787,8 @@ public class AudioService extends IAudioService.Stub
suspendedPackages[i], suspendedUids[i]);
}
}
+ } else if (action.equals(ACTION_CHECK_MUSIC_ACTIVE)) {
+ onCheckMusicActive(ACTION_CHECK_MUSIC_ACTIVE);
}
}
} // end class AudioServiceBroadcastReceiver
@@ -9708,12 +9734,20 @@ public class AudioService extends IAudioService.Stub
// When this time reaches UNSAFE_VOLUME_MUSIC_ACTIVE_MS_MAX, the safe media volume is re-enabled
// automatically. mMusicActiveMs is rounded to a multiple of MUSIC_ACTIVE_POLL_PERIOD_MS.
private int mMusicActiveMs;
+ private long mLastMusicActiveTimeMs = 0;
+ private PendingIntent mMusicActiveIntent = null;
+ private AlarmManager mAlarmManager;
+
private static final int UNSAFE_VOLUME_MUSIC_ACTIVE_MS_MAX = (20 * 3600 * 1000); // 20 hours
private static final int MUSIC_ACTIVE_POLL_PERIOD_MS = 60000; // 1 minute polling interval
private static final int SAFE_VOLUME_CONFIGURE_TIMEOUT_MS = 30000; // 30s after boot completed
// check playback or record activity every 6 seconds for UIDs owning mode IN_COMMUNICATION
private static final int CHECK_MODE_FOR_UID_PERIOD_MS = 6000;
+ private static final String ACTION_CHECK_MUSIC_ACTIVE =
+ AudioService.class.getSimpleName() + ".CHECK_MUSIC_ACTIVE";
+ private static final int REQUEST_CODE_CHECK_MUSIC_ACTIVE = 1;
+
private int safeMediaVolumeIndex(int device) {
if (!mSafeMediaVolumeDevices.contains(device)) {
return MAX_STREAM_VOLUME[AudioSystem.STREAM_MUSIC];
@@ -9735,14 +9769,9 @@ public class AudioService extends IAudioService.Stub
} else if (!on && (mSafeMediaVolumeState == SAFE_MEDIA_VOLUME_ACTIVE)) {
mSafeMediaVolumeState = SAFE_MEDIA_VOLUME_INACTIVE;
mMusicActiveMs = 1; // nonzero = confirmed
+ mLastMusicActiveTimeMs = 0;
saveMusicActiveMs();
- sendMsg(mAudioHandler,
- MSG_CHECK_MUSIC_ACTIVE,
- SENDMSG_REPLACE,
- 0,
- 0,
- caller,
- MUSIC_ACTIVE_POLL_PERIOD_MS);
+ scheduleMusicActiveCheck();
}
}
}
@@ -9784,7 +9813,9 @@ public class AudioService extends IAudioService.Stub
public void disableSafeMediaVolume(String callingPackage) {
enforceVolumeController("disable the safe media volume");
synchronized (mSafeMediaVolumeStateLock) {
+ final long identity = Binder.clearCallingIdentity();
setSafeMediaVolumeEnabled(false, callingPackage);
+ Binder.restoreCallingIdentity(identity);
if (mPendingVolumeCommand != null) {
onSetStreamVolume(mPendingVolumeCommand.mStreamType,
mPendingVolumeCommand.mIndex,