Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 80dbf184 authored by Brandon Maxwell's avatar Brandon Maxwell
Browse files

Fixing refresh bug with ContactsPreferences

Observed: ContactsPreferences would detect that SharePreferences had
changed, but wouldn't update its cached values. This resulted in the
initial cached values always getting returned, regardless of what value
was stored in SharedPreferences.

Change-Id: Ie11e1e655ccdeb344a99b8eff02d81f56dad2c18
parent 9fea7488
Loading
Loading
Loading
Loading
+35 −18
Original line number Diff line number Diff line
@@ -16,14 +16,11 @@

package com.android.contacts.common.preference;

import android.content.ContentResolver;
import android.content.Context;
import android.content.SharedPreferences;
import android.content.SharedPreferences.Editor;
import android.content.SharedPreferences.OnSharedPreferenceChangeListener;
import android.database.ContentObserver;
import android.os.Handler;
import android.provider.ContactsContract;
import android.provider.Settings;
import android.provider.Settings.SettingNotFoundException;
import android.text.TextUtils;
@@ -61,11 +58,17 @@ public final class ContactsPreferences implements OnSharedPreferenceChangeListen
    public static final int SORT_ORDER_ALTERNATIVE = 2;

    public static final String PREF_DISPLAY_ONLY_PHONES = "only_phones";

    public static final boolean PREF_DISPLAY_ONLY_PHONES_DEFAULT = false;

    /**
     * Value to use when a preference is unassigned and needs to be read from the shared preferences
     */
    private static final int PREFERENCE_UNASSIGNED = -1;

    private final Context mContext;
    private int mSortOrder = -1;
    private int mDisplayOrder = -1;
    private int mSortOrder = PREFERENCE_UNASSIGNED;
    private int mDisplayOrder = PREFERENCE_UNASSIGNED;
    private String mDefaultAccount = null;
    private ChangeListener mListener = null;
    private Handler mHandler;
@@ -101,7 +104,7 @@ public final class ContactsPreferences implements OnSharedPreferenceChangeListen
        if (!isSortOrderUserChangeable()) {
            return getDefaultSortOrder();
        }
        if (mSortOrder == -1) {
        if (mSortOrder == PREFERENCE_UNASSIGNED) {
            mSortOrder = mPreferences.getInt(SORT_ORDER_KEY, getDefaultSortOrder());
        }
        return mSortOrder;
@@ -130,7 +133,7 @@ public final class ContactsPreferences implements OnSharedPreferenceChangeListen
        if (!isDisplayOrderUserChangeable()) {
            return getDefaultDisplayOrder();
        }
        if (mDisplayOrder == -1) {
        if (mDisplayOrder == PREFERENCE_UNASSIGNED) {
            mDisplayOrder = mPreferences.getInt(DISPLAY_ORDER_KEY, getDefaultDisplayOrder());
        }
        return mDisplayOrder;
@@ -152,7 +155,8 @@ public final class ContactsPreferences implements OnSharedPreferenceChangeListen
            return mDefaultAccount;
        }
        if (TextUtils.isEmpty(mDefaultAccount)) {
            final String accountString = mPreferences.getString(mDefaultAccountKey, mDefaultAccount);
            final String accountString = mPreferences
                    .getString(mDefaultAccountKey, mDefaultAccount);
            if (!TextUtils.isEmpty(accountString)) {
                final AccountWithDataSet accountWithDataSet = AccountWithDataSet.unstringify(
                        accountString);
@@ -181,8 +185,8 @@ public final class ContactsPreferences implements OnSharedPreferenceChangeListen

        // Reset preferences to "unknown" because they may have changed while the
        // listener was unregistered.
        mDisplayOrder = -1;
        mSortOrder = -1;
        mDisplayOrder = PREFERENCE_UNASSIGNED;
        mSortOrder = PREFERENCE_UNASSIGNED;
        mDefaultAccount = null;

        mPreferences.registerOnSharedPreferenceChangeListener(this);
@@ -203,17 +207,30 @@ public final class ContactsPreferences implements OnSharedPreferenceChangeListen
        mHandler.post(new Runnable() {
            @Override
            public void run() {
                refreshValue(key);
            }
        });
    }

    /**
     * Forces the value for the given key to be looked up from shared preferences and notifies
     * the registered {@link ChangeListener}
     *
     * @param key the {@link SharedPreferences} key to look up
     */
    public void refreshValue(String key) {
        if (DISPLAY_ORDER_KEY.equals(key)) {
            mDisplayOrder = PREFERENCE_UNASSIGNED;
            mDisplayOrder = getDisplayOrder();
        } else if (SORT_ORDER_KEY.equals(key)) {
            mSortOrder = PREFERENCE_UNASSIGNED;
            mSortOrder = getSortOrder();
        } else if (mDefaultAccountKey.equals(key)) {
            mDefaultAccount = null;
            mDefaultAccount = getDefaultAccount();
        }
        if (mListener != null) mListener.onChange();
    }
        });
    }

    public interface ChangeListener {
        void onChange();
+1 −1
Original line number Diff line number Diff line
@@ -20,7 +20,7 @@ import android.content.Context;
import android.test.InstrumentationTestCase;
import android.test.suitebuilder.annotation.SmallTest;

import com.android.contacts.common.unittest.R;
import com.android.contacts.common.R;

/**
 * Test case for {@link AccountType}.
+1 −1
Original line number Diff line number Diff line
@@ -33,7 +33,7 @@ import android.test.suitebuilder.annotation.SmallTest;
import android.util.Log;

import com.android.contacts.common.model.dataitem.DataKind;
import com.android.contacts.common.unittest.R;
import com.android.contacts.common.R;
import com.google.common.base.Objects;

import java.util.List;
+147 −0
Original line number Diff line number Diff line
/*
 * 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.contacts.common.preference;

import android.content.Context;
import android.content.SharedPreferences;
import android.content.res.Resources;
import android.test.AndroidTestCase;
import android.test.suitebuilder.annotation.MediumTest;

import com.android.contacts.common.model.account.AccountWithDataSet;

import junit.framework.Assert;

import org.mockito.Mock;
import org.mockito.Mockito;
import org.mockito.MockitoAnnotations;

@MediumTest
public class ContactsPreferencesTest extends AndroidTestCase {

    private static final String ACCOUNT_KEY = "ACCOUNT_KEY";

    @Mock private Context mContext;
    @Mock private Resources mResources;
    @Mock private SharedPreferences mSharedPreferences;

    private ContactsPreferences mContactsPreferences;

    @Override
    public void setUp() throws Exception {
        super.setUp();
        MockitoAnnotations.initMocks(this);

        Mockito.when(mContext.getResources()).thenReturn(mResources);
        Mockito.when(mResources.getString(Mockito.anyInt()))
                .thenReturn(ACCOUNT_KEY); // contact_editor_default_account_key

        Mockito.when(mContext.getSharedPreferences(Mockito.anyString(), Mockito.anyInt()))
                .thenReturn(mSharedPreferences);
        Mockito.when(mSharedPreferences.contains(ContactsPreferences.SORT_ORDER_KEY))
                .thenReturn(true);
        Mockito.when(mSharedPreferences.contains(ContactsPreferences.DISPLAY_ORDER_KEY))
                .thenReturn(true);

        mContactsPreferences = new ContactsPreferences(mContext);
    }

    public void testGetSortOrderDefault() {
        Mockito.when(mResources.getBoolean(Mockito.anyInt())).thenReturn(
                false, // R.bool.config_sort_order_user_changeable
                true // R.bool.config_default_sort_order_primary
        );
        Assert.assertEquals(ContactsPreferences.SORT_ORDER_PRIMARY,
                mContactsPreferences.getSortOrder());
    }

    public void testGetSortOrder() {
        Mockito.when(mResources.getBoolean(Mockito.anyInt())).thenReturn(
                true // R.bool.config_sort_order_user_changeable
        );
        Mockito.when(mSharedPreferences.getInt(Mockito.eq(ContactsPreferences.SORT_ORDER_KEY),
                Mockito.anyInt())).thenReturn(ContactsPreferences.SORT_ORDER_PRIMARY);
        Assert.assertEquals(ContactsPreferences.SORT_ORDER_PRIMARY,
                mContactsPreferences.getSortOrder());
    }

    public void testGetDisplayOrderDefault() {
        Mockito.when(mResources.getBoolean(Mockito.anyInt())).thenReturn(
                false, // R.bool.config_display_order_user_changeable
                true // R.bool.config_default_display_order_primary
        );
        Assert.assertEquals(ContactsPreferences.DISPLAY_ORDER_PRIMARY,
                mContactsPreferences.getDisplayOrder());
    }

    public void testGetDisplayOrder() {
        Mockito.when(mResources.getBoolean(Mockito.anyInt())).thenReturn(
                true // R.bool.config_display_order_user_changeable
        );
        Mockito.when(mSharedPreferences.getInt(Mockito.eq(ContactsPreferences.DISPLAY_ORDER_KEY),
                Mockito.anyInt())).thenReturn(ContactsPreferences.DISPLAY_ORDER_PRIMARY);
        Assert.assertEquals(ContactsPreferences.DISPLAY_ORDER_PRIMARY,
                mContactsPreferences.getDisplayOrder());
    }

    public void testRefreshSortOrder() throws InterruptedException {
        Mockito.when(mResources.getBoolean(Mockito.anyInt())).thenReturn(
                true // R.bool.config_sort_order_user_changeable
        );
        Mockito.when(mSharedPreferences.getInt(Mockito.eq(ContactsPreferences.SORT_ORDER_KEY),
                Mockito.anyInt())).thenReturn(ContactsPreferences.SORT_ORDER_PRIMARY,
                ContactsPreferences.SORT_ORDER_ALTERNATIVE);

        Assert.assertEquals(ContactsPreferences.SORT_ORDER_PRIMARY,
                mContactsPreferences.getSortOrder());
        mContactsPreferences.refreshValue(ContactsPreferences.SORT_ORDER_KEY);

        Assert.assertEquals(ContactsPreferences.SORT_ORDER_ALTERNATIVE,
                mContactsPreferences.getSortOrder());
    }

    public void testRefreshDisplayOrder() throws InterruptedException {
        Mockito.when(mResources.getBoolean(Mockito.anyInt())).thenReturn(
                true // R.bool.config_display_order_user_changeable
        );
        Mockito.when(mSharedPreferences.getInt(Mockito.eq(ContactsPreferences.DISPLAY_ORDER_KEY),
                Mockito.anyInt())).thenReturn(ContactsPreferences.DISPLAY_ORDER_PRIMARY,
                ContactsPreferences.DISPLAY_ORDER_ALTERNATIVE);

        Assert.assertEquals(ContactsPreferences.DISPLAY_ORDER_PRIMARY,
                mContactsPreferences.getDisplayOrder());
        mContactsPreferences.refreshValue(ContactsPreferences.DISPLAY_ORDER_KEY);

        Assert.assertEquals(ContactsPreferences.DISPLAY_ORDER_ALTERNATIVE,
                mContactsPreferences.getDisplayOrder());
    }

    public void testRefreshDefaultAccount() throws InterruptedException {
        Mockito.when(mResources.getBoolean(Mockito.anyInt())).thenReturn(
                true // R.bool.config_default_account_user_changeable
        );

        Mockito.when(mSharedPreferences.getString(Mockito.eq(ACCOUNT_KEY), Mockito.anyString()))
                .thenReturn(new AccountWithDataSet("name1", "type1", "dataset1").stringify(),
                        new AccountWithDataSet("name2", "type2", "dataset2").stringify());

        Assert.assertEquals("name1", mContactsPreferences.getDefaultAccount());
        mContactsPreferences.refreshValue(ACCOUNT_KEY);

        Assert.assertEquals("name2", mContactsPreferences.getDefaultAccount());
    }
}