| Index: media/base/android/java/src/org/chromium/media/DialogSurfaceManager.java
|
| diff --git a/media/base/android/java/src/org/chromium/media/DialogSurfaceManager.java b/media/base/android/java/src/org/chromium/media/DialogSurfaceManager.java
|
| new file mode 100644
|
| index 0000000000000000000000000000000000000000..d2c5067c861f80efd11f16e1a99c3c57d4faad4c
|
| --- /dev/null
|
| +++ b/media/base/android/java/src/org/chromium/media/DialogSurfaceManager.java
|
| @@ -0,0 +1,116 @@
|
| +// Copyright 2016 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.media;
|
| +
|
| +import android.os.Handler;
|
| +import android.os.HandlerThread;
|
| +import android.os.IBinder;
|
| +
|
| +import org.chromium.base.annotations.CalledByNative;
|
| +import org.chromium.base.annotations.JNINamespace;
|
| +
|
| +/**
|
| + * Singleton class to create and manage DialogSurface. Normally, you won't need
|
| + * to access this directly. Instead, see the native wrappers in
|
| + * dialog_surface_manager.cc for usage.
|
| + *
|
| + * The wrappers do roughly the following on the gpu side:
|
| + * - Create an IDialogSurfaceCallback. For native, DialogSurfaceCallback hides
|
| + * the threading issues and provides the java peer.
|
| + * - Get an IDialogSurfaceManager from the browser via ChildProcessCallback .
|
| + * - dialogSurface = IDialogSurfaceManager.createSurface(callback)
|
| + * This calls into the browser, and returns an IDialogSurface IBinder.
|
| + * - Wrap the DialogSurface in a DialogSurfaceWrapper. This provides the JNI
|
| + * bindings for native.
|
| + * - Expect callbacks on the callback to let you know when the underlying
|
| + * android surface state changes.
|
| + * - Use the surface.
|
| + * - Call IDialogSurface::release() to destroy the surface when done.
|
| + */
|
| +@JNINamespace("media")
|
| +public class DialogSurfaceManager extends IDialogSurfaceManager.Stub {
|
| + private static final String TAG = "cr_media";
|
| + private static DialogSurfaceManager sInstance;
|
| +
|
| + // We maintain a thread with a Looper for the DialogSurfaces to use,
|
| + // since Dialog requires one. We don't want this to be the native thread
|
| + // that's used to create them, because it probably also has a native message
|
| + // loop. Including a looper on it is not a good idea.
|
| + private HandlerThread mThread;
|
| + private Handler mHandler;
|
| + private IDialogSurfaceActivityMapper mMapper;
|
| +
|
| + // Number of DialogSurfaces that have been created but not released.
|
| + private int mNumSurfaces;
|
| +
|
| + // Maximum number of concurrent surfaces we allow.
|
| + private static final int sMaxSurfaces = 1;
|
| +
|
| + private DialogSurfaceManager(IDialogSurfaceActivityMapper mapper) {
|
| + mMapper = mapper;
|
| + mNumSurfaces = 0;
|
| + }
|
| +
|
| + public static IBinder instance(IDialogSurfaceActivityMapper mapper) {
|
| + if (sInstance == null) sInstance = new DialogSurfaceManager(mapper);
|
| +
|
| + return sInstance.asBinder();
|
| + }
|
| +
|
| + @Override
|
| + @CalledByNative
|
| + public IDialogSurface createSurface(int rendererPid, int renderFrameId,
|
| + IDialogSurfaceCallback callback, int x, int y, int width, int height) {
|
| + // Limit the number of concurrent surfaces.
|
| + if (mNumSurfaces >= sMaxSurfaces) return null;
|
| +
|
| + // TODO(liberato): would get the WindowToken / Activity here.
|
| +
|
| + startThreadIfNeeded();
|
| +
|
| + mNumSurfaces++;
|
| +
|
| + // TODO(liberato): would instantiate DialogSurface here.
|
| + return null;
|
| + }
|
| +
|
| + /**
|
| + * Called by DialogSurfaces when they no longer need the thread.
|
| + */
|
| + public void notifyReleased() {
|
| + if (mNumSurfaces > 0) mNumSurfaces--;
|
| +
|
| + // We don't stop the looper thread here, else android can get mad when
|
| + // it tries to send a message from the dialog on this thread.
|
| + // DialogSurface might have to notify us separately to tell us
|
| + // when it's done with the thread, if we don't want to wait until then
|
| + // to start creating a new SV.
|
| + // Instead, we just avoid shutting down the thread at all for now.
|
| + }
|
| +
|
| + /**
|
| + * Make sure that mThread and mHandler are ready for use. Do nothing if
|
| + * they already are.
|
| + */
|
| + private void startThreadIfNeeded() {
|
| + // Called on main thread only.
|
| + if (mThread != null) return;
|
| +
|
| + // Just to avoid "Unread field" in findbugs. Normally, we wills send
|
| + // mHandler to DialogSurface.
|
| + if (mHandler != null) return;
|
| +
|
| + mThread = new HandlerThread("DialogSurfaceThread");
|
| + mThread.start();
|
| + mHandler = new Handler(mThread.getLooper());
|
| + }
|
| +
|
| + /**
|
| + * Return the activity mapper.
|
| + */
|
| + public IDialogSurfaceActivityMapper getMapper() {
|
| + return mMapper;
|
| + }
|
| +}
|
|
|