Merge changes from topic 'sort-order'
* changes:
Migrate phone account sorting to use lamba expressions and add test.
PhoneAccounts sorting
diff --git a/src/com/android/server/telecom/PhoneAccountRegistrar.java b/src/com/android/server/telecom/PhoneAccountRegistrar.java
index 8cdec30..074f325 100644
--- a/src/com/android/server/telecom/PhoneAccountRegistrar.java
+++ b/src/com/android/server/telecom/PhoneAccountRegistrar.java
@@ -73,6 +73,7 @@
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 @@
}
}
+ 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 @@
private void write() {
try {
+ sortPhoneAccounts();
ByteArrayOutputStream os = new ByteArrayOutputStream();
XmlSerializer serializer = new FastXmlSerializer();
serializer.setOutput(os, "utf-8");
@@ -1870,4 +1918,8 @@
return null;
}
};
+
+ private String nullToEmpty(String str) {
+ return str == null ? "" : str;
+ }
}
diff --git a/tests/src/com/android/server/telecom/tests/PhoneAccountRegistrarTest.java b/tests/src/com/android/server/telecom/tests/PhoneAccountRegistrarTest.java
index 2898457..a98712c 100644
--- a/tests/src/com/android/server/telecom/tests/PhoneAccountRegistrarTest.java
+++ b/tests/src/com/android/server/telecom/tests/PhoneAccountRegistrarTest.java
@@ -51,6 +51,7 @@
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 @@
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",