aboutsummaryrefslogtreecommitdiffstats
path: root/java/src
diff options
context:
space:
mode:
Diffstat (limited to 'java/src')
-rw-r--r--java/src/com/android/inputmethod/keyboard/internal/KeyboardState.java2
-rw-r--r--java/src/com/android/inputmethod/latin/ExpandableBinaryDictionary.java10
-rw-r--r--java/src/com/android/inputmethod/latin/LatinIME.java4
-rw-r--r--java/src/com/android/inputmethod/latin/makedict/BinaryDictDecoderUtils.java1
-rw-r--r--java/src/com/android/inputmethod/latin/makedict/BinaryDictEncoderUtils.java8
-rw-r--r--java/src/com/android/inputmethod/latin/makedict/DynamicBinaryDictIOUtils.java5
-rw-r--r--java/src/com/android/inputmethod/latin/makedict/SparseTable.java131
-rw-r--r--java/src/com/android/inputmethod/latin/makedict/Ver3DictEncoder.java8
-rw-r--r--java/src/com/android/inputmethod/latin/makedict/Ver4DictDecoder.java5
-rw-r--r--java/src/com/android/inputmethod/latin/makedict/Ver4DictEncoder.java18
-rw-r--r--java/src/com/android/inputmethod/latin/personalization/DecayingExpandableBinaryDictionaryBase.java4
-rw-r--r--java/src/com/android/inputmethod/latin/personalization/DictionaryDecayBroadcastReciever.java66
-rw-r--r--java/src/com/android/inputmethod/latin/personalization/PersonalizationHelper.java13
13 files changed, 190 insertions, 85 deletions
diff --git a/java/src/com/android/inputmethod/keyboard/internal/KeyboardState.java b/java/src/com/android/inputmethod/keyboard/internal/KeyboardState.java
index 9f9fdaa6f..506dfa751 100644
--- a/java/src/com/android/inputmethod/keyboard/internal/KeyboardState.java
+++ b/java/src/com/android/inputmethod/keyboard/internal/KeyboardState.java
@@ -178,6 +178,8 @@ public final class KeyboardState {
if (!state.mIsAlphabetShiftLocked) {
setShifted(state.mShiftMode);
}
+ // TODO: is this the right place to do this? Should we do this in setShift* instead?
+ mSwitchActions.requestUpdatingShiftState();
} else {
mPrevMainKeyboardWasShiftLocked = state.mIsAlphabetShiftLocked;
}
diff --git a/java/src/com/android/inputmethod/latin/ExpandableBinaryDictionary.java b/java/src/com/android/inputmethod/latin/ExpandableBinaryDictionary.java
index 306c1a253..0985aae58 100644
--- a/java/src/com/android/inputmethod/latin/ExpandableBinaryDictionary.java
+++ b/java/src/com/android/inputmethod/latin/ExpandableBinaryDictionary.java
@@ -273,9 +273,9 @@ abstract public class ExpandableBinaryDictionary extends Dictionary {
lastModifiedTime);
}
- private void runGCIfRequired() {
+ protected void runGCIfRequired(final boolean mindsBlockByGC) {
if (!ENABLE_BINARY_DICTIONARY_DYNAMIC_UPDATE) return;
- if (mBinaryDictionary.needsToRunGC(true /* mindsBlockByGC */)) {
+ if (mBinaryDictionary.needsToRunGC(mindsBlockByGC)) {
if (setIsRegeneratingIfNotRegenerating()) {
getExecutor(mFilename).execute(new Runnable() {
@Override
@@ -300,7 +300,7 @@ abstract public class ExpandableBinaryDictionary extends Dictionary {
Log.w(TAG, "addWordDynamically is called for non-updatable dictionary: " + mFilename);
return;
}
- runGCIfRequired();
+ runGCIfRequired(true /* mindsBlockByGC */);
getExecutor(mFilename).execute(new Runnable() {
@Override
public void run() {
@@ -324,7 +324,7 @@ abstract public class ExpandableBinaryDictionary extends Dictionary {
+ mFilename);
return;
}
- runGCIfRequired();
+ runGCIfRequired(true /* mindsBlockByGC */);
getExecutor(mFilename).execute(new Runnable() {
@Override
public void run() {
@@ -348,7 +348,7 @@ abstract public class ExpandableBinaryDictionary extends Dictionary {
+ mFilename);
return;
}
- runGCIfRequired();
+ runGCIfRequired(true /* mindsBlockByGC */);
getExecutor(mFilename).execute(new Runnable() {
@Override
public void run() {
diff --git a/java/src/com/android/inputmethod/latin/LatinIME.java b/java/src/com/android/inputmethod/latin/LatinIME.java
index 96e16de0d..0f3d28976 100644
--- a/java/src/com/android/inputmethod/latin/LatinIME.java
+++ b/java/src/com/android/inputmethod/latin/LatinIME.java
@@ -77,6 +77,7 @@ import com.android.inputmethod.keyboard.MainKeyboardView;
import com.android.inputmethod.latin.Suggest.OnGetSuggestedWordsCallback;
import com.android.inputmethod.latin.SuggestedWords.SuggestedWordInfo;
import com.android.inputmethod.latin.define.ProductionFlag;
+import com.android.inputmethod.latin.personalization.DictionaryDecayBroadcastReciever;
import com.android.inputmethod.latin.personalization.PersonalizationDictionary;
import com.android.inputmethod.latin.personalization.PersonalizationDictionarySessionRegister;
import com.android.inputmethod.latin.personalization.PersonalizationHelper;
@@ -567,6 +568,8 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
newDictFilter.addAction(DictionaryPackConstants.NEW_DICTIONARY_INTENT_ACTION);
registerReceiver(mDictionaryPackInstallReceiver, newDictFilter);
+ DictionaryDecayBroadcastReciever.setUpIntervalAlarmForDictionaryDecaying(this);
+
mInputUpdater = new InputUpdater(this);
}
@@ -2929,6 +2932,7 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
return;
}
tryFixLyingCursorPosition();
+ mKeyboardSwitcher.updateShiftState();
if (tryResumeSuggestions) mHandler.postResumeSuggestions();
}
diff --git a/java/src/com/android/inputmethod/latin/makedict/BinaryDictDecoderUtils.java b/java/src/com/android/inputmethod/latin/makedict/BinaryDictDecoderUtils.java
index 665c7a27c..2c3d1346f 100644
--- a/java/src/com/android/inputmethod/latin/makedict/BinaryDictDecoderUtils.java
+++ b/java/src/com/android/inputmethod/latin/makedict/BinaryDictDecoderUtils.java
@@ -295,7 +295,6 @@ public final class BinaryDictDecoderUtils {
return address;
}
}
- int address;
switch (optionFlags & FormatSpec.MASK_CHILDREN_ADDRESS_TYPE) {
case FormatSpec.FLAG_CHILDREN_ADDRESS_TYPE_ONEBYTE:
return dictBuffer.readUnsignedByte();
diff --git a/java/src/com/android/inputmethod/latin/makedict/BinaryDictEncoderUtils.java b/java/src/com/android/inputmethod/latin/makedict/BinaryDictEncoderUtils.java
index af61f2979..b6024243f 100644
--- a/java/src/com/android/inputmethod/latin/makedict/BinaryDictEncoderUtils.java
+++ b/java/src/com/android/inputmethod/latin/makedict/BinaryDictEncoderUtils.java
@@ -278,7 +278,6 @@ public class BinaryDictEncoderUtils {
// For future reference, the code to remove duplicate is a simple : list.remove(node);
list.add(ptNodeArray);
final ArrayList<PtNode> branches = ptNodeArray.mData;
- final int nodeSize = branches.size();
for (PtNode ptNode : branches) {
if (null != ptNode.mChildren) flattenTreeInner(list, ptNode.mChildren);
}
@@ -427,9 +426,6 @@ public class BinaryDictEncoderUtils {
nodeCountSize + nodeArrayOffset + nodeffset;
nodeffset += ptNode.mCachedSize;
}
- final int nodeSize = nodeCountSize + nodeffset
- + (formatOptions.mSupportsDynamicUpdate
- ? FormatSpec.FORWARD_LINK_ADDRESS_SIZE : 0);
nodeArrayOffset += nodeArray.mCachedSize;
}
return nodeArrayOffset;
@@ -653,8 +649,8 @@ public class BinaryDictEncoderUtils {
return flags;
}
- /* package */ static byte makePtNodeFlags(final PtNode node, final int ptNodeAddress,
- final int childrenOffset, final FormatOptions formatOptions) {
+ /* package */ static byte makePtNodeFlags(final PtNode node, final int childrenOffset,
+ final FormatOptions formatOptions) {
return (byte) makePtNodeFlags(node.mChars.length > 1, node.mFrequency >= 0,
getByteSize(childrenOffset),
node.mShortcutTargets != null && !node.mShortcutTargets.isEmpty(),
diff --git a/java/src/com/android/inputmethod/latin/makedict/DynamicBinaryDictIOUtils.java b/java/src/com/android/inputmethod/latin/makedict/DynamicBinaryDictIOUtils.java
index 411e265b3..5c6994119 100644
--- a/java/src/com/android/inputmethod/latin/makedict/DynamicBinaryDictIOUtils.java
+++ b/java/src/com/android/inputmethod/latin/makedict/DynamicBinaryDictIOUtils.java
@@ -59,7 +59,7 @@ public final class DynamicBinaryDictIOUtils {
throws IOException, UnsupportedFormatException {
final DictBuffer dictBuffer = dictDecoder.getDictBuffer();
dictBuffer.position(0);
- final FileHeader header = dictDecoder.readHeader();
+ dictDecoder.readHeader();
final int wordPosition = dictDecoder.getTerminalPosition(word);
if (wordPosition == FormatSpec.NOT_VALID_WORD) return;
@@ -142,8 +142,7 @@ public final class DynamicBinaryDictIOUtils {
final int originalPosition = dictBuffer.position();
dictBuffer.position(ptNodeOriginAddress);
final int flags = dictBuffer.readUnsignedByte();
- final int parentAddress = BinaryDictDecoderUtils.readParentAddress(dictBuffer,
- formatOptions);
+ BinaryDictDecoderUtils.readParentAddress(dictBuffer, formatOptions);
BinaryDictIOUtils.skipString(dictBuffer, (flags & FormatSpec.FLAG_HAS_MULTIPLE_CHARS) != 0);
if ((flags & FormatSpec.FLAG_IS_TERMINAL) != 0) dictBuffer.readUnsignedByte();
final int childrenOffset = newChildrenAddress == FormatSpec.NO_CHILDREN_ADDRESS
diff --git a/java/src/com/android/inputmethod/latin/makedict/SparseTable.java b/java/src/com/android/inputmethod/latin/makedict/SparseTable.java
index 96d057a44..7592a0c13 100644
--- a/java/src/com/android/inputmethod/latin/makedict/SparseTable.java
+++ b/java/src/com/android/inputmethod/latin/makedict/SparseTable.java
@@ -17,6 +17,7 @@
package com.android.inputmethod.latin.makedict;
import com.android.inputmethod.annotations.UsedForTesting;
+import com.android.inputmethod.latin.utils.CollectionUtils;
import java.io.File;
import java.io.FileInputStream;
@@ -37,35 +38,39 @@ public class SparseTable {
/**
* mLookupTable is indexed by terminal ID, containing exactly one entry for every mBlockSize
* terminals.
- * It contains at index i = j / mBlockSize the index in mContentsTable where the values for
- * terminals with IDs j to j + mBlockSize - 1 are stored as an mBlockSize-sized integer array.
+ * It contains at index i = j / mBlockSize the index in each ArrayList in mContentsTables where
+ * the values for terminals with IDs j to j + mBlockSize - 1 are stored as an mBlockSize-sized
+ * integer array.
*/
private final ArrayList<Integer> mLookupTable;
- private final ArrayList<Integer> mContentTable;
+ private final ArrayList<ArrayList<Integer>> mContentTables;
private final int mBlockSize;
+ private final int mContentTableCount;
public static final int NOT_EXIST = -1;
+ public static final int SIZE_OF_INT_IN_BYTES = 4;
@UsedForTesting
- public SparseTable(final int initialCapacity, final int blockSize) {
+ public SparseTable(final int initialCapacity, final int blockSize,
+ final int contentTableCount) {
mBlockSize = blockSize;
final int lookupTableSize = initialCapacity / mBlockSize
+ (initialCapacity % mBlockSize > 0 ? 1 : 0);
mLookupTable = new ArrayList<Integer>(Collections.nCopies(lookupTableSize, NOT_EXIST));
- mContentTable = new ArrayList<Integer>();
+ mContentTableCount = contentTableCount;
+ mContentTables = CollectionUtils.newArrayList();
+ for (int i = 0; i < mContentTableCount; ++i) {
+ mContentTables.add(new ArrayList<Integer>());
+ }
}
@UsedForTesting
- public SparseTable(final int[] lookupTable, final int[] contentTable, final int blockSize) {
+ public SparseTable(final ArrayList<Integer> lookupTable,
+ final ArrayList<ArrayList<Integer>> contentTables, final int blockSize) {
mBlockSize = blockSize;
- mLookupTable = new ArrayList<Integer>(lookupTable.length);
- for (int i = 0; i < lookupTable.length; ++i) {
- mLookupTable.add(lookupTable[i]);
- }
- mContentTable = new ArrayList<Integer>(contentTable.length);
- for (int i = 0; i < contentTable.length; ++i) {
- mContentTable.add(contentTable[i]);
- }
+ mContentTableCount = contentTables.size();
+ mLookupTable = lookupTable;
+ mContentTables = contentTables;
}
/**
@@ -75,8 +80,8 @@ public class SparseTable {
* Otherwise, IndexOutOfBoundsException will be raised.
*/
@UsedForTesting
- private static void convertByteArrayToIntegerArray(final byte[] byteArray,
- final ArrayList<Integer> integerArray) {
+ private static ArrayList<Integer> convertByteArrayToIntegerArray(final byte[] byteArray) {
+ final ArrayList<Integer> integerArray = new ArrayList<Integer>(byteArray.length / 4);
for (int i = 0; i < byteArray.length; i += 4) {
int value = 0;
for (int j = i; j < i + 4; ++j) {
@@ -85,39 +90,43 @@ public class SparseTable {
}
integerArray.add(value);
}
+ return integerArray;
}
@UsedForTesting
- public SparseTable(final byte[] lookupTable, final byte[] contentTable, final int blockSize) {
- mBlockSize = blockSize;
- mLookupTable = new ArrayList<Integer>(lookupTable.length / 4);
- mContentTable = new ArrayList<Integer>(contentTable.length / 4);
- convertByteArrayToIntegerArray(lookupTable, mLookupTable);
- convertByteArrayToIntegerArray(contentTable, mContentTable);
+ public int get(final int contentTableIndex, final int index) {
+ if (!contains(index)) {
+ return NOT_EXIST;
+ }
+ return mContentTables.get(contentTableIndex).get(
+ mLookupTable.get(index / mBlockSize) + (index % mBlockSize));
}
@UsedForTesting
- public int get(final int index) {
- if (index < 0 || index / mBlockSize >= mLookupTable.size()
- || mLookupTable.get(index / mBlockSize) == NOT_EXIST) {
- return NOT_EXIST;
+ public ArrayList<Integer> getAll(final int index) {
+ final ArrayList<Integer> ret = CollectionUtils.newArrayList();
+ for (int i = 0; i < mContentTableCount; ++i) {
+ ret.add(get(i, index));
}
- return mContentTable.get(mLookupTable.get(index / mBlockSize) + (index % mBlockSize));
+ return ret;
}
@UsedForTesting
- public void set(final int index, final int value) {
+ public void set(final int contentTableIndex, final int index, final int value) {
if (mLookupTable.get(index / mBlockSize) == NOT_EXIST) {
- mLookupTable.set(index / mBlockSize, mContentTable.size());
- for (int i = 0; i < mBlockSize; ++i) {
- mContentTable.add(NOT_EXIST);
+ mLookupTable.set(index / mBlockSize, mContentTables.get(contentTableIndex).size());
+ for (int i = 0; i < mContentTableCount; ++i) {
+ for (int j = 0; j < mBlockSize; ++j) {
+ mContentTables.get(i).add(NOT_EXIST);
+ }
}
}
- mContentTable.set(mLookupTable.get(index / mBlockSize) + (index % mBlockSize), value);
+ mContentTables.get(contentTableIndex).set(
+ mLookupTable.get(index / mBlockSize) + (index % mBlockSize), value);
}
- public void remove(final int index) {
- set(index, NOT_EXIST);
+ public void remove(final int indexOfContent, final int index) {
+ set(indexOfContent, index, NOT_EXIST);
}
@UsedForTesting
@@ -127,7 +136,8 @@ public class SparseTable {
@UsedForTesting
/* package */ int getContentTableSize() {
- return mContentTable.size();
+ // This class always has at least one content table.
+ return mContentTables.get(0).size();
}
@UsedForTesting
@@ -136,36 +146,51 @@ public class SparseTable {
}
public boolean contains(final int index) {
- return get(index) != NOT_EXIST;
+ if (index < 0 || index / mBlockSize >= mLookupTable.size()
+ || mLookupTable.get(index / mBlockSize) == NOT_EXIST) {
+ return false;
+ }
+ return true;
}
@UsedForTesting
- public void write(final OutputStream lookupOutStream, final OutputStream contentOutStream)
+ public void write(final OutputStream lookupOutStream, final OutputStream[] contentOutStreams)
throws IOException {
+ if (contentOutStreams.length != mContentTableCount) {
+ throw new RuntimeException(contentOutStreams.length + " streams are given, but the"
+ + " table has " + mContentTableCount + " content tables.");
+ }
for (final int index : mLookupTable) {
- BinaryDictEncoderUtils.writeUIntToStream(lookupOutStream, index, 4);
+ BinaryDictEncoderUtils.writeUIntToStream(lookupOutStream, index, SIZE_OF_INT_IN_BYTES);
}
- for (final int index : mContentTable) {
- BinaryDictEncoderUtils.writeUIntToStream(contentOutStream, index, 4);
+ for (int i = 0; i < contentOutStreams.length; ++i) {
+ for (final int data : mContentTables.get(i)) {
+ BinaryDictEncoderUtils.writeUIntToStream(contentOutStreams[i], data,
+ SIZE_OF_INT_IN_BYTES);
+ }
}
}
@UsedForTesting
- public void writeToFiles(final File lookupTableFile, final File contentFile)
+ public void writeToFiles(final File lookupTableFile, final File[] contentFiles)
throws IOException {
- FileOutputStream lookupTableOutStream = null;
- FileOutputStream contentOutStream = null;
+ FileOutputStream lookupTableOutStream = null;
+ final FileOutputStream[] contentTableOutStreams = new FileOutputStream[mContentTableCount];
try {
lookupTableOutStream = new FileOutputStream(lookupTableFile);
- contentOutStream = new FileOutputStream(contentFile);
- write(lookupTableOutStream, contentOutStream);
+ for (int i = 0; i < contentFiles.length; ++i) {
+ contentTableOutStreams[i] = new FileOutputStream(contentFiles[i]);
+ }
+ write(lookupTableOutStream, contentTableOutStreams);
} finally {
if (lookupTableOutStream != null) {
lookupTableOutStream.close();
}
- if (contentOutStream != null) {
- contentOutStream.close();
+ for (int i = 0; i < contentTableOutStreams.length; ++i) {
+ if (contentTableOutStreams[i] != null) {
+ contentTableOutStreams[i].close();
+ }
}
}
}
@@ -185,10 +210,14 @@ public class SparseTable {
}
@UsedForTesting
- public static SparseTable readFromFiles(final File lookupTableFile, final File contentFile,
+ public static SparseTable readFromFiles(final File lookupTableFile, final File[] contentFiles,
final int blockSize) throws IOException {
- final byte[] lookupTable = readFileToByteArray(lookupTableFile);
- final byte[] content = readFileToByteArray(contentFile);
- return new SparseTable(lookupTable, content, blockSize);
+ final ArrayList<ArrayList<Integer>> contentTables =
+ new ArrayList<ArrayList<Integer>>(contentFiles.length);
+ for (int i = 0; i < contentFiles.length; ++i) {
+ contentTables.add(convertByteArrayToIntegerArray(readFileToByteArray(contentFiles[i])));
+ }
+ return new SparseTable(convertByteArrayToIntegerArray(readFileToByteArray(lookupTableFile)),
+ contentTables, blockSize);
}
}
diff --git a/java/src/com/android/inputmethod/latin/makedict/Ver3DictEncoder.java b/java/src/com/android/inputmethod/latin/makedict/Ver3DictEncoder.java
index 76f0f4052..d9e19899c 100644
--- a/java/src/com/android/inputmethod/latin/makedict/Ver3DictEncoder.java
+++ b/java/src/com/android/inputmethod/latin/makedict/Ver3DictEncoder.java
@@ -133,12 +133,10 @@ public class Ver3DictEncoder implements DictEncoder {
countSize);
}
- private void writePtNodeFlags(final PtNode ptNode, final int parentAddress,
- final FormatOptions formatOptions) {
+ private void writePtNodeFlags(final PtNode ptNode, final FormatOptions formatOptions) {
final int childrenPos = BinaryDictEncoderUtils.getChildrenPosition(ptNode, formatOptions);
mPosition = BinaryDictEncoderUtils.writeUIntToBuffer(mBuffer, mPosition,
- BinaryDictEncoderUtils.makePtNodeFlags(ptNode, mPosition, childrenPos,
- formatOptions),
+ BinaryDictEncoderUtils.makePtNodeFlags(ptNode, childrenPos, formatOptions),
FormatSpec.PTNODE_FLAGS_SIZE);
}
@@ -244,7 +242,7 @@ public class Ver3DictEncoder implements DictEncoder {
@Override
public void writePtNode(final PtNode ptNode, final int parentPosition,
final FormatOptions formatOptions, final FusionDictionary dict) {
- writePtNodeFlags(ptNode, parentPosition, formatOptions);
+ writePtNodeFlags(ptNode, formatOptions);
writeParentPosition(parentPosition, ptNode, formatOptions);
writeCharacters(ptNode.mChars, ptNode.hasSeveralChars());
writeFrequency(ptNode.mFrequency);
diff --git a/java/src/com/android/inputmethod/latin/makedict/Ver4DictDecoder.java b/java/src/com/android/inputmethod/latin/makedict/Ver4DictDecoder.java
index 89370f0dc..624b2784f 100644
--- a/java/src/com/android/inputmethod/latin/makedict/Ver4DictDecoder.java
+++ b/java/src/com/android/inputmethod/latin/makedict/Ver4DictDecoder.java
@@ -95,7 +95,6 @@ public class Ver4DictDecoder extends DictDecoder {
@Override
public void openDictBuffer() throws FileNotFoundException, IOException {
- final String filename = mDictDirectory.getName();
mDictBuffer = mBufferFactory.getDictionaryBuffer(getFile(FILETYPE_TRIE));
mFrequencyBuffer = mBufferFactory.getDictionaryBuffer(getFile(FILETYPE_FREQUENCY));
mTerminalAddressTableBuffer = mBufferFactory.getDictionaryBuffer(
@@ -131,7 +130,7 @@ public class Ver4DictDecoder extends DictDecoder {
mDictDirectory.getName() + FormatSpec.BIGRAM_LOOKUP_TABLE_FILE_EXTENSION);
final File contentFile = new File(mDictDirectory,
mDictDirectory.getName() + FormatSpec.BIGRAM_ADDRESS_TABLE_FILE_EXTENSION);
- mBigramAddressTable = SparseTable.readFromFiles(lookupIndexFile, contentFile,
+ mBigramAddressTable = SparseTable.readFromFiles(lookupIndexFile, new File[] { contentFile },
FormatSpec.BIGRAM_ADDRESS_TABLE_BLOCK_SIZE);
}
@@ -208,7 +207,7 @@ public class Ver4DictDecoder extends DictDecoder {
final ArrayList<PendingAttribute> bigrams;
if (0 != (flags & FormatSpec.FLAG_HAS_BIGRAMS)) {
bigrams = new ArrayList<PendingAttribute>();
- final int posOfBigrams = mBigramAddressTable.get(terminalId);
+ final int posOfBigrams = mBigramAddressTable.get(0 /* contentTableIndex */, terminalId);
mBigramBuffer.position(posOfBigrams);
while (bigrams.size() < FormatSpec.MAX_BIGRAMS_IN_A_PTNODE) {
// If bigrams.size() reaches FormatSpec.MAX_BIGRAMS_IN_A_PTNODE,
diff --git a/java/src/com/android/inputmethod/latin/makedict/Ver4DictEncoder.java b/java/src/com/android/inputmethod/latin/makedict/Ver4DictEncoder.java
index 4c25faf88..a403e25db 100644
--- a/java/src/com/android/inputmethod/latin/makedict/Ver4DictEncoder.java
+++ b/java/src/com/android/inputmethod/latin/makedict/Ver4DictEncoder.java
@@ -136,7 +136,7 @@ public class Ver4DictEncoder implements DictEncoder {
writeTerminalData(flatNodes, terminalCount);
mBigramAddressTable = new SparseTable(terminalCount,
- FormatSpec.BIGRAM_ADDRESS_TABLE_BLOCK_SIZE);
+ FormatSpec.BIGRAM_ADDRESS_TABLE_BLOCK_SIZE, 1 /* contentTableCount */);
writeBigrams(flatNodes, dict);
writeBigramAddressSparseTable();
@@ -181,12 +181,10 @@ public class Ver4DictEncoder implements DictEncoder {
countSize);
}
- private void writePtNodeFlags(final PtNode ptNode, final int parentAddress,
- final FormatOptions formatOptions) {
+ private void writePtNodeFlags(final PtNode ptNode, final FormatOptions formatOptions) {
final int childrenPos = BinaryDictEncoderUtils.getChildrenPosition(ptNode, formatOptions);
mTriePos = BinaryDictEncoderUtils.writeUIntToBuffer(mTrieBuf, mTriePos,
- BinaryDictEncoderUtils.makePtNodeFlags(ptNode, mTriePos, childrenPos,
- formatOptions),
+ BinaryDictEncoderUtils.makePtNodeFlags(ptNode, childrenPos, formatOptions),
FormatSpec.PTNODE_FLAGS_SIZE);
}
@@ -231,8 +229,7 @@ public class Ver4DictEncoder implements DictEncoder {
while (shortcutIterator.hasNext()) {
final WeightedString target = shortcutIterator.next();
final int shortcutFlags = BinaryDictEncoderUtils.makeShortcutFlags(
- shortcutIterator.hasNext(),
- target.mFrequency);
+ shortcutIterator.hasNext(), target.mFrequency);
mTrieBuf[mTriePos++] = (byte)shortcutFlags;
final int shortcutShift = CharEncoding.writeString(mTrieBuf, mTriePos,
target.mWord);
@@ -254,7 +251,8 @@ public class Ver4DictEncoder implements DictEncoder {
for (final PtNode ptNode : nodeArray.mData) {
if (ptNode.mBigrams != null) {
final int startPos = bigramBuffer.size();
- mBigramAddressTable.set(ptNode.mTerminalId, startPos);
+ mBigramAddressTable.set(0 /* contentTableIndex */, ptNode.mTerminalId,
+ startPos);
final Iterator<WeightedString> bigramIterator = ptNode.mBigrams.iterator();
while (bigramIterator.hasNext()) {
final WeightedString bigram = bigramIterator.next();
@@ -280,7 +278,7 @@ public class Ver4DictEncoder implements DictEncoder {
new File(mDictDir, mBaseFilename + FormatSpec.BIGRAM_LOOKUP_TABLE_FILE_EXTENSION);
final File contentFile =
new File(mDictDir, mBaseFilename + FormatSpec.BIGRAM_ADDRESS_TABLE_FILE_EXTENSION);
- mBigramAddressTable.writeToFiles(lookupIndexFile, contentFile);
+ mBigramAddressTable.writeToFiles(lookupIndexFile, new File[] { contentFile });
}
@Override
@@ -292,7 +290,7 @@ public class Ver4DictEncoder implements DictEncoder {
@Override
public void writePtNode(final PtNode ptNode, final int parentPosition,
final FormatOptions formatOptions, final FusionDictionary dict) {
- writePtNodeFlags(ptNode, parentPosition, formatOptions);
+ writePtNodeFlags(ptNode, formatOptions);
writeParentPosition(parentPosition, ptNode, formatOptions);
writeCharacters(ptNode.mChars, ptNode.hasSeveralChars());
if (ptNode.isTerminal()) {
diff --git a/java/src/com/android/inputmethod/latin/personalization/DecayingExpandableBinaryDictionaryBase.java b/java/src/com/android/inputmethod/latin/personalization/DecayingExpandableBinaryDictionaryBase.java
index 7cf4f0c88..266216410 100644
--- a/java/src/com/android/inputmethod/latin/personalization/DecayingExpandableBinaryDictionaryBase.java
+++ b/java/src/com/android/inputmethod/latin/personalization/DecayingExpandableBinaryDictionaryBase.java
@@ -236,4 +236,8 @@ public abstract class DecayingExpandableBinaryDictionaryBase extends ExpandableB
// Then flush the cleared state of the dictionary on disk.
asyncFlashAllBinaryDictionary();
}
+
+ /* package */ void decayIfNeeded() {
+ runGCIfRequired(false /* mindsBlockByGC */);
+ }
}
diff --git a/java/src/com/android/inputmethod/latin/personalization/DictionaryDecayBroadcastReciever.java b/java/src/com/android/inputmethod/latin/personalization/DictionaryDecayBroadcastReciever.java
new file mode 100644
index 000000000..e9ca662e7
--- /dev/null
+++ b/java/src/com/android/inputmethod/latin/personalization/DictionaryDecayBroadcastReciever.java
@@ -0,0 +1,66 @@
+/*
+ * 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.personalization;
+
+import android.app.AlarmManager;
+import android.app.PendingIntent;
+import android.content.BroadcastReceiver;
+import android.content.Context;
+import android.content.Intent;
+
+import java.util.concurrent.TimeUnit;
+
+/**
+ * Broadcast receiver for periodically updating decaying dictionaries.
+ */
+public class DictionaryDecayBroadcastReciever extends BroadcastReceiver {
+ /**
+ * The root domain for the personalization.
+ */
+ private static final String PERSONALIZATION_DOMAIN =
+ "com.android.inputmethod.latin.personalization";
+
+ /**
+ * The action of the intent to tell the time to decay dictionaries.
+ */
+ private static final String DICTIONARY_DECAY_INTENT_ACTION =
+ PERSONALIZATION_DOMAIN + ".DICT_DECAY";
+
+ /**
+ * Interval to update for decaying dictionaries.
+ */
+ private static final long DICTIONARY_DECAY_INTERVAL = TimeUnit.MINUTES.toMillis(60);
+
+ public static void setUpIntervalAlarmForDictionaryDecaying(Context context) {
+ AlarmManager alarmManager = (AlarmManager)context.getSystemService(Context.ALARM_SERVICE);
+ final Intent updateIntent = new Intent(DICTIONARY_DECAY_INTENT_ACTION);
+ updateIntent.setClass(context, DictionaryDecayBroadcastReciever.class);
+ final long alarmTime = System.currentTimeMillis() + DICTIONARY_DECAY_INTERVAL;
+ final PendingIntent pendingIntent = PendingIntent.getBroadcast(context, 0 /* requestCode */,
+ updateIntent, PendingIntent.FLAG_CANCEL_CURRENT);
+ if (null != alarmManager) alarmManager.setInexactRepeating(AlarmManager.RTC,
+ alarmTime, DICTIONARY_DECAY_INTERVAL, pendingIntent);
+ }
+
+ @Override
+ public void onReceive(final Context context, final Intent intent) {
+ final String action = intent.getAction();
+ if (action.equals(DICTIONARY_DECAY_INTENT_ACTION)) {
+ PersonalizationHelper.tryDecayingAllOpeningUserHistoryDictionary();
+ }
+ }
+}
diff --git a/java/src/com/android/inputmethod/latin/personalization/PersonalizationHelper.java b/java/src/com/android/inputmethod/latin/personalization/PersonalizationHelper.java
index 8c9484b12..221ddeeba 100644
--- a/java/src/com/android/inputmethod/latin/personalization/PersonalizationHelper.java
+++ b/java/src/com/android/inputmethod/latin/personalization/PersonalizationHelper.java
@@ -29,7 +29,6 @@ import java.util.concurrent.ConcurrentHashMap;
public class PersonalizationHelper {
private static final String TAG = PersonalizationHelper.class.getSimpleName();
private static final boolean DEBUG = false;
-
private static final ConcurrentHashMap<String, SoftReference<UserHistoryDictionary>>
sLangUserHistoryDictCache = CollectionUtils.newConcurrentHashMap();
@@ -62,6 +61,18 @@ public class PersonalizationHelper {
}
}
+ public static void tryDecayingAllOpeningUserHistoryDictionary() {
+ for (final ConcurrentHashMap.Entry<String, SoftReference<UserHistoryDictionary>> entry
+ : sLangUserHistoryDictCache.entrySet()) {
+ if (entry.getValue() != null) {
+ final UserHistoryDictionary dict = entry.getValue().get();
+ if (dict != null) {
+ dict.decayIfNeeded();
+ }
+ }
+ }
+ }
+
public static void registerPersonalizationDictionaryUpdateSession(final Context context,
final PersonalizationDictionaryUpdateSession session, String locale) {
final PersonalizationPredictionDictionary predictionDictionary =