aboutsummaryrefslogtreecommitdiffstats
path: root/java/src
diff options
context:
space:
mode:
Diffstat (limited to 'java/src')
-rw-r--r--java/src/com/android/inputmethod/compat/AppWorkaroundsHelper.java29
-rw-r--r--java/src/com/android/inputmethod/compat/AppWorkaroundsUtils.java60
-rw-r--r--java/src/com/android/inputmethod/compat/IntentCompatUtils.java9
-rw-r--r--java/src/com/android/inputmethod/keyboard/internal/HermiteInterpolator.java5
-rw-r--r--java/src/com/android/inputmethod/latin/DictionaryPackInstallBroadcastReceiver.java2
-rw-r--r--java/src/com/android/inputmethod/latin/LatinIME.java41
-rw-r--r--java/src/com/android/inputmethod/latin/RichInputMethodManager.java7
-rw-r--r--java/src/com/android/inputmethod/latin/TargetPackageInfoGetterTask.java (renamed from java/src/com/android/inputmethod/latin/TargetApplicationGetter.java)36
-rw-r--r--java/src/com/android/inputmethod/latin/setup/LauncherIconVisibilityManager.java13
-rw-r--r--java/src/com/android/inputmethod/research/FeedbackLog.java32
-rw-r--r--java/src/com/android/inputmethod/research/ResearchLog.java11
-rw-r--r--java/src/com/android/inputmethod/research/ResearchLogger.java34
12 files changed, 220 insertions, 59 deletions
diff --git a/java/src/com/android/inputmethod/compat/AppWorkaroundsHelper.java b/java/src/com/android/inputmethod/compat/AppWorkaroundsHelper.java
new file mode 100644
index 000000000..21535e421
--- /dev/null
+++ b/java/src/com/android/inputmethod/compat/AppWorkaroundsHelper.java
@@ -0,0 +1,29 @@
+/*
+ * 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.compat;
+
+import android.content.pm.PackageInfo;
+
+public class AppWorkaroundsHelper {
+ private AppWorkaroundsHelper() {
+ // This helper class is not publicly instantiable.
+ }
+
+ public static boolean evaluateIsBrokenByRecorrection(final PackageInfo info) {
+ return false;
+ }
+}
diff --git a/java/src/com/android/inputmethod/compat/AppWorkaroundsUtils.java b/java/src/com/android/inputmethod/compat/AppWorkaroundsUtils.java
new file mode 100644
index 000000000..7e9e2e37b
--- /dev/null
+++ b/java/src/com/android/inputmethod/compat/AppWorkaroundsUtils.java
@@ -0,0 +1,60 @@
+/*
+ * 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.compat;
+
+import android.content.pm.PackageInfo;
+import android.os.Build.VERSION_CODES;
+
+/**
+ * A class to encapsulate work-arounds specific to particular apps.
+ */
+public class AppWorkaroundsUtils {
+ private PackageInfo mPackageInfo; // May be null
+ private boolean mIsBrokenByRecorrection = false;
+
+ public void setPackageInfo(final PackageInfo packageInfo) {
+ mPackageInfo = packageInfo;
+ mIsBrokenByRecorrection = AppWorkaroundsHelper.evaluateIsBrokenByRecorrection(
+ packageInfo);
+ }
+
+ public boolean isBrokenByRecorrection() {
+ return mIsBrokenByRecorrection;
+ }
+
+ public boolean isBeforeJellyBean() {
+ if (null == mPackageInfo || null == mPackageInfo.applicationInfo) {
+ return false;
+ }
+ return mPackageInfo.applicationInfo.targetSdkVersion < VERSION_CODES.JELLY_BEAN;
+ }
+
+ @Override
+ public String toString() {
+ if (null == mPackageInfo || null == mPackageInfo.applicationInfo) {
+ return "";
+ }
+ final StringBuilder s = new StringBuilder();
+ s.append("Target application : ")
+ .append(mPackageInfo.applicationInfo.name)
+ .append("\nPackage : ")
+ .append(mPackageInfo.applicationInfo.packageName)
+ .append("\nTarget app sdk version : ")
+ .append(mPackageInfo.applicationInfo.targetSdkVersion);
+ return s.toString();
+ }
+}
diff --git a/java/src/com/android/inputmethod/compat/IntentCompatUtils.java b/java/src/com/android/inputmethod/compat/IntentCompatUtils.java
index df2e22fe8..965a2a891 100644
--- a/java/src/com/android/inputmethod/compat/IntentCompatUtils.java
+++ b/java/src/com/android/inputmethod/compat/IntentCompatUtils.java
@@ -21,16 +21,15 @@ import android.content.Intent;
public final class IntentCompatUtils {
// Note that Intent.ACTION_USER_INITIALIZE have been introduced in API level 17
// (Build.VERSION_CODE.JELLY_BEAN_MR1).
- public static final String ACTION_USER_INITIALIZE =
- (String)CompatUtils.getFieldValue(null, null,
+ private static final String ACTION_USER_INITIALIZE =
+ (String)CompatUtils.getFieldValue(null /* receiver */, null /* defaultValue */,
CompatUtils.getField(Intent.class, "ACTION_USER_INITIALIZE"));
private IntentCompatUtils() {
// This utility class is not publicly instantiable.
}
- public static boolean has_ACTION_USER_INITIALIZE(final Intent intent) {
- return ACTION_USER_INITIALIZE != null && intent != null
- && ACTION_USER_INITIALIZE.equals(intent.getAction());
+ public static boolean is_ACTION_USER_INITIALIZE(final String action) {
+ return ACTION_USER_INITIALIZE != null && ACTION_USER_INITIALIZE.equals(action);
}
}
diff --git a/java/src/com/android/inputmethod/keyboard/internal/HermiteInterpolator.java b/java/src/com/android/inputmethod/keyboard/internal/HermiteInterpolator.java
index 0ec8153f5..b526a942a 100644
--- a/java/src/com/android/inputmethod/keyboard/internal/HermiteInterpolator.java
+++ b/java/src/com/android/inputmethod/keyboard/internal/HermiteInterpolator.java
@@ -16,8 +16,6 @@
package com.android.inputmethod.keyboard.internal;
-import com.android.inputmethod.annotations.UsedForTesting;
-
/**
* Interpolates XY-coordinates using Cubic Hermite Curve.
*/
@@ -54,7 +52,6 @@ public final class HermiteInterpolator {
* @param minPos the minimum index of left-open interval of valid data.
* @param maxPos the maximum index of left-open interval of valid data.
*/
- @UsedForTesting
public void reset(final int[] xCoords, final int[] yCoords, final int minPos,
final int maxPos) {
mXCoords = xCoords;
@@ -79,7 +76,6 @@ public final class HermiteInterpolator {
* valid points, <code>p3</code> must be equal or greater than <code>maxPos</code> of
* {@link #reset(int[],int[],int,int)}.
*/
- @UsedForTesting
public void setInterval(final int p0, final int p1, final int p2, final int p3) {
mP1X = mXCoords[p1];
mP1Y = mYCoords[p1];
@@ -152,7 +148,6 @@ public final class HermiteInterpolator {
*
* @param t the interpolation parameter. The value must be in close interval <code>[0,1]</code>.
*/
- @UsedForTesting
public void interpolate(final float t) {
final float omt = 1.0f - t;
final float tm2 = 2.0f * t;
diff --git a/java/src/com/android/inputmethod/latin/DictionaryPackInstallBroadcastReceiver.java b/java/src/com/android/inputmethod/latin/DictionaryPackInstallBroadcastReceiver.java
index 41fcb83e6..56096127e 100644
--- a/java/src/com/android/inputmethod/latin/DictionaryPackInstallBroadcastReceiver.java
+++ b/java/src/com/android/inputmethod/latin/DictionaryPackInstallBroadcastReceiver.java
@@ -75,7 +75,7 @@ public final class DictionaryPackInstallBroadcastReceiver extends BroadcastRecei
final String packageName = packageUri.getSchemeSpecificPart();
if (null == packageName) return;
// TODO: do this in a more appropriate place
- TargetApplicationGetter.removeApplicationInfoCache(packageName);
+ TargetPackageInfoGetterTask.removeCachedPackageInfo(packageName);
final PackageInfo packageInfo;
try {
packageInfo = manager.getPackageInfo(packageName, PackageManager.GET_PROVIDERS);
diff --git a/java/src/com/android/inputmethod/latin/LatinIME.java b/java/src/com/android/inputmethod/latin/LatinIME.java
index 883c9469b..f85c16be3 100644
--- a/java/src/com/android/inputmethod/latin/LatinIME.java
+++ b/java/src/com/android/inputmethod/latin/LatinIME.java
@@ -28,14 +28,13 @@ import android.content.DialogInterface;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.SharedPreferences;
-import android.content.pm.ApplicationInfo;
+import android.content.pm.PackageInfo;
import android.content.res.Configuration;
import android.content.res.Resources;
import android.graphics.Rect;
import android.inputmethodservice.InputMethodService;
import android.media.AudioManager;
import android.net.ConnectivityManager;
-import android.os.Build.VERSION_CODES;
import android.os.Debug;
import android.os.Handler;
import android.os.HandlerThread;
@@ -64,6 +63,7 @@ import android.view.inputmethod.InputMethodSubtype;
import com.android.inputmethod.accessibility.AccessibilityUtils;
import com.android.inputmethod.accessibility.AccessibleKeyboardViewProxy;
import com.android.inputmethod.annotations.UsedForTesting;
+import com.android.inputmethod.compat.AppWorkaroundsUtils;
import com.android.inputmethod.compat.InputMethodServiceCompatUtils;
import com.android.inputmethod.compat.SuggestionSpanUtils;
import com.android.inputmethod.dictionarypack.DictionaryPackConstants;
@@ -91,7 +91,7 @@ import java.util.TreeSet;
* Input method implementation for Qwerty'ish keyboard.
*/
public class LatinIME extends InputMethodService implements KeyboardActionListener,
- SuggestionStripView.Listener, TargetApplicationGetter.OnTargetApplicationKnownListener,
+ SuggestionStripView.Listener, TargetPackageInfoGetterTask.OnTargetPackageInfoKnownListener,
Suggest.SuggestInitializationListener {
private static final String TAG = LatinIME.class.getSimpleName();
private static final boolean TRACE = false;
@@ -141,7 +141,7 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
private SuggestedWords mSuggestedWords = SuggestedWords.EMPTY;
@UsedForTesting Suggest mSuggest;
private CompletionInfo[] mApplicationSpecifiedCompletions;
- private ApplicationInfo mTargetApplicationInfo;
+ private AppWorkaroundsUtils mAppWorkAroundsUtils = new AppWorkaroundsUtils();
private RichInputMethodManager mRichImm;
@UsedForTesting final KeyboardSwitcher mKeyboardSwitcher;
@@ -711,10 +711,11 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
Log.w(TAG, "Use EditorInfo.IME_FLAG_FORCE_ASCII flag instead");
}
- mTargetApplicationInfo =
- TargetApplicationGetter.getCachedApplicationInfo(editorInfo.packageName);
- if (null == mTargetApplicationInfo) {
- new TargetApplicationGetter(this /* context */, this /* listener */)
+ final PackageInfo packageInfo =
+ TargetPackageInfoGetterTask.getCachedPackageInfo(editorInfo.packageName);
+ mAppWorkAroundsUtils.setPackageInfo(packageInfo);
+ if (null == packageInfo) {
+ new TargetPackageInfoGetterTask(this /* context */, this /* listener */)
.execute(editorInfo.packageName);
}
@@ -819,10 +820,10 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
if (TRACE) Debug.startMethodTracing("/data/trace/latinime");
}
- // Callback for the TargetApplicationGetter
+ // Callback for the TargetPackageInfoGetterTask
@Override
- public void onTargetApplicationKnown(final ApplicationInfo info) {
- mTargetApplicationInfo = info;
+ public void onTargetPackageInfoKnown(final PackageInfo info) {
+ mAppWorkAroundsUtils.setPackageInfo(info);
}
@Override
@@ -1369,8 +1370,7 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
return;
}
- if (Constants.CODE_ENTER == code && mTargetApplicationInfo != null
- && mTargetApplicationInfo.targetSdkVersion < VERSION_CODES.JELLY_BEAN) {
+ if (Constants.CODE_ENTER == code && mAppWorkAroundsUtils.isBeforeJellyBean()) {
// Backward compatibility mode. Before Jelly bean, the keyboard would simulate
// a hardware keyboard event on pressing enter or delete. This is bad for many
// reasons (there are race conditions with commits) but some applications are
@@ -1864,8 +1864,7 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
// This should never happen.
Log.e(TAG, "Backspace when we don't know the selection position");
}
- if (mTargetApplicationInfo != null
- && mTargetApplicationInfo.targetSdkVersion < VERSION_CODES.JELLY_BEAN) {
+ if (mAppWorkAroundsUtils.isBeforeJellyBean()) {
// Backward compatibility mode. Before Jelly bean, the keyboard would simulate
// a hardware keyboard event on pressing enter or delete. This is bad for many
// reasons (there are race conditions with commits) but some applications are
@@ -2451,6 +2450,10 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
* do nothing.
*/
private void restartSuggestionsOnWordTouchedByCursor() {
+ // HACK: We may want to special-case some apps that exhibit bad behavior in case of
+ // recorrection. This is a temporary, stopgap measure that will be removed later.
+ // TODO: remove this.
+ if (mAppWorkAroundsUtils.isBrokenByRecorrection()) return;
// If the cursor is not touching a word, or if there is a selection, return right away.
if (mLastSelectionStart != mLastSelectionEnd) return;
// If we don't know the cursor location, return.
@@ -2783,12 +2786,8 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
}
public void debugDumpStateAndCrashWithException(final String context) {
- final StringBuilder s = new StringBuilder();
- s.append("Target application : ").append(mTargetApplicationInfo.name)
- .append("\nPackage : ").append(mTargetApplicationInfo.packageName)
- .append("\nTarget app sdk version : ")
- .append(mTargetApplicationInfo.targetSdkVersion)
- .append("\nAttributes : ").append(mSettings.getCurrent().mInputAttributes)
+ final StringBuilder s = new StringBuilder(mAppWorkAroundsUtils.toString());
+ s.append("\nAttributes : ").append(mSettings.getCurrent().mInputAttributes)
.append("\nContext : ").append(context);
throw new RuntimeException(s.toString());
}
diff --git a/java/src/com/android/inputmethod/latin/RichInputMethodManager.java b/java/src/com/android/inputmethod/latin/RichInputMethodManager.java
index 94513e635..0dd302afa 100644
--- a/java/src/com/android/inputmethod/latin/RichInputMethodManager.java
+++ b/java/src/com/android/inputmethod/latin/RichInputMethodManager.java
@@ -54,6 +54,13 @@ public final class RichInputMethodManager {
return sInstance;
}
+ // Caveat: This may cause IPC
+ public static boolean isInputMethodManagerValidForUserOfThisProcess(final Context context) {
+ // Basically called to check whether this IME has been triggered by the current user or not
+ return !((InputMethodManager)context.getSystemService(Context.INPUT_METHOD_SERVICE)).
+ getInputMethodList().isEmpty();
+ }
+
public static void init(final Context context) {
final SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context);
sInstance.initInternal(context, prefs);
diff --git a/java/src/com/android/inputmethod/latin/TargetApplicationGetter.java b/java/src/com/android/inputmethod/latin/TargetPackageInfoGetterTask.java
index 1ea4ac346..947b0c586 100644
--- a/java/src/com/android/inputmethod/latin/TargetApplicationGetter.java
+++ b/java/src/com/android/inputmethod/latin/TargetPackageInfoGetterTask.java
@@ -17,54 +17,54 @@
package com.android.inputmethod.latin;
import android.content.Context;
-import android.content.pm.ApplicationInfo;
+import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.os.AsyncTask;
import android.util.LruCache;
-public final class TargetApplicationGetter extends AsyncTask<String, Void, ApplicationInfo> {
+public final class TargetPackageInfoGetterTask extends
+ AsyncTask<String, Void, PackageInfo> {
private static final int MAX_CACHE_ENTRIES = 64; // arbitrary
- private static LruCache<String, ApplicationInfo> sCache =
- new LruCache<String, ApplicationInfo>(MAX_CACHE_ENTRIES);
+ private static final LruCache<String, PackageInfo> sCache =
+ new LruCache<String, PackageInfo>(MAX_CACHE_ENTRIES);
- public static ApplicationInfo getCachedApplicationInfo(final String packageName) {
+ public static PackageInfo getCachedPackageInfo(final String packageName) {
if (null == packageName) return null;
return sCache.get(packageName);
}
- public static void removeApplicationInfoCache(final String packageName) {
+ public static void removeCachedPackageInfo(final String packageName) {
sCache.remove(packageName);
}
- public interface OnTargetApplicationKnownListener {
- public void onTargetApplicationKnown(final ApplicationInfo info);
+ public interface OnTargetPackageInfoKnownListener {
+ public void onTargetPackageInfoKnown(final PackageInfo info);
}
private Context mContext;
- private final OnTargetApplicationKnownListener mListener;
+ private final OnTargetPackageInfoKnownListener mListener;
- public TargetApplicationGetter(final Context context,
- final OnTargetApplicationKnownListener listener) {
+ public TargetPackageInfoGetterTask(final Context context,
+ final OnTargetPackageInfoKnownListener listener) {
mContext = context;
mListener = listener;
}
@Override
- protected ApplicationInfo doInBackground(final String... packageName) {
+ protected PackageInfo doInBackground(final String... packageName) {
final PackageManager pm = mContext.getPackageManager();
mContext = null; // Bazooka-powered anti-leak device
try {
- final ApplicationInfo targetAppInfo =
- pm.getApplicationInfo(packageName[0], 0 /* flags */);
- sCache.put(packageName[0], targetAppInfo);
- return targetAppInfo;
+ final PackageInfo packageInfo = pm.getPackageInfo(packageName[0], 0 /* flags */);
+ sCache.put(packageName[0], packageInfo);
+ return packageInfo;
} catch (android.content.pm.PackageManager.NameNotFoundException e) {
return null;
}
}
@Override
- protected void onPostExecute(final ApplicationInfo info) {
- mListener.onTargetApplicationKnown(info);
+ protected void onPostExecute(final PackageInfo info) {
+ mListener.onTargetPackageInfoKnown(info);
}
}
diff --git a/java/src/com/android/inputmethod/latin/setup/LauncherIconVisibilityManager.java b/java/src/com/android/inputmethod/latin/setup/LauncherIconVisibilityManager.java
index 1b893a65d..604ebeeb6 100644
--- a/java/src/com/android/inputmethod/latin/setup/LauncherIconVisibilityManager.java
+++ b/java/src/com/android/inputmethod/latin/setup/LauncherIconVisibilityManager.java
@@ -68,8 +68,15 @@ public final class LauncherIconVisibilityManager extends BroadcastReceiver {
// 1) the package has been re-installed, 2) the device has been booted,
// 3) a multiuser has been created.
// There is no good reason to keep the process alive if this IME isn't a current IME.
- RichInputMethodManager.init(context);
- if (!SetupActivity.isThisImeCurrent(context)) {
+ final boolean isCurrentImeOfCurrentUser;
+ if (RichInputMethodManager.isInputMethodManagerValidForUserOfThisProcess(context)) {
+ RichInputMethodManager.init(context);
+ isCurrentImeOfCurrentUser = SetupActivity.isThisImeCurrent(context);
+ } else {
+ isCurrentImeOfCurrentUser = false;
+ }
+
+ if (!isCurrentImeOfCurrentUser) {
final int myPid = Process.myPid();
Log.i(TAG, "Killing my process: pid=" + myPid);
Process.killProcess(myPid);
@@ -84,7 +91,7 @@ public final class LauncherIconVisibilityManager extends BroadcastReceiver {
} else if (Intent.ACTION_BOOT_COMPLETED.equals(action)) {
Log.i(TAG, "Boot has been completed");
return true;
- } else if (IntentCompatUtils.has_ACTION_USER_INITIALIZE(intent)) {
+ } else if (IntentCompatUtils.is_ACTION_USER_INITIALIZE(action)) {
Log.i(TAG, "User initialize");
return true;
}
diff --git a/java/src/com/android/inputmethod/research/FeedbackLog.java b/java/src/com/android/inputmethod/research/FeedbackLog.java
new file mode 100644
index 000000000..5af194c32
--- /dev/null
+++ b/java/src/com/android/inputmethod/research/FeedbackLog.java
@@ -0,0 +1,32 @@
+/*
+ * 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.research;
+
+import android.content.Context;
+
+import java.io.File;
+
+public class FeedbackLog extends ResearchLog {
+ public FeedbackLog(final File outputFile, final Context context) {
+ super(outputFile, context);
+ }
+
+ @Override
+ public boolean isFeedbackLog() {
+ return true;
+ }
+}
diff --git a/java/src/com/android/inputmethod/research/ResearchLog.java b/java/src/com/android/inputmethod/research/ResearchLog.java
index 3e82139a6..fde2798e1 100644
--- a/java/src/com/android/inputmethod/research/ResearchLog.java
+++ b/java/src/com/android/inputmethod/research/ResearchLog.java
@@ -81,6 +81,17 @@ public class ResearchLog {
}
/**
+ * Returns true if this is a FeedbackLog.
+ *
+ * FeedbackLogs record only the data associated with a Feedback dialog. Instead of normal
+ * logging, they contain a LogStatement with the complete feedback string and optionally a
+ * recording of the user's supplied demo of the problem.
+ */
+ public boolean isFeedbackLog() {
+ return false;
+ }
+
+ /**
* Waits for any publication requests to finish and closes the {@link JsonWriter} used for
* output.
*
diff --git a/java/src/com/android/inputmethod/research/ResearchLogger.java b/java/src/com/android/inputmethod/research/ResearchLogger.java
index f426d58d5..0220e20bd 100644
--- a/java/src/com/android/inputmethod/research/ResearchLogger.java
+++ b/java/src/com/android/inputmethod/research/ResearchLogger.java
@@ -194,6 +194,8 @@ public class ResearchLogger implements SharedPreferences.OnSharedPreferenceChang
// gesture, and when committing the earlier word, split the LogUnit.
private long mSavedDownEventTime;
private Bundle mFeedbackDialogBundle = null;
+ // Whether the feedback dialog is visible, and the user is typing into it. Normal logging is
+ // not performed on text that the user types into the feedback dialog.
private boolean mInFeedbackDialog = false;
private Handler mUserRecordingTimeoutHandler;
private static final long USER_RECORDING_TIMEOUT_MS = 30L * DateUtils.SECOND_IN_MILLIS;
@@ -655,7 +657,7 @@ public class ResearchLogger implements SharedPreferences.OnSharedPreferenceChang
feedbackLogUnit.addLogStatement(LOGSTATEMENT_FEEDBACK, SystemClock.uptimeMillis(),
feedbackContents, accountName, recording);
- final ResearchLog feedbackLog = new ResearchLog(mResearchLogDirectory.getLogFilePath(
+ final ResearchLog feedbackLog = new FeedbackLog(mResearchLogDirectory.getLogFilePath(
System.currentTimeMillis(), System.nanoTime()), mLatinIME);
final LogBuffer feedbackLogBuffer = new LogBuffer();
feedbackLogBuffer.shiftIn(feedbackLogUnit);
@@ -718,8 +720,28 @@ public class ResearchLogger implements SharedPreferences.OnSharedPreferenceChang
mIsPasswordView = isPasswordView;
}
- private boolean isAllowedToLog() {
- return !mIsPasswordView && sIsLogging && !mInFeedbackDialog;
+ /**
+ * Returns true if logging is permitted.
+ *
+ * This method is called when adding a LogStatement to a LogUnit, and when adding a LogUnit to a
+ * ResearchLog. It is checked in both places in case conditions change between these times, and
+ * as a defensive measure in case refactoring changes the logging pipeline.
+ */
+ private boolean isAllowedToLogTo(final ResearchLog researchLog) {
+ // Logging is never allowed in these circumstances
+ if (mIsPasswordView) return false;
+ if (!sIsLogging) return false;
+ if (mInFeedbackDialog) {
+ // The FeedbackDialog is up. Normal logging should not happen (the user might be trying
+ // out things while the dialog is up, and their reporting of an issue may not be
+ // representative of what they normally type). However, after the user has finished
+ // entering their feedback, the logger packs their comments and an encoded version of
+ // any demonstration of the issue into a special "FeedbackLog". So if the FeedbackLog
+ // is the destination, we do want to allow logging to it.
+ return researchLog.isFeedbackLog();
+ }
+ // No other exclusions. Logging is permitted.
+ return true;
}
public void requestIndicatorRedraw() {
@@ -752,7 +774,7 @@ public class ResearchLogger implements SharedPreferences.OnSharedPreferenceChang
// and remove this method.
// The check for MainKeyboardView ensures that the indicator only decorates the main
// keyboard, not every keyboard.
- if (IS_SHOWING_INDICATOR && (isAllowedToLog() || isReplaying())
+ if (IS_SHOWING_INDICATOR && (isAllowedToLogTo(mMainResearchLog) || isReplaying())
&& view instanceof MainKeyboardView) {
final int savedColor = paint.getColor();
paint.setColor(getIndicatorColor());
@@ -787,7 +809,7 @@ public class ResearchLogger implements SharedPreferences.OnSharedPreferenceChang
private synchronized void enqueueEvent(final LogUnit logUnit, final LogStatement logStatement,
final Object... values) {
assert values.length == logStatement.getKeys().length;
- if (isAllowedToLog() && logUnit != null) {
+ if (isAllowedToLogTo(mMainResearchLog) && logUnit != null) {
final long time = SystemClock.uptimeMillis();
logUnit.addLogStatement(logStatement, time, values);
}
@@ -886,7 +908,7 @@ public class ResearchLogger implements SharedPreferences.OnSharedPreferenceChang
final ResearchLog researchLog, final boolean canIncludePrivateData) {
final LogUnit openingLogUnit = new LogUnit();
if (logUnits.isEmpty()) return;
- if (!isAllowedToLog()) return;
+ if (!isAllowedToLogTo(researchLog)) return;
// LogUnits not containing private data, such as contextual data for the log, do not require
// logSegment boundary statements.
if (canIncludePrivateData) {