Loading java/src/com/android/inputmethod/latin/LatinIME.java +7 −19 Original line number Diff line number Diff line Loading @@ -86,6 +86,7 @@ import com.android.inputmethod.latin.settings.SettingsActivity; import com.android.inputmethod.latin.settings.SettingsValues; import com.android.inputmethod.latin.suggestions.SuggestionStripView; import com.android.inputmethod.latin.utils.ApplicationUtils; import com.android.inputmethod.latin.utils.AsyncResultHolder; import com.android.inputmethod.latin.utils.AutoCorrectionUtils; import com.android.inputmethod.latin.utils.CapsModeUtils; import com.android.inputmethod.latin.utils.CollectionUtils; Loading @@ -107,8 +108,6 @@ import java.io.PrintWriter; import java.util.ArrayList; import java.util.Locale; import java.util.TreeSet; import java.util.concurrent.CountDownLatch; import java.util.concurrent.TimeUnit; /** * Input method implementation for Qwerty'ish keyboard. Loading Loading @@ -2428,31 +2427,20 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen return; } final CountDownLatch latch = new CountDownLatch(1); final SuggestedWords[] suggestedWordsArray = new SuggestedWords[1]; final AsyncResultHolder<SuggestedWords> holder = new AsyncResultHolder<SuggestedWords>(); getSuggestedWordsOrOlderSuggestionsAsync(Suggest.SESSION_TYPING, new OnGetSuggestedWordsCallback() { @Override public void onGetSuggestedWords(final SuggestedWords suggestedWords) { suggestedWordsArray[0] = suggestedWords; latch.countDown(); holder.set(suggestedWords); } } ); // TODO: Quit blocking the main thread. try { // Wait for the result of getSuggestedWords // We set the time out to avoid ANR. latch.await(GET_SUGGESTED_WORDS_TIMEOUT, TimeUnit.MILLISECONDS); } catch (InterruptedException e) { // TODO: Cancel all pending "getSuggestedWords" tasks when it failed. We may want to add // "onGetSuggestionFailed" to "OnGetSuggestedWordsCallback". Log.e(TAG, "InterruptedException while waiting for getSuggestedWords.", e); return; } if (suggestedWordsArray[0] != null) { showSuggestionStrip(suggestedWordsArray[0]); // This line may cause the current thread to wait. final SuggestedWords suggestedWords = holder.get(null, GET_SUGGESTED_WORDS_TIMEOUT); if (suggestedWords != null) { showSuggestionStrip(suggestedWords); } } Loading java/src/com/android/inputmethod/latin/utils/AsyncResultHolder.java 0 → 100644 +71 −0 Original line number Diff line number Diff line /* * 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.utils; import java.util.concurrent.CountDownLatch; import java.util.concurrent.TimeUnit; /** * This class is a holder of a result of asynchronous computation. * * @param <E> the type of the result. */ public class AsyncResultHolder<E> { private final Object mLock = new Object(); private E mResult; private final CountDownLatch mLatch; public AsyncResultHolder() { mLatch = new CountDownLatch(1); } /** * Sets the result value to this holder. * * @param result the value which is set. */ public void set(final E result) { synchronized(mLock) { if (mLatch.getCount() > 0) { mResult = result; mLatch.countDown(); } } } /** * Gets the result value held in this holder. * Causes the current thread to wait unless the value is set or the specified time is elapsed. * * @param defaultValue the default value. * @param timeOut the time to wait. * @return if the result is set until the time limit then the result, otherwise defaultValue. */ public E get(final E defaultValue, final long timeOut) { try { if(mLatch.await(timeOut, TimeUnit.MILLISECONDS)) { return mResult; } else { return defaultValue; } } catch (InterruptedException e) { return defaultValue; } } } tests/src/com/android/inputmethod/latin/utils/AsyncResultHolderTests.java 0 → 100644 +73 −0 Original line number Diff line number Diff line /* * 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.utils; import android.test.AndroidTestCase; import android.test.suitebuilder.annotation.MediumTest; import android.util.Log; @MediumTest public class AsyncResultHolderTests extends AndroidTestCase { private static final String TAG = AsyncResultHolderTests.class.getSimpleName(); private static final int TIMEOUT_IN_MILLISECONDS = 500; private static final int MARGIN_IN_MILLISECONDS = 250; private static final int DEFAULT_VALUE = 2; private static final int SET_VALUE = 1; private <T> void setAfterGivenTime(final AsyncResultHolder<T> holder, final T value, final long time) { new Thread(new Runnable() { @Override public void run() { try { Thread.sleep(time); } catch (InterruptedException e) { Log.d(TAG, "Exception while sleeping", e); } holder.set(value); } }).start(); } public void testGetWithoutSet() { final AsyncResultHolder<Integer> holder = new AsyncResultHolder<Integer>(); final int resultValue = holder.get(DEFAULT_VALUE, TIMEOUT_IN_MILLISECONDS); assertEquals(DEFAULT_VALUE, resultValue); } public void testGetBeforeSet() { final AsyncResultHolder<Integer> holder = new AsyncResultHolder<Integer>(); setAfterGivenTime(holder, SET_VALUE, TIMEOUT_IN_MILLISECONDS + MARGIN_IN_MILLISECONDS); final int resultValue = holder.get(DEFAULT_VALUE, TIMEOUT_IN_MILLISECONDS); assertEquals(DEFAULT_VALUE, resultValue); } public void testGetAfterSet() { final AsyncResultHolder<Integer> holder = new AsyncResultHolder<Integer>(); holder.set(SET_VALUE); final int resultValue = holder.get(DEFAULT_VALUE, TIMEOUT_IN_MILLISECONDS); assertEquals(SET_VALUE, resultValue); } public void testGetBeforeTimeout() { final AsyncResultHolder<Integer> holder = new AsyncResultHolder<Integer>(); setAfterGivenTime(holder, SET_VALUE, TIMEOUT_IN_MILLISECONDS - MARGIN_IN_MILLISECONDS); final int resultValue = holder.get(DEFAULT_VALUE, TIMEOUT_IN_MILLISECONDS); assertEquals(SET_VALUE, resultValue); } } Loading
java/src/com/android/inputmethod/latin/LatinIME.java +7 −19 Original line number Diff line number Diff line Loading @@ -86,6 +86,7 @@ import com.android.inputmethod.latin.settings.SettingsActivity; import com.android.inputmethod.latin.settings.SettingsValues; import com.android.inputmethod.latin.suggestions.SuggestionStripView; import com.android.inputmethod.latin.utils.ApplicationUtils; import com.android.inputmethod.latin.utils.AsyncResultHolder; import com.android.inputmethod.latin.utils.AutoCorrectionUtils; import com.android.inputmethod.latin.utils.CapsModeUtils; import com.android.inputmethod.latin.utils.CollectionUtils; Loading @@ -107,8 +108,6 @@ import java.io.PrintWriter; import java.util.ArrayList; import java.util.Locale; import java.util.TreeSet; import java.util.concurrent.CountDownLatch; import java.util.concurrent.TimeUnit; /** * Input method implementation for Qwerty'ish keyboard. Loading Loading @@ -2428,31 +2427,20 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen return; } final CountDownLatch latch = new CountDownLatch(1); final SuggestedWords[] suggestedWordsArray = new SuggestedWords[1]; final AsyncResultHolder<SuggestedWords> holder = new AsyncResultHolder<SuggestedWords>(); getSuggestedWordsOrOlderSuggestionsAsync(Suggest.SESSION_TYPING, new OnGetSuggestedWordsCallback() { @Override public void onGetSuggestedWords(final SuggestedWords suggestedWords) { suggestedWordsArray[0] = suggestedWords; latch.countDown(); holder.set(suggestedWords); } } ); // TODO: Quit blocking the main thread. try { // Wait for the result of getSuggestedWords // We set the time out to avoid ANR. latch.await(GET_SUGGESTED_WORDS_TIMEOUT, TimeUnit.MILLISECONDS); } catch (InterruptedException e) { // TODO: Cancel all pending "getSuggestedWords" tasks when it failed. We may want to add // "onGetSuggestionFailed" to "OnGetSuggestedWordsCallback". Log.e(TAG, "InterruptedException while waiting for getSuggestedWords.", e); return; } if (suggestedWordsArray[0] != null) { showSuggestionStrip(suggestedWordsArray[0]); // This line may cause the current thread to wait. final SuggestedWords suggestedWords = holder.get(null, GET_SUGGESTED_WORDS_TIMEOUT); if (suggestedWords != null) { showSuggestionStrip(suggestedWords); } } Loading
java/src/com/android/inputmethod/latin/utils/AsyncResultHolder.java 0 → 100644 +71 −0 Original line number Diff line number Diff line /* * 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.utils; import java.util.concurrent.CountDownLatch; import java.util.concurrent.TimeUnit; /** * This class is a holder of a result of asynchronous computation. * * @param <E> the type of the result. */ public class AsyncResultHolder<E> { private final Object mLock = new Object(); private E mResult; private final CountDownLatch mLatch; public AsyncResultHolder() { mLatch = new CountDownLatch(1); } /** * Sets the result value to this holder. * * @param result the value which is set. */ public void set(final E result) { synchronized(mLock) { if (mLatch.getCount() > 0) { mResult = result; mLatch.countDown(); } } } /** * Gets the result value held in this holder. * Causes the current thread to wait unless the value is set or the specified time is elapsed. * * @param defaultValue the default value. * @param timeOut the time to wait. * @return if the result is set until the time limit then the result, otherwise defaultValue. */ public E get(final E defaultValue, final long timeOut) { try { if(mLatch.await(timeOut, TimeUnit.MILLISECONDS)) { return mResult; } else { return defaultValue; } } catch (InterruptedException e) { return defaultValue; } } }
tests/src/com/android/inputmethod/latin/utils/AsyncResultHolderTests.java 0 → 100644 +73 −0 Original line number Diff line number Diff line /* * 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.utils; import android.test.AndroidTestCase; import android.test.suitebuilder.annotation.MediumTest; import android.util.Log; @MediumTest public class AsyncResultHolderTests extends AndroidTestCase { private static final String TAG = AsyncResultHolderTests.class.getSimpleName(); private static final int TIMEOUT_IN_MILLISECONDS = 500; private static final int MARGIN_IN_MILLISECONDS = 250; private static final int DEFAULT_VALUE = 2; private static final int SET_VALUE = 1; private <T> void setAfterGivenTime(final AsyncResultHolder<T> holder, final T value, final long time) { new Thread(new Runnable() { @Override public void run() { try { Thread.sleep(time); } catch (InterruptedException e) { Log.d(TAG, "Exception while sleeping", e); } holder.set(value); } }).start(); } public void testGetWithoutSet() { final AsyncResultHolder<Integer> holder = new AsyncResultHolder<Integer>(); final int resultValue = holder.get(DEFAULT_VALUE, TIMEOUT_IN_MILLISECONDS); assertEquals(DEFAULT_VALUE, resultValue); } public void testGetBeforeSet() { final AsyncResultHolder<Integer> holder = new AsyncResultHolder<Integer>(); setAfterGivenTime(holder, SET_VALUE, TIMEOUT_IN_MILLISECONDS + MARGIN_IN_MILLISECONDS); final int resultValue = holder.get(DEFAULT_VALUE, TIMEOUT_IN_MILLISECONDS); assertEquals(DEFAULT_VALUE, resultValue); } public void testGetAfterSet() { final AsyncResultHolder<Integer> holder = new AsyncResultHolder<Integer>(); holder.set(SET_VALUE); final int resultValue = holder.get(DEFAULT_VALUE, TIMEOUT_IN_MILLISECONDS); assertEquals(SET_VALUE, resultValue); } public void testGetBeforeTimeout() { final AsyncResultHolder<Integer> holder = new AsyncResultHolder<Integer>(); setAfterGivenTime(holder, SET_VALUE, TIMEOUT_IN_MILLISECONDS - MARGIN_IN_MILLISECONDS); final int resultValue = holder.get(DEFAULT_VALUE, TIMEOUT_IN_MILLISECONDS); assertEquals(SET_VALUE, resultValue); } }