diff options
| author | 2022-09-20 00:43:05 +0000 | |
|---|---|---|
| committer | 2022-10-05 19:07:31 +0000 | |
| commit | 8a1cbede1dba2cd359324aaef245b4dbd49b9e90 (patch) | |
| tree | 5893c5a7af082cb0db57fe5628562c2a3508a19a | |
| parent | 3e5c74adf4c36aee6f635dfae4a686eb8a15ee2c (diff) | |
AudioService: fix unsafe volume playback time accumulation
Use the AlarmManager and intents as periodic timer instead of the
message handler when accumulating the playback time with unsafe volume levels.
Using the handler was not counting time spend in suspend which happens
when using offload playback.
Bug: 244322644
Test: repo steps in bug
Change-Id: Ife6fda6120b9a2d6c30cc87a76be1521416c0628
(cherry picked from commit 92cb946d7fbb01d1683aa6c3dff2e29f41b573a9)
| -rw-r--r-- | services/core/java/com/android/server/audio/AudioService.java | 111 |
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 0b6b89074cfc..02bfdfc7b076 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 @@ -6032,30 +6039,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; } } } @@ -6124,6 +6153,7 @@ public class AudioService extends IAudioService.Stub } else { // We have existing playback time recorded, already confirmed. mSafeMediaVolumeState = SAFE_MEDIA_VOLUME_INACTIVE; + mLastMusicActiveTimeMs = 0; } } } else { @@ -8633,13 +8663,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(); } } @@ -8764,6 +8788,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 @@ -9709,12 +9735,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]; @@ -9736,14 +9770,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(); } } } @@ -9785,7 +9814,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, |