Update stable to r5019.

git-svn-id: http://webrtc.googlecode.com/svn/stable/talk@5022 4adac7df-926f-26a2-2b94-8c16560cd09d
diff --git a/app/webrtc/java/jni/peerconnection_jni.cc b/app/webrtc/java/jni/peerconnection_jni.cc
index 218864c..0b7c78b 100644
--- a/app/webrtc/java/jni/peerconnection_jni.cc
+++ b/app/webrtc/java/jni/peerconnection_jni.cc
@@ -72,6 +72,7 @@
 #include "talk/media/devices/videorendererfactory.h"
 #include "talk/media/webrtc/webrtcvideocapturer.h"
 #include "third_party/icu/source/common/unicode/unistr.h"
+#include "webrtc/system_wrappers/interface/compile_assert.h"
 #include "webrtc/system_wrappers/interface/trace.h"
 #include "webrtc/video_engine/include/vie_base.h"
 #include "webrtc/voice_engine/include/voe_base.h"
@@ -135,12 +136,6 @@
     CHECK(!count, "Unexpected refcount");                         \
   } while (0)
 
-// Lifted from chromium's base/basictypes.h.
-template <bool>
-struct CompileAssert {};
-#define COMPILE_ASSERT(expr, msg) \
-  typedef CompileAssert<(bool(expr))> msg[bool(expr) ? 1 : -1]
-
 namespace {
 
 static JavaVM* g_jvm = NULL;  // Set in JNI_OnLoad().
diff --git a/app/webrtc/peerconnection_unittest.cc b/app/webrtc/peerconnection_unittest.cc
index 74f420b..9de6ec9 100644
--- a/app/webrtc/peerconnection_unittest.cc
+++ b/app/webrtc/peerconnection_unittest.cc
@@ -1065,7 +1065,7 @@
 
 // This test sets up a audio call initially and then upgrades to audio/video,
 // using DTLS.
-TEST_F(JsepPeerConnectionP2PTestClient, DISABLED_LocalP2PTestDtlsRenegotiate) {
+TEST_F(JsepPeerConnectionP2PTestClient, LocalP2PTestDtlsRenegotiate) {
   MAYBE_SKIP_TEST(talk_base::SSLStreamAdapter::HaveDtlsSrtp);
   FakeConstraints setup_constraints;
   setup_constraints.AddMandatory(MediaConstraintsInterface::kEnableDtlsSrtp,
diff --git a/app/webrtc/test/fakeaudiocapturemodule.cc b/app/webrtc/test/fakeaudiocapturemodule.cc
index 4bdaf89..3b36163 100644
--- a/app/webrtc/test/fakeaudiocapturemodule.cc
+++ b/app/webrtc/test/fakeaudiocapturemodule.cc
@@ -52,6 +52,7 @@
 static const uint32_t kMaxVolume = 14392;
 
 enum {
+  MSG_START_PROCESS,
   MSG_RUN_PROCESS,
   MSG_STOP_PROCESS,
 };
@@ -89,6 +90,7 @@
 }
 
 int FakeAudioCaptureModule::frames_received() const {
+  talk_base::CritScope cs(&crit_);
   return frames_received_;
 }
 
@@ -142,6 +144,7 @@
 
 int32_t FakeAudioCaptureModule::RegisterAudioCallback(
     webrtc::AudioTransport* audio_callback) {
+  talk_base::CritScope cs(&crit_callback_);
   audio_callback_ = audio_callback;
   return 0;
 }
@@ -245,18 +248,28 @@
   if (!play_is_initialized_) {
     return -1;
   }
-  playing_ = true;
-  UpdateProcessing();
+  {
+    talk_base::CritScope cs(&crit_);
+    playing_ = true;
+  }
+  bool start = true;
+  UpdateProcessing(start);
   return 0;
 }
 
 int32_t FakeAudioCaptureModule::StopPlayout() {
-  playing_ = false;
-  UpdateProcessing();
+  bool start = false;
+  {
+    talk_base::CritScope cs(&crit_);
+    playing_ = false;
+    start = ShouldStartProcessing();
+  }
+  UpdateProcessing(start);
   return 0;
 }
 
 bool FakeAudioCaptureModule::Playing() const {
+  talk_base::CritScope cs(&crit_);
   return playing_;
 }
 
@@ -264,18 +277,28 @@
   if (!rec_is_initialized_) {
     return -1;
   }
-  recording_ = true;
-  UpdateProcessing();
+  {
+    talk_base::CritScope cs(&crit_);
+    recording_ = true;
+  }
+  bool start = true;
+  UpdateProcessing(start);
   return 0;
 }
 
 int32_t FakeAudioCaptureModule::StopRecording() {
-  recording_ = false;
-  UpdateProcessing();
+  bool start = false;
+  {
+    talk_base::CritScope cs(&crit_);
+    recording_ = false;
+    start = ShouldStartProcessing();
+  }
+  UpdateProcessing(start);
   return 0;
 }
 
 bool FakeAudioCaptureModule::Recording() const {
+  talk_base::CritScope cs(&crit_);
   return recording_;
 }
 
@@ -373,12 +396,14 @@
   return 0;
 }
 
-int32_t FakeAudioCaptureModule::SetMicrophoneVolume(uint32_t /*volume*/) {
-  ASSERT(false);
+int32_t FakeAudioCaptureModule::SetMicrophoneVolume(uint32_t volume) {
+  talk_base::CritScope cs(&crit_);
+  current_mic_level_ = volume;
   return 0;
 }
 
 int32_t FakeAudioCaptureModule::MicrophoneVolume(uint32_t* volume) const {
+  talk_base::CritScope cs(&crit_);
   *volume = current_mic_level_;
   return 0;
 }
@@ -594,6 +619,9 @@
 
 void FakeAudioCaptureModule::OnMessage(talk_base::Message* msg) {
   switch (msg->message_id) {
+    case MSG_START_PROCESS:
+      StartProcessP();
+      break;
     case MSG_RUN_PROCESS:
       ProcessFrameP();
       break;
@@ -640,33 +668,48 @@
   return false;
 }
 
-void FakeAudioCaptureModule::UpdateProcessing() {
-  const bool process = recording_ || playing_;
-  if (process) {
-    if (started_) {
-      // Already started.
-      return;
-    }
-    process_thread_->Post(this, MSG_RUN_PROCESS);
+bool FakeAudioCaptureModule::ShouldStartProcessing() {
+  return recording_ || playing_;
+}
+
+void FakeAudioCaptureModule::UpdateProcessing(bool start) {
+  if (start) {
+    process_thread_->Post(this, MSG_START_PROCESS);
   } else {
     process_thread_->Send(this, MSG_STOP_PROCESS);
   }
 }
 
+void FakeAudioCaptureModule::StartProcessP() {
+  ASSERT(talk_base::Thread::Current() == process_thread_);
+  if (started_) {
+    // Already started.
+    return;
+  }
+  ProcessFrameP();
+}
+
 void FakeAudioCaptureModule::ProcessFrameP() {
   ASSERT(talk_base::Thread::Current() == process_thread_);
   if (!started_) {
     next_frame_time_ = talk_base::Time();
     started_ = true;
   }
+
+  bool playing;
+  bool recording;
+  {
+    talk_base::CritScope cs(&crit_);
+    playing = playing_;
+    recording = recording_;
+  }
+
   // Receive and send frames every kTimePerFrameMs.
-  if (audio_callback_ != NULL) {
-    if (playing_) {
-      ReceiveFrameP();
-    }
-    if (recording_) {
-      SendFrameP();
-    }
+  if (playing) {
+    ReceiveFrameP();
+  }
+  if (recording) {
+    SendFrameP();
   }
 
   next_frame_time_ += kTimePerFrameMs;
@@ -678,35 +721,51 @@
 
 void FakeAudioCaptureModule::ReceiveFrameP() {
   ASSERT(talk_base::Thread::Current() == process_thread_);
-  ResetRecBuffer();
-  uint32_t nSamplesOut = 0;
-  if (audio_callback_->NeedMorePlayData(kNumberSamples, kNumberBytesPerSample,
-                                       kNumberOfChannels, kSamplesPerSecond,
-                                       rec_buffer_, nSamplesOut) != 0) {
-    ASSERT(false);
+  {
+    talk_base::CritScope cs(&crit_callback_);
+    if (!audio_callback_) {
+      return;
+    }
+    ResetRecBuffer();
+    uint32_t nSamplesOut = 0;
+    if (audio_callback_->NeedMorePlayData(kNumberSamples, kNumberBytesPerSample,
+                                         kNumberOfChannels, kSamplesPerSecond,
+                                         rec_buffer_, nSamplesOut) != 0) {
+      ASSERT(false);
+    }
+    ASSERT(nSamplesOut == kNumberSamples);
   }
-  ASSERT(nSamplesOut == kNumberSamples);
   // The SetBuffer() function ensures that after decoding, the audio buffer
   // should contain samples of similar magnitude (there is likely to be some
   // distortion due to the audio pipeline). If one sample is detected to
   // have the same or greater magnitude somewhere in the frame, an actual frame
   // has been received from the remote side (i.e. faked frames are not being
   // pulled).
-  if (CheckRecBuffer(kHighSampleValue)) ++frames_received_;
+  if (CheckRecBuffer(kHighSampleValue)) {
+    talk_base::CritScope cs(&crit_);
+    ++frames_received_;
+  }
 }
 
 void FakeAudioCaptureModule::SendFrameP() {
   ASSERT(talk_base::Thread::Current() == process_thread_);
+  talk_base::CritScope cs(&crit_callback_);
+  if (!audio_callback_) {
+    return;
+  }
   bool key_pressed = false;
+  uint32_t current_mic_level = 0;
+  MicrophoneVolume(&current_mic_level);
   if (audio_callback_->RecordedDataIsAvailable(send_buffer_, kNumberSamples,
                                               kNumberBytesPerSample,
                                               kNumberOfChannels,
                                               kSamplesPerSecond, kTotalDelayMs,
-                                              kClockDriftMs, current_mic_level_,
+                                              kClockDriftMs, current_mic_level,
                                               key_pressed,
-                                              current_mic_level_) != 0) {
+                                              current_mic_level) != 0) {
     ASSERT(false);
   }
+  SetMicrophoneVolume(current_mic_level);
 }
 
 void FakeAudioCaptureModule::StopProcessP() {
diff --git a/app/webrtc/test/fakeaudiocapturemodule.h b/app/webrtc/test/fakeaudiocapturemodule.h
index c32fa1f..2267902 100644
--- a/app/webrtc/test/fakeaudiocapturemodule.h
+++ b/app/webrtc/test/fakeaudiocapturemodule.h
@@ -38,6 +38,7 @@
 #define TALK_APP_WEBRTC_TEST_FAKEAUDIOCAPTUREMODULE_H_
 
 #include "talk/base/basictypes.h"
+#include "talk/base/criticalsection.h"
 #include "talk/base/messagehandler.h"
 #include "talk/base/scoped_ref_ptr.h"
 #include "webrtc/common_types.h"
@@ -88,6 +89,7 @@
   virtual int32_t RegisterEventObserver(
       webrtc::AudioDeviceObserver* event_callback);
 
+  // Note: Calling this method from a callback may result in deadlock.
   virtual int32_t RegisterAudioCallback(webrtc::AudioTransport* audio_callback);
 
   virtual int32_t Init();
@@ -225,10 +227,15 @@
   // equal to |value|.
   bool CheckRecBuffer(int value);
 
-  // Starts or stops the pushing and pulling of audio frames depending on if
-  // recording or playback has been enabled/started.
-  void UpdateProcessing();
+  // Returns true/false depending on if recording or playback has been
+  // enabled/started.
+  bool ShouldStartProcessing();
 
+  // Starts or stops the pushing and pulling of audio frames.
+  void UpdateProcessing(bool start);
+
+  // Starts the periodic calling of ProcessFrame() in a thread safe way.
+  void StartProcessP();
   // Periodcally called function that ensures that frames are pulled and pushed
   // periodically if enabled/started.
   void ProcessFrameP();
@@ -275,6 +282,13 @@
   // indicate that the frames are not faked somewhere in the audio pipeline
   // (e.g. by a jitter buffer).
   int frames_received_;
+
+  // Protects variables that are accessed from process_thread_ and
+  // the main thread.
+  mutable talk_base::CriticalSection crit_;
+  // Protects |audio_callback_| that is accessed from process_thread_ and
+  // the main thread.
+  talk_base::CriticalSection crit_callback_;
 };
 
 #endif  // TALK_APP_WEBRTC_TEST_FAKEAUDIOCAPTUREMODULE_H_
diff --git a/base/cpumonitor_unittest.cc b/base/cpumonitor_unittest.cc
index 952b89e..b9f5ba3 100644
--- a/base/cpumonitor_unittest.cc
+++ b/base/cpumonitor_unittest.cc
@@ -54,6 +54,9 @@
   BusyThread(double load, double duration, double interval) :
     load_(load), duration_(duration), interval_(interval) {
   }
+  virtual ~BusyThread() {
+    Stop();
+  }
   void Run() {
     Timing time;
     double busy_time = interval_ * load_ / 100.0;
diff --git a/base/dbus.cc b/base/dbus.cc
index 8e071c7..78e717a 100644
--- a/base/dbus.cc
+++ b/base/dbus.cc
@@ -158,6 +158,10 @@
     ASSERT(filter_list_);
   }
 
+  virtual ~DBusMonitoringThread() {
+    Stop();
+  }
+
   // Override virtual method of Thread. Context: worker-thread.
   virtual void Run() {
     ASSERT(NULL == connection_);
diff --git a/base/logging_unittest.cc b/base/logging_unittest.cc
index b0c219f..53cab66 100644
--- a/base/logging_unittest.cc
+++ b/base/logging_unittest.cc
@@ -87,6 +87,12 @@
 // Ensure we don't crash when adding/removing streams while threads are going.
 // We should restore the correct global state at the end.
 class LogThread : public Thread {
+ public:
+  virtual ~LogThread() {
+    Stop();
+  }
+
+ private:
   void Run() {
     // LS_SENSITIVE to avoid cluttering up any real logging going on
     LOG(LS_SENSITIVE) << "LOG";
diff --git a/base/maccocoasocketserver_unittest.mm b/base/maccocoasocketserver_unittest.mm
index d6f4b2c..818c30d 100644
--- a/base/maccocoasocketserver_unittest.mm
+++ b/base/maccocoasocketserver_unittest.mm
@@ -36,6 +36,9 @@
  public:
   WakeThread(SocketServer* ss) : ss_(ss) {
   }
+  virtual ~WakeThread() {
+    Stop();
+  }
   void Run() {
     ss_->WakeUp();
   }
diff --git a/base/macsocketserver_unittest.cc b/base/macsocketserver_unittest.cc
index a4a7101..f10aebc 100644
--- a/base/macsocketserver_unittest.cc
+++ b/base/macsocketserver_unittest.cc
@@ -37,6 +37,9 @@
  public:
   WakeThread(SocketServer* ss) : ss_(ss) {
   }
+  virtual ~WakeThread() {
+    Stop();
+  }
   void Run() {
     ss_->WakeUp();
   }
diff --git a/base/signalthread.h b/base/signalthread.h
index 79c00be..46dd0a3 100644
--- a/base/signalthread.h
+++ b/base/signalthread.h
@@ -123,6 +123,7 @@
   class Worker : public Thread {
    public:
     explicit Worker(SignalThread* parent) : parent_(parent) {}
+    virtual ~Worker() { Stop(); }
     virtual void Run() { parent_->Run(); }
 
    private:
diff --git a/base/signalthread_unittest.cc b/base/signalthread_unittest.cc
index 4458f52..e5734d4 100644
--- a/base/signalthread_unittest.cc
+++ b/base/signalthread_unittest.cc
@@ -120,6 +120,10 @@
         has_run_(false) {
   }
 
+  virtual ~OwnerThread() {
+    Stop();
+  }
+
   virtual void Run() {
     SignalThreadTest::SlowSignalThread* signal_thread =
         new SignalThreadTest::SlowSignalThread(harness_);
diff --git a/base/thread.cc b/base/thread.cc
index 316e14b..d07efb5 100644
--- a/base/thread.cc
+++ b/base/thread.cc
@@ -557,6 +557,7 @@
 }
 
 AutoThread::~AutoThread() {
+  Stop();
   if (ThreadManager::Instance()->CurrentThread() == this) {
     ThreadManager::Instance()->SetCurrentThread(NULL);
   }
diff --git a/base/thread.h b/base/thread.h
index e679ea4..4dc09f6 100644
--- a/base/thread.h
+++ b/base/thread.h
@@ -111,9 +111,15 @@
   DISALLOW_COPY_AND_ASSIGN(Runnable);
 };
 
+// WARNING! SUBCLASSES MUST CALL Stop() IN THEIR DESTRUCTORS!  See ~Thread().
+
 class Thread : public MessageQueue {
  public:
   explicit Thread(SocketServer* ss = NULL);
+  // NOTE: ALL SUBCLASSES OF Thread MUST CALL Stop() IN THEIR DESTRUCTORS (or
+  // guarantee Stop() is explicitly called before the subclass is destroyed).
+  // This is required to avoid a data race between the destructor modifying the
+  // vtable, and the Thread::PreRun calling the virtual method Run().
   virtual ~Thread();
 
   static Thread* Current();
@@ -291,6 +297,7 @@
 class ComThread : public Thread {
  public:
   ComThread() {}
+  virtual ~ComThread() { Stop(); }
 
  protected:
   virtual void Run();
diff --git a/base/thread_unittest.cc b/base/thread_unittest.cc
index 148e27b..d6af17a 100644
--- a/base/thread_unittest.cc
+++ b/base/thread_unittest.cc
@@ -122,7 +122,7 @@
 class CustomThread : public talk_base::Thread {
  public:
   CustomThread() {}
-  virtual ~CustomThread() {}
+  virtual ~CustomThread() { Stop(); }
   bool Start() { return false; }
 };
 
@@ -136,6 +136,7 @@
   }
 
   virtual ~SignalWhenDestroyedThread() {
+    Stop();
     event_->Set();
   }
 
diff --git a/base/win32socketserver.h b/base/win32socketserver.h
index 1fa6523..3459879 100644
--- a/base/win32socketserver.h
+++ b/base/win32socketserver.h
@@ -156,6 +156,7 @@
     set_socketserver(&ss_);
   }
   virtual ~Win32Thread() {
+    Stop();
     set_socketserver(NULL);
   }
   virtual void Run() {
diff --git a/examples/android/AndroidManifest.xml b/examples/android/AndroidManifest.xml
index 52e67a2..59974f7 100644
--- a/examples/android/AndroidManifest.xml
+++ b/examples/android/AndroidManifest.xml
@@ -13,7 +13,6 @@
   <uses-permission android:name="android.permission.MODIFY_AUDIO_SETTINGS" />
   <uses-permission android:name="android.permission.RECORD_AUDIO" />
   <uses-permission android:name="android.permission.INTERNET" />
-  <uses-permission android:name="android.permission.WAKE_LOCK" />
   <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
 
   <application android:label="@string/app_name"
diff --git a/examples/android/src/org/appspot/apprtc/AppRTCDemoActivity.java b/examples/android/src/org/appspot/apprtc/AppRTCDemoActivity.java
index 81c5ba9..c1dff74 100644
--- a/examples/android/src/org/appspot/apprtc/AppRTCDemoActivity.java
+++ b/examples/android/src/org/appspot/apprtc/AppRTCDemoActivity.java
@@ -34,7 +34,6 @@
 import android.graphics.Point;
 import android.media.AudioManager;
 import android.os.Bundle;
-import android.os.PowerManager;
 import android.util.Log;
 import android.view.WindowManager;
 import android.webkit.JavascriptInterface;
@@ -88,7 +87,6 @@
   // Synchronize on quit[0] to avoid teardown-related crashes.
   private final Boolean[] quit = new Boolean[] { false };
   private MediaConstraints sdpMediaConstraints;
-  private PowerManager.WakeLock wakeLock;
 
   @Override
   public void onCreate(Bundle savedInstanceState) {
@@ -547,7 +545,6 @@
         factory.dispose();
         factory = null;
       }
-      wakeLock.release();
       finish();
     }
   }
diff --git a/media/base/filemediaengine.cc b/media/base/filemediaengine.cc
index 1a3547c..e5183f6 100644
--- a/media/base/filemediaengine.cc
+++ b/media/base/filemediaengine.cc
@@ -125,6 +125,7 @@
   RtpSenderReceiver(MediaChannel* channel,
                     talk_base::StreamInterface* input_file_stream,
                     talk_base::StreamInterface* output_file_stream);
+  virtual ~RtpSenderReceiver();
 
   // Called by media channel. Context: media channel thread.
   bool SetSend(bool send);
@@ -183,6 +184,10 @@
   }
 }
 
+RtpSenderReceiver::~RtpSenderReceiver() {
+  Stop();
+}
+
 bool RtpSenderReceiver::SetSend(bool send) {
   bool was_sending = sending_;
   sending_ = send;
diff --git a/media/devices/filevideocapturer.cc b/media/devices/filevideocapturer.cc
index 1747816..f5c078d 100644
--- a/media/devices/filevideocapturer.cc
+++ b/media/devices/filevideocapturer.cc
@@ -28,6 +28,7 @@
 #include "talk/media/devices/filevideocapturer.h"
 
 #include "talk/base/bytebuffer.h"
+#include "talk/base/criticalsection.h"
 #include "talk/base/logging.h"
 #include "talk/base/thread.h"
 
@@ -108,6 +109,10 @@
         finished_(false) {
   }
 
+  virtual ~FileReadThread() {
+    Stop();
+  }
+
   // Override virtual method of parent Thread. Context: Worker Thread.
   virtual void Run() {
     // Read the first frame and start the message pump. The pump runs until
@@ -117,6 +122,8 @@
       PostDelayed(waiting_time_ms, this);
       Thread::Run();
     }
+
+    talk_base::CritScope cs(&crit_);
     finished_ = true;
   }
 
@@ -131,10 +138,14 @@
   }
 
   // Check if Run() is finished.
-  bool Finished() const { return finished_; }
+  bool Finished() const {
+    talk_base::CritScope cs(&crit_);
+    return finished_;
+  }
 
  private:
   FileVideoCapturer* capturer_;
+  mutable talk_base::CriticalSection crit_;
   bool finished_;
 
   DISALLOW_COPY_AND_ASSIGN(FileReadThread);
@@ -224,9 +235,9 @@
   SetCaptureFormat(&capture_format);
   // Create a thread to read the file.
   file_read_thread_ = new FileReadThread(this);
-  bool ret = file_read_thread_->Start();
   start_time_ns_ = kNumNanoSecsPerMilliSec *
       static_cast<int64>(talk_base::Time());
+  bool ret = file_read_thread_->Start();
   if (ret) {
     LOG(LS_INFO) << "File video capturer '" << GetId() << "' started";
     return CS_RUNNING;
diff --git a/media/devices/gdivideorenderer.cc b/media/devices/gdivideorenderer.cc
index d5edfc6..c8024b7 100755
--- a/media/devices/gdivideorenderer.cc
+++ b/media/devices/gdivideorenderer.cc
@@ -69,6 +69,10 @@
    public:
     explicit WindowThread(VideoWindow* window) : window_(window) {}
 
+    virtual ~WindowThread() {
+      Stop();
+    }
+
     // Override virtual method of talk_base::Thread. Context: worker Thread.
     virtual void Run() {
       // Initialize the window
diff --git a/xmllite/xmlelement_unittest.cc b/xmllite/xmlelement_unittest.cc
index 6d488fa..3c31ce4 100644
--- a/xmllite/xmlelement_unittest.cc
+++ b/xmllite/xmlelement_unittest.cc
@@ -235,6 +235,10 @@
   XmlElementCreatorThread(int count, buzz::QName qname) :
       count_(count), qname_(qname) {}
 
+  virtual ~XmlElementCreatorThread() {
+    Stop();
+  }
+
   virtual void Run() {
     std::vector<buzz::XmlElement*> elems;
     for (int i = 0; i < count_; i++) {
diff --git a/xmpp/xmppthread.cc b/xmpp/xmppthread.cc
index 43dded8..716aaf8 100644
--- a/xmpp/xmppthread.cc
+++ b/xmpp/xmppthread.cc
@@ -50,6 +50,7 @@
 }
 
 XmppThread::~XmppThread() {
+  Stop();
   delete pump_;
 }