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