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

Commit a8478233 authored by Tyler Gunn's avatar Tyler Gunn Committed by Gerrit Code Review
Browse files

Merge changes from topic 'sort-order'

* changes:
  Migrate phone account sorting to use lamba expressions and add test.
  PhoneAccounts sorting
parents 0647b0b1 702fdd02
Loading
Loading
Loading
Loading
+52 −0
Original line number Diff line number Diff line
@@ -73,6 +73,7 @@ import java.lang.SecurityException;
import java.lang.String;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
@@ -1089,6 +1090,52 @@ public class PhoneAccountRegistrar {
        }
    }

    private void sortPhoneAccounts() {
        if (mState.accounts.size() > 1) {
            // Sort the phone accounts using sort order:
            // 1) SIM accounts first, followed by non-sim accounts
            // 2) Sort order, with those specifying no sort order last.
            // 3) Label

            // Comparator to sort SIM subscriptions before non-sim subscriptions.
            Comparator<PhoneAccount> bySimCapability = (p1, p2) -> {
                if (p1.hasCapabilities(PhoneAccount.CAPABILITY_SIM_SUBSCRIPTION)
                        && !p2.hasCapabilities(PhoneAccount.CAPABILITY_SIM_SUBSCRIPTION)) {
                    return -1;
                } else if (!p1.hasCapabilities(PhoneAccount.CAPABILITY_SIM_SUBSCRIPTION)
                        && p2.hasCapabilities(PhoneAccount.CAPABILITY_SIM_SUBSCRIPTION)) {
                    return 1;
                } else {
                    return 0;
                }
            };

            // Create a string comparator which will sort strings, placing nulls last.
            Comparator<String> nullSafeStringComparator = Comparator.nullsLast(
                    String::compareTo);

            // Comparator which places PhoneAccounts with a specified sort order first, followed by
            // those with no sort order.
            Comparator<PhoneAccount> bySortOrder = (p1, p2) -> {
                String sort1 = p1.getExtras() == null ? null :
                        p1.getExtras().getString(PhoneAccount.EXTRA_SORT_ORDER, null);
                String sort2 = p2.getExtras() == null ? null :
                        p2.getExtras().getString(PhoneAccount.EXTRA_SORT_ORDER, null);
                return nullSafeStringComparator.compare(sort1, sort2);
            };

            // Comparator which sorts PhoneAccounts by label.
            Comparator<PhoneAccount> byLabel = (p1, p2) -> {
                String s1 = p1.getLabel() == null ? null : p1.getLabel().toString();
                String s2 = p2.getLabel() == null ? null : p2.getLabel().toString();
                return nullSafeStringComparator.compare(s1, s2);
            };

            // Sort the phone accounts.
            mState.accounts.sort(bySimCapability.thenComparing(bySortOrder.thenComparing(byLabel)));
        }
    }

    ////////////////////////////////////////////////////////////////////////////////////////////////
    //
    // State management
@@ -1115,6 +1162,7 @@ public class PhoneAccountRegistrar {

    private void write() {
        try {
            sortPhoneAccounts();
            ByteArrayOutputStream os = new ByteArrayOutputStream();
            XmlSerializer serializer = new FastXmlSerializer();
            serializer.setOutput(os, "utf-8");
@@ -1870,4 +1918,8 @@ public class PhoneAccountRegistrar {
            return null;
        }
    };

    private String nullToEmpty(String str) {
        return str == null ? "" : str;
    }
}
+187 −0
Original line number Diff line number Diff line
@@ -51,6 +51,7 @@ import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.util.Arrays;
import java.util.List;
import java.util.Set;

import static org.mockito.Matchers.anyInt;
@@ -577,6 +578,192 @@ public class PhoneAccountRegistrarTest extends TelecomTestCase {
        assertEquals(PhoneAccount.CAPABILITY_SELF_MANAGED, registeredAccount.getCapabilities());
    }

    @MediumTest
    public void testSortSimFirst() throws Exception {
        ComponentName componentA = new ComponentName("a", "a");
        ComponentName componentB = new ComponentName("b", "b");
        mComponentContextFixture.addConnectionService(componentA,
                Mockito.mock(IConnectionService.class));
        mComponentContextFixture.addConnectionService(componentB,
                Mockito.mock(IConnectionService.class));

        PhoneAccount simAccount = new PhoneAccount.Builder(
                makeQuickAccountHandle(componentB, "2"), "2")
                .setCapabilities(PhoneAccount.CAPABILITY_CALL_PROVIDER |
                        PhoneAccount.CAPABILITY_SIM_SUBSCRIPTION)
                .setIsEnabled(true)
                .build();

        PhoneAccount nonSimAccount = new PhoneAccount.Builder(
                makeQuickAccountHandle(componentA, "1"), "1")
                .setCapabilities(PhoneAccount.CAPABILITY_CALL_PROVIDER)
                .setIsEnabled(true)
                .build();

        registerAndEnableAccount(nonSimAccount);
        registerAndEnableAccount(simAccount);

        List<PhoneAccount> accounts = mRegistrar.getAllPhoneAccounts(Process.myUserHandle());
        assertTrue(accounts.get(0).getLabel().toString().equals("2"));
        assertTrue(accounts.get(1).getLabel().toString().equals("1"));
    }

    @MediumTest
    public void testSortBySortOrder() throws Exception {
        ComponentName componentA = new ComponentName("a", "a");
        ComponentName componentB = new ComponentName("b", "b");
        ComponentName componentC = new ComponentName("c", "c");
        mComponentContextFixture.addConnectionService(componentA,
                Mockito.mock(IConnectionService.class));
        mComponentContextFixture.addConnectionService(componentB,
                Mockito.mock(IConnectionService.class));
        mComponentContextFixture.addConnectionService(componentC,
                Mockito.mock(IConnectionService.class));

        PhoneAccount account1 = new PhoneAccount.Builder(
                makeQuickAccountHandle(componentA, "c"), "c")
                .setCapabilities(PhoneAccount.CAPABILITY_CALL_PROVIDER)
                .setExtras(Bundle.forPair(PhoneAccount.EXTRA_SORT_ORDER, "A"))
                .build();

        PhoneAccount account2 = new PhoneAccount.Builder(
                makeQuickAccountHandle(componentB, "b"), "b")
                .setCapabilities(PhoneAccount.CAPABILITY_CALL_PROVIDER)
                .setExtras(Bundle.forPair(PhoneAccount.EXTRA_SORT_ORDER, "B"))
                .build();

        PhoneAccount account3 = new PhoneAccount.Builder(
                makeQuickAccountHandle(componentC, "c"), "a")
                .setCapabilities(PhoneAccount.CAPABILITY_CALL_PROVIDER)
                .build();

        registerAndEnableAccount(account3);
        registerAndEnableAccount(account2);
        registerAndEnableAccount(account1);

        List<PhoneAccount> accounts = mRegistrar.getAllPhoneAccounts(Process.myUserHandle());
        assertTrue(accounts.get(0).getLabel().toString().equals("c"));
        assertTrue(accounts.get(1).getLabel().toString().equals("b"));
        assertTrue(accounts.get(2).getLabel().toString().equals("a"));
    }

    @MediumTest
    public void testSortByLabel() throws Exception {
        ComponentName componentA = new ComponentName("a", "a");
        ComponentName componentB = new ComponentName("b", "b");
        ComponentName componentC = new ComponentName("c", "c");
        mComponentContextFixture.addConnectionService(componentA,
                Mockito.mock(IConnectionService.class));
        mComponentContextFixture.addConnectionService(componentB,
                Mockito.mock(IConnectionService.class));
        mComponentContextFixture.addConnectionService(componentC,
                Mockito.mock(IConnectionService.class));

        PhoneAccount account1 = new PhoneAccount.Builder(makeQuickAccountHandle(componentA, "c"),
                "c")
                .setCapabilities(PhoneAccount.CAPABILITY_CALL_PROVIDER)
                .build();

        PhoneAccount account2 = new PhoneAccount.Builder(makeQuickAccountHandle(componentB, "b"),
                "b")
                .setCapabilities(PhoneAccount.CAPABILITY_CALL_PROVIDER)
                .build();

        PhoneAccount account3 = new PhoneAccount.Builder(makeQuickAccountHandle(componentC, "a"),
                "a")
                .setCapabilities(PhoneAccount.CAPABILITY_CALL_PROVIDER)
                .build();

        registerAndEnableAccount(account1);
        registerAndEnableAccount(account2);
        registerAndEnableAccount(account3);

        List<PhoneAccount> accounts = mRegistrar.getAllPhoneAccounts(Process.myUserHandle());
        assertTrue(accounts.get(0).getLabel().toString().equals("a"));
        assertTrue(accounts.get(1).getLabel().toString().equals("b"));
        assertTrue(accounts.get(2).getLabel().toString().equals("c"));
    }

    @MediumTest
    public void testSortAll() throws Exception {
        ComponentName componentA = new ComponentName("a", "a");
        ComponentName componentB = new ComponentName("b", "b");
        ComponentName componentC = new ComponentName("c", "c");
        ComponentName componentW = new ComponentName("w", "w");
        ComponentName componentX = new ComponentName("x", "x");
        ComponentName componentY = new ComponentName("y", "y");
        ComponentName componentZ = new ComponentName("z", "z");
        mComponentContextFixture.addConnectionService(componentA,
                Mockito.mock(IConnectionService.class));
        mComponentContextFixture.addConnectionService(componentB,
                Mockito.mock(IConnectionService.class));
        mComponentContextFixture.addConnectionService(componentC,
                Mockito.mock(IConnectionService.class));
        mComponentContextFixture.addConnectionService(componentW,
                Mockito.mock(IConnectionService.class));
        mComponentContextFixture.addConnectionService(componentX,
                Mockito.mock(IConnectionService.class));
        mComponentContextFixture.addConnectionService(componentY,
                Mockito.mock(IConnectionService.class));
        mComponentContextFixture.addConnectionService(componentZ,
                Mockito.mock(IConnectionService.class));
        PhoneAccount account1 = new PhoneAccount.Builder(makeQuickAccountHandle(
                makeQuickConnectionServiceComponentName(), "y"), "y")
                .setCapabilities(PhoneAccount.CAPABILITY_CALL_PROVIDER |
                        PhoneAccount.CAPABILITY_SIM_SUBSCRIPTION)
                .setExtras(Bundle.forPair(PhoneAccount.EXTRA_SORT_ORDER, "2"))
                .build();

        PhoneAccount account2 = new PhoneAccount.Builder(makeQuickAccountHandle(
                makeQuickConnectionServiceComponentName(), "z"), "z")
                .setCapabilities(PhoneAccount.CAPABILITY_CALL_PROVIDER |
                        PhoneAccount.CAPABILITY_SIM_SUBSCRIPTION)
                .setExtras(Bundle.forPair(PhoneAccount.EXTRA_SORT_ORDER, "1"))
                .build();

        PhoneAccount account3 = new PhoneAccount.Builder(makeQuickAccountHandle(
                makeQuickConnectionServiceComponentName(), "x"), "x")
                .setCapabilities(PhoneAccount.CAPABILITY_CALL_PROVIDER |
                        PhoneAccount.CAPABILITY_SIM_SUBSCRIPTION)
                .build();

        PhoneAccount account4 = new PhoneAccount.Builder(makeQuickAccountHandle(
                makeQuickConnectionServiceComponentName(), "w"), "w")
                .setCapabilities(PhoneAccount.CAPABILITY_CALL_PROVIDER |
                        PhoneAccount.CAPABILITY_SIM_SUBSCRIPTION)
                .build();

        PhoneAccount account5 = new PhoneAccount.Builder(makeQuickAccountHandle(
                makeQuickConnectionServiceComponentName(), "b"), "b")
                .setCapabilities(PhoneAccount.CAPABILITY_CALL_PROVIDER)
                .build();

        PhoneAccount account6 = new PhoneAccount.Builder(makeQuickAccountHandle(
                makeQuickConnectionServiceComponentName(), "c"), "a")
                .setCapabilities(PhoneAccount.CAPABILITY_CALL_PROVIDER)
                .build();

        registerAndEnableAccount(account1);
        registerAndEnableAccount(account2);
        registerAndEnableAccount(account3);
        registerAndEnableAccount(account4);
        registerAndEnableAccount(account5);
        registerAndEnableAccount(account6);

        List<PhoneAccount> accounts = mRegistrar.getAllPhoneAccounts(Process.myUserHandle());
        // Sim accts ordered by sort order first
        assertTrue(accounts.get(0).getLabel().toString().equals("z"));
        assertTrue(accounts.get(1).getLabel().toString().equals("y"));

        // Sim accts with no sort order next
        assertTrue(accounts.get(2).getLabel().toString().equals("w"));
        assertTrue(accounts.get(3).getLabel().toString().equals("x"));

        // Other accts sorted by label next
        assertTrue(accounts.get(4).getLabel().toString().equals("a"));
        assertTrue(accounts.get(5).getLabel().toString().equals("b"));
    }

    private static ComponentName makeQuickConnectionServiceComponentName() {
        return new ComponentName(
                "com.android.server.telecom.tests",