/*
 * 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.applications;

import static android.net.NetworkPolicyManager.POLICY_NONE;
import static android.net.NetworkPolicyManager.POLICY_REJECT_METERED_BACKGROUND;

import android.app.Activity;
import android.app.ActivityManager;
import android.app.AlertDialog;
import android.app.Fragment;
import android.app.INotificationManager;
import android.content.ComponentName;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.ServiceConnection;
import android.content.pm.ApplicationInfo;
import android.content.pm.IPackageManager;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.net.NetworkPolicyManager;
import android.os.AsyncTask;
import android.os.Bundle;
import android.os.Environment;
import android.os.Handler;
import android.os.IBinder;
import android.os.RemoteException;
import android.os.ServiceManager;
import android.os.UserHandle;
import android.preference.PreferenceActivity;
import android.preference.PreferenceFrameLayout;
import android.provider.Settings;
import android.support.v4.view.PagerAdapter;
import android.support.v4.view.PagerTabStrip;
import android.support.v4.view.ViewPager;
import android.text.format.Formatter;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.View;
import android.view.ViewGroup;
import android.view.animation.AnimationUtils;
import android.widget.AbsListView;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemClickListener;
import android.widget.BaseAdapter;
import android.widget.Filter;
import android.widget.Filterable;
import android.widget.ListView;
import android.widget.TextView;

import com.android.internal.app.IMediaContainerService;
import com.android.internal.content.PackageHelper;
import com.android.settings.R;
import com.android.settings.Settings.RunningServicesActivity;
import com.android.settings.Settings.StorageUseActivity;
import com.android.settings.applications.ApplicationsState.AppEntry;
import com.android.settings.deviceinfo.StorageMeasurement;
import com.android.settings.Utils;

import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;

final class CanBeOnSdCardChecker {
    final IPackageManager mPm;
    int mInstallLocation;
    
    CanBeOnSdCardChecker() {
        mPm = IPackageManager.Stub.asInterface(
                ServiceManager.getService("package"));
    }
    
    void init() {
        try {
            mInstallLocation = mPm.getInstallLocation();
        } catch (RemoteException e) {
            Log.e("CanBeOnSdCardChecker", "Is Package Manager running?");
            return;
        }
    }
    
    boolean check(ApplicationInfo info) {
        boolean canBe = false;
        if ((info.flags & ApplicationInfo.FLAG_EXTERNAL_STORAGE) != 0) {
            canBe = true;
        } else {
            if ((info.flags & ApplicationInfo.FLAG_SYSTEM) == 0) {
                if (info.installLocation == PackageInfo.INSTALL_LOCATION_PREFER_EXTERNAL ||
                        info.installLocation == PackageInfo.INSTALL_LOCATION_AUTO) {
                    canBe = true;
                } else if (info.installLocation
                        == PackageInfo.INSTALL_LOCATION_UNSPECIFIED) {
                    if (mInstallLocation == PackageHelper.APP_INSTALL_EXTERNAL) {
                        // For apps with no preference and the default value set
                        // to install on sdcard.
                        canBe = true;
                    }
                }
            }
        }
        return canBe;
    }
}

interface AppClickListener {
    void onItemClick(ManageApplications.TabInfo tab, AdapterView<?> parent,
            View view, int position, long id);
}

/**
 * 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.
 */
public class ManageApplications extends Fragment implements
        AppClickListener, DialogInterface.OnClickListener,
        DialogInterface.OnDismissListener {

    static final String TAG = "ManageApplications";
    static final boolean DEBUG = false;

    private static final String EXTRA_SORT_ORDER = "sortOrder";
    private static final String EXTRA_SHOW_BACKGROUND = "showBackground";
    private static final String EXTRA_DEFAULT_LIST_TYPE = "defaultListType";
    private static final String EXTRA_RESET_DIALOG = "resetDialog";

    // attributes used as keys when passing values to InstalledAppDetails activity
    public static final String APP_CHG = "chg";

    // constant value that can be used to check return code from sub activity.
    private static final int INSTALLED_APP_DETAILS = 1;

    public static final int SIZE_TOTAL = 0;
    public static final int SIZE_INTERNAL = 1;
    public static final int SIZE_EXTERNAL = 2;

    // 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_THIRD_PARTY = MENU_OPTIONS_BASE + 1;
    public static final int FILTER_APPS_SDCARD = MENU_OPTIONS_BASE + 2;

    public static final int SORT_ORDER_ALPHA = MENU_OPTIONS_BASE + 4;
    public static final int SORT_ORDER_SIZE = MENU_OPTIONS_BASE + 5;
    public static final int SHOW_RUNNING_SERVICES = MENU_OPTIONS_BASE + 6;
    public static final int SHOW_BACKGROUND_PROCESSES = MENU_OPTIONS_BASE + 7;
    public static final int RESET_APP_PREFERENCES = MENU_OPTIONS_BASE + 8;
    // sort order
    private int mSortOrder = SORT_ORDER_ALPHA;
    
    private ApplicationsState mApplicationsState;

    public static class TabInfo implements OnItemClickListener {
        public final ManageApplications mOwner;
        public final ApplicationsState mApplicationsState;
        public final CharSequence mLabel;
        public final int mListType;
        public final int mFilter;
        public final AppClickListener mClickListener;
        public final CharSequence mInvalidSizeStr;
        public final CharSequence mComputingSizeStr;
        private final Bundle mSavedInstanceState;

        public ApplicationsAdapter mApplications;
        public LayoutInflater mInflater;
        public View mRootView;

        private IMediaContainerService mContainerService;

        private View mLoadingContainer;

        private View mListContainer;

        // ListView used to display list
        private ListView mListView;
        // Custom view used to display running processes
        private RunningProcessesView mRunningProcessesView;
        
        private LinearColorBar mColorBar;
        private TextView mStorageChartLabel;
        private TextView mUsedStorageText;
        private TextView mFreeStorageText;
        private long mFreeStorage = 0, mAppStorage = 0, mTotalStorage = 0;
        private long mLastUsedStorage, mLastAppStorage, mLastFreeStorage;

        final Runnable mRunningProcessesAvail = new Runnable() {
            public void run() {
                handleRunningProcessesAvail();
            }
        };

        public TabInfo(ManageApplications owner, ApplicationsState apps,
                CharSequence label, int listType, AppClickListener clickListener,
                Bundle savedInstanceState) {
            mOwner = owner;
            mApplicationsState = apps;
            mLabel = label;
            mListType = listType;
            switch (listType) {
                case LIST_TYPE_DOWNLOADED: mFilter = FILTER_APPS_THIRD_PARTY; break;
                case LIST_TYPE_SDCARD: mFilter = FILTER_APPS_SDCARD; break;
                default: mFilter = FILTER_APPS_ALL; break;
            }
            mClickListener = clickListener;
            mInvalidSizeStr = owner.getActivity().getText(R.string.invalid_size_value);
            mComputingSizeStr = owner.getActivity().getText(R.string.computing_size);
            mSavedInstanceState = savedInstanceState;
        }

        public void setContainerService(IMediaContainerService containerService) {
            mContainerService = containerService;
            updateStorageUsage();
        }

        public View build(LayoutInflater inflater, ViewGroup contentParent, View contentChild) {
            if (mRootView != null) {
                return mRootView;
            }

            mInflater = inflater;
            mRootView = inflater.inflate(mListType == LIST_TYPE_RUNNING
                    ? R.layout.manage_applications_running
                    : R.layout.manage_applications_apps, null);
            mLoadingContainer = mRootView.findViewById(R.id.loading_container);
            mLoadingContainer.setVisibility(View.VISIBLE);
            mListContainer = mRootView.findViewById(R.id.list_container);
            if (mListContainer != null) {
                // Create adapter and list view here
                View emptyView = mListContainer.findViewById(com.android.internal.R.id.empty);
                ListView lv = (ListView) mListContainer.findViewById(android.R.id.list);
                if (emptyView != null) {
                    lv.setEmptyView(emptyView);
                }
                lv.setOnItemClickListener(this);
                lv.setSaveEnabled(true);
                lv.setItemsCanFocus(true);
                lv.setTextFilterEnabled(true);
                mListView = lv;
                mApplications = new ApplicationsAdapter(mApplicationsState, this, mFilter);
                mListView.setAdapter(mApplications);
                mListView.setRecyclerListener(mApplications);
                mColorBar = (LinearColorBar)mListContainer.findViewById(R.id.storage_color_bar);
                mStorageChartLabel = (TextView)mListContainer.findViewById(R.id.storageChartLabel);
                mUsedStorageText = (TextView)mListContainer.findViewById(R.id.usedStorageText);
                mFreeStorageText = (TextView)mListContainer.findViewById(R.id.freeStorageText);
                Utils.prepareCustomPreferencesList(contentParent, contentChild, mListView, false);
                if (mFilter == FILTER_APPS_SDCARD) {
                    mStorageChartLabel.setText(mOwner.getActivity().getText(
                            R.string.sd_card_storage));
                } else {
                    mStorageChartLabel.setText(mOwner.getActivity().getText(
                            R.string.internal_storage));
                }
                applyCurrentStorage();
            }
            mRunningProcessesView = (RunningProcessesView)mRootView.findViewById(
                    R.id.running_processes);
            if (mRunningProcessesView != null) {
                mRunningProcessesView.doCreate(mSavedInstanceState);
            }

            return mRootView;
        }

        public void detachView() {
            if (mRootView != null) {
                ViewGroup group = (ViewGroup)mRootView.getParent();
                if (group != null) {
                    group.removeView(mRootView);
                }
            }
        }

        public void resume(int sortOrder) {
            if (mApplications != null) {
                mApplications.resume(sortOrder);
            }
            if (mRunningProcessesView != null) {
                boolean haveData = mRunningProcessesView.doResume(mOwner, mRunningProcessesAvail);
                if (haveData) {
                    mRunningProcessesView.setVisibility(View.VISIBLE);
                    mLoadingContainer.setVisibility(View.INVISIBLE);
                } else {
                    mLoadingContainer.setVisibility(View.VISIBLE);
                }
            }
        }

        public void pause() {
            if (mApplications != null) {
                mApplications.pause();
            }
            if (mRunningProcessesView != null) {
                mRunningProcessesView.doPause();
            }
        }

        void updateStorageUsage() {
            // Make sure a callback didn't come at an inopportune time.
            if (mOwner.getActivity() == null) return;
            // Doesn't make sense for stuff that is not an app list.
            if (mApplications == null) return;

            mFreeStorage = 0;
            mAppStorage = 0;
            mTotalStorage = 0;

            if (mFilter == FILTER_APPS_SDCARD) {
                if (mContainerService != null) {
                    try {
                        final long[] stats = mContainerService.getFileSystemStats(
                                Environment.getExternalStorageDirectory().getPath());
                        mTotalStorage = stats[0];
                        mFreeStorage = stats[1];
                    } catch (RemoteException e) {
                        Log.w(TAG, "Problem in container service", e);
                    }
                }

                if (mApplications != null) {
                    final int N = mApplications.getCount();
                    for (int i=0; i<N; i++) {
                        ApplicationsState.AppEntry ae = mApplications.getAppEntry(i);
                        mAppStorage += ae.externalCodeSize + ae.externalDataSize
                                + ae.externalCacheSize;
                    }
                }
            } else {
                if (mContainerService != null) {
                    try {
                        final long[] stats = mContainerService.getFileSystemStats(
                                Environment.getDataDirectory().getPath());
                        mTotalStorage = stats[0];
                        mFreeStorage = stats[1];
                    } catch (RemoteException e) {
                        Log.w(TAG, "Problem in container service", e);
                    }
                }

                final boolean emulatedStorage = Environment.isExternalStorageEmulated();
                if (mApplications != null) {
                    final int N = mApplications.getCount();
                    for (int i=0; i<N; i++) {
                        ApplicationsState.AppEntry ae = mApplications.getAppEntry(i);
                        mAppStorage += ae.codeSize + ae.dataSize;
                        if (emulatedStorage) {
                            mAppStorage += ae.externalCodeSize + ae.externalDataSize;
                        }
                    }
                }
                mFreeStorage += mApplicationsState.sumCacheSizes();
            }

            applyCurrentStorage();
        }

        void applyCurrentStorage() {
            // If view hierarchy is not yet created, no views to update.
            if (mRootView == null) {
                return;
            }
            if (mTotalStorage > 0) {
                mColorBar.setRatios((mTotalStorage-mFreeStorage-mAppStorage)/(float)mTotalStorage,
                        mAppStorage/(float)mTotalStorage, mFreeStorage/(float)mTotalStorage);
                long usedStorage = mTotalStorage - mFreeStorage;
                if (mLastUsedStorage != usedStorage) {
                    mLastUsedStorage = usedStorage;
                    String sizeStr = Formatter.formatShortFileSize(
                            mOwner.getActivity(), usedStorage);
                    mUsedStorageText.setText(mOwner.getActivity().getResources().getString(
                            R.string.service_foreground_processes, sizeStr));
                }
                if (mLastFreeStorage != mFreeStorage) {
                    mLastFreeStorage = mFreeStorage;
                    String sizeStr = Formatter.formatShortFileSize(
                            mOwner.getActivity(), mFreeStorage);
                    mFreeStorageText.setText(mOwner.getActivity().getResources().getString(
                            R.string.service_background_processes, sizeStr));
                }
            } else {
                mColorBar.setRatios(0, 0, 0);
                if (mLastUsedStorage != -1) {
                    mLastUsedStorage = -1;
                    mUsedStorageText.setText("");
                }
                if (mLastFreeStorage != -1) {
                    mLastFreeStorage = -1;
                    mFreeStorageText.setText("");
                }
            }
        }

        @Override
        public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
            mClickListener.onItemClick(this, parent, view, position, id);
        }

        void handleRunningProcessesAvail() {
            mLoadingContainer.startAnimation(AnimationUtils.loadAnimation(
                    mOwner.getActivity(), android.R.anim.fade_out));
            mRunningProcessesView.startAnimation(AnimationUtils.loadAnimation(
                    mOwner.getActivity(), android.R.anim.fade_in));
            mRunningProcessesView.setVisibility(View.VISIBLE);
            mLoadingContainer.setVisibility(View.GONE);
        }
    }
    private final ArrayList<TabInfo> mTabs = new ArrayList<TabInfo>();
    TabInfo mCurTab = null;

    // Size resource used for packages whose size computation failed for some reason
    CharSequence mInvalidSizeStr;
    private CharSequence mComputingSizeStr;
    
    // layout inflater object used to inflate views
    private LayoutInflater mInflater;
    
    private String mCurrentPkgName;
    
    private Menu mOptionsMenu;

    // These are for keeping track of activity and spinner switch state.
    private boolean mActivityResumed;
    
    static final int LIST_TYPE_DOWNLOADED = 0;
    static final int LIST_TYPE_RUNNING = 1;
    static final int LIST_TYPE_SDCARD = 2;
    static final int LIST_TYPE_ALL = 3;

    private boolean mShowBackground = false;
    
    private int mDefaultListType = -1;

    private ViewGroup mContentContainer;
    private View mRootView;
    private ViewPager mViewPager;

    AlertDialog mResetDialog;

    class MyPagerAdapter extends PagerAdapter
            implements ViewPager.OnPageChangeListener {
        int mCurPos = 0;

        @Override
        public int getCount() {
            return mTabs.size();
        }
        
        @Override
        public Object instantiateItem(ViewGroup container, int position) {
            TabInfo tab = mTabs.get(position);
            View root = tab.build(mInflater, mContentContainer, mRootView);
            container.addView(root);
            return root;
        }

        @Override
        public void destroyItem(ViewGroup container, int position, Object object) {
            container.removeView((View)object);
        }

        @Override
        public boolean isViewFromObject(View view, Object object) {
            return view == object;
        }

        @Override
        public CharSequence getPageTitle(int position) {
            return mTabs.get(position).mLabel;
        }

        @Override
        public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
        }

        @Override
        public void onPageSelected(int position) {
            mCurPos = position;
        }

        @Override
        public void onPageScrollStateChanged(int state) {
            if (state == ViewPager.SCROLL_STATE_IDLE) {
                updateCurrentTab(mCurPos);
            }
        }
    }

    /*
     * 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
     */
    static class ApplicationsAdapter extends BaseAdapter implements Filterable,
            ApplicationsState.Callbacks, AbsListView.RecyclerListener {
        private final ApplicationsState mState;
        private final ApplicationsState.Session mSession;
        private final TabInfo mTab;
        private final Context mContext;
        private final ArrayList<View> mActive = new ArrayList<View>();
        private final int mFilterMode;
        private ArrayList<ApplicationsState.AppEntry> mBaseEntries;
        private ArrayList<ApplicationsState.AppEntry> mEntries;
        private boolean mResumed;
        private int mLastSortMode=-1;
        private boolean mWaitingForData;
        private int mWhichSize = SIZE_TOTAL;
        CharSequence mCurFilterPrefix;

        private Filter mFilter = new Filter() {
            @Override
            protected FilterResults performFiltering(CharSequence constraint) {
                ArrayList<ApplicationsState.AppEntry> entries
                        = applyPrefixFilter(constraint, mBaseEntries);
                FilterResults fr = new FilterResults();
                fr.values = entries;
                fr.count = entries.size();
                return fr;
            }

            @Override
            protected void publishResults(CharSequence constraint, FilterResults results) {
                mCurFilterPrefix = constraint;
                mEntries = (ArrayList<ApplicationsState.AppEntry>)results.values;
                notifyDataSetChanged();
                mTab.updateStorageUsage();
            }
        };

        public ApplicationsAdapter(ApplicationsState state, TabInfo tab, int filterMode) {
            mState = state;
            mSession = state.newSession(this);
            mTab = tab;
            mContext = tab.mOwner.getActivity();
            mFilterMode = filterMode;
        }

        public void resume(int sort) {
            if (DEBUG) Log.i(TAG, "Resume!  mResumed=" + mResumed);
            if (!mResumed) {
                mResumed = true;
                mSession.resume();
                mLastSortMode = sort;
                rebuild(true);
            } else {
                rebuild(sort);
            }
        }

        public void pause() {
            if (mResumed) {
                mResumed = false;
                mSession.pause();
            }
        }

        public void rebuild(int sort) {
            if (sort == mLastSortMode) {
                return;
            }
            mLastSortMode = sort;
            rebuild(true);
        }
        
        public void rebuild(boolean eraseold) {
            if (DEBUG) Log.i(TAG, "Rebuilding app list...");
            ApplicationsState.AppFilter filterObj;
            Comparator<AppEntry> comparatorObj;
            boolean emulated = Environment.isExternalStorageEmulated();
            if (emulated) {
                mWhichSize = SIZE_TOTAL;
            } else {
                mWhichSize = SIZE_INTERNAL;
            }
            switch (mFilterMode) {
                case FILTER_APPS_THIRD_PARTY:
                    filterObj = ApplicationsState.THIRD_PARTY_FILTER;
                    break;
                case FILTER_APPS_SDCARD:
                    filterObj = ApplicationsState.ON_SD_CARD_FILTER;
                    if (!emulated) {
                        mWhichSize = SIZE_EXTERNAL;
                    }
                    break;
                default:
                    filterObj = null;
                    break;
            }
            switch (mLastSortMode) {
                case SORT_ORDER_SIZE:
                    switch (mWhichSize) {
                        case SIZE_INTERNAL:
                            comparatorObj = ApplicationsState.INTERNAL_SIZE_COMPARATOR;
                            break;
                        case SIZE_EXTERNAL:
                            comparatorObj = ApplicationsState.EXTERNAL_SIZE_COMPARATOR;
                            break;
                        default:
                            comparatorObj = ApplicationsState.SIZE_COMPARATOR;
                            break;
                    }
                    break;
                default:
                    comparatorObj = ApplicationsState.ALPHA_COMPARATOR;
                    break;
            }
            ArrayList<ApplicationsState.AppEntry> entries
                    = mSession.rebuild(filterObj, comparatorObj);
            if (entries == null && !eraseold) {
                // Don't have new list yet, but can continue using the old one.
                return;
            }
            mBaseEntries = entries;
            if (mBaseEntries != null) {
                mEntries = applyPrefixFilter(mCurFilterPrefix, mBaseEntries);
            } else {
                mEntries = null;
            }
            notifyDataSetChanged();
            mTab.updateStorageUsage();

            if (entries == null) {
                mWaitingForData = true;
                mTab.mListContainer.setVisibility(View.INVISIBLE);
                mTab.mLoadingContainer.setVisibility(View.VISIBLE);
            } else {
                mTab.mListContainer.setVisibility(View.VISIBLE);
                mTab.mLoadingContainer.setVisibility(View.GONE);
            }
        }

        ArrayList<ApplicationsState.AppEntry> applyPrefixFilter(CharSequence prefix,
                ArrayList<ApplicationsState.AppEntry> origEntries) {
            if (prefix == null || prefix.length() == 0) {
                return origEntries;
            } else {
                String prefixStr = ApplicationsState.normalize(prefix.toString());
                final String spacePrefixStr = " " + prefixStr;
                ArrayList<ApplicationsState.AppEntry> newEntries
                        = new ArrayList<ApplicationsState.AppEntry>();
                for (int i=0; i<origEntries.size(); i++) {
                    ApplicationsState.AppEntry entry = origEntries.get(i);
                    String nlabel = entry.getNormalizedLabel();
                    if (nlabel.startsWith(prefixStr) || nlabel.indexOf(spacePrefixStr) != -1) {
                        newEntries.add(entry);
                    }
                }
                return newEntries;
            }
        }

        @Override
        public void onRunningStateChanged(boolean running) {
            mTab.mOwner.getActivity().setProgressBarIndeterminateVisibility(running);
        }

        @Override
        public void onRebuildComplete(ArrayList<AppEntry> apps) {
            if (mTab.mLoadingContainer.getVisibility() == View.VISIBLE) {
                mTab.mLoadingContainer.startAnimation(AnimationUtils.loadAnimation(
                        mContext, android.R.anim.fade_out));
                mTab.mListContainer.startAnimation(AnimationUtils.loadAnimation(
                        mContext, android.R.anim.fade_in));
            }
            mTab.mListContainer.setVisibility(View.VISIBLE);
            mTab.mLoadingContainer.setVisibility(View.GONE);
            mWaitingForData = false;
            mBaseEntries = apps;
            mEntries = applyPrefixFilter(mCurFilterPrefix, mBaseEntries);
            notifyDataSetChanged();
            mTab.updateStorageUsage();
        }

        @Override
        public void onPackageListChanged() {
            rebuild(false);
        }

        @Override
        public void onPackageIconChanged() {
            // We ensure icons are loaded when their item is displayed, so
            // don't care about icons loaded in the background.
        }

        @Override
        public void onPackageSizeChanged(String packageName) {
            for (int i=0; i<mActive.size(); i++) {
                AppViewHolder holder = (AppViewHolder)mActive.get(i).getTag();
                if (holder.entry.info.packageName.equals(packageName)) {
                    synchronized (holder.entry) {
                        holder.updateSizeText(mTab.mInvalidSizeStr, mWhichSize);
                    }
                    if (holder.entry.info.packageName.equals(mTab.mOwner.mCurrentPkgName)
                            && mLastSortMode == SORT_ORDER_SIZE) {
                        // We got the size information for the last app the
                        // user viewed, and are sorting by size...  they may
                        // have cleared data, so we immediately want to resort
                        // the list with the new size to reflect it to the user.
                        rebuild(false);
                    }
                    mTab.updateStorageUsage();
                    return;
                }
            }
        }

        @Override
        public void onAllSizesComputed() {
            if (mLastSortMode == SORT_ORDER_SIZE) {
                rebuild(false);
            }
            mTab.updateStorageUsage();
        }
        
        public int getCount() {
            return mEntries != null ? mEntries.size() : 0;
        }
        
        public Object getItem(int position) {
            return mEntries.get(position);
        }
        
        public ApplicationsState.AppEntry getAppEntry(int position) {
            return mEntries.get(position);
        }

        public long getItemId(int position) {
            return mEntries.get(position).id;
        }
        
        public View getView(int position, View convertView, ViewGroup parent) {
            // A ViewHolder keeps references to children views to avoid unnecessary calls
            // to findViewById() on each row.
            AppViewHolder holder = AppViewHolder.createOrRecycle(mTab.mInflater, convertView);
            convertView = holder.rootView;

            // Bind the data efficiently with the holder
            ApplicationsState.AppEntry entry = mEntries.get(position);
            synchronized (entry) {
                holder.entry = entry;
                if (entry.label != null) {
                    holder.appName.setText(entry.label);
                }
                mState.ensureIcon(entry);
                if (entry.icon != null) {
                    holder.appIcon.setImageDrawable(entry.icon);
                }
                holder.updateSizeText(mTab.mInvalidSizeStr, mWhichSize);
                if ((entry.info.flags&ApplicationInfo.FLAG_INSTALLED) == 0) {
                    holder.disabled.setVisibility(View.VISIBLE);
                    holder.disabled.setText(R.string.not_installed);
                } else if (!entry.info.enabled) {
                    holder.disabled.setVisibility(View.VISIBLE);
                    holder.disabled.setText(R.string.disabled);
                } else {
                    holder.disabled.setVisibility(View.GONE);
                }
                if (mFilterMode == FILTER_APPS_SDCARD) {
                    holder.checkBox.setVisibility(View.VISIBLE);
                    holder.checkBox.setChecked((entry.info.flags
                            & ApplicationInfo.FLAG_EXTERNAL_STORAGE) != 0);
                } else {
                    holder.checkBox.setVisibility(View.GONE);
                }
            }
            mActive.remove(convertView);
            mActive.add(convertView);
            return convertView;
        }

        @Override
        public Filter getFilter() {
            return mFilter;
        }

        @Override
        public void onMovedToScrapHeap(View view) {
            mActive.remove(view);
        }
    }
    
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        setHasOptionsMenu(true);

        mApplicationsState = ApplicationsState.getInstance(getActivity().getApplication());
        Intent intent = getActivity().getIntent();
        String action = intent.getAction();
        int defaultListType = LIST_TYPE_DOWNLOADED;
        String className = getArguments() != null
                ? getArguments().getString("classname") : null;
        if (className == null) {
            className = intent.getComponent().getClassName();
        }
        if (className.equals(RunningServicesActivity.class.getName())
                || className.endsWith(".RunningServices")) {
            defaultListType = LIST_TYPE_RUNNING;
        } else if (className.equals(StorageUseActivity.class.getName())
                || Intent.ACTION_MANAGE_PACKAGE_STORAGE.equals(action)
                || className.endsWith(".StorageUse")) {
            mSortOrder = SORT_ORDER_SIZE;
            defaultListType = LIST_TYPE_ALL;
        } else if (Settings.ACTION_MANAGE_ALL_APPLICATIONS_SETTINGS.equals(action)) {
            // Select the all-apps list, with the default sorting
            defaultListType = LIST_TYPE_ALL;
        }

        if (savedInstanceState != null) {
            mSortOrder = savedInstanceState.getInt(EXTRA_SORT_ORDER, mSortOrder);
            int tmp = savedInstanceState.getInt(EXTRA_DEFAULT_LIST_TYPE, -1);
            if (tmp != -1) defaultListType = tmp;
            mShowBackground = savedInstanceState.getBoolean(EXTRA_SHOW_BACKGROUND, false);
        }

        mDefaultListType = defaultListType;

        final Intent containerIntent = new Intent().setComponent(
                StorageMeasurement.DEFAULT_CONTAINER_COMPONENT);
        getActivity().bindService(containerIntent, mContainerConnection, Context.BIND_AUTO_CREATE);

        mInvalidSizeStr = getActivity().getText(R.string.invalid_size_value);
        mComputingSizeStr = getActivity().getText(R.string.computing_size);

        TabInfo tab = new TabInfo(this, mApplicationsState,
                getActivity().getString(R.string.filter_apps_third_party),
                LIST_TYPE_DOWNLOADED, this, savedInstanceState);
        mTabs.add(tab);

        if (!Environment.isExternalStorageEmulated()) {
            tab = new TabInfo(this, mApplicationsState,
                    getActivity().getString(R.string.filter_apps_onsdcard),
                    LIST_TYPE_SDCARD, this, savedInstanceState);
            mTabs.add(tab);
        }

        tab = new TabInfo(this, mApplicationsState,
                getActivity().getString(R.string.filter_apps_running),
                LIST_TYPE_RUNNING, this, savedInstanceState);
        mTabs.add(tab);

        tab = new TabInfo(this, mApplicationsState,
                getActivity().getString(R.string.filter_apps_all),
                LIST_TYPE_ALL, this, savedInstanceState);
        mTabs.add(tab);
    }


    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
        // initialize the inflater
        mInflater = inflater;

        View rootView = mInflater.inflate(R.layout.manage_applications_content,
                container, false);
        mContentContainer = container;
        mRootView = rootView;

        mViewPager = (ViewPager) rootView.findViewById(R.id.pager);
        MyPagerAdapter adapter = new MyPagerAdapter();
        mViewPager.setAdapter(adapter);
        mViewPager.setOnPageChangeListener(adapter);
        PagerTabStrip tabs = (PagerTabStrip) rootView.findViewById(R.id.tabs);
        tabs.setTabIndicatorColorResource(android.R.color.holo_blue_light);

        // We have to do this now because PreferenceFrameLayout looks at it
        // only when the view is added.
        if (container instanceof PreferenceFrameLayout) {
            ((PreferenceFrameLayout.LayoutParams) rootView.getLayoutParams()).removeBorders = true;
        }

        if (savedInstanceState != null && savedInstanceState.getBoolean(EXTRA_RESET_DIALOG)) {
            buildResetDialog();
        }

        if (savedInstanceState == null) {
            // First time init: make sure view pager is showing the correct tab.
            for (int i = 0; i < mTabs.size(); i++) {
                TabInfo tab = mTabs.get(i);
                if (tab.mListType == mDefaultListType) {
                    mViewPager.setCurrentItem(i);
                    break;
                }
            }
        }

        return rootView;
    }

    @Override
    public void onStart() {
        super.onStart();
    }

    @Override
    public void onResume() {
        super.onResume();
        mActivityResumed = true;
        updateCurrentTab(mViewPager.getCurrentItem());
        updateOptionsMenu();
    }

    @Override
    public void onSaveInstanceState(Bundle outState) {
        super.onSaveInstanceState(outState);
        outState.putInt(EXTRA_SORT_ORDER, mSortOrder);
        if (mDefaultListType != -1) {
            outState.putInt(EXTRA_DEFAULT_LIST_TYPE, mDefaultListType);
        }
        outState.putBoolean(EXTRA_SHOW_BACKGROUND, mShowBackground);
        if (mResetDialog != null) {
            outState.putBoolean(EXTRA_RESET_DIALOG, true);
        }
    }

    @Override
    public void onPause() {
        super.onPause();
        mActivityResumed = false;
        for (int i=0; i<mTabs.size(); i++) {
            mTabs.get(i).pause();
        }
    }

    @Override
    public void onStop() {
        super.onStop();
        if (mResetDialog != null) {
            mResetDialog.dismiss();
            mResetDialog = null;
        }
    }

    @Override
    public void onDestroyView() {
        super.onDestroyView();

        // We are going to keep the tab data structures around, but they
        // are no longer attached to their view hierarchy.
        for (int i=0; i<mTabs.size(); i++) {
            mTabs.get(i).detachView();
        }
    }

    @Override
    public void onActivityResult(int requestCode, int resultCode, Intent data) {
        if (requestCode == INSTALLED_APP_DETAILS && mCurrentPkgName != null) {
            mApplicationsState.requestSize(mCurrentPkgName);
        }
    }

    TabInfo tabForType(int type) {
        for (int i = 0; i < mTabs.size(); i++) {
            TabInfo tab = mTabs.get(i);
            if (tab.mListType == type) {
                return tab;
            }
        }
        return null;
    }

    // utility method used to start sub activity
    private void startApplicationDetailsActivity() {
        // start new fragment to display extended information
        Bundle args = new Bundle();
        args.putString(InstalledAppDetails.ARG_PACKAGE_NAME, mCurrentPkgName);

        PreferenceActivity pa = (PreferenceActivity)getActivity();
        pa.startPreferencePanel(InstalledAppDetails.class.getName(), args,
                R.string.application_info_label, null, this, INSTALLED_APP_DETAILS);
    }
    
    @Override
    public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
        mOptionsMenu = menu;
        // note: icons removed for now because the cause the new action
        // bar UI to be very confusing.
        menu.add(0, SORT_ORDER_ALPHA, 1, R.string.sort_order_alpha)
                //.setIcon(android.R.drawable.ic_menu_sort_alphabetically)
                .setShowAsAction(MenuItem.SHOW_AS_ACTION_NEVER);
        menu.add(0, SORT_ORDER_SIZE, 2, R.string.sort_order_size)
                //.setIcon(android.R.drawable.ic_menu_sort_by_size)
                .setShowAsAction(MenuItem.SHOW_AS_ACTION_NEVER);
        menu.add(0, SHOW_RUNNING_SERVICES, 3, R.string.show_running_services)
                .setShowAsAction(MenuItem.SHOW_AS_ACTION_IF_ROOM);
        menu.add(0, SHOW_BACKGROUND_PROCESSES, 3, R.string.show_background_processes)
                .setShowAsAction(MenuItem.SHOW_AS_ACTION_IF_ROOM);
        menu.add(0, RESET_APP_PREFERENCES, 4, R.string.reset_app_preferences)
                .setShowAsAction(MenuItem.SHOW_AS_ACTION_NEVER);
        updateOptionsMenu();
    }
    
    @Override
    public void onPrepareOptionsMenu(Menu menu) {
        updateOptionsMenu();
    }
    
    @Override
    public void onDestroyOptionsMenu() {
        mOptionsMenu = null;
    }

    @Override
    public void onDestroy() {
        getActivity().unbindService(mContainerConnection);
        super.onDestroy();
    }

    void updateOptionsMenu() {
        if (mOptionsMenu == null) {
            return;
        }
        
        /*
         * The running processes screen doesn't use the mApplicationsAdapter
         * so bringing up this menu in that case doesn't make any sense.
         */
        if (mCurTab != null && mCurTab.mListType == LIST_TYPE_RUNNING) {
            TabInfo tab = tabForType(LIST_TYPE_RUNNING);
            boolean showingBackground = tab != null && tab.mRunningProcessesView != null
                    ? tab.mRunningProcessesView.mAdapter.getShowBackground() : false;
            mOptionsMenu.findItem(SORT_ORDER_ALPHA).setVisible(false);
            mOptionsMenu.findItem(SORT_ORDER_SIZE).setVisible(false);
            mOptionsMenu.findItem(SHOW_RUNNING_SERVICES).setVisible(showingBackground);
            mOptionsMenu.findItem(SHOW_BACKGROUND_PROCESSES).setVisible(!showingBackground);
            mOptionsMenu.findItem(RESET_APP_PREFERENCES).setVisible(false);
        } else {
            mOptionsMenu.findItem(SORT_ORDER_ALPHA).setVisible(mSortOrder != SORT_ORDER_ALPHA);
            mOptionsMenu.findItem(SORT_ORDER_SIZE).setVisible(mSortOrder != SORT_ORDER_SIZE);
            mOptionsMenu.findItem(SHOW_RUNNING_SERVICES).setVisible(false);
            mOptionsMenu.findItem(SHOW_BACKGROUND_PROCESSES).setVisible(false);
            mOptionsMenu.findItem(RESET_APP_PREFERENCES).setVisible(true);
        }
    }

    void buildResetDialog() {
        if (mResetDialog == null) {
            AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
            builder.setTitle(R.string.reset_app_preferences_title);
            builder.setMessage(R.string.reset_app_preferences_desc);
            builder.setPositiveButton(R.string.reset_app_preferences_button, this);
            builder.setNegativeButton(R.string.cancel, null);
            mResetDialog = builder.show();
            mResetDialog.setOnDismissListener(this);
        }
    }

    @Override
    public void onDismiss(DialogInterface dialog) {
        if (mResetDialog == dialog) {
            mResetDialog = null;
        }
    }


    @Override
    public void onClick(DialogInterface dialog, int which) {
        if (mResetDialog == dialog) {
            final PackageManager pm = getActivity().getPackageManager();
            final INotificationManager nm = INotificationManager.Stub.asInterface(
                    ServiceManager.getService(Context.NOTIFICATION_SERVICE));
            final NetworkPolicyManager npm = NetworkPolicyManager.from(getActivity());
            final Handler handler = new Handler(getActivity().getMainLooper());
            (new AsyncTask<Void, Void, Void>() {
                @Override protected Void doInBackground(Void... params) {
                    List<ApplicationInfo> apps = pm.getInstalledApplications(
                            PackageManager.GET_DISABLED_COMPONENTS);
                    for (int i=0; i<apps.size(); i++) {
                        ApplicationInfo app = apps.get(i);
                        try {
                            if (DEBUG) Log.v(TAG, "Enabling notifications: " + app.packageName);
                            nm.setNotificationsEnabledForPackage(app.packageName, true);
                        } catch (android.os.RemoteException ex) {
                        }
                        if (DEBUG) Log.v(TAG, "Clearing preferred: " + app.packageName);
                        pm.clearPackagePreferredActivities(app.packageName);
                        if (!app.enabled) {
                            if (DEBUG) Log.v(TAG, "Enabling app: " + app.packageName);
                            if (pm.getApplicationEnabledSetting(app.packageName)
                                    == PackageManager.COMPONENT_ENABLED_STATE_DISABLED_USER) {
                                pm.setApplicationEnabledSetting(app.packageName,
                                        PackageManager.COMPONENT_ENABLED_STATE_DEFAULT,
                                        PackageManager.DONT_KILL_APP);
                            }
                        }
                    }
                    // We should have cleared all of the preferred apps above;
                    // just in case some may be lingering, retrieve whatever is
                    // still set and remove it.
                    ArrayList<IntentFilter> filters = new ArrayList<IntentFilter>();
                    ArrayList<ComponentName> prefActivities = new ArrayList<ComponentName>();
                    pm.getPreferredActivities(filters, prefActivities, null);
                    for (int i=0; i<prefActivities.size(); i++) {
                        if (DEBUG) Log.v(TAG, "Clearing preferred: "
                                + prefActivities.get(i).getPackageName());
                        pm.clearPackagePreferredActivities(prefActivities.get(i).getPackageName());
                    }
                    final int[] restrictedUids = npm.getUidsWithPolicy(
                            POLICY_REJECT_METERED_BACKGROUND);
                    final int currentUserId = ActivityManager.getCurrentUser();
                    for (int uid : restrictedUids) {
                        // Only reset for current user
                        if (UserHandle.getUserId(uid) == currentUserId) {
                            if (DEBUG) Log.v(TAG, "Clearing data policy: " + uid);
                            npm.setUidPolicy(uid, POLICY_NONE);
                        }
                    }
                    handler.post(new Runnable() {
                        @Override public void run() {
                            if (DEBUG) Log.v(TAG, "Done clearing");
                            if (getActivity() != null && mActivityResumed) {
                                if (DEBUG) Log.v(TAG, "Updating UI!");
                                for (int i=0; i<mTabs.size(); i++) {
                                    TabInfo tab = mTabs.get(i);
                                    if (tab.mApplications != null) {
                                        tab.mApplications.pause();
                                    }
                                }
                                if (mCurTab != null) {
                                    mCurTab.resume(mSortOrder);
                                }
                            }
                        }
                    });
                    return null;
                }
            }).execute();
        }
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        int menuId = item.getItemId();
        if ((menuId == SORT_ORDER_ALPHA) || (menuId == SORT_ORDER_SIZE)) {
            mSortOrder = menuId;
            if (mCurTab != null && mCurTab.mApplications != null) {
                mCurTab.mApplications.rebuild(mSortOrder);
            }
        } else if (menuId == SHOW_RUNNING_SERVICES) {
            mShowBackground = false;
            if (mCurTab != null && mCurTab.mRunningProcessesView != null) {
                mCurTab.mRunningProcessesView.mAdapter.setShowBackground(false);
            }
        } else if (menuId == SHOW_BACKGROUND_PROCESSES) {
            mShowBackground = true;
            if (mCurTab != null && mCurTab.mRunningProcessesView != null) {
                mCurTab.mRunningProcessesView.mAdapter.setShowBackground(true);
            }
        } else if (menuId == RESET_APP_PREFERENCES) {
            buildResetDialog();
        } else {
            // Handle the home button
            return false;
        }
        updateOptionsMenu();
        return true;
    }
    
    public void onItemClick(TabInfo tab, AdapterView<?> parent, View view, int position,
            long id) {
        if (tab.mApplications != null && tab.mApplications.getCount() > position) {
            ApplicationsState.AppEntry entry = tab.mApplications.getAppEntry(position);
            mCurrentPkgName = entry.info.packageName;
            startApplicationDetailsActivity();
        }
    }

    public void updateCurrentTab(int position) {
        TabInfo tab = mTabs.get(position);
        mCurTab = tab;

        // Put things in the correct paused/resumed state.
        if (mActivityResumed) {
            mCurTab.build(mInflater, mContentContainer, mRootView);
            mCurTab.resume(mSortOrder);
        } else {
            mCurTab.pause();
        }
        for (int i=0; i<mTabs.size(); i++) {
            TabInfo t = mTabs.get(i);
            if (t != mCurTab) {
                t.pause();
            }
        }

        mCurTab.updateStorageUsage();
        updateOptionsMenu();
        final Activity host = getActivity();
        if (host != null) {
            host.invalidateOptionsMenu();
        }
    }

    private volatile IMediaContainerService mContainerService;

    private final ServiceConnection mContainerConnection = new ServiceConnection() {
        @Override
        public void onServiceConnected(ComponentName name, IBinder service) {
            mContainerService = IMediaContainerService.Stub.asInterface(service);
            for (int i=0; i<mTabs.size(); i++) {
                mTabs.get(i).setContainerService(mContainerService);
            }
        }

        @Override
        public void onServiceDisconnected(ComponentName name) {
            mContainerService = null;
        }
    };
}
