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