Fix NPE in AccountSettingsFragment.

Bug 19773815.

Change-Id: Ib5eb27cdf385c81d1a3822836f424fa29c0bbaa8
diff --git a/java/src/com/android/inputmethod/latin/settings/AccountsSettingsFragment.java b/java/src/com/android/inputmethod/latin/settings/AccountsSettingsFragment.java
index fe52cfe..48361bf 100644
--- a/java/src/com/android/inputmethod/latin/settings/AccountsSettingsFragment.java
+++ b/java/src/com/android/inputmethod/latin/settings/AccountsSettingsFragment.java
@@ -119,24 +119,34 @@
             removeSyncPreferences();
         } else {
             disableSyncPreferences();
-            final AsyncTask<Void, Void, Void> checkManagedProfileTask =
-                    new AsyncTask<Void, Void, Void>() {
-                        @Override
-                        protected Void doInBackground(Void... params) {
-                            if (ManagedProfileUtils.hasManagedWorkProfile(getActivity())) {
-                                removeSyncPreferences();
-                            } else {
-                                enableSyncPreferences();
-                            }
-                            return null;
-                        }
-                    };
-            checkManagedProfileTask.execute();
+            new ManagedProfileCheckerTask(this).execute();
+        }
+    }
+
+    private static class ManagedProfileCheckerTask extends AsyncTask<Void, Void, Void> {
+        private final AccountsSettingsFragment mFragment;
+
+        private ManagedProfileCheckerTask(final AccountsSettingsFragment fragment) {
+            mFragment = fragment;
+        }
+
+        @Override
+        protected Void doInBackground(Void... params) {
+            if (ManagedProfileUtils.getInstance().hasManagedWorkProfile(mFragment.getActivity())) {
+                mFragment.removeSyncPreferences();
+            } else {
+                mFragment.enableSyncPreferences();
+            }
+            return null;
         }
     }
 
     private void enableSyncPreferences() {
         mAccountSwitcher = findPreference(PREF_ACCCOUNT_SWITCHER);
+        if (mAccountSwitcher == null) {
+            // Preference has been removed because the device has a managed profile.
+            return;
+        }
         mAccountSwitcher.setEnabled(true);
 
         mEnableSyncPreference = (TwoStatePreference) findPreference(PREF_ENABLE_SYNC_NOW);
@@ -154,6 +164,10 @@
 
     private void disableSyncPreferences() {
         mAccountSwitcher = findPreference(PREF_ACCCOUNT_SWITCHER);
+        if (mAccountSwitcher == null) {
+            // Preference has been removed because the device has a managed profile.
+            return;
+        }
         mAccountSwitcher.setEnabled(false);
 
         mEnableSyncPreference = (TwoStatePreference) findPreference(PREF_ENABLE_SYNC_NOW);
@@ -211,6 +225,9 @@
 
         if (accountsForLogin.length > 0) {
             enableSyncPreferences();
+            if (mAccountSwitcher == null) {
+                return;
+            }
             mAccountSwitcher.setOnPreferenceClickListener(new OnPreferenceClickListener() {
                 @Override
                 public boolean onPreferenceClick(final Preference preference) {
diff --git a/java/src/com/android/inputmethod/latin/utils/ManagedProfileUtils.java b/java/src/com/android/inputmethod/latin/utils/ManagedProfileUtils.java
index f0d6d08..1bd8f31 100644
--- a/java/src/com/android/inputmethod/latin/utils/ManagedProfileUtils.java
+++ b/java/src/com/android/inputmethod/latin/utils/ManagedProfileUtils.java
@@ -23,6 +23,8 @@
 import android.os.UserManager;
 import android.util.Log;
 
+import com.android.inputmethod.annotations.UsedForTesting;
+
 import java.util.List;
 
 /**
@@ -32,16 +34,28 @@
     private static final boolean DEBUG = false;
     private static final String TAG = ManagedProfileUtils.class.getSimpleName();
 
+    private static ManagedProfileUtils INSTANCE = new ManagedProfileUtils();
+    private static ManagedProfileUtils sTestInstance;
+
     private ManagedProfileUtils() {
         // This utility class is not publicly instantiable.
     }
 
+    @UsedForTesting
+    public static void setTestInstance(final ManagedProfileUtils testInstance) {
+        sTestInstance = testInstance;
+    }
+
+    public static ManagedProfileUtils getInstance() {
+        return sTestInstance == null ? INSTANCE : sTestInstance;
+    }
+
     /**
      * Note that {@link UserManager#getUserProfiles} has been introduced
      * in API level 21 (Build.VERSION_CODES.LOLLIPOP).
      */
     @TargetApi(Build.VERSION_CODES.LOLLIPOP)
-    public static boolean hasManagedWorkProfile(final Context context) {
+    public boolean hasManagedWorkProfile(final Context context) {
         if (Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP) {
             return false;
         }
diff --git a/tests/src/com/android/inputmethod/latin/settings/AccountsSettingsFragmentTests.java b/tests/src/com/android/inputmethod/latin/settings/AccountsSettingsFragmentTests.java
index 81a0f69..0878e74 100644
--- a/tests/src/com/android/inputmethod/latin/settings/AccountsSettingsFragmentTests.java
+++ b/tests/src/com/android/inputmethod/latin/settings/AccountsSettingsFragmentTests.java
@@ -16,7 +16,12 @@
 
 package com.android.inputmethod.latin.settings;
 
+import static org.mockito.Matchers.any;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+
 import android.app.AlertDialog;
+import android.content.Context;
 import android.content.DialogInterface;
 import android.content.Intent;
 import android.test.ActivityInstrumentationTestCase2;
@@ -24,6 +29,11 @@
 import android.view.View;
 import android.widget.ListView;
 
+import com.android.inputmethod.latin.utils.ManagedProfileUtils;
+
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+
 import java.util.concurrent.CountDownLatch;
 import java.util.concurrent.TimeUnit;
 
@@ -33,6 +43,8 @@
     private static final String FRAG_NAME = AccountsSettingsFragment.class.getName();
     private static final long TEST_TIMEOUT_MILLIS = 5000;
 
+    @Mock private ManagedProfileUtils mManagedProfileUtils;
+
     public AccountsSettingsFragmentTests() {
         super(TestFragmentActivity.class);
     }
@@ -40,11 +52,22 @@
     @Override
     protected void setUp() throws Exception {
         super.setUp();
+
+        // Initialize the mocks.
+        MockitoAnnotations.initMocks(this);
+        ManagedProfileUtils.setTestInstance(mManagedProfileUtils);
+
         Intent intent = new Intent();
         intent.putExtra(TestFragmentActivity.EXTRA_SHOW_FRAGMENT, FRAG_NAME);
         setActivityIntent(intent);
     }
 
+    @Override
+    public void tearDown() throws Exception {
+        ManagedProfileUtils.setTestInstance(null);
+        super.tearDown();
+    }
+
     public void testEmptyAccounts() {
         final AccountsSettingsFragment fragment =
                 (AccountsSettingsFragment) getActivity().mFragment;
@@ -61,36 +84,26 @@
         DialogHolder() {}
     }
 
-    public void testMultipleAccounts_noCurrentAccount() {
+    public void testMultipleAccounts_noSettingsForManagedProfile() {
+        when(mManagedProfileUtils.hasManagedWorkProfile(any(Context.class))).thenReturn(true);
+
         final AccountsSettingsFragment fragment =
                 (AccountsSettingsFragment) getActivity().mFragment;
-        final DialogHolder dialogHolder = new DialogHolder();
-        final CountDownLatch latch = new CountDownLatch(1);
-
-        getActivity().runOnUiThread(new Runnable() {
-            @Override
-            public void run() {
-                final AlertDialog dialog = fragment.createAccountPicker(
-                        new String[] {
-                                "1@example.com",
-                                "2@example.com",
-                                "3@example.com",
-                                "4@example.com"},
-                        null, null /* positiveButtonListner */);
-                dialog.show();
-                dialogHolder.mDialog = dialog;
-                latch.countDown();
-            }
-        });
-
-        try {
-            latch.await(TEST_TIMEOUT_MILLIS, TimeUnit.MILLISECONDS);
-        } catch (InterruptedException ex) {
-            fail();
-        }
-        getInstrumentation().waitForIdleSync();
-        final AlertDialog dialog = dialogHolder.mDialog;
+        final AlertDialog dialog = initDialog(fragment, null).mDialog;
         final ListView lv = dialog.getListView();
+
+        // Nothing to check/uncheck.
+        assertNull(fragment.findPreference(AccountsSettingsFragment.PREF_ACCCOUNT_SWITCHER));
+    }
+
+    public void testMultipleAccounts_noCurrentAccount() {
+        when(mManagedProfileUtils.hasManagedWorkProfile(any(Context.class))).thenReturn(false);
+
+        final AccountsSettingsFragment fragment =
+                (AccountsSettingsFragment) getActivity().mFragment;
+        final AlertDialog dialog = initDialog(fragment, null).mDialog;
+        final ListView lv = dialog.getListView();
+
         // The 1st account should be checked by default.
         assertEquals("checked-item", 0, lv.getCheckedItemPosition());
         // There should be 4 accounts in the list.
@@ -105,10 +118,32 @@
     }
 
     public void testMultipleAccounts_currentAccount() {
+        when(mManagedProfileUtils.hasManagedWorkProfile(any(Context.class))).thenReturn(false);
+
         final AccountsSettingsFragment fragment =
                 (AccountsSettingsFragment) getActivity().mFragment;
+        final AlertDialog dialog = initDialog(fragment, "3@example.com").mDialog;
+        final ListView lv = dialog.getListView();
+
+        // The 3rd account should be checked by default.
+        assertEquals("checked-item", 2, lv.getCheckedItemPosition());
+        // There should be 4 accounts in the list.
+        assertEquals("count", 4, lv.getCount());
+        // The sign-out button should be shown
+        assertEquals(View.VISIBLE,
+                dialog.getButton(DialogInterface.BUTTON_NEUTRAL).getVisibility());
+        assertEquals(View.VISIBLE,
+                dialog.getButton(DialogInterface.BUTTON_NEGATIVE).getVisibility());
+        assertEquals(View.VISIBLE,
+                dialog.getButton(DialogInterface.BUTTON_POSITIVE).getVisibility());
+    }
+
+    private DialogHolder initDialog(
+            final AccountsSettingsFragment fragment,
+            final String selectedAccount) {
         final DialogHolder dialogHolder = new DialogHolder();
         final CountDownLatch latch = new CountDownLatch(1);
+
         getActivity().runOnUiThread(new Runnable() {
             @Override
             public void run() {
@@ -118,7 +153,7 @@
                                 "2@example.com",
                                 "3@example.com",
                                 "4@example.com"},
-                        "3@example.com", null /* positiveButtonListner */);
+                        selectedAccount, null /* positiveButtonListner */);
                 dialog.show();
                 dialogHolder.mDialog = dialog;
                 latch.countDown();
@@ -131,18 +166,6 @@
             fail();
         }
         getInstrumentation().waitForIdleSync();
-        final AlertDialog dialog = dialogHolder.mDialog;
-        final ListView lv = dialog.getListView();
-        // The 3rd account should be checked by default.
-        assertEquals("checked-item", 2, lv.getCheckedItemPosition());
-        // There should be 4 accounts in the list.
-        assertEquals("count", 4, lv.getCount());
-        // The sign-out button should be shown
-        assertEquals(View.VISIBLE,
-                dialog.getButton(DialogInterface.BUTTON_NEUTRAL).getVisibility());
-        assertEquals(View.VISIBLE,
-                dialog.getButton(DialogInterface.BUTTON_NEGATIVE).getVisibility());
-        assertEquals(View.VISIBLE,
-                dialog.getButton(DialogInterface.BUTTON_POSITIVE).getVisibility());
+        return dialogHolder;
     }
 }