Skip to content

Commit de1f065

Browse files
committed
Fix 5607938 AudioFocusDeathHandler leaks GREF
The AudioFocus death handler was correctly updating the audio focus stack when an audio focus client dies, but the death handler was leaking GREF if unlinkToDeath() is not called. The fix consists in making sure unlinkToDeath() is always called by calling it in its finalizer. Change-Id: I0c5343b4986ab582cadbf171fc53816952dc16f5
1 parent 24597eb commit de1f065

File tree

1 file changed

+16
-4
lines changed

1 file changed

+16
-4
lines changed

media/java/android/media/AudioService.java

Lines changed: 16 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2693,11 +2693,22 @@ public FocusStackEntry(int streamType, int duration,
26932693
mCallingUid = uid;
26942694
}
26952695

2696-
public void unlinkToDeath() {
2696+
private void unlinkToDeath() {
26972697
if (mSourceRef != null && mHandler != null) {
26982698
mSourceRef.unlinkToDeath(mHandler, 0);
26992699
}
27002700
}
2701+
2702+
@Override
2703+
protected void finalize() throws Throwable {
2704+
try {
2705+
unlinkToDeath();
2706+
} catch (java.util.NoSuchElementException e) {
2707+
Log.w(TAG, e + " thrown by unlinkToDeath() during finalize, ignoring");
2708+
} finally {
2709+
super.finalize();
2710+
}
2711+
}
27012712
}
27022713

27032714
private Stack<FocusStackEntry> mFocusStack = new Stack<FocusStackEntry>();
@@ -2732,8 +2743,7 @@ private void removeFocusStackEntry(String clientToRemove, boolean signal) {
27322743
if (!mFocusStack.empty() && mFocusStack.peek().mClientId.equals(clientToRemove))
27332744
{
27342745
//Log.i(TAG, " removeFocusStackEntry() removing top of stack");
2735-
FocusStackEntry fse = mFocusStack.pop();
2736-
fse.unlinkToDeath();
2746+
mFocusStack.pop();
27372747
if (signal) {
27382748
// notify the new top of the stack it gained focus
27392749
notifyTopOfAudioFocusStack();
@@ -2752,7 +2762,6 @@ private void removeFocusStackEntry(String clientToRemove, boolean signal) {
27522762
Log.i(TAG, " AudioFocus abandonAudioFocus(): removing entry for "
27532763
+ fse.mClientId);
27542764
stackIterator.remove();
2755-
fse.unlinkToDeath();
27562765
}
27572766
}
27582767
}
@@ -2858,6 +2867,9 @@ public int requestAudioFocus(int mainStreamType, int focusChangeHint, IBinder cb
28582867
// if focus is already owned by this client and the reason for acquiring the focus
28592868
// hasn't changed, don't do anything
28602869
if (mFocusStack.peek().mFocusChangeType == focusChangeHint) {
2870+
// unlink death handler so it can be gc'ed.
2871+
// linkToDeath() creates a JNI global reference preventing collection.
2872+
cb.unlinkToDeath(afdh, 0);
28612873
return AudioManager.AUDIOFOCUS_REQUEST_GRANTED;
28622874
}
28632875
// the reason for the audio focus request has changed: remove the current top of

0 commit comments

Comments
 (0)