diff options
author | Dianne Hackborn <hackbod@google.com> | 2013-06-15 00:39:30 +0000 |
---|---|---|
committer | Android (Google) Code Review <android-gerrit@google.com> | 2013-06-15 00:39:31 +0000 |
commit | fbf7a9aea201484ff40e827de97a6db903b53ac3 (patch) | |
tree | 5be4b3db5aa8886a041fffa688029182252ce7bd | |
parent | e0dae4b493d3547b223f498a9f3e5aa2ddd856f6 (diff) | |
parent | 91268cf21eace600792d04db1ac62e9268f48002 (diff) | |
download | frameworks_base-fbf7a9aea201484ff40e827de97a6db903b53ac3.zip frameworks_base-fbf7a9aea201484ff40e827de97a6db903b53ac3.tar.gz frameworks_base-fbf7a9aea201484ff40e827de97a6db903b53ac3.tar.bz2 |
Merge "More work on process tracking."
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); |