Merge "Fix issue# 2544176: running services list update outside of ui thread." into froyo
This commit is contained in:
committed by
Android (Google) Code Review
commit
d4fb738aa7
@@ -64,6 +64,8 @@ import android.widget.TextView;
|
|||||||
|
|
||||||
import java.io.FileInputStream;
|
import java.io.FileInputStream;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.Comparator;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.Iterator;
|
import java.util.Iterator;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
@@ -189,6 +191,11 @@ public class RunningServices extends ListActivity
|
|||||||
int mRunningSeq;
|
int mRunningSeq;
|
||||||
ActivityManager.RunningAppProcessInfo mRunningProcessInfo;
|
ActivityManager.RunningAppProcessInfo mRunningProcessInfo;
|
||||||
|
|
||||||
|
// Purely for sorting.
|
||||||
|
boolean mIsSystem;
|
||||||
|
boolean mIsStarted;
|
||||||
|
long mActiveSince;
|
||||||
|
|
||||||
public ProcessItem(Context context, int uid, String processName) {
|
public ProcessItem(Context context, int uid, String processName) {
|
||||||
super(true);
|
super(true);
|
||||||
mDescription = context.getResources().getString(
|
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 {
|
static class State {
|
||||||
final SparseArray<HashMap<String, ProcessItem>> mProcesses
|
final SparseArray<HashMap<String, ProcessItem>> mProcesses
|
||||||
= new SparseArray<HashMap<String, ProcessItem>>();
|
= new SparseArray<HashMap<String, ProcessItem>>();
|
||||||
final SparseArray<ProcessItem> mActiveProcesses
|
final SparseArray<ProcessItem> mActiveProcesses
|
||||||
= new SparseArray<ProcessItem>();
|
= new SparseArray<ProcessItem>();
|
||||||
|
final ServiceProcessComparator mServiceProcessComparator
|
||||||
|
= new ServiceProcessComparator();
|
||||||
|
|
||||||
// Temporary for finding process dependencies.
|
// Temporary for finding process dependencies.
|
||||||
final SparseArray<ProcessItem> mRunningProcesses
|
final SparseArray<ProcessItem> mRunningProcesses
|
||||||
@@ -566,10 +594,37 @@ public class RunningServices extends ListActivity
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (changed) {
|
if (changed) {
|
||||||
ArrayList<BaseItem> newItems = new ArrayList<BaseItem>();
|
// First determine an order for the services.
|
||||||
mProcessItems.clear();
|
ArrayList<ProcessItem> sortedProcesses = new ArrayList<ProcessItem>();
|
||||||
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.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;
|
pi.mNeedDivider = false;
|
||||||
// First add processes we are dependent on.
|
// First add processes we are dependent on.
|
||||||
pi.addDependentProcesses(newItems, mProcessItems);
|
pi.addDependentProcesses(newItems, mProcessItems);
|
||||||
@@ -586,7 +641,6 @@ public class RunningServices extends ListActivity
|
|||||||
newItems.add(si);
|
newItems.add(si);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
synchronized (mLock) {
|
synchronized (mLock) {
|
||||||
mItems = newItems;
|
mItems = newItems;
|
||||||
}
|
}
|
||||||
@@ -660,6 +714,12 @@ public class RunningServices extends ListActivity
|
|||||||
|
|
||||||
return changed;
|
return changed;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ArrayList<BaseItem> getCurrentItems() {
|
||||||
|
synchronized (mLock) {
|
||||||
|
return mItems;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static class TimeTicker extends TextView {
|
static class TimeTicker extends TextView {
|
||||||
@@ -679,11 +739,21 @@ public class RunningServices extends ListActivity
|
|||||||
class ServiceListAdapter extends BaseAdapter {
|
class ServiceListAdapter extends BaseAdapter {
|
||||||
final State mState;
|
final State mState;
|
||||||
final LayoutInflater mInflater;
|
final LayoutInflater mInflater;
|
||||||
|
ArrayList<BaseItem> mItems;
|
||||||
|
|
||||||
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);
|
||||||
|
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() {
|
public int getCount() {
|
||||||
synchronized (mState.mLock) {
|
return mItems.size();
|
||||||
return mState.mItems.size();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public Object getItem(int position) {
|
public Object getItem(int position) {
|
||||||
synchronized (mState.mLock) {
|
return mItems.get(position);
|
||||||
return mState.mItems.get(position);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public long getItemId(int position) {
|
public long getItemId(int position) {
|
||||||
return position;
|
return mItems.get(position).hashCode();
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean areAllItemsEnabled() {
|
public boolean areAllItemsEnabled() {
|
||||||
@@ -712,9 +778,7 @@ public class RunningServices extends ListActivity
|
|||||||
}
|
}
|
||||||
|
|
||||||
public boolean isEnabled(int position) {
|
public boolean isEnabled(int position) {
|
||||||
synchronized (mState.mLock) {
|
return !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) {
|
||||||
@@ -743,13 +807,13 @@ public class RunningServices extends ListActivity
|
|||||||
public void bindView(View view, int position) {
|
public void bindView(View view, int position) {
|
||||||
synchronized (mState.mLock) {
|
synchronized (mState.mLock) {
|
||||||
ViewHolder vh = (ViewHolder) view.getTag();
|
ViewHolder vh = (ViewHolder) view.getTag();
|
||||||
if (position >= mState.mItems.size()) {
|
if (position >= mItems.size()) {
|
||||||
// List must have changed since we last reported its
|
// List must have changed since we last reported its
|
||||||
// size... ignore here, we will be doing a data changed
|
// size... ignore here, we will be doing a data changed
|
||||||
// to refresh the entire list.
|
// to refresh the entire list.
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
BaseItem item = mState.mItems.get(position);
|
BaseItem item = mItems.get(position);
|
||||||
vh.name.setText(item.mDisplayLabel);
|
vh.name.setText(item.mDisplayLabel);
|
||||||
vh.separator.setVisibility(item.mNeedDivider
|
vh.separator.setVisibility(item.mNeedDivider
|
||||||
? View.VISIBLE : View.INVISIBLE);
|
? View.VISIBLE : View.INVISIBLE);
|
||||||
@@ -967,7 +1031,9 @@ public class RunningServices extends ListActivity
|
|||||||
|
|
||||||
void refreshUi(boolean dataChanged) {
|
void refreshUi(boolean dataChanged) {
|
||||||
if (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
|
// This is the amount of available memory until we start killing
|
||||||
|
Reference in New Issue
Block a user