Merge "AudioService: fix unsafe volume playback time accumulation" into tm-qpr-dev
This commit is contained in:
@@ -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,
|
||||||
|
|||||||
Reference in New Issue
Block a user