Bug 1499137 - unbind media manager service only when both codecs and DRM bridges are gone. r=jya,snorp
authorJohn Lin <jolin@mozilla.com>
Wed, 17 Oct 2018 15:26:49 +0000
changeset 490088 d72b8e9bac3f8eead0f679b5ad07f9b1b6a7e7d8
parent 490087 2fee8f9b283dac85340edf7815fd62b93352bd33
child 490089 c203c7e7a7fa5e6c519d390dd67d9826febcf7cd
push id247
push userfmarier@mozilla.com
push dateSat, 27 Oct 2018 01:06:44 +0000
reviewersjya, snorp
bugs1499137
milestone64.0a1
Bug 1499137 - unbind media manager service only when both codecs and DRM bridges are gone. r=jya,snorp Differential Revision: https://phabricator.services.mozilla.com/D8794
mobile/android/geckoview/src/main/java/org/mozilla/gecko/media/RemoteManager.java
mobile/android/geckoview/src/main/java/org/mozilla/gecko/media/RemoteMediaDrmBridge.java
--- a/mobile/android/geckoview/src/main/java/org/mozilla/gecko/media/RemoteManager.java
+++ b/mobile/android/geckoview/src/main/java/org/mozilla/gecko/media/RemoteManager.java
@@ -32,17 +32,19 @@ public final class RemoteManager impleme
         if (sRemoteManager == null) {
             sRemoteManager = new RemoteManager();
         }
 
         sRemoteManager.init();
         return sRemoteManager;
     }
 
-    private List<CodecProxy> mProxies = new LinkedList<CodecProxy>();
+    private List<CodecProxy> mCodecs = new LinkedList<CodecProxy>();
+    private List<IMediaDrmBridge> mDrmBridges = new LinkedList<IMediaDrmBridge>();
+
     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);
@@ -128,17 +130,17 @@ public final class RemoteManager impleme
         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(isEncoder, format, surface, callbacks, drmStubId);
             if (proxy.init(remote)) {
-                mProxies.add(proxy);
+                mCodecs.add(proxy);
                 return proxy;
             } else {
                 return null;
             }
         } catch (RemoteException e) {
             e.printStackTrace();
             return null;
         }
@@ -148,16 +150,17 @@ public final class RemoteManager impleme
                                                                    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);
+            mDrmBridges.add(remoteBridge);
             return remoteBridge;
         } catch (RemoteException e) {
             Log.e(LOGTAG, "Got exception during createRemoteMediaDrmBridge().", e);
             return null;
         }
     }
 
     @Override
@@ -172,46 +175,63 @@ public final class RemoteManager impleme
         if (init() && recoverRemoteCodec()) {
             notifyError(false);
         } else {
             notifyError(true);
         }
     }
 
     private synchronized void notifyError(boolean fatal) {
-        for (CodecProxy proxy : mProxies) {
+        for (CodecProxy proxy : mCodecs) {
             proxy.reportError(fatal);
         }
     }
 
     private synchronized boolean recoverRemoteCodec() {
         if (DEBUG) Log.d(LOGTAG, "recover codec");
         boolean ok = true;
         try {
-            for (CodecProxy proxy : mProxies) {
+            for (CodecProxy proxy : mCodecs) {
                 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();
+            if (mCodecs.remove(proxy)) {
+                releaseIfNeeded();
             }
         }
     }
 
-    private void release() {
+    private void releaseIfNeeded() {
+        if (!mCodecs.isEmpty() || !mDrmBridges.isEmpty()) {
+            return;
+        }
+
         if (DEBUG) Log.d(LOGTAG, "release remote manager " + this);
         mConnection.unlink();
         Context appCtxt = GeckoAppShell.getApplicationContext();
         appCtxt.unbindService(mConnection);
     }
+
+    public void onRemoteMediaDrmBridgeReleased(IMediaDrmBridge remote) {
+        if (!mDrmBridges.contains(remote)) {
+            Log.e(LOGTAG, "Try to release unknown remote MediaDrm bridge: " + remote);
+            return;
+        }
+
+        synchronized (this) {
+            if (mDrmBridges.remove(remote)) {
+                releaseIfNeeded();
+            }
+        }
+    }
 } // RemoteManager
\ No newline at end of file
--- a/mobile/android/geckoview/src/main/java/org/mozilla/gecko/media/RemoteMediaDrmBridge.java
+++ b/mobile/android/geckoview/src/main/java/org/mozilla/gecko/media/RemoteMediaDrmBridge.java
@@ -134,16 +134,17 @@ final class RemoteMediaDrmBridge impleme
     public synchronized void release() {
         if (DEBUG) Log.d(LOGTAG, "release()");
 
         try {
             mRemote.release();
         } catch (Exception e) {
             Log.e(LOGTAG, "Got exception while releasing RemoteDrmBridge.", e);
         }
+        RemoteManager.getInstance().onRemoteMediaDrmBridgeReleased(mRemote);
         mRemote = null;
         mCallbacksFwd = null;
     }
 
     @Override
     public synchronized MediaCrypto getMediaCrypto() {
         if (DEBUG) Log.d(LOGTAG, "getMediaCrypto(), should not enter here!");
         assertTrue(false);