Ensure metadata bundles are unparceled before making them available

Bundles can't be read from multiple threads safely. This adds locking
around a read that had been previously overlooked and ensures that
unparcel is called on the metadata before it is even available to
other threads.

bug:17894033
Change-Id: I9a4b86a0d0af05b1dcba28a52df2e7a87c685704
This commit is contained in:
RoboErik
2014-10-08 10:38:42 -07:00
parent 78cc93ec80
commit 82df2c0839

View File

@@ -625,12 +625,12 @@ public class MediaSessionRecord implements IBinder.DeathRecipient {
private PlaybackState getStateWithUpdatedPosition() {
PlaybackState state;
long duration = -1;
synchronized (mLock) {
state = mPlaybackState;
}
long duration = -1;
if (mMetadata != null && mMetadata.containsKey(MediaMetadata.METADATA_KEY_DURATION)) {
duration = mMetadata.getLong(MediaMetadata.METADATA_KEY_DURATION);
if (mMetadata != null && mMetadata.containsKey(MediaMetadata.METADATA_KEY_DURATION)) {
duration = mMetadata.getLong(MediaMetadata.METADATA_KEY_DURATION);
}
}
PlaybackState result = null;
if (state != null) {
@@ -725,10 +725,14 @@ public class MediaSessionRecord implements IBinder.DeathRecipient {
@Override
public void setMetadata(MediaMetadata metadata) {
// Make a copy of the metadata as the underlying bundle may be
// modified on this thread.
synchronized (mLock) {
mMetadata = metadata == null ? null : new MediaMetadata.Builder(metadata).build();
MediaMetadata temp = metadata == null ? null : new MediaMetadata.Builder(metadata)
.build();
// This is to guarantee that the underlying bundle is unparceled
// before we set it to prevent concurrent reads from throwing an
// exception
temp.size();
mMetadata = temp;
}
mHandler.post(MessageHandler.MSG_UPDATE_METADATA);
}