diff --git a/java/AndroidManifest.xml b/java/AndroidManifest.xml
index f58c401c7..8882cdea5 100644
--- a/java/AndroidManifest.xml
+++ b/java/AndroidManifest.xml
@@ -18,7 +18,7 @@
coreApp="true"
package="com.android.inputmethod.latin">
-
+
@@ -77,6 +77,13 @@
+
+
+
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/java/res/values/important_notice_strings.xml b/java/res/values/important_notice_strings.xml
new file mode 100644
index 000000000..b1f3fc137
--- /dev/null
+++ b/java/res/values/important_notice_strings.xml
@@ -0,0 +1,21 @@
+
+
+
+
+
+ Suggest contact names? Touch for info.
+
\ No newline at end of file
diff --git a/java/res/values/strings-config-important-notice.xml b/java/res/values/strings-config-important-notice.xml
deleted file mode 100644
index aa3cd109c..000000000
--- a/java/res/values/strings-config-important-notice.xml
+++ /dev/null
@@ -1,25 +0,0 @@
-
-
-
-
- 0
-
- Learn from your communications and typed data to improve suggestions
-
diff --git a/java/src/com/android/inputmethod/latin/ContactsBinaryDictionary.java b/java/src/com/android/inputmethod/latin/ContactsBinaryDictionary.java
index 15a14e5af..dbd639fe8 100644
--- a/java/src/com/android/inputmethod/latin/ContactsBinaryDictionary.java
+++ b/java/src/com/android/inputmethod/latin/ContactsBinaryDictionary.java
@@ -16,6 +16,7 @@
package com.android.inputmethod.latin;
+import android.Manifest;
import android.content.Context;
import android.net.Uri;
import android.provider.ContactsContract;
@@ -25,6 +26,7 @@ import android.util.Log;
import com.android.inputmethod.annotations.ExternallyReferenced;
import com.android.inputmethod.latin.ContactsManager.ContactsChangedListener;
import com.android.inputmethod.latin.common.StringUtils;
+import com.android.inputmethod.latin.permissions.PermissionsUtil;
import com.android.inputmethod.latin.personalization.AccountUtils;
import java.io.File;
@@ -108,6 +110,11 @@ public class ContactsBinaryDictionary extends ExpandableBinaryDictionary
* Loads data within content providers to the dictionary.
*/
private void loadDictionaryForUriLocked(final Uri uri) {
+ if (!PermissionsUtil.checkAllPermissionsGranted(
+ mContext, Manifest.permission.READ_CONTACTS)) {
+ Log.i(TAG, "No permission to read contacts. Not loading the Dictionary.");
+ }
+
final ArrayList validNames = mContactsManager.getValidNames(uri);
for (final String name : validNames) {
addNameLocked(name);
diff --git a/java/src/com/android/inputmethod/latin/ContactsContentObserver.java b/java/src/com/android/inputmethod/latin/ContactsContentObserver.java
index 872e4c8fc..6103a8296 100644
--- a/java/src/com/android/inputmethod/latin/ContactsContentObserver.java
+++ b/java/src/com/android/inputmethod/latin/ContactsContentObserver.java
@@ -16,6 +16,7 @@
package com.android.inputmethod.latin;
+import android.Manifest;
import android.content.ContentResolver;
import android.content.Context;
import android.database.ContentObserver;
@@ -25,6 +26,7 @@ import android.util.Log;
import com.android.inputmethod.latin.ContactsManager.ContactsChangedListener;
import com.android.inputmethod.latin.define.DebugFlags;
+import com.android.inputmethod.latin.permissions.PermissionsUtil;
import com.android.inputmethod.latin.utils.ExecutorUtils;
import java.util.ArrayList;
@@ -35,10 +37,10 @@ import java.util.concurrent.atomic.AtomicBoolean;
*/
public class ContactsContentObserver implements Runnable {
private static final String TAG = "ContactsContentObserver";
- private static AtomicBoolean sRunning = new AtomicBoolean(false);
private final Context mContext;
private final ContactsManager mManager;
+ private final AtomicBoolean mRunning = new AtomicBoolean(false);
private ContentObserver mContentObserver;
private ContactsChangedListener mContactsChangedListener;
@@ -49,6 +51,13 @@ public class ContactsContentObserver implements Runnable {
}
public void registerObserver(final ContactsChangedListener listener) {
+ if (!PermissionsUtil.checkAllPermissionsGranted(
+ mContext, Manifest.permission.READ_CONTACTS)) {
+ Log.i(TAG, "No permission to read contacts. Not registering the observer.");
+ // do nothing if we do not have the permission to read contacts.
+ return;
+ }
+
if (DebugFlags.DEBUG_ENABLED) {
Log.d(TAG, "registerObserver()");
}
@@ -66,7 +75,14 @@ public class ContactsContentObserver implements Runnable {
@Override
public void run() {
- if (!sRunning.compareAndSet(false /* expect */, true /* update */)) {
+ if (!PermissionsUtil.checkAllPermissionsGranted(
+ mContext, Manifest.permission.READ_CONTACTS)) {
+ Log.i(TAG, "No permission to read contacts. Not updating the contacts.");
+ unregister();
+ return;
+ }
+
+ if (!mRunning.compareAndSet(false /* expect */, true /* update */)) {
if (DebugFlags.DEBUG_ENABLED) {
Log.d(TAG, "run() : Already running. Don't waste time checking again.");
}
@@ -78,10 +94,16 @@ public class ContactsContentObserver implements Runnable {
}
mContactsChangedListener.onContactsChange();
}
- sRunning.set(false);
+ mRunning.set(false);
}
boolean haveContentsChanged() {
+ if (!PermissionsUtil.checkAllPermissionsGranted(
+ mContext, Manifest.permission.READ_CONTACTS)) {
+ Log.i(TAG, "No permission to read contacts. Marking contacts as not changed.");
+ return false;
+ }
+
final long startTime = SystemClock.uptimeMillis();
final int contactCount = mManager.getContactCount();
if (contactCount > ContactsDictionaryConstants.MAX_CONTACTS_PROVIDER_QUERY_LIMIT) {
diff --git a/java/src/com/android/inputmethod/latin/DictionaryFacilitatorImpl.java b/java/src/com/android/inputmethod/latin/DictionaryFacilitatorImpl.java
index c7115c9d9..b435de867 100644
--- a/java/src/com/android/inputmethod/latin/DictionaryFacilitatorImpl.java
+++ b/java/src/com/android/inputmethod/latin/DictionaryFacilitatorImpl.java
@@ -16,6 +16,7 @@
package com.android.inputmethod.latin;
+import android.Manifest;
import android.content.Context;
import android.text.TextUtils;
import android.util.Log;
@@ -28,6 +29,7 @@ import com.android.inputmethod.latin.SuggestedWords.SuggestedWordInfo;
import com.android.inputmethod.latin.common.ComposedData;
import com.android.inputmethod.latin.common.Constants;
import com.android.inputmethod.latin.common.StringUtils;
+import com.android.inputmethod.latin.permissions.PermissionsUtil;
import com.android.inputmethod.latin.personalization.UserHistoryDictionary;
import com.android.inputmethod.latin.settings.SettingsValuesForSuggestion;
import com.android.inputmethod.latin.utils.ExecutorUtils;
@@ -287,7 +289,11 @@ public class DictionaryFacilitatorImpl implements DictionaryFacilitator {
// TODO: Make subDictTypesToUse configurable by resource or a static final list.
final HashSet subDictTypesToUse = new HashSet<>();
subDictTypesToUse.add(Dictionary.TYPE_USER);
- if (useContactsDict) {
+
+ // Do not use contacts dictionary if we do not have permissions to read contacts.
+ final boolean contactsPermissionGranted = PermissionsUtil.checkAllPermissionsGranted(
+ context, Manifest.permission.READ_CONTACTS);
+ if (useContactsDict && contactsPermissionGranted) {
subDictTypesToUse.add(Dictionary.TYPE_CONTACTS);
}
if (usePersonalizedDicts) {
diff --git a/java/src/com/android/inputmethod/latin/ImportantNoticeDialog.java b/java/src/com/android/inputmethod/latin/ImportantNoticeDialog.java
deleted file mode 100644
index 567087c81..000000000
--- a/java/src/com/android/inputmethod/latin/ImportantNoticeDialog.java
+++ /dev/null
@@ -1,78 +0,0 @@
-/*
- * Copyright (C) 2014 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;
-
-import android.app.AlertDialog;
-import android.content.Context;
-import android.content.DialogInterface;
-import android.content.DialogInterface.OnClickListener;
-
-import com.android.inputmethod.latin.utils.DialogUtils;
-import com.android.inputmethod.latin.utils.ImportantNoticeUtils;
-
-/**
- * The dialog box that shows the important notice contents.
- */
-public final class ImportantNoticeDialog extends AlertDialog implements OnClickListener {
- public interface ImportantNoticeDialogListener {
- public void onUserAcknowledgmentOfImportantNoticeDialog(final int nextVersion);
- public void onClickSettingsOfImportantNoticeDialog(final int nextVersion);
- }
-
- private final ImportantNoticeDialogListener mListener;
- private final int mNextImportantNoticeVersion;
-
- public ImportantNoticeDialog(
- final Context context, final ImportantNoticeDialogListener listener) {
- super(DialogUtils.getPlatformDialogThemeContext(context));
- mListener = listener;
- mNextImportantNoticeVersion = ImportantNoticeUtils.getNextImportantNoticeVersion(context);
- setMessage(ImportantNoticeUtils.getNextImportantNoticeContents(context));
- // Create buttons and set listeners.
- setButton(BUTTON_POSITIVE, context.getString(android.R.string.ok), this);
- if (shouldHaveSettingsButton()) {
- setButton(BUTTON_NEGATIVE, context.getString(R.string.go_to_settings), this);
- }
- // This dialog is cancelable by pressing back key. See {@link #onBackPress()}.
- setCancelable(true /* cancelable */);
- setCanceledOnTouchOutside(false /* cancelable */);
- }
-
- private boolean shouldHaveSettingsButton() {
- return mNextImportantNoticeVersion
- == ImportantNoticeUtils.VERSION_TO_ENABLE_PERSONALIZED_SUGGESTIONS;
- }
-
- private void userAcknowledged() {
- ImportantNoticeUtils.updateLastImportantNoticeVersion(getContext());
- mListener.onUserAcknowledgmentOfImportantNoticeDialog(mNextImportantNoticeVersion);
- }
-
- @Override
- public void onClick(final DialogInterface dialog, final int which) {
- if (shouldHaveSettingsButton() && which == BUTTON_NEGATIVE) {
- mListener.onClickSettingsOfImportantNoticeDialog(mNextImportantNoticeVersion);
- }
- userAcknowledged();
- }
-
- @Override
- public void onBackPressed() {
- super.onBackPressed();
- userAcknowledged();
- }
-}
diff --git a/java/src/com/android/inputmethod/latin/LatinIME.java b/java/src/com/android/inputmethod/latin/LatinIME.java
index 089670ebf..1f2b6f25d 100644
--- a/java/src/com/android/inputmethod/latin/LatinIME.java
+++ b/java/src/com/android/inputmethod/latin/LatinIME.java
@@ -20,6 +20,7 @@ import static com.android.inputmethod.latin.common.Constants.ImeOption.FORCE_ASC
import static com.android.inputmethod.latin.common.Constants.ImeOption.NO_MICROPHONE;
import static com.android.inputmethod.latin.common.Constants.ImeOption.NO_MICROPHONE_COMPAT;
+import android.Manifest.permission;
import android.app.AlertDialog;
import android.content.BroadcastReceiver;
import android.content.Context;
@@ -73,6 +74,7 @@ import com.android.inputmethod.latin.common.InputPointers;
import com.android.inputmethod.latin.define.DebugFlags;
import com.android.inputmethod.latin.define.ProductionFlags;
import com.android.inputmethod.latin.inputlogic.InputLogic;
+import com.android.inputmethod.latin.permissions.PermissionsManager;
import com.android.inputmethod.latin.personalization.PersonalizationHelper;
import com.android.inputmethod.latin.settings.Settings;
import com.android.inputmethod.latin.settings.SettingsActivity;
@@ -106,7 +108,7 @@ import javax.annotation.Nonnull;
public class LatinIME extends InputMethodService implements KeyboardActionListener,
SuggestionStripView.Listener, SuggestionStripViewAccessor,
DictionaryFacilitator.DictionaryInitializationListener,
- ImportantNoticeDialog.ImportantNoticeDialogListener {
+ PermissionsManager.PermissionsResultCallback {
static final String TAG = LatinIME.class.getSimpleName();
private static final boolean TRACE = false;
@@ -1251,18 +1253,14 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
// pressed.
@Override
public void showImportantNoticeContents() {
- showOptionDialog(new ImportantNoticeDialog(this /* context */, this /* listener */));
+ PermissionsManager.get(this).requestPermissions(
+ this /* PermissionsResultCallback */,
+ null /* activity */, permission.READ_CONTACTS);
}
- // Implement {@link ImportantNoticeDialog.ImportantNoticeDialogListener}
@Override
- public void onClickSettingsOfImportantNoticeDialog(final int nextVersion) {
- launchSettings(SettingsActivity.EXTRA_ENTRY_VALUE_NOTICE_DIALOG);
- }
-
- // Implement {@link ImportantNoticeDialog.ImportantNoticeDialogListener}
- @Override
- public void onUserAcknowledgmentOfImportantNoticeDialog(final int nextVersion) {
+ public void onRequestPermissionsResult(boolean allGranted) {
+ ImportantNoticeUtils.updateContactsNoticeShown(this /* context */);
setNeutralSuggestionStrip();
}
diff --git a/java/src/com/android/inputmethod/latin/permissions/PermissionsActivity.java b/java/src/com/android/inputmethod/latin/permissions/PermissionsActivity.java
new file mode 100644
index 000000000..bdd63fa00
--- /dev/null
+++ b/java/src/com/android/inputmethod/latin/permissions/PermissionsActivity.java
@@ -0,0 +1,97 @@
+/*
+ * Copyright (C) 2015 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.permissions;
+
+
+import android.app.Activity;
+import android.content.Context;
+import android.content.Intent;
+import android.os.Bundle;
+import android.support.annotation.NonNull;
+import android.support.v4.app.ActivityCompat;
+
+/**
+ * An activity to help request permissions. It's used when no other activity is available, e.g. in
+ * InputMethodService. This activity assumes that all permissions are not granted yet.
+ */
+public final class PermissionsActivity
+ extends Activity implements ActivityCompat.OnRequestPermissionsResultCallback {
+
+ /**
+ * Key to retrieve requested permissions from the intent.
+ */
+ public static final String EXTRA_PERMISSION_REQUESTED_PERMISSIONS = "requested_permissions";
+
+ /**
+ * Key to retrieve request code from the intent.
+ */
+ public static final String EXTRA_PERMISSION_REQUEST_CODE = "request_code";
+
+ private static final int INVALID_REQUEST_CODE = -1;
+
+ private int mPendingRequestCode = INVALID_REQUEST_CODE;
+
+ /**
+ * Starts a PermissionsActivity and checks/requests supplied permissions.
+ */
+ public static void run(
+ @NonNull Context context, int requestCode, @NonNull String... permissionStrings) {
+ Intent intent = new Intent(context.getApplicationContext(), PermissionsActivity.class);
+ intent.putExtra(EXTRA_PERMISSION_REQUESTED_PERMISSIONS, permissionStrings);
+ intent.putExtra(EXTRA_PERMISSION_REQUEST_CODE, requestCode);
+ intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS);
+ context.startActivity(intent);
+ }
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ mPendingRequestCode = (savedInstanceState != null)
+ ? savedInstanceState.getInt(EXTRA_PERMISSION_REQUEST_CODE, INVALID_REQUEST_CODE)
+ : INVALID_REQUEST_CODE;
+ }
+
+ @Override
+ protected void onSaveInstanceState(Bundle outState) {
+ super.onSaveInstanceState(outState);
+ outState.putInt(EXTRA_PERMISSION_REQUEST_CODE, mPendingRequestCode);
+ }
+
+ @Override
+ protected void onResume() {
+ super.onResume();
+ // Only do request when there is no pending request to avoid duplicated requests.
+ if (mPendingRequestCode == INVALID_REQUEST_CODE) {
+ final Bundle extras = getIntent().getExtras();
+ final String[] permissionsToRequest =
+ extras.getStringArray(EXTRA_PERMISSION_REQUESTED_PERMISSIONS);
+ mPendingRequestCode = extras.getInt(EXTRA_PERMISSION_REQUEST_CODE);
+ // Assuming that all supplied permissions are not granted yet, so that we don't need to
+ // check them again.
+ PermissionsUtil.requestPermissions(this, mPendingRequestCode, permissionsToRequest);
+ }
+ }
+
+ @Override
+ public void onRequestPermissionsResult(
+ int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
+ mPendingRequestCode = INVALID_REQUEST_CODE;
+ PermissionsManager.get(this).onRequestPermissionsResult(
+ requestCode, permissions, grantResults);
+ finish();
+ }
+}
diff --git a/java/src/com/android/inputmethod/latin/permissions/PermissionsManager.java b/java/src/com/android/inputmethod/latin/permissions/PermissionsManager.java
new file mode 100644
index 000000000..08c623ab5
--- /dev/null
+++ b/java/src/com/android/inputmethod/latin/permissions/PermissionsManager.java
@@ -0,0 +1,91 @@
+/*
+ * Copyright (C) 2015 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.permissions;
+
+import android.app.Activity;
+import android.content.Context;
+
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import javax.annotation.Nonnull;
+import javax.annotation.Nullable;
+
+/**
+ * Manager to perform permission related tasks. Always call on the UI thread.
+ */
+public class PermissionsManager {
+
+ public interface PermissionsResultCallback {
+ void onRequestPermissionsResult(boolean allGranted);
+ }
+
+ private int mRequestCodeId;
+
+ private final Context mContext;
+ private final Map mRequestIdToCallback = new HashMap<>();
+
+ private static PermissionsManager sInstance;
+
+ public PermissionsManager(Context context) {
+ mContext = context;
+ }
+
+ @Nonnull
+ public static synchronized PermissionsManager get(@Nonnull Context context) {
+ if (sInstance == null) {
+ sInstance = new PermissionsManager(context);
+ }
+ return sInstance;
+ }
+
+ private synchronized int getNextRequestId() {
+ return ++mRequestCodeId;
+ }
+
+
+ public synchronized void requestPermissions(@Nonnull PermissionsResultCallback callback,
+ @Nullable Activity activity,
+ String... permissionsToRequest) {
+ List deniedPermissions = PermissionsUtil.getDeniedPermissions(
+ mContext, permissionsToRequest);
+ if (deniedPermissions.isEmpty()) {
+ return;
+ }
+ // otherwise request the permissions.
+ int requestId = getNextRequestId();
+ String[] permissionsArray = deniedPermissions.toArray(
+ new String[deniedPermissions.size()]);
+
+ mRequestIdToCallback.put(requestId, callback);
+ if (activity != null) {
+ PermissionsUtil.requestPermissions(activity, requestId, permissionsArray);
+ } else {
+ PermissionsActivity.run(mContext, requestId, permissionsArray);
+ }
+ }
+
+ public synchronized void onRequestPermissionsResult(
+ int requestCode, String[] permissions, int[] grantResults) {
+ PermissionsResultCallback permissionsResultCallback = mRequestIdToCallback.get(requestCode);
+ mRequestIdToCallback.remove(requestCode);
+
+ boolean allGranted = PermissionsUtil.allGranted(grantResults);
+ permissionsResultCallback.onRequestPermissionsResult(allGranted);
+ }
+}
diff --git a/java/src/com/android/inputmethod/latin/permissions/PermissionsUtil.java b/java/src/com/android/inputmethod/latin/permissions/PermissionsUtil.java
new file mode 100644
index 000000000..747f64f24
--- /dev/null
+++ b/java/src/com/android/inputmethod/latin/permissions/PermissionsUtil.java
@@ -0,0 +1,93 @@
+/*
+ * Copyright (C) 2015 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.permissions;
+
+import android.app.Activity;
+import android.content.Context;
+import android.content.pm.PackageManager;
+import android.os.Build;
+import android.support.annotation.NonNull;
+import android.support.v4.app.ActivityCompat;
+import android.support.v4.content.ContextCompat;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Utility class for permissions.
+ */
+public class PermissionsUtil {
+
+ /**
+ * Returns the list of permissions not granted from the given list of permissions.
+ * @param context Context
+ * @param permissions list of permissions to check.
+ * @return the list of permissions that do not have permission to use.
+ */
+ public static List getDeniedPermissions(Context context,
+ String... permissions) {
+ final List deniedPermissions = new ArrayList<>();
+ for (String permission : permissions) {
+ if (ContextCompat.checkSelfPermission(context, permission)
+ != PackageManager.PERMISSION_GRANTED) {
+ deniedPermissions.add(permission);
+ }
+ }
+ return deniedPermissions;
+ }
+
+ /**
+ * Uses the given activity and requests the user for permissions.
+ * @param activity activity to use.
+ * @param requestCode request code/id to use.
+ * @param permissions String array of permissions that needs to be requested.
+ */
+ public static void requestPermissions(Activity activity, int requestCode,
+ String[] permissions) {
+ ActivityCompat.requestPermissions(activity, permissions, requestCode);
+ }
+
+ /**
+ * Checks if all the permissions are granted.
+ */
+ public static boolean allGranted(@NonNull int[] grantResults) {
+ for (int result : grantResults) {
+ if (result != PackageManager.PERMISSION_GRANTED) {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ /**
+ * Queries if al the permissions are granted for the given permission strings.
+ */
+ public static boolean checkAllPermissionsGranted(Context context, String... permissions) {
+ if (Build.VERSION.SDK_INT <= Build.VERSION_CODES.LOLLIPOP_MR1) {
+ // For all pre-M devices, we should have all the premissions granted on install.
+ return true;
+ }
+
+ for (String permission : permissions) {
+ if (ContextCompat.checkSelfPermission(context, permission)
+ != PackageManager.PERMISSION_GRANTED) {
+ return false;
+ }
+ }
+ return true;
+ }
+}
diff --git a/java/src/com/android/inputmethod/latin/settings/CorrectionSettingsFragment.java b/java/src/com/android/inputmethod/latin/settings/CorrectionSettingsFragment.java
index d28e703fe..dfe899ece 100644
--- a/java/src/com/android/inputmethod/latin/settings/CorrectionSettingsFragment.java
+++ b/java/src/com/android/inputmethod/latin/settings/CorrectionSettingsFragment.java
@@ -16,17 +16,23 @@
package com.android.inputmethod.latin.settings;
+import android.Manifest;
import android.app.Activity;
import android.content.Context;
import android.content.Intent;
+import android.content.SharedPreferences;
import android.content.pm.PackageManager;
import android.content.pm.ResolveInfo;
import android.os.Build;
import android.os.Bundle;
import android.preference.Preference;
+import android.preference.SwitchPreference;
+import android.text.TextUtils;
import com.android.inputmethod.dictionarypack.DictionarySettingsActivity;
import com.android.inputmethod.latin.R;
+import com.android.inputmethod.latin.permissions.PermissionsManager;
+import com.android.inputmethod.latin.permissions.PermissionsUtil;
import com.android.inputmethod.latin.userdictionary.UserDictionaryList;
import com.android.inputmethod.latin.userdictionary.UserDictionarySettings;
@@ -45,12 +51,17 @@ import java.util.TreeSet;
* - Suggest Contact names
* - Next-word suggestions
*/
-public final class CorrectionSettingsFragment extends SubScreenFragment {
+public final class CorrectionSettingsFragment extends SubScreenFragment
+ implements SharedPreferences.OnSharedPreferenceChangeListener,
+ PermissionsManager.PermissionsResultCallback {
+
private static final boolean DBG_USE_INTERNAL_PERSONAL_DICTIONARY_SETTINGS = false;
private static final boolean USE_INTERNAL_PERSONAL_DICTIONARY_SETTINGS =
DBG_USE_INTERNAL_PERSONAL_DICTIONARY_SETTINGS
|| Build.VERSION.SDK_INT <= Build.VERSION_CODES.JELLY_BEAN_MR2;
+ private SwitchPreference mUseContactsPreference;
+
@Override
public void onCreate(final Bundle icicle) {
super.onCreate(icicle);
@@ -76,6 +87,9 @@ public final class CorrectionSettingsFragment extends SubScreenFragment {
if (ri == null) {
overwriteUserDictionaryPreference(editPersonalDictionary);
}
+
+ mUseContactsPreference = (SwitchPreference) findPreference(Settings.PREF_KEY_USE_CONTACTS_DICT);
+ turnOffUseContactsIfNoPermission();
}
private void overwriteUserDictionaryPreference(final Preference userDictionaryPreference) {
@@ -101,4 +115,38 @@ public final class CorrectionSettingsFragment extends SubScreenFragment {
userDictionaryPreference.setFragment(UserDictionaryList.class.getName());
}
}
+
+ @Override
+ public void onSharedPreferenceChanged(final SharedPreferences sharedPreferences, final String key) {
+ if (!TextUtils.equals(key, Settings.PREF_KEY_USE_CONTACTS_DICT)) {
+ return;
+ }
+ if (!sharedPreferences.getBoolean(key, false)) {
+ // don't care if the preference is turned off.
+ return;
+ }
+
+ // Check for permissions.
+ if (PermissionsUtil.checkAllPermissionsGranted(
+ getActivity() /* context */, Manifest.permission.READ_CONTACTS)) {
+ return; // all permissions granted, no need to request permissions.
+ }
+
+ PermissionsManager.get(getActivity() /* context */).requestPermissions(
+ this /* PermissionsResultCallback */,
+ getActivity() /* activity */,
+ Manifest.permission.READ_CONTACTS);
+ }
+
+ @Override
+ public void onRequestPermissionsResult(boolean allGranted) {
+ turnOffUseContactsIfNoPermission();
+ }
+
+ private void turnOffUseContactsIfNoPermission() {
+ if (!PermissionsUtil.checkAllPermissionsGranted(
+ getActivity(), Manifest.permission.READ_CONTACTS)) {
+ mUseContactsPreference.setChecked(false);
+ }
+ }
}
diff --git a/java/src/com/android/inputmethod/latin/settings/SettingsActivity.java b/java/src/com/android/inputmethod/latin/settings/SettingsActivity.java
index 9975277e4..a7d157a6b 100644
--- a/java/src/com/android/inputmethod/latin/settings/SettingsActivity.java
+++ b/java/src/com/android/inputmethod/latin/settings/SettingsActivity.java
@@ -16,6 +16,7 @@
package com.android.inputmethod.latin.settings;
+import com.android.inputmethod.latin.permissions.PermissionsManager;
import com.android.inputmethod.latin.utils.FragmentUtils;
import com.android.inputmethod.latin.utils.StatsUtils;
import com.android.inputmethod.latin.utils.StatsUtilsManager;
@@ -24,9 +25,11 @@ import android.app.ActionBar;
import android.content.Intent;
import android.os.Bundle;
import android.preference.PreferenceActivity;
+import android.support.v4.app.ActivityCompat;
import android.view.MenuItem;
-public final class SettingsActivity extends PreferenceActivity {
+public final class SettingsActivity extends PreferenceActivity
+ implements ActivityCompat.OnRequestPermissionsResultCallback {
private static final String DEFAULT_FRAGMENT = SettingsFragment.class.getName();
public static final String EXTRA_SHOW_HOME_AS_UP = "show_home_as_up";
@@ -77,4 +80,9 @@ public final class SettingsActivity extends PreferenceActivity {
public boolean isValidFragment(final String fragmentName) {
return FragmentUtils.isValidFragment(fragmentName);
}
+
+ @Override
+ public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {
+ PermissionsManager.get(this).onRequestPermissionsResult(requestCode, permissions, grantResults);
+ }
}
diff --git a/java/src/com/android/inputmethod/latin/suggestions/SuggestionStripView.java b/java/src/com/android/inputmethod/latin/suggestions/SuggestionStripView.java
index 7dd0f03df..c1d1fad68 100644
--- a/java/src/com/android/inputmethod/latin/suggestions/SuggestionStripView.java
+++ b/java/src/com/android/inputmethod/latin/suggestions/SuggestionStripView.java
@@ -220,7 +220,7 @@ public final class SuggestionStripView extends RelativeLayout implements OnClick
if (getWidth() <= 0) {
return false;
}
- final String importantNoticeTitle = ImportantNoticeUtils.getNextImportantNoticeTitle(
+ final String importantNoticeTitle = ImportantNoticeUtils.getSuggestContactsNoticeTitle(
getContext());
if (TextUtils.isEmpty(importantNoticeTitle)) {
return false;
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;
}
- final String importantNoticeTitle = getNextImportantNoticeTitle(context);
+
+ // Don't show the dialog if we have all the permissions.
+ if (PermissionsUtil.checkAllPermissionsGranted(
+ context, Manifest.permission.READ_CONTACTS)) {
+ return false;
+ }
+
+ 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) {
+ public static String getSuggestContactsNoticeTitle(final Context context) {
+ return context.getResources().getString(R.string.important_notice_suggest_contact_names);
+ }
+
+ @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();
+ }
+ final long firstDisplayTimeInMillis = prefs.getLong(
+ KEY_TIMESTAMP_OF_CONTACTS_NOTICE, currentTimeInMillis);
+ final long elapsedTime = currentTimeInMillis - firstDisplayTimeInMillis;
+ return elapsedTime >= TIMEOUT_OF_IMPORTANT_NOTICE;
+ }
+
+ public static void updateContactsNoticeShown(final Context context) {
getImportantNoticePreferences(context)
.edit()
- .putInt(KEY_IMPORTANT_NOTICE_VERSION, getNextImportantNoticeVersion(context))
- .remove(KEY_TIMESTAMP_OF_FIRST_IMPORTANT_NOTICE)
+ .putBoolean(KEY_SUGGEST_CONTACTS_NOTICE, true)
+ .remove(KEY_TIMESTAMP_OF_CONTACTS_NOTICE)
.apply();
}
-
- 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];
- }
- return null;
- }
-
- 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;
- }
}
diff --git a/tests/src/com/android/inputmethod/latin/utils/ImportantNoticeUtilsTests.java b/tests/src/com/android/inputmethod/latin/utils/ImportantNoticeUtilsTests.java
index e361c7704..df0180729 100644
--- a/tests/src/com/android/inputmethod/latin/utils/ImportantNoticeUtilsTests.java
+++ b/tests/src/com/android/inputmethod/latin/utils/ImportantNoticeUtilsTests.java
@@ -16,8 +16,7 @@
package com.android.inputmethod.latin.utils;
-import static com.android.inputmethod.latin.utils.ImportantNoticeUtils.KEY_IMPORTANT_NOTICE_VERSION;
-import static com.android.inputmethod.latin.utils.ImportantNoticeUtils.KEY_TIMESTAMP_OF_FIRST_IMPORTANT_NOTICE;
+import static com.android.inputmethod.latin.utils.ImportantNoticeUtils.KEY_TIMESTAMP_OF_CONTACTS_NOTICE;
import static org.mockito.Mockito.when;
import android.content.Context;
@@ -35,8 +34,6 @@ import java.util.concurrent.TimeUnit;
@MediumTest
public class ImportantNoticeUtilsTests extends AndroidTestCase {
- // This should be aligned with R.integer.config_important_notice_version.
- private static final int CURRENT_IMPORTANT_NOTICE_VERSION = 1;
private ImportantNoticePreferences mImportantNoticePreferences;
@@ -87,18 +84,15 @@ public class ImportantNoticeUtilsTests extends AndroidTestCase {
}
public void save() {
- mVersion = getInt(KEY_IMPORTANT_NOTICE_VERSION);
- mLastTime = getLong(KEY_TIMESTAMP_OF_FIRST_IMPORTANT_NOTICE);
+ mLastTime = getLong(KEY_TIMESTAMP_OF_CONTACTS_NOTICE);
}
public void restore() {
- putInt(KEY_IMPORTANT_NOTICE_VERSION, mVersion);
- putLong(KEY_TIMESTAMP_OF_FIRST_IMPORTANT_NOTICE, mLastTime);
+ putLong(KEY_TIMESTAMP_OF_CONTACTS_NOTICE, mLastTime);
}
public void clear() {
- removePreference(KEY_IMPORTANT_NOTICE_VERSION);
- removePreference(KEY_TIMESTAMP_OF_FIRST_IMPORTANT_NOTICE);
+ removePreference(KEY_TIMESTAMP_OF_CONTACTS_NOTICE);
}
}
@@ -117,141 +111,6 @@ public class ImportantNoticeUtilsTests extends AndroidTestCase {
mImportantNoticePreferences.restore();
}
- public void testCurrentVersion() {
- assertEquals("Current version", CURRENT_IMPORTANT_NOTICE_VERSION,
- ImportantNoticeUtils.getCurrentImportantNoticeVersion(getContext()));
- }
-
- public void testStateAfterFreshInstall() {
- mImportantNoticePreferences.clear();
-
- // Check internal state of {@link ImportantNoticeUtils.shouldShowImportantNotice(Context)}
- // after fresh install.
- assertEquals("Has new important notice after fresh install", true,
- ImportantNoticeUtils.hasNewImportantNotice(getContext()));
- assertEquals("Next important notice title after fresh install", false, TextUtils.isEmpty(
- ImportantNoticeUtils.getNextImportantNoticeTitle(getContext())));
- assertEquals("Is in system setup wizard after fresh install", false,
- ImportantNoticeUtils.isInSystemSetupWizard(getContext()));
- final long currentTimeMillis = System.currentTimeMillis();
- assertEquals("Has timeout passed after fresh install", false,
- ImportantNoticeUtils.hasTimeoutPassed(getContext(), currentTimeMillis));
- assertEquals("Timestamp of first important notice after fresh install",
- (Long)currentTimeMillis,
- mImportantNoticePreferences.getLong(KEY_TIMESTAMP_OF_FIRST_IMPORTANT_NOTICE));
-
- assertEquals("Current boolean before update", true,
- ImportantNoticeUtils.shouldShowImportantNotice(getContext(), mMockSettingsValues));
- }
-
- public void testUpdateVersion() {
- mImportantNoticePreferences.clear();
-
- assertEquals("Current boolean before update", true,
- ImportantNoticeUtils.shouldShowImportantNotice(getContext(), mMockSettingsValues));
- assertEquals("Last version before update", 0,
- ImportantNoticeUtils.getLastImportantNoticeVersion(getContext()));
- assertEquals("Next version before update ", 1,
- ImportantNoticeUtils.getNextImportantNoticeVersion(getContext()));
- assertEquals("Current title before update", false, TextUtils.isEmpty(
- ImportantNoticeUtils.getNextImportantNoticeTitle(getContext())));
- assertEquals("Current contents before update", false, TextUtils.isEmpty(
- ImportantNoticeUtils.getNextImportantNoticeContents(getContext())));
-
- ImportantNoticeUtils.updateLastImportantNoticeVersion(getContext());
-
- assertEquals("Current boolean after update", false,
- ImportantNoticeUtils.shouldShowImportantNotice(getContext(), mMockSettingsValues));
- assertEquals("Last version after update", 1,
- ImportantNoticeUtils.getLastImportantNoticeVersion(getContext()));
- assertEquals("Next version after update", 2,
- ImportantNoticeUtils.getNextImportantNoticeVersion(getContext()));
- assertEquals("Current title after update", true, TextUtils.isEmpty(
- ImportantNoticeUtils.getNextImportantNoticeTitle(getContext())));
- assertEquals("Current contents after update", true, TextUtils.isEmpty(
- ImportantNoticeUtils.getNextImportantNoticeContents(getContext())));
- }
-
- private static void sleep(final long millseconds) {
- try { Thread.sleep(millseconds); } catch (final Exception e) { /* ignore */ }
- }
-
- public void testTimeout() {
- final long lastTime = System.currentTimeMillis()
- - ImportantNoticeUtils.TIMEOUT_OF_IMPORTANT_NOTICE
- + TimeUnit.MILLISECONDS.toMillis(1000);
- mImportantNoticePreferences.clear();
- assertEquals("Before set last time", null,
- mImportantNoticePreferences.getLong(KEY_TIMESTAMP_OF_FIRST_IMPORTANT_NOTICE));
- assertEquals("Set last time", false,
- ImportantNoticeUtils.hasTimeoutPassed(getContext(), lastTime));
- assertEquals("After set last time", (Long)lastTime,
- mImportantNoticePreferences.getLong(KEY_TIMESTAMP_OF_FIRST_IMPORTANT_NOTICE));
-
- // Call {@link ImportantNoticeUtils#shouldShowImportantNotice(Context)} before timeout.
- assertEquals("Current boolean before timeout 1", true,
- ImportantNoticeUtils.shouldShowImportantNotice(getContext(), mMockSettingsValues));
- assertEquals("Last version before timeout 1", 0,
- ImportantNoticeUtils.getLastImportantNoticeVersion(getContext()));
- assertEquals("Next version before timeout 1", 1,
- ImportantNoticeUtils.getNextImportantNoticeVersion(getContext()));
- assertEquals("Timestamp of first important notice before timeout 1", (Long)lastTime,
- mImportantNoticePreferences.getLong(KEY_TIMESTAMP_OF_FIRST_IMPORTANT_NOTICE));
- assertEquals("Current title before timeout 1", false, TextUtils.isEmpty(
- ImportantNoticeUtils.getNextImportantNoticeTitle(getContext())));
- assertEquals("Current contents before timeout 1", false, TextUtils.isEmpty(
- ImportantNoticeUtils.getNextImportantNoticeContents(getContext())));
-
- sleep(TimeUnit.MILLISECONDS.toMillis(600));
-
- // Call {@link ImportantNoticeUtils#shouldShowImportantNotice(Context)} before timeout
- // again.
- assertEquals("Current boolean before timeout 2", true,
- ImportantNoticeUtils.shouldShowImportantNotice(getContext(), mMockSettingsValues));
- assertEquals("Last version before timeout 2", 0,
- ImportantNoticeUtils.getLastImportantNoticeVersion(getContext()));
- assertEquals("Next version before timeout 2", 1,
- ImportantNoticeUtils.getNextImportantNoticeVersion(getContext()));
- assertEquals("Timestamp of first important notice before timeout 2", (Long)lastTime,
- mImportantNoticePreferences.getLong(KEY_TIMESTAMP_OF_FIRST_IMPORTANT_NOTICE));
- assertEquals("Current title before timeout 2", false, TextUtils.isEmpty(
- ImportantNoticeUtils.getNextImportantNoticeTitle(getContext())));
- assertEquals("Current contents before timeout 2", false, TextUtils.isEmpty(
- ImportantNoticeUtils.getNextImportantNoticeContents(getContext())));
-
- sleep(TimeUnit.MILLISECONDS.toMillis(600));
-
- // Call {@link ImportantNoticeUtils#shouldShowImportantNotice(Context)} after timeout.
- assertEquals("Current boolean after timeout 1", false,
- ImportantNoticeUtils.shouldShowImportantNotice(getContext(), mMockSettingsValues));
- assertEquals("Last version after timeout 1", 1,
- ImportantNoticeUtils.getLastImportantNoticeVersion(getContext()));
- assertEquals("Next version after timeout 1", 2,
- ImportantNoticeUtils.getNextImportantNoticeVersion(getContext()));
- assertEquals("Timestamp of first important notice after timeout 1", null,
- mImportantNoticePreferences.getLong(KEY_TIMESTAMP_OF_FIRST_IMPORTANT_NOTICE));
- assertEquals("Current title after timeout 1", true, TextUtils.isEmpty(
- ImportantNoticeUtils.getNextImportantNoticeTitle(getContext())));
- assertEquals("Current contents after timeout 1", true, TextUtils.isEmpty(
- ImportantNoticeUtils.getNextImportantNoticeContents(getContext())));
-
- sleep(TimeUnit.MILLISECONDS.toMillis(600));
-
- // Call {@link ImportantNoticeUtils#shouldShowImportantNotice(Context)} after timeout again.
- assertEquals("Current boolean after timeout 2", false,
- ImportantNoticeUtils.shouldShowImportantNotice(getContext(), mMockSettingsValues));
- assertEquals("Last version after timeout 2", 1,
- ImportantNoticeUtils.getLastImportantNoticeVersion(getContext()));
- assertEquals("Next version after timeout 2", 2,
- ImportantNoticeUtils.getNextImportantNoticeVersion(getContext()));
- assertEquals("Timestamp of first important notice after timeout 2", null,
- mImportantNoticePreferences.getLong(KEY_TIMESTAMP_OF_FIRST_IMPORTANT_NOTICE));
- assertEquals("Current title after timeout 2", true, TextUtils.isEmpty(
- ImportantNoticeUtils.getNextImportantNoticeTitle(getContext())));
- assertEquals("Current contents after timeout 2", true, TextUtils.isEmpty(
- ImportantNoticeUtils.getNextImportantNoticeContents(getContext())));
- }
-
public void testPersonalizationSetting() {
mImportantNoticePreferences.clear();