Put all isTintable check at one place.

Make a bunch fields private in TIle and DashboardCategory

Bug: 77600770
Test: robotests
Change-Id: Ifa7b5d1fc3baa3327044c310849cc9f110d14fcd
diff --git a/packages/SettingsLib/src/com/android/settingslib/drawer/DashboardCategory.java b/packages/SettingsLib/src/com/android/settingslib/drawer/DashboardCategory.java
index 2e0a94c..cb21f87 100644
--- a/packages/SettingsLib/src/com/android/settingslib/drawer/DashboardCategory.java
+++ b/packages/SettingsLib/src/com/android/settingslib/drawer/DashboardCategory.java
@@ -31,19 +31,26 @@
     /**
      * Key used for placing external tiles.
      */
-    public String key;
+    public final String key;
 
     /**
      * List of the category's children
      */
     private List<Tile> mTiles = new ArrayList<>();
 
-    public DashboardCategory() {
-        // Empty
+    public DashboardCategory(String key) {
+        this.key = key;
     }
 
     DashboardCategory(Parcel in) {
-        readFromParcel(in);
+        key = in.readString();
+
+        final int count = in.readInt();
+
+        for (int n = 0; n < count; n++) {
+            Tile tile = Tile.CREATOR.createFromParcel(in);
+            mTiles.add(tile);
+        }
     }
 
     /**
@@ -128,18 +135,6 @@
         }
     }
 
-    public void readFromParcel(Parcel in) {
-        key = in.readString();
-
-        final int count = in.readInt();
-
-        for (int n = 0; n < count; n++) {
-            Tile tile = Tile.CREATOR.createFromParcel(in);
-            mTiles.add(tile);
-        }
-    }
-
-
     public static final Creator<DashboardCategory> CREATOR = new Creator<DashboardCategory>() {
         public DashboardCategory createFromParcel(Parcel source) {
             return new DashboardCategory(source);
diff --git a/packages/SettingsLib/src/com/android/settingslib/drawer/Tile.java b/packages/SettingsLib/src/com/android/settingslib/drawer/Tile.java
index 18f94b7..3320433 100644
--- a/packages/SettingsLib/src/com/android/settingslib/drawer/Tile.java
+++ b/packages/SettingsLib/src/com/android/settingslib/drawer/Tile.java
@@ -60,12 +60,6 @@
     public CharSequence summary;
 
     /**
-     * Whether the icon can be tinted. This should be set to true for monochrome (single-color)
-     * icons that can be tinted to match the design.
-     */
-    public boolean isIconTintable;
-
-    /**
      * Intent to launch when the preference is selected.
      */
     public Intent intent;
@@ -75,10 +69,7 @@
      */
     public ArrayList<UserHandle> userHandle = new ArrayList<>();
 
-    /**
-     * Category in which the tile should be placed.
-     */
-    public String category;
+    private String mCategory;
 
     /**
      * Priority of the intent filter that created this tile, used for display ordering.
@@ -88,22 +79,23 @@
     /**
      * The metaData from the activity that defines this tile.
      */
-    public Bundle metaData;
+    private Bundle mMetaData;
 
     /**
      * Optional key to use for this tile.
      */
     public String key;
 
-
     private final String mActivityPackage;
     private final String mActivityName;
     private ActivityInfo mActivityInfo;
 
-    public Tile(ActivityInfo activityInfo) {
+    public Tile(ActivityInfo activityInfo, String category) {
         mActivityInfo = activityInfo;
         mActivityPackage = mActivityInfo.packageName;
         mActivityName = mActivityInfo.name;
+        mMetaData = activityInfo.metaData;
+        mCategory = category;
     }
 
     @Override
@@ -128,11 +120,32 @@
         for (int i = 0; i < N; i++) {
             userHandle.get(i).writeToParcel(dest, flags);
         }
-        dest.writeString(category);
+        dest.writeString(mCategory);
         dest.writeInt(priority);
-        dest.writeBundle(metaData);
+        dest.writeBundle(mMetaData);
         dest.writeString(key);
-        dest.writeBoolean(isIconTintable);
+    }
+
+    /**
+     * Category in which the tile should be placed.
+     */
+    public String getCategory() {
+        return mCategory;
+    }
+
+    public void setCategory(String newCategoryKey) {
+        mCategory = newCategoryKey;
+    }
+
+    /**
+     * Priority of the intent filter that created this tile, used for display ordering.
+     */
+    public int getPriority() {
+        return 0;
+    }
+
+    public Bundle getMetaData() {
+        return mMetaData;
     }
 
     /**
@@ -141,17 +154,17 @@
      * @attr ref android.R.styleable#PreferenceHeader_icon
      */
     public Icon getIcon(Context context) {
-        if (context == null || metaData == null) {
+        if (context == null || mMetaData == null) {
             return null;
         }
 
-        int iconResId = metaData.getInt(META_DATA_PREFERENCE_ICON);
+        int iconResId = mMetaData.getInt(META_DATA_PREFERENCE_ICON);
         // Set the icon
         if (iconResId == 0) {
             // Only fallback to activityinfo.icon if metadata does not contain ICON_URI.
             // ICON_URI should be loaded in app UI when need the icon object. Handling IPC at this
             // level is too complex because we don't have a strong threading contract for this class
-            if (!metaData.containsKey(META_DATA_PREFERENCE_ICON_URI)) {
+            if (!mMetaData.containsKey(META_DATA_PREFERENCE_ICON_URI)) {
                 iconResId = getActivityInfo(context).icon;
             }
         }
@@ -162,6 +175,21 @@
         }
     }
 
+    /**
+     * Whether the icon can be tinted. This is true when icon needs to be monochrome (single-color)
+     */
+    public boolean isIconTintable(Context context) {
+        if (mMetaData != null
+                && mMetaData.containsKey(TileUtils.META_DATA_PREFERENCE_ICON_TINTABLE)) {
+            return mMetaData.getBoolean(TileUtils.META_DATA_PREFERENCE_ICON_TINTABLE);
+        }
+        final String pkgName = context.getPackageName();
+        // If this drawable is coming from outside Settings, tint it to match the color.
+        final ActivityInfo activityInfo = getActivityInfo(context);
+        return activityInfo != null
+                && !TextUtils.equals(pkgName, activityInfo.packageName);
+    }
+
     Tile(Parcel in) {
         mActivityPackage = in.readString();
         mActivityName = in.readString();
@@ -174,11 +202,10 @@
         for (int i = 0; i < N; i++) {
             userHandle.add(UserHandle.CREATOR.createFromParcel(in));
         }
-        category = in.readString();
+        mCategory = in.readString();
         priority = in.readInt();
-        metaData = in.readBundle();
+        mMetaData = in.readBundle();
         key = in.readString();
-        isIconTintable = in.readBoolean();
     }
 
     private ActivityInfo getActivityInfo(Context context) {
@@ -205,8 +232,8 @@
     };
 
     public boolean isPrimaryProfileOnly() {
-        String profile = metaData != null ?
-                metaData.getString(META_DATA_KEY_PROFILE) : PROFILE_ALL;
+        String profile = mMetaData != null ?
+                mMetaData.getString(META_DATA_KEY_PROFILE) : PROFILE_ALL;
         profile = (profile != null ? profile : PROFILE_ALL);
         return TextUtils.equals(profile, PROFILE_PRIMARY);
     }
diff --git a/packages/SettingsLib/src/com/android/settingslib/drawer/TileUtils.java b/packages/SettingsLib/src/com/android/settingslib/drawer/TileUtils.java
index 6b9a08e..7b54fe1 100644
--- a/packages/SettingsLib/src/com/android/settingslib/drawer/TileUtils.java
+++ b/packages/SettingsLib/src/com/android/settingslib/drawer/TileUtils.java
@@ -228,16 +228,16 @@
 
         HashMap<String, DashboardCategory> categoryMap = new HashMap<>();
         for (Tile tile : tiles) {
-            DashboardCategory category = categoryMap.get(tile.category);
+            final String categoryKey = tile.getCategory();
+            DashboardCategory category = categoryMap.get(categoryKey);
             if (category == null) {
-                category = new DashboardCategory();
-                category.key = tile.category;
+                category = new DashboardCategory(categoryKey);
 
                 if (category == null) {
-                    Log.w(LOG_TAG, "Couldn't find category " + tile.category);
+                    Log.w(LOG_TAG, "Couldn't find category " + categoryKey);
                     continue;
                 }
-                categoryMap.put(category.key, category);
+                categoryMap.put(categoryKey, category);
             }
             category.addTile(tile);
         }
@@ -269,13 +269,13 @@
             intent.setPackage(SETTING_PKG);
         }
         getTilesForIntent(context, user, intent, addedCache, defaultCategory, outTiles,
-                usePriority, true);
+                usePriority);
     }
 
     public static void getTilesForIntent(
             Context context, UserHandle user, Intent intent,
             Map<Pair<String, String>, Tile> addedCache, String defaultCategory, List<Tile> outTiles,
-            boolean usePriority, boolean checkCategory) {
+            boolean usePriority) {
         PackageManager pm = context.getPackageManager();
         List<ResolveInfo> results = pm.queryIntentActivitiesAsUser(intent,
                 PackageManager.GET_META_DATA, user.getIdentifier());
@@ -289,7 +289,7 @@
             String categoryKey = defaultCategory;
 
             // Load category
-            if (checkCategory && ((metaData == null) || !metaData.containsKey(EXTRA_CATEGORY_KEY))
+            if ((metaData == null || !metaData.containsKey(EXTRA_CATEGORY_KEY))
                     && categoryKey == null) {
                 Log.w(LOG_TAG, "Found " + resolved.activityInfo.name + " for intent "
                         + intent + " missing metadata "
@@ -302,12 +302,10 @@
             Pair<String, String> key = new Pair<>(activityInfo.packageName, activityInfo.name);
             Tile tile = addedCache.get(key);
             if (tile == null) {
-                tile = new Tile(activityInfo);
+                tile = new Tile(activityInfo, categoryKey);
                 tile.intent = new Intent().setClassName(
                         activityInfo.packageName, activityInfo.name);
-                tile.category = categoryKey;
                 tile.priority = usePriority ? resolved.priority : 0;
-                tile.metaData = activityInfo.metaData;
                 updateTileData(context, tile, activityInfo, activityInfo.applicationInfo, pm);
                 if (DEBUG) Log.d(LOG_TAG, "Adding tile " + tile.title);
                 addedCache.put(key, tile);
@@ -325,31 +323,16 @@
     private static boolean updateTileData(Context context, Tile tile,
             ActivityInfo activityInfo, ApplicationInfo applicationInfo, PackageManager pm) {
         if (applicationInfo.isSystemApp()) {
-            boolean forceTintIcon = false;
             CharSequence title = null;
             String summary = null;
             String keyHint = null;
-            boolean isIconTintable = false;
 
             // Get the activity's meta-data
             try {
                 Resources res = pm.getResourcesForApplication(applicationInfo.packageName);
                 Bundle metaData = activityInfo.metaData;
 
-                if (!context.getPackageName().equals(applicationInfo.packageName)) {
-                    isIconTintable = true;
-                    forceTintIcon = true;
-                }
-
                 if (res != null && metaData != null) {
-                    if (metaData.containsKey(META_DATA_PREFERENCE_ICON_TINTABLE)) {
-                        if (forceTintIcon) {
-                            Log.w(LOG_TAG, "Ignoring icon tintable for " + activityInfo);
-                        } else {
-                            isIconTintable =
-                                    metaData.getBoolean(META_DATA_PREFERENCE_ICON_TINTABLE);
-                        }
-                    }
                     if (metaData.containsKey(META_DATA_PREFERENCE_TITLE)) {
                         if (metaData.get(META_DATA_PREFERENCE_TITLE) instanceof Integer) {
                             title = res.getString(metaData.getInt(META_DATA_PREFERENCE_TITLE));
@@ -390,7 +373,6 @@
                     activityInfo.name);
             // Suggest a key for this tile
             tile.key = keyHint;
-            tile.isIconTintable = isIconTintable;
 
             return true;
         }
diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/drawer/TileTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/drawer/TileTest.java
index a9e5aae..d959657 100644
--- a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/drawer/TileTest.java
+++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/drawer/TileTest.java
@@ -31,19 +31,19 @@
         mActivityInfo = new ActivityInfo();
         mActivityInfo.packageName = RuntimeEnvironment.application.getPackageName();
         mActivityInfo.icon = R.drawable.ic_plus;
-        mTile = new Tile(mActivityInfo);
-        mTile.metaData = new Bundle();
+        mActivityInfo.metaData = new Bundle();
+        mTile = new Tile(mActivityInfo, "category");
     }
 
     @Test
     public void isPrimaryProfileOnly_profilePrimary_shouldReturnTrue() {
-        mTile.metaData.putString(META_DATA_KEY_PROFILE, PROFILE_PRIMARY);
+        mActivityInfo.metaData.putString(META_DATA_KEY_PROFILE, PROFILE_PRIMARY);
         assertThat(mTile.isPrimaryProfileOnly()).isTrue();
     }
 
     @Test
     public void isPrimaryProfileOnly_profileAll_shouldReturnFalse() {
-        mTile.metaData.putString(META_DATA_KEY_PROFILE, PROFILE_ALL);
+        mActivityInfo.metaData.putString(META_DATA_KEY_PROFILE, PROFILE_ALL);
         assertThat(mTile.isPrimaryProfileOnly()).isFalse();
     }
 
@@ -54,27 +54,27 @@
 
     @Test
     public void isPrimaryProfileOnly_nullMetadata_shouldReturnFalse() {
-        mTile.metaData = null;
+        mActivityInfo.metaData = null;
         assertThat(mTile.isPrimaryProfileOnly()).isFalse();
     }
 
     @Test
     public void getIcon_noContextOrMetadata_returnNull() {
-        final Tile tile = new Tile(new ActivityInfo());
+        final Tile tile = new Tile(new ActivityInfo(), "category");
         assertThat(tile.getIcon(null)).isNull();
         assertThat(tile.getIcon(RuntimeEnvironment.application)).isNull();
     }
 
     @Test
     public void getIcon_providedByUri_returnNull() {
-        mTile.metaData.putString(META_DATA_PREFERENCE_ICON_URI, "content://foobar/icon");
+        mActivityInfo.metaData.putString(META_DATA_PREFERENCE_ICON_URI, "content://foobar/icon");
 
         assertThat(mTile.getIcon(RuntimeEnvironment.application)).isNull();
     }
 
     @Test
     public void getIcon_hasIconMetadata_returnIcon() {
-        mTile.metaData.putInt(META_DATA_PREFERENCE_ICON, R.drawable.ic_info);
+        mActivityInfo.metaData.putInt(META_DATA_PREFERENCE_ICON, R.drawable.ic_info);
 
         assertThat(mTile.getIcon(RuntimeEnvironment.application).getResId())
                 .isEqualTo(R.drawable.ic_info);
@@ -82,9 +82,39 @@
 
     @Test
     public void getIcon_noIconMetadata_returnActivityIcon() {
-        mTile.metaData.putInt(META_DATA_PREFERENCE_ICON, 0);
+        mActivityInfo.metaData.putInt(META_DATA_PREFERENCE_ICON, 0);
 
         assertThat(mTile.getIcon(RuntimeEnvironment.application).getResId())
                 .isEqualTo(mActivityInfo.icon);
     }
+
+    @Test
+    public void isIconTintable_hasMetadata_shouldReturnIconTintableMetadata() {
+        final Tile tile = new Tile(mActivityInfo, "category");
+
+        mActivityInfo.metaData.putBoolean(TileUtils.META_DATA_PREFERENCE_ICON_TINTABLE, false);
+        assertThat(tile.isIconTintable(RuntimeEnvironment.application)).isFalse();
+
+        mActivityInfo.metaData.putBoolean(TileUtils.META_DATA_PREFERENCE_ICON_TINTABLE, true);
+        assertThat(tile.isIconTintable(RuntimeEnvironment.application)).isTrue();
+    }
+
+    @Test
+    public void isIconTintable_noIcon_shouldReturnFalse() {
+        final Tile tile = new Tile(mActivityInfo, "category");
+
+        assertThat(tile.isIconTintable(RuntimeEnvironment.application)).isFalse();
+    }
+
+    @Test
+    public void isIconTintable_noMetadata_shouldReturnPackageNameCheck() {
+        final Tile tile1 = new Tile(mActivityInfo, "category");
+        assertThat(tile1.isIconTintable(RuntimeEnvironment.application)).isFalse();
+
+        final ActivityInfo activityInfo = new ActivityInfo();
+        activityInfo.packageName = "blah";
+
+        final Tile tile2 = new Tile(activityInfo, "category");
+        assertThat(tile2.isIconTintable(RuntimeEnvironment.application)).isTrue();
+    }
 }
diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/drawer/TileUtilsTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/drawer/TileUtilsTest.java
index 0b6acde..9fda8564 100644
--- a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/drawer/TileUtilsTest.java
+++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/drawer/TileUtilsTest.java
@@ -108,11 +108,10 @@
                 .thenReturn(info);
 
         TileUtils.getTilesForIntent(mContext, UserHandle.CURRENT, intent, addedCache,
-                null /* defaultCategory */, outTiles, false /* usePriority */,
-                false /* checkCategory */);
+                null /* defaultCategory */, outTiles, false /* usePriority */);
 
         assertThat(outTiles.size()).isEqualTo(1);
-        assertThat(outTiles.get(0).category).isEqualTo(testCategory);
+        assertThat(outTiles.get(0).getCategory()).isEqualTo(testCategory);
     }
 
     @Test
@@ -129,8 +128,7 @@
                 .thenReturn(info);
 
         TileUtils.getTilesForIntent(mContext, UserHandle.CURRENT, intent, addedCache,
-                null /* defaultCategory */, outTiles, false /* usePriority */,
-                false /* checkCategory */);
+                null /* defaultCategory */, outTiles, false /* usePriority */);
 
         assertThat(outTiles.size()).isEqualTo(1);
         assertThat(outTiles.get(0).key).isEqualTo(keyHint);
@@ -149,8 +147,7 @@
                 .thenReturn(info);
 
         TileUtils.getTilesForIntent(mContext, UserHandle.CURRENT, intent, addedCache,
-                null /* defaultCategory */, outTiles, false /* usePriority */,
-                false /* checkCategory */);
+                null /* defaultCategory */, outTiles, false /* usePriority */);
 
         assertThat(outTiles.isEmpty()).isTrue();
     }
@@ -173,7 +170,7 @@
                 .thenReturn(info);
 
         List<DashboardCategory> categoryList = TileUtils.getCategories(mContext, cache, testAction);
-        assertThat(categoryList.get(0).getTile(0).category).isEqualTo(testCategory);
+        assertThat(categoryList.get(0).getTile(0).getCategory()).isEqualTo(testCategory);
     }
 
     @Test
@@ -209,8 +206,7 @@
                 .thenReturn(info);
 
         TileUtils.getTilesForIntent(mContext, UserHandle.CURRENT, intent, addedCache,
-                null /* defaultCategory */, outTiles, false /* usePriority */,
-                false /* checkCategory */);
+                null /* defaultCategory */, outTiles, false /* usePriority */);
 
         assertThat(outTiles.size()).isEqualTo(1);
         assertThat(outTiles.get(0).title).isEqualTo("my title");
@@ -233,15 +229,13 @@
                 .thenReturn("my localized title");
 
         TileUtils.getTilesForIntent(mContext, UserHandle.CURRENT, intent, addedCache,
-                null /* defaultCategory */, outTiles, false /* usePriority */,
-                false /* checkCategory */);
-
+                null /* defaultCategory */, outTiles, false /* usePriority */);
         assertThat(outTiles.size()).isEqualTo(1);
         assertThat(outTiles.get(0).title).isEqualTo("my localized title");
 
         // Icon should be tintable because the tile is not from settings package, and
         // "forceTintExternalIcon" is set
-        assertThat(outTiles.get(0).isIconTintable).isTrue();
+        assertThat(outTiles.get(0).isIconTintable(mContext)).isTrue();
     }
 
     @Test
@@ -260,11 +254,9 @@
                 .thenReturn(info);
 
         TileUtils.getTilesForIntent(mContext, UserHandle.CURRENT, intent, addedCache,
-                null /* defaultCategory */, outTiles, false /* usePriority */,
-                false /* checkCategory */);
+                null /* defaultCategory */, outTiles, false /* usePriority */);
 
-        assertThat(outTiles.size()).isEqualTo(1);
-        assertThat(outTiles.get(0).isIconTintable).isFalse();
+        assertThat(outTiles.get(0).isIconTintable(mContext)).isFalse();
     }
 
     @Test
@@ -283,11 +275,9 @@
                 .thenReturn(info);
 
         TileUtils.getTilesForIntent(mContext, UserHandle.CURRENT, intent, addedCache,
-                null /* defaultCategory */, outTiles, false /* usePriority */,
-                false /* checkCategory */);
+                null /* defaultCategory */, outTiles, false /* usePriority */);
 
-        assertThat(outTiles.size()).isEqualTo(1);
-        assertThat(outTiles.get(0).isIconTintable).isTrue();
+        assertThat(outTiles.get(0).isIconTintable(mContext)).isTrue();
     }
 
     @Test
@@ -305,8 +295,7 @@
 
         // Case 1: No provider associated with the uri specified.
         TileUtils.getTilesForIntent(mContext, UserHandle.CURRENT, intent, addedCache,
-                null /* defaultCategory */, outTiles, false /* usePriority */,
-                false /* checkCategory */);
+                null /* defaultCategory */, outTiles, false /* usePriority */);
 
         assertThat(outTiles.size()).isEqualTo(1);
         assertThat(outTiles.get(0).getIcon(mContext).getResId()).isEqualTo(314159);
@@ -323,8 +312,7 @@
                 .thenReturn(mIContentProvider);
 
         TileUtils.getTilesForIntent(mContext, UserHandle.CURRENT, intent, addedCache,
-                null /* defaultCategory */, outTiles, false /* usePriority */,
-                false /* checkCategory */);
+                null /* defaultCategory */, outTiles, false /* usePriority */);
 
         assertThat(outTiles.size()).isEqualTo(1);
         assertThat(outTiles.get(0).getIcon(mContext).getResId()).isEqualTo(314159);
@@ -345,8 +333,7 @@
                 .thenReturn(info);
 
         TileUtils.getTilesForIntent(mContext, UserHandle.CURRENT, intent, addedCache,
-                null /* defaultCategory */, outTiles, false /* usePriority */,
-                false /* checkCategory */);
+                null /* defaultCategory */, outTiles, false /* usePriority */);
 
         assertThat(outTiles.size()).isEqualTo(1);
     }