diff --git a/res/layout/applist_preference_icon.xml b/res/layout/applist_preference_icon.xml
new file mode 100644
index 0000000..687de3d
--- /dev/null
+++ b/res/layout/applist_preference_icon.xml
@@ -0,0 +1,69 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/com/cherish/settings/preferences/PackageListAdapter.java b/src/com/cherish/settings/preferences/PackageListAdapter.java
new file mode 100644
index 0000000..0e85ec8
--- /dev/null
+++ b/src/com/cherish/settings/preferences/PackageListAdapter.java
@@ -0,0 +1,186 @@
+/*
+ * Copyright (C) 2012-2014 The CyanogenMod Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.cherish.settings.preferences;
+
+import android.content.Context;
+import android.content.Intent;
+import android.content.pm.ApplicationInfo;
+import android.content.pm.PackageManager;
+import android.content.pm.ResolveInfo;
+import android.graphics.drawable.Drawable;
+import android.os.Handler;
+import android.os.Message;
+import android.text.TextUtils;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.BaseAdapter;
+import android.widget.ImageView;
+import android.widget.TextView;
+
+import java.util.Collections;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.TreeSet;
+
+import com.android.settings.R;
+
+public class PackageListAdapter extends BaseAdapter implements Runnable {
+ private PackageManager mPm;
+ private LayoutInflater mInflater;
+ private List mInstalledPackages = new LinkedList();
+
+ // Packages which don't have launcher icons, but which we want to show nevertheless
+ private static final String[] PACKAGE_WHITELIST = new String[] {
+ "android", /* system server */
+ "com.android.systemui", /* system UI */
+ "com.android.providers.downloads" /* download provider */
+ };
+
+ private final Handler mHandler = new Handler() {
+ @Override
+ public void handleMessage(Message msg) {
+ PackageItem item = (PackageItem) msg.obj;
+ int index = Collections.binarySearch(mInstalledPackages, item);
+ if (index < 0) {
+ mInstalledPackages.add(-index - 1, item);
+ } else {
+ mInstalledPackages.get(index).activityTitles.addAll(item.activityTitles);
+ }
+ notifyDataSetChanged();
+ }
+ };
+
+ public static class PackageItem implements Comparable {
+ public final String packageName;
+ public final CharSequence title;
+ private final TreeSet activityTitles = new TreeSet();
+ public final Drawable icon;
+
+ PackageItem(String packageName, CharSequence title, Drawable icon) {
+ this.packageName = packageName;
+ this.title = title;
+ this.icon = icon;
+ }
+
+ @Override
+ public int compareTo(PackageItem another) {
+ int result = title.toString().compareToIgnoreCase(another.title.toString());
+ return result != 0 ? result : packageName.compareTo(another.packageName);
+ }
+ }
+
+ public PackageListAdapter(Context context) {
+ mPm = context.getPackageManager();
+ mInflater = LayoutInflater.from(context);
+ reloadList();
+ }
+
+ @Override
+ public int getCount() {
+ synchronized (mInstalledPackages) {
+ return mInstalledPackages.size();
+ }
+ }
+
+ @Override
+ public PackageItem getItem(int position) {
+ synchronized (mInstalledPackages) {
+ return mInstalledPackages.get(position);
+ }
+ }
+
+ @Override
+ public long getItemId(int position) {
+ synchronized (mInstalledPackages) {
+ // packageName is guaranteed to be unique in mInstalledPackages
+ return mInstalledPackages.get(position).packageName.hashCode();
+ }
+ }
+
+ @Override
+ public View getView(int position, View convertView, ViewGroup parent) {
+ ViewHolder holder;
+ if (convertView != null) {
+ holder = (ViewHolder) convertView.getTag();
+ } else {
+ convertView = mInflater.inflate(R.layout.applist_preference_icon, null, false);
+ holder = new ViewHolder();
+ convertView.setTag(holder);
+ holder.title = (TextView) convertView.findViewById(com.android.internal.R.id.title);
+ holder.summary = (TextView) convertView.findViewById(com.android.internal.R.id.summary);
+ holder.icon = (ImageView) convertView.findViewById(R.id.icon);
+ }
+
+ PackageItem applicationInfo = getItem(position);
+ holder.title.setText(applicationInfo.title);
+ holder.icon.setImageDrawable(applicationInfo.icon);
+
+ boolean needSummary = applicationInfo.activityTitles.size() > 0;
+ if (applicationInfo.activityTitles.size() == 1) {
+ if (TextUtils.equals(applicationInfo.title, applicationInfo.activityTitles.first())) {
+ needSummary = false;
+ }
+ }
+
+ if (needSummary) {
+ holder.summary.setText(TextUtils.join(", ", applicationInfo.activityTitles));
+ holder.summary.setVisibility(View.VISIBLE);
+ } else {
+ holder.summary.setVisibility(View.GONE);
+ }
+
+ return convertView;
+ }
+
+ private void reloadList() {
+ mInstalledPackages.clear();
+ new Thread(this).start();
+ }
+
+ @Override
+ public void run() {
+ final Intent mainIntent = new Intent(Intent.ACTION_MAIN, null);
+ mainIntent.addCategory(Intent.CATEGORY_LAUNCHER);
+ List installedAppsInfo = mPm.queryIntentActivities(mainIntent, 0);
+
+ for (ResolveInfo info : installedAppsInfo) {
+ ApplicationInfo appInfo = info.activityInfo.applicationInfo;
+ final PackageItem item = new PackageItem(appInfo.packageName,
+ appInfo.loadLabel(mPm), appInfo.loadIcon(mPm));
+ item.activityTitles.add(info.loadLabel(mPm));
+ mHandler.obtainMessage(0, item).sendToTarget();
+ }
+
+ for (String packageName : PACKAGE_WHITELIST) {
+ try {
+ ApplicationInfo appInfo = mPm.getApplicationInfo(packageName, 0);
+ final PackageItem item = new PackageItem(appInfo.packageName,
+ appInfo.loadLabel(mPm), appInfo.loadIcon(mPm));
+ mHandler.obtainMessage(0, item).sendToTarget();
+ } catch (PackageManager.NameNotFoundException ignored) {
+ // package not present, so nothing to add -> ignore it
+ }
+ }
+ }
+
+ private static class ViewHolder {
+ TextView title;
+ TextView summary;
+ ImageView icon;
+ }
+}