summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
author Gyumin Sim <gyumin@google.com> 2021-06-01 13:23:51 +0900
committer Gyumin Sim <gyumin@google.com> 2021-06-01 21:20:05 +0900
commita3aec61861b8d1f8e95454b7411f4181614f07b3 (patch)
tree5f0c0a53c4d8003da139eeebe0e9d183fe557042
parenta0ecdaafd516b94f59d420a86b3632eaa9de55aa (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.java32
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);
}
}
}