Chromium Code Reviews| 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; |
| } |
| } |
| } |