Merge "Make shortcut-only user dict entry non-words."
diff --git a/java/src/com/android/inputmethod/latin/BinaryDictionaryFileDumper.java b/java/src/com/android/inputmethod/latin/BinaryDictionaryFileDumper.java
index 562e1d0..42f7136 100644
--- a/java/src/com/android/inputmethod/latin/BinaryDictionaryFileDumper.java
+++ b/java/src/com/android/inputmethod/latin/BinaryDictionaryFileDumper.java
@@ -422,7 +422,7 @@
 
     private static void reinitializeClientRecordInDictionaryContentProvider(final Context context,
             final ContentProviderClient client, final String clientId) throws RemoteException {
-        final String metadataFileUri = context.getString(R.string.dictionary_pack_metadata_uri);
+        final String metadataFileUri = MetadataFileUriGetter.getMetadataUri(context);
         if (TextUtils.isEmpty(metadataFileUri)) return;
         // Tell the content provider to reset all information about this client id
         final Uri metadataContentUri = getProviderUriBuilder(clientId)
diff --git a/java/src/com/android/inputmethod/latin/MetadataFileUriGetter.java b/java/src/com/android/inputmethod/latin/MetadataFileUriGetter.java
new file mode 100644
index 0000000..e6dc6db
--- /dev/null
+++ b/java/src/com/android/inputmethod/latin/MetadataFileUriGetter.java
@@ -0,0 +1,28 @@
+/*
+ * Copyright (C) 2013 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.inputmethod.latin;
+
+import android.content.Context;
+
+/**
+ * Helper class to get the metadata URI.
+ */
+public class MetadataFileUriGetter {
+    public static String getMetadataUri(Context context) {
+        return context.getString(R.string.dictionary_pack_metadata_uri);
+    }
+}
diff --git a/native/jni/src/suggest/core/suggest.h b/native/jni/src/suggest/core/suggest.h
index 136c4e5..becd6c1 100644
--- a/native/jni/src/suggest/core/suggest.h
+++ b/native/jni/src/suggest/core/suggest.h
@@ -42,8 +42,9 @@
 class Suggest : public SuggestInterface {
  public:
     AK_FORCE_INLINE Suggest(const SuggestPolicy *const suggestPolicy)
-            : TRAVERSAL(suggestPolicy->getTraversal()),
-              SCORING(suggestPolicy->getScoring()), WEIGHTING(suggestPolicy->getWeighting()) {}
+            : TRAVERSAL(suggestPolicy ? suggestPolicy->getTraversal() : 0),
+              SCORING(suggestPolicy ? suggestPolicy->getScoring() : 0),
+              WEIGHTING(suggestPolicy ? suggestPolicy->getWeighting() : 0) {}
     AK_FORCE_INLINE virtual ~Suggest() {}
     int getSuggestions(ProximityInfo *pInfo, void *traverseSession, int *inputXs, int *inputYs,
             int *times, int *pointerIds, int *inputCodePoints, int inputSize, int commitPoint,
diff --git a/tests/src/com/android/inputmethod/latin/InputTestsBase.java b/tests/src/com/android/inputmethod/latin/InputTestsBase.java
index 4583eab..9e107a4 100644
--- a/tests/src/com/android/inputmethod/latin/InputTestsBase.java
+++ b/tests/src/com/android/inputmethod/latin/InputTestsBase.java
@@ -162,45 +162,22 @@
     // on the same thread that the tests are running on to mimic the actual environment as
     // closely as possible.
     // Now, Looper#loop() never exits in normal operation unless the Looper#quit() method
-    // is called, so we need to do that at the right time so that #loop() returns at some
-    // point and we don't end up in an infinite loop.
-    // After we quit, the looper is still technically ready to process more messages but
-    // the handler will refuse to enqueue any because #quit() has been called and it
-    // explicitly tests for it on message enqueuing, so we'll have to reset it so that
-    // it lets us continue normal operation.
+    // is called, which has a lot of bad side effects. We can however just throw an exception
+    // in the runnable which will unwind the stack and allow us to exit.
+    private final class InterruptRunMessagesException extends RuntimeException {
+        // Empty class
+    }
     protected void runMessages() {
-        // Here begins deep magic.
-        final Looper looper = mLatinIME.mHandler.getLooper();
         mLatinIME.mHandler.post(new Runnable() {
                 @Override
                 public void run() {
-                    looper.quit();
+                    throw new InterruptRunMessagesException();
                 }
             });
-        // The only way to get out of Looper#loop() is to call #quit() on it (or on its queue).
-        // Once #quit() is called remaining messages are not processed, which is why we post
-        // a message that calls it instead of calling it directly.
-        Looper.loop();
-
-        // Once #quit() has been called, the looper is not functional any more (it used to be,
-        // but now it SIGSEGV's if it's used again).
-        // It won't accept creating a new looper for this thread and switching to it...
-        // ...unless we can trick it into throwing out the old looper and believing it hasn't
-        // been initialized before.
-        MessageQueue queue = Looper.myQueue();
         try {
-            // However there is no way of doing it externally, and the static ThreadLocal
-            // field into which it's stored is private.
-            // So... get out the big guns.
-            java.lang.reflect.Field f = Looper.class.getDeclaredField("sThreadLocal");
-            f.setAccessible(true); // private lolwut
-            final ThreadLocal<Looper> a = (ThreadLocal<Looper>) f.get(looper);
-            a.set(null);
-            looper.prepare();
-        } catch (NoSuchFieldException e) {
-            throw new RuntimeException(e);
-        } catch (IllegalAccessException e) {
-            throw new RuntimeException(e);
+            Looper.loop();
+        } catch (InterruptRunMessagesException e) {
+            // Resume normal operation
         }
     }