Commit f3a52aea authored by az's avatar az
Browse files

Bug 1724027 - Forward CBCS crypto pattern to remote decoding process on...

Bug 1724027 - Forward CBCS crypto pattern to remote decoding process on Android r=jolin,geckoview-reviewers,m_kato

Differential Revision: https://phabricator.services.mozilla.com/D178572
parent 7f6a8f46
Loading
Loading
Loading
Loading
+59 −0
Original line number Diff line number Diff line
@@ -4,11 +4,15 @@

package org.mozilla.gecko.media;

import android.annotation.SuppressLint;
import android.media.MediaCodec;
import android.media.MediaCodec.BufferInfo;
import android.media.MediaCodec.CryptoInfo;
import android.os.Build;
import android.os.Parcel;
import android.os.Parcelable;
import androidx.annotation.ChecksSdkIntAtLeast;
import java.lang.reflect.Field;
import java.nio.ByteBuffer;
import org.mozilla.gecko.annotation.WrapForJNI;

@@ -65,6 +69,11 @@ public final class Sample implements Parcelable {
      cryptoInfo = new CryptoInfo();
    }
    cryptoInfo.set(numSubSamples, numBytesOfClearData, numBytesOfEncryptedData, key, iv, mode);
    if (supportsCryptoPattern()) {
      final int numEncryptBlocks = in.readInt();
      final int numSkipBlocks = in.readInt();
      cryptoInfo.setPattern(new CryptoInfo.Pattern(numEncryptBlocks, numSkipBlocks));
    }
  }

  public Sample set(final BufferInfo info, final CryptoInfo cryptoInfo) {
@@ -93,6 +102,13 @@ public final class Sample implements Parcelable {
        crypto.key,
        crypto.iv,
        crypto.mode);
    if (supportsCryptoPattern()) {
      final CryptoInfo.Pattern pattern = getCryptoPatternCompat(crypto);
      if (pattern == null) {
        return;
      }
      cryptoInfo.setPattern(pattern);
    }
  }

  @WrapForJNI
@@ -185,6 +201,17 @@ public final class Sample implements Parcelable {
      dest.writeIntArray(cryptoInfo.numBytesOfClearData);
      dest.writeIntArray(cryptoInfo.numBytesOfEncryptedData);
      dest.writeInt(cryptoInfo.numSubSamples);
      if (supportsCryptoPattern()) {
        final CryptoInfo.Pattern pattern = getCryptoPatternCompat(cryptoInfo);
        if (pattern != null) {
          dest.writeInt(pattern.getEncryptBlocks());
          dest.writeInt(pattern.getSkipBlocks());
        } else {
          // Couldn't get pattern - write default values
          dest.writeInt(0);
          dest.writeInt(0);
        }
      }
    } else {
      dest.writeInt(0);
    }
@@ -229,4 +256,36 @@ public final class Sample implements Parcelable {
        .append(" }");
    return str.toString();
  }

  @ChecksSdkIntAtLeast(api = android.os.Build.VERSION_CODES.N)
  public static boolean supportsCryptoPattern() {
    return Build.VERSION.SDK_INT >= 24;
  }

  @SuppressLint("DiscouragedPrivateApi")
  public static CryptoInfo.Pattern getCryptoPatternCompat(final CryptoInfo cryptoInfo) {
    if (!supportsCryptoPattern()) {
      return null;
    }
    // getPattern() added in API 31:
    // https://developer.android.com/reference/android/media/MediaCodec.CryptoInfo#getPattern()
    if (Build.VERSION.SDK_INT >= 31) {
      return cryptoInfo.getPattern();
    }

    // CryptoInfo.Pattern added in API 24:
    // https://developer.android.com/reference/android/media/MediaCodec.CryptoInfo.Pattern
    if (Build.VERSION.SDK_INT >= 24) {
      try {
        // Without getPattern(), no way to access the pattern without reflection.
        // https://cs.android.com/android/platform/superproject/+/android-11.0.0_r1:frameworks/base/media/java/android/media/MediaCodec.java;l=2718;drc=3c715d5778e15dc84082e63dc65b382d31fe8e45
        final Field patternField = CryptoInfo.class.getDeclaredField("pattern");
        patternField.setAccessible(true);
        return (CryptoInfo.Pattern) patternField.get(cryptoInfo);
      } catch (final NoSuchFieldException | IllegalAccessException e) {
        return null;
      }
    }
    return null;
  }
}