Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 98d55dae authored by Dianne Hackborn's avatar Dianne Hackborn
Browse files

Update running services in background thread.

This avoid the main UI glitching when an update happens.  Also fix
some problems with how overall memory usage was shown.

Change-Id: Ida415eb07c8671059a24c3be1ebf16910f4b6da2
parent 28bcb47e
Loading
Loading
Loading
Loading
+155 −87
Original line number Original line Diff line number Diff line
@@ -41,6 +41,8 @@ import android.graphics.Rect;
import android.os.Bundle;
import android.os.Bundle;
import android.os.Debug;
import android.os.Debug;
import android.os.Handler;
import android.os.Handler;
import android.os.HandlerThread;
import android.os.Looper;
import android.os.Message;
import android.os.Message;
import android.os.RemoteException;
import android.os.RemoteException;
import android.os.SystemClock;
import android.os.SystemClock;
@@ -76,6 +78,7 @@ public class RunningServices extends ListActivity
    
    
    static final int MSG_UPDATE_TIMES = 1;
    static final int MSG_UPDATE_TIMES = 1;
    static final int MSG_UPDATE_CONTENTS = 2;
    static final int MSG_UPDATE_CONTENTS = 2;
    static final int MSG_REFRESH_UI = 3;
    
    
    static final long TIME_UPDATE_DELAY = 1000;
    static final long TIME_UPDATE_DELAY = 1000;
    static final long CONTENTS_UPDATE_DELAY = 2000;
    static final long CONTENTS_UPDATE_DELAY = 2000;
@@ -389,12 +392,19 @@ public class RunningServices extends ListActivity
        final SparseArray<ProcessItem> mRunningProcesses
        final SparseArray<ProcessItem> mRunningProcesses
                = new SparseArray<ProcessItem>();
                = new SparseArray<ProcessItem>();
        
        
        final ArrayList<BaseItem> mItems = new ArrayList<BaseItem>();
        final ArrayList<ProcessItem> mProcessItems = new ArrayList<ProcessItem>();
        final ArrayList<ProcessItem> mProcessItems = new ArrayList<ProcessItem>();
        final ArrayList<ProcessItem> mAllProcessItems = new ArrayList<ProcessItem>();
        final ArrayList<ProcessItem> mAllProcessItems = new ArrayList<ProcessItem>();
        
        
        int mSequence = 0;
        int mSequence = 0;
        
        
        // ----- 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();
        
        ArrayList<BaseItem> mItems = new ArrayList<BaseItem>();
        
        int mNumBackgroundProcesses;
        int mNumBackgroundProcesses;
        long mBackgroundProcessMemory;
        long mBackgroundProcessMemory;
        int mNumForegroundProcesses;
        int mNumForegroundProcesses;
@@ -556,15 +566,15 @@ public class RunningServices extends ListActivity
            }
            }
            
            
            if (changed) {
            if (changed) {
                mItems.clear();
                ArrayList<BaseItem> newItems = new ArrayList<BaseItem>();
                mProcessItems.clear();
                mProcessItems.clear();
                for (int i=0; i<mProcesses.size(); i++) {
                for (int i=0; i<mProcesses.size(); i++) {
                    for (ProcessItem pi : mProcesses.valueAt(i).values()) {
                    for (ProcessItem pi : mProcesses.valueAt(i).values()) {
                        pi.mNeedDivider = false;
                        pi.mNeedDivider = false;
                        // First add processes we are dependent on.
                        // First add processes we are dependent on.
                        pi.addDependentProcesses(mItems, mProcessItems);
                        pi.addDependentProcesses(newItems, mProcessItems);
                        // And add the process itself.
                        // And add the process itself.
                        mItems.add(pi);
                        newItems.add(pi);
                        if (pi.mPid > 0) {
                        if (pi.mPid > 0) {
                            mProcessItems.add(pi);
                            mProcessItems.add(pi);
                        }
                        }
@@ -573,19 +583,22 @@ public class RunningServices extends ListActivity
                        for (ServiceItem si : pi.mServices.values()) {
                        for (ServiceItem si : pi.mServices.values()) {
                            si.mNeedDivider = needDivider;
                            si.mNeedDivider = needDivider;
                            needDivider = true;
                            needDivider = true;
                            mItems.add(si);
                            newItems.add(si);
                        }
                        }
                    }
                    }
                }
                }
                synchronized (mLock) {
                    mItems = newItems;
                }
            }
            }
            
            
            // Count number of interesting other (non-active) processes, and
            // Count number of interesting other (non-active) processes, and
            // build a list of all processes we will retrieve memory for.
            // build a list of all processes we will retrieve memory for.
            mAllProcessItems.clear();
            mAllProcessItems.clear();
            mAllProcessItems.addAll(mProcessItems);
            mAllProcessItems.addAll(mProcessItems);
            mNumBackgroundProcesses = 0;
            int numBackgroundProcesses = 0;
            mNumForegroundProcesses = 0;
            int numForegroundProcesses = 0;
            mNumServiceProcesses = 0;
            int numServiceProcesses = 0;
            NRP = mRunningProcesses.size();
            NRP = mRunningProcesses.size();
            for (int i=0; i<NRP; i++) {
            for (int i=0; i<NRP; i++) {
                ProcessItem proc = mRunningProcesses.valueAt(i);
                ProcessItem proc = mRunningProcesses.valueAt(i);
@@ -594,25 +607,25 @@ public class RunningServices extends ListActivity
                    // of our active ones, so add it up if needed.
                    // of our active ones, so add it up if needed.
                    if (proc.mRunningProcessInfo.importance >=
                    if (proc.mRunningProcessInfo.importance >=
                            ActivityManager.RunningAppProcessInfo.IMPORTANCE_BACKGROUND) {
                            ActivityManager.RunningAppProcessInfo.IMPORTANCE_BACKGROUND) {
                        mNumBackgroundProcesses++;
                        numBackgroundProcesses++;
                        mAllProcessItems.add(proc);
                        mAllProcessItems.add(proc);
                    } else if (proc.mRunningProcessInfo.importance <=
                    } else if (proc.mRunningProcessInfo.importance <=
                            ActivityManager.RunningAppProcessInfo.IMPORTANCE_VISIBLE) {
                            ActivityManager.RunningAppProcessInfo.IMPORTANCE_VISIBLE) {
                        mNumForegroundProcesses++;
                        numForegroundProcesses++;
                        mAllProcessItems.add(proc);
                        mAllProcessItems.add(proc);
                    } else {
                    } else {
                        Log.i(TAG, "Unknown non-service process: "
                        Log.i(TAG, "Unknown non-service process: "
                                + proc.mProcessName + " #" + proc.mPid);
                                + proc.mProcessName + " #" + proc.mPid);
                    }
                    }
                } else {
                } else {
                    mNumServiceProcesses++;
                    numServiceProcesses++;
                }
                }
            }
            }
            
            
            long backgroundProcessMemory = 0;
            long foregroundProcessMemory = 0;
            long serviceProcessMemory = 0;
            try {
            try {
                mBackgroundProcessMemory = 0;
                mForegroundProcessMemory = 0;
                mServiceProcessMemory = 0;
                final int numProc = mAllProcessItems.size();
                final int numProc = mAllProcessItems.size();
                int[] pids = new int[numProc];
                int[] pids = new int[numProc];
                for (int i=0; i<numProc; i++) {
                for (int i=0; i<numProc; i++) {
@@ -624,18 +637,27 @@ public class RunningServices extends ListActivity
                    ProcessItem proc = mAllProcessItems.get(i);
                    ProcessItem proc = mAllProcessItems.get(i);
                    changed |= proc.updateSize(context, mem[i], mSequence);
                    changed |= proc.updateSize(context, mem[i], mSequence);
                    if (proc.mCurSeq == mSequence) {
                    if (proc.mCurSeq == mSequence) {
                        mServiceProcessMemory += proc.mSize;
                        serviceProcessMemory += proc.mSize;
                    } else if (proc.mRunningProcessInfo.importance >=
                    } else if (proc.mRunningProcessInfo.importance >=
                            ActivityManager.RunningAppProcessInfo.IMPORTANCE_BACKGROUND) {
                            ActivityManager.RunningAppProcessInfo.IMPORTANCE_BACKGROUND) {
                        mBackgroundProcessMemory += proc.mSize;
                        backgroundProcessMemory += proc.mSize;
                    } else if (proc.mRunningProcessInfo.importance <=
                    } else if (proc.mRunningProcessInfo.importance <=
                            ActivityManager.RunningAppProcessInfo.IMPORTANCE_VISIBLE) {
                            ActivityManager.RunningAppProcessInfo.IMPORTANCE_VISIBLE) {
                        mForegroundProcessMemory += proc.mSize;
                        foregroundProcessMemory += proc.mSize;
                    }
                    }
                }
                }
            } catch (RemoteException e) {
            } catch (RemoteException e) {
            }
            }
            
            
            synchronized (mLock) {
                mNumBackgroundProcesses = numBackgroundProcesses;
                mNumForegroundProcesses = numForegroundProcesses;
                mNumServiceProcesses = numServiceProcesses;
                mBackgroundProcessMemory = backgroundProcessMemory;
                mForegroundProcessMemory = foregroundProcessMemory;
                mServiceProcessMemory = serviceProcessMemory;
            }
            
            return changed;
            return changed;
        }
        }
    }
    }
@@ -659,21 +681,27 @@ public class RunningServices extends ListActivity
        final LayoutInflater mInflater;
        final LayoutInflater mInflater;
        
        
        ServiceListAdapter(State state) {
        ServiceListAdapter(State state) {
            synchronized (state.mLock) {
                mState = state;
                mState = state;
                mInflater = (LayoutInflater)getSystemService(Context.LAYOUT_INFLATER_SERVICE);
                mInflater = (LayoutInflater)getSystemService(Context.LAYOUT_INFLATER_SERVICE);
            }
            }
        }


        public boolean hasStableIds() {
        public boolean hasStableIds() {
            return true;
            return true;
        }
        }
        
        
        public int getCount() {
        public int getCount() {
            synchronized (mState.mLock) {
                return mState.mItems.size();
                return mState.mItems.size();
            }
            }
        }


        public Object getItem(int position) {
        public Object getItem(int position) {
            synchronized (mState.mLock) {
                return mState.mItems.get(position);
                return mState.mItems.get(position);
            }
            }
        }


        public long getItemId(int position) {
        public long getItemId(int position) {
            return position;
            return position;
@@ -684,8 +712,10 @@ public class RunningServices extends ListActivity
        }
        }


        public boolean isEnabled(int position) {
        public boolean isEnabled(int position) {
            synchronized (mState.mLock) {
                return !mState.mItems.get(position).mIsProcess;
                return !mState.mItems.get(position).mIsProcess;
            }
            }
        }


        public View getView(int position, View convertView, ViewGroup parent) {
        public View getView(int position, View convertView, ViewGroup parent) {
            View v;
            View v;
@@ -711,7 +741,14 @@ public class RunningServices extends ListActivity
        }
        }
        
        
        public void bindView(View view, int position) {
        public void bindView(View view, int position) {
            synchronized (mState.mLock) {
                ViewHolder vh = (ViewHolder) view.getTag();
                ViewHolder vh = (ViewHolder) view.getTag();
                if (position >= mState.mItems.size()) {
                    // List must have changed since we last reported its
                    // size...  ignore here, we will be doing a data changed
                    // to refresh the entire list.
                    return;
                }
                BaseItem item = mState.mItems.get(position);
                BaseItem item = mState.mItems.get(position);
                vh.name.setText(item.mDisplayLabel);
                vh.name.setText(item.mDisplayLabel);
                vh.separator.setVisibility(item.mNeedDivider
                vh.separator.setVisibility(item.mNeedDivider
@@ -739,6 +776,7 @@ public class RunningServices extends ListActivity
                mActiveItems.put(view, ai);
                mActiveItems.put(view, ai);
            }
            }
        }
        }
    }
    
    
    public static class LinearColorBar extends LinearLayout {
    public static class LinearColorBar extends LinearLayout {
        private float mRedRatio;
        private float mRedRatio;
@@ -801,6 +839,28 @@ public class RunningServices extends ListActivity
        }
        }
    }
    }
    
    
    HandlerThread mBackgroundThread;
    final class BackgroundHandler extends Handler {
        public BackgroundHandler(Looper looper) {
            super(looper);
        }
        
        @Override
        public void handleMessage(Message msg) {
            switch (msg.what) {
                case MSG_UPDATE_CONTENTS:
                    Message cmd = mHandler.obtainMessage(MSG_REFRESH_UI);
                    cmd.arg1 = mState.update(RunningServices.this, mAm) ? 1 : 0;
                    mHandler.sendMessage(cmd);
                    removeMessages(MSG_UPDATE_CONTENTS);
                    msg = obtainMessage(MSG_UPDATE_CONTENTS);
                    sendMessageDelayed(msg, CONTENTS_UPDATE_DELAY);
                    break;
            }
        }
    };
    BackgroundHandler mBackgroundHandler;
    
    final Handler mHandler = new Handler() {
    final Handler mHandler = new Handler() {
        @Override
        @Override
        public void handleMessage(Message msg) {
        public void handleMessage(Message msg) {
@@ -820,11 +880,8 @@ public class RunningServices extends ListActivity
                    msg = obtainMessage(MSG_UPDATE_TIMES);
                    msg = obtainMessage(MSG_UPDATE_TIMES);
                    sendMessageDelayed(msg, TIME_UPDATE_DELAY);
                    sendMessageDelayed(msg, TIME_UPDATE_DELAY);
                    break;
                    break;
                case MSG_UPDATE_CONTENTS:
                case MSG_REFRESH_UI:
                    updateList();
                    refreshUi(msg.arg1 != 0);
                    removeMessages(MSG_UPDATE_CONTENTS);
                    msg = obtainMessage(MSG_UPDATE_CONTENTS);
                    sendMessageDelayed(msg, CONTENTS_UPDATE_DELAY);
                    break;
                    break;
            }
            }
        }
        }
@@ -908,8 +965,8 @@ public class RunningServices extends ListActivity
            Integer.valueOf(SystemProperties.get("ro.SECONDARY_SERVER_MEM"))*PAGE_SIZE;
            Integer.valueOf(SystemProperties.get("ro.SECONDARY_SERVER_MEM"))*PAGE_SIZE;
    }
    }


    void updateList() {
    void refreshUi(boolean dataChanged) {
        if (mState.update(this, mAm)) {
        if (dataChanged) {
            ((ServiceListAdapter)(getListView().getAdapter())).notifyDataSetChanged();
            ((ServiceListAdapter)(getListView().getAdapter())).notifyDataSetChanged();
        }
        }
        
        
@@ -920,6 +977,7 @@ public class RunningServices extends ListActivity
            availMem = 0;
            availMem = 0;
        }
        }
        
        
        synchronized (mState.mLock) {
            if (mLastNumBackgroundProcesses != mState.mNumBackgroundProcesses
            if (mLastNumBackgroundProcesses != mState.mNumBackgroundProcesses
                    || mLastBackgroundProcessMemory != mState.mBackgroundProcessMemory
                    || mLastBackgroundProcessMemory != mState.mBackgroundProcessMemory
                    || mLastAvailMemory != availMem) {
                    || mLastAvailMemory != availMem) {
@@ -944,11 +1002,12 @@ public class RunningServices extends ListActivity
            mLastNumServiceProcesses = mState.mNumServiceProcesses;
            mLastNumServiceProcesses = mState.mNumServiceProcesses;
            mLastServiceProcessMemory = mState.mServiceProcessMemory;
            mLastServiceProcessMemory = mState.mServiceProcessMemory;
            
            
        float totalMem = mLastBackgroundProcessMemory
            float totalMem = availMem + mLastBackgroundProcessMemory
                    + mLastForegroundProcessMemory + mLastServiceProcessMemory;
                    + mLastForegroundProcessMemory + mLastServiceProcessMemory;
            mColorBar.setRatios(mLastForegroundProcessMemory/totalMem,
            mColorBar.setRatios(mLastForegroundProcessMemory/totalMem,
                    mLastServiceProcessMemory/totalMem,
                    mLastServiceProcessMemory/totalMem,
                mLastForegroundProcessMemory/totalMem);
                    (availMem+mLastBackgroundProcessMemory)/totalMem);
        }
    }
    }
    
    
    @Override
    @Override
@@ -996,7 +1055,9 @@ public class RunningServices extends ListActivity
        if (mCurSelected != null) {
        if (mCurSelected != null) {
            stopService(new Intent().setComponent(
            stopService(new Intent().setComponent(
                    ((ServiceItem)mCurSelected).mRunningService.service));
                    ((ServiceItem)mCurSelected).mRunningService.service));
            updateList();
            if (mBackgroundHandler != null) {
                mBackgroundHandler.sendEmptyMessage(MSG_UPDATE_CONTENTS);
            }
        }
        }
    }
    }


@@ -1004,19 +1065,26 @@ public class RunningServices extends ListActivity
    protected void onPause() {
    protected void onPause() {
        super.onPause();
        super.onPause();
        mHandler.removeMessages(MSG_UPDATE_TIMES);
        mHandler.removeMessages(MSG_UPDATE_TIMES);
        mHandler.removeMessages(MSG_UPDATE_CONTENTS);
        if (mBackgroundThread != null) {
            mBackgroundThread.quit();
            mBackgroundThread = null;
            mBackgroundHandler = null;
        }
    }
    }


    @Override
    @Override
    protected void onResume() {
    protected void onResume() {
        super.onResume();
        super.onResume();
        updateList();
        refreshUi(mState.update(this, mAm));
        mBackgroundThread = new HandlerThread("RunningServices");
        mBackgroundThread.start();
        mBackgroundHandler = new BackgroundHandler(mBackgroundThread.getLooper());
        mHandler.removeMessages(MSG_UPDATE_TIMES);
        mHandler.removeMessages(MSG_UPDATE_TIMES);
        Message msg = mHandler.obtainMessage(MSG_UPDATE_TIMES);
        Message msg = mHandler.obtainMessage(MSG_UPDATE_TIMES);
        mHandler.sendMessageDelayed(msg, TIME_UPDATE_DELAY);
        mHandler.sendMessageDelayed(msg, TIME_UPDATE_DELAY);
        mHandler.removeMessages(MSG_UPDATE_CONTENTS);
        mBackgroundHandler.removeMessages(MSG_UPDATE_CONTENTS);
        msg = mHandler.obtainMessage(MSG_UPDATE_CONTENTS);
        msg = mBackgroundHandler.obtainMessage(MSG_UPDATE_CONTENTS);
        mHandler.sendMessageDelayed(msg, CONTENTS_UPDATE_DELAY);
        mBackgroundHandler.sendMessageDelayed(msg, CONTENTS_UPDATE_DELAY);
    }
    }


    @Override
    @Override