Merge "AudioService: fix unsafe volume playback time accumulation" into tm-qpr-dev am: 9a778e33ed

Original change: https://googleplex-android-review.googlesource.com/c/platform/frameworks/base/+/20105538

Change-Id: Ic7b5bfbd06d2eadf79db9a18c90786dd18bcb5f5
Signed-off-by: Automerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com>
This commit is contained in:
Eric Laurent
2022-10-07 13:55:03 +00:00
committed by Automerger Merge Worker

View File

@@ -41,10 +41,12 @@ import android.annotation.SuppressLint;
import android.annotation.UserIdInt; import android.annotation.UserIdInt;
import android.app.ActivityManager; import android.app.ActivityManager;
import android.app.ActivityManagerInternal; import android.app.ActivityManagerInternal;
import android.app.AlarmManager;
import android.app.AppGlobals; import android.app.AppGlobals;
import android.app.AppOpsManager; import android.app.AppOpsManager;
import android.app.IUidObserver; import android.app.IUidObserver;
import android.app.NotificationManager; import android.app.NotificationManager;
import android.app.PendingIntent;
import android.app.role.OnRoleHoldersChangedListener; import android.app.role.OnRoleHoldersChangedListener;
import android.app.role.RoleManager; import android.app.role.RoleManager;
import android.bluetooth.BluetoothAdapter; import android.bluetooth.BluetoothAdapter;
@@ -1185,6 +1187,8 @@ public class AudioService extends IAudioService.Stub
mSafeMediaVolumeIndex = mContext.getResources().getInteger( mSafeMediaVolumeIndex = mContext.getResources().getInteger(
com.android.internal.R.integer.config_safe_media_volume_index) * 10; com.android.internal.R.integer.config_safe_media_volume_index) * 10;
mAlarmManager = (AlarmManager) mContext.getSystemService(Context.ALARM_SERVICE);
mUseFixedVolume = mContext.getResources().getBoolean( mUseFixedVolume = mContext.getResources().getBoolean(
com.android.internal.R.bool.config_useFixedVolume); com.android.internal.R.bool.config_useFixedVolume);
@@ -1202,7 +1206,7 @@ public class AudioService extends IAudioService.Stub
mPlaybackMonitor = mPlaybackMonitor =
new PlaybackActivityMonitor(context, MAX_STREAM_VOLUME[AudioSystem.STREAM_ALARM], new PlaybackActivityMonitor(context, MAX_STREAM_VOLUME[AudioSystem.STREAM_ALARM],
device -> onMuteAwaitConnectionTimeout(device)); device -> onMuteAwaitConnectionTimeout(device));
mPlaybackMonitor.registerPlaybackCallback(mVoicePlaybackActivityMonitor, true); mPlaybackMonitor.registerPlaybackCallback(mPlaybackActivityMonitor, true);
mMediaFocusControl = new MediaFocusControl(mContext, mPlaybackMonitor); 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_OPEN_AUDIO_EFFECT_CONTROL_SESSION);
intentFilter.addAction(AudioEffect.ACTION_CLOSE_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, mContext.registerReceiverAsUser(mReceiver, UserHandle.ALL, intentFilter, null, null,
Context.RECEIVER_EXPORTED); Context.RECEIVER_EXPORTED);
@@ -1927,13 +1932,7 @@ public class AudioService extends IAudioService.Stub
if (state == AudioService.CONNECTION_STATE_CONNECTED) { if (state == AudioService.CONNECTION_STATE_CONNECTED) {
// DEVICE_OUT_HDMI is now connected // DEVICE_OUT_HDMI is now connected
if (mSafeMediaVolumeDevices.contains(AudioSystem.DEVICE_OUT_HDMI)) { if (mSafeMediaVolumeDevices.contains(AudioSystem.DEVICE_OUT_HDMI)) {
sendMsg(mAudioHandler, scheduleMusicActiveCheck();
MSG_CHECK_MUSIC_ACTIVE,
SENDMSG_REPLACE,
0,
0,
caller,
MUSIC_ACTIVE_POLL_PERIOD_MS);
} }
if (isPlatformTelevision()) { if (isPlatformTelevision()) {
@@ -3822,8 +3821,9 @@ public class AudioService extends IAudioService.Stub
} }
private AtomicBoolean mVoicePlaybackActive = new AtomicBoolean(false); private AtomicBoolean mVoicePlaybackActive = new AtomicBoolean(false);
private AtomicBoolean mMediaPlaybackActive = new AtomicBoolean(false);
private final IPlaybackConfigDispatcher mVoicePlaybackActivityMonitor = private final IPlaybackConfigDispatcher mPlaybackActivityMonitor =
new IPlaybackConfigDispatcher.Stub() { new IPlaybackConfigDispatcher.Stub() {
@Override @Override
public void dispatchPlaybackConfigChange(List<AudioPlaybackConfiguration> configs, public void dispatchPlaybackConfigChange(List<AudioPlaybackConfiguration> configs,
@@ -3836,19 +3836,26 @@ public class AudioService extends IAudioService.Stub
private void onPlaybackConfigChange(List<AudioPlaybackConfiguration> configs) { private void onPlaybackConfigChange(List<AudioPlaybackConfiguration> configs) {
boolean voiceActive = false; boolean voiceActive = false;
boolean mediaActive = false;
for (AudioPlaybackConfiguration config : configs) { for (AudioPlaybackConfiguration config : configs) {
final int usage = config.getAudioAttributes().getUsage(); final int usage = config.getAudioAttributes().getUsage();
if ((usage == AudioAttributes.USAGE_VOICE_COMMUNICATION if (!config.isActive()) {
|| usage == AudioAttributes.USAGE_VOICE_COMMUNICATION_SIGNALLING) continue;
&& config.getPlayerState() == AudioPlaybackConfiguration.PLAYER_STATE_STARTED) { }
if (usage == AudioAttributes.USAGE_VOICE_COMMUNICATION
|| usage == AudioAttributes.USAGE_VOICE_COMMUNICATION_SIGNALLING) {
voiceActive = true; voiceActive = true;
break; }
if (usage == AudioAttributes.USAGE_MEDIA || usage == AudioAttributes.USAGE_GAME) {
mediaActive = true;
} }
} }
if (mVoicePlaybackActive.getAndSet(voiceActive) != voiceActive) { if (mVoicePlaybackActive.getAndSet(voiceActive) != voiceActive) {
updateHearingAidVolumeOnVoiceActivityUpdate(); updateHearingAidVolumeOnVoiceActivityUpdate();
} }
if (mMediaPlaybackActive.getAndSet(mediaActive) != mediaActive && mediaActive) {
scheduleMusicActiveCheck();
}
// Update playback active state for all apps in audio mode stack. // 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 // 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 // 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; 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) { private void onCheckMusicActive(String caller) {
synchronized (mSafeMediaVolumeStateLock) { synchronized (mSafeMediaVolumeStateLock) {
if (mSafeMediaVolumeState == SAFE_MEDIA_VOLUME_INACTIVE) { if (mSafeMediaVolumeState == SAFE_MEDIA_VOLUME_INACTIVE) {
int device = getDeviceForStream(AudioSystem.STREAM_MUSIC); int device = getDeviceForStream(AudioSystem.STREAM_MUSIC);
if (mSafeMediaVolumeDevices.contains(device)
if (mSafeMediaVolumeDevices.contains(device)) { && mAudioSystem.isStreamActive(AudioSystem.STREAM_MUSIC, 0)) {
sendMsg(mAudioHandler, scheduleMusicActiveCheck();
MSG_CHECK_MUSIC_ACTIVE,
SENDMSG_REPLACE,
0,
0,
caller,
MUSIC_ACTIVE_POLL_PERIOD_MS);
int index = mStreamStates[AudioSystem.STREAM_MUSIC].getIndex(device); int index = mStreamStates[AudioSystem.STREAM_MUSIC].getIndex(device);
if (mAudioSystem.isStreamActive(AudioSystem.STREAM_MUSIC, 0) if (index > safeMediaVolumeIndex(device)) {
&& (index > safeMediaVolumeIndex(device))) {
// Approximate cumulative active music time // 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) { if (mMusicActiveMs > UNSAFE_VOLUME_MUSIC_ACTIVE_MS_MAX) {
setSafeMediaVolumeEnabled(true, caller); setSafeMediaVolumeEnabled(true, caller);
mMusicActiveMs = 0; mMusicActiveMs = 0;
} }
saveMusicActiveMs(); saveMusicActiveMs();
} }
} else {
cancelMusicActiveCheck();
mLastMusicActiveTimeMs = 0;
} }
} }
} }
@@ -6123,6 +6152,7 @@ public class AudioService extends IAudioService.Stub
} else { } else {
// We have existing playback time recorded, already confirmed. // We have existing playback time recorded, already confirmed.
mSafeMediaVolumeState = SAFE_MEDIA_VOLUME_INACTIVE; mSafeMediaVolumeState = SAFE_MEDIA_VOLUME_INACTIVE;
mLastMusicActiveTimeMs = 0;
} }
} }
} else { } else {
@@ -8632,13 +8662,7 @@ public class AudioService extends IAudioService.Stub
@VisibleForTesting @VisibleForTesting
public void checkMusicActive(int deviceType, String caller) { public void checkMusicActive(int deviceType, String caller) {
if (mSafeMediaVolumeDevices.contains(deviceType)) { if (mSafeMediaVolumeDevices.contains(deviceType)) {
sendMsg(mAudioHandler, scheduleMusicActiveCheck();
MSG_CHECK_MUSIC_ACTIVE,
SENDMSG_REPLACE,
0,
0,
caller,
MUSIC_ACTIVE_POLL_PERIOD_MS);
} }
} }
@@ -8763,6 +8787,8 @@ public class AudioService extends IAudioService.Stub
suspendedPackages[i], suspendedUids[i]); suspendedPackages[i], suspendedUids[i]);
} }
} }
} else if (action.equals(ACTION_CHECK_MUSIC_ACTIVE)) {
onCheckMusicActive(ACTION_CHECK_MUSIC_ACTIVE);
} }
} }
} // end class AudioServiceBroadcastReceiver } // 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 // 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. // automatically. mMusicActiveMs is rounded to a multiple of MUSIC_ACTIVE_POLL_PERIOD_MS.
private int mMusicActiveMs; 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 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 MUSIC_ACTIVE_POLL_PERIOD_MS = 60000; // 1 minute polling interval
private static final int SAFE_VOLUME_CONFIGURE_TIMEOUT_MS = 30000; // 30s after boot completed 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 // 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 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) { private int safeMediaVolumeIndex(int device) {
if (!mSafeMediaVolumeDevices.contains(device)) { if (!mSafeMediaVolumeDevices.contains(device)) {
return MAX_STREAM_VOLUME[AudioSystem.STREAM_MUSIC]; 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)) { } else if (!on && (mSafeMediaVolumeState == SAFE_MEDIA_VOLUME_ACTIVE)) {
mSafeMediaVolumeState = SAFE_MEDIA_VOLUME_INACTIVE; mSafeMediaVolumeState = SAFE_MEDIA_VOLUME_INACTIVE;
mMusicActiveMs = 1; // nonzero = confirmed mMusicActiveMs = 1; // nonzero = confirmed
mLastMusicActiveTimeMs = 0;
saveMusicActiveMs(); saveMusicActiveMs();
sendMsg(mAudioHandler, scheduleMusicActiveCheck();
MSG_CHECK_MUSIC_ACTIVE,
SENDMSG_REPLACE,
0,
0,
caller,
MUSIC_ACTIVE_POLL_PERIOD_MS);
} }
} }
} }
@@ -9784,7 +9813,9 @@ public class AudioService extends IAudioService.Stub
public void disableSafeMediaVolume(String callingPackage) { public void disableSafeMediaVolume(String callingPackage) {
enforceVolumeController("disable the safe media volume"); enforceVolumeController("disable the safe media volume");
synchronized (mSafeMediaVolumeStateLock) { synchronized (mSafeMediaVolumeStateLock) {
final long identity = Binder.clearCallingIdentity();
setSafeMediaVolumeEnabled(false, callingPackage); setSafeMediaVolumeEnabled(false, callingPackage);
Binder.restoreCallingIdentity(identity);
if (mPendingVolumeCommand != null) { if (mPendingVolumeCommand != null) {
onSetStreamVolume(mPendingVolumeCommand.mStreamType, onSetStreamVolume(mPendingVolumeCommand.mStreamType,
mPendingVolumeCommand.mIndex, mPendingVolumeCommand.mIndex,