OLD | NEW |
(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 } |
OLD | NEW |