summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDianne Hackborn <hackbod@google.com>2013-06-15 00:39:30 +0000
committerAndroid (Google) Code Review <android-gerrit@google.com>2013-06-15 00:39:31 +0000
commitfbf7a9aea201484ff40e827de97a6db903b53ac3 (patch)
tree5be4b3db5aa8886a041fffa688029182252ce7bd
parente0dae4b493d3547b223f498a9f3e5aa2ddd856f6 (diff)
parent91268cf21eace600792d04db1ac62e9268f48002 (diff)
downloadframeworks_base-fbf7a9aea201484ff40e827de97a6db903b53ac3.zip
frameworks_base-fbf7a9aea201484ff40e827de97a6db903b53ac3.tar.gz
frameworks_base-fbf7a9aea201484ff40e827de97a6db903b53ac3.tar.bz2
Merge "More work on process tracking."
-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);