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

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

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

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

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

        public View getView(int position, View convertView, ViewGroup parent) {
            View v;
@@ -711,7 +741,14 @@ public class RunningServices extends ListActivity
        }
        
        public void bindView(View view, int position) {
            synchronized (mState.mLock) {
                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);
                vh.name.setText(item.mDisplayLabel);
                vh.separator.setVisibility(item.mNeedDivider
@@ -739,6 +776,7 @@ public class RunningServices extends ListActivity
                mActiveItems.put(view, ai);
            }
        }
    }
    
    public static class LinearColorBar extends LinearLayout {
        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() {
        @Override
        public void handleMessage(Message msg) {
@@ -820,11 +880,8 @@ public class RunningServices extends ListActivity
                    msg = obtainMessage(MSG_UPDATE_TIMES);
                    sendMessageDelayed(msg, TIME_UPDATE_DELAY);
                    break;
                case MSG_UPDATE_CONTENTS:
                    updateList();
                    removeMessages(MSG_UPDATE_CONTENTS);
                    msg = obtainMessage(MSG_UPDATE_CONTENTS);
                    sendMessageDelayed(msg, CONTENTS_UPDATE_DELAY);
                case MSG_REFRESH_UI:
                    refreshUi(msg.arg1 != 0);
                    break;
            }
        }
@@ -908,8 +965,8 @@ public class RunningServices extends ListActivity
            Integer.valueOf(SystemProperties.get("ro.SECONDARY_SERVER_MEM"))*PAGE_SIZE;
    }

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

    @Override
    protected void 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);
        Message msg = mHandler.obtainMessage(MSG_UPDATE_TIMES);
        mHandler.sendMessageDelayed(msg, TIME_UPDATE_DELAY);
        mHandler.removeMessages(MSG_UPDATE_CONTENTS);
        msg = mHandler.obtainMessage(MSG_UPDATE_CONTENTS);
        mHandler.sendMessageDelayed(msg, CONTENTS_UPDATE_DELAY);
        mBackgroundHandler.removeMessages(MSG_UPDATE_CONTENTS);
        msg = mBackgroundHandler.obtainMessage(MSG_UPDATE_CONTENTS);
        mBackgroundHandler.sendMessageDelayed(msg, CONTENTS_UPDATE_DELAY);
    }

    @Override