Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(735)

Unified Diff: media/base/android/android_overlay_callback.cc

Issue 2178973004: DialogSurfaceManager implementation. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: cleanup Created 3 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: media/base/android/android_overlay_callback.cc
diff --git a/media/base/android/android_overlay_callback.cc b/media/base/android/android_overlay_callback.cc
new file mode 100644
index 0000000000000000000000000000000000000000..acccbe94cb4fb38f22997a9c4fd4c1f8644a39dc
--- /dev/null
+++ b/media/base/android/android_overlay_callback.cc
@@ -0,0 +1,183 @@
+// 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/android_overlay_callback.h"
+
+#include <map>
+
+#include "base/android/jni_android.h"
+#include "base/bind.h"
+#include "base/location.h"
+#include "base/synchronization/lock.h"
+#include "base/synchronization/waitable_event.h"
+#include "base/threading/thread_task_runner_handle.h"
+#include "jni/AndroidOverlayCallback_jni.h"
+
+using base::android::AttachCurrentThread;
+
+namespace media {
+
+static long next_id_ = 1;
+
+scoped_refptr<base::SingleThreadTaskRunner>
+ AndroidOverlayCallback::task_runner_;
+
+// Map of ids to AndroidOverlayCallbacks. This is called from multiple threads.
+class AndroidOverlayCallbackmap {
+ public:
+ // Associate |thiz| with |id| from any thread.
+ void Insert(long id, AndroidOverlayCallback* thiz) {
+ base::AutoLock _l(lock_);
+ DCHECK(map_.find(id) == map_.end());
+ map_[id] = thiz;
+ }
+
+ // Forget about |id| from any thread. It's okay if it's not present.
+ // if it's not present.
+ void Erase(long id) {
+ base::AutoLock _l(lock_);
+ map_.erase(id);
+ }
+
+ // Return the associated callback for |id|, or null, from any thread.
+ AndroidOverlayCallback* Lookup(long id) {
+ base::AutoLock _l(lock_);
+ return LookupLocked(id);
+ }
+
+ private:
+ // Lookup |id|. The caller must hold |lock_|.
+ AndroidOverlayCallback* LookupLocked(long id) {
+ lock_.AssertAcquired();
+ AndroidOverlayCallback* 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, AndroidOverlayCallback*>;
+ Map map_;
+
+ base::Lock lock_;
+};
+
+static base::LazyInstance<AndroidOverlayCallbackmap>::Leaky g_map =
+ LAZY_INSTANCE_INITIALIZER;
+
+AndroidOverlayCallback::AndroidOverlayCallback(
+ const AndroidOverlayProxy::Callback& callback)
+ : id_(next_id_++), callback_(callback) {
+ if (!task_runner_)
+ task_runner_ = base::ThreadTaskRunnerHandle::Get();
boliu 2017/02/08 00:01:58 else DCHECK it's still the same thread?
+
+ JNIEnv* env = AttachCurrentThread();
+ j_surface_callback_.Reset(Java_AndroidOverlayCallback_create(env, id_));
+
+ g_map.Pointer()->Insert(id_, this);
+}
+
+AndroidOverlayCallback::~AndroidOverlayCallback() {
+ DCHECK(thread_checker_.CalledOnValidThread());
+ g_map.Pointer()->Erase(id_);
+}
+
+void AndroidOverlayCallback::SetAndroidSurfaceCB(
+ const AndroidSurfaceCB& android_surface_cb) {
+ android_surface_cb_ = android_surface_cb;
+}
+
+bool AndroidOverlayCallback::RegisterAndroidOverlayCallback(JNIEnv* env) {
+ return RegisterNativesImpl(env);
+}
+
+scoped_refptr<base::SingleThreadTaskRunner>
+AndroidOverlayCallback::GetTaskRunner() {
+ // May be called on any thread.
+ return task_runner_;
+}
+
+bool AndroidOverlayCallback::CalledOnValidThread() const {
+ return thread_checker_.CalledOnValidThread();
+}
+
+void AndroidOverlayCallback::OnCallbackProperThread(
+ long id,
+ AndroidOverlayProxy::CallbackOp what,
+ base::android::ScopedJavaGlobalRef<jobject> jobject_opt,
+ base::android::ScopedJavaGlobalRef<jobject> jcompletion_opt) {
+ // A callback has happened on some other thread. We're run on the correct
+ // thread in response to it.
+ AndroidOverlayCallback* 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) {
+ // If this is SURFACE_DESTROYED, then no further callbacks are permitted.
+ // Erase the map entry in case the IAndroidOverlay decides to send another.
+ if (what == AndroidOverlayProxy::CallbackOp::SURFACE_DESTROYED)
+ g_map.Pointer()->Erase(id);
+
+ DCHECK(thiz->CalledOnValidThread());
+ // Send the java surface to the AndroidOverlay before the callback.
+ if (what == AndroidOverlayProxy::CallbackOp::SURFACE_CREATED &&
+ !thiz->android_surface_cb_.is_null()) {
+ thiz->android_surface_cb_.Run(jobject_opt);
+ }
+
+ // Run the client-supplied callback.
+ thiz->callback_.Run(what);
+ }
+
+ // If this is a synchronous callback, then signal that we've completed.
+ if (!jcompletion_opt.is_null()) {
+ JNIEnv* env = AttachCurrentThread();
+ Java_AndroidOverlayCallback_signalCompletion(env, jcompletion_opt);
+ }
+}
+
+void OnAndroidOverlayCallbackCreated(
+ JNIEnv* env,
+ const base::android::JavaParamRef<jclass>& jcaller,
+ jlong id,
+ const base::android::JavaParamRef<jobject>& jsurface) {
+ // Called from some random thread in java.
+ // 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.
+ // Remember that we're on a random thread, but |g_map| is thread safe.
+ base::Closure cb = base::Bind(
+ &AndroidOverlayCallback::OnCallbackProperThread, id,
+ AndroidOverlayProxy::CallbackOp::SURFACE_CREATED,
+ base::android::ScopedJavaGlobalRef<jobject>(jsurface), nullptr);
+#if 1
+ AndroidOverlayCallback::GetTaskRunner()->PostTask(FROM_HERE, cb);
+#else
+ // DO NOT COMMIT -- just so that picture buffer manager can wait.
+ // (I'll remove this before landing)
+ LOG(ERROR) << "AVDA: DO NOT COMMIT";
+ cb.Run();
+#endif
+}
+
+void OnAndroidOverlayCallbackDestroyed(
+ JNIEnv* env,
+ const base::android::JavaParamRef<jclass>& jcaller,
+ jlong id,
+ const base::android::JavaParamRef<jobject>& jcompletion) {
+ // Called from some random thread in java.
+ base::Closure cb =
+ base::Bind(&AndroidOverlayCallback::OnCallbackProperThread, id,
+ AndroidOverlayProxy::CallbackOp::SURFACE_DESTROYED, nullptr,
+ base::android::ScopedJavaGlobalRef<jobject>(jcompletion));
+ AndroidOverlayCallback::GetTaskRunner()->PostTask(FROM_HERE, cb);
+}
+
+} // namespace media

Powered by Google App Engine
This is Rietveld 408576698