Merge "Extend MediaCodec.CryptoInfo to support Sample AES"
diff --git a/api/current.txt b/api/current.txt
index 84e9079..c161242 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -15511,6 +15511,7 @@
     field public static final int BUFFER_FLAG_KEY_FRAME = 1; // 0x1
     field public static final deprecated int BUFFER_FLAG_SYNC_FRAME = 1; // 0x1
     field public static final int CONFIGURE_FLAG_ENCODE = 1; // 0x1
+    field public static final int CRYPTO_MODE_AES_CBC = 2; // 0x2
     field public static final int CRYPTO_MODE_AES_CTR = 1; // 0x1
     field public static final int CRYPTO_MODE_UNENCRYPTED = 0; // 0x0
     field public static final deprecated int INFO_OUTPUT_BUFFERS_CHANGED = -3; // 0xfffffffd
@@ -15562,6 +15563,7 @@
   public static final class MediaCodec.CryptoInfo {
     ctor public MediaCodec.CryptoInfo();
     method public void set(int, int[], int[], byte[], byte[], int);
+    method public void setPattern(android.media.MediaCodec.CryptoInfo.Pattern);
     field public byte[] iv;
     field public byte[] key;
     field public int mode;
@@ -15570,6 +15572,13 @@
     field public int numSubSamples;
   }
 
+  public static final class MediaCodec.CryptoInfo.Pattern {
+    ctor public MediaCodec.CryptoInfo.Pattern(int, int);
+    method public int getEncryptBlocks();
+    method public int getSkipBlocks();
+    method public void set(int, int);
+  }
+
   public static abstract interface MediaCodec.OnFrameRenderedListener {
     method public abstract void onFrameRendered(android.media.MediaCodec, long, long);
   }
diff --git a/api/system-current.txt b/api/system-current.txt
index 31634bf..dd6a2839 100644
--- a/api/system-current.txt
+++ b/api/system-current.txt
@@ -16796,6 +16796,7 @@
     field public static final int BUFFER_FLAG_KEY_FRAME = 1; // 0x1
     field public static final deprecated int BUFFER_FLAG_SYNC_FRAME = 1; // 0x1
     field public static final int CONFIGURE_FLAG_ENCODE = 1; // 0x1
+    field public static final int CRYPTO_MODE_AES_CBC = 2; // 0x2
     field public static final int CRYPTO_MODE_AES_CTR = 1; // 0x1
     field public static final int CRYPTO_MODE_UNENCRYPTED = 0; // 0x0
     field public static final deprecated int INFO_OUTPUT_BUFFERS_CHANGED = -3; // 0xfffffffd
@@ -16847,6 +16848,7 @@
   public static final class MediaCodec.CryptoInfo {
     ctor public MediaCodec.CryptoInfo();
     method public void set(int, int[], int[], byte[], byte[], int);
+    method public void setPattern(android.media.MediaCodec.CryptoInfo.Pattern);
     field public byte[] iv;
     field public byte[] key;
     field public int mode;
@@ -16855,6 +16857,13 @@
     field public int numSubSamples;
   }
 
+  public static final class MediaCodec.CryptoInfo.Pattern {
+    ctor public MediaCodec.CryptoInfo.Pattern(int, int);
+    method public int getEncryptBlocks();
+    method public int getSkipBlocks();
+    method public void set(int, int);
+  }
+
   public static abstract interface MediaCodec.OnFrameRenderedListener {
     method public abstract void onFrameRendered(android.media.MediaCodec, long, long);
   }
diff --git a/media/java/android/media/MediaCodec.java b/media/java/android/media/MediaCodec.java
index 6c224e5..478fd99 100644
--- a/media/java/android/media/MediaCodec.java
+++ b/media/java/android/media/MediaCodec.java
@@ -2179,6 +2179,7 @@
     // in media/hardware/CryptoAPI.h !
     public static final int CRYPTO_MODE_UNENCRYPTED = 0;
     public static final int CRYPTO_MODE_AES_CTR     = 1;
+    public static final int CRYPTO_MODE_AES_CBC     = 2;
 
     /**
      * Metadata describing the structure of a (at least partially) encrypted
@@ -2186,27 +2187,14 @@
      * A buffer's data is considered to be partitioned into "subSamples",
      * each subSample starts with a (potentially empty) run of plain,
      * unencrypted bytes followed by a (also potentially empty) run of
-     * encrypted bytes.
-     * numBytesOfClearData can be null to indicate that all data is encrypted.
-     * This information encapsulates per-sample metadata as outlined in
-     * ISO/IEC FDIS 23001-7:2011 "Common encryption in ISO base media file format files".
+     * encrypted bytes. If pattern encryption applies, each of the latter runs
+     * is encrypted only partly, according to a repeating pattern of "encrypt"
+     * and "skip" blocks. numBytesOfClearData can be null to indicate that all
+     * data is encrypted. This information encapsulates per-sample metadata as
+     * outlined in ISO/IEC FDIS 23001-7:2011 "Common encryption in ISO base
+     * media file format files".
      */
     public final static class CryptoInfo {
-        public void set(
-                int newNumSubSamples,
-                @NonNull int[] newNumBytesOfClearData,
-                @NonNull int[] newNumBytesOfEncryptedData,
-                @NonNull byte[] newKey,
-                @NonNull byte[] newIV,
-                int newMode) {
-            numSubSamples = newNumSubSamples;
-            numBytesOfClearData = newNumBytesOfClearData;
-            numBytesOfEncryptedData = newNumBytesOfEncryptedData;
-            key = newKey;
-            iv = newIV;
-            mode = newMode;
-        }
-
         /**
          * The number of subSamples that make up the buffer's contents.
          */
@@ -2220,7 +2208,7 @@
          */
         public int[] numBytesOfEncryptedData;
         /**
-         * A 16-byte opaque key
+         * A 16-byte key id
          */
         public byte[] key;
         /**
@@ -2229,10 +2217,84 @@
         public byte[] iv;
         /**
          * The type of encryption that has been applied,
-         * see {@link #CRYPTO_MODE_UNENCRYPTED} and {@link #CRYPTO_MODE_AES_CTR}.
+         * see {@link #CRYPTO_MODE_UNENCRYPTED}, {@link #CRYPTO_MODE_AES_CTR}
+         * and {@link #CRYPTO_MODE_AES_CBC}
          */
         public int mode;
 
+        /**
+         * Metadata describing encryption pattern for the protected bytes in a subsample.
+         */
+        public final static class Pattern {
+            /**
+             * Number of blocks to be encrypted in the pattern. If zero, pattern
+             * encryption is inoperative.
+             */
+            private int mEncryptBlocks;
+
+            /**
+             * Number of blocks to be skipped (left clear) in the pattern. If zero,
+             * pattern encryption is inoperative.
+             */
+            private int mSkipBlocks;
+
+            /**
+             * Construct a sample encryption pattern given the number of blocks to
+             * encrypt and skip in the pattern.
+             */
+            public Pattern(int blocksToEncrypt, int blocksToSkip) {
+                set(blocksToEncrypt, blocksToSkip);
+            }
+
+            /**
+             * Set the number of blocks to encrypt and skip in a sample encryption
+             * pattern.
+             */
+            public void set(int blocksToEncrypt, int blocksToSkip) {
+                mEncryptBlocks = blocksToEncrypt;
+                mSkipBlocks = blocksToSkip;
+            }
+
+            /**
+             * Return the number of blocks to skip in a sample encryption pattern.
+             */
+            public int getSkipBlocks() {
+                return mSkipBlocks;
+            }
+
+            /**
+             * Return the number of blocks to encrypt in a sample encryption pattern.
+             */
+            public int getEncryptBlocks() {
+                return mEncryptBlocks;
+            }
+        };
+
+        /**
+         * The pattern applicable to the protected data in each subsample.
+         */
+        private Pattern pattern;
+
+        public void set(
+                int newNumSubSamples,
+                @NonNull int[] newNumBytesOfClearData,
+                @NonNull int[] newNumBytesOfEncryptedData,
+                @NonNull byte[] newKey,
+                @NonNull byte[] newIV,
+                int newMode) {
+            numSubSamples = newNumSubSamples;
+            numBytesOfClearData = newNumBytesOfClearData;
+            numBytesOfEncryptedData = newNumBytesOfEncryptedData;
+            key = newKey;
+            iv = newIV;
+            mode = newMode;
+            pattern = new Pattern(0, 0);
+        }
+
+        public void setPattern(Pattern newPattern) {
+            pattern = newPattern;
+        }
+
         @Override
         public String toString() {
             StringBuilder builder = new StringBuilder();