| Index: content/public/android/java/src/org/chromium/content/browser/androidoverlay/DialogAndroidOverlay.java
|
| diff --git a/content/public/android/java/src/org/chromium/content/browser/androidoverlay/DialogAndroidOverlay.java b/content/public/android/java/src/org/chromium/content/browser/androidoverlay/DialogAndroidOverlay.java
|
| new file mode 100644
|
| index 0000000000000000000000000000000000000000..76a91aeb8fbe0f0013a36873a9f2cf2507a7b307
|
| --- /dev/null
|
| +++ b/content/public/android/java/src/org/chromium/content/browser/androidoverlay/DialogAndroidOverlay.java
|
| @@ -0,0 +1,177 @@
|
| +// Copyright 2017 The Chromium Authors. All rights reserved.
|
| +// Use of this source code is governed by a BSD-style license that can be
|
| +// found in the LICENSE file.
|
| +
|
| +package org.chromium.content.browser.androidoverlay;
|
| +
|
| +import android.content.Context;
|
| +import android.os.Handler;
|
| +import android.os.IBinder;
|
| +
|
| +import org.chromium.base.annotations.CalledByNative;
|
| +import org.chromium.base.annotations.JNINamespace;
|
| +import org.chromium.media.IAndroidOverlay;
|
| +import org.chromium.media.IAndroidOverlayCallback;
|
| +
|
| +/**
|
| + * Provide access to Dialog-based Surfaces. It is unlikely that you want to
|
| + * use this class directly. Instead, use the native wrappers for it in
|
| + * dialog_surface_holder.h . If you must use these from Java, then it's likely
|
| + * that you should be using IAndroidOverlay instead.
|
| + *
|
| + * This class is thread-safe, since it gets calls from random binder threads and
|
| + * callbacks on the UI thread. It interacts with DialogAndroidOverlayCore to do the
|
| + * actual work of managing the AndroidOverlay. It also hides all the threading
|
| + * by posting messages to a single thread for DialogAndroidOverlayCore.
|
| + */
|
| +@JNINamespace("content")
|
| +class DialogAndroidOverlay extends IAndroidOverlay.Stub {
|
| + private static final String TAG = "DSImpl";
|
| +
|
| + private final Handler mHandler;
|
| +
|
| + private long mNativeHandle;
|
| +
|
| + // Note that we never do any work in response to a binder call with mLock
|
| + // held. We always post elsewhere, which prevents reentrant calls from
|
| + // the client from deadlocking on mLock.
|
| + private final Object mLock = new Object();
|
| + private AndroidOverlayProviderImpl mOwner;
|
| + private DialogAndroidOverlayCore mDialogCore;
|
| +
|
| + /**
|
| + * Called from a random thread.
|
| + * Note that (pid, frameId) might be replaced by a token.
|
| + * @param rendererPid pid of owning renderer process
|
| + * @param renderFrameId render frame ID owned by Pid
|
| + * @param context Context that we use.
|
| + * @param owner Owning manager that we'll notify on release().
|
| + * @param handler handler for a thread with a looper.
|
| + * @param callback callback object to notify about state changes.
|
| + * @param x initial x position in chrome compositor (not screen) coords.
|
| + * @param y initial y position in chrome compositor (not screen) coords.
|
| + * @param width initial width.
|
| + * @param height initial height.
|
| + */
|
| + public DialogAndroidOverlay(int rendererPid, int renderFrameId, final Context context,
|
| + AndroidOverlayProviderImpl owner, Handler handler,
|
| + final IAndroidOverlayCallback callback, final int x, final int y, final int width,
|
| + final int height) {
|
| + mOwner = owner;
|
| + mHandler = handler;
|
| +
|
| + mDialogCore = new DialogAndroidOverlayCore();
|
| +
|
| + // Runnable that |mDialogCore| will use to notify us that it has shut down. This is useful
|
| + // so that we know if it shuts down by itself, generally due to loss of the surface.
|
| + final Runnable releaseCallback = new Runnable() {
|
| + @Override
|
| + public void run() {
|
| + release();
|
| + }
|
| + };
|
| +
|
| + // Post init to the proper thread.
|
| + final DialogAndroidOverlayCore dialogCore = mDialogCore;
|
| + Runnable r = new Runnable() {
|
| + @Override
|
| + public void run() {
|
| + dialogCore.initialize(context, callback, x, y, width, height, releaseCallback);
|
| + }
|
| + };
|
| + mHandler.post(r);
|
| +
|
| + // Register to get token updates.
|
| + mNativeHandle = nativeInit(rendererPid, renderFrameId);
|
| + }
|
| +
|
| + /**
|
| + * Release the underlying surface, and generally clean up, in response to
|
| + * the client releasing the IAndroidOverlay.
|
| + */
|
| + @Override
|
| + public void release() {
|
| + synchronized (mLock) {
|
| + // If we've already been released, then do nothing. Remember that |mDialogCore| will
|
| + // call the release callback in response to us asking it to shut down. |mDialogCore|
|
| + // will be null in those cases. We only process the callback if it notifies us before
|
| + // we've asked it to shut down, e.g., if it loses the surface.
|
| + if (mDialogCore == null) return;
|
| +
|
| + // Unregister for token callbacks.
|
| + if (mNativeHandle != 0) {
|
| + nativeShutdown(mNativeHandle);
|
| + mNativeHandle = 0;
|
| + }
|
| +
|
| + // Post a release on the proper thread to |mDialogCore|. Note that it will call us back
|
| + // when it gets the message, which is fine.
|
| + final DialogAndroidOverlayCore dialogCore = mDialogCore;
|
| + Runnable r = new Runnable() {
|
| + @Override
|
| + public void run() {
|
| + dialogCore.release();
|
| + }
|
| + };
|
| + mHandler.post(r);
|
| +
|
| + // Notify our owner. We don't bother to wait until the post completes, since it'll get
|
| + // cleaned up shortly anyway.
|
| + mOwner.notifyReleased();
|
| + mOwner = null;
|
| +
|
| + mDialogCore = null;
|
| + }
|
| + }
|
| +
|
| + @Override
|
| + public void scheduleLayoutSurface(final int x, final int y, final int width, final int height) {
|
| + // Random thread.
|
| + synchronized (mLock) {
|
| + if (mDialogCore == null) return;
|
| +
|
| + final DialogAndroidOverlayCore dialogCore = mDialogCore;
|
| + Runnable r = new Runnable() {
|
| + @Override
|
| + public void run() {
|
| + dialogCore.layoutSurface(x, y, width, height);
|
| + }
|
| + };
|
| +
|
| + mHandler.post(r);
|
| + }
|
| + }
|
| +
|
| + @CalledByNative
|
| + public void onWindowToken(final IBinder token) {
|
| + synchronized (mLock) {
|
| + // Forward this change.
|
| + // Note that if we don't have a window token, then we could wait
|
| + // until we do, simply by skipping sending null if we haven't sent
|
| + // any non-null token yet. If we're transitioning between windows,
|
| + // that might make the client's job easier, since it wouldn't have
|
| + // to guess when a new token is available.
|
| + final DialogAndroidOverlayCore dialogCore = mDialogCore;
|
| + Runnable r = new Runnable() {
|
| + @Override
|
| + public void run() {
|
| + dialogCore.onWindowToken(token);
|
| + }
|
| + };
|
| +
|
| + mHandler.post(r);
|
| + }
|
| + }
|
| +
|
| + // We're not getting any more window tokens.
|
| + @CalledByNative
|
| + public void onDismissed() {
|
| + release();
|
| + }
|
| +
|
| + // Initializes native side. Will register for onWindowToken callbacks.
|
| + native long nativeInit(int rendererPid, int renderFrameId);
|
| +
|
| + // Stops native side.
|
| + native void nativeShutdown(long handle);
|
| +}
|
|
|