parent
72c2feb573
commit
4be6198cb7
|
@ -28,8 +28,8 @@ import android.util.Log;
|
||||||
|
|
||||||
import com.android.inputmethod.compat.DownloadManagerCompatUtils;
|
import com.android.inputmethod.compat.DownloadManagerCompatUtils;
|
||||||
import com.android.inputmethod.latin.R;
|
import com.android.inputmethod.latin.R;
|
||||||
|
import com.android.inputmethod.latin.utils.ApplicationUtils;
|
||||||
import com.android.inputmethod.latin.utils.DebugLogUtils;
|
import com.android.inputmethod.latin.utils.DebugLogUtils;
|
||||||
import com.android.inputmethod.latin.utils.Utils;
|
|
||||||
|
|
||||||
import java.util.LinkedList;
|
import java.util.LinkedList;
|
||||||
import java.util.Queue;
|
import java.util.Queue;
|
||||||
|
@ -144,7 +144,7 @@ public final class ActionBatch {
|
||||||
// DownloadManager also stupidly cuts the extension to replace with its own that it
|
// DownloadManager also stupidly cuts the extension to replace with its own that it
|
||||||
// gets from the content-type. We need to circumvent this.
|
// gets from the content-type. We need to circumvent this.
|
||||||
final String disambiguator = "#" + System.currentTimeMillis()
|
final String disambiguator = "#" + System.currentTimeMillis()
|
||||||
+ Utils.getVersionName(context) + ".dict";
|
+ ApplicationUtils.getVersionName(context) + ".dict";
|
||||||
final Uri uri = Uri.parse(mWordList.mRemoteFilename + disambiguator);
|
final Uri uri = Uri.parse(mWordList.mRemoteFilename + disambiguator);
|
||||||
final Request request = new Request(uri);
|
final Request request = new Request(uri);
|
||||||
|
|
||||||
|
|
|
@ -38,8 +38,8 @@ import android.util.Log;
|
||||||
import com.android.inputmethod.compat.ConnectivityManagerCompatUtils;
|
import com.android.inputmethod.compat.ConnectivityManagerCompatUtils;
|
||||||
import com.android.inputmethod.compat.DownloadManagerCompatUtils;
|
import com.android.inputmethod.compat.DownloadManagerCompatUtils;
|
||||||
import com.android.inputmethod.latin.R;
|
import com.android.inputmethod.latin.R;
|
||||||
|
import com.android.inputmethod.latin.utils.ApplicationUtils;
|
||||||
import com.android.inputmethod.latin.utils.DebugLogUtils;
|
import com.android.inputmethod.latin.utils.DebugLogUtils;
|
||||||
import com.android.inputmethod.latin.utils.Utils;
|
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.io.FileInputStream;
|
import java.io.FileInputStream;
|
||||||
|
@ -222,7 +222,7 @@ public final class UpdateHandler {
|
||||||
// DownloadManager also stupidly cuts the extension to replace with its own that it
|
// DownloadManager also stupidly cuts the extension to replace with its own that it
|
||||||
// gets from the content-type. We need to circumvent this.
|
// gets from the content-type. We need to circumvent this.
|
||||||
final String disambiguator = "#" + System.currentTimeMillis()
|
final String disambiguator = "#" + System.currentTimeMillis()
|
||||||
+ Utils.getVersionName(context) + ".json";
|
+ ApplicationUtils.getVersionName(context) + ".json";
|
||||||
final Request metadataRequest = new Request(Uri.parse(metadataUri + disambiguator));
|
final Request metadataRequest = new Request(Uri.parse(metadataUri + disambiguator));
|
||||||
DebugLogUtils.l("Request =", metadataRequest);
|
DebugLogUtils.l("Request =", metadataRequest);
|
||||||
|
|
||||||
|
|
|
@ -70,7 +70,7 @@ import com.android.inputmethod.latin.utils.CoordinateUtils;
|
||||||
import com.android.inputmethod.latin.utils.ResourceUtils;
|
import com.android.inputmethod.latin.utils.ResourceUtils;
|
||||||
import com.android.inputmethod.latin.utils.StaticInnerHandlerWrapper;
|
import com.android.inputmethod.latin.utils.StaticInnerHandlerWrapper;
|
||||||
import com.android.inputmethod.latin.utils.StringUtils;
|
import com.android.inputmethod.latin.utils.StringUtils;
|
||||||
import com.android.inputmethod.latin.utils.Utils.UsabilityStudyLogUtils;
|
import com.android.inputmethod.latin.utils.UsabilityStudyLogUtils;
|
||||||
import com.android.inputmethod.research.ResearchLogger;
|
import com.android.inputmethod.research.ResearchLogger;
|
||||||
|
|
||||||
import java.util.Locale;
|
import java.util.Locale;
|
||||||
|
|
|
@ -25,7 +25,7 @@ import android.preference.PreferenceFragment;
|
||||||
import android.preference.PreferenceScreen;
|
import android.preference.PreferenceScreen;
|
||||||
|
|
||||||
import com.android.inputmethod.keyboard.KeyboardSwitcher;
|
import com.android.inputmethod.keyboard.KeyboardSwitcher;
|
||||||
import com.android.inputmethod.latin.utils.Utils;
|
import com.android.inputmethod.latin.utils.ApplicationUtils;
|
||||||
|
|
||||||
public final class DebugSettings extends PreferenceFragment
|
public final class DebugSettings extends PreferenceFragment
|
||||||
implements SharedPreferences.OnSharedPreferenceChangeListener {
|
implements SharedPreferences.OnSharedPreferenceChangeListener {
|
||||||
|
@ -118,7 +118,7 @@ public final class DebugSettings extends PreferenceFragment
|
||||||
}
|
}
|
||||||
boolean isDebugMode = mDebugMode.isChecked();
|
boolean isDebugMode = mDebugMode.isChecked();
|
||||||
final String version = getResources().getString(
|
final String version = getResources().getString(
|
||||||
R.string.version_text, Utils.getVersionName(getActivity()));
|
R.string.version_text, ApplicationUtils.getVersionName(getActivity()));
|
||||||
if (!isDebugMode) {
|
if (!isDebugMode) {
|
||||||
mDebugMode.setTitle(version);
|
mDebugMode.setTitle(version);
|
||||||
mDebugMode.setSummary("");
|
mDebugMode.setSummary("");
|
||||||
|
|
|
@ -76,19 +76,19 @@ import com.android.inputmethod.keyboard.MainKeyboardView;
|
||||||
import com.android.inputmethod.latin.SuggestedWords.SuggestedWordInfo;
|
import com.android.inputmethod.latin.SuggestedWords.SuggestedWordInfo;
|
||||||
import com.android.inputmethod.latin.define.ProductionFlag;
|
import com.android.inputmethod.latin.define.ProductionFlag;
|
||||||
import com.android.inputmethod.latin.suggestions.SuggestionStripView;
|
import com.android.inputmethod.latin.suggestions.SuggestionStripView;
|
||||||
|
import com.android.inputmethod.latin.utils.ApplicationUtils;
|
||||||
import com.android.inputmethod.latin.utils.CapsModeUtils;
|
import com.android.inputmethod.latin.utils.CapsModeUtils;
|
||||||
import com.android.inputmethod.latin.utils.CollectionUtils;
|
import com.android.inputmethod.latin.utils.CollectionUtils;
|
||||||
import com.android.inputmethod.latin.utils.CompletionInfoUtils;
|
import com.android.inputmethod.latin.utils.CompletionInfoUtils;
|
||||||
import com.android.inputmethod.latin.utils.InputTypeUtils;
|
import com.android.inputmethod.latin.utils.InputTypeUtils;
|
||||||
import com.android.inputmethod.latin.utils.IntentUtils;
|
import com.android.inputmethod.latin.utils.IntentUtils;
|
||||||
import com.android.inputmethod.latin.utils.JniUtils;
|
import com.android.inputmethod.latin.utils.JniUtils;
|
||||||
|
import com.android.inputmethod.latin.utils.LatinImeLoggerUtils;
|
||||||
import com.android.inputmethod.latin.utils.PositionalInfoForUserDictPendingAddition;
|
import com.android.inputmethod.latin.utils.PositionalInfoForUserDictPendingAddition;
|
||||||
import com.android.inputmethod.latin.utils.RecapitalizeStatus;
|
import com.android.inputmethod.latin.utils.RecapitalizeStatus;
|
||||||
import com.android.inputmethod.latin.utils.StaticInnerHandlerWrapper;
|
import com.android.inputmethod.latin.utils.StaticInnerHandlerWrapper;
|
||||||
import com.android.inputmethod.latin.utils.TargetPackageInfoGetterTask;
|
import com.android.inputmethod.latin.utils.TargetPackageInfoGetterTask;
|
||||||
import com.android.inputmethod.latin.utils.TextRange;
|
import com.android.inputmethod.latin.utils.TextRange;
|
||||||
import com.android.inputmethod.latin.utils.Utils;
|
|
||||||
import com.android.inputmethod.latin.utils.Utils.Stats;
|
|
||||||
import com.android.inputmethod.research.ResearchLogger;
|
import com.android.inputmethod.research.ResearchLogger;
|
||||||
|
|
||||||
import java.io.FileDescriptor;
|
import java.io.FileDescriptor;
|
||||||
|
@ -1551,7 +1551,7 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
|
||||||
if (SPACE_STATE_PHANTOM == spaceState) {
|
if (SPACE_STATE_PHANTOM == spaceState) {
|
||||||
if (mSettings.isInternal()) {
|
if (mSettings.isInternal()) {
|
||||||
if (mWordComposer.isComposingWord() && mWordComposer.isBatchMode()) {
|
if (mWordComposer.isComposingWord() && mWordComposer.isBatchMode()) {
|
||||||
Stats.onAutoCorrection(
|
LatinImeLoggerUtils.onAutoCorrection(
|
||||||
"", mWordComposer.getTypedWord(), " ", mWordComposer);
|
"", mWordComposer.getTypedWord(), " ", mWordComposer);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1612,7 +1612,8 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
|
||||||
if (mWordComposer.isComposingWord()) {
|
if (mWordComposer.isComposingWord()) {
|
||||||
if (mSettings.isInternal()) {
|
if (mSettings.isInternal()) {
|
||||||
if (mWordComposer.isBatchMode()) {
|
if (mWordComposer.isBatchMode()) {
|
||||||
Stats.onAutoCorrection("", mWordComposer.getTypedWord(), " ", mWordComposer);
|
LatinImeLoggerUtils.onAutoCorrection(
|
||||||
|
"", mWordComposer.getTypedWord(), " ", mWordComposer);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
final int wordComposerSize = mWordComposer.size();
|
final int wordComposerSize = mWordComposer.size();
|
||||||
|
@ -1860,7 +1861,7 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
|
||||||
} else {
|
} else {
|
||||||
if (mLastComposedWord.canRevertCommit()) {
|
if (mLastComposedWord.canRevertCommit()) {
|
||||||
if (mSettings.isInternal()) {
|
if (mSettings.isInternal()) {
|
||||||
Stats.onAutoCorrectionCancellation();
|
LatinImeLoggerUtils.onAutoCorrectionCancellation();
|
||||||
}
|
}
|
||||||
revertCommit();
|
revertCommit();
|
||||||
return;
|
return;
|
||||||
|
@ -2031,7 +2032,7 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
|
||||||
}
|
}
|
||||||
mHandler.postUpdateSuggestionStrip();
|
mHandler.postUpdateSuggestionStrip();
|
||||||
if (mSettings.isInternal()) {
|
if (mSettings.isInternal()) {
|
||||||
Utils.Stats.onNonSeparator((char)primaryCode, x, y);
|
LatinImeLoggerUtils.onNonSeparator((char)primaryCode, x, y);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2136,7 +2137,7 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
|
||||||
setPunctuationSuggestions();
|
setPunctuationSuggestions();
|
||||||
}
|
}
|
||||||
if (mSettings.isInternal()) {
|
if (mSettings.isInternal()) {
|
||||||
Utils.Stats.onSeparator((char)primaryCode, x, y);
|
LatinImeLoggerUtils.onSeparator((char)primaryCode, x, y);
|
||||||
}
|
}
|
||||||
|
|
||||||
mKeyboardSwitcher.updateShiftState();
|
mKeyboardSwitcher.updateShiftState();
|
||||||
|
@ -2325,7 +2326,8 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
|
||||||
+ "is empty? Impossible! I must commit suicide.");
|
+ "is empty? Impossible! I must commit suicide.");
|
||||||
}
|
}
|
||||||
if (mSettings.isInternal()) {
|
if (mSettings.isInternal()) {
|
||||||
Stats.onAutoCorrection(typedWord, autoCorrection, separatorString, mWordComposer);
|
LatinImeLoggerUtils.onAutoCorrection(
|
||||||
|
typedWord, autoCorrection, separatorString, mWordComposer);
|
||||||
}
|
}
|
||||||
if (ProductionFlag.USES_DEVELOPMENT_ONLY_DIAGNOSTICS) {
|
if (ProductionFlag.USES_DEVELOPMENT_ONLY_DIAGNOSTICS) {
|
||||||
final SuggestedWords suggestedWords = mSuggestedWords;
|
final SuggestedWords suggestedWords = mSuggestedWords;
|
||||||
|
@ -2429,7 +2431,7 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
|
||||||
&& !AutoCorrection.isValidWord(mSuggest, suggestion, true);
|
&& !AutoCorrection.isValidWord(mSuggest, suggestion, true);
|
||||||
|
|
||||||
if (mSettings.isInternal()) {
|
if (mSettings.isInternal()) {
|
||||||
Stats.onSeparator((char)Constants.CODE_SPACE,
|
LatinImeLoggerUtils.onSeparator((char)Constants.CODE_SPACE,
|
||||||
Constants.NOT_A_COORDINATE, Constants.NOT_A_COORDINATE);
|
Constants.NOT_A_COORDINATE, Constants.NOT_A_COORDINATE);
|
||||||
}
|
}
|
||||||
if (showingAddToDictionaryHint && mIsUserDictionaryAvailable) {
|
if (showingAddToDictionaryHint && mIsUserDictionaryAvailable) {
|
||||||
|
@ -2633,7 +2635,7 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
|
||||||
}
|
}
|
||||||
mConnection.commitText(originallyTypedWord + mLastComposedWord.mSeparatorString, 1);
|
mConnection.commitText(originallyTypedWord + mLastComposedWord.mSeparatorString, 1);
|
||||||
if (mSettings.isInternal()) {
|
if (mSettings.isInternal()) {
|
||||||
Stats.onSeparator(mLastComposedWord.mSeparatorString,
|
LatinImeLoggerUtils.onSeparator(mLastComposedWord.mSeparatorString,
|
||||||
Constants.NOT_A_COORDINATE, Constants.NOT_A_COORDINATE);
|
Constants.NOT_A_COORDINATE, Constants.NOT_A_COORDINATE);
|
||||||
}
|
}
|
||||||
if (ProductionFlag.USES_DEVELOPMENT_ONLY_DIAGNOSTICS) {
|
if (ProductionFlag.USES_DEVELOPMENT_ONLY_DIAGNOSTICS) {
|
||||||
|
@ -2787,7 +2789,7 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
|
||||||
final CharSequence[] items = new CharSequence[] {
|
final CharSequence[] items = new CharSequence[] {
|
||||||
// TODO: Should use new string "Select active input modes".
|
// TODO: Should use new string "Select active input modes".
|
||||||
getString(R.string.language_selection_title),
|
getString(R.string.language_selection_title),
|
||||||
getString(Utils.getAcitivityTitleResId(this, SettingsActivity.class)),
|
getString(ApplicationUtils.getAcitivityTitleResId(this, SettingsActivity.class)),
|
||||||
};
|
};
|
||||||
final DialogInterface.OnClickListener listener = new DialogInterface.OnClickListener() {
|
final DialogInterface.OnClickListener listener = new DialogInterface.OnClickListener() {
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -42,8 +42,8 @@ import com.android.inputmethod.latin.setup.LauncherIconVisibilityManager;
|
||||||
import com.android.inputmethod.latin.userdictionary.UserDictionaryList;
|
import com.android.inputmethod.latin.userdictionary.UserDictionaryList;
|
||||||
import com.android.inputmethod.latin.userdictionary.UserDictionarySettings;
|
import com.android.inputmethod.latin.userdictionary.UserDictionarySettings;
|
||||||
import com.android.inputmethod.latin.utils.AdditionalFeaturesSettingUtils;
|
import com.android.inputmethod.latin.utils.AdditionalFeaturesSettingUtils;
|
||||||
|
import com.android.inputmethod.latin.utils.ApplicationUtils;
|
||||||
import com.android.inputmethod.latin.utils.FeedbackUtils;
|
import com.android.inputmethod.latin.utils.FeedbackUtils;
|
||||||
import com.android.inputmethod.latin.utils.Utils;
|
|
||||||
import com.android.inputmethod.research.ResearchLogger;
|
import com.android.inputmethod.research.ResearchLogger;
|
||||||
import com.android.inputmethodcommon.InputMethodSettingsFragment;
|
import com.android.inputmethodcommon.InputMethodSettingsFragment;
|
||||||
|
|
||||||
|
@ -90,7 +90,7 @@ public final class SettingsFragment extends InputMethodSettingsFragment
|
||||||
final PreferenceScreen preferenceScreen = getPreferenceScreen();
|
final PreferenceScreen preferenceScreen = getPreferenceScreen();
|
||||||
if (preferenceScreen != null) {
|
if (preferenceScreen != null) {
|
||||||
preferenceScreen.setTitle(
|
preferenceScreen.setTitle(
|
||||||
Utils.getAcitivityTitleResId(getActivity(), SettingsActivity.class));
|
ApplicationUtils.getAcitivityTitleResId(getActivity(), SettingsActivity.class));
|
||||||
}
|
}
|
||||||
|
|
||||||
final Resources res = getResources();
|
final Resources res = getResources();
|
||||||
|
|
|
@ -75,6 +75,21 @@ public final class SuggestedWords {
|
||||||
return mSuggestedWordInfoList.get(index);
|
return mSuggestedWordInfoList.get(index);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public String getDebugString(final int pos) {
|
||||||
|
if (!LatinImeLogger.sDBG) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
final SuggestedWordInfo wordInfo = getInfo(pos);
|
||||||
|
if (wordInfo == null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
final String debugString = wordInfo.getDebugString();
|
||||||
|
if (TextUtils.isEmpty(debugString)) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
return debugString;
|
||||||
|
}
|
||||||
|
|
||||||
public boolean willAutoCorrect() {
|
public boolean willAutoCorrect() {
|
||||||
return mWillAutoCorrect;
|
return mWillAutoCorrect;
|
||||||
}
|
}
|
||||||
|
|
|
@ -21,7 +21,7 @@ import android.preference.PreferenceFragment;
|
||||||
import android.preference.PreferenceScreen;
|
import android.preference.PreferenceScreen;
|
||||||
|
|
||||||
import com.android.inputmethod.latin.R;
|
import com.android.inputmethod.latin.R;
|
||||||
import com.android.inputmethod.latin.utils.Utils;
|
import com.android.inputmethod.latin.utils.ApplicationUtils;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Preference screen.
|
* Preference screen.
|
||||||
|
@ -39,7 +39,7 @@ public final class SpellCheckerSettingsFragment extends PreferenceFragment {
|
||||||
addPreferencesFromResource(R.xml.spell_checker_settings);
|
addPreferencesFromResource(R.xml.spell_checker_settings);
|
||||||
final PreferenceScreen preferenceScreen = getPreferenceScreen();
|
final PreferenceScreen preferenceScreen = getPreferenceScreen();
|
||||||
if (preferenceScreen != null) {
|
if (preferenceScreen != null) {
|
||||||
preferenceScreen.setTitle(Utils.getAcitivityTitleResId(
|
preferenceScreen.setTitle(ApplicationUtils.getAcitivityTitleResId(
|
||||||
getActivity(), SpellCheckerSettingsActivity.class));
|
getActivity(), SpellCheckerSettingsActivity.class));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -31,7 +31,6 @@ import com.android.inputmethod.keyboard.internal.KeyboardParams;
|
||||||
import com.android.inputmethod.latin.R;
|
import com.android.inputmethod.latin.R;
|
||||||
import com.android.inputmethod.latin.SuggestedWords;
|
import com.android.inputmethod.latin.SuggestedWords;
|
||||||
import com.android.inputmethod.latin.SuggestedWords.SuggestedWordInfo;
|
import com.android.inputmethod.latin.SuggestedWords.SuggestedWordInfo;
|
||||||
import com.android.inputmethod.latin.utils.Utils;
|
|
||||||
|
|
||||||
public final class MoreSuggestions extends Keyboard {
|
public final class MoreSuggestions extends Keyboard {
|
||||||
public static final int SUGGESTION_CODE_BASE = 1024;
|
public static final int SUGGESTION_CODE_BASE = 1024;
|
||||||
|
@ -207,7 +206,7 @@ public final class MoreSuggestions extends Keyboard {
|
||||||
final int y = params.getY(index);
|
final int y = params.getY(index);
|
||||||
final int width = params.getWidth(index);
|
final int width = params.getWidth(index);
|
||||||
final String word = mSuggestedWords.getWord(index);
|
final String word = mSuggestedWords.getWord(index);
|
||||||
final String info = Utils.getDebugInfo(mSuggestedWords, index);
|
final String info = mSuggestedWords.getDebugString(index);
|
||||||
final int indexInMoreSuggestions = index + SUGGESTION_CODE_BASE;
|
final int indexInMoreSuggestions = index + SUGGESTION_CODE_BASE;
|
||||||
final Key key = new Key(
|
final Key key = new Key(
|
||||||
params, word, info, KeyboardIconsSet.ICON_UNDEFINED, indexInMoreSuggestions,
|
params, word, info, KeyboardIconsSet.ICON_UNDEFINED, indexInMoreSuggestions,
|
||||||
|
|
|
@ -51,7 +51,6 @@ import com.android.inputmethod.latin.LatinImeLogger;
|
||||||
import com.android.inputmethod.latin.R;
|
import com.android.inputmethod.latin.R;
|
||||||
import com.android.inputmethod.latin.SuggestedWords;
|
import com.android.inputmethod.latin.SuggestedWords;
|
||||||
import com.android.inputmethod.latin.utils.ResourceUtils;
|
import com.android.inputmethod.latin.utils.ResourceUtils;
|
||||||
import com.android.inputmethod.latin.utils.Utils;
|
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
|
||||||
|
@ -446,7 +445,7 @@ final class SuggestionStripLayoutHelper {
|
||||||
wordView.setTextColor(getSuggestionTextColor(positionInStrip, suggestedWords));
|
wordView.setTextColor(getSuggestionTextColor(positionInStrip, suggestedWords));
|
||||||
if (SuggestionStripView.DBG) {
|
if (SuggestionStripView.DBG) {
|
||||||
mDebugInfoViews.get(positionInStrip).setText(
|
mDebugInfoViews.get(positionInStrip).setText(
|
||||||
Utils.getDebugInfo(suggestedWords, indexInSuggestedWords));
|
suggestedWords.getDebugString(indexInSuggestedWords));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,65 @@
|
||||||
|
/*
|
||||||
|
* 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.app.Activity;
|
||||||
|
import android.content.ComponentName;
|
||||||
|
import android.content.Context;
|
||||||
|
import android.content.pm.ActivityInfo;
|
||||||
|
import android.content.pm.PackageInfo;
|
||||||
|
import android.content.pm.PackageManager.NameNotFoundException;
|
||||||
|
import android.util.Log;
|
||||||
|
|
||||||
|
public final class ApplicationUtils {
|
||||||
|
private static final String TAG = ApplicationUtils.class.getSimpleName();
|
||||||
|
|
||||||
|
private ApplicationUtils() {
|
||||||
|
// This utility class is not publicly instantiable.
|
||||||
|
}
|
||||||
|
|
||||||
|
public static int getAcitivityTitleResId(final Context context,
|
||||||
|
final Class<? extends Activity> cls) {
|
||||||
|
final ComponentName cn = new ComponentName(context, cls);
|
||||||
|
try {
|
||||||
|
final ActivityInfo ai = context.getPackageManager().getActivityInfo(cn, 0);
|
||||||
|
if (ai != null) {
|
||||||
|
return ai.labelRes;
|
||||||
|
}
|
||||||
|
} catch (final NameNotFoundException e) {
|
||||||
|
Log.e(TAG, "Failed to get settings activity title res id.", e);
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A utility method to get the application's PackageInfo.versionName
|
||||||
|
* @return the application's PackageInfo.versionName
|
||||||
|
*/
|
||||||
|
public static String getVersionName(final Context context) {
|
||||||
|
try {
|
||||||
|
if (context == null) {
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
final String packageName = context.getPackageName();
|
||||||
|
final PackageInfo info = context.getPackageManager().getPackageInfo(packageName, 0);
|
||||||
|
return info.versionName;
|
||||||
|
} catch (final NameNotFoundException e) {
|
||||||
|
Log.e(TAG, "Could not find version info.", e);
|
||||||
|
}
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,77 @@
|
||||||
|
/*
|
||||||
|
* 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.text.TextUtils;
|
||||||
|
|
||||||
|
import com.android.inputmethod.latin.Constants;
|
||||||
|
import com.android.inputmethod.latin.LatinImeLogger;
|
||||||
|
import com.android.inputmethod.latin.WordComposer;
|
||||||
|
|
||||||
|
public final class LatinImeLoggerUtils {
|
||||||
|
private LatinImeLoggerUtils() {
|
||||||
|
// This utility class is not publicly instantiable.
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void onNonSeparator(final char code, final int x, final int y) {
|
||||||
|
UserLogRingCharBuffer.getInstance().push(code, x, y);
|
||||||
|
LatinImeLogger.logOnInputChar();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void onSeparator(final int code, final int x, final int y) {
|
||||||
|
// Helper method to log a single code point separator
|
||||||
|
// TODO: cache this mapping of a code point to a string in a sparse array in StringUtils
|
||||||
|
onSeparator(new String(new int[]{code}, 0, 1), x, y);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void onSeparator(final String separator, final int x, final int y) {
|
||||||
|
final int length = separator.length();
|
||||||
|
for (int i = 0; i < length; i = Character.offsetByCodePoints(separator, i, 1)) {
|
||||||
|
int codePoint = Character.codePointAt(separator, i);
|
||||||
|
// TODO: accept code points
|
||||||
|
UserLogRingCharBuffer.getInstance().push((char)codePoint, x, y);
|
||||||
|
}
|
||||||
|
LatinImeLogger.logOnInputSeparator();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void onAutoCorrection(final String typedWord, final String correctedWord,
|
||||||
|
final String separatorString, final WordComposer wordComposer) {
|
||||||
|
final boolean isBatchMode = wordComposer.isBatchMode();
|
||||||
|
if (!isBatchMode && TextUtils.isEmpty(typedWord)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
// TODO: this fails when the separator is more than 1 code point long, but
|
||||||
|
// the backend can't handle it yet. The only case when this happens is with
|
||||||
|
// smileys and other multi-character keys.
|
||||||
|
final int codePoint = TextUtils.isEmpty(separatorString) ? Constants.NOT_A_CODE
|
||||||
|
: separatorString.codePointAt(0);
|
||||||
|
if (!isBatchMode) {
|
||||||
|
LatinImeLogger.logOnAutoCorrectionForTyping(typedWord, correctedWord, codePoint);
|
||||||
|
} else {
|
||||||
|
if (!TextUtils.isEmpty(correctedWord)) {
|
||||||
|
// We must make sure that InputPointer contains only the relative timestamps,
|
||||||
|
// not actual timestamps.
|
||||||
|
LatinImeLogger.logOnAutoCorrectionForGeometric(
|
||||||
|
"", correctedWord, codePoint, wordComposer.getInputPointers());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void onAutoCorrectionCancellation() {
|
||||||
|
LatinImeLogger.logOnAutoCorrectionCancelled();
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,255 @@
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2016 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.content.Intent;
|
||||||
|
import android.content.pm.PackageManager;
|
||||||
|
import android.inputmethodservice.InputMethodService;
|
||||||
|
import android.net.Uri;
|
||||||
|
import android.os.Environment;
|
||||||
|
import android.os.Handler;
|
||||||
|
import android.os.HandlerThread;
|
||||||
|
import android.os.Process;
|
||||||
|
import android.util.Log;
|
||||||
|
|
||||||
|
import com.android.inputmethod.latin.LatinImeLogger;
|
||||||
|
|
||||||
|
import java.io.BufferedReader;
|
||||||
|
import java.io.File;
|
||||||
|
import java.io.FileInputStream;
|
||||||
|
import java.io.FileNotFoundException;
|
||||||
|
import java.io.FileOutputStream;
|
||||||
|
import java.io.FileReader;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.PrintWriter;
|
||||||
|
import java.nio.channels.FileChannel;
|
||||||
|
import java.text.SimpleDateFormat;
|
||||||
|
import java.util.Date;
|
||||||
|
import java.util.Locale;
|
||||||
|
|
||||||
|
public final class UsabilityStudyLogUtils {
|
||||||
|
// TODO: remove code duplication with ResearchLog class
|
||||||
|
private static final String USABILITY_TAG = UsabilityStudyLogUtils.class.getSimpleName();
|
||||||
|
private static final String FILENAME = "log.txt";
|
||||||
|
private final Handler mLoggingHandler;
|
||||||
|
private File mFile;
|
||||||
|
private File mDirectory;
|
||||||
|
private InputMethodService mIms;
|
||||||
|
private PrintWriter mWriter;
|
||||||
|
private final Date mDate;
|
||||||
|
private final SimpleDateFormat mDateFormat;
|
||||||
|
|
||||||
|
private UsabilityStudyLogUtils() {
|
||||||
|
mDate = new Date();
|
||||||
|
mDateFormat = new SimpleDateFormat("yyyyMMdd-HHmmss.SSSZ", Locale.US);
|
||||||
|
|
||||||
|
HandlerThread handlerThread = new HandlerThread("UsabilityStudyLogUtils logging task",
|
||||||
|
Process.THREAD_PRIORITY_BACKGROUND);
|
||||||
|
handlerThread.start();
|
||||||
|
mLoggingHandler = new Handler(handlerThread.getLooper());
|
||||||
|
}
|
||||||
|
|
||||||
|
// Initialization-on-demand holder
|
||||||
|
private static final class OnDemandInitializationHolder {
|
||||||
|
public static final UsabilityStudyLogUtils sInstance = new UsabilityStudyLogUtils();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static UsabilityStudyLogUtils getInstance() {
|
||||||
|
return OnDemandInitializationHolder.sInstance;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void init(final InputMethodService ims) {
|
||||||
|
mIms = ims;
|
||||||
|
mDirectory = ims.getFilesDir();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void createLogFileIfNotExist() {
|
||||||
|
if ((mFile == null || !mFile.exists())
|
||||||
|
&& (mDirectory != null && mDirectory.exists())) {
|
||||||
|
try {
|
||||||
|
mWriter = getPrintWriter(mDirectory, FILENAME, false);
|
||||||
|
} catch (final IOException e) {
|
||||||
|
Log.e(USABILITY_TAG, "Can't create log file.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void writeBackSpace(final int x, final int y) {
|
||||||
|
UsabilityStudyLogUtils.getInstance().write("<backspace>\t" + x + "\t" + y);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void writeChar(final char c, final int x, final int y) {
|
||||||
|
String inputChar = String.valueOf(c);
|
||||||
|
switch (c) {
|
||||||
|
case '\n':
|
||||||
|
inputChar = "<enter>";
|
||||||
|
break;
|
||||||
|
case '\t':
|
||||||
|
inputChar = "<tab>";
|
||||||
|
break;
|
||||||
|
case ' ':
|
||||||
|
inputChar = "<space>";
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
UsabilityStudyLogUtils.getInstance().write(inputChar + "\t" + x + "\t" + y);
|
||||||
|
LatinImeLogger.onPrintAllUsabilityStudyLogs();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void write(final String log) {
|
||||||
|
mLoggingHandler.post(new Runnable() {
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
createLogFileIfNotExist();
|
||||||
|
final long currentTime = System.currentTimeMillis();
|
||||||
|
mDate.setTime(currentTime);
|
||||||
|
|
||||||
|
final String printString = String.format(Locale.US, "%s\t%d\t%s\n",
|
||||||
|
mDateFormat.format(mDate), currentTime, log);
|
||||||
|
if (LatinImeLogger.sDBG) {
|
||||||
|
Log.d(USABILITY_TAG, "Write: " + log);
|
||||||
|
}
|
||||||
|
mWriter.print(printString);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
private synchronized String getBufferedLogs() {
|
||||||
|
mWriter.flush();
|
||||||
|
final StringBuilder sb = new StringBuilder();
|
||||||
|
final BufferedReader br = getBufferedReader();
|
||||||
|
String line;
|
||||||
|
try {
|
||||||
|
while ((line = br.readLine()) != null) {
|
||||||
|
sb.append('\n');
|
||||||
|
sb.append(line);
|
||||||
|
}
|
||||||
|
} catch (final IOException e) {
|
||||||
|
Log.e(USABILITY_TAG, "Can't read log file.");
|
||||||
|
} finally {
|
||||||
|
if (LatinImeLogger.sDBG) {
|
||||||
|
Log.d(USABILITY_TAG, "Got all buffered logs\n" + sb.toString());
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
br.close();
|
||||||
|
} catch (final IOException e) {
|
||||||
|
// ignore.
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return sb.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void emailResearcherLogsAll() {
|
||||||
|
mLoggingHandler.post(new Runnable() {
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
final Date date = new Date();
|
||||||
|
date.setTime(System.currentTimeMillis());
|
||||||
|
final String currentDateTimeString =
|
||||||
|
new SimpleDateFormat("yyyyMMdd-HHmmssZ", Locale.US).format(date);
|
||||||
|
if (mFile == null) {
|
||||||
|
Log.w(USABILITY_TAG, "No internal log file found.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (mIms.checkCallingOrSelfPermission(
|
||||||
|
android.Manifest.permission.WRITE_EXTERNAL_STORAGE)
|
||||||
|
!= PackageManager.PERMISSION_GRANTED) {
|
||||||
|
Log.w(USABILITY_TAG, "Doesn't have the permission WRITE_EXTERNAL_STORAGE");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
mWriter.flush();
|
||||||
|
final String destPath = Environment.getExternalStorageDirectory()
|
||||||
|
+ "/research-" + currentDateTimeString + ".log";
|
||||||
|
final File destFile = new File(destPath);
|
||||||
|
try {
|
||||||
|
final FileInputStream srcStream = new FileInputStream(mFile);
|
||||||
|
final FileOutputStream destStream = new FileOutputStream(destFile);
|
||||||
|
final FileChannel src = srcStream.getChannel();
|
||||||
|
final FileChannel dest = destStream.getChannel();
|
||||||
|
src.transferTo(0, src.size(), dest);
|
||||||
|
src.close();
|
||||||
|
srcStream.close();
|
||||||
|
dest.close();
|
||||||
|
destStream.close();
|
||||||
|
} catch (final FileNotFoundException e1) {
|
||||||
|
Log.w(USABILITY_TAG, e1);
|
||||||
|
return;
|
||||||
|
} catch (final IOException e2) {
|
||||||
|
Log.w(USABILITY_TAG, e2);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (destFile == null || !destFile.exists()) {
|
||||||
|
Log.w(USABILITY_TAG, "Dest file doesn't exist.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
final Intent intent = new Intent(Intent.ACTION_SEND);
|
||||||
|
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
|
||||||
|
if (LatinImeLogger.sDBG) {
|
||||||
|
Log.d(USABILITY_TAG, "Destination file URI is " + destFile.toURI());
|
||||||
|
}
|
||||||
|
intent.setType("text/plain");
|
||||||
|
intent.putExtra(Intent.EXTRA_STREAM, Uri.parse("file://" + destPath));
|
||||||
|
intent.putExtra(Intent.EXTRA_SUBJECT,
|
||||||
|
"[Research Logs] " + currentDateTimeString);
|
||||||
|
mIms.startActivity(intent);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
public void printAll() {
|
||||||
|
mLoggingHandler.post(new Runnable() {
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
mIms.getCurrentInputConnection().commitText(getBufferedLogs(), 0);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
public void clearAll() {
|
||||||
|
mLoggingHandler.post(new Runnable() {
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
if (mFile != null && mFile.exists()) {
|
||||||
|
if (LatinImeLogger.sDBG) {
|
||||||
|
Log.d(USABILITY_TAG, "Delete log file.");
|
||||||
|
}
|
||||||
|
mFile.delete();
|
||||||
|
mWriter.close();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
private BufferedReader getBufferedReader() {
|
||||||
|
createLogFileIfNotExist();
|
||||||
|
try {
|
||||||
|
return new BufferedReader(new FileReader(mFile));
|
||||||
|
} catch (final FileNotFoundException e) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private PrintWriter getPrintWriter(final File dir, final String filename,
|
||||||
|
final boolean renew) throws IOException {
|
||||||
|
mFile = new File(dir, filename);
|
||||||
|
if (mFile.exists()) {
|
||||||
|
if (renew) {
|
||||||
|
mFile.delete();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return new PrintWriter(new FileOutputStream(mFile), true /* autoFlush */);
|
||||||
|
}
|
||||||
|
}
|
|
@ -20,7 +20,6 @@ import android.inputmethodservice.InputMethodService;
|
||||||
|
|
||||||
import com.android.inputmethod.annotations.UsedForTesting;
|
import com.android.inputmethod.annotations.UsedForTesting;
|
||||||
import com.android.inputmethod.latin.Settings;
|
import com.android.inputmethod.latin.Settings;
|
||||||
import com.android.inputmethod.latin.utils.Utils.UsabilityStudyLogUtils;
|
|
||||||
|
|
||||||
public final class UserLogRingCharBuffer {
|
public final class UserLogRingCharBuffer {
|
||||||
public /* for test */ static final int BUFSIZE = 20;
|
public /* for test */ static final int BUFSIZE = 20;
|
||||||
|
|
|
@ -1,374 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright (C) 2010 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.app.Activity;
|
|
||||||
import android.content.ComponentName;
|
|
||||||
import android.content.Context;
|
|
||||||
import android.content.Intent;
|
|
||||||
import android.content.pm.ActivityInfo;
|
|
||||||
import android.content.pm.PackageInfo;
|
|
||||||
import android.content.pm.PackageManager;
|
|
||||||
import android.content.pm.PackageManager.NameNotFoundException;
|
|
||||||
import android.inputmethodservice.InputMethodService;
|
|
||||||
import android.net.Uri;
|
|
||||||
import android.os.Environment;
|
|
||||||
import android.os.Handler;
|
|
||||||
import android.os.HandlerThread;
|
|
||||||
import android.os.Process;
|
|
||||||
import android.text.TextUtils;
|
|
||||||
import android.util.Log;
|
|
||||||
|
|
||||||
import com.android.inputmethod.latin.Constants;
|
|
||||||
import com.android.inputmethod.latin.LatinImeLogger;
|
|
||||||
import com.android.inputmethod.latin.SuggestedWords;
|
|
||||||
import com.android.inputmethod.latin.SuggestedWords.SuggestedWordInfo;
|
|
||||||
import com.android.inputmethod.latin.WordComposer;
|
|
||||||
|
|
||||||
import java.io.BufferedReader;
|
|
||||||
import java.io.File;
|
|
||||||
import java.io.FileInputStream;
|
|
||||||
import java.io.FileNotFoundException;
|
|
||||||
import java.io.FileOutputStream;
|
|
||||||
import java.io.FileReader;
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.io.PrintWriter;
|
|
||||||
import java.nio.channels.FileChannel;
|
|
||||||
import java.text.SimpleDateFormat;
|
|
||||||
import java.util.Date;
|
|
||||||
import java.util.Locale;
|
|
||||||
|
|
||||||
// TODO: Come up with a more descriptive class name
|
|
||||||
public final class Utils {
|
|
||||||
private static final String TAG = Utils.class.getSimpleName();
|
|
||||||
|
|
||||||
private Utils() {
|
|
||||||
// This utility class is not publicly instantiable.
|
|
||||||
}
|
|
||||||
|
|
||||||
// TODO: Make this an external class
|
|
||||||
public static final class UsabilityStudyLogUtils {
|
|
||||||
// TODO: remove code duplication with ResearchLog class
|
|
||||||
private static final String USABILITY_TAG = UsabilityStudyLogUtils.class.getSimpleName();
|
|
||||||
private static final String FILENAME = "log.txt";
|
|
||||||
private final Handler mLoggingHandler;
|
|
||||||
private File mFile;
|
|
||||||
private File mDirectory;
|
|
||||||
private InputMethodService mIms;
|
|
||||||
private PrintWriter mWriter;
|
|
||||||
private final Date mDate;
|
|
||||||
private final SimpleDateFormat mDateFormat;
|
|
||||||
|
|
||||||
private UsabilityStudyLogUtils() {
|
|
||||||
mDate = new Date();
|
|
||||||
mDateFormat = new SimpleDateFormat("yyyyMMdd-HHmmss.SSSZ", Locale.US);
|
|
||||||
|
|
||||||
HandlerThread handlerThread = new HandlerThread("UsabilityStudyLogUtils logging task",
|
|
||||||
Process.THREAD_PRIORITY_BACKGROUND);
|
|
||||||
handlerThread.start();
|
|
||||||
mLoggingHandler = new Handler(handlerThread.getLooper());
|
|
||||||
}
|
|
||||||
|
|
||||||
// Initialization-on-demand holder
|
|
||||||
private static final class OnDemandInitializationHolder {
|
|
||||||
public static final UsabilityStudyLogUtils sInstance = new UsabilityStudyLogUtils();
|
|
||||||
}
|
|
||||||
|
|
||||||
public static UsabilityStudyLogUtils getInstance() {
|
|
||||||
return OnDemandInitializationHolder.sInstance;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void init(final InputMethodService ims) {
|
|
||||||
mIms = ims;
|
|
||||||
mDirectory = ims.getFilesDir();
|
|
||||||
}
|
|
||||||
|
|
||||||
private void createLogFileIfNotExist() {
|
|
||||||
if ((mFile == null || !mFile.exists())
|
|
||||||
&& (mDirectory != null && mDirectory.exists())) {
|
|
||||||
try {
|
|
||||||
mWriter = getPrintWriter(mDirectory, FILENAME, false);
|
|
||||||
} catch (final IOException e) {
|
|
||||||
Log.e(USABILITY_TAG, "Can't create log file.");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void writeBackSpace(final int x, final int y) {
|
|
||||||
UsabilityStudyLogUtils.getInstance().write("<backspace>\t" + x + "\t" + y);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void writeChar(final char c, final int x, final int y) {
|
|
||||||
String inputChar = String.valueOf(c);
|
|
||||||
switch (c) {
|
|
||||||
case '\n':
|
|
||||||
inputChar = "<enter>";
|
|
||||||
break;
|
|
||||||
case '\t':
|
|
||||||
inputChar = "<tab>";
|
|
||||||
break;
|
|
||||||
case ' ':
|
|
||||||
inputChar = "<space>";
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
UsabilityStudyLogUtils.getInstance().write(inputChar + "\t" + x + "\t" + y);
|
|
||||||
LatinImeLogger.onPrintAllUsabilityStudyLogs();
|
|
||||||
}
|
|
||||||
|
|
||||||
public void write(final String log) {
|
|
||||||
mLoggingHandler.post(new Runnable() {
|
|
||||||
@Override
|
|
||||||
public void run() {
|
|
||||||
createLogFileIfNotExist();
|
|
||||||
final long currentTime = System.currentTimeMillis();
|
|
||||||
mDate.setTime(currentTime);
|
|
||||||
|
|
||||||
final String printString = String.format(Locale.US, "%s\t%d\t%s\n",
|
|
||||||
mDateFormat.format(mDate), currentTime, log);
|
|
||||||
if (LatinImeLogger.sDBG) {
|
|
||||||
Log.d(USABILITY_TAG, "Write: " + log);
|
|
||||||
}
|
|
||||||
mWriter.print(printString);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
private synchronized String getBufferedLogs() {
|
|
||||||
mWriter.flush();
|
|
||||||
final StringBuilder sb = new StringBuilder();
|
|
||||||
final BufferedReader br = getBufferedReader();
|
|
||||||
String line;
|
|
||||||
try {
|
|
||||||
while ((line = br.readLine()) != null) {
|
|
||||||
sb.append('\n');
|
|
||||||
sb.append(line);
|
|
||||||
}
|
|
||||||
} catch (final IOException e) {
|
|
||||||
Log.e(USABILITY_TAG, "Can't read log file.");
|
|
||||||
} finally {
|
|
||||||
if (LatinImeLogger.sDBG) {
|
|
||||||
Log.d(USABILITY_TAG, "Got all buffered logs\n" + sb.toString());
|
|
||||||
}
|
|
||||||
try {
|
|
||||||
br.close();
|
|
||||||
} catch (final IOException e) {
|
|
||||||
// ignore.
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return sb.toString();
|
|
||||||
}
|
|
||||||
|
|
||||||
public void emailResearcherLogsAll() {
|
|
||||||
mLoggingHandler.post(new Runnable() {
|
|
||||||
@Override
|
|
||||||
public void run() {
|
|
||||||
final Date date = new Date();
|
|
||||||
date.setTime(System.currentTimeMillis());
|
|
||||||
final String currentDateTimeString =
|
|
||||||
new SimpleDateFormat("yyyyMMdd-HHmmssZ", Locale.US).format(date);
|
|
||||||
if (mFile == null) {
|
|
||||||
Log.w(USABILITY_TAG, "No internal log file found.");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (mIms.checkCallingOrSelfPermission(
|
|
||||||
android.Manifest.permission.WRITE_EXTERNAL_STORAGE)
|
|
||||||
!= PackageManager.PERMISSION_GRANTED) {
|
|
||||||
Log.w(USABILITY_TAG, "Doesn't have the permission WRITE_EXTERNAL_STORAGE");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
mWriter.flush();
|
|
||||||
final String destPath = Environment.getExternalStorageDirectory()
|
|
||||||
+ "/research-" + currentDateTimeString + ".log";
|
|
||||||
final File destFile = new File(destPath);
|
|
||||||
try {
|
|
||||||
final FileInputStream srcStream = new FileInputStream(mFile);
|
|
||||||
final FileOutputStream destStream = new FileOutputStream(destFile);
|
|
||||||
final FileChannel src = srcStream.getChannel();
|
|
||||||
final FileChannel dest = destStream.getChannel();
|
|
||||||
src.transferTo(0, src.size(), dest);
|
|
||||||
src.close();
|
|
||||||
srcStream.close();
|
|
||||||
dest.close();
|
|
||||||
destStream.close();
|
|
||||||
} catch (final FileNotFoundException e1) {
|
|
||||||
Log.w(USABILITY_TAG, e1);
|
|
||||||
return;
|
|
||||||
} catch (final IOException e2) {
|
|
||||||
Log.w(USABILITY_TAG, e2);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (destFile == null || !destFile.exists()) {
|
|
||||||
Log.w(USABILITY_TAG, "Dest file doesn't exist.");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
final Intent intent = new Intent(Intent.ACTION_SEND);
|
|
||||||
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
|
|
||||||
if (LatinImeLogger.sDBG) {
|
|
||||||
Log.d(USABILITY_TAG, "Destination file URI is " + destFile.toURI());
|
|
||||||
}
|
|
||||||
intent.setType("text/plain");
|
|
||||||
intent.putExtra(Intent.EXTRA_STREAM, Uri.parse("file://" + destPath));
|
|
||||||
intent.putExtra(Intent.EXTRA_SUBJECT,
|
|
||||||
"[Research Logs] " + currentDateTimeString);
|
|
||||||
mIms.startActivity(intent);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
public void printAll() {
|
|
||||||
mLoggingHandler.post(new Runnable() {
|
|
||||||
@Override
|
|
||||||
public void run() {
|
|
||||||
mIms.getCurrentInputConnection().commitText(getBufferedLogs(), 0);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
public void clearAll() {
|
|
||||||
mLoggingHandler.post(new Runnable() {
|
|
||||||
@Override
|
|
||||||
public void run() {
|
|
||||||
if (mFile != null && mFile.exists()) {
|
|
||||||
if (LatinImeLogger.sDBG) {
|
|
||||||
Log.d(USABILITY_TAG, "Delete log file.");
|
|
||||||
}
|
|
||||||
mFile.delete();
|
|
||||||
mWriter.close();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
private BufferedReader getBufferedReader() {
|
|
||||||
createLogFileIfNotExist();
|
|
||||||
try {
|
|
||||||
return new BufferedReader(new FileReader(mFile));
|
|
||||||
} catch (final FileNotFoundException e) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private PrintWriter getPrintWriter(final File dir, final String filename,
|
|
||||||
final boolean renew) throws IOException {
|
|
||||||
mFile = new File(dir, filename);
|
|
||||||
if (mFile.exists()) {
|
|
||||||
if (renew) {
|
|
||||||
mFile.delete();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return new PrintWriter(new FileOutputStream(mFile), true /* autoFlush */);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// TODO: Make this an external class
|
|
||||||
public static final class Stats {
|
|
||||||
public static void onNonSeparator(final char code, final int x, final int y) {
|
|
||||||
UserLogRingCharBuffer.getInstance().push(code, x, y);
|
|
||||||
LatinImeLogger.logOnInputChar();
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void onSeparator(final int code, final int x, final int y) {
|
|
||||||
// Helper method to log a single code point separator
|
|
||||||
// TODO: cache this mapping of a code point to a string in a sparse array in StringUtils
|
|
||||||
onSeparator(new String(new int[]{code}, 0, 1), x, y);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void onSeparator(final String separator, final int x, final int y) {
|
|
||||||
final int length = separator.length();
|
|
||||||
for (int i = 0; i < length; i = Character.offsetByCodePoints(separator, i, 1)) {
|
|
||||||
int codePoint = Character.codePointAt(separator, i);
|
|
||||||
// TODO: accept code points
|
|
||||||
UserLogRingCharBuffer.getInstance().push((char)codePoint, x, y);
|
|
||||||
}
|
|
||||||
LatinImeLogger.logOnInputSeparator();
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void onAutoCorrection(final String typedWord, final String correctedWord,
|
|
||||||
final String separatorString, final WordComposer wordComposer) {
|
|
||||||
final boolean isBatchMode = wordComposer.isBatchMode();
|
|
||||||
if (!isBatchMode && TextUtils.isEmpty(typedWord)) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
// TODO: this fails when the separator is more than 1 code point long, but
|
|
||||||
// the backend can't handle it yet. The only case when this happens is with
|
|
||||||
// smileys and other multi-character keys.
|
|
||||||
final int codePoint = TextUtils.isEmpty(separatorString) ? Constants.NOT_A_CODE
|
|
||||||
: separatorString.codePointAt(0);
|
|
||||||
if (!isBatchMode) {
|
|
||||||
LatinImeLogger.logOnAutoCorrectionForTyping(typedWord, correctedWord, codePoint);
|
|
||||||
} else {
|
|
||||||
if (!TextUtils.isEmpty(correctedWord)) {
|
|
||||||
// We must make sure that InputPointer contains only the relative timestamps,
|
|
||||||
// not actual timestamps.
|
|
||||||
LatinImeLogger.logOnAutoCorrectionForGeometric(
|
|
||||||
"", correctedWord, codePoint, wordComposer.getInputPointers());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void onAutoCorrectionCancellation() {
|
|
||||||
LatinImeLogger.logOnAutoCorrectionCancelled();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public static String getDebugInfo(final SuggestedWords suggestions, final int pos) {
|
|
||||||
if (!LatinImeLogger.sDBG) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
final SuggestedWordInfo wordInfo = suggestions.getInfo(pos);
|
|
||||||
if (wordInfo == null) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
final String info = wordInfo.getDebugString();
|
|
||||||
if (TextUtils.isEmpty(info)) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
return info;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static int getAcitivityTitleResId(final Context context,
|
|
||||||
final Class<? extends Activity> cls) {
|
|
||||||
final ComponentName cn = new ComponentName(context, cls);
|
|
||||||
try {
|
|
||||||
final ActivityInfo ai = context.getPackageManager().getActivityInfo(cn, 0);
|
|
||||||
if (ai != null) {
|
|
||||||
return ai.labelRes;
|
|
||||||
}
|
|
||||||
} catch (final NameNotFoundException e) {
|
|
||||||
Log.e(TAG, "Failed to get settings activity title res id.", e);
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* A utility method to get the application's PackageInfo.versionName
|
|
||||||
* @return the application's PackageInfo.versionName
|
|
||||||
*/
|
|
||||||
public static String getVersionName(final Context context) {
|
|
||||||
try {
|
|
||||||
if (context == null) {
|
|
||||||
return "";
|
|
||||||
}
|
|
||||||
final String packageName = context.getPackageName();
|
|
||||||
final PackageInfo info = context.getPackageManager().getPackageInfo(packageName, 0);
|
|
||||||
return info.versionName;
|
|
||||||
} catch (final NameNotFoundException e) {
|
|
||||||
Log.e(TAG, "Could not find version info.", e);
|
|
||||||
}
|
|
||||||
return "";
|
|
||||||
}
|
|
||||||
}
|
|
Loading…
Reference in New Issue