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

Commit 2ddd29df authored by Doris Ling's avatar Doris Ling
Browse files

Remove nested preference from its parent.

PreferenceScreen.remvoePreference() only removes top level preference in
the preference screen. When we try to remove preference inside a
preference category, it will fail. Add handling to recursively find
the preference and remove it directly from its parent instead.

Change-Id: Ib33efe0b716db2366d712ce1d1eb8b5e33a4683a
Fix: 35365702
Test: make RunSettingsLibRoboTests
parent b69aaf0b
Loading
Loading
Loading
Loading
+22 −3
Original line number Diff line number Diff line
@@ -2,6 +2,7 @@ package com.android.settingslib.core;

import android.content.Context;
import android.support.v7.preference.Preference;
import android.support.v7.preference.PreferenceGroup;
import android.support.v7.preference.PreferenceScreen;
import java.util.List;

@@ -73,9 +74,27 @@ public abstract class AbstractPreferenceController {
   * Removes preference from screen.
   */
  protected final void removePreference(PreferenceScreen screen, String key) {
      Preference pref = screen.findPreference(key);
      if (pref != null) {
          screen.removePreference(pref);
      findAndRemovePreference(screen, key);
  }

  // finds the preference recursively and removes it from its parent
  private boolean findAndRemovePreference(PreferenceGroup prefGroup, String key) {
      final int preferenceCount = prefGroup.getPreferenceCount();
      for (int i = 0; i < preferenceCount; i++) {
          final Preference preference = prefGroup.getPreference(i);
          final String curKey = preference.getKey();

          if (curKey != null && curKey.equals(key)) {
              return prefGroup.removePreference(preference);
          }

          if (preference instanceof PreferenceGroup) {
              if (findAndRemovePreference((PreferenceGroup) preference, key)) {
                  return true;
              }
          }
      }
      return false;
  }

}
+66 −2
Original line number Diff line number Diff line
@@ -17,6 +17,8 @@ package com.android.settingslib.core;

import android.content.Context;
import android.support.v7.preference.Preference;
import android.support.v7.preference.PreferenceGroup;
import android.support.v7.preference.PreferenceManager;
import android.support.v7.preference.PreferenceScreen;
import com.android.settingslib.TestConfig;
import com.android.settingslib.core.AbstractPreferenceController;
@@ -26,10 +28,13 @@ import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
import org.robolectric.annotation.Config;
import org.robolectric.shadows.ShadowApplication;
import org.robolectric.RobolectricTestRunner;

import static org.mockito.Matchers.any;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;

@@ -54,7 +59,9 @@ public class PreferenceControllerTest {

    @Test
    public void removeExistingPref_shouldBeRemoved() {
        when(mScreen.findPreference(TestPrefController.KEY_PREF)).thenReturn(mPreference);
        when(mScreen.getPreferenceCount()).thenReturn(1);
        when(mScreen.getPreference(0)).thenReturn(mPreference);
        when(mPreference.getKey()).thenReturn(TestPrefController.KEY_PREF);

        mTestPrefController.removePreference(mScreen, TestPrefController.KEY_PREF);

@@ -79,7 +86,9 @@ public class PreferenceControllerTest {

    @Test
    public void doNotDisplayPref_ifNotAvailable() {
        when(mScreen.findPreference(TestPrefController.KEY_PREF)).thenReturn(mPreference);
        when(mScreen.getPreferenceCount()).thenReturn(1);
        when(mScreen.getPreference(0)).thenReturn(mPreference);
        when(mPreference.getKey()).thenReturn(TestPrefController.KEY_PREF);
        mTestPrefController.isAvailable = false;

        mTestPrefController.displayPreference(mScreen);
@@ -87,6 +96,61 @@ public class PreferenceControllerTest {
        verify(mScreen).removePreference(any(Preference.class));
    }

    @Test
    public void removePreference_shouldRemoveRecursively() {
        final Context context = ShadowApplication.getInstance().getApplicationContext();
        final PreferenceManager preferenceManager = mock(PreferenceManager.class);
        // Top level
        PreferenceScreen prefRoot = spy(new PreferenceScreen(context, null));
        when(prefRoot.getPreferenceManager()).thenReturn(preferenceManager);
        Preference pref1 = mock(Preference.class);
        when(pref1.getKey()).thenReturn("key1");
        PreferenceGroup prefGroup2 = spy(new PreferenceScreen(context, null));
        when(prefGroup2.getPreferenceManager()).thenReturn(preferenceManager);
        when(prefGroup2.getKey()).thenReturn("group2");
        Preference pref3 = mock(Preference.class);
        when(pref3.getKey()).thenReturn("key3");
        PreferenceGroup prefGroup4 = spy(new PreferenceScreen(context, null));
        when(prefGroup4.getPreferenceManager()).thenReturn(preferenceManager);
        when(prefGroup4.getKey()).thenReturn("group4");
        prefRoot.addPreference(pref1);
        prefRoot.addPreference(prefGroup2);
        prefRoot.addPreference(pref3);
        prefRoot.addPreference(prefGroup4);

        // 2nd level
        Preference pref21 = mock(Preference.class);
        when(pref21.getKey()).thenReturn("key21");
        Preference pref22 = mock(Preference.class);
        when(pref22.getKey()).thenReturn("key22");
        prefGroup2.addPreference(pref21);
        prefGroup2.addPreference(pref22);
        PreferenceGroup prefGroup41 = spy(new PreferenceScreen(context, null));
        when(prefGroup41.getKey()).thenReturn("group41");
        when(prefGroup41.getPreferenceManager()).thenReturn(preferenceManager);
        Preference pref42 = mock(Preference.class);
        when(pref42.getKey()).thenReturn("key42");
        prefGroup4.addPreference(prefGroup41);
        prefGroup4.addPreference(pref42);

        // 3rd level
        Preference pref411 = mock(Preference.class);
        when(pref411.getKey()).thenReturn("key411");
        Preference pref412 = mock(Preference.class);
        when(pref412.getKey()).thenReturn("key412");
        prefGroup41.addPreference(pref411);
        prefGroup41.addPreference(pref412);

        mTestPrefController.removePreference(prefRoot, "key1");
        verify(prefRoot).removePreference(pref1);

        mTestPrefController.removePreference(prefRoot, "key411");
        verify(prefGroup41).removePreference(pref411);

        mTestPrefController.removePreference(prefRoot, "group41");
        verify(prefGroup4).removePreference(prefGroup41);
    }

    private class TestPrefController extends AbstractPreferenceController {
        private static final String KEY_PREF = "test_pref";
        public boolean isAvailable;