Merge "Support INVITE w/o SDP."
diff --git a/core/java/android/provider/VoicemailContract.java b/core/java/android/provider/VoicemailContract.java
index ae41876..9966753 100644
--- a/core/java/android/provider/VoicemailContract.java
+++ b/core/java/android/provider/VoicemailContract.java
@@ -69,8 +69,15 @@
      * that caused the change in content provider.
      * <p>Receivers of the broadcast can use this field to determine if this is
      * a self change.
+     * @deprecated {@link #EXTRA_SELF_CHANGE} is now populated instead.
      */
     public static final String EXTRA_CHANGED_BY = "com.android.voicemail.extra.CHANGED_BY";
+    /**
+     * Extra included in {@value Intent#ACTION_PROVIDER_CHANGED} and
+     * {@value #ACTION_NEW_VOICEMAIL} broadcast intents to indicate if the receiving
+     * package made this change.
+     */
+    public static final String EXTRA_SELF_CHANGE = "com.android.voicemail.extra.SELF_CHANGE";
 
     /** The mime type for a collection of voicemails. */
     public static final String DIR_TYPE =
diff --git a/core/java/android/speech/tts/TextToSpeech.java b/core/java/android/speech/tts/TextToSpeech.java
index 5ee33e1..8e4725f 100755
--- a/core/java/android/speech/tts/TextToSpeech.java
+++ b/core/java/android/speech/tts/TextToSpeech.java
@@ -442,7 +442,7 @@
     private final Map<String, Uri> mUtterances;
     private final Bundle mParams = new Bundle();
     private final TtsEngines mEnginesHelper;
-    private String mCurrentEngine = null;
+    private volatile String mCurrentEngine = null;
 
     /**
      * The constructor for the TextToSpeech class, using the default TTS engine.
@@ -573,6 +573,7 @@
                 service.setCallback(getPackageName(), null);
                 service.stop(getPackageName());
                 mServiceConnection.disconnect();
+                mCurrentEngine = null;
                 return null;
             }
         }, null, "shutdown");
@@ -869,6 +870,14 @@
     }
 
     /**
+     * @return the engine currently in use by this TextToSpeech instance.
+     * @hide
+     */
+    public String getCurrentEngine() {
+        return mCurrentEngine;
+    }
+
+    /**
      * Sets the text-to-speech language.
      * The TTS engine will try to use the closest match to the specified
      * language as represented by the Locale, but there is no guarantee that the exact same Locale
diff --git a/services/java/com/android/server/accessibility/AccessibilityManagerService.java b/services/java/com/android/server/accessibility/AccessibilityManagerService.java
index a2019fc..10dd924 100644
--- a/services/java/com/android/server/accessibility/AccessibilityManagerService.java
+++ b/services/java/com/android/server/accessibility/AccessibilityManagerService.java
@@ -550,6 +550,26 @@
     private void notifyEventListenerLocked(Service service, int eventType) {
         IEventListener listener = service.mServiceInterface;
         AccessibilityEvent event = service.mPendingEvents.get(eventType);
+
+        // Check for null here because there is a concurrent scenario in which this
+        // happens: 1) A binder thread calls notifyAccessibilityServiceDelayedLocked
+        // which posts a message for dispatching an event. 2) The message is pulled
+        // from the queue by the handler on the service thread and the latter is
+        // just about to acquire the lock and call this method. 3) Now another binder
+        // thread acquires the lock calling notifyAccessibilityServiceDelayedLocked
+        // so the service thread waits for the lock; 4) The binder thread replaces
+        // the event with a more recent one (assume the same event type) and posts a
+        // dispatch request releasing the lock. 5) Now the main thread is unblocked and
+        // dispatches the event which is removed from the pending ones. 6) And ... now
+        // the service thread handles the last message posted by the last binder call
+        // but the event is already dispatched and hence looking it up in the pending
+        // ones yields null. This check is much simpler that keeping count for each
+        // event type of each service to catch such a scenario since only one message
+        // is processed at a time.
+        if (event == null) {
+            return;
+        }
+
         service.mPendingEvents.remove(eventType);
         try {
             if (mSecurityPolicy.canRetrieveWindowContent(service)) {