| Index: media/base/android/dialog_surface_callback.cc
|
| diff --git a/media/base/android/dialog_surface_callback.cc b/media/base/android/dialog_surface_callback.cc
|
| new file mode 100644
|
| index 0000000000000000000000000000000000000000..691c62717a1a35b4f042115ac6b2a5dc44972a57
|
| --- /dev/null
|
| +++ b/media/base/android/dialog_surface_callback.cc
|
| @@ -0,0 +1,165 @@
|
| +// 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.
|
| +
|
| +#include "media/base/android/dialog_surface_callback.h"
|
| +
|
| +#include <algorithm>
|
| +#include <limits>
|
| +#include <map>
|
| +#include <memory>
|
| +#include <utility>
|
| +
|
| +#include "base/android/build_info.h"
|
| +#include "base/android/jni_android.h"
|
| +#include "base/android/jni_array.h"
|
| +#include "base/android/jni_string.h"
|
| +#include "base/bind.h"
|
| +#include "base/lazy_instance.h"
|
| +#include "base/location.h"
|
| +#include "base/logging.h"
|
| +#include "base/numerics/safe_conversions.h"
|
| +#include "base/strings/string_util.h"
|
| +#include "base/synchronization/lock.h"
|
| +#include "base/synchronization/waitable_event.h"
|
| +#include "base/threading/thread_task_runner_handle.h"
|
| +#include "jni/DialogSurfaceCallback_jni.h"
|
| +
|
| +using base::android::AttachCurrentThread;
|
| +
|
| +namespace media {
|
| +
|
| +static long next_id_ = 1;
|
| +
|
| +// Map of ids to DialogSurfaceCallbacks. This is called from multiple threads.
|
| +class DialogCallbackMap {
|
| + public:
|
| + // Associate |thiz| with |id|.
|
| + void Insert(long id, DialogSurfaceCallback* thiz) {
|
| + base::AutoLock _l(lock_);
|
| + map_[id] = thiz;
|
| + }
|
| +
|
| + // Forget about |id|.
|
| + void Erase(long id) {
|
| + base::AutoLock _l(lock_);
|
| + map_.erase(id);
|
| + }
|
| +
|
| + // Return the associated callback for |id|, or null.
|
| + DialogSurfaceCallback* Lookup(long id) {
|
| + base::AutoLock _l(lock_);
|
| + return LookupLocked(id);
|
| + }
|
| +
|
| + // Map |id| to the correct task runner for callbacks, or null.
|
| + scoped_refptr<base::SingleThreadTaskRunner> GetTaskRunner(long id) {
|
| + scoped_refptr<base::SingleThreadTaskRunner> task_runner;
|
| + base::AutoLock _l(lock_);
|
| + DialogSurfaceCallback* thiz = LookupLocked(id);
|
| + // While under lock, |thiz| cannot be removed from the map.
|
| + if (thiz)
|
| + task_runner = thiz->GetTaskRunner();
|
| +
|
| + return task_runner;
|
| + }
|
| +
|
| + private:
|
| + // Lookup |id|. The caller must hold |lock_|.
|
| + DialogSurfaceCallback* LookupLocked(long id) {
|
| + DialogSurfaceCallback* thiz = nullptr;
|
| + Map::const_iterator it = map_.find(id);
|
| + if (it != map_.end())
|
| + thiz = it->second;
|
| +
|
| + return thiz;
|
| + }
|
| +
|
| + // Alternatively, we could put in a callback that is bound to the correct
|
| + // thread, and use a weak ref. However, since we still need a default
|
| + // action when the weak ref is cleared to unblock the callback, it ends up
|
| + // not being any simpler.
|
| + using Map = std::map<long, DialogSurfaceCallback*>;
|
| + Map map_;
|
| +
|
| + base::Lock lock_;
|
| +};
|
| +
|
| +static base::LazyInstance<DialogCallbackMap>::Leaky g_map =
|
| + LAZY_INSTANCE_INITIALIZER;
|
| +
|
| +DialogSurfaceCallback::DialogSurfaceCallback(
|
| + const DialogSurfaceHolder::Callback& callback)
|
| + : task_runner_(base::ThreadTaskRunnerHandle::Get()),
|
| + id_(next_id_++),
|
| + callback_(callback) {
|
| + JNIEnv* env = AttachCurrentThread();
|
| + CHECK(env);
|
| + j_surface_callback_.Reset(Java_DialogSurfaceCallback_create(env, id_));
|
| + g_map.Pointer()->Insert(id_, this);
|
| +}
|
| +
|
| +DialogSurfaceCallback::~DialogSurfaceCallback() {
|
| + DCHECK(thread_checker_.CalledOnValidThread());
|
| + g_map.Pointer()->Erase(id_);
|
| +}
|
| +
|
| +bool DialogSurfaceCallback::RegisterDialogSurfaceCallback(JNIEnv* env) {
|
| + return RegisterNativesImpl(env);
|
| +}
|
| +
|
| +scoped_refptr<base::SingleThreadTaskRunner>
|
| +DialogSurfaceCallback::GetTaskRunner() const {
|
| + // May be called on any thread.
|
| + return task_runner_;
|
| +}
|
| +
|
| +bool DialogSurfaceCallback::CalledOnValidThread() const {
|
| + return thread_checker_.CalledOnValidThread();
|
| +}
|
| +
|
| +void DialogSurfaceCallback::OnCallbackProperThread(
|
| + long id,
|
| + DialogSurfaceHolder::CallbackOp what,
|
| + base::WaitableEvent* event) {
|
| + // A callback has happened on some other thread. We're run on the correct
|
| + // thread in response to it.
|
| + DialogSurfaceCallback* thiz = g_map.Pointer()->Lookup(id);
|
| + // |thiz| cannot be deleted here, since we're on the main thread. However,
|
| + // it might have been deleted earlier, so it can be null.
|
| +
|
| + if (thiz) {
|
| + DCHECK(thiz->CalledOnValidThread());
|
| + thiz->callback_.Run(what);
|
| + }
|
| +
|
| + // If this is a synchronous callback, then signal that we've completed.
|
| + if (event)
|
| + event->Signal();
|
| +}
|
| +
|
| +void OnDialogSurfaceCallbackCallback(JNIEnv* env,
|
| + const JavaParamRef<jclass>& jcaller,
|
| + jlong id,
|
| + jint what) {
|
| + // Post back to the main thread. We get a strong ref here to the task
|
| + // runner, so that it's okay if the controller is deleted. Holding the
|
| + // lock during the callback is not safe; the caller might require it to
|
| + // complete the callback.
|
| + scoped_refptr<base::SingleThreadTaskRunner> task_runner =
|
| + g_map.Pointer()->GetTaskRunner(id);
|
| +
|
| + if (task_runner) {
|
| + // TODO(liberato): check the thread, and just call if needed. That way,
|
| + // we'll work regardless of how the java classes handle threading.
|
| + base::WaitableEvent event(base::WaitableEvent::ResetPolicy::AUTOMATIC,
|
| + base::WaitableEvent::InitialState::NOT_SIGNALED);
|
| + base::Closure cb =
|
| + base::Bind(&DialogSurfaceCallback::OnCallbackProperThread, id,
|
| + static_cast<DialogSurfaceHolder::CallbackOp>(what), &event);
|
| + task_runner->PostTask(FROM_HERE, cb);
|
| + event.Wait();
|
| + }
|
| +}
|
| +
|
| +} // namespace media
|
|
|