summaryrefslogtreecommitdiffstats
path: root/services/java/com/android
diff options
context:
space:
mode:
Diffstat (limited to 'services/java/com/android')
-rw-r--r--services/java/com/android/server/ConnectivityService.java306
-rw-r--r--services/java/com/android/server/ProcessStats.java148
-rw-r--r--services/java/com/android/server/WindowManagerService.java5
-rw-r--r--services/java/com/android/server/am/ActivityManagerService.java777
-rw-r--r--services/java/com/android/server/am/ProcessRecord.java28
-rw-r--r--services/java/com/android/server/am/ServiceRecord.java4
-rw-r--r--services/java/com/android/server/sip/SipService.java25
-rw-r--r--services/java/com/android/server/sip/SipSessionGroup.java107
-rw-r--r--services/java/com/android/server/sip/SipSessionListenerProxy.java2
9 files changed, 918 insertions, 484 deletions
diff --git a/services/java/com/android/server/ConnectivityService.java b/services/java/com/android/server/ConnectivityService.java
index aae3cff..6095117 100644
--- a/services/java/com/android/server/ConnectivityService.java
+++ b/services/java/com/android/server/ConnectivityService.java
@@ -114,6 +114,71 @@ public class ConnectivityService extends IConnectivityManager.Stub {
private boolean mTestMode;
private static ConnectivityService sServiceInstance;
+ private static final int ENABLED = 1;
+ private static final int DISABLED = 0;
+
+ // Share the event space with NetworkStateTracker (which can't see this
+ // internal class but sends us events). If you change these, change
+ // NetworkStateTracker.java too.
+ private static final int MIN_NETWORK_STATE_TRACKER_EVENT = 1;
+ private static final int MAX_NETWORK_STATE_TRACKER_EVENT = 100;
+
+ /**
+ * used internally as a delayed event to make us switch back to the
+ * default network
+ */
+ private static final int EVENT_RESTORE_DEFAULT_NETWORK =
+ MAX_NETWORK_STATE_TRACKER_EVENT + 1;
+
+ /**
+ * used internally to change our mobile data enabled flag
+ */
+ private static final int EVENT_CHANGE_MOBILE_DATA_ENABLED =
+ MAX_NETWORK_STATE_TRACKER_EVENT + 2;
+
+ /**
+ * used internally to change our network preference setting
+ * arg1 = networkType to prefer
+ */
+ private static final int EVENT_SET_NETWORK_PREFERENCE =
+ MAX_NETWORK_STATE_TRACKER_EVENT + 3;
+
+ /**
+ * used internally to synchronize inet condition reports
+ * arg1 = networkType
+ * arg2 = condition (0 bad, 100 good)
+ */
+ private static final int EVENT_INET_CONDITION_CHANGE =
+ MAX_NETWORK_STATE_TRACKER_EVENT + 4;
+
+ /**
+ * used internally to mark the end of inet condition hold periods
+ * arg1 = networkType
+ */
+ private static final int EVENT_INET_CONDITION_HOLD_END =
+ MAX_NETWORK_STATE_TRACKER_EVENT + 5;
+
+ /**
+ * used internally to set the background data preference
+ * arg1 = TRUE for enabled, FALSE for disabled
+ */
+ private static final int EVENT_SET_BACKGROUND_DATA =
+ MAX_NETWORK_STATE_TRACKER_EVENT + 6;
+
+ /**
+ * used internally to set enable/disable cellular data
+ * arg1 = ENBALED or DISABLED
+ */
+ private static final int EVENT_SET_MOBILE_DATA =
+ MAX_NETWORK_STATE_TRACKER_EVENT + 7;
+
+ /**
+ * used internally to clear a wakelock when transitioning
+ * from one net to another
+ */
+ private static final int EVENT_CLEAR_NET_TRANSITION_WAKELOCK =
+ MAX_NETWORK_STATE_TRACKER_EVENT + 8;
+
private Handler mHandler;
// list of DeathRecipients used to make sure features are turned off when
@@ -354,30 +419,36 @@ public class ConnectivityService extends IConnectivityManager.Stub {
* Sets the preferred network.
* @param preference the new preference
*/
- public synchronized void setNetworkPreference(int preference) {
+ public void setNetworkPreference(int preference) {
enforceChangePermission();
+
+ mHandler.sendMessage(mHandler.obtainMessage(EVENT_SET_NETWORK_PREFERENCE, preference, 0));
+ }
+
+ public int getNetworkPreference() {
+ enforceAccessPermission();
+ int preference;
+ synchronized(this) {
+ preference = mNetworkPreference;
+ }
+ return preference;
+ }
+
+ private void handleSetNetworkPreference(int preference) {
if (ConnectivityManager.isNetworkTypeValid(preference) &&
mNetAttributes[preference] != null &&
mNetAttributes[preference].isDefault()) {
if (mNetworkPreference != preference) {
- persistNetworkPreference(preference);
- mNetworkPreference = preference;
+ final ContentResolver cr = mContext.getContentResolver();
+ Settings.Secure.putInt(cr, Settings.Secure.NETWORK_PREFERENCE, preference);
+ synchronized(this) {
+ mNetworkPreference = preference;
+ }
enforcePreference();
}
}
}
- public int getNetworkPreference() {
- enforceAccessPermission();
- return mNetworkPreference;
- }
-
- private void persistNetworkPreference(int networkPreference) {
- final ContentResolver cr = mContext.getContentResolver();
- Settings.Secure.putInt(cr, Settings.Secure.NETWORK_PREFERENCE,
- networkPreference);
- }
-
private int getPersistedNetworkPreference() {
final ContentResolver cr = mContext.getContentResolver();
@@ -628,8 +699,7 @@ public class ConnectivityService extends IConnectivityManager.Stub {
mNetRequestersPids[usedNetworkType].add(currentPid);
}
}
- mHandler.sendMessageDelayed(mHandler.obtainMessage(
- NetworkStateTracker.EVENT_RESTORE_DEFAULT_NETWORK,
+ mHandler.sendMessageDelayed(mHandler.obtainMessage(EVENT_RESTORE_DEFAULT_NETWORK,
f), getRestoreDefaultNetworkDelay());
@@ -871,15 +941,18 @@ public class ConnectivityService extends IConnectivityManager.Stub {
android.Manifest.permission.CHANGE_BACKGROUND_DATA_SETTING,
"ConnectivityService");
- if (getBackgroundDataSetting() == allowBackgroundDataUsage) return;
-
- Settings.Secure.putInt(mContext.getContentResolver(),
- Settings.Secure.BACKGROUND_DATA,
- allowBackgroundDataUsage ? 1 : 0);
+ mHandler.sendMessage(mHandler.obtainMessage(EVENT_SET_BACKGROUND_DATA,
+ (allowBackgroundDataUsage ? ENABLED : DISABLED), 0));
+ }
- Intent broadcast = new Intent(
- ConnectivityManager.ACTION_BACKGROUND_DATA_SETTING_CHANGED);
- mContext.sendBroadcast(broadcast);
+ private void handleSetBackgroundData(boolean enabled) {
+ if (enabled != getBackgroundDataSetting()) {
+ Settings.Secure.putInt(mContext.getContentResolver(),
+ Settings.Secure.BACKGROUND_DATA, enabled ? 1 : 0);
+ Intent broadcast = new Intent(
+ ConnectivityManager.ACTION_BACKGROUND_DATA_SETTING_CHANGED);
+ mContext.sendBroadcast(broadcast);
+ }
}
/**
@@ -896,10 +969,15 @@ public class ConnectivityService extends IConnectivityManager.Stub {
/**
* @see ConnectivityManager#setMobileDataEnabled(boolean)
*/
- public synchronized void setMobileDataEnabled(boolean enabled) {
+ public void setMobileDataEnabled(boolean enabled) {
enforceChangePermission();
if (DBG) Slog.d(TAG, "setMobileDataEnabled(" + enabled + ")");
+ mHandler.sendMessage(mHandler.obtainMessage(EVENT_SET_MOBILE_DATA,
+ (enabled ? ENABLED : DISABLED), 0));
+ }
+
+ private void handleSetMobileData(boolean enabled) {
if (getMobileDataEnabled() == enabled) return;
Settings.Secure.putInt(mContext.getContentResolver(),
@@ -907,7 +985,9 @@ public class ConnectivityService extends IConnectivityManager.Stub {
if (enabled) {
if (mNetTrackers[ConnectivityManager.TYPE_MOBILE] != null) {
- if (DBG) Slog.d(TAG, "starting up " + mNetTrackers[ConnectivityManager.TYPE_MOBILE]);
+ if (DBG) {
+ Slog.d(TAG, "starting up " + mNetTrackers[ConnectivityManager.TYPE_MOBILE]);
+ }
mNetTrackers[ConnectivityManager.TYPE_MOBILE].reconnect();
}
} else {
@@ -1267,7 +1347,7 @@ public class ConnectivityService extends IConnectivityManager.Stub {
// new network
if (mNetTransitionWakeLock.isHeld()) {
mHandler.sendMessageDelayed(mHandler.obtainMessage(
- NetworkStateTracker.EVENT_CLEAR_NET_TRANSITION_WAKELOCK,
+ EVENT_CLEAR_NET_TRANSITION_WAKELOCK,
mNetTransitionWakeLockSerialNumber, 0),
1000);
}
@@ -1705,11 +1785,7 @@ public class ConnectivityService extends IConnectivityManager.Stub {
type = info.getType();
handleDnsConfigurationChange(type);
break;
- case NetworkStateTracker.EVENT_RESTORE_DEFAULT_NETWORK:
- FeatureUser u = (FeatureUser)msg.obj;
- u.expire();
- break;
- case NetworkStateTracker.EVENT_CLEAR_NET_TRANSITION_WAKELOCK:
+ case EVENT_CLEAR_NET_TRANSITION_WAKELOCK:
String causedBy = null;
synchronized (ConnectivityService.this) {
if (msg.arg1 == mNetTransitionWakeLockSerialNumber &&
@@ -1723,70 +1799,42 @@ public class ConnectivityService extends IConnectivityManager.Stub {
causedBy + " released by timeout");
}
break;
- case NetworkStateTracker.EVENT_INET_CONDITION_CHANGE:
- if (DBG) {
- Slog.d(TAG, "Inet connectivity change, net=" +
- msg.arg1 + ", condition=" + msg.arg2 +
- ",mActiveDefaultNetwork=" + mActiveDefaultNetwork);
- }
- if (mActiveDefaultNetwork == -1) {
- if (DBG) Slog.d(TAG, "no active default network - aborting");
- break;
- }
- if (mActiveDefaultNetwork != msg.arg1) {
- if (DBG) Slog.d(TAG, "given net not default - aborting");
- break;
- }
- mDefaultInetCondition = msg.arg2;
- int delay;
- if (mInetConditionChangeInFlight == false) {
- if (DBG) Slog.d(TAG, "starting a change hold");
- // setup a new hold to debounce this
- if (mDefaultInetCondition > 50) {
- delay = Settings.Secure.getInt(mContext.getContentResolver(),
- Settings.Secure.INET_CONDITION_DEBOUNCE_UP_DELAY, 500);
- } else {
- delay = Settings.Secure.getInt(mContext.getContentResolver(),
- Settings.Secure.INET_CONDITION_DEBOUNCE_DOWN_DELAY, 3000);
- }
- mInetConditionChangeInFlight = true;
- sendMessageDelayed(obtainMessage(
- NetworkStateTracker.EVENT_INET_CONDITION_HOLD_END,
- mActiveDefaultNetwork, mDefaultConnectionSequence), delay);
- } else {
- // we've set the new condition, when this hold ends that will get
- // picked up
- if (DBG) Slog.d(TAG, "currently in hold - not setting new end evt");
- }
+ case EVENT_RESTORE_DEFAULT_NETWORK:
+ FeatureUser u = (FeatureUser)msg.obj;
+ u.expire();
break;
- case NetworkStateTracker.EVENT_INET_CONDITION_HOLD_END:
- if (DBG) {
- Slog.d(TAG, "Inet hold end, net=" + msg.arg1 +
- ", condition =" + mDefaultInetCondition +
- ", published condition =" + mDefaultInetConditionPublished);
- }
- mInetConditionChangeInFlight = false;
-
- if (mActiveDefaultNetwork == -1) {
- if (DBG) Slog.d(TAG, "no active default network - aborting");
- break;
- }
- if (mDefaultConnectionSequence != msg.arg2) {
- if (DBG) Slog.d(TAG, "event hold for obsolete network - aborting");
- break;
- }
- if (mDefaultInetConditionPublished == mDefaultInetCondition) {
- if (DBG) Slog.d(TAG, "no change in condition - aborting");
- break;
- }
- NetworkInfo networkInfo = mNetTrackers[mActiveDefaultNetwork].getNetworkInfo();
- if (networkInfo.isConnected() == false) {
- if (DBG) Slog.d(TAG, "default network not connected - aborting");
- break;
- }
- mDefaultInetConditionPublished = mDefaultInetCondition;
- sendInetConditionBroadcast(networkInfo);
+ case EVENT_INET_CONDITION_CHANGE:
+ {
+ int netType = msg.arg1;
+ int condition = msg.arg2;
+ handleInetConditionChange(netType, condition);
+ break;
+ }
+ case EVENT_INET_CONDITION_HOLD_END:
+ {
+ int netType = msg.arg1;
+ int sequence = msg.arg2;
+ handleInetConditionHoldEnd(netType, sequence);
+ break;
+ }
+ case EVENT_SET_NETWORK_PREFERENCE:
+ {
+ int preference = msg.arg1;
+ handleSetNetworkPreference(preference);
+ break;
+ }
+ case EVENT_SET_BACKGROUND_DATA:
+ {
+ boolean enabled = (msg.arg1 == ENABLED);
+ handleSetBackgroundData(enabled);
+ break;
+ }
+ case EVENT_SET_MOBILE_DATA:
+ {
+ boolean enabled = (msg.arg1 == ENABLED);
+ handleSetMobileData(enabled);
break;
+ }
}
}
}
@@ -1893,7 +1941,7 @@ public class ConnectivityService extends IConnectivityManager.Stub {
mNetTransitionWakeLockCausedBy = forWhom;
}
mHandler.sendMessageDelayed(mHandler.obtainMessage(
- NetworkStateTracker.EVENT_CLEAR_NET_TRANSITION_WAKELOCK,
+ EVENT_CLEAR_NET_TRANSITION_WAKELOCK,
mNetTransitionWakeLockSerialNumber, 0),
mNetTransitionWakeLockTimeout);
return;
@@ -1918,6 +1966,72 @@ public class ConnectivityService extends IConnectivityManager.Stub {
}
}
mHandler.sendMessage(mHandler.obtainMessage(
- NetworkStateTracker.EVENT_INET_CONDITION_CHANGE, networkType, percentage));
+ EVENT_INET_CONDITION_CHANGE, networkType, percentage));
+ }
+
+ private void handleInetConditionChange(int netType, int condition) {
+ if (DBG) {
+ Slog.d(TAG, "Inet connectivity change, net=" +
+ netType + ", condition=" + condition +
+ ",mActiveDefaultNetwork=" + mActiveDefaultNetwork);
+ }
+ if (mActiveDefaultNetwork == -1) {
+ if (DBG) Slog.d(TAG, "no active default network - aborting");
+ return;
+ }
+ if (mActiveDefaultNetwork != netType) {
+ if (DBG) Slog.d(TAG, "given net not default - aborting");
+ return;
+ }
+ mDefaultInetCondition = condition;
+ int delay;
+ if (mInetConditionChangeInFlight == false) {
+ if (DBG) Slog.d(TAG, "starting a change hold");
+ // setup a new hold to debounce this
+ if (mDefaultInetCondition > 50) {
+ delay = Settings.Secure.getInt(mContext.getContentResolver(),
+ Settings.Secure.INET_CONDITION_DEBOUNCE_UP_DELAY, 500);
+ } else {
+ delay = Settings.Secure.getInt(mContext.getContentResolver(),
+ Settings.Secure.INET_CONDITION_DEBOUNCE_DOWN_DELAY, 3000);
+ }
+ mInetConditionChangeInFlight = true;
+ mHandler.sendMessageDelayed(mHandler.obtainMessage(EVENT_INET_CONDITION_HOLD_END,
+ mActiveDefaultNetwork, mDefaultConnectionSequence), delay);
+ } else {
+ // we've set the new condition, when this hold ends that will get
+ // picked up
+ if (DBG) Slog.d(TAG, "currently in hold - not setting new end evt");
+ }
+ }
+
+ private void handleInetConditionHoldEnd(int netType, int sequence) {
+ if (DBG) {
+ Slog.d(TAG, "Inet hold end, net=" + netType +
+ ", condition =" + mDefaultInetCondition +
+ ", published condition =" + mDefaultInetConditionPublished);
+ }
+ mInetConditionChangeInFlight = false;
+
+ if (mActiveDefaultNetwork == -1) {
+ if (DBG) Slog.d(TAG, "no active default network - aborting");
+ return;
+ }
+ if (mDefaultConnectionSequence != sequence) {
+ if (DBG) Slog.d(TAG, "event hold for obsolete network - aborting");
+ return;
+ }
+ if (mDefaultInetConditionPublished == mDefaultInetCondition) {
+ if (DBG) Slog.d(TAG, "no change in condition - aborting");
+ return;
+ }
+ NetworkInfo networkInfo = mNetTrackers[mActiveDefaultNetwork].getNetworkInfo();
+ if (networkInfo.isConnected() == false) {
+ if (DBG) Slog.d(TAG, "default network not connected - aborting");
+ return;
+ }
+ mDefaultInetConditionPublished = mDefaultInetCondition;
+ sendInetConditionBroadcast(networkInfo);
+ return;
}
}
diff --git a/services/java/com/android/server/ProcessStats.java b/services/java/com/android/server/ProcessStats.java
index 5bdadcc..43dbcc0 100644
--- a/services/java/com/android/server/ProcessStats.java
+++ b/services/java/com/android/server/ProcessStats.java
@@ -80,16 +80,24 @@ public class ProcessStats {
PROC_SPACE_TERM|PROC_OUT_LONG, // 11: major faults
PROC_SPACE_TERM,
PROC_SPACE_TERM|PROC_OUT_LONG, // 13: utime
- PROC_SPACE_TERM|PROC_OUT_LONG // 14: stime
+ PROC_SPACE_TERM|PROC_OUT_LONG, // 14: stime
+ PROC_SPACE_TERM,
+ PROC_SPACE_TERM,
+ PROC_SPACE_TERM,
+ PROC_SPACE_TERM,
+ PROC_SPACE_TERM,
+ PROC_SPACE_TERM,
+ PROC_SPACE_TERM|PROC_OUT_LONG, // 21: vsize
};
static final int PROCESS_FULL_STAT_MINOR_FAULTS = 1;
static final int PROCESS_FULL_STAT_MAJOR_FAULTS = 2;
static final int PROCESS_FULL_STAT_UTIME = 3;
static final int PROCESS_FULL_STAT_STIME = 4;
+ static final int PROCESS_FULL_STAT_VSIZE = 5;
- private final String[] mProcessFullStatsStringData = new String[5];
- private final long[] mProcessFullStatsData = new long[5];
+ private final String[] mProcessFullStatsStringData = new String[6];
+ private final long[] mProcessFullStatsData = new long[6];
private static final int[] SYSTEM_CPU_FORMAT = new int[] {
PROC_SPACE_TERM|PROC_COMBINE,
@@ -171,6 +179,8 @@ public class ProcessStats {
final ArrayList<Stats> threadStats;
final ArrayList<Stats> workingThreads;
+ public boolean interesting;
+
public String baseName;
public String name;
int nameWidth;
@@ -349,59 +359,62 @@ public class ProcessStats {
+ (parentPid < 0 ? "process" : "thread")
+ " pid " + pid + ": " + st);
- final long uptime = SystemClock.uptimeMillis();
+ if (st.interesting) {
+ final long uptime = SystemClock.uptimeMillis();
- final long[] procStats = mProcessStatsData;
- if (!Process.readProcFile(st.statFile.toString(),
- PROCESS_STATS_FORMAT, null, procStats, null)) {
- continue;
- }
-
- final long minfaults = procStats[PROCESS_STAT_MINOR_FAULTS];
- final long majfaults = procStats[PROCESS_STAT_MAJOR_FAULTS];
- final long utime = procStats[PROCESS_STAT_UTIME];
- final long stime = procStats[PROCESS_STAT_STIME];
-
- if (utime == st.base_utime && stime == st.base_stime) {
- st.rel_utime = 0;
- st.rel_stime = 0;
- st.rel_minfaults = 0;
- st.rel_majfaults = 0;
- if (st.active) {
- st.active = false;
+ final long[] procStats = mProcessStatsData;
+ if (!Process.readProcFile(st.statFile.toString(),
+ PROCESS_STATS_FORMAT, null, procStats, null)) {
+ continue;
}
- continue;
- }
- if (!st.active) {
- st.active = true;
- }
+ final long minfaults = procStats[PROCESS_STAT_MINOR_FAULTS];
+ final long majfaults = procStats[PROCESS_STAT_MAJOR_FAULTS];
+ final long utime = procStats[PROCESS_STAT_UTIME];
+ final long stime = procStats[PROCESS_STAT_STIME];
+
+ if (utime == st.base_utime && stime == st.base_stime) {
+ st.rel_utime = 0;
+ st.rel_stime = 0;
+ st.rel_minfaults = 0;
+ st.rel_majfaults = 0;
+ if (st.active) {
+ st.active = false;
+ }
+ continue;
+ }
- if (parentPid < 0) {
- getName(st, st.cmdlineFile);
- if (st.threadStats != null) {
- mCurThreadPids = collectStats(st.threadsDir, pid, false,
- mCurThreadPids, st.threadStats);
+ if (!st.active) {
+ st.active = true;
}
+
+ if (parentPid < 0) {
+ getName(st, st.cmdlineFile);
+ if (st.threadStats != null) {
+ mCurThreadPids = collectStats(st.threadsDir, pid, false,
+ mCurThreadPids, st.threadStats);
+ }
+ }
+
+ if (DEBUG) Slog.v("Load", "Stats changed " + st.name + " pid=" + st.pid
+ + " utime=" + utime + "-" + st.base_utime
+ + " stime=" + stime + "-" + st.base_stime
+ + " minfaults=" + minfaults + "-" + st.base_minfaults
+ + " majfaults=" + majfaults + "-" + st.base_majfaults);
+
+ st.rel_uptime = uptime - st.base_uptime;
+ st.base_uptime = uptime;
+ st.rel_utime = (int)(utime - st.base_utime);
+ st.rel_stime = (int)(stime - st.base_stime);
+ st.base_utime = utime;
+ st.base_stime = stime;
+ st.rel_minfaults = (int)(minfaults - st.base_minfaults);
+ st.rel_majfaults = (int)(majfaults - st.base_majfaults);
+ st.base_minfaults = minfaults;
+ st.base_majfaults = majfaults;
+ st.working = true;
}
- if (DEBUG) Slog.v("Load", "Stats changed " + st.name + " pid=" + st.pid
- + " utime=" + utime + "-" + st.base_utime
- + " stime=" + stime + "-" + st.base_stime
- + " minfaults=" + minfaults + "-" + st.base_minfaults
- + " majfaults=" + majfaults + "-" + st.base_majfaults);
-
- st.rel_uptime = uptime - st.base_uptime;
- st.base_uptime = uptime;
- st.rel_utime = (int)(utime - st.base_utime);
- st.rel_stime = (int)(stime - st.base_stime);
- st.base_utime = utime;
- st.base_stime = stime;
- st.rel_minfaults = (int)(minfaults - st.base_minfaults);
- st.rel_majfaults = (int)(majfaults - st.base_majfaults);
- st.base_minfaults = minfaults;
- st.base_majfaults = majfaults;
- st.working = true;
continue;
}
@@ -421,12 +434,24 @@ public class ProcessStats {
if (Process.readProcFile(st.statFile.toString(),
PROCESS_FULL_STATS_FORMAT, procStatsString,
procStats, null)) {
- st.baseName = procStatsString[0];
- st.base_minfaults = procStats[PROCESS_FULL_STAT_MINOR_FAULTS];
- st.base_majfaults = procStats[PROCESS_FULL_STAT_MAJOR_FAULTS];
- st.base_utime = procStats[PROCESS_FULL_STAT_UTIME];
- st.base_stime = procStats[PROCESS_FULL_STAT_STIME];
+ // This is a possible way to filter out processes that
+ // are actually kernel threads... do we want to? Some
+ // of them do use CPU, but there can be a *lot* that are
+ // not doing anything.
+ if (true || procStats[PROCESS_FULL_STAT_VSIZE] != 0) {
+ st.interesting = true;
+ st.baseName = procStatsString[0];
+ st.base_minfaults = procStats[PROCESS_FULL_STAT_MINOR_FAULTS];
+ st.base_majfaults = procStats[PROCESS_FULL_STAT_MAJOR_FAULTS];
+ st.base_utime = procStats[PROCESS_FULL_STAT_UTIME];
+ st.base_stime = procStats[PROCESS_FULL_STAT_STIME];
+ } else {
+ Slog.i(TAG, "Skipping kernel process pid " + pid
+ + " name " + procStatsString[0]);
+ st.baseName = procStatsString[0];
+ }
} else {
+ Slog.w(TAG, "Skipping unknown process pid " + pid);
st.baseName = "<unknown>";
st.base_utime = st.base_stime = 0;
st.base_minfaults = st.base_majfaults = 0;
@@ -438,7 +463,7 @@ public class ProcessStats {
mCurThreadPids = collectStats(st.threadsDir, pid, true,
mCurThreadPids, st.threadStats);
}
- } else {
+ } else if (st.interesting) {
st.name = st.baseName;
st.nameWidth = onMeasureProcessName(st.name);
}
@@ -452,7 +477,7 @@ public class ProcessStats {
st.rel_minfaults = 0;
st.rel_majfaults = 0;
st.added = true;
- if (!first) {
+ if (!first && st.interesting) {
st.working = true;
}
continue;
@@ -624,6 +649,14 @@ public class ProcessStats {
}
}
+ final public int countStats() {
+ return mProcStats.size();
+ }
+
+ final public Stats getStats(int index) {
+ return mProcStats.get(index);
+ }
+
final public int countWorkingStats() {
buildWorkingProcs();
return mWorkingProcs.size();
@@ -788,7 +821,8 @@ public class ProcessStats {
private void getName(Stats st, String cmdlineFile) {
String newName = st.name;
- if (st.name == null || st.name.equals("app_process")) {
+ if (st.name == null || st.name.equals("app_process")
+ || st.name.equals("<pre-initialized>")) {
String cmdName = readFile(cmdlineFile, '\0');
if (cmdName != null && cmdName.length() > 1) {
newName = cmdName;
diff --git a/services/java/com/android/server/WindowManagerService.java b/services/java/com/android/server/WindowManagerService.java
index 3e4f522..7100cc5 100644
--- a/services/java/com/android/server/WindowManagerService.java
+++ b/services/java/com/android/server/WindowManagerService.java
@@ -5687,9 +5687,12 @@ public class WindowManagerService extends IWindowManager.Stub
int requestedWidth, int requestedHeight, int viewFlags,
boolean insetsPending, Rect outFrame, Rect outContentInsets,
Rect outVisibleInsets, Configuration outConfig, Surface outSurface) {
- return relayoutWindow(this, window, attrs,
+ //Log.d(TAG, ">>>>>> ENTERED relayout from " + Binder.getCallingPid());
+ int res = relayoutWindow(this, window, attrs,
requestedWidth, requestedHeight, viewFlags, insetsPending,
outFrame, outContentInsets, outVisibleInsets, outConfig, outSurface);
+ //Log.d(TAG, "<<<<<< EXITING relayout to " + Binder.getCallingPid());
+ return res;
}
public void setTransparentRegion(IWindow window, Region region) {
diff --git a/services/java/com/android/server/am/ActivityManagerService.java b/services/java/com/android/server/am/ActivityManagerService.java
index c896c94..9685fb7 100644
--- a/services/java/com/android/server/am/ActivityManagerService.java
+++ b/services/java/com/android/server/am/ActivityManagerService.java
@@ -122,6 +122,8 @@ import java.io.PrintWriter;
import java.lang.IllegalStateException;
import java.lang.ref.WeakReference;
import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Comparator;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
@@ -145,6 +147,7 @@ public final class ActivityManagerService extends ActivityManagerNative
static final boolean DEBUG_BROADCAST = localLOGV || false;
static final boolean DEBUG_BROADCAST_LIGHT = DEBUG_BROADCAST || false;
static final boolean DEBUG_SERVICE = localLOGV || false;
+ static final boolean DEBUG_SERVICE_EXECUTING = localLOGV || false;
static final boolean DEBUG_VISBILITY = localLOGV || false;
static final boolean DEBUG_PROCESSES = localLOGV || false;
static final boolean DEBUG_PROVIDER = localLOGV || false;
@@ -153,6 +156,8 @@ public final class ActivityManagerService extends ActivityManagerNative
static final boolean DEBUG_RESULTS = localLOGV || false;
static final boolean DEBUG_BACKUP = localLOGV || false;
static final boolean DEBUG_CONFIGURATION = localLOGV || false;
+ static final boolean DEBUG_POWER = localLOGV || false;
+ static final boolean DEBUG_POWER_QUICK = DEBUG_POWER || false;
static final boolean VALIDATE_TOKENS = false;
static final boolean SHOW_ACTIVITY_START_TIME = true;
@@ -198,8 +203,16 @@ public final class ActivityManagerService extends ActivityManagerNative
// The minimum amount of time between successive GC requests for a process.
static final int GC_MIN_INTERVAL = 60*1000;
- // The rate at which we check for apps using excessive wake locks -- 15 mins.
- static final int WAKE_LOCK_CHECK_DELAY = 15*60*1000;
+ // The rate at which we check for apps using excessive power -- 15 mins.
+ static final int POWER_CHECK_DELAY = (DEBUG_POWER_QUICK ? 2 : 15) * 60*1000;
+
+ // The minimum sample duration we will allow before deciding we have
+ // enough data on wake locks to start killing things.
+ static final int WAKE_LOCK_MIN_CHECK_DURATION = (DEBUG_POWER_QUICK ? 1 : 5) * 60*1000;
+
+ // The minimum sample duration we will allow before deciding we have
+ // enough data on CPU usage to start killing things.
+ static final int CPU_MIN_CHECK_DURATION = (DEBUG_POWER_QUICK ? 1 : 5) * 60*1000;
// How long we allow a receiver to run before giving up on it.
static final int BROADCAST_TIMEOUT = 10*1000;
@@ -553,6 +566,11 @@ public final class ActivityManagerService extends ActivityManagerNative
private final StringBuilder mStrictModeBuffer = new StringBuilder();
/**
+ * True if we have a pending unexpired BROADCAST_TIMEOUT_MSG posted to our handler.
+ */
+ private boolean mPendingBroadcastTimeoutMessage;
+
+ /**
* Intent broadcast that we have tried to start, but are
* waiting for its application's process to be created. We only
* need one (instead of a list) because we always process broadcasts
@@ -780,9 +798,14 @@ public final class ActivityManagerService extends ActivityManagerNative
boolean mDidAppSwitch;
/**
- * Last time (in realtime) at which we checked for wake lock usage.
+ * Last time (in realtime) at which we checked for power usage.
+ */
+ long mLastPowerCheckRealtime;
+
+ /**
+ * Last time (in uptime) at which we checked for power usage.
*/
- long mLastWakeLockCheckTime;
+ long mLastPowerCheckUptime;
/**
* Set while we are wanting to sleep, to prevent any
@@ -1053,17 +1076,8 @@ public final class ActivityManagerService extends ActivityManagerNative
processNextBroadcast(true);
} break;
case BROADCAST_TIMEOUT_MSG: {
- if (mDidDexOpt) {
- mDidDexOpt = false;
- Message nmsg = mHandler.obtainMessage(BROADCAST_TIMEOUT_MSG);
- mHandler.sendMessageDelayed(nmsg, BROADCAST_TIMEOUT);
- return;
- }
- // Only process broadcast timeouts if the system is ready. That way
- // PRE_BOOT_COMPLETED broadcasts can't timeout as they are intended
- // to do heavy lifting for system up
- if (mProcessesReady) {
- broadcastTimeout();
+ synchronized (ActivityManagerService.this) {
+ broadcastTimeoutLocked(true);
}
} break;
case SERVICE_TIMEOUT_MSG: {
@@ -1195,12 +1209,10 @@ public final class ActivityManagerService extends ActivityManagerNative
} break;
case CHECK_EXCESSIVE_WAKE_LOCKS_MSG: {
synchronized (ActivityManagerService.this) {
- checkExcessiveWakeLocksLocked(true);
+ checkExcessivePowerUsageLocked(true);
removeMessages(CHECK_EXCESSIVE_WAKE_LOCKS_MSG);
- if (mSleeping) {
- Message nmsg = obtainMessage(CHECK_EXCESSIVE_WAKE_LOCKS_MSG);
- sendMessageDelayed(nmsg, WAKE_LOCK_CHECK_DELAY);
- }
+ Message nmsg = obtainMessage(CHECK_EXCESSIVE_WAKE_LOCKS_MSG);
+ sendMessageDelayed(nmsg, POWER_CHECK_DELAY);
}
} break;
}
@@ -1395,7 +1407,8 @@ public final class ActivityManagerService extends ActivityManagerNative
systemDir, "batterystats.bin").toString());
mBatteryStatsService.getActiveStatistics().readLocked();
mBatteryStatsService.getActiveStatistics().writeAsyncLocked();
- mOnBattery = mBatteryStatsService.getActiveStatistics().getIsOnBattery();
+ mOnBattery = DEBUG_POWER ? true
+ : mBatteryStatsService.getActiveStatistics().getIsOnBattery();
mBatteryStatsService.getActiveStatistics().setCallback(this);
mUsageStatsService = new UsageStatsService(new File(
@@ -1515,10 +1528,12 @@ public final class ActivityManagerService extends ActivityManagerNative
int perc = bstats.startAddingCpuLocked();
int totalUTime = 0;
int totalSTime = 0;
- final int N = mProcessStats.countWorkingStats();
+ final int N = mProcessStats.countStats();
for (int i=0; i<N; i++) {
- ProcessStats.Stats st
- = mProcessStats.getWorkingStats(i);
+ ProcessStats.Stats st = mProcessStats.getStats(i);
+ if (!st.working) {
+ continue;
+ }
ProcessRecord pr = mPidsSelfLocked.get(st.pid);
int otherUTime = (st.rel_utime*perc)/100;
int otherSTime = (st.rel_stime*perc)/100;
@@ -1529,6 +1544,7 @@ public final class ActivityManagerService extends ActivityManagerNative
ps.addCpuTimeLocked(st.rel_utime-otherUTime,
st.rel_stime-otherSTime);
ps.addSpeedStepTimes(cpuSpeedTimes);
+ pr.curCpuTime += (st.rel_utime+st.rel_stime) * 10;
} else {
BatteryStatsImpl.Uid.Proc ps =
bstats.getProcessStatsLocked(st.name, st.pid);
@@ -1565,7 +1581,7 @@ public final class ActivityManagerService extends ActivityManagerNative
updateCpuStatsNow();
synchronized (this) {
synchronized(mPidsSelfLocked) {
- mOnBattery = onBattery;
+ mOnBattery = DEBUG_POWER ? true : onBattery;
}
}
}
@@ -2790,11 +2806,36 @@ public final class ActivityManagerService extends ActivityManagerNative
}
}
+ private final class AppNotResponding implements Runnable {
+ private final ProcessRecord mApp;
+ private final String mAnnotation;
+
+ public AppNotResponding(ProcessRecord app, String annotation) {
+ mApp = app;
+ mAnnotation = annotation;
+ }
+
+ @Override
+ public void run() {
+ appNotResponding(mApp, null, null, mAnnotation);
+ }
+ }
+
final void appNotResponding(ProcessRecord app, ActivityRecord activity,
ActivityRecord parent, final String annotation) {
ArrayList<Integer> firstPids = new ArrayList<Integer>(5);
SparseArray<Boolean> lastPids = new SparseArray<Boolean>(20);
+ if (mController != null) {
+ try {
+ // 0 == continue, -1 = kill process immediately
+ int res = mController.appEarlyNotResponding(app.processName, app.pid, annotation);
+ if (res < 0 && app.pid != MY_PID) Process.killProcess(app.pid);
+ } catch (RemoteException e) {
+ mController = null;
+ }
+ }
+
long anrTime = SystemClock.uptimeMillis();
if (MONITOR_CPU_USAGE) {
updateCpuStatsNow();
@@ -2845,10 +2886,6 @@ public final class ActivityManagerService extends ActivityManagerNative
}
}
- final ProcessStats processStats = new ProcessStats(true);
-
- File tracesFile = dumpStackTraces(true, firstPids, processStats, lastPids);
-
// Log the ANR to the main log.
StringBuilder info = mStringBuilder;
info.setLength(0);
@@ -2864,6 +2901,10 @@ public final class ActivityManagerService extends ActivityManagerNative
info.append("Parent: ").append(parent.shortComponentName).append("\n");
}
+ final ProcessStats processStats = new ProcessStats(true);
+
+ File tracesFile = dumpStackTraces(true, firstPids, processStats, lastPids);
+
String cpuInfo = null;
if (MONITOR_CPU_USAGE) {
updateCpuStatsNow();
@@ -3648,7 +3689,7 @@ public final class ActivityManagerService extends ActivityManagerNative
Slog.w(TAG, "Exception in new application when starting receiver "
+ br.curComponent.flattenToShortString(), e);
badApp = true;
- logBroadcastReceiverDiscard(br);
+ logBroadcastReceiverDiscardLocked(br);
finishReceiverLocked(br.receiver, br.resultCode, br.resultData,
br.resultExtras, br.resultAbort, true);
scheduleBroadcastsLocked();
@@ -3742,7 +3783,7 @@ public final class ActivityManagerService extends ActivityManagerNative
if (mFactoryTest != SystemServer.FACTORY_TEST_LOW_LEVEL) {
// Start looking for apps that are abusing wake locks.
Message nmsg = mHandler.obtainMessage(CHECK_EXCESSIVE_WAKE_LOCKS_MSG);
- mHandler.sendMessageDelayed(nmsg, WAKE_LOCK_CHECK_DELAY);
+ mHandler.sendMessageDelayed(nmsg, POWER_CHECK_DELAY);
// Tell anyone interested that we are done booting!
SystemProperties.set("sys.boot_completed", "1");
broadcastIntentLocked(null, null,
@@ -5655,10 +5696,10 @@ public final class ActivityManagerService extends ActivityManagerNative
}
// Initialize the wake times of all processes.
- checkExcessiveWakeLocksLocked(false);
+ checkExcessivePowerUsageLocked(false);
mHandler.removeMessages(CHECK_EXCESSIVE_WAKE_LOCKS_MSG);
Message nmsg = mHandler.obtainMessage(CHECK_EXCESSIVE_WAKE_LOCKS_MSG);
- mHandler.sendMessageDelayed(nmsg, WAKE_LOCK_CHECK_DELAY);
+ mHandler.sendMessageDelayed(nmsg, POWER_CHECK_DELAY);
}
}
@@ -5708,7 +5749,6 @@ public final class ActivityManagerService extends ActivityManagerNative
mWindowManager.setEventDispatching(true);
mSleeping = false;
mMainStack.resumeTopActivityLocked(null);
- mHandler.removeMessages(CHECK_EXCESSIVE_WAKE_LOCKS_MSG);
}
}
@@ -6377,7 +6417,7 @@ public final class ActivityManagerService extends ActivityManagerNative
// The current broadcast is waiting for this app's receiver
// to be finished. Looks like that's not going to happen, so
// let the broadcast continue.
- logBroadcastReceiverDiscard(r);
+ logBroadcastReceiverDiscardLocked(r);
finishReceiverLocked(r.receiver, r.resultCode, r.resultData,
r.resultExtras, r.resultAbort, true);
reschedule = true;
@@ -6386,7 +6426,7 @@ public final class ActivityManagerService extends ActivityManagerNative
if (r != null && r.curApp == app) {
if (DEBUG_BROADCAST) Slog.v(TAG,
"skip & discard pending app " + r);
- logBroadcastReceiverDiscard(r);
+ logBroadcastReceiverDiscardLocked(r);
finishReceiverLocked(r.receiver, r.resultCode, r.resultData,
r.resultExtras, r.resultAbort, true);
reschedule = true;
@@ -7055,12 +7095,13 @@ public final class ActivityManagerService extends ActivityManagerNative
pw.println("Activity manager dump options:");
pw.println(" [-a] [-h] [cmd] ...");
pw.println(" cmd may be one of:");
- pw.println(" activities: activity stack state");
- pw.println(" broadcasts: broadcast state");
- pw.println(" intents: pending intent state");
- pw.println(" processes: process state");
- pw.println(" providers: content provider state");
- pw.println(" services: service state");
+ pw.println(" a[ctivities]: activity stack state");
+ pw.println(" b[roadcasts]: broadcast state");
+ pw.println(" i[ntents]: pending intent state");
+ pw.println(" p[rocesses]: process state");
+ pw.println(" o[om]: out of memory management");
+ pw.println(" prov[iders]: content provider state");
+ pw.println(" s[ervices]: service state");
pw.println(" service [name]: service client-side state");
return;
} else {
@@ -7092,6 +7133,11 @@ public final class ActivityManagerService extends ActivityManagerNative
dumpProcessesLocked(fd, pw, args, opti, true);
}
return;
+ } else if ("oom".equals(cmd) || "o".equals(cmd)) {
+ synchronized (this) {
+ dumpOomLocked(fd, pw, args, opti, true);
+ }
+ return;
} else if ("providers".equals(cmd) || "prov".equals(cmd)) {
synchronized (this) {
dumpProvidersLocked(fd, pw, args, opti, true);
@@ -7213,7 +7259,7 @@ public final class ActivityManagerService extends ActivityManagerNative
return true;
}
-
+
boolean dumpProcessesLocked(FileDescriptor fd, PrintWriter pw, String[] args,
int opti, boolean dumpAll) {
boolean needSep = false;
@@ -7243,8 +7289,8 @@ public final class ActivityManagerService extends ActivityManagerNative
if (needSep) pw.println(" ");
needSep = true;
pw.println(" Running processes (most recent first):");
- dumpProcessList(pw, this, mLruProcesses, " ",
- "Proc", "PERS", true);
+ dumpProcessOomList(pw, this, mLruProcesses, " ",
+ "Proc", "PERS", false);
needSep = true;
}
@@ -7275,7 +7321,7 @@ public final class ActivityManagerService extends ActivityManagerNative
needSep = true;
pw.println(" Persisent processes that are starting:");
dumpProcessList(pw, this, mPersistentStartingProcesses, " ",
- "Starting Norm", "Restarting PERS", false);
+ "Starting Norm", "Restarting PERS");
}
if (mStartingProcesses.size() > 0) {
@@ -7283,7 +7329,7 @@ public final class ActivityManagerService extends ActivityManagerNative
needSep = true;
pw.println(" Processes that are starting:");
dumpProcessList(pw, this, mStartingProcesses, " ",
- "Starting Norm", "Starting PERS", false);
+ "Starting Norm", "Starting PERS");
}
if (mRemovedProcesses.size() > 0) {
@@ -7291,7 +7337,7 @@ public final class ActivityManagerService extends ActivityManagerNative
needSep = true;
pw.println(" Processes that are being removed:");
dumpProcessList(pw, this, mRemovedProcesses, " ",
- "Removed Norm", "Removed PERS", false);
+ "Removed Norm", "Removed PERS");
}
if (mProcessesOnHold.size() > 0) {
@@ -7299,26 +7345,10 @@ public final class ActivityManagerService extends ActivityManagerNative
needSep = true;
pw.println(" Processes that are on old until the system is ready:");
dumpProcessList(pw, this, mProcessesOnHold, " ",
- "OnHold Norm", "OnHold PERS", false);
+ "OnHold Norm", "OnHold PERS");
}
- if (mProcessesToGc.size() > 0) {
- if (needSep) pw.println(" ");
- needSep = true;
- pw.println(" Processes that are waiting to GC:");
- long now = SystemClock.uptimeMillis();
- for (int i=0; i<mProcessesToGc.size(); i++) {
- ProcessRecord proc = mProcessesToGc.get(i);
- pw.print(" Process "); pw.println(proc);
- pw.print(" lowMem="); pw.print(proc.reportLowMemory);
- pw.print(", last gced=");
- pw.print(now-proc.lastRequestedGc);
- pw.print(" ms ago, last lowMem=");
- pw.print(now-proc.lastLowMemory);
- pw.println(" ms ago");
-
- }
- }
+ needSep = dumpProcessesToGc(fd, pw, args, opti, needSep, dumpAll);
if (mProcessCrashTimes.getMap().size() > 0) {
if (needSep) pw.println(" ");
@@ -7382,6 +7412,12 @@ public final class ActivityManagerService extends ActivityManagerNative
pw.println(" mBooting=" + mBooting
+ " mBooted=" + mBooted
+ " mFactoryTest=" + mFactoryTest);
+ pw.print(" mLastPowerCheckRealtime=");
+ TimeUtils.formatDuration(mLastPowerCheckRealtime, pw);
+ pw.println("");
+ pw.print(" mLastPowerCheckUptime=");
+ TimeUtils.formatDuration(mLastPowerCheckUptime, pw);
+ pw.println("");
pw.println(" mGoingToSleep=" + mMainStack.mGoingToSleep);
pw.println(" mLaunchingActivity=" + mMainStack.mLaunchingActivity);
pw.println(" mAdjSeq=" + mAdjSeq + " mLruSeq=" + mLruSeq);
@@ -7390,6 +7426,75 @@ public final class ActivityManagerService extends ActivityManagerNative
return true;
}
+ boolean dumpProcessesToGc(FileDescriptor fd, PrintWriter pw, String[] args,
+ int opti, boolean needSep, boolean dumpAll) {
+ if (mProcessesToGc.size() > 0) {
+ if (needSep) pw.println(" ");
+ needSep = true;
+ pw.println(" Processes that are waiting to GC:");
+ long now = SystemClock.uptimeMillis();
+ for (int i=0; i<mProcessesToGc.size(); i++) {
+ ProcessRecord proc = mProcessesToGc.get(i);
+ pw.print(" Process "); pw.println(proc);
+ pw.print(" lowMem="); pw.print(proc.reportLowMemory);
+ pw.print(", last gced=");
+ pw.print(now-proc.lastRequestedGc);
+ pw.print(" ms ago, last lowMem=");
+ pw.print(now-proc.lastLowMemory);
+ pw.println(" ms ago");
+
+ }
+ }
+ return needSep;
+ }
+
+ boolean dumpOomLocked(FileDescriptor fd, PrintWriter pw, String[] args,
+ int opti, boolean dumpAll) {
+ boolean needSep = false;
+
+ if (mLruProcesses.size() > 0) {
+ ArrayList<ProcessRecord> procs = new ArrayList<ProcessRecord>(mLruProcesses);
+
+ Comparator<ProcessRecord> comparator = new Comparator<ProcessRecord>() {
+ @Override
+ public int compare(ProcessRecord object1, ProcessRecord object2) {
+ if (object1.setAdj != object2.setAdj) {
+ return object1.setAdj > object2.setAdj ? -1 : 1;
+ }
+ if (object1.setSchedGroup != object2.setSchedGroup) {
+ return object1.setSchedGroup > object2.setSchedGroup ? -1 : 1;
+ }
+ if (object1.keeping != object2.keeping) {
+ return object1.keeping ? -1 : 1;
+ }
+ if (object1.pid != object2.pid) {
+ return object1.pid > object2.pid ? -1 : 1;
+ }
+ return 0;
+ }
+ };
+
+ Collections.sort(procs, comparator);
+
+ if (needSep) pw.println(" ");
+ needSep = true;
+ pw.println(" Process OOM control:");
+ dumpProcessOomList(pw, this, procs, " ",
+ "Proc", "PERS", true);
+ needSep = true;
+ }
+
+ needSep = dumpProcessesToGc(fd, pw, args, opti, needSep, dumpAll);
+
+ pw.println(" ");
+ pw.println(" mHomeProcess: " + mHomeProcess);
+ if (mHeavyWeightProcess != null) {
+ pw.println(" mHeavyWeightProcess: " + mHeavyWeightProcess);
+ }
+
+ return true;
+ }
+
/**
* There are three ways to call this:
* - no service specified: dump all the services
@@ -7833,89 +7938,145 @@ public final class ActivityManagerService extends ActivityManagerNative
private static final int dumpProcessList(PrintWriter pw,
ActivityManagerService service, List list,
- String prefix, String normalLabel, String persistentLabel,
- boolean inclOomAdj) {
+ String prefix, String normalLabel, String persistentLabel) {
int numPers = 0;
final int N = list.size()-1;
for (int i=N; i>=0; i--) {
ProcessRecord r = (ProcessRecord)list.get(i);
- if (false) {
- pw.println(prefix + (r.persistent ? persistentLabel : normalLabel)
- + " #" + i + ":");
- r.dump(pw, prefix + " ");
- } else if (inclOomAdj) {
- String oomAdj;
- if (r.setAdj >= EMPTY_APP_ADJ) {
- oomAdj = buildOomTag("empty", null, r.setAdj, EMPTY_APP_ADJ);
- } else if (r.setAdj >= HIDDEN_APP_MIN_ADJ) {
- oomAdj = buildOomTag("bak", " ", r.setAdj, HIDDEN_APP_MIN_ADJ);
- } else if (r.setAdj >= HOME_APP_ADJ) {
- oomAdj = buildOomTag("home ", null, r.setAdj, HOME_APP_ADJ);
- } else if (r.setAdj >= SECONDARY_SERVER_ADJ) {
- oomAdj = buildOomTag("svc", " ", r.setAdj, SECONDARY_SERVER_ADJ);
- } else if (r.setAdj >= BACKUP_APP_ADJ) {
- oomAdj = buildOomTag("bckup", null, r.setAdj, BACKUP_APP_ADJ);
- } else if (r.setAdj >= HEAVY_WEIGHT_APP_ADJ) {
- oomAdj = buildOomTag("hvy ", null, r.setAdj, HEAVY_WEIGHT_APP_ADJ);
- } else if (r.setAdj >= PERCEPTIBLE_APP_ADJ) {
- oomAdj = buildOomTag("prcp ", null, r.setAdj, PERCEPTIBLE_APP_ADJ);
- } else if (r.setAdj >= VISIBLE_APP_ADJ) {
- oomAdj = buildOomTag("vis ", null, r.setAdj, VISIBLE_APP_ADJ);
- } else if (r.setAdj >= FOREGROUND_APP_ADJ) {
- oomAdj = buildOomTag("fore ", null, r.setAdj, FOREGROUND_APP_ADJ);
- } else if (r.setAdj >= CORE_SERVER_ADJ) {
- oomAdj = buildOomTag("core ", null, r.setAdj, CORE_SERVER_ADJ);
- } else if (r.setAdj >= SYSTEM_ADJ) {
- oomAdj = buildOomTag("sys ", null, r.setAdj, SYSTEM_ADJ);
+ pw.println(String.format("%s%s #%2d: %s",
+ prefix, (r.persistent ? persistentLabel : normalLabel),
+ i, r.toString()));
+ if (r.persistent) {
+ numPers++;
+ }
+ }
+ return numPers;
+ }
+
+ private static final void dumpProcessOomList(PrintWriter pw,
+ ActivityManagerService service, List<ProcessRecord> list,
+ String prefix, String normalLabel, String persistentLabel,
+ boolean inclDetails) {
+
+ final long curRealtime = SystemClock.elapsedRealtime();
+ final long realtimeSince = curRealtime - service.mLastPowerCheckRealtime;
+ final long curUptime = SystemClock.uptimeMillis();
+ final long uptimeSince = curUptime - service.mLastPowerCheckUptime;
+
+ final int N = list.size()-1;
+ for (int i=N; i>=0; i--) {
+ ProcessRecord r = list.get(i);
+ String oomAdj;
+ if (r.setAdj >= EMPTY_APP_ADJ) {
+ oomAdj = buildOomTag("empty", null, r.setAdj, EMPTY_APP_ADJ);
+ } else if (r.setAdj >= HIDDEN_APP_MIN_ADJ) {
+ oomAdj = buildOomTag("bak", " ", r.setAdj, HIDDEN_APP_MIN_ADJ);
+ } else if (r.setAdj >= HOME_APP_ADJ) {
+ oomAdj = buildOomTag("home ", null, r.setAdj, HOME_APP_ADJ);
+ } else if (r.setAdj >= SECONDARY_SERVER_ADJ) {
+ oomAdj = buildOomTag("svc", " ", r.setAdj, SECONDARY_SERVER_ADJ);
+ } else if (r.setAdj >= BACKUP_APP_ADJ) {
+ oomAdj = buildOomTag("bckup", null, r.setAdj, BACKUP_APP_ADJ);
+ } else if (r.setAdj >= HEAVY_WEIGHT_APP_ADJ) {
+ oomAdj = buildOomTag("hvy ", null, r.setAdj, HEAVY_WEIGHT_APP_ADJ);
+ } else if (r.setAdj >= PERCEPTIBLE_APP_ADJ) {
+ oomAdj = buildOomTag("prcp ", null, r.setAdj, PERCEPTIBLE_APP_ADJ);
+ } else if (r.setAdj >= VISIBLE_APP_ADJ) {
+ oomAdj = buildOomTag("vis ", null, r.setAdj, VISIBLE_APP_ADJ);
+ } else if (r.setAdj >= FOREGROUND_APP_ADJ) {
+ oomAdj = buildOomTag("fore ", null, r.setAdj, FOREGROUND_APP_ADJ);
+ } else if (r.setAdj >= CORE_SERVER_ADJ) {
+ oomAdj = buildOomTag("core ", null, r.setAdj, CORE_SERVER_ADJ);
+ } else if (r.setAdj >= SYSTEM_ADJ) {
+ oomAdj = buildOomTag("sys ", null, r.setAdj, SYSTEM_ADJ);
+ } else {
+ oomAdj = Integer.toString(r.setAdj);
+ }
+ String schedGroup;
+ switch (r.setSchedGroup) {
+ case Process.THREAD_GROUP_BG_NONINTERACTIVE:
+ schedGroup = "B";
+ break;
+ case Process.THREAD_GROUP_DEFAULT:
+ schedGroup = "F";
+ break;
+ default:
+ schedGroup = Integer.toString(r.setSchedGroup);
+ break;
+ }
+ pw.println(String.format("%s%s #%2d: adj=%s/%s %s (%s)",
+ prefix, (r.persistent ? persistentLabel : normalLabel),
+ N-i, oomAdj, schedGroup, r.toShortString(), r.adjType));
+ if (r.adjSource != null || r.adjTarget != null) {
+ pw.print(prefix);
+ pw.print(" ");
+ if (r.adjTarget instanceof ComponentName) {
+ pw.print(((ComponentName)r.adjTarget).flattenToShortString());
+ } else if (r.adjTarget != null) {
+ pw.print(r.adjTarget.toString());
} else {
- oomAdj = Integer.toString(r.setAdj);
- }
- String schedGroup;
- switch (r.setSchedGroup) {
- case Process.THREAD_GROUP_BG_NONINTERACTIVE:
- schedGroup = "B";
- break;
- case Process.THREAD_GROUP_DEFAULT:
- schedGroup = "F";
- break;
- default:
- schedGroup = Integer.toString(r.setSchedGroup);
- break;
+ pw.print("{null}");
+ }
+ pw.print("<=");
+ if (r.adjSource instanceof ProcessRecord) {
+ pw.print("Proc{");
+ pw.print(((ProcessRecord)r.adjSource).toShortString());
+ pw.println("}");
+ } else if (r.adjSource != null) {
+ pw.println(r.adjSource.toString());
+ } else {
+ pw.println("{null}");
}
- pw.println(String.format("%s%s #%2d: adj=%s/%s %s (%s)",
- prefix, (r.persistent ? persistentLabel : normalLabel),
- N-i, oomAdj, schedGroup, r.toShortString(), r.adjType));
- if (r.adjSource != null || r.adjTarget != null) {
- pw.print(prefix);
- pw.print(" ");
- if (r.adjTarget instanceof ComponentName) {
- pw.print(((ComponentName)r.adjTarget).flattenToShortString());
- } else if (r.adjTarget != null) {
- pw.print(r.adjTarget.toString());
- } else {
- pw.print("{null}");
- }
- pw.print("<=");
- if (r.adjSource instanceof ProcessRecord) {
- pw.print("Proc{");
- pw.print(((ProcessRecord)r.adjSource).toShortString());
- pw.println("}");
- } else if (r.adjSource != null) {
- pw.println(r.adjSource.toString());
- } else {
- pw.println("{null}");
+ }
+ if (inclDetails) {
+ pw.print(prefix);
+ pw.print(" ");
+ pw.print("oom: max="); pw.print(r.maxAdj);
+ pw.print(" hidden="); pw.print(r.hiddenAdj);
+ pw.print(" curRaw="); pw.print(r.curRawAdj);
+ pw.print(" setRaw="); pw.print(r.setRawAdj);
+ pw.print(" cur="); pw.print(r.curAdj);
+ pw.print(" set="); pw.println(r.setAdj);
+ pw.print(prefix);
+ pw.print(" ");
+ pw.print("keeping="); pw.print(r.keeping);
+ pw.print(" hidden="); pw.print(r.hidden);
+ pw.print(" empty="); pw.println(r.empty);
+
+ if (!r.keeping) {
+ if (r.lastWakeTime != 0) {
+ long wtime;
+ BatteryStatsImpl stats = service.mBatteryStatsService.getActiveStatistics();
+ synchronized (stats) {
+ wtime = stats.getProcessWakeTime(r.info.uid,
+ r.pid, curRealtime);
+ }
+ long timeUsed = wtime - r.lastWakeTime;
+ pw.print(prefix);
+ pw.print(" ");
+ pw.print("keep awake over ");
+ TimeUtils.formatDuration(realtimeSince, pw);
+ pw.print(" used ");
+ TimeUtils.formatDuration(timeUsed, pw);
+ pw.print(" (");
+ pw.print((timeUsed*100)/realtimeSince);
+ pw.println("%)");
+ }
+ if (r.lastCpuTime != 0) {
+ long timeUsed = r.curCpuTime - r.lastCpuTime;
+ pw.print(prefix);
+ pw.print(" ");
+ pw.print("run cpu over ");
+ TimeUtils.formatDuration(uptimeSince, pw);
+ pw.print(" used ");
+ TimeUtils.formatDuration(timeUsed, pw);
+ pw.print(" (");
+ pw.print((timeUsed*100)/uptimeSince);
+ pw.println("%)");
}
}
- } else {
- pw.println(String.format("%s%s #%2d: %s",
- prefix, (r.persistent ? persistentLabel : normalLabel),
- i, r.toString()));
- }
- if (r.persistent) {
- numPers++;
}
}
- return numPers;
}
static final void dumpApplicationMemoryUsage(FileDescriptor fd,
@@ -8544,7 +8705,11 @@ public final class ActivityManagerService extends ActivityManagerNative
return null;
}
- private final void bumpServiceExecutingLocked(ServiceRecord r) {
+ private final void bumpServiceExecutingLocked(ServiceRecord r, String why) {
+ if (DEBUG_SERVICE) Log.v(TAG, ">>> EXECUTING "
+ + why + " of " + r + " in app " + r.app);
+ 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) {
@@ -8582,8 +8747,7 @@ public final class ActivityManagerService extends ActivityManagerNative
grantUriPermissionUncheckedFromIntentLocked(si.targetPermissionUid,
r.packageName, si.intent, si.getUriPermissionsLocked());
}
- if (DEBUG_SERVICE) Slog.v(TAG, ">>> EXECUTING start of " + r);
- bumpServiceExecutingLocked(r);
+ bumpServiceExecutingLocked(r, "start");
if (!oomAdjusted) {
oomAdjusted = true;
updateOomAdjLocked(r.app);
@@ -8616,9 +8780,7 @@ public final class ActivityManagerService extends ActivityManagerNative
}
if ((!i.requested || rebind) && i.apps.size() > 0) {
try {
- if (DEBUG_SERVICE) Slog.v(TAG, ">>> EXECUTING bind of " + r
- + " in " + i + ": shouldUnbind=" + i.hasBound);
- bumpServiceExecutingLocked(r);
+ bumpServiceExecutingLocked(r, "bind");
r.app.thread.scheduleBindService(r, i.intent.getIntent(), rebind);
if (!rebind) {
i.requested = true;
@@ -8653,8 +8815,7 @@ public final class ActivityManagerService extends ActivityManagerNative
r.restartTime = r.lastActivity = SystemClock.uptimeMillis();
app.services.add(r);
- if (DEBUG_SERVICE) Slog.v(TAG, ">>> EXECUTING create of " + r + " " + r.intent);
- bumpServiceExecutingLocked(r);
+ bumpServiceExecutingLocked(r, "create");
updateLruProcessLocked(app, true, true);
boolean created = false;
@@ -8906,9 +9067,7 @@ public final class ActivityManagerService extends ActivityManagerNative
+ ": hasBound=" + ibr.hasBound);
if (r.app != null && r.app.thread != null && ibr.hasBound) {
try {
- if (DEBUG_SERVICE) Slog.v(TAG, ">>> EXECUTING bring down unbind of " + r
- + " for " + ibr);
- bumpServiceExecutingLocked(r);
+ bumpServiceExecutingLocked(r, "bring down unbind");
updateOomAdjLocked(r.app);
ibr.hasBound = false;
r.app.thread.scheduleUnbindService(r,
@@ -8959,12 +9118,7 @@ public final class ActivityManagerService extends ActivityManagerNative
r.app.services.remove(r);
if (r.app.thread != null) {
try {
- if (DEBUG_SERVICE) {
- RuntimeException here = new RuntimeException();
- here.fillInStackTrace();
- Slog.v(TAG, ">>> EXECUTING stop of " + r, here);
- }
- bumpServiceExecutingLocked(r);
+ bumpServiceExecutingLocked(r, "stop");
mStoppingServices.add(r);
updateOomAdjLocked(r.app);
r.app.thread.scheduleStopService(r);
@@ -9420,9 +9574,7 @@ public final class ActivityManagerService extends ActivityManagerNative
if (s.app != null && s.app.thread != null && b.intent.apps.size() == 0
&& b.intent.hasBound) {
try {
- if (DEBUG_SERVICE) Slog.v(TAG, ">>> EXECUTING unbind of " + s
- + " from " + b);
- bumpServiceExecutingLocked(s);
+ bumpServiceExecutingLocked(s, "unbind");
updateOomAdjLocked(s.app);
b.intent.hasBound = false;
// Assume the client doesn't want to know about a rebind;
@@ -9643,14 +9795,20 @@ public final class ActivityManagerService extends ActivityManagerNative
if (DEBUG_SERVICE) Slog.v(TAG, "<<< DONE EXECUTING " + r
+ ": nesting=" + r.executeNesting
+ ", 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);
mHandler.removeMessages(SERVICE_TIMEOUT_MSG, r.app);
}
if (inStopping) {
- if (DEBUG_SERVICE) Slog.v(TAG, "doneExecuting remove stopping " + r);
+ if (DEBUG_SERVICE) Slog.v(TAG,
+ "doneExecuting remove stopping " + r);
mStoppingServices.remove(r);
}
updateOomAdjLocked(r.app);
@@ -9760,20 +9918,20 @@ public final class ActivityManagerService extends ActivityManagerNative
Slog.e(TAG, "Backup agent created for " + agentPackageName + " but not requested!");
return;
}
+ }
- long oldIdent = Binder.clearCallingIdentity();
- try {
- IBackupManager bm = IBackupManager.Stub.asInterface(
- ServiceManager.getService(Context.BACKUP_SERVICE));
- bm.agentConnected(agentPackageName, agent);
- } catch (RemoteException e) {
- // can't happen; the backup manager service is local
- } catch (Exception e) {
- Slog.w(TAG, "Exception trying to deliver BackupAgent binding: ");
- e.printStackTrace();
- } finally {
- Binder.restoreCallingIdentity(oldIdent);
- }
+ long oldIdent = Binder.clearCallingIdentity();
+ try {
+ IBackupManager bm = IBackupManager.Stub.asInterface(
+ ServiceManager.getService(Context.BACKUP_SERVICE));
+ bm.agentConnected(agentPackageName, agent);
+ } catch (RemoteException e) {
+ // can't happen; the backup manager service is local
+ } catch (Exception e) {
+ Slog.w(TAG, "Exception trying to deliver BackupAgent binding: ");
+ e.printStackTrace();
+ } finally {
+ Binder.restoreCallingIdentity(oldIdent);
}
}
@@ -10486,7 +10644,7 @@ public final class ActivityManagerService extends ActivityManagerNative
Binder.restoreCallingIdentity(origId);
}
- private final void logBroadcastReceiverDiscard(BroadcastRecord r) {
+ private final void logBroadcastReceiverDiscardLocked(BroadcastRecord r) {
if (r.nextReceiver > 0) {
Object curReceiver = r.receivers.get(r.nextReceiver-1);
if (curReceiver instanceof BroadcastFilter) {
@@ -10514,67 +10672,108 @@ public final class ActivityManagerService extends ActivityManagerNative
}
}
- private final void broadcastTimeout() {
- ProcessRecord app = null;
- String anrMessage = null;
+ private final void setBroadcastTimeoutLocked(long timeoutTime) {
+ if (! mPendingBroadcastTimeoutMessage) {
+ Message msg = mHandler.obtainMessage(BROADCAST_TIMEOUT_MSG);
+ mHandler.sendMessageAtTime(msg, timeoutTime);
+ mPendingBroadcastTimeoutMessage = true;
+ }
+ }
- synchronized (this) {
- if (mOrderedBroadcasts.size() == 0) {
+ private final void cancelBroadcastTimeoutLocked() {
+ if (mPendingBroadcastTimeoutMessage) {
+ mHandler.removeMessages(BROADCAST_TIMEOUT_MSG);
+ mPendingBroadcastTimeoutMessage = false;
+ }
+ }
+
+ private final void broadcastTimeoutLocked(boolean fromMsg) {
+ if (fromMsg) {
+ mPendingBroadcastTimeoutMessage = false;
+ }
+
+ if (mOrderedBroadcasts.size() == 0) {
+ return;
+ }
+
+ long now = SystemClock.uptimeMillis();
+ BroadcastRecord r = mOrderedBroadcasts.get(0);
+ if (fromMsg) {
+ if (mDidDexOpt) {
+ // Delay timeouts until dexopt finishes.
+ mDidDexOpt = false;
+ long timeoutTime = SystemClock.uptimeMillis() + BROADCAST_TIMEOUT;
+ setBroadcastTimeoutLocked(timeoutTime);
return;
}
- long now = SystemClock.uptimeMillis();
- BroadcastRecord r = mOrderedBroadcasts.get(0);
- if ((r.receiverTime+BROADCAST_TIMEOUT) > now) {
+ if (! mProcessesReady) {
+ // Only process broadcast timeouts if the system is ready. That way
+ // PRE_BOOT_COMPLETED broadcasts can't timeout as they are intended
+ // to do heavy lifting for system up.
+ return;
+ }
+
+ long timeoutTime = r.receiverTime + BROADCAST_TIMEOUT;
+ if (timeoutTime > now) {
+ // We can observe premature timeouts because we do not cancel and reset the
+ // broadcast timeout message after each receiver finishes. Instead, we set up
+ // an initial timeout then kick it down the road a little further as needed
+ // when it expires.
if (DEBUG_BROADCAST) Slog.v(TAG,
"Premature timeout @ " + now + ": resetting BROADCAST_TIMEOUT_MSG for "
- + (r.receiverTime + BROADCAST_TIMEOUT));
- Message msg = mHandler.obtainMessage(BROADCAST_TIMEOUT_MSG);
- mHandler.sendMessageAtTime(msg, r.receiverTime+BROADCAST_TIMEOUT);
+ + timeoutTime);
+ setBroadcastTimeoutLocked(timeoutTime);
return;
}
+ }
- Slog.w(TAG, "Timeout of broadcast " + r + " - receiver=" + r.receiver);
- r.receiverTime = now;
- r.anrCount++;
+ Slog.w(TAG, "Timeout of broadcast " + r + " - receiver=" + r.receiver
+ + ", started " + (now - r.receiverTime) + "ms ago");
+ r.receiverTime = now;
+ r.anrCount++;
- // Current receiver has passed its expiration date.
- if (r.nextReceiver <= 0) {
- Slog.w(TAG, "Timeout on receiver with nextReceiver <= 0");
- return;
- }
+ // Current receiver has passed its expiration date.
+ if (r.nextReceiver <= 0) {
+ Slog.w(TAG, "Timeout on receiver with nextReceiver <= 0");
+ return;
+ }
- Object curReceiver = r.receivers.get(r.nextReceiver-1);
- Slog.w(TAG, "Receiver during timeout: " + curReceiver);
- logBroadcastReceiverDiscard(r);
- if (curReceiver instanceof BroadcastFilter) {
- BroadcastFilter bf = (BroadcastFilter)curReceiver;
- if (bf.receiverList.pid != 0
- && bf.receiverList.pid != MY_PID) {
- synchronized (this.mPidsSelfLocked) {
- app = this.mPidsSelfLocked.get(
- bf.receiverList.pid);
- }
- }
- } else {
- app = r.curApp;
- }
-
- if (app != null) {
- anrMessage = "Broadcast of " + r.intent.toString();
- }
+ ProcessRecord app = null;
+ String anrMessage = null;
- if (mPendingBroadcast == r) {
- mPendingBroadcast = null;
+ Object curReceiver = r.receivers.get(r.nextReceiver-1);
+ Slog.w(TAG, "Receiver during timeout: " + curReceiver);
+ logBroadcastReceiverDiscardLocked(r);
+ if (curReceiver instanceof BroadcastFilter) {
+ BroadcastFilter bf = (BroadcastFilter)curReceiver;
+ if (bf.receiverList.pid != 0
+ && bf.receiverList.pid != MY_PID) {
+ synchronized (this.mPidsSelfLocked) {
+ app = this.mPidsSelfLocked.get(
+ bf.receiverList.pid);
+ }
}
-
- // Move on to the next receiver.
- finishReceiverLocked(r.receiver, r.resultCode, r.resultData,
- r.resultExtras, r.resultAbort, true);
- scheduleBroadcastsLocked();
+ } else {
+ app = r.curApp;
}
+ if (app != null) {
+ anrMessage = "Broadcast of " + r.intent.toString();
+ }
+
+ if (mPendingBroadcast == r) {
+ mPendingBroadcast = null;
+ }
+
+ // Move on to the next receiver.
+ finishReceiverLocked(r.receiver, r.resultCode, r.resultData,
+ r.resultExtras, r.resultAbort, true);
+ scheduleBroadcastsLocked();
+
if (anrMessage != null) {
- appNotResponding(app, null, null, anrMessage);
+ // Post the ANR to the handler since we do not want to process ANRs while
+ // potentially holding our lock.
+ mHandler.post(new AppNotResponding(app, anrMessage));
}
}
@@ -10616,9 +10815,10 @@ public final class ActivityManagerService extends ActivityManagerNative
}
- static void performReceive(ProcessRecord app, IIntentReceiver receiver,
+ static void performReceiveLocked(ProcessRecord app, IIntentReceiver receiver,
Intent intent, int resultCode, String data, Bundle extras,
boolean ordered, boolean sticky) throws RemoteException {
+ // Send the intent to the receiver asynchronously using one-way binder calls.
if (app != null && app.thread != null) {
// If we have an app thread, do the call through that so it is
// correctly ordered with other one-way calls.
@@ -10629,7 +10829,7 @@ public final class ActivityManagerService extends ActivityManagerNative
}
}
- private final void deliverToRegisteredReceiver(BroadcastRecord r,
+ private final void deliverToRegisteredReceiverLocked(BroadcastRecord r,
BroadcastFilter filter, boolean ordered) {
boolean skip = false;
if (filter.requiredPermission != null) {
@@ -10687,7 +10887,7 @@ public final class ActivityManagerService extends ActivityManagerNative
Slog.i(TAG, "Delivering to " + filter
+ " (seq=" + seq + "): " + r);
}
- performReceive(filter.receiverList.app, filter.receiverList.receiver,
+ performReceiveLocked(filter.receiverList.app, filter.receiverList.receiver,
new Intent(r.intent), r.resultCode,
r.resultData, r.resultExtras, r.ordered, r.initialSticky);
if (ordered) {
@@ -10744,7 +10944,7 @@ public final class ActivityManagerService extends ActivityManagerNative
if (DEBUG_BROADCAST) Slog.v(TAG,
"Delivering non-ordered to registered "
+ target + ": " + r);
- deliverToRegisteredReceiver(r, (BroadcastFilter)target, false);
+ deliverToRegisteredReceiverLocked(r, (BroadcastFilter)target, false);
}
addBroadcastToHistoryLocked(r);
if (DEBUG_BROADCAST_LIGHT) Slog.v(TAG, "Done with parallel broadcast "
@@ -10800,7 +11000,7 @@ public final class ActivityManagerService extends ActivityManagerNative
// and continue to make progress.
//
// This is only done if the system is ready so that PRE_BOOT_COMPLETED
- // receivers don't get executed with with timeouts. They're intended for
+ // receivers don't get executed with timeouts. They're intended for
// one time heavy lifting after system upgrades and can take
// significant amounts of time.
int numReceivers = (r.receivers != null) ? r.receivers.size() : 0;
@@ -10816,7 +11016,7 @@ public final class ActivityManagerService extends ActivityManagerNative
+ " numReceivers=" + numReceivers
+ " nextReceiver=" + r.nextReceiver
+ " state=" + r.state);
- broadcastTimeout(); // forcibly finish this broadcast
+ broadcastTimeoutLocked(false); // forcibly finish this broadcast
forceReceive = true;
r.state = BroadcastRecord.IDLE;
}
@@ -10840,7 +11040,7 @@ public final class ActivityManagerService extends ActivityManagerNative
Slog.i(TAG, "Finishing broadcast " + r.intent.getAction()
+ " seq=" + seq + " app=" + r.callerApp);
}
- performReceive(r.callerApp, r.resultTo,
+ performReceiveLocked(r.callerApp, r.resultTo,
new Intent(r.intent), r.resultCode,
r.resultData, r.resultExtras, false, false);
} catch (RemoteException e) {
@@ -10849,7 +11049,7 @@ public final class ActivityManagerService extends ActivityManagerNative
}
if (DEBUG_BROADCAST) Slog.v(TAG, "Cancelling BROADCAST_TIMEOUT_MSG");
- mHandler.removeMessages(BROADCAST_TIMEOUT_MSG);
+ cancelBroadcastTimeoutLocked();
if (DEBUG_BROADCAST_LIGHT) Slog.v(TAG, "Finished with ordered broadcast "
+ r);
@@ -10874,11 +11074,12 @@ public final class ActivityManagerService extends ActivityManagerNative
if (DEBUG_BROADCAST_LIGHT) Slog.v(TAG, "Processing ordered broadcast "
+ r);
+ }
+ if (! mPendingBroadcastTimeoutMessage) {
+ long timeoutTime = r.receiverTime + BROADCAST_TIMEOUT;
if (DEBUG_BROADCAST) Slog.v(TAG,
- "Submitting BROADCAST_TIMEOUT_MSG for " + r + " at "
- + (r.receiverTime + BROADCAST_TIMEOUT));
- Message msg = mHandler.obtainMessage(BROADCAST_TIMEOUT_MSG);
- mHandler.sendMessageAtTime(msg, r.receiverTime+BROADCAST_TIMEOUT);
+ "Submitting BROADCAST_TIMEOUT_MSG for " + r + " at " + timeoutTime);
+ setBroadcastTimeoutLocked(timeoutTime);
}
Object nextReceiver = r.receivers.get(recIdx);
@@ -10889,7 +11090,7 @@ public final class ActivityManagerService extends ActivityManagerNative
if (DEBUG_BROADCAST) Slog.v(TAG,
"Delivering ordered to registered "
+ filter + ": " + r);
- deliverToRegisteredReceiver(r, filter, r.ordered);
+ deliverToRegisteredReceiverLocked(r, filter, r.ordered);
if (r.receiver == null || !r.ordered) {
// The receiver has already finished, so schedule to
// process the next one.
@@ -10997,7 +11198,7 @@ public final class ActivityManagerService extends ActivityManagerNative
+ info.activityInfo.applicationInfo.packageName + "/"
+ info.activityInfo.applicationInfo.uid + " for broadcast "
+ r.intent + ": process is bad");
- logBroadcastReceiverDiscard(r);
+ logBroadcastReceiverDiscardLocked(r);
finishReceiverLocked(r.receiver, r.resultCode, r.resultData,
r.resultExtras, r.resultAbort, true);
scheduleBroadcastsLocked();
@@ -11326,6 +11527,7 @@ public final class ActivityManagerService extends ActivityManagerNative
app.adjType = "fixed";
app.adjSeq = mAdjSeq;
app.curRawAdj = app.maxAdj;
+ app.keeping = true;
app.curSchedGroup = Process.THREAD_GROUP_DEFAULT;
return (app.curAdj=app.maxAdj);
}
@@ -11333,6 +11535,7 @@ public final class ActivityManagerService extends ActivityManagerNative
app.adjTypeCode = ActivityManager.RunningAppProcessInfo.REASON_UNKNOWN;
app.adjSource = null;
app.adjTarget = null;
+ app.keeping = false;
app.empty = false;
app.hidden = false;
@@ -11462,6 +11665,9 @@ public final class ActivityManagerService extends ActivityManagerNative
if (adj > SECONDARY_SERVER_ADJ) {
app.adjType = "started-bg-services";
}
+ // Don't kill this process because it is doing work; it
+ // has said it is doing work.
+ app.keeping = true;
}
if (s.connections.size() > 0 && (adj > FOREGROUND_APP_ADJ
|| schedGroup == Process.THREAD_GROUP_BG_NONINTERACTIVE)) {
@@ -11495,6 +11701,9 @@ public final class ActivityManagerService extends ActivityManagerNative
if (!client.hidden) {
app.hidden = false;
}
+ if (client.keeping) {
+ app.keeping = true;
+ }
app.adjType = "service";
app.adjTypeCode = ActivityManager.RunningAppProcessInfo
.REASON_SERVICE_IN_USE;
@@ -11528,7 +11737,7 @@ public final class ActivityManagerService extends ActivityManagerNative
}
}
- // Finally, f this process has active services running in it, we
+ // Finally, if this process has active services running in it, we
// would like to avoid killing it unless it would prevent the current
// application from running. By default we put the process in
// with the rest of the background processes; as we scan through
@@ -11570,6 +11779,9 @@ public final class ActivityManagerService extends ActivityManagerNative
if (!client.hidden) {
app.hidden = false;
}
+ if (client.keeping) {
+ app.keeping = true;
+ }
app.adjType = "provider";
app.adjTypeCode = ActivityManager.RunningAppProcessInfo
.REASON_PROVIDER_IN_USE;
@@ -11589,6 +11801,7 @@ public final class ActivityManagerService extends ActivityManagerNative
adj = FOREGROUND_APP_ADJ;
schedGroup = Process.THREAD_GROUP_DEFAULT;
app.hidden = false;
+ app.keeping = true;
app.adjType = "provider";
app.adjTarget = cpr.name;
}
@@ -11606,6 +11819,9 @@ public final class ActivityManagerService extends ActivityManagerNative
schedGroup = Process.THREAD_GROUP_DEFAULT;
}
}
+ if (adj < HIDDEN_APP_MIN_ADJ) {
+ app.keeping = true;
+ }
app.curAdj = adj;
app.curSchedGroup = schedGroup;
@@ -11743,57 +11959,99 @@ public final class ActivityManagerService extends ActivityManagerNative
}
}
- final void checkExcessiveWakeLocksLocked(boolean doKills) {
+ final void checkExcessivePowerUsageLocked(boolean doKills) {
+ updateCpuStatsNow();
+
BatteryStatsImpl stats = mBatteryStatsService.getActiveStatistics();
- if (mLastWakeLockCheckTime == 0) {
- doKills = false;
+ boolean doWakeKills = doKills;
+ boolean doCpuKills = doKills;
+ if (mLastPowerCheckRealtime == 0) {
+ doWakeKills = false;
+ }
+ if (mLastPowerCheckUptime == 0) {
+ doCpuKills = false;
}
if (stats.isScreenOn()) {
- doKills = false;
+ doWakeKills = false;
}
final long curRealtime = SystemClock.elapsedRealtime();
- final long timeSince = curRealtime - mLastWakeLockCheckTime;
- mLastWakeLockCheckTime = curRealtime;
- if (timeSince < (WAKE_LOCK_CHECK_DELAY/3)) {
- doKills = false;
+ final long realtimeSince = curRealtime - mLastPowerCheckRealtime;
+ final long curUptime = SystemClock.uptimeMillis();
+ final long uptimeSince = curUptime - mLastPowerCheckUptime;
+ mLastPowerCheckRealtime = curRealtime;
+ mLastPowerCheckUptime = curUptime;
+ if (realtimeSince < WAKE_LOCK_MIN_CHECK_DURATION) {
+ doWakeKills = false;
+ }
+ if (uptimeSince < CPU_MIN_CHECK_DURATION) {
+ doCpuKills = false;
}
int i = mLruProcesses.size();
while (i > 0) {
i--;
ProcessRecord app = mLruProcesses.get(i);
- if (app.curAdj >= HIDDEN_APP_MIN_ADJ) {
+ if (!app.keeping) {
long wtime;
synchronized (stats) {
wtime = stats.getProcessWakeTime(app.info.uid,
app.pid, curRealtime);
}
- long timeUsed = wtime - app.lastWakeTime;
- if (false) {
+ long wtimeUsed = wtime - app.lastWakeTime;
+ long cputimeUsed = app.curCpuTime - app.lastCpuTime;
+ if (DEBUG_POWER) {
StringBuilder sb = new StringBuilder(128);
sb.append("Wake for ");
app.toShortString(sb);
sb.append(": over ");
- TimeUtils.formatDuration(timeSince, sb);
+ TimeUtils.formatDuration(realtimeSince, sb);
+ sb.append(" used ");
+ TimeUtils.formatDuration(wtimeUsed, sb);
+ sb.append(" (");
+ sb.append((wtimeUsed*100)/realtimeSince);
+ sb.append("%)");
+ Slog.i(TAG, sb.toString());
+ sb.setLength(0);
+ sb.append("CPU for ");
+ app.toShortString(sb);
+ sb.append(": over ");
+ TimeUtils.formatDuration(uptimeSince, sb);
sb.append(" used ");
- TimeUtils.formatDuration(timeUsed, sb);
+ TimeUtils.formatDuration(cputimeUsed, sb);
sb.append(" (");
- sb.append((timeUsed*100)/timeSince);
+ sb.append((cputimeUsed*100)/uptimeSince);
sb.append("%)");
Slog.i(TAG, sb.toString());
}
// If a process has held a wake lock for more
// than 50% of the time during this period,
// that sounds pad. Kill!
- if (doKills && timeSince > 0
- && ((timeUsed*100)/timeSince) >= 50) {
- Slog.i(TAG, "Excessive wake lock in " + app.processName
- + " (pid " + app.pid + "): held " + timeUsed
- + " during " + timeSince);
+ if (doWakeKills && realtimeSince > 0
+ && ((wtimeUsed*100)/realtimeSince) >= 50) {
+ synchronized (stats) {
+ stats.reportExcessiveWakeLocked(app.info.uid, app.processName,
+ realtimeSince, wtimeUsed);
+ }
+ Slog.w(TAG, "Excessive wake lock in " + app.processName
+ + " (pid " + app.pid + "): held " + wtimeUsed
+ + " during " + realtimeSince);
EventLog.writeEvent(EventLogTags.AM_KILL, app.pid,
app.processName, app.setAdj, "excessive wake lock");
Process.killProcessQuiet(app.pid);
+ } else if (doCpuKills && uptimeSince > 0
+ && ((cputimeUsed*100)/uptimeSince) >= 50) {
+ synchronized (stats) {
+ stats.reportExcessiveCpuLocked(app.info.uid, app.processName,
+ uptimeSince, cputimeUsed);
+ }
+ Slog.w(TAG, "Excessive CPU in " + app.processName
+ + " (pid " + app.pid + "): used " + cputimeUsed
+ + " during " + uptimeSince);
+ EventLog.writeEvent(EventLogTags.AM_KILL, app.pid,
+ app.processName, app.setAdj, "excessive cpu");
+ Process.killProcessQuiet(app.pid);
} else {
app.lastWakeTime = wtime;
+ app.lastCpuTime = app.curCpuTime;
}
}
}
@@ -11807,6 +12065,8 @@ public final class ActivityManagerService extends ActivityManagerNative
return true;
}
+ final boolean wasKeeping = app.keeping;
+
int adj = computeOomAdjLocked(app, hiddenAdj, TOP_APP, false);
if ((app.pid != 0 && app.pid != MY_PID) || Process.supportsProcesses()) {
@@ -11821,13 +12081,20 @@ public final class ActivityManagerService extends ActivityManagerNative
// Likewise do a gc when an app is moving in to the
// background (such as a service stopping).
scheduleAppGcLocked(app);
- // And note its current wake lock time.
+ }
+
+ if (wasKeeping && !app.keeping) {
+ // This app is no longer something we want to keep. Note
+ // its current wake lock time to later know to kill it if
+ // it is not behaving well.
BatteryStatsImpl stats = mBatteryStatsService.getActiveStatistics();
synchronized (stats) {
app.lastWakeTime = stats.getProcessWakeTime(app.info.uid,
app.pid, SystemClock.elapsedRealtime());
}
+ app.lastCpuTime = app.curCpuTime;
}
+
app.setRawAdj = app.curRawAdj;
}
if (adj != app.setAdj) {
diff --git a/services/java/com/android/server/am/ProcessRecord.java b/services/java/com/android/server/am/ProcessRecord.java
index 67df707..404c6be 100644
--- a/services/java/com/android/server/am/ProcessRecord.java
+++ b/services/java/com/android/server/am/ProcessRecord.java
@@ -60,6 +60,7 @@ class ProcessRecord {
int setAdj; // Last set OOM adjustment for this process
int curSchedGroup; // Currently desired scheduling class
int setSchedGroup; // Last set to background scheduling class
+ boolean keeping; // Actively running code so don't kill due to that?
boolean setIsForeground; // Running foreground UI when last set?
boolean foregroundServices; // Running any services that are foreground?
boolean bad; // True if disabled in the bad process list
@@ -75,6 +76,8 @@ class ProcessRecord {
ComponentName instrumentationResultClass;// copy of instrumentationClass
BroadcastRecord curReceiver;// receiver currently running in the app
long lastWakeTime; // How long proc held wake lock at last check
+ long lastCpuTime; // How long proc has run CPU at last check
+ long curCpuTime; // How long proc has run CPU most recently
long lastRequestedGc; // When we last asked the app to do a gc
long lastLowMemory; // When we last told the app that memory is low
boolean reportLowMemory; // Set to true when waiting to report low mem
@@ -131,13 +134,6 @@ class ProcessRecord {
void dump(PrintWriter pw, String prefix) {
final long now = SystemClock.uptimeMillis();
- long wtime;
- synchronized (batteryStats.getBatteryStats()) {
- wtime = batteryStats.getBatteryStats().getProcessWakeTime(info.uid,
- pid, SystemClock.elapsedRealtime());
- }
- long timeUsed = wtime - lastWakeTime;
-
if (info.className != null) {
pw.print(prefix); pw.print("class="); pw.println(info.className);
}
@@ -170,6 +166,7 @@ class ProcessRecord {
pw.print(prefix); pw.print("lastActivityTime=");
TimeUtils.formatDuration(lastActivityTime, now, pw);
pw.print(" lruWeight="); pw.print(lruWeight);
+ pw.print(" keeping="); pw.print(keeping);
pw.print(" hidden="); pw.print(hidden);
pw.print(" empty="); pw.println(empty);
pw.print(prefix); pw.print("oom: max="); pw.print(maxAdj);
@@ -188,9 +185,20 @@ class ProcessRecord {
pw.print(" persistentActivities="); pw.println(persistentActivities);
pw.print(prefix); pw.print("adjSeq="); pw.print(adjSeq);
pw.print(" lruSeq="); pw.println(lruSeq);
- pw.print(prefix); pw.print("lastWakeTime="); pw.print(lastWakeTime);
- pw.print(" time used=");
- TimeUtils.formatDuration(timeUsed, pw); pw.println("");
+ if (!keeping) {
+ long wtime;
+ synchronized (batteryStats.getBatteryStats()) {
+ wtime = batteryStats.getBatteryStats().getProcessWakeTime(info.uid,
+ pid, SystemClock.elapsedRealtime());
+ }
+ long timeUsed = wtime - lastWakeTime;
+ pw.print(prefix); pw.print("lastWakeTime="); pw.print(lastWakeTime);
+ pw.print(" time used=");
+ TimeUtils.formatDuration(timeUsed, pw); pw.println("");
+ pw.print(prefix); pw.print("lastCpuTime="); pw.print(lastCpuTime);
+ pw.print(" time used=");
+ TimeUtils.formatDuration(curCpuTime-lastCpuTime, pw); pw.println("");
+ }
pw.print(prefix); pw.print("lastRequestedGc=");
TimeUtils.formatDuration(lastRequestedGc, now, pw);
pw.print(" lastLowMemory=");
diff --git a/services/java/com/android/server/am/ServiceRecord.java b/services/java/com/android/server/am/ServiceRecord.java
index f35a68e..e5aceb4 100644
--- a/services/java/com/android/server/am/ServiceRecord.java
+++ b/services/java/com/android/server/am/ServiceRecord.java
@@ -347,7 +347,9 @@ class ServiceRecord extends Binder {
// If it gave us a garbage notification, it doesn't
// get to be foreground.
ams.setServiceForeground(name, ServiceRecord.this,
- localForegroundId, null, true);
+ 0, null, true);
+ ams.crashApplication(appUid, appPid, localPackageName,
+ "Bad notification for startForeground: " + e);
}
}
});
diff --git a/services/java/com/android/server/sip/SipService.java b/services/java/com/android/server/sip/SipService.java
index f1dcd5a..3f43e1c 100644
--- a/services/java/com/android/server/sip/SipService.java
+++ b/services/java/com/android/server/sip/SipService.java
@@ -30,8 +30,8 @@ import android.net.sip.ISipSessionListener;
import android.net.sip.SipErrorCode;
import android.net.sip.SipManager;
import android.net.sip.SipProfile;
+import android.net.sip.SipSession;
import android.net.sip.SipSessionAdapter;
-import android.net.sip.SipSessionState;
import android.net.wifi.WifiManager;
import android.os.Binder;
import android.os.Bundle;
@@ -143,7 +143,7 @@ public final class SipService extends ISipService.Stub {
}
private void openToReceiveCalls(SipProfile localProfile) {
- open3(localProfile, SipManager.SIP_INCOMING_CALL_ACTION, null);
+ open3(localProfile, SipManager.ACTION_SIP_INCOMING_CALL, null);
}
public synchronized void open3(SipProfile localProfile,
@@ -255,15 +255,15 @@ public final class SipService extends ISipService.Stub {
private void notifyProfileAdded(SipProfile localProfile) {
if (DEBUG) Log.d(TAG, "notify: profile added: " + localProfile);
- Intent intent = new Intent(SipManager.SIP_ADD_PHONE_ACTION);
- intent.putExtra(SipManager.LOCAL_URI_KEY, localProfile.getUriString());
+ Intent intent = new Intent(SipManager.ACTION_SIP_ADD_PHONE);
+ intent.putExtra(SipManager.EXTRA_LOCAL_URI, localProfile.getUriString());
mContext.sendBroadcast(intent);
}
private void notifyProfileRemoved(SipProfile localProfile) {
if (DEBUG) Log.d(TAG, "notify: profile removed: " + localProfile);
- Intent intent = new Intent(SipManager.SIP_REMOVE_PHONE_ACTION);
- intent.putExtra(SipManager.LOCAL_URI_KEY, localProfile.getUriString());
+ Intent intent = new Intent(SipManager.ACTION_SIP_REMOVE_PHONE);
+ intent.putExtra(SipManager.EXTRA_LOCAL_URI, localProfile.getUriString());
mContext.sendBroadcast(intent);
}
@@ -474,8 +474,8 @@ public final class SipService extends ISipService.Stub {
// send out incoming call broadcast
addPendingSession(session);
Intent intent = SipManager.createIncomingCallBroadcast(
- mIncomingCallBroadcastAction, session.getCallId(),
- sessionDescription);
+ session.getCallId(), sessionDescription)
+ .setAction(mIncomingCallBroadcastAction);
if (DEBUG) Log.d(TAG, " ringing~~ " + getUri() + ": "
+ caller.getUri() + ": " + session.getCallId()
+ " " + mIncomingCallBroadcastAction);
@@ -613,10 +613,10 @@ public final class SipService extends ISipService.Stub {
try {
int state = (mSession == null)
- ? SipSessionState.READY_TO_CALL
+ ? SipSession.State.READY_TO_CALL
: mSession.getState();
- if ((state == SipSessionState.REGISTERING)
- || (state == SipSessionState.DEREGISTERING)) {
+ if ((state == SipSession.State.REGISTERING)
+ || (state == SipSession.State.DEREGISTERING)) {
mProxy.onRegistering(mSession);
} else if (mRegistered) {
int duration = (int)
@@ -1138,7 +1138,8 @@ public final class SipService extends ISipService.Stub {
event.mTriggerTime += event.mPeriod;
// run the callback in a new thread to prevent deadlock
- new Thread(event.mCallback).start();
+ new Thread(event.mCallback, "SipServiceTimerCallbackThread")
+ .start();
}
if (DEBUG_TIMER) {
Log.d(TAG, "after timeout execution");
diff --git a/services/java/com/android/server/sip/SipSessionGroup.java b/services/java/com/android/server/sip/SipSessionGroup.java
index b4c2241..fa3f64a 100644
--- a/services/java/com/android/server/sip/SipSessionGroup.java
+++ b/services/java/com/android/server/sip/SipSessionGroup.java
@@ -25,11 +25,10 @@ import gov.nist.javax.sip.message.SIPMessage;
import android.net.sip.ISipSession;
import android.net.sip.ISipSessionListener;
-import android.net.sip.SessionDescription;
import android.net.sip.SipErrorCode;
import android.net.sip.SipProfile;
+import android.net.sip.SipSession;
import android.net.sip.SipSessionAdapter;
-import android.net.sip.SipSessionState;
import android.text.TextUtils;
import android.util.Log;
@@ -85,7 +84,7 @@ class SipSessionGroup implements SipListener {
private static final String ANONYMOUS = "anonymous";
private static final String SERVER_ERROR_PREFIX = "Response: ";
private static final int EXPIRY_TIME = 3600; // in seconds
- private static final int CANCEL_CALL_TIMER = 5; // in seconds
+ private static final int CANCEL_CALL_TIMER = 3; // in seconds
private static final EventObject DEREGISTER = new EventObject("Deregister");
private static final EventObject END_CALL = new EventObject("End call");
@@ -121,7 +120,7 @@ class SipSessionGroup implements SipListener {
reset(localIp);
}
- void reset(String localIp) throws SipException, IOException {
+ synchronized void reset(String localIp) throws SipException, IOException {
mLocalIp = localIp;
if (localIp == null) return;
@@ -301,7 +300,7 @@ class SipSessionGroup implements SipListener {
boolean processed = (session != null) && session.process(event);
if (isLoggable && processed) {
Log.d(TAG, "new state after: "
- + SipSessionState.toString(session.mState));
+ + SipSession.State.toString(session.mState));
}
} catch (Throwable e) {
Log.w(TAG, "event process error: " + event, e);
@@ -332,7 +331,7 @@ class SipSessionGroup implements SipListener {
public boolean process(EventObject evt) throws SipException {
if (isLoggable(this, evt)) Log.d(TAG, " ~~~~~ " + this + ": "
- + SipSessionState.toString(mState) + ": processing "
+ + SipSession.State.toString(mState) + ": processing "
+ log(evt));
if (isRequestEvent(Request.INVITE, evt)) {
RequestEvent event = (RequestEvent) evt;
@@ -342,13 +341,16 @@ class SipSessionGroup implements SipListener {
newSession.mDialog = newSession.mServerTransaction.getDialog();
newSession.mInviteReceived = event;
newSession.mPeerProfile = createPeerProfile(event.getRequest());
- newSession.mState = SipSessionState.INCOMING_CALL;
+ newSession.mState = SipSession.State.INCOMING_CALL;
newSession.mPeerSessionDescription =
extractContent(event.getRequest());
addSipSession(newSession);
mProxy.onRinging(newSession, newSession.mPeerProfile,
newSession.mPeerSessionDescription);
return true;
+ } else if (isRequestEvent(Request.OPTIONS, evt)) {
+ mSipHelper.sendResponse((RequestEvent) evt, Response.OK);
+ return true;
} else {
return false;
}
@@ -358,7 +360,7 @@ class SipSessionGroup implements SipListener {
class SipSessionImpl extends ISipSession.Stub {
SipProfile mPeerProfile;
SipSessionListenerProxy mProxy = new SipSessionListenerProxy();
- int mState = SipSessionState.READY_TO_CALL;
+ int mState = SipSession.State.READY_TO_CALL;
RequestEvent mInviteReceived;
Dialog mDialog;
ServerTransaction mServerTransaction;
@@ -378,7 +380,7 @@ class SipSessionGroup implements SipListener {
sleep(timeout);
if (mRunning) timeout();
}
- }).start();
+ }, "SipSessionTimerThread").start();
}
synchronized void cancel() {
@@ -413,7 +415,7 @@ class SipSessionGroup implements SipListener {
mInCall = false;
removeSipSession(this);
mPeerProfile = null;
- mState = SipSessionState.READY_TO_CALL;
+ mState = SipSession.State.READY_TO_CALL;
mInviteReceived = null;
mDialog = null;
mServerTransaction = null;
@@ -470,7 +472,7 @@ class SipSessionGroup implements SipListener {
onError(e);
}
}
- }).start();
+ }, "SipSessionAsyncCmdThread").start();
}
public void makeCall(SipProfile peerProfile, String sessionDescription,
@@ -520,10 +522,10 @@ class SipSessionGroup implements SipListener {
}
public void sendKeepAlive() {
- mState = SipSessionState.PINGING;
+ mState = SipSession.State.PINGING;
try {
processCommand(new OptionsCommand());
- while (SipSessionState.PINGING == mState) {
+ while (SipSession.State.PINGING == mState) {
Thread.sleep(1000);
}
} catch (SipException e) {
@@ -550,7 +552,7 @@ class SipSessionGroup implements SipListener {
try {
String s = super.toString();
return s.substring(s.indexOf("@")) + ":"
- + SipSessionState.toString(mState);
+ + SipSession.State.toString(mState);
} catch (Throwable e) {
return super.toString();
}
@@ -558,7 +560,7 @@ class SipSessionGroup implements SipListener {
public boolean process(EventObject evt) throws SipException {
if (isLoggable(this, evt)) Log.d(TAG, " ~~~~~ " + this + ": "
- + SipSessionState.toString(mState) + ": processing "
+ + SipSession.State.toString(mState) + ": processing "
+ log(evt));
synchronized (SipSessionGroup.this) {
if (isClosed()) return false;
@@ -574,30 +576,30 @@ class SipSessionGroup implements SipListener {
boolean processed;
switch (mState) {
- case SipSessionState.REGISTERING:
- case SipSessionState.DEREGISTERING:
+ case SipSession.State.REGISTERING:
+ case SipSession.State.DEREGISTERING:
processed = registeringToReady(evt);
break;
- case SipSessionState.PINGING:
+ case SipSession.State.PINGING:
processed = keepAliveProcess(evt);
break;
- case SipSessionState.READY_TO_CALL:
+ case SipSession.State.READY_TO_CALL:
processed = readyForCall(evt);
break;
- case SipSessionState.INCOMING_CALL:
+ case SipSession.State.INCOMING_CALL:
processed = incomingCall(evt);
break;
- case SipSessionState.INCOMING_CALL_ANSWERING:
+ case SipSession.State.INCOMING_CALL_ANSWERING:
processed = incomingCallToInCall(evt);
break;
- case SipSessionState.OUTGOING_CALL:
- case SipSessionState.OUTGOING_CALL_RING_BACK:
+ case SipSession.State.OUTGOING_CALL:
+ case SipSession.State.OUTGOING_CALL_RING_BACK:
processed = outgoingCall(evt);
break;
- case SipSessionState.OUTGOING_CALL_CANCELING:
+ case SipSession.State.OUTGOING_CALL_CANCELING:
processed = outgoingCallToReady(evt);
break;
- case SipSessionState.IN_CALL:
+ case SipSession.State.IN_CALL:
processed = inCall(evt);
break;
default:
@@ -625,6 +627,9 @@ class SipSessionGroup implements SipListener {
(TransactionTerminatedEvent) evt);
}
return true;
+ } else if (isRequestEvent(Request.OPTIONS, evt)) {
+ mSipHelper.sendResponse((RequestEvent) evt, Response.OK);
+ return true;
} else if (evt instanceof DialogTerminatedEvent) {
processDialogTerminated((DialogTerminatedEvent) evt);
return true;
@@ -644,8 +649,8 @@ class SipSessionGroup implements SipListener {
private void processTransactionTerminated(
TransactionTerminatedEvent event) {
switch (mState) {
- case SipSessionState.IN_CALL:
- case SipSessionState.READY_TO_CALL:
+ case SipSession.State.IN_CALL:
+ case SipSession.State.READY_TO_CALL:
Log.d(TAG, "Transaction terminated; do nothing");
break;
default:
@@ -664,27 +669,27 @@ class SipSessionGroup implements SipListener {
? event.getServerTransaction()
: event.getClientTransaction();
- if ((current != target) && (mState != SipSessionState.PINGING)) {
+ if ((current != target) && (mState != SipSession.State.PINGING)) {
Log.d(TAG, "not the current transaction; current=" + current
+ ", timed out=" + target);
return;
}
switch (mState) {
- case SipSessionState.REGISTERING:
- case SipSessionState.DEREGISTERING:
+ case SipSession.State.REGISTERING:
+ case SipSession.State.DEREGISTERING:
reset();
mProxy.onRegistrationTimeout(this);
break;
- case SipSessionState.INCOMING_CALL:
- case SipSessionState.INCOMING_CALL_ANSWERING:
- case SipSessionState.OUTGOING_CALL:
- case SipSessionState.OUTGOING_CALL_CANCELING:
+ case SipSession.State.INCOMING_CALL:
+ case SipSession.State.INCOMING_CALL_ANSWERING:
+ case SipSession.State.OUTGOING_CALL:
+ case SipSession.State.OUTGOING_CALL_CANCELING:
onError(SipErrorCode.TIME_OUT, event.toString());
break;
- case SipSessionState.PINGING:
+ case SipSession.State.PINGING:
reset();
mReRegisterFlag = true;
- mState = SipSessionState.READY_TO_CALL;
+ mState = SipSession.State.READY_TO_CALL;
break;
default:
@@ -758,7 +763,7 @@ class SipSessionGroup implements SipListener {
switch (statusCode) {
case Response.OK:
int state = mState;
- onRegistrationDone((state == SipSessionState.REGISTERING)
+ onRegistrationDone((state == SipSession.State.REGISTERING)
? getExpiryTime(((ResponseEvent) evt).getResponse())
: -1);
mLastNonce = null;
@@ -845,7 +850,7 @@ class SipSessionGroup implements SipListener {
generateTag());
mDialog = mClientTransaction.getDialog();
addSipSession(this);
- mState = SipSessionState.OUTGOING_CALL;
+ mState = SipSession.State.OUTGOING_CALL;
mProxy.onCalling(this);
startSessionTimer(cmd.getTimeout());
return true;
@@ -855,7 +860,7 @@ class SipSessionGroup implements SipListener {
generateTag(), duration);
mDialog = mClientTransaction.getDialog();
addSipSession(this);
- mState = SipSessionState.REGISTERING;
+ mState = SipSession.State.REGISTERING;
mProxy.onRegistering(this);
return true;
} else if (DEREGISTER == evt) {
@@ -863,7 +868,7 @@ class SipSessionGroup implements SipListener {
generateTag(), 0);
mDialog = mClientTransaction.getDialog();
addSipSession(this);
- mState = SipSessionState.DEREGISTERING;
+ mState = SipSession.State.DEREGISTERING;
mProxy.onRegistering(this);
return true;
}
@@ -878,7 +883,7 @@ class SipSessionGroup implements SipListener {
mLocalProfile,
((MakeCallCommand) evt).getSessionDescription(),
mServerTransaction);
- mState = SipSessionState.INCOMING_CALL_ANSWERING;
+ mState = SipSession.State.INCOMING_CALL_ANSWERING;
startSessionTimer(((MakeCallCommand) evt).getTimeout());
return true;
} else if (END_CALL == evt) {
@@ -919,8 +924,8 @@ class SipSessionGroup implements SipListener {
int statusCode = response.getStatusCode();
switch (statusCode) {
case Response.RINGING:
- if (mState == SipSessionState.OUTGOING_CALL) {
- mState = SipSessionState.OUTGOING_CALL_RING_BACK;
+ if (mState == SipSession.State.OUTGOING_CALL) {
+ mState = SipSession.State.OUTGOING_CALL_RING_BACK;
mProxy.onRingingBack(this);
cancelSessionTimer();
}
@@ -963,7 +968,7 @@ class SipSessionGroup implements SipListener {
// response comes back yet. We are cheating for not checking
// response.
mSipHelper.sendCancel(mClientTransaction);
- mState = SipSessionState.OUTGOING_CALL_CANCELING;
+ mState = SipSession.State.OUTGOING_CALL_CANCELING;
startSessionTimer(CANCEL_CALL_TIMER);
return true;
}
@@ -1019,7 +1024,7 @@ class SipSessionGroup implements SipListener {
} else if (isRequestEvent(Request.INVITE, evt)) {
// got Re-INVITE
RequestEvent event = mInviteReceived = (RequestEvent) evt;
- mState = SipSessionState.INCOMING_CALL;
+ mState = SipSession.State.INCOMING_CALL;
mPeerSessionDescription = extractContent(event.getRequest());
mServerTransaction = null;
mProxy.onRinging(this, mPeerProfile, mPeerSessionDescription);
@@ -1032,7 +1037,7 @@ class SipSessionGroup implements SipListener {
// to change call
mClientTransaction = mSipHelper.sendReinvite(mDialog,
((MakeCallCommand) evt).getSessionDescription());
- mState = SipSessionState.OUTGOING_CALL;
+ mState = SipSession.State.OUTGOING_CALL;
startSessionTimer(((MakeCallCommand) evt).getTimeout());
return true;
}
@@ -1060,14 +1065,14 @@ class SipSessionGroup implements SipListener {
}
private void establishCall() {
- mState = SipSessionState.IN_CALL;
+ mState = SipSession.State.IN_CALL;
mInCall = true;
cancelSessionTimer();
mProxy.onCallEstablished(this, mPeerSessionDescription);
}
private void fallbackToPreviousInCall(int errorCode, String message) {
- mState = SipSessionState.IN_CALL;
+ mState = SipSession.State.IN_CALL;
mProxy.onCallChangeFailed(this, errorCode, message);
}
@@ -1089,8 +1094,8 @@ class SipSessionGroup implements SipListener {
private void onError(int errorCode, String message) {
cancelSessionTimer();
switch (mState) {
- case SipSessionState.REGISTERING:
- case SipSessionState.DEREGISTERING:
+ case SipSession.State.REGISTERING:
+ case SipSession.State.DEREGISTERING:
onRegistrationFailed(errorCode, message);
break;
default:
@@ -1264,7 +1269,7 @@ class SipSessionGroup implements SipListener {
private static boolean isLoggable(SipSessionImpl s) {
if (s != null) {
switch (s.mState) {
- case SipSessionState.PINGING:
+ case SipSession.State.PINGING:
return DEBUG_PING;
}
}
diff --git a/services/java/com/android/server/sip/SipSessionListenerProxy.java b/services/java/com/android/server/sip/SipSessionListenerProxy.java
index a4cd102..f8be0a8 100644
--- a/services/java/com/android/server/sip/SipSessionListenerProxy.java
+++ b/services/java/com/android/server/sip/SipSessionListenerProxy.java
@@ -40,7 +40,7 @@ class SipSessionListenerProxy extends ISipSessionListener.Stub {
// One thread for each calling back.
// Note: Guarantee ordering if the issue becomes important. Currently,
// the chance of handling two callback events at a time is none.
- new Thread(runnable).start();
+ new Thread(runnable, "SipSessionCallbackThread").start();
}
public void onCalling(final ISipSession session) {