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 |
| 11 import org.chromium.base.annotations.CalledByNative; |
| 12 import org.chromium.base.annotations.JNINamespace; |
| 13 import org.chromium.media.IAndroidOverlay; |
| 14 import org.chromium.media.IAndroidOverlayCallback; |
| 15 |
| 16 /** |
| 17 * Provide access to Dialog-based Surfaces. It is unlikely that you want to |
| 18 * use this class directly. Instead, use the native wrappers for it in |
| 19 * dialog_surface_holder.h . If you must use these from Java, then it's likely |
| 20 * that you should be using IAndroidOverlay instead. |
| 21 * |
| 22 * This class is thread-safe, since it gets calls from random binder threads and |
| 23 * callbacks on the UI thread. It interacts with DialogAndroidOverlayCore to do
the |
| 24 * actual work of managing the AndroidOverlay. It also hides all the threading |
| 25 * by posting messages to a single thread for DialogAndroidOverlayCore. |
| 26 */ |
| 27 @JNINamespace("content") |
| 28 class DialogAndroidOverlay extends IAndroidOverlay.Stub { |
| 29 private static final String TAG = "DSImpl"; |
| 30 |
| 31 private final Handler mHandler; |
| 32 |
| 33 private long mNativeHandle; |
| 34 |
| 35 // Note that we never do any work in response to a binder call with mLock |
| 36 // held. We always post elsewhere, which prevents reentrant calls from |
| 37 // the client from deadlocking on mLock. |
| 38 private final Object mLock = new Object(); |
| 39 private AndroidOverlayProviderImpl mOwner; |
| 40 private DialogAndroidOverlayCore mDialogCore; |
| 41 |
| 42 /** |
| 43 * Called from a random thread. |
| 44 * Note that (pid, frameId) might be replaced by a token. |
| 45 * @param rendererPid pid of owning renderer process |
| 46 * @param renderFrameId render frame ID owned by Pid |
| 47 * @param context Context that we use. |
| 48 * @param owner Owning manager that we'll notify on release(). |
| 49 * @param handler handler for a thread with a looper. |
| 50 * @param callback callback object to notify about state changes. |
| 51 * @param x initial x position in chrome compositor (not screen) coords. |
| 52 * @param y initial y position in chrome compositor (not screen) coords. |
| 53 * @param width initial width. |
| 54 * @param height initial height. |
| 55 */ |
| 56 public DialogAndroidOverlay(int rendererPid, int renderFrameId, final Contex
t context, |
| 57 AndroidOverlayProviderImpl owner, Handler handler, |
| 58 final IAndroidOverlayCallback callback, final int x, final int y, fi
nal int width, |
| 59 final int height) { |
| 60 mOwner = owner; |
| 61 mHandler = handler; |
| 62 |
| 63 mDialogCore = new DialogAndroidOverlayCore(); |
| 64 |
| 65 // Runnable that |mDialogCore| will use to notify us that it has shut do
wn. This is useful |
| 66 // so that we know if it shuts down by itself, generally due to loss of
the surface. |
| 67 final Runnable releaseCallback = new Runnable() { |
| 68 @Override |
| 69 public void run() { |
| 70 release(); |
| 71 } |
| 72 }; |
| 73 |
| 74 // Post init to the proper thread. |
| 75 final DialogAndroidOverlayCore dialogCore = mDialogCore; |
| 76 Runnable r = new Runnable() { |
| 77 @Override |
| 78 public void run() { |
| 79 dialogCore.initialize(context, callback, x, y, width, height, re
leaseCallback); |
| 80 } |
| 81 }; |
| 82 mHandler.post(r); |
| 83 |
| 84 // Register to get token updates. |
| 85 mNativeHandle = nativeInit(rendererPid, renderFrameId); |
| 86 } |
| 87 |
| 88 /** |
| 89 * Release the underlying surface, and generally clean up, in response to |
| 90 * the client releasing the IAndroidOverlay. |
| 91 */ |
| 92 @Override |
| 93 public void release() { |
| 94 synchronized (mLock) { |
| 95 // If we've already been released, then do nothing. Remember that |
mDialogCore| will |
| 96 // call the release callback in response to us asking it to shut dow
n. |mDialogCore| |
| 97 // will be null in those cases. We only process the callback if it
notifies us before |
| 98 // we've asked it to shut down, e.g., if it loses the surface. |
| 99 if (mDialogCore == null) return; |
| 100 |
| 101 // Unregister for token callbacks. |
| 102 if (mNativeHandle != 0) { |
| 103 nativeShutdown(mNativeHandle); |
| 104 mNativeHandle = 0; |
| 105 } |
| 106 |
| 107 // Post a release on the proper thread to |mDialogCore|. Note that
it will call us back |
| 108 // when it gets the message, which is fine. |
| 109 final DialogAndroidOverlayCore dialogCore = mDialogCore; |
| 110 Runnable r = new Runnable() { |
| 111 @Override |
| 112 public void run() { |
| 113 dialogCore.release(); |
| 114 } |
| 115 }; |
| 116 mHandler.post(r); |
| 117 |
| 118 // Notify our owner. We don't bother to wait until the post complet
es, since it'll get |
| 119 // cleaned up shortly anyway. |
| 120 mOwner.notifyReleased(); |
| 121 mOwner = null; |
| 122 |
| 123 mDialogCore = null; |
| 124 } |
| 125 } |
| 126 |
| 127 @Override |
| 128 public void scheduleLayoutSurface(final int x, final int y, final int width,
final int height) { |
| 129 // Random thread. |
| 130 synchronized (mLock) { |
| 131 if (mDialogCore == null) return; |
| 132 |
| 133 final DialogAndroidOverlayCore dialogCore = mDialogCore; |
| 134 Runnable r = new Runnable() { |
| 135 @Override |
| 136 public void run() { |
| 137 dialogCore.layoutSurface(x, y, width, height); |
| 138 } |
| 139 }; |
| 140 |
| 141 mHandler.post(r); |
| 142 } |
| 143 } |
| 144 |
| 145 @CalledByNative |
| 146 public void onWindowToken(final IBinder token) { |
| 147 synchronized (mLock) { |
| 148 // Forward this change. |
| 149 // Note that if we don't have a window token, then we could wait |
| 150 // until we do, simply by skipping sending null if we haven't sent |
| 151 // any non-null token yet. If we're transitioning between windows, |
| 152 // that might make the client's job easier, since it wouldn't have |
| 153 // to guess when a new token is available. |
| 154 final DialogAndroidOverlayCore dialogCore = mDialogCore; |
| 155 Runnable r = new Runnable() { |
| 156 @Override |
| 157 public void run() { |
| 158 dialogCore.onWindowToken(token); |
| 159 } |
| 160 }; |
| 161 |
| 162 mHandler.post(r); |
| 163 } |
| 164 } |
| 165 |
| 166 // We're not getting any more window tokens. |
| 167 @CalledByNative |
| 168 public void onDismissed() { |
| 169 release(); |
| 170 } |
| 171 |
| 172 // Initializes native side. Will register for onWindowToken callbacks. |
| 173 native long nativeInit(int rendererPid, int renderFrameId); |
| 174 |
| 175 // Stops native side. |
| 176 native void nativeShutdown(long handle); |
| 177 } |
OLD | NEW |