Fix UAF in AndroidVideoTrackSource::SetState

Tasks posted to the signaling thread could execute after destruction
because the safety flag was not being marked as not alive. This caused
use-after-free crashes (SIGSEGV) in callbacks like FireOnChange.

This change ensures that the safety flag is marked as not alive in the
destructor, preventing tasks from running post-destruction.

Bug: b/403168866
Change-Id: I6ea1db070d32305725b8e7cd34d8b636f8ac70c9
Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/462920
Reviewed-by: Per Åhgren <peah@webrtc.org>
Reviewed-by: Tomas Gunnarsson <tommi@webrtc.org>
Commit-Queue: Viktor Grönroos <wilhelmsson@google.com>
Cr-Commit-Position: refs/heads/main@{#47456}
diff --git a/sdk/android/src/jni/android_video_track_source.cc b/sdk/android/src/jni/android_video_track_source.cc
index 36c48e8..7ac66c7 100644
--- a/sdk/android/src/jni/android_video_track_source.cc
+++ b/sdk/android/src/jni/android_video_track_source.cc
@@ -77,10 +77,30 @@
       signaling_thread_(signaling_thread),
       is_screencast_(is_screencast),
       align_timestamps_(align_timestamps),
-      safety_(PendingTaskSafetyFlag::Create()) {
+      safety_(PendingTaskSafetyFlag::CreateAttachedToTaskQueue(
+          /*alive=*/true,
+          signaling_thread)) {
+  RTC_DCHECK(signaling_thread_);
   RTC_LOG(LS_INFO) << "AndroidVideoTrackSource ctor";
 }
-AndroidVideoTrackSource::~AndroidVideoTrackSource() = default;
+
+AndroidVideoTrackSource::~AndroidVideoTrackSource() {
+  RTC_LOG(LS_INFO) << "AndroidVideoTrackSource dtor";
+
+  // TODO(b/403168866): This is a workaround to ensure
+  // safety_flag_->SetNotAlive() is called on the signaling thread.
+  //
+  // In production code, this object should always be destroyed on the signaling
+  // thread. However, during teardown in instrumentation tests, calling
+  // VideoSource.dispose() from Java drops the last reference to this object on
+  // the Java test thread. This trigger destruction on the wrong thread, which
+  // would cause a crash due to the sequence checker DCHECK in SetNotAlive().
+  if (signaling_thread_->IsCurrent()) {
+    safety_->SetNotAlive();
+  } else {
+    signaling_thread_->BlockingCall([&] { safety_->SetNotAlive(); });
+  }
+}
 
 bool AndroidVideoTrackSource::is_screencast() const {
   return is_screencast_.load();