Home | History | Annotate | Download | only in applications
      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 
     54     public ProcStatsPackageEntry(String pkg, long windowLength) {
     55         mPackage = pkg;
     56         mWindowLength = windowLength;
     57     }
     58 
     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 
     72     public CharSequence getRunningFrequency(Context context) {
     73         float amountRunning = mRunDuration / (float) mWindowLength;
     74         return getFrequency(amountRunning, context);
     75     }
     76 
     77     public CharSequence getBackgroundFrequency(Context context) {
     78         float amountRunning = mBgDuration / (float) mWindowLength;
     79         return getFrequency(amountRunning, context);
     80     }
     81 
     82     public void addEntry(ProcStatsEntry entry) {
     83         mEntries.add(entry);
     84     }
     85 
     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 
    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
    136     public int describeContents() {
    137         return 0;
    138     }
    139 
    140     @Override
    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.
    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