/*
 * Copyright (C) 2006 The Android Open Source 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.android.settings;

import com.android.settings.R;

import android.app.ActivityManager;
import android.app.Dialog;
import android.app.ProgressDialog;
import android.app.TabActivity;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.SharedPreferences;
import android.content.pm.ApplicationInfo;
import android.content.pm.IPackageStatsObserver;
import android.content.pm.PackageManager;
import android.content.pm.PackageStats;
import android.content.pm.PackageManager.NameNotFoundException;
import android.content.res.Configuration;
import android.content.res.Resources;
import android.graphics.drawable.Drawable;
import android.net.Uri;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.os.SystemClock;
import android.text.format.Formatter;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.view.ViewGroup;
import android.view.Window;
import android.widget.AdapterView;
import android.widget.BaseAdapter;
import android.widget.Filter;
import android.widget.Filterable;
import android.widget.ImageView;
import android.widget.ListView;
import android.widget.TabHost;
import android.widget.TextView;
import android.widget.AdapterView.OnItemClickListener;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.text.Collator;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.TreeMap;
import java.util.concurrent.CountDownLatch;

/**
 * Activity to pick an application that will be used to display installation information and
 * options to uninstall/delete user data for system applications. This activity
 * can be launched through Settings or via the ACTION_MANAGE_PACKAGE_STORAGE
 * intent.
 * 
 * Initially a compute in progress message is displayed while the application retrieves
 * the list of application information from the PackageManager. The size information
 * for each package is refreshed to the screen. The resource (app description and
 * icon) information for each package is not available yet, so some default values for size
 * icon and descriptions are used initially. Later the resource information for each 
 * application is retrieved and dynamically updated on the screen.
 *  
 * A Broadcast receiver registers for package additions or deletions when the activity is
 * in focus. If the user installs or deletes packages when the activity has focus, the receiver
 * gets notified and proceeds to add/delete these packages from the list on the screen.
 * This is an unlikely scenario but could happen. The entire list gets created every time
 * the activity's onStart gets invoked. This is to avoid having the receiver for the entire
 * life cycle of the application.
 *  
 * The applications can be sorted either alphabetically or 
 * based on size (descending).  If this activity gets launched under low memory
 * situations (a low memory notification dispatches intent 
 * ACTION_MANAGE_PACKAGE_STORAGE) the list is sorted per size.
 *  
 * If the user selects an application, extended info (like size, uninstall/clear data options,
 * permissions info etc.,) is displayed via the InstalledAppDetails activity.
 */
public class ManageApplications extends TabActivity implements
        OnItemClickListener, DialogInterface.OnCancelListener,
        TabHost.TabContentFactory,
        TabHost.OnTabChangeListener {
    // TAG for this activity
    private static final String TAG = "ManageApplications";
    private static final String PREFS_NAME = "ManageAppsInfo.prefs";
    private static final String PREF_DISABLE_CACHE = "disableCache";
    
    // Log information boolean
    private boolean localLOGV = false;
    private static final boolean DEBUG_SIZE = false;
    private static final boolean DEBUG_TIME = false;
    
    // attributes used as keys when passing values to InstalledAppDetails activity
    public static final String APP_PKG_NAME = "pkg";
    public static final String APP_CHG = "chg";
    
    // attribute name used in receiver for tagging names of added/deleted packages
    private static final String ATTR_PKG_NAME="p";
    private static final String ATTR_PKGS="ps";
    private static final String ATTR_STATS="ss";
    private static final String ATTR_SIZE_STRS="fs";
    
    private static final String ATTR_GET_SIZE_STATUS="passed";
    private static final String ATTR_PKG_STATS="s";
    private static final String ATTR_PKG_SIZE_STR="f";
    
    // constant value that can be used to check return code from sub activity.
    private static final int INSTALLED_APP_DETAILS = 1;
    
    // sort order that can be changed through the menu can be sorted alphabetically
    // or size(descending)
    private static final int MENU_OPTIONS_BASE = 0;
    // Filter options used for displayed list of applications
    public static final int FILTER_APPS_ALL = MENU_OPTIONS_BASE + 0;
    public static final int FILTER_APPS_RUNNING = MENU_OPTIONS_BASE + 1;
    public static final int FILTER_APPS_THIRD_PARTY = MENU_OPTIONS_BASE + 2;
    public static final int FILTER_APPS_SDCARD = MENU_OPTIONS_BASE + 3;

    public static final int SORT_ORDER_ALPHA = MENU_OPTIONS_BASE + 4;
    public static final int SORT_ORDER_SIZE = MENU_OPTIONS_BASE + 5;
    // sort order
    private int mSortOrder = SORT_ORDER_ALPHA;
    // Filter value
    private int mFilterApps = FILTER_APPS_THIRD_PARTY;
    
    // Custom Adapter used for managing items in the list
    private AppInfoAdapter mAppInfoAdapter;
    
    // messages posted to the handler
    private static final int HANDLER_MESSAGE_BASE = 0;
    private static final int INIT_PKG_INFO = HANDLER_MESSAGE_BASE+1;
    private static final int COMPUTE_BULK_SIZE = HANDLER_MESSAGE_BASE+2;
    private static final int REMOVE_PKG = HANDLER_MESSAGE_BASE+3;
    private static final int REORDER_LIST = HANDLER_MESSAGE_BASE+4;
    private static final int ADD_PKG_START = HANDLER_MESSAGE_BASE+5;
    private static final int ADD_PKG_DONE = HANDLER_MESSAGE_BASE+6;
    private static final int REFRESH_LABELS = HANDLER_MESSAGE_BASE+7;
    private static final int REFRESH_DONE = HANDLER_MESSAGE_BASE+8;
    private static final int NEXT_LOAD_STEP = HANDLER_MESSAGE_BASE+9;
    private static final int COMPUTE_END = HANDLER_MESSAGE_BASE+10;
    private static final int REFRESH_ICONS = HANDLER_MESSAGE_BASE+11;
    
    // observer object used for computing pkg sizes
    private PkgSizeObserver mObserver;
    // local handle to PackageManager
    private PackageManager mPm;
    // Broadcast Receiver object that receives notifications for added/deleted
    // packages
    private PackageIntentReceiver mReceiver;
    // atomic variable used to track if computing pkg sizes is in progress. should be volatile?
    
    private boolean mComputeSizesFinished = false;
    // default icon thats used when displaying applications initially before resource info is
    // retrieved
    private static Drawable mDefaultAppIcon;
    
    // temporary dialog displayed while the application info loads
    private static final int DLG_BASE = 0;
    private static final int DLG_LOADING = DLG_BASE + 1;
    
    // Size resource used for packages whose size computation failed for some reason
    private CharSequence mInvalidSizeStr;
    private CharSequence mComputingSizeStr;
    
    // map used to store list of added and removed packages. Immutable Boolean
    // variables indicate if a package has been added or removed. If a package is
    // added or deleted multiple times a single entry with the latest operation will
    // be recorded in the map.
    private Map<String, Boolean> mAddRemoveMap;
    
    // layout inflater object used to inflate views
    private LayoutInflater mInflater;
    
    // invalid size value used initially and also when size retrieval through PackageManager
    // fails for whatever reason
    private static final int SIZE_INVALID = -1;
    
    // debug boolean variable to test delays from PackageManager API's
    private boolean DEBUG_PKG_DELAY = false;
    
    // Thread to load resources
    ResourceLoaderThread mResourceThread;
    private TaskRunner mSizeComputor;
    
    private String mCurrentPkgName;
    
    // Cache application attributes
    private AppInfoCache mCache = new AppInfoCache();
    
    // Boolean variables indicating state
    private boolean mLoadLabelsFinished = false;
    private boolean mSizesFirst = false;
    // ListView used to display list
    private ListView mListView;
    // State variables used to figure out menu options and also
    // initiate the first computation and loading of resources
    private boolean mJustCreated = true;
    private boolean mFirst = false;
    private long mLoadTimeStart;
    private boolean mSetListViewLater = true;
    
    /*
     * Handler class to handle messages for various operations.
     * Most of the operations that effect Application related data
     * are posted as messages to the handler to avoid synchronization
     * when accessing these structures.
     * 
     * When the size retrieval gets kicked off for the first time, a COMPUTE_PKG_SIZE_START
     * message is posted to the handler which invokes the getSizeInfo for the pkg at index 0.
     * 
     * When the PackageManager's asynchronous call back through
     * PkgSizeObserver.onGetStatsCompleted gets invoked, the application resources like
     * label, description, icon etc., are loaded in the same thread and these values are
     * set on the observer.  The observer then posts a COMPUTE_PKG_SIZE_DONE message
     * to the handler.  This information is updated on the AppInfoAdapter associated with
     * the list view of this activity and size info retrieval is initiated for the next package as 
     * indicated by mComputeIndex.
     * 
     * When a package gets added while the activity has focus, the PkgSizeObserver posts
     * ADD_PKG_START message to the handler.  If the computation is not in progress, the size
     * is retrieved for the newly added package through the observer object and the newly
     * installed app info is updated on the screen.  If the computation is still in progress
     * the package is added to an internal structure and action deferred till the computation
     * is done for all the packages.
     * 
     * When a package gets deleted, REMOVE_PKG is posted to the handler
     * if computation is not in progress (as indicated by
     * mDoneIniting), the package is deleted from the displayed list of apps.  If computation is
     * still in progress the package is added to an internal structure and action deferred till
     * the computation is done for all packages.
     * 
     * When the sizes of all packages is computed, the newly
     * added or removed packages are processed in order.
     * If the user changes the order in which these applications are viewed by hitting the
     * menu key, REORDER_LIST message is posted to the handler. this sorts the list
     * of items based on the sort order.
     */
    private Handler mHandler = new Handler() {
        public void handleMessage(Message msg) {
            boolean status;
            long size;
            String formattedSize;
            ApplicationInfo info;
            Bundle data;
            String pkgName = null;
            AppInfo appInfo;
            data = msg.getData();
            if(data != null) {
                pkgName = data.getString(ATTR_PKG_NAME);
            }
            switch (msg.what) {
            case INIT_PKG_INFO:
                if(localLOGV) Log.i(TAG, "Message INIT_PKG_INFO, justCreated = " + mJustCreated);
                List<ApplicationInfo> newList = null;
                if (!mJustCreated) {
                    if (localLOGV) Log.i(TAG, "List already created");
                    // Add or delete newly created packages by comparing lists
                    newList = getInstalledApps(FILTER_APPS_ALL);
                    updateAppList(newList);
                }
                // Retrieve the package list and init some structures
                initAppList(newList, mFilterApps);
                mHandler.sendEmptyMessage(NEXT_LOAD_STEP);
                break;
            case COMPUTE_BULK_SIZE:
                if(localLOGV) Log.i(TAG, "Message COMPUTE_BULK_PKG_SIZE");
                String[] pkgs = data.getStringArray(ATTR_PKGS);
                long[] sizes = data.getLongArray(ATTR_STATS);
                String[] formatted = data.getStringArray(ATTR_SIZE_STRS);
                if(pkgs == null || sizes == null || formatted == null) {
                     Log.w(TAG, "Ignoring message");
                     break;
                }
                mAppInfoAdapter.bulkUpdateSizes(pkgs, sizes, formatted);
                break;
            case COMPUTE_END:
                mComputeSizesFinished = true;
                mFirst = true;
                mHandler.sendEmptyMessage(NEXT_LOAD_STEP);
                break;
            case REMOVE_PKG:
                if(localLOGV) Log.i(TAG, "Message REMOVE_PKG");
                if(pkgName == null) {
                    Log.w(TAG, "Ignoring message:REMOVE_PKG for null pkgName");
                    break;
                }
                if (!mComputeSizesFinished) {
                    Boolean currB = mAddRemoveMap.get(pkgName);
                    if (currB == null || (currB.equals(Boolean.TRUE))) {
                        mAddRemoveMap.put(pkgName, Boolean.FALSE);
                    }
                    break;
                }
                List<String> pkgList = new ArrayList<String>();
                pkgList.add(pkgName);
                mAppInfoAdapter.removeFromList(pkgList);
                break;
            case REORDER_LIST:
                if(localLOGV) Log.i(TAG, "Message REORDER_LIST");
                int menuOption = msg.arg1;
                if((menuOption == SORT_ORDER_ALPHA) || 
                        (menuOption == SORT_ORDER_SIZE)) {
                    // Option to sort list
                    if (menuOption != mSortOrder) {
                        mSortOrder = menuOption;
                        if (localLOGV) Log.i(TAG, "Changing sort order to "+mSortOrder);
                        mAppInfoAdapter.sortList(mSortOrder);
                    }
                } else if(menuOption != mFilterApps) {
                    // Option to filter list
                    mFilterApps = menuOption;
                    boolean ret = mAppInfoAdapter.resetAppList(mFilterApps);
                    if(!ret) {
                        // Reset cache
                        mFilterApps = FILTER_APPS_ALL;
                        mHandler.sendEmptyMessage(INIT_PKG_INFO);
                        sendMessageToHandler(REORDER_LIST, menuOption);
                    }
                }
                break;
            case ADD_PKG_START:
                if(localLOGV) Log.i(TAG, "Message ADD_PKG_START");
                if(pkgName == null) {
                    Log.w(TAG, "Ignoring message:ADD_PKG_START for null pkgName");
                    break;
                }
                if (!mComputeSizesFinished || !mLoadLabelsFinished) {
                    Boolean currB = mAddRemoveMap.get(pkgName);
                    if (currB == null || (currB.equals(Boolean.FALSE))) {
                        mAddRemoveMap.put(pkgName, Boolean.TRUE);
                    }
                    break;
                }
                try {
                    info = mPm.getApplicationInfo(pkgName, 0);
                } catch (NameNotFoundException e) {
                    Log.w(TAG, "Couldnt find application info for:"+pkgName);
                    break;
                }
                mObserver.invokeGetSizeInfo(pkgName);
                break;
            case ADD_PKG_DONE:
                if(localLOGV) Log.i(TAG, "Message ADD_PKG_DONE");
                if(pkgName == null) {
                    Log.w(TAG, "Ignoring message:ADD_PKG_START for null pkgName");
                    break;
                }
                status = data.getBoolean(ATTR_GET_SIZE_STATUS);
                if (status) {
                    size = data.getLong(ATTR_PKG_STATS);
                    formattedSize = data.getString(ATTR_PKG_SIZE_STR);
                    if (!mAppInfoAdapter.isInstalled(pkgName)) {
                        mAppInfoAdapter.addToList(pkgName, size, formattedSize);
                    } else {
                        mAppInfoAdapter.updatePackage(pkgName, size, formattedSize);
                    }
                }
                break;
            case REFRESH_LABELS:
                Map<String, CharSequence> labelMap = (Map<String, CharSequence>) msg.obj;
                if (labelMap != null) {
                    mAppInfoAdapter.bulkUpdateLabels(labelMap);
                }
                break;
            case REFRESH_ICONS:
                Map<String, Drawable> iconMap = (Map<String, Drawable>) msg.obj;
                if (iconMap != null) {
                    mAppInfoAdapter.bulkUpdateIcons(iconMap);
                }
                break;
            case REFRESH_DONE:
                mLoadLabelsFinished = true;
                mHandler.sendEmptyMessage(NEXT_LOAD_STEP);
                break;
            case NEXT_LOAD_STEP:
                if (!mCache.isEmpty() && mSetListViewLater) {
                    if (localLOGV) Log.i(TAG, "Using cache to populate list view");
                    initListView();
                    mSetListViewLater = false;
                    mFirst = true;
                }
                if (mComputeSizesFinished && mLoadLabelsFinished) {
                    doneLoadingData();
                    // Check for added/removed packages
                    Set<String> keys =  mAddRemoveMap.keySet();
                    for (String key : keys) {
                        if (mAddRemoveMap.get(key) == Boolean.TRUE) {
                            // Add the package
                            updatePackageList(Intent.ACTION_PACKAGE_ADDED, key);
                        } else {
                            // Remove the package
                            updatePackageList(Intent.ACTION_PACKAGE_REMOVED, key);
                        }
                    }
                    mAddRemoveMap.clear();
                } else if (!mComputeSizesFinished && !mLoadLabelsFinished) {
                     // Either load the package labels or initiate get size info
                    if (mSizesFirst) {
                        initComputeSizes();
                    } else {
                        initResourceThread();
                    }
                } else {
                    if (mSetListViewLater) {
                        if (localLOGV) Log.i(TAG, "Initing list view for very first time");
                        initListView();
                        mSetListViewLater = false;
                    }
                    if (!mComputeSizesFinished) {
                        initComputeSizes();
                    } else if (!mLoadLabelsFinished) {
                        initResourceThread();
                    }
                }
                break;
            default:
                break;
            }
        }
    };
    
    private void initListView() {
       // Create list view from the adapter here. Wait till the sort order
        // of list is defined. its either by label or by size. So atleast one of the
        // first steps should have been completed before the list gets filled.
        mAppInfoAdapter.sortBaseList(mSortOrder);
        if (mJustCreated) {
            // Set the adapter here.
            mJustCreated = false;
            mListView.setAdapter(mAppInfoAdapter);
            dismissLoadingMsg();
        }
    }

   class SizeObserver extends IPackageStatsObserver.Stub {
       private CountDownLatch mCount;
       PackageStats stats;
       boolean succeeded;
       
       public void invokeGetSize(String packageName, CountDownLatch count) {
           mCount = count;
           mPm.getPackageSizeInfo(packageName, this);
       }
       
        public void onGetStatsCompleted(PackageStats pStats, boolean pSucceeded) {
            succeeded = pSucceeded;
            stats = pStats;
            mCount.countDown();
        }
    }

    class TaskRunner extends Thread {
        private List<ApplicationInfo> mPkgList;
        private SizeObserver mSizeObserver;
        private static final int END_MSG = COMPUTE_END;
        private static final int SEND_PKG_SIZES = COMPUTE_BULK_SIZE;
        volatile boolean abort = false;
        static final int MSG_PKG_SIZE = 8;
        
        TaskRunner(List<ApplicationInfo> appList) {
           mPkgList = appList;
           mSizeObserver = new SizeObserver();
           start();
        }
        
        public void setAbort() {
            abort = true;
        }

        public void run() {
            long startTime;
            if (DEBUG_SIZE || DEBUG_TIME) {
               startTime =  SystemClock.elapsedRealtime();
            }
            int size = mPkgList.size();
            int numMsgs = size / MSG_PKG_SIZE;
            if (size > (numMsgs * MSG_PKG_SIZE)) {
                numMsgs++;
            }
            int endi = 0;
            for (int j = 0; j < size; j += MSG_PKG_SIZE) {
                long sizes[];
                String formatted[];
                String packages[];
                endi += MSG_PKG_SIZE;
                if (endi > size) {
                    endi = size;
                }
                sizes = new long[endi-j];
                formatted = new String[endi-j];
                packages = new String[endi-j];
                for (int i = j; i < endi; i++) {
                    if (abort) {
                        // Exit if abort has been set.
                        break;
                    }
                    CountDownLatch count = new CountDownLatch(1);
                    String packageName = mPkgList.get(i).packageName;
                    mSizeObserver.invokeGetSize(packageName, count);
                    try {
                        count.await();
                    } catch (InterruptedException e) {
                        Log.i(TAG, "Failed computing size for pkg : "+packageName);
                    }
                    // Process the package statistics
                    PackageStats pStats = mSizeObserver.stats;
                    boolean succeeded = mSizeObserver.succeeded;
                    long total;
                    if(succeeded && pStats != null) {
                        total = getTotalSize(pStats);
                    } else {
                        total = SIZE_INVALID;
                    }
                    sizes[i-j] = total;
                    formatted[i-j] = getSizeStr(total).toString();
                    packages[i-j] = packageName;
                }
                // Post update message
                Bundle data = new Bundle();
                data.putStringArray(ATTR_PKGS, packages);
                data.putLongArray(ATTR_STATS, sizes);
                data.putStringArray(ATTR_SIZE_STRS, formatted);
                Message msg = mHandler.obtainMessage(SEND_PKG_SIZES, data);
                msg.setData(data);
                mHandler.sendMessage(msg);
            }
            if (DEBUG_SIZE || DEBUG_TIME) Log.i(TAG, "Took "+
                    (SystemClock.elapsedRealtime() - startTime)+
                    " ms to compute sizes of all packages ");
            mHandler.sendEmptyMessage(END_MSG);
        }
    }
    
    /*
     * This method compares the current cache against a new list of
     * installed applications and tries to update the list with add or remove
     * messages.
     */
    private boolean updateAppList(List<ApplicationInfo> newList) {
        if ((newList == null) || mCache.isEmpty()) {
            return false;
        }
        Set<String> existingList = new HashSet<String>();
        boolean ret = false;
        // Loop over new list and find out common elements between old and new lists
        int N = newList.size();
        for (int i = (N-1); i >= 0; i--) {
            ApplicationInfo info = newList.get(i);
            String pkgName = info.packageName;
            AppInfo aInfo = mCache.getEntry(pkgName);
            if (aInfo != null) {
                existingList.add(pkgName);
            } else {
                // New package. update info by refreshing
                if (localLOGV) Log.i(TAG, "New pkg :"+pkgName+" installed when paused");
                updatePackageList(Intent.ACTION_PACKAGE_ADDED, pkgName);
                // Remove from current list so that the newly added package can
                // be handled later
                newList.remove(i);
                ret = true;
            }
        }

        // Loop over old list and figure out stale entries
        List<String> deletedList = null;
        Set<String> staleList = mCache.getPkgList();
        for (String pkgName : staleList) {
            if (!existingList.contains(pkgName)) {
                if (localLOGV) Log.i(TAG, "Pkg :"+pkgName+" deleted when paused");
                if (deletedList == null) {
                    deletedList = new ArrayList<String>();
                    deletedList.add(pkgName);
                }
                ret = true;
            }
        }
        // Delete right away
        if (deletedList != null) {
            if (localLOGV) Log.i(TAG, "Deleting right away");
            mAppInfoAdapter.removeFromList(deletedList);
        }
        return ret;
    }
    
    private void doneLoadingData() {
        setProgressBarIndeterminateVisibility(false);
    }
    
    List<ApplicationInfo> getInstalledApps(int filterOption) {
        List<ApplicationInfo> installedAppList = mPm.getInstalledApplications(
                PackageManager.GET_UNINSTALLED_PACKAGES);
        if (installedAppList == null) {
            return new ArrayList<ApplicationInfo> ();
        }
        if (filterOption == FILTER_APPS_SDCARD) {
            List<ApplicationInfo> appList =new ArrayList<ApplicationInfo> ();
            for (ApplicationInfo appInfo : installedAppList) {
                if ((appInfo.flags & ApplicationInfo.FLAG_EXTERNAL_STORAGE) != 0) {
                    // App on sdcard
                    appList.add(appInfo);
                }
            }
            return appList;
        } else if (filterOption == FILTER_APPS_THIRD_PARTY) {
            List<ApplicationInfo> appList =new ArrayList<ApplicationInfo> ();
            for (ApplicationInfo appInfo : installedAppList) {
                boolean flag = false;
                if ((appInfo.flags & ApplicationInfo.FLAG_UPDATED_SYSTEM_APP) != 0) {
                    // Updated system app
                    flag = true;
                } else if ((appInfo.flags & ApplicationInfo.FLAG_SYSTEM) == 0) {
                    // Non-system app
                    flag = true;
                }
                if (flag) {
                    appList.add(appInfo);
                }
            }
            return appList;
        } else if (filterOption == FILTER_APPS_RUNNING) {
            List<ApplicationInfo> appList =new ArrayList<ApplicationInfo> ();
            List<ActivityManager.RunningAppProcessInfo> procList = getRunningAppProcessesList();
            if ((procList == null) || (procList.size() == 0)) {
                return appList;
            }
            // Retrieve running processes from ActivityManager
            for (ActivityManager.RunningAppProcessInfo appProcInfo : procList) {
                if ((appProcInfo != null)  && (appProcInfo.pkgList != null)){
                    int size = appProcInfo.pkgList.length;
                    for (int i = 0; i < size; i++) {
                        ApplicationInfo appInfo = null;
                        try {
                            appInfo = mPm.getApplicationInfo(appProcInfo.pkgList[i], 
                                    PackageManager.GET_UNINSTALLED_PACKAGES);
                        } catch (NameNotFoundException e) {
                           Log.w(TAG, "Error retrieving ApplicationInfo for pkg:"+appProcInfo.pkgList[i]);
                           continue;
                        }
                        if(appInfo != null) {
                            appList.add(appInfo);
                        }
                    }
                }
            }
            return appList;
        } else {
            return installedAppList;
        }
    }

    private static boolean matchFilter(boolean filter, Map<String, String> filterMap, String pkg) {
        boolean add = true;
        if (filter) {
            if (filterMap == null || !filterMap.containsKey(pkg)) {
                add = false;
            }
        }
        return add;
    }
    
    /*
     * Utility method used to figure out list of apps based on filterOption
     * If the framework supports an additional flag to indicate running apps
     *  we can get away with some code here.
     */
    List<ApplicationInfo> getFilteredApps(List<ApplicationInfo> pAppList, int filterOption, boolean filter,
            Map<String, String> filterMap) {
        List<ApplicationInfo> retList = new ArrayList<ApplicationInfo>();
        if(pAppList == null) {
            return retList;
        }
        if (filterOption == FILTER_APPS_SDCARD) {
            for (ApplicationInfo appInfo : pAppList) {
                boolean flag = false;
                if ((appInfo.flags & ApplicationInfo.FLAG_EXTERNAL_STORAGE) != 0) {
                    // App on sdcard
                    flag = true;
                }
                if (flag) {
                    if (matchFilter(filter, filterMap, appInfo.packageName)) {
                        retList.add(appInfo);
                    }
                }
            }
            return retList;
        } else if (filterOption == FILTER_APPS_THIRD_PARTY) {
            for (ApplicationInfo appInfo : pAppList) {
                boolean flag = false;
                if ((appInfo.flags & ApplicationInfo.FLAG_UPDATED_SYSTEM_APP) != 0) {
                    // Updated system app
                    flag = true;
                } else if ((appInfo.flags & ApplicationInfo.FLAG_SYSTEM) == 0) {
                    // Non-system app
                    flag = true;
                }
                if (flag) {
                    if (matchFilter(filter, filterMap, appInfo.packageName)) {
                        retList.add(appInfo);
                    }
                }
            }
            return retList;
        } else if (filterOption == FILTER_APPS_RUNNING) {
            List<ActivityManager.RunningAppProcessInfo> procList = getRunningAppProcessesList();
            if ((procList == null) || (procList.size() == 0)) {
                return retList;
            }
            // Retrieve running processes from ActivityManager
            HashMap<String, ActivityManager.RunningAppProcessInfo> runningMap = 
                new HashMap<String, ActivityManager.RunningAppProcessInfo>();
            for (ActivityManager.RunningAppProcessInfo appProcInfo : procList) {
                if ((appProcInfo != null)  && (appProcInfo.pkgList != null)){
                    int size = appProcInfo.pkgList.length;
                    for (int i = 0; i < size; i++) {
                        runningMap.put(appProcInfo.pkgList[i], appProcInfo);
                    }
                }
            }
            // Query list to find running processes in current list
            for (ApplicationInfo appInfo : pAppList) {
                if (runningMap.get(appInfo.packageName) != null) {
                    if (matchFilter(filter, filterMap, appInfo.packageName)) {
                        retList.add(appInfo);
                    }
                }
            }
            return retList;
        } else {
            for (ApplicationInfo appInfo : pAppList) {
                if (matchFilter(filter, filterMap, appInfo.packageName)) {
                    retList.add(appInfo);
                }
            }
            return retList;
        }
    }

    private List<ActivityManager.RunningAppProcessInfo> getRunningAppProcessesList() {
        ActivityManager am = (ActivityManager)getSystemService(Context.ACTIVITY_SERVICE);
        return am.getRunningAppProcesses();
    }

     // Some initialization code used when kicking off the size computation
    private void initAppList(List<ApplicationInfo> appList, int filterOption) {
        setProgressBarIndeterminateVisibility(true);
        mComputeSizesFinished = false;
        mLoadLabelsFinished = false;
        // Initialize lists
        mAddRemoveMap = new TreeMap<String, Boolean>();
        mAppInfoAdapter.initMapFromList(appList, filterOption);
    }

    // Utility method to start a thread to read application labels and icons
    private void initResourceThread() {
        if ((mResourceThread != null) && mResourceThread.isAlive()) {
            mResourceThread.setAbort();
        }
        mResourceThread = new ResourceLoaderThread();
        List<ApplicationInfo> appList = mAppInfoAdapter.getBaseAppList();
        if ((appList != null) && (appList.size()) > 0) {
            mResourceThread.loadAllResources(appList);
        }
    }

    private void initComputeSizes() {
         // Initiate compute package sizes
        if (localLOGV) Log.i(TAG, "Initiating compute sizes for first time");
        if ((mSizeComputor != null) && (mSizeComputor.isAlive())) {
            mSizeComputor.setAbort();
        }
        List<ApplicationInfo> appList = mAppInfoAdapter.getBaseAppList();
        if ((appList != null) && (appList.size()) > 0) {
            mSizeComputor = new TaskRunner(appList);
        } else {
            mComputeSizesFinished = true;
        }
    }
    
    // internal structure used to track added and deleted packages when
    // the activity has focus
    static class AddRemoveInfo {
        String pkgName;
        boolean add;
        public AddRemoveInfo(String pPkgName, boolean pAdd) {
            pkgName = pPkgName;
            add = pAdd;
        }
    }
    
    class ResourceLoaderThread extends Thread {
        List<ApplicationInfo> mAppList;
        volatile boolean abort = false;
        static final int MSG_PKG_SIZE = 8;
        
        public void setAbort() {
            abort = true;
        }
        void loadAllResources(List<ApplicationInfo> appList) {
            mAppList = appList;
            start();
        }

        public void run() {
            long start;
            if (DEBUG_TIME) {
                start = SystemClock.elapsedRealtime();
            }
            int imax;
            if(mAppList == null || (imax = mAppList.size()) <= 0) {
                Log.w(TAG, "Empty or null application list");
            } else {
                int size = mAppList.size();
                int numMsgs = size / MSG_PKG_SIZE;
                if (size > (numMsgs * MSG_PKG_SIZE)) {
                    numMsgs++;
                }
                int endi = 0;
                for (int j = 0; j < size; j += MSG_PKG_SIZE) {
                    Map<String, CharSequence> map = new HashMap<String, CharSequence>();
                    endi += MSG_PKG_SIZE;
                    if (endi > size) {
                        endi = size;
                    }
                    for (int i = j; i < endi; i++) {
                        if (abort) {
                            // Exit if abort has been set.
                            break;
                        }
                        ApplicationInfo appInfo = mAppList.get(i);
                        map.put(appInfo.packageName, appInfo.loadLabel(mPm));
                    }
                    // Post update message
                    Message msg = mHandler.obtainMessage(REFRESH_LABELS);
                    msg.obj = map;
                    mHandler.sendMessage(msg);
                }
                Message doneMsg = mHandler.obtainMessage(REFRESH_DONE);
                mHandler.sendMessage(doneMsg);
                if (DEBUG_TIME) Log.i(TAG, "Took "+(SystemClock.elapsedRealtime()-start)+
                        " ms to load app labels");
                long startIcons;
                if (DEBUG_TIME) {
                    startIcons = SystemClock.elapsedRealtime();
                }
                Map<String, Drawable> map = new HashMap<String, Drawable>();
                for (int i = (imax-1); i >= 0; i--) {
                    if (abort) {
                        return;
                    }
                    ApplicationInfo appInfo = mAppList.get(i);
                    map.put(appInfo.packageName, appInfo.loadIcon(mPm));
                }
                Message msg = mHandler.obtainMessage(REFRESH_ICONS);
                msg.obj = map;
                mHandler.sendMessage(msg);
                if (DEBUG_TIME) Log.i(TAG, "Took "+(SystemClock.elapsedRealtime()-startIcons)+" ms to load app icons");
            }
            if (DEBUG_TIME) Log.i(TAG, "Took "+(SystemClock.elapsedRealtime()-start)+" ms to load app resources");
        }
    }
    
    /* Internal class representing an application or packages displayable attributes
     * 
     */
    static private class AppInfo {
        public String pkgName;
        int index;
        public CharSequence appName;
        public Drawable appIcon;
        public CharSequence appSize;
        long size;

        public void refreshIcon(Drawable icon) {
            if (icon == null) {
                return;
            }
            appIcon = icon;
        }
        public void refreshLabel(CharSequence label) {
            if (label == null) {
                return;
            }
            appName = label;
        }

        public AppInfo(String pName, int pIndex, CharSequence aName,
                long pSize,
                CharSequence pSizeStr) {
            this(pName, pIndex, aName, mDefaultAppIcon, pSize, pSizeStr);
        }
 
        public AppInfo(String pName, int pIndex, CharSequence aName, Drawable aIcon,
                long pSize,
                CharSequence pSizeStr) {
            index = pIndex;
            pkgName = pName;
            appName = aName;
            appIcon = aIcon;
            size = pSize;
            appSize = pSizeStr;
        }
 
        public boolean setSize(long newSize, String formattedSize) {
            if (size != newSize) {
                size = newSize;
                appSize = formattedSize;
                return true;
            }
            return false;
        }
    }
    
    private long getTotalSize(PackageStats ps) {
        if (ps != null) {
            return ps.cacheSize+ps.codeSize+ps.dataSize;
        }
        return SIZE_INVALID;
    }

    private CharSequence getSizeStr(long size) {
        CharSequence appSize = null;
        if (size == SIZE_INVALID) {
             return mInvalidSizeStr;
        }
        appSize = Formatter.formatFileSize(ManageApplications.this, size);
        return appSize;
    }

    // View Holder used when displaying views
    static class AppViewHolder {
        TextView appName;
        ImageView appIcon;
        TextView appSize;
    }
    
    /* 
     * Custom adapter implementation for the ListView
     * This adapter maintains a map for each displayed application and its properties
     * An index value on each AppInfo object indicates the correct position or index
     * in the list. If the list gets updated dynamically when the user is viewing the list of
     * applications, we need to return the correct index of position. This is done by mapping
     * the getId methods via the package name into the internal maps and indices.
     * The order of applications in the list is mirrored in mAppLocalList
     */
    class AppInfoAdapter extends BaseAdapter implements Filterable {   
        private List<ApplicationInfo> mAppList;
        private List<ApplicationInfo> mAppLocalList;
        private Map<String, String> mFilterMap = new HashMap<String, String>();
        AlphaComparator mAlphaComparator = new AlphaComparator();
        SizeComparator mSizeComparator = new SizeComparator();
        private Filter mAppFilter = new AppFilter();
        final private Object mFilterLock = new Object();
        private Map<String, String> mCurrentFilterMap = null;

        private void generateFilterListLocked(List<ApplicationInfo> list) {
            mAppLocalList = new ArrayList<ApplicationInfo>(list);
            synchronized(mFilterLock) {
                for (ApplicationInfo info : mAppLocalList) {
                    String label = info.packageName;
                    AppInfo aInfo = mCache.getEntry(info.packageName);
                    if ((aInfo != null) && (aInfo.appName != null)) {
                        label = aInfo.appName.toString();
                    }
                    mFilterMap.put(info.packageName, label.toLowerCase());
                }
            }
        }

        private void addFilterListLocked(int newIdx, ApplicationInfo info, CharSequence pLabel) {
            mAppLocalList.add(newIdx, info);
            synchronized (mFilterLock) {
                String label = info.packageName;
                if (pLabel != null) {
                    label = pLabel.toString();
                }
                mFilterMap.put(info.packageName, label.toLowerCase());
            }
        }

        private boolean removeFilterListLocked(String removePkg) {
            // Remove from filtered list
            int N = mAppLocalList.size();
            int i;
            for (i = (N-1); i >= 0; i--) {
                ApplicationInfo info = mAppLocalList.get(i);
                if (info.packageName.equalsIgnoreCase(removePkg)) {
                    if (localLOGV) Log.i(TAG, "Removing " + removePkg + " from local list");
                    mAppLocalList.remove(i);
                    synchronized (mFilterLock) {
                        mFilterMap.remove(removePkg);
                    }
                    return true;
                }
            }
            return false;
        }

        private void reverseGenerateList() {
            generateFilterListLocked(getFilteredApps(mAppList, mFilterApps, mCurrentFilterMap!= null, mCurrentFilterMap));
            sortListInner(mSortOrder);
        }

        // Make sure the cache or map contains entries for all elements
        // in appList for a valid sort.
        public void initMapFromList(List<ApplicationInfo> pAppList, int filterOption) {
            boolean notify = false;
            List<ApplicationInfo> appList = null;
            if (pAppList == null) {
                // Just refresh the list
                appList = mAppList;
            } else {
                mAppList = new ArrayList<ApplicationInfo>(pAppList);
                appList = pAppList;
                notify = true;
            }
            generateFilterListLocked(getFilteredApps(appList, filterOption, mCurrentFilterMap!= null, mCurrentFilterMap));
            // This loop verifies and creates new entries for new packages in list
            int imax = appList.size();
            for (int i = 0; i < imax; i++) {
                ApplicationInfo info  = appList.get(i);
                AppInfo aInfo = mCache.getEntry(info.packageName);
                if(aInfo == null){
                    aInfo = new AppInfo(info.packageName, i, 
                            info.packageName, -1, mComputingSizeStr);
                    if (localLOGV) Log.i(TAG, "Creating entry pkg:"+info.packageName+" to map");
                    mCache.addEntry(aInfo);
                }
            }
            sortListInner(mSortOrder);
            if (notify) {
                notifyDataSetChanged();
            }
        }
        
        public AppInfoAdapter(Context c, List<ApplicationInfo> appList) {
           mAppList = appList;
        }
        
        public int getCount() {
            return mAppLocalList.size();
        }
        
        public Object getItem(int position) {
            return mAppLocalList.get(position);
        }
        
        public boolean isInstalled(String pkgName) {
            if(pkgName == null) {
                if (localLOGV) Log.w(TAG, "Null pkg name when checking if installed");
                return false;
            }
            for (ApplicationInfo info : mAppList) {
                if (info.packageName.equalsIgnoreCase(pkgName)) {
                    return true;
                }
            }
            return false;
        }

        public ApplicationInfo getApplicationInfo(int position) {
            int imax = mAppLocalList.size();
            if( (position < 0) || (position >= imax)) {
                Log.w(TAG, "Position out of bounds in List Adapter");
                return null;
            }
            return mAppLocalList.get(position);
        }

        public long getItemId(int position) {
            int imax = mAppLocalList.size();
            if( (position < 0) || (position >= imax)) {
                Log.w(TAG, "Position out of bounds in List Adapter");
                return -1;
            }
            AppInfo aInfo = mCache.getEntry(mAppLocalList.get(position).packageName);
            if (aInfo == null) {
                return -1;
            }
            return aInfo.index;
        }
        
        public List<ApplicationInfo> getBaseAppList() {
            return mAppList;
        }
        
        public View getView(int position, View convertView, ViewGroup parent) {
            if (position >= mAppLocalList.size()) {
                Log.w(TAG, "Invalid view position:"+position+", actual size is:"+mAppLocalList.size());
                return null;
            }
            // A ViewHolder keeps references to children views to avoid unnecessary calls
            // to findViewById() on each row.
            AppViewHolder holder;

            // When convertView is not null, we can reuse it directly, there is no need
            // to reinflate it. We only inflate a new View when the convertView supplied
            // by ListView is null.
            if (convertView == null) {
                convertView = mInflater.inflate(R.layout.manage_applications_item, null);

                // Creates a ViewHolder and store references to the two children views
                // we want to bind data to.
                holder = new AppViewHolder();
                holder.appName = (TextView) convertView.findViewById(R.id.app_name);
                holder.appIcon = (ImageView) convertView.findViewById(R.id.app_icon);
                holder.appSize = (TextView) convertView.findViewById(R.id.app_size);
                convertView.setTag(holder);
            } else {
                // Get the ViewHolder back to get fast access to the TextView
                // and the ImageView.
                holder = (AppViewHolder) convertView.getTag();
            }

            // Bind the data efficiently with the holder
            ApplicationInfo appInfo = mAppLocalList.get(position);
            AppInfo mInfo = mCache.getEntry(appInfo.packageName);
            if(mInfo != null) {
                if(mInfo.appName != null) {
                    holder.appName.setText(mInfo.appName);
                }
                if(mInfo.appIcon != null) {
                    holder.appIcon.setImageDrawable(mInfo.appIcon);
                }
                if (mInfo.appSize != null) {
                    holder.appSize.setText(mInfo.appSize);
                }
            } else {
                Log.w(TAG, "No info for package:"+appInfo.packageName+" in property map");
            }
            return convertView;
        }
        
        private void adjustIndex() {
            int imax = mAppLocalList.size();
            for (int i = 0; i < imax; i++) {
                ApplicationInfo info = mAppLocalList.get(i);
                mCache.getEntry(info.packageName).index = i;
            }
        }
        
        public void sortAppList(List<ApplicationInfo> appList, int sortOrder) {
            Collections.sort(appList, getAppComparator(sortOrder));
        }
        
        public void sortBaseList(int sortOrder) {
            if (localLOGV) Log.i(TAG, "Sorting base list based on sortOrder = "+sortOrder);
            sortAppList(mAppList, sortOrder);
            generateFilterListLocked(getFilteredApps(mAppList, mFilterApps, mCurrentFilterMap!= null, mCurrentFilterMap));
            adjustIndex();
        }

        private void sortListInner(int sortOrder) {
            sortAppList(mAppLocalList, sortOrder);
            adjustIndex(); 
        }
        
        public void sortList(int sortOrder) {
            if (localLOGV) Log.i(TAG, "sortOrder = "+sortOrder);
            sortListInner(sortOrder);
            notifyDataSetChanged();
        }
        
        /*
         * Reset the application list associated with this adapter.
         * @param filterOption Sort the list based on this value
         * @param appList the actual application list that is used to reset
         * @return Return a boolean value to indicate inconsistency
         */
        public boolean resetAppList(int filterOption) {
           // Change application list based on filter option
           generateFilterListLocked(getFilteredApps(mAppList, filterOption, mCurrentFilterMap!= null, mCurrentFilterMap));
           // Check for all properties in map before sorting. Populate values from cache
           for(ApplicationInfo applicationInfo : mAppLocalList) {
               AppInfo appInfo = mCache.getEntry(applicationInfo.packageName);
               if(appInfo == null) {
                  Log.i(TAG, " Entry does not exist for pkg:  " + applicationInfo.packageName);
               }
           }
           if (mAppLocalList.size() > 0) {
               sortList(mSortOrder);
           } else {
               notifyDataSetChanged();
           }
           return true;
        }
        
        private Comparator<ApplicationInfo> getAppComparator(int sortOrder) {
            if (sortOrder == SORT_ORDER_ALPHA) {
                return mAlphaComparator;
            }
            return mSizeComparator;
        }

        public void bulkUpdateIcons(Map<String, Drawable> icons) {
            if (icons == null) {
                return;
            }
            Set<String> keys = icons.keySet();
            boolean changed = false;
            for (String key : keys) {
                Drawable ic = icons.get(key);
                if (ic != null) {
                    AppInfo aInfo = mCache.getEntry(key);
                    if (aInfo != null) {
                        aInfo.refreshIcon(ic);
                        changed = true;
                    }
                }
            }
            if (changed) {
                notifyDataSetChanged();
            }
        }

        public void bulkUpdateLabels(Map<String, CharSequence> map) {
            if (map == null) {
                return;
            }
            Set<String> keys = map.keySet();
            boolean changed = false;
            for (String key : keys) {
                CharSequence label = map.get(key);
                AppInfo aInfo = mCache.getEntry(key);
                if (aInfo != null) {
                    aInfo.refreshLabel(label);
                    changed = true;
                }
            }
            if (changed) {
                notifyDataSetChanged();
            }
        }

        private boolean shouldBeInList(int filterOption, ApplicationInfo info) {
            // Match filter here
            if (filterOption == FILTER_APPS_RUNNING) {
                List<ApplicationInfo> runningList = getInstalledApps(FILTER_APPS_RUNNING);
                for (ApplicationInfo running : runningList) {
                    if (running.packageName.equalsIgnoreCase(info.packageName)) {
                        return true;
                    }
                }
            } else if (filterOption == FILTER_APPS_THIRD_PARTY) {
                if ((info.flags & ApplicationInfo.FLAG_SYSTEM) == 0) {
                    return true;
                } else if ((info.flags & ApplicationInfo.FLAG_UPDATED_SYSTEM_APP) != 0) {
                    return true;
                }
            } else if (filterOption == FILTER_APPS_SDCARD) {
                if ((info.flags & ApplicationInfo.FLAG_EXTERNAL_STORAGE) != 0) {
                    return true;
                }
            } else {
                return true;
            }
            return false;
        }
        
        /*
         * Add a package to the current list.
         * The package is only added to the displayed list
         * based on the filter value. The package is always added to the property map.
         * @param pkgName name of package to be added
         * @param ps PackageStats of new package
         */
        public void addToList(String pkgName, long size, String formattedSize) {
            if (pkgName == null) {
                return;
            }
            // Get ApplicationInfo
            ApplicationInfo info = null;
            try {
                info = mPm.getApplicationInfo(pkgName, 0);
            } catch (NameNotFoundException e) {
                Log.w(TAG, "Ignoring non-existent package:"+pkgName);
                return;
            }
            if(info == null) {
                // Nothing to do log error message and return
                Log.i(TAG, "Null ApplicationInfo for package:"+pkgName);
                return;
            }
            // Add entry to base list
            mAppList.add(info);
            // Add entry to map. Note that the index gets adjusted later on based on
            // whether the newly added package is part of displayed list
            CharSequence label = info.loadLabel(mPm);
            mCache.addEntry(new AppInfo(pkgName, -1,
                    label, info.loadIcon(mPm), size, formattedSize));
            if (addLocalEntry(info, label)) {
                notifyDataSetChanged();
            }
        }

        private boolean addLocalEntry(ApplicationInfo info, CharSequence label) {
            String pkgName = info.packageName;
            // Add to list
            if (shouldBeInList(mFilterApps, info)) {
                // Binary search returns a negative index (ie -index) of the position where
                // this might be inserted. 
                int newIdx = Collections.binarySearch(mAppLocalList, info, 
                        getAppComparator(mSortOrder));
                if(newIdx >= 0) {
                    if (localLOGV) Log.i(TAG, "Strange. Package:" + pkgName + " is not new");
                    return false;
                }
                // New entry
                newIdx = -newIdx-1;
                addFilterListLocked(newIdx, info, label);
                // Adjust index
                adjustIndex();
                return true;
            }
            return false;
        }

        public void updatePackage(String pkgName,
                long size, String formattedSize) {
            ApplicationInfo info = null;
            try {
                info = mPm.getApplicationInfo(pkgName,
                        PackageManager.GET_UNINSTALLED_PACKAGES);
            } catch (NameNotFoundException e) {
                return;
            }
            AppInfo aInfo = mCache.getEntry(pkgName);
            if (aInfo != null) {
                CharSequence label = info.loadLabel(mPm);
                aInfo.refreshLabel(label);
                aInfo.refreshIcon(info.loadIcon(mPm));
                aInfo.setSize(size, formattedSize);
                // Check if the entry has to be added to the displayed list
                addLocalEntry(info, label);
                // Refresh list since size might have changed
                notifyDataSetChanged();
            }
        }

        private void removePkgBase(String pkgName) {
            int imax = mAppList.size();
            for (int i = 0; i < imax; i++) {
                ApplicationInfo app = mAppList.get(i);
                if (app.packageName.equalsIgnoreCase(pkgName)) {
                    if (localLOGV) Log.i(TAG, "Removing pkg: "+pkgName+" from base list");
                    mAppList.remove(i);
                    return;
                }
            }
        }
 
        public void removeFromList(List<String> pkgNames) {
            if(pkgNames == null) {
                return;
            }
            if(pkgNames.size()  <= 0) {
                return;
            }
            boolean found = false;
            for (String pkg : pkgNames) {
                // Remove from the base application list
                removePkgBase(pkg);
                // Remove from cache
                if (localLOGV) Log.i(TAG, "Removing " + pkg + " from cache");
                mCache.removeEntry(pkg);
                // Remove from filtered list
                if (removeFilterListLocked(pkg)) {
                    found = true;
                }
            }
            // Adjust indices of list entries
            if (found) {
                adjustIndex();
                if (localLOGV) Log.i(TAG, "adjusting index and notifying list view");
                notifyDataSetChanged();
            }
        }

        public void bulkUpdateSizes(String pkgs[], long sizes[], String formatted[]) {
            if(pkgs == null || sizes == null || formatted == null) {
                return;
            }
            boolean changed = false;
            for (int i = 0; i < pkgs.length; i++) {
                AppInfo entry = mCache.getEntry(pkgs[i]);
                if (entry == null) {
                    if (localLOGV) Log.w(TAG, "Entry for package:"+ pkgs[i] +"doesn't exist in map");
                    continue;
                }
                if (entry.setSize(sizes[i], formatted[i])) {
                    changed = true;
                }
            }
            if (changed) {
                notifyDataSetChanged();
            }
        }

        public Filter getFilter() {
            return mAppFilter;
        }

        private class AppFilter extends Filter {
            @Override
            protected FilterResults performFiltering(CharSequence prefix) {
                FilterResults results = new FilterResults();
                if (prefix == null || prefix.length() == 0) {
                    synchronized (mFilterLock) {
                        results.values = new HashMap<String, String>(mFilterMap);
                        results.count = mFilterMap.size();
                    }
                } else {
                    final String prefixString = prefix.toString().toLowerCase();
                    final String spacePrefixString = " " + prefixString;
                    Map<String, String> newMap = new HashMap<String, String>();
                    synchronized (mFilterLock) {
                        Map<String, String> localMap = mFilterMap;
                        Set<String> keys = mFilterMap.keySet();
                        for (String key : keys) {
                            String label = localMap.get(key);
                            if (label == null) continue;
                            label = label.toLowerCase();
                            if (label.startsWith(prefixString)
                                    || label.indexOf(spacePrefixString) != -1) {
                                newMap.put(key, label);
                            }
                        }
                    }
                    results.values = newMap;
                    results.count = newMap.size();
                }
                return results;
            }

            @Override
            protected void publishResults(CharSequence constraint, FilterResults results) {
                mCurrentFilterMap = (Map<String, String>) results.values;
                reverseGenerateList();
                if (results.count > 0) {
                    notifyDataSetChanged();
                } else {
                    notifyDataSetInvalidated();
                }
            }
        }
    }
    
    /*
     * Utility method to clear messages to Handler
     * We need'nt synchronize on the Handler since posting messages is guaranteed
     * to be thread safe. Even if the other thread that retrieves package sizes
     * posts a message, we do a cursory check of validity on mAppInfoAdapter's applist
     */
    private void clearMessagesInHandler() {
        mHandler.removeMessages(INIT_PKG_INFO);
        mHandler.removeMessages(COMPUTE_BULK_SIZE);
        mHandler.removeMessages(REMOVE_PKG);
        mHandler.removeMessages(REORDER_LIST);
        mHandler.removeMessages(ADD_PKG_START);
        mHandler.removeMessages(ADD_PKG_DONE);
        mHandler.removeMessages(REFRESH_LABELS);
        mHandler.removeMessages(REFRESH_DONE);
        mHandler.removeMessages(NEXT_LOAD_STEP);
        mHandler.removeMessages(COMPUTE_END);
    }
    
    private void sendMessageToHandler(int msgId, int arg1) {
        Message msg = mHandler.obtainMessage(msgId);
        msg.arg1 = arg1;
        mHandler.sendMessage(msg);
    }
    
    private void sendMessageToHandler(int msgId, Bundle data) {
        Message msg = mHandler.obtainMessage(msgId);
        msg.setData(data);
        mHandler.sendMessage(msg);
    }
    
    private void sendMessageToHandler(int msgId) {
        mHandler.sendEmptyMessage(msgId);
    }
    
    /*
     * Stats Observer class used to compute package sizes and retrieve size information
     * PkgSizeOberver is the call back thats used when invoking getPackageSizeInfo on
     * PackageManager. The values in call back onGetStatsCompleted are validated
     * and the specified message is passed to mHandler. The package name
     * and the AppInfo object corresponding to the package name are set on the message
     */
    class PkgSizeObserver extends IPackageStatsObserver.Stub {
        String pkgName;
        public void onGetStatsCompleted(PackageStats pStats, boolean pSucceeded) {
            if(DEBUG_PKG_DELAY) {
                try {
                    Thread.sleep(10*1000);
                } catch (InterruptedException e) {
                }
            }
            Bundle data = new Bundle();
            data.putString(ATTR_PKG_NAME, pkgName);
            data.putBoolean(ATTR_GET_SIZE_STATUS, pSucceeded);
            if(pSucceeded && pStats != null) {
                if (localLOGV) Log.i(TAG, "onGetStatsCompleted::"+pkgName+", ("+
                        pStats.cacheSize+","+
                        pStats.codeSize+", "+pStats.dataSize);
                long total = getTotalSize(pStats);
                data.putLong(ATTR_PKG_STATS, total);
                CharSequence sizeStr = getSizeStr(total);
                data.putString(ATTR_PKG_SIZE_STR, sizeStr.toString());
            } else {
                Log.w(TAG, "Invalid package stats from PackageManager");
            }
            // Post message to Handler
            Message msg = mHandler.obtainMessage(ADD_PKG_DONE, data);
            msg.setData(data);
            mHandler.sendMessage(msg);
        }

        public void invokeGetSizeInfo(String packageName) {
            if (packageName == null) {
                return;
            }
            pkgName = packageName;
            if(localLOGV) Log.i(TAG, "Invoking getPackageSizeInfo for package:"+
                    packageName);
            mPm.getPackageSizeInfo(packageName, this);
        }
    }
    
    /**
     * Receives notifications when applications are added/removed.
     */
    private class PackageIntentReceiver extends BroadcastReceiver {
         void registerReceiver() {
             IntentFilter filter = new IntentFilter(Intent.ACTION_PACKAGE_ADDED);
             filter.addAction(Intent.ACTION_PACKAGE_REMOVED);
             filter.addAction(Intent.ACTION_PACKAGE_CHANGED);
             filter.addDataScheme("package");
             ManageApplications.this.registerReceiver(this, filter);
             // Register for events related to sdcard installation.
             IntentFilter sdFilter = new IntentFilter();
             sdFilter.addAction(Intent.ACTION_EXTERNAL_APPLICATIONS_AVAILABLE);
             sdFilter.addAction(Intent.ACTION_EXTERNAL_APPLICATIONS_UNAVAILABLE);
             ManageApplications.this.registerReceiver(this, sdFilter);
         }
         @Override
         public void onReceive(Context context, Intent intent) {
             String actionStr = intent.getAction();
             if (Intent.ACTION_PACKAGE_ADDED.equals(actionStr) ||
                     Intent.ACTION_PACKAGE_REMOVED.equals(actionStr)) {
                 Uri data = intent.getData();
                 String pkgName = data.getEncodedSchemeSpecificPart();
                 updatePackageList(actionStr, pkgName);
             } else if (Intent.ACTION_EXTERNAL_APPLICATIONS_AVAILABLE.equals(actionStr) ||
                     Intent.ACTION_EXTERNAL_APPLICATIONS_UNAVAILABLE.equals(actionStr)) {
                 // When applications become available or unavailable (perhaps because
                 // the SD card was inserted or ejected) we need to refresh the
                 // AppInfo with new label, icon and size information as appropriate
                 // given the newfound (un)availability of the application.
                 // A simple way to do that is to treat the refresh as a package
                 // removal followed by a package addition.
                 String pkgList[] = intent.getStringArrayExtra(Intent.EXTRA_CHANGED_PACKAGE_LIST);
                 if (pkgList == null || pkgList.length == 0) {
                     // Ignore
                     return;
                 }
                 for (String pkgName : pkgList) {
                     updatePackageList(Intent.ACTION_PACKAGE_REMOVED, pkgName);
                     updatePackageList(Intent.ACTION_PACKAGE_ADDED, pkgName);
                 }
             }
         }
    }

    private void updatePackageList(String actionStr, String pkgName) {
        if (Intent.ACTION_PACKAGE_ADDED.equalsIgnoreCase(actionStr)) {
            Bundle data = new Bundle();
            data.putString(ATTR_PKG_NAME, pkgName);
            sendMessageToHandler(ADD_PKG_START, data);
        } else if (Intent.ACTION_PACKAGE_REMOVED.equalsIgnoreCase(actionStr)) {
            Bundle data = new Bundle();
            data.putString(ATTR_PKG_NAME, pkgName);
            sendMessageToHandler(REMOVE_PKG, data);
        }
    }

    static final String TAB_DOWNLOADED = "Downloaded";
    static final String TAB_RUNNING = "Running";
    static final String TAB_ALL = "All";
    static final String TAB_SDCARD = "OnSdCard";
    private View mRootView;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        if(localLOGV) Log.i(TAG, "Activity created");
        long sCreate;
        if (DEBUG_TIME) {
            sCreate = SystemClock.elapsedRealtime();
        }
        Intent intent = getIntent();
        String action = intent.getAction();
        String defaultTabTag = TAB_DOWNLOADED;
        if (action.equals(Intent.ACTION_MANAGE_PACKAGE_STORAGE)) {
            mSortOrder = SORT_ORDER_SIZE;
            mFilterApps = FILTER_APPS_ALL;
            defaultTabTag = TAB_ALL;
            mSizesFirst = true;
        }
        mPm = getPackageManager();
        // initialize some window features
        requestWindowFeature(Window.FEATURE_RIGHT_ICON);
        requestWindowFeature(Window.FEATURE_PROGRESS);
        requestWindowFeature(Window.FEATURE_INDETERMINATE_PROGRESS);
        showLoadingMsg();
        mDefaultAppIcon = Resources.getSystem().getDrawable(
                com.android.internal.R.drawable.sym_def_app_icon);
        mInvalidSizeStr = getText(R.string.invalid_size_value);
        mComputingSizeStr = getText(R.string.computing_size);
        // initialize the inflater
        mInflater = (LayoutInflater)getSystemService(Context.LAYOUT_INFLATER_SERVICE);
        mRootView = mInflater.inflate(R.layout.compute_sizes, null);
        mReceiver = new PackageIntentReceiver();
        mObserver = new PkgSizeObserver();
        // Create adapter and list view here
        List<ApplicationInfo> appList = getInstalledApps(FILTER_APPS_ALL);
        mAppInfoAdapter = new AppInfoAdapter(this, appList);
        ListView lv = (ListView) mRootView.findViewById(android.R.id.list);
        lv.setOnItemClickListener(this);
        lv.setSaveEnabled(true);
        lv.setItemsCanFocus(true);
        lv.setOnItemClickListener(this);
        lv.setTextFilterEnabled(true);
        mListView = lv;
        if (DEBUG_TIME) {
            Log.i(TAG, "Total time in Activity.create:: " +
                    (SystemClock.elapsedRealtime() - sCreate)+ " ms");
        }
        // Get initial info from file for the very first time this activity started
        long sStart;
        if (DEBUG_TIME) {
            sStart = SystemClock.elapsedRealtime();
        }
        mCache.loadCache();
        if (DEBUG_TIME) {
            Log.i(TAG, "Took " + (SystemClock.elapsedRealtime()-sStart) + " ms to init cache");
        }

        final TabHost tabHost = getTabHost();
        tabHost.addTab(tabHost.newTabSpec(TAB_DOWNLOADED)
                .setIndicator(getString(R.string.filter_apps_third_party),
                        getResources().getDrawable(R.drawable.ic_tab_download))
                .setContent(this));
        tabHost.addTab(tabHost.newTabSpec(TAB_RUNNING)
                .setIndicator(getString(R.string.filter_apps_running),
                        getResources().getDrawable(R.drawable.ic_tab_running))
                .setContent(this));
        tabHost.addTab(tabHost.newTabSpec(TAB_ALL)
                .setIndicator(getString(R.string.filter_apps_all),
                        getResources().getDrawable(R.drawable.ic_tab_all))
                .setContent(this));
        tabHost.addTab(tabHost.newTabSpec(TAB_SDCARD)
                .setIndicator(getString(R.string.filter_apps_onsdcard),
                        getResources().getDrawable(R.drawable.ic_tab_sdcard))
                .setContent(this));
        tabHost.setCurrentTabByTag(defaultTabTag);
        tabHost.setOnTabChangedListener(this);
    }
    
    @Override
    protected void onDestroy() {
        // Persist values in cache
        mCache.updateCache();
        super.onDestroy();
    }

    @Override
    public Dialog onCreateDialog(int id, Bundle args) {
        if (id == DLG_LOADING) {
            ProgressDialog dlg = new ProgressDialog(this);
            dlg.setProgressStyle(ProgressDialog.STYLE_SPINNER);
            dlg.setMessage(getText(R.string.loading));
            dlg.setIndeterminate(true);        
            dlg.setOnCancelListener(this);
            return dlg;
        }
        return null;
    }

    private void showLoadingMsg() {
        if (DEBUG_TIME) {
            mLoadTimeStart = SystemClock.elapsedRealtime();
        }
        showDialog(DLG_LOADING); 
        if(localLOGV) Log.i(TAG, "Displaying Loading message");
    }
    
    private void dismissLoadingMsg() {
        if(localLOGV) Log.i(TAG, "Dismissing Loading message");
        dismissDialog(DLG_LOADING);
        if (DEBUG_TIME) Log.i(TAG, "Displayed loading message for "+
                (SystemClock.elapsedRealtime() - mLoadTimeStart) + " ms");
    }

    class AppInfoCache {
        final static boolean FILE_CACHE = true;
        private static final String mFileCacheName="ManageAppsInfo.txt";
        private static final int FILE_BUFFER_SIZE = 1024;
        private static final boolean DEBUG_CACHE = false;
        private static final boolean DEBUG_CACHE_TIME = false;
        private Map<String, AppInfo> mAppPropCache = new HashMap<String, AppInfo>();

        private boolean isEmpty() {
            return (mAppPropCache.size() == 0);
        }

        private AppInfo getEntry(String pkgName) {
            return mAppPropCache.get(pkgName);
        }

        private Set<String> getPkgList() {
            return mAppPropCache.keySet();
        }

        public void addEntry(AppInfo aInfo) {
            if ((aInfo != null) && (aInfo.pkgName != null)) {
                mAppPropCache.put(aInfo.pkgName, aInfo);
            }
        }

        public void removeEntry(String pkgName) {
            if (pkgName != null) {
                mAppPropCache.remove(pkgName);
            }
        }

        private void readFromFile() {
            File cacheFile = new File(getFilesDir(), mFileCacheName);
            if (!cacheFile.exists()) {
                return;
            }
            FileInputStream fis = null;
            boolean err = false;
            try {
                fis = new FileInputStream(cacheFile);
            } catch (FileNotFoundException e) {
                Log.w(TAG, "Error opening file for read operation : " + cacheFile
                        + " with exception " + e);
                return;
            }
            try {
                byte[] byteBuff = new byte[FILE_BUFFER_SIZE];
                byte[] lenBytes = new byte[2];
                mAppPropCache.clear();
                while(fis.available() > 0) {
                    fis.read(lenBytes, 0, 2);
                    int buffLen = (lenBytes[0] << 8) | lenBytes[1];
                    if ((buffLen <= 0) || (buffLen > byteBuff.length)) {
                        err = true;
                        break;
                    }
                    // Buffer length cannot be greater than max.
                    fis.read(byteBuff, 0, buffLen);
                    String buffStr = new String(byteBuff);
                    if (DEBUG_CACHE) {
                        Log.i(TAG, "Read string of len= " + buffLen + " :: " + buffStr + " from file");
                    }
                    // Parse string for sizes
                    String substrs[] = buffStr.split(",");
                    if (substrs.length < 4) {
                        // Something wrong. Bail out and let recomputation proceed.
                        err = true;
                        break;
                    }
                    long size = -1;
                    int idx = -1;
                    try {
                        size = Long.parseLong(substrs[1]);
                    } catch (NumberFormatException e) {
                        err = true;
                        break;
                    }
                    if (DEBUG_CACHE) {
                        Log.i(TAG, "Creating entry(" + substrs[0] + ", " + idx+"," + size + ", " + substrs[2] + ")");
                    }
                    AppInfo aInfo = new AppInfo(substrs[0], idx, substrs[3], size, substrs[2]);
                    mAppPropCache.put(aInfo.pkgName, aInfo);
                }
            } catch (IOException e) {
                Log.w(TAG, "Failed reading from file : " + cacheFile + " with exception : " + e);
                err = true;
            } finally {
                if (fis != null) {
                    try {
                        fis.close();
                    } catch (IOException e) {
                        Log.w(TAG, "Failed to close file " + cacheFile + " with exception : " +e);
                        err = true;
                    }
                }
                if (err) {
                    Log.i(TAG, "Failed to load cache. Not using cache for now.");
                    // Clear cache and bail out
                    mAppPropCache.clear();
                }
            }
        }

        boolean writeToFile() {
            File cacheFile = new File(getFilesDir(), mFileCacheName);
            FileOutputStream fos = null;
            try {
                long opStartTime = SystemClock.uptimeMillis();
                fos = new FileOutputStream(cacheFile);
                Set<String> keys = mAppPropCache.keySet();
                byte[] lenBytes = new byte[2];
                for (String key : keys) {
                    AppInfo aInfo = mAppPropCache.get(key);
                    StringBuilder buff = new StringBuilder(aInfo.pkgName);
                    buff.append(",");
                    buff.append(aInfo.size);
                    buff.append(",");
                    buff.append(aInfo.appSize);
                    buff.append(",");
                    buff.append(aInfo.appName);
                    if (DEBUG_CACHE) {
                        Log.i(TAG, "Writing str : " + buff.toString() + " to file of length:" +
                                buff.toString().length());
                    }
                    try {
                        byte[] byteBuff = buff.toString().getBytes();
                        int len = byteBuff.length;
                        if (byteBuff.length >= FILE_BUFFER_SIZE) {
                            // Truncate the output
                            len = FILE_BUFFER_SIZE;
                        }
                        // Use 2 bytes to write length
                        lenBytes[1] = (byte) (len & 0x00ff);
                        lenBytes[0] = (byte) ((len & 0x00ff00) >> 8);
                        fos.write(lenBytes, 0, 2);
                        fos.write(byteBuff, 0, len);
                    } catch (IOException e) {
                        Log.w(TAG, "Failed to write to file : " + cacheFile + " with exception : " + e);
                        return false;
                    }
                }
                if (DEBUG_CACHE_TIME) {
                    Log.i(TAG, "Took " + (SystemClock.uptimeMillis() - opStartTime) + " ms to write and process from file");
                }
                return true;
            } catch (FileNotFoundException e) {
                Log.w(TAG, "Error opening file for write operation : " + cacheFile+
                        " with exception : " + e);
                return false;
            } finally {
                if (fos != null) {
                    try {
                        fos.close();
                    } catch (IOException e) {
                        Log.w(TAG, "Failed closing file : " + cacheFile + " with exception : " + e);
                        return false;
                    }
                }
            }
        }
        private void loadCache() {
             // Restore preferences
            SharedPreferences settings = getSharedPreferences(PREFS_NAME, 0);
            boolean disable = settings.getBoolean(PREF_DISABLE_CACHE, true);
            if (disable) Log.w(TAG, "Cache has been disabled");
            // Disable cache till the data is loaded successfully
            SharedPreferences.Editor editor = settings.edit();
            editor.putBoolean(PREF_DISABLE_CACHE, true);
            editor.commit();
            if (FILE_CACHE && !disable) {
                readFromFile();
                // Enable cache since the file has been read successfully
                editor.putBoolean(PREF_DISABLE_CACHE, false);
                editor.commit();
            }
        }

        private void updateCache() {
            SharedPreferences settings = getSharedPreferences(PREFS_NAME, 0);
            SharedPreferences.Editor editor = settings.edit();
            editor.putBoolean(PREF_DISABLE_CACHE, true);
            editor.commit();
            if (FILE_CACHE) {
                boolean writeStatus = writeToFile();
                mAppPropCache.clear();
                if (writeStatus) {
                    // Enable cache since the file has been read successfully
                    editor.putBoolean(PREF_DISABLE_CACHE, false);
                    editor.commit();
                }
            }
        }
    }

    @Override
    public void onStart() {
        super.onStart();
        // Register receiver
        mReceiver.registerReceiver();
        sendMessageToHandler(INIT_PKG_INFO);
    }

    @Override
    public void onStop() {
        super.onStop();
        // Stop the background threads
        if (mResourceThread != null) {
            mResourceThread.setAbort();
        }
        if (mSizeComputor != null) {
            mSizeComputor.setAbort();
        }
        // clear all messages related to application list
        clearMessagesInHandler();
        // register receiver here
        unregisterReceiver(mReceiver);
    }
    
    // Avoid the restart and pause when orientation changes
    @Override
    public void onConfigurationChanged(Configuration newConfig) {
        super.onConfigurationChanged(newConfig);
    }
    
    /*
     * comparator class used to sort AppInfo objects based on size
     */
    class SizeComparator implements Comparator<ApplicationInfo> {
        public final int compare(ApplicationInfo a, ApplicationInfo b) {
            AppInfo ainfo = mCache.getEntry(a.packageName);
            AppInfo binfo = mCache.getEntry(b.packageName);
            long atotal = ainfo.size;
            long btotal = binfo.size;
            long ret = atotal - btotal;
            // negate result to sort in descending order
            if (ret < 0) {
                return 1;
            }
            if (ret == 0) {
                return 0;
            }
            return -1;
        }
    }

    /*
     * Customized comparator class to compare labels.
     * Don't use the one defined in ApplicationInfo since that loads the labels again.
     */
    class AlphaComparator implements Comparator<ApplicationInfo> {
        private final Collator   sCollator = Collator.getInstance();

        public final int compare(ApplicationInfo a, ApplicationInfo b) {
            AppInfo ainfo = mCache.getEntry(a.packageName);
            AppInfo binfo = mCache.getEntry(b.packageName);
            // Check for null app names, to avoid NPE in rare cases
            if (ainfo == null || ainfo.appName == null) return -1;
            if (binfo == null || binfo.appName == null) return 1;
            return sCollator.compare(ainfo.appName.toString(), binfo.appName.toString());
        }
    }

    // utility method used to start sub activity
    private void startApplicationDetailsActivity() {
        // Create intent to start new activity
        Intent intent = new Intent(Intent.ACTION_VIEW);
        intent.setClass(this, InstalledAppDetails.class);
        intent.putExtra(APP_PKG_NAME, mCurrentPkgName);
        // start new activity to display extended information
        startActivityForResult(intent, INSTALLED_APP_DETAILS);
    }
    
    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        menu.add(0, SORT_ORDER_ALPHA, 1, R.string.sort_order_alpha)
                .setIcon(android.R.drawable.ic_menu_sort_alphabetically);
        menu.add(0, SORT_ORDER_SIZE, 2, R.string.sort_order_size)
                .setIcon(android.R.drawable.ic_menu_sort_by_size); 
        return true;
    }
    
    @Override
    public boolean onPrepareOptionsMenu(Menu menu) {
        if (mFirst) {
            menu.findItem(SORT_ORDER_ALPHA).setVisible(mSortOrder != SORT_ORDER_ALPHA);
            menu.findItem(SORT_ORDER_SIZE).setVisible(mSortOrder != SORT_ORDER_SIZE);
            return true;
        }
        return false;
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        int menuId = item.getItemId();
        if ((menuId == SORT_ORDER_ALPHA) || (menuId == SORT_ORDER_SIZE)) {
            sendMessageToHandler(REORDER_LIST, menuId);
        }
        return true;
    }

    public void onItemClick(AdapterView<?> parent, View view, int position,
            long id) {
        ApplicationInfo info = (ApplicationInfo)mAppInfoAdapter.getItem(position);
        mCurrentPkgName = info.packageName;
        startApplicationDetailsActivity();
    }
    
    // Finish the activity if the user presses the back button to cancel the activity
    public void onCancel(DialogInterface dialog) {
        finish();
    }

    public View createTabContent(String tag) {
        return mRootView;
    }

    public void onTabChanged(String tabId) {
        int newOption;
        if (TAB_DOWNLOADED.equalsIgnoreCase(tabId)) {
            newOption = FILTER_APPS_THIRD_PARTY;
        } else if (TAB_RUNNING.equalsIgnoreCase(tabId)) {
            newOption = FILTER_APPS_RUNNING;
        } else if (TAB_ALL.equalsIgnoreCase(tabId)) {
            newOption = FILTER_APPS_ALL;
        } else if (TAB_SDCARD.equalsIgnoreCase(tabId)) {
            newOption = FILTER_APPS_SDCARD;
        } else {
            // Invalid option. Do nothing
            return;
        }
        sendMessageToHandler(REORDER_LIST, newOption);
    }

    @Override
    protected void onActivityResult(int requestCode, int resultCode,
            Intent data) {
        if (requestCode == INSTALLED_APP_DETAILS && mCurrentPkgName != null) {
            // Refresh package attributes
            try {
                ApplicationInfo info = mPm.getApplicationInfo(mCurrentPkgName,
                        PackageManager.GET_UNINSTALLED_PACKAGES);
            } catch (NameNotFoundException e) {
                Bundle rData = new Bundle();
                rData.putString(ATTR_PKG_NAME, mCurrentPkgName);
                sendMessageToHandler(REMOVE_PKG, rData);
                mCurrentPkgName = null;
            }
        }
    }
}
