diff options
| author | 2021-06-01 13:23:51 +0900 | |
|---|---|---|
| committer | 2021-06-01 21:20:05 +0900 | |
| commit | a3aec61861b8d1f8e95454b7411f4181614f07b3 (patch) | |
| tree | 5f0c0a53c4d8003da139eeebe0e9d183fe557042 | |
| parent | a0ecdaafd516b94f59d420a86b3632eaa9de55aa (diff) | |
Ensure MediaSession2Record is initialized before used
NPE happens at mController.close() if session is destroyed while the
MediaController2 instance is being created in the constructor of
MediaSession2Record. It ensures the MediaSession2Record instance is
initialized before the instance is used by Controller2Callback.
Bug: 189119798
Fix: 189119798
Test: atest CtsMediaTestCases:android.media.cts.MediaSessionTest
Change-Id: I23ca2f3dbc657ac38f4154a0fb428a4c25e6b5ad
| -rw-r--r-- | services/core/java/com/android/server/media/MediaSession2Record.java | 32 |
1 files changed, 22 insertions, 10 deletions
diff --git a/services/core/java/com/android/server/media/MediaSession2Record.java b/services/core/java/com/android/server/media/MediaSession2Record.java index 162c388dadd1..607218e20ea8 100644 --- a/services/core/java/com/android/server/media/MediaSession2Record.java +++ b/services/core/java/com/android/server/media/MediaSession2Record.java @@ -56,13 +56,17 @@ public class MediaSession2Record implements MediaSessionRecordImpl { public MediaSession2Record(Session2Token sessionToken, MediaSessionService service, Looper handlerLooper, int policies) { - mSessionToken = sessionToken; - mService = service; - mHandlerExecutor = new HandlerExecutor(new Handler(handlerLooper)); - mController = new MediaController2.Builder(service.getContext(), sessionToken) - .setControllerCallback(mHandlerExecutor, new Controller2Callback()) - .build(); - mPolicies = policies; + // The lock is required to prevent `Controller2Callback` from using partially initialized + // `MediaSession2Record.this`. + synchronized (mLock) { + mSessionToken = sessionToken; + mService = service; + mHandlerExecutor = new HandlerExecutor(new Handler(handlerLooper)); + mController = new MediaController2.Builder(service.getContext(), sessionToken) + .setControllerCallback(mHandlerExecutor, new Controller2Callback()) + .build(); + mPolicies = policies; + } } @Override @@ -176,10 +180,12 @@ public class MediaSession2Record implements MediaSessionRecordImpl { if (DEBUG) { Log.d(TAG, "connected to " + mSessionToken + ", allowed=" + allowedCommands); } + MediaSessionService service; synchronized (mLock) { mIsConnected = true; + service = mService; } - mService.onSessionActiveStateChanged(MediaSession2Record.this); + service.onSessionActiveStateChanged(MediaSession2Record.this); } @Override @@ -187,10 +193,12 @@ public class MediaSession2Record implements MediaSessionRecordImpl { if (DEBUG) { Log.d(TAG, "disconnected from " + mSessionToken); } + MediaSessionService service; synchronized (mLock) { mIsConnected = false; + service = mService; } - mService.onSessionDied(MediaSession2Record.this); + service.onSessionDied(MediaSession2Record.this); } @Override @@ -199,7 +207,11 @@ public class MediaSession2Record implements MediaSessionRecordImpl { Log.d(TAG, "playback active changed, " + mSessionToken + ", active=" + playbackActive); } - mService.onSessionPlaybackStateChanged(MediaSession2Record.this, playbackActive); + MediaSessionService service; + synchronized (mLock) { + service = mService; + } + service.onSessionPlaybackStateChanged(MediaSession2Record.this, playbackActive); } } } |