am ca8053d7: am 707ca769: Handle Cloud Sync and SpellChecker settings when permission changed

* commit 'ca8053d7f3236b7d6df1ed6709172b2f887b477e':
  Handle Cloud Sync and SpellChecker settings when permission changed
diff --git a/java/src/com/android/inputmethod/latin/settings/AccountsSettingsFragment.java b/java/src/com/android/inputmethod/latin/settings/AccountsSettingsFragment.java
index cb20978..b39e6b4 100644
--- a/java/src/com/android/inputmethod/latin/settings/AccountsSettingsFragment.java
+++ b/java/src/com/android/inputmethod/latin/settings/AccountsSettingsFragment.java
@@ -19,6 +19,7 @@
 import static com.android.inputmethod.latin.settings.LocalSettingsConstants.PREF_ACCOUNT_NAME;
 import static com.android.inputmethod.latin.settings.LocalSettingsConstants.PREF_ENABLE_CLOUD_SYNC;
 
+import android.Manifest;
 import android.app.AlertDialog;
 import android.content.Context;
 import android.content.DialogInterface;
@@ -40,6 +41,7 @@
 import com.android.inputmethod.latin.accounts.AccountStateChangedListener;
 import com.android.inputmethod.latin.accounts.LoginAccountUtils;
 import com.android.inputmethod.latin.define.ProductionFlags;
+import com.android.inputmethod.latin.permissions.PermissionsUtil;
 import com.android.inputmethod.latin.utils.ManagedProfileUtils;
 
 import java.util.concurrent.atomic.AtomicBoolean;
@@ -254,11 +256,14 @@
         if (!ProductionFlags.ENABLE_USER_HISTORY_DICTIONARY_SYNC) {
             return;
         }
-        final String[] accountsForLogin =
-                LoginAccountUtils.getAccountsForLogin(getActivity());
-        final String currentAccount = getSignedInAccountName();
+        boolean hasAccountsPermission = PermissionsUtil.checkAllPermissionsGranted(
+            getActivity(), Manifest.permission.READ_CONTACTS);
 
-        if (!mManagedProfileBeingDetected.get() &&
+        final String[] accountsForLogin = hasAccountsPermission ?
+                LoginAccountUtils.getAccountsForLogin(getActivity()) : new String[0];
+        final String currentAccount = hasAccountsPermission ? getSignedInAccountName() : null;
+
+        if (hasAccountsPermission && !mManagedProfileBeingDetected.get() &&
                 !mHasManagedProfile.get() && accountsForLogin.length > 0) {
             // Sync can be used by user; enable all preferences.
             enableSyncPreferences(accountsForLogin, currentAccount);
@@ -266,26 +271,35 @@
             // Sync cannot be used by user; disable all preferences.
             disableSyncPreferences();
         }
-        refreshSyncSettingsMessaging(mManagedProfileBeingDetected.get(),
+        refreshSyncSettingsMessaging(hasAccountsPermission, mManagedProfileBeingDetected.get(),
                 mHasManagedProfile.get(), accountsForLogin.length > 0,
                 currentAccount);
     }
 
     /**
+     * @param hasAccountsPermission whether the app has the permission to read accounts.
      * @param managedProfileBeingDetected whether we are in process of determining work profile.
      * @param hasManagedProfile whether the device has work profile.
      * @param hasAccountsForLogin whether the device has enough accounts for login.
      * @param currentAccount the account currently selected in the application.
      */
-    private void refreshSyncSettingsMessaging(boolean managedProfileBeingDetected,
-            boolean hasManagedProfile, boolean hasAccountsForLogin, String currentAccount) {
+    private void refreshSyncSettingsMessaging(boolean hasAccountsPermission,
+                                              boolean managedProfileBeingDetected,
+                                              boolean hasManagedProfile,
+                                              boolean hasAccountsForLogin,
+                                              String currentAccount) {
         if (!ProductionFlags.ENABLE_USER_HISTORY_DICTIONARY_SYNC) {
             return;
         }
 
-        // If we are determining eligiblity, we show empty summaries.
-        // Once we have some deterministic result, we set summaries based on different results.
-        if (managedProfileBeingDetected) {
+        if (!hasAccountsPermission) {
+            mEnableSyncPreference.setChecked(false);
+            mEnableSyncPreference.setSummary(getString(R.string.cloud_sync_summary_disabled));
+            mAccountSwitcher.setSummary("");
+            return;
+        } else if (managedProfileBeingDetected) {
+            // If we are determining eligiblity, we show empty summaries.
+            // Once we have some deterministic result, we set summaries based on different results.
             mEnableSyncPreference.setSummary("");
             mAccountSwitcher.setSummary("");
         } else if (hasManagedProfile) {
@@ -462,7 +476,7 @@
                                 new DialogInterface.OnClickListener() {
                                     @Override
                                     public void onClick(final DialogInterface dialog,
-                                            final int which) {
+                                                        final int which) {
                                         if (which == DialogInterface.BUTTON_POSITIVE) {
                                             final Context context = getActivity();
                                             final String[] accountsForLogin =
@@ -473,9 +487,9 @@
                                                     .show();
                                         }
                                     }
-                         })
-                         .setNegativeButton(R.string.cloud_sync_cancel, null)
-                         .create();
+                        })
+                        .setNegativeButton(R.string.cloud_sync_cancel, null)
+                        .create();
                 optInDialog.setOnShowListener(this);
                 optInDialog.show();
             }
diff --git a/java/src/com/android/inputmethod/latin/settings/SubScreenFragment.java b/java/src/com/android/inputmethod/latin/settings/SubScreenFragment.java
index 240f8f8..5994a76 100644
--- a/java/src/com/android/inputmethod/latin/settings/SubScreenFragment.java
+++ b/java/src/com/android/inputmethod/latin/settings/SubScreenFragment.java
@@ -32,7 +32,7 @@
  * A base abstract class for a {@link PreferenceFragment} that implements a nested
  * {@link PreferenceScreen} of the main preference screen.
  */
-abstract class SubScreenFragment extends PreferenceFragment
+public abstract class SubScreenFragment extends PreferenceFragment
         implements OnSharedPreferenceChangeListener {
     private OnSharedPreferenceChangeListener mSharedPreferenceChangeListener;
 
diff --git a/java/src/com/android/inputmethod/latin/spellcheck/SpellCheckerSettingsActivity.java b/java/src/com/android/inputmethod/latin/spellcheck/SpellCheckerSettingsActivity.java
index 294666b..356d9d0 100644
--- a/java/src/com/android/inputmethod/latin/spellcheck/SpellCheckerSettingsActivity.java
+++ b/java/src/com/android/inputmethod/latin/spellcheck/SpellCheckerSettingsActivity.java
@@ -16,6 +16,7 @@
 
 package com.android.inputmethod.latin.spellcheck;
 
+import com.android.inputmethod.latin.permissions.PermissionsManager;
 import com.android.inputmethod.latin.utils.FragmentUtils;
 
 import android.annotation.TargetApi;
@@ -23,11 +24,13 @@
 import android.os.Build;
 import android.os.Bundle;
 import android.preference.PreferenceActivity;
+import android.support.v4.app.ActivityCompat;
 
 /**
  * Spell checker preference screen.
  */
-public final class SpellCheckerSettingsActivity extends PreferenceActivity {
+public final class SpellCheckerSettingsActivity extends PreferenceActivity
+        implements ActivityCompat.OnRequestPermissionsResultCallback {
     private static final String DEFAULT_FRAGMENT = SpellCheckerSettingsFragment.class.getName();
 
     @Override
@@ -48,4 +51,11 @@
     public boolean isValidFragment(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/spellcheck/SpellCheckerSettingsFragment.java b/java/src/com/android/inputmethod/latin/spellcheck/SpellCheckerSettingsFragment.java
index 6850e9b..12005c2 100644
--- a/java/src/com/android/inputmethod/latin/spellcheck/SpellCheckerSettingsFragment.java
+++ b/java/src/com/android/inputmethod/latin/spellcheck/SpellCheckerSettingsFragment.java
@@ -16,18 +16,31 @@
 
 package com.android.inputmethod.latin.spellcheck;
 
+import android.Manifest;
+import android.content.SharedPreferences;
 import android.os.Bundle;
-import android.preference.PreferenceFragment;
 import android.preference.PreferenceScreen;
+import android.preference.SwitchPreference;
+import android.text.TextUtils;
 
 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.settings.SubScreenFragment;
 import com.android.inputmethod.latin.settings.TwoStatePreferenceHelper;
 import com.android.inputmethod.latin.utils.ApplicationUtils;
 
+import static com.android.inputmethod.latin.permissions.PermissionsManager.get;
+
 /**
  * Preference screen.
  */
-public final class SpellCheckerSettingsFragment extends PreferenceFragment {
+public final class SpellCheckerSettingsFragment extends SubScreenFragment
+    implements SharedPreferences.OnSharedPreferenceChangeListener,
+            PermissionsManager.PermissionsResultCallback {
+
+    private SwitchPreference mLookupContactsPreference;
+
     @Override
     public void onActivityCreated(final Bundle savedInstanceState) {
         super.onActivityCreated(savedInstanceState);
@@ -36,5 +49,42 @@
         preferenceScreen.setTitle(ApplicationUtils.getActivityTitleResId(
                 getActivity(), SpellCheckerSettingsActivity.class));
         TwoStatePreferenceHelper.replaceCheckBoxPreferencesBySwitchPreferences(preferenceScreen);
+
+        mLookupContactsPreference = (SwitchPreference) findPreference(
+                AndroidSpellCheckerService.PREF_USE_CONTACTS_KEY);
+        turnOffLookupContactsIfNoPermission();
+    }
+
+    @Override
+    public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key) {
+        if (!TextUtils.equals(key, AndroidSpellCheckerService.PREF_USE_CONTACTS_KEY)) {
+            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.
+        }
+
+        get(getActivity() /* context */).requestPermissions(this /* PermissionsResultCallback */,
+                getActivity() /* activity */, Manifest.permission.READ_CONTACTS);
+    }
+
+    @Override
+    public void onRequestPermissionsResult(boolean allGranted) {
+        turnOffLookupContactsIfNoPermission();
+    }
+
+    private void turnOffLookupContactsIfNoPermission() {
+        if (!PermissionsUtil.checkAllPermissionsGranted(
+                getActivity(), Manifest.permission.READ_CONTACTS)) {
+            mLookupContactsPreference.setChecked(false);
+        }
     }
 }