OLD | NEW |
1 // Copyright 2017 The Chromium Authors. All rights reserved. | 1 // Copyright 2017 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 package org.chromium.content.browser.androidoverlay; | 5 package org.chromium.content.browser.androidoverlay; |
6 | 6 |
7 import android.content.Context; | 7 import android.content.Context; |
| 8 import android.os.Handler; |
| 9 import android.os.HandlerThread; |
8 | 10 |
| 11 import org.chromium.base.ThreadUtils; |
9 import org.chromium.media.mojom.AndroidOverlay; | 12 import org.chromium.media.mojom.AndroidOverlay; |
10 import org.chromium.media.mojom.AndroidOverlayClient; | 13 import org.chromium.media.mojom.AndroidOverlayClient; |
11 import org.chromium.media.mojom.AndroidOverlayConfig; | 14 import org.chromium.media.mojom.AndroidOverlayConfig; |
12 import org.chromium.media.mojom.AndroidOverlayProvider; | 15 import org.chromium.media.mojom.AndroidOverlayProvider; |
13 import org.chromium.mojo.bindings.InterfaceRequest; | 16 import org.chromium.mojo.bindings.InterfaceRequest; |
14 import org.chromium.mojo.system.MojoException; | 17 import org.chromium.mojo.system.MojoException; |
15 import org.chromium.services.service_manager.InterfaceFactory; | 18 import org.chromium.services.service_manager.InterfaceFactory; |
16 | 19 |
17 /** | 20 /** |
18 * Default impl of AndroidOverlayProvider. Creates AndroidOverlayImpls. | 21 * Default impl of AndroidOverlayProvider. Creates AndroidOverlayImpls. We're
a singleton, in the |
| 22 * sense that all provider clients talk to the same instance in the browser. |
19 */ | 23 */ |
20 public class AndroidOverlayProviderImpl implements AndroidOverlayProvider { | 24 public class AndroidOverlayProviderImpl implements AndroidOverlayProvider { |
21 private static final String TAG = "AndroidOverlayProvider"; | 25 private static final String TAG = "AndroidOverlayProvider"; |
22 | 26 |
| 27 // Maximum number of concurrent overlays that we allow. |
| 28 private static final int MAX_OVERLAYS = 1; |
| 29 |
| 30 // We maintain a thread with a Looper for the AndroidOverlays to use, since
Dialog requires one. |
| 31 // We don't want this to be the native thread that's used to create them (th
e browser UI thread) |
| 32 // since we don't want to block that waiting for sync callbacks from Android
, such as |
| 33 // surfaceDestroyed. Instead, we run all AndroidOverlays on one shared over
lay-ui thread. |
| 34 private HandlerThread mOverlayUiThread; |
| 35 private Handler mHandler; |
| 36 |
| 37 // Number of AndroidOverlays that have been created but not released. |
| 38 private int mNumOverlays; |
| 39 |
| 40 // Runnable that notifies us that a client has been released. |
| 41 private Runnable mNotifyReleasedRunnable = new Runnable() { |
| 42 @Override |
| 43 public void run() { |
| 44 notifyReleased(); |
| 45 } |
| 46 }; |
| 47 |
23 /** | 48 /** |
24 * Create an overlay matching |config| for |client|, and bind it to |request
|. Remember that | 49 * Create an overlay matching |config| for |client|, and bind it to |request
|. Remember that |
25 * potentially many providers are created. | 50 * potentially many providers are created. |
26 */ | 51 */ |
| 52 @Override |
27 public void createOverlay(InterfaceRequest<AndroidOverlay> request, AndroidO
verlayClient client, | 53 public void createOverlay(InterfaceRequest<AndroidOverlay> request, AndroidO
verlayClient client, |
28 AndroidOverlayConfig config) { | 54 AndroidOverlayConfig config) { |
29 client.onDestroyed(); | 55 ThreadUtils.assertOnUiThread(); |
| 56 |
| 57 // Limit the number of concurrent surfaces. |
| 58 if (mNumOverlays >= MAX_OVERLAYS) { |
| 59 client.onDestroyed(); |
| 60 return; |
| 61 } |
| 62 |
| 63 startThreadIfNeeded(); |
| 64 mNumOverlays++; |
| 65 |
| 66 DialogOverlayImpl impl = |
| 67 new DialogOverlayImpl(client, config, mHandler, mNotifyReleasedR
unnable); |
| 68 DialogOverlayImpl.MANAGER.bind(impl, request); |
30 } | 69 } |
31 | 70 |
| 71 /** |
| 72 * Make sure that mOverlayUiThread and mHandler are ready for use, if needed
. |
| 73 */ |
| 74 private void startThreadIfNeeded() { |
| 75 if (mOverlayUiThread != null) return; |
| 76 |
| 77 mOverlayUiThread = new HandlerThread("AndroidOverlayThread"); |
| 78 mOverlayUiThread.start(); |
| 79 mHandler = new Handler(mOverlayUiThread.getLooper()); |
| 80 } |
| 81 |
| 82 /** |
| 83 * Called by AndroidOverlays when they no longer need the thread via |mNotif
yReleasedRunnable|. |
| 84 */ |
| 85 private void notifyReleased() { |
| 86 ThreadUtils.assertOnUiThread(); |
| 87 assert mNumOverlays > 0; |
| 88 mNumOverlays--; |
| 89 |
| 90 // We don't stop the looper thread here, else android can get mad when i
t tries to send |
| 91 // a message from the dialog on this thread. AndroidOverlay might have
to notify us |
| 92 // separately to tell us when it's done with the thread, if we don't wan
t to wait until |
| 93 // then to start creating a new SV. |
| 94 // Instead, we just avoid shutting down the thread at all for now. |
| 95 } |
| 96 |
| 97 // Remember that we can't tell which client disconnected. |
32 @Override | 98 @Override |
33 public void close() {} | 99 public void close() {} |
34 | 100 |
| 101 // Remember that we can't tell which client disconnected. |
35 @Override | 102 @Override |
36 public void onConnectionError(MojoException e) {} | 103 public void onConnectionError(MojoException e) {} |
37 | 104 |
38 /** | 105 /** |
39 * Mojo factory. | 106 * Mojo factory. |
40 */ | 107 */ |
41 public static class Factory implements InterfaceFactory<AndroidOverlayProvid
er> { | 108 public static class Factory implements InterfaceFactory<AndroidOverlayProvid
er> { |
| 109 private static AndroidOverlayProviderImpl sImpl; |
42 public Factory(Context context) {} | 110 public Factory(Context context) {} |
43 | 111 |
44 @Override | 112 @Override |
45 public AndroidOverlayProvider createImpl() { | 113 public AndroidOverlayProvider createImpl() { |
46 return new AndroidOverlayProviderImpl(); | 114 if (sImpl == null) sImpl = new AndroidOverlayProviderImpl(); |
| 115 return sImpl; |
47 } | 116 } |
48 } | 117 } |
49 } | 118 } |
OLD | NEW |