Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(41)

Side by Side Diff: content/public/android/java/src/org/chromium/content/browser/androidoverlay/DialogOverlayImpl.java

Issue 2765443004: AndroidOverlay implementation using Dialog. (Closed)
Patch Set: rebased onto gpu_surface_tracker Created 3 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(Empty)
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
3 // found in the LICENSE file.
4
5 package org.chromium.content.browser.androidoverlay;
6
7 import android.app.Dialog;
8 import android.content.Context;
9 import android.os.IBinder;
10 import android.view.Surface;
11 import android.view.Window;
12
13 import org.chromium.base.ContextUtils;
14 import org.chromium.base.ThreadUtils;
15 import org.chromium.gfx.mojom.Rect;
16 import org.chromium.media.mojom.AndroidOverlay;
17 import org.chromium.media.mojom.AndroidOverlayClient;
18 import org.chromium.media.mojom.AndroidOverlayConfig;
19 import org.chromium.mojo.system.MojoException;
20
21 /**
22 * Default AndroidOverlay impl. Uses a separate (shared) overlay thread to own a Dialog instance,
23 * probably via a separate object that operates only on that thread. We will po st messages to /
24 * from that thread from the main thread.
25 */
26 public class DialogOverlayImpl implements AndroidOverlay, DialogOverlayCore.Host ,
27 DialogOverlayOperations.WindowTokenLis tener {
28 private static final String TAG = "DialogOverlayImpl";
29
30 private final DialogOverlayOperations mOps;
31 private final ThreadHoppingHost mHoppingHost;
32 private AndroidOverlayClient mClient;
33 private DialogOverlayCore mDialogCore;
34
35 // If nonzero, then we have registered a surface with this ID.
36 private int mSurfaceId;
37
38 /**
39 * @param client Mojo client interface.
40 * @param config initial overlay configuration.
41 * @param handler handler that posts to the overlay thread. This is the and roid UI thread that
42 * the dialog uses, not the browser UI thread.
43 * @param provider the overlay provider that owns us.
44 */
45 public DialogOverlayImpl(AndroidOverlayClient client, final AndroidOverlayCo nfig config,
46 DialogOverlayOperations ops) {
47 ThreadUtils.assertOnUiThread();
48
49 mClient = client;
50 mOps = ops;
51 mDialogCore = new DialogOverlayCore();
52 mHoppingHost = new ThreadHoppingHost(this);
53
54 // Post init to the overlay thread.
55 final DialogOverlayCore dialogCore = mDialogCore;
56 final Context context = ContextUtils.getApplicationContext();
57 mOps.getOverlayHandler().post(new Runnable() {
58 @Override
59 public void run() {
60 // Create the dialog, but don't lay it out or show it yet. |dia logCore| will do
61 // that when we get a window token.
62 Dialog dialog = new Dialog(context, android.R.style.Theme_NoDisp lay);
boliu 2017/04/22 00:22:43 do this stuff in dialogcore? seems odd this is her
liberato (no reviews please) 2017/04/24 22:19:41 it was originally to allow DialogOverlayCoreTest t
63 dialog.requestWindowFeature(Window.FEATURE_NO_TITLE);
64 dialog.setCancelable(false);
65 dialogCore.initialize(dialog, config, mHoppingHost);
66 }
67 });
68
69 // Register to get token updates.
70 mOps.registerWindowTokenListener(config.routingToken, this);
71 }
72
73 @Override
74 public void onSurfaceReady(Surface surface) {
75 ThreadUtils.assertOnUiThread();
76
77 if (mDialogCore == null || mClient == null) return;
78
79 mSurfaceId = mOps.registerSurface(surface);
80 mClient.onSurfaceReady(mSurfaceId);
81 }
82
83 @Override
84 public void onOverlayDestroyed() {
85 ThreadUtils.assertOnUiThread();
86
87 if (mDialogCore == null) return;
88
89 // Notify the client that the overlay is gone.
90 if (mClient != null) mClient.onDestroyed();
91
92 // Also clear out |mDialogCore| to prevent us from sending useless messa ges to it. Note
93 // that we might have already sent useless messages to it, and it should be robust against
94 // that sort of thing.
95 cleanup();
96
97 // Note that we don't notify |mOps| yet, though we could. We wait for t he client to close
98 // their connection first.
99 }
100
101 // Due to threading issues, |mHoppingHost| doesn't forward this.
102 @Override
103 public void waitForCleanup() {
104 assert false : "Not reached";
105 }
106
107 // Client is done with this overlay.
108 @Override
109 public void close() {
110 ThreadUtils.assertOnUiThread();
111
112 // TODO(liberato): verify that this actually works, else add an explicit shutdown and hope
113 // that the client calls it.
114
115 // Allow surfaceDestroyed to proceed, if it's waiting.
116 mHoppingHost.onCleanup();
117
118 // Notify |mDialogCore| that it has been released. This might not be ca lled if it notifies
119 // us that it's been destroyed. We still might send it in that case if the client closes
120 // the connection before we find out that it's been destroyed on the ove rlay thread.
121 if (mDialogCore != null) {
122 final DialogOverlayCore dialogCore = mDialogCore;
123 mOps.getOverlayHandler().post(new Runnable() {
124 @Override
125 public void run() {
126 dialogCore.release();
127 }
128 });
129
130 // Note that we might get messagaes from |mDialogCore| after this, s ince they might be
131 // dispatched before |r| arrives. Clearing |mDialogCore| causes us to ignore them.
132 cleanup();
133 }
134
135 // Notify the provider that we've been released by the client. Note tha t the surface might
136 // not have been destroyed yet, but that's okay. We could wait for a ca llback from the
137 // dialog core before proceeding, but this makes it easier for the clien t to destroy and
138 // re-create an overlay without worrying about an intermittent failure d ue to having too
139 // many overlays open at once.
140 mOps.notifyReleased();
141 }
142
143 private void sendWindowTokenToCore(final IBinder token) {
144 ThreadUtils.assertOnUiThread();
145
146 final DialogOverlayCore dialogCore = mDialogCore;
147 mOps.getOverlayHandler().post(new Runnable() {
148 @Override
149 public void run() {
150 dialogCore.onWindowToken(token);
151 }
152 });
153 }
154
155 @Override
156 public void onWindowToken(final IBinder token) {
boliu 2017/04/22 00:22:43 this class is implementing three interfaces, and i
liberato (no reviews please) 2017/04/24 22:19:42 i've merged Ops, so WindowTokenListener is gone no
157 ThreadUtils.assertOnUiThread();
158
159 if (mDialogCore == null) return;
160
161 // Forward this change.
162 // Note that if we don't have a window token, then we could wait until w e do, simply by
163 // skipping sending null if we haven't sent any non-null token yet. If we're transitioning
164 // between windows, that might make the client's job easier. It wouldn't have to guess when
165 // a new token is available.
166 sendWindowTokenToCore(token);
167 }
168
169 @Override
170 public void onDismissed() {
171 ThreadUtils.assertOnUiThread();
172
173 // Notify the client that the overlay is going away.
174 if (mClient != null) mClient.onDestroyed();
175
176 // Notify |mDialogCore| that it lost the token, if it had one.
177 sendWindowTokenToCore(null);
178
179 cleanup();
180 }
181
182 @Override
183 public void onConnectionError(MojoException e) {
184 ThreadUtils.assertOnUiThread();
185
186 close();
187 }
188
189 @Override
190 public void scheduleLayout(final Rect rect) {
191 ThreadUtils.assertOnUiThread();
192
193 if (mDialogCore == null) return;
194
195 final DialogOverlayCore dialogCore = mDialogCore;
196 mOps.getOverlayHandler().post(new Runnable() {
197 @Override
198 public void run() {
199 dialogCore.layoutSurface(rect);
200 }
201 });
202 }
203
204 /**
205 * Unregister for callbacks, unregister any surface that we have, and forget about
206 * |mDialogCore|. Multiple calls are okay.
207 */
208 private void cleanup() {
209 ThreadUtils.assertOnUiThread();
210
211 if (mSurfaceId != 0) {
212 mOps.unregisterSurface(mSurfaceId);
213 mSurfaceId = 0;
214 }
215
216 // Note that we might not be registered for a token.
217 mOps.unregisterWindowTokenListenerIfNeeded();
218
219 // Also clear out |mDialogCore| to prevent us from sending useless messa ges to it. Note
220 // that we might have already sent useless messages to it, and it should be robust against
221 // that sort of thing.
222 mDialogCore = null;
223
224 // If we wanted to send any message to |mClient|, we should have done so already.
225 mClient = null;
226 }
227 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698