From 1438db068e6be2e6ac240089195bcfd97c0da90f Mon Sep 17 00:00:00 2001 From: Simon Bowden Date: Wed, 12 Apr 2023 16:18:29 +0000 Subject: [PATCH] Don't hold clients lock while initializing Ringtone. Bug: 275012141 Test: presubmit Change-Id: I9f1bfb8d6eae7020ff64f6798c96639bfa401c7b Merged-In: Ic1b753cde9afc6536d137618df54c21eec38487a --- .../systemui/media/RingtonePlayer.java | 40 +++++++++++-------- 1 file changed, 24 insertions(+), 16 deletions(-) diff --git a/packages/SystemUI/src/com/android/systemui/media/RingtonePlayer.java b/packages/SystemUI/src/com/android/systemui/media/RingtonePlayer.java index 2a8168b0cb36a..05e04a11d7bab 100644 --- a/packages/SystemUI/src/com/android/systemui/media/RingtonePlayer.java +++ b/packages/SystemUI/src/com/android/systemui/media/RingtonePlayer.java @@ -88,18 +88,9 @@ public class RingtonePlayer implements CoreStartable { private final IBinder mToken; private final Ringtone mRingtone; - public Client(IBinder token, Uri uri, UserHandle user, AudioAttributes aa) { - this(token, uri, user, aa, null); - } - - Client(IBinder token, Uri uri, UserHandle user, AudioAttributes aa, - @Nullable VolumeShaper.Configuration volumeShaperConfig) { + Client(IBinder token, Ringtone ringtone) { mToken = token; - - mRingtone = new Ringtone(getContextForUser(user), false); - mRingtone.setAudioAttributesField(aa); - mRingtone.setUri(uri, volumeShaperConfig); - mRingtone.createLocalMediaPlayer(); + mRingtone = ringtone; } @Override @@ -129,11 +120,28 @@ public class RingtonePlayer implements CoreStartable { Client client; synchronized (mClients) { client = mClients.get(token); - if (client == null) { - final UserHandle user = Binder.getCallingUserHandle(); - client = new Client(token, uri, user, aa, volumeShaperConfig); - token.linkToDeath(client, 0); - mClients.put(token, client); + } + // Don't hold the lock while constructing the ringtone, since it can be slow. The caller + // shouldn't call play on the same ringtone from 2 threads, so this shouldn't race and + // waste the build. + if (client == null) { + final UserHandle user = Binder.getCallingUserHandle(); + Ringtone ringtone = new Ringtone(getContextForUser(user), false); + ringtone.setAudioAttributesField(aa); + ringtone.setUri(uri, volumeShaperConfig); + ringtone.createLocalMediaPlayer(); + synchronized (mClients) { + client = mClients.get(token); + if (client == null) { + client = new Client(token, ringtone); + token.linkToDeath(client, 0); + mClients.put(token, client); + ringtone = null; // "owned" by the client now. + } + } + // Clean up ringtone if it was abandoned (a client already existed). + if (ringtone != null) { + ringtone.stop(); } } client.mRingtone.setLooping(looping);