public final class

DefaultContentMetadata

extends java.lang.Object

implements ContentMetadata

 java.lang.Object

↳androidx.media3.datasource.cache.DefaultContentMetadata

Gradle dependencies

compile group: 'androidx.media3', name: 'media3-datasource', version: '1.5.0-alpha01'

  • groupId: androidx.media3
  • artifactId: media3-datasource
  • version: 1.5.0-alpha01

Artifact androidx.media3:media3-datasource:1.5.0-alpha01 it located at Google repository (https://maven.google.com/)

Overview

Default implementation of ContentMetadata. Values are stored as byte arrays.

Summary

Fields
public static final DefaultContentMetadataEMPTY

An empty DefaultContentMetadata.

Constructors
publicDefaultContentMetadata()

publicDefaultContentMetadata(java.util.Map<java.lang.String, UnknownReference> metadata)

Methods
public final booleancontains(java.lang.String key)

public DefaultContentMetadatacopyWithMutationsApplied(ContentMetadataMutations mutations)

Returns a copy DefaultContentMetadata with mutations applied.

public java.util.Set<java.util.Map.Entry>entrySet()

Returns the set of metadata entries in their raw byte array form.

public booleanequals(java.lang.Object o)

public final byte[]get(java.lang.String key, byte[] defaultValue[])

public final longget(java.lang.String key, long defaultValue)

public final java.lang.Stringget(java.lang.String key, java.lang.String defaultValue)

public inthashCode()

from java.lang.Objectclone, finalize, getClass, notify, notifyAll, toString, wait, wait, wait

Fields

public static final DefaultContentMetadata EMPTY

An empty DefaultContentMetadata.

Constructors

public DefaultContentMetadata()

public DefaultContentMetadata(java.util.Map<java.lang.String, UnknownReference> metadata)

Parameters:

metadata: The metadata entries in their raw byte array form.

Methods

public DefaultContentMetadata copyWithMutationsApplied(ContentMetadataMutations mutations)

Returns a copy DefaultContentMetadata with mutations applied. If mutations don't change anything, returns this instance.

public java.util.Set<java.util.Map.Entry> entrySet()

Returns the set of metadata entries in their raw byte array form.

public final byte[] get(java.lang.String key, byte[] defaultValue[])

public final java.lang.String get(java.lang.String key, java.lang.String defaultValue)

public final long get(java.lang.String key, long defaultValue)

public final boolean contains(java.lang.String key)

public boolean equals(java.lang.Object o)

public int hashCode()

Source

/*
 * Copyright (C) 2018 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 androidx.media3.datasource.cache;

import androidx.annotation.Nullable;
import androidx.media3.common.util.UnstableApi;
import java.nio.ByteBuffer;
import java.nio.charset.StandardCharsets;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;

/** Default implementation of {@link ContentMetadata}. Values are stored as byte arrays. */
@UnstableApi
public final class DefaultContentMetadata implements ContentMetadata {

  /** An empty DefaultContentMetadata. */
  public static final DefaultContentMetadata EMPTY =
      new DefaultContentMetadata(Collections.emptyMap());

  private int hashCode;

  private final Map<String, byte[]> metadata;

  public DefaultContentMetadata() {
    this(Collections.emptyMap());
  }

  /**
   * @param metadata The metadata entries in their raw byte array form.
   */
  public DefaultContentMetadata(Map<String, byte[]> metadata) {
    this.metadata = Collections.unmodifiableMap(metadata);
  }

  /**
   * Returns a copy {@link DefaultContentMetadata} with {@code mutations} applied. If {@code
   * mutations} don't change anything, returns this instance.
   */
  public DefaultContentMetadata copyWithMutationsApplied(ContentMetadataMutations mutations) {
    Map<String, byte[]> mutatedMetadata = applyMutations(metadata, mutations);
    if (isMetadataEqual(metadata, mutatedMetadata)) {
      return this;
    }
    return new DefaultContentMetadata(mutatedMetadata);
  }

  /** Returns the set of metadata entries in their raw byte array form. */
  public Set<Entry<String, byte[]>> entrySet() {
    return metadata.entrySet();
  }

  @Override
  @Nullable
  public final byte[] get(String key, @Nullable byte[] defaultValue) {
    @Nullable byte[] bytes = metadata.get(key);
    if (bytes != null) {
      return Arrays.copyOf(bytes, bytes.length);
    } else {
      return defaultValue;
    }
  }

  @Override
  @Nullable
  public final String get(String key, @Nullable String defaultValue) {
    @Nullable byte[] bytes = metadata.get(key);
    if (bytes != null) {
      return new String(bytes, StandardCharsets.UTF_8);
    } else {
      return defaultValue;
    }
  }

  @Override
  public final long get(String key, long defaultValue) {
    @Nullable byte[] bytes = metadata.get(key);
    if (bytes != null) {
      return ByteBuffer.wrap(bytes).getLong();
    } else {
      return defaultValue;
    }
  }

  @Override
  public final boolean contains(String key) {
    return metadata.containsKey(key);
  }

  @Override
  public boolean equals(@Nullable Object o) {
    if (this == o) {
      return true;
    }
    if (o == null || getClass() != o.getClass()) {
      return false;
    }
    return isMetadataEqual(metadata, ((DefaultContentMetadata) o).metadata);
  }

  @Override
  public int hashCode() {
    if (hashCode == 0) {
      int result = 0;
      for (Entry<String, byte[]> entry : metadata.entrySet()) {
        result += entry.getKey().hashCode() ^ Arrays.hashCode(entry.getValue());
      }
      hashCode = result;
    }
    return hashCode;
  }

  private static boolean isMetadataEqual(Map<String, byte[]> first, Map<String, byte[]> second) {
    if (first.size() != second.size()) {
      return false;
    }
    for (Entry<String, byte[]> entry : first.entrySet()) {
      byte[] value = entry.getValue();
      @Nullable byte[] otherValue = second.get(entry.getKey());
      if (!Arrays.equals(value, otherValue)) {
        return false;
      }
    }
    return true;
  }

  private static Map<String, byte[]> applyMutations(
      Map<String, byte[]> otherMetadata, ContentMetadataMutations mutations) {
    HashMap<String, byte[]> metadata = new HashMap<>(otherMetadata);
    removeValues(metadata, mutations.getRemovedValues());
    addValues(metadata, mutations.getEditedValues());
    return metadata;
  }

  private static void removeValues(HashMap<String, byte[]> metadata, List<String> names) {
    for (int i = 0; i < names.size(); i++) {
      metadata.remove(names.get(i));
    }
  }

  private static void addValues(HashMap<String, byte[]> metadata, Map<String, Object> values) {
    for (Entry<String, Object> entry : values.entrySet()) {
      metadata.put(entry.getKey(), getBytes(entry.getValue()));
    }
  }

  private static byte[] getBytes(Object value) {
    if (value instanceof Long) {
      return ByteBuffer.allocate(8).putLong((Long) value).array();
    } else if (value instanceof String) {
      return ((String) value).getBytes(StandardCharsets.UTF_8);
    } else if (value instanceof byte[]) {
      return (byte[]) value;
    } else {
      throw new IllegalArgumentException();
    }
  }
}