Bug 1344347 - Move Android out-of-process decoder service into GeckoView r=jolin draft
authorJames Willcox <snorp@snorp.net>
Wed, 01 Mar 2017 10:17:09 -0600
changeset 552479 e3860a4ae165205cd6f02c7755f6bc31c424180d
parent 552478 d59f2627562afb95f2a50815c68343600b4f9bea
child 552480 3ac73f1b5924ba189afb9bef94de773c2bdfda6e
push id51353
push userbmo:snorp@snorp.net
push dateTue, 28 Mar 2017 13:31:07 +0000
reviewersjolin
bugs1344347
milestone55.0a1
Bug 1344347 - Move Android out-of-process decoder service into GeckoView r=jolin
mobile/android/base/Makefile.in
mobile/android/base/aidl/org/mozilla/gecko/media/FormatParam.aidl
mobile/android/base/aidl/org/mozilla/gecko/media/ICodec.aidl
mobile/android/base/aidl/org/mozilla/gecko/media/ICodecCallbacks.aidl
mobile/android/base/aidl/org/mozilla/gecko/media/IMediaDrmBridge.aidl
mobile/android/base/aidl/org/mozilla/gecko/media/IMediaDrmBridgeCallbacks.aidl
mobile/android/base/aidl/org/mozilla/gecko/media/IMediaManager.aidl
mobile/android/base/aidl/org/mozilla/gecko/media/Sample.aidl
mobile/android/base/aidl/org/mozilla/gecko/media/SessionKeyInfo.aidl
mobile/android/base/java/org/mozilla/gecko/GeckoApplication.java
mobile/android/base/java/org/mozilla/gecko/media/AsyncCodec.java
mobile/android/base/java/org/mozilla/gecko/media/AsyncCodecFactory.java
mobile/android/base/java/org/mozilla/gecko/media/Codec.java
mobile/android/base/java/org/mozilla/gecko/media/CodecProxy.java
mobile/android/base/java/org/mozilla/gecko/media/FormatParam.java
mobile/android/base/java/org/mozilla/gecko/media/GeckoMediaDrm.java
mobile/android/base/java/org/mozilla/gecko/media/GeckoMediaDrmBridgeV21.java
mobile/android/base/java/org/mozilla/gecko/media/GeckoMediaDrmBridgeV23.java
mobile/android/base/java/org/mozilla/gecko/media/JellyBeanAsyncCodec.java
mobile/android/base/java/org/mozilla/gecko/media/MediaDrmProxy.java
mobile/android/base/java/org/mozilla/gecko/media/MediaManager.java
mobile/android/base/java/org/mozilla/gecko/media/RemoteManager.java
mobile/android/base/java/org/mozilla/gecko/media/RemoteMediaDrmBridge.java
mobile/android/base/java/org/mozilla/gecko/media/RemoteMediaDrmBridgeStub.java
mobile/android/base/java/org/mozilla/gecko/media/Sample.java
mobile/android/base/java/org/mozilla/gecko/media/SamplePool.java
mobile/android/base/java/org/mozilla/gecko/media/SessionKeyInfo.java
mobile/android/base/java/org/mozilla/gecko/mozglue/SharedMemBuffer.java
mobile/android/base/java/org/mozilla/gecko/mozglue/SharedMemory.java
mobile/android/base/moz.build
mobile/android/geckoview/src/main/aidl/org/mozilla/gecko/media/FormatParam.aidl
mobile/android/geckoview/src/main/aidl/org/mozilla/gecko/media/ICodec.aidl
mobile/android/geckoview/src/main/aidl/org/mozilla/gecko/media/ICodecCallbacks.aidl
mobile/android/geckoview/src/main/aidl/org/mozilla/gecko/media/IMediaDrmBridge.aidl
mobile/android/geckoview/src/main/aidl/org/mozilla/gecko/media/IMediaDrmBridgeCallbacks.aidl
mobile/android/geckoview/src/main/aidl/org/mozilla/gecko/media/IMediaManager.aidl
mobile/android/geckoview/src/main/aidl/org/mozilla/gecko/media/Sample.aidl
mobile/android/geckoview/src/main/aidl/org/mozilla/gecko/media/SessionKeyInfo.aidl
mobile/android/geckoview/src/main/java/org/mozilla/gecko/media/AsyncCodec.java
mobile/android/geckoview/src/main/java/org/mozilla/gecko/media/AsyncCodecFactory.java
mobile/android/geckoview/src/main/java/org/mozilla/gecko/media/Codec.java
mobile/android/geckoview/src/main/java/org/mozilla/gecko/media/CodecProxy.java
mobile/android/geckoview/src/main/java/org/mozilla/gecko/media/FormatParam.java
mobile/android/geckoview/src/main/java/org/mozilla/gecko/media/GeckoMediaDrm.java
mobile/android/geckoview/src/main/java/org/mozilla/gecko/media/GeckoMediaDrmBridgeV21.java
mobile/android/geckoview/src/main/java/org/mozilla/gecko/media/GeckoMediaDrmBridgeV23.java
mobile/android/geckoview/src/main/java/org/mozilla/gecko/media/JellyBeanAsyncCodec.java
mobile/android/geckoview/src/main/java/org/mozilla/gecko/media/MediaDrmProxy.java
mobile/android/geckoview/src/main/java/org/mozilla/gecko/media/MediaManager.java
mobile/android/geckoview/src/main/java/org/mozilla/gecko/media/RemoteManager.java
mobile/android/geckoview/src/main/java/org/mozilla/gecko/media/RemoteMediaDrmBridge.java
mobile/android/geckoview/src/main/java/org/mozilla/gecko/media/RemoteMediaDrmBridgeStub.java
mobile/android/geckoview/src/main/java/org/mozilla/gecko/media/Sample.java
mobile/android/geckoview/src/main/java/org/mozilla/gecko/media/SamplePool.java
mobile/android/geckoview/src/main/java/org/mozilla/gecko/media/SessionKeyInfo.java
mobile/android/geckoview/src/main/java/org/mozilla/gecko/media/SharedMemBuffer.java
mobile/android/geckoview/src/main/java/org/mozilla/gecko/mozglue/SharedMemory.java
mozglue/android/SharedMemNatives.cpp
widget/android/fennec/FennecJNINatives.h
widget/android/fennec/FennecJNIWrappers.cpp
widget/android/fennec/FennecJNIWrappers.h
--- a/mobile/android/base/Makefile.in
+++ b/mobile/android/base/Makefile.in
@@ -566,23 +566,28 @@ endif
 libs:: classes.dex
 	$(INSTALL) classes.dex $(FINAL_TARGET)
 
 # Generate Java binder interfaces from AIDL files.
 aidl_src_path := $(srcdir)/aidl
 aidl_target_path := generated
 media_pkg := org/mozilla/gecko/media
 
-$(aidl_target_path)/$(media_pkg)/%.java:$(aidl_src_path)/$(media_pkg)/%.aidl
+$(aidl_target_path)/$(media_pkg)/%.java:$(aidl_geckoview_src_path)/$(media_pkg)/%.aidl
 	@echo "Processing AIDL: $< => $@"
-	$(AIDL) -p$(ANDROID_SDK)/framework.aidl -I$(aidl_src_path) -o$(aidl_target_path) $<
+	$(AIDL) -p$(ANDROID_SDK)/framework.aidl -I$(aidl_geckoview_src_path) -o$(aidl_target_path) $<
 
 GECKOVIEW_AIDLS = \
   org/mozilla/gecko/IGeckoEditableChild.aidl \
   org/mozilla/gecko/IGeckoEditableParent.aidl \
+  org/mozilla/gecko/media/ICodec.java \
+  org/mozilla/gecko/media/ICodecCallbacks.java \
+  org/mozilla/gecko/media/IMediaDrmBridge.java \
+  org/mozilla/gecko/media/IMediaDrmBridgeCallbacks.java \
+  org/mozilla/gecko/media/IMediaManager.java \
   org/mozilla/gecko/process/IChildProcess.aidl \
   org/mozilla/gecko/process/IProcessManager.aidl \
   $(NULL)
 
 geckoview_aidl_src_path := $(topsrcdir)/mobile/android/geckoview/src/main/aidl
 geckoview_aidl_target_path := generated
 geckoview_aidl_targets := $(addprefix $(geckoview_aidl_target_path)/,$(GECKOVIEW_AIDLS:.aidl=.java))
 
--- a/mobile/android/base/java/org/mozilla/gecko/GeckoApplication.java
+++ b/mobile/android/base/java/org/mozilla/gecko/GeckoApplication.java
@@ -19,32 +19,34 @@ import org.mozilla.gecko.db.BrowserContr
 import org.mozilla.gecko.db.BrowserDB;
 import org.mozilla.gecko.db.LocalBrowserDB;
 import org.mozilla.gecko.distribution.Distribution;
 import org.mozilla.gecko.dlc.DownloadContentService;
 import org.mozilla.gecko.home.HomePanelsManager;
 import org.mozilla.gecko.lwt.LightweightTheme;
 import org.mozilla.gecko.mdns.MulticastDNSManager;
 import org.mozilla.gecko.media.AudioFocusAgent;
+import org.mozilla.gecko.media.RemoteManager;
 import org.mozilla.gecko.notifications.NotificationClient;
 import org.mozilla.gecko.notifications.NotificationHelper;
 import org.mozilla.gecko.preferences.DistroSharedPrefsImport;
 import org.mozilla.gecko.util.BundleEventListener;
 import org.mozilla.gecko.util.Clipboard;
 import org.mozilla.gecko.util.EventCallback;
 import org.mozilla.gecko.util.GeckoBundle;
 import org.mozilla.gecko.util.HardwareUtils;
 import org.mozilla.gecko.util.ThreadUtils;
 
 import java.io.File;
 import java.lang.reflect.Method;
 
 public class GeckoApplication extends Application
     implements ContextGetter {
     private static final String LOG_TAG = "GeckoApplication";
+    private static final String MEDIA_DECODING_PROCESS_CRASH = "MEDIA_DECODING_PROCESS_CRASH";
 
     private boolean mInBackground;
     private boolean mPausedGecko;
     private boolean mIsInitialResume;
 
     private LightweightTheme mLightweightTheme;
 
     private RefWatcher mRefWatcher;
@@ -194,16 +196,22 @@ public class GeckoApplication extends Ap
                     }
                 }
             });
         }
 
         GeckoAccessibility.setAccessibilityManagerListeners(this);
 
         AudioFocusAgent.getInstance().attachToContext(this);
+
+        RemoteManager.setCrashReporter(new RemoteManager.ICrashReporter() {
+            public void reportDecodingProcessCrash() {
+                Telemetry.addToHistogram(MEDIA_DECODING_PROCESS_CRASH, 1);
+            }
+        });
     }
 
     private class EventListener implements BundleEventListener
     {
         private void onProfileCreate(final String name, final String path) {
             // Add everything when we're done loading the distribution.
             final Context context = GeckoApplication.this;
             final GeckoProfile profile = GeckoProfile.get(context, name);
deleted file mode 100644
--- a/mobile/android/base/java/org/mozilla/gecko/media/RemoteManager.java
+++ /dev/null
@@ -1,212 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-package org.mozilla.gecko.media;
-
-import org.mozilla.gecko.GeckoAppShell;
-import org.mozilla.gecko.Telemetry;
-
-import android.content.ComponentName;
-import android.content.Context;
-import android.content.Intent;
-import android.content.ServiceConnection;
-import android.media.MediaFormat;
-import android.os.DeadObjectException;
-import android.os.IBinder;
-import android.os.RemoteException;
-import android.view.Surface;
-import android.util.Log;
-
-import java.util.LinkedList;
-import java.util.List;
-
-public final class RemoteManager implements IBinder.DeathRecipient {
-    private static final String LOGTAG = "GeckoRemoteManager";
-    private static final boolean DEBUG = false;
-    private static RemoteManager sRemoteManager = null;
-
-    public synchronized static RemoteManager getInstance() {
-        if (sRemoteManager == null) {
-            sRemoteManager = new RemoteManager();
-        }
-
-        sRemoteManager.init();
-        return sRemoteManager;
-    }
-
-    private List<CodecProxy> mProxies = new LinkedList<CodecProxy>();
-    private volatile IMediaManager mRemote;
-
-    private final class RemoteConnection implements ServiceConnection {
-        @Override
-        public void onServiceConnected(ComponentName name, IBinder service) {
-            if (DEBUG) Log.d(LOGTAG, "service connected");
-            try {
-                service.linkToDeath(RemoteManager.this, 0);
-            } catch (RemoteException e) {
-                e.printStackTrace();
-            }
-            synchronized (this) {
-                mRemote = IMediaManager.Stub.asInterface(service);
-                notify();
-            }
-        }
-
-        @Override
-        public void onServiceDisconnected(ComponentName name) {
-            if (DEBUG) Log.d(LOGTAG, "service disconnected");
-            mRemote.asBinder().unlinkToDeath(RemoteManager.this, 0);
-            synchronized (this) {
-                mRemote = null;
-                notify();
-            }
-        }
-
-        private boolean connect() {
-            Context appCtxt = GeckoAppShell.getApplicationContext();
-            appCtxt.bindService(new Intent(appCtxt, MediaManager.class),
-                    mConnection, Context.BIND_AUTO_CREATE);
-            waitConnect();
-            return mRemote != null;
-        }
-
-        // Wait up to 5s.
-        private synchronized void waitConnect() {
-            int waitCount = 0;
-            while (mRemote == null && waitCount < 5) {
-                try {
-                    wait(1000);
-                    waitCount++;
-                } catch (InterruptedException e) {
-                    if (DEBUG) { e.printStackTrace(); }
-                }
-            }
-            if (DEBUG) {
-                Log.d(LOGTAG, "wait ~" + waitCount + "s for connection: " + (mRemote == null ? "fail" : "ok"));
-            }
-        }
-
-        private synchronized void waitDisconnect() {
-            while (mRemote != null) {
-                try {
-                    wait(1000);
-                } catch (InterruptedException e) {
-                    if (DEBUG) { e.printStackTrace(); }
-                }
-            }
-        }
-    };
-
-    RemoteConnection mConnection = new RemoteConnection();
-
-    private synchronized boolean init() {
-        if (mRemote != null) {
-            return true;
-        }
-
-        if (DEBUG) Log.d(LOGTAG, "init remote manager " + this);
-        return mConnection.connect();
-    }
-
-    public synchronized CodecProxy createCodec(MediaFormat format,
-                                               Surface surface,
-                                               CodecProxy.Callbacks callbacks,
-                                               String drmStubId) {
-        if (mRemote == null) {
-            if (DEBUG) Log.d(LOGTAG, "createCodec failed due to not initialize");
-            return null;
-        }
-        try {
-            ICodec remote = mRemote.createCodec();
-            CodecProxy proxy = CodecProxy.createCodecProxy(format, surface, callbacks, drmStubId);
-            if (proxy.init(remote)) {
-                mProxies.add(proxy);
-                return proxy;
-            } else {
-                return null;
-            }
-        } catch (RemoteException e) {
-            e.printStackTrace();
-            return null;
-        }
-    }
-
-    private static final String MEDIA_DECODING_PROCESS_CRASH = "MEDIA_DECODING_PROCESS_CRASH";
-    private void reportDecodingProcessCrash() {
-        Telemetry.addToHistogram(MEDIA_DECODING_PROCESS_CRASH, 1);
-    }
-
-    public synchronized IMediaDrmBridge createRemoteMediaDrmBridge(String keySystem,
-                                                                   String stubId) {
-        if (mRemote == null) {
-            if (DEBUG) Log.d(LOGTAG, "createRemoteMediaDrmBridge failed due to not initialize");
-            return null;
-        }
-        try {
-            IMediaDrmBridge remoteBridge =
-                mRemote.createRemoteMediaDrmBridge(keySystem, stubId);
-            return remoteBridge;
-        } catch (RemoteException e) {
-            Log.e(LOGTAG, "Got exception during createRemoteMediaDrmBridge().", e);
-            return null;
-        }
-    }
-
-    @Override
-    public void binderDied() {
-        Log.e(LOGTAG, "remote codec is dead");
-        reportDecodingProcessCrash();
-        handleRemoteDeath();
-    }
-
-    private synchronized void handleRemoteDeath() {
-        mConnection.waitDisconnect();
-
-        if (init() && recoverRemoteCodec()) {
-            notifyError(false);
-        } else {
-            notifyError(true);
-        }
-    }
-
-    private synchronized void notifyError(boolean fatal) {
-        for (CodecProxy proxy : mProxies) {
-            proxy.reportError(fatal);
-        }
-    }
-
-    private synchronized boolean recoverRemoteCodec() {
-        if (DEBUG) Log.d(LOGTAG, "recover codec");
-        boolean ok = true;
-        try {
-            for (CodecProxy proxy : mProxies) {
-                ok &= proxy.init(mRemote.createCodec());
-            }
-            return ok;
-        } catch (RemoteException e) {
-            return false;
-        }
-    }
-
-    public void releaseCodec(CodecProxy proxy) throws DeadObjectException, RemoteException {
-        if (mRemote == null) {
-            if (DEBUG) Log.d(LOGTAG, "releaseCodec called but not initialized yet");
-            return;
-        }
-        proxy.deinit();
-        synchronized (this) {
-            if (mProxies.remove(proxy) && mProxies.isEmpty()) {
-                release();
-            }
-        }
-    }
-
-    private void release() {
-        if (DEBUG) Log.d(LOGTAG, "release remote manager " + this);
-        Context appCtxt = GeckoAppShell.getApplicationContext();
-        mRemote.asBinder().unlinkToDeath(this, 0);
-        mRemote = null;
-        appCtxt.unbindService(mConnection);
-    }
-} // RemoteManager
\ No newline at end of file
deleted file mode 100644
--- a/mobile/android/base/java/org/mozilla/gecko/media/Sample.java
+++ /dev/null
@@ -1,264 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-package org.mozilla.gecko.media;
-
-import android.media.MediaCodec;
-import android.media.MediaCodec.BufferInfo;
-import android.media.MediaCodec.CryptoInfo;
-import android.os.Parcel;
-import android.os.Parcelable;
-
-import org.mozilla.gecko.annotation.WrapForJNI;
-import org.mozilla.gecko.mozglue.SharedMemBuffer;
-import org.mozilla.gecko.mozglue.SharedMemory;
-
-import java.io.IOException;
-import java.nio.ByteBuffer;
-
-// Parcelable carrying input/output sample data and info cross process.
-public final class Sample implements Parcelable {
-    public static final Sample EOS;
-    static {
-        BufferInfo eosInfo = new BufferInfo();
-        eosInfo.set(0, 0, Long.MIN_VALUE, MediaCodec.BUFFER_FLAG_END_OF_STREAM);
-        EOS = new Sample(null, eosInfo, null);
-    }
-
-    public interface Buffer extends Parcelable {
-        int capacity();
-        void readFromByteBuffer(ByteBuffer src, int offset, int size) throws IOException;
-        void writeToByteBuffer(ByteBuffer dest, int offset, int size) throws IOException;
-        void dispose();
-    }
-
-    private static final class ArrayBuffer implements Buffer {
-        private byte[] mArray;
-
-        public static final Creator<ArrayBuffer> CREATOR = new Creator<ArrayBuffer>() {
-            @Override
-            public ArrayBuffer createFromParcel(Parcel in) {
-                return new ArrayBuffer(in);
-            }
-
-            @Override
-            public ArrayBuffer[] newArray(int size) {
-                return new ArrayBuffer[size];
-            }
-        };
-
-        private ArrayBuffer(Parcel in) {
-            mArray = in.createByteArray();
-        }
-
-        private ArrayBuffer(byte[] bytes) { mArray = bytes; }
-
-        @Override
-        public int describeContents() { return 0; }
-
-        @Override
-        public void writeToParcel(Parcel dest, int flags) {
-            dest.writeByteArray(mArray);
-        }
-
-        @Override
-        public int capacity() {
-            return mArray != null ? mArray.length : 0;
-        }
-
-        @Override
-        public void readFromByteBuffer(ByteBuffer src, int offset, int size) throws IOException {
-            src.position(offset);
-            if (mArray == null || mArray.length != size) {
-                mArray = new byte[size];
-            }
-            src.get(mArray, 0, size);
-        }
-
-        @Override
-        public void writeToByteBuffer(ByteBuffer dest, int offset, int size) throws IOException {
-            dest.put(mArray, offset, size);
-        }
-
-        @Override
-        public void dispose() {
-            mArray = null;
-        }
-    }
-
-    public Buffer buffer;
-    @WrapForJNI
-    public BufferInfo info;
-    public CryptoInfo cryptoInfo;
-
-    public static Sample create() { return create(null, new BufferInfo(), null); }
-
-    public static Sample create(ByteBuffer src, BufferInfo info, CryptoInfo cryptoInfo) {
-        ArrayBuffer buffer = new ArrayBuffer(byteArrayFromBuffer(src, info.offset, info.size));
-
-        BufferInfo bufferInfo = new BufferInfo();
-        bufferInfo.set(0, info.size, info.presentationTimeUs, info.flags);
-
-        return new Sample(buffer, bufferInfo, cryptoInfo);
-    }
-
-    public static Sample create(SharedMemory sharedMem) {
-        return new Sample(new SharedMemBuffer(sharedMem), new BufferInfo(), null);
-    }
-
-    private Sample(Buffer bytes, BufferInfo info, CryptoInfo cryptoInfo) {
-        buffer = bytes;
-        this.info = info;
-        this.cryptoInfo = cryptoInfo;
-    }
-
-    private Sample(Parcel in) {
-        readInfo(in);
-        readCrypto(in);
-        buffer = in.readParcelable(Sample.class.getClassLoader());
-    }
-
-    private void readInfo(Parcel in) {
-        int offset = in.readInt();
-        int size = in.readInt();
-        long pts = in.readLong();
-        int flags = in.readInt();
-
-        info = new BufferInfo();
-        info.set(offset, size, pts, flags);
-    }
-
-    private void readCrypto(Parcel in) {
-        int hasCryptoInfo = in.readInt();
-        if (hasCryptoInfo == 0) {
-            return;
-        }
-
-        byte[] iv = in.createByteArray();
-        byte[] key = in.createByteArray();
-        int mode = in.readInt();
-        int[] numBytesOfClearData = in.createIntArray();
-        int[] numBytesOfEncryptedData = in.createIntArray();
-        int numSubSamples = in.readInt();
-
-        cryptoInfo = new CryptoInfo();
-        cryptoInfo.set(numSubSamples,
-                      numBytesOfClearData,
-                      numBytesOfEncryptedData,
-                      key,
-                      iv,
-                      mode);
-    }
-
-    public Sample set(ByteBuffer bytes, BufferInfo info, CryptoInfo cryptoInfo) throws IOException {
-        if (bytes != null && info.size > 0) {
-            buffer.readFromByteBuffer(bytes, info.offset, info.size);
-        }
-        this.info.set(0, info.size, info.presentationTimeUs, info.flags);
-        this.cryptoInfo = cryptoInfo;
-
-        return this;
-    }
-
-    public void dispose() {
-        if (isEOS()) {
-            return;
-        }
-
-        if (buffer != null) {
-            buffer.dispose();
-            buffer = null;
-        }
-        info = null;
-        cryptoInfo = null;
-    }
-
-    public boolean isEOS() {
-        return (this == EOS) ||
-                ((info.flags & MediaCodec.BUFFER_FLAG_END_OF_STREAM) != 0);
-    }
-
-    public static final Creator<Sample> CREATOR = new Creator<Sample>() {
-        @Override
-        public Sample createFromParcel(Parcel in) {
-            return new Sample(in);
-        }
-
-        @Override
-        public Sample[] newArray(int size) {
-            return new Sample[size];
-        }
-    };
-
-    @Override
-    public int describeContents() {
-        return 0;
-    }
-
-    @Override
-    public void writeToParcel(Parcel dest, int parcelableFlags) {
-        writeInfo(dest);
-        writeCrypto(dest);
-        dest.writeParcelable(buffer, parcelableFlags);
-    }
-
-    private void writeInfo(Parcel dest) {
-        dest.writeInt(info.offset);
-        dest.writeInt(info.size);
-        dest.writeLong(info.presentationTimeUs);
-        dest.writeInt(info.flags);
-    }
-
-    private void writeCrypto(Parcel dest) {
-        if (cryptoInfo != null) {
-            dest.writeInt(1);
-            dest.writeByteArray(cryptoInfo.iv);
-            dest.writeByteArray(cryptoInfo.key);
-            dest.writeInt(cryptoInfo.mode);
-            dest.writeIntArray(cryptoInfo.numBytesOfClearData);
-            dest.writeIntArray(cryptoInfo.numBytesOfEncryptedData);
-            dest.writeInt(cryptoInfo.numSubSamples);
-        } else {
-            dest.writeInt(0);
-        }
-    }
-
-    public static byte[] byteArrayFromBuffer(ByteBuffer buffer, int offset, int size) {
-        if (buffer == null || buffer.capacity() == 0 || size == 0) {
-            return null;
-        }
-        if (buffer.hasArray() && offset == 0 && buffer.array().length == size) {
-            return buffer.array();
-        }
-        int length = Math.min(offset + size, buffer.capacity()) - offset;
-        byte[] bytes = new byte[length];
-        buffer.position(offset);
-        buffer.get(bytes);
-        return bytes;
-    }
-
-    @WrapForJNI
-    public void writeToByteBuffer(ByteBuffer dest) throws IOException {
-        if (buffer != null && dest != null && info.size > 0) {
-            buffer.writeToByteBuffer(dest, info.offset, info.size);
-        }
-    }
-
-    @Override
-    public String toString() {
-        if (isEOS()) {
-            return "EOS sample";
-        }
-
-        StringBuilder str = new StringBuilder();
-        str.append("{ buffer=").append(buffer).
-                append(", info=").
-                append("{ offset=").append(info.offset).
-                append(", size=").append(info.size).
-                append(", pts=").append(info.presentationTimeUs).
-                append(", flags=").append(Integer.toHexString(info.flags)).append(" }").
-                append(" }");
-            return str.toString();
-    }
-}
\ No newline at end of file
deleted file mode 100644
--- a/mobile/android/base/java/org/mozilla/gecko/mozglue/SharedMemBuffer.java
+++ /dev/null
@@ -1,89 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-package org.mozilla.gecko.mozglue;
-
-import android.os.Parcel;
-
-import org.mozilla.gecko.media.Sample;
-
-import java.io.IOException;
-import java.nio.ByteBuffer;
-
-public final class SharedMemBuffer implements Sample.Buffer {
-    private SharedMemory mSharedMem;
-
-    /* package */
-    public SharedMemBuffer(SharedMemory sharedMem) {
-        mSharedMem = sharedMem;
-    }
-
-    protected SharedMemBuffer(Parcel in) {
-        mSharedMem = in.readParcelable(Sample.class.getClassLoader());
-    }
-
-    @Override
-    public void writeToParcel(Parcel dest, int flags) {
-        dest.writeParcelable(mSharedMem, flags);
-    }
-
-    @Override
-    public int describeContents() {
-        return 0;
-    }
-
-    public static final Creator<SharedMemBuffer> CREATOR = new Creator<SharedMemBuffer>() {
-        @Override
-        public SharedMemBuffer createFromParcel(Parcel in) {
-            return new SharedMemBuffer(in);
-        }
-
-        @Override
-        public SharedMemBuffer[] newArray(int size) {
-            return new SharedMemBuffer[size];
-        }
-    };
-
-    @Override
-    public int capacity() {
-        return mSharedMem != null ? mSharedMem.getSize() : 0;
-    }
-
-    @Override
-    public void readFromByteBuffer(ByteBuffer src, int offset, int size) throws IOException {
-        if (!src.isDirect()) {
-            throw new IOException("SharedMemBuffer only support reading from direct byte buffer.");
-        }
-        try {
-            nativeReadFromDirectBuffer(src, mSharedMem.getPointer(), offset, size);
-        } catch (NullPointerException e) {
-            throw new IOException(e);
-        }
-    }
-
-    private native static void nativeReadFromDirectBuffer(ByteBuffer src, long dest, int offset, int size);
-
-    @Override
-    public void writeToByteBuffer(ByteBuffer dest, int offset, int size) throws IOException {
-        if (!dest.isDirect()) {
-            throw new IOException("SharedMemBuffer only support writing to direct byte buffer.");
-        }
-        try {
-            nativeWriteToDirectBuffer(mSharedMem.getPointer(), dest, offset, size);
-        } catch (NullPointerException e) {
-            throw new IOException(e);
-        }
-    }
-
-    private native static void nativeWriteToDirectBuffer(long src, ByteBuffer dest, int offset, int size);
-
-    @Override
-    public void dispose() {
-        if (mSharedMem != null) {
-            mSharedMem.dispose();
-            mSharedMem = null;
-        }
-    }
-
-    @Override public String toString() { return "Buffer: " + mSharedMem; }
-}
--- a/mobile/android/base/moz.build
+++ b/mobile/android/base/moz.build
@@ -116,16 +116,17 @@ mgjar = add_java_jar('gecko-mozglue')
 mgjar.sources += [geckoview_source_dir + 'java/org/mozilla/gecko/' + x for x in [
     'mozglue/ByteBufferInputStream.java',
     'mozglue/DirectBufferAllocator.java',
     'mozglue/GeckoLoader.java',
     'mozglue/JNIObject.java',
     'mozglue/NativeReference.java',
     'mozglue/NativeZip.java',
     'mozglue/SafeIntent.java',
+    'mozglue/SharedMemory.java',
 ]]
 mgjar.generated_sources = [] # Keep it this way.
 mgjar.extra_jars += [
     CONFIG['ANDROID_SUPPORT_ANNOTATIONS_JAR_LIB'],
     'constants.jar',
 ]
 mgjar.javac_flags += ['-Xlint:all']
 
@@ -282,16 +283,34 @@ gvjar.sources += [geckoview_source_dir +
     'gfx/RectUtils.java',
     'gfx/RenderTask.java',
     'gfx/StackScroller.java',
     'gfx/SurfaceTextureListener.java',
     'gfx/ViewTransform.java',
     'gfx/VsyncSource.java',
     'InputConnectionListener.java',
     'InputMethods.java',
+    'media/AsyncCodec.java',
+    'media/AsyncCodecFactory.java',
+    'media/Codec.java',
+    'media/CodecProxy.java',
+    'media/FormatParam.java',
+    'media/GeckoMediaDrm.java',
+    'media/GeckoMediaDrmBridgeV21.java',
+    'media/GeckoMediaDrmBridgeV23.java',
+    'media/JellyBeanAsyncCodec.java',
+    'media/MediaDrmProxy.java',
+    'media/MediaManager.java',
+    'media/RemoteManager.java',
+    'media/RemoteMediaDrmBridge.java',
+    'media/RemoteMediaDrmBridgeStub.java',
+    'media/Sample.java',
+    'media/SamplePool.java',
+    'media/SessionKeyInfo.java',
+    'media/SharedMemBuffer.java',
     'NativeQueue.java',
     'NotificationListener.java',
     'NSSBridge.java',
     'permissions/PermissionBlock.java',
     'permissions/Permissions.java',
     'permissions/PermissionsHelper.java',
     'PrefsHelper.java',
     'process/GeckoProcessManager.java',
@@ -588,50 +607,31 @@ gbjar.sources += ['java/org/mozilla/geck
     'icons/storage/MemoryStorage.java',
     'IntentHelper.java',
     'javaaddons/JavaAddonManager.java',
     'javaaddons/JavaAddonManagerV1.java',
     'LauncherActivity.java',
     'lwt/LightweightTheme.java',
     'lwt/LightweightThemeDrawable.java',
     'mdns/MulticastDNSManager.java',
-    'media/AsyncCodec.java',
-    'media/AsyncCodecFactory.java',
     'media/AudioFocusAgent.java',
-    'media/Codec.java',
-    'media/CodecProxy.java',
-    'media/FormatParam.java',
-    'media/GeckoMediaDrm.java',
-    'media/GeckoMediaDrmBridgeV21.java',
-    'media/GeckoMediaDrmBridgeV23.java',
-    'media/JellyBeanAsyncCodec.java',
     'media/MediaControlService.java',
-    'media/MediaDrmProxy.java',
-    'media/MediaManager.java',
-    'media/RemoteManager.java',
-    'media/RemoteMediaDrmBridge.java',
-    'media/RemoteMediaDrmBridgeStub.java',
-    'media/Sample.java',
-    'media/SamplePool.java',
-    'media/SessionKeyInfo.java',
     'media/VideoPlayer.java',
     'MediaCastingBar.java',
     'MemoryMonitor.java',
     'menu/GeckoMenu.java',
     'menu/GeckoMenuInflater.java',
     'menu/GeckoMenuItem.java',
     'menu/GeckoSubMenu.java',
     'menu/MenuItemActionBar.java',
     'menu/MenuItemDefault.java',
     'menu/MenuItemSwitcherLayout.java',
     'menu/MenuPanel.java',
     'menu/MenuPopup.java',
     'MotionEventInterceptor.java',
-    'mozglue/SharedMemBuffer.java',
-    'mozglue/SharedMemory.java',
     'notifications/NotificationClient.java',
     'notifications/NotificationHelper.java',
     'notifications/NotificationReceiver.java',
     'notifications/NotificationService.java',
     'notifications/WhatsNewReceiver.java',
     'overlays/OverlayConstants.java',
     'overlays/service/OverlayActionService.java',
     'overlays/service/ShareData.java',
@@ -1181,22 +1181,19 @@ FINAL_TARGET_PP_FILES += ['package-name.
 
 DEFINES['OBJDIR'] = OBJDIR
 DEFINES['TOPOBJDIR'] = TOPOBJDIR
 
 OBJDIR_PP_FILES.mobile.android.base += [
     'AndroidManifest.xml.in',
 ]
 
-gbjar.sources += ['generated/org/mozilla/gecko/' + x for x in [
+gvjar.sources += ['generated/org/mozilla/gecko/' + x for x in [
+    'IGeckoEditableChild.java',
+    'IGeckoEditableParent.java',
     'media/ICodec.java',
     'media/ICodecCallbacks.java',
     'media/IMediaDrmBridge.java',
     'media/IMediaDrmBridgeCallbacks.java',
     'media/IMediaManager.java',
-]]
-
-gvjar.sources += ['generated/org/mozilla/gecko/' + x for x in [
-    'IGeckoEditableChild.java',
-    'IGeckoEditableParent.java',
     'process/IChildProcess.java',
     'process/IProcessManager.java',
 ]]
rename from mobile/android/base/aidl/org/mozilla/gecko/media/FormatParam.aidl
rename to mobile/android/geckoview/src/main/aidl/org/mozilla/gecko/media/FormatParam.aidl
rename from mobile/android/base/aidl/org/mozilla/gecko/media/ICodec.aidl
rename to mobile/android/geckoview/src/main/aidl/org/mozilla/gecko/media/ICodec.aidl
rename from mobile/android/base/aidl/org/mozilla/gecko/media/ICodecCallbacks.aidl
rename to mobile/android/geckoview/src/main/aidl/org/mozilla/gecko/media/ICodecCallbacks.aidl
rename from mobile/android/base/aidl/org/mozilla/gecko/media/IMediaDrmBridge.aidl
rename to mobile/android/geckoview/src/main/aidl/org/mozilla/gecko/media/IMediaDrmBridge.aidl
rename from mobile/android/base/aidl/org/mozilla/gecko/media/IMediaDrmBridgeCallbacks.aidl
rename to mobile/android/geckoview/src/main/aidl/org/mozilla/gecko/media/IMediaDrmBridgeCallbacks.aidl
rename from mobile/android/base/aidl/org/mozilla/gecko/media/IMediaManager.aidl
rename to mobile/android/geckoview/src/main/aidl/org/mozilla/gecko/media/IMediaManager.aidl
rename from mobile/android/base/aidl/org/mozilla/gecko/media/Sample.aidl
rename to mobile/android/geckoview/src/main/aidl/org/mozilla/gecko/media/Sample.aidl
rename from mobile/android/base/aidl/org/mozilla/gecko/media/SessionKeyInfo.aidl
rename to mobile/android/geckoview/src/main/aidl/org/mozilla/gecko/media/SessionKeyInfo.aidl
rename from mobile/android/base/java/org/mozilla/gecko/media/AsyncCodec.java
rename to mobile/android/geckoview/src/main/java/org/mozilla/gecko/media/AsyncCodec.java
rename from mobile/android/base/java/org/mozilla/gecko/media/AsyncCodecFactory.java
rename to mobile/android/geckoview/src/main/java/org/mozilla/gecko/media/AsyncCodecFactory.java
rename from mobile/android/base/java/org/mozilla/gecko/media/Codec.java
rename to mobile/android/geckoview/src/main/java/org/mozilla/gecko/media/Codec.java
rename from mobile/android/base/java/org/mozilla/gecko/media/CodecProxy.java
rename to mobile/android/geckoview/src/main/java/org/mozilla/gecko/media/CodecProxy.java
rename from mobile/android/base/java/org/mozilla/gecko/media/FormatParam.java
rename to mobile/android/geckoview/src/main/java/org/mozilla/gecko/media/FormatParam.java
rename from mobile/android/base/java/org/mozilla/gecko/media/GeckoMediaDrm.java
rename to mobile/android/geckoview/src/main/java/org/mozilla/gecko/media/GeckoMediaDrm.java
rename from mobile/android/base/java/org/mozilla/gecko/media/GeckoMediaDrmBridgeV21.java
rename to mobile/android/geckoview/src/main/java/org/mozilla/gecko/media/GeckoMediaDrmBridgeV21.java
rename from mobile/android/base/java/org/mozilla/gecko/media/GeckoMediaDrmBridgeV23.java
rename to mobile/android/geckoview/src/main/java/org/mozilla/gecko/media/GeckoMediaDrmBridgeV23.java
rename from mobile/android/base/java/org/mozilla/gecko/media/JellyBeanAsyncCodec.java
rename to mobile/android/geckoview/src/main/java/org/mozilla/gecko/media/JellyBeanAsyncCodec.java
rename from mobile/android/base/java/org/mozilla/gecko/media/MediaDrmProxy.java
rename to mobile/android/geckoview/src/main/java/org/mozilla/gecko/media/MediaDrmProxy.java
rename from mobile/android/base/java/org/mozilla/gecko/media/MediaManager.java
rename to mobile/android/geckoview/src/main/java/org/mozilla/gecko/media/MediaManager.java
new file mode 100644
--- /dev/null
+++ b/mobile/android/geckoview/src/main/java/org/mozilla/gecko/media/RemoteManager.java
@@ -0,0 +1,221 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+package org.mozilla.gecko.media;
+
+import org.mozilla.gecko.GeckoAppShell;
+
+import android.content.ComponentName;
+import android.content.Context;
+import android.content.Intent;
+import android.content.ServiceConnection;
+import android.media.MediaFormat;
+import android.os.DeadObjectException;
+import android.os.IBinder;
+import android.os.RemoteException;
+import android.view.Surface;
+import android.util.Log;
+
+import java.util.LinkedList;
+import java.util.List;
+
+public final class RemoteManager implements IBinder.DeathRecipient {
+    private static final String LOGTAG = "GeckoRemoteManager";
+    private static final boolean DEBUG = false;
+    private static RemoteManager sRemoteManager = null;
+    private static ICrashReporter setCrashReporter = null;
+
+    public synchronized static RemoteManager getInstance() {
+        if (sRemoteManager == null) {
+            sRemoteManager = new RemoteManager();
+        }
+
+        sRemoteManager.init();
+        return sRemoteManager;
+    }
+
+    private List<CodecProxy> mProxies = new LinkedList<CodecProxy>();
+    private volatile IMediaManager mRemote;
+
+    private final class RemoteConnection implements ServiceConnection {
+        @Override
+        public void onServiceConnected(ComponentName name, IBinder service) {
+            if (DEBUG) Log.d(LOGTAG, "service connected");
+            try {
+                service.linkToDeath(RemoteManager.this, 0);
+            } catch (RemoteException e) {
+                e.printStackTrace();
+            }
+            synchronized (this) {
+                mRemote = IMediaManager.Stub.asInterface(service);
+                notify();
+            }
+        }
+
+        @Override
+        public void onServiceDisconnected(ComponentName name) {
+            if (DEBUG) Log.d(LOGTAG, "service disconnected");
+            mRemote.asBinder().unlinkToDeath(RemoteManager.this, 0);
+            synchronized (this) {
+                mRemote = null;
+                notify();
+            }
+        }
+
+        private boolean connect() {
+            Context appCtxt = GeckoAppShell.getApplicationContext();
+            appCtxt.bindService(new Intent(appCtxt, MediaManager.class),
+                    mConnection, Context.BIND_AUTO_CREATE);
+            waitConnect();
+            return mRemote != null;
+        }
+
+        // Wait up to 5s.
+        private synchronized void waitConnect() {
+            int waitCount = 0;
+            while (mRemote == null && waitCount < 5) {
+                try {
+                    wait(1000);
+                    waitCount++;
+                } catch (InterruptedException e) {
+                    if (DEBUG) { e.printStackTrace(); }
+                }
+            }
+            if (DEBUG) {
+                Log.d(LOGTAG, "wait ~" + waitCount + "s for connection: " + (mRemote == null ? "fail" : "ok"));
+            }
+        }
+
+        private synchronized void waitDisconnect() {
+            while (mRemote != null) {
+                try {
+                    wait(1000);
+                } catch (InterruptedException e) {
+                    if (DEBUG) { e.printStackTrace(); }
+                }
+            }
+        }
+    };
+
+    RemoteConnection mConnection = new RemoteConnection();
+
+    private synchronized boolean init() {
+        if (mRemote != null) {
+            return true;
+        }
+
+        if (DEBUG) Log.d(LOGTAG, "init remote manager " + this);
+        return mConnection.connect();
+    }
+
+    public synchronized CodecProxy createCodec(MediaFormat format,
+                                               Surface surface,
+                                               CodecProxy.Callbacks callbacks,
+                                               String drmStubId) {
+        if (mRemote == null) {
+            if (DEBUG) Log.d(LOGTAG, "createCodec failed due to not initialize");
+            return null;
+        }
+        try {
+            ICodec remote = mRemote.createCodec();
+            CodecProxy proxy = CodecProxy.createCodecProxy(format, surface, callbacks, drmStubId);
+            if (proxy.init(remote)) {
+                mProxies.add(proxy);
+                return proxy;
+            } else {
+                return null;
+            }
+        } catch (RemoteException e) {
+            e.printStackTrace();
+            return null;
+        }
+    }
+
+    private void reportDecodingProcessCrash() {
+        if (setCrashReporter != null) {
+            setCrashReporter.reportDecodingProcessCrash();
+        }
+    }
+
+    public static void setCrashReporter(ICrashReporter reporter) {
+        setCrashReporter = reporter;
+    }
+
+    public interface ICrashReporter {
+        void reportDecodingProcessCrash();
+    }
+
+    public synchronized IMediaDrmBridge createRemoteMediaDrmBridge(String keySystem,
+                                                                   String stubId) {
+        if (mRemote == null) {
+            if (DEBUG) Log.d(LOGTAG, "createRemoteMediaDrmBridge failed due to not initialize");
+            return null;
+        }
+        try {
+            IMediaDrmBridge remoteBridge =
+                mRemote.createRemoteMediaDrmBridge(keySystem, stubId);
+            return remoteBridge;
+        } catch (RemoteException e) {
+            Log.e(LOGTAG, "Got exception during createRemoteMediaDrmBridge().", e);
+            return null;
+        }
+    }
+
+    @Override
+    public void binderDied() {
+        Log.e(LOGTAG, "remote codec is dead");
+        reportDecodingProcessCrash();
+        handleRemoteDeath();
+    }
+
+    private synchronized void handleRemoteDeath() {
+        mConnection.waitDisconnect();
+
+        if (init() && recoverRemoteCodec()) {
+            notifyError(false);
+        } else {
+            notifyError(true);
+        }
+    }
+
+    private synchronized void notifyError(boolean fatal) {
+        for (CodecProxy proxy : mProxies) {
+            proxy.reportError(fatal);
+        }
+    }
+
+    private synchronized boolean recoverRemoteCodec() {
+        if (DEBUG) Log.d(LOGTAG, "recover codec");
+        boolean ok = true;
+        try {
+            for (CodecProxy proxy : mProxies) {
+                ok &= proxy.init(mRemote.createCodec());
+            }
+            return ok;
+        } catch (RemoteException e) {
+            return false;
+        }
+    }
+
+    public void releaseCodec(CodecProxy proxy) throws DeadObjectException, RemoteException {
+        if (mRemote == null) {
+            if (DEBUG) Log.d(LOGTAG, "releaseCodec called but not initialized yet");
+            return;
+        }
+        proxy.deinit();
+        synchronized (this) {
+            if (mProxies.remove(proxy) && mProxies.isEmpty()) {
+                release();
+            }
+        }
+    }
+
+    private void release() {
+        if (DEBUG) Log.d(LOGTAG, "release remote manager " + this);
+        Context appCtxt = GeckoAppShell.getApplicationContext();
+        mRemote.asBinder().unlinkToDeath(this, 0);
+        mRemote = null;
+        appCtxt.unbindService(mConnection);
+    }
+} // RemoteManager
\ No newline at end of file
rename from mobile/android/base/java/org/mozilla/gecko/media/RemoteMediaDrmBridge.java
rename to mobile/android/geckoview/src/main/java/org/mozilla/gecko/media/RemoteMediaDrmBridge.java
rename from mobile/android/base/java/org/mozilla/gecko/media/RemoteMediaDrmBridgeStub.java
rename to mobile/android/geckoview/src/main/java/org/mozilla/gecko/media/RemoteMediaDrmBridgeStub.java
new file mode 100644
--- /dev/null
+++ b/mobile/android/geckoview/src/main/java/org/mozilla/gecko/media/Sample.java
@@ -0,0 +1,263 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+package org.mozilla.gecko.media;
+
+import android.media.MediaCodec;
+import android.media.MediaCodec.BufferInfo;
+import android.media.MediaCodec.CryptoInfo;
+import android.os.Parcel;
+import android.os.Parcelable;
+
+import org.mozilla.gecko.annotation.WrapForJNI;
+import org.mozilla.gecko.mozglue.SharedMemory;
+
+import java.io.IOException;
+import java.nio.ByteBuffer;
+
+// Parcelable carrying input/output sample data and info cross process.
+public final class Sample implements Parcelable {
+    public static final Sample EOS;
+    static {
+        BufferInfo eosInfo = new BufferInfo();
+        eosInfo.set(0, 0, Long.MIN_VALUE, MediaCodec.BUFFER_FLAG_END_OF_STREAM);
+        EOS = new Sample(null, eosInfo, null);
+    }
+
+    public interface Buffer extends Parcelable {
+        int capacity();
+        void readFromByteBuffer(ByteBuffer src, int offset, int size) throws IOException;
+        void writeToByteBuffer(ByteBuffer dest, int offset, int size) throws IOException;
+        void dispose();
+    }
+
+    private static final class ArrayBuffer implements Buffer {
+        private byte[] mArray;
+
+        public static final Creator<ArrayBuffer> CREATOR = new Creator<ArrayBuffer>() {
+            @Override
+            public ArrayBuffer createFromParcel(Parcel in) {
+                return new ArrayBuffer(in);
+            }
+
+            @Override
+            public ArrayBuffer[] newArray(int size) {
+                return new ArrayBuffer[size];
+            }
+        };
+
+        private ArrayBuffer(Parcel in) {
+            mArray = in.createByteArray();
+        }
+
+        private ArrayBuffer(byte[] bytes) { mArray = bytes; }
+
+        @Override
+        public int describeContents() { return 0; }
+
+        @Override
+        public void writeToParcel(Parcel dest, int flags) {
+            dest.writeByteArray(mArray);
+        }
+
+        @Override
+        public int capacity() {
+            return mArray != null ? mArray.length : 0;
+        }
+
+        @Override
+        public void readFromByteBuffer(ByteBuffer src, int offset, int size) throws IOException {
+            src.position(offset);
+            if (mArray == null || mArray.length != size) {
+                mArray = new byte[size];
+            }
+            src.get(mArray, 0, size);
+        }
+
+        @Override
+        public void writeToByteBuffer(ByteBuffer dest, int offset, int size) throws IOException {
+            dest.put(mArray, offset, size);
+        }
+
+        @Override
+        public void dispose() {
+            mArray = null;
+        }
+    }
+
+    public Buffer buffer;
+    @WrapForJNI
+    public BufferInfo info;
+    public CryptoInfo cryptoInfo;
+
+    public static Sample create() { return create(null, new BufferInfo(), null); }
+
+    public static Sample create(ByteBuffer src, BufferInfo info, CryptoInfo cryptoInfo) {
+        ArrayBuffer buffer = new ArrayBuffer(byteArrayFromBuffer(src, info.offset, info.size));
+
+        BufferInfo bufferInfo = new BufferInfo();
+        bufferInfo.set(0, info.size, info.presentationTimeUs, info.flags);
+
+        return new Sample(buffer, bufferInfo, cryptoInfo);
+    }
+
+    public static Sample create(SharedMemory sharedMem) {
+        return new Sample(new SharedMemBuffer(sharedMem), new BufferInfo(), null);
+    }
+
+    private Sample(Buffer bytes, BufferInfo info, CryptoInfo cryptoInfo) {
+        buffer = bytes;
+        this.info = info;
+        this.cryptoInfo = cryptoInfo;
+    }
+
+    private Sample(Parcel in) {
+        readInfo(in);
+        readCrypto(in);
+        buffer = in.readParcelable(Sample.class.getClassLoader());
+    }
+
+    private void readInfo(Parcel in) {
+        int offset = in.readInt();
+        int size = in.readInt();
+        long pts = in.readLong();
+        int flags = in.readInt();
+
+        info = new BufferInfo();
+        info.set(offset, size, pts, flags);
+    }
+
+    private void readCrypto(Parcel in) {
+        int hasCryptoInfo = in.readInt();
+        if (hasCryptoInfo == 0) {
+            return;
+        }
+
+        byte[] iv = in.createByteArray();
+        byte[] key = in.createByteArray();
+        int mode = in.readInt();
+        int[] numBytesOfClearData = in.createIntArray();
+        int[] numBytesOfEncryptedData = in.createIntArray();
+        int numSubSamples = in.readInt();
+
+        cryptoInfo = new CryptoInfo();
+        cryptoInfo.set(numSubSamples,
+                      numBytesOfClearData,
+                      numBytesOfEncryptedData,
+                      key,
+                      iv,
+                      mode);
+    }
+
+    public Sample set(ByteBuffer bytes, BufferInfo info, CryptoInfo cryptoInfo) throws IOException {
+        if (bytes != null && info.size > 0) {
+            buffer.readFromByteBuffer(bytes, info.offset, info.size);
+        }
+        this.info.set(0, info.size, info.presentationTimeUs, info.flags);
+        this.cryptoInfo = cryptoInfo;
+
+        return this;
+    }
+
+    public void dispose() {
+        if (isEOS()) {
+            return;
+        }
+
+        if (buffer != null) {
+            buffer.dispose();
+            buffer = null;
+        }
+        info = null;
+        cryptoInfo = null;
+    }
+
+    public boolean isEOS() {
+        return (this == EOS) ||
+                ((info.flags & MediaCodec.BUFFER_FLAG_END_OF_STREAM) != 0);
+    }
+
+    public static final Creator<Sample> CREATOR = new Creator<Sample>() {
+        @Override
+        public Sample createFromParcel(Parcel in) {
+            return new Sample(in);
+        }
+
+        @Override
+        public Sample[] newArray(int size) {
+            return new Sample[size];
+        }
+    };
+
+    @Override
+    public int describeContents() {
+        return 0;
+    }
+
+    @Override
+    public void writeToParcel(Parcel dest, int parcelableFlags) {
+        writeInfo(dest);
+        writeCrypto(dest);
+        dest.writeParcelable(buffer, parcelableFlags);
+    }
+
+    private void writeInfo(Parcel dest) {
+        dest.writeInt(info.offset);
+        dest.writeInt(info.size);
+        dest.writeLong(info.presentationTimeUs);
+        dest.writeInt(info.flags);
+    }
+
+    private void writeCrypto(Parcel dest) {
+        if (cryptoInfo != null) {
+            dest.writeInt(1);
+            dest.writeByteArray(cryptoInfo.iv);
+            dest.writeByteArray(cryptoInfo.key);
+            dest.writeInt(cryptoInfo.mode);
+            dest.writeIntArray(cryptoInfo.numBytesOfClearData);
+            dest.writeIntArray(cryptoInfo.numBytesOfEncryptedData);
+            dest.writeInt(cryptoInfo.numSubSamples);
+        } else {
+            dest.writeInt(0);
+        }
+    }
+
+    public static byte[] byteArrayFromBuffer(ByteBuffer buffer, int offset, int size) {
+        if (buffer == null || buffer.capacity() == 0 || size == 0) {
+            return null;
+        }
+        if (buffer.hasArray() && offset == 0 && buffer.array().length == size) {
+            return buffer.array();
+        }
+        int length = Math.min(offset + size, buffer.capacity()) - offset;
+        byte[] bytes = new byte[length];
+        buffer.position(offset);
+        buffer.get(bytes);
+        return bytes;
+    }
+
+    @WrapForJNI
+    public void writeToByteBuffer(ByteBuffer dest) throws IOException {
+        if (buffer != null && dest != null && info.size > 0) {
+            buffer.writeToByteBuffer(dest, info.offset, info.size);
+        }
+    }
+
+    @Override
+    public String toString() {
+        if (isEOS()) {
+            return "EOS sample";
+        }
+
+        StringBuilder str = new StringBuilder();
+        str.append("{ buffer=").append(buffer).
+                append(", info=").
+                append("{ offset=").append(info.offset).
+                append(", size=").append(info.size).
+                append(", pts=").append(info.presentationTimeUs).
+                append(", flags=").append(Integer.toHexString(info.flags)).append(" }").
+                append(" }");
+            return str.toString();
+    }
+}
\ No newline at end of file
rename from mobile/android/base/java/org/mozilla/gecko/media/SamplePool.java
rename to mobile/android/geckoview/src/main/java/org/mozilla/gecko/media/SamplePool.java
rename from mobile/android/base/java/org/mozilla/gecko/media/SessionKeyInfo.java
rename to mobile/android/geckoview/src/main/java/org/mozilla/gecko/media/SessionKeyInfo.java
new file mode 100644
--- /dev/null
+++ b/mobile/android/geckoview/src/main/java/org/mozilla/gecko/media/SharedMemBuffer.java
@@ -0,0 +1,90 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+package org.mozilla.gecko.media;
+
+import android.os.Parcel;
+
+import org.mozilla.gecko.mozglue.SharedMemory;
+import org.mozilla.gecko.media.Sample;
+
+import java.io.IOException;
+import java.nio.ByteBuffer;
+
+public final class SharedMemBuffer implements Sample.Buffer {
+    private SharedMemory mSharedMem;
+
+    /* package */
+    public SharedMemBuffer(SharedMemory sharedMem) {
+        mSharedMem = sharedMem;
+    }
+
+    protected SharedMemBuffer(Parcel in) {
+        mSharedMem = in.readParcelable(Sample.class.getClassLoader());
+    }
+
+    @Override
+    public void writeToParcel(Parcel dest, int flags) {
+        dest.writeParcelable(mSharedMem, flags);
+    }
+
+    @Override
+    public int describeContents() {
+        return 0;
+    }
+
+    public static final Creator<SharedMemBuffer> CREATOR = new Creator<SharedMemBuffer>() {
+        @Override
+        public SharedMemBuffer createFromParcel(Parcel in) {
+            return new SharedMemBuffer(in);
+        }
+
+        @Override
+        public SharedMemBuffer[] newArray(int size) {
+            return new SharedMemBuffer[size];
+        }
+    };
+
+    @Override
+    public int capacity() {
+        return mSharedMem != null ? mSharedMem.getSize() : 0;
+    }
+
+    @Override
+    public void readFromByteBuffer(ByteBuffer src, int offset, int size) throws IOException {
+        if (!src.isDirect()) {
+            throw new IOException("SharedMemBuffer only support reading from direct byte buffer.");
+        }
+        try {
+            nativeReadFromDirectBuffer(src, mSharedMem.getPointer(), offset, size);
+        } catch (NullPointerException e) {
+            throw new IOException(e);
+        }
+    }
+
+    private native static void nativeReadFromDirectBuffer(ByteBuffer src, long dest, int offset, int size);
+
+    @Override
+    public void writeToByteBuffer(ByteBuffer dest, int offset, int size) throws IOException {
+        if (!dest.isDirect()) {
+            throw new IOException("SharedMemBuffer only support writing to direct byte buffer.");
+        }
+        try {
+            nativeWriteToDirectBuffer(mSharedMem.getPointer(), dest, offset, size);
+        } catch (NullPointerException e) {
+            throw new IOException(e);
+        }
+    }
+
+    private native static void nativeWriteToDirectBuffer(long src, ByteBuffer dest, int offset, int size);
+
+    @Override
+    public void dispose() {
+        if (mSharedMem != null) {
+            mSharedMem.dispose();
+            mSharedMem = null;
+        }
+    }
+
+    @Override public String toString() { return "Buffer: " + mSharedMem; }
+}
rename from mobile/android/base/java/org/mozilla/gecko/mozglue/SharedMemory.java
rename to mobile/android/geckoview/src/main/java/org/mozilla/gecko/mozglue/SharedMemory.java
--- a/mozglue/android/SharedMemNatives.cpp
+++ b/mozglue/android/SharedMemNatives.cpp
@@ -8,17 +8,17 @@
 #include <stdio.h>
 #include <string.h>
 #include <sys/mman.h>
 
 extern "C" {
 
 JNIEXPORT
 void JNICALL
-Java_org_mozilla_gecko_mozglue_SharedMemBuffer_nativeReadFromDirectBuffer(JNIEnv* jenv, jclass, jobject src, jlong dest, jint offset, jint size)
+Java_org_mozilla_gecko_media_SharedMemBuffer_nativeReadFromDirectBuffer(JNIEnv* jenv, jclass, jobject src, jlong dest, jint offset, jint size)
 {
   uint8_t* from = static_cast<uint8_t*>(jenv->GetDirectBufferAddress(src));
   if (from == nullptr) {
     jenv->ThrowNew(jenv->FindClass("java/lang/NullPointerException"), "Null direct buffer");
     return;
   }
 
   void* to = reinterpret_cast<void*>(dest);
@@ -27,17 +27,17 @@ Java_org_mozilla_gecko_mozglue_SharedMem
     return;
   }
 
   memcpy(to, from + offset, size);
 }
 
 JNIEXPORT
 void JNICALL
-Java_org_mozilla_gecko_mozglue_SharedMemBuffer_nativeWriteToDirectBuffer(JNIEnv* jenv, jclass, jlong src, jobject dest, jint offset, jint size)
+Java_org_mozilla_gecko_media_SharedMemBuffer_nativeWriteToDirectBuffer(JNIEnv* jenv, jclass, jlong src, jobject dest, jint offset, jint size)
 {
   uint8_t* from = reinterpret_cast<uint8_t*>(src);
   if (from == nullptr) {
     jenv->ThrowNew(jenv->FindClass("java/lang/NullPointerException"), "Null shared memory buffer");
     return;
   }
 
   void* to = jenv->GetDirectBufferAddress(dest);
--- a/widget/android/fennec/FennecJNINatives.h
+++ b/widget/android/fennec/FennecJNINatives.h
@@ -145,81 +145,11 @@ public:
 template<class Impl>
 const JNINativeMethod ZoomedView::Natives<Impl>::methods[] = {
 
     mozilla::jni::MakeNativeMethod<ZoomedView::RequestZoomedViewData_t>(
             mozilla::jni::NativeStub<ZoomedView::RequestZoomedViewData_t, Impl>
             ::template Wrap<&Impl::RequestZoomedViewData>)
 };
 
-template<class Impl>
-class CodecProxy::NativeCallbacks::Natives : public mozilla::jni::NativeImpl<NativeCallbacks, Impl>
-{
-public:
-    static const JNINativeMethod methods[5];
-};
-
-template<class Impl>
-const JNINativeMethod CodecProxy::NativeCallbacks::Natives<Impl>::methods[] = {
-
-    mozilla::jni::MakeNativeMethod<CodecProxy::NativeCallbacks::DisposeNative_t>(
-            mozilla::jni::NativeStub<CodecProxy::NativeCallbacks::DisposeNative_t, Impl>
-            ::template Wrap<&Impl::DisposeNative>),
-
-    mozilla::jni::MakeNativeMethod<CodecProxy::NativeCallbacks::OnError_t>(
-            mozilla::jni::NativeStub<CodecProxy::NativeCallbacks::OnError_t, Impl>
-            ::template Wrap<&Impl::OnError>),
-
-    mozilla::jni::MakeNativeMethod<CodecProxy::NativeCallbacks::OnInputExhausted_t>(
-            mozilla::jni::NativeStub<CodecProxy::NativeCallbacks::OnInputExhausted_t, Impl>
-            ::template Wrap<&Impl::OnInputExhausted>),
-
-    mozilla::jni::MakeNativeMethod<CodecProxy::NativeCallbacks::OnOutput_t>(
-            mozilla::jni::NativeStub<CodecProxy::NativeCallbacks::OnOutput_t, Impl>
-            ::template Wrap<&Impl::OnOutput>),
-
-    mozilla::jni::MakeNativeMethod<CodecProxy::NativeCallbacks::OnOutputFormatChanged_t>(
-            mozilla::jni::NativeStub<CodecProxy::NativeCallbacks::OnOutputFormatChanged_t, Impl>
-            ::template Wrap<&Impl::OnOutputFormatChanged>)
-};
-
-template<class Impl>
-class MediaDrmProxy::NativeMediaDrmProxyCallbacks::Natives : public mozilla::jni::NativeImpl<NativeMediaDrmProxyCallbacks, Impl>
-{
-public:
-    static const JNINativeMethod methods[7];
-};
-
-template<class Impl>
-const JNINativeMethod MediaDrmProxy::NativeMediaDrmProxyCallbacks::Natives<Impl>::methods[] = {
-
-    mozilla::jni::MakeNativeMethod<MediaDrmProxy::NativeMediaDrmProxyCallbacks::OnRejectPromise_t>(
-            mozilla::jni::NativeStub<MediaDrmProxy::NativeMediaDrmProxyCallbacks::OnRejectPromise_t, Impl>
-            ::template Wrap<&Impl::OnRejectPromise>),
-
-    mozilla::jni::MakeNativeMethod<MediaDrmProxy::NativeMediaDrmProxyCallbacks::OnSessionBatchedKeyChanged_t>(
-            mozilla::jni::NativeStub<MediaDrmProxy::NativeMediaDrmProxyCallbacks::OnSessionBatchedKeyChanged_t, Impl>
-            ::template Wrap<&Impl::OnSessionBatchedKeyChanged>),
-
-    mozilla::jni::MakeNativeMethod<MediaDrmProxy::NativeMediaDrmProxyCallbacks::OnSessionClosed_t>(
-            mozilla::jni::NativeStub<MediaDrmProxy::NativeMediaDrmProxyCallbacks::OnSessionClosed_t, Impl>
-            ::template Wrap<&Impl::OnSessionClosed>),
-
-    mozilla::jni::MakeNativeMethod<MediaDrmProxy::NativeMediaDrmProxyCallbacks::OnSessionCreated_t>(
-            mozilla::jni::NativeStub<MediaDrmProxy::NativeMediaDrmProxyCallbacks::OnSessionCreated_t, Impl>
-            ::template Wrap<&Impl::OnSessionCreated>),
-
-    mozilla::jni::MakeNativeMethod<MediaDrmProxy::NativeMediaDrmProxyCallbacks::OnSessionError_t>(
-            mozilla::jni::NativeStub<MediaDrmProxy::NativeMediaDrmProxyCallbacks::OnSessionError_t, Impl>
-            ::template Wrap<&Impl::OnSessionError>),
-
-    mozilla::jni::MakeNativeMethod<MediaDrmProxy::NativeMediaDrmProxyCallbacks::OnSessionMessage_t>(
-            mozilla::jni::NativeStub<MediaDrmProxy::NativeMediaDrmProxyCallbacks::OnSessionMessage_t, Impl>
-            ::template Wrap<&Impl::OnSessionMessage>),
-
-    mozilla::jni::MakeNativeMethod<MediaDrmProxy::NativeMediaDrmProxyCallbacks::OnSessionUpdated_t>(
-            mozilla::jni::NativeStub<MediaDrmProxy::NativeMediaDrmProxyCallbacks::OnSessionUpdated_t, Impl>
-            ::template Wrap<&Impl::OnSessionUpdated>)
-};
-
 } /* java */
 } /* mozilla */
 #endif // FennecJNINatives_h
--- a/widget/android/fennec/FennecJNIWrappers.cpp
+++ b/widget/android/fennec/FennecJNIWrappers.cpp
@@ -173,281 +173,16 @@ auto AudioFocusAgent::NotifyStartedPlayi
 constexpr char AudioFocusAgent::NotifyStoppedPlaying_t::name[];
 constexpr char AudioFocusAgent::NotifyStoppedPlaying_t::signature[];
 
 auto AudioFocusAgent::NotifyStoppedPlaying() -> void
 {
     return mozilla::jni::Method<NotifyStoppedPlaying_t>::Call(AudioFocusAgent::Context(), nullptr);
 }
 
-const char CodecProxy::name[] =
-        "org/mozilla/gecko/media/CodecProxy";
-
-constexpr char CodecProxy::Create_t::name[];
-constexpr char CodecProxy::Create_t::signature[];
-
-auto CodecProxy::Create(mozilla::jni::Object::Param a0, mozilla::jni::Object::Param a1, mozilla::jni::Object::Param a2, mozilla::jni::String::Param a3) -> CodecProxy::LocalRef
-{
-    return mozilla::jni::Method<Create_t>::Call(CodecProxy::Context(), nullptr, a0, a1, a2, a3);
-}
-
-constexpr char CodecProxy::Flush_t::name[];
-constexpr char CodecProxy::Flush_t::signature[];
-
-auto CodecProxy::Flush() const -> bool
-{
-    return mozilla::jni::Method<Flush_t>::Call(CodecProxy::mCtx, nullptr);
-}
-
-constexpr char CodecProxy::Input_t::name[];
-constexpr char CodecProxy::Input_t::signature[];
-
-auto CodecProxy::Input(mozilla::jni::ByteBuffer::Param a0, mozilla::jni::Object::Param a1, mozilla::jni::Object::Param a2) const -> bool
-{
-    return mozilla::jni::Method<Input_t>::Call(CodecProxy::mCtx, nullptr, a0, a1, a2);
-}
-
-constexpr char CodecProxy::IsAdaptivePlaybackSupported_t::name[];
-constexpr char CodecProxy::IsAdaptivePlaybackSupported_t::signature[];
-
-auto CodecProxy::IsAdaptivePlaybackSupported() const -> bool
-{
-    return mozilla::jni::Method<IsAdaptivePlaybackSupported_t>::Call(CodecProxy::mCtx, nullptr);
-}
-
-constexpr char CodecProxy::Release_t::name[];
-constexpr char CodecProxy::Release_t::signature[];
-
-auto CodecProxy::Release() const -> bool
-{
-    return mozilla::jni::Method<Release_t>::Call(CodecProxy::mCtx, nullptr);
-}
-
-constexpr char CodecProxy::ReleaseOutput_t::name[];
-constexpr char CodecProxy::ReleaseOutput_t::signature[];
-
-auto CodecProxy::ReleaseOutput(mozilla::jni::Object::Param a0, bool a1) const -> bool
-{
-    return mozilla::jni::Method<ReleaseOutput_t>::Call(CodecProxy::mCtx, nullptr, a0, a1);
-}
-
-const char CodecProxy::NativeCallbacks::name[] =
-        "org/mozilla/gecko/media/CodecProxy$NativeCallbacks";
-
-constexpr char CodecProxy::NativeCallbacks::New_t::name[];
-constexpr char CodecProxy::NativeCallbacks::New_t::signature[];
-
-auto CodecProxy::NativeCallbacks::New() -> NativeCallbacks::LocalRef
-{
-    return mozilla::jni::Constructor<New_t>::Call(NativeCallbacks::Context(), nullptr);
-}
-
-constexpr char CodecProxy::NativeCallbacks::DisposeNative_t::name[];
-constexpr char CodecProxy::NativeCallbacks::DisposeNative_t::signature[];
-
-constexpr char CodecProxy::NativeCallbacks::OnError_t::name[];
-constexpr char CodecProxy::NativeCallbacks::OnError_t::signature[];
-
-constexpr char CodecProxy::NativeCallbacks::OnInputExhausted_t::name[];
-constexpr char CodecProxy::NativeCallbacks::OnInputExhausted_t::signature[];
-
-constexpr char CodecProxy::NativeCallbacks::OnOutput_t::name[];
-constexpr char CodecProxy::NativeCallbacks::OnOutput_t::signature[];
-
-constexpr char CodecProxy::NativeCallbacks::OnOutputFormatChanged_t::name[];
-constexpr char CodecProxy::NativeCallbacks::OnOutputFormatChanged_t::signature[];
-
-const char MediaDrmProxy::name[] =
-        "org/mozilla/gecko/media/MediaDrmProxy";
-
-constexpr char MediaDrmProxy::CanDecode_t::name[];
-constexpr char MediaDrmProxy::CanDecode_t::signature[];
-
-auto MediaDrmProxy::CanDecode(mozilla::jni::String::Param a0) -> bool
-{
-    return mozilla::jni::Method<CanDecode_t>::Call(MediaDrmProxy::Context(), nullptr, a0);
-}
-
-constexpr char MediaDrmProxy::IsCryptoSchemeSupported_t::name[];
-constexpr char MediaDrmProxy::IsCryptoSchemeSupported_t::signature[];
-
-auto MediaDrmProxy::IsCryptoSchemeSupported(mozilla::jni::String::Param a0, mozilla::jni::String::Param a1) -> bool
-{
-    return mozilla::jni::Method<IsCryptoSchemeSupported_t>::Call(MediaDrmProxy::Context(), nullptr, a0, a1);
-}
-
-constexpr char MediaDrmProxy::CloseSession_t::name[];
-constexpr char MediaDrmProxy::CloseSession_t::signature[];
-
-auto MediaDrmProxy::CloseSession(int32_t a0, mozilla::jni::String::Param a1) const -> void
-{
-    return mozilla::jni::Method<CloseSession_t>::Call(MediaDrmProxy::mCtx, nullptr, a0, a1);
-}
-
-constexpr char MediaDrmProxy::Create_t::name[];
-constexpr char MediaDrmProxy::Create_t::signature[];
-
-auto MediaDrmProxy::Create(mozilla::jni::String::Param a0, mozilla::jni::Object::Param a1) -> MediaDrmProxy::LocalRef
-{
-    return mozilla::jni::Method<Create_t>::Call(MediaDrmProxy::Context(), nullptr, a0, a1);
-}
-
-constexpr char MediaDrmProxy::CreateSession_t::name[];
-constexpr char MediaDrmProxy::CreateSession_t::signature[];
-
-auto MediaDrmProxy::CreateSession(int32_t a0, int32_t a1, mozilla::jni::String::Param a2, mozilla::jni::ByteArray::Param a3) const -> void
-{
-    return mozilla::jni::Method<CreateSession_t>::Call(MediaDrmProxy::mCtx, nullptr, a0, a1, a2, a3);
-}
-
-constexpr char MediaDrmProxy::Destroy_t::name[];
-constexpr char MediaDrmProxy::Destroy_t::signature[];
-
-auto MediaDrmProxy::Destroy() const -> void
-{
-    return mozilla::jni::Method<Destroy_t>::Call(MediaDrmProxy::mCtx, nullptr);
-}
-
-constexpr char MediaDrmProxy::GetMediaCrypto_t::name[];
-constexpr char MediaDrmProxy::GetMediaCrypto_t::signature[];
-
-auto MediaDrmProxy::GetMediaCrypto(mozilla::jni::String::Param a0) -> mozilla::jni::Object::LocalRef
-{
-    return mozilla::jni::Method<GetMediaCrypto_t>::Call(MediaDrmProxy::Context(), nullptr, a0);
-}
-
-constexpr char MediaDrmProxy::GetStubId_t::name[];
-constexpr char MediaDrmProxy::GetStubId_t::signature[];
-
-auto MediaDrmProxy::GetStubId() const -> mozilla::jni::String::LocalRef
-{
-    return mozilla::jni::Method<GetStubId_t>::Call(MediaDrmProxy::mCtx, nullptr);
-}
-
-constexpr char MediaDrmProxy::IsSchemeSupported_t::name[];
-constexpr char MediaDrmProxy::IsSchemeSupported_t::signature[];
-
-auto MediaDrmProxy::IsSchemeSupported(mozilla::jni::String::Param a0) -> bool
-{
-    return mozilla::jni::Method<IsSchemeSupported_t>::Call(MediaDrmProxy::Context(), nullptr, a0);
-}
-
-constexpr char MediaDrmProxy::UpdateSession_t::name[];
-constexpr char MediaDrmProxy::UpdateSession_t::signature[];
-
-auto MediaDrmProxy::UpdateSession(int32_t a0, mozilla::jni::String::Param a1, mozilla::jni::ByteArray::Param a2) const -> void
-{
-    return mozilla::jni::Method<UpdateSession_t>::Call(MediaDrmProxy::mCtx, nullptr, a0, a1, a2);
-}
-
-const char16_t MediaDrmProxy::AAC[] = u"audio/mp4a-latm";
-
-const char16_t MediaDrmProxy::AVC[] = u"video/avc";
-
-const char16_t MediaDrmProxy::OPUS[] = u"audio/opus";
-
-const char16_t MediaDrmProxy::VORBIS[] = u"audio/vorbis";
-
-const char16_t MediaDrmProxy::VP8[] = u"video/x-vnd.on2.vp8";
-
-const char16_t MediaDrmProxy::VP9[] = u"video/x-vnd.on2.vp9";
-
-const char MediaDrmProxy::NativeMediaDrmProxyCallbacks::name[] =
-        "org/mozilla/gecko/media/MediaDrmProxy$NativeMediaDrmProxyCallbacks";
-
-constexpr char MediaDrmProxy::NativeMediaDrmProxyCallbacks::New_t::name[];
-constexpr char MediaDrmProxy::NativeMediaDrmProxyCallbacks::New_t::signature[];
-
-auto MediaDrmProxy::NativeMediaDrmProxyCallbacks::New() -> NativeMediaDrmProxyCallbacks::LocalRef
-{
-    return mozilla::jni::Constructor<New_t>::Call(NativeMediaDrmProxyCallbacks::Context(), nullptr);
-}
-
-constexpr char MediaDrmProxy::NativeMediaDrmProxyCallbacks::OnRejectPromise_t::name[];
-constexpr char MediaDrmProxy::NativeMediaDrmProxyCallbacks::OnRejectPromise_t::signature[];
-
-constexpr char MediaDrmProxy::NativeMediaDrmProxyCallbacks::OnSessionBatchedKeyChanged_t::name[];
-constexpr char MediaDrmProxy::NativeMediaDrmProxyCallbacks::OnSessionBatchedKeyChanged_t::signature[];
-
-constexpr char MediaDrmProxy::NativeMediaDrmProxyCallbacks::OnSessionClosed_t::name[];
-constexpr char MediaDrmProxy::NativeMediaDrmProxyCallbacks::OnSessionClosed_t::signature[];
-
-constexpr char MediaDrmProxy::NativeMediaDrmProxyCallbacks::OnSessionCreated_t::name[];
-constexpr char MediaDrmProxy::NativeMediaDrmProxyCallbacks::OnSessionCreated_t::signature[];
-
-constexpr char MediaDrmProxy::NativeMediaDrmProxyCallbacks::OnSessionError_t::name[];
-constexpr char MediaDrmProxy::NativeMediaDrmProxyCallbacks::OnSessionError_t::signature[];
-
-constexpr char MediaDrmProxy::NativeMediaDrmProxyCallbacks::OnSessionMessage_t::name[];
-constexpr char MediaDrmProxy::NativeMediaDrmProxyCallbacks::OnSessionMessage_t::signature[];
-
-constexpr char MediaDrmProxy::NativeMediaDrmProxyCallbacks::OnSessionUpdated_t::name[];
-constexpr char MediaDrmProxy::NativeMediaDrmProxyCallbacks::OnSessionUpdated_t::signature[];
-
-const char Sample::name[] =
-        "org/mozilla/gecko/media/Sample";
-
-constexpr char Sample::WriteToByteBuffer_t::name[];
-constexpr char Sample::WriteToByteBuffer_t::signature[];
-
-auto Sample::WriteToByteBuffer(mozilla::jni::ByteBuffer::Param a0) const -> void
-{
-    return mozilla::jni::Method<WriteToByteBuffer_t>::Call(Sample::mCtx, nullptr, a0);
-}
-
-constexpr char Sample::Info_t::name[];
-constexpr char Sample::Info_t::signature[];
-
-auto Sample::Info() const -> mozilla::jni::Object::LocalRef
-{
-    return mozilla::jni::Field<Info_t>::Get(Sample::mCtx, nullptr);
-}
-
-auto Sample::Info(mozilla::jni::Object::Param a0) const -> void
-{
-    return mozilla::jni::Field<Info_t>::Set(Sample::mCtx, nullptr, a0);
-}
-
-const char SessionKeyInfo::name[] =
-        "org/mozilla/gecko/media/SessionKeyInfo";
-
-constexpr char SessionKeyInfo::New_t::name[];
-constexpr char SessionKeyInfo::New_t::signature[];
-
-auto SessionKeyInfo::New(mozilla::jni::ByteArray::Param a0, int32_t a1) -> SessionKeyInfo::LocalRef
-{
-    return mozilla::jni::Constructor<New_t>::Call(SessionKeyInfo::Context(), nullptr, a0, a1);
-}
-
-constexpr char SessionKeyInfo::KeyId_t::name[];
-constexpr char SessionKeyInfo::KeyId_t::signature[];
-
-auto SessionKeyInfo::KeyId() const -> mozilla::jni::ByteArray::LocalRef
-{
-    return mozilla::jni::Field<KeyId_t>::Get(SessionKeyInfo::mCtx, nullptr);
-}
-
-auto SessionKeyInfo::KeyId(mozilla::jni::ByteArray::Param a0) const -> void
-{
-    return mozilla::jni::Field<KeyId_t>::Set(SessionKeyInfo::mCtx, nullptr, a0);
-}
-
-constexpr char SessionKeyInfo::Status_t::name[];
-constexpr char SessionKeyInfo::Status_t::signature[];
-
-auto SessionKeyInfo::Status() const -> int32_t
-{
-    return mozilla::jni::Field<Status_t>::Get(SessionKeyInfo::mCtx, nullptr);
-}
-
-auto SessionKeyInfo::Status(int32_t a0) const -> void
-{
-    return mozilla::jni::Field<Status_t>::Set(SessionKeyInfo::mCtx, nullptr, a0);
-}
-
 const char Restrictions::name[] =
         "org/mozilla/gecko/restrictions/Restrictions";
 
 constexpr char Restrictions::IsAllowed_t::name[];
 constexpr char Restrictions::IsAllowed_t::signature[];
 
 auto Restrictions::IsAllowed(int32_t a0, mozilla::jni::String::Param a1) -> bool
 {
--- a/widget/android/fennec/FennecJNIWrappers.h
+++ b/widget/android/fennec/FennecJNIWrappers.h
@@ -649,801 +649,16 @@ public:
 
     static auto NotifyStoppedPlaying() -> void;
 
     static const mozilla::jni::CallingThread callingThread =
             mozilla::jni::CallingThread::GECKO;
 
 };
 
-class CodecProxy : public mozilla::jni::ObjectBase<CodecProxy>
-{
-public:
-    static const char name[];
-
-    explicit CodecProxy(const Context& ctx) : ObjectBase<CodecProxy>(ctx) {}
-
-    class NativeCallbacks;
-
-    struct Create_t {
-        typedef CodecProxy Owner;
-        typedef CodecProxy::LocalRef ReturnType;
-        typedef CodecProxy::Param SetterType;
-        typedef mozilla::jni::Args<
-                mozilla::jni::Object::Param,
-                mozilla::jni::Object::Param,
-                mozilla::jni::Object::Param,
-                mozilla::jni::String::Param> Args;
-        static constexpr char name[] = "create";
-        static constexpr char signature[] =
-                "(Landroid/media/MediaFormat;Landroid/view/Surface;Lorg/mozilla/gecko/media/CodecProxy$Callbacks;Ljava/lang/String;)Lorg/mozilla/gecko/media/CodecProxy;";
-        static const bool isStatic = true;
-        static const mozilla::jni::ExceptionMode exceptionMode =
-                mozilla::jni::ExceptionMode::ABORT;
-        static const mozilla::jni::CallingThread callingThread =
-                mozilla::jni::CallingThread::ANY;
-        static const mozilla::jni::DispatchTarget dispatchTarget =
-                mozilla::jni::DispatchTarget::CURRENT;
-    };
-
-    static auto Create(mozilla::jni::Object::Param, mozilla::jni::Object::Param, mozilla::jni::Object::Param, mozilla::jni::String::Param) -> CodecProxy::LocalRef;
-
-    struct Flush_t {
-        typedef CodecProxy Owner;
-        typedef bool ReturnType;
-        typedef bool SetterType;
-        typedef mozilla::jni::Args<> Args;
-        static constexpr char name[] = "flush";
-        static constexpr char signature[] =
-                "()Z";
-        static const bool isStatic = false;
-        static const mozilla::jni::ExceptionMode exceptionMode =
-                mozilla::jni::ExceptionMode::ABORT;
-        static const mozilla::jni::CallingThread callingThread =
-                mozilla::jni::CallingThread::ANY;
-        static const mozilla::jni::DispatchTarget dispatchTarget =
-                mozilla::jni::DispatchTarget::CURRENT;
-    };
-
-    auto Flush() const -> bool;
-
-    struct Input_t {
-        typedef CodecProxy Owner;
-        typedef bool ReturnType;
-        typedef bool SetterType;
-        typedef mozilla::jni::Args<
-                mozilla::jni::ByteBuffer::Param,
-                mozilla::jni::Object::Param,
-                mozilla::jni::Object::Param> Args;
-        static constexpr char name[] = "input";
-        static constexpr char signature[] =
-                "(Ljava/nio/ByteBuffer;Landroid/media/MediaCodec$BufferInfo;Landroid/media/MediaCodec$CryptoInfo;)Z";
-        static const bool isStatic = false;
-        static const mozilla::jni::ExceptionMode exceptionMode =
-                mozilla::jni::ExceptionMode::ABORT;
-        static const mozilla::jni::CallingThread callingThread =
-                mozilla::jni::CallingThread::ANY;
-        static const mozilla::jni::DispatchTarget dispatchTarget =
-                mozilla::jni::DispatchTarget::CURRENT;
-    };
-
-    auto Input(mozilla::jni::ByteBuffer::Param, mozilla::jni::Object::Param, mozilla::jni::Object::Param) const -> bool;
-
-    struct IsAdaptivePlaybackSupported_t {
-        typedef CodecProxy Owner;
-        typedef bool ReturnType;
-        typedef bool SetterType;
-        typedef mozilla::jni::Args<> Args;
-        static constexpr char name[] = "isAdaptivePlaybackSupported";
-        static constexpr char signature[] =
-                "()Z";
-        static const bool isStatic = false;
-        static const mozilla::jni::ExceptionMode exceptionMode =
-                mozilla::jni::ExceptionMode::ABORT;
-        static const mozilla::jni::CallingThread callingThread =
-                mozilla::jni::CallingThread::ANY;
-        static const mozilla::jni::DispatchTarget dispatchTarget =
-                mozilla::jni::DispatchTarget::CURRENT;
-    };
-
-    auto IsAdaptivePlaybackSupported() const -> bool;
-
-    struct Release_t {
-        typedef CodecProxy Owner;
-        typedef bool ReturnType;
-        typedef bool SetterType;
-        typedef mozilla::jni::Args<> Args;
-        static constexpr char name[] = "release";
-        static constexpr char signature[] =
-                "()Z";
-        static const bool isStatic = false;
-        static const mozilla::jni::ExceptionMode exceptionMode =
-                mozilla::jni::ExceptionMode::ABORT;
-        static const mozilla::jni::CallingThread callingThread =
-                mozilla::jni::CallingThread::ANY;
-        static const mozilla::jni::DispatchTarget dispatchTarget =
-                mozilla::jni::DispatchTarget::CURRENT;
-    };
-
-    auto Release() const -> bool;
-
-    struct ReleaseOutput_t {
-        typedef CodecProxy Owner;
-        typedef bool ReturnType;
-        typedef bool SetterType;
-        typedef mozilla::jni::Args<
-                mozilla::jni::Object::Param,
-                bool> Args;
-        static constexpr char name[] = "releaseOutput";
-        static constexpr char signature[] =
-                "(Lorg/mozilla/gecko/media/Sample;Z)Z";
-        static const bool isStatic = false;
-        static const mozilla::jni::ExceptionMode exceptionMode =
-                mozilla::jni::ExceptionMode::ABORT;
-        static const mozilla::jni::CallingThread callingThread =
-                mozilla::jni::CallingThread::ANY;
-        static const mozilla::jni::DispatchTarget dispatchTarget =
-                mozilla::jni::DispatchTarget::CURRENT;
-    };
-
-    auto ReleaseOutput(mozilla::jni::Object::Param, bool) const -> bool;
-
-    static const mozilla::jni::CallingThread callingThread =
-            mozilla::jni::CallingThread::ANY;
-
-};
-
-class CodecProxy::NativeCallbacks : public mozilla::jni::ObjectBase<NativeCallbacks>
-{
-public:
-    static const char name[];
-
-    explicit NativeCallbacks(const Context& ctx) : ObjectBase<NativeCallbacks>(ctx) {}
-
-    struct New_t {
-        typedef NativeCallbacks Owner;
-        typedef NativeCallbacks::LocalRef ReturnType;
-        typedef NativeCallbacks::Param SetterType;
-        typedef mozilla::jni::Args<> Args;
-        static constexpr char name[] = "<init>";
-        static constexpr char signature[] =
-                "()V";
-        static const bool isStatic = false;
-        static const mozilla::jni::ExceptionMode exceptionMode =
-                mozilla::jni::ExceptionMode::ABORT;
-        static const mozilla::jni::CallingThread callingThread =
-                mozilla::jni::CallingThread::ANY;
-        static const mozilla::jni::DispatchTarget dispatchTarget =
-                mozilla::jni::DispatchTarget::CURRENT;
-    };
-
-    static auto New() -> NativeCallbacks::LocalRef;
-
-    struct DisposeNative_t {
-        typedef NativeCallbacks Owner;
-        typedef void ReturnType;
-        typedef void SetterType;
-        typedef mozilla::jni::Args<> Args;
-        static constexpr char name[] = "disposeNative";
-        static constexpr char signature[] =
-                "()V";
-        static const bool isStatic = false;
-        static const mozilla::jni::ExceptionMode exceptionMode =
-                mozilla::jni::ExceptionMode::ABORT;
-        static const mozilla::jni::CallingThread callingThread =
-                mozilla::jni::CallingThread::ANY;
-        static const mozilla::jni::DispatchTarget dispatchTarget =
-                mozilla::jni::DispatchTarget::CURRENT;
-    };
-
-    struct OnError_t {
-        typedef NativeCallbacks Owner;
-        typedef void ReturnType;
-        typedef void SetterType;
-        typedef mozilla::jni::Args<
-                bool> Args;
-        static constexpr char name[] = "onError";
-        static constexpr char signature[] =
-                "(Z)V";
-        static const bool isStatic = false;
-        static const mozilla::jni::ExceptionMode exceptionMode =
-                mozilla::jni::ExceptionMode::ABORT;
-        static const mozilla::jni::CallingThread callingThread =
-                mozilla::jni::CallingThread::ANY;
-        static const mozilla::jni::DispatchTarget dispatchTarget =
-                mozilla::jni::DispatchTarget::CURRENT;
-    };
-
-    struct OnInputExhausted_t {
-        typedef NativeCallbacks Owner;
-        typedef void ReturnType;
-        typedef void SetterType;
-        typedef mozilla::jni::Args<> Args;
-        static constexpr char name[] = "onInputExhausted";
-        static constexpr char signature[] =
-                "()V";
-        static const bool isStatic = false;
-        static const mozilla::jni::ExceptionMode exceptionMode =
-                mozilla::jni::ExceptionMode::ABORT;
-        static const mozilla::jni::CallingThread callingThread =
-                mozilla::jni::CallingThread::ANY;
-        static const mozilla::jni::DispatchTarget dispatchTarget =
-                mozilla::jni::DispatchTarget::CURRENT;
-    };
-
-    struct OnOutput_t {
-        typedef NativeCallbacks Owner;
-        typedef void ReturnType;
-        typedef void SetterType;
-        typedef mozilla::jni::Args<
-                mozilla::jni::Object::Param> Args;
-        static constexpr char name[] = "onOutput";
-        static constexpr char signature[] =
-                "(Lorg/mozilla/gecko/media/Sample;)V";
-        static const bool isStatic = false;
-        static const mozilla::jni::ExceptionMode exceptionMode =
-                mozilla::jni::ExceptionMode::ABORT;
-        static const mozilla::jni::CallingThread callingThread =
-                mozilla::jni::CallingThread::ANY;
-        static const mozilla::jni::DispatchTarget dispatchTarget =
-                mozilla::jni::DispatchTarget::CURRENT;
-    };
-
-    struct OnOutputFormatChanged_t {
-        typedef NativeCallbacks Owner;
-        typedef void ReturnType;
-        typedef void SetterType;
-        typedef mozilla::jni::Args<
-                mozilla::jni::Object::Param> Args;
-        static constexpr char name[] = "onOutputFormatChanged";
-        static constexpr char signature[] =
-                "(Landroid/media/MediaFormat;)V";
-        static const bool isStatic = false;
-        static const mozilla::jni::ExceptionMode exceptionMode =
-                mozilla::jni::ExceptionMode::ABORT;
-        static const mozilla::jni::CallingThread callingThread =
-                mozilla::jni::CallingThread::ANY;
-        static const mozilla::jni::DispatchTarget dispatchTarget =
-                mozilla::jni::DispatchTarget::CURRENT;
-    };
-
-    static const mozilla::jni::CallingThread callingThread =
-            mozilla::jni::CallingThread::ANY;
-
-    template<class Impl> class Natives;
-};
-
-class MediaDrmProxy : public mozilla::jni::ObjectBase<MediaDrmProxy>
-{
-public:
-    static const char name[];
-
-    explicit MediaDrmProxy(const Context& ctx) : ObjectBase<MediaDrmProxy>(ctx) {}
-
-    class NativeMediaDrmProxyCallbacks;
-
-    struct CanDecode_t {
-        typedef MediaDrmProxy Owner;
-        typedef bool ReturnType;
-        typedef bool SetterType;
-        typedef mozilla::jni::Args<
-                mozilla::jni::String::Param> Args;
-        static constexpr char name[] = "CanDecode";
-        static constexpr char signature[] =
-                "(Ljava/lang/String;)Z";
-        static const bool isStatic = true;
-        static const mozilla::jni::ExceptionMode exceptionMode =
-                mozilla::jni::ExceptionMode::ABORT;
-        static const mozilla::jni::CallingThread callingThread =
-                mozilla::jni::CallingThread::ANY;
-        static const mozilla::jni::DispatchTarget dispatchTarget =
-                mozilla::jni::DispatchTarget::CURRENT;
-    };
-
-    static auto CanDecode(mozilla::jni::String::Param) -> bool;
-
-    struct IsCryptoSchemeSupported_t {
-        typedef MediaDrmProxy Owner;
-        typedef bool ReturnType;
-        typedef bool SetterType;
-        typedef mozilla::jni::Args<
-                mozilla::jni::String::Param,
-                mozilla::jni::String::Param> Args;
-        static constexpr char name[] = "IsCryptoSchemeSupported";
-        static constexpr char signature[] =
-                "(Ljava/lang/String;Ljava/lang/String;)Z";
-        static const bool isStatic = true;
-        static const mozilla::jni::ExceptionMode exceptionMode =
-                mozilla::jni::ExceptionMode::ABORT;
-        static const mozilla::jni::CallingThread callingThread =
-                mozilla::jni::CallingThread::ANY;
-        static const mozilla::jni::DispatchTarget dispatchTarget =
-                mozilla::jni::DispatchTarget::CURRENT;
-    };
-
-    static auto IsCryptoSchemeSupported(mozilla::jni::String::Param, mozilla::jni::String::Param) -> bool;
-
-    struct CloseSession_t {
-        typedef MediaDrmProxy Owner;
-        typedef void ReturnType;
-        typedef void SetterType;
-        typedef mozilla::jni::Args<
-                int32_t,
-                mozilla::jni::String::Param> Args;
-        static constexpr char name[] = "closeSession";
-        static constexpr char signature[] =
-                "(ILjava/lang/String;)V";
-        static const bool isStatic = false;
-        static const mozilla::jni::ExceptionMode exceptionMode =
-                mozilla::jni::ExceptionMode::ABORT;
-        static const mozilla::jni::CallingThread callingThread =
-                mozilla::jni::CallingThread::ANY;
-        static const mozilla::jni::DispatchTarget dispatchTarget =
-                mozilla::jni::DispatchTarget::CURRENT;
-    };
-
-    auto CloseSession(int32_t, mozilla::jni::String::Param) const -> void;
-
-    struct Create_t {
-        typedef MediaDrmProxy Owner;
-        typedef MediaDrmProxy::LocalRef ReturnType;
-        typedef MediaDrmProxy::Param SetterType;
-        typedef mozilla::jni::Args<
-                mozilla::jni::String::Param,
-                mozilla::jni::Object::Param> Args;
-        static constexpr char name[] = "create";
-        static constexpr char signature[] =
-                "(Ljava/lang/String;Lorg/mozilla/gecko/media/MediaDrmProxy$Callbacks;)Lorg/mozilla/gecko/media/MediaDrmProxy;";
-        static const bool isStatic = true;
-        static const mozilla::jni::ExceptionMode exceptionMode =
-                mozilla::jni::ExceptionMode::ABORT;
-        static const mozilla::jni::CallingThread callingThread =
-                mozilla::jni::CallingThread::GECKO;
-        static const mozilla::jni::DispatchTarget dispatchTarget =
-                mozilla::jni::DispatchTarget::CURRENT;
-    };
-
-    static auto Create(mozilla::jni::String::Param, mozilla::jni::Object::Param) -> MediaDrmProxy::LocalRef;
-
-    struct CreateSession_t {
-        typedef MediaDrmProxy Owner;
-        typedef void ReturnType;
-        typedef void SetterType;
-        typedef mozilla::jni::Args<
-                int32_t,
-                int32_t,
-                mozilla::jni::String::Param,
-                mozilla::jni::ByteArray::Param> Args;
-        static constexpr char name[] = "createSession";
-        static constexpr char signature[] =
-                "(IILjava/lang/String;[B)V";
-        static const bool isStatic = false;
-        static const mozilla::jni::ExceptionMode exceptionMode =
-                mozilla::jni::ExceptionMode::ABORT;
-        static const mozilla::jni::CallingThread callingThread =
-                mozilla::jni::CallingThread::ANY;
-        static const mozilla::jni::DispatchTarget dispatchTarget =
-                mozilla::jni::DispatchTarget::CURRENT;
-    };
-
-    auto CreateSession(int32_t, int32_t, mozilla::jni::String::Param, mozilla::jni::ByteArray::Param) const -> void;
-
-    struct Destroy_t {
-        typedef MediaDrmProxy Owner;
-        typedef void ReturnType;
-        typedef void SetterType;
-        typedef mozilla::jni::Args<> Args;
-        static constexpr char name[] = "destroy";
-        static constexpr char signature[] =
-                "()V";
-        static const bool isStatic = false;
-        static const mozilla::jni::ExceptionMode exceptionMode =
-                mozilla::jni::ExceptionMode::ABORT;
-        static const mozilla::jni::CallingThread callingThread =
-                mozilla::jni::CallingThread::ANY;
-        static const mozilla::jni::DispatchTarget dispatchTarget =
-                mozilla::jni::DispatchTarget::CURRENT;
-    };
-
-    auto Destroy() const -> void;
-
-    struct GetMediaCrypto_t {
-        typedef MediaDrmProxy Owner;
-        typedef mozilla::jni::Object::LocalRef ReturnType;
-        typedef mozilla::jni::Object::Param SetterType;
-        typedef mozilla::jni::Args<
-                mozilla::jni::String::Param> Args;
-        static constexpr char name[] = "getMediaCrypto";
-        static constexpr char signature[] =
-                "(Ljava/lang/String;)Landroid/media/MediaCrypto;";
-        static const bool isStatic = true;
-        static const mozilla::jni::ExceptionMode exceptionMode =
-                mozilla::jni::ExceptionMode::ABORT;
-        static const mozilla::jni::CallingThread callingThread =
-                mozilla::jni::CallingThread::ANY;
-        static const mozilla::jni::DispatchTarget dispatchTarget =
-                mozilla::jni::DispatchTarget::CURRENT;
-    };
-
-    static auto GetMediaCrypto(mozilla::jni::String::Param) -> mozilla::jni::Object::LocalRef;
-
-    struct GetStubId_t {
-        typedef MediaDrmProxy Owner;
-        typedef mozilla::jni::String::LocalRef ReturnType;
-        typedef mozilla::jni::String::Param SetterType;
-        typedef mozilla::jni::Args<> Args;
-        static constexpr char name[] = "getStubId";
-        static constexpr char signature[] =
-                "()Ljava/lang/String;";
-        static const bool isStatic = false;
-        static const mozilla::jni::ExceptionMode exceptionMode =
-                mozilla::jni::ExceptionMode::ABORT;
-        static const mozilla::jni::CallingThread callingThread =
-                mozilla::jni::CallingThread::GECKO;
-        static const mozilla::jni::DispatchTarget dispatchTarget =
-                mozilla::jni::DispatchTarget::CURRENT;
-    };
-
-    auto GetStubId() const -> mozilla::jni::String::LocalRef;
-
-    struct IsSchemeSupported_t {
-        typedef MediaDrmProxy Owner;
-        typedef bool ReturnType;
-        typedef bool SetterType;
-        typedef mozilla::jni::Args<
-                mozilla::jni::String::Param> Args;
-        static constexpr char name[] = "isSchemeSupported";
-        static constexpr char signature[] =
-                "(Ljava/lang/String;)Z";
-        static const bool isStatic = true;
-        static const mozilla::jni::ExceptionMode exceptionMode =
-                mozilla::jni::ExceptionMode::ABORT;
-        static const mozilla::jni::CallingThread callingThread =
-                mozilla::jni::CallingThread::ANY;
-        static const mozilla::jni::DispatchTarget dispatchTarget =
-                mozilla::jni::DispatchTarget::CURRENT;
-    };
-
-    static auto IsSchemeSupported(mozilla::jni::String::Param) -> bool;
-
-    struct UpdateSession_t {
-        typedef MediaDrmProxy Owner;
-        typedef void ReturnType;
-        typedef void SetterType;
-        typedef mozilla::jni::Args<
-                int32_t,
-                mozilla::jni::String::Param,
-                mozilla::jni::ByteArray::Param> Args;
-        static constexpr char name[] = "updateSession";
-        static constexpr char signature[] =
-                "(ILjava/lang/String;[B)V";
-        static const bool isStatic = false;
-        static const mozilla::jni::ExceptionMode exceptionMode =
-                mozilla::jni::ExceptionMode::ABORT;
-        static const mozilla::jni::CallingThread callingThread =
-                mozilla::jni::CallingThread::ANY;
-        static const mozilla::jni::DispatchTarget dispatchTarget =
-                mozilla::jni::DispatchTarget::CURRENT;
-    };
-
-    auto UpdateSession(int32_t, mozilla::jni::String::Param, mozilla::jni::ByteArray::Param) const -> void;
-
-    static const char16_t AAC[];
-
-    static const char16_t AVC[];
-
-    static const char16_t OPUS[];
-
-    static const char16_t VORBIS[];
-
-    static const char16_t VP8[];
-
-    static const char16_t VP9[];
-
-    static const mozilla::jni::CallingThread callingThread =
-            mozilla::jni::CallingThread::ANY;
-
-};
-
-class MediaDrmProxy::NativeMediaDrmProxyCallbacks : public mozilla::jni::ObjectBase<NativeMediaDrmProxyCallbacks>
-{
-public:
-    static const char name[];
-
-    explicit NativeMediaDrmProxyCallbacks(const Context& ctx) : ObjectBase<NativeMediaDrmProxyCallbacks>(ctx) {}
-
-    struct New_t {
-        typedef NativeMediaDrmProxyCallbacks Owner;
-        typedef NativeMediaDrmProxyCallbacks::LocalRef ReturnType;
-        typedef NativeMediaDrmProxyCallbacks::Param SetterType;
-        typedef mozilla::jni::Args<> Args;
-        static constexpr char name[] = "<init>";
-        static constexpr char signature[] =
-                "()V";
-        static const bool isStatic = false;
-        static const mozilla::jni::ExceptionMode exceptionMode =
-                mozilla::jni::ExceptionMode::ABORT;
-        static const mozilla::jni::CallingThread callingThread =
-                mozilla::jni::CallingThread::GECKO;
-        static const mozilla::jni::DispatchTarget dispatchTarget =
-                mozilla::jni::DispatchTarget::CURRENT;
-    };
-
-    static auto New() -> NativeMediaDrmProxyCallbacks::LocalRef;
-
-    struct OnRejectPromise_t {
-        typedef NativeMediaDrmProxyCallbacks Owner;
-        typedef void ReturnType;
-        typedef void SetterType;
-        typedef mozilla::jni::Args<
-                int32_t,
-                mozilla::jni::String::Param> Args;
-        static constexpr char name[] = "onRejectPromise";
-        static constexpr char signature[] =
-                "(ILjava/lang/String;)V";
-        static const bool isStatic = false;
-        static const mozilla::jni::ExceptionMode exceptionMode =
-                mozilla::jni::ExceptionMode::ABORT;
-        static const mozilla::jni::CallingThread callingThread =
-                mozilla::jni::CallingThread::ANY;
-        static const mozilla::jni::DispatchTarget dispatchTarget =
-                mozilla::jni::DispatchTarget::GECKO;
-    };
-
-    struct OnSessionBatchedKeyChanged_t {
-        typedef NativeMediaDrmProxyCallbacks Owner;
-        typedef void ReturnType;
-        typedef void SetterType;
-        typedef mozilla::jni::Args<
-                mozilla::jni::ByteArray::Param,
-                mozilla::jni::ObjectArray::Param> Args;
-        static constexpr char name[] = "onSessionBatchedKeyChanged";
-        static constexpr char signature[] =
-                "([B[Lorg/mozilla/gecko/media/SessionKeyInfo;)V";
-        static const bool isStatic = false;
-        static const mozilla::jni::ExceptionMode exceptionMode =
-                mozilla::jni::ExceptionMode::ABORT;
-        static const mozilla::jni::CallingThread callingThread =
-                mozilla::jni::CallingThread::ANY;
-        static const mozilla::jni::DispatchTarget dispatchTarget =
-                mozilla::jni::DispatchTarget::GECKO;
-    };
-
-    struct OnSessionClosed_t {
-        typedef NativeMediaDrmProxyCallbacks Owner;
-        typedef void ReturnType;
-        typedef void SetterType;
-        typedef mozilla::jni::Args<
-                int32_t,
-                mozilla::jni::ByteArray::Param> Args;
-        static constexpr char name[] = "onSessionClosed";
-        static constexpr char signature[] =
-                "(I[B)V";
-        static const bool isStatic = false;
-        static const mozilla::jni::ExceptionMode exceptionMode =
-                mozilla::jni::ExceptionMode::ABORT;
-        static const mozilla::jni::CallingThread callingThread =
-                mozilla::jni::CallingThread::ANY;
-        static const mozilla::jni::DispatchTarget dispatchTarget =
-                mozilla::jni::DispatchTarget::GECKO;
-    };
-
-    struct OnSessionCreated_t {
-        typedef NativeMediaDrmProxyCallbacks Owner;
-        typedef void ReturnType;
-        typedef void SetterType;
-        typedef mozilla::jni::Args<
-                int32_t,
-                int32_t,
-                mozilla::jni::ByteArray::Param,
-                mozilla::jni::ByteArray::Param> Args;
-        static constexpr char name[] = "onSessionCreated";
-        static constexpr char signature[] =
-                "(II[B[B)V";
-        static const bool isStatic = false;
-        static const mozilla::jni::ExceptionMode exceptionMode =
-                mozilla::jni::ExceptionMode::ABORT;
-        static const mozilla::jni::CallingThread callingThread =
-                mozilla::jni::CallingThread::ANY;
-        static const mozilla::jni::DispatchTarget dispatchTarget =
-                mozilla::jni::DispatchTarget::GECKO;
-    };
-
-    struct OnSessionError_t {
-        typedef NativeMediaDrmProxyCallbacks Owner;
-        typedef void ReturnType;
-        typedef void SetterType;
-        typedef mozilla::jni::Args<
-                mozilla::jni::ByteArray::Param,
-                mozilla::jni::String::Param> Args;
-        static constexpr char name[] = "onSessionError";
-        static constexpr char signature[] =
-                "([BLjava/lang/String;)V";
-        static const bool isStatic = false;
-        static const mozilla::jni::ExceptionMode exceptionMode =
-                mozilla::jni::ExceptionMode::ABORT;
-        static const mozilla::jni::CallingThread callingThread =
-                mozilla::jni::CallingThread::ANY;
-        static const mozilla::jni::DispatchTarget dispatchTarget =
-                mozilla::jni::DispatchTarget::GECKO;
-    };
-
-    struct OnSessionMessage_t {
-        typedef NativeMediaDrmProxyCallbacks Owner;
-        typedef void ReturnType;
-        typedef void SetterType;
-        typedef mozilla::jni::Args<
-                mozilla::jni::ByteArray::Param,
-                int32_t,
-                mozilla::jni::ByteArray::Param> Args;
-        static constexpr char name[] = "onSessionMessage";
-        static constexpr char signature[] =
-                "([BI[B)V";
-        static const bool isStatic = false;
-        static const mozilla::jni::ExceptionMode exceptionMode =
-                mozilla::jni::ExceptionMode::ABORT;
-        static const mozilla::jni::CallingThread callingThread =
-                mozilla::jni::CallingThread::ANY;
-        static const mozilla::jni::DispatchTarget dispatchTarget =
-                mozilla::jni::DispatchTarget::GECKO;
-    };
-
-    struct OnSessionUpdated_t {
-        typedef NativeMediaDrmProxyCallbacks Owner;
-        typedef void ReturnType;
-        typedef void SetterType;
-        typedef mozilla::jni::Args<
-                int32_t,
-                mozilla::jni::ByteArray::Param> Args;
-        static constexpr char name[] = "onSessionUpdated";
-        static constexpr char signature[] =
-                "(I[B)V";
-        static const bool isStatic = false;
-        static const mozilla::jni::ExceptionMode exceptionMode =
-                mozilla::jni::ExceptionMode::ABORT;
-        static const mozilla::jni::CallingThread callingThread =
-                mozilla::jni::CallingThread::ANY;
-        static const mozilla::jni::DispatchTarget dispatchTarget =
-                mozilla::jni::DispatchTarget::GECKO;
-    };
-
-    static const mozilla::jni::CallingThread callingThread =
-            mozilla::jni::CallingThread::ANY;
-
-    template<class Impl> class Natives;
-};
-
-class Sample : public mozilla::jni::ObjectBase<Sample>
-{
-public:
-    static const char name[];
-
-    explicit Sample(const Context& ctx) : ObjectBase<Sample>(ctx) {}
-
-    struct WriteToByteBuffer_t {
-        typedef Sample Owner;
-        typedef void ReturnType;
-        typedef void SetterType;
-        typedef mozilla::jni::Args<
-                mozilla::jni::ByteBuffer::Param> Args;
-        static constexpr char name[] = "writeToByteBuffer";
-        static constexpr char signature[] =
-                "(Ljava/nio/ByteBuffer;)V";
-        static const bool isStatic = false;
-        static const mozilla::jni::ExceptionMode exceptionMode =
-                mozilla::jni::ExceptionMode::ABORT;
-        static const mozilla::jni::CallingThread callingThread =
-                mozilla::jni::CallingThread::ANY;
-        static const mozilla::jni::DispatchTarget dispatchTarget =
-                mozilla::jni::DispatchTarget::CURRENT;
-    };
-
-    auto WriteToByteBuffer(mozilla::jni::ByteBuffer::Param) const -> void;
-
-    struct Info_t {
-        typedef Sample Owner;
-        typedef mozilla::jni::Object::LocalRef ReturnType;
-        typedef mozilla::jni::Object::Param SetterType;
-        typedef mozilla::jni::Args<> Args;
-        static constexpr char name[] = "info";
-        static constexpr char signature[] =
-                "Landroid/media/MediaCodec$BufferInfo;";
-        static const bool isStatic = false;
-        static const mozilla::jni::ExceptionMode exceptionMode =
-                mozilla::jni::ExceptionMode::ABORT;
-        static const mozilla::jni::CallingThread callingThread =
-                mozilla::jni::CallingThread::ANY;
-        static const mozilla::jni::DispatchTarget dispatchTarget =
-                mozilla::jni::DispatchTarget::CURRENT;
-    };
-
-    auto Info() const -> mozilla::jni::Object::LocalRef;
-
-    auto Info(mozilla::jni::Object::Param) const -> void;
-
-    static const mozilla::jni::CallingThread callingThread =
-            mozilla::jni::CallingThread::ANY;
-
-};
-
-class SessionKeyInfo : public mozilla::jni::ObjectBase<SessionKeyInfo>
-{
-public:
-    static const char name[];
-
-    explicit SessionKeyInfo(const Context& ctx) : ObjectBase<SessionKeyInfo>(ctx) {}
-
-    struct New_t {
-        typedef SessionKeyInfo Owner;
-        typedef SessionKeyInfo::LocalRef ReturnType;
-        typedef SessionKeyInfo::Param SetterType;
-        typedef mozilla::jni::Args<
-                mozilla::jni::ByteArray::Param,
-                int32_t> Args;
-        static constexpr char name[] = "<init>";
-        static constexpr char signature[] =
-                "([BI)V";
-        static const bool isStatic = false;
-        static const mozilla::jni::ExceptionMode exceptionMode =
-                mozilla::jni::ExceptionMode::ABORT;
-        static const mozilla::jni::CallingThread callingThread =
-                mozilla::jni::CallingThread::ANY;
-        static const mozilla::jni::DispatchTarget dispatchTarget =
-                mozilla::jni::DispatchTarget::CURRENT;
-    };
-
-    static auto New(mozilla::jni::ByteArray::Param, int32_t) -> SessionKeyInfo::LocalRef;
-
-    struct KeyId_t {
-        typedef SessionKeyInfo Owner;
-        typedef mozilla::jni::ByteArray::LocalRef ReturnType;
-        typedef mozilla::jni::ByteArray::Param SetterType;
-        typedef mozilla::jni::Args<> Args;
-        static constexpr char name[] = "keyId";
-        static constexpr char signature[] =
-                "[B";
-        static const bool isStatic = false;
-        static const mozilla::jni::ExceptionMode exceptionMode =
-                mozilla::jni::ExceptionMode::ABORT;
-        static const mozilla::jni::CallingThread callingThread =
-                mozilla::jni::CallingThread::ANY;
-        static const mozilla::jni::DispatchTarget dispatchTarget =
-                mozilla::jni::DispatchTarget::CURRENT;
-    };
-
-    auto KeyId() const -> mozilla::jni::ByteArray::LocalRef;
-
-    auto KeyId(mozilla::jni::ByteArray::Param) const -> void;
-
-    struct Status_t {
-        typedef SessionKeyInfo Owner;
-        typedef int32_t ReturnType;
-        typedef int32_t SetterType;
-        typedef mozilla::jni::Args<> Args;
-        static constexpr char name[] = "status";
-        static constexpr char signature[] =
-                "I";
-        static const bool isStatic = false;
-        static const mozilla::jni::ExceptionMode exceptionMode =
-                mozilla::jni::ExceptionMode::ABORT;
-        static const mozilla::jni::CallingThread callingThread =
-                mozilla::jni::CallingThread::ANY;
-        static const mozilla::jni::DispatchTarget dispatchTarget =
-                mozilla::jni::DispatchTarget::CURRENT;
-    };
-
-    auto Status() const -> int32_t;
-
-    auto Status(int32_t) const -> void;
-
-    static const mozilla::jni::CallingThread callingThread =
-            mozilla::jni::CallingThread::ANY;
-
-};
-
 class Restrictions : public mozilla::jni::ObjectBase<Restrictions>
 {
 public:
     static const char name[];
 
     explicit Restrictions(const Context& ctx) : ObjectBase<Restrictions>(ctx) {}
 
     struct IsAllowed_t {