Home | History | Annotate | Download | only in am
      1 /*
      2  * Copyright (C) 2006 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.server.am;
     18 
     19 import com.android.internal.os.BatteryStatsImpl;
     20 
     21 import android.app.ActivityManager;
     22 import android.app.Dialog;
     23 import android.app.IApplicationThread;
     24 import android.app.IInstrumentationWatcher;
     25 import android.content.ComponentName;
     26 import android.content.pm.ApplicationInfo;
     27 import android.os.Bundle;
     28 import android.os.IBinder;
     29 import android.os.SystemClock;
     30 import android.util.PrintWriterPrinter;
     31 import android.util.TimeUtils;
     32 
     33 import java.io.PrintWriter;
     34 import java.util.ArrayList;
     35 import java.util.HashMap;
     36 import java.util.HashSet;
     37 
     38 /**
     39  * Full information about a particular process that
     40  * is currently running.
     41  */
     42 class ProcessRecord {
     43     final BatteryStatsImpl.Uid.Proc batteryStats; // where to collect runtime statistics
     44     final ApplicationInfo info; // all about the first app in the process
     45     final String processName;   // name of the process
     46     // List of packages running in the process
     47     final HashSet<String> pkgList = new HashSet<String>();
     48     IApplicationThread thread;  // the actual proc...  may be null only if
     49                                 // 'persistent' is true (in which case we
     50                                 // are in the process of launching the app)
     51     int pid;                    // The process of this application; 0 if none
     52     boolean starting;           // True if the process is being started
     53     long lastActivityTime;      // For managing the LRU list
     54     long lruWeight;             // Weight for ordering in LRU list
     55     int maxAdj;                 // Maximum OOM adjustment for this process
     56     int hiddenAdj;              // If hidden, this is the adjustment to use
     57     int curRawAdj;              // Current OOM unlimited adjustment for this process
     58     int setRawAdj;              // Last set OOM unlimited adjustment for this process
     59     int curAdj;                 // Current OOM adjustment for this process
     60     int setAdj;                 // Last set OOM adjustment for this process
     61     int curSchedGroup;          // Currently desired scheduling class
     62     int setSchedGroup;          // Last set to background scheduling class
     63     boolean keeping;            // Actively running code so don't kill due to that?
     64     boolean setIsForeground;    // Running foreground UI when last set?
     65     boolean foregroundServices; // Running any services that are foreground?
     66     boolean bad;                // True if disabled in the bad process list
     67     boolean killedBackground;   // True when proc has been killed due to too many bg
     68     IBinder forcingToForeground;// Token that is forcing this process to be foreground
     69     int adjSeq;                 // Sequence id for identifying oom_adj assignment cycles
     70     int lruSeq;                 // Sequence id for identifying LRU update cycles
     71     ComponentName instrumentationClass;// class installed to instrument app
     72     ApplicationInfo instrumentationInfo; // the application being instrumented
     73     String instrumentationProfileFile; // where to save profiling
     74     IInstrumentationWatcher instrumentationWatcher; // who is waiting
     75     Bundle instrumentationArguments;// as given to us
     76     ComponentName instrumentationResultClass;// copy of instrumentationClass
     77     BroadcastRecord curReceiver;// receiver currently running in the app
     78     long lastWakeTime;          // How long proc held wake lock at last check
     79     long lastCpuTime;           // How long proc has run CPU at last check
     80     long curCpuTime;            // How long proc has run CPU most recently
     81     long lastRequestedGc;       // When we last asked the app to do a gc
     82     long lastLowMemory;         // When we last told the app that memory is low
     83     boolean reportLowMemory;    // Set to true when waiting to report low mem
     84     boolean empty;              // Is this an empty background process?
     85     boolean hidden;             // Is this a hidden process?
     86     int lastPss;                // Last pss size reported by app.
     87     String adjType;             // Debugging: primary thing impacting oom_adj.
     88     int adjTypeCode;            // Debugging: adj code to report to app.
     89     Object adjSource;           // Debugging: option dependent object.
     90     Object adjTarget;           // Debugging: target component impacting oom_adj.
     91 
     92     // contains HistoryRecord objects
     93     final ArrayList<ActivityRecord> activities = new ArrayList<ActivityRecord>();
     94     // all ServiceRecord running in this process
     95     final HashSet<ServiceRecord> services = new HashSet<ServiceRecord>();
     96     // services that are currently executing code (need to remain foreground).
     97     final HashSet<ServiceRecord> executingServices
     98              = new HashSet<ServiceRecord>();
     99     // All ConnectionRecord this process holds
    100     final HashSet<ConnectionRecord> connections
    101             = new HashSet<ConnectionRecord>();
    102     // all IIntentReceivers that are registered from this process.
    103     final HashSet<ReceiverList> receivers = new HashSet<ReceiverList>();
    104     // class (String) -> ContentProviderRecord
    105     final HashMap<String, ContentProviderRecord> pubProviders
    106             = new HashMap<String, ContentProviderRecord>();
    107     // All ContentProviderRecord process is using
    108     final HashMap<ContentProviderRecord, Integer> conProviders
    109             = new HashMap<ContentProviderRecord, Integer>();
    110 
    111     boolean persistent;         // always keep this application running?
    112     boolean crashing;           // are we in the process of crashing?
    113     Dialog crashDialog;         // dialog being displayed due to crash.
    114     boolean notResponding;      // does the app have a not responding dialog?
    115     Dialog anrDialog;           // dialog being displayed due to app not resp.
    116     boolean removed;            // has app package been removed from device?
    117     boolean debugging;          // was app launched for debugging?
    118     boolean waitedForDebugger;  // has process show wait for debugger dialog?
    119     Dialog waitDialog;          // current wait for debugger dialog
    120 
    121     String shortStringName;     // caching of toShortString() result.
    122     String stringName;          // caching of toString() result.
    123 
    124     // These reports are generated & stored when an app gets into an error condition.
    125     // They will be "null" when all is OK.
    126     ActivityManager.ProcessErrorStateInfo crashingReport;
    127     ActivityManager.ProcessErrorStateInfo notRespondingReport;
    128 
    129     // Who will be notified of the error. This is usually an activity in the
    130     // app that installed the package.
    131     ComponentName errorReportReceiver;
    132 
    133     void dump(PrintWriter pw, String prefix) {
    134         final long now = SystemClock.uptimeMillis();
    135 
    136         if (info.className != null) {
    137             pw.print(prefix); pw.print("class="); pw.println(info.className);
    138         }
    139         if (info.manageSpaceActivityName != null) {
    140             pw.print(prefix); pw.print("manageSpaceActivityName=");
    141             pw.println(info.manageSpaceActivityName);
    142         }
    143         pw.print(prefix); pw.print("dir="); pw.print(info.sourceDir);
    144                 pw.print(" publicDir="); pw.print(info.publicSourceDir);
    145                 pw.print(" data="); pw.println(info.dataDir);
    146         pw.print(prefix); pw.print("packageList="); pw.println(pkgList);
    147         if (instrumentationClass != null || instrumentationProfileFile != null
    148                 || instrumentationArguments != null) {
    149             pw.print(prefix); pw.print("instrumentationClass=");
    150                     pw.print(instrumentationClass);
    151                     pw.print(" instrumentationProfileFile=");
    152                     pw.println(instrumentationProfileFile);
    153             pw.print(prefix); pw.print("instrumentationArguments=");
    154                     pw.println(instrumentationArguments);
    155             pw.print(prefix); pw.print("instrumentationInfo=");
    156                     pw.println(instrumentationInfo);
    157             if (instrumentationInfo != null) {
    158                 instrumentationInfo.dump(new PrintWriterPrinter(pw), prefix + "  ");
    159             }
    160         }
    161         pw.print(prefix); pw.print("thread="); pw.print(thread);
    162                 pw.print(" curReceiver="); pw.println(curReceiver);
    163         pw.print(prefix); pw.print("pid="); pw.print(pid); pw.print(" starting=");
    164                 pw.print(starting); pw.print(" lastPss="); pw.println(lastPss);
    165         pw.print(prefix); pw.print("lastActivityTime=");
    166                 TimeUtils.formatDuration(lastActivityTime, now, pw);
    167                 pw.print(" lruWeight="); pw.print(lruWeight);
    168                 pw.print(" keeping="); pw.print(keeping);
    169                 pw.print(" hidden="); pw.print(hidden);
    170                 pw.print(" empty="); pw.println(empty);
    171         pw.print(prefix); pw.print("oom: max="); pw.print(maxAdj);
    172                 pw.print(" hidden="); pw.print(hiddenAdj);
    173                 pw.print(" curRaw="); pw.print(curRawAdj);
    174                 pw.print(" setRaw="); pw.print(setRawAdj);
    175                 pw.print(" cur="); pw.print(curAdj);
    176                 pw.print(" set="); pw.println(setAdj);
    177         pw.print(prefix); pw.print("curSchedGroup="); pw.print(curSchedGroup);
    178                 pw.print(" setSchedGroup="); pw.println(setSchedGroup);
    179         pw.print(prefix); pw.print("setIsForeground="); pw.print(setIsForeground);
    180                 pw.print(" foregroundServices="); pw.print(foregroundServices);
    181                 pw.print(" forcingToForeground="); pw.println(forcingToForeground);
    182         pw.print(prefix); pw.print("persistent="); pw.print(persistent);
    183                 pw.print(" removed="); pw.println(removed);
    184         pw.print(prefix); pw.print("adjSeq="); pw.print(adjSeq);
    185                 pw.print(" lruSeq="); pw.println(lruSeq);
    186         if (!keeping) {
    187             long wtime;
    188             synchronized (batteryStats.getBatteryStats()) {
    189                 wtime = batteryStats.getBatteryStats().getProcessWakeTime(info.uid,
    190                         pid, SystemClock.elapsedRealtime());
    191             }
    192             long timeUsed = wtime - lastWakeTime;
    193             pw.print(prefix); pw.print("lastWakeTime="); pw.print(lastWakeTime);
    194                     pw.print(" time used=");
    195                     TimeUtils.formatDuration(timeUsed, pw); pw.println("");
    196             pw.print(prefix); pw.print("lastCpuTime="); pw.print(lastCpuTime);
    197                     pw.print(" time used=");
    198                     TimeUtils.formatDuration(curCpuTime-lastCpuTime, pw); pw.println("");
    199         }
    200         pw.print(prefix); pw.print("lastRequestedGc=");
    201                 TimeUtils.formatDuration(lastRequestedGc, now, pw);
    202                 pw.print(" lastLowMemory=");
    203                 TimeUtils.formatDuration(lastLowMemory, now, pw);
    204                 pw.print(" reportLowMemory="); pw.println(reportLowMemory);
    205         if (killedBackground) {
    206             pw.print(prefix); pw.print("killedBackground="); pw.println(killedBackground);
    207         }
    208         if (debugging || crashing || crashDialog != null || notResponding
    209                 || anrDialog != null || bad) {
    210             pw.print(prefix); pw.print("debugging="); pw.print(debugging);
    211                     pw.print(" crashing="); pw.print(crashing);
    212                     pw.print(" "); pw.print(crashDialog);
    213                     pw.print(" notResponding="); pw.print(notResponding);
    214                     pw.print(" " ); pw.print(anrDialog);
    215                     pw.print(" bad="); pw.print(bad);
    216 
    217                     // crashing or notResponding is always set before errorReportReceiver
    218                     if (errorReportReceiver != null) {
    219                         pw.print(" errorReportReceiver=");
    220                         pw.print(errorReportReceiver.flattenToShortString());
    221                     }
    222                     pw.println();
    223         }
    224         if (activities.size() > 0) {
    225             pw.print(prefix); pw.print("activities="); pw.println(activities);
    226         }
    227         if (services.size() > 0) {
    228             pw.print(prefix); pw.print("services="); pw.println(services);
    229         }
    230         if (executingServices.size() > 0) {
    231             pw.print(prefix); pw.print("executingServices="); pw.println(executingServices);
    232         }
    233         if (connections.size() > 0) {
    234             pw.print(prefix); pw.print("connections="); pw.println(connections);
    235         }
    236         if (pubProviders.size() > 0) {
    237             pw.print(prefix); pw.print("pubProviders="); pw.println(pubProviders);
    238         }
    239         if (conProviders.size() > 0) {
    240             pw.print(prefix); pw.print("conProviders="); pw.println(conProviders);
    241         }
    242         if (receivers.size() > 0) {
    243             pw.print(prefix); pw.print("receivers="); pw.println(receivers);
    244         }
    245     }
    246 
    247     ProcessRecord(BatteryStatsImpl.Uid.Proc _batteryStats, IApplicationThread _thread,
    248             ApplicationInfo _info, String _processName) {
    249         batteryStats = _batteryStats;
    250         info = _info;
    251         processName = _processName;
    252         pkgList.add(_info.packageName);
    253         thread = _thread;
    254         maxAdj = ActivityManagerService.EMPTY_APP_ADJ;
    255         hiddenAdj = ActivityManagerService.HIDDEN_APP_MIN_ADJ;
    256         curRawAdj = setRawAdj = -100;
    257         curAdj = setAdj = -100;
    258         persistent = false;
    259         removed = false;
    260     }
    261 
    262     public void setPid(int _pid) {
    263         pid = _pid;
    264         shortStringName = null;
    265         stringName = null;
    266     }
    267 
    268     /**
    269      * This method returns true if any of the activities within the process record are interesting
    270      * to the user. See HistoryRecord.isInterestingToUserLocked()
    271      */
    272     public boolean isInterestingToUserLocked() {
    273         final int size = activities.size();
    274         for (int i = 0 ; i < size ; i++) {
    275             ActivityRecord r = activities.get(i);
    276             if (r.isInterestingToUserLocked()) {
    277                 return true;
    278             }
    279         }
    280         return false;
    281     }
    282 
    283     public void stopFreezingAllLocked() {
    284         int i = activities.size();
    285         while (i > 0) {
    286             i--;
    287             activities.get(i).stopFreezingScreenLocked(true);
    288         }
    289     }
    290 
    291     public String toShortString() {
    292         if (shortStringName != null) {
    293             return shortStringName;
    294         }
    295         StringBuilder sb = new StringBuilder(128);
    296         toShortString(sb);
    297         return shortStringName = sb.toString();
    298     }
    299 
    300     void toShortString(StringBuilder sb) {
    301         sb.append(Integer.toHexString(System.identityHashCode(this)));
    302         sb.append(' ');
    303         sb.append(pid);
    304         sb.append(':');
    305         sb.append(processName);
    306         sb.append('/');
    307         sb.append(info.uid);
    308     }
    309 
    310     public String toString() {
    311         if (stringName != null) {
    312             return stringName;
    313         }
    314         StringBuilder sb = new StringBuilder(128);
    315         sb.append("ProcessRecord{");
    316         toShortString(sb);
    317         sb.append('}');
    318         return stringName = sb.toString();
    319     }
    320 
    321     /*
    322      *  Return true if package has been added false if not
    323      */
    324     public boolean addPackage(String pkg) {
    325         if (!pkgList.contains(pkg)) {
    326             pkgList.add(pkg);
    327             return true;
    328         }
    329         return false;
    330     }
    331 
    332     /*
    333      *  Delete all packages from list except the package indicated in info
    334      */
    335     public void resetPackageList() {
    336         pkgList.clear();
    337         pkgList.add(info.packageName);
    338     }
    339 
    340     public String[] getPackageList() {
    341         int size = pkgList.size();
    342         if (size == 0) {
    343             return null;
    344         }
    345         String list[] = new String[size];
    346         pkgList.toArray(list);
    347         return list;
    348     }
    349 }
    350