aboutsummaryrefslogtreecommitdiffstats
path: root/java/src/com/android/inputmethod/latin/utils
diff options
context:
space:
mode:
Diffstat (limited to 'java/src/com/android/inputmethod/latin/utils')
-rw-r--r--java/src/com/android/inputmethod/latin/utils/DictionaryInfoUtils.java72
-rw-r--r--java/src/com/android/inputmethod/latin/utils/ImportantNoticeUtils.java107
2 files changed, 114 insertions, 65 deletions
diff --git a/java/src/com/android/inputmethod/latin/utils/DictionaryInfoUtils.java b/java/src/com/android/inputmethod/latin/utils/DictionaryInfoUtils.java
index cfa977a46..cea2e13b1 100644
--- a/java/src/com/android/inputmethod/latin/utils/DictionaryInfoUtils.java
+++ b/java/src/com/android/inputmethod/latin/utils/DictionaryInfoUtils.java
@@ -30,6 +30,7 @@ import com.android.inputmethod.latin.AssetFileAddress;
import com.android.inputmethod.latin.BinaryDictionaryGetter;
import com.android.inputmethod.latin.R;
import com.android.inputmethod.latin.RichInputMethodManager;
+import com.android.inputmethod.latin.common.FileUtils;
import com.android.inputmethod.latin.common.LocaleUtils;
import com.android.inputmethod.latin.define.DecoderSpecificConstants;
import com.android.inputmethod.latin.makedict.DictionaryHeader;
@@ -53,7 +54,7 @@ import javax.annotation.Nullable;
*/
public class DictionaryInfoUtils {
private static final String TAG = DictionaryInfoUtils.class.getSimpleName();
- private static final String RESOURCE_PACKAGE_NAME = R.class.getPackage().getName();
+ public static final String RESOURCE_PACKAGE_NAME = R.class.getPackage().getName();
private static final String DEFAULT_MAIN_DICT = "main";
private static final String MAIN_DICT_PREFIX = "main_";
private static final String DECODER_DICT_SUFFIX = DecoderSpecificConstants.DECODER_DICT_SUFFIX;
@@ -102,6 +103,13 @@ public class DictionaryInfoUtils {
values.put(VERSION_COLUMN, mVersion);
return values;
}
+
+ @Override
+ public String toString() {
+ return "DictionaryInfo : Id = '" + mId
+ + "' : Locale=" + mLocale
+ + " : Version=" + mVersion;
+ }
}
private DictionaryInfoUtils() {
@@ -153,6 +161,13 @@ public class DictionaryInfoUtils {
}
/**
+ * Helper method to get the top level cache directory.
+ */
+ public static String getWordListStagingDirectory(final Context context) {
+ return context.getFilesDir() + File.separator + "staging";
+ }
+
+ /**
* Helper method to get the top level temp directory.
*/
public static String getWordListTempDirectory(final Context context) {
@@ -188,6 +203,10 @@ public class DictionaryInfoUtils {
return new File(DictionaryInfoUtils.getWordListCacheDirectory(context)).listFiles();
}
+ public static File[] getStagingDirectoryList(final Context context) {
+ return new File(DictionaryInfoUtils.getWordListStagingDirectory(context)).listFiles();
+ }
+
@Nullable
public static File[] getUnusedDictionaryList(final Context context) {
return context.getFilesDir().listFiles(new FilenameFilter() {
@@ -221,7 +240,7 @@ public class DictionaryInfoUtils {
/**
* Find out the cache directory associated with a specific locale.
*/
- private static String getCacheDirectoryForLocale(final String locale, final Context context) {
+ public static String getCacheDirectoryForLocale(final String locale, final Context context) {
final String relativeDirectoryName = replaceFileNameDangerousCharacters(locale);
final String absoluteDirectoryName = getWordListCacheDirectory(context) + File.separator
+ relativeDirectoryName;
@@ -254,6 +273,55 @@ public class DictionaryInfoUtils {
return getCacheDirectoryForLocale(locale, context) + File.separator + fileName;
}
+ public static String getStagingFileName(String id, String locale, Context context) {
+ final String stagingDirectory = getWordListStagingDirectory(context);
+ // create the directory if it does not exist.
+ final File directory = new File(stagingDirectory);
+ if (!directory.exists()) {
+ if (!directory.mkdirs()) {
+ Log.e(TAG, "Could not create the staging directory.");
+ }
+ }
+ // e.g. id="main:en_in", locale ="en_IN"
+ final String fileName = replaceFileNameDangerousCharacters(
+ locale + TEMP_DICT_FILE_SUB + id);
+ return stagingDirectory + File.separator + fileName;
+ }
+
+ public static void moveStagingFilesIfExists(Context context) {
+ final File[] stagingFiles = DictionaryInfoUtils.getStagingDirectoryList(context);
+ if (stagingFiles != null && stagingFiles.length > 0) {
+ for (final File stagingFile : stagingFiles) {
+ final String fileName = stagingFile.getName();
+ final int index = fileName.indexOf(TEMP_DICT_FILE_SUB);
+ if (index == -1) {
+ // This should never happen.
+ Log.e(TAG, "Staging file does not have ___ substring.");
+ continue;
+ }
+ final String[] localeAndFileId = fileName.split(TEMP_DICT_FILE_SUB);
+ if (localeAndFileId.length != 2) {
+ Log.e(TAG, String.format("malformed staging file %s. Deleting.",
+ stagingFile.getAbsoluteFile()));
+ stagingFile.delete();
+ continue;
+ }
+
+ final String locale = localeAndFileId[0];
+ // already escaped while moving to staging.
+ final String fileId = localeAndFileId[1];
+ final String cacheDirectoryForLocale = getCacheDirectoryForLocale(locale, context);
+ final String cacheFilename = cacheDirectoryForLocale + File.separator + fileId;
+ final File cacheFile = new File(cacheFilename);
+ // move the staging file to cache file.
+ if (!FileUtils.renameTo(stagingFile, cacheFile)) {
+ Log.e(TAG, String.format("Failed to rename from %s to %s.",
+ stagingFile.getAbsoluteFile(), cacheFile.getAbsoluteFile()));
+ }
+ }
+ }
+ }
+
public static boolean isMainWordListId(final String id) {
final String[] idArray = id.split(BinaryDictionaryGetter.ID_CATEGORY_SEPARATOR);
// An id is supposed to be in format category:locale, so splitting on the separator
diff --git a/java/src/com/android/inputmethod/latin/utils/ImportantNoticeUtils.java b/java/src/com/android/inputmethod/latin/utils/ImportantNoticeUtils.java
index df0cd8437..cea263b3b 100644
--- a/java/src/com/android/inputmethod/latin/utils/ImportantNoticeUtils.java
+++ b/java/src/com/android/inputmethod/latin/utils/ImportantNoticeUtils.java
@@ -16,6 +16,7 @@
package com.android.inputmethod.latin.utils;
+import android.Manifest;
import android.content.Context;
import android.content.SharedPreferences;
import android.provider.Settings;
@@ -25,6 +26,7 @@ import android.util.Log;
import com.android.inputmethod.annotations.UsedForTesting;
import com.android.inputmethod.latin.R;
+import com.android.inputmethod.latin.permissions.PermissionsUtil;
import com.android.inputmethod.latin.settings.SettingsValues;
import java.util.concurrent.TimeUnit;
@@ -35,14 +37,14 @@ public final class ImportantNoticeUtils {
// {@link SharedPreferences} name to save the last important notice version that has been
// displayed to users.
private static final String PREFERENCE_NAME = "important_notice_pref";
+
+ private static final String KEY_SUGGEST_CONTACTS_NOTICE = "important_notice_suggest_contacts";
+
@UsedForTesting
- static final String KEY_IMPORTANT_NOTICE_VERSION = "important_notice_version";
- @UsedForTesting
- static final String KEY_TIMESTAMP_OF_FIRST_IMPORTANT_NOTICE =
- "timestamp_of_first_important_notice";
+ static final String KEY_TIMESTAMP_OF_CONTACTS_NOTICE = "timestamp_of_suggest_contacts_notice";
+
@UsedForTesting
static final long TIMEOUT_OF_IMPORTANT_NOTICE = TimeUnit.HOURS.toMillis(23);
- public static final int VERSION_TO_ENABLE_PERSONALIZED_SUGGESTIONS = 1;
// Copy of the hidden {@link Settings.Secure#USER_SETUP_COMPLETE} settings key.
// The value is zero until each multiuser completes system setup wizard.
@@ -73,87 +75,66 @@ public final class ImportantNoticeUtils {
}
@UsedForTesting
- static int getCurrentImportantNoticeVersion(final Context context) {
- return context.getResources().getInteger(R.integer.config_important_notice_version);
- }
-
- @UsedForTesting
- static int getLastImportantNoticeVersion(final Context context) {
- return getImportantNoticePreferences(context).getInt(KEY_IMPORTANT_NOTICE_VERSION, 0);
- }
-
- public static int getNextImportantNoticeVersion(final Context context) {
- return getLastImportantNoticeVersion(context) + 1;
- }
-
- @UsedForTesting
- static boolean hasNewImportantNotice(final Context context) {
- final int lastVersion = getLastImportantNoticeVersion(context);
- return getCurrentImportantNoticeVersion(context) > lastVersion;
- }
-
- @UsedForTesting
- static boolean hasTimeoutPassed(final Context context, final long currentTimeInMillis) {
- final SharedPreferences prefs = getImportantNoticePreferences(context);
- if (!prefs.contains(KEY_TIMESTAMP_OF_FIRST_IMPORTANT_NOTICE)) {
- prefs.edit()
- .putLong(KEY_TIMESTAMP_OF_FIRST_IMPORTANT_NOTICE, currentTimeInMillis)
- .apply();
- }
- final long firstDisplayTimeInMillis = prefs.getLong(
- KEY_TIMESTAMP_OF_FIRST_IMPORTANT_NOTICE, currentTimeInMillis);
- final long elapsedTime = currentTimeInMillis - firstDisplayTimeInMillis;
- return elapsedTime >= TIMEOUT_OF_IMPORTANT_NOTICE;
+ static boolean hasContactsNoticeShown(final Context context) {
+ return getImportantNoticePreferences(context).getBoolean(
+ KEY_SUGGEST_CONTACTS_NOTICE, false);
}
public static boolean shouldShowImportantNotice(final Context context,
final SettingsValues settingsValues) {
- // Check to see whether personalization is enabled by the user.
- if (!settingsValues.isPersonalizationEnabled()) {
+ // Check to see whether "Use Contacts" is enabled by the user.
+ if (!settingsValues.mUseContactsDict) {
return false;
}
- if (!hasNewImportantNotice(context)) {
+
+ if (hasContactsNoticeShown(context)) {
+ return false;
+ }
+
+ // Don't show the dialog if we have all the permissions.
+ if (PermissionsUtil.checkAllPermissionsGranted(
+ context, Manifest.permission.READ_CONTACTS)) {
return false;
}
- final String importantNoticeTitle = getNextImportantNoticeTitle(context);
+
+ final String importantNoticeTitle = getSuggestContactsNoticeTitle(context);
if (TextUtils.isEmpty(importantNoticeTitle)) {
return false;
}
if (isInSystemSetupWizard(context)) {
return false;
}
- if (hasTimeoutPassed(context, System.currentTimeMillis())) {
- updateLastImportantNoticeVersion(context);
+ if (hasContactsNoticeTimeoutPassed(context, System.currentTimeMillis())) {
+ updateContactsNoticeShown(context);
return false;
}
return true;
}
- public static void updateLastImportantNoticeVersion(final Context context) {
- getImportantNoticePreferences(context)
- .edit()
- .putInt(KEY_IMPORTANT_NOTICE_VERSION, getNextImportantNoticeVersion(context))
- .remove(KEY_TIMESTAMP_OF_FIRST_IMPORTANT_NOTICE)
- .apply();
+ public static String getSuggestContactsNoticeTitle(final Context context) {
+ return context.getResources().getString(R.string.important_notice_suggest_contact_names);
}
- public static String getNextImportantNoticeTitle(final Context context) {
- final int nextVersion = getNextImportantNoticeVersion(context);
- final String[] importantNoticeTitleArray = context.getResources().getStringArray(
- R.array.important_notice_title_array);
- if (nextVersion > 0 && nextVersion < importantNoticeTitleArray.length) {
- return importantNoticeTitleArray[nextVersion];
+ @UsedForTesting
+ static boolean hasContactsNoticeTimeoutPassed(
+ final Context context, final long currentTimeInMillis) {
+ final SharedPreferences prefs = getImportantNoticePreferences(context);
+ if (!prefs.contains(KEY_TIMESTAMP_OF_CONTACTS_NOTICE)) {
+ prefs.edit()
+ .putLong(KEY_TIMESTAMP_OF_CONTACTS_NOTICE, currentTimeInMillis)
+ .apply();
}
- return null;
+ final long firstDisplayTimeInMillis = prefs.getLong(
+ KEY_TIMESTAMP_OF_CONTACTS_NOTICE, currentTimeInMillis);
+ final long elapsedTime = currentTimeInMillis - firstDisplayTimeInMillis;
+ return elapsedTime >= TIMEOUT_OF_IMPORTANT_NOTICE;
}
- public static String getNextImportantNoticeContents(final Context context) {
- final int nextVersion = getNextImportantNoticeVersion(context);
- final String[] importantNoticeContentsArray = context.getResources().getStringArray(
- R.array.important_notice_contents_array);
- if (nextVersion > 0 && nextVersion < importantNoticeContentsArray.length) {
- return importantNoticeContentsArray[nextVersion];
- }
- return null;
+ public static void updateContactsNoticeShown(final Context context) {
+ getImportantNoticePreferences(context)
+ .edit()
+ .putBoolean(KEY_SUGGEST_CONTACTS_NOTICE, true)
+ .remove(KEY_TIMESTAMP_OF_CONTACTS_NOTICE)
+ .apply();
}
}