/*
 * Copyright (C) 2010 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 com.android.settings.R;
import com.android.settings.users.UserUtils;

import android.app.ActivityManager;
import android.app.ActivityManagerNative;
import android.app.ActivityThread;
import android.content.ComponentName;
import android.content.Context;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageInfo;
import android.content.pm.PackageItemInfo;
import android.content.pm.PackageManager;
import android.content.pm.ServiceInfo;
import android.content.pm.UserInfo;
import android.content.res.Resources;
import android.graphics.drawable.Drawable;
import android.os.Handler;
import android.os.HandlerThread;
import android.os.Looper;
import android.os.Message;
import android.os.RemoteException;
import android.os.UserHandle;
import android.os.UserManager;
import android.text.format.Formatter;
import android.util.Log;
import android.util.SparseArray;

import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;

/**
 * Singleton for retrieving and monitoring the state about all running
 * applications/processes/services.
 */
public class RunningState {
    static final String TAG = "RunningState";
    static final boolean DEBUG_COMPARE = false;

    static Object sGlobalLock = new Object();
    static RunningState sInstance;

    static final int MSG_RESET_CONTENTS = 1;
    static final int MSG_UPDATE_CONTENTS = 2;
    static final int MSG_REFRESH_UI = 3;
    static final int MSG_UPDATE_TIME = 4;

    static final long TIME_UPDATE_DELAY = 1000;
    static final long CONTENTS_UPDATE_DELAY = 2000;

    static final int MAX_SERVICES = 100;

    final Context mApplicationContext;
    final ActivityManager mAm;
    final PackageManager mPm;
    final UserManager mUm;
    final int mMyUserId;

    OnRefreshUiListener mRefreshUiListener;

    final InterestingConfigChanges mInterestingConfigChanges = new InterestingConfigChanges();

    // Processes that are hosting a service we are interested in, organized
    // by uid and name.  Note that this mapping does not change even across
    // service restarts, and during a restart there will still be a process
    // entry.
    final SparseArray<HashMap<String, ProcessItem>> mServiceProcessesByName
            = new SparseArray<HashMap<String, ProcessItem>>();
    
    // Processes that are hosting a service we are interested in, organized
    // by their pid.  These disappear and re-appear as services are restarted.
    final SparseArray<ProcessItem> mServiceProcessesByPid
            = new SparseArray<ProcessItem>();
    
    // Used to sort the interesting processes.
    final ServiceProcessComparator mServiceProcessComparator
            = new ServiceProcessComparator();
    
    // Additional interesting processes to be shown to the user, even if
    // there is no service running in them.
    final ArrayList<ProcessItem> mInterestingProcesses = new ArrayList<ProcessItem>();
    
    // All currently running processes, for finding dependencies etc.
    final SparseArray<ProcessItem> mRunningProcesses
            = new SparseArray<ProcessItem>();
    
    // The processes associated with services, in sorted order.
    final ArrayList<ProcessItem> mProcessItems = new ArrayList<ProcessItem>();
    
    // All processes, used for retrieving memory information.
    final ArrayList<ProcessItem> mAllProcessItems = new ArrayList<ProcessItem>();

    // If there are other users on the device, these are the merged items
    // representing all items that would be put in mMergedItems for that user.
    final SparseArray<MergedItem> mOtherUserMergedItems = new SparseArray<MergedItem>();

    // If there are other users on the device, these are the merged items
    // representing all items that would be put in mUserBackgroundItems for that user.
    final SparseArray<MergedItem> mOtherUserBackgroundItems = new SparseArray<MergedItem>();

    // Tracking of information about users.
    final SparseArray<UserState> mUsers = new SparseArray<UserState>();

    static class AppProcessInfo {
        final ActivityManager.RunningAppProcessInfo info;
        boolean hasServices;
        boolean hasForegroundServices;

        AppProcessInfo(ActivityManager.RunningAppProcessInfo _info) {
            info = _info;
        }
    }

    // Temporary structure used when updating above information.
    final SparseArray<AppProcessInfo> mTmpAppProcesses = new SparseArray<AppProcessInfo>();

    int mSequence = 0;

    final Comparator<RunningState.MergedItem> mBackgroundComparator
        = new Comparator<RunningState.MergedItem>() {
            @Override
            public int compare(MergedItem lhs, MergedItem rhs) {
                if (DEBUG_COMPARE) {
                    Log.i(TAG, "Comparing " + lhs + " with " + rhs);
                    Log.i(TAG, "     Proc " + lhs.mProcess + " with " + rhs.mProcess);
                    Log.i(TAG, "   UserId " + lhs.mUserId + " with " + rhs.mUserId);
                }
                if (lhs.mUserId != rhs.mUserId) {
                    if (lhs.mUserId == mMyUserId) return -1;
                    if (rhs.mUserId == mMyUserId) return 1;
                    return lhs.mUserId < rhs.mUserId ? -1 : 1;
                }
                if (lhs.mProcess == rhs.mProcess) {
                    if (lhs.mLabel == rhs.mLabel) {
                        return 0;
                    }
                    return lhs.mLabel != null ? lhs.mLabel.compareTo(rhs.mLabel) : -1;
                }
                if (lhs.mProcess == null) return -1;
                if (rhs.mProcess == null) return 1;
                if (DEBUG_COMPARE) Log.i(TAG, "    Label " + lhs.mProcess.mLabel
                        + " with " + rhs.mProcess.mLabel);
                final ActivityManager.RunningAppProcessInfo lhsInfo
                        = lhs.mProcess.mRunningProcessInfo;
                final ActivityManager.RunningAppProcessInfo rhsInfo
                        = rhs.mProcess.mRunningProcessInfo;
                final boolean lhsBg = lhsInfo.importance
                        >= ActivityManager.RunningAppProcessInfo.IMPORTANCE_BACKGROUND;
                final boolean rhsBg = rhsInfo.importance
                        >= ActivityManager.RunningAppProcessInfo.IMPORTANCE_BACKGROUND;
                        if (DEBUG_COMPARE) Log.i(TAG, "       Bg " + lhsBg + " with " + rhsBg);
                if (lhsBg != rhsBg) {
                    return lhsBg ? 1 : -1;
                }
                final boolean lhsA = (lhsInfo.flags
                        & ActivityManager.RunningAppProcessInfo.FLAG_HAS_ACTIVITIES) != 0;
                final boolean rhsA = (rhsInfo.flags
                        & ActivityManager.RunningAppProcessInfo.FLAG_HAS_ACTIVITIES) != 0;
                if (DEBUG_COMPARE) Log.i(TAG, "      Act " + lhsA + " with " + rhsA);
                if (lhsA != rhsA) {
                    return lhsA ? -1 : 1;
                }
                if (DEBUG_COMPARE) Log.i(TAG, "      Lru " + lhsInfo.lru + " with " + rhsInfo.lru);
                if (lhsInfo.lru != rhsInfo.lru) {
                    return lhsInfo.lru < rhsInfo.lru ? -1 : 1;
                }
                if (lhs.mProcess.mLabel == rhs.mProcess.mLabel) {
                    return 0;
                }
                if (lhs.mProcess.mLabel == null) return 1;
                if (rhs.mProcess.mLabel == null) return -1;
                return lhs.mProcess.mLabel.compareTo(rhs.mProcess.mLabel);
            }
    };

    // ----- following protected by mLock -----
    
    // Lock for protecting the state that will be shared between the
    // background update thread and the UI thread.
    final Object mLock = new Object();
    
    boolean mResumed;
    boolean mHaveData;
    boolean mWatchingBackgroundItems;

    ArrayList<BaseItem> mItems = new ArrayList<BaseItem>();
    ArrayList<MergedItem> mMergedItems = new ArrayList<MergedItem>();
    ArrayList<MergedItem> mBackgroundItems = new ArrayList<MergedItem>();
    ArrayList<MergedItem> mUserBackgroundItems = new ArrayList<MergedItem>();
    
    int mNumBackgroundProcesses;
    long mBackgroundProcessMemory;
    int mNumForegroundProcesses;
    long mForegroundProcessMemory;
    int mNumServiceProcesses;
    long mServiceProcessMemory;

    // ----- BACKGROUND MONITORING THREAD -----

    final HandlerThread mBackgroundThread;
    final class BackgroundHandler extends Handler {
        public BackgroundHandler(Looper looper) {
            super(looper);
        }

        @Override
        public void handleMessage(Message msg) {
            switch (msg.what) {
                case MSG_RESET_CONTENTS:
                    reset();
                    break;
                case MSG_UPDATE_CONTENTS:
                    synchronized (mLock) {
                        if (!mResumed) {
                            return;
                        }
                    }
                    Message cmd = mHandler.obtainMessage(MSG_REFRESH_UI);
                    cmd.arg1 = update(mApplicationContext, mAm) ? 1 : 0;
                    mHandler.sendMessage(cmd);
                    removeMessages(MSG_UPDATE_CONTENTS);
                    msg = obtainMessage(MSG_UPDATE_CONTENTS);
                    sendMessageDelayed(msg, CONTENTS_UPDATE_DELAY);
                    break;
            }
        }
    };

    final BackgroundHandler mBackgroundHandler;

    final Handler mHandler = new Handler() {
        int mNextUpdate = OnRefreshUiListener.REFRESH_TIME;

        @Override
        public void handleMessage(Message msg) {
            switch (msg.what) {
                case MSG_REFRESH_UI:
                    mNextUpdate = msg.arg1 != 0
                            ? OnRefreshUiListener.REFRESH_STRUCTURE
                            : OnRefreshUiListener.REFRESH_DATA;
                    break;
                case MSG_UPDATE_TIME:
                    synchronized (mLock) {
                        if (!mResumed) {
                            return;
                        }
                    }
                    removeMessages(MSG_UPDATE_TIME);
                    Message m = obtainMessage(MSG_UPDATE_TIME);
                    sendMessageDelayed(m, TIME_UPDATE_DELAY);

                    if (mRefreshUiListener != null) {
                        //Log.i("foo", "Refresh UI: " + mNextUpdate
                        //        + " @ " + SystemClock.uptimeMillis());
                        mRefreshUiListener.onRefreshUi(mNextUpdate);
                        mNextUpdate = OnRefreshUiListener.REFRESH_TIME;
                    }
                    break;
            }
        }
    };

    // ----- DATA STRUCTURES -----

    static interface OnRefreshUiListener {
        public static final int REFRESH_TIME = 0;
        public static final int REFRESH_DATA = 1;
        public static final int REFRESH_STRUCTURE = 2;

        public void onRefreshUi(int what);
    }

    static class UserState {
        UserInfo mInfo;
        String mLabel;
        Drawable mIcon;
    }

    static class BaseItem {
        final boolean mIsProcess;
        final int mUserId;

        PackageItemInfo mPackageInfo;
        CharSequence mDisplayLabel;
        String mLabel;
        String mDescription;

        int mCurSeq;

        long mActiveSince;
        long mSize;
        String mSizeStr;
        String mCurSizeStr;
        boolean mNeedDivider;
        boolean mBackground;

        public BaseItem(boolean isProcess, int userId) {
            mIsProcess = isProcess;
            mUserId = userId;
        }

        public Drawable loadIcon(Context context, RunningState state) {
            if (mPackageInfo != null) {
                return mPackageInfo.loadIcon(state.mPm);
            }
            return null;
        }
    }

    static class ServiceItem extends BaseItem {
        ActivityManager.RunningServiceInfo mRunningService;
        ServiceInfo mServiceInfo;
        boolean mShownAsStarted;
        
        MergedItem mMergedItem;
        
        public ServiceItem(int userId) {
            super(false, userId);
        }
    }

    static class ProcessItem extends BaseItem {
        final HashMap<ComponentName, ServiceItem> mServices
                = new HashMap<ComponentName, ServiceItem>();
        final SparseArray<ProcessItem> mDependentProcesses
                = new SparseArray<ProcessItem>();
        
        final int mUid;
        final String mProcessName;
        int mPid;
        
        ProcessItem mClient;
        int mLastNumDependentProcesses;
        
        int mRunningSeq;
        ActivityManager.RunningAppProcessInfo mRunningProcessInfo;
        
        MergedItem mMergedItem;

        boolean mInteresting;

        // Purely for sorting.
        boolean mIsSystem;
        boolean mIsStarted;
        long mActiveSince;
        
        public ProcessItem(Context context, int uid, String processName) {
            super(true, UserHandle.getUserId(uid));
            mDescription = context.getResources().getString(
                    R.string.service_process_name, processName);
            mUid = uid;
            mProcessName = processName;
        }
        
        void ensureLabel(PackageManager pm) {
            if (mLabel != null) {
                return;
            }
            
            try {
                ApplicationInfo ai = pm.getApplicationInfo(mProcessName,
                        PackageManager.GET_UNINSTALLED_PACKAGES);
                if (ai.uid == mUid) {
                    mDisplayLabel = ai.loadLabel(pm);
                    mLabel = mDisplayLabel.toString();
                    mPackageInfo = ai;
                    return;
                }
            } catch (PackageManager.NameNotFoundException e) {
            }
            
            // If we couldn't get information about the overall
            // process, try to find something about the uid.
            String[] pkgs = pm.getPackagesForUid(mUid);
            
            // If there is one package with this uid, that is what we want.
            if (pkgs.length == 1) {
                try {
                    ApplicationInfo ai = pm.getApplicationInfo(pkgs[0],
                            PackageManager.GET_UNINSTALLED_PACKAGES);
                    mDisplayLabel = ai.loadLabel(pm);
                    mLabel = mDisplayLabel.toString();
                    mPackageInfo = ai;
                    return;
                } catch (PackageManager.NameNotFoundException e) {
                }
            }
            
            // If there are multiple, see if one gives us the official name
            // for this uid.
            for (String name : pkgs) {
                try {
                    PackageInfo pi = pm.getPackageInfo(name, 0);
                    if (pi.sharedUserLabel != 0) {
                        CharSequence nm = pm.getText(name,
                                pi.sharedUserLabel, pi.applicationInfo);
                        if (nm != null) {
                            mDisplayLabel = nm;
                            mLabel = nm.toString();
                            mPackageInfo = pi.applicationInfo;
                            return;
                        }
                    }
                } catch (PackageManager.NameNotFoundException e) {
                }
            }
            
            // If still don't have anything to display, just use the
            // service info.
            if (mServices.size() > 0) {
                ApplicationInfo ai = mServices.values().iterator().next()
                        .mServiceInfo.applicationInfo;
                mPackageInfo = ai;
                mDisplayLabel = mPackageInfo.loadLabel(pm);
                mLabel = mDisplayLabel.toString();
                return;
            }
            
            // Finally... whatever, just pick the first package's name.
            try {
                ApplicationInfo ai = pm.getApplicationInfo(pkgs[0],
                        PackageManager.GET_UNINSTALLED_PACKAGES);
                mDisplayLabel = ai.loadLabel(pm);
                mLabel = mDisplayLabel.toString();
                mPackageInfo = ai;
                return;
            } catch (PackageManager.NameNotFoundException e) {
            }
        }

        boolean updateService(Context context, ActivityManager.RunningServiceInfo service) {
            final PackageManager pm = context.getPackageManager();

            boolean changed = false;
            ServiceItem si = mServices.get(service.service);
            if (si == null) {
                changed = true;
                si = new ServiceItem(mUserId);
                si.mRunningService = service;
                try {
                    si.mServiceInfo = ActivityThread.getPackageManager().getServiceInfo(
                            service.service, PackageManager.GET_UNINSTALLED_PACKAGES,
                            UserHandle.getUserId(service.uid));
                } catch (RemoteException e) {
                }
                si.mDisplayLabel = makeLabel(pm,
                        si.mRunningService.service.getClassName(), si.mServiceInfo);
                mLabel = mDisplayLabel != null ? mDisplayLabel.toString() : null;
                si.mPackageInfo = si.mServiceInfo.applicationInfo;
                mServices.put(service.service, si);
            }
            si.mCurSeq = mCurSeq;
            si.mRunningService = service;
            long activeSince = service.restarting == 0 ? service.activeSince : -1;
            if (si.mActiveSince != activeSince) {
                si.mActiveSince = activeSince;
                changed = true;
            }
            if (service.clientPackage != null && service.clientLabel != 0) {
                if (si.mShownAsStarted) {
                    si.mShownAsStarted = false;
                    changed = true;
                }
                try {
                    Resources clientr = pm.getResourcesForApplication(service.clientPackage);
                    String label = clientr.getString(service.clientLabel);
                    si.mDescription = context.getResources().getString(
                            R.string.service_client_name, label);
                } catch (PackageManager.NameNotFoundException e) {
                    si.mDescription = null;
                }
            } else {
                if (!si.mShownAsStarted) {
                    si.mShownAsStarted = true;
                    changed = true;
                }
                si.mDescription = context.getResources().getString(
                        R.string.service_started_by_app);
            }
            
            return changed;
        }
        
        boolean updateSize(Context context, long pss, int curSeq) {
            mSize = pss * 1024;
            if (mCurSeq == curSeq) {
                String sizeStr = Formatter.formatShortFileSize(
                        context, mSize);
                if (!sizeStr.equals(mSizeStr)){
                    mSizeStr = sizeStr;
                    // We update this on the second tick where we update just
                    // the text in the current items, so no need to say we
                    // changed here.
                    return false;
                }
            }
            return false;
        }
        
        boolean buildDependencyChain(Context context, PackageManager pm, int curSeq) {
            final int NP = mDependentProcesses.size();
            boolean changed = false;
            for (int i=0; i<NP; i++) {
                ProcessItem proc = mDependentProcesses.valueAt(i);
                if (proc.mClient != this) {
                    changed = true;
                    proc.mClient = this;
                }
                proc.mCurSeq = curSeq;
                proc.ensureLabel(pm);
                changed |= proc.buildDependencyChain(context, pm, curSeq);
            }
            
            if (mLastNumDependentProcesses != mDependentProcesses.size()) {
                changed = true;
                mLastNumDependentProcesses = mDependentProcesses.size();
            }
            
            return changed;
        }
        
        void addDependentProcesses(ArrayList<BaseItem> dest,
                ArrayList<ProcessItem> destProc) {
            final int NP = mDependentProcesses.size();
            for (int i=0; i<NP; i++) {
                ProcessItem proc = mDependentProcesses.valueAt(i);
                proc.addDependentProcesses(dest, destProc);
                dest.add(proc);
                if (proc.mPid > 0) {
                    destProc.add(proc);
                }
            }
        }
    }

    static class MergedItem extends BaseItem {
        ProcessItem mProcess;
        UserState mUser;
        final ArrayList<ProcessItem> mOtherProcesses = new ArrayList<ProcessItem>();
        final ArrayList<ServiceItem> mServices = new ArrayList<ServiceItem>();
        final ArrayList<MergedItem> mChildren = new ArrayList<MergedItem>();
        
        private int mLastNumProcesses = -1, mLastNumServices = -1;

        MergedItem(int userId) {
            super(false, userId);
        }

        private void setDescription(Context context, int numProcesses, int numServices) {
            if (mLastNumProcesses != numProcesses || mLastNumServices != numServices) {
                mLastNumProcesses = numProcesses;
                mLastNumServices = numServices;
                int resid = R.string.running_processes_item_description_s_s;
                if (numProcesses != 1) {
                    resid = numServices != 1
                            ? R.string.running_processes_item_description_p_p
                            : R.string.running_processes_item_description_p_s;
                } else if (numServices != 1) {
                    resid = R.string.running_processes_item_description_s_p;
                }
                mDescription = context.getResources().getString(resid, numProcesses,
                        numServices);
            }
        }

        boolean update(Context context, boolean background) {
            mBackground = background;

            if (mUser != null) {
                // This is a merged item that contains a child collection
                // of items...  that is, it is an entire user, containing
                // everything associated with that user.  So set it up as such.
                // For concrete stuff we need about the process of this item,
                // we will just use the info from the first child.
                MergedItem child0 = mChildren.get(0);
                mPackageInfo = child0.mProcess.mPackageInfo;
                mLabel = mUser != null ? mUser.mLabel : null;
                mDisplayLabel = mLabel;
                int numProcesses = 0;
                int numServices = 0;
                mActiveSince = -1;
                for (int i=0; i<mChildren.size(); i++) {
                    MergedItem child = mChildren.get(i);
                    numProcesses += child.mLastNumProcesses;
                    numServices += child.mLastNumServices;
                    if (child.mActiveSince >= 0 && mActiveSince < child.mActiveSince) {
                        mActiveSince = child.mActiveSince;
                    }
                }
                if (!mBackground) {
                    setDescription(context, numProcesses, numServices);
                }
            } else {
                mPackageInfo = mProcess.mPackageInfo;
                mDisplayLabel = mProcess.mDisplayLabel;
                mLabel = mProcess.mLabel;
                
                if (!mBackground) {
                    setDescription(context, (mProcess.mPid > 0 ? 1 : 0) + mOtherProcesses.size(),
                            mServices.size());
                }
                
                mActiveSince = -1;
                for (int i=0; i<mServices.size(); i++) {
                    ServiceItem si = mServices.get(i);
                    if (si.mActiveSince >= 0 && mActiveSince < si.mActiveSince) {
                        mActiveSince = si.mActiveSince;
                    }
                }
            }

            return false;
        }
        
        boolean updateSize(Context context) {
            if (mUser != null) {
                mSize = 0;
                for (int i=0; i<mChildren.size(); i++) {
                    MergedItem child = mChildren.get(i);
                    child.updateSize(context);
                    mSize += child.mSize;
                }
            } else {
                mSize = mProcess.mSize;
                for (int i=0; i<mOtherProcesses.size(); i++) {
                    mSize += mOtherProcesses.get(i).mSize;
                }
            }
            
            String sizeStr = Formatter.formatShortFileSize(
                    context, mSize);
            if (!sizeStr.equals(mSizeStr)){
                mSizeStr = sizeStr;
                // We update this on the second tick where we update just
                // the text in the current items, so no need to say we
                // changed here.
                return false;
            }
            return false;
        }

        public Drawable loadIcon(Context context, RunningState state) {
            if (mUser == null) {
                return super.loadIcon(context, state);
            }
            if (mUser.mIcon != null) {
                return mUser.mIcon.getConstantState().newDrawable();
            }
            return context.getResources().getDrawable(
                    com.android.internal.R.drawable.ic_menu_cc);
        }
    }

    class ServiceProcessComparator implements Comparator<ProcessItem> {
        public int compare(ProcessItem object1, ProcessItem object2) {
            if (object1.mUserId != object2.mUserId) {
                if (object1.mUserId == mMyUserId) return -1;
                if (object2.mUserId == mMyUserId) return 1;
                return object1.mUserId < object2.mUserId ? -1 : 1;
            }
            if (object1.mIsStarted != object2.mIsStarted) {
                // Non-started processes go last.
                return object1.mIsStarted ? -1 : 1;
            }
            if (object1.mIsSystem != object2.mIsSystem) {
                // System processes go below non-system.
                return object1.mIsSystem ? 1 : -1;
            }
            if (object1.mActiveSince != object2.mActiveSince) {
                // Remaining ones are sorted with the longest running
                // services last.
                return (object1.mActiveSince > object2.mActiveSince) ? -1 : 1;
            }
            return 0;
        }
    }
    
    static CharSequence makeLabel(PackageManager pm,
            String className, PackageItemInfo item) {
        if (item != null && (item.labelRes != 0
                || item.nonLocalizedLabel != null)) {
            CharSequence label = item.loadLabel(pm);
            if (label != null) {
                return label;
            }
        }
        
        String label = className;
        int tail = label.lastIndexOf('.');
        if (tail >= 0) {
            label = label.substring(tail+1, label.length());
        }
        return label;
    }
    
    static RunningState getInstance(Context context) {
        synchronized (sGlobalLock) {
            if (sInstance == null) {
                sInstance = new RunningState(context);
            }
            return sInstance;
        }
    }

    private RunningState(Context context) {
        mApplicationContext = context.getApplicationContext();
        mAm = (ActivityManager)mApplicationContext.getSystemService(Context.ACTIVITY_SERVICE);
        mPm = mApplicationContext.getPackageManager();
        mUm = (UserManager)mApplicationContext.getSystemService(Context.USER_SERVICE);
        mMyUserId = UserHandle.myUserId();
        mResumed = false;
        mBackgroundThread = new HandlerThread("RunningState:Background");
        mBackgroundThread.start();
        mBackgroundHandler = new BackgroundHandler(mBackgroundThread.getLooper());
    }

    void resume(OnRefreshUiListener listener) {
        synchronized (mLock) {
            mResumed = true;
            mRefreshUiListener = listener;
            if (mInterestingConfigChanges.applyNewConfig(mApplicationContext.getResources())) {
                mHaveData = false;
                mBackgroundHandler.removeMessages(MSG_RESET_CONTENTS);
                mBackgroundHandler.removeMessages(MSG_UPDATE_CONTENTS);
                mBackgroundHandler.sendEmptyMessage(MSG_RESET_CONTENTS);
            }
            if (!mBackgroundHandler.hasMessages(MSG_UPDATE_CONTENTS)) {
                mBackgroundHandler.sendEmptyMessage(MSG_UPDATE_CONTENTS);
            }
            mHandler.sendEmptyMessage(MSG_UPDATE_TIME);
        }
    }

    void updateNow() {
        synchronized (mLock) {
            mBackgroundHandler.removeMessages(MSG_UPDATE_CONTENTS);
            mBackgroundHandler.sendEmptyMessage(MSG_UPDATE_CONTENTS);
        }
    }

    boolean hasData() {
        synchronized (mLock) {
            return mHaveData;
        }
    }

    void waitForData() {
        synchronized (mLock) {
            while (!mHaveData) {
                try {
                    mLock.wait(0);
                } catch (InterruptedException e) {
                }
            }
        }
    }

    void pause() {
        synchronized (mLock) {
            mResumed = false;
            mRefreshUiListener = null;
            mHandler.removeMessages(MSG_UPDATE_TIME);
        }
    }

    private boolean isInterestingProcess(ActivityManager.RunningAppProcessInfo pi) {
        if ((pi.flags&ActivityManager.RunningAppProcessInfo.FLAG_CANT_SAVE_STATE) != 0) {
            return true;
        }
        if ((pi.flags&ActivityManager.RunningAppProcessInfo.FLAG_PERSISTENT) == 0
                && pi.importance >= ActivityManager.RunningAppProcessInfo.IMPORTANCE_FOREGROUND
                && pi.importance < ActivityManager.RunningAppProcessInfo.IMPORTANCE_CANT_SAVE_STATE
                && pi.importanceReasonCode
                        == ActivityManager.RunningAppProcessInfo.REASON_UNKNOWN) {
            return true;
        }
        return false;
    }

    private void reset() {
        mServiceProcessesByName.clear();
        mServiceProcessesByPid.clear();
        mInterestingProcesses.clear();
        mRunningProcesses.clear();
        mProcessItems.clear();
        mAllProcessItems.clear();
        mUsers.clear();
    }

    private void addOtherUserItem(Context context, ArrayList<MergedItem> newMergedItems,
            SparseArray<MergedItem> userItems, MergedItem newItem) {
        MergedItem userItem = userItems.get(newItem.mUserId);
        boolean first = userItem == null || userItem.mCurSeq != mSequence;
        if (first) {
            if (userItem == null) {
                userItem = new MergedItem(newItem.mUserId);
                userItems.put(newItem.mUserId, userItem);
            } else {
                userItem.mChildren.clear();
            }
            userItem.mCurSeq = mSequence;
            if ((userItem.mUser=mUsers.get(newItem.mUserId)) == null) {
                userItem.mUser = new UserState();
                UserInfo info = mUm.getUserInfo(newItem.mUserId);
                userItem.mUser.mInfo = info;
                if (info != null) {
                    userItem.mUser.mIcon = UserUtils.getUserIcon(mUm, info,
                            context.getResources());
                }
                String name = info != null ? info.name : null;
                if (name == null) {
                    name = Integer.toString(info.id);
                }
                userItem.mUser.mLabel = context.getResources().getString(
                        R.string.running_process_item_user_label, name);
            }
            newMergedItems.add(userItem);
        }
        userItem.mChildren.add(newItem);
    }

    private boolean update(Context context, ActivityManager am) {
        final PackageManager pm = context.getPackageManager();
        
        mSequence++;
        
        boolean changed = false;

        // Retrieve list of services, filtering out anything that definitely
        // won't be shown in the UI.
        List<ActivityManager.RunningServiceInfo> services 
                = am.getRunningServices(MAX_SERVICES);
        int NS = services != null ? services.size() : 0;
        for (int i=0; i<NS; i++) {
            ActivityManager.RunningServiceInfo si = services.get(i);
            // We are not interested in services that have not been started
            // and don't have a known client, because
            // there is nothing the user can do about them.
            if (!si.started && si.clientLabel == 0) {
                services.remove(i);
                i--;
                NS--;
                continue;
            }
            // We likewise don't care about services running in a
            // persistent process like the system or phone.
            if ((si.flags&ActivityManager.RunningServiceInfo.FLAG_PERSISTENT_PROCESS)
                    != 0) {
                services.remove(i);
                i--;
                NS--;
                continue;
            }
        }

        // Retrieve list of running processes, organizing them into a sparse
        // array for easy retrieval.
        List<ActivityManager.RunningAppProcessInfo> processes
                = am.getRunningAppProcesses();
        final int NP = processes != null ? processes.size() : 0;
        mTmpAppProcesses.clear();
        for (int i=0; i<NP; i++) {
            ActivityManager.RunningAppProcessInfo pi = processes.get(i);
            mTmpAppProcesses.put(pi.pid, new AppProcessInfo(pi));
        }

        // Initial iteration through running services to collect per-process
        // info about them.
        for (int i=0; i<NS; i++) {
            ActivityManager.RunningServiceInfo si = services.get(i);
            if (si.restarting == 0 && si.pid > 0) {
                AppProcessInfo ainfo = mTmpAppProcesses.get(si.pid);
                if (ainfo != null) {
                    ainfo.hasServices = true;
                    if (si.foreground) {
                        ainfo.hasForegroundServices = true;
                    }
                }
            }
        }

        // Update state we are maintaining about process that are running services.
        for (int i=0; i<NS; i++) {
            ActivityManager.RunningServiceInfo si = services.get(i);

            // If this service's process is in use at a higher importance
            // due to another process bound to one of its services, then we
            // won't put it in the top-level list of services.  Instead we
            // want it to be included in the set of processes that the other
            // process needs.
            if (si.restarting == 0 && si.pid > 0) {
                AppProcessInfo ainfo = mTmpAppProcesses.get(si.pid);
                if (ainfo != null && !ainfo.hasForegroundServices) {
                    // This process does not have any foreground services.
                    // If its importance is greater than the service importance
                    // then there is something else more significant that is
                    // keeping it around that it should possibly be included as
                    // a part of instead of being shown by itself.
                    if (ainfo.info.importance
                            < ActivityManager.RunningAppProcessInfo.IMPORTANCE_SERVICE) {
                        // Follow process chain to see if there is something
                        // else that could be shown
                        boolean skip = false;
                        ainfo = mTmpAppProcesses.get(ainfo.info.importanceReasonPid);
                        while (ainfo != null) {
                            if (ainfo.hasServices || isInterestingProcess(ainfo.info)) {
                                skip = true;
                                break;
                            }
                            ainfo = mTmpAppProcesses.get(ainfo.info.importanceReasonPid);
                        }
                        if (skip) {
                            continue;
                        }
                    }
                }
            }

            HashMap<String, ProcessItem> procs = mServiceProcessesByName.get(si.uid);
            if (procs == null) {
                procs = new HashMap<String, ProcessItem>();
                mServiceProcessesByName.put(si.uid, procs);
            }
            ProcessItem proc = procs.get(si.process);
            if (proc == null) {
                changed = true;
                proc = new ProcessItem(context, si.uid, si.process);
                procs.put(si.process, proc);
            }
            
            if (proc.mCurSeq != mSequence) {
                int pid = si.restarting == 0 ? si.pid : 0;
                if (pid != proc.mPid) {
                    changed = true;
                    if (proc.mPid != pid) {
                        if (proc.mPid != 0) {
                            mServiceProcessesByPid.remove(proc.mPid);
                        }
                        if (pid != 0) {
                            mServiceProcessesByPid.put(pid, proc);
                        }
                        proc.mPid = pid;
                    }
                }
                proc.mDependentProcesses.clear();
                proc.mCurSeq = mSequence;
            }
            changed |= proc.updateService(context, si);
        }
        
        // Now update the map of other processes that are running (but
        // don't have services actively running inside them).
        for (int i=0; i<NP; i++) {
            ActivityManager.RunningAppProcessInfo pi = processes.get(i);
            ProcessItem proc = mServiceProcessesByPid.get(pi.pid);
            if (proc == null) {
                // This process is not one that is a direct container
                // of a service, so look for it in the secondary
                // running list.
                proc = mRunningProcesses.get(pi.pid);
                if (proc == null) {
                    changed = true;
                    proc = new ProcessItem(context, pi.uid, pi.processName);
                    proc.mPid = pi.pid;
                    mRunningProcesses.put(pi.pid, proc);
                }
                proc.mDependentProcesses.clear();
            }
            
            if (isInterestingProcess(pi)) {
                if (!mInterestingProcesses.contains(proc)) {
                    changed = true;
                    mInterestingProcesses.add(proc);
                }
                proc.mCurSeq = mSequence;
                proc.mInteresting = true;
                proc.ensureLabel(pm);
            } else {
                proc.mInteresting = false;
            }
            
            proc.mRunningSeq = mSequence;
            proc.mRunningProcessInfo = pi;
        }

        // Build the chains from client processes to the process they are
        // dependent on; also remove any old running processes.
        int NRP = mRunningProcesses.size();
        for (int i = 0; i < NRP;) {
            ProcessItem proc = mRunningProcesses.valueAt(i);
            if (proc.mRunningSeq == mSequence) {
                int clientPid = proc.mRunningProcessInfo.importanceReasonPid;
                if (clientPid != 0) {
                    ProcessItem client = mServiceProcessesByPid.get(clientPid);
                    if (client == null) {
                        client = mRunningProcesses.get(clientPid);
                    }
                    if (client != null) {
                        client.mDependentProcesses.put(proc.mPid, proc);
                    }
                } else {
                    // In this pass the process doesn't have a client.
                    // Clear to make sure that, if it later gets the same one,
                    // we will detect the change.
                    proc.mClient = null;
                }
                i++;
            } else {
                changed = true;
                mRunningProcesses.remove(mRunningProcesses.keyAt(i));
                NRP--;
            }
        }
        
        // Remove any old interesting processes.
        int NHP = mInterestingProcesses.size();
        for (int i=0; i<NHP; i++) {
            ProcessItem proc = mInterestingProcesses.get(i);
            if (!proc.mInteresting || mRunningProcesses.get(proc.mPid) == null) {
                changed = true;
                mInterestingProcesses.remove(i);
                i--;
                NHP--;
            }
        }
        
        // Follow the tree from all primary service processes to all
        // processes they are dependent on, marking these processes as
        // still being active and determining if anything has changed.
        final int NAP = mServiceProcessesByPid.size();
        for (int i=0; i<NAP; i++) {
            ProcessItem proc = mServiceProcessesByPid.valueAt(i);
            if (proc.mCurSeq == mSequence) {
                changed |= proc.buildDependencyChain(context, pm, mSequence);
            }
        }
        
        // Look for services and their primary processes that no longer exist...
        ArrayList<Integer> uidToDelete = null;
        for (int i=0; i<mServiceProcessesByName.size(); i++) {
            HashMap<String, ProcessItem> procs = mServiceProcessesByName.valueAt(i);
            Iterator<ProcessItem> pit = procs.values().iterator();
            while (pit.hasNext()) {
                ProcessItem pi = pit.next();
                if (pi.mCurSeq == mSequence) {
                    pi.ensureLabel(pm);
                    if (pi.mPid == 0) {
                        // Sanity: a non-process can't be dependent on
                        // anything.
                        pi.mDependentProcesses.clear();
                    }
                } else {
                    changed = true;
                    pit.remove();
                    if (procs.size() == 0) {
                        if (uidToDelete == null) {
                            uidToDelete = new ArrayList<Integer>();
                        }
                        uidToDelete.add(mServiceProcessesByName.keyAt(i));
                    }
                    if (pi.mPid != 0) {
                        mServiceProcessesByPid.remove(pi.mPid);
                    }
                    continue;
                }
                Iterator<ServiceItem> sit = pi.mServices.values().iterator();
                while (sit.hasNext()) {
                    ServiceItem si = sit.next();
                    if (si.mCurSeq != mSequence) {
                        changed = true;
                        sit.remove();
                    }
                }
            }
        }
        
        if (uidToDelete != null) {
            for (int i = 0; i < uidToDelete.size(); i++) {
                int uid = uidToDelete.get(i);
                mServiceProcessesByName.remove(uid);
            }
        }

        if (changed) {
            // First determine an order for the services.
            ArrayList<ProcessItem> sortedProcesses = new ArrayList<ProcessItem>();
            for (int i=0; i<mServiceProcessesByName.size(); i++) {
                for (ProcessItem pi : mServiceProcessesByName.valueAt(i).values()) {
                    pi.mIsSystem = false;
                    pi.mIsStarted = true;
                    pi.mActiveSince = Long.MAX_VALUE;
                    for (ServiceItem si : pi.mServices.values()) {
                        if (si.mServiceInfo != null
                                && (si.mServiceInfo.applicationInfo.flags
                                        & ApplicationInfo.FLAG_SYSTEM) != 0) {
                            pi.mIsSystem = true;
                        }
                        if (si.mRunningService != null
                                && si.mRunningService.clientLabel != 0) {
                            pi.mIsStarted = false;
                            if (pi.mActiveSince > si.mRunningService.activeSince) {
                                pi.mActiveSince = si.mRunningService.activeSince;
                            }
                        }
                    }
                    sortedProcesses.add(pi);
                }
            }
            
            Collections.sort(sortedProcesses, mServiceProcessComparator);
            
            ArrayList<BaseItem> newItems = new ArrayList<BaseItem>();
            ArrayList<MergedItem> newMergedItems = new ArrayList<MergedItem>();
            SparseArray<MergedItem> otherUsers = null;
            mProcessItems.clear();
            for (int i=0; i<sortedProcesses.size(); i++) {
                ProcessItem pi = sortedProcesses.get(i);
                pi.mNeedDivider = false;
                
                int firstProc = mProcessItems.size();
                // First add processes we are dependent on.
                pi.addDependentProcesses(newItems, mProcessItems);
                // And add the process itself.
                newItems.add(pi);
                if (pi.mPid > 0) {
                    mProcessItems.add(pi);
                }
                
                // Now add the services running in it.
                MergedItem mergedItem = null;
                boolean haveAllMerged = false;
                boolean needDivider = false;
                for (ServiceItem si : pi.mServices.values()) {
                    si.mNeedDivider = needDivider;
                    needDivider = true;
                    newItems.add(si);
                    if (si.mMergedItem != null) {
                        if (mergedItem != null && mergedItem != si.mMergedItem) {
                            haveAllMerged = false;
                        }
                        mergedItem = si.mMergedItem;
                    } else {
                        haveAllMerged = false;
                    }
                }
                
                if (!haveAllMerged || mergedItem == null
                        || mergedItem.mServices.size() != pi.mServices.size()) {
                    // Whoops, we need to build a new MergedItem!
                    mergedItem = new MergedItem(pi.mUserId);
                    for (ServiceItem si : pi.mServices.values()) {
                        mergedItem.mServices.add(si);
                        si.mMergedItem = mergedItem;
                    }
                    mergedItem.mProcess = pi;
                    mergedItem.mOtherProcesses.clear();
                    for (int mpi=firstProc; mpi<(mProcessItems.size()-1); mpi++) {
                        mergedItem.mOtherProcesses.add(mProcessItems.get(mpi));
                    }
                }
                
                mergedItem.update(context, false);
                if (mergedItem.mUserId != mMyUserId) {
                    addOtherUserItem(context, newMergedItems, mOtherUserMergedItems, mergedItem);
                } else {
                    newMergedItems.add(mergedItem);
                }
            }

            // Finally, interesting processes need to be shown and will
            // go at the top.
            NHP = mInterestingProcesses.size();
            for (int i=0; i<NHP; i++) {
                ProcessItem proc = mInterestingProcesses.get(i);
                if (proc.mClient == null && proc.mServices.size() <= 0) {
                    if (proc.mMergedItem == null) {
                        proc.mMergedItem = new MergedItem(proc.mUserId);
                        proc.mMergedItem.mProcess = proc;
                    }
                    proc.mMergedItem.update(context, false);
                    if (proc.mMergedItem.mUserId != mMyUserId) {
                        addOtherUserItem(context, newMergedItems, mOtherUserMergedItems,
                                proc.mMergedItem);
                    } else {
                        newMergedItems.add(0, proc.mMergedItem);
                    }
                    mProcessItems.add(proc);
                }
            }

            // Finally finally, user aggregated merged items need to be
            // updated now that they have all of their children.
            final int NU = mOtherUserMergedItems.size();
            for (int i=0; i<NU; i++) {
                MergedItem user = mOtherUserMergedItems.valueAt(i);
                if (user.mCurSeq == mSequence) {
                    user.update(context, false);
                }
            }

            synchronized (mLock) {
                mItems = newItems;
                mMergedItems = newMergedItems;
            }
        }
        
        // Count number of interesting other (non-active) processes, and
        // build a list of all processes we will retrieve memory for.
        mAllProcessItems.clear();
        mAllProcessItems.addAll(mProcessItems);
        int numBackgroundProcesses = 0;
        int numForegroundProcesses = 0;
        int numServiceProcesses = 0;
        NRP = mRunningProcesses.size();
        for (int i=0; i<NRP; i++) {
            ProcessItem proc = mRunningProcesses.valueAt(i);
            if (proc.mCurSeq != mSequence) {
                // We didn't hit this process as a dependency on one
                // of our active ones, so add it up if needed.
                if (proc.mRunningProcessInfo.importance >=
                        ActivityManager.RunningAppProcessInfo.IMPORTANCE_BACKGROUND) {
                    numBackgroundProcesses++;
                    mAllProcessItems.add(proc);
                } else if (proc.mRunningProcessInfo.importance <=
                        ActivityManager.RunningAppProcessInfo.IMPORTANCE_VISIBLE) {
                    numForegroundProcesses++;
                    mAllProcessItems.add(proc);
                } else {
                    Log.i("RunningState", "Unknown non-service process: "
                            + proc.mProcessName + " #" + proc.mPid);
                }
            } else {
                numServiceProcesses++;
            }
        }
        
        long backgroundProcessMemory = 0;
        long foregroundProcessMemory = 0;
        long serviceProcessMemory = 0;
        ArrayList<MergedItem> newBackgroundItems = null;
        ArrayList<MergedItem> newUserBackgroundItems = null;
        boolean diffUsers = false;
        try {
            final int numProc = mAllProcessItems.size();
            int[] pids = new int[numProc];
            for (int i=0; i<numProc; i++) {
                pids[i] = mAllProcessItems.get(i).mPid;
            }
            long[] pss = ActivityManagerNative.getDefault()
                    .getProcessPss(pids);
            int bgIndex = 0;
            for (int i=0; i<pids.length; i++) {
                ProcessItem proc = mAllProcessItems.get(i);
                changed |= proc.updateSize(context, pss[i], mSequence);
                if (proc.mCurSeq == mSequence) {
                    serviceProcessMemory += proc.mSize;
                } else if (proc.mRunningProcessInfo.importance >=
                        ActivityManager.RunningAppProcessInfo.IMPORTANCE_BACKGROUND) {
                    backgroundProcessMemory += proc.mSize;
                    MergedItem mergedItem;
                    if (newBackgroundItems != null) {
                        mergedItem = proc.mMergedItem = new MergedItem(proc.mUserId);
                        proc.mMergedItem.mProcess = proc;
                        diffUsers |= mergedItem.mUserId != mMyUserId;
                        newBackgroundItems.add(mergedItem);
                    } else {
                        if (bgIndex >= mBackgroundItems.size()
                                || mBackgroundItems.get(bgIndex).mProcess != proc) {
                            newBackgroundItems = new ArrayList<MergedItem>(numBackgroundProcesses);
                            for (int bgi=0; bgi<bgIndex; bgi++) {
                                mergedItem = mBackgroundItems.get(bgi);
                                diffUsers |= mergedItem.mUserId != mMyUserId;
                                newBackgroundItems.add(mergedItem);
                            }
                            mergedItem = proc.mMergedItem = new MergedItem(proc.mUserId);
                            proc.mMergedItem.mProcess = proc;
                            diffUsers |= mergedItem.mUserId != mMyUserId;
                            newBackgroundItems.add(mergedItem);
                        } else {
                            mergedItem = mBackgroundItems.get(bgIndex);
                        }
                    }
                    mergedItem.update(context, true);
                    mergedItem.updateSize(context);
                    bgIndex++;
                } else if (proc.mRunningProcessInfo.importance <=
                        ActivityManager.RunningAppProcessInfo.IMPORTANCE_VISIBLE) {
                    foregroundProcessMemory += proc.mSize;
                }
            }
        } catch (RemoteException e) {
        }
        
        if (newBackgroundItems == null) {
            // One or more at the bottom may no longer exist.
            if (mBackgroundItems.size() > numBackgroundProcesses) {
                newBackgroundItems = new ArrayList<MergedItem>(numBackgroundProcesses);
                for (int bgi=0; bgi<numBackgroundProcesses; bgi++) {
                    MergedItem mergedItem = mBackgroundItems.get(bgi);
                    diffUsers |= mergedItem.mUserId != mMyUserId;
                    newBackgroundItems.add(mergedItem);
                }
            }
        }

        if (newBackgroundItems != null) {
            // The background items have changed; we need to re-build the
            // per-user items.
            if (!diffUsers) {
                // Easy: there are no other users, we can just use the same array.
                newUserBackgroundItems = newBackgroundItems;
            } else {
                // We now need to re-build the per-user list so that background
                // items for users are collapsed together.
                newUserBackgroundItems = new ArrayList<MergedItem>();
                final int NB = newBackgroundItems.size();
                for (int i=0; i<NB; i++) {
                    MergedItem mergedItem = newBackgroundItems.get(i);
                    if (mergedItem.mUserId != mMyUserId) {
                        addOtherUserItem(context, newUserBackgroundItems,
                                mOtherUserBackgroundItems, mergedItem);
                    } else {
                        newUserBackgroundItems.add(mergedItem);
                    }
                }
                // And user aggregated merged items need to be
                // updated now that they have all of their children.
                final int NU = mOtherUserBackgroundItems.size();
                for (int i=0; i<NU; i++) {
                    MergedItem user = mOtherUserBackgroundItems.valueAt(i);
                    if (user.mCurSeq == mSequence) {
                        user.update(context, true);
                        user.updateSize(context);
                    }
                }
            }
        }

        for (int i=0; i<mMergedItems.size(); i++) {
            mMergedItems.get(i).updateSize(context);
        }
        
        synchronized (mLock) {
            mNumBackgroundProcesses = numBackgroundProcesses;
            mNumForegroundProcesses = numForegroundProcesses;
            mNumServiceProcesses = numServiceProcesses;
            mBackgroundProcessMemory = backgroundProcessMemory;
            mForegroundProcessMemory = foregroundProcessMemory;
            mServiceProcessMemory = serviceProcessMemory;
            if (newBackgroundItems != null) {
                mBackgroundItems = newBackgroundItems;
                mUserBackgroundItems = newUserBackgroundItems;
                if (mWatchingBackgroundItems) {
                    changed = true;
                }
            }
            if (!mHaveData) {
                mHaveData = true;
                mLock.notifyAll();
            }
        }
        
        return changed;
    }
    
    ArrayList<BaseItem> getCurrentItems() {
        synchronized (mLock) {
            return mItems;
        }
    }
    
    void setWatchingBackgroundItems(boolean watching) {
        synchronized (mLock) {
            mWatchingBackgroundItems = watching;
        }
    }

    ArrayList<MergedItem> getCurrentMergedItems() {
        synchronized (mLock) {
            return mMergedItems;
        }
    }

    ArrayList<MergedItem> getCurrentBackgroundItems() {
        synchronized (mLock) {
            return mUserBackgroundItems;
        }
    }
}
