summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--cmds/am/src/com/android/commands/am/Am.java214
-rw-r--r--core/java/android/app/ActivityThread.java13
-rw-r--r--core/java/android/app/IActivityController.aidl5
-rw-r--r--core/java/android/os/BatteryStats.java24
-rw-r--r--core/java/android/view/ViewRoot.java63
-rw-r--r--core/java/com/android/internal/os/BatteryStatsImpl.java78
-rwxr-xr-xcore/tests/coretests/src/android/content/pm/PackageManagerTests.java56
-rw-r--r--docs/html/sdk/adt_download.jd11
-rw-r--r--docs/html/sdk/eclipse-adt.jd45
-rw-r--r--docs/html/sdk/requirements.jd2
-rw-r--r--docs/html/sdk/sdk_toc.cs2
-rw-r--r--media/libstagefright/MPEG4Writer.cpp10
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/StatusBarIconView.java7
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/StatusBarService.java60
-rwxr-xr-xpolicy/src/com/android/internal/policy/impl/PhoneWindowManager.java50
-rw-r--r--services/java/com/android/server/ProcessStats.java148
-rw-r--r--services/java/com/android/server/am/ActivityManagerService.java573
-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/SipSessionGroup.java6
-rw-r--r--tests/BatteryWaster/src/com/android/batterywaster/BatteryWaster.java28
-rw-r--r--tools/aapt/Bundle.h5
-rw-r--r--tools/aapt/Main.cpp13
-rw-r--r--tools/aapt/ResourceTable.cpp82
24 files changed, 1120 insertions, 407 deletions
diff --git a/cmds/am/src/com/android/commands/am/Am.java b/cmds/am/src/com/android/commands/am/Am.java
index 301883f..194e8e1 100644
--- a/cmds/am/src/com/android/commands/am/Am.java
+++ b/cmds/am/src/com/android/commands/am/Am.java
@@ -19,6 +19,7 @@
package com.android.commands.am;
import android.app.ActivityManagerNative;
+import android.app.IActivityController;
import android.app.IActivityManager;
import android.app.IInstrumentationWatcher;
import android.app.Instrumentation;
@@ -33,8 +34,13 @@ import android.os.ServiceManager;
import android.util.AndroidException;
import android.view.IWindowManager;
+import java.io.BufferedReader;
+import java.io.DataInputStream;
import java.io.File;
+import java.io.FileInputStream;
import java.io.FileNotFoundException;
+import java.io.IOException;
+import java.io.InputStreamReader;
import java.io.PrintStream;
import java.net.URISyntaxException;
import java.util.Iterator;
@@ -98,6 +104,8 @@ public class Am {
sendBroadcast();
} else if (op.equals("profile")) {
runProfile();
+ } else if (op.equals("monitor")) {
+ runMonitor();
} else {
throw new IllegalArgumentException("Unknown command: " + op);
}
@@ -424,6 +432,210 @@ public class Am {
}
}
+ class MyActivityController extends IActivityController.Stub {
+ static final int STATE_NORMAL = 0;
+ static final int STATE_CRASHED = 1;
+ static final int STATE_EARLY_ANR = 2;
+ static final int STATE_ANR = 3;
+
+ int mState;
+
+ static final int RESULT_DEFAULT = 0;
+
+ static final int RESULT_CRASH_DIALOG = 0;
+ static final int RESULT_CRASH_KILL = 1;
+
+ static final int RESULT_EARLY_ANR_CONTINUE = 0;
+ static final int RESULT_EARLY_ANR_KILL = 1;
+
+ static final int RESULT_ANR_DIALOG = 0;
+ static final int RESULT_ANR_KILL = 1;
+ static final int RESULT_ANR_WAIT = 1;
+
+ int mResult;
+
+ @Override
+ public boolean activityResuming(String pkg) throws RemoteException {
+ synchronized (this) {
+ System.out.println("** Activity resuming: " + pkg);
+ }
+ return true;
+ }
+
+ @Override
+ public boolean activityStarting(Intent intent, String pkg) throws RemoteException {
+ synchronized (this) {
+ System.out.println("** Activity starting: " + pkg);
+ }
+ return true;
+ }
+
+ @Override
+ public boolean appCrashed(String processName, int pid, String shortMsg, String longMsg,
+ long timeMillis, String stackTrace) throws RemoteException {
+ synchronized (this) {
+ System.out.println("** ERROR: PROCESS CRASHED");
+ System.out.println("processName: " + processName);
+ System.out.println("processPid: " + pid);
+ System.out.println("shortMsg: " + shortMsg);
+ System.out.println("longMsg: " + longMsg);
+ System.out.println("timeMillis: " + timeMillis);
+ System.out.println("stack:");
+ System.out.print(stackTrace);
+ System.out.println("#");
+ int result = waitControllerLocked(STATE_CRASHED);
+ return result == RESULT_CRASH_KILL ? false : true;
+ }
+ }
+
+ @Override
+ public int appEarlyNotResponding(String processName, int pid, String annotation)
+ throws RemoteException {
+ synchronized (this) {
+ System.out.println("** ERROR: EARLY PROCESS NOT RESPONDING");
+ System.out.println("processName: " + processName);
+ System.out.println("processPid: " + pid);
+ System.out.println("annotation: " + annotation);
+ int result = waitControllerLocked(STATE_EARLY_ANR);
+ if (result == RESULT_EARLY_ANR_KILL) return -1;
+ return 0;
+ }
+ }
+
+ @Override
+ public int appNotResponding(String processName, int pid, String processStats)
+ throws RemoteException {
+ synchronized (this) {
+ System.out.println("** ERROR: PROCESS NOT RESPONDING");
+ System.out.println("processName: " + processName);
+ System.out.println("processPid: " + pid);
+ System.out.println("processStats:");
+ System.out.print(processStats);
+ System.out.println("#");
+ int result = waitControllerLocked(STATE_ANR);
+ if (result == RESULT_ANR_KILL) return -1;
+ if (result == RESULT_ANR_WAIT) return 1;
+ return 0;
+ }
+ }
+
+ int waitControllerLocked(int state) {
+ mState = state;
+ System.out.println("");
+ printMessageForState();
+
+ while (mState != STATE_NORMAL) {
+ try {
+ wait();
+ } catch (InterruptedException e) {
+ }
+ }
+
+ return mResult;
+ }
+
+ void resumeController(int result) {
+ synchronized (this) {
+ mState = STATE_NORMAL;
+ mResult = result;
+ notifyAll();
+ }
+ }
+
+ void printMessageForState() {
+ switch (mState) {
+ case STATE_NORMAL:
+ System.out.println("Monitoring activity manager... available commands:");
+ break;
+ case STATE_CRASHED:
+ System.out.println("Waiting after crash... available commands:");
+ System.out.println("(c)ontinue: show crash dialog");
+ System.out.println("(k)ill: immediately kill app");
+ break;
+ case STATE_EARLY_ANR:
+ System.out.println("Waiting after early ANR... available commands:");
+ System.out.println("(c)ontinue: standard ANR processing");
+ System.out.println("(k)ill: immediately kill app");
+ break;
+ case STATE_ANR:
+ System.out.println("Waiting after ANR... available commands:");
+ System.out.println("(c)ontinue: show ANR dialog");
+ System.out.println("(k)ill: immediately kill app");
+ System.out.println("(w)ait: wait some more");
+ break;
+ }
+ System.out.println("(q)uit: finish monitoring");
+ }
+
+ void run() throws RemoteException {
+ try {
+ printMessageForState();
+
+ mAm.setActivityController(this);
+ mState = STATE_NORMAL;
+
+ InputStreamReader converter = new InputStreamReader(System.in);
+ BufferedReader in = new BufferedReader(converter);
+ String line;
+
+ while ((line = in.readLine()) != null) {
+ boolean addNewline = true;
+ if (line.length() <= 0) {
+ addNewline = false;
+ } else if ("q".equals(line) || "quit".equals(line)) {
+ resumeController(RESULT_DEFAULT);
+ break;
+ } else if (mState == STATE_CRASHED) {
+ if ("c".equals(line) || "continue".equals(line)) {
+ resumeController(RESULT_CRASH_DIALOG);
+ } else if ("k".equals(line) || "kill".equals(line)) {
+ resumeController(RESULT_CRASH_KILL);
+ } else {
+ System.out.println("Invalid command: " + line);
+ }
+ } else if (mState == STATE_ANR) {
+ if ("c".equals(line) || "continue".equals(line)) {
+ resumeController(RESULT_ANR_DIALOG);
+ } else if ("k".equals(line) || "kill".equals(line)) {
+ resumeController(RESULT_ANR_KILL);
+ } else if ("w".equals(line) || "wait".equals(line)) {
+ resumeController(RESULT_ANR_WAIT);
+ } else {
+ System.out.println("Invalid command: " + line);
+ }
+ } else if (mState == STATE_EARLY_ANR) {
+ if ("c".equals(line) || "continue".equals(line)) {
+ resumeController(RESULT_EARLY_ANR_CONTINUE);
+ } else if ("k".equals(line) || "kill".equals(line)) {
+ resumeController(RESULT_EARLY_ANR_KILL);
+ } else {
+ System.out.println("Invalid command: " + line);
+ }
+ } else {
+ System.out.println("Invalid command: " + line);
+ }
+
+ synchronized (this) {
+ if (addNewline) {
+ System.out.println("");
+ }
+ printMessageForState();
+ }
+ }
+
+ } catch (IOException e) {
+ e.printStackTrace();
+ } finally {
+ mAm.setActivityController(null);
+ }
+ }
+ }
+
+ private void runMonitor() throws Exception {
+ MyActivityController controller = new MyActivityController();
+ controller.run();
+ }
+
private class IntentReceiver extends IIntentReceiver.Stub {
private boolean mFinished = false;
@@ -594,6 +806,8 @@ public class Am {
" start profiling: am profile <PROCESS> start <FILE>\n" +
" stop profiling: am profile <PROCESS> stop\n" +
"\n" +
+ " start monitoring: am monitor\n" +
+ "\n" +
" <INTENT> specifications include these flags:\n" +
" [-a <ACTION>] [-d <DATA_URI>] [-t <MIME_TYPE>]\n" +
" [-c <CATEGORY> [-c <CATEGORY>] ...]\n" +
diff --git a/core/java/android/app/ActivityThread.java b/core/java/android/app/ActivityThread.java
index 3c7bebf..6d1bf96 100644
--- a/core/java/android/app/ActivityThread.java
+++ b/core/java/android/app/ActivityThread.java
@@ -60,6 +60,7 @@ import android.util.Config;
import android.util.DisplayMetrics;
import android.util.EventLog;
import android.util.Log;
+import android.util.LogPrinter;
import android.util.Slog;
import android.view.Display;
import android.view.View;
@@ -118,6 +119,7 @@ public final class ActivityThread {
private static final android.graphics.Bitmap.Config THUMBNAIL_FORMAT = Bitmap.Config.RGB_565;
private static final boolean DEBUG = false;
static final boolean localLOGV = DEBUG ? Config.LOGD : Config.LOGV;
+ static final boolean DEBUG_MESSAGES = false;
static final boolean DEBUG_BROADCAST = false;
private static final boolean DEBUG_RESULTS = false;
private static final boolean DEBUG_BACKUP = false;
@@ -874,7 +876,7 @@ public final class ActivityThread {
public static final int DISPATCH_PACKAGE_BROADCAST = 133;
public static final int SCHEDULE_CRASH = 134;
String codeToString(int code) {
- if (localLOGV) {
+ if (DEBUG_MESSAGES) {
switch (code) {
case LAUNCH_ACTIVITY: return "LAUNCH_ACTIVITY";
case PAUSE_ACTIVITY: return "PAUSE_ACTIVITY";
@@ -916,6 +918,7 @@ public final class ActivityThread {
return "(unknown)";
}
public void handleMessage(Message msg) {
+ if (DEBUG_MESSAGES) Slog.v(TAG, ">>> handling: " + msg.what);
switch (msg.what) {
case LAUNCH_ACTIVITY: {
ActivityClientRecord r = (ActivityClientRecord)msg.obj;
@@ -1037,6 +1040,7 @@ public final class ActivityThread {
case SCHEDULE_CRASH:
throw new RemoteServiceException((String)msg.obj);
}
+ if (DEBUG_MESSAGES) Slog.v(TAG, "<<< done: " + msg.what);
}
void maybeSnapshot() {
@@ -1484,7 +1488,7 @@ public final class ActivityThread {
private final void queueOrSendMessage(int what, Object obj, int arg1, int arg2) {
synchronized (this) {
- if (localLOGV) Slog.v(
+ if (DEBUG_MESSAGES) Slog.v(
TAG, "SCHEDULE " + what + " " + mH.codeToString(what)
+ ": " + arg1 + " / " + obj);
Message msg = Message.obtain();
@@ -3608,6 +3612,11 @@ public final class ActivityThread {
ActivityThread thread = new ActivityThread();
thread.attach(false);
+ if (false) {
+ Looper.myLooper().setMessageLogging(new
+ LogPrinter(Log.DEBUG, "ActivityThread"));
+ }
+
Looper.loop();
if (Process.supportsProcesses()) {
diff --git a/core/java/android/app/IActivityController.aidl b/core/java/android/app/IActivityController.aidl
index c76a517..aca8305 100644
--- a/core/java/android/app/IActivityController.aidl
+++ b/core/java/android/app/IActivityController.aidl
@@ -48,6 +48,11 @@ interface IActivityController
long timeMillis, String stackTrace);
/**
+ * Early call as soon as an ANR is detected.
+ */
+ int appEarlyNotResponding(String processName, int pid, String annotation);
+
+ /**
* An application process is not responding. Return 0 to show the "app
* not responding" dialog, 1 to continue waiting, or -1 to kill it
* immediately.
diff --git a/core/java/android/os/BatteryStats.java b/core/java/android/os/BatteryStats.java
index ba8014f..d49c8be 100644
--- a/core/java/android/os/BatteryStats.java
+++ b/core/java/android/os/BatteryStats.java
@@ -301,7 +301,11 @@ public abstract class BatteryStats implements Parcelable {
*/
public static abstract class Proc {
- public static class ExcessiveWake {
+ public static class ExcessivePower {
+ public static final int TYPE_WAKE = 1;
+ public static final int TYPE_CPU = 2;
+
+ public int type;
public long overTime;
public long usedTime;
}
@@ -343,9 +347,9 @@ public abstract class BatteryStats implements Parcelable {
*/
public abstract long getTimeAtCpuSpeedStep(int speedStep, int which);
- public abstract int countExcessiveWakes();
+ public abstract int countExcessivePowers();
- public abstract ExcessiveWake getExcessiveWake(int i);
+ public abstract ExcessivePower getExcessivePower(int i);
}
/**
@@ -1593,7 +1597,7 @@ public abstract class BatteryStats implements Parcelable {
systemTime = ps.getSystemTime(which);
starts = ps.getStarts(which);
numExcessive = which == STATS_SINCE_CHARGED
- ? ps.countExcessiveWakes() : 0;
+ ? ps.countExcessivePowers() : 0;
if (userTime != 0 || systemTime != 0 || starts != 0
|| numExcessive != 0) {
@@ -1609,9 +1613,17 @@ public abstract class BatteryStats implements Parcelable {
}
pw.println(sb.toString());
for (int e=0; e<numExcessive; e++) {
- Uid.Proc.ExcessiveWake ew = ps.getExcessiveWake(e);
+ Uid.Proc.ExcessivePower ew = ps.getExcessivePower(e);
if (ew != null) {
- pw.print(prefix); pw.print(" * Killed for wake lock use: ");
+ pw.print(prefix); pw.print(" * Killed for ");
+ if (ew.type == Uid.Proc.ExcessivePower.TYPE_WAKE) {
+ pw.print("wake lock");
+ } else if (ew.type == Uid.Proc.ExcessivePower.TYPE_CPU) {
+ pw.print("cpu");
+ } else {
+ pw.print("unknown");
+ }
+ pw.print(" use: ");
TimeUtils.formatDuration(ew.usedTime, pw);
pw.print(" over ");
TimeUtils.formatDuration(ew.overTime, pw);
diff --git a/core/java/android/view/ViewRoot.java b/core/java/android/view/ViewRoot.java
index 59980ef..0608e72 100644
--- a/core/java/android/view/ViewRoot.java
+++ b/core/java/android/view/ViewRoot.java
@@ -1876,6 +1876,9 @@ public final class ViewRoot extends Handler implements ViewParent,
deliverPointerEvent(event);
} finally {
event.recycle();
+ if (msg.arg1 != 0) {
+ finishInputEvent();
+ }
if (LOCAL_LOGV || WATCH_POINTER) Log.i(TAG, "Done dispatching!");
}
} break;
@@ -1885,6 +1888,9 @@ public final class ViewRoot extends Handler implements ViewParent,
deliverTrackballEvent(event);
} finally {
event.recycle();
+ if (msg.arg1 != 0) {
+ finishInputEvent();
+ }
}
} break;
case DISPATCH_APP_VISIBILITY:
@@ -2019,15 +2025,24 @@ public final class ViewRoot extends Handler implements ViewParent,
}
}
- private void finishKeyEvent(KeyEvent event) {
- if (LOCAL_LOGV) Log.v(TAG, "Telling window manager key is finished");
+ private void startInputEvent(Runnable finishedCallback) {
+ if (mFinishedCallback != null) {
+ Slog.w(TAG, "Received a new input event from the input queue but there is "
+ + "already an unfinished input event in progress.");
+ }
+
+ mFinishedCallback = finishedCallback;
+ }
+
+ private void finishInputEvent() {
+ if (LOCAL_LOGV) Log.v(TAG, "Telling window manager input event is finished");
if (mFinishedCallback != null) {
mFinishedCallback.run();
mFinishedCallback = null;
} else {
- Slog.w(TAG, "Attempted to tell the input queue that the current key event "
- + "is finished but there is no key event actually in progress.");
+ Slog.w(TAG, "Attempted to tell the input queue that the current input event "
+ + "is finished but there is no input event actually in progress.");
}
}
@@ -2487,7 +2502,7 @@ public final class ViewRoot extends Handler implements ViewParent,
? mView.dispatchKeyEventPreIme(event) : true;
if (handled) {
if (sendDone) {
- finishKeyEvent(event);
+ finishInputEvent();
}
return;
}
@@ -2518,7 +2533,7 @@ public final class ViewRoot extends Handler implements ViewParent,
deliverKeyEventToViewHierarchy(event, sendDone);
return;
} else if (sendDone) {
- finishKeyEvent(event);
+ finishInputEvent();
} else {
Log.w(TAG, "handleFinishedEvent(seq=" + seq
+ " handled=" + handled + " ev=" + event
@@ -2591,7 +2606,7 @@ public final class ViewRoot extends Handler implements ViewParent,
} finally {
if (sendDone) {
- finishKeyEvent(event);
+ finishInputEvent();
}
// Let the exception fall through -- the looper will catch
// it and take care of the bad app for us.
@@ -2774,20 +2789,13 @@ public final class ViewRoot extends Handler implements ViewParent,
private final InputHandler mInputHandler = new InputHandler() {
public void handleKey(KeyEvent event, Runnable finishedCallback) {
- if (mFinishedCallback != null) {
- Slog.w(TAG, "Received a new key event from the input queue but there is "
- + "already an unfinished key event in progress.");
- }
-
- mFinishedCallback = finishedCallback;
-
+ startInputEvent(finishedCallback);
dispatchKey(event, true);
}
public void handleMotion(MotionEvent event, Runnable finishedCallback) {
- finishedCallback.run();
-
- dispatchMotion(event);
+ startInputEvent(finishedCallback);
+ dispatchMotion(event, true);
}
};
@@ -2820,26 +2828,43 @@ public final class ViewRoot extends Handler implements ViewParent,
}
public void dispatchMotion(MotionEvent event) {
+ dispatchMotion(event, false);
+ }
+
+ private void dispatchMotion(MotionEvent event, boolean sendDone) {
int source = event.getSource();
if ((source & InputDevice.SOURCE_CLASS_POINTER) != 0) {
- dispatchPointer(event);
+ dispatchPointer(event, sendDone);
} else if ((source & InputDevice.SOURCE_CLASS_TRACKBALL) != 0) {
- dispatchTrackball(event);
+ dispatchTrackball(event, sendDone);
} else {
// TODO
Log.v(TAG, "Dropping unsupported motion event (unimplemented): " + event);
+ if (sendDone) {
+ finishInputEvent();
+ }
}
}
public void dispatchPointer(MotionEvent event) {
+ dispatchPointer(event, false);
+ }
+
+ private void dispatchPointer(MotionEvent event, boolean sendDone) {
Message msg = obtainMessage(DISPATCH_POINTER);
msg.obj = event;
+ msg.arg1 = sendDone ? 1 : 0;
sendMessageAtTime(msg, event.getEventTime());
}
public void dispatchTrackball(MotionEvent event) {
+ dispatchTrackball(event, false);
+ }
+
+ private void dispatchTrackball(MotionEvent event, boolean sendDone) {
Message msg = obtainMessage(DISPATCH_TRACKBALL);
msg.obj = event;
+ msg.arg1 = sendDone ? 1 : 0;
sendMessageAtTime(msg, event.getEventTime());
}
diff --git a/core/java/com/android/internal/os/BatteryStatsImpl.java b/core/java/com/android/internal/os/BatteryStatsImpl.java
index 6e5c47f..b033fad 100644
--- a/core/java/com/android/internal/os/BatteryStatsImpl.java
+++ b/core/java/com/android/internal/os/BatteryStatsImpl.java
@@ -67,7 +67,7 @@ public final class BatteryStatsImpl extends BatteryStats {
private static final int MAGIC = 0xBA757475; // 'BATSTATS'
// Current on-disk Parcel version
- private static final int VERSION = 51;
+ private static final int VERSION = 52;
// Maximum number of items we will record in the history.
private static final int MAX_HISTORY_ITEMS = 2000;
@@ -85,7 +85,7 @@ public final class BatteryStatsImpl extends BatteryStats {
static final int MSG_UPDATE_WAKELOCKS = 1;
static final int MSG_REPORT_POWER_CHANGE = 2;
- static final long DELAY_UPDATE_WAKELOCKS = 15*1000;
+ static final long DELAY_UPDATE_WAKELOCKS = 5*1000;
public interface BatteryCallback {
public void batteryNeedsCpuUpdate();
@@ -1474,6 +1474,13 @@ public final class BatteryStatsImpl extends BatteryStats {
}
}
+ public void reportExcessiveCpuLocked(int uid, String proc, long overTime, long usedTime) {
+ Uid u = mUidStats.get(uid);
+ if (u != null) {
+ u.reportExcessiveCpuLocked(proc, overTime, usedTime);
+ }
+ }
+
int mSensorNesting;
public void noteStartSensorLocked(int uid, int sensor) {
@@ -2975,7 +2982,7 @@ public final class BatteryStatsImpl extends BatteryStats {
SamplingCounter[] mSpeedBins;
- ArrayList<ExcessiveWake> mExcessiveWake;
+ ArrayList<ExcessivePower> mExcessivePower;
Proc() {
mUnpluggables.add(this);
@@ -3003,55 +3010,69 @@ public final class BatteryStatsImpl extends BatteryStats {
}
}
- public int countExcessiveWakes() {
- return mExcessiveWake != null ? mExcessiveWake.size() : 0;
+ public int countExcessivePowers() {
+ return mExcessivePower != null ? mExcessivePower.size() : 0;
}
- public ExcessiveWake getExcessiveWake(int i) {
- if (mExcessiveWake != null) {
- return mExcessiveWake.get(i);
+ public ExcessivePower getExcessivePower(int i) {
+ if (mExcessivePower != null) {
+ return mExcessivePower.get(i);
}
return null;
}
public void addExcessiveWake(long overTime, long usedTime) {
- if (mExcessiveWake == null) {
- mExcessiveWake = new ArrayList<ExcessiveWake>();
+ if (mExcessivePower == null) {
+ mExcessivePower = new ArrayList<ExcessivePower>();
}
- ExcessiveWake ew = new ExcessiveWake();
+ ExcessivePower ew = new ExcessivePower();
+ ew.type = ExcessivePower.TYPE_WAKE;
ew.overTime = overTime;
ew.usedTime = usedTime;
- mExcessiveWake.add(ew);
+ mExcessivePower.add(ew);
}
- void writeExcessiveWakeToParcelLocked(Parcel out) {
- if (mExcessiveWake == null) {
+ public void addExcessiveCpu(long overTime, long usedTime) {
+ if (mExcessivePower == null) {
+ mExcessivePower = new ArrayList<ExcessivePower>();
+ }
+ ExcessivePower ew = new ExcessivePower();
+ ew.type = ExcessivePower.TYPE_CPU;
+ ew.overTime = overTime;
+ ew.usedTime = usedTime;
+ mExcessivePower.add(ew);
+ }
+
+ void writeExcessivePowerToParcelLocked(Parcel out) {
+ if (mExcessivePower == null) {
out.writeInt(0);
return;
}
- final int N = mExcessiveWake.size();
+ final int N = mExcessivePower.size();
out.writeInt(N);
for (int i=0; i<N; i++) {
- ExcessiveWake ew = mExcessiveWake.get(i);
+ ExcessivePower ew = mExcessivePower.get(i);
+ out.writeInt(ew.type);
out.writeLong(ew.overTime);
out.writeLong(ew.usedTime);
}
}
- void readExcessiveWakeFromParcelLocked(Parcel in) {
+ void readExcessivePowerFromParcelLocked(Parcel in) {
final int N = in.readInt();
if (N == 0) {
- mExcessiveWake = null;
+ mExcessivePower = null;
return;
}
- mExcessiveWake = new ArrayList<ExcessiveWake>();
+ mExcessivePower = new ArrayList<ExcessivePower>();
for (int i=0; i<N; i++) {
- ExcessiveWake ew = new ExcessiveWake();
+ ExcessivePower ew = new ExcessivePower();
+ ew.type = in.readInt();
ew.overTime = in.readLong();
ew.usedTime = in.readLong();
- mExcessiveWake.add(ew);
+ mExcessivePower.add(ew);
}
}
@@ -3080,7 +3101,7 @@ public final class BatteryStatsImpl extends BatteryStats {
}
}
- writeExcessiveWakeToParcelLocked(out);
+ writeExcessivePowerToParcelLocked(out);
}
void readFromParcelLocked(Parcel in) {
@@ -3110,7 +3131,7 @@ public final class BatteryStatsImpl extends BatteryStats {
}
}
- readExcessiveWakeFromParcelLocked(in);
+ readExcessivePowerFromParcelLocked(in);
}
public BatteryStatsImpl getBatteryStats() {
@@ -3744,6 +3765,13 @@ public final class BatteryStatsImpl extends BatteryStats {
}
}
+ public void reportExcessiveCpuLocked(String proc, long overTime, long usedTime) {
+ Proc p = getProcessStatsLocked(proc);
+ if (p != null) {
+ p.addExcessiveCpu(overTime, usedTime);
+ }
+ }
+
public void noteStartSensor(int sensor) {
StopwatchTimer t = getSensorTimerLocked(sensor, true);
if (t != null) {
@@ -4686,7 +4714,7 @@ public final class BatteryStatsImpl extends BatteryStats {
p.mSpeedBins[i].readSummaryFromParcelLocked(in);
}
}
- p.readExcessiveWakeFromParcelLocked(in);
+ p.readExcessivePowerFromParcelLocked(in);
}
NP = in.readInt();
@@ -4885,7 +4913,7 @@ public final class BatteryStatsImpl extends BatteryStats {
out.writeInt(0);
}
}
- ps.writeExcessiveWakeToParcelLocked(out);
+ ps.writeExcessivePowerToParcelLocked(out);
}
}
diff --git a/core/tests/coretests/src/android/content/pm/PackageManagerTests.java b/core/tests/coretests/src/android/content/pm/PackageManagerTests.java
index 975a4c2..1289a9e 100755
--- a/core/tests/coretests/src/android/content/pm/PackageManagerTests.java
+++ b/core/tests/coretests/src/android/content/pm/PackageManagerTests.java
@@ -167,8 +167,7 @@ public class PackageManagerTests extends AndroidTestCase {
return ipm;
}
- public boolean invokeInstallPackage(Uri packageURI, int flags,
- GenericReceiver receiver) throws Exception {
+ public boolean invokeInstallPackage(Uri packageURI, int flags, GenericReceiver receiver) {
PackageInstallObserver observer = new PackageInstallObserver();
final boolean received = false;
mContext.registerReceiver(receiver, receiver.filter);
@@ -180,11 +179,15 @@ public class PackageManagerTests extends AndroidTestCase {
getPm().installPackage(packageURI, observer, flags, null);
long waitTime = 0;
while((!observer.isDone()) && (waitTime < MAX_WAIT_TIME) ) {
- observer.wait(WAIT_TIME_INCR);
- waitTime += WAIT_TIME_INCR;
+ try {
+ observer.wait(WAIT_TIME_INCR);
+ waitTime += WAIT_TIME_INCR;
+ } catch (InterruptedException e) {
+ Log.i(TAG, "Interrupted during sleep", e);
+ }
}
if(!observer.isDone()) {
- throw new Exception("Timed out waiting for packageInstalled callback");
+ fail("Timed out waiting for packageInstalled callback");
}
if (observer.returnCode != PackageManager.INSTALL_SUCCEEDED) {
Log.i(TAG, "Failed to install with error code = " + observer.returnCode);
@@ -193,11 +196,15 @@ public class PackageManagerTests extends AndroidTestCase {
// Verify we received the broadcast
waitTime = 0;
while((!receiver.isDone()) && (waitTime < MAX_WAIT_TIME) ) {
- receiver.wait(WAIT_TIME_INCR);
- waitTime += WAIT_TIME_INCR;
+ try {
+ receiver.wait(WAIT_TIME_INCR);
+ waitTime += WAIT_TIME_INCR;
+ } catch (InterruptedException e) {
+ Log.i(TAG, "Interrupted during sleep", e);
+ }
}
if(!receiver.isDone()) {
- throw new Exception("Timed out waiting for PACKAGE_ADDED notification");
+ fail("Timed out waiting for PACKAGE_ADDED notification");
}
return receiver.received;
}
@@ -207,7 +214,7 @@ public class PackageManagerTests extends AndroidTestCase {
}
}
- public void invokeInstallPackageFail(Uri packageURI, int flags, int result) throws Exception {
+ public void invokeInstallPackageFail(Uri packageURI, int flags, int result) {
PackageInstallObserver observer = new PackageInstallObserver();
try {
// Wait on observer
@@ -215,11 +222,15 @@ public class PackageManagerTests extends AndroidTestCase {
getPm().installPackage(packageURI, observer, flags, null);
long waitTime = 0;
while((!observer.isDone()) && (waitTime < MAX_WAIT_TIME) ) {
- observer.wait(WAIT_TIME_INCR);
- waitTime += WAIT_TIME_INCR;
+ try {
+ observer.wait(WAIT_TIME_INCR);
+ waitTime += WAIT_TIME_INCR;
+ } catch (InterruptedException e) {
+ Log.i(TAG, "Interrupted during sleep", e);
+ }
}
if(!observer.isDone()) {
- throw new Exception("Timed out waiting for packageInstalled callback");
+ fail("Timed out waiting for packageInstalled callback");
}
assertEquals(observer.returnCode, result);
}
@@ -265,7 +276,7 @@ public class PackageManagerTests extends AndroidTestCase {
Environment.getExternalStorageDirectory().getPath());
sdSize = (long)sdStats.getAvailableBlocks() *
(long)sdStats.getBlockSize();
- // TODO check for thesholds here
+ // TODO check for thresholds here
return pkgLen <= sdSize;
}
@@ -368,12 +379,21 @@ public class PackageManagerTests extends AndroidTestCase {
assertFalse((info.flags & ApplicationInfo.FLAG_EXTERNAL_STORAGE) != 0);
assertTrue(info.nativeLibraryDir.startsWith(dataDir.getPath()));
} else if (rLoc == INSTALL_LOC_SD){
- assertTrue((info.flags & ApplicationInfo.FLAG_EXTERNAL_STORAGE) != 0);
- assertTrue(srcPath.startsWith(SECURE_CONTAINERS_PREFIX));
- assertTrue(publicSrcPath.startsWith(SECURE_CONTAINERS_PREFIX));
- assertTrue(info.nativeLibraryDir.startsWith(SECURE_CONTAINERS_PREFIX));
+ assertTrue("Application flags (" + info.flags
+ + ") should contain FLAG_EXTERNAL_STORAGE",
+ (info.flags & ApplicationInfo.FLAG_EXTERNAL_STORAGE) != 0);
+ assertTrue("The APK path (" + srcPath + ") should start with "
+ + SECURE_CONTAINERS_PREFIX, srcPath
+ .startsWith(SECURE_CONTAINERS_PREFIX));
+ assertTrue("The public APK path (" + publicSrcPath + ") should start with "
+ + SECURE_CONTAINERS_PREFIX, publicSrcPath
+ .startsWith(SECURE_CONTAINERS_PREFIX));
+ assertTrue("The native library path (" + info.nativeLibraryDir
+ + ") should start with " + SECURE_CONTAINERS_PREFIX,
+ info.nativeLibraryDir.startsWith(SECURE_CONTAINERS_PREFIX));
} else {
// TODO handle error. Install should have failed.
+ fail("Install should have failed");
}
}
} catch (NameNotFoundException e) {
@@ -544,8 +564,6 @@ public class PackageManagerTests extends AndroidTestCase {
// Verify installed information
assertInstall(pkg, flags, expInstallLocation);
}
- } catch (Exception e) {
- failStr("Failed with exception : " + e);
} finally {
if (cleanUp) {
cleanUpInstall(ip);
diff --git a/docs/html/sdk/adt_download.jd b/docs/html/sdk/adt_download.jd
index 5e642d7..3da576a 100644
--- a/docs/html/sdk/adt_download.jd
+++ b/docs/html/sdk/adt_download.jd
@@ -22,10 +22,17 @@ ADT Installation</a>.</p>
<th>Notes</th>
</tr>
<tr>
+ <td>0.9.9</td>
+ <td><a href="http://dl-ssl.google.com/android/ADT-0.9.9.zip">ADT-0.9.9.zip</a></td>
+ <td><nobr>8301681 bytes</nobr></td>
+ <td>7deff0c9b25940a74cea7a0815a3bc36</td>
+ <td>Requires SDK Tools, Revision 7 <em><nobr>September 2010</nobr></em></td>
+ </tr>
+ <tr>
<td>0.9.8</td>
<td><a href="http://dl-ssl.google.com/android/ADT-0.9.8.zip">ADT-0.9.8.zip</a></td>
- <td><nobr>8703591 bytes</nobr></td>
- <td>22070f8e52924605a3b3abf87c1ba39f</td>
+ <td><nobr>8301417 bytes</nobr></td>
+ <td>27e0de800512f13feae46fb554e6ee2f</td>
<td>Requires SDK Tools, Revision 7 <em><nobr>September 2010</nobr></em></td>
</tr>
<tr>
diff --git a/docs/html/sdk/eclipse-adt.jd b/docs/html/sdk/eclipse-adt.jd
index a984d56..9f3c8b0 100644
--- a/docs/html/sdk/eclipse-adt.jd
+++ b/docs/html/sdk/eclipse-adt.jd
@@ -1,9 +1,9 @@
page.title=ADT Plugin for Eclipse
sdk.preview=0
-adt.zip.version=0.9.8
-adt.zip.download=ADT-0.9.8.zip
-adt.zip.bytes=8703591
-adt.zip.checksum=22070f8e52924605a3b3abf87c1ba39f
+adt.zip.version=0.9.9
+adt.zip.download=ADT-0.9.9.zip
+adt.zip.bytes=8301681
+adt.zip.checksum=7deff0c9b25940a74cea7a0815a3bc36
@jd:body
@@ -100,11 +100,40 @@ padding: .25em 1em;
</style>
-
-
<div class="toggleable opened">
<a href="#" onclick="return toggleDiv(this)">
<img src="{@docRoot}assets/images/triangle-opened.png" class="toggle-img" height="9px" width="9px" />
+ADT 0.9.9</a> <em>(September 2010)</em>
+ <div class="toggleme">
+
+
+</ul>
+</dd>
+
+<dl>
+
+<dt>Dependencies:</dt>
+
+<dd><p>ADT 0.9.9 replaces ADT 0.9.8 and is designed for use with SDK Tools r7
+and later. ADT 0.9.9 includes the ADT 0.9.8 features as well as an important
+bugfix, so we recommend that you upgrade as soon as possible. If you haven't
+already installed SDK Tools r7 into your SDK, use the Android SDK Manager to do
+so.</p></dd>
+
+<dt>General notes:</dt>
+<dd>
+<ul>
+<li>Fixes a problem in project import, in which source files were deleted in some cases.</li>
+<li>Includes all other ADT 0.9.8 features (see below).</li>
+</ul>
+</dd>
+</dl>
+ </div>
+</div>
+
+<div class="toggleable closed">
+ <a href="#" onclick="return toggleDiv(this)">
+ <img src="{@docRoot}assets/images/triangle-closed.png" class="toggle-img" height="9px" width="9px" />
ADT 0.9.8</a> <em>(September 2010)</em>
<div class="toggleme">
@@ -116,9 +145,7 @@ ADT 0.9.8</a> <em>(September 2010)</em>
<dt>Dependencies:</dt>
-<dd><p>ADT 0.9.8 is designed for use with SDK Tools r7 and later. Before
-updating to ADT 0.9.8, we highly recommend that you use the Android SDK and
-AVD Manager to install SDK Tools r7 into your SDK.</p></dd>
+<dd><p>ADT 0.9.8 is now deprecated. Please use ADT 0.9.9 instead.</p></dd>
<dt>General notes:</dt>
<dd>
diff --git a/docs/html/sdk/requirements.jd b/docs/html/sdk/requirements.jd
index d710b8e..7b11654 100644
--- a/docs/html/sdk/requirements.jd
+++ b/docs/html/sdk/requirements.jd
@@ -6,7 +6,7 @@ Android applications using the Android SDK. </p>
<h3>Supported Operating Systems</h3>
<ul>
- <li>Windows XP (32-bit) or Vista (32- or 64-bit)</li>
+ <li>Windows XP (32-bit), Vista (32- or 64-bit), or Windows 7 (32- or 64-bit)</li>
<li>Mac OS X 10.5.8 or later (x86 only)</li>
<li>Linux (tested on Linux Ubuntu Hardy Heron)
<ul>
diff --git a/docs/html/sdk/sdk_toc.cs b/docs/html/sdk/sdk_toc.cs
index a665e95..fdf4438 100644
--- a/docs/html/sdk/sdk_toc.cs
+++ b/docs/html/sdk/sdk_toc.cs
@@ -94,7 +94,7 @@
<span style="display:none" class="zh-TW"></span>
</h2>
<ul>
- <li><a href="<?cs var:toroot ?>sdk/eclipse-adt.html">ADT 0.9.8
+ <li><a href="<?cs var:toroot ?>sdk/eclipse-adt.html">ADT 0.9.9
<span style="display:none" class="de"></span>
<span style="display:none" class="es"></span>
<span style="display:none" class="fr"></span>
diff --git a/media/libstagefright/MPEG4Writer.cpp b/media/libstagefright/MPEG4Writer.cpp
index f0d8943..ba1e218 100644
--- a/media/libstagefright/MPEG4Writer.cpp
+++ b/media/libstagefright/MPEG4Writer.cpp
@@ -2111,7 +2111,15 @@ void MPEG4Writer::Track::writeTrackHeader(
mOwner->endBox(); // d263
} else if (!strcasecmp(MEDIA_MIMETYPE_VIDEO_AVC, mime)) {
CHECK(mCodecSpecificData);
- CHECK(mCodecSpecificDataSize > 0);
+ CHECK(mCodecSpecificDataSize >= 5);
+
+ // Patch avcc's lengthSize field to match the number
+ // of bytes we use to indicate the size of a nal unit.
+ uint8_t *ptr = (uint8_t *)mCodecSpecificData;
+ ptr[4] =
+ (ptr[4] & 0xfc)
+ | (mOwner->useNalLengthFour() ? 3 : 1);
+
mOwner->beginBox("avcC");
mOwner->write(mCodecSpecificData, mCodecSpecificDataSize);
mOwner->endBox(); // avcC
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarIconView.java b/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarIconView.java
index d98bd7d..0ca0572 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarIconView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarIconView.java
@@ -22,6 +22,7 @@ import android.content.res.Resources;
import android.graphics.drawable.Drawable;
import android.graphics.Canvas;
import android.util.Slog;
+import android.util.Log;
import android.view.ViewDebug;
import android.widget.FrameLayout;
@@ -124,4 +125,10 @@ public class StatusBarIconView extends AnimatedImageView {
public StatusBarIcon getStatusBarIcon() {
return mIcon;
}
+
+ protected void debug(int depth) {
+ super.debug(depth);
+ Log.d("View", debugIndent(depth) + "slot=" + mSlot);
+ Log.d("View", debugIndent(depth) + "icon=" + mIcon);
+ }
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarService.java b/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarService.java
index b555277..fece5ce 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarService.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarService.java
@@ -82,7 +82,8 @@ import com.android.systemui.statusbar.policy.StatusBarPolicy;
public class StatusBarService extends Service implements CommandQueue.Callbacks {
static final String TAG = "StatusBarService";
- static final boolean SPEW = true;
+ static final boolean SPEW_ICONS = true;
+ static final boolean SPEW = false;
public static final String ACTION_STATUSBAR_START
= "com.android.internal.policy.statusbar.START";
@@ -346,8 +347,10 @@ public class StatusBarService extends Service implements CommandQueue.Callbacks
}
public void addIcon(String slot, int index, int viewIndex, StatusBarIcon icon) {
- if (SPEW) Slog.d(TAG, "addIcon slot=" + slot + " index=" + index + " viewIndex=" + viewIndex
- + " icon=" + icon);
+ if (SPEW_ICONS) {
+ Slog.d(TAG, "addIcon slot=" + slot + " index=" + index + " viewIndex=" + viewIndex
+ + " icon=" + icon);
+ }
StatusBarIconView view = new StatusBarIconView(this, slot);
view.set(icon);
mStatusIcons.addView(view, viewIndex, new LinearLayout.LayoutParams(mIconSize, mIconSize));
@@ -355,14 +358,18 @@ public class StatusBarService extends Service implements CommandQueue.Callbacks
public void updateIcon(String slot, int index, int viewIndex,
StatusBarIcon old, StatusBarIcon icon) {
- if (SPEW) Slog.d(TAG, "updateIcon slot=" + slot + " index=" + index + " viewIndex=" + viewIndex
- + " old=" + old + " icon=" + icon);
+ if (SPEW_ICONS) {
+ Slog.d(TAG, "updateIcon slot=" + slot + " index=" + index + " viewIndex=" + viewIndex
+ + " old=" + old + " icon=" + icon);
+ }
StatusBarIconView view = (StatusBarIconView)mStatusIcons.getChildAt(viewIndex);
view.set(icon);
}
public void removeIcon(String slot, int index, int viewIndex) {
- if (SPEW) Slog.d(TAG, "removeIcon slot=" + slot + " index=" + index + " viewIndex=" + viewIndex);
+ if (SPEW_ICONS) {
+ Slog.d(TAG, "removeIcon slot=" + slot + " index=" + index + " viewIndex=" + viewIndex);
+ }
mStatusIcons.removeViewAt(viewIndex);
}
@@ -1175,50 +1182,17 @@ public class StatusBarService extends Service implements CommandQueue.Callbacks
+ " scroll " + mScrollView.getScrollX() + "," + mScrollView.getScrollY());
pw.println("mNotificationLinearLayout: " + viewInfo(mNotificationLinearLayout));
}
- /*
- synchronized (mNotificationData) {
- int N = mNotificationData.ongoingCount();
- pw.println(" ongoingCount.size=" + N);
- for (int i=0; i<N; i++) {
- StatusBarNotification n = mNotificationData.getOngoing(i);
- pw.println(" [" + i + "] key=" + n.key + " view=" + n.view);
- pw.println(" data=" + n.data);
- }
- N = mNotificationData.latestCount();
- pw.println(" ongoingCount.size=" + N);
- for (int i=0; i<N; i++) {
- StatusBarNotification n = mNotificationData.getLatest(i);
- pw.println(" [" + i + "] key=" + n.key + " view=" + n.view);
- pw.println(" data=" + n.data);
- }
- }
- */
- if (false) {
- pw.println("see the logcat for a dump of the views we have created.");
+ if (true) {
// must happen on ui thread
mHandler.post(new Runnable() {
public void run() {
- mStatusBarView.getLocationOnScreen(mAbsPos);
- Slog.d(TAG, "mStatusBarView: ----- (" + mAbsPos[0] + "," + mAbsPos[1]
- + ") " + mStatusBarView.getWidth() + "x"
- + mStatusBarView.getHeight());
- mStatusBarView.debug();
-
- mExpandedView.getLocationOnScreen(mAbsPos);
- Slog.d(TAG, "mExpandedView: ----- (" + mAbsPos[0] + "," + mAbsPos[1]
- + ") " + mExpandedView.getWidth() + "x"
- + mExpandedView.getHeight());
- mExpandedView.debug();
-
- mTrackingView.getLocationOnScreen(mAbsPos);
- Slog.d(TAG, "mTrackingView: ----- (" + mAbsPos[0] + "," + mAbsPos[1]
- + ") " + mTrackingView.getWidth() + "x"
- + mTrackingView.getHeight());
- mTrackingView.debug();
+ Slog.d(TAG, "mStatusIcons:");
+ mStatusIcons.debug();
}
});
}
+
}
void onBarViewAttached() {
diff --git a/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java b/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java
index 274124b..384f527 100755
--- a/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java
+++ b/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java
@@ -232,8 +232,11 @@ public class PhoneWindowManager implements WindowManagerPolicy {
@Override
public void handleMotion(MotionEvent event, Runnable finishedCallback) {
finishedCallback.run();
+
synchronized (mLock) {
- mPointerLocationView.addTouchEvent(event);
+ if (mPointerLocationView != null) {
+ mPointerLocationView.addTouchEvent(event);
+ }
}
}
};
@@ -283,7 +286,8 @@ public class PhoneWindowManager implements WindowManagerPolicy {
// (See Settings.Secure.INCALL_POWER_BUTTON_BEHAVIOR.)
int mIncallPowerBehavior;
- int mLandscapeRotation = -1;
+ int mLandscapeRotation = -1; // default landscape rotation
+ int mSeascapeRotation = -1; // "other" landscape rotation, 180 degrees from mLandscapeRotation
int mPortraitRotation = -1;
// Nothing to see here, move along...
@@ -353,9 +357,12 @@ public class PhoneWindowManager implements WindowManagerPolicy {
return true;
}
// The user preference says we can rotate, and the app is willing to rotate.
+ // Note we include SCREEN_ORIENTATION_LANDSCAPE since we can use the sensor to choose
+ // between the two possible landscape rotations.
if (mAccelerometerDefault != 0 &&
(appOrientation == ActivityInfo.SCREEN_ORIENTATION_USER
- || appOrientation == ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED)) {
+ || appOrientation == ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED
+ || appOrientation == ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE)) {
return true;
}
// We're in a dock that has a rotation affinity, an the app is willing to rotate.
@@ -364,7 +371,8 @@ public class PhoneWindowManager implements WindowManagerPolicy {
// Note we override the nosensor flag here.
if (appOrientation == ActivityInfo.SCREEN_ORIENTATION_USER
|| appOrientation == ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED
- || appOrientation == ActivityInfo.SCREEN_ORIENTATION_NOSENSOR) {
+ || appOrientation == ActivityInfo.SCREEN_ORIENTATION_NOSENSOR
+ || appOrientation == ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE) {
return true;
}
}
@@ -2050,20 +2058,20 @@ public class PhoneWindowManager implements WindowManagerPolicy {
if (d.getWidth() > d.getHeight()) {
mPortraitRotation = Surface.ROTATION_90;
mLandscapeRotation = Surface.ROTATION_0;
+ mSeascapeRotation = Surface.ROTATION_180;
} else {
mPortraitRotation = Surface.ROTATION_0;
mLandscapeRotation = Surface.ROTATION_90;
+ mSeascapeRotation = Surface.ROTATION_270;
}
}
synchronized (mLock) {
- switch (orientation) {
- case ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE:
- //always return landscape if orientation set to landscape
- return mLandscapeRotation;
- case ActivityInfo.SCREEN_ORIENTATION_PORTRAIT:
- //always return portrait if orientation set to portrait
- return mPortraitRotation;
+ if (orientation == ActivityInfo.SCREEN_ORIENTATION_PORTRAIT) {
+ //always return portrait if orientation set to portrait
+ return mPortraitRotation;
+ } else if (orientation == ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE) {
+ return getCurrentLandscapeRotation(lastRotation);
}
// case for nosensor meaning ignore sensor and consider only lid
// or orientation sensor disabled
@@ -2083,6 +2091,26 @@ public class PhoneWindowManager implements WindowManagerPolicy {
}
}
+ private int getCurrentLandscapeRotation(int lastRotation) {
+ // landscape-only apps can take either landscape rotation
+ if (useSensorForOrientationLp(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE)) {
+ int sensorRotation = mOrientationListener.getCurrentRotation(lastRotation);
+ if (isLandscapeOrSeascape(sensorRotation)) {
+ return sensorRotation;
+ }
+ }
+ // try to preserve the old rotation if it was landscape
+ if (isLandscapeOrSeascape(lastRotation)) {
+ return lastRotation;
+ }
+ // default to one of the two landscape rotations
+ return mLandscapeRotation;
+ }
+
+ private boolean isLandscapeOrSeascape(int sensorRotation) {
+ return sensorRotation == mLandscapeRotation || sensorRotation == mSeascapeRotation;
+ }
+
public boolean detectSafeMode() {
try {
int menuState = mWindowManager.getKeycodeState(KeyEvent.KEYCODE_MENU);
diff --git a/services/java/com/android/server/ProcessStats.java b/services/java/com/android/server/ProcessStats.java
index 0c8c2fd..020f9ed 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/am/ActivityManagerService.java b/services/java/com/android/server/am/ActivityManagerService.java
index 4f0d2d5..ff650ec 100644
--- a/services/java/com/android/server/am/ActivityManagerService.java
+++ b/services/java/com/android/server/am/ActivityManagerService.java
@@ -121,6 +121,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;
@@ -144,6 +146,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;
@@ -152,6 +155,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;
@@ -197,8 +202,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;
@@ -779,9 +792,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
@@ -1194,12 +1212,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;
}
@@ -1394,7 +1410,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(
@@ -1514,10 +1531,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;
@@ -1528,6 +1547,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);
@@ -1564,7 +1584,7 @@ public final class ActivityManagerService extends ActivityManagerNative
updateCpuStatsNow();
synchronized (this) {
synchronized(mPidsSelfLocked) {
- mOnBattery = onBattery;
+ mOnBattery = DEBUG_POWER ? true : onBattery;
}
}
}
@@ -2790,6 +2810,16 @@ public final class ActivityManagerService extends ActivityManagerNative
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();
@@ -2840,10 +2870,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);
@@ -2859,6 +2885,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();
@@ -3735,7 +3765,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,
@@ -5648,10 +5678,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);
}
}
@@ -5701,7 +5731,6 @@ public final class ActivityManagerService extends ActivityManagerNative
mWindowManager.setEventDispatching(true);
mSleeping = false;
mMainStack.resumeTopActivityLocked(null);
- mHandler.removeMessages(CHECK_EXCESSIVE_WAKE_LOCKS_MSG);
}
}
@@ -6998,12 +7027,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 {
@@ -7035,6 +7065,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);
@@ -7150,7 +7185,7 @@ public final class ActivityManagerService extends ActivityManagerNative
return true;
}
-
+
boolean dumpProcessesLocked(FileDescriptor fd, PrintWriter pw, String[] args,
int opti, boolean dumpAll) {
boolean needSep = false;
@@ -7180,8 +7215,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;
}
@@ -7212,7 +7247,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) {
@@ -7220,7 +7255,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) {
@@ -7228,7 +7263,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) {
@@ -7236,26 +7271,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(" ");
@@ -7319,6 +7338,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);
@@ -7327,6 +7352,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
@@ -7694,89 +7788,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,
@@ -8405,7 +8555,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) {
@@ -8443,8 +8597,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);
@@ -8477,9 +8630,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;
@@ -8514,8 +8665,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;
@@ -8767,9 +8917,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,
@@ -8820,12 +8968,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);
@@ -9281,9 +9424,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;
@@ -9504,14 +9645,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);
@@ -9621,20 +9768,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);
}
}
@@ -11187,6 +11334,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);
}
@@ -11194,6 +11342,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;
@@ -11323,6 +11472,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)) {
@@ -11356,6 +11508,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;
@@ -11389,7 +11544,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
@@ -11431,6 +11586,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;
@@ -11450,6 +11608,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;
}
@@ -11467,6 +11626,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;
@@ -11604,57 +11766,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;
}
}
}
@@ -11668,6 +11872,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()) {
@@ -11682,13 +11888,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/SipSessionGroup.java b/services/java/com/android/server/sip/SipSessionGroup.java
index b4c2241..03a076c 100644
--- a/services/java/com/android/server/sip/SipSessionGroup.java
+++ b/services/java/com/android/server/sip/SipSessionGroup.java
@@ -349,6 +349,9 @@ class SipSessionGroup implements SipListener {
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;
}
@@ -625,6 +628,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;
diff --git a/tests/BatteryWaster/src/com/android/batterywaster/BatteryWaster.java b/tests/BatteryWaster/src/com/android/batterywaster/BatteryWaster.java
index 48c4520..5fb09a7 100644
--- a/tests/BatteryWaster/src/com/android/batterywaster/BatteryWaster.java
+++ b/tests/BatteryWaster/src/com/android/batterywaster/BatteryWaster.java
@@ -25,6 +25,7 @@ import android.os.BatteryManager;
import android.os.Bundle;
import android.os.PowerManager;
import android.view.View;
+import android.view.WindowManager;
import android.widget.CheckBox;
import android.widget.TextView;
@@ -38,7 +39,6 @@ public class BatteryWaster extends Activity {
TextView mLog;
DateFormat mDateFormat;
IntentFilter mFilter;
- PowerManager.WakeLock mWakeLock;
PowerManager.WakeLock mPartialWakeLock;
SpinThread mThread;
@@ -65,24 +65,26 @@ public class BatteryWaster extends Activity {
mFilter.addAction(Intent.ACTION_POWER_CONNECTED);
PowerManager pm = (PowerManager)getSystemService(POWER_SERVICE);
- mWakeLock = pm.newWakeLock(PowerManager.FULL_WAKE_LOCK, "BatteryWaster");
- mWakeLock.setReferenceCounted(false);
mPartialWakeLock = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "BatteryWaster");
mPartialWakeLock.setReferenceCounted(false);
}
@Override
- public void onPause() {
- super.onPause();
- stopRunning();
+ public void onResume() {
+ super.onResume();
+ if (((CheckBox)findViewById(R.id.checkbox)).isChecked()) {
+ startRunning();
+ }
+ if (((CheckBox)findViewById(R.id.checkbox_wake)).isChecked()) {
+ mWaking = true;
+ updateWakeLock();
+ }
}
@Override
public void onDestroy() {
super.onDestroy();
- if (mWakeLock.isHeld()) {
- mWakeLock.release();
- }
+ stopRunning();
if (mPartialWakeLock.isHeld()) {
mPartialWakeLock.release();
}
@@ -140,13 +142,9 @@ public class BatteryWaster extends Activity {
void updateWakeLock() {
if (mWasting) {
- if (!mWakeLock.isHeld()) {
- mWakeLock.acquire();
- }
+ getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
} else {
- if (mWakeLock.isHeld()) {
- mWakeLock.release();
- }
+ getWindow().clearFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
}
if (mWaking) {
if (!mPartialWakeLock.isHeld()) {
diff --git a/tools/aapt/Bundle.h b/tools/aapt/Bundle.h
index a1bc241..c5aa573 100644
--- a/tools/aapt/Bundle.h
+++ b/tools/aapt/Bundle.h
@@ -45,7 +45,7 @@ public:
mRClassDir(NULL), mResourceIntermediatesDir(NULL), mManifestMinSdkVersion(NULL),
mMinSdkVersion(NULL), mTargetSdkVersion(NULL), mMaxSdkVersion(NULL),
mVersionCode(NULL), mVersionName(NULL), mCustomPackage(NULL),
- mMaxResVersion(NULL), mDebugMode(false),
+ mMaxResVersion(NULL), mDebugMode(false), mProduct(NULL),
mArgc(0), mArgv(NULL)
{}
~Bundle(void) {}
@@ -139,6 +139,8 @@ public:
void setMaxResVersion(const char * val) { mMaxResVersion = val; }
bool getDebugMode() { return mDebugMode; }
void setDebugMode(bool val) { mDebugMode = val; }
+ const char* getProduct() const { return mProduct; }
+ void setProduct(const char * val) { mProduct = val; }
/*
* Set and get the file specification.
@@ -237,6 +239,7 @@ private:
const char* mCustomPackage;
const char* mMaxResVersion;
bool mDebugMode;
+ const char* mProduct;
/* file specification */
int mArgc;
diff --git a/tools/aapt/Main.cpp b/tools/aapt/Main.cpp
index 71c023d..739b01f 100644
--- a/tools/aapt/Main.cpp
+++ b/tools/aapt/Main.cpp
@@ -67,6 +67,7 @@ void usage(void)
" [-A asset-source-dir] [-G class-list-file] [-P public-definitions-file] \\\n"
" [-S resource-sources [-S resource-sources ...]] "
" [-F apk-file] [-J R-file-dir] \\\n"
+ " [--product product1,product2,...] \\\n"
" [raw-files-dir [raw-files-dir] ...]\n"
"\n"
" Package the android resources. It will read assets and resources that are\n"
@@ -154,6 +155,9 @@ void usage(void)
" components target the given package. Useful when used in\n"
" conjunction with --rename-manifest-package to fix tests against\n"
" a package that has been renamed.\n"
+ " --product\n"
+ " Specifies which variant to choose for strings that have\n"
+ " product variants\n"
" --utf16\n"
" changes default encoding for resources to UTF-16. Only useful when API\n"
" level is set to 7 or higher where the default encoding is UTF-8.\n");
@@ -484,6 +488,15 @@ int main(int argc, char* const argv[])
bundle.setInstrumentationPackageNameOverride(argv[0]);
} else if (strcmp(cp, "-auto-add-overlay") == 0) {
bundle.setAutoAddOverlay(true);
+ } else if (strcmp(cp, "-product") == 0) {
+ argc--;
+ argv++;
+ if (!argc) {
+ fprintf(stderr, "ERROR: No argument supplied for '--product' option\n");
+ wantUsage = true;
+ goto bail;
+ }
+ bundle.setProduct(argv[0]);
} else {
fprintf(stderr, "ERROR: Unknown option '-%s'\n", cp);
wantUsage = true;
diff --git a/tools/aapt/ResourceTable.cpp b/tools/aapt/ResourceTable.cpp
index 755b93b..532fb65 100644
--- a/tools/aapt/ResourceTable.cpp
+++ b/tools/aapt/ResourceTable.cpp
@@ -574,6 +574,7 @@ status_t parseAndAddBag(Bundle* bundle,
const String16& itemIdent,
int32_t curFormat,
bool isFormatted,
+ const String16& product,
bool pseudolocalize,
const bool overwrite,
ResourceTable* outTable)
@@ -606,6 +607,32 @@ status_t parseAndAddBag(Bundle* bundle,
return err;
}
+/*
+ * Returns true if needle is one of the elements in the comma-separated list
+ * haystack, false otherwise.
+ */
+bool isInProductList(const String16& needle, const String16& haystack) {
+ const char16_t *needle2 = needle.string();
+ const char16_t *haystack2 = haystack.string();
+ size_t needlesize = needle.size();
+
+ while (*haystack2 != '\0') {
+ if (strncmp16(haystack2, needle2, needlesize) == 0) {
+ if (haystack2[needlesize] == '\0' || haystack2[needlesize] == ',') {
+ return true;
+ }
+ }
+
+ while (*haystack2 != '\0' && *haystack2 != ',') {
+ haystack2++;
+ }
+ if (*haystack2 == ',') {
+ haystack2++;
+ }
+ }
+
+ return false;
+}
status_t parseAndAddEntry(Bundle* bundle,
const sp<AaptFile>& in,
@@ -618,6 +645,7 @@ status_t parseAndAddEntry(Bundle* bundle,
bool curIsStyled,
int32_t curFormat,
bool isFormatted,
+ const String16& product,
bool pseudolocalize,
const bool overwrite,
ResourceTable* outTable)
@@ -634,6 +662,47 @@ status_t parseAndAddEntry(Bundle* bundle,
return err;
}
+ /*
+ * If a product type was specified on the command line
+ * and also in the string, and the two are not the same,
+ * return without adding the string.
+ */
+
+ const char *bundleProduct = bundle->getProduct();
+ if (bundleProduct == NULL) {
+ bundleProduct = "";
+ }
+
+ if (product.size() != 0) {
+ /*
+ * If the command-line-specified product is empty, only "default"
+ * matches. Other variants are skipped. This is so generation
+ * of the R.java file when the product is not known is predictable.
+ */
+
+ if (bundleProduct[0] == '\0') {
+ if (strcmp16(String16("default").string(), product.string()) != 0) {
+ return NO_ERROR;
+ }
+ } else {
+ /*
+ * The command-line product is not empty.
+ * If the product for this string is on the command-line list,
+ * it matches. "default" also matches, but only if nothing
+ * else has matched already.
+ */
+
+ if (isInProductList(product, String16(bundleProduct))) {
+ ;
+ } else if (strcmp16(String16("default").string(), product.string()) == 0 &&
+ !outTable->hasBagOrEntry(myPackage, curType, ident)) {
+ ;
+ } else {
+ return NO_ERROR;
+ }
+ }
+ }
+
NOISY(printf("Adding resource entry l=%c%c c=%c%c orien=%d d=%d id=%s: %s\n",
config.language[0], config.language[1],
config.country[0], config.country[1],
@@ -713,6 +782,7 @@ status_t compileResourceFile(Bundle* bundle,
const String16 translatable16("translatable");
const String16 formatted16("formatted");
const String16 false16("false");
+ const String16 product16("product");
const String16 myPackage(assets->getPackage());
@@ -760,6 +830,7 @@ status_t compileResourceFile(Bundle* bundle,
bool curIsStyled = false;
bool curIsPseudolocalizable = false;
bool curIsFormatted = fileIsTranslatable;
+ String16 curProduct;
bool localHasErrors = false;
if (strcmp16(block.getElementName(&len), skip16.string()) == 0) {
@@ -1157,6 +1228,8 @@ status_t compileResourceFile(Bundle* bundle,
translatable.setTo(block.getAttributeStringValue(i, &length));
} else if (strcmp16(attr, formatted16.string()) == 0) {
formatted.setTo(block.getAttributeStringValue(i, &length));
+ } else if (strcmp16(attr, product16.string()) == 0) {
+ curProduct.setTo(block.getAttributeStringValue(i, &length));
}
}
@@ -1374,7 +1447,7 @@ status_t compileResourceFile(Bundle* bundle,
err = parseAndAddBag(bundle, in, &block, curParams, myPackage, curType,
ident, parentIdent, itemIdent, curFormat, curIsFormatted,
- false, overwrite, outTable);
+ curProduct, false, overwrite, outTable);
if (err == NO_ERROR) {
if (curIsPseudolocalizable && localeIsDefined(curParams)
&& bundle->getPseudolocalize()) {
@@ -1383,7 +1456,7 @@ status_t compileResourceFile(Bundle* bundle,
block.setPosition(parserPosition);
err = parseAndAddBag(bundle, in, &block, pseudoParams, myPackage,
curType, ident, parentIdent, itemIdent, curFormat,
- curIsFormatted, true, overwrite, outTable);
+ curIsFormatted, curProduct, true, overwrite, outTable);
#endif
}
}
@@ -1407,7 +1480,7 @@ status_t compileResourceFile(Bundle* bundle,
err = parseAndAddEntry(bundle, in, &block, curParams, myPackage, curType, ident,
*curTag, curIsStyled, curFormat, curIsFormatted,
- false, overwrite, outTable);
+ curProduct, false, overwrite, outTable);
if (err < NO_ERROR) { // Why err < NO_ERROR instead of err != NO_ERROR?
hasErrors = localHasErrors = true;
@@ -1419,7 +1492,8 @@ status_t compileResourceFile(Bundle* bundle,
block.setPosition(parserPosition);
err = parseAndAddEntry(bundle, in, &block, pseudoParams, myPackage, curType,
ident, *curTag, curIsStyled, curFormat,
- curIsFormatted, true, overwrite, outTable);
+ curIsFormatted, curProduct,
+ true, overwrite, outTable);
if (err != NO_ERROR) {
hasErrors = localHasErrors = true;
}