summaryrefslogtreecommitdiffstats
path: root/services/core/java
diff options
context:
space:
mode:
Diffstat (limited to 'services/core/java')
-rw-r--r--services/core/java/com/android/server/AlarmManagerService.java418
-rw-r--r--services/core/java/com/android/server/AppOpsService.java5
-rw-r--r--services/core/java/com/android/server/ConnectivityService.java111
-rw-r--r--services/core/java/com/android/server/InputMethodManagerService.java2
-rw-r--r--services/core/java/com/android/server/LocationManagerService.java24
-rw-r--r--services/core/java/com/android/server/am/ActivityManagerService.java2
-rwxr-xr-xservices/core/java/com/android/server/am/ActivityStack.java17
-rw-r--r--services/core/java/com/android/server/display/DisplayPowerController.java5
-rw-r--r--services/core/java/com/android/server/media/MediaRouteProviderProxy.java2
-rw-r--r--services/core/java/com/android/server/media/MediaSessionRecord.java42
-rw-r--r--services/core/java/com/android/server/media/MediaSessionService.java106
-rw-r--r--services/core/java/com/android/server/media/MediaSessionStack.java8
-rw-r--r--services/core/java/com/android/server/notification/ConditionProviders.java12
-rw-r--r--services/core/java/com/android/server/notification/NotificationManagerService.java144
-rwxr-xr-xservices/core/java/com/android/server/pm/PackageManagerService.java9
-rw-r--r--services/core/java/com/android/server/pm/UserManagerService.java12
-rw-r--r--services/core/java/com/android/server/statusbar/StatusBarManagerService.java18
-rw-r--r--services/core/java/com/android/server/trust/TrustManagerService.java2
-rw-r--r--services/core/java/com/android/server/wm/AppTransition.java35
-rw-r--r--services/core/java/com/android/server/wm/WindowManagerService.java12
-rw-r--r--services/core/java/com/android/server/wm/WindowStateAnimator.java17
21 files changed, 712 insertions, 291 deletions
diff --git a/services/core/java/com/android/server/AlarmManagerService.java b/services/core/java/com/android/server/AlarmManagerService.java
index 168742f..4ab8a01 100644
--- a/services/core/java/com/android/server/AlarmManagerService.java
+++ b/services/core/java/com/android/server/AlarmManagerService.java
@@ -22,7 +22,6 @@ import android.app.AlarmManager;
import android.app.IAlarmManager;
import android.app.PendingIntent;
import android.content.BroadcastReceiver;
-import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
@@ -40,7 +39,6 @@ import android.os.UserHandle;
import android.os.WorkSource;
import android.text.TextUtils;
import android.util.ArrayMap;
-import android.util.Pair;
import android.util.Slog;
import android.util.SparseArray;
import android.util.TimeUtils;
@@ -104,13 +102,21 @@ class AlarmManagerService extends SystemService {
int mBroadcastRefCount = 0;
PowerManager.WakeLock mWakeLock;
boolean mLastWakeLockUnimportantForLogging;
+ ArrayList<Alarm> mPendingNonWakeupAlarms = new ArrayList<Alarm>();
ArrayList<InFlight> mInFlight = new ArrayList<InFlight>();
final AlarmHandler mHandler = new AlarmHandler();
ClockReceiver mClockReceiver;
+ InteractiveStateReceiver mInteractiveStateReceiver;
private UninstallReceiver mUninstallReceiver;
final ResultReceiver mResultReceiver = new ResultReceiver();
PendingIntent mTimeTickSender;
PendingIntent mDateChangeSender;
+ boolean mInteractive = true;
+ long mNonInteractiveStartTime;
+ long mNonInteractiveTime;
+ long mLastAlarmDeliveryTime;
+ long mStartCurrentDelayTime;
+ long mNextNonWakeupDeliveryTime;
class WakeupEvent {
public long when;
@@ -318,7 +324,11 @@ class AlarmManagerService extends SystemService {
final Comparator<Alarm> mAlarmDispatchComparator = new Comparator<Alarm>() {
@Override
public int compare(Alarm lhs, Alarm rhs) {
- if (lhs.wakeup != rhs.wakeup) {
+ if ((!lhs.operation.getCreatorPackage().equals(rhs.operation.getCreatorPackage()))
+ && lhs.wakeup != rhs.wakeup) {
+ // We want to put wakeup alarms before non-wakeup alarms, since they are
+ // the things that drive most activity in the alarm manager. However,
+ // alarms from the same package should always be ordered strictly by time.
return lhs.wakeup ? -1 : 1;
}
if (lhs.whenElapsed < rhs.whenElapsed) {
@@ -424,24 +434,21 @@ class AlarmManagerService extends SystemService {
static final class InFlight extends Intent {
final PendingIntent mPendingIntent;
final WorkSource mWorkSource;
- final Pair<String, ComponentName> mTarget;
+ final String mTag;
final BroadcastStats mBroadcastStats;
final FilterStats mFilterStats;
final int mAlarmType;
InFlight(AlarmManagerService service, PendingIntent pendingIntent, WorkSource workSource,
- int alarmType) {
+ int alarmType, String tag) {
mPendingIntent = pendingIntent;
mWorkSource = workSource;
- Intent intent = pendingIntent.getIntent();
- mTarget = intent != null
- ? new Pair<String, ComponentName>(intent.getAction(), intent.getComponent())
- : null;
+ mTag = tag;
mBroadcastStats = service.getStatsLocked(pendingIntent);
- FilterStats fs = mBroadcastStats.filterStats.get(mTarget);
+ FilterStats fs = mBroadcastStats.filterStats.get(mTag);
if (fs == null) {
- fs = new FilterStats(mBroadcastStats, mTarget);
- mBroadcastStats.filterStats.put(mTarget, fs);
+ fs = new FilterStats(mBroadcastStats, mTag);
+ mBroadcastStats.filterStats.put(mTag, fs);
}
mFilterStats = fs;
mAlarmType = alarmType;
@@ -450,7 +457,7 @@ class AlarmManagerService extends SystemService {
static final class FilterStats {
final BroadcastStats mBroadcastStats;
- final Pair<String, ComponentName> mTarget;
+ final String mTag;
long aggregateTime;
int count;
@@ -458,9 +465,9 @@ class AlarmManagerService extends SystemService {
long startTime;
int nesting;
- FilterStats(BroadcastStats broadcastStats, Pair<String, ComponentName> target) {
+ FilterStats(BroadcastStats broadcastStats, String tag) {
mBroadcastStats = broadcastStats;
- mTarget = target;
+ mTag = tag;
}
}
@@ -473,8 +480,7 @@ class AlarmManagerService extends SystemService {
int numWakeup;
long startTime;
int nesting;
- final ArrayMap<Pair<String, ComponentName>, FilterStats> filterStats
- = new ArrayMap<Pair<String, ComponentName>, FilterStats>();
+ final ArrayMap<String, FilterStats> filterStats = new ArrayMap<String, FilterStats>();
BroadcastStats(int uid, String packageName) {
mUid = uid;
@@ -484,7 +490,11 @@ class AlarmManagerService extends SystemService {
final SparseArray<ArrayMap<String, BroadcastStats>> mBroadcastStats
= new SparseArray<ArrayMap<String, BroadcastStats>>();
-
+
+ int mNumDelayedAlarms = 0;
+ long mTotalDelayTime = 0;
+ long mMaxDelayTime = 0;
+
@Override
public void onStart() {
mNativeData = init();
@@ -511,6 +521,7 @@ class AlarmManagerService extends SystemService {
mClockReceiver = new ClockReceiver();
mClockReceiver.scheduleTimeTickEvent();
mClockReceiver.scheduleDateChangedEvent();
+ mInteractiveStateReceiver = new InteractiveStateReceiver();
mUninstallReceiver = new UninstallReceiver();
if (mNativeData != 0) {
@@ -735,13 +746,29 @@ class AlarmManagerService extends SystemService {
pw.print("nowRTC="); pw.print(nowRTC);
pw.print("="); pw.print(sdf.format(new Date(nowRTC)));
- pw.print(" nowELAPSED="); pw.println(nowELAPSED);
+ pw.print(" nowELAPSED="); TimeUtils.formatDuration(nowELAPSED, pw);
+ pw.println();
+ if (!mInteractive) {
+ pw.print("Time since non-interactive: ");
+ TimeUtils.formatDuration(nowELAPSED - mNonInteractiveStartTime, pw);
+ pw.println();
+ pw.print("Max wakeup delay: ");
+ TimeUtils.formatDuration(currentNonWakeupFuzzLocked(nowELAPSED), pw);
+ pw.println();
+ pw.print("Time since last dispatch: ");
+ TimeUtils.formatDuration(nowELAPSED - mLastAlarmDeliveryTime, pw);
+ pw.println();
+ pw.print("Next non-wakeup delivery time: ");
+ TimeUtils.formatDuration(nowELAPSED - mNextNonWakeupDeliveryTime, pw);
+ pw.println();
+ }
long nextWakeupRTC = mNextWakeup + (nowRTC - nowELAPSED);
long nextNonWakeupRTC = mNextNonWakeup + (nowRTC - nowELAPSED);
- pw.print("Next alarm: "); pw.print(mNextNonWakeup);
+ pw.print("Next non-wakeup alarm: ");
+ TimeUtils.formatDuration(mNextNonWakeup, nowELAPSED, pw);
pw.print(" = "); pw.println(sdf.format(new Date(nextNonWakeupRTC)));
- pw.print("Next wakeup: "); pw.print(mNextWakeup);
+ pw.print("Next wakeup: "); TimeUtils.formatDuration(mNextWakeup, nowELAPSED, pw);
pw.print(" = "); pw.println(sdf.format(new Date(nextWakeupRTC)));
if (mAlarmBatches.size() > 0) {
@@ -750,11 +777,27 @@ class AlarmManagerService extends SystemService {
pw.println(mAlarmBatches.size());
for (Batch b : mAlarmBatches) {
pw.print(b); pw.println(':');
- dumpAlarmList(pw, b.alarms, " ", nowELAPSED, nowRTC);
+ dumpAlarmList(pw, b.alarms, " ", nowELAPSED, nowRTC, sdf);
}
}
pw.println();
+ pw.print("Past-due non-wakeup alarms: ");
+ if (mPendingNonWakeupAlarms.size() > 0) {
+ pw.println(mPendingNonWakeupAlarms.size());
+ dumpAlarmList(pw, mPendingNonWakeupAlarms, " ", nowELAPSED, nowRTC, sdf);
+ } else {
+ pw.println("(none)");
+ }
+ pw.print(" Number of delayed alarms: "); pw.print(mNumDelayedAlarms);
+ pw.print(", total delay time: "); TimeUtils.formatDuration(mTotalDelayTime, pw);
+ pw.println();
+ pw.print(" Max delay time: "); TimeUtils.formatDuration(mMaxDelayTime, pw);
+ pw.print(", max non-interactive time: ");
+ TimeUtils.formatDuration(mNonInteractiveTime, pw);
+ pw.println();
+
+ pw.println();
pw.print(" Broadcast ref count: "); pw.println(mBroadcastRefCount);
pw.println();
@@ -811,13 +854,7 @@ class AlarmManagerService extends SystemService {
pw.print(" alarms: "); UserHandle.formatUid(pw, fs.mBroadcastStats.mUid);
pw.print(":"); pw.print(fs.mBroadcastStats.mPackageName);
pw.println();
- pw.print(" ");
- if (fs.mTarget.first != null) {
- pw.print(" act="); pw.print(fs.mTarget.first);
- }
- if (fs.mTarget.second != null) {
- pw.print(" cmp="); pw.print(fs.mTarget.second.toShortString());
- }
+ pw.print(" "); pw.print(fs.mTag);
pw.println();
}
}
@@ -849,13 +886,8 @@ class AlarmManagerService extends SystemService {
TimeUtils.formatDuration(fs.aggregateTime, pw);
pw.print(" "); pw.print(fs.numWakeup);
pw.print(" wakes " ); pw.print(fs.count);
- pw.print(" alarms:");
- if (fs.mTarget.first != null) {
- pw.print(" act="); pw.print(fs.mTarget.first);
- }
- if (fs.mTarget.second != null) {
- pw.print(" cmp="); pw.print(fs.mTarget.second.toShortString());
- }
+ pw.print(" alarms: ");
+ pw.print(fs.mTag);
pw.println();
}
}
@@ -883,7 +915,7 @@ class AlarmManagerService extends SystemService {
}
}
- private void logBatchesLocked() {
+ private void logBatchesLocked(SimpleDateFormat sdf) {
ByteArrayOutputStream bs = new ByteArrayOutputStream(2048);
PrintWriter pw = new PrintWriter(bs);
final long nowRTC = System.currentTimeMillis();
@@ -892,7 +924,7 @@ class AlarmManagerService extends SystemService {
for (int iz = 0; iz < NZ; iz++) {
Batch bz = mAlarmBatches.get(iz);
pw.append("Batch "); pw.print(iz); pw.append(": "); pw.println(bz);
- dumpAlarmList(pw, bz.alarms, " ", nowELAPSED, nowRTC);
+ dumpAlarmList(pw, bz.alarms, " ", nowELAPSED, nowRTC, sdf);
pw.flush();
Slog.v(TAG, bs.toString());
bs.reset();
@@ -910,7 +942,8 @@ class AlarmManagerService extends SystemService {
lastTime = b.start;
} else {
Slog.e(TAG, "CONSISTENCY FAILURE: Batch " + i + " is out of order");
- logBatchesLocked();
+ SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
+ logBatchesLocked(sdf);
return false;
}
}
@@ -932,6 +965,7 @@ class AlarmManagerService extends SystemService {
void rescheduleKernelAlarmsLocked() {
// Schedule the next upcoming wakeup alarm. If there is a deliverable batch
// prior to that which contains no wakeups, we schedule that as well.
+ long nextNonWakeup = 0;
if (mAlarmBatches.size() > 0) {
final Batch firstWakeup = findFirstWakeupBatchLocked();
final Batch firstBatch = mAlarmBatches.get(0);
@@ -939,11 +973,19 @@ class AlarmManagerService extends SystemService {
mNextWakeup = firstWakeup.start;
setLocked(ELAPSED_REALTIME_WAKEUP, firstWakeup.start);
}
- if (firstBatch != firstWakeup && mNextNonWakeup != firstBatch.start) {
- mNextNonWakeup = firstBatch.start;
- setLocked(ELAPSED_REALTIME, firstBatch.start);
+ if (firstBatch != firstWakeup) {
+ nextNonWakeup = firstBatch.start;
+ }
+ }
+ if (mPendingNonWakeupAlarms.size() > 0) {
+ if (nextNonWakeup == 0 || mNextNonWakeupDeliveryTime < nextNonWakeup) {
+ nextNonWakeup = mNextNonWakeupDeliveryTime;
}
}
+ if (nextNonWakeup != 0 && mNextNonWakeup != nextNonWakeup) {
+ mNextNonWakeup = nextNonWakeup;
+ setLocked(ELAPSED_REALTIME, nextNonWakeup);
+ }
}
private void removeLocked(PendingIntent operation) {
@@ -1003,6 +1045,32 @@ class AlarmManagerService extends SystemService {
}
}
+ void interactiveStateChangedLocked(boolean interactive) {
+ if (mInteractive != interactive) {
+ mInteractive = interactive;
+ final long nowELAPSED = SystemClock.elapsedRealtime();
+ if (interactive) {
+ if (mPendingNonWakeupAlarms.size() > 0) {
+ final long thisDelayTime = nowELAPSED - mStartCurrentDelayTime;
+ mTotalDelayTime += thisDelayTime;
+ if (mMaxDelayTime < thisDelayTime) {
+ mMaxDelayTime = thisDelayTime;
+ }
+ deliverAlarmsLocked(mPendingNonWakeupAlarms, nowELAPSED);
+ mPendingNonWakeupAlarms.clear();
+ }
+ if (mNonInteractiveStartTime > 0) {
+ long dur = nowELAPSED - mNonInteractiveStartTime;
+ if (dur > mNonInteractiveTime) {
+ mNonInteractiveTime = dur;
+ }
+ }
+ } else {
+ mNonInteractiveStartTime = nowELAPSED;
+ }
+ }
+ }
+
boolean lookForPackageLocked(String packageName) {
for (int i = 0; i < mAlarmBatches.size(); i++) {
Batch b = mAlarmBatches.get(i);
@@ -1037,12 +1105,12 @@ class AlarmManagerService extends SystemService {
}
private static final void dumpAlarmList(PrintWriter pw, ArrayList<Alarm> list,
- String prefix, String label, long now) {
+ String prefix, String label, long nowRTC, long nowELAPSED, SimpleDateFormat sdf) {
for (int i=list.size()-1; i>=0; i--) {
Alarm a = list.get(i);
pw.print(prefix); pw.print(label); pw.print(" #"); pw.print(i);
pw.print(": "); pw.println(a);
- a.dump(pw, prefix + " ", now);
+ a.dump(pw, prefix + " ", nowRTC, nowELAPSED, sdf);
}
}
@@ -1059,14 +1127,13 @@ class AlarmManagerService extends SystemService {
}
private static final void dumpAlarmList(PrintWriter pw, ArrayList<Alarm> list,
- String prefix, long nowELAPSED, long nowRTC) {
+ String prefix, long nowELAPSED, long nowRTC, SimpleDateFormat sdf) {
for (int i=list.size()-1; i>=0; i--) {
Alarm a = list.get(i);
final String label = labelForType(a.type);
- long now = (a.type <= RTC) ? nowRTC : nowELAPSED;
pw.print(prefix); pw.print(label); pw.print(" #"); pw.print(i);
pw.print(": "); pw.println(a);
- a.dump(pw, prefix + " ", now);
+ a.dump(pw, prefix + " ", nowRTC, nowELAPSED, sdf);
}
}
@@ -1077,8 +1144,9 @@ class AlarmManagerService extends SystemService {
private native int setKernelTime(long nativeData, long millis);
private native int setKernelTimezone(long nativeData, int minuteswest);
- void triggerAlarmsLocked(ArrayList<Alarm> triggerList, final long nowELAPSED,
+ boolean triggerAlarmsLocked(ArrayList<Alarm> triggerList, final long nowELAPSED,
final long nowRTC) {
+ boolean hasWakeup = false;
// batches are temporally sorted, so we need only pull from the
// start of the list until we either empty it or hit a batch
// that is not yet deliverable
@@ -1113,8 +1181,14 @@ class AlarmManagerService extends SystemService {
maxTriggerTime(nowELAPSED, nextElapsed, alarm.repeatInterval),
alarm.repeatInterval, alarm.operation, batch.standalone, true,
alarm.workSource);
- }
+ // For now we count this as a wakeup alarm, meaning it needs to be
+ // delivered immediately. In the future we should change this, but
+ // that required delaying when we reschedule the repeat...!
+ hasWakeup = false;
+ } else if (alarm.wakeup) {
+ hasWakeup = true;
+ }
}
}
@@ -1125,6 +1199,8 @@ class AlarmManagerService extends SystemService {
Slog.v(TAG, "Triggering alarm #" + i + ": " + triggerList.get(i));
}
}
+
+ return hasWakeup;
}
/**
@@ -1147,15 +1223,16 @@ class AlarmManagerService extends SystemService {
private static class Alarm {
public final int type;
public final boolean wakeup;
+ public final PendingIntent operation;
+ public final String tag;
+ public final WorkSource workSource;
public int count;
public long when;
public long windowLength;
public long whenElapsed; // 'when' in the elapsed time base
public long maxWhen; // also in the elapsed time base
public long repeatInterval;
- public PendingIntent operation;
- public WorkSource workSource;
-
+
public Alarm(int _type, long _when, long _whenElapsed, long _windowLength, long _maxWhen,
long _interval, PendingIntent _op, WorkSource _ws) {
type = _type;
@@ -1167,12 +1244,17 @@ class AlarmManagerService extends SystemService {
maxWhen = _maxWhen;
repeatInterval = _interval;
operation = _op;
+ tag = makeTag(_op, _type);
workSource = _ws;
}
+ public static String makeTag(PendingIntent pi, int type) {
+ return pi.getTag(type == ELAPSED_REALTIME_WAKEUP || type == RTC_WAKEUP
+ ? "*walarm*:" : "*alarm*:");
+ }
+
@Override
- public String toString()
- {
+ public String toString() {
StringBuilder sb = new StringBuilder(128);
sb.append("Alarm{");
sb.append(Integer.toHexString(System.identityHashCode(this)));
@@ -1186,11 +1268,20 @@ class AlarmManagerService extends SystemService {
return sb.toString();
}
- public void dump(PrintWriter pw, String prefix, long now) {
+ public void dump(PrintWriter pw, String prefix, long nowRTC, long nowELAPSED,
+ SimpleDateFormat sdf) {
+ final boolean isRtc = (type == RTC || type == RTC_WAKEUP);
+ pw.print(prefix); pw.print("tag="); pw.println(tag);
pw.print(prefix); pw.print("type="); pw.print(type);
- pw.print(" whenElapsed="); pw.print(whenElapsed);
- pw.print(" when="); TimeUtils.formatDuration(when, now, pw);
- pw.print(" window="); pw.print(windowLength);
+ pw.print(" whenElapsed="); TimeUtils.formatDuration(whenElapsed,
+ nowELAPSED, pw);
+ if (isRtc) {
+ pw.print(" when="); pw.print(sdf.format(new Date(when)));
+ } else {
+ pw.print(" when="); TimeUtils.formatDuration(when, nowELAPSED, pw);
+ }
+ pw.println();
+ pw.print(prefix); pw.print("window="); pw.print(windowLength);
pw.print(" repeatInterval="); pw.print(repeatInterval);
pw.print(" count="); pw.println(count);
pw.print(prefix); pw.print("operation="); pw.println(operation);
@@ -1216,6 +1307,102 @@ class AlarmManagerService extends SystemService {
}
}
+ long currentNonWakeupFuzzLocked(long nowELAPSED) {
+ long timeSinceOn = nowELAPSED - mNonInteractiveStartTime;
+ if (timeSinceOn < 5*60*1000) {
+ // If the screen has been off for 5 minutes, only delay by at most two minutes.
+ return 2*60*1000;
+ } else if (timeSinceOn < 30*60*1000) {
+ // If the screen has been off for 30 minutes, only delay by at most 15 minutes.
+ return 15*60*1000;
+ } else {
+ // Otherwise, we will delay by at most an hour.
+ return 60*60*1000;
+ }
+ }
+
+ boolean checkAllowNonWakeupDelayLocked(long nowELAPSED) {
+ if (mInteractive) {
+ return false;
+ }
+ if (mLastAlarmDeliveryTime <= 0) {
+ return false;
+ }
+ if (mPendingNonWakeupAlarms.size() > 0 && mNextNonWakeupDeliveryTime > nowELAPSED) {
+ // This is just a little paranoia, if somehow we have pending non-wakeup alarms
+ // and the next delivery time is in the past, then just deliver them all. This
+ // avoids bugs where we get stuck in a loop trying to poll for alarms.
+ return false;
+ }
+ long timeSinceLast = nowELAPSED - mLastAlarmDeliveryTime;
+ return timeSinceLast <= currentNonWakeupFuzzLocked(nowELAPSED);
+ }
+
+ void deliverAlarmsLocked(ArrayList<Alarm> triggerList, long nowELAPSED) {
+ mLastAlarmDeliveryTime = nowELAPSED;
+ for (int i=0; i<triggerList.size(); i++) {
+ Alarm alarm = triggerList.get(i);
+ try {
+ if (localLOGV) Slog.v(TAG, "sending alarm " + alarm);
+ alarm.operation.send(getContext(), 0,
+ mBackgroundIntent.putExtra(
+ Intent.EXTRA_ALARM_COUNT, alarm.count),
+ mResultReceiver, mHandler);
+
+ // we have an active broadcast so stay awake.
+ if (mBroadcastRefCount == 0) {
+ setWakelockWorkSource(alarm.operation, alarm.workSource,
+ alarm.type, alarm.tag, true);
+ mWakeLock.acquire();
+ }
+ final InFlight inflight = new InFlight(AlarmManagerService.this,
+ alarm.operation, alarm.workSource, alarm.type, alarm.tag);
+ mInFlight.add(inflight);
+ mBroadcastRefCount++;
+
+ final BroadcastStats bs = inflight.mBroadcastStats;
+ bs.count++;
+ if (bs.nesting == 0) {
+ bs.nesting = 1;
+ bs.startTime = nowELAPSED;
+ } else {
+ bs.nesting++;
+ }
+ final FilterStats fs = inflight.mFilterStats;
+ fs.count++;
+ if (fs.nesting == 0) {
+ fs.nesting = 1;
+ fs.startTime = nowELAPSED;
+ } else {
+ fs.nesting++;
+ }
+ if (alarm.type == ELAPSED_REALTIME_WAKEUP
+ || alarm.type == RTC_WAKEUP) {
+ bs.numWakeup++;
+ fs.numWakeup++;
+ if (alarm.workSource != null && alarm.workSource.size() > 0) {
+ for (int wi=0; wi<alarm.workSource.size(); wi++) {
+ ActivityManagerNative.noteWakeupAlarm(
+ alarm.operation, alarm.workSource.get(wi),
+ alarm.workSource.getName(wi));
+ }
+ } else {
+ ActivityManagerNative.noteWakeupAlarm(
+ alarm.operation, -1, null);
+ }
+ }
+ } catch (PendingIntent.CanceledException e) {
+ if (alarm.repeatInterval > 0) {
+ // This IntentSender is no longer valid, but this
+ // is a repeating alarm, so toss the hoser.
+ removeImpl(alarm.operation);
+ }
+ } catch (RuntimeException e) {
+ Slog.w(TAG, "Failure sending alarm.", e);
+ }
+ }
+ }
+
private class AlarmThread extends Thread
{
public AlarmThread()
@@ -1269,70 +1456,35 @@ class AlarmManagerService extends SystemService {
}
}
- triggerAlarmsLocked(triggerList, nowELAPSED, nowRTC);
- rescheduleKernelAlarmsLocked();
-
- // now deliver the alarm intents
- for (int i=0; i<triggerList.size(); i++) {
- Alarm alarm = triggerList.get(i);
- try {
- if (localLOGV) Slog.v(TAG, "sending alarm " + alarm);
- alarm.operation.send(getContext(), 0,
- mBackgroundIntent.putExtra(
- Intent.EXTRA_ALARM_COUNT, alarm.count),
- mResultReceiver, mHandler);
-
- // we have an active broadcast so stay awake.
- if (mBroadcastRefCount == 0) {
- setWakelockWorkSource(alarm.operation, alarm.workSource,
- alarm.type, true);
- mWakeLock.acquire();
- }
- final InFlight inflight = new InFlight(AlarmManagerService.this,
- alarm.operation, alarm.workSource, alarm.type);
- mInFlight.add(inflight);
- mBroadcastRefCount++;
-
- final BroadcastStats bs = inflight.mBroadcastStats;
- bs.count++;
- if (bs.nesting == 0) {
- bs.nesting = 1;
- bs.startTime = nowELAPSED;
- } else {
- bs.nesting++;
- }
- final FilterStats fs = inflight.mFilterStats;
- fs.count++;
- if (fs.nesting == 0) {
- fs.nesting = 1;
- fs.startTime = nowELAPSED;
- } else {
- fs.nesting++;
- }
- if (alarm.type == ELAPSED_REALTIME_WAKEUP
- || alarm.type == RTC_WAKEUP) {
- bs.numWakeup++;
- fs.numWakeup++;
- if (alarm.workSource != null && alarm.workSource.size() > 0) {
- for (int wi=0; wi<alarm.workSource.size(); wi++) {
- ActivityManagerNative.noteWakeupAlarm(
- alarm.operation, alarm.workSource.get(wi),
- alarm.workSource.getName(wi));
- }
- } else {
- ActivityManagerNative.noteWakeupAlarm(
- alarm.operation, -1, null);
- }
- }
- } catch (PendingIntent.CanceledException e) {
- if (alarm.repeatInterval > 0) {
- // This IntentSender is no longer valid, but this
- // is a repeating alarm, so toss the hoser.
- removeImpl(alarm.operation);
+ boolean hasWakeup = triggerAlarmsLocked(triggerList, nowELAPSED, nowRTC);
+ if (!hasWakeup && checkAllowNonWakeupDelayLocked(nowELAPSED)) {
+ // if there are no wakeup alarms and the screen is off, we can
+ // delay what we have so far until the future.
+ if (mPendingNonWakeupAlarms.size() == 0) {
+ mStartCurrentDelayTime = nowELAPSED;
+ mNextNonWakeupDeliveryTime = nowELAPSED
+ + ((currentNonWakeupFuzzLocked(nowELAPSED)*3)/2);
+ }
+ mPendingNonWakeupAlarms.addAll(triggerList);
+ mNumDelayedAlarms += triggerList.size();
+ rescheduleKernelAlarmsLocked();
+ } else {
+ // now deliver the alarm intents; if there are pending non-wakeup
+ // alarms, we need to merge them in to the list. note we don't
+ // just deliver them first because we generally want non-wakeup
+ // alarms delivered after wakeup alarms.
+ rescheduleKernelAlarmsLocked();
+ if (mPendingNonWakeupAlarms.size() > 0) {
+ triggerList.addAll(mPendingNonWakeupAlarms);
+ Collections.sort(triggerList, mAlarmDispatchComparator);
+ final long thisDelayTime = nowELAPSED - mStartCurrentDelayTime;
+ mTotalDelayTime += thisDelayTime;
+ if (mMaxDelayTime < thisDelayTime) {
+ mMaxDelayTime = thisDelayTime;
}
- } catch (RuntimeException e) {
- Slog.w(TAG, "Failure sending alarm.", e);
+ mPendingNonWakeupAlarms.clear();
}
+ deliverAlarmsLocked(triggerList, nowELAPSED);
}
}
}
@@ -1344,14 +1496,13 @@ class AlarmManagerService extends SystemService {
* @param pi PendingIntent to attribute blame to if ws is null.
* @param ws WorkSource to attribute blame.
*/
- void setWakelockWorkSource(PendingIntent pi, WorkSource ws, int type, boolean first) {
+ void setWakelockWorkSource(PendingIntent pi, WorkSource ws, int type, String tag,
+ boolean first) {
try {
final boolean unimportant = pi == mTimeTickSender;
mWakeLock.setUnimportantForLogging(unimportant);
if (first || mLastWakeLockUnimportantForLogging) {
- mWakeLock.setHistoryTag(pi.getTag(
- type == ELAPSED_REALTIME_WAKEUP || type == RTC_WAKEUP
- ? "*walarm*:" : "*alarm*:"));
+ mWakeLock.setHistoryTag(tag);
} else {
mWakeLock.setHistoryTag(null);
}
@@ -1462,6 +1613,23 @@ class AlarmManagerService extends SystemService {
}
}
+ class InteractiveStateReceiver extends BroadcastReceiver {
+ public InteractiveStateReceiver() {
+ IntentFilter filter = new IntentFilter();
+ filter.addAction(Intent.ACTION_SCREEN_OFF);
+ filter.addAction(Intent.ACTION_SCREEN_ON);
+ filter.setPriority(IntentFilter.SYSTEM_HIGH_PRIORITY);
+ getContext().registerReceiver(this, filter);
+ }
+
+ @Override
+ public void onReceive(Context context, Intent intent) {
+ synchronized (mLock) {
+ interactiveStateChangedLocked(Intent.ACTION_SCREEN_ON.equals(intent.getAction()));
+ }
+ }
+ }
+
class UninstallReceiver extends BroadcastReceiver {
public UninstallReceiver() {
IntentFilter filter = new IntentFilter();
@@ -1589,7 +1757,7 @@ class AlarmManagerService extends SystemService {
if (mInFlight.size() > 0) {
InFlight inFlight = mInFlight.get(0);
setWakelockWorkSource(inFlight.mPendingIntent, inFlight.mWorkSource,
- inFlight.mAlarmType, false);
+ inFlight.mAlarmType, inFlight.mTag, false);
} else {
// should never happen
mLog.w("Alarm wakelock still held but sent queue empty");
diff --git a/services/core/java/com/android/server/AppOpsService.java b/services/core/java/com/android/server/AppOpsService.java
index be20616..bfa0402 100644
--- a/services/core/java/com/android/server/AppOpsService.java
+++ b/services/core/java/com/android/server/AppOpsService.java
@@ -1253,7 +1253,10 @@ public class AppOpsService extends IAppOpsService.Stub {
public void removeUser(int userHandle) throws RemoteException {
checkSystemUid("removeUser");
mOpRestrictions.remove(userHandle);
- mProfileOwnerUids.removeAt(mProfileOwnerUids.indexOfKey(userHandle));
+ final int index = mProfileOwnerUids.indexOfKey(userHandle);
+ if (index >= 0) {
+ mProfileOwnerUids.removeAt(index);
+ }
}
private void checkSystemUid(String function) {
diff --git a/services/core/java/com/android/server/ConnectivityService.java b/services/core/java/com/android/server/ConnectivityService.java
index 5f53e49..af53fef 100644
--- a/services/core/java/com/android/server/ConnectivityService.java
+++ b/services/core/java/com/android/server/ConnectivityService.java
@@ -20,7 +20,7 @@ import static android.Manifest.permission.MANAGE_NETWORK_POLICY;
import static android.Manifest.permission.RECEIVE_DATA_ACTIVITY_CHANGE;
import static android.net.ConnectivityManager.CONNECTIVITY_ACTION;
import static android.net.ConnectivityManager.CONNECTIVITY_ACTION_IMMEDIATE;
-import static android.net.ConnectivityManager.NetworkCallbacks;
+import static android.net.ConnectivityManager.NetworkCallbackListener;
import static android.net.ConnectivityManager.TYPE_BLUETOOTH;
import static android.net.ConnectivityManager.TYPE_DUMMY;
import static android.net.ConnectivityManager.TYPE_ETHERNET;
@@ -398,7 +398,7 @@ public class ConnectivityService extends IConnectivityManager.Stub {
/**
* used internally when registering NetworkFactories
- * obj = Messenger
+ * obj = NetworkFactoryInfo
*/
private static final int EVENT_REGISTER_NETWORK_FACTORY = 17;
@@ -434,6 +434,13 @@ public class ConnectivityService extends IConnectivityManager.Stub {
*/
private static final int EVENT_RELEASE_NETWORK_REQUEST = 22;
+ /**
+ * used internally when registering NetworkFactories
+ * obj = Messenger
+ */
+ private static final int EVENT_UNREGISTER_NETWORK_FACTORY = 23;
+
+
/** Handler used for internal events. */
final private InternalHandler mHandler;
/** Handler used for incoming {@link NetworkStateTracker} events. */
@@ -507,10 +514,14 @@ public class ConnectivityService extends IConnectivityManager.Stub {
TelephonyManager mTelephonyManager;
+ // sequence number for Networks
private final static int MIN_NET_ID = 10; // some reserved marks
private final static int MAX_NET_ID = 65535;
private int mNextNetId = MIN_NET_ID;
+ // sequence number of NetworkRequests
+ private int mNextNetworkRequestId = 1;
+
public ConnectivityService(Context context, INetworkManagementService netd,
INetworkStatsService statsService, INetworkPolicyManager policyManager) {
// Currently, omitting a NetworkFactory will create one internally
@@ -526,7 +537,7 @@ public class ConnectivityService extends IConnectivityManager.Stub {
NetworkCapabilities netCap = new NetworkCapabilities();
netCap.addNetworkCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET);
netCap.addNetworkCapability(NetworkCapabilities.NET_CAPABILITY_NOT_RESTRICTED);
- mDefaultRequest = new NetworkRequest(netCap, true);
+ mDefaultRequest = new NetworkRequest(netCap, true, nextNetworkRequestId());
NetworkRequestInfo nri = new NetworkRequestInfo(null, mDefaultRequest, new Binder(),
NetworkRequestInfo.REQUEST);
mNetworkRequests.put(mDefaultRequest, nri);
@@ -773,6 +784,10 @@ public class ConnectivityService extends IConnectivityManager.Stub {
mAppOpsManager = (AppOpsManager) context.getSystemService(Context.APP_OPS_SERVICE);
}
+ private synchronized int nextNetworkRequestId() {
+ return mNextNetworkRequestId++;
+ }
+
private synchronized int nextNetId() {
int netId = mNextNetId;
if (++mNextNetId > MAX_NET_ID) mNextNetId = MIN_NET_ID;
@@ -2881,6 +2896,14 @@ public class ConnectivityService extends IConnectivityManager.Stub {
return;
}
+ pw.println("NetworkFactories for:");
+ pw.increaseIndent();
+ for (NetworkFactoryInfo nfi : mNetworkFactoryInfos.values()) {
+ pw.println(nfi.name);
+ }
+ pw.decreaseIndent();
+ pw.println();
+
NetworkAgentInfo defaultNai = mNetworkForRequestId.get(mDefaultRequest.requestId);
pw.print("Active default network: ");
if (defaultNai == null) {
@@ -2975,6 +2998,7 @@ public class ConnectivityService extends IConnectivityManager.Stub {
if (nai == null) {
loge("NetworkAgent not found for EVENT_NETWORK_PROPERTIES_CHANGED");
} else {
+ if (VDBG) log("Update of Linkproperties for " + nai.name());
LinkProperties oldLp = nai.linkProperties;
nai.linkProperties = (LinkProperties)msg.obj;
updateLinkProperties(nai, oldLp);
@@ -3088,18 +3112,19 @@ public class ConnectivityService extends IConnectivityManager.Stub {
private void handleAsyncChannelHalfConnect(Message msg) {
AsyncChannel ac = (AsyncChannel) msg.obj;
- if (mNetworkFactories.contains(ac)) {
+ if (mNetworkFactoryInfos.containsKey(msg.replyTo)) {
if (msg.arg1 == AsyncChannel.STATUS_SUCCESSFUL) {
if (VDBG) log("NetworkFactory connected");
// A network factory has connected. Send it all current NetworkRequests.
for (NetworkRequestInfo nri : mNetworkRequests.values()) {
+ if (nri.isRequest == false) continue;
NetworkAgentInfo nai = mNetworkForRequestId.get(nri.request.requestId);
ac.sendMessage(NetworkFactoryProtocol.CMD_REQUEST_NETWORK,
(nai != null ? nai.currentScore : 0), 0, nri.request);
}
} else {
loge("Error connecting NetworkFactory");
- mNetworkFactories.remove(ac);
+ mNetworkFactoryInfos.remove(msg.obj);
}
} else if (mNetworkAgentInfos.containsKey(msg.replyTo)) {
if (msg.arg1 == AsyncChannel.STATUS_SUCCESSFUL) {
@@ -3206,8 +3231,8 @@ public class ConnectivityService extends IConnectivityManager.Stub {
mNetworkRequests.put(nri.request, nri);
if (msg.what == EVENT_REGISTER_NETWORK_REQUEST) {
if (DBG) log("sending new NetworkRequest to factories");
- for (AsyncChannel ac : mNetworkFactories) {
- ac.sendMessage(NetworkFactoryProtocol.CMD_REQUEST_NETWORK, score, 0, nri.request);
+ for (NetworkFactoryInfo nfi : mNetworkFactoryInfos.values()) {
+ nfi.asyncChannel.sendMessage(NetworkFactoryProtocol.CMD_REQUEST_NETWORK, score, 0, nri.request);
}
}
}
@@ -3228,8 +3253,8 @@ public class ConnectivityService extends IConnectivityManager.Stub {
}
if (nri.isRequest) {
- for (AsyncChannel factory : mNetworkFactories) {
- factory.sendMessage(NetworkFactoryProtocol.CMD_CANCEL_REQUEST, nri.request);
+ for (NetworkFactoryInfo nfi : mNetworkFactoryInfos.values()) {
+ nfi.asyncChannel.sendMessage(NetworkFactoryProtocol.CMD_CANCEL_REQUEST, nri.request);
}
if (affectedNetwork != null) {
@@ -3348,7 +3373,11 @@ public class ConnectivityService extends IConnectivityManager.Stub {
break;
}
case EVENT_REGISTER_NETWORK_FACTORY: {
- handleRegisterNetworkFactory((Messenger)msg.obj);
+ handleRegisterNetworkFactory((NetworkFactoryInfo)msg.obj);
+ break;
+ }
+ case EVENT_UNREGISTER_NETWORK_FACTORY: {
+ handleUnregisterNetworkFactory((Messenger)msg.obj);
break;
}
case EVENT_REGISTER_NETWORK_AGENT: {
@@ -5214,10 +5243,22 @@ public class ConnectivityService extends IConnectivityManager.Stub {
mAlarmManager.set(AlarmManager.ELAPSED_REALTIME_WAKEUP, wakeupTime, intent);
}
- private final ArrayList<AsyncChannel> mNetworkFactories = new ArrayList<AsyncChannel>();
+ private final HashMap<Messenger, NetworkFactoryInfo> mNetworkFactoryInfos =
+ new HashMap<Messenger, NetworkFactoryInfo>();
private final HashMap<NetworkRequest, NetworkRequestInfo> mNetworkRequests =
new HashMap<NetworkRequest, NetworkRequestInfo>();
+ private static class NetworkFactoryInfo {
+ public final String name;
+ public final Messenger messenger;
+ public final AsyncChannel asyncChannel;
+
+ public NetworkFactoryInfo(String name, Messenger messenger, AsyncChannel asyncChannel) {
+ this.name = name;
+ this.messenger = messenger;
+ this.asyncChannel = asyncChannel;
+ }
+ }
private class NetworkRequestInfo implements IBinder.DeathRecipient {
static final boolean REQUEST = true;
@@ -5255,6 +5296,11 @@ public class ConnectivityService extends IConnectivityManager.Stub {
request + ", " + mBinder + ")");
releaseNetworkRequest(request);
}
+
+ public String toString() {
+ return (isRequest ? "Request" : "Listen") + " from uid/pid:" + mUid + "/" +
+ mPid + " for " + request;
+ }
}
@Override
@@ -5271,7 +5317,7 @@ public class ConnectivityService extends IConnectivityManager.Stub {
throw new IllegalArgumentException("Bad timeout specified");
}
NetworkRequest networkRequest = new NetworkRequest(new NetworkCapabilities(
- networkCapabilities));
+ networkCapabilities), false, nextNetworkRequestId());
if (DBG) log("requestNetwork for " + networkRequest);
NetworkRequestInfo nri = new NetworkRequestInfo(messenger, networkRequest, binder,
NetworkRequestInfo.REQUEST);
@@ -5297,7 +5343,7 @@ public class ConnectivityService extends IConnectivityManager.Stub {
enforceAccessPermission();
NetworkRequest networkRequest = new NetworkRequest(new NetworkCapabilities(
- networkCapabilities));
+ networkCapabilities), false, nextNetworkRequestId());
if (DBG) log("listenForNetwork for " + networkRequest);
NetworkRequestInfo nri = new NetworkRequestInfo(messenger, networkRequest, binder,
NetworkRequestInfo.LISTEN);
@@ -5318,24 +5364,31 @@ public class ConnectivityService extends IConnectivityManager.Stub {
}
@Override
- public void registerNetworkFactory(Messenger messenger) {
+ public void registerNetworkFactory(Messenger messenger, String name) {
enforceConnectivityInternalPermission();
- mHandler.sendMessage(mHandler.obtainMessage(EVENT_REGISTER_NETWORK_FACTORY, messenger));
+ NetworkFactoryInfo nfi = new NetworkFactoryInfo(name, messenger, new AsyncChannel());
+ mHandler.sendMessage(mHandler.obtainMessage(EVENT_REGISTER_NETWORK_FACTORY, nfi));
}
- private void handleRegisterNetworkFactory(Messenger messenger) {
- if (VDBG) log("Got NetworkFactory Messenger");
- AsyncChannel ac = new AsyncChannel();
- mNetworkFactories.add(ac);
- ac.connect(mContext, mTrackerHandler, messenger);
- for (NetworkRequestInfo nri : mNetworkRequests.values()) {
- if (nri.isRequest) {
- int score = 0;
- NetworkAgentInfo currentNetwork = mNetworkForRequestId.get(nri.request.requestId);
- if (currentNetwork != null) score = currentNetwork.currentScore;
- ac.sendMessage(NetworkFactoryProtocol.CMD_REQUEST_NETWORK, score, 0, nri.request);
- }
+ private void handleRegisterNetworkFactory(NetworkFactoryInfo nfi) {
+ if (VDBG) log("Got NetworkFactory Messenger for " + nfi.name);
+ mNetworkFactoryInfos.put(nfi.messenger, nfi);
+ nfi.asyncChannel.connect(mContext, mTrackerHandler, nfi.messenger);
+ }
+
+ @Override
+ public void unregisterNetworkFactory(Messenger messenger) {
+ enforceConnectivityInternalPermission();
+ mHandler.sendMessage(mHandler.obtainMessage(EVENT_UNREGISTER_NETWORK_FACTORY, messenger));
+ }
+
+ private void handleUnregisterNetworkFactory(Messenger messenger) {
+ NetworkFactoryInfo nfi = mNetworkFactoryInfos.remove(messenger);
+ if (nfi == null) {
+ if (VDBG) log("Failed to find Messenger in unregisterNetworkFactory");
+ return;
}
+ if (VDBG) log("unregisterNetworkFactory for " + nfi.name);
}
/**
@@ -5527,8 +5580,8 @@ public class ConnectivityService extends IConnectivityManager.Stub {
private void sendUpdatedScoreToFactories(NetworkRequest networkRequest, int score) {
if (VDBG) log("sending new Min Network Score(" + score + "): " + networkRequest.toString());
- for (AsyncChannel ac : mNetworkFactories) {
- ac.sendMessage(NetworkFactoryProtocol.CMD_REQUEST_NETWORK, score, 0, networkRequest);
+ for (NetworkFactoryInfo nfi : mNetworkFactoryInfos.values()) {
+ nfi.asyncChannel.sendMessage(NetworkFactoryProtocol.CMD_REQUEST_NETWORK, score, 0, networkRequest);
}
}
diff --git a/services/core/java/com/android/server/InputMethodManagerService.java b/services/core/java/com/android/server/InputMethodManagerService.java
index 50553ee..5cb2a8a 100644
--- a/services/core/java/com/android/server/InputMethodManagerService.java
+++ b/services/core/java/com/android/server/InputMethodManagerService.java
@@ -3439,7 +3439,7 @@ public class InputMethodManagerService extends IInputMethodManager.Stub
+ " mShowExplicitlyRequested=" + mShowExplicitlyRequested
+ " mShowForced=" + mShowForced
+ " mInputShown=" + mInputShown);
- p.println(" mSystemReady=" + mSystemReady + " mScreenOn=" + mScreenOn);
+ p.println(" mSystemReady=" + mSystemReady + " mInteractive=" + mScreenOn);
}
p.println(" ");
diff --git a/services/core/java/com/android/server/LocationManagerService.java b/services/core/java/com/android/server/LocationManagerService.java
index e54e5d0..11fc941 100644
--- a/services/core/java/com/android/server/LocationManagerService.java
+++ b/services/core/java/com/android/server/LocationManagerService.java
@@ -1847,10 +1847,10 @@ public class LocationManagerService extends ILocationManager.Stub {
return true;
}
if (mGeocodeProvider != null) {
- if (doesPackageHaveUid(uid, mGeocodeProvider.getConnectedPackageName())) return true;
+ if (doesUidHavePackage(uid, mGeocodeProvider.getConnectedPackageName())) return true;
}
for (LocationProviderProxy proxy : mProxyProviders) {
- if (doesPackageHaveUid(uid, proxy.getConnectedPackageName())) return true;
+ if (doesUidHavePackage(uid, proxy.getConnectedPackageName())) return true;
}
return false;
}
@@ -1876,19 +1876,23 @@ public class LocationManagerService extends ILocationManager.Stub {
"or UID of a currently bound location provider");
}
- private boolean doesPackageHaveUid(int uid, String packageName) {
+ /**
+ * Returns true if the given package belongs to the given uid.
+ */
+ private boolean doesUidHavePackage(int uid, String packageName) {
if (packageName == null) {
return false;
}
- try {
- ApplicationInfo appInfo = mPackageManager.getApplicationInfo(packageName, 0);
- if (appInfo.uid != uid) {
- return false;
- }
- } catch (NameNotFoundException e) {
+ String[] packageNames = mPackageManager.getPackagesForUid(uid);
+ if (packageNames == null) {
return false;
}
- return true;
+ for (String name : packageNames) {
+ if (packageName.equals(name)) {
+ return true;
+ }
+ }
+ return false;
}
@Override
diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java
index 7abc75f..7cd4ef8 100644
--- a/services/core/java/com/android/server/am/ActivityManagerService.java
+++ b/services/core/java/com/android/server/am/ActivityManagerService.java
@@ -13837,7 +13837,7 @@ public final class ActivityManagerService extends ActivityManagerNative
}
if (Proxy.PROXY_CHANGE_ACTION.equals(intent.getAction())) {
- ProxyInfo proxy = intent.getParcelableExtra("proxy");
+ ProxyInfo proxy = intent.getParcelableExtra(Proxy.EXTRA_PROXY_INFO);
mHandler.sendMessage(mHandler.obtainMessage(UPDATE_HTTP_PROXY_MSG, proxy));
}
diff --git a/services/core/java/com/android/server/am/ActivityStack.java b/services/core/java/com/android/server/am/ActivityStack.java
index c1e5e5b..33e59a7 100755
--- a/services/core/java/com/android/server/am/ActivityStack.java
+++ b/services/core/java/com/android/server/am/ActivityStack.java
@@ -742,19 +742,10 @@ final class ActivityStack {
int w = mThumbnailWidth;
int h = mThumbnailHeight;
if (w < 0) {
- Configuration config = res.getConfiguration();
- boolean useAlternateRecents = (config.smallestScreenWidthDp < 600);
- if (useAlternateRecents) {
- mThumbnailWidth = w =
- res.getDimensionPixelSize(com.android.internal.R.dimen.recents_thumbnail_width);
- mThumbnailHeight = h =
- res.getDimensionPixelSize(com.android.internal.R.dimen.recents_thumbnail_height);
- } else {
- mThumbnailWidth = w =
- res.getDimensionPixelSize(com.android.internal.R.dimen.thumbnail_width);
- mThumbnailHeight = h =
- res.getDimensionPixelSize(com.android.internal.R.dimen.thumbnail_height);
- }
+ mThumbnailWidth = w =
+ res.getDimensionPixelSize(com.android.internal.R.dimen.recents_thumbnail_width);
+ mThumbnailHeight = h =
+ res.getDimensionPixelSize(com.android.internal.R.dimen.recents_thumbnail_height);
}
if (w > 0) {
diff --git a/services/core/java/com/android/server/display/DisplayPowerController.java b/services/core/java/com/android/server/display/DisplayPowerController.java
index 3d5fb57..bc264fa 100644
--- a/services/core/java/com/android/server/display/DisplayPowerController.java
+++ b/services/core/java/com/android/server/display/DisplayPowerController.java
@@ -421,6 +421,7 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call
final boolean mustNotify;
boolean mustInitialize = false;
boolean wasDimOrDoze = false;
+ boolean autoBrightnessAdjustmentChanged = false;
synchronized (mLock) {
mPendingUpdatePowerStateLocked = false;
@@ -437,6 +438,8 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call
} else if (mPendingRequestChangedLocked) {
wasDimOrDoze = (mPowerRequest.screenState == DisplayPowerRequest.SCREEN_STATE_DIM
|| mPowerRequest.screenState == DisplayPowerRequest.SCREEN_STATE_DOZE);
+ autoBrightnessAdjustmentChanged = (mPowerRequest.screenAutoBrightnessAdjustment
+ != mPendingRequestLocked.screenAutoBrightnessAdjustment);
mPowerRequest.copyFrom(mPendingRequestLocked);
mWaitingForNegativeProximity |= mPendingWaitForNegativeProximityLocked;
mPendingWaitForNegativeProximityLocked = false;
@@ -494,7 +497,7 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call
if (screenAutoBrightness >= 0 && mPowerRequest.useAutoBrightness) {
// Use current auto-brightness value.
target = screenAutoBrightness;
- slow = mUsingScreenAutoBrightness;
+ slow = mUsingScreenAutoBrightness && !autoBrightnessAdjustmentChanged;
mUsingScreenAutoBrightness = true;
} else {
// Light sensor is disabled or not ready yet.
diff --git a/services/core/java/com/android/server/media/MediaRouteProviderProxy.java b/services/core/java/com/android/server/media/MediaRouteProviderProxy.java
index 1c5cacd..b31153b 100644
--- a/services/core/java/com/android/server/media/MediaRouteProviderProxy.java
+++ b/services/core/java/com/android/server/media/MediaRouteProviderProxy.java
@@ -26,7 +26,7 @@ import android.media.routeprovider.RouteProviderService;
import android.media.routeprovider.RouteRequest;
import android.media.session.RouteEvent;
import android.media.session.RouteInfo;
-import android.media.session.Session;
+import android.media.session.MediaSession;
import android.os.Bundle;
import android.os.Handler;
import android.os.IBinder;
diff --git a/services/core/java/com/android/server/media/MediaSessionRecord.java b/services/core/java/com/android/server/media/MediaSessionRecord.java
index 9677577..00d364b 100644
--- a/services/core/java/com/android/server/media/MediaSessionRecord.java
+++ b/services/core/java/com/android/server/media/MediaSessionRecord.java
@@ -24,16 +24,16 @@ import android.media.session.ISessionController;
import android.media.session.ISessionControllerCallback;
import android.media.session.ISession;
import android.media.session.ISessionCallback;
-import android.media.session.SessionController;
-import android.media.session.MediaMetadata;
+import android.media.session.MediaController;
import android.media.session.RouteCommand;
import android.media.session.RouteInfo;
import android.media.session.RouteOptions;
import android.media.session.RouteEvent;
-import android.media.session.Session;
-import android.media.session.SessionInfo;
+import android.media.session.MediaSession;
+import android.media.session.MediaSessionInfo;
import android.media.session.RouteInterface;
import android.media.session.PlaybackState;
+import android.media.MediaMetadata;
import android.media.Rating;
import android.os.Bundle;
import android.os.Handler;
@@ -85,7 +85,7 @@ public class MediaSessionRecord implements IBinder.DeathRecipient {
private final int mOwnerPid;
private final int mOwnerUid;
private final int mUserId;
- private final SessionInfo mSessionInfo;
+ private final MediaSessionInfo mSessionInfo;
private final String mTag;
private final ControllerStub mController;
private final SessionStub mSession;
@@ -120,7 +120,7 @@ public class MediaSessionRecord implements IBinder.DeathRecipient {
mOwnerPid = ownerPid;
mOwnerUid = ownerUid;
mUserId = userId;
- mSessionInfo = new SessionInfo(UUID.randomUUID().toString(), ownerPackageName);
+ mSessionInfo = new MediaSessionInfo(UUID.randomUUID().toString(), ownerPackageName);
mTag = tag;
mController = new ControllerStub();
mSession = new SessionStub();
@@ -130,7 +130,7 @@ public class MediaSessionRecord implements IBinder.DeathRecipient {
}
/**
- * Get the binder for the {@link Session}.
+ * Get the binder for the {@link MediaSession}.
*
* @return The session binder apps talk to.
*/
@@ -139,7 +139,7 @@ public class MediaSessionRecord implements IBinder.DeathRecipient {
}
/**
- * Get the binder for the {@link SessionController}.
+ * Get the binder for the {@link MediaController}.
*
* @return The controller binder apps talk to.
*/
@@ -170,7 +170,7 @@ public class MediaSessionRecord implements IBinder.DeathRecipient {
*
* @return Info that identifies this session.
*/
- public SessionInfo getSessionInfo() {
+ public MediaSessionInfo getSessionInfo() {
return mSessionInfo;
}
@@ -209,7 +209,7 @@ public class MediaSessionRecord implements IBinder.DeathRecipient {
* @return True if this is a system priority session, false otherwise
*/
public boolean isSystemPriority() {
- return (mFlags & Session.FLAG_EXCLUSIVE_GLOBAL_PRIORITY) != 0;
+ return (mFlags & MediaSession.FLAG_EXCLUSIVE_GLOBAL_PRIORITY) != 0;
}
/**
@@ -221,7 +221,7 @@ public class MediaSessionRecord implements IBinder.DeathRecipient {
public void selectRoute(RouteInfo route) {
synchronized (mLock) {
if (route != mRoute) {
- disconnect(Session.DISCONNECT_REASON_ROUTE_CHANGED);
+ disconnect(MediaSession.DISCONNECT_REASON_ROUTE_CHANGED);
}
mRoute = route;
}
@@ -335,7 +335,7 @@ public class MediaSessionRecord implements IBinder.DeathRecipient {
}
public boolean isTransportControlEnabled() {
- return hasFlag(Session.FLAG_HANDLES_TRANSPORT_CONTROLS);
+ return hasFlag(MediaSession.FLAG_HANDLES_TRANSPORT_CONTROLS);
}
@Override
@@ -353,7 +353,7 @@ public class MediaSessionRecord implements IBinder.DeathRecipient {
return;
}
if (isConnected()) {
- disconnectLocked(Session.DISCONNECT_REASON_SESSION_DESTROYED);
+ disconnectLocked(MediaSession.DISCONNECT_REASON_SESSION_DESTROYED);
}
mRoute = null;
mRequest = null;
@@ -365,6 +365,10 @@ public class MediaSessionRecord implements IBinder.DeathRecipient {
return mSessionCb.mCb;
}
+ public void sendMediaButton(KeyEvent ke, ResultReceiver cb) {
+ mSessionCb.sendMediaButton(ke, cb);
+ }
+
public void dump(PrintWriter pw, String prefix) {
pw.println(prefix + mTag + " " + this);
@@ -536,7 +540,7 @@ public class MediaSessionRecord implements IBinder.DeathRecipient {
@Override
public void disconnect() {
- MediaSessionRecord.this.disconnect(Session.DISCONNECT_REASON_PROVIDER_DISCONNECTED);
+ MediaSessionRecord.this.disconnect(MediaSession.DISCONNECT_REASON_PROVIDER_DISCONNECTED);
}
};
@@ -565,7 +569,7 @@ public class MediaSessionRecord implements IBinder.DeathRecipient {
@Override
public void setFlags(int flags) {
- if ((flags & Session.FLAG_EXCLUSIVE_GLOBAL_PRIORITY) != 0) {
+ if ((flags & MediaSession.FLAG_EXCLUSIVE_GLOBAL_PRIORITY) != 0) {
int pid = getCallingPid();
int uid = getCallingUid();
mService.enforcePhoneStatePermission(pid, uid);
@@ -623,7 +627,7 @@ public class MediaSessionRecord implements IBinder.DeathRecipient {
public void disconnectFromRoute(RouteInfo route) {
if (route != null && mRoute != null
&& TextUtils.equals(route.getId(), mRoute.getId())) {
- disconnect(Session.DISCONNECT_REASON_SESSION_DISCONNECTED);
+ disconnect(MediaSession.DISCONNECT_REASON_SESSION_DISCONNECTED);
}
}
@@ -645,11 +649,11 @@ public class MediaSessionRecord implements IBinder.DeathRecipient {
mCb = cb;
}
- public void sendMediaButton(KeyEvent keyEvent) {
+ public void sendMediaButton(KeyEvent keyEvent, ResultReceiver cb) {
Intent mediaButtonIntent = new Intent(Intent.ACTION_MEDIA_BUTTON);
mediaButtonIntent.putExtra(Intent.EXTRA_KEY_EVENT, keyEvent);
try {
- mCb.onMediaButton(mediaButtonIntent);
+ mCb.onMediaButton(mediaButtonIntent, cb);
} catch (RemoteException e) {
Slog.e(TAG, "Remote failure in sendMediaRequest.", e);
}
@@ -785,7 +789,7 @@ public class MediaSessionRecord implements IBinder.DeathRecipient {
@Override
public void sendMediaButton(KeyEvent mediaButtonIntent) {
- mSessionCb.sendMediaButton(mediaButtonIntent);
+ mSessionCb.sendMediaButton(mediaButtonIntent, null);
}
@Override
diff --git a/services/core/java/com/android/server/media/MediaSessionService.java b/services/core/java/com/android/server/media/MediaSessionService.java
index 78f3b5f..d9e45f5ba 100644
--- a/services/core/java/com/android/server/media/MediaSessionService.java
+++ b/services/core/java/com/android/server/media/MediaSessionService.java
@@ -17,9 +17,12 @@
package com.android.server.media;
import android.Manifest;
+import android.app.Activity;
import android.app.ActivityManager;
+import android.content.BroadcastReceiver;
import android.content.ComponentName;
import android.content.Context;
+import android.content.Intent;
import android.content.pm.PackageManager;
import android.media.routeprovider.RouteRequest;
import android.media.session.ISession;
@@ -27,16 +30,20 @@ import android.media.session.ISessionCallback;
import android.media.session.ISessionManager;
import android.media.session.RouteInfo;
import android.media.session.RouteOptions;
-import android.media.session.Session;
+import android.media.session.MediaSession;
import android.os.Binder;
+import android.os.Bundle;
import android.os.Handler;
import android.os.IBinder;
+import android.os.PowerManager;
import android.os.RemoteException;
+import android.os.ResultReceiver;
import android.os.UserHandle;
import android.provider.Settings;
import android.text.TextUtils;
import android.util.Log;
import android.util.SparseArray;
+import android.view.KeyEvent;
import com.android.server.SystemService;
import com.android.server.Watchdog;
@@ -64,6 +71,7 @@ public class MediaSessionService extends SystemService implements Monitor {
// = new ArrayList<MediaRouteProviderProxy>();
private final Object mLock = new Object();
private final Handler mHandler = new Handler();
+ private final PowerManager.WakeLock mMediaEventWakeLock;
private MediaSessionRecord mPrioritySession;
private int mCurrentUserId = -1;
@@ -79,6 +87,8 @@ public class MediaSessionService extends SystemService implements Monitor {
super(context);
mSessionManagerImpl = new SessionManagerImpl();
mPriorityStack = new MediaSessionStack();
+ PowerManager pm = (PowerManager) context.getSystemService(Context.POWER_SERVICE);
+ mMediaEventWakeLock = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "handleMediaEvent");
}
@Override
@@ -377,7 +387,7 @@ public class MediaSessionService extends SystemService implements Monitor {
/*
* When a session is created the following things need to happen.
- * 1. It's callback binder needs a link to death
+ * 1. Its callback binder needs a link to death
* 2. It needs to be added to all sessions.
* 3. It needs to be added to the priority stack.
* 4. It needs to be added to the relevant user record.
@@ -493,7 +503,7 @@ public class MediaSessionService extends SystemService implements Monitor {
MediaSessionRecord session = mSessions.get(i);
MediaSessionService.this.destroySessionLocked(session);
if (session.isConnected()) {
- session.disconnect(Session.DISCONNECT_REASON_USER_STOPPING);
+ session.disconnect(MediaSession.DISCONNECT_REASON_USER_STOPPING);
}
}
}
@@ -585,9 +595,10 @@ public class MediaSessionService extends SystemService implements Monitor {
}
class SessionManagerImpl extends ISessionManager.Stub {
- // TODO add createSessionAsUser, pass user-id to
- // ActivityManagerNative.handleIncomingUser and stash result for use
- // when starting services on that session's behalf.
+ private static final String EXTRA_WAKELOCK_ACQUIRED =
+ "android.media.AudioService.WAKELOCK_ACQUIRED";
+ private static final int WAKELOCK_RELEASE_ON_FINISHED = 1980; // magic number
+
@Override
public ISession createSession(String packageName, ISessionCallback cb, String tag,
int userId) throws RemoteException {
@@ -644,6 +655,59 @@ public class MediaSessionService extends SystemService implements Monitor {
}
}
+ /**
+ * Handles the dispatching of the media button events to one of the
+ * registered listeners, or if there was none, broadcast an
+ * ACTION_MEDIA_BUTTON intent to the rest of the system.
+ *
+ * @param keyEvent a non-null KeyEvent whose key code is one of the
+ * supported media buttons
+ * @param needWakeLock true if a PARTIAL_WAKE_LOCK needs to be held
+ * while this key event is dispatched.
+ */
+ @Override
+ public void dispatchMediaKeyEvent(KeyEvent keyEvent, boolean needWakeLock) {
+ if (keyEvent == null || !KeyEvent.isMediaKey(keyEvent.getKeyCode())) {
+ Log.w(TAG, "Attempted to dispatch null or non-media key event.");
+ return;
+ }
+ final int pid = Binder.getCallingPid();
+ final int uid = Binder.getCallingUid();
+ final long token = Binder.clearCallingIdentity();
+
+ try {
+ if (needWakeLock) {
+ mMediaEventWakeLock.acquire();
+ }
+ synchronized (mLock) {
+ MediaSessionRecord mbSession = mPriorityStack
+ .getDefaultMediaButtonSession(mCurrentUserId);
+ if (mbSession != null) {
+ if (DEBUG) {
+ Log.d(TAG, "Sending media key to " + mbSession.getSessionInfo());
+ }
+ mbSession.sendMediaButton(keyEvent,
+ needWakeLock ? mKeyEventDoneReceiver : null);
+ } else {
+ if (DEBUG) {
+ Log.d(TAG, "Sending media key ordered broadcast");
+ }
+ // Fallback to legacy behavior
+ Intent keyIntent = new Intent(Intent.ACTION_MEDIA_BUTTON, null);
+ keyIntent.putExtra(Intent.EXTRA_KEY_EVENT, keyEvent);
+ if (needWakeLock) {
+ keyIntent.putExtra(EXTRA_WAKELOCK_ACQUIRED,
+ WAKELOCK_RELEASE_ON_FINISHED);
+ }
+ getContext().sendOrderedBroadcastAsUser(keyIntent, UserHandle.ALL,
+ null, mKeyEventDone, mHandler, Activity.RESULT_OK, null, null);
+ }
+ }
+ } finally {
+ Binder.restoreCallingIdentity(token);
+ }
+ }
+
@Override
public void dump(FileDescriptor fd, final PrintWriter pw, String[] args) {
if (getContext().checkCallingOrSelfPermission(Manifest.permission.DUMP)
@@ -678,6 +742,36 @@ public class MediaSessionService extends SystemService implements Monitor {
}
}
}
+
+ ResultReceiver mKeyEventDoneReceiver = new ResultReceiver(mHandler) {
+ @Override
+ protected void onReceiveResult(int resultCode, Bundle resultData) {
+ synchronized (mLock) {
+ if (mMediaEventWakeLock.isHeld()) {
+ mMediaEventWakeLock.release();
+ }
+ }
+ }
+ };
+
+ BroadcastReceiver mKeyEventDone = new BroadcastReceiver() {
+ @Override
+ public void onReceive(Context context, Intent intent) {
+ if (intent == null) {
+ return;
+ }
+ Bundle extras = intent.getExtras();
+ if (extras == null) {
+ return;
+ }
+ synchronized (mLock) {
+ if (extras.containsKey(EXTRA_WAKELOCK_ACQUIRED)
+ && mMediaEventWakeLock.isHeld()) {
+ mMediaEventWakeLock.release();
+ }
+ }
+ }
+ };
}
}
diff --git a/services/core/java/com/android/server/media/MediaSessionStack.java b/services/core/java/com/android/server/media/MediaSessionStack.java
index f89b14a..7ba9212 100644
--- a/services/core/java/com/android/server/media/MediaSessionStack.java
+++ b/services/core/java/com/android/server/media/MediaSessionStack.java
@@ -17,7 +17,7 @@
package com.android.server.media;
import android.media.session.PlaybackState;
-import android.media.session.Session;
+import android.media.session.MediaSession;
import android.os.UserHandle;
import java.io.PrintWriter;
@@ -62,7 +62,7 @@ public class MediaSessionStack {
*/
public void addSession(MediaSessionRecord record) {
mSessions.add(record);
- if ((record.getFlags() & Session.FLAG_EXCLUSIVE_GLOBAL_PRIORITY) != 0) {
+ if ((record.getFlags() & MediaSession.FLAG_EXCLUSIVE_GLOBAL_PRIORITY) != 0) {
mGlobalPrioritySession = record;
}
clearCache();
@@ -134,7 +134,7 @@ public class MediaSessionStack {
public ArrayList<MediaSessionRecord> getTransportControlSessions(int userId) {
if (mCachedTransportControlList == null) {
mCachedTransportControlList = getPriorityListLocked(true,
- Session.FLAG_HANDLES_TRANSPORT_CONTROLS, userId);
+ MediaSession.FLAG_HANDLES_TRANSPORT_CONTROLS, userId);
}
return mCachedTransportControlList;
}
@@ -170,7 +170,7 @@ public class MediaSessionStack {
return mCachedButtonReceiver;
}
ArrayList<MediaSessionRecord> records = getPriorityListLocked(true,
- Session.FLAG_HANDLES_MEDIA_BUTTONS, userId);
+ MediaSession.FLAG_HANDLES_MEDIA_BUTTONS, userId);
if (records.size() > 0) {
mCachedButtonReceiver = records.get(0);
}
diff --git a/services/core/java/com/android/server/notification/ConditionProviders.java b/services/core/java/com/android/server/notification/ConditionProviders.java
index 007032e..dbfb1cf 100644
--- a/services/core/java/com/android/server/notification/ConditionProviders.java
+++ b/services/core/java/com/android/server/notification/ConditionProviders.java
@@ -88,6 +88,8 @@ public class ConditionProviders extends ManagedServices {
for (int i = 0; i < mRecords.size(); i++) {
pw.print(" "); pw.println(mRecords.get(i));
}
+ pw.print(" mCountdownHelper: ");
+ pw.println(mCountdownHelper.getCurrentConditionDescription());
}
}
@@ -474,6 +476,16 @@ public class ConditionProviders extends ManagedServices {
}
}
+ public String getCurrentConditionDescription() {
+ if (mCurrent == 0) return null;
+ final long time = mCurrent;
+ final long now = System.currentTimeMillis();
+ final CharSequence span =
+ DateUtils.getRelativeTimeSpanString(time, now, DateUtils.MINUTE_IN_MILLIS);
+ return String.format("Scheduled for %s, %s in the future (%s), now=%s",
+ ts(time), time - now, span, ts(now));
+ }
+
private String ts(long time) {
return new Date(time) + " (" + time + ")";
}
diff --git a/services/core/java/com/android/server/notification/NotificationManagerService.java b/services/core/java/com/android/server/notification/NotificationManagerService.java
index 1734a33..9569c0d 100644
--- a/services/core/java/com/android/server/notification/NotificationManagerService.java
+++ b/services/core/java/com/android/server/notification/NotificationManagerService.java
@@ -63,7 +63,7 @@ import android.service.notification.INotificationListener;
import android.service.notification.IConditionListener;
import android.service.notification.IConditionProvider;
import android.service.notification.NotificationListenerService;
-import android.service.notification.NotificationOrderUpdate;
+import android.service.notification.NotificationRankingUpdate;
import android.service.notification.StatusBarNotification;
import android.service.notification.Condition;
import android.service.notification.ZenModeConfig;
@@ -1744,7 +1744,7 @@ public class NotificationManagerService extends SystemService {
sendAccessibilityEvent(notification, pkg);
}
- mListeners.notifyPostedLocked(r.sbn);
+ mListeners.notifyPostedLocked(r.sbn, cloneNotificationListLocked());
} else {
Slog.e(TAG, "Not posting notification with icon==0: " + notification);
if (old != null && old.statusBarKey != null) {
@@ -1755,7 +1755,7 @@ public class NotificationManagerService extends SystemService {
Binder.restoreCallingIdentity(identity);
}
- mListeners.notifyRemovedLocked(r.sbn);
+ mListeners.notifyRemovedLocked(r.sbn, cloneNotificationListLocked());
}
// ATTENTION: in a future release we will bail out here
// so that we do not play sounds, show lights, etc. for invalid
@@ -2041,14 +2041,17 @@ public class NotificationManagerService extends SystemService {
private void handleSendRankingUpdate() {
synchronized (mNotificationList) {
- final int N = mNotificationList.size();
- ArrayList<StatusBarNotification> sbns =
- new ArrayList<StatusBarNotification>(N);
- for (int i = 0; i < N; i++ ) {
- sbns.add(mNotificationList.get(i).sbn);
- }
- mListeners.notifyOrderUpdateLocked(sbns);
+ mListeners.notifyRankingUpdateLocked(cloneNotificationListLocked());
+ }
+ }
+
+ private ArrayList<StatusBarNotification> cloneNotificationListLocked() {
+ final int N = mNotificationList.size();
+ ArrayList<StatusBarNotification> sbns = new ArrayList<StatusBarNotification>(N);
+ for (int i = 0; i < N; i++) {
+ sbns.add(mNotificationList.get(i).sbn);
}
+ return sbns;
}
private final class WorkerHandler extends Handler
@@ -2136,7 +2139,7 @@ public class NotificationManagerService extends SystemService {
Binder.restoreCallingIdentity(identity);
}
r.statusBarKey = null;
- mListeners.notifyRemovedLocked(r.sbn);
+ mListeners.notifyRemovedLocked(r.sbn, cloneNotificationListLocked());
}
// sound
@@ -2442,6 +2445,33 @@ public class NotificationManagerService extends SystemService {
}
}
+ /**
+ * Generates a NotificationRankingUpdate from 'sbns', considering only
+ * notifications visible to the given listener.
+ */
+ private static NotificationRankingUpdate makeRankingUpdateForListener(ManagedServiceInfo info,
+ ArrayList<StatusBarNotification> sbns) {
+ int speedBumpIndex = -1;
+ ArrayList<String> keys = new ArrayList<String>(sbns.size());
+ ArrayList<String> dndKeys = new ArrayList<String>(sbns.size());
+ for (StatusBarNotification sbn: sbns) {
+ if (!info.enabledAndUserMatches(sbn.getUserId())) {
+ continue;
+ }
+ keys.add(sbn.getKey());
+ if (sbn.getNotification().extras.getBoolean(EXTRA_INTERCEPT)) {
+ dndKeys.add(sbn.getKey());
+ }
+ if (speedBumpIndex == -1 &&
+ sbn.getNotification().priority == Notification.PRIORITY_MIN) {
+ speedBumpIndex = keys.size() - 1;
+ }
+ }
+ String[] keysAr = keys.toArray(new String[keys.size()]);
+ String[] dndKeysAr = dndKeys.toArray(new String[dndKeys.size()]);
+ return new NotificationRankingUpdate(keysAr, dndKeysAr, speedBumpIndex);
+ }
+
public class NotificationListeners extends ManagedServices {
public NotificationListeners() {
@@ -2468,9 +2498,12 @@ public class NotificationManagerService extends SystemService {
@Override
public void onServiceAdded(ManagedServiceInfo info) {
final INotificationListener listener = (INotificationListener) info.service;
- final String[] keys = getActiveNotificationKeys(listener);
+ final ArrayList<StatusBarNotification> sbns;
+ synchronized (mNotificationList) {
+ sbns = cloneNotificationListLocked();
+ }
try {
- listener.onListenerConnected(new NotificationOrderUpdate(keys));
+ listener.onListenerConnected(makeRankingUpdateForListener(info, sbns));
} catch (RemoteException e) {
// we tried
}
@@ -2479,44 +2512,47 @@ public class NotificationManagerService extends SystemService {
/**
* asynchronously notify all listeners about a new notification
*/
- public void notifyPostedLocked(StatusBarNotification sbn) {
+ public void notifyPostedLocked(StatusBarNotification sbn,
+ final ArrayList<StatusBarNotification> sbns) {
// make a copy in case changes are made to the underlying Notification object
final StatusBarNotification sbnClone = sbn.clone();
for (final ManagedServiceInfo info : mServices) {
- if (info.isEnabledForCurrentProfiles()) {
- final INotificationListener listener = (INotificationListener) info.service;
- final String[] keys = getActiveNotificationKeys(listener);
- if (keys.length > 0) {
- mHandler.post(new Runnable() {
- @Override
- public void run() {
- notifyPostedIfUserMatch(info, sbnClone, keys);
- }
- });
- }
+ if (!info.isEnabledForCurrentProfiles()) {
+ continue;
}
+ final NotificationRankingUpdate update = makeRankingUpdateForListener(info, sbns);
+ if (update.getOrderedKeys().length == 0) {
+ continue;
+ }
+ mHandler.post(new Runnable() {
+ @Override
+ public void run() {
+ notifyPostedIfUserMatch(info, sbnClone, update);
+ }
+ });
}
}
/**
* asynchronously notify all listeners about a removed notification
*/
- public void notifyRemovedLocked(StatusBarNotification sbn) {
+ public void notifyRemovedLocked(StatusBarNotification sbn,
+ final ArrayList<StatusBarNotification> sbns) {
// make a copy in case changes are made to the underlying Notification object
// NOTE: this copy is lightweight: it doesn't include heavyweight parts of the
// notification
final StatusBarNotification sbnLight = sbn.cloneLight();
for (final ManagedServiceInfo info : mServices) {
- if (info.isEnabledForCurrentProfiles()) {
- final INotificationListener listener = (INotificationListener) info.service;
- final String[] keys = getActiveNotificationKeys(listener);
- mHandler.post(new Runnable() {
- @Override
- public void run() {
- notifyRemovedIfUserMatch(info, sbnLight, keys);
- }
- });
+ if (!info.isEnabledForCurrentProfiles()) {
+ continue;
}
+ mHandler.post(new Runnable() {
+ @Override
+ public void run() {
+ notifyRemovedIfUserMatch(info, sbnLight,
+ makeRankingUpdateForListener(info, sbns));
+ }
+ });
}
}
@@ -2526,60 +2562,52 @@ public class NotificationManagerService extends SystemService {
* must not rely on mutable members of these objects, such as the
* {@link Notification}.
*/
- public void notifyOrderUpdateLocked(final ArrayList<StatusBarNotification> sbns) {
+ public void notifyRankingUpdateLocked(final ArrayList<StatusBarNotification> sbns) {
for (final ManagedServiceInfo serviceInfo : mServices) {
+ if (!serviceInfo.isEnabledForCurrentProfiles()) {
+ continue;
+ }
mHandler.post(new Runnable() {
@Override
public void run() {
- notifyOrderUpdateIfUserMatch(serviceInfo, sbns);
+ notifyRankingUpdate(serviceInfo,
+ makeRankingUpdateForListener(serviceInfo, sbns));
}
});
}
}
private void notifyPostedIfUserMatch(final ManagedServiceInfo info,
- final StatusBarNotification sbn, String[] keys) {
+ final StatusBarNotification sbn, NotificationRankingUpdate rankingUpdate) {
if (!info.enabledAndUserMatches(sbn.getUserId())) {
return;
}
final INotificationListener listener = (INotificationListener)info.service;
try {
- listener.onNotificationPosted(sbn, new NotificationOrderUpdate(keys));
+ listener.onNotificationPosted(sbn, rankingUpdate);
} catch (RemoteException ex) {
Log.e(TAG, "unable to notify listener (posted): " + listener, ex);
}
}
private void notifyRemovedIfUserMatch(ManagedServiceInfo info, StatusBarNotification sbn,
- String[] keys) {
+ NotificationRankingUpdate rankingUpdate) {
if (!info.enabledAndUserMatches(sbn.getUserId())) {
return;
}
- final INotificationListener listener = (INotificationListener)info.service;
+ final INotificationListener listener = (INotificationListener) info.service;
try {
- listener.onNotificationRemoved(sbn, new NotificationOrderUpdate(keys));
+ listener.onNotificationRemoved(sbn, rankingUpdate);
} catch (RemoteException ex) {
Log.e(TAG, "unable to notify listener (removed): " + listener, ex);
}
}
- /**
- * @param sbns an array of {@link StatusBarNotification}s to consider. This code
- * must not rely on mutable members of these objects, such as the
- * {@link Notification}.
- */
- public void notifyOrderUpdateIfUserMatch(ManagedServiceInfo info,
- ArrayList<StatusBarNotification> sbns) {
- ArrayList<String> keys = new ArrayList<String>(sbns.size());
- for (StatusBarNotification sbn: sbns) {
- if (info.enabledAndUserMatches(sbn.getUserId())) {
- keys.add(sbn.getKey());
- }
- }
- final INotificationListener listener = (INotificationListener)info.service;
+ private void notifyRankingUpdate(ManagedServiceInfo info,
+ NotificationRankingUpdate rankingUpdate) {
+ final INotificationListener listener = (INotificationListener) info.service;
try {
- listener.onNotificationOrderUpdate(
- new NotificationOrderUpdate(keys.toArray(new String[keys.size()])));
+ listener.onNotificationRankingUpdate(rankingUpdate);
} catch (RemoteException ex) {
Log.e(TAG, "unable to notify listener (ranking update): " + listener, ex);
}
diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java
index 61b3a89..46c5482 100755
--- a/services/core/java/com/android/server/pm/PackageManagerService.java
+++ b/services/core/java/com/android/server/pm/PackageManagerService.java
@@ -11876,6 +11876,7 @@ public class PackageManagerService extends IPackageManager.Stub {
pw.println(" cmd may be one of:");
pw.println(" l[ibraries]: list known shared libraries");
pw.println(" f[ibraries]: list device features");
+ pw.println(" k[eysets]: print known keysets");
pw.println(" r[esolvers]: dump intent resolvers");
pw.println(" perm[issions]: dump permissions");
pw.println(" pref[erred]: print preferred package settings");
@@ -11886,8 +11887,8 @@ public class PackageManagerService extends IPackageManager.Stub {
pw.println(" m[essages]: print collected runtime messages");
pw.println(" v[erifiers]: print package verifier info");
pw.println(" version: print database version info");
+ pw.println(" write: write current settings now");
pw.println(" <package.name>: info about given package");
- pw.println(" k[eysets]: print known keysets");
return;
} else if ("--checkin".equals(opt)) {
checkin = true;
@@ -11938,6 +11939,12 @@ public class PackageManagerService extends IPackageManager.Stub {
dumpState.setDump(DumpState.DUMP_VERSION);
} else if ("k".equals(cmd) || "keysets".equals(cmd)) {
dumpState.setDump(DumpState.DUMP_KEYSETS);
+ } else if ("write".equals(cmd)) {
+ synchronized (mPackages) {
+ mSettings.writeLPr();
+ pw.println("Settings written.");
+ return;
+ }
}
}
diff --git a/services/core/java/com/android/server/pm/UserManagerService.java b/services/core/java/com/android/server/pm/UserManagerService.java
index 131d05b..fd180bf 100644
--- a/services/core/java/com/android/server/pm/UserManagerService.java
+++ b/services/core/java/com/android/server/pm/UserManagerService.java
@@ -511,8 +511,16 @@ public class UserManagerService extends IUserManager.Stub {
* Check if we've hit the limit of how many users can be created.
*/
private boolean isUserLimitReachedLocked() {
- int nUsers = mUsers.size();
- return nUsers >= UserManager.getMaxSupportedUsers();
+ int aliveUserCount = 0;
+ final int totalUserCount = mUsers.size();
+ // Skip over users being removed
+ for (int i = 0; i < totalUserCount; i++) {
+ UserInfo user = mUsers.valueAt(i);
+ if (!mRemovingUserIds.get(user.id)) {
+ aliveUserCount++;
+ }
+ }
+ return aliveUserCount >= UserManager.getMaxSupportedUsers();
}
/**
diff --git a/services/core/java/com/android/server/statusbar/StatusBarManagerService.java b/services/core/java/com/android/server/statusbar/StatusBarManagerService.java
index 738ad32..8b8c73d 100644
--- a/services/core/java/com/android/server/statusbar/StatusBarManagerService.java
+++ b/services/core/java/com/android/server/statusbar/StatusBarManagerService.java
@@ -460,6 +460,24 @@ public class StatusBarManagerService extends IStatusBarService.Stub
}
@Override
+ public void showRecentApps(boolean triggeredFromAltTab) {
+ if (mBar != null) {
+ try {
+ mBar.showRecentApps(triggeredFromAltTab);
+ } catch (RemoteException ex) {}
+ }
+ }
+
+ @Override
+ public void hideRecentApps(boolean triggeredFromAltTab) {
+ if (mBar != null) {
+ try {
+ mBar.hideRecentApps(triggeredFromAltTab);
+ } catch (RemoteException ex) {}
+ }
+ }
+
+ @Override
public void setCurrentUser(int newUserId) {
if (SPEW) Slog.d(TAG, "Setting current user to user " + newUserId);
mCurrentUserId = newUserId;
diff --git a/services/core/java/com/android/server/trust/TrustManagerService.java b/services/core/java/com/android/server/trust/TrustManagerService.java
index c1b9a33..efaa91b 100644
--- a/services/core/java/com/android/server/trust/TrustManagerService.java
+++ b/services/core/java/com/android/server/trust/TrustManagerService.java
@@ -324,8 +324,6 @@ public class TrustManagerService extends SystemService {
mTrustListeners.get(i).onTrustChanged(enabled, userId);
} catch (RemoteException e) {
Slog.e(TAG, "Exception while notifying TrustListener. Removing listener.", e);
- mTrustListeners.get(i);
- i--;
}
}
}
diff --git a/services/core/java/com/android/server/wm/AppTransition.java b/services/core/java/com/android/server/wm/AppTransition.java
index 99ec242..e2d2ac6 100644
--- a/services/core/java/com/android/server/wm/AppTransition.java
+++ b/services/core/java/com/android/server/wm/AppTransition.java
@@ -26,6 +26,7 @@ import android.os.Handler;
import android.os.IRemoteCallback;
import android.os.SystemProperties;
import android.util.Slog;
+import android.view.View;
import android.view.WindowManager;
import android.view.animation.AlphaAnimation;
import android.view.animation.Animation;
@@ -34,7 +35,6 @@ import android.view.animation.AnimationUtils;
import android.view.animation.ClipRectAnimation;
import android.view.animation.Interpolator;
import android.view.animation.ScaleAnimation;
-
import android.view.animation.TranslateAnimation;
import com.android.internal.util.DumpUtils.Dump;
import com.android.server.AttributeCache;
@@ -500,7 +500,8 @@ public class AppTransition implements Dump {
*/
Animation createAlternateThumbnailEnterExitAnimationLocked(int thumbTransitState, int appWidth,
int appHeight, int orientation, int transit,
- Rect containingFrame, Rect contentInsets) {
+ Rect containingFrame, Rect contentInsets,
+ boolean isFullScreen) {
Animation a;
final int thumbWidthI = mNextAppTransitionThumbnail.getWidth();
final float thumbWidth = thumbWidthI > 0 ? thumbWidthI : 1;
@@ -520,6 +521,9 @@ public class AppTransition implements Dump {
scaledTopDecor = (int) (scale * contentInsets.top);
int unscaledThumbHeight = (int) (thumbHeight / scale);
mTmpFromClipRect.set(containingFrame);
+ if (isFullScreen) {
+ mTmpFromClipRect.top = contentInsets.top;
+ }
mTmpFromClipRect.bottom = (mTmpFromClipRect.top + unscaledThumbHeight);
mTmpToClipRect.set(containingFrame);
} else {
@@ -527,7 +531,12 @@ public class AppTransition implements Dump {
scale = thumbHeight / (appHeight - contentInsets.top);
scaledTopDecor = (int) (scale * contentInsets.top);
int unscaledThumbWidth = (int) (thumbWidth / scale);
+ int unscaledThumbHeight = (int) (thumbHeight / scale);
mTmpFromClipRect.set(containingFrame);
+ if (isFullScreen) {
+ mTmpFromClipRect.top = contentInsets.top;
+ mTmpFromClipRect.bottom = (mTmpFromClipRect.top + unscaledThumbHeight);
+ }
mTmpFromClipRect.right = (mTmpFromClipRect.left + unscaledThumbWidth);
mTmpToClipRect.set(containingFrame);
}
@@ -575,14 +584,22 @@ public class AppTransition implements Dump {
int unscaledThumbHeight = (int) (thumbHeight / scale);
mTmpFromClipRect.set(containingFrame);
mTmpToClipRect.set(containingFrame);
+ if (isFullScreen) {
+ mTmpToClipRect.top = contentInsets.top;
+ }
mTmpToClipRect.bottom = (mTmpToClipRect.top + unscaledThumbHeight);
} else {
// In landscape, we scale the height and clip to the top/left square
scale = thumbHeight / (appHeight - contentInsets.top);
scaledTopDecor = (int) (scale * contentInsets.top);
int unscaledThumbWidth = (int) (thumbWidth / scale);
+ int unscaledThumbHeight = (int) (thumbHeight / scale);
mTmpFromClipRect.set(containingFrame);
mTmpToClipRect.set(containingFrame);
+ if (isFullScreen) {
+ mTmpToClipRect.top = contentInsets.top;
+ mTmpToClipRect.bottom = (mTmpToClipRect.top + unscaledThumbHeight);
+ }
mTmpToClipRect.right = (mTmpToClipRect.left + unscaledThumbWidth);
}
@@ -679,7 +696,7 @@ public class AppTransition implements Dump {
Animation loadAnimation(WindowManager.LayoutParams lp, int transit, boolean enter,
int appWidth, int appHeight, int orientation,
- Rect containingFrame, Rect contentInsets, Configuration configuration) {
+ Rect containingFrame, Rect contentInsets, boolean isFullScreen) {
Animation a;
if (mNextAppTransitionType == NEXT_TRANSIT_TYPE_CUSTOM) {
a = loadAnimation(mNextAppTransitionPackage, enter ?
@@ -700,15 +717,9 @@ public class AppTransition implements Dump {
mNextAppTransitionType == NEXT_TRANSIT_TYPE_THUMBNAIL_SCALE_DOWN) {
mNextAppTransitionScaleUp =
(mNextAppTransitionType == NEXT_TRANSIT_TYPE_THUMBNAIL_SCALE_UP);
- boolean useAlternateThumbnailAnimation = (configuration.smallestScreenWidthDp < 600);
- if (useAlternateThumbnailAnimation) {
- a = createAlternateThumbnailEnterExitAnimationLocked(
- getThumbnailTransitionState(enter), appWidth, appHeight, orientation,
- transit, containingFrame, contentInsets);
- } else {
- a = createThumbnailEnterExitAnimationLocked(getThumbnailTransitionState(enter),
- appWidth, appHeight, transit);
- }
+ a = createAlternateThumbnailEnterExitAnimationLocked(
+ getThumbnailTransitionState(enter), appWidth, appHeight, orientation,
+ transit, containingFrame, contentInsets, isFullScreen);
if (DEBUG_APP_TRANSITIONS || DEBUG_ANIM) {
String animName = mNextAppTransitionScaleUp ?
"ANIM_THUMBNAIL_SCALE_UP" : "ANIM_THUMBNAIL_SCALE_DOWN";
diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java
index b61ba5c..63a4f52 100644
--- a/services/core/java/com/android/server/wm/WindowManagerService.java
+++ b/services/core/java/com/android/server/wm/WindowManagerService.java
@@ -289,6 +289,11 @@ public class WindowManagerService extends IWindowManager.Stub
private static final int MAX_SCREENSHOT_RETRIES = 3;
+ // The flag describing a full screen app window (where the app takes care of drawing under the
+ // SystemUI bars)
+ private static final int SYSTEM_UI_FLAGS_LAYOUT_STABLE_FULLSCREEN =
+ View.SYSTEM_UI_FLAG_LAYOUT_STABLE | View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN;
+
final private KeyguardDisableHandler mKeyguardDisableHandler;
final BroadcastReceiver mBroadcastReceiver = new BroadcastReceiver() {
@@ -3193,8 +3198,11 @@ public class WindowManagerService extends IWindowManager.Stub
}
}
+ boolean isFullScreen =
+ ((win.mSystemUiVisibility & SYSTEM_UI_FLAGS_LAYOUT_STABLE_FULLSCREEN)
+ == SYSTEM_UI_FLAGS_LAYOUT_STABLE_FULLSCREEN);
Animation a = mAppTransition.loadAnimation(lp, transit, enter, width, height,
- mCurConfiguration.orientation, containingFrame, contentInsets, mCurConfiguration);
+ mCurConfiguration.orientation, containingFrame, contentInsets, isFullScreen);
if (a != null) {
if (DEBUG_ANIM) {
RuntimeException e = null;
@@ -8677,7 +8685,7 @@ public class WindowManagerService extends IWindowManager.Stub
wtoken.deferClearAllDrawn = false;
}
- boolean useAlternateThumbnailAnimation = (mCurConfiguration.smallestScreenWidthDp < 600);
+ boolean useAlternateThumbnailAnimation = true;
AppWindowAnimator appAnimator =
topOpeningApp == null ? null : topOpeningApp.mAppAnimator;
Bitmap nextAppTransitionThumbnail = mAppTransition.getNextAppTransitionThumbnail();
diff --git a/services/core/java/com/android/server/wm/WindowStateAnimator.java b/services/core/java/com/android/server/wm/WindowStateAnimator.java
index 3c9d53e..1e79dcb 100644
--- a/services/core/java/com/android/server/wm/WindowStateAnimator.java
+++ b/services/core/java/com/android/server/wm/WindowStateAnimator.java
@@ -46,6 +46,7 @@ import android.view.MagnificationSpec;
import android.view.Surface.OutOfResourcesException;
import android.view.SurfaceControl;
import android.view.SurfaceSession;
+import android.view.View;
import android.view.WindowManager;
import android.view.WindowManagerPolicy;
import android.view.WindowManager.LayoutParams;
@@ -151,6 +152,10 @@ class WindowStateAnimator {
static final int READY_TO_SHOW = 3;
/** Set when the window has been shown in the screen the first time. */
static final int HAS_DRAWN = 4;
+
+ private static final int SYSTEM_UI_FLAGS_LAYOUT_STABLE_FULLSCREEN =
+ View.SYSTEM_UI_FLAG_LAYOUT_STABLE | View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN;
+
static String drawStateToString(int state) {
switch (state) {
case NO_SURFACE: return "NO_SURFACE";
@@ -1176,9 +1181,15 @@ class WindowStateAnimator {
// content insets as well.
int offsetTop = Math.max(w.mSystemDecorRect.top, w.mContentInsets.top);
mTmpClipRect.set(w.mSystemDecorRect);
- mTmpClipRect.offset(0, -offsetTop);
- mTmpClipRect.intersect(mClipRect);
- mTmpClipRect.offset(0, offsetTop);
+ // Don't apply the workaround to apps explicitly requesting fullscreen layout.
+ if ((w.mSystemUiVisibility & SYSTEM_UI_FLAGS_LAYOUT_STABLE_FULLSCREEN)
+ == SYSTEM_UI_FLAGS_LAYOUT_STABLE_FULLSCREEN) {
+ mTmpClipRect.intersect(mClipRect);
+ } else {
+ mTmpClipRect.offset(0, -offsetTop);
+ mTmpClipRect.intersect(mClipRect);
+ mTmpClipRect.offset(0, offsetTop);
+ }
clipRect = mTmpClipRect;
}