Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 21daa532 authored by Amith Yamasani's avatar Amith Yamasani Committed by Android (Google) Code Review
Browse files

Merge "Load UserDictionary and AutoDictionary in a background thread."

parents 918f1b1d 283a77f6
Loading
Loading
Loading
Loading
+4 −10
Original line number Diff line number Diff line
@@ -96,11 +96,14 @@ public class AutoDictionary extends ExpandableDictionary {
        return frequency >= VALIDITY_THRESHOLD;
    }

    @Override
    public void close() {
        mOpenHelper.close();
        super.close();
    }

    private void loadDictionary() {
    @Override
    public void loadDictionaryAsync() {
        // Load the words that correspond to the current input locale
        Cursor cursor = query(COLUMN_LOCALE + "=?", new String[] { mLocale });
        if (cursor.moveToFirst()) {
@@ -183,15 +186,6 @@ public class AutoDictionary extends ExpandableDictionary {
        return c;
    }

    private boolean insert(ContentValues values) {
        SQLiteDatabase db = mOpenHelper.getWritableDatabase();
        long rowId = db.insert(AUTODICT_TABLE_NAME, Words.WORD, values);
        if (rowId > 0) {
            return true;
        }
        return false;
    }

    private int delete(String where, String[] whereArgs) {
        SQLiteDatabase db = mOpenHelper.getWritableDatabase();
        int count = db.delete(AUTODICT_TABLE_NAME, where, whereArgs);
+12 −61
Original line number Diff line number Diff line
@@ -35,15 +35,8 @@ public class ContactsDictionary extends ExpandableDictionary {

    private ContentObserver mObserver;

    private boolean mRequiresReload;

    private long mLastLoadedContacts;

    private boolean mUpdatingContacts;

    // Use this lock before touching mUpdatingContacts & mRequiresDownload
    private Object mUpdatingLock = new Object();

    public ContactsDictionary(Context context) {
        super(context);
        // Perform a managed query. The Activity will handle closing and requerying the cursor
@@ -53,15 +46,10 @@ public class ContactsDictionary extends ExpandableDictionary {
        cres.registerContentObserver(Contacts.CONTENT_URI, true, mObserver = new ContentObserver(null) {
            @Override
            public void onChange(boolean self) {
                synchronized (mUpdatingLock) {
                    mRequiresReload = true;
                }
                setRequiresReload(true);
            }
        });

        synchronized (mUpdatingLock) {
            loadDictionaryAsyncLocked();
        }
        loadDictionary();
    }

    public synchronized void close() {
@@ -69,41 +57,26 @@ public class ContactsDictionary extends ExpandableDictionary {
            getContext().getContentResolver().unregisterContentObserver(mObserver);
            mObserver = null;
        }
        super.close();
    }

    private synchronized void loadDictionaryAsyncLocked() {
    @Override
    public void startDictionaryLoadingTaskLocked() {
        long now = SystemClock.uptimeMillis();
        if (mLastLoadedContacts == 0
                || now - mLastLoadedContacts > 30 * 60 * 1000 /* 30 minutes */) {
            if (!mUpdatingContacts) {
                mUpdatingContacts = true;
                mRequiresReload = false;
                new LoadContactsTask().execute();
            }
            super.startDictionaryLoadingTaskLocked();
        }
    }

    @Override
    public synchronized void getWords(final WordComposer codes, final WordCallback callback,
            int[] nextLettersFrequencies) {
        synchronized (mUpdatingLock) {
            // If we need to update, start off a background task
            if (mRequiresReload) loadDictionaryAsyncLocked();
            // Currently updating contacts, don't return any results.
            if (mUpdatingContacts) return;
        }
        super.getWords(codes, callback, nextLettersFrequencies);
    }

    @Override
    public synchronized boolean isValidWord(CharSequence word) {
        synchronized (mUpdatingLock) {
            // If we need to update, start off a background task
            if (mRequiresReload) loadDictionaryAsyncLocked();
            if (mUpdatingContacts) return false;
    public void loadDictionaryAsync() {
        Cursor cursor = getContext().getContentResolver()
                .query(Contacts.CONTENT_URI, PROJECTION, null, null, null);
        if (cursor != null) {
            addWords(cursor);
        }

        return super.isValidWord(word);
        mLastLoadedContacts = SystemClock.uptimeMillis();
    }

    private void addWords(Cursor cursor) {
@@ -151,26 +124,4 @@ public class ContactsDictionary extends ExpandableDictionary {
        cursor.close();
    }

    private class LoadContactsTask extends AsyncTask<Void, Void, Void> {
        @Override
        protected Void doInBackground(Void... v) {
            Cursor cursor = getContext().getContentResolver()
                    .query(Contacts.CONTENT_URI, PROJECTION, null, null, null);
            if (cursor != null) {
                addWords(cursor);
            }
            mLastLoadedContacts = SystemClock.uptimeMillis();
            return null;
        }

        @Override
        protected void onPostExecute(Void result) {
            // TODO Auto-generated method stub
            synchronized (mUpdatingLock) {
                mUpdatingContacts = false;
            }
            super.onPostExecute(result);
        }
        
    }
}
+69 −0
Original line number Diff line number Diff line
@@ -16,7 +16,11 @@

package com.android.inputmethod.latin;

import com.android.inputmethod.latin.Dictionary.WordCallback;

import android.content.Context;
import android.os.AsyncTask;
import android.os.SystemClock;

/**
 * Base class for an in-memory dictionary that can grow dynamically and can
@@ -32,6 +36,13 @@ public class ExpandableDictionary extends Dictionary {
    public static final int MAX_WORD_LENGTH = 32;
    private static final char QUOTE = '\'';

    private boolean mRequiresReload;

    private boolean mUpdatingDictionary;

    // Use this lock before touching mUpdatingDictionary & mRequiresDownload
    private Object mUpdatingLock = new Object();

    static class Node {
        char code;
        int frequency;
@@ -70,6 +81,34 @@ public class ExpandableDictionary extends Dictionary {
        mCodes = new int[MAX_WORD_LENGTH][];
    }

    public void loadDictionary() {
        synchronized (mUpdatingLock) {
            startDictionaryLoadingTaskLocked();
        }
    }

    public void startDictionaryLoadingTaskLocked() {
        if (!mUpdatingDictionary) {
            mUpdatingDictionary = true;
            mRequiresReload = false;
            new LoadDictionaryTask().execute();
        }
    }

    public void setRequiresReload(boolean reload) {
        synchronized (mUpdatingLock) {
            mRequiresReload = reload;
        }
    }

    public boolean getRequiresReload() {
        return mRequiresReload;
    }

    /** Override to load your dictionary here, on a background thread. */
    public void loadDictionaryAsync() {
    }

    Context getContext() {
        return mContext;
    }
@@ -119,6 +158,13 @@ public class ExpandableDictionary extends Dictionary {
    @Override
    public void getWords(final WordComposer codes, final WordCallback callback,
            int[] nextLettersFrequencies) {
        synchronized (mUpdatingLock) {
            // If we need to update, start off a background task
            if (mRequiresReload) startDictionaryLoadingTaskLocked();
            // Currently updating contacts, don't return any results.
            if (mUpdatingDictionary) return;
        }

        mInputLength = codes.size();
        mNextLettersFrequencies = nextLettersFrequencies;
        if (mCodes.length < mInputLength) mCodes = new int[mInputLength][];
@@ -135,6 +181,11 @@ public class ExpandableDictionary extends Dictionary {

    @Override
    public synchronized boolean isValidWord(CharSequence word) {
        synchronized (mUpdatingLock) {
            // If we need to update, start off a background task
            if (mRequiresReload) startDictionaryLoadingTaskLocked();
            if (mUpdatingDictionary) return false;
        }
        final int freq = getWordFrequencyRec(mRoots, word, 0, word.length());
        return freq > -1;
    }
@@ -277,6 +328,24 @@ public class ExpandableDictionary extends Dictionary {
        mRoots = new NodeArray();
    }

    private class LoadDictionaryTask extends AsyncTask<Void, Void, Void> {
        @Override
        protected Void doInBackground(Void... v) {
            loadDictionaryAsync();
            return null;
        }

        @Override
        protected void onPostExecute(Void result) {
            // TODO Auto-generated method stub
            synchronized (mUpdatingLock) {
                mUpdatingDictionary = false;
            }
            super.onPostExecute(result);
        }
        
    }

    static char toLowerCase(char c) {
        if (c < BASE_CHARS.length) {
            c = BASE_CHARS[c];
+9 −16
Original line number Diff line number Diff line
@@ -16,16 +16,11 @@

package com.android.inputmethod.latin;

import java.util.ArrayList;
import java.util.List;
import java.util.Locale;

import android.content.ContentResolver;
import android.content.ContentValues;
import android.content.Context;
import android.database.ContentObserver;
import android.database.Cursor;
import android.net.Uri;
import android.provider.UserDictionary.Words;

public class UserDictionary extends ExpandableDictionary {
@@ -40,8 +35,6 @@ public class UserDictionary extends ExpandableDictionary {
    private static final int INDEX_FREQUENCY = 2;
    
    private ContentObserver mObserver;
    
    private boolean mRequiresReload;
    private String mLocale;

    public UserDictionary(Context context, String locale) {
@@ -54,7 +47,7 @@ public class UserDictionary extends ExpandableDictionary {
        cres.registerContentObserver(Words.CONTENT_URI, true, mObserver = new ContentObserver(null) {
            @Override
            public void onChange(boolean self) {
                mRequiresReload = true;
                setRequiresReload(true);
            }
        });

@@ -66,14 +59,15 @@ public class UserDictionary extends ExpandableDictionary {
            getContext().getContentResolver().unregisterContentObserver(mObserver);
            mObserver = null;
        }
        super.close();
    }

    private synchronized void loadDictionary() {
    @Override
    public void loadDictionaryAsync() {
        Cursor cursor = getContext().getContentResolver()
                .query(Words.CONTENT_URI, PROJECTION, "(locale IS NULL) or (locale=?)", 
                        new String[] { mLocale }, null);
        addWords(cursor);
        mRequiresReload = false;
    }

    /**
@@ -86,7 +80,8 @@ public class UserDictionary extends ExpandableDictionary {
     */
    @Override
    public synchronized void addWord(String word, int frequency) {
        if (mRequiresReload) loadDictionary();
        // Force load the dictionary here synchronously
        if (getRequiresReload()) loadDictionaryAsync();
        // Safeguard against adding long words. Can cause stack overflow.
        if (word.length() >= getMaxWordLength()) return;

@@ -101,19 +96,17 @@ public class UserDictionary extends ExpandableDictionary {

        getContext().getContentResolver().insert(Words.CONTENT_URI, values);
        // In case the above does a synchronous callback of the change observer
        mRequiresReload = false;
        setRequiresReload(false);
    }

    @Override
    public synchronized void getWords(final WordComposer codes, final WordCallback callback,
            int[] nextLettersFrequencies) {
        if (mRequiresReload) loadDictionary();
        super.getWords(codes, callback, nextLettersFrequencies);
    }

    @Override
    public synchronized boolean isValidWord(CharSequence word) {
        if (mRequiresReload) loadDictionary();
        return super.isValidWord(word);
    }