summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDianne Hackborn <hackbod@google.com>2013-06-13 19:06:50 -0700
committerDianne Hackborn <hackbod@google.com>2013-06-14 17:30:17 -0700
commit91268cf21eace600792d04db1ac62e9268f48002 (patch)
tree6369a1478c9ac69be921818b830e6963603d7376
parent756a53f4e4dc8671287d7a192c619e0e1c627ebd (diff)
downloadframeworks_base-91268cf21eace600792d04db1ac62e9268f48002.zip
frameworks_base-91268cf21eace600792d04db1ac62e9268f48002.tar.gz
frameworks_base-91268cf21eace600792d04db1ac62e9268f48002.tar.bz2
More work on process tracking.
Re-arranged code to be more flexible, now track state of services, dump ordered list of running processes while memory was critical and low. Also rename battery stats service from "batteryinfo" to "batterystats". Change-Id: I0f4f0c8d443c49d255cb84d0fc917e8ec18b152e
-rw-r--r--core/java/android/app/ActivityManager.java3
-rw-r--r--core/java/android/os/BatteryStats.java5
-rw-r--r--services/java/com/android/server/NetworkManagementService.java3
-rw-r--r--services/java/com/android/server/VibratorService.java4
-rw-r--r--services/java/com/android/server/am/ActiveServices.java161
-rw-r--r--services/java/com/android/server/am/ActivityManagerService.java11
-rw-r--r--services/java/com/android/server/am/BatteryStatsService.java7
-rw-r--r--services/java/com/android/server/am/ProcessTracker.java390
-rw-r--r--services/java/com/android/server/am/ServiceRecord.java19
-rw-r--r--services/java/com/android/server/location/GpsLocationProvider.java4
-rw-r--r--wifi/java/android/net/wifi/WifiStateMachine.java4
11 files changed, 471 insertions, 140 deletions
diff --git a/core/java/android/app/ActivityManager.java b/core/java/android/app/ActivityManager.java
index f523b55..62ed697 100644
--- a/core/java/android/app/ActivityManager.java
+++ b/core/java/android/app/ActivityManager.java
@@ -16,6 +16,7 @@
package android.app;
+import android.os.BatteryStats;
import android.os.IBinder;
import com.android.internal.app.IUsageStats;
import com.android.internal.os.PkgUsageStats;
@@ -2210,7 +2211,7 @@ public class ActivityManager {
pw.println();
dumpService(pw, fd, "package", new String[] { packageName});
pw.println();
- dumpService(pw, fd, "batteryinfo", new String[] { packageName});
+ dumpService(pw, fd, BatteryStats.SERVICE_NAME, new String[] { packageName});
pw.flush();
}
diff --git a/core/java/android/os/BatteryStats.java b/core/java/android/os/BatteryStats.java
index fef1818..7c09e89 100644
--- a/core/java/android/os/BatteryStats.java
+++ b/core/java/android/os/BatteryStats.java
@@ -41,7 +41,10 @@ import android.util.TimeUtils;
public abstract class BatteryStats implements Parcelable {
private static final boolean LOCAL_LOGV = false;
-
+
+ /** @hide */
+ public static final String SERVICE_NAME = "batterystats";
+
/**
* A constant indicating a partial wake lock timer.
*/
diff --git a/services/java/com/android/server/NetworkManagementService.java b/services/java/com/android/server/NetworkManagementService.java
index ce952d1..6f740cd 100644
--- a/services/java/com/android/server/NetworkManagementService.java
+++ b/services/java/com/android/server/NetworkManagementService.java
@@ -43,6 +43,7 @@ import android.net.NetworkUtils;
import android.net.RouteInfo;
import android.net.wifi.WifiConfiguration;
import android.net.wifi.WifiConfiguration.KeyMgmt;
+import android.os.BatteryStats;
import android.os.Binder;
import android.os.Handler;
import android.os.INetworkManagementService;
@@ -347,7 +348,7 @@ public class NetworkManagementService extends INetworkManagementService.Stub
if (mBandwidthControlEnabled) {
try {
- IBatteryStats.Stub.asInterface(ServiceManager.getService("batteryinfo"))
+ IBatteryStats.Stub.asInterface(ServiceManager.getService(BatteryStats.SERVICE_NAME))
.noteNetworkStatsEnabled();
} catch (RemoteException e) {
}
diff --git a/services/java/com/android/server/VibratorService.java b/services/java/com/android/server/VibratorService.java
index 21d3111..9b5f8f6 100644
--- a/services/java/com/android/server/VibratorService.java
+++ b/services/java/com/android/server/VibratorService.java
@@ -24,6 +24,7 @@ import android.content.IntentFilter;
import android.content.pm.PackageManager;
import android.database.ContentObserver;
import android.hardware.input.InputManager;
+import android.os.BatteryStats;
import android.os.Handler;
import android.os.IVibratorService;
import android.os.PowerManager;
@@ -143,7 +144,8 @@ public class VibratorService extends IVibratorService.Stub
mWakeLock.setReferenceCounted(true);
mAppOpsService = IAppOpsService.Stub.asInterface(ServiceManager.getService(Context.APP_OPS_SERVICE));
- mBatteryStatsService = IBatteryStats.Stub.asInterface(ServiceManager.getService("batteryinfo"));
+ mBatteryStatsService = IBatteryStats.Stub.asInterface(ServiceManager.getService(
+ BatteryStats.SERVICE_NAME));
mVibrations = new LinkedList<Vibration>();
diff --git a/services/java/com/android/server/am/ActiveServices.java b/services/java/com/android/server/am/ActiveServices.java
index 912c465..c558fbd 100644
--- a/services/java/com/android/server/am/ActiveServices.java
+++ b/services/java/com/android/server/am/ActiveServices.java
@@ -241,11 +241,14 @@ public final class ActiveServices {
if (unscheduleServiceRestartLocked(r)) {
if (DEBUG_SERVICE) Slog.v(TAG, "START SERVICE WHILE RESTART PENDING: " + r);
}
+ r.lastActivity = SystemClock.uptimeMillis();
r.startRequested = true;
+ if (r.tracker != null) {
+ r.tracker.setStarted(true, mAm.mProcessTracker.getMemFactor(), r.lastActivity);
+ }
r.callStart = false;
r.pendingStarts.add(new ServiceRecord.StartItem(r, false, r.makeNextStartId(),
service, neededGrants));
- r.lastActivity = SystemClock.uptimeMillis();
synchronized (r.stats.getBatteryStats()) {
r.stats.startRunningLocked();
}
@@ -261,8 +264,12 @@ public final class ActiveServices {
service.stats.stopRunningLocked();
}
service.startRequested = false;
+ if (service.tracker != null) {
+ service.tracker.setStarted(false, mAm.mProcessTracker.getMemFactor(),
+ SystemClock.uptimeMillis());
+ }
service.callStart = false;
- bringDownServiceLocked(service, false);
+ bringDownServiceIfNeededLocked(service, false, false);
}
int stopServiceLocked(IApplicationThread caller, Intent service,
@@ -355,11 +362,15 @@ public final class ActiveServices {
synchronized (r.stats.getBatteryStats()) {
r.stats.stopRunningLocked();
- r.startRequested = false;
- r.callStart = false;
}
+ r.startRequested = false;
+ if (r.tracker != null) {
+ r.tracker.setStarted(false, mAm.mProcessTracker.getMemFactor(),
+ SystemClock.uptimeMillis());
+ }
+ r.callStart = false;
final long origId = Binder.clearCallingIdentity();
- bringDownServiceLocked(r, false);
+ bringDownServiceIfNeededLocked(r, false, false);
Binder.restoreCallingIdentity(origId);
return true;
}
@@ -489,6 +500,17 @@ public final class ActiveServices {
+ s);
}
+ if ((flags&Context.BIND_AUTO_CREATE) != 0) {
+ s.lastActivity = SystemClock.uptimeMillis();
+ if (!s.hasAutoCreateConnections()) {
+ // This is the first binding, let the tracker know.
+ if (s.tracker != null) {
+ s.tracker.setBound(true, mAm.mProcessTracker.getMemFactor(),
+ s.lastActivity);
+ }
+ }
+ }
+
AppBindRecord b = s.retrieveAppBindingLocked(service, callerApp);
ConnectionRecord c = new ConnectionRecord(b, activity,
connection, flags, clientLabel, clientIntent);
@@ -748,7 +770,12 @@ public final class ActiveServices {
sInfo.applicationInfo.uid, sInfo.packageName,
sInfo.name);
}
- r = new ServiceRecord(mAm, ss, name, filter, sInfo, res);
+ ProcessTracker.ServiceState tracker = null;
+ if ((sInfo.applicationInfo.flags&ApplicationInfo.FLAG_PERSISTENT) == 0) {
+ tracker = mAm.mProcessTracker.getServiceStateLocked(sInfo.packageName,
+ sInfo.applicationInfo.uid, sInfo.name);
+ }
+ r = new ServiceRecord(mAm, ss, name, filter, sInfo, res, tracker);
res.setService(r);
mServiceMap.putServiceByName(name, UserHandle.getUserId(r.appInfo.uid), r);
mServiceMap.putServiceByIntent(filter, UserHandle.getUserId(r.appInfo.uid), r);
@@ -798,14 +825,19 @@ public final class ActiveServices {
else if (DEBUG_SERVICE_EXECUTING) Log.v(TAG, ">>> EXECUTING "
+ why + " of " + r.shortName);
long now = SystemClock.uptimeMillis();
- if (r.executeNesting == 0 && r.app != null) {
- if (r.app.executingServices.size() == 0) {
- Message msg = mAm.mHandler.obtainMessage(
- ActivityManagerService.SERVICE_TIMEOUT_MSG);
- msg.obj = r.app;
- mAm.mHandler.sendMessageAtTime(msg, now+SERVICE_TIMEOUT);
+ if (r.executeNesting == 0) {
+ if (r.tracker != null) {
+ r.tracker.setExecuting(true, mAm.mProcessTracker.getMemFactor(), now);
+ }
+ if (r.app != null) {
+ if (r.app.executingServices.size() == 0) {
+ Message msg = mAm.mHandler.obtainMessage(
+ ActivityManagerService.SERVICE_TIMEOUT_MSG);
+ msg.obj = r.app;
+ mAm.mHandler.sendMessageAtTime(msg, now+SERVICE_TIMEOUT);
+ }
+ r.app.executingServices.add(r);
}
- r.app.executingServices.add(r);
}
r.executeNesting++;
r.executingStart = now;
@@ -991,7 +1023,7 @@ public final class ActiveServices {
+ r.appInfo.uid + " for service "
+ r.intent.getIntent() + ": user " + r.userId + " is stopped";
Slog.w(TAG, msg);
- bringDownServiceLocked(r, true);
+ bringDownServiceLocked(r);
return msg;
}
@@ -1045,7 +1077,7 @@ public final class ActiveServices {
+ r.appInfo.uid + " for service "
+ r.intent.getIntent() + ": process is bad";
Slog.w(TAG, msg);
- bringDownServiceLocked(r, true);
+ bringDownServiceLocked(r);
return msg;
}
if (isolated) {
@@ -1167,26 +1199,29 @@ public final class ActiveServices {
}
}
- private final void bringDownServiceLocked(ServiceRecord r, boolean force) {
+ private final void bringDownServiceIfNeededLocked(ServiceRecord r, boolean knowConn,
+ boolean hasConn) {
//Slog.i(TAG, "Bring down service:");
//r.dump(" ");
// Does it still need to run?
- if (!force && r.startRequested) {
+ if (r.startRequested) {
return;
}
- if (!force) {
- // XXX should probably keep a count of the number of auto-create
- // connections directly in the service.
- for (int conni=r.connections.size()-1; conni>=0; conni--) {
- ArrayList<ConnectionRecord> cr = r.connections.valueAt(conni);
- for (int i=0; i<cr.size(); i++) {
- if ((cr.get(i).flags&Context.BIND_AUTO_CREATE) != 0) {
- return;
- }
- }
- }
+
+ if (!knowConn) {
+ hasConn = r.hasAutoCreateConnections();
}
+ if (hasConn) {
+ return;
+ }
+
+ bringDownServiceLocked(r);
+ }
+
+ private final void bringDownServiceLocked(ServiceRecord r) {
+ //Slog.i(TAG, "Bring down service:");
+ //r.dump(" ");
// Report to all of the connections that the service is no longer
// available.
@@ -1291,6 +1326,13 @@ public final class ActiveServices {
if (r.restarter instanceof ServiceRestarter) {
((ServiceRestarter)r.restarter).setService(null);
}
+
+ int memFactor = mAm.mProcessTracker.getMemFactor();
+ long now = SystemClock.uptimeMillis();
+ if (r.tracker != null) {
+ r.tracker.setStarted(false, memFactor, now);
+ r.tracker.setBound(false, memFactor, now);
+ }
}
void removeConnectionLocked(
@@ -1349,7 +1391,14 @@ public final class ActiveServices {
}
if ((c.flags&Context.BIND_AUTO_CREATE) != 0) {
- bringDownServiceLocked(s, false);
+ boolean hasAutoCreate = s.hasAutoCreateConnections();
+ if (!hasAutoCreate) {
+ if (s.tracker != null) {
+ s.tracker.setBound(false, mAm.mProcessTracker.getMemFactor(),
+ SystemClock.uptimeMillis());
+ }
+ }
+ bringDownServiceIfNeededLocked(s, true, hasAutoCreate);
}
}
}
@@ -1422,22 +1471,28 @@ public final class ActiveServices {
+ ", inStopping=" + inStopping + ", app=" + r.app);
else if (DEBUG_SERVICE_EXECUTING) Slog.v(TAG, "<<< DONE EXECUTING " + r.shortName);
r.executeNesting--;
- if (r.executeNesting <= 0 && r.app != null) {
- if (DEBUG_SERVICE) Slog.v(TAG,
- "Nesting at 0 of " + r.shortName);
- r.app.executingServices.remove(r);
- if (r.app.executingServices.size() == 0) {
- if (DEBUG_SERVICE || DEBUG_SERVICE_EXECUTING) Slog.v(TAG,
- "No more executingServices of " + r.shortName);
- mAm.mHandler.removeMessages(ActivityManagerService.SERVICE_TIMEOUT_MSG, r.app);
- }
- if (inStopping) {
+ if (r.executeNesting <= 0) {
+ if (r.app != null) {
if (DEBUG_SERVICE) Slog.v(TAG,
- "doneExecuting remove stopping " + r);
- mStoppingServices.remove(r);
- r.bindings.clear();
+ "Nesting at 0 of " + r.shortName);
+ r.app.executingServices.remove(r);
+ if (r.app.executingServices.size() == 0) {
+ if (DEBUG_SERVICE || DEBUG_SERVICE_EXECUTING) Slog.v(TAG,
+ "No more executingServices of " + r.shortName);
+ mAm.mHandler.removeMessages(ActivityManagerService.SERVICE_TIMEOUT_MSG, r.app);
+ }
+ if (inStopping) {
+ if (DEBUG_SERVICE) Slog.v(TAG,
+ "doneExecuting remove stopping " + r);
+ mStoppingServices.remove(r);
+ r.bindings.clear();
+ }
+ mAm.updateOomAdjLocked(r.app);
+ }
+ if (r.tracker != null) {
+ r.tracker.setExecuting(false, mAm.mProcessTracker.getMemFactor(),
+ SystemClock.uptimeMillis());
}
- mAm.updateOomAdjLocked(r.app);
}
}
@@ -1494,7 +1549,7 @@ public final class ActiveServices {
sr.isolatedProc = null;
mPendingServices.remove(i);
i--;
- bringDownServiceLocked(sr, true);
+ bringDownServiceLocked(sr);
}
}
}
@@ -1545,7 +1600,7 @@ public final class ActiveServices {
int N = services.size();
for (int i=0; i<N; i++) {
- bringDownServiceLocked(services.get(i), true);
+ bringDownServiceLocked(services.get(i));
}
return didSomething;
}
@@ -1628,6 +1683,10 @@ public final class ActiveServices {
sr.app = null;
sr.isolatedProc = null;
sr.executeNesting = 0;
+ if (sr.tracker != null) {
+ sr.tracker.setExecuting(false, mAm.mProcessTracker.getMemFactor(),
+ SystemClock.uptimeMillis());
+ }
if (mStoppingServices.remove(sr)) {
if (DEBUG_SERVICE) Slog.v(TAG, "killServices remove stopping " + sr);
}
@@ -1647,9 +1706,9 @@ public final class ActiveServices {
+ " times, stopping: " + sr);
EventLog.writeEvent(EventLogTags.AM_SERVICE_CRASHED_TOO_MUCH,
sr.userId, sr.crashCount, sr.shortName, app.pid);
- bringDownServiceLocked(sr, true);
+ bringDownServiceLocked(sr);
} else if (!allowRestart) {
- bringDownServiceLocked(sr, true);
+ bringDownServiceLocked(sr);
} else {
boolean canceled = scheduleServiceRestartLocked(sr, true);
@@ -1659,9 +1718,13 @@ public final class ActiveServices {
if (sr.startRequested && (sr.stopIfKilled || canceled)) {
if (sr.pendingStarts.size() == 0) {
sr.startRequested = false;
- if (numClients > 0) {
+ if (sr.tracker != null) {
+ sr.tracker.setStarted(false, mAm.mProcessTracker.getMemFactor(),
+ SystemClock.uptimeMillis());
+ }
+ if (!sr.hasAutoCreateConnections()) {
// Whoops, no reason to restart!
- bringDownServiceLocked(sr, true);
+ bringDownServiceLocked(sr);
}
}
}
diff --git a/services/java/com/android/server/am/ActivityManagerService.java b/services/java/com/android/server/am/ActivityManagerService.java
index 2124095..21c752b 100644
--- a/services/java/com/android/server/am/ActivityManagerService.java
+++ b/services/java/com/android/server/am/ActivityManagerService.java
@@ -7292,7 +7292,6 @@ public final class ActivityManagerService extends ActivityManagerNative
if (isolated) {
int userId = UserHandle.getUserId(uid);
int stepsLeft = Process.LAST_ISOLATED_UID - Process.FIRST_ISOLATED_UID + 1;
- uid = 0;
while (true) {
if (mNextIsolatedProcessUid < Process.FIRST_ISOLATED_UID
|| mNextIsolatedProcessUid > Process.LAST_ISOLATED_UID) {
@@ -7314,7 +7313,7 @@ public final class ActivityManagerService extends ActivityManagerNative
ps = stats.getProcessStatsLocked(info.uid, proc);
}
return new ProcessRecord(ps, thread, info, proc, uid,
- mProcessTracker.getProcessStateLocked(info.packageName, uid, proc));
+ mProcessTracker.getProcessStateLocked(info.packageName, info.uid, proc));
}
final ProcessRecord addAppLocked(ApplicationInfo info, boolean isolated) {
@@ -14193,7 +14192,7 @@ public final class ActivityManagerService extends ActivityManagerNative
// are managing to keep around is less than half the maximum we desire;
// if we are keeping a good number around, we'll let them use whatever
// memory they want.
- int memFactor = ProcessTracker.STATE_MEM_FACTOR_NORMAL_ADJ;
+ int memFactor = ProcessTracker.ADJ_MEM_FACTOR_NORMAL;
if (numCached <= ProcessList.TRIM_CACHED_APPS
&& numEmpty <= ProcessList.TRIM_EMPTY_APPS) {
final int numCachedAndEmpty = numCached + numEmpty;
@@ -14207,13 +14206,13 @@ public final class ActivityManagerService extends ActivityManagerNative
int fgTrimLevel;
if (numCachedAndEmpty <= ProcessList.TRIM_CRITICAL_THRESHOLD) {
fgTrimLevel = ComponentCallbacks2.TRIM_MEMORY_RUNNING_CRITICAL;
- memFactor = ProcessTracker.STATE_MEM_FACTOR_CRITIAL_ADJ;
+ memFactor = ProcessTracker.ADJ_MEM_FACTOR_CRITICAL;
} else if (numCachedAndEmpty <= ProcessList.TRIM_LOW_THRESHOLD) {
fgTrimLevel = ComponentCallbacks2.TRIM_MEMORY_RUNNING_LOW;
- memFactor = ProcessTracker.STATE_MEM_FACTOR_LOW_ADJ;
+ memFactor = ProcessTracker.ADJ_MEM_FACTOR_LOW;
} else {
fgTrimLevel = ComponentCallbacks2.TRIM_MEMORY_RUNNING_MODERATE;
- memFactor = ProcessTracker.STATE_MEM_FACTOR_MODERATE_ADJ;
+ memFactor = ProcessTracker.ADJ_MEM_FACTOR_MODERATE;
}
int curLevel = ComponentCallbacks2.TRIM_MEMORY_COMPLETE;
for (i=0; i<N; i++) {
diff --git a/services/java/com/android/server/am/BatteryStatsService.java b/services/java/com/android/server/am/BatteryStatsService.java
index f143feb..12cad7b 100644
--- a/services/java/com/android/server/am/BatteryStatsService.java
+++ b/services/java/com/android/server/am/BatteryStatsService.java
@@ -22,6 +22,7 @@ import android.bluetooth.BluetoothProfile;
import android.content.Context;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageManager;
+import android.os.BatteryStats;
import android.os.Binder;
import android.os.IBinder;
import android.os.Parcel;
@@ -59,7 +60,7 @@ public final class BatteryStatsService extends IBatteryStats.Stub {
public void publish(Context context) {
mContext = context;
- ServiceManager.addService("batteryinfo", asBinder());
+ ServiceManager.addService(BatteryStats.SERVICE_NAME, asBinder());
mStats.setNumSpeedSteps(new PowerProfile(mContext).getNumSpeedSteps());
mStats.setRadioScanningTimeout(mContext.getResources().getInteger(
com.android.internal.R.integer.config_radioScanningTimeout)
@@ -77,7 +78,7 @@ public final class BatteryStatsService extends IBatteryStats.Stub {
if (sService != null) {
return sService;
}
- IBinder b = ServiceManager.getService("batteryinfo");
+ IBinder b = ServiceManager.getService(BatteryStats.SERVICE_NAME);
sService = asInterface(b);
return sService;
}
@@ -479,7 +480,7 @@ public final class BatteryStatsService extends IBatteryStats.Stub {
}
private void dumpHelp(PrintWriter pw) {
- pw.println("Battery stats (batteryinfo) dump options:");
+ pw.println("Battery stats (batterystats) dump options:");
pw.println(" [--checkin] [--unplugged] [--reset] [--write] [-h] [<package.name>]");
pw.println(" --checkin: format output for a checkin report.");
pw.println(" --unplugged: only output data since last unplugged.");
diff --git a/services/java/com/android/server/am/ProcessTracker.java b/services/java/com/android/server/am/ProcessTracker.java
index fb8d09c..ec8a0b2 100644
--- a/services/java/com/android/server/am/ProcessTracker.java
+++ b/services/java/com/android/server/am/ProcessTracker.java
@@ -17,6 +17,7 @@
package com.android.server.am;
import android.os.SystemClock;
+import android.os.UserHandle;
import android.util.ArrayMap;
import android.util.SparseArray;
import android.util.TimeUtils;
@@ -24,6 +25,9 @@ import com.android.server.ProcessMap;
import java.io.FileDescriptor;
import java.io.PrintWriter;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Comparator;
public final class ProcessTracker {
public static final int STATE_NOTHING = -1;
@@ -36,16 +40,18 @@ public final class ProcessTracker {
public static final int STATE_HOME = 6;
public static final int STATE_PREVIOUS = 7;
public static final int STATE_CACHED = 8;
- public static final int STATE_MEM_FACTOR_MOD = STATE_CACHED+1;
- public static final int STATE_MEM_FACTOR_NORMAL_ADJ = 0;
- public static final int STATE_MEM_FACTOR_MODERATE_ADJ = STATE_MEM_FACTOR_MOD;
- public static final int STATE_MEM_FACTOR_LOW_ADJ = STATE_MEM_FACTOR_MOD*2;
- public static final int STATE_MEM_FACTOR_CRITIAL_ADJ = STATE_MEM_FACTOR_MOD*3;
- public static final int STATE_MEM_FACTOR_COUNT = STATE_MEM_FACTOR_MOD*4;
- public static final int STATE_SCREEN_ON_MOD = STATE_MEM_FACTOR_COUNT;
- public static final int STATE_SCREEN_OFF_ADJ = 0;
- public static final int STATE_SCREEN_ON_ADJ = STATE_SCREEN_ON_MOD;
- public static final int STATE_COUNT = STATE_SCREEN_ON_MOD*2;
+ public static final int STATE_COUNT = STATE_CACHED+1;
+
+ public static final int ADJ_NOTHING = -1;
+ public static final int ADJ_MEM_FACTOR_NORMAL = 0;
+ public static final int ADJ_MEM_FACTOR_MODERATE = 1;
+ public static final int ADJ_MEM_FACTOR_LOW = 2;
+ public static final int ADJ_MEM_FACTOR_CRITICAL = 3;
+ public static final int ADJ_MEM_FACTOR_COUNT = ADJ_MEM_FACTOR_CRITICAL+1;
+ public static final int ADJ_SCREEN_MOD = ADJ_MEM_FACTOR_COUNT;
+ public static final int ADJ_SCREEN_OFF = 0;
+ public static final int ADJ_SCREEN_ON = ADJ_SCREEN_MOD;
+ public static final int ADJ_COUNT = ADJ_SCREEN_ON*2;
static String[] STATE_NAMES = new String[] {
"Top ", "Foreground ", "Visible ", "Perceptible", "Backup ",
@@ -53,13 +59,25 @@ public final class ProcessTracker {
};
public static final class ProcessState {
- final long[] mDurations = new long[STATE_COUNT];
+ final String mPackage;
+ final int mUid;
+ final String mName;
+
+ final long[] mDurations = new long[STATE_COUNT*ADJ_COUNT];
int mCurState = STATE_NOTHING;
long mStartTime;
+ long mTmpTotalTime;
+
+ public ProcessState(String pkg, int uid, String name) {
+ mPackage = pkg;
+ mUid = uid;
+ mName = name;
+ }
+
public void setState(int state, int memFactor, long now) {
if (state != STATE_NOTHING) {
- state += memFactor;
+ state += memFactor*STATE_COUNT;
}
if (mCurState != state) {
if (mCurState != STATE_NOTHING) {
@@ -72,8 +90,59 @@ public final class ProcessTracker {
}
public static final class ServiceState {
- long mStartedDuration;
- long mStartedTime;
+ final long[] mStartedDurations = new long[ADJ_COUNT];
+ int mStartedCount;
+ int mStartedState = STATE_NOTHING;
+ long mStartedStartTime;
+
+ final long[] mBoundDurations = new long[ADJ_COUNT];
+ int mBoundCount;
+ int mBoundState = STATE_NOTHING;
+ long mBoundStartTime;
+
+ final long[] mExecDurations = new long[ADJ_COUNT];
+ int mExecCount;
+ int mExecState = STATE_NOTHING;
+ long mExecStartTime;
+
+ public void setStarted(boolean started, int memFactor, long now) {
+ int state = started ? memFactor : STATE_NOTHING;
+ if (mStartedState != state) {
+ if (mStartedState != STATE_NOTHING) {
+ mStartedDurations[mStartedState] += now - mStartedStartTime;
+ } else if (started) {
+ mStartedCount++;
+ }
+ mStartedState = state;
+ mStartedStartTime = now;
+ }
+ }
+
+ public void setBound(boolean bound, int memFactor, long now) {
+ int state = bound ? memFactor : STATE_NOTHING;
+ if (mBoundState != state) {
+ if (mBoundState != STATE_NOTHING) {
+ mBoundDurations[mBoundState] += now - mBoundStartTime;
+ } else if (bound) {
+ mBoundCount++;
+ }
+ mBoundState = state;
+ mBoundStartTime = now;
+ }
+ }
+
+ public void setExecuting(boolean executing, int memFactor, long now) {
+ int state = executing ? memFactor : STATE_NOTHING;
+ if (mExecState != state) {
+ if (mExecState != STATE_NOTHING) {
+ mExecDurations[mExecState] += now - mExecStartTime;
+ } else if (executing) {
+ mExecCount++;
+ }
+ mExecState = state;
+ mExecStartTime = now;
+ }
+ }
}
public static final class PackageState {
@@ -88,7 +157,7 @@ public final class ProcessTracker {
static final class State {
final ProcessMap<PackageState> mPackages = new ProcessMap<PackageState>();
- final long[] mMemFactorDurations = new long[STATE_COUNT/STATE_MEM_FACTOR_MOD];
+ final long[] mMemFactorDurations = new long[ADJ_COUNT];
int mMemFactor = STATE_NOTHING;
long mStartTime;
}
@@ -114,7 +183,7 @@ public final class ProcessTracker {
if (ps != null) {
return ps;
}
- ps = new ProcessState();
+ ps = new ProcessState(packageName, uid, processName);
as.mProcesses.put(processName, ps);
return ps;
}
@@ -132,15 +201,31 @@ public final class ProcessTracker {
public boolean setMemFactor(int memFactor, boolean screenOn, long now) {
if (screenOn) {
- memFactor += STATE_SCREEN_ON_MOD;
+ memFactor += ADJ_SCREEN_ON;
}
if (memFactor != mState.mMemFactor) {
if (mState.mMemFactor != STATE_NOTHING) {
- mState.mMemFactorDurations[mState.mMemFactor/STATE_MEM_FACTOR_MOD]
- += now - mState.mStartTime;
+ mState.mMemFactorDurations[mState.mMemFactor] += now - mState.mStartTime;
}
mState.mMemFactor = memFactor;
mState.mStartTime = now;
+ ArrayMap<String, SparseArray<PackageState>> pmap = mState.mPackages.getMap();
+ for (int i=0; i<pmap.size(); i++) {
+ SparseArray<PackageState> uids = pmap.valueAt(i);
+ for (int j=0; j<uids.size(); j++) {
+ PackageState pkg = uids.valueAt(j);
+ ArrayMap<String, ServiceState> services = pkg.mServices;
+ for (int k=0; k<services.size(); k++) {
+ ServiceState service = services.valueAt(k);
+ if (service.mStartedState != STATE_NOTHING) {
+ service.setStarted(true, memFactor, now);
+ }
+ if (service.mBoundState != STATE_NOTHING) {
+ service.setBound(true, memFactor, now);
+ }
+ }
+ }
+ }
return true;
}
return false;
@@ -150,15 +235,15 @@ public final class ProcessTracker {
return mState.mMemFactor != STATE_NOTHING ? mState.mMemFactor : 0;
}
- private void printScreenLabel(PrintWriter pw, int offset) {
+ static private void printScreenLabel(PrintWriter pw, int offset) {
switch (offset) {
- case STATE_NOTHING:
+ case ADJ_NOTHING:
pw.print(" ");
break;
- case STATE_SCREEN_OFF_ADJ:
+ case ADJ_SCREEN_OFF:
pw.print("Screen Off / ");
break;
- case STATE_SCREEN_ON_ADJ:
+ case ADJ_SCREEN_ON:
pw.print("Screen On / ");
break;
default:
@@ -167,21 +252,21 @@ public final class ProcessTracker {
}
}
- private void printMemLabel(PrintWriter pw, int offset) {
+ static private void printMemLabel(PrintWriter pw, int offset) {
switch (offset) {
- case STATE_NOTHING:
+ case ADJ_NOTHING:
pw.print(" ");
break;
- case STATE_MEM_FACTOR_NORMAL_ADJ:
+ case ADJ_MEM_FACTOR_NORMAL:
pw.print("Norm / ");
break;
- case STATE_MEM_FACTOR_MODERATE_ADJ:
+ case ADJ_MEM_FACTOR_MODERATE:
pw.print("Mod / ");
break;
- case STATE_MEM_FACTOR_LOW_ADJ:
+ case ADJ_MEM_FACTOR_LOW:
pw.print("Low / ");
break;
- case STATE_MEM_FACTOR_CRITIAL_ADJ:
+ case ADJ_MEM_FACTOR_CRITICAL:
pw.print("Crit / ");
break;
default:
@@ -190,29 +275,191 @@ public final class ProcessTracker {
}
}
+ static void dumpSingleTime(PrintWriter pw, String prefix, long[] durations,
+ int curState, long curStartTime, long now) {
+ long totalTime = 0;
+ int printedScreen = -1;
+ for (int iscreen=0; iscreen<ADJ_COUNT; iscreen+=ADJ_SCREEN_MOD) {
+ int printedMem = -1;
+ for (int imem=0; imem<ADJ_MEM_FACTOR_COUNT; imem++) {
+ int state = imem+iscreen;
+ long time = durations[state];
+ String running = "";
+ if (curState == state) {
+ time += now - curStartTime;
+ running = " (running)";
+ }
+ if (time != 0) {
+ pw.print(prefix);
+ printScreenLabel(pw, printedScreen != iscreen
+ ? iscreen : STATE_NOTHING);
+ printedScreen = iscreen;
+ printMemLabel(pw, printedMem != imem ? imem : STATE_NOTHING);
+ printedMem = imem;
+ TimeUtils.formatDuration(time, pw); pw.println(running);
+ totalTime += time;
+ }
+ }
+ }
+ if (totalTime != 0) {
+ pw.print(prefix);
+ printScreenLabel(pw, STATE_NOTHING);
+ pw.print("TOTAL: ");
+ TimeUtils.formatDuration(totalTime, pw);
+ pw.println();
+ }
+ }
+
+ long computeProcessTimeLocked(ProcessState proc, int[] screenStates, int[] memStates,
+ int[] procStates, long now) {
+ long totalTime = 0;
+ for (int is=0; is<screenStates.length; is++) {
+ for (int im=0; im<memStates.length; im++) {
+ for (int ip=0; ip<procStates.length; ip++) {
+ int bucket = ((screenStates[is]+ memStates[im]) * STATE_COUNT)
+ + procStates[ip];
+ totalTime += proc.mDurations[bucket];
+ if (proc.mCurState == bucket) {
+ totalTime += now - proc.mStartTime;
+ }
+ }
+ }
+ }
+ proc.mTmpTotalTime = totalTime;
+ return totalTime;
+ }
+
+ ArrayList<ProcessState> collectProcessesLocked(int[] screenStates, int[] memStates,
+ int[] procStates, long now) {
+ ArrayList<ProcessState> outProcs = new ArrayList<ProcessState>();
+ ArrayMap<String, SparseArray<PackageState>> pmap = mState.mPackages.getMap();
+ for (int ip=0; ip<pmap.size(); ip++) {
+ SparseArray<PackageState> procs = pmap.valueAt(ip);
+ for (int iu=0; iu<procs.size(); iu++) {
+ PackageState state = procs.valueAt(iu);
+ for (int iproc=0; iproc<state.mProcesses.size(); iproc++) {
+ if (computeProcessTimeLocked(state.mProcesses.valueAt(iproc),
+ screenStates, memStates, procStates, now) > 0) {
+ outProcs.add(state.mProcesses.valueAt(iproc));
+ }
+ }
+ }
+ }
+ Collections.sort(outProcs, new Comparator<ProcessState>() {
+ @Override
+ public int compare(ProcessState lhs, ProcessState rhs) {
+ if (lhs.mTmpTotalTime < rhs.mTmpTotalTime) {
+ return -1;
+ } else if (lhs.mTmpTotalTime > rhs.mTmpTotalTime) {
+ return 1;
+ }
+ return 0;
+ }
+ });
+ return outProcs;
+ }
+
+ void dumpProcessState(PrintWriter pw, String prefix, ProcessState proc, int[] screenStates,
+ int[] memStates, int[] procStates, long now) {
+ long totalTime = 0;
+ int printedScreen = -1;
+ for (int is=0; is<screenStates.length; is++) {
+ int printedMem = -1;
+ for (int im=0; im<memStates.length; im++) {
+ for (int ip=0; ip<procStates.length; ip++) {
+ final int iscreen = screenStates[is];
+ final int imem = memStates[im];
+ final int bucket = ((iscreen + imem) * STATE_COUNT) + procStates[ip];
+ long time = proc.mDurations[bucket];
+ String running = "";
+ if (proc.mCurState == bucket) {
+ time += now - proc.mStartTime;
+ running = " (running)";
+ }
+ totalTime += time;
+ if (time != 0) {
+ pw.print(prefix);
+ if (screenStates.length > 1) {
+ printScreenLabel(pw, printedScreen != iscreen
+ ? iscreen : STATE_NOTHING);
+ printedScreen = iscreen;
+ }
+ if (memStates.length > 1) {
+ printMemLabel(pw, printedMem != imem ? imem : STATE_NOTHING);
+ printedMem = imem;
+ }
+ pw.print(STATE_NAMES[procStates[ip]]); pw.print(": ");
+ TimeUtils.formatDuration(time, pw); pw.println(running);
+ totalTime += time;
+ }
+ }
+ }
+ }
+ if (totalTime != 0) {
+ pw.print(prefix);
+ if (screenStates.length > 1) {
+ printScreenLabel(pw, STATE_NOTHING);
+ }
+ if (memStates.length > 1) {
+ printMemLabel(pw, STATE_NOTHING);
+ }
+ pw.print("TOTAL : ");
+ TimeUtils.formatDuration(totalTime, pw);
+ pw.println();
+ }
+ }
+
+ void dumpProcessList(PrintWriter pw, String prefix, ArrayList<ProcessState> procs,
+ int[] screenStates, int[] memStates, int[] procStates, long now) {
+ String innerPrefix = prefix + " ";
+ for (int i=procs.size()-1; i>=0; i--) {
+ ProcessState proc = procs.get(i);
+ pw.print(prefix);
+ pw.print(proc.mPackage);
+ pw.print(" / ");
+ UserHandle.formatUid(pw, proc.mUid);
+ pw.print(" / ");
+ pw.print(proc.mName);
+ pw.println(":");
+ dumpProcessState(pw, innerPrefix, proc, screenStates, memStates, procStates, now);
+ }
+ }
+
+ void dumpFilteredProcesses(PrintWriter pw, String header, String prefix,
+ int[] screenStates, int[] memStates, int[] procStates, long now) {
+ ArrayList<ProcessState> procs = collectProcessesLocked(screenStates, memStates,
+ procStates, now);
+ if (procs.size() > 0) {
+ pw.println();
+ pw.println(header);
+ dumpProcessList(pw, prefix, procs, screenStates, memStates, procStates, now);
+ }
+ }
+
public void dumpLocked(FileDescriptor fd, PrintWriter pw, String[] args) {
final long now = SystemClock.uptimeMillis();
ArrayMap<String, SparseArray<PackageState>> pmap = mState.mPackages.getMap();
- pw.println("Process Stats:");
+ pw.println("Per-Package Process Stats:");
for (int ip=0; ip<pmap.size(); ip++) {
String procName = pmap.keyAt(ip);
SparseArray<PackageState> procs = pmap.valueAt(ip);
for (int iu=0; iu<procs.size(); iu++) {
int uid = procs.keyAt(iu);
PackageState state = procs.valueAt(iu);
- pw.print(" "); pw.print(procName); pw.print(" / "); pw.print(uid); pw.println(":");
+ pw.print(" * "); pw.print(procName); pw.print(" / ");
+ UserHandle.formatUid(pw, uid); pw.println(":");
for (int iproc=0; iproc<state.mProcesses.size(); iproc++) {
- pw.print(" Process ");
+ pw.print(" Process ");
pw.print(state.mProcesses.keyAt(iproc));
pw.println(":");
long totalTime = 0;
ProcessState proc = state.mProcesses.valueAt(iproc);
int printedScreen = -1;
- for (int iscreen=0; iscreen<STATE_COUNT; iscreen+=STATE_SCREEN_ON_MOD) {
+ for (int iscreen=0; iscreen<ADJ_COUNT; iscreen+=ADJ_SCREEN_MOD) {
int printedMem = -1;
- for (int imem=0; imem<STATE_MEM_FACTOR_COUNT; imem+=STATE_MEM_FACTOR_MOD) {
+ for (int imem=0; imem<ADJ_MEM_FACTOR_COUNT; imem++) {
for (int is=0; is<STATE_NAMES.length; is++) {
- int bucket = is+imem+iscreen;
+ int bucket = is+(STATE_COUNT*(imem+iscreen));
long time = proc.mDurations[bucket];
String running = "";
if (proc.mCurState == bucket) {
@@ -220,7 +467,7 @@ public final class ProcessTracker {
running = " (running)";
}
if (time != 0) {
- pw.print(" ");
+ pw.print(" ");
printScreenLabel(pw, printedScreen != iscreen
? iscreen : STATE_NOTHING);
printedScreen = iscreen;
@@ -234,7 +481,7 @@ public final class ProcessTracker {
}
}
if (totalTime != 0) {
- pw.print(" ");
+ pw.print(" ");
printScreenLabel(pw, STATE_NOTHING);
printMemLabel(pw, STATE_NOTHING);
pw.print("TOTAL : ");
@@ -243,53 +490,46 @@ public final class ProcessTracker {
}
}
for (int isvc=0; isvc<state.mServices.size(); isvc++) {
- pw.print(" Service ");
+ pw.print(" Service ");
pw.print(state.mServices.keyAt(isvc));
pw.println(":");
ServiceState svc = state.mServices.valueAt(isvc);
- long time = svc.mStartedDuration;
- if (svc.mStartedTime >= 0) {
- time += now - svc.mStartedTime;
+ if (svc.mStartedCount != 0) {
+ pw.print(" Started op count "); pw.print(svc.mStartedCount);
+ pw.println(":");
+ dumpSingleTime(pw, " ", svc.mStartedDurations, svc.mStartedState,
+ svc.mStartedStartTime, now);
}
- if (time != 0) {
- pw.print(" Started: ");
- TimeUtils.formatDuration(time, pw); pw.println();
+ if (svc.mBoundCount != 0) {
+ pw.print(" Bound op count "); pw.print(svc.mBoundCount);
+ pw.println(":");
+ dumpSingleTime(pw, " ", svc.mBoundDurations, svc.mBoundState,
+ svc.mBoundStartTime, now);
+ }
+ if (svc.mExecCount != 0) {
+ pw.print(" Executing op count "); pw.print(svc.mExecCount);
+ pw.println(":");
+ dumpSingleTime(pw, " ", svc.mExecDurations, svc.mExecState,
+ svc.mExecStartTime, now);
}
}
}
}
+ dumpFilteredProcesses(pw, "Processes running while critical mem:", " ",
+ new int[] {ADJ_SCREEN_OFF, ADJ_SCREEN_ON},
+ new int[] {ADJ_MEM_FACTOR_CRITICAL},
+ new int[] {STATE_TOP, STATE_FOREGROUND, STATE_VISIBLE, STATE_PERCEPTIBLE,
+ STATE_BACKUP, STATE_SERVICE, STATE_HOME, STATE_PREVIOUS},
+ now);
+ dumpFilteredProcesses(pw, "Processes running while low mem:", " ",
+ new int[] {ADJ_SCREEN_OFF, ADJ_SCREEN_ON},
+ new int[] {ADJ_MEM_FACTOR_LOW},
+ new int[] {STATE_TOP, STATE_FOREGROUND, STATE_VISIBLE, STATE_PERCEPTIBLE,
+ STATE_BACKUP, STATE_SERVICE, STATE_HOME, STATE_PREVIOUS},
+ now);
pw.println();
pw.println("Run time Stats:");
- long totalTime = 0;
- int printedScreen = -1;
- for (int iscreen=0; iscreen<STATE_COUNT; iscreen+=STATE_SCREEN_ON_MOD) {
- int printedMem = -1;
- for (int imem=0; imem<STATE_MEM_FACTOR_COUNT; imem+=STATE_MEM_FACTOR_MOD) {
- int bucket = imem+iscreen;
- long time = mState.mMemFactorDurations[bucket/STATE_MEM_FACTOR_MOD];
- String running = "";
- if (mState.mMemFactor == bucket) {
- time += now - mState.mStartTime;
- running = " (running)";
- }
- if (time != 0) {
- pw.print(" ");
- printScreenLabel(pw, printedScreen != iscreen
- ? iscreen : STATE_NOTHING);
- printedScreen = iscreen;
- printMemLabel(pw, printedMem != imem ? imem : STATE_NOTHING);
- printedMem = imem;
- TimeUtils.formatDuration(time, pw); pw.println(running);
- totalTime += time;
- }
- }
- }
- if (totalTime != 0) {
- pw.print(" ");
- printScreenLabel(pw, STATE_NOTHING);
- pw.print("TOTAL: ");
- TimeUtils.formatDuration(totalTime, pw);
- pw.println();
- }
+ dumpSingleTime(pw, " ", mState.mMemFactorDurations, mState.mMemFactor,
+ mState.mStartTime, now);
}
}
diff --git a/services/java/com/android/server/am/ServiceRecord.java b/services/java/com/android/server/am/ServiceRecord.java
index 45e248b..5000940 100644
--- a/services/java/com/android/server/am/ServiceRecord.java
+++ b/services/java/com/android/server/am/ServiceRecord.java
@@ -73,6 +73,7 @@ final class ServiceRecord extends Binder {
final String dataDir; // where activity data should go
final boolean exported; // from ServiceInfo.exported
final Runnable restarter; // used to schedule retries of starting the service
+ final ProcessTracker.ServiceState tracker; // tracking service execution, may be null
final long createTime; // when this service was created
final ArrayMap<Intent.FilterComparison, IntentBindRecord> bindings
= new ArrayMap<Intent.FilterComparison, IntentBindRecord>();
@@ -281,7 +282,8 @@ final class ServiceRecord extends Binder {
ServiceRecord(ActivityManagerService ams,
BatteryStatsImpl.Uid.Pkg.Serv servStats, ComponentName name,
- Intent.FilterComparison intent, ServiceInfo sInfo, Runnable restarter) {
+ Intent.FilterComparison intent, ServiceInfo sInfo, Runnable restarter,
+ ProcessTracker.ServiceState tracker) {
this.ams = ams;
this.stats = servStats;
this.name = name;
@@ -297,6 +299,7 @@ final class ServiceRecord extends Binder {
dataDir = sInfo.applicationInfo.dataDir;
exported = sInfo.exported;
this.restarter = restarter;
+ this.tracker = tracker;
createTime = SystemClock.elapsedRealtime();
lastActivity = SystemClock.uptimeMillis();
userId = UserHandle.getUserId(appInfo.uid);
@@ -319,6 +322,20 @@ final class ServiceRecord extends Binder {
return a;
}
+ public boolean hasAutoCreateConnections() {
+ // XXX should probably keep a count of the number of auto-create
+ // connections directly in the service.
+ for (int conni=connections.size()-1; conni>=0; conni--) {
+ ArrayList<ConnectionRecord> cr = connections.valueAt(conni);
+ for (int i=0; i<cr.size(); i++) {
+ if ((cr.get(i).flags&Context.BIND_AUTO_CREATE) != 0) {
+ return true;
+ }
+ }
+ }
+ return false;
+ }
+
public void resetRestartCounter() {
restartCount = 0;
restartDelay = 0;
diff --git a/services/java/com/android/server/location/GpsLocationProvider.java b/services/java/com/android/server/location/GpsLocationProvider.java
index 8c88cab..4791ec0 100644
--- a/services/java/com/android/server/location/GpsLocationProvider.java
+++ b/services/java/com/android/server/location/GpsLocationProvider.java
@@ -41,6 +41,7 @@ import android.net.ConnectivityManager;
import android.net.NetworkInfo;
import android.net.Uri;
import android.os.AsyncTask;
+import android.os.BatteryStats;
import android.os.Binder;
import android.os.Bundle;
import android.os.Handler;
@@ -456,7 +457,8 @@ public class GpsLocationProvider implements LocationProviderInterface {
Context.APP_OPS_SERVICE));
// Battery statistics service to be notified when GPS turns on or off
- mBatteryStats = IBatteryStats.Stub.asInterface(ServiceManager.getService("batteryinfo"));
+ mBatteryStats = IBatteryStats.Stub.asInterface(ServiceManager.getService(
+ BatteryStats.SERVICE_NAME));
mProperties = new Properties();
try {
diff --git a/wifi/java/android/net/wifi/WifiStateMachine.java b/wifi/java/android/net/wifi/WifiStateMachine.java
index 9f3a0d3..1040ab1 100644
--- a/wifi/java/android/net/wifi/WifiStateMachine.java
+++ b/wifi/java/android/net/wifi/WifiStateMachine.java
@@ -54,6 +54,7 @@ import android.net.NetworkUtils;
import android.net.wifi.WpsResult.Status;
import android.net.wifi.p2p.WifiP2pManager;
import android.net.wifi.p2p.WifiP2pService;
+import android.os.BatteryStats;
import android.os.Binder;
import android.os.IBinder;
import android.os.INetworkManagementService;
@@ -542,7 +543,8 @@ public class WifiStateMachine extends StateMachine {
mInterfaceName = wlanInterface;
mNetworkInfo = new NetworkInfo(ConnectivityManager.TYPE_WIFI, 0, NETWORKTYPE, "");
- mBatteryStats = IBatteryStats.Stub.asInterface(ServiceManager.getService("batteryinfo"));
+ mBatteryStats = IBatteryStats.Stub.asInterface(ServiceManager.getService(
+ BatteryStats.SERVICE_NAME));
IBinder b = ServiceManager.getService(Context.NETWORKMANAGEMENT_SERVICE);
mNwService = INetworkManagementService.Stub.asInterface(b);