Commit d72d2547 by gyumin Committed by Oliver Woodman

Add Bundleable interface

It's for classes to clearly denote they support bundling and it gives
us a good place to document the best practice to implement fromBundle.

PiperOrigin-RevId: 355609942
parent 35d34af2
/*
* Copyright 2021 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.google.android.exoplayer2;
import android.os.Bundle;
/**
* Interface for classes whose instance can be stored in a {@link Bundle} by {@link #toBundle()} and
* can be restored from the {@link Bundle} by using the static {@code CREATOR} field that implements
* {@link Bundleable.Creator}.
*
* <p>For example, a {@link Bundleable} class {@code Foo} supports the following:
*
* <pre>{@code
* Foo foo = ...;
* Bundle fooBundle = foo.toBundle();
* Foo restoredFoo = Foo.CREATOR.fromBundle(fooBundle);
* assertThat(restoredFoo).isEqualTo(foo);
* }</pre>
*/
public interface Bundleable {
/** Returns a {@link Bundle} representing the information stored in this object. */
Bundle toBundle();
/** Interface for the static {@code CREATOR} field of {@link Bundleable} classes. */
interface Creator<T extends Bundleable> {
/**
* Restores a {@link Bundleable} instance from a {@link Bundle} produced by {@link
* Bundleable#toBundle()}.
*
* <p>It guarantees the compatibility of {@link Bundle} representations produced by different
* versions of {@link Bundleable#toBundle()} by providing best default values for missing
* fields. It may throw an {@link IllegalArgumentException} if any essential fields are missing.
*/
T fromBundle(Bundle bundle);
}
}
...@@ -18,6 +18,7 @@ package com.google.android.exoplayer2.audio; ...@@ -18,6 +18,7 @@ package com.google.android.exoplayer2.audio;
import android.os.Bundle; import android.os.Bundle;
import androidx.annotation.Nullable; import androidx.annotation.Nullable;
import androidx.annotation.RequiresApi; import androidx.annotation.RequiresApi;
import com.google.android.exoplayer2.Bundleable;
import com.google.android.exoplayer2.C; import com.google.android.exoplayer2.C;
import com.google.android.exoplayer2.util.Util; import com.google.android.exoplayer2.util.Util;
...@@ -32,7 +33,7 @@ import com.google.android.exoplayer2.util.Util; ...@@ -32,7 +33,7 @@ import com.google.android.exoplayer2.util.Util;
* <p>This class is based on {@link android.media.AudioAttributes}, but can be used on all supported * <p>This class is based on {@link android.media.AudioAttributes}, but can be used on all supported
* API versions. * API versions.
*/ */
public final class AudioAttributes { public final class AudioAttributes implements Bundleable {
private static final String FIELD_CONTENT_TYPE = "contentType"; private static final String FIELD_CONTENT_TYPE = "contentType";
private static final String FIELD_FLAGS = "flags"; private static final String FIELD_FLAGS = "flags";
...@@ -165,7 +166,7 @@ public final class AudioAttributes { ...@@ -165,7 +166,7 @@ public final class AudioAttributes {
return result; return result;
} }
/** Converts this instance into a {@link Bundle}. */ @Override
public Bundle toBundle() { public Bundle toBundle() {
Bundle bundle = new Bundle(); Bundle bundle = new Bundle();
bundle.putInt(FIELD_CONTENT_TYPE, contentType); bundle.putInt(FIELD_CONTENT_TYPE, contentType);
...@@ -175,21 +176,21 @@ public final class AudioAttributes { ...@@ -175,21 +176,21 @@ public final class AudioAttributes {
return bundle; return bundle;
} }
/** Creates an {@link AudioAttributes} instance from a {@link Bundle}. */ public static final Creator<AudioAttributes> CREATOR =
public static AudioAttributes fromBundle(Bundle bundle) { bundle -> {
Builder builder = new Builder(); Builder builder = new Builder();
if (bundle.containsKey(FIELD_CONTENT_TYPE)) { if (bundle.containsKey(FIELD_CONTENT_TYPE)) {
builder.setContentType(bundle.getInt(FIELD_CONTENT_TYPE)); builder.setContentType(bundle.getInt(FIELD_CONTENT_TYPE));
} }
if (bundle.containsKey(FIELD_FLAGS)) { if (bundle.containsKey(FIELD_FLAGS)) {
builder.setFlags(bundle.getInt(FIELD_FLAGS)); builder.setFlags(bundle.getInt(FIELD_FLAGS));
} }
if (bundle.containsKey(FIELD_USAGE)) { if (bundle.containsKey(FIELD_USAGE)) {
builder.setUsage(bundle.getInt(FIELD_USAGE)); builder.setUsage(bundle.getInt(FIELD_USAGE));
} }
if (bundle.containsKey(FIELD_ALLOWED_CAPTURE_POLICY)) { if (bundle.containsKey(FIELD_ALLOWED_CAPTURE_POLICY)) {
builder.setAllowedCapturePolicy(bundle.getInt(FIELD_ALLOWED_CAPTURE_POLICY)); builder.setAllowedCapturePolicy(bundle.getInt(FIELD_ALLOWED_CAPTURE_POLICY));
} }
return builder.build(); return builder.build();
} };
} }
...@@ -18,6 +18,7 @@ package com.google.android.exoplayer2.device; ...@@ -18,6 +18,7 @@ package com.google.android.exoplayer2.device;
import android.os.Bundle; import android.os.Bundle;
import androidx.annotation.IntDef; import androidx.annotation.IntDef;
import androidx.annotation.Nullable; import androidx.annotation.Nullable;
import com.google.android.exoplayer2.Bundleable;
import java.lang.annotation.Documented; import java.lang.annotation.Documented;
import java.lang.annotation.ElementType; import java.lang.annotation.ElementType;
import java.lang.annotation.Retention; import java.lang.annotation.Retention;
...@@ -25,7 +26,7 @@ import java.lang.annotation.RetentionPolicy; ...@@ -25,7 +26,7 @@ import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target; import java.lang.annotation.Target;
/** Information about the playback device. */ /** Information about the playback device. */
public final class DeviceInfo { public final class DeviceInfo implements Bundleable {
private static final String FIELD_PLAYBACK_TYPE = "playbackType"; private static final String FIELD_PLAYBACK_TYPE = "playbackType";
private static final String FIELD_MIN_VOLUME = "minVolume"; private static final String FIELD_MIN_VOLUME = "minVolume";
...@@ -86,7 +87,7 @@ public final class DeviceInfo { ...@@ -86,7 +87,7 @@ public final class DeviceInfo {
return result; return result;
} }
/** Converts this instance into a {@link Bundle}. */ @Override
public Bundle toBundle() { public Bundle toBundle() {
Bundle bundle = new Bundle(); Bundle bundle = new Bundle();
bundle.putInt(FIELD_PLAYBACK_TYPE, playbackType); bundle.putInt(FIELD_PLAYBACK_TYPE, playbackType);
...@@ -95,11 +96,12 @@ public final class DeviceInfo { ...@@ -95,11 +96,12 @@ public final class DeviceInfo {
return bundle; return bundle;
} }
/** Creates an {@link DeviceInfo} instance from a {@link Bundle}. */ public static final Creator<DeviceInfo> CREATOR =
public static DeviceInfo fromBundle(Bundle bundle) { bundle -> {
int playbackType = bundle.getInt(FIELD_PLAYBACK_TYPE, /* defaultValue= */ PLAYBACK_TYPE_LOCAL); int playbackType =
int minVolume = bundle.getInt(FIELD_MIN_VOLUME, /* defaultValue= */ 0); bundle.getInt(FIELD_PLAYBACK_TYPE, /* defaultValue= */ PLAYBACK_TYPE_LOCAL);
int maxVolume = bundle.getInt(FIELD_MAX_VOLUME, /* defaultValue= */ 0); int minVolume = bundle.getInt(FIELD_MIN_VOLUME, /* defaultValue= */ 0);
return new DeviceInfo(playbackType, minVolume, maxVolume); int maxVolume = bundle.getInt(FIELD_MAX_VOLUME, /* defaultValue= */ 0);
} return new DeviceInfo(playbackType, minVolume, maxVolume);
};
} }
...@@ -36,6 +36,7 @@ public class AudioAttributesTest { ...@@ -36,6 +36,7 @@ public class AudioAttributesTest {
.setAllowedCapturePolicy(C.ALLOW_CAPTURE_BY_SYSTEM) .setAllowedCapturePolicy(C.ALLOW_CAPTURE_BY_SYSTEM)
.build(); .build();
assertThat(AudioAttributes.fromBundle(audioAttributes.toBundle())).isEqualTo(audioAttributes); assertThat(AudioAttributes.CREATOR.fromBundle(audioAttributes.toBundle()))
.isEqualTo(audioAttributes);
} }
} }
...@@ -30,6 +30,6 @@ public class DeviceInfoTest { ...@@ -30,6 +30,6 @@ public class DeviceInfoTest {
DeviceInfo deviceInfo = DeviceInfo deviceInfo =
new DeviceInfo(DeviceInfo.PLAYBACK_TYPE_REMOTE, /* minVolume= */ 1, /* maxVolume= */ 9); new DeviceInfo(DeviceInfo.PLAYBACK_TYPE_REMOTE, /* minVolume= */ 1, /* maxVolume= */ 9);
assertThat(DeviceInfo.fromBundle(deviceInfo.toBundle())).isEqualTo(deviceInfo); assertThat(DeviceInfo.CREATOR.fromBundle(deviceInfo.toBundle())).isEqualTo(deviceInfo);
} }
} }
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or sign in to comment