diff --git a/res/layout/preference_linearcolor.xml b/res/layout/preference_linearcolor.xml new file mode 100644 index 00000000000..bbaf7a1bc89 --- /dev/null +++ b/res/layout/preference_linearcolor.xml @@ -0,0 +1,30 @@ + + + + + diff --git a/res/values/arrays.xml b/res/values/arrays.xml index 72a6b157e13..44981152342 100644 --- a/res/values/arrays.xml +++ b/res/values/arrays.xml @@ -1149,4 +1149,16 @@ Always allow + + + + normal + + moderate + + low + + critical + + diff --git a/res/values/strings.xml b/res/values/strings.xml index b787c8dbe2e..cdf0243166f 100644 --- a/res/values/strings.xml +++ b/res/values/strings.xml @@ -3557,7 +3557,10 @@ Memory use - Over %1$s + Stats over %1$s + + Device memory is currently + %1$s diff --git a/src/com/android/settings/applications/LinearColorBar.java b/src/com/android/settings/applications/LinearColorBar.java index 74fb02e3757..8343595f9e1 100644 --- a/src/com/android/settings/applications/LinearColorBar.java +++ b/src/com/android/settings/applications/LinearColorBar.java @@ -23,6 +23,11 @@ public class LinearColorBar extends LinearLayout { private float mYellowRatio; private float mGreenRatio; + private int mLeftColor = LEFT_COLOR; + private int mMiddleColor = MIDDLE_COLOR; + private int mRightColor = RIGHT_COLOR; + + private boolean mShowIndicator = true; private boolean mShowingGreen; final Rect mRect = new Rect(); @@ -57,6 +62,20 @@ public class LinearColorBar extends LinearLayout { invalidate(); } + public void setColors(int red, int yellow, int green) { + mLeftColor = red; + mMiddleColor = yellow; + mRightColor = green; + updateIndicator(); + invalidate(); + } + + public void setShowIndicator(boolean showIndicator) { + mShowIndicator = showIndicator; + updateIndicator(); + invalidate(); + } + public void setShowingGreen(boolean showingGreen) { if (mShowingGreen != showingGreen) { mShowingGreen = showingGreen; @@ -70,12 +89,15 @@ public class LinearColorBar extends LinearLayout { if (off < 0) off = 0; mRect.top = off; mRect.bottom = getHeight(); + if (!mShowIndicator) { + return; + } if (mShowingGreen) { mColorGradientPaint.setShader(new LinearGradient( - 0, 0, 0, off-2, RIGHT_COLOR&0xffffff, RIGHT_COLOR, Shader.TileMode.CLAMP)); + 0, 0, 0, off-2, mRightColor &0xffffff, mRightColor, Shader.TileMode.CLAMP)); } else { mColorGradientPaint.setShader(new LinearGradient( - 0, 0, 0, off-2, MIDDLE_COLOR&0xffffff, MIDDLE_COLOR, Shader.TileMode.CLAMP)); + 0, 0, 0, off-2, mMiddleColor&0xffffff, mMiddleColor, Shader.TileMode.CLAMP)); } mEdgeGradientPaint.setShader(new LinearGradient( 0, 0, 0, off/2, 0x00a0a0a0, 0xffa0a0a0, Shader.TileMode.CLAMP)); @@ -111,7 +133,7 @@ public class LinearColorBar extends LinearLayout { if (mLastInterestingLeft != indicatorLeft || mLastInterestingRight != indicatorRight) { mColorPath.reset(); mEdgePath.reset(); - if (indicatorLeft < indicatorRight) { + if (mShowIndicator && indicatorLeft < indicatorRight) { final int midTopY = mRect.top; final int midBottomY = 0; final int xoff = 2; @@ -146,7 +168,7 @@ public class LinearColorBar extends LinearLayout { if (left < right) { mRect.left = left; mRect.right = right; - mPaint.setColor(LEFT_COLOR); + mPaint.setColor(mLeftColor); canvas.drawRect(mRect, mPaint); width -= (right-left); left = right; @@ -157,7 +179,7 @@ public class LinearColorBar extends LinearLayout { if (left < right) { mRect.left = left; mRect.right = right; - mPaint.setColor(MIDDLE_COLOR); + mPaint.setColor(mMiddleColor); canvas.drawRect(mRect, mPaint); width -= (right-left); left = right; @@ -168,7 +190,7 @@ public class LinearColorBar extends LinearLayout { if (left < right) { mRect.left = left; mRect.right = right; - mPaint.setColor(RIGHT_COLOR); + mPaint.setColor(mRightColor); canvas.drawRect(mRect, mPaint); } } diff --git a/src/com/android/settings/applications/LinearColorPreference.java b/src/com/android/settings/applications/LinearColorPreference.java new file mode 100644 index 00000000000..6d9a399ed73 --- /dev/null +++ b/src/com/android/settings/applications/LinearColorPreference.java @@ -0,0 +1,51 @@ +/* + * Copyright (C) 2013 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.settings.applications; + +import android.content.Context; +import android.preference.Preference; +import android.view.View; +import com.android.settings.R; + +public class LinearColorPreference extends Preference { + float mRedRatio; + float mYellowRatio; + float mGreenRatio; + + public LinearColorPreference(Context context) { + super(context); + setLayoutResource(R.layout.preference_linearcolor); + } + + public void setRatios(float red, float yellow, float green) { + mRedRatio = red; + mYellowRatio = yellow; + mGreenRatio = green; + notifyChanged(); + } + + @Override + protected void onBindView(View view) { + super.onBindView(view); + + LinearColorBar colors = (LinearColorBar)view.findViewById( + R.id.linear_color_bar); + colors.setShowIndicator(false); + colors.setColors(0xffcc3000, 0xffcccc00, 0xff00cc30); + colors.setRatios(mRedRatio, mYellowRatio, mGreenRatio); + } +} diff --git a/src/com/android/settings/applications/ProcStatsEntry.java b/src/com/android/settings/applications/ProcStatsEntry.java index dec283f1b73..e1802054f16 100644 --- a/src/com/android/settings/applications/ProcStatsEntry.java +++ b/src/com/android/settings/applications/ProcStatsEntry.java @@ -18,7 +18,9 @@ package com.android.settings.applications; import com.android.internal.app.ProcessStats; -public class ProcStatsEntry { +import java.util.ArrayList; + +public final class ProcStatsEntry { final String mPackage; final int mUid; final String mName; @@ -27,7 +29,10 @@ public class ProcStatsEntry { final long mAvgPss; final long mWeight; - ProcStatsEntry(ProcessStats.ProcessState proc, ProcessStats.ProcessDataCollection tmpTotals) { + ArrayList mServices; + + public ProcStatsEntry(ProcessStats.ProcessState proc, + ProcessStats.ProcessDataCollection tmpTotals) { ProcessStats.computeProcessData(proc, tmpTotals, 0); mPackage = proc.mPackage; mUid = proc.mUid; @@ -37,4 +42,35 @@ public class ProcStatsEntry { mAvgPss = tmpTotals.avgPss; mWeight = mDuration * mAvgPss; } + + public void addServices(ProcessStats.PackageState pkgState) { + for (int isvc=0, NSVC=pkgState.mServices.size(); isvc(); + } + mServices.add(new Service(svc)); + } + } + + public static final class Service { + final String mPackage; + final String mName; + final long mDuration; + + public Service(ProcessStats.ServiceState service) { + mPackage = service.mPackage; + mName = service.mName; + mDuration = ProcessStats.dumpSingleServiceTime(null, null, service, + ProcessStats.ServiceState.SERVICE_STARTED, + ProcessStats.STATE_NOTHING, 0, 0) + + ProcessStats.dumpSingleServiceTime(null, null, service, + ProcessStats.ServiceState.SERVICE_BOUND, + ProcessStats.STATE_NOTHING, 0, 0) + + ProcessStats.dumpSingleServiceTime(null, null, service, + ProcessStats.ServiceState.SERVICE_EXEC, + ProcessStats.STATE_NOTHING, 0, 0); + } + } } diff --git a/src/com/android/settings/applications/ProcessStatsUi.java b/src/com/android/settings/applications/ProcessStatsUi.java index 3632288a27f..ec49e0d5149 100644 --- a/src/com/android/settings/applications/ProcessStatsUi.java +++ b/src/com/android/settings/applications/ProcessStatsUi.java @@ -33,6 +33,7 @@ import android.preference.PreferenceGroup; import android.preference.PreferenceScreen; import android.text.format.DateFormat; import android.util.Log; +import android.util.SparseArray; import android.util.TimeUtils; import android.view.Menu; import android.view.MenuInflater; @@ -60,11 +61,24 @@ public class ProcessStatsUi extends PreferenceFragment { static final int MAX_ITEMS_TO_LIST = 20; + final static Comparator sEntryCompare = new Comparator() { + @Override + public int compare(ProcStatsEntry lhs, ProcStatsEntry rhs) { + if (lhs.mWeight < rhs.mWeight) { + return 1; + } else if (lhs.mWeight > rhs.mWeight) { + return -1; + } + return 0; + } + }; + private static ProcessStats sStatsXfer; IProcessStats mProcessStats; UserManager mUm; ProcessStats mStats; + int mMemState; private PreferenceGroup mAppListGroup; private Preference mMemStatusPref; @@ -169,8 +183,17 @@ public class ProcessStatsUi extends PreferenceFragment { mAppListGroup.addPreference(mMemStatusPref); String durationString = Utils.formatElapsedTime(getActivity(), mStats.mTimePeriodEndRealtime-mStats.mTimePeriodStartRealtime); + CharSequence memString; + CharSequence[] memStates = getResources().getTextArray(R.array.ram_states); + if (mMemState >= 0 && mMemState < memStates.length) { + memString = memStates[mMemState]; + } else { + memString = "?"; + } mMemStatusPref.setTitle(getActivity().getString(R.string.process_stats_total_duration, durationString)); + mMemStatusPref.setSummary(getActivity().getString(R.string.process_stats_memory_status, + memString)); /* mMemStatusPref.setTitle(DateFormat.format(DateFormat.getBestDateTimePattern( getActivity().getResources().getConfiguration().locale, @@ -188,30 +211,47 @@ public class ProcessStatsUi extends PreferenceFragment { long now = SystemClock.uptimeMillis(); + final PackageManager pm = getActivity().getPackageManager(); + mTotalTime = ProcessStats.dumpSingleTime(null, null, mStats.mMemFactorDurations, mStats.mMemFactor, mStats.mStartTime, now); + LinearColorPreference colors = new LinearColorPreference(getActivity()); + colors.setOrder(-1); + mAppListGroup.addPreference(colors); + + long[] memTimes = new long[ProcessStats.ADJ_MEM_FACTOR_COUNT]; + for (int iscreen=0; iscreen procs = new ArrayList(); + + /* ArrayList rawProcs = mStats.collectProcessesLocked( ProcessStats.ALL_SCREEN_ADJ, ProcessStats.ALL_MEM_ADJ, ProcessStats.BACKGROUND_PROC_STATES, now, null); - - final PackageManager pm = getActivity().getPackageManager(); - - ArrayList procs = new ArrayList(); for (int i=0, N=(rawProcs != null ? rawProcs.size() : 0); i() { - @Override - public int compare(ProcStatsEntry lhs, ProcStatsEntry rhs) { - if (lhs.mWeight < rhs.mWeight) { - return 1; - } else if (lhs.mWeight > rhs.mWeight) { - return -1; - } - return 0; + */ + + for (int ip=0, N=mStats.mProcesses.getMap().size(); ip uids = mStats.mProcesses.getMap().valueAt(ip); + for (int iu=0; iu MAX_ITEMS_TO_LIST) { procs.remove(procs.size()-1); } @@ -232,19 +272,56 @@ public class ProcessStatsUi extends PreferenceFragment { ProcessStatsPreference pref = new ProcessStatsPreference(getActivity(), null); ApplicationInfo targetApp = null; String label = proc.mName; + String pkgName = null; if (proc.mUnique) { + pkgName = proc.mPackage; + proc.addServices(mStats.getPackageStateLocked(proc.mPackage, proc.mUid)); + } else { + // See if there is one significant package that was running here. + ArrayList subProcs = new ArrayList(); + for (int ipkg=0, NPKG=mStats.mPackages.getMap().size(); ipkg uids + = mStats.mPackages.getMap().valueAt(ipkg); + for (int iu=0, NU=uids.size(); iu 1) { + Collections.sort(subProcs, sEntryCompare); + if (subProcs.get(0).mWeight > (subProcs.get(1).mWeight*3)) { + pkgName = subProcs.get(0).mPackage; + } + } + } + if (pkgName != null) { // Only one app associated with this process. try { - targetApp = pm.getApplicationInfo(proc.mPackage, + targetApp = pm.getApplicationInfo(pkgName, PackageManager.GET_DISABLED_COMPONENTS | PackageManager.GET_DISABLED_UNTIL_USED_COMPONENTS | PackageManager.GET_UNINSTALLED_PACKAGES); String name = targetApp.loadLabel(pm).toString(); - if (proc.mName.equals(proc.mPackage)) { + if (proc.mName.equals(pkgName)) { label = name; } else { - if (proc.mName.startsWith(proc.mPackage)) { - int off = proc.mPackage.length(); + if (proc.mName.startsWith(pkgName)) { + int off = pkgName.length(); if (proc.mName.length() > off) { off++; } @@ -258,15 +335,15 @@ public class ProcessStatsUi extends PreferenceFragment { } if (targetApp == null) { String[] packages = pm.getPackagesForUid(proc.mUid); - for (String pkgName : packages) { + for (String curPkg : packages) { try { - final PackageInfo pi = pm.getPackageInfo(pkgName, + final PackageInfo pi = pm.getPackageInfo(curPkg, PackageManager.GET_DISABLED_COMPONENTS | PackageManager.GET_DISABLED_UNTIL_USED_COMPONENTS | PackageManager.GET_UNINSTALLED_PACKAGES); if (pi.sharedUserLabel != 0) { targetApp = pi.applicationInfo; - final CharSequence nm = pm.getText(pkgName, + final CharSequence nm = pm.getText(curPkg, pi.sharedUserLabel, pi.applicationInfo); if (nm != null) { label = nm.toString() + " (" + proc.mName + ")"; @@ -293,6 +370,7 @@ public class ProcessStatsUi extends PreferenceFragment { private void load() { try { + mMemState = mProcessStats.getCurrentMemoryState(); ArrayList fds = new ArrayList(); byte[] data = mProcessStats.getCurrentStats(fds); Parcel parcel = Parcel.obtain(); @@ -300,7 +378,7 @@ public class ProcessStatsUi extends PreferenceFragment { parcel.setDataPosition(0); mStats = ProcessStats.CREATOR.createFromParcel(parcel); int i = fds.size()-1; - while (i > 0 && (mStats.mTimePeriodEndRealtime-mStats.mTimePeriodStartRealtime) + while (i >= 0 && (mStats.mTimePeriodEndRealtime-mStats.mTimePeriodStartRealtime) < (24*60*60*1000)) { Log.i(TAG, "Not enough data, loading next file @ " + i); ProcessStats stats = new ProcessStats(false);