diff --git a/res/layout/running_services.xml b/res/layout/running_services.xml index 8fe7f9f76d2..120a1135bed 100644 --- a/res/layout/running_services.xml +++ b/res/layout/running_services.xml @@ -15,16 +15,46 @@ * limitations under the License. --> - - - + + + + + - + android:layout_height="wrap_content" + android:orientation="horizontal" + android:background="?android:attr/colorForeground" + android:padding="4dp"> + + + + diff --git a/res/values/arrays.xml b/res/values/arrays.xml index bb786c2bed6..8dadc54143e 100644 --- a/res/values/arrays.xml +++ b/res/values/arrays.xml @@ -50,10 +50,10 @@ - Off - Some - All - Slow + No animations + Some animations + All animations + Slower all animations diff --git a/res/values/strings.xml b/res/values/strings.xml index 847e879d70b..4d89630ceeb 100644 --- a/res/values/strings.xml +++ b/res/values/strings.xml @@ -1422,9 +1422,13 @@ found in the list of installed applications. Cancel - Started by application + Started by application: select to stop %1$s: select to manage + + Background procs: %1$d + + Foreground procs: %1$d diff --git a/src/com/android/settings/RunningServices.java b/src/com/android/settings/RunningServices.java index 675c59e5af2..5593ce95cd3 100644 --- a/src/com/android/settings/RunningServices.java +++ b/src/com/android/settings/RunningServices.java @@ -23,28 +23,17 @@ import android.app.AlertDialog; import android.app.Dialog; import android.app.ListActivity; import android.app.PendingIntent; -import android.app.ProgressDialog; -import android.content.BroadcastReceiver; +import android.content.ActivityNotFoundException; import android.content.ComponentName; import android.content.Context; import android.content.DialogInterface; import android.content.Intent; -import android.content.IntentFilter; -import android.content.SharedPreferences; import android.content.pm.ApplicationInfo; -import android.content.pm.IPackageStatsObserver; import android.content.pm.PackageInfo; import android.content.pm.PackageItemInfo; import android.content.pm.PackageManager; -import android.content.pm.PackageStats; import android.content.pm.ServiceInfo; -import android.content.pm.PackageManager.NameNotFoundException; -import android.content.res.Configuration; import android.content.res.Resources; -import android.content.res.TypedArray; -import android.database.Cursor; -import android.graphics.drawable.Drawable; -import android.net.Uri; import android.os.Bundle; import android.os.Debug; import android.os.Handler; @@ -54,24 +43,16 @@ import android.os.SystemClock; import android.text.format.DateUtils; import android.text.format.Formatter; import android.util.AttributeSet; -import android.util.Config; import android.util.Log; import android.util.SparseArray; import android.view.LayoutInflater; -import android.view.Menu; -import android.view.MenuItem; import android.view.View; import android.view.ViewGroup; -import android.view.Window; import android.widget.AbsListView; -import android.widget.AdapterView; import android.widget.BaseAdapter; -import android.widget.Filter; -import android.widget.Filterable; import android.widget.ImageView; import android.widget.ListView; import android.widget.TextView; -import android.widget.AdapterView.OnItemClickListener; import java.util.ArrayList; import java.util.HashMap; @@ -104,6 +85,12 @@ public class RunningServices extends ListActivity int mProcessBgColor; + TextView mBackgroundProcessText; + TextView mForegroundProcessText; + + int mLastNumBackgroundProcesses = -1; + int mLastNumForegroundProcesses = -1; + Dialog mCurDialog; class ActiveItem { @@ -114,18 +101,27 @@ public class RunningServices extends ListActivity long mFirstRunTime; void updateTime(Context context) { - if (mItem.mActiveSince >= 0) { - mHolder.size.setText(DateUtils.formatElapsedTime(mBuilder, - (SystemClock.uptimeMillis()-mFirstRunTime)/1000)); + if (mItem.mIsProcess) { + String size = mItem.mSizeStr != null ? mItem.mSizeStr : ""; + if (!size.equals(mItem.mCurSizeStr)) { + mItem.mCurSizeStr = size; + mHolder.size.setText(size); + } } else { - mHolder.size.setText(context.getResources().getText( - R.string.service_restarting)); + if (mItem.mActiveSince >= 0) { + mHolder.size.setText(DateUtils.formatElapsedTime(mBuilder, + (SystemClock.uptimeMillis()-mFirstRunTime)/1000)); + } else { + mHolder.size.setText(context.getResources().getText( + R.string.service_restarting)); + } } } } static class BaseItem { - boolean mIsProcess; + final boolean mIsProcess; + PackageItemInfo mPackageInfo; CharSequence mDisplayLabel; String mLabel; @@ -136,21 +132,119 @@ public class RunningServices extends ListActivity long mActiveSince; long mSize; String mSizeStr; + String mCurSizeStr; boolean mNeedDivider; + + public BaseItem(boolean isProcess) { + mIsProcess = isProcess; + } } static class ServiceItem extends BaseItem { ActivityManager.RunningServiceInfo mRunningService; ServiceInfo mServiceInfo; boolean mShownAsStarted; + + public ServiceItem() { + super(false); + } } static class ProcessItem extends BaseItem { final HashMap mServices = new HashMap(); - int mUid; + final SparseArray mDependentProcesses + = new SparseArray(); + + final int mUid; + final String mProcessName; int mPid; + ProcessItem mClient; + int mLastNumDependentProcesses; + + int mRunningSeq; + ActivityManager.RunningAppProcessInfo mRunningProcessInfo; + + public ProcessItem(int uid, String processName) { + super(true); + mDescription = processName; + mUid = uid; + mProcessName = processName; + } + + void ensureLabel(PackageManager pm) { + if (mLabel != null) { + return; + } + + try { + ApplicationInfo ai = pm.getApplicationInfo(mProcessName, 0); + 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], 0); + 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) { + mPackageInfo = mServices.values().iterator().next() + .mServiceInfo.applicationInfo; + mDisplayLabel = mPackageInfo.loadLabel(pm); + mLabel = mDisplayLabel.toString(); + return; + } + + // Finally... whatever, just pick the first package's name. + try { + ApplicationInfo ai = pm.getApplicationInfo(pkgs[0], 0); + 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(); @@ -211,16 +305,89 @@ public class RunningServices extends ListActivity return changed; } + + boolean updateSize(Context context) { + boolean changed = false; + + if (mPid != 0 && mSize == 0) { + final int NP = mDependentProcesses.size(); + for (int i=0; i dest) { + final int NP = mDependentProcesses.size(); + for (int i=0; i> mProcesses = new SparseArray>(); + final SparseArray mActiveProcesses + = new SparseArray(); + + // Temporary for finding process dependencies. + final SparseArray mRunningProcesses + = new SparseArray(); final ArrayList mItems = new ArrayList(); int mSequence = 0; + int mNumBackgroundProcesses; + int mNumForegroundProcesses; + boolean update(Context context, ActivityManager am) { final PackageManager pm = context.getPackageManager(); @@ -230,10 +397,7 @@ public class RunningServices extends ListActivity List services = am.getRunningServices(MAX_SERVICES); - if (services == null) { - return false; - } - final int NS = services.size(); + final int NS = services != null ? services.size() : 0; for (int i=0; i processes + = am.getRunningAppProcesses(); + final int NP = processes != null ? processes.size() : 0; + for (int i=0; i= + ActivityManager.RunningAppProcessInfo.IMPORTANCE_BACKGROUND) { + mNumBackgroundProcesses++; + } else if (proc.mRunningProcessInfo.importance <= + ActivityManager.RunningAppProcessInfo.IMPORTANCE_VISIBLE) { + mNumForegroundProcesses++; } } } - // Look for anything that no longer exists... + // Look for services and their primary processes that no longer exist... for (int i=0; i procs = mProcesses.valueAt(i); Iterator pit = procs.values().iterator(); while (pit.hasNext()) { ProcessItem pi = pit.next(); - if (pi.mCurSeq != mSequence) { + if (pi.mCurSeq == mSequence) { + pi.ensureLabel(pm); + changed |= pi.updateSize(context); + 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) { mProcesses.remove(mProcesses.keyAt(i)); } + if (pi.mPid != 0) { + mActiveProcesses.remove(pi.mPid); + } continue; } Iterator sit = pi.mServices.values().iterator(); @@ -365,7 +568,11 @@ public class RunningServices extends ListActivity for (int i=0; i