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

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: fixed test Created 3 years, 7 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.content.Context;
8 import android.os.Handler;
9 import android.os.IBinder;
10 import android.view.Surface;
11
12 import org.chromium.base.ContextUtils;
13 import org.chromium.base.ThreadUtils;
14 import org.chromium.base.annotations.CalledByNative;
15 import org.chromium.base.annotations.JNINamespace;
16 import org.chromium.gfx.mojom.Rect;
17 import org.chromium.media.mojom.AndroidOverlay;
18 import org.chromium.media.mojom.AndroidOverlayClient;
19 import org.chromium.media.mojom.AndroidOverlayConfig;
20 import org.chromium.mojo.system.MojoException;
21
22 /**
23 * Default AndroidOverlay impl. Uses a separate (shared) overlay thread to own a Dialog instance,
24 * probably via a separate object that operates only on that thread. We will po st messages to /
25 * from that thread from the UI thread.
26 */
27 @JNINamespace("content")
28 public class DialogOverlayImpl implements AndroidOverlay, DialogOverlayCore.Host {
29 private static final String TAG = "DialogOverlayImpl";
30
31 private AndroidOverlayClient mClient;
32 private Handler mOverlayHandler;
33 // Runnable that we'll run when the overlay notifies us that it's been relea sed.
34 private Runnable mReleasedRunnable;
35
36 private final ThreadHoppingHost mHoppingHost;
37
38 private DialogOverlayCore mDialogCore;
39
40 private long mNativeHandle;
41
42 // If nonzero, then we have registered a surface with this ID.
43 private int mSurfaceId;
44
45 /**
46 * @param client Mojo client interface.
47 * @param config initial overlay configuration.
48 * @param handler handler that posts to the overlay thread. This is the and roid UI thread that
49 * the dialog uses, not the browser UI thread.
50 * @param provider the overlay provider that owns us.
51 */
52 public DialogOverlayImpl(AndroidOverlayClient client, final AndroidOverlayCo nfig config,
53 Handler overlayHandler, Runnable releasedRunnable) {
54 ThreadUtils.assertOnUiThread();
55
56 mClient = client;
57 mReleasedRunnable = releasedRunnable;
58 mOverlayHandler = overlayHandler;
59
60 mDialogCore = new DialogOverlayCore();
61 mHoppingHost = new ThreadHoppingHost(this);
62
63 // Post init to the overlay thread.
64 final DialogOverlayCore dialogCore = mDialogCore;
65 final Context context = ContextUtils.getApplicationContext();
66 mOverlayHandler.post(new Runnable() {
67 @Override
68 public void run() {
69 dialogCore.initialize(context, config, mHoppingHost);
70 }
71 });
72
73 // Register to get token updates.
74 mNativeHandle = nativeInit(config.routingToken.high, config.routingToken .low);
75 assert mNativeHandle != 0;
76 }
77
78 // AndroidOverlay impl.
79 // Client is done with this overlay.
80 @Override
81 public void close() {
82 ThreadUtils.assertOnUiThread();
83
84 // TODO(liberato): verify that this actually works, else add an explicit shutdown and hope
85 // that the client calls it.
86
87 // Allow surfaceDestroyed to proceed, if it's waiting.
88 mHoppingHost.onCleanup();
89
90 // Notify |mDialogCore| that it has been released. This might not be ca lled if it notifies
91 // us that it's been destroyed. We still might send it in that case if the client closes
92 // the connection before we find out that it's been destroyed on the ove rlay thread.
93 if (mDialogCore != null) {
94 final DialogOverlayCore dialogCore = mDialogCore;
95 mOverlayHandler.post(new Runnable() {
96 @Override
97 public void run() {
98 dialogCore.release();
99 }
100 });
101
102 // Note that we might get messagaes from |mDialogCore| after this, s ince they might be
103 // dispatched before |r| arrives. Clearing |mDialogCore| causes us to ignore them.
104 cleanup();
105 }
106
107 // Notify the provider that we've been released by the client. Note tha t the surface might
108 // not have been destroyed yet, but that's okay. We could wait for a ca llback from the
109 // dialog core before proceeding, but this makes it easier for the clien t to destroy and
110 // re-create an overlay without worrying about an intermittent failure d ue to having too
111 // many overlays open at once.
112 mReleasedRunnable.run();
113 }
114
115 // AndroidOverlay impl.
116 @Override
117 public void onConnectionError(MojoException e) {
118 ThreadUtils.assertOnUiThread();
119
120 close();
121 }
122
123 // AndroidOverlay impl.
124 @Override
125 public void scheduleLayout(final Rect rect) {
126 ThreadUtils.assertOnUiThread();
127
128 if (mDialogCore == null) return;
129
130 final DialogOverlayCore dialogCore = mDialogCore;
131 mOverlayHandler.post(new Runnable() {
132 @Override
133 public void run() {
134 dialogCore.layoutSurface(rect);
135 }
136 });
137 }
138
139 // DialogOverlayCore.Host impl.
140 // |surface| is now ready. Register it with the surface tracker, and notify the client.
141 @Override
142 public void onSurfaceReady(Surface surface) {
143 ThreadUtils.assertOnUiThread();
144
145 if (mDialogCore == null || mClient == null) return;
146
147 mSurfaceId = nativeRegisterSurface(surface);
148 mClient.onSurfaceReady(mSurfaceId);
149 }
150
151 // DialogOverlayCore.Host impl.
152 @Override
153 public void onOverlayDestroyed() {
154 ThreadUtils.assertOnUiThread();
155
156 if (mDialogCore == null) return;
157
158 // Notify the client that the overlay is gone.
159 if (mClient != null) mClient.onDestroyed();
160
161 // Also clear out |mDialogCore| to prevent us from sending useless messa ges to it. Note
162 // that we might have already sent useless messages to it, and it should be robust against
163 // that sort of thing.
164 cleanup();
165
166 // Note that we don't notify |mReleasedRunnable| yet, though we could. We wait for the
167 // client to close their connection first.
168 }
169
170 // DialogOverlayCore.Host impl.
171 // Due to threading issues, |mHoppingHost| doesn't forward this.
172 @Override
173 public void waitForCleanup() {
174 assert false : "Not reached";
175 }
176
177 /**
178 * Send |token| to the |mDialogCore| on the overlay thread.
179 */
180 private void sendWindowTokenToCore(final IBinder token) {
181 ThreadUtils.assertOnUiThread();
182
183 final DialogOverlayCore dialogCore = mDialogCore;
184 mOverlayHandler.post(new Runnable() {
185 @Override
186 public void run() {
187 dialogCore.onWindowToken(token);
188 }
189 });
190 }
191
192 /**
193 * Callback from native that the window token has changed.
194 */
195 @CalledByNative
196 public void onWindowToken(final IBinder token) {
197 ThreadUtils.assertOnUiThread();
198
199 if (mDialogCore == null) return;
200
201 // Forward this change.
202 // Note that if we don't have a window token, then we could wait until w e do, simply by
203 // skipping sending null if we haven't sent any non-null token yet. If we're transitioning
204 // between windows, that might make the client's job easier. It wouldn't have to guess when
205 // a new token is available.
206 sendWindowTokenToCore(token);
207 }
208
209 /**
210 * Callback from native that we will be getting no additional tokens.
211 */
212 @CalledByNative
213 public void onDismissed() {
214 ThreadUtils.assertOnUiThread();
215
216 // Notify the client that the overlay is going away.
217 if (mClient != null) mClient.onDestroyed();
218
219 // Notify |mDialogCore| that it lost the token, if it had one.
220 sendWindowTokenToCore(null);
221
222 cleanup();
223 }
224
225 /**
226 * Unregister for callbacks, unregister any surface that we have, and forget about
227 * |mDialogCore|. Multiple calls are okay.
228 */
229 private void cleanup() {
230 ThreadUtils.assertOnUiThread();
231
232 if (mSurfaceId != 0) {
233 nativeUnregisterSurface(mSurfaceId);
234 mSurfaceId = 0;
235 }
236
237 // Note that we might not be registered for a token.
238 if (mNativeHandle != 0) {
239 nativeDestroy(mNativeHandle);
240 mNativeHandle = 0;
241 }
242
243 // Also clear out |mDialogCore| to prevent us from sending useless messa ges to it. Note
244 // that we might have already sent useless messages to it, and it should be robust against
245 // that sort of thing.
246 mDialogCore = null;
247
248 // If we wanted to send any message to |mClient|, we should have done so already.
249 mClient = null;
250 }
251
252 /**
253 * Initializes native side. Will register for onWindowToken callbacks on |t his|. Returns a
254 * handle that should be provided to nativeDestroy.
255 */
256 private native long nativeInit(long high, long low);
257
258 /**
259 * Stops native side and deallocates |handle|.
260 */
261 private native void nativeDestroy(long nativeDialogOverlayImpl);
262
263 /**
264 * Register a surface and return the surface id for it.
265 * @param surface Surface that we should register.
266 * @return surface id that we associated with |surface|.
267 */
268 private static native int nativeRegisterSurface(Surface surface);
269
270 /**
271 * Unregister a surface.
272 * @param surfaceId Id that was returned by registerSurface.
273 */
274 private static native void nativeUnregisterSurface(int surfaceId);
275 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698