Index: content/public/android/java/src/org/chromium/content/browser/androidoverlay/AndroidOverlayProviderImpl.java |
diff --git a/content/public/android/java/src/org/chromium/content/browser/androidoverlay/AndroidOverlayProviderImpl.java b/content/public/android/java/src/org/chromium/content/browser/androidoverlay/AndroidOverlayProviderImpl.java |
index cf4766ffda92be146b7eb04d9ff855cb517b8386..03e7dbe9bdb866502f60987cb086344da92c40c4 100644 |
--- a/content/public/android/java/src/org/chromium/content/browser/androidoverlay/AndroidOverlayProviderImpl.java |
+++ b/content/public/android/java/src/org/chromium/content/browser/androidoverlay/AndroidOverlayProviderImpl.java |
@@ -5,6 +5,8 @@ |
package org.chromium.content.browser.androidoverlay; |
import android.content.Context; |
+import android.os.Handler; |
+import android.os.HandlerThread; |
import org.chromium.media.mojom.AndroidOverlay; |
import org.chromium.media.mojom.AndroidOverlayClient; |
@@ -15,23 +17,86 @@ import org.chromium.mojo.system.MojoException; |
import org.chromium.services.service_manager.InterfaceFactory; |
/** |
- * Default impl of AndroidOverlayProvider. Creates AndroidOverlayImpls. |
+ * Default impl of AndroidOverlayProvider. Creates AndroidOverlayImpls. We're a singleton, in the |
+ * sense that all provider clients talk to the same instance in the browser. |
*/ |
public class AndroidOverlayProviderImpl implements AndroidOverlayProvider { |
private static final String TAG = "AndroidOverlayProvider"; |
+ // Maximum number of concurrent overlays that we allow. |
+ private static final int MAX_OVERLAYS = 1; |
+ |
+ // We maintain a thread with a Looper for the AndroidOverlays to use, since Dialog requires one. |
+ // We don't want this to be the native thread that's used to create them (the browser UI thread) |
+ // since we don't want to block that waiting for sync callbacks from Android, such as |
+ // surfaceDestroyed. Instead, we run all AndroidOverlays on one shared overlay-ui thread. |
+ private HandlerThread mOverlayUiThread; |
+ private Handler mHandler; |
+ |
+ // Number of AndroidOverlays that have been created but not released. |
+ private int mNumOverlays; |
+ |
+ // Runnable that notifies us that a client has been released. |
+ private Runnable mNotifyReleasedRunnable = new Runnable() { |
+ @Override |
+ public void run() { |
+ notifyReleased(); |
+ } |
+ }; |
+ |
/** |
* Create an overlay matching |config| for |client|, and bind it to |request|. Remember that |
* potentially many providers are created. |
*/ |
+ @Override |
public void createOverlay(InterfaceRequest<AndroidOverlay> request, AndroidOverlayClient client, |
AndroidOverlayConfig config) { |
- client.onDestroyed(); |
+ // Limit the number of concurrent surfaces. |
+ if (mNumOverlays >= MAX_OVERLAYS) { |
+ client.onDestroyed(); |
+ return; |
+ } |
+ |
+ startThreadIfNeeded(); |
+ mNumOverlays++; |
boliu
2017/04/22 00:22:43
add thread asserts to this file as well? eg it's n
liberato (no reviews please)
2017/04/24 22:19:41
Done.
|
+ |
+ DialogOverlayOperations ops = |
+ new DialogOverlayOperationsImpl(mHandler, mNotifyReleasedRunnable); |
+ |
+ DialogOverlayImpl impl = new DialogOverlayImpl(client, config, ops); |
+ DialogOverlayImpl.MANAGER.bind(impl, request); |
+ } |
+ |
+ /** |
+ * Make sure that mOverlayUiThread and mHandler are ready for use, if needed. |
+ */ |
+ private void startThreadIfNeeded() { |
+ if (mOverlayUiThread != null) return; |
+ |
+ mOverlayUiThread = new HandlerThread("AndroidOverlayThread"); |
+ mOverlayUiThread.start(); |
+ mHandler = new Handler(mOverlayUiThread.getLooper()); |
+ } |
+ |
+ /** |
+ * Called by AndroidOverlays when they no longer need the thread via |mNotifyReleasedRunnable|. |
+ */ |
+ private void notifyReleased() { |
+ assert mNumOverlays > 0; |
+ mNumOverlays--; |
+ |
+ // We don't stop the looper thread here, else android can get mad when it tries to send |
+ // a message from the dialog on this thread. AndroidOverlay might have to notify us |
+ // separately to tell us when it's done with the thread, if we don't want to wait until |
+ // then to start creating a new SV. |
+ // Instead, we just avoid shutting down the thread at all for now. |
} |
+ // Remember that we can't tell which client disconnected. |
@Override |
public void close() {} |
+ // Remember that we can't tell which client disconnected. |
@Override |
public void onConnectionError(MojoException e) {} |
@@ -39,11 +104,13 @@ public class AndroidOverlayProviderImpl implements AndroidOverlayProvider { |
* Mojo factory. |
*/ |
public static class Factory implements InterfaceFactory<AndroidOverlayProvider> { |
+ private static AndroidOverlayProviderImpl sImpl; |
public Factory(Context context) {} |
@Override |
public AndroidOverlayProvider createImpl() { |
- return new AndroidOverlayProviderImpl(); |
+ if (sImpl == null) sImpl = new AndroidOverlayProviderImpl(); |
+ return sImpl; |
} |
} |
} |