ProcStatsEntry.java revision 49759af6b06b884d3a1af9dbb120370893744b94
1/* 2 * Copyright (C) 2013 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17package com.android.settings.applications; 18 19import android.content.pm.ApplicationInfo; 20import android.content.pm.PackageInfo; 21import android.content.pm.PackageManager; 22import android.os.Parcel; 23import android.os.Parcelable; 24import android.util.Log; 25import android.util.SparseArray; 26import com.android.internal.app.ProcessStats; 27 28import java.util.ArrayList; 29import java.util.Collections; 30import java.util.Comparator; 31 32public final class ProcStatsEntry implements Parcelable { 33 private static final String TAG = "ProcStatsEntry"; 34 35 final String mPackage; 36 final int mUid; 37 final String mName; 38 final boolean mUnique; 39 final long mDuration; 40 final long mAvgPss; 41 final long mMaxPss; 42 final long mAvgUss; 43 final long mMaxUss; 44 final long mWeight; 45 46 String mBestTargetPackage; 47 48 ArrayList<Service> mServices = new ArrayList<Service>(2); 49 50 public ApplicationInfo mUiTargetApp; 51 public String mUiLabel; 52 public String mUiBaseLabel; 53 public String mUiPackage; 54 55 public ProcStatsEntry(ProcessStats.ProcessState proc, 56 ProcessStats.ProcessDataCollection tmpTotals, boolean useUss, boolean weightWithTime) { 57 ProcessStats.computeProcessData(proc, tmpTotals, 0); 58 mPackage = proc.mPackage; 59 mUid = proc.mUid; 60 mName = proc.mName; 61 mUnique = proc.mCommonProcess == proc; 62 mDuration = tmpTotals.totalTime; 63 mAvgPss = tmpTotals.avgPss; 64 mMaxPss = tmpTotals.maxPss; 65 mAvgUss = tmpTotals.avgUss; 66 mMaxUss = tmpTotals.maxUss; 67 mWeight = (weightWithTime ? mDuration : 1) * (useUss ? mAvgUss : mAvgPss); 68 } 69 70 public ProcStatsEntry(Parcel in) { 71 mPackage = in.readString(); 72 mUid = in.readInt(); 73 mName = in.readString(); 74 mUnique = in.readInt() != 0; 75 mDuration = in.readLong(); 76 mAvgPss = in.readLong(); 77 mMaxPss = in.readLong(); 78 mAvgUss = in.readLong(); 79 mMaxUss = in.readLong(); 80 mWeight = in.readLong(); 81 mBestTargetPackage = in.readString(); 82 in.readTypedList(mServices, Service.CREATOR); 83 } 84 85 public void evaluateTargetPackage(ProcessStats stats, ProcessStats.ProcessDataCollection totals, 86 Comparator<ProcStatsEntry> compare, boolean useUss, boolean weightWithTime) { 87 mBestTargetPackage = null; 88 if (mUnique) { 89 mBestTargetPackage = mPackage; 90 } else { 91 // See if there is one significant package that was running here. 92 ArrayList<ProcStatsEntry> subProcs = new ArrayList<ProcStatsEntry>(); 93 for (int ipkg=0, NPKG=stats.mPackages.getMap().size(); ipkg<NPKG; ipkg++) { 94 SparseArray<ProcessStats.PackageState> uids 95 = stats.mPackages.getMap().valueAt(ipkg); 96 for (int iu=0, NU=uids.size(); iu<NU; iu++) { 97 if (uids.keyAt(iu) != mUid) { 98 continue; 99 } 100 ProcessStats.PackageState pkgState = uids.valueAt(iu); 101 for (int iproc=0, NPROC=pkgState.mProcesses.size(); iproc<NPROC; iproc++) { 102 ProcessStats.ProcessState subProc = 103 pkgState.mProcesses.valueAt(iproc); 104 if (subProc.mName.equals(mName)) { 105 subProcs.add(new ProcStatsEntry(subProc, totals, useUss, 106 weightWithTime)); 107 } 108 } 109 } 110 } 111 if (subProcs.size() > 1) { 112 Collections.sort(subProcs, compare); 113 if (subProcs.get(0).mWeight > (subProcs.get(1).mWeight*3)) { 114 mBestTargetPackage = subProcs.get(0).mPackage; 115 } 116 } 117 } 118 } 119 120 public void retrieveUiData(PackageManager pm) { 121 mUiTargetApp = null; 122 mUiLabel = mUiBaseLabel = mName; 123 mUiPackage = mBestTargetPackage; 124 if (mUiPackage != null) { 125 // Only one app associated with this process. 126 try { 127 mUiTargetApp = pm.getApplicationInfo(mUiPackage, 128 PackageManager.GET_DISABLED_COMPONENTS | 129 PackageManager.GET_DISABLED_UNTIL_USED_COMPONENTS | 130 PackageManager.GET_UNINSTALLED_PACKAGES); 131 String name = mUiBaseLabel = mUiTargetApp.loadLabel(pm).toString(); 132 if (mName.equals(mUiPackage)) { 133 mUiLabel = name; 134 } else { 135 if (mName.startsWith(mUiPackage)) { 136 int off = mUiPackage.length(); 137 if (mName.length() > off) { 138 off++; 139 } 140 mUiLabel = name + " (" + mName.substring(off) + ")"; 141 } else { 142 mUiLabel = name + " (" + mName + ")"; 143 } 144 } 145 } catch (PackageManager.NameNotFoundException e) { 146 } 147 } 148 if (mUiTargetApp == null) { 149 String[] packages = pm.getPackagesForUid(mUid); 150 if (packages != null) { 151 for (String curPkg : packages) { 152 try { 153 final PackageInfo pi = pm.getPackageInfo(curPkg, 154 PackageManager.GET_DISABLED_COMPONENTS | 155 PackageManager.GET_DISABLED_UNTIL_USED_COMPONENTS | 156 PackageManager.GET_UNINSTALLED_PACKAGES); 157 if (pi.sharedUserLabel != 0) { 158 mUiTargetApp = pi.applicationInfo; 159 final CharSequence nm = pm.getText(curPkg, 160 pi.sharedUserLabel, pi.applicationInfo); 161 if (nm != null) { 162 mUiBaseLabel = nm.toString(); 163 mUiLabel = mUiBaseLabel + " (" + mName + ")"; 164 } else { 165 mUiBaseLabel = mUiTargetApp.loadLabel(pm).toString(); 166 mUiLabel = mUiBaseLabel + " (" + mName + ")"; 167 } 168 break; 169 } 170 } catch (PackageManager.NameNotFoundException e) { 171 } 172 } 173 } else { 174 // no current packages for this uid, typically because of uninstall 175 Log.i(TAG, "No package for uid " + mUid); 176 } 177 } 178 } 179 180 public void addService(ProcessStats.ServiceState svc) { 181 mServices.add(new Service(svc)); 182 } 183 184 @Override 185 public int describeContents() { 186 return 0; 187 } 188 189 @Override 190 public void writeToParcel(Parcel dest, int flags) { 191 dest.writeString(mPackage); 192 dest.writeInt(mUid); 193 dest.writeString(mName); 194 dest.writeInt(mUnique ? 1 : 0); 195 dest.writeLong(mDuration); 196 dest.writeLong(mAvgPss); 197 dest.writeLong(mMaxPss); 198 dest.writeLong(mAvgUss); 199 dest.writeLong(mMaxUss); 200 dest.writeLong(mWeight); 201 dest.writeString(mBestTargetPackage); 202 dest.writeTypedList(mServices); 203 } 204 205 public static final Parcelable.Creator<ProcStatsEntry> CREATOR 206 = new Parcelable.Creator<ProcStatsEntry>() { 207 public ProcStatsEntry createFromParcel(Parcel in) { 208 return new ProcStatsEntry(in); 209 } 210 211 public ProcStatsEntry[] newArray(int size) { 212 return new ProcStatsEntry[size]; 213 } 214 }; 215 216 public static final class Service implements Parcelable { 217 final String mPackage; 218 final String mName; 219 final String mProcess; 220 final long mDuration; 221 222 public Service(ProcessStats.ServiceState service) { 223 mPackage = service.mPackage; 224 mName = service.mName; 225 mProcess = service.mProcessName; 226 mDuration = ProcessStats.dumpSingleServiceTime(null, null, service, 227 ProcessStats.ServiceState.SERVICE_RUN, 228 ProcessStats.STATE_NOTHING, 0, 0); 229 } 230 231 public Service(Parcel in) { 232 mPackage = in.readString(); 233 mName = in.readString(); 234 mProcess = in.readString(); 235 mDuration = in.readLong(); 236 } 237 238 @Override 239 public int describeContents() { 240 return 0; 241 } 242 243 @Override 244 public void writeToParcel(Parcel dest, int flags) { 245 dest.writeString(mPackage); 246 dest.writeString(mName); 247 dest.writeString(mProcess); 248 dest.writeLong(mDuration); 249 } 250 251 public static final Parcelable.Creator<Service> CREATOR 252 = new Parcelable.Creator<Service>() { 253 public Service createFromParcel(Parcel in) { 254 return new Service(in); 255 } 256 257 public Service[] newArray(int size) { 258 return new Service[size]; 259 } 260 }; 261 } 262} 263