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

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

Merge "Improve process stats UI." into klp-dev

parents c0f79432 c9e4bd11
Loading
Loading
Loading
Loading
+5 −3
Original line number Diff line number Diff line
@@ -3550,12 +3550,14 @@
    <!-- Process Stats strings -->
    <skip />

    <!-- Activity title for Process Stats summary -->
    <!-- [CHAR LIMIT=NONE] Activity title for Process Stats summary -->
    <string name="process_stats_summary_title">Process Stats</string>
    <!-- Activity title summary for Process Stats summary -->
    <!-- [CHAR LIMIT=NONE] Activity title summary for Process Stats summary -->
    <string name="process_stats_summary">Geeky stats about running processes</string>
    <!-- Battery usage since unplugged -->
    <!-- [CHAR LIMIT=NONE] Label for amount of memory use -->
    <string name="app_memory_use">Memory use</string>
    <!-- [CHAR LIMIT=NONE] Label for process stats, duration of time the stats are over -->
    <string name="process_stats_total_duration">Over <xliff:g id="time">%1$s</xliff:g></string>

    <!-- Voice input/output settings --><skip />
    <!-- Title of setting on main settings screen. This item will take the user to the screen to tweak settings related to speech functionality -->
+40 −0
Original line number Diff line number Diff line
/*
 * 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 com.android.internal.app.ProcessStats;

public class ProcStatsEntry {
    final String mPackage;
    final int mUid;
    final String mName;
    final boolean mUnique;
    final long mDuration;
    final long mAvgPss;
    final long mWeight;

    ProcStatsEntry(ProcessStats.ProcessState proc, ProcessStats.ProcessDataCollection tmpTotals) {
        ProcessStats.computeProcessData(proc, tmpTotals, 0);
        mPackage = proc.mPackage;
        mUid = proc.mUid;
        mName = proc.mName;
        mUnique = proc.mCommonProcess == proc;
        mDuration = tmpTotals.totalTime;
        mAvgPss = tmpTotals.avgPss;
        mWeight = mDuration * mAvgPss;
    }
}
+4 −3
Original line number Diff line number Diff line
@@ -36,9 +36,10 @@ public class ProcessStatsPreference extends Preference {
        setIcon(icon != null ? icon : new ColorDrawable(0));
    }

    public void setPercent(double percentOfTotal, long pss) {
        mProgress = (int) Math.ceil(percentOfTotal);
        mProgressText = pss > 0 ? Formatter.formatShortFileSize(getContext(), pss) : "";
    public void setPercent(double percentOfWeight, double percentOfTime) {
        mProgress = (int) Math.ceil(percentOfWeight);
        mProgressText = getContext().getResources().getString(
                R.string.percentage, (int) Math.ceil(percentOfTime));
        notifyChanged();
    }

+93 −24
Original line number Diff line number Diff line
@@ -31,16 +31,22 @@ import android.preference.Preference;
import android.preference.PreferenceFragment;
import android.preference.PreferenceGroup;
import android.preference.PreferenceScreen;
import android.text.format.DateFormat;
import android.util.Log;
import android.util.TimeUtils;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import com.android.internal.app.IProcessStats;
import com.android.internal.app.ProcessStats;
import com.android.settings.R;
import com.android.settings.fuelgauge.Utils;

import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;

public class ProcessStatsUi extends PreferenceFragment {
    private static final String TAG = "ProcessStatsUi";
@@ -161,6 +167,15 @@ public class ProcessStatsUi extends PreferenceFragment {

        mMemStatusPref.setOrder(-2);
        mAppListGroup.addPreference(mMemStatusPref);
        String durationString = Utils.formatElapsedTime(getActivity(),
                mStats.mTimePeriodEndRealtime-mStats.mTimePeriodStartRealtime);
        mMemStatusPref.setTitle(getActivity().getString(R.string.process_stats_total_duration,
                durationString));
        /*
        mMemStatusPref.setTitle(DateFormat.format(DateFormat.getBestDateTimePattern(
                getActivity().getResources().getConfiguration().locale,
                "MMMM dd, yyyy h:mm a"), mStats.mTimePeriodStartClock));
        */
        /*
        BatteryHistoryPreference hist = new BatteryHistoryPreference(getActivity(), mStats);
        hist.setOrder(-1);
@@ -176,45 +191,73 @@ public class ProcessStatsUi extends PreferenceFragment {
        mTotalTime = ProcessStats.dumpSingleTime(null, null, mStats.mMemFactorDurations,
                mStats.mMemFactor, mStats.mStartTime, now);

        ArrayList<ProcessStats.ProcessState> procs = mStats.collectProcessesLocked(
        ArrayList<ProcessStats.ProcessState> rawProcs = mStats.collectProcessesLocked(
                ProcessStats.ALL_SCREEN_ADJ, ProcessStats.ALL_MEM_ADJ,
                ProcessStats.BACKGROUND_PROC_STATES, now, null);

        final PackageManager pm = getActivity().getPackageManager();

        ArrayList<ProcStatsEntry> procs = new ArrayList<ProcStatsEntry>();
        for (int i=0, N=(rawProcs != null ? rawProcs.size() : 0); i<N; i++) {
            procs.add(new ProcStatsEntry(rawProcs.get(i), totals));
        }
        Collections.sort(procs, new Comparator<ProcStatsEntry>() {
            @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;
            }
        });
        while (procs.size() > MAX_ITEMS_TO_LIST) {
            procs.remove(procs.size()-1);
        }

        long maxWeight = 0;
        for (int i=0, N=(procs != null ? procs.size() : 0); i<N; i++) {
            ProcStatsEntry proc = procs.get(i);
            if (maxWeight < proc.mWeight) {
                maxWeight = proc.mWeight;
            }
        }

        for (int i=0, N=(procs != null ? procs.size() : 0); i<N; i++) {
            ProcessStats.ProcessState ps = procs.get(i);
            final double percentOfTotal = (((double)ps.mTmpTotalTime) / mTotalTime) * 100;
            if (percentOfTotal < 1) continue;
            ProcStatsEntry proc = procs.get(i);
            final double percentOfWeight = (((double)proc.mWeight) / maxWeight) * 100;
            final double percentOfTime = (((double)proc.mDuration) / mTotalTime) * 100;
            if (percentOfWeight < 1) continue;
            ProcessStatsPreference pref = new ProcessStatsPreference(getActivity(), null);
            ApplicationInfo targetApp = null;
            String label = ps.mName;
            if (ps.mCommonProcess == ps) {
            String label = proc.mName;
            if (proc.mUnique) {
                // Only one app associated with this process.
                try {
                    targetApp = pm.getApplicationInfo(ps.mPackage,
                    targetApp = pm.getApplicationInfo(proc.mPackage,
                            PackageManager.GET_DISABLED_COMPONENTS |
                            PackageManager.GET_DISABLED_UNTIL_USED_COMPONENTS |
                            PackageManager.GET_UNINSTALLED_PACKAGES);
                    String name = targetApp.loadLabel(pm).toString();
                    if (ps.mName.equals(ps.mPackage)) {
                    if (proc.mName.equals(proc.mPackage)) {
                        label = name;
                    } else {
                        if (ps.mName.startsWith(ps.mPackage)) {
                            int off = ps.mPackage.length();
                            if (ps.mName.length() > off) {
                        if (proc.mName.startsWith(proc.mPackage)) {
                            int off = proc.mPackage.length();
                            if (proc.mName.length() > off) {
                                off++;
                            }
                            label = name + " (" + ps.mName.substring(off) + ")";
                            label = name + " (" + proc.mName.substring(off) + ")";
                        } else {
                            label = name + " (" + ps.mName + ")";
                            label = name + " (" + proc.mName + ")";
                        }
                    }
                } catch (PackageManager.NameNotFoundException e) {
                }
            }
            if (targetApp == null) {
                String[] packages = pm.getPackagesForUid(ps.mUid);
                String[] packages = pm.getPackagesForUid(proc.mUid);
                for (String pkgName : packages) {
                    try {
                        final PackageInfo pi = pm.getPackageInfo(pkgName,
@@ -226,9 +269,10 @@ public class ProcessStatsUi extends PreferenceFragment {
                            final CharSequence nm = pm.getText(pkgName,
                                    pi.sharedUserLabel, pi.applicationInfo);
                            if (nm != null) {
                                label = nm.toString() + " (" + ps.mName + ")";
                                label = nm.toString() + " (" + proc.mName + ")";
                            } else {
                                label = targetApp.loadLabel(pm).toString() + " (" + ps.mName + ")";
                                label = targetApp.loadLabel(pm).toString() + " ("
                                        + proc.mName + ")";
                            }
                            break;
                        }
@@ -240,9 +284,8 @@ public class ProcessStatsUi extends PreferenceFragment {
            if (targetApp != null) {
                pref.setIcon(targetApp.loadIcon(pm));
            }
            pref.setOrder(N+100-i);
            ProcessStats.computeProcessData(ps, totals, now);
            pref.setPercent(percentOfTotal, totals.avgPss * 1024);
            pref.setOrder(i);
            pref.setPercent(percentOfWeight, percentOfTime);
            mAppListGroup.addPreference(pref);
            if (mAppListGroup.getPreferenceCount() > (MAX_ITEMS_TO_LIST+1)) break;
        }
@@ -252,16 +295,42 @@ public class ProcessStatsUi extends PreferenceFragment {
        try {
            ArrayList<ParcelFileDescriptor> fds = new ArrayList<ParcelFileDescriptor>();
            byte[] data = mProcessStats.getCurrentStats(fds);
            for (int i=0; i<fds.size(); i++) {
            Parcel parcel = Parcel.obtain();
            parcel.unmarshall(data, 0, data.length);
            parcel.setDataPosition(0);
            mStats = ProcessStats.CREATOR.createFromParcel(parcel);
            int i = fds.size()-1;
            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);
                InputStream stream = new ParcelFileDescriptor.AutoCloseInputStream(fds.get(i));
                stats.read(stream);
                try {
                    stream.close();
                } catch (IOException e) {
                }
                if (stats.mReadError == null) {
                    mStats.add(stats);
                    StringBuilder sb = new StringBuilder();
                    sb.append("Added stats: ");
                    sb.append(stats.mTimePeriodStartClockStr);
                    sb.append(", over ");
                    TimeUtils.formatDuration(
                            stats.mTimePeriodEndRealtime-stats.mTimePeriodStartRealtime, sb);
                    Log.i(TAG, sb.toString());
                } else {
                    Log.w(TAG, "Read error: " + stats.mReadError);
                }
                i--;
            }
            while (i >= 0) {
                try {
                    fds.get(i).close();
                } catch (IOException e) {
                }
                i--;
            }
            Parcel parcel = Parcel.obtain();
            parcel.unmarshall(data, 0, data.length);
            parcel.setDataPosition(0);
            mStats = ProcessStats.CREATOR.createFromParcel(parcel);
        } catch (RemoteException e) {
            Log.e(TAG, "RemoteException:", e);
        }