Merge change 8620 into donut

* changes:
  Fix swapped gsm/cdma function dispatch, and 7bit text fragmentation.
diff --git a/api/current.xml b/api/current.xml
index d56263f..dd13db5 100644
--- a/api/current.xml
+++ b/api/current.xml
@@ -698,7 +698,7 @@
  type="java.lang.String"
  transient="false"
  volatile="false"
- value=""android.permission.READ_HISTORY_BOOKMARKS""
+ value=""com.android.browser.permission.READ_HISTORY_BOOKMARKS""
  static="true"
  final="true"
  deprecated="not deprecated"
@@ -1160,7 +1160,7 @@
  type="java.lang.String"
  transient="false"
  volatile="false"
- value=""android.permission.WRITE_HISTORY_BOOKMARKS""
+ value=""com.android.browser.permission.WRITE_HISTORY_BOOKMARKS""
  static="true"
  final="true"
  deprecated="not deprecated"
diff --git a/core/java/android/app/ActivityThread.java b/core/java/android/app/ActivityThread.java
index 182843a..e21b1d9 100644
--- a/core/java/android/app/ActivityThread.java
+++ b/core/java/android/app/ActivityThread.java
@@ -3753,6 +3753,14 @@
 
         data.info = getPackageInfoNoCheck(data.appInfo);
 
+        /**
+         * Switch this process to density compatibility mode if needed.
+         */
+        if ((data.appInfo.flags&ApplicationInfo.FLAG_SUPPORTS_SCREEN_DENSITIES)
+                == 0) {
+            Bitmap.setDefaultDensity(DisplayMetrics.DENSITY_DEFAULT);
+        }
+        
         if (data.debugMode != IApplicationThread.DEBUG_OFF) {
             // XXX should have option to change the port.
             Debug.changeDebugPort(8100);
diff --git a/core/java/android/app/SearchDialog.java b/core/java/android/app/SearchDialog.java
index 26b5b7a..dd70130 100644
--- a/core/java/android/app/SearchDialog.java
+++ b/core/java/android/app/SearchDialog.java
@@ -800,7 +800,6 @@
             
             if (!event.isSystem() && 
                     (keyCode != KeyEvent.KEYCODE_DPAD_UP) &&
-                    (keyCode != KeyEvent.KEYCODE_DPAD_DOWN) &&
                     (keyCode != KeyEvent.KEYCODE_DPAD_LEFT) &&
                     (keyCode != KeyEvent.KEYCODE_DPAD_RIGHT) &&
                     (keyCode != KeyEvent.KEYCODE_DPAD_CENTER)) {
diff --git a/core/java/android/app/SearchManager.java b/core/java/android/app/SearchManager.java
index 0631ad5..fd559d6 100644
--- a/core/java/android/app/SearchManager.java
+++ b/core/java/android/app/SearchManager.java
@@ -1215,18 +1215,13 @@
                 = "DialogCursorProtocol.POST_REFRESH.displayNotify";
 
         /**
-         * Just before closing the cursor.
-         */
-        public final static int PRE_CLOSE = 1;
-        public final static String PRE_CLOSE_SEND_MAX_DISPLAY_POS
-                = "DialogCursorProtocol.PRE_CLOSE.sendDisplayPosition";
-
-        /**
          * When a position has been clicked.
          */
         public final static int CLICK = 2;
         public final static String CLICK_SEND_POSITION
                 = "DialogCursorProtocol.CLICK.sendPosition";
+        public final static String CLICK_SEND_MAX_DISPLAY_POS
+                = "DialogCursorProtocol.CLICK.sendDisplayPosition";
         public final static String CLICK_RECEIVE_SELECTED_POS
                 = "DialogCursorProtocol.CLICK.receiveSelectedPosition";
 
diff --git a/core/java/android/app/SuggestionsAdapter.java b/core/java/android/app/SuggestionsAdapter.java
index 17e6e50..4a00e48 100644
--- a/core/java/android/app/SuggestionsAdapter.java
+++ b/core/java/android/app/SuggestionsAdapter.java
@@ -194,10 +194,6 @@
     public void changeCursor(Cursor c) {
         if (DBG) Log.d(LOG_TAG, "changeCursor(" + c + ")");
 
-        if (mCursor != null) {
-            callCursorPreClose(mCursor);
-        }
-
         try {
             super.changeCursor(c);
             if (c != null) {
@@ -213,22 +209,6 @@
         }
     }
 
-    /**
-     * Handle sending and receiving information associated with
-     * {@link DialogCursorProtocol#PRE_CLOSE}.
-     *
-     * @param cursor The cursor to call.
-     */
-    private void callCursorPreClose(Cursor cursor) {
-        if (!mGlobalSearchMode) return;
-        final Bundle request = new Bundle();
-        request.putInt(DialogCursorProtocol.METHOD, DialogCursorProtocol.PRE_CLOSE);
-        request.putInt(DialogCursorProtocol.PRE_CLOSE_SEND_MAX_DISPLAY_POS, mMaxDisplayed);
-        final Bundle response = cursor.respond(request);
-
-        mMaxDisplayed = -1;
-    }
-
     @Override
     public void notifyDataSetChanged() {
         if (DBG) Log.d(LOG_TAG, "notifyDataSetChanged");
@@ -274,7 +254,9 @@
         final Bundle request = new Bundle(1);
         request.putInt(DialogCursorProtocol.METHOD, DialogCursorProtocol.CLICK);
         request.putInt(DialogCursorProtocol.CLICK_SEND_POSITION, position);
+        request.putInt(DialogCursorProtocol.CLICK_SEND_MAX_DISPLAY_POS, mMaxDisplayed);
         final Bundle response = cursor.respond(request);
+        mMaxDisplayed = -1;
         mListItemToSelect = response.getInt(
                 DialogCursorProtocol.CLICK_RECEIVE_SELECTED_POS, SuggestionsAdapter.NONE);
     }
diff --git a/core/java/android/webkit/WebView.java b/core/java/android/webkit/WebView.java
index fcf946f..6936435 100644
--- a/core/java/android/webkit/WebView.java
+++ b/core/java/android/webkit/WebView.java
@@ -545,7 +545,6 @@
 
     private ZoomButtonsController mZoomButtonsController; 
     private ImageView mZoomOverviewButton;
-    private ImageView mZoomFitPageButton;
 
     // These keep track of the center point of the zoom.  They are used to
     // determine the point around which we should zoom.
@@ -617,6 +616,16 @@
         // Create the buttons controller
         mZoomButtonsController = new ZoomButtonsController(this);
         mZoomButtonsController.setOnZoomListener(mZoomListener);
+        // ZoomButtonsController positions the buttons at the bottom, but in
+        // the middle.  Change their layout parameters so they appear on the
+        // right.
+        View controls = mZoomButtonsController.getZoomControls();
+        ViewGroup.LayoutParams params = controls.getLayoutParams();
+        if (params instanceof FrameLayout.LayoutParams) {
+            FrameLayout.LayoutParams frameParams = (FrameLayout.LayoutParams)
+                    params;
+            frameParams.gravity = Gravity.RIGHT;
+        }
 
         // Create the accessory buttons
         LayoutInflater inflater =
@@ -636,15 +645,6 @@
                     }
                 }
             });
-        mZoomFitPageButton =
-                (ImageView) container.findViewById(com.android.internal.R.id.zoom_fit_page);
-        mZoomFitPageButton.setOnClickListener(
-            new View.OnClickListener() {
-                public void onClick(View v) {
-                    zoomWithPreview(mDefaultScale);
-                    updateZoomButtonsEnabled();
-                }
-            });
     }
 
     private void updateZoomButtonsEnabled() {
@@ -654,17 +654,14 @@
             // Hide the zoom in and out buttons, as well as the fit to page
             // button, if the page cannot zoom
             mZoomButtonsController.getZoomControls().setVisibility(View.GONE);
-            mZoomFitPageButton.setVisibility(View.GONE);
         } else {
             // Bring back the hidden zoom controls.
             mZoomButtonsController.getZoomControls()
                     .setVisibility(View.VISIBLE);
-            mZoomFitPageButton.setVisibility(View.VISIBLE);
             // Set each one individually, as a page may be able to zoom in
             // or out.
             mZoomButtonsController.setZoomInEnabled(canZoomIn);
             mZoomButtonsController.setZoomOutEnabled(canZoomOut);
-            mZoomFitPageButton.setEnabled(mActualScale != mDefaultScale);
         }
         mZoomOverviewButton.setVisibility(canZoomScrollOut() ? View.VISIBLE:
                 View.GONE);
diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml
index 00d9cf6..e16db61 100644
--- a/core/res/AndroidManifest.xml
+++ b/core/res/AndroidManifest.xml
@@ -209,7 +209,7 @@
 
     <!-- Allows an application to read (but not write) the user's
         browsing history and bookmarks. -->
-    <permission android:name="android.permission.READ_HISTORY_BOOKMARKS"
+    <permission android:name="com.android.browser.permission.READ_HISTORY_BOOKMARKS"
         android:permissionGroup="android.permission-group.PERSONAL_INFO"
         android:label="@string/permlab_readHistoryBookmarks"
         android:description="@string/permdesc_readHistoryBookmarks"
@@ -217,7 +217,7 @@
 
     <!-- Allows an application to write (but not read) the user's
         browsing history and bookmarks. -->
-    <permission android:name="android.permission.WRITE_HISTORY_BOOKMARKS"
+    <permission android:name="com.android.browser.permission.WRITE_HISTORY_BOOKMARKS"
         android:permissionGroup="android.permission-group.PERSONAL_INFO"
         android:label="@string/permlab_writeHistoryBookmarks"
         android:description="@string/permdesc_writeHistoryBookmarks"
diff --git a/core/res/res/drawable/rate_star_small_half.png b/core/res/res/drawable/rate_star_small_half.png
index a81449b..437a11c 100644
--- a/core/res/res/drawable/rate_star_small_half.png
+++ b/core/res/res/drawable/rate_star_small_half.png
Binary files differ
diff --git a/core/res/res/drawable/rate_star_small_off.png b/core/res/res/drawable/rate_star_small_off.png
index 618766f..6fb0a36 100644
--- a/core/res/res/drawable/rate_star_small_off.png
+++ b/core/res/res/drawable/rate_star_small_off.png
Binary files differ
diff --git a/core/res/res/drawable/rate_star_small_on.png b/core/res/res/drawable/rate_star_small_on.png
index 74e3280..5392361 100644
--- a/core/res/res/drawable/rate_star_small_on.png
+++ b/core/res/res/drawable/rate_star_small_on.png
Binary files differ
diff --git a/core/res/res/layout/zoom_browser_accessory_buttons.xml b/core/res/res/layout/zoom_browser_accessory_buttons.xml
index 4bf2bdf..69afca9 100644
--- a/core/res/res/layout/zoom_browser_accessory_buttons.xml
+++ b/core/res/res/layout/zoom_browser_accessory_buttons.xml
@@ -18,18 +18,11 @@
 */
 -->
 <merge xmlns:android="http://schemas.android.com/apk/res/android">
-    <ImageView android:id="@+id/zoom_fit_page" 
-        android:background="@android:drawable/btn_browser_zoom_fit_page"
-        android:layout_width="wrap_content"
-        android:layout_height="wrap_content"
-        android:layout_gravity="bottom|left"
-        android:layout_marginLeft="7dip"
-        />
     <ImageView android:id="@+id/zoom_page_overview" 
         android:background="@android:drawable/btn_browser_zoom_page_overview"
         android:layout_width="wrap_content"
         android:layout_height="wrap_content"
-        android:layout_gravity="bottom|right"
-        android:layout_marginRight="7dip"
+        android:layout_gravity="bottom|left"
+        android:layout_marginLeft="7dip"
         />
 </merge>
diff --git a/graphics/java/android/graphics/Bitmap.java b/graphics/java/android/graphics/Bitmap.java
index bb19229..eef1096 100644
--- a/graphics/java/android/graphics/Bitmap.java
+++ b/graphics/java/android/graphics/Bitmap.java
@@ -46,10 +46,29 @@
     private boolean mRecycled;
 
     // Package-scoped for fast access.
-    /*package*/ int mDensity = DENSITY_NONE;
+    /*package*/ int mDensity = sDefaultDensity = getDefaultDensity();
 
     private static volatile Matrix sScaleMatrix;
 
+    private static volatile int sDefaultDensity = -1;
+    
+    /**
+     * For backwards compatibility, allows the app layer to change the default
+     * density when running old apps.
+     * @hide
+     */
+    public static void setDefaultDensity(int density) {
+        sDefaultDensity = density;
+    }
+    
+    /*package*/ static int getDefaultDensity() {
+        if (sDefaultDensity >= 0) {
+            return sDefaultDensity;
+        }
+        sDefaultDensity = DisplayMetrics.DENSITY_DEVICE;
+        return sDefaultDensity;
+    }
+    
     /**
      * @noinspection UnusedDeclaration
      */
@@ -72,9 +91,16 @@
     /**
      * <p>Returns the density for this bitmap.</p>
      *
-     * <p>The default density scale is {@link #DENSITY_NONE}.</p>
+     * <p>The default density is the same density as the current display,
+     * unless the current application does not support different screen
+     * densities in which case it is
+     * {@link android.util.DisplayMetrics#DENSITY_DEFAULT}.  Note that
+     * compatibility mode is determined by the application that was initially
+     * loaded into a process -- applications that share the same process should
+     * all have the same compatibility, or ensure they explicitly set the
+     * density of their bitmaps appropriately.</p>
      *
-     * @return A scaling factor of the default density (160) or {@link #DENSITY_NONE}
+     * @return A scaling factor of the default density or {@link #DENSITY_NONE}
      *         if the scaling factor is unknown.
      *
      * @see #setDensity(int)
@@ -272,7 +298,8 @@
      * Tries to make a new bitmap based on the dimensions of this bitmap,
      * setting the new bitmap's config to the one specified, and then copying
      * this bitmap's pixels into the new bitmap. If the conversion is not
-     * supported, or the allocator fails, then this returns NULL.
+     * supported, or the allocator fails, then this returns NULL.  The returned
+     * bitmap initially has the same density as the original.
      *
      * @param config    The desired config for the resulting bitmap
      * @param isMutable True if the resulting bitmap should be mutable (i.e.
@@ -281,7 +308,11 @@
      */
     public Bitmap copy(Config config, boolean isMutable) {
         checkRecycled("Can't copy a recycled bitmap");
-        return nativeCopy(mNativeBitmap, config.nativeInt, isMutable);
+        Bitmap b = nativeCopy(mNativeBitmap, config.nativeInt, isMutable);
+        if (b != null) {
+            b.mDensity = mDensity;
+        }
+        return b;
     }
 
     public static Bitmap createScaledBitmap(Bitmap src, int dstWidth,
@@ -316,7 +347,8 @@
 
     /**
      * Returns an immutable bitmap from the source bitmap. The new bitmap may
-     * be the same object as source, or a copy may have been made.
+     * be the same object as source, or a copy may have been made.  It is
+     * initialized with the same density as the original bitmap.
      */
     public static Bitmap createBitmap(Bitmap src) {
         return createBitmap(src, 0, 0, src.getWidth(), src.getHeight());
@@ -325,7 +357,8 @@
     /**
      * Returns an immutable bitmap from the specified subset of the source
      * bitmap. The new bitmap may be the same object as source, or a copy may
-     * have been made.
+     * have been made.  It is
+     * initialized with the same density as the original bitmap.
      *
      * @param source   The bitmap we are subsetting
      * @param x        The x coordinate of the first pixel in source
@@ -339,7 +372,8 @@
 
     /**
      * Returns an immutable bitmap from subset of the source bitmap,
-     * transformed by the optional matrix.
+     * transformed by the optional matrix.  It is
+     * initialized with the same density as the original bitmap.
      *
      * @param source   The bitmap we are subsetting
      * @param x        The x coordinate of the first pixel in source
@@ -406,18 +440,20 @@
                 paint.setAntiAlias(true);
             }
         }
-        canvas.setBitmap(bitmap);
-        canvas.drawBitmap(source, srcR, dstR, paint);
-
+        
         // The new bitmap was created from a known bitmap source so assume that
         // they use the same density
         bitmap.mDensity = source.mDensity;
+        
+        canvas.setBitmap(bitmap);
+        canvas.drawBitmap(source, srcR, dstR, paint);
 
         return bitmap;
     }
 
     /**
-     * Returns a mutable bitmap with the specified width and height.
+     * Returns a mutable bitmap with the specified width and height.  Its
+     * initial density is as per {@link #getDensity}.
      *
      * @param width    The width of the bitmap
      * @param height   The height of the bitmap
@@ -432,7 +468,8 @@
 
     /**
      * Returns a immutable bitmap with the specified width and height, with each
-     * pixel value set to the corresponding value in the colors array.
+     * pixel value set to the corresponding value in the colors array.  Its
+     * initial density is as per {@link #getDensity}.
      *
      * @param colors   Array of {@link Color} used to initialize the pixels.
      * @param offset   Number of values to skip before the first color in the
@@ -466,7 +503,8 @@
 
     /**
      * Returns a immutable bitmap with the specified width and height, with each
-     * pixel value set to the corresponding value in the colors array.
+     * pixel value set to the corresponding value in the colors array.  Its
+     * initial density is as per {@link #getDensity}.
      *
      * @param colors   Array of {@link Color} used to initialize the pixels.
      *                 This array must be at least as large as width * height.
@@ -882,6 +920,9 @@
      * -2, -2, so that drawing the alpha bitmap offset by (-2, -2) and then
      * drawing the original would result in the blur visually aligning with
      * the original.
+     * 
+     * <p>The initial density of the returned bitmap is the same as the original's.
+     * 
      * @param paint Optional paint used to modify the alpha values in the
      *              resulting bitmap. Pass null for default behavior.
      * @param offsetXY Optional array that returns the X (index 0) and Y
@@ -899,6 +940,7 @@
         if (bm == null) {
             throw new RuntimeException("Failed to extractAlpha on Bitmap");
         }
+        bm.mDensity = mDensity;
         return bm;
     }
 
diff --git a/graphics/java/android/graphics/Canvas.java b/graphics/java/android/graphics/Canvas.java
index 8ecbfbd..bc2e42e 100644
--- a/graphics/java/android/graphics/Canvas.java
+++ b/graphics/java/android/graphics/Canvas.java
@@ -49,7 +49,7 @@
     private DrawFilter  mDrawFilter;
 
     // Package-scoped for quick access.
-    /*package*/ int mDensity = DisplayMetrics.DENSITY_DEFAULT;
+    /*package*/ int mDensity = Bitmap.DENSITY_NONE;
     
     // Used by native code
     @SuppressWarnings({"UnusedDeclaration"})
@@ -57,7 +57,9 @@
 
     /**
      * Construct an empty raster canvas. Use setBitmap() to specify a bitmap to
-     * draw into.
+     * draw into.  The initial target density is {@link Bitmap#DENSITY_NONE};
+     * this will typically be replaced when a target bitmap is set for the
+     * canvas.
      */
     public Canvas() {
         // 0 means no native bitmap
@@ -67,6 +69,9 @@
     /**
      * Construct a canvas with the specified bitmap to draw into. The bitmap
      * must be mutable.
+     * 
+     * <p>The initial target density of the canvas is the same as the given
+     * bitmap's density.
      *
      * @param bitmap Specifies a mutable bitmap for the canvas to draw into.
      */
@@ -78,9 +83,7 @@
         throwIfRecycled(bitmap);
         mNativeCanvas = initRaster(bitmap.ni());
         mBitmap = bitmap;
-        final int density = bitmap.mDensity;
-        mDensity = density == Bitmap.DENSITY_NONE
-                ? DisplayMetrics.DENSITY_DEFAULT : density;
+        mDensity = bitmap.mDensity;
     }
     
     /*package*/ Canvas(int nativeCanvas) {
@@ -88,6 +91,7 @@
             throw new IllegalStateException();
         }
         mNativeCanvas = nativeCanvas;
+        mDensity = Bitmap.getDefaultDensity();
     }
     
     /**
@@ -96,10 +100,14 @@
      * be supported in this mode (e.g. some GL implementations may not support
      * antialiasing or certain effects like ColorMatrix or certain Xfermodes).
      * However, no exception will be thrown in those cases.
+     * 
+     * <p>The initial target density of the canvas is the same as the initial
+     * density of bitmaps as per {@link Bitmap#getDensity() Bitmap.getDensity()}.
      */
     public Canvas(GL gl) {
         mNativeCanvas = initGL();
         mGL = gl;
+        mDensity = Bitmap.getDefaultDensity();
     }
     
     /**
@@ -120,9 +128,13 @@
     }
         
     /**
-     * Specify a bitmap for the canvas to draw into.
+     * Specify a bitmap for the canvas to draw into.  As a side-effect, also
+     * updates the canvas's target density to match that of the bitmap.
      *
      * @param bitmap Specifies a mutable bitmap for the canvas to draw into.
+     * 
+     * @see #setDensity(int)
+     * @see #getDensity()
      */
     public void setBitmap(Bitmap bitmap) {
         if (!bitmap.isMutable()) {
@@ -135,9 +147,7 @@
 
         native_setBitmap(mNativeCanvas, bitmap.ni());
         mBitmap = bitmap;
-        final int density = bitmap.mDensity;
-        mDensity = density == Bitmap.DENSITY_NONE
-                ? DisplayMetrics.DENSITY_DEFAULT : density;
+        mDensity = bitmap.mDensity;
     }
     
     /**
@@ -176,12 +186,12 @@
     public native int getHeight();
 
     /**
-     * <p>Returns the density for this Canvas' backing bitmap.</p>
+     * <p>Returns the target density of the canvas.  The default density is
+     * derived from the density of its backing bitmap, or
+     * {@link Bitmap#DENSITY_NONE} if there is not one.</p>
      *
-     * <p>The default density scale is {@link Bitmap#DENSITY_NONE}.</p>
-     *
-     * @return A scaling factor of the default density (160dpi) or
-     *        {@link Bitmap#DENSITY_NONE} if the scaling factor is unknown.
+     * @return Returns the current target density of the canvas, which is used
+     * to determine the scaling factor when drawing a bitmap into it.
      *
      * @see #setDensity(int)
      * @see Bitmap#getDensity() 
@@ -191,10 +201,13 @@
     }
 
     /**
-     * <p>Specifies the density for this Canvas' backing bitmap.
+     * <p>Specifies the density for this Canvas' backing bitmap.  This modifies
+     * the target density of the canvas itself, as well as the density of its
+     * backing bitmap via {@link Bitmap#setDensity(int) Bitmap.setDensity(int)}.
      *
-     * @param density The density scaling factor to use with this bitmap or
-     *        {@link Bitmap#DENSITY_NONE} if the factor is unknown.
+     * @param density The new target density of the canvas, which is used
+     * to determine the scaling factor when drawing a bitmap into it.  Use
+     * {@link Bitmap#DENSITY_NONE} to disable bitmap scaling.
      *
      * @see #getDensity()
      * @see Bitmap#setDensity(int) 
diff --git a/packages/TtsService/src/android/tts/TtsService.java b/packages/TtsService/src/android/tts/TtsService.java
index e52ba80..6832862 100755
--- a/packages/TtsService/src/android/tts/TtsService.java
+++ b/packages/TtsService/src/android/tts/TtsService.java
@@ -109,7 +109,9 @@
             mFilename = file;
         }
     }
-
+    // If the speech queue is locked for more than 5 seconds, something has gone
+    // very wrong with processSpeechQueue.
+    private static final int SPEECHQUEUELOCK_TIMEOUT = 5000;
     private static final int MAX_SPEECH_ITEM_CHAR_LENGTH = 4000;
     private static final int MAX_FILENAME_LENGTH = 250;
     // TODO use the TTS stream type when available
@@ -389,9 +391,8 @@
         int result = TextToSpeech.TTS_ERROR;
         boolean speechQueueAvailable = false;
         try{
-            // If the queue is locked for more than 1 second,
-            // something has gone very wrong with processSpeechQueue.
-            speechQueueAvailable = speechQueueLock.tryLock(1000, TimeUnit.MILLISECONDS);
+            speechQueueAvailable =
+                    speechQueueLock.tryLock(SPEECHQUEUELOCK_TIMEOUT, TimeUnit.MILLISECONDS);
             if (speechQueueAvailable) {
                 Log.i("TtsService", "Stopping");
                 for (int i = mSpeechQueue.size() - 1; i > -1; i--){
@@ -439,9 +440,8 @@
         int result = TextToSpeech.TTS_ERROR;
         boolean speechQueueAvailable = false;
         try{
-            // If the queue is locked for more than 1 second,
-            // something has gone very wrong with processSpeechQueue.
-            speechQueueAvailable = speechQueueLock.tryLock(1000, TimeUnit.MILLISECONDS);
+            speechQueueAvailable =
+                    speechQueueLock.tryLock(SPEECHQUEUELOCK_TIMEOUT, TimeUnit.MILLISECONDS);
             if (speechQueueAvailable) {
                 for (int i = mSpeechQueue.size() - 1; i > -1; i--){
                     if (mSpeechQueue.get(i).mType != SpeechItem.TEXT_TO_FILE){
@@ -752,8 +752,10 @@
     private void processSpeechQueue() {
         boolean speechQueueAvailable = false;
         try {
-            speechQueueAvailable = speechQueueLock.tryLock();
+            speechQueueAvailable =
+                    speechQueueLock.tryLock(SPEECHQUEUELOCK_TIMEOUT, TimeUnit.MILLISECONDS);
             if (!speechQueueAvailable) {
+                Log.e("TtsService", "processSpeechQueue - Speech queue is unavailable.");
                 return;
             }
             if (mSpeechQueue.size() < 1) {
@@ -822,6 +824,9 @@
             if (mSpeechQueue.size() > 0) {
                 mSpeechQueue.remove(0);
             }
+        } catch (InterruptedException e) {
+          Log.e("TtsService", "TTS processSpeechQueue: tryLock interrupted");
+          e.printStackTrace();
         } finally {
             // This check is needed because finally will always run; even if the
             // method returns somewhere in the try block.