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

Commit d4fb738a authored by Dianne Hackborn's avatar Dianne Hackborn Committed by Android (Google) Code Review
Browse files

Merge "Fix issue# 2544176: running services list update outside of ui thread." into froyo

parents 388b4a87 309f2362
Loading
Loading
Loading
Loading
+98 −32
Original line number Diff line number Diff line
@@ -64,6 +64,8 @@ import android.widget.TextView;

import java.io.FileInputStream;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
@@ -189,6 +191,11 @@ public class RunningServices extends ListActivity
        int mRunningSeq;
        ActivityManager.RunningAppProcessInfo mRunningProcessInfo;
        
        // Purely for sorting.
        boolean mIsSystem;
        boolean mIsStarted;
        long mActiveSince;
        
        public ProcessItem(Context context, int uid, String processName) {
            super(true);
            mDescription = context.getResources().getString(
@@ -382,11 +389,32 @@ public class RunningServices extends ListActivity
        }
    }
    
    static class ServiceProcessComparator implements Comparator<ProcessItem> {
        public int compare(ProcessItem object1, ProcessItem object2) {
            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 class State {
        final SparseArray<HashMap<String, ProcessItem>> mProcesses
                = new SparseArray<HashMap<String, ProcessItem>>();
        final SparseArray<ProcessItem> mActiveProcesses
                = new SparseArray<ProcessItem>();
        final ServiceProcessComparator mServiceProcessComparator
                = new ServiceProcessComparator();
        
        // Temporary for finding process dependencies.
        final SparseArray<ProcessItem> mRunningProcesses
@@ -566,10 +594,37 @@ public class RunningServices extends ListActivity
            }
            
            if (changed) {
                ArrayList<BaseItem> newItems = new ArrayList<BaseItem>();
                mProcessItems.clear();
                // First determine an order for the services.
                ArrayList<ProcessItem> sortedProcesses = new ArrayList<ProcessItem>();
                for (int i=0; i<mProcesses.size(); i++) {
                    for (ProcessItem pi : mProcesses.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>();
                mProcessItems.clear();
                for (int i=0; i<sortedProcesses.size(); i++) {
                    ProcessItem pi = sortedProcesses.get(i);
                    pi.mNeedDivider = false;
                    // First add processes we are dependent on.
                    pi.addDependentProcesses(newItems, mProcessItems);
@@ -586,7 +641,6 @@ public class RunningServices extends ListActivity
                        newItems.add(si);
                    }
                }
                }
                synchronized (mLock) {
                    mItems = newItems;
                }
@@ -660,6 +714,12 @@ public class RunningServices extends ListActivity
            
            return changed;
        }
        
        ArrayList<BaseItem> getCurrentItems() {
            synchronized (mLock) {
                return mItems;
            }
        }
    }
    
    static class TimeTicker extends TextView {
@@ -679,11 +739,21 @@ public class RunningServices extends ListActivity
    class ServiceListAdapter extends BaseAdapter {
        final State mState;
        final LayoutInflater mInflater;
        ArrayList<BaseItem> mItems;
        
        ServiceListAdapter(State state) {
            synchronized (state.mLock) {
            mState = state;
            mInflater = (LayoutInflater)getSystemService(Context.LAYOUT_INFLATER_SERVICE);
            refreshItems();
        }

        void refreshItems() {
            ArrayList<BaseItem> newItems = mState.getCurrentItems();
            if (mItems != newItems) {
                mItems = newItems;
            }
            if (mItems == null) {
                mItems = new ArrayList<BaseItem>();
            }
        }
        
@@ -692,19 +762,15 @@ public class RunningServices extends ListActivity
        }
        
        public int getCount() {
            synchronized (mState.mLock) {
                return mState.mItems.size();
            }
            return mItems.size();
        }

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

        public long getItemId(int position) {
            return position;
            return mItems.get(position).hashCode();
        }

        public boolean areAllItemsEnabled() {
@@ -712,9 +778,7 @@ public class RunningServices extends ListActivity
        }

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

        public View getView(int position, View convertView, ViewGroup parent) {
@@ -743,13 +807,13 @@ 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()) {
                if (position >= 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 = mItems.get(position);
                vh.name.setText(item.mDisplayLabel);
                vh.separator.setVisibility(item.mNeedDivider
                        ? View.VISIBLE : View.INVISIBLE);
@@ -967,7 +1031,9 @@ public class RunningServices extends ListActivity

    void refreshUi(boolean dataChanged) {
        if (dataChanged) {
            ((ServiceListAdapter)(getListView().getAdapter())).notifyDataSetChanged();
            ServiceListAdapter adapter = (ServiceListAdapter)(getListView().getAdapter());
            adapter.refreshItems();
            adapter.notifyDataSetChanged();
        }
        
        // This is the amount of available memory until we start killing