/* * 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.pm.ApplicationInfo; import android.content.pm.PackageManager; import android.os.Parcel; import android.os.Parcelable; import android.util.ArrayMap; import android.util.Log; import android.util.SparseArray; import com.android.internal.app.ProcessStats; import java.util.ArrayList; import java.util.Collections; import java.util.Comparator; public final class ProcStatsEntry implements Parcelable { private static final String TAG = "ProcStatsEntry"; private static boolean DEBUG = ProcessStatsUi.DEBUG; final String mPackage; final int mUid; final String mName; public CharSequence mLabel; final ArrayList mPackages = new ArrayList(); final long mBgDuration; final long mAvgBgMem; final long mMaxBgMem; final double mBgWeight; final long mRunDuration; final long mAvgRunMem; final long mMaxRunMem; final double mRunWeight; String mBestTargetPackage; ArrayMap> mServices = new ArrayMap>(1); public ProcStatsEntry(ProcessStats.ProcessState proc, String packageName, ProcessStats.ProcessDataCollection tmpBgTotals, ProcessStats.ProcessDataCollection tmpRunTotals, boolean useUss) { ProcessStats.computeProcessData(proc, tmpBgTotals, 0); ProcessStats.computeProcessData(proc, tmpRunTotals, 0); mPackage = proc.mPackage; mUid = proc.mUid; mName = proc.mName; mPackages.add(packageName); mBgDuration = tmpBgTotals.totalTime; mAvgBgMem = useUss ? tmpBgTotals.avgUss : tmpBgTotals.avgPss; mMaxBgMem = useUss ? tmpBgTotals.maxUss : tmpBgTotals.maxPss; mBgWeight = mAvgBgMem * (double) mBgDuration; mRunDuration = tmpRunTotals.totalTime; mAvgRunMem = useUss ? tmpRunTotals.avgUss : tmpRunTotals.avgPss; mMaxRunMem = useUss ? tmpRunTotals.maxUss : tmpRunTotals.maxPss; mRunWeight = mAvgRunMem * (double) mRunDuration; if (DEBUG) Log.d(TAG, "New proc entry " + proc.mName + ": dur=" + mBgDuration + " avgpss=" + mAvgBgMem + " weight=" + mBgWeight); } public ProcStatsEntry(String pkgName, int uid, String procName, long duration, long mem, long memDuration) { mPackage = pkgName; mUid = uid; mName = procName; mBgDuration = mRunDuration = duration; mAvgBgMem = mMaxBgMem = mAvgRunMem = mMaxRunMem = mem; mBgWeight = mRunWeight = ((double)memDuration) * mem; if (DEBUG) Log.d(TAG, "New proc entry " + procName + ": dur=" + mBgDuration + " avgpss=" + mAvgBgMem + " weight=" + mBgWeight); } public ProcStatsEntry(Parcel in) { mPackage = in.readString(); mUid = in.readInt(); mName = in.readString(); in.readStringList(mPackages); mBgDuration = in.readLong(); mAvgBgMem = in.readLong(); mMaxBgMem = in.readLong(); mBgWeight = in.readDouble(); mRunDuration = in.readLong(); mAvgRunMem = in.readLong(); mMaxRunMem = in.readLong(); mRunWeight = in.readDouble(); mBestTargetPackage = in.readString(); final int N = in.readInt(); if (N > 0) { mServices.ensureCapacity(N); for (int i=0; i value = new ArrayList(); in.readTypedList(value, Service.CREATOR); mServices.append(key, value); } } } public void addPackage(String packageName) { mPackages.add(packageName); } public void evaluateTargetPackage(PackageManager pm, ProcessStats stats, ProcessStats.ProcessDataCollection bgTotals, ProcessStats.ProcessDataCollection runTotals, Comparator compare, boolean useUss) { mBestTargetPackage = null; if (mPackages.size() == 1) { if (DEBUG) Log.d(TAG, "Eval pkg of " + mName + ": single pkg " + mPackages.get(0)); mBestTargetPackage = mPackages.get(0); return; } // If one of the packages is the framework itself, that wins. // See if there is one significant package that was running here. for (int ipkg=0; ipkg subProcs = new ArrayList<>(); for (int ipkg=0; ipkg vpkgs = stats.mPackages.get(mPackages.get(ipkg), mUid); for (int ivers=0; ivers 1) { Collections.sort(subProcs, compare); if (subProcs.get(0).mRunWeight > (subProcs.get(1).mRunWeight *3)) { if (DEBUG) Log.d(TAG, "Eval pkg of " + mName + ": best pkg " + subProcs.get(0).mPackage + " weight " + subProcs.get(0).mRunWeight + " better than " + subProcs.get(1).mPackage + " weight " + subProcs.get(1).mRunWeight); mBestTargetPackage = subProcs.get(0).mPackage; return; } // Couldn't find one that is best by weight, let's decide on best another // way: the one that has the longest running service, accounts for at least // half of the maximum weight, and has specified an explicit app icon. double maxWeight = subProcs.get(0).mRunWeight; long bestRunTime = -1; boolean bestPersistent = false; for (int i=0; i bestRunTime) { if (DEBUG) Log.d(TAG, "Eval pkg of " + mName + ": pkg " + subProc.mPackage + " new best pers run time " + thisRunTime); bestRunTime = thisRunTime; bestPersistent = true; } else { if (DEBUG) Log.d(TAG, "Eval pkg of " + mName + ": pkg " + subProc.mPackage + " pers run time " + thisRunTime + " not as good as last " + bestRunTime); } continue; } else if (bestPersistent) { if (DEBUG) Log.d(TAG, "Eval pkg of " + mName + ": pkg " + subProc.mPackage + " is not persistent"); continue; } } catch (PackageManager.NameNotFoundException e) { if (DEBUG) Log.d(TAG, "Eval pkg of " + mName + ": pkg " + subProc.mPackage + " failed finding app info"); continue; } ArrayList subProcServices = null; for (int isp=0, NSP=mServices.size(); isp subServices = mServices.valueAt(isp); if (subServices.get(0).mPackage.equals(subProc.mPackage)) { subProcServices = subServices; break; } } long thisRunTime = 0; if (subProcServices != null) { for (int iss=0, NSS=subProcServices.size(); iss thisRunTime) { if (DEBUG) Log.d(TAG, "Eval pkg of " + mName + ": pkg " + subProc.mPackage + " service " + service.mName + " run time is " + service.mDuration); thisRunTime = service.mDuration; break; } } } if (thisRunTime > bestRunTime) { if (DEBUG) Log.d(TAG, "Eval pkg of " + mName + ": pkg " + subProc.mPackage + " new best run time " + thisRunTime); mBestTargetPackage = subProc.mPackage; bestRunTime = thisRunTime; } else { if (DEBUG) Log.d(TAG, "Eval pkg of " + mName + ": pkg " + subProc.mPackage + " run time " + thisRunTime + " not as good as last " + bestRunTime); } } } else if (subProcs.size() == 1) { mBestTargetPackage = subProcs.get(0).mPackage; } } public void addService(ProcessStats.ServiceState svc) { ArrayList services = mServices.get(svc.mPackage); if (services == null) { services = new ArrayList(); mServices.put(svc.mPackage, services); } services.add(new Service(svc)); } @Override public int describeContents() { return 0; } @Override public void writeToParcel(Parcel dest, int flags) { dest.writeString(mPackage); dest.writeInt(mUid); dest.writeString(mName); dest.writeStringList(mPackages); dest.writeLong(mBgDuration); dest.writeLong(mAvgBgMem); dest.writeLong(mMaxBgMem); dest.writeDouble(mBgWeight); dest.writeLong(mRunDuration); dest.writeLong(mAvgRunMem); dest.writeLong(mMaxRunMem); dest.writeDouble(mRunWeight); dest.writeString(mBestTargetPackage); final int N = mServices.size(); dest.writeInt(N); for (int i=0; i CREATOR = new Parcelable.Creator() { public ProcStatsEntry createFromParcel(Parcel in) { return new ProcStatsEntry(in); } public ProcStatsEntry[] newArray(int size) { return new ProcStatsEntry[size]; } }; public static final class Service implements Parcelable { final String mPackage; final String mName; final String mProcess; final long mDuration; public Service(ProcessStats.ServiceState service) { mPackage = service.mPackage; mName = service.mName; mProcess = service.mProcessName; mDuration = ProcessStats.dumpSingleServiceTime(null, null, service, ProcessStats.ServiceState.SERVICE_RUN, ProcessStats.STATE_NOTHING, 0, 0); } public Service(Parcel in) { mPackage = in.readString(); mName = in.readString(); mProcess = in.readString(); mDuration = in.readLong(); } @Override public int describeContents() { return 0; } @Override public void writeToParcel(Parcel dest, int flags) { dest.writeString(mPackage); dest.writeString(mName); dest.writeString(mProcess); dest.writeLong(mDuration); } public static final Parcelable.Creator CREATOR = new Parcelable.Creator() { public Service createFromParcel(Parcel in) { return new Service(in); } public Service[] newArray(int size) { return new Service[size]; } }; } }