diff options
Diffstat (limited to 'java/src')
10 files changed, 174 insertions, 94 deletions
diff --git a/java/src/com/android/inputmethod/keyboard/PointerTracker.java b/java/src/com/android/inputmethod/keyboard/PointerTracker.java index 03d610a39..d4902ec28 100644 --- a/java/src/com/android/inputmethod/keyboard/PointerTracker.java +++ b/java/src/com/android/inputmethod/keyboard/PointerTracker.java @@ -688,7 +688,7 @@ public class PointerTracker implements PointerTrackerQueue.Element { mIsDetectingGesture = true; final int elapsedTimeFromFirstDown = (int)(eventTime - sGestureFirstDownTime); mGestureStrokeWithPreviewPoints.addPoint(x, y, elapsedTimeFromFirstDown, - false /* isHistorical */); + true /* isMajorEvent */); } private void onDownEventInternal(final int x, final int y, final long eventTime) { @@ -724,10 +724,10 @@ public class PointerTracker implements PointerTrackerQueue.Element { } private void onGestureMoveEvent(final int x, final int y, final long eventTime, - final boolean isHistorical, final Key key) { + final boolean isMajorEvent, final Key key) { final int gestureTime = (int)(eventTime - sGestureFirstDownTime); if (mIsDetectingGesture) { - mGestureStrokeWithPreviewPoints.addPoint(x, y, gestureTime, isHistorical); + mGestureStrokeWithPreviewPoints.addPoint(x, y, gestureTime, isMajorEvent); mayStartBatchInput(); if (sInGesture && key != null) { updateBatchInput(eventTime); @@ -752,7 +752,7 @@ public class PointerTracker implements PointerTrackerQueue.Element { final int historicalY = (int)me.getHistoricalY(pointerIndex, h); final long historicalTime = me.getHistoricalEventTime(h); onGestureMoveEvent(historicalX, historicalY, historicalTime, - true /* isHistorical */, null); + false /* isMajorEvent */, null); } } @@ -767,7 +767,7 @@ public class PointerTracker implements PointerTrackerQueue.Element { if (sShouldHandleGesture) { // Register move event on gesture tracker. - onGestureMoveEvent(x, y, eventTime, false /* isHistorical */, key); + onGestureMoveEvent(x, y, eventTime, true /* isMajorEvent */, key); if (sInGesture) { mIgnoreModifierKey = true; mTimerProxy.cancelLongPressTimer(); diff --git a/java/src/com/android/inputmethod/keyboard/internal/GestureStroke.java b/java/src/com/android/inputmethod/keyboard/internal/GestureStroke.java index f0be0ee94..73413f698 100644 --- a/java/src/com/android/inputmethod/keyboard/internal/GestureStroke.java +++ b/java/src/com/android/inputmethod/keyboard/internal/GestureStroke.java @@ -14,34 +14,45 @@ package com.android.inputmethod.keyboard.internal; +import android.util.Log; + import com.android.inputmethod.latin.InputPointers; import com.android.inputmethod.latin.ResizableIntArray; public class GestureStroke { + private static final String TAG = GestureStroke.class.getSimpleName(); + private static final boolean DEBUG = false; + public static final int DEFAULT_CAPACITY = 128; private final int mPointerId; private final ResizableIntArray mEventTimes = new ResizableIntArray(DEFAULT_CAPACITY); private final ResizableIntArray mXCoordinates = new ResizableIntArray(DEFAULT_CAPACITY); private final ResizableIntArray mYCoordinates = new ResizableIntArray(DEFAULT_CAPACITY); - private float mLength; private int mIncrementalRecognitionSize; private int mLastIncrementalBatchSize; - private long mLastPointTime; - private int mLastPointX; - private int mLastPointY; - - private int mMinGestureLength; // pixel - private int mMinGestureSampleLength; // pixel - private int mGestureRecognitionThreshold; // pixel / sec + private long mLastMajorEventTime; + private int mLastMajorEventX; + private int mLastMajorEventY; + + private int mKeyWidth; + private int mStartGestureLengthThreshold; // pixel + private int mMinGestureSamplingLength; // pixel + private int mGestureRecognitionSpeedThreshold; // pixel / sec + private int mDetectFastMoveSpeedThreshold; // pixel /sec + private int mDetectFastMoveTime; + private int mDetectFastMoveX; + private int mDetectFastMoveY; // TODO: Move some of these to resource. - private static final float MIN_GESTURE_LENGTH_RATIO_TO_KEY_WIDTH = 0.75f; - private static final int MIN_GESTURE_START_DURATION = 100; // msec + private static final float START_GESTURE_LENGTH_THRESHOLD_RATIO_TO_KEY_WIDTH = 0.75f; + private static final int START_GESTURE_DURATION_THRESHOLD = 70; // msec private static final int MIN_GESTURE_RECOGNITION_TIME = 100; // msec private static final float MIN_GESTURE_SAMPLING_RATIO_TO_KEY_WIDTH = 1.0f / 6.0f; private static final float GESTURE_RECOGNITION_SPEED_THRESHOLD_RATIO_TO_KEY_WIDTH = 5.5f; // keyWidth / sec + private static final float DETECT_FAST_MOVE_SPEED_THRESHOLD_RATIO_TO_KEY_WIDTH = + 5.0f; // keyWidth / sec private static final int MSEC_PER_SEC = 1000; public static final boolean hasRecognitionTimePast( @@ -54,64 +65,120 @@ public class GestureStroke { } public void setKeyboardGeometry(final int keyWidth) { + mKeyWidth = keyWidth; // TODO: Find an appropriate base metric for these length. Maybe diagonal length of the key? - mMinGestureLength = (int)(keyWidth * MIN_GESTURE_LENGTH_RATIO_TO_KEY_WIDTH); - mMinGestureSampleLength = (int)(keyWidth * MIN_GESTURE_SAMPLING_RATIO_TO_KEY_WIDTH); - mGestureRecognitionThreshold = + mStartGestureLengthThreshold = + (int)(keyWidth * START_GESTURE_LENGTH_THRESHOLD_RATIO_TO_KEY_WIDTH); + mMinGestureSamplingLength = (int)(keyWidth * MIN_GESTURE_SAMPLING_RATIO_TO_KEY_WIDTH); + mGestureRecognitionSpeedThreshold = (int)(keyWidth * GESTURE_RECOGNITION_SPEED_THRESHOLD_RATIO_TO_KEY_WIDTH); + mDetectFastMoveSpeedThreshold = + (int)(keyWidth * DETECT_FAST_MOVE_SPEED_THRESHOLD_RATIO_TO_KEY_WIDTH); + if (DEBUG) { + Log.d(TAG, "setKeyboardGeometry: keyWidth=" + keyWidth); + } } public boolean isStartOfAGesture() { + if (mDetectFastMoveTime == 0) { + return false; + } final int size = mEventTimes.getLength(); - final int downDuration = (size > 0) ? mEventTimes.get(size - 1) : 0; - return downDuration > MIN_GESTURE_START_DURATION && mLength > mMinGestureLength; + if (size <= 0) { + return false; + } + final int lastIndex = size - 1; + final int deltaTime = mEventTimes.get(lastIndex) - mDetectFastMoveTime; + final int deltaLength = getDistance( + mXCoordinates.get(lastIndex), mYCoordinates.get(lastIndex), + mDetectFastMoveX, mDetectFastMoveY); + final boolean isStartOfAGesture = deltaTime > START_GESTURE_DURATION_THRESHOLD + && deltaLength > mStartGestureLengthThreshold; + if (DEBUG) { + Log.d(TAG, "isStartOfAGesture: dT=" + deltaTime + " dL=" + deltaLength + + " points=" + size + (isStartOfAGesture ? " Detect start of a gesture" : "")); + } + return isStartOfAGesture; } public void reset() { - mLength = 0; mIncrementalRecognitionSize = 0; mLastIncrementalBatchSize = 0; - mLastPointTime = 0; mEventTimes.setLength(0); mXCoordinates.setLength(0); mYCoordinates.setLength(0); + mLastMajorEventTime = 0; + mDetectFastMoveTime = 0; + } + + private void appendPoint(final int x, final int y, final int time) { + mEventTimes.add(time); + mXCoordinates.add(x); + mYCoordinates.add(y); } - public void addPoint(final int x, final int y, final int time, final boolean isHistorical) { - final boolean needsSampling; + private void updateMajorEvent(final int x, final int y, final int time) { + mLastMajorEventTime = time; + mLastMajorEventX = x; + mLastMajorEventY = y; + } + + private int detectFastMove(final int x, final int y, final int time) { final int size = mEventTimes.getLength(); - if (size == 0) { - needsSampling = true; - } else { - final int lastIndex = size - 1; - final int lastX = mXCoordinates.get(lastIndex); - final int lastY = mYCoordinates.get(lastIndex); - final float dist = getDistance(lastX, lastY, x, y); - needsSampling = dist > mMinGestureSampleLength; - mLength += dist; + final int lastIndex = size - 1; + final int lastX = mXCoordinates.get(lastIndex); + final int lastY = mYCoordinates.get(lastIndex); + final int dist = getDistance(lastX, lastY, x, y); + final int msecs = time - mEventTimes.get(lastIndex); + if (msecs > 0) { + final int pixels = getDistance(lastX, lastY, x, y); + final int pixelsPerSec = pixels * MSEC_PER_SEC; + if (DEBUG) { + final float speed = (float)pixelsPerSec / msecs / mKeyWidth; + Log.d(TAG, String.format("Speed=%.3f keyWidth/sec", speed)); + } + // Equivalent to (pixels / msecs < mStartSpeedThreshold / MSEC_PER_SEC) + if (mDetectFastMoveTime == 0 && pixelsPerSec > mDetectFastMoveSpeedThreshold * msecs) { + if (DEBUG) { + Log.d(TAG, "Detect fast move: T=" + time + " points = " + size); + } + mDetectFastMoveTime = time; + mDetectFastMoveX = x; + mDetectFastMoveY = y; + } } - if (needsSampling) { - mEventTimes.add(time); - mXCoordinates.add(x); - mYCoordinates.add(y); + return dist; + } + + public void addPoint(final int x, final int y, final int time, final boolean isMajorEvent) { + final int size = mEventTimes.getLength(); + if (size <= 0) { + // Down event + appendPoint(x, y, time); + updateMajorEvent(x, y, time); + } else { + final int dist = detectFastMove(x, y, time); + if (dist > mMinGestureSamplingLength) { + appendPoint(x, y, time); + } } - if (!isHistorical) { + if (isMajorEvent) { updateIncrementalRecognitionSize(x, y, time); + updateMajorEvent(x, y, time); } } private void updateIncrementalRecognitionSize(final int x, final int y, final int time) { - final int msecs = (int)(time - mLastPointTime); - if (msecs > 0) { - final int pixels = (int)getDistance(mLastPointX, mLastPointY, x, y); - // Equivalent to (pixels / msecs < mGestureRecognitionThreshold / MSEC_PER_SEC) - if (pixels * MSEC_PER_SEC < mGestureRecognitionThreshold * msecs) { - mIncrementalRecognitionSize = mEventTimes.getLength(); - } + final int msecs = (int)(time - mLastMajorEventTime); + if (msecs <= 0) { + return; + } + final int pixels = getDistance(mLastMajorEventX, mLastMajorEventY, x, y); + final int pixelsPerSec = pixels * MSEC_PER_SEC; + // Equivalent to (pixels / msecs < mGestureRecognitionThreshold / MSEC_PER_SEC) + if (pixelsPerSec < mGestureRecognitionSpeedThreshold * msecs) { + mIncrementalRecognitionSize = mEventTimes.getLength(); } - mLastPointTime = time; - mLastPointX = x; - mLastPointY = y; } public void appendAllBatchPoints(final InputPointers out) { @@ -132,11 +199,11 @@ public class GestureStroke { mLastIncrementalBatchSize = size; } - private static float getDistance(final int x1, final int y1, final int x2, final int y2) { - final float dx = x1 - x2; - final float dy = y1 - y2; + private static int getDistance(final int x1, final int y1, final int x2, final int y2) { + final int dx = x1 - x2; + final int dy = y1 - y2; // Note that, in recent versions of Android, FloatMath is actually slower than // java.lang.Math due to the way the JIT optimizes java.lang.Math. - return (float)Math.sqrt(dx * dx + dy * dy); + return (int)Math.sqrt(dx * dx + dy * dy); } } diff --git a/java/src/com/android/inputmethod/keyboard/internal/GestureStrokeWithPreviewPoints.java b/java/src/com/android/inputmethod/keyboard/internal/GestureStrokeWithPreviewPoints.java index ce3914076..3487b5018 100644 --- a/java/src/com/android/inputmethod/keyboard/internal/GestureStrokeWithPreviewPoints.java +++ b/java/src/com/android/inputmethod/keyboard/internal/GestureStrokeWithPreviewPoints.java @@ -65,21 +65,18 @@ public class GestureStrokeWithPreviewPoints extends GestureStroke { private boolean needsSampling(final int x, final int y) { final int dx = x - mLastX; final int dy = y - mLastY; - final boolean needsSampling = (dx * dx + dy * dy >= mMinPreviewSampleLengthSquare); - if (needsSampling) { - mLastX = x; - mLastY = y; - } - return needsSampling; + return dx * dx + dy * dy >= mMinPreviewSampleLengthSquare; } @Override - public void addPoint(final int x, final int y, final int time, final boolean isHistorical) { - super.addPoint(x, y, time, isHistorical); - if (mPreviewEventTimes.getLength() == 0 || isHistorical || needsSampling(x, y)) { + public void addPoint(final int x, final int y, final int time, final boolean isMajorEvent) { + super.addPoint(x, y, time, isMajorEvent); + if (isMajorEvent || needsSampling(x, y)) { mPreviewEventTimes.add(time); mPreviewXCoordinates.add(x); mPreviewYCoordinates.add(y); + mLastX = x; + mLastY = y; } } diff --git a/java/src/com/android/inputmethod/latin/BinaryDictionary.java b/java/src/com/android/inputmethod/latin/BinaryDictionary.java index c3ae81f3a..9244f16b1 100644 --- a/java/src/com/android/inputmethod/latin/BinaryDictionary.java +++ b/java/src/com/android/inputmethod/latin/BinaryDictionary.java @@ -45,7 +45,7 @@ public class BinaryDictionary extends Dictionary { public static final int MAX_WORDS = 18; public static final int MAX_SPACES = 16; - private static final String TAG = "BinaryDictionary"; + private static final String TAG = BinaryDictionary.class.getSimpleName(); private static final int MAX_PREDICTIONS = 60; private static final int MAX_RESULTS = Math.max(MAX_PREDICTIONS, MAX_WORDS); diff --git a/java/src/com/android/inputmethod/latin/DebugSettings.java b/java/src/com/android/inputmethod/latin/DebugSettings.java index af7649863..1ea14dad5 100644 --- a/java/src/com/android/inputmethod/latin/DebugSettings.java +++ b/java/src/com/android/inputmethod/latin/DebugSettings.java @@ -23,10 +23,12 @@ import android.content.pm.PackageManager.NameNotFoundException; import android.os.Bundle; import android.os.Process; import android.preference.CheckBoxPreference; +import android.preference.Preference; import android.preference.PreferenceFragment; import android.util.Log; import com.android.inputmethod.keyboard.KeyboardSwitcher; +import com.android.inputmethod.research.ResearchLogger; public class DebugSettings extends PreferenceFragment implements SharedPreferences.OnSharedPreferenceChangeListener { @@ -34,6 +36,7 @@ public class DebugSettings extends PreferenceFragment private static final String TAG = DebugSettings.class.getSimpleName(); private static final String DEBUG_MODE_KEY = "debug_mode"; public static final String FORCE_NON_DISTINCT_MULTITOUCH_KEY = "force_non_distinct_multitouch"; + public static final String PREF_USABILITY_STUDY_MODE = "usability_study_mode"; private boolean mServiceNeedsRestart = false; private CheckBoxPreference mDebugMode; @@ -45,6 +48,14 @@ public class DebugSettings extends PreferenceFragment SharedPreferences prefs = getPreferenceManager().getSharedPreferences(); prefs.registerOnSharedPreferenceChangeListener(this); + final Preference usabilityStudyPref = findPreference(PREF_USABILITY_STUDY_MODE); + if (usabilityStudyPref instanceof CheckBoxPreference) { + final CheckBoxPreference checkbox = (CheckBoxPreference)usabilityStudyPref; + checkbox.setChecked(prefs.getBoolean(PREF_USABILITY_STUDY_MODE, + ResearchLogger.DEFAULT_USABILITY_STUDY_MODE)); + checkbox.setSummary(R.string.settings_warning_researcher_mode); + } + mServiceNeedsRestart = false; mDebugMode = (CheckBoxPreference) findPreference(DEBUG_MODE_KEY); updateDebugMode(); diff --git a/java/src/com/android/inputmethod/latin/Settings.java b/java/src/com/android/inputmethod/latin/Settings.java index 9479a88a7..b984ec367 100644 --- a/java/src/com/android/inputmethod/latin/Settings.java +++ b/java/src/com/android/inputmethod/latin/Settings.java @@ -39,12 +39,10 @@ import android.widget.SeekBar.OnSeekBarChangeListener; import android.widget.TextView; import com.android.inputmethod.latin.define.ProductionFlag; -import com.android.inputmethod.research.ResearchLogger; import com.android.inputmethodcommon.InputMethodSettingsFragment; public final class Settings extends InputMethodSettingsFragment implements SharedPreferences.OnSharedPreferenceChangeListener { - public static final boolean ENABLE_INTERNAL_SETTINGS = ProductionFlag.IS_INTERNAL; // In the same order as xml/prefs.xml public static final String PREF_GENERAL_SETTINGS = "general_settings"; @@ -58,7 +56,6 @@ public final class Settings extends InputMethodSettingsFragment public static final String PREF_AUTO_CORRECTION_THRESHOLD = "auto_correction_threshold"; public static final String PREF_SHOW_SUGGESTIONS_SETTING = "show_suggestions_setting"; public static final String PREF_MISC_SETTINGS = "misc_settings"; - public static final String PREF_USABILITY_STUDY_MODE = "usability_study_mode"; public static final String PREF_LAST_USER_DICTIONARY_WRITE_TIME = "last_user_dictionary_write_time"; public static final String PREF_ADVANCED_SETTINGS = "pref_advanced_settings"; @@ -133,14 +130,6 @@ public final class Settings extends InputMethodSettingsFragment mAutoCorrectionThresholdPreference = (ListPreference) findPreference(PREF_AUTO_CORRECTION_THRESHOLD); mBigramPrediction = (CheckBoxPreference) findPreference(PREF_BIGRAM_PREDICTIONS); - mDebugSettingsPreference = findPreference(PREF_DEBUG_SETTINGS); - if (mDebugSettingsPreference != null) { - final Intent debugSettingsIntent = new Intent(Intent.ACTION_MAIN); - debugSettingsIntent.setClassName( - context.getPackageName(), DebugSettings.class.getName()); - mDebugSettingsPreference.setIntent(debugSettingsIntent); - } - ensureConsistencyOfAutoCorrectionSettings(); final PreferenceGroup generalSettings = @@ -150,6 +139,18 @@ public final class Settings extends InputMethodSettingsFragment final PreferenceGroup miscSettings = (PreferenceGroup) findPreference(PREF_MISC_SETTINGS); + mDebugSettingsPreference = findPreference(PREF_DEBUG_SETTINGS); + if (mDebugSettingsPreference != null) { + if (ProductionFlag.IS_INTERNAL) { + final Intent debugSettingsIntent = new Intent(Intent.ACTION_MAIN); + debugSettingsIntent.setClassName( + context.getPackageName(), DebugSettingsActivity.class.getName()); + mDebugSettingsPreference.setIntent(debugSettingsIntent); + } else { + miscSettings.removePreference(mDebugSettingsPreference); + } + } + final boolean showVoiceKeyOption = res.getBoolean( R.bool.config_enable_show_voice_key_option); if (!showVoiceKeyOption) { @@ -218,24 +219,6 @@ public final class Settings extends InputMethodSettingsFragment setPreferenceEnabled(gestureFloatingPreviewText, gestureInputEnabledByUser); } - final boolean showUsabilityStudyModeOption = - res.getBoolean(R.bool.config_enable_usability_study_mode_option) - || ProductionFlag.IS_EXPERIMENTAL || ENABLE_INTERNAL_SETTINGS; - final Preference usabilityStudyPref = findPreference(PREF_USABILITY_STUDY_MODE); - if (!showUsabilityStudyModeOption) { - if (usabilityStudyPref != null) { - miscSettings.removePreference(usabilityStudyPref); - } - } - if (ProductionFlag.IS_EXPERIMENTAL) { - if (usabilityStudyPref instanceof CheckBoxPreference) { - CheckBoxPreference checkbox = (CheckBoxPreference)usabilityStudyPref; - checkbox.setChecked(prefs.getBoolean(PREF_USABILITY_STUDY_MODE, - ResearchLogger.DEFAULT_USABILITY_STUDY_MODE)); - checkbox.setSummary(R.string.settings_warning_researcher_mode); - } - } - mKeypressVibrationDurationSettingsPref = (PreferenceScreen) findPreference(PREF_VIBRATION_DURATION_SETTINGS); if (mKeypressVibrationDurationSettingsPref != null) { diff --git a/java/src/com/android/inputmethod/latin/SettingsValues.java b/java/src/com/android/inputmethod/latin/SettingsValues.java index 9d8379a7a..5b8f1cfb4 100644 --- a/java/src/com/android/inputmethod/latin/SettingsValues.java +++ b/java/src/com/android/inputmethod/latin/SettingsValues.java @@ -410,7 +410,7 @@ public final class SettingsValues { // Likewise public static boolean getUsabilityStudyMode(final SharedPreferences prefs) { // TODO: use mUsabilityStudyMode instead of reading it again here - return prefs.getBoolean(Settings.PREF_USABILITY_STUDY_MODE, true); + return prefs.getBoolean(DebugSettings.PREF_USABILITY_STUDY_MODE, true); } public static long getLastUserHistoryWriteTime(final SharedPreferences prefs, diff --git a/java/src/com/android/inputmethod/latin/UserHistoryDictionary.java b/java/src/com/android/inputmethod/latin/UserHistoryDictionary.java index 683ee4f5c..e03af649c 100644 --- a/java/src/com/android/inputmethod/latin/UserHistoryDictionary.java +++ b/java/src/com/android/inputmethod/latin/UserHistoryDictionary.java @@ -42,7 +42,7 @@ import java.util.concurrent.locks.ReentrantLock; * cancellation or manual picks. This allows the keyboard to adapt to the typist over time. */ public class UserHistoryDictionary extends ExpandableDictionary { - private static final String TAG = "UserHistoryDictionary"; + private static final String TAG = UserHistoryDictionary.class.getSimpleName(); public static final boolean DBG_SAVE_RESTORE = false; public static final boolean DBG_STRESS_TEST = false; public static final boolean DBG_ALWAYS_WRITE = false; diff --git a/java/src/com/android/inputmethod/latin/makedict/BinaryDictIOUtils.java b/java/src/com/android/inputmethod/latin/makedict/BinaryDictIOUtils.java index 406071071..397532933 100644 --- a/java/src/com/android/inputmethod/latin/makedict/BinaryDictIOUtils.java +++ b/java/src/com/android/inputmethod/latin/makedict/BinaryDictIOUtils.java @@ -201,4 +201,26 @@ public class BinaryDictIOUtils { } return FormatSpec.NOT_VALID_WORD; } + + /** + * Delete the word from the binary file. + * + * @param buffer the buffer to write. + * @param word the word we delete + * @throws IOException + * @throws UnsupportedFormatException + */ + public static void deleteWord(final FusionDictionaryBufferInterface buffer, + final String word) throws IOException, UnsupportedFormatException { + buffer.position(0); + final FileHeader header = BinaryDictInputOutput.readHeader(buffer); + final int wordPosition = getTerminalPosition(buffer, word); + if (wordPosition == FormatSpec.NOT_VALID_WORD) return; + + buffer.position(wordPosition); + final int flags = buffer.readUnsignedByte(); + final int newFlags = flags ^ FormatSpec.FLAG_IS_TERMINAL; + buffer.position(wordPosition); + buffer.put((byte)newFlags); + } } diff --git a/java/src/com/android/inputmethod/latin/makedict/BinaryDictInputOutput.java b/java/src/com/android/inputmethod/latin/makedict/BinaryDictInputOutput.java index 1d3e94bb7..7b8dc5cc5 100644 --- a/java/src/com/android/inputmethod/latin/makedict/BinaryDictInputOutput.java +++ b/java/src/com/android/inputmethod/latin/makedict/BinaryDictInputOutput.java @@ -392,7 +392,7 @@ public class BinaryDictInputOutput { /** * Helper method to check whether the CharGroup has a parent address. */ - private static boolean hasParentAddress(final FormatOptions options) { + public static boolean hasParentAddress(final FormatOptions options) { return options.mVersion >= FormatSpec.FIRST_VERSION_WITH_PARENT_ADDRESS && options.mHasParentAddress; } |