| 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++;
|
| +
|
| + 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;
|
| }
|
| }
|
| }
|
|
|