diff --git a/res/values/config.xml b/res/values/config.xml
index 7901a4cc17e..9069340be09 100755
--- a/res/values/config.xml
+++ b/res/values/config.xml
@@ -586,4 +586,8 @@
- 0.5
+
+ 20
diff --git a/src/com/android/settings/SettingsApplication.java b/src/com/android/settings/SettingsApplication.java
index 353208d6dc7..fc56e934f01 100644
--- a/src/com/android/settings/SettingsApplication.java
+++ b/src/com/android/settings/SettingsApplication.java
@@ -20,6 +20,7 @@ import android.app.Application;
import com.android.settings.activityembedding.ActivityEmbeddingRulesController;
import com.android.settings.homepage.SettingsHomepageActivity;
+import com.android.settingslib.applications.AppIconCacheManager;
import java.lang.ref.WeakReference;
@@ -44,4 +45,10 @@ public class SettingsApplication extends Application {
public SettingsHomepageActivity getHomeActivity() {
return mHomeActivity.get();
}
+
+ @Override
+ public void onLowMemory() {
+ super.onLowMemory();
+ AppIconCacheManager.getInstance().release();
+ }
}
diff --git a/src/com/android/settings/applications/manageapplications/ManageApplications.java b/src/com/android/settings/applications/manageapplications/ManageApplications.java
index 01bc2f19bb9..879bfde2a0e 100644
--- a/src/com/android/settings/applications/manageapplications/ManageApplications.java
+++ b/src/com/android/settings/applications/manageapplications/ManageApplications.java
@@ -43,6 +43,7 @@ import android.content.Context;
import android.content.Intent;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageItemInfo;
+import android.graphics.drawable.Drawable;
import android.net.Uri;
import android.os.Build;
import android.os.Bundle;
@@ -125,6 +126,8 @@ import com.android.settings.notification.app.AppNotificationSettings;
import com.android.settings.widget.LoadingViewController;
import com.android.settings.wifi.AppStateChangeWifiStateBridge;
import com.android.settings.wifi.ChangeWifiStateDetails;
+import com.android.settingslib.applications.AppIconCacheManager;
+import com.android.settingslib.applications.AppUtils;
import com.android.settingslib.applications.ApplicationsState;
import com.android.settingslib.applications.ApplicationsState.AppEntry;
import com.android.settingslib.applications.ApplicationsState.AppFilter;
@@ -556,6 +559,7 @@ public class ManageApplications extends InstrumentedFragment
mApplications.release();
}
mRootView = null;
+ AppIconCacheManager.getInstance().release();
}
@Override
@@ -1323,6 +1327,11 @@ public class ManageApplications extends InstrumentedFragment
if (DEBUG) {
Log.d(TAG, "onRebuildComplete size=" + entries.size());
}
+
+ // Preload top visible icons of app list.
+ AppUtils.preloadTopIcons(mContext, entries,
+ mContext.getResources().getInteger(R.integer.config_num_visible_app_icons));
+
final int filterType = mAppFilter.getFilterType();
if (filterType == FILTER_APPS_POWER_ALLOWLIST
|| filterType == FILTER_APPS_POWER_ALLOWLIST_ALL) {
@@ -1480,8 +1489,7 @@ public class ManageApplications extends InstrumentedFragment
synchronized (entry) {
mState.ensureLabelDescription(entry);
holder.setTitle(entry.label, entry.labelDescription);
- mState.ensureIcon(entry);
- holder.setIcon(entry.icon);
+ updateIcon(holder, entry);
updateSummary(holder, entry);
updateSwitch(holder, entry);
holder.updateDisableView(entry.info);
@@ -1491,6 +1499,20 @@ public class ManageApplications extends InstrumentedFragment
holder.itemView.setOnClickListener(mManageApplications);
}
+ private void updateIcon(ApplicationViewHolder holder, AppEntry entry) {
+ final Drawable cachedIcon = AppUtils.getIconFromCache(entry);
+ if (cachedIcon != null && entry.mounted) {
+ holder.setIcon(cachedIcon);
+ } else {
+ ThreadUtils.postOnBackgroundThread(() -> {
+ final Drawable icon = AppUtils.getIcon(mContext, entry);
+ if (icon != null) {
+ ThreadUtils.postOnMainThread(() -> holder.setIcon(icon));
+ }
+ });
+ }
+ }
+
private void updateSummary(ApplicationViewHolder holder, AppEntry entry) {
switch (mManageApplications.mListType) {
case LIST_TYPE_NOTIFICATION:
diff --git a/src/com/android/settings/datausage/UnrestrictedDataAccess.java b/src/com/android/settings/datausage/UnrestrictedDataAccess.java
index 6d8a4bad249..319ab6fe5a3 100644
--- a/src/com/android/settings/datausage/UnrestrictedDataAccess.java
+++ b/src/com/android/settings/datausage/UnrestrictedDataAccess.java
@@ -25,6 +25,7 @@ import android.view.View;
import com.android.settings.R;
import com.android.settings.dashboard.DashboardFragment;
import com.android.settings.search.BaseSearchIndexProvider;
+import com.android.settingslib.applications.AppIconCacheManager;
import com.android.settingslib.applications.ApplicationsState;
import com.android.settingslib.applications.ApplicationsState.AppFilter;
import com.android.settingslib.search.SearchIndexable;
@@ -112,6 +113,12 @@ public class UnrestrictedDataAccess extends DashboardFragment {
return R.xml.unrestricted_data_access_settings;
}
+ @Override
+ public void onDestroyView() {
+ super.onDestroyView();
+ AppIconCacheManager.getInstance().release();
+ }
+
public static final BaseSearchIndexProvider SEARCH_INDEX_DATA_PROVIDER =
new BaseSearchIndexProvider(R.xml.unrestricted_data_access_settings);
}
diff --git a/src/com/android/settings/datausage/UnrestrictedDataAccessPreference.java b/src/com/android/settings/datausage/UnrestrictedDataAccessPreference.java
index a41b5828b46..cd26ed16e8f 100644
--- a/src/com/android/settings/datausage/UnrestrictedDataAccessPreference.java
+++ b/src/com/android/settings/datausage/UnrestrictedDataAccessPreference.java
@@ -16,6 +16,7 @@ package com.android.settings.datausage;
import static com.android.settingslib.RestrictedLockUtilsInternal.checkIfMeteredDataRestricted;
import android.content.Context;
+import android.graphics.drawable.Drawable;
import android.os.UserHandle;
import android.view.View;
@@ -26,8 +27,10 @@ import com.android.settings.applications.appinfo.AppInfoDashboardFragment;
import com.android.settings.dashboard.DashboardFragment;
import com.android.settingslib.RestrictedLockUtils.EnforcedAdmin;
import com.android.settingslib.RestrictedPreferenceHelper;
+import com.android.settingslib.applications.AppUtils;
import com.android.settingslib.applications.ApplicationsState;
import com.android.settingslib.applications.ApplicationsState.AppEntry;
+import com.android.settingslib.utils.ThreadUtils;
import com.android.settingslib.widget.AppSwitchPreference;
public class UnrestrictedDataAccessPreference extends AppSwitchPreference implements
@@ -39,6 +42,7 @@ public class UnrestrictedDataAccessPreference extends AppSwitchPreference implem
private final DataSaverBackend mDataSaverBackend;
private final DashboardFragment mParentFragment;
private final RestrictedPreferenceHelper mHelper;
+ private Drawable mCacheIcon;
public UnrestrictedDataAccessPreference(final Context context, AppEntry entry,
ApplicationsState applicationsState, DataSaverBackend dataSaverBackend,
@@ -56,8 +60,13 @@ public class UnrestrictedDataAccessPreference extends AppSwitchPreference implem
UserHandle.getUserId(entry.info.uid)));
updateState();
setKey(generateKey(mEntry));
- if (mEntry.icon != null) {
- setIcon(mEntry.icon);
+
+ mCacheIcon = AppUtils.getIconFromCache(mEntry);
+ if (mCacheIcon != null) {
+ setIcon(mCacheIcon);
+ } else {
+ // Set empty icon as default.
+ setIcon(R.drawable.empty_icon);
}
}
@@ -101,16 +110,13 @@ public class UnrestrictedDataAccessPreference extends AppSwitchPreference implem
@Override
public void onBindViewHolder(PreferenceViewHolder holder) {
- if (mEntry.icon == null) {
- holder.itemView.post(new Runnable() {
- @Override
- public void run() {
- // Ensure we have an icon before binding.
- mApplicationsState.ensureIcon(mEntry);
- // This might trigger us to bind again, but it gives an easy way to only
- // load the icon once its needed, so its probably worth it.
- setIcon(mEntry.icon);
- }
+ if (mCacheIcon == null) {
+ ThreadUtils.postOnBackgroundThread(() -> {
+ final Drawable icon = AppUtils.getIcon(getContext(), mEntry);
+ ThreadUtils.postOnMainThread(() -> {
+ setIcon(icon);
+ mCacheIcon = icon;
+ });
});
}
final boolean disabledByAdmin = isDisabledByAdmin();
diff --git a/src/com/android/settings/datausage/UnrestrictedDataAccessPreferenceController.java b/src/com/android/settings/datausage/UnrestrictedDataAccessPreferenceController.java
index e3c79a7e8a7..ac088c037e0 100644
--- a/src/com/android/settings/datausage/UnrestrictedDataAccessPreferenceController.java
+++ b/src/com/android/settings/datausage/UnrestrictedDataAccessPreferenceController.java
@@ -29,6 +29,7 @@ import com.android.settings.applications.AppStateBaseBridge;
import com.android.settings.core.BasePreferenceController;
import com.android.settings.dashboard.DashboardFragment;
import com.android.settings.overlay.FeatureFactory;
+import com.android.settingslib.applications.AppUtils;
import com.android.settingslib.applications.ApplicationsState;
import com.android.settingslib.applications.ApplicationsState.AppEntry;
import com.android.settingslib.applications.ApplicationsState.AppFilter;
@@ -125,6 +126,10 @@ public class UnrestrictedDataAccessPreferenceController extends BasePreferenceCo
return;
}
+ // Preload top visible icons of app list.
+ AppUtils.preloadTopIcons(mContext, apps,
+ mContext.getResources().getInteger(R.integer.config_num_visible_app_icons));
+
// Create apps key set for removing useless preferences
final Set appsKeySet = new TreeSet<>();
// Add or update preferences