1 /*
2  * Copyright (C) 2015 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 
17 package com.android.settings.applications;
18 
19 import android.content.Context;
20 import android.content.pm.ApplicationInfo;
21 import android.content.pm.PackageManager;
22 import android.os.Parcel;
23 import android.os.Parcelable;
24 
25 import com.android.settings.R;
26 import com.android.settings.Utils;
27 
28 import java.util.ArrayList;
29 
30 public class ProcStatsPackageEntry implements Parcelable {
31     private static final String TAG = "ProcStatsEntry";
32     private static boolean DEBUG = ProcessStatsUi.DEBUG;
33 
34     private static final float ALWAYS_THRESHOLD = .95f;
35     private static final float SOMETIMES_THRESHOLD = .25f;
36 
37     final String mPackage;
38     final ArrayList<ProcStatsEntry> mEntries = new ArrayList<ProcStatsEntry>();
39 
40     long mBgDuration;
41     long mAvgBgMem;
42     long mMaxBgMem;
43     double mBgWeight;
44     long mRunDuration;
45     long mAvgRunMem;
46     long mMaxRunMem;
47     double mRunWeight;
48 
49     public ApplicationInfo mUiTargetApp;
50     public String mUiLabel;
51     private long mWindowLength;
52 
ProcStatsPackageEntry(String pkg, long windowLength)53     public ProcStatsPackageEntry(String pkg, long windowLength) {
54         mPackage = pkg;
55         mWindowLength = windowLength;
56     }
57 
ProcStatsPackageEntry(Parcel in)58     public ProcStatsPackageEntry(Parcel in) {
59         mPackage = in.readString();
60         in.readTypedList(mEntries, ProcStatsEntry.CREATOR);
61         mBgDuration = in.readLong();
62         mAvgBgMem = in.readLong();
63         mMaxBgMem = in.readLong();
64         mBgWeight = in.readDouble();
65         mRunDuration = in.readLong();
66         mAvgRunMem = in.readLong();
67         mMaxRunMem = in.readLong();
68         mRunWeight = in.readDouble();
69     }
70 
getRunningFrequency(Context context)71     public CharSequence getRunningFrequency(Context context) {
72         float amountRunning = mRunDuration / (float) mWindowLength;
73         return getFrequency(amountRunning, context);
74     }
75 
getBackgroundFrequency(Context context)76     public CharSequence getBackgroundFrequency(Context context) {
77         float amountRunning = mBgDuration / (float) mWindowLength;
78         return getFrequency(amountRunning, context);
79     }
80 
addEntry(ProcStatsEntry entry)81     public void addEntry(ProcStatsEntry entry) {
82         mEntries.add(entry);
83     }
84 
updateMetrics()85     public void updateMetrics() {
86         mBgDuration = mAvgBgMem = mMaxBgMem = 0;
87         mBgWeight = 0;
88         mRunDuration = mAvgRunMem = mMaxRunMem = 0;
89         mRunWeight = 0;
90         final int N = mEntries.size();
91         for (int i=0; i < N; i++) {
92             ProcStatsEntry entry = mEntries.get(i);
93             mBgDuration = Math.max(entry.mBgDuration, mBgDuration);
94             mAvgBgMem += entry.mAvgBgMem;
95             mBgWeight += entry.mBgWeight;
96             mRunDuration = Math.max(entry.mRunDuration, mRunDuration);
97             mAvgRunMem += entry.mAvgRunMem;
98             mRunWeight += entry.mRunWeight;
99 
100             // Each entry is generally a process or something similar.  Since it is extremely
101             // unlikely that any apps are going to avoid running processes at the same time
102             // to avoid memory usage, we will sum the maximum memory usage to create a
103             // hypothetical worst case scenario of memory.
104             mMaxBgMem += entry.mMaxBgMem;
105             mMaxRunMem += entry.mMaxRunMem;
106         }
107         mAvgBgMem /= N;
108         mAvgRunMem /= N;
109     }
110 
retrieveUiData(Context context, PackageManager pm)111     public void retrieveUiData(Context context, PackageManager pm) {
112         mUiTargetApp = null;
113         mUiLabel = mPackage;
114         // Only one app associated with this process.
115         try {
116             if ("os".equals(mPackage)) {
117                 mUiTargetApp = pm.getApplicationInfo("android",
118                         PackageManager.GET_DISABLED_COMPONENTS |
119                         PackageManager.GET_DISABLED_UNTIL_USED_COMPONENTS |
120                         PackageManager.GET_UNINSTALLED_PACKAGES);
121                 mUiLabel = context.getString(R.string.process_stats_os_label);
122             } else {
123                 mUiTargetApp = pm.getApplicationInfo(mPackage,
124                         PackageManager.GET_DISABLED_COMPONENTS |
125                         PackageManager.GET_DISABLED_UNTIL_USED_COMPONENTS |
126                         PackageManager.GET_UNINSTALLED_PACKAGES);
127                 mUiLabel = mUiTargetApp.loadLabel(pm).toString();
128             }
129         } catch (PackageManager.NameNotFoundException e) {
130         }
131     }
132 
133     @Override
describeContents()134     public int describeContents() {
135         return 0;
136     }
137 
138     @Override
writeToParcel(Parcel dest, int flags)139     public void writeToParcel(Parcel dest, int flags) {
140         dest.writeString(mPackage);
141         dest.writeTypedList(mEntries);
142         dest.writeLong(mBgDuration);
143         dest.writeLong(mAvgBgMem);
144         dest.writeLong(mMaxBgMem);
145         dest.writeDouble(mBgWeight);
146         dest.writeLong(mRunDuration);
147         dest.writeLong(mAvgRunMem);
148         dest.writeLong(mMaxRunMem);
149         dest.writeDouble(mRunWeight);
150     }
151 
152     public static final Parcelable.Creator<ProcStatsPackageEntry> CREATOR
153             = new Parcelable.Creator<ProcStatsPackageEntry>() {
154         public ProcStatsPackageEntry createFromParcel(Parcel in) {
155             return new ProcStatsPackageEntry(in);
156         }
157 
158         public ProcStatsPackageEntry[] newArray(int size) {
159             return new ProcStatsPackageEntry[size];
160         }
161     };
162 
163     // TODO: Find better place for this.
getFrequency(float amount, Context context)164     public static CharSequence getFrequency(float amount, Context context) {
165         if (amount > ALWAYS_THRESHOLD) {
166             return context.getString(R.string.always_running,
167                     Utils.formatPercentage((int) (amount * 100)));
168         } else if (amount > SOMETIMES_THRESHOLD) {
169             return context.getString(R.string.sometimes_running,
170                     Utils.formatPercentage((int) (amount * 100)));
171         } else {
172             return context.getString(R.string.rarely_running,
173                     Utils.formatPercentage((int) (amount * 100)));
174         }
175     }
176 }
177