Loading packages/SettingsLib/src/com/android/settingslib/drawer/CategoryManager.java +58 −0 Original line number Diff line number Diff line Loading @@ -18,6 +18,7 @@ package com.android.settingslib.drawer; import android.content.ComponentName; import android.content.Context; import android.support.annotation.VisibleForTesting; import android.text.TextUtils; import android.util.ArrayMap; import android.util.Log; import android.util.Pair; Loading @@ -25,12 +26,15 @@ import android.util.Pair; import com.android.settingslib.applications.InterestingConfigChanges; import java.util.ArrayList; import java.util.Collections; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Map.Entry; import java.util.Set; import static java.lang.String.CASE_INSENSITIVE_ORDER; public class CategoryManager { private static final String TAG = "CategoryManager"; Loading Loading @@ -111,6 +115,7 @@ public class CategoryManager { mCategoryByKeyMap.put(category.key, category); } backwardCompatCleanupForCategory(mTileByComponentCache, mCategoryByKeyMap); normalizePriority(context, mCategoryByKeyMap); } } Loading Loading @@ -163,4 +168,57 @@ public class CategoryManager { } } } /** * Normalize priority values on tiles across injected from all apps to make sure they don't set * the same priority value. However internal tiles' priority remains unchanged. * <p/> * A list of tiles are considered normalized when their priority value increases in a linear * scan. */ @VisibleForTesting synchronized void normalizePriority(Context context, Map<String, DashboardCategory> categoryByKeyMap) { for (Entry<String, DashboardCategory> categoryEntry : categoryByKeyMap.entrySet()) { normalizePriorityForExternalTiles(context, categoryEntry.getValue()); } } /** * Normalize priority value for tiles within a single {@code DashboardCategory}. * * @see #normalizePriority(Context, Map) */ private synchronized void normalizePriorityForExternalTiles(Context context, DashboardCategory dashboardCategory) { final String skipPackageName = context.getPackageName(); // Sort tiles based on [package, priority within package] Collections.sort(dashboardCategory.tiles, (tile1, tile2) -> { final String package1 = tile1.intent.getComponent().getPackageName(); final String package2 = tile2.intent.getComponent().getPackageName(); final int packageCompare = CASE_INSENSITIVE_ORDER.compare(package1, package2); // First sort by package name if (packageCompare != 0) { return packageCompare; } else if (TextUtils.equals(package1, skipPackageName)) { return 0; } // Then sort by priority return tile1.priority - tile2.priority; }); // Update priority for all items so no package define the same priority value. final int count = dashboardCategory.tiles.size(); for (int i = 0; i < count; i++) { final String packageName = dashboardCategory.tiles.get(i).intent.getComponent().getPackageName(); if (TextUtils.equals(packageName, skipPackageName)) { // We skip this tile because it's a intent pointing to our own app. We trust the // priority is set correctly, so don't normalize. continue; } dashboardCategory.tiles.get(i).priority = i; } } } packages/SettingsLib/tests/robotests/src/com/android/settingslib/drawer/CategoryManagerTest.java +112 −0 Original line number Diff line number Diff line Loading @@ -16,7 +16,9 @@ package com.android.settingslib.drawer; import android.content.ComponentName; import android.content.Context; import android.content.Intent; import android.util.Pair; import com.android.settingslib.TestConfig; Loading Loading @@ -116,4 +118,114 @@ public class CategoryManagerTest { // Old category still exists. assertThat(mCategoryByKeyMap.get(oldCategory).tiles.size()).isEqualTo(1); } @Test public void normalizePriority_singlePackage_shouldReorderBasedOnPriority() { // Create some fake tiles that are not sorted. final String testPackage = "com.android.test"; final DashboardCategory category = new DashboardCategory(); final Tile tile1 = new Tile(); tile1.intent = new Intent().setComponent(new ComponentName(testPackage, "class1")); tile1.priority = 100; final Tile tile2 = new Tile(); tile2.intent = new Intent().setComponent(new ComponentName(testPackage, "class2")); tile2.priority = 50; final Tile tile3 = new Tile(); tile3.intent = new Intent().setComponent(new ComponentName(testPackage, "class3")); tile3.priority = 200; category.tiles.add(tile1); category.tiles.add(tile2); category.tiles.add(tile3); mCategoryByKeyMap.put(CategoryKey.CATEGORY_HOMEPAGE, category); // Normalize their priorities mCategoryManager.normalizePriority(ShadowApplication.getInstance().getApplicationContext(), mCategoryByKeyMap); // Verify they are now sorted. assertThat(category.tiles.get(0)).isSameAs(tile2); assertThat(category.tiles.get(1)).isSameAs(tile1); assertThat(category.tiles.get(2)).isSameAs(tile3); // Verify their priority is normalized assertThat(category.tiles.get(0).priority).isEqualTo(0); assertThat(category.tiles.get(1).priority).isEqualTo(1); assertThat(category.tiles.get(2).priority).isEqualTo(2); } @Test public void normalizePriority_multiPackage_shouldReorderBasedOnPackageAndPriority() { // Create some fake tiles that are not sorted. final String testPackage1 = "com.android.test1"; final String testPackage2 = "com.android.test2"; final DashboardCategory category = new DashboardCategory(); final Tile tile1 = new Tile(); tile1.intent = new Intent().setComponent(new ComponentName(testPackage2, "class1")); tile1.priority = 100; final Tile tile2 = new Tile(); tile2.intent = new Intent().setComponent(new ComponentName(testPackage1, "class2")); tile2.priority = 100; final Tile tile3 = new Tile(); tile3.intent = new Intent().setComponent(new ComponentName(testPackage1, "class3")); tile3.priority = 50; category.tiles.add(tile1); category.tiles.add(tile2); category.tiles.add(tile3); mCategoryByKeyMap.put(CategoryKey.CATEGORY_HOMEPAGE, category); // Normalize their priorities mCategoryManager.normalizePriority(ShadowApplication.getInstance().getApplicationContext(), mCategoryByKeyMap); // Verify they are now sorted. assertThat(category.tiles.get(0)).isSameAs(tile3); assertThat(category.tiles.get(1)).isSameAs(tile2); assertThat(category.tiles.get(2)).isSameAs(tile1); // Verify their priority is normalized assertThat(category.tiles.get(0).priority).isEqualTo(0); assertThat(category.tiles.get(1).priority).isEqualTo(1); assertThat(category.tiles.get(2).priority).isEqualTo(2); } @Test public void normalizePriority_internalPackageTiles_shouldSkipTileForInternalPackage() { // Create some fake tiles that are not sorted. final String testPackage = ShadowApplication.getInstance().getApplicationContext().getPackageName(); final DashboardCategory category = new DashboardCategory(); final Tile tile1 = new Tile(); tile1.intent = new Intent().setComponent(new ComponentName(testPackage, "class1")); tile1.priority = 100; final Tile tile2 = new Tile(); tile2.intent = new Intent().setComponent(new ComponentName(testPackage, "class2")); tile2.priority = 100; final Tile tile3 = new Tile(); tile3.intent = new Intent().setComponent(new ComponentName(testPackage, "class3")); tile3.priority = 50; category.tiles.add(tile1); category.tiles.add(tile2); category.tiles.add(tile3); mCategoryByKeyMap.put(CategoryKey.CATEGORY_HOMEPAGE, category); // Normalize their priorities mCategoryManager.normalizePriority(ShadowApplication.getInstance().getApplicationContext(), mCategoryByKeyMap); // Verify the sorting order is not changed assertThat(category.tiles.get(0)).isSameAs(tile1); assertThat(category.tiles.get(1)).isSameAs(tile2); assertThat(category.tiles.get(2)).isSameAs(tile3); // Verify their priorities are not changed. assertThat(category.tiles.get(0).priority).isEqualTo(100); assertThat(category.tiles.get(1).priority).isEqualTo(100); assertThat(category.tiles.get(2).priority).isEqualTo(50); } } Loading
packages/SettingsLib/src/com/android/settingslib/drawer/CategoryManager.java +58 −0 Original line number Diff line number Diff line Loading @@ -18,6 +18,7 @@ package com.android.settingslib.drawer; import android.content.ComponentName; import android.content.Context; import android.support.annotation.VisibleForTesting; import android.text.TextUtils; import android.util.ArrayMap; import android.util.Log; import android.util.Pair; Loading @@ -25,12 +26,15 @@ import android.util.Pair; import com.android.settingslib.applications.InterestingConfigChanges; import java.util.ArrayList; import java.util.Collections; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Map.Entry; import java.util.Set; import static java.lang.String.CASE_INSENSITIVE_ORDER; public class CategoryManager { private static final String TAG = "CategoryManager"; Loading Loading @@ -111,6 +115,7 @@ public class CategoryManager { mCategoryByKeyMap.put(category.key, category); } backwardCompatCleanupForCategory(mTileByComponentCache, mCategoryByKeyMap); normalizePriority(context, mCategoryByKeyMap); } } Loading Loading @@ -163,4 +168,57 @@ public class CategoryManager { } } } /** * Normalize priority values on tiles across injected from all apps to make sure they don't set * the same priority value. However internal tiles' priority remains unchanged. * <p/> * A list of tiles are considered normalized when their priority value increases in a linear * scan. */ @VisibleForTesting synchronized void normalizePriority(Context context, Map<String, DashboardCategory> categoryByKeyMap) { for (Entry<String, DashboardCategory> categoryEntry : categoryByKeyMap.entrySet()) { normalizePriorityForExternalTiles(context, categoryEntry.getValue()); } } /** * Normalize priority value for tiles within a single {@code DashboardCategory}. * * @see #normalizePriority(Context, Map) */ private synchronized void normalizePriorityForExternalTiles(Context context, DashboardCategory dashboardCategory) { final String skipPackageName = context.getPackageName(); // Sort tiles based on [package, priority within package] Collections.sort(dashboardCategory.tiles, (tile1, tile2) -> { final String package1 = tile1.intent.getComponent().getPackageName(); final String package2 = tile2.intent.getComponent().getPackageName(); final int packageCompare = CASE_INSENSITIVE_ORDER.compare(package1, package2); // First sort by package name if (packageCompare != 0) { return packageCompare; } else if (TextUtils.equals(package1, skipPackageName)) { return 0; } // Then sort by priority return tile1.priority - tile2.priority; }); // Update priority for all items so no package define the same priority value. final int count = dashboardCategory.tiles.size(); for (int i = 0; i < count; i++) { final String packageName = dashboardCategory.tiles.get(i).intent.getComponent().getPackageName(); if (TextUtils.equals(packageName, skipPackageName)) { // We skip this tile because it's a intent pointing to our own app. We trust the // priority is set correctly, so don't normalize. continue; } dashboardCategory.tiles.get(i).priority = i; } } }
packages/SettingsLib/tests/robotests/src/com/android/settingslib/drawer/CategoryManagerTest.java +112 −0 Original line number Diff line number Diff line Loading @@ -16,7 +16,9 @@ package com.android.settingslib.drawer; import android.content.ComponentName; import android.content.Context; import android.content.Intent; import android.util.Pair; import com.android.settingslib.TestConfig; Loading Loading @@ -116,4 +118,114 @@ public class CategoryManagerTest { // Old category still exists. assertThat(mCategoryByKeyMap.get(oldCategory).tiles.size()).isEqualTo(1); } @Test public void normalizePriority_singlePackage_shouldReorderBasedOnPriority() { // Create some fake tiles that are not sorted. final String testPackage = "com.android.test"; final DashboardCategory category = new DashboardCategory(); final Tile tile1 = new Tile(); tile1.intent = new Intent().setComponent(new ComponentName(testPackage, "class1")); tile1.priority = 100; final Tile tile2 = new Tile(); tile2.intent = new Intent().setComponent(new ComponentName(testPackage, "class2")); tile2.priority = 50; final Tile tile3 = new Tile(); tile3.intent = new Intent().setComponent(new ComponentName(testPackage, "class3")); tile3.priority = 200; category.tiles.add(tile1); category.tiles.add(tile2); category.tiles.add(tile3); mCategoryByKeyMap.put(CategoryKey.CATEGORY_HOMEPAGE, category); // Normalize their priorities mCategoryManager.normalizePriority(ShadowApplication.getInstance().getApplicationContext(), mCategoryByKeyMap); // Verify they are now sorted. assertThat(category.tiles.get(0)).isSameAs(tile2); assertThat(category.tiles.get(1)).isSameAs(tile1); assertThat(category.tiles.get(2)).isSameAs(tile3); // Verify their priority is normalized assertThat(category.tiles.get(0).priority).isEqualTo(0); assertThat(category.tiles.get(1).priority).isEqualTo(1); assertThat(category.tiles.get(2).priority).isEqualTo(2); } @Test public void normalizePriority_multiPackage_shouldReorderBasedOnPackageAndPriority() { // Create some fake tiles that are not sorted. final String testPackage1 = "com.android.test1"; final String testPackage2 = "com.android.test2"; final DashboardCategory category = new DashboardCategory(); final Tile tile1 = new Tile(); tile1.intent = new Intent().setComponent(new ComponentName(testPackage2, "class1")); tile1.priority = 100; final Tile tile2 = new Tile(); tile2.intent = new Intent().setComponent(new ComponentName(testPackage1, "class2")); tile2.priority = 100; final Tile tile3 = new Tile(); tile3.intent = new Intent().setComponent(new ComponentName(testPackage1, "class3")); tile3.priority = 50; category.tiles.add(tile1); category.tiles.add(tile2); category.tiles.add(tile3); mCategoryByKeyMap.put(CategoryKey.CATEGORY_HOMEPAGE, category); // Normalize their priorities mCategoryManager.normalizePriority(ShadowApplication.getInstance().getApplicationContext(), mCategoryByKeyMap); // Verify they are now sorted. assertThat(category.tiles.get(0)).isSameAs(tile3); assertThat(category.tiles.get(1)).isSameAs(tile2); assertThat(category.tiles.get(2)).isSameAs(tile1); // Verify their priority is normalized assertThat(category.tiles.get(0).priority).isEqualTo(0); assertThat(category.tiles.get(1).priority).isEqualTo(1); assertThat(category.tiles.get(2).priority).isEqualTo(2); } @Test public void normalizePriority_internalPackageTiles_shouldSkipTileForInternalPackage() { // Create some fake tiles that are not sorted. final String testPackage = ShadowApplication.getInstance().getApplicationContext().getPackageName(); final DashboardCategory category = new DashboardCategory(); final Tile tile1 = new Tile(); tile1.intent = new Intent().setComponent(new ComponentName(testPackage, "class1")); tile1.priority = 100; final Tile tile2 = new Tile(); tile2.intent = new Intent().setComponent(new ComponentName(testPackage, "class2")); tile2.priority = 100; final Tile tile3 = new Tile(); tile3.intent = new Intent().setComponent(new ComponentName(testPackage, "class3")); tile3.priority = 50; category.tiles.add(tile1); category.tiles.add(tile2); category.tiles.add(tile3); mCategoryByKeyMap.put(CategoryKey.CATEGORY_HOMEPAGE, category); // Normalize their priorities mCategoryManager.normalizePriority(ShadowApplication.getInstance().getApplicationContext(), mCategoryByKeyMap); // Verify the sorting order is not changed assertThat(category.tiles.get(0)).isSameAs(tile1); assertThat(category.tiles.get(1)).isSameAs(tile2); assertThat(category.tiles.get(2)).isSameAs(tile3); // Verify their priorities are not changed. assertThat(category.tiles.get(0).priority).isEqualTo(100); assertThat(category.tiles.get(1).priority).isEqualTo(100); assertThat(category.tiles.get(2).priority).isEqualTo(50); } }