Merge "Ensure that activities behind keyguard are paused." into klp-dev
diff --git a/api/current.txt b/api/current.txt
index 49ce637..fd9f0be 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -3167,31 +3167,27 @@
}
public class AppOpsManager {
- method public int checkOp(int, int, java.lang.String);
- method public int checkOpNoThrow(int, int, java.lang.String);
+ method public int checkOp(java.lang.String, int, java.lang.String);
+ method public int checkOpNoThrow(java.lang.String, int, java.lang.String);
method public void checkPackage(int, java.lang.String);
- method public void finishOp(int, int, java.lang.String);
- method public void finishOp(int);
- method public int noteOp(int, int, java.lang.String);
- method public int noteOpNoThrow(int, int, java.lang.String);
- method public static java.lang.String opToName(int);
- method public int startOp(int, int, java.lang.String);
- method public int startOpNoThrow(int, int, java.lang.String);
- method public void startWatchingMode(int, java.lang.String, android.app.AppOpsManager.Callback);
- method public void stopWatchingMode(android.app.AppOpsManager.Callback);
+ method public void finishOp(java.lang.String, int, java.lang.String);
+ method public int noteOp(java.lang.String, int, java.lang.String);
+ method public int noteOpNoThrow(java.lang.String, int, java.lang.String);
+ method public int startOp(java.lang.String, int, java.lang.String);
+ method public int startOpNoThrow(java.lang.String, int, java.lang.String);
+ method public void startWatchingMode(int, java.lang.String, android.app.AppOpsManager.OnOpChangedListener);
+ method public void stopWatchingMode(android.app.AppOpsManager.OnOpChangedListener);
field public static final int MODE_ALLOWED = 0; // 0x0
field public static final int MODE_ERRORED = 2; // 0x2
field public static final int MODE_IGNORED = 1; // 0x1
- field public static final int OP_COARSE_LOCATION = 0; // 0x0
- field public static final int OP_FINE_LOCATION = 1; // 0x1
- field public static final int OP_GPS = 2; // 0x2
- field public static final int OP_MONITOR_HIGH_POWER_LOCATION = 42; // 0x2a
- field public static final int OP_MONITOR_LOCATION = 41; // 0x29
- field public static final int OP_NONE = -1; // 0xffffffff
+ field public static final java.lang.String OPSTR_COARSE_LOCATION = "android:coarse_location";
+ field public static final java.lang.String OPSTR_FINE_LOCATION = "android:fine_location";
+ field public static final java.lang.String OPSTR_MONITOR_HIGH_POWER_LOCATION = "android:monitor_location_high_power";
+ field public static final java.lang.String OPSTR_MONITOR_LOCATION = "android:monitor_location";
}
- public static abstract interface AppOpsManager.Callback {
- method public abstract void opChanged(int, java.lang.String);
+ public static abstract interface AppOpsManager.OnOpChangedListener {
+ method public abstract void onOpChanged(java.lang.String, java.lang.String);
}
public class Application extends android.content.ContextWrapper implements android.content.ComponentCallbacks2 {
diff --git a/core/java/android/app/AppOpsManager.java b/core/java/android/app/AppOpsManager.java
index bf2a1e4..055044b 100644
--- a/core/java/android/app/AppOpsManager.java
+++ b/core/java/android/app/AppOpsManager.java
@@ -23,6 +23,7 @@
import com.android.internal.app.IAppOpsCallback;
import java.util.ArrayList;
+import java.util.HashMap;
import java.util.List;
import android.content.Context;
@@ -32,50 +33,76 @@
import android.os.RemoteException;
/**
- * API for interacting with "application operation" tracking. Allows you to:
+ * API for interacting with "application operation" tracking.
*
- * <ul>
- * <li> Note when operations are happening, and find out if they are allowed for the current
- * caller.</li>
- * <li> Disallow specific apps from doing specific operations.</li>
- * <li> Collect all of the current information about operations that have been executed or are not
- * being allowed.</li>
- * <li> Monitor for changes in whether an operation is allowed.</li>
- * </ul>
- *
- * <p>Each operation is identified by a single integer; these integers are a fixed set of
- * operations, enumerated by the OP_* constants.
- *
- * <p></p>When checking operations, the result is a "mode" integer indicating the current setting
- * for the operation under that caller: MODE_ALLOWED, MODE_IGNORED (don't execute the operation but
- * fake its behavior enough so that the caller doesn't crash), MODE_ERRORED (through a
- * SecurityException back to the caller; the normal operation calls will do this for you).
+ * <p>This API is not generally intended for third party application developers; most
+ * features are only available to system applicatins. Obtain an instance of it through
+ * {@link Context#getSystemService(String) Context.getSystemService} with
+ * {@link Context#APP_OPS_SERVICE Context.APP_OPS_SERVICE}.</p>
*/
public class AppOpsManager {
+ /**
+ * <p>App ops allows callers to:</p>
+ *
+ * <ul>
+ * <li> Note when operations are happening, and find out if they are allowed for the current
+ * caller.</li>
+ * <li> Disallow specific apps from doing specific operations.</li>
+ * <li> Collect all of the current information about operations that have been executed or
+ * are not being allowed.</li>
+ * <li> Monitor for changes in whether an operation is allowed.</li>
+ * </ul>
+ *
+ * <p>Each operation is identified by a single integer; these integers are a fixed set of
+ * operations, enumerated by the OP_* constants.
+ *
+ * <p></p>When checking operations, the result is a "mode" integer indicating the current
+ * setting for the operation under that caller: MODE_ALLOWED, MODE_IGNORED (don't execute
+ * the operation but fake its behavior enough so that the caller doesn't crash),
+ * MODE_ERRORED (throw a SecurityException back to the caller; the normal operation calls
+ * will do this for you).
+ */
+
final Context mContext;
final IAppOpsService mService;
- final ArrayMap<Callback, IAppOpsCallback> mModeWatchers
- = new ArrayMap<Callback, IAppOpsCallback>();
+ final ArrayMap<OnOpChangedListener, IAppOpsCallback> mModeWatchers
+ = new ArrayMap<OnOpChangedListener, IAppOpsCallback>();
static IBinder sToken;
+ /**
+ * Result from {@link #checkOp}, {@link #noteOp}, {@link #startOp}: the given caller is
+ * allowed to perform the given operation.
+ */
public static final int MODE_ALLOWED = 0;
+
+ /**
+ * Result from {@link #checkOp}, {@link #noteOp}, {@link #startOp}: the given caller is
+ * not allowed to perform the given operation, and this attempt should
+ * <em>silently fail</em> (it should not cause the app to crash).
+ */
public static final int MODE_IGNORED = 1;
+
+ /**
+ * Result from {@link #checkOpNoThrow}, {@link #noteOpNoThrow}, {@link #startOpNoThrow}: the
+ * given caller is not allowed to perform the given operation, and this attempt should
+ * cause it to have a fatal error, typically a {@link SecurityException}.
+ */
public static final int MODE_ERRORED = 2;
// when adding one of these:
// - increment _NUM_OP
- // - add rows to sOpToSwitch, sOpNames, sOpPerms, sOpDefaultMode
+ // - add rows to sOpToSwitch, sOpToString, sOpNames, sOpPerms, sOpDefaultMode
// - add descriptive strings to Settings/res/values/arrays.xml
// - add the op to the appropriate template in AppOpsState.OpsTemplate (settings app)
- /** No operation specified. */
+ /** @hide No operation specified. */
public static final int OP_NONE = -1;
- /** Access to coarse location information. */
+ /** @hide Access to coarse location information. */
public static final int OP_COARSE_LOCATION = 0;
- /** Access to fine location information. */
+ /** @hide Access to fine location information. */
public static final int OP_FINE_LOCATION = 1;
- /** Causing GPS to run. */
+ /** @hide Causing GPS to run. */
public static final int OP_GPS = 2;
/** @hide */
public static final int OP_VIBRATE = 3;
@@ -153,13 +180,26 @@
public static final int OP_AUDIO_BLUETOOTH_VOLUME = 39;
/** @hide */
public static final int OP_WAKE_LOCK = 40;
- /** Continually monitoring location data. */
+ /** @hide Continually monitoring location data. */
public static final int OP_MONITOR_LOCATION = 41;
- /** Continually monitoring location data with a relatively high power request. */
+ /** @hide Continually monitoring location data with a relatively high power request. */
public static final int OP_MONITOR_HIGH_POWER_LOCATION = 42;
/** @hide */
public static final int _NUM_OP = 43;
+ /** Access to coarse location information. */
+ public static final String OPSTR_COARSE_LOCATION =
+ "android:coarse_location";
+ /** Access to fine location information. */
+ public static final String OPSTR_FINE_LOCATION =
+ "android:fine_location";
+ /** Continually monitoring location data. */
+ public static final String OPSTR_MONITOR_LOCATION
+ = "android:monitor_location";
+ /** Continually monitoring location data with a relatively high power request. */
+ public static final String OPSTR_MONITOR_HIGH_POWER_LOCATION
+ = "android:monitor_location_high_power";
+
/**
* This maps each operation to the operation that serves as the
* switch to determine whether it is allowed. Generally this is
@@ -215,6 +255,56 @@
};
/**
+ * This maps each operation to the public string constant for it.
+ * If it doesn't have a public string constant, it maps to null.
+ */
+ private static String[] sOpToString = new String[] {
+ OPSTR_COARSE_LOCATION,
+ OPSTR_FINE_LOCATION,
+ null,
+ null,
+ null,
+ null,
+ null,
+ null,
+ null,
+ null,
+ null,
+ null,
+ null,
+ null,
+ null,
+ null,
+ null,
+ null,
+ null,
+ null,
+ null,
+ null,
+ null,
+ null,
+ null,
+ null,
+ null,
+ null,
+ null,
+ null,
+ null,
+ null,
+ null,
+ null,
+ null,
+ null,
+ null,
+ null,
+ null,
+ null,
+ null,
+ OPSTR_MONITOR_LOCATION,
+ OPSTR_MONITOR_HIGH_POWER_LOCATION,
+ };
+
+ /**
* This provides a simple name for each operation to be used
* in debug output.
*/
@@ -363,6 +453,36 @@
AppOpsManager.MODE_ALLOWED,
};
+ private static HashMap<String, Integer> sOpStrToOp = new HashMap<String, Integer>();
+
+ static {
+ if (sOpToSwitch.length != _NUM_OP) {
+ throw new IllegalStateException("sOpStringLength " + sOpToSwitch.length
+ + " should be " + _NUM_OP);
+ }
+ if (sOpToString.length != _NUM_OP) {
+ throw new IllegalStateException("sOpStringLength " + sOpToString.length
+ + " should be " + _NUM_OP);
+ }
+ if (sOpNames.length != _NUM_OP) {
+ throw new IllegalStateException("sOpStringLength " + sOpNames.length
+ + " should be " + _NUM_OP);
+ }
+ if (sOpPerms.length != _NUM_OP) {
+ throw new IllegalStateException("sOpStringLength " + sOpPerms.length
+ + " should be " + _NUM_OP);
+ }
+ if (sOpDefaultMode.length != _NUM_OP) {
+ throw new IllegalStateException("sOpStringLength " + sOpDefaultMode.length
+ + " should be " + _NUM_OP);
+ }
+ for (int i=0; i<_NUM_OP; i++) {
+ if (sOpToString[i] != null) {
+ sOpStrToOp.put(sOpToString[i], i);
+ }
+ }
+ }
+
/**
* Retrieve the op switch that controls the given operation.
* @hide
@@ -373,6 +493,7 @@
/**
* Retrieve a non-localized name for the operation, for debugging output.
+ * @hide
*/
public static String opToName(int op) {
if (op == OP_NONE) return "NONE";
@@ -537,8 +658,18 @@
/**
* Callback for notification of changes to operation state.
*/
- public interface Callback {
- public void opChanged(int op, String packageName);
+ public interface OnOpChangedListener {
+ public void onOpChanged(String op, String packageName);
+ }
+
+ /**
+ * Callback for notification of changes to operation state.
+ * This allows you to see the raw op codes instead of strings.
+ * @hide
+ */
+ public static class OnOpChangedInternalListener implements OnOpChangedListener {
+ public void onOpChanged(String op, String packageName) { }
+ public void onOpChanged(int op, String packageName) { }
}
AppOpsManager(Context context, IAppOpsService service) {
@@ -598,13 +729,18 @@
* @param packageName The name of the application to monitor.
* @param callback Where to report changes.
*/
- public void startWatchingMode(int op, String packageName, final Callback callback) {
+ public void startWatchingMode(int op, String packageName, final OnOpChangedListener callback) {
synchronized (mModeWatchers) {
IAppOpsCallback cb = mModeWatchers.get(callback);
if (cb == null) {
cb = new IAppOpsCallback.Stub() {
public void opChanged(int op, String packageName) {
- callback.opChanged(op, packageName);
+ if (callback instanceof OnOpChangedInternalListener) {
+ ((OnOpChangedInternalListener)callback).onOpChanged(op, packageName);
+ }
+ if (sOpToString[op] != null) {
+ callback.onOpChanged(sOpToString[op], packageName);
+ }
}
};
mModeWatchers.put(callback, cb);
@@ -620,7 +756,7 @@
* Stop monitoring that was previously started with {@link #startWatchingMode}. All
* monitoring associated with this callback will be removed.
*/
- public void stopWatchingMode(Callback callback) {
+ public void stopWatchingMode(OnOpChangedListener callback) {
synchronized (mModeWatchers) {
IAppOpsCallback cb = mModeWatchers.get(callback);
if (cb != null) {
@@ -636,6 +772,106 @@
return packageName + " from uid " + uid + " not allowed to perform " + sOpNames[op];
}
+ private int strOpToOp(String op) {
+ Integer val = sOpStrToOp.get(op);
+ if (val == null) {
+ throw new IllegalArgumentException("Unknown operation string: " + op);
+ }
+ return val;
+ }
+
+ /**
+ * Do a quick check for whether an application might be able to perform an operation.
+ * This is <em>not</em> a security check; you must use {@link #noteOp(String, int, String)}
+ * or {@link #startOp(String, int, String)} for your actual security checks, which also
+ * ensure that the given uid and package name are consistent. This function can just be
+ * used for a quick check to see if an operation has been disabled for the application,
+ * as an early reject of some work. This does not modify the time stamp or other data
+ * about the operation.
+ * @param op The operation to check. One of the OPSTR_* constants.
+ * @param uid The user id of the application attempting to perform the operation.
+ * @param packageName The name of the application attempting to perform the operation.
+ * @return Returns {@link #MODE_ALLOWED} if the operation is allowed, or
+ * {@link #MODE_IGNORED} if it is not allowed and should be silently ignored (without
+ * causing the app to crash).
+ * @throws SecurityException If the app has been configured to crash on this op.
+ */
+ public int checkOp(String op, int uid, String packageName) {
+ return checkOp(strOpToOp(op), uid, packageName);
+ }
+
+ /**
+ * Like {@link #checkOp but instead of throwing a {@link SecurityException} it
+ * returns {@link #MODE_ERRORED}.
+ */
+ public int checkOpNoThrow(String op, int uid, String packageName) {
+ return checkOpNoThrow(strOpToOp(op), uid, packageName);
+ }
+
+ /**
+ * Make note of an application performing an operation. Note that you must pass
+ * in both the uid and name of the application to be checked; this function will verify
+ * that these two match, and if not, return {@link #MODE_IGNORED}. If this call
+ * succeeds, the last execution time of the operation for this app will be updated to
+ * the current time.
+ * @param op The operation to note. One of the OPSTR_* constants.
+ * @param uid The user id of the application attempting to perform the operation.
+ * @param packageName The name of the application attempting to perform the operation.
+ * @return Returns {@link #MODE_ALLOWED} if the operation is allowed, or
+ * {@link #MODE_IGNORED} if it is not allowed and should be silently ignored (without
+ * causing the app to crash).
+ * @throws SecurityException If the app has been configured to crash on this op.
+ */
+ public int noteOp(String op, int uid, String packageName) {
+ return noteOp(strOpToOp(op), uid, packageName);
+ }
+
+ /**
+ * Like {@link #noteOp} but instead of throwing a {@link SecurityException} it
+ * returns {@link #MODE_ERRORED}.
+ */
+ public int noteOpNoThrow(String op, int uid, String packageName) {
+ return noteOpNoThrow(strOpToOp(op), uid, packageName);
+ }
+
+ /**
+ * Report that an application has started executing a long-running operation. Note that you
+ * must pass in both the uid and name of the application to be checked; this function will
+ * verify that these two match, and if not, return {@link #MODE_IGNORED}. If this call
+ * succeeds, the last execution time of the operation for this app will be updated to
+ * the current time and the operation will be marked as "running". In this case you must
+ * later call {@link #finishOp(String, int, String)} to report when the application is no
+ * longer performing the operation.
+ * @param op The operation to start. One of the OPSTR_* constants.
+ * @param uid The user id of the application attempting to perform the operation.
+ * @param packageName The name of the application attempting to perform the operation.
+ * @return Returns {@link #MODE_ALLOWED} if the operation is allowed, or
+ * {@link #MODE_IGNORED} if it is not allowed and should be silently ignored (without
+ * causing the app to crash).
+ * @throws SecurityException If the app has been configured to crash on this op.
+ */
+ public int startOp(String op, int uid, String packageName) {
+ return startOp(strOpToOp(op), uid, packageName);
+ }
+
+ /**
+ * Like {@link #startOp} but instead of throwing a {@link SecurityException} it
+ * returns {@link #MODE_ERRORED}.
+ */
+ public int startOpNoThrow(String op, int uid, String packageName) {
+ return startOpNoThrow(strOpToOp(op), uid, packageName);
+ }
+
+ /**
+ * Report that an application is no longer performing an operation that had previously
+ * been started with {@link #startOp(String, int, String)}. There is no validation of input
+ * or result; the parameters supplied here must be the exact same ones previously passed
+ * in when starting the operation.
+ */
+ public void finishOp(String op, int uid, String packageName) {
+ finishOp(strOpToOp(op), uid, packageName);
+ }
+
/**
* Do a quick check for whether an application might be able to perform an operation.
* This is <em>not</em> a security check; you must use {@link #noteOp(int, int, String)}
@@ -651,6 +887,7 @@
* {@link #MODE_IGNORED} if it is not allowed and should be silently ignored (without
* causing the app to crash).
* @throws SecurityException If the app has been configured to crash on this op.
+ * @hide
*/
public int checkOp(int op, int uid, String packageName) {
try {
@@ -667,6 +904,7 @@
/**
* Like {@link #checkOp} but instead of throwing a {@link SecurityException} it
* returns {@link #MODE_ERRORED}.
+ * @hide
*/
public int checkOpNoThrow(int op, int uid, String packageName) {
try {
@@ -706,6 +944,7 @@
* {@link #MODE_IGNORED} if it is not allowed and should be silently ignored (without
* causing the app to crash).
* @throws SecurityException If the app has been configured to crash on this op.
+ * @hide
*/
public int noteOp(int op, int uid, String packageName) {
try {
@@ -722,6 +961,7 @@
/**
* Like {@link #noteOp} but instead of throwing a {@link SecurityException} it
* returns {@link #MODE_ERRORED}.
+ * @hide
*/
public int noteOpNoThrow(int op, int uid, String packageName) {
try {
@@ -766,6 +1006,7 @@
* {@link #MODE_IGNORED} if it is not allowed and should be silently ignored (without
* causing the app to crash).
* @throws SecurityException If the app has been configured to crash on this op.
+ * @hide
*/
public int startOp(int op, int uid, String packageName) {
try {
@@ -782,6 +1023,7 @@
/**
* Like {@link #startOp} but instead of throwing a {@link SecurityException} it
* returns {@link #MODE_ERRORED}.
+ * @hide
*/
public int startOpNoThrow(int op, int uid, String packageName) {
try {
@@ -801,6 +1043,7 @@
* been started with {@link #startOp(int, int, String)}. There is no validation of input
* or result; the parameters supplied here must be the exact same ones previously passed
* in when starting the operation.
+ * @hide
*/
public void finishOp(int op, int uid, String packageName) {
try {
@@ -809,6 +1052,7 @@
}
}
+ /** @hide */
public void finishOp(int op) {
finishOp(op, Process.myUid(), mContext.getOpPackageName());
}
diff --git a/packages/PrintSpooler/src/com/android/printspooler/PrintJobConfigActivity.java b/packages/PrintSpooler/src/com/android/printspooler/PrintJobConfigActivity.java
index bcef79c..5d48350 100644
--- a/packages/PrintSpooler/src/com/android/printspooler/PrintJobConfigActivity.java
+++ b/packages/PrintSpooler/src/com/android/printspooler/PrintJobConfigActivity.java
@@ -444,6 +444,10 @@
// the requested pages, then nothing else to do.
if (!infoChanged && !layoutChanged
&& PageRangeUtils.contains(mDocument.pages, mRequestedPages)) {
+ // Nothing interesting changed and we have all requested pages.
+ // Then update the print jobs's pages as we will not do a write
+ // and we usually update the pages in the write complete callback.
+ updatePrintJobPages(mDocument.pages, mRequestedPages);
if (mEditor.isDone()) {
requestCreatePdfFileOrFinish();
}
@@ -499,36 +503,44 @@
+ " and got: " + Arrays.toString(mDocument.pages));
}
+ updatePrintJobPages(mDocument.pages, mRequestedPages);
+
+ if (mEditor.isDone()) {
+ requestCreatePdfFileOrFinish();
+ }
+ }
+
+ private void updatePrintJobPages(PageRange[] writtenPages, PageRange[] requestedPages) {
// Adjust the print job pages based on what was requested and written.
// The cases are ordered in the most expected to the least expected.
- if (Arrays.equals(mDocument.pages, mRequestedPages)) {
+ if (Arrays.equals(writtenPages, requestedPages)) {
// We got a document with exactly the pages we wanted. Hence,
// the printer has to print all pages in the data.
PrintSpoolerService.peekInstance().setPrintJobPagesNoPersistence(mPrintJobId,
ALL_PAGES_ARRAY);
- } else if (Arrays.equals(mDocument.pages, ALL_PAGES_ARRAY)) {
+ } else if (Arrays.equals(writtenPages, ALL_PAGES_ARRAY)) {
// We requested specific pages but got all of them. Hence,
// the printer has to print only the requested pages.
PrintSpoolerService.peekInstance().setPrintJobPagesNoPersistence(mPrintJobId,
- mRequestedPages);
- } else if (PageRangeUtils.contains(mDocument.pages, mRequestedPages)) {
+ requestedPages);
+ } else if (PageRangeUtils.contains(writtenPages, requestedPages)) {
// We requested specific pages and got more but not all pages.
// Hence, we have to offset appropriately the printed pages to
- // exclude the pages we did not request. Note that pages is
- // guaranteed to be not null and not empty.
- final int offset = mDocument.pages[0].getStart() - pages[0].getStart();
- PageRange[] offsetPages = Arrays.copyOf(mDocument.pages, mDocument.pages.length);
- PageRangeUtils.offsetStart(offsetPages, offset);
+ // be based off the start of the written ones instead of zero.
+ // The written pages are always non-null and not empty.
+ final int offset = -writtenPages[0].getStart();
+ PageRange[] offsetPages = Arrays.copyOf(requestedPages, requestedPages.length);
+ PageRangeUtils.offset(offsetPages, offset);
PrintSpoolerService.peekInstance().setPrintJobPagesNoPersistence(mPrintJobId,
offsetPages);
- } else if (Arrays.equals(mRequestedPages, ALL_PAGES_ARRAY)
- && mDocument.pages.length == 1 && mDocument.pages[0].getStart() == 0
- && mDocument.pages[0].getEnd() == mDocument.info.getPageCount() - 1) {
+ } else if (Arrays.equals(requestedPages, ALL_PAGES_ARRAY)
+ && writtenPages.length == 1 && writtenPages[0].getStart() == 0
+ && writtenPages[0].getEnd() == mDocument.info.getPageCount() - 1) {
// We requested all pages via the special constant and got all
// of them as an explicit enumeration. Hence, the printer has
// to print only the requested pages.
PrintSpoolerService.peekInstance().setPrintJobPagesNoPersistence(mPrintJobId,
- mDocument.pages);
+ writtenPages);
} else {
// We did not get the pages we requested, then the application
// misbehaves, so we fail quickly.
@@ -537,10 +549,6 @@
Log.e(LOG_TAG, "Received invalid pages from the app");
PrintJobConfigActivity.this.finish();
}
-
- if (mEditor.isDone()) {
- requestCreatePdfFileOrFinish();
- }
}
private void requestCreatePdfFileOrFinish() {
@@ -2191,38 +2199,39 @@
throw new UnsupportedOperationException();
}
- public static boolean contains(PageRange[] ourPageRanges, PageRange[] otherPageRanges) {
- if (ourPageRanges == null || otherPageRanges == null) {
+ public static boolean contains(PageRange[] ourRanges, PageRange[] otherRanges) {
+ if (ourRanges == null || otherRanges == null) {
return false;
}
- if (ourPageRanges.length == 1
- && PageRange.ALL_PAGES.equals(ourPageRanges[0])) {
+ if (ourRanges.length == 1
+ && PageRange.ALL_PAGES.equals(ourRanges[0])) {
return true;
}
- otherPageRanges = normalize(otherPageRanges);
+ ourRanges = normalize(ourRanges);
+ otherRanges = normalize(otherRanges);
- int otherPageIdx = 0;
- final int myPageCount = ourPageRanges.length;
- final int otherPageCount = otherPageRanges.length;
- for (int i= 0; i < myPageCount; i++) {
- PageRange myPage = ourPageRanges[i];
- for (; otherPageIdx < otherPageCount; otherPageIdx++) {
- PageRange otherPage = otherPageRanges[otherPageIdx];
- if (otherPage.getStart() > myPage.getStart()) {
+ // Note that the code below relies on the ranges being normalized
+ // which is they contain monotonically increasing non-intersecting
+ // subranges whose start is less that or equal to the end.
+ int otherRangeIdx = 0;
+ final int ourRangeCount = ourRanges.length;
+ final int otherRangeCount = otherRanges.length;
+ for (int ourRangeIdx = 0; ourRangeIdx < ourRangeCount; ourRangeIdx++) {
+ PageRange ourRange = ourRanges[ourRangeIdx];
+ for (; otherRangeIdx < otherRangeCount; otherRangeIdx++) {
+ PageRange otherRange = otherRanges[otherRangeIdx];
+ if (otherRange.getStart() > ourRange.getEnd()) {
break;
}
- if ((otherPage.getStart() < myPage.getStart()
- && otherPage.getEnd() > myPage.getStart())
- || (otherPage.getEnd() > myPage.getEnd()
- && otherPage.getStart() < myPage.getEnd())
- || (otherPage.getEnd() < myPage.getStart())) {
+ if (otherRange.getStart() < ourRange.getStart()
+ || otherRange.getEnd() > ourRange.getEnd()) {
return false;
}
}
}
- if (otherPageIdx < otherPageCount) {
+ if (otherRangeIdx < otherRangeCount) {
return false;
}
return true;
@@ -2256,7 +2265,7 @@
oldRangeCount);
}
- public static void offsetStart(PageRange[] pageRanges, int offset) {
+ public static void offset(PageRange[] pageRanges, int offset) {
if (offset == 0) {
return;
}
diff --git a/services/java/com/android/server/LocationManagerService.java b/services/java/com/android/server/LocationManagerService.java
index b6ccce7..3e8770e 100644
--- a/services/java/com/android/server/LocationManagerService.java
+++ b/services/java/com/android/server/LocationManagerService.java
@@ -223,8 +223,9 @@
mGeofenceManager = new GeofenceManager(mContext, mBlacklist);
// Monitor for app ops mode changes.
- AppOpsManager.Callback callback = new AppOpsManager.Callback() {
- public void opChanged(int op, String packageName) {
+ AppOpsManager.OnOpChangedListener callback
+ = new AppOpsManager.OnOpChangedInternalListener() {
+ public void onOpChanged(int op, String packageName) {
synchronized (mLock) {
for (Receiver receiver : mReceivers.values()) {
receiver.updateMonitoring(true);
diff --git a/services/java/com/android/server/am/ActiveServices.java b/services/java/com/android/server/am/ActiveServices.java
index 4379c70..fa1769f 100644
--- a/services/java/com/android/server/am/ActiveServices.java
+++ b/services/java/com/android/server/am/ActiveServices.java
@@ -1009,23 +1009,15 @@
stracker.setExecuting(true, mAm.mProcessStats.getMemFactorLocked(), now);
}
if (r.app != null) {
- if (r.app.executingServices.size() == 0) {
- Message msg = mAm.mHandler.obtainMessage(
- ActivityManagerService.SERVICE_TIMEOUT_MSG);
- msg.obj = r.app;
- mAm.mHandler.sendMessageAtTime(msg,
- fg ? (now+SERVICE_TIMEOUT) : (now+ SERVICE_BACKGROUND_TIMEOUT));
- }
r.app.executingServices.add(r);
r.app.execServicesFg |= fg;
+ if (r.app.executingServices.size() == 1) {
+ scheduleServiceTimeoutLocked(r.app);
+ }
}
} else if (r.app != null && fg && !r.app.execServicesFg) {
- mAm.mHandler.removeMessages(ActivityManagerService.SERVICE_TIMEOUT_MSG);
- Message msg = mAm.mHandler.obtainMessage(
- ActivityManagerService.SERVICE_TIMEOUT_MSG);
- msg.obj = r.app;
- mAm.mHandler.sendMessageAtTime(msg,now+SERVICE_TIMEOUT);
r.app.execServicesFg = true;
+ scheduleServiceTimeoutLocked(r.app);
}
r.executeFg |= fg;
r.executeNesting++;
@@ -2144,7 +2136,7 @@
ActivityManagerService.SERVICE_TIMEOUT_MSG);
msg.obj = proc;
mAm.mHandler.sendMessageAtTime(msg, proc.execServicesFg
- ? (nextTime+SERVICE_TIMEOUT) : (nextTime+ SERVICE_BACKGROUND_TIMEOUT));
+ ? (nextTime+SERVICE_TIMEOUT) : (nextTime + SERVICE_BACKGROUND_TIMEOUT));
}
}
@@ -2153,6 +2145,18 @@
}
}
+ void scheduleServiceTimeoutLocked(ProcessRecord proc) {
+ if (proc.executingServices.size() == 0 || proc.thread == null) {
+ return;
+ }
+ long now = SystemClock.uptimeMillis();
+ Message msg = mAm.mHandler.obtainMessage(
+ ActivityManagerService.SERVICE_TIMEOUT_MSG);
+ msg.obj = proc;
+ mAm.mHandler.sendMessageAtTime(msg,
+ proc.execServicesFg ? (now+SERVICE_TIMEOUT) : (now+ SERVICE_BACKGROUND_TIMEOUT));
+ }
+
/**
* Prints a list of ServiceRecords (dumpsys activity services)
*/
diff --git a/services/java/com/android/server/am/ActivityManagerService.java b/services/java/com/android/server/am/ActivityManagerService.java
index 47297c0..cbe97d2 100644
--- a/services/java/com/android/server/am/ActivityManagerService.java
+++ b/services/java/com/android/server/am/ActivityManagerService.java
@@ -2230,7 +2230,8 @@
mHandler.sendMessage(msg);
}
- private final int updateLruProcessInternalLocked(ProcessRecord app, long now, int index) {
+ private final int updateLruProcessInternalLocked(ProcessRecord app, long now, int index,
+ String what, Object obj, ProcessRecord srcApp) {
app.lastActivityTime = now;
if (app.activities.size() > 0) {
@@ -2241,7 +2242,7 @@
int lrui = mLruProcesses.lastIndexOf(app);
if (lrui < 0) {
throw new IllegalStateException("Adding dependent process " + app
- + " not on LRU list!");
+ + " not on LRU list: " + what + obj + " from " + srcApp);
}
if (lrui >= mLruProcessActivityStart) {
@@ -2309,13 +2310,15 @@
if (cr.binding != null && cr.binding.service != null
&& cr.binding.service.app != null
&& cr.binding.service.app.lruSeq != mLruSeq) {
- nextIndex = updateLruProcessInternalLocked(cr.binding.service.app, now, nextIndex);
+ nextIndex = updateLruProcessInternalLocked(cr.binding.service.app, now, nextIndex,
+ "service connection", cr, app);
}
}
for (int j=app.conProviders.size()-1; j>=0; j--) {
ContentProviderRecord cpr = app.conProviders.get(j).provider;
if (cpr.proc != null && cpr.proc.lruSeq != mLruSeq) {
- nextIndex = updateLruProcessInternalLocked(cpr.proc, now, nextIndex);
+ nextIndex = updateLruProcessInternalLocked(cpr.proc, now, nextIndex,
+ "provider reference", cpr, app);
}
}
@@ -3863,7 +3866,13 @@
// 0 == show dialog, 1 = keep waiting, -1 = kill process immediately
int res = mController.appNotResponding(app.processName, app.pid, info.toString());
if (res != 0) {
- if (res < 0 && app.pid != MY_PID) Process.killProcess(app.pid);
+ if (res < 0 && app.pid != MY_PID) {
+ Process.killProcess(app.pid);
+ } else {
+ synchronized (this) {
+ mServices.scheduleServiceTimeoutLocked(app);
+ }
+ }
return;
}
} catch (RemoteException e) {
diff --git a/services/java/com/android/server/am/AppNotRespondingDialog.java b/services/java/com/android/server/am/AppNotRespondingDialog.java
index b5e0715..d0a0441 100644
--- a/services/java/com/android/server/am/AppNotRespondingDialog.java
+++ b/services/java/com/android/server/am/AppNotRespondingDialog.java
@@ -128,6 +128,7 @@
if (app.anrDialog == AppNotRespondingDialog.this) {
app.anrDialog = null;
}
+ mService.mServices.scheduleServiceTimeoutLocked(app);
}
break;
}
diff --git a/services/java/com/android/server/am/ServiceRecord.java b/services/java/com/android/server/am/ServiceRecord.java
index 448117e..ac14da9 100644
--- a/services/java/com/android/server/am/ServiceRecord.java
+++ b/services/java/com/android/server/am/ServiceRecord.java
@@ -253,6 +253,7 @@
pw.print(" executeFg="); pw.print(executeFg);
pw.print(" executingStart=");
TimeUtils.formatDuration(executingStart, now, pw);
+ pw.println();
}
if (crashCount != 0 || restartCount != 0
|| restartDelay != 0 || nextRestartTime != 0) {
diff --git a/services/java/com/android/server/content/SyncManager.java b/services/java/com/android/server/content/SyncManager.java
index 9a41166..635ba5c 100644
--- a/services/java/com/android/server/content/SyncManager.java
+++ b/services/java/com/android/server/content/SyncManager.java
@@ -315,7 +315,9 @@
if (Log.isLoggable(TAG, Log.VERBOSE)) {
Log.v(TAG, "Reconnection detected: clearing all backoffs");
}
- mSyncStorageEngine.clearAllBackoffs(mSyncQueue);
+ synchronized(mSyncQueue) {
+ mSyncStorageEngine.clearAllBackoffsLocked(mSyncQueue);
+ }
}
sendCheckAlarmsMessage();
}
diff --git a/services/java/com/android/server/content/SyncStorageEngine.java b/services/java/com/android/server/content/SyncStorageEngine.java
index 1b9ed98..d51c2d7 100644
--- a/services/java/com/android/server/content/SyncStorageEngine.java
+++ b/services/java/com/android/server/content/SyncStorageEngine.java
@@ -710,28 +710,31 @@
}
}
- public void clearAllBackoffs(SyncQueue syncQueue) {
+ /**
+ * Callers of this function need to hold a lock for syncQueue object passed in. Bear in mind
+ * this function grabs the lock for {@link #mAuthorities}
+ * @param syncQueue queue containing pending sync operations.
+ */
+ public void clearAllBackoffsLocked(SyncQueue syncQueue) {
boolean changed = false;
synchronized (mAuthorities) {
- synchronized (syncQueue) {
- for (AccountInfo accountInfo : mAccounts.values()) {
- for (AuthorityInfo authorityInfo : accountInfo.authorities.values()) {
- if (authorityInfo.backoffTime != NOT_IN_BACKOFF_MODE
- || authorityInfo.backoffDelay != NOT_IN_BACKOFF_MODE) {
- if (DEBUG) {
- Log.v(TAG, "clearAllBackoffs:"
- + " authority:" + authorityInfo.authority
- + " account:" + accountInfo.accountAndUser.account.name
- + " user:" + accountInfo.accountAndUser.userId
- + " backoffTime was: " + authorityInfo.backoffTime
- + " backoffDelay was: " + authorityInfo.backoffDelay);
- }
- authorityInfo.backoffTime = NOT_IN_BACKOFF_MODE;
- authorityInfo.backoffDelay = NOT_IN_BACKOFF_MODE;
- syncQueue.onBackoffChanged(accountInfo.accountAndUser.account,
- accountInfo.accountAndUser.userId, authorityInfo.authority, 0);
- changed = true;
+ for (AccountInfo accountInfo : mAccounts.values()) {
+ for (AuthorityInfo authorityInfo : accountInfo.authorities.values()) {
+ if (authorityInfo.backoffTime != NOT_IN_BACKOFF_MODE
+ || authorityInfo.backoffDelay != NOT_IN_BACKOFF_MODE) {
+ if (DEBUG) {
+ Log.v(TAG, "clearAllBackoffs:"
+ + " authority:" + authorityInfo.authority
+ + " account:" + accountInfo.accountAndUser.account.name
+ + " user:" + accountInfo.accountAndUser.userId
+ + " backoffTime was: " + authorityInfo.backoffTime
+ + " backoffDelay was: " + authorityInfo.backoffDelay);
}
+ authorityInfo.backoffTime = NOT_IN_BACKOFF_MODE;
+ authorityInfo.backoffDelay = NOT_IN_BACKOFF_MODE;
+ syncQueue.onBackoffChanged(accountInfo.accountAndUser.account,
+ accountInfo.accountAndUser.userId, authorityInfo.authority, 0);
+ changed = true;
}
}
}
diff --git a/services/java/com/android/server/wm/WindowManagerService.java b/services/java/com/android/server/wm/WindowManagerService.java
index d063db5..e4f5c7c 100644
--- a/services/java/com/android/server/wm/WindowManagerService.java
+++ b/services/java/com/android/server/wm/WindowManagerService.java
@@ -754,9 +754,9 @@
mBatteryStats = BatteryStatsService.getService();
mAppOps = (AppOpsManager)context.getSystemService(Context.APP_OPS_SERVICE);
mAppOps.startWatchingMode(AppOpsManager.OP_SYSTEM_ALERT_WINDOW, null,
- new AppOpsManager.Callback() {
+ new AppOpsManager.OnOpChangedInternalListener() {
@Override
- public void opChanged(int op, String packageName) {
+ public void onOpChanged(int op, String packageName) {
updateAppOpsState();
}
}
diff --git a/wifi/java/android/net/wifi/WifiConfiguration.java b/wifi/java/android/net/wifi/WifiConfiguration.java
index 4c84f17..87afa88 100644
--- a/wifi/java/android/net/wifi/WifiConfiguration.java
+++ b/wifi/java/android/net/wifi/WifiConfiguration.java
@@ -361,7 +361,8 @@
if (allowedKeyManagement.get(KeyMgmt.WPA_EAP) == false) {
return false;
}
- if (allowedKeyManagement.get(KeyMgmt.IEEE8021X) == false) {
+ if ((allowedKeyManagement.get(KeyMgmt.IEEE8021X) == false)
+ && (allowedKeyManagement.get(KeyMgmt.WPA_PSK) == false)) {
return false;
}
}