Fix issue #21814207 and issue #21814212 (alarm manager)
Issue #21814207: AlarmManager.setAndAllowWhileIdle should also allow wake locks.
Introduce a whole new infrastructure for providing options when
sending broadcasts, much like ActivityOptions. There is a single
option right now, asking the activity manager to apply a tempory
whitelist to each receiver of the broadcast.
Issue #21814212: Need to allow configuration of alarm manager parameters
The various alarm manager timing configurations are not modifiable
through settings, much like DeviceIdleController. Also did a few
tweaks in the existing DeviceIdleController impl.
Change-Id: Ifd01013185acc4de668617b1e46e78e30ebed041
diff --git a/services/core/java/com/android/server/am/BroadcastQueue.java b/services/core/java/com/android/server/am/BroadcastQueue.java
index 80b8a93..2335071 100644
--- a/services/core/java/com/android/server/am/BroadcastQueue.java
+++ b/services/core/java/com/android/server/am/BroadcastQueue.java
@@ -26,6 +26,7 @@
import android.app.ActivityManager;
import android.app.AppGlobals;
import android.app.AppOpsManager;
+import android.app.BroadcastOptions;
import android.content.ComponentName;
import android.content.IIntentReceiver;
import android.content.Intent;
@@ -43,6 +44,7 @@
import android.os.UserHandle;
import android.util.EventLog;
import android.util.Slog;
+import com.android.server.DeviceIdleController;
import static com.android.server.am.ActivityManagerDebugConfig.*;
@@ -146,6 +148,8 @@
static final int BROADCAST_INTENT_MSG = ActivityManagerService.FIRST_BROADCAST_QUEUE_MSG;
static final int BROADCAST_TIMEOUT_MSG = ActivityManagerService.FIRST_BROADCAST_QUEUE_MSG + 1;
+ static final int SCHEDULE_TEMP_WHITELIST_MSG
+ = ActivityManagerService.FIRST_BROADCAST_QUEUE_MSG + 2;
final BroadcastHandler mHandler;
@@ -167,6 +171,13 @@
broadcastTimeoutLocked(true);
}
} break;
+ case SCHEDULE_TEMP_WHITELIST_MSG: {
+ DeviceIdleController.LocalService dic = mService.mLocalDeviceIdleController;
+ if (dic != null) {
+ dic.addPowerSaveTempWhitelistAppDirect(UserHandle.getAppId(msg.arg1),
+ msg.arg2);
+ }
+ } break;
}
}
};
@@ -547,6 +558,19 @@
}
}
+ final void scheduleTempWhitelistLocked(int uid, long duration) {
+ if (duration > Integer.MAX_VALUE) {
+ duration = Integer.MAX_VALUE;
+ }
+ // XXX ideally we should pause the broadcast until everything behind this is done,
+ // or else we will likely start dispatching the broadcast before we have opened
+ // access to the app (there is a lot of asynchronicity behind this). It is probably
+ // not that big a deal, however, because the main purpose here is to allow apps
+ // to hold wake locks, and they will be able to acquire their wake lock immediately
+ // it just won't be enabled until we get through this work.
+ mHandler.obtainMessage(SCHEDULE_TEMP_WHITELIST_MSG, uid, (int)duration).sendToTarget();
+ }
+
final void processNextBroadcast(boolean fromMsg) {
synchronized(mService) {
BroadcastRecord r;
@@ -721,7 +745,9 @@
setBroadcastTimeoutLocked(timeoutTime);
}
- Object nextReceiver = r.receivers.get(recIdx);
+ final BroadcastOptions brOptions = r.options;
+ final Object nextReceiver = r.receivers.get(recIdx);
+
if (nextReceiver instanceof BroadcastFilter) {
// Simple case: this is a registered receiver who gets
// a direct call.
@@ -739,6 +765,11 @@
+ r.ordered + " receiver=" + r.receiver);
r.state = BroadcastRecord.IDLE;
scheduleBroadcastsLocked();
+ } else {
+ if (brOptions != null && brOptions.getTemporaryAppWhitelistDuration() > 0) {
+ scheduleTempWhitelistLocked(filter.owningUid,
+ brOptions.getTemporaryAppWhitelistDuration());
+ }
}
return;
}
@@ -882,6 +913,11 @@
+ info.activityInfo.applicationInfo.uid);
}
+ if (brOptions != null && brOptions.getTemporaryAppWhitelistDuration() > 0) {
+ scheduleTempWhitelistLocked(receiverUid,
+ brOptions.getTemporaryAppWhitelistDuration());
+ }
+
// Broadcast is being executed, its package can't be stopped.
try {
AppGlobals.getPackageManager().setPackageStoppedState(