diff options
author | Dianne Hackborn <hackbod@google.com> | 2012-11-27 11:31:53 -0800 |
---|---|---|
committer | Android Git Automerger <android-git-automerger@android.com> | 2012-11-27 11:31:53 -0800 |
commit | 78551bc7d5541c86503b32db0e3e2564218bf179 (patch) | |
tree | 8584ff0257ea17603a5402bf2323afe316376818 | |
parent | 3407c24dd95896706a51d816b085e4ed8df3443a (diff) | |
parent | ba4ac51823c59152e2167365b81ac56857b6b4d0 (diff) | |
download | frameworks_base-78551bc7d5541c86503b32db0e3e2564218bf179.zip frameworks_base-78551bc7d5541c86503b32db0e3e2564218bf179.tar.gz frameworks_base-78551bc7d5541c86503b32db0e3e2564218bf179.tar.bz2 |
am ba4ac518: Merge "Improve debugging for issue #7586414: AlarmManager wakelocks held" into jb-mr1.1-dev
* commit 'ba4ac51823c59152e2167365b81ac56857b6b4d0':
Improve debugging for issue #7586414: AlarmManager wakelocks held
-rw-r--r-- | core/java/android/app/ActivityManagerNative.java | 29 | ||||
-rw-r--r-- | core/java/android/app/IActivityManager.java | 3 | ||||
-rw-r--r-- | core/java/android/app/PendingIntent.java | 14 | ||||
-rw-r--r-- | core/java/android/os/BatteryStats.java | 96 | ||||
-rw-r--r-- | core/java/com/android/internal/util/LocalLog.java | 66 | ||||
-rw-r--r-- | services/java/com/android/server/AlarmManagerService.java | 232 | ||||
-rw-r--r-- | services/java/com/android/server/am/ActivityManagerService.java | 12 |
7 files changed, 400 insertions, 52 deletions
diff --git a/core/java/android/app/ActivityManagerNative.java b/core/java/android/app/ActivityManagerNative.java index 67d3930..61b2067 100644 --- a/core/java/android/app/ActivityManagerNative.java +++ b/core/java/android/app/ActivityManagerNative.java @@ -1701,6 +1701,21 @@ public abstract class ActivityManagerNative extends Binder implements IActivityM return true; } + case GET_INTENT_FOR_INTENT_SENDER_TRANSACTION: { + data.enforceInterface(IActivityManager.descriptor); + IIntentSender r = IIntentSender.Stub.asInterface( + data.readStrongBinder()); + Intent intent = getIntentForIntentSender(r); + reply.writeNoException(); + if (intent != null) { + reply.writeInt(1); + intent.writeToParcel(reply, Parcelable.PARCELABLE_WRITE_RETURN_VALUE); + } else { + reply.writeInt(0); + } + return true; + } + case UPDATE_PERSISTENT_CONFIGURATION_TRANSACTION: { data.enforceInterface(IActivityManager.descriptor); Configuration config = Configuration.CREATOR.createFromParcel(data); @@ -3977,6 +3992,20 @@ class ActivityManagerProxy implements IActivityManager return res; } + public Intent getIntentForIntentSender(IIntentSender sender) throws RemoteException { + Parcel data = Parcel.obtain(); + Parcel reply = Parcel.obtain(); + data.writeInterfaceToken(IActivityManager.descriptor); + data.writeStrongBinder(sender.asBinder()); + mRemote.transact(GET_INTENT_FOR_INTENT_SENDER_TRANSACTION, data, reply, 0); + reply.readException(); + Intent res = reply.readInt() != 0 + ? Intent.CREATOR.createFromParcel(reply) : null; + data.recycle(); + reply.recycle(); + return res; + } + public void updatePersistentConfiguration(Configuration values) throws RemoteException { Parcel data = Parcel.obtain(); diff --git a/core/java/android/app/IActivityManager.java b/core/java/android/app/IActivityManager.java index 8fc1c86..8af17a4 100644 --- a/core/java/android/app/IActivityManager.java +++ b/core/java/android/app/IActivityManager.java @@ -341,6 +341,8 @@ public interface IActivityManager extends IInterface { public boolean isIntentSenderAnActivity(IIntentSender sender) throws RemoteException; + public Intent getIntentForIntentSender(IIntentSender sender) throws RemoteException; + public void updatePersistentConfiguration(Configuration values) throws RemoteException; public long[] getProcessPss(int[] pids) throws RemoteException; @@ -621,4 +623,5 @@ public interface IActivityManager extends IInterface { int REQUEST_BUG_REPORT_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+157; int INPUT_DISPATCHING_TIMED_OUT_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+158; int CLEAR_PENDING_BACKUP_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+159; + int GET_INTENT_FOR_INTENT_SENDER_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+160; } diff --git a/core/java/android/app/PendingIntent.java b/core/java/android/app/PendingIntent.java index d36d99d..5c75aff 100644 --- a/core/java/android/app/PendingIntent.java +++ b/core/java/android/app/PendingIntent.java @@ -790,6 +790,20 @@ public final class PendingIntent implements Parcelable { } /** + * @hide + * Return the Intent of this PendingIntent. + */ + public Intent getIntent() { + try { + return ActivityManagerNative.getDefault() + .getIntentForIntentSender(mTarget); + } catch (RemoteException e) { + // Should never happen. + return null; + } + } + + /** * Comparison operator on two PendingIntent objects, such that true * is returned then they both represent the same operation from the * same package. This allows you to use {@link #getActivity}, diff --git a/core/java/android/os/BatteryStats.java b/core/java/android/os/BatteryStats.java index 54f2fe3..9821824 100644 --- a/core/java/android/os/BatteryStats.java +++ b/core/java/android/os/BatteryStats.java @@ -18,6 +18,8 @@ package android.os; import java.io.PrintWriter; import java.util.ArrayList; +import java.util.Collections; +import java.util.Comparator; import java.util.Formatter; import java.util.List; import java.util.Map; @@ -1127,8 +1129,10 @@ public abstract class BatteryStats implements Parcelable { if (totalTimeMillis != 0) { sb.append(linePrefix); formatTimeMs(sb, totalTimeMillis); - if (name != null) sb.append(name); - sb.append(' '); + if (name != null) { + sb.append(name); + sb.append(' '); + } sb.append('('); sb.append(count); sb.append(" times)"); @@ -1440,8 +1444,21 @@ public abstract class BatteryStats implements Parcelable { } } + static final class TimerEntry { + final String mName; + final int mId; + final BatteryStats.Timer mTimer; + final long mTime; + TimerEntry(String name, int id, BatteryStats.Timer timer, long time) { + mName = name; + mId = id; + mTimer = timer; + mTime = time; + } + } + @SuppressWarnings("unused") - public final void dumpLocked(PrintWriter pw, String prefix, int which, int reqUid) { + public final void dumpLocked(PrintWriter pw, String prefix, final int which, int reqUid) { final long rawUptime = SystemClock.uptimeMillis() * 1000; final long rawRealtime = SystemClock.elapsedRealtime() * 1000; final long batteryUptime = getBatteryUptime(rawUptime); @@ -1516,19 +1533,43 @@ public abstract class BatteryStats implements Parcelable { long txTotal = 0; long fullWakeLockTimeTotalMicros = 0; long partialWakeLockTimeTotalMicros = 0; - + + final Comparator<TimerEntry> timerComparator = new Comparator<TimerEntry>() { + @Override + public int compare(TimerEntry lhs, TimerEntry rhs) { + long lhsTime = lhs.mTime; + long rhsTime = rhs.mTime; + if (lhsTime < rhsTime) { + return 1; + } + if (lhsTime > rhsTime) { + return -1; + } + return 0; + } + }; + if (reqUid < 0) { Map<String, ? extends BatteryStats.Timer> kernelWakelocks = getKernelWakelockStats(); if (kernelWakelocks.size() > 0) { + final ArrayList<TimerEntry> timers = new ArrayList<TimerEntry>(); for (Map.Entry<String, ? extends BatteryStats.Timer> ent : kernelWakelocks.entrySet()) { - + BatteryStats.Timer timer = ent.getValue(); + long totalTimeMillis = computeWakeLock(timer, batteryRealtime, which); + if (totalTimeMillis > 0) { + timers.add(new TimerEntry(ent.getKey(), 0, timer, totalTimeMillis)); + } + } + Collections.sort(timers, timerComparator); + for (int i=0; i<timers.size(); i++) { + TimerEntry timer = timers.get(i); String linePrefix = ": "; sb.setLength(0); sb.append(prefix); sb.append(" Kernel Wake lock "); - sb.append(ent.getKey()); - linePrefix = printWakeLock(sb, ent.getValue(), batteryRealtime, null, which, - linePrefix); + sb.append(timer.mName); + linePrefix = printWakeLock(sb, timer.mTimer, batteryRealtime, null, + which, linePrefix); if (!linePrefix.equals(": ")) { sb.append(" realtime"); // Only print out wake locks that were held @@ -1537,7 +1578,9 @@ public abstract class BatteryStats implements Parcelable { } } } - + + final ArrayList<TimerEntry> timers = new ArrayList<TimerEntry>(); + for (int iu = 0; iu < NU; iu++) { Uid u = uidStats.valueAt(iu); rxTotal += u.getTcpBytesReceived(which); @@ -1557,8 +1600,18 @@ public abstract class BatteryStats implements Parcelable { Timer partialWakeTimer = wl.getWakeTime(WAKE_TYPE_PARTIAL); if (partialWakeTimer != null) { - partialWakeLockTimeTotalMicros += partialWakeTimer.getTotalTimeLocked( + long totalTimeMicros = partialWakeTimer.getTotalTimeLocked( batteryRealtime, which); + if (totalTimeMicros > 0) { + if (reqUid < 0) { + // Only show the ordered list of all wake + // locks if the caller is not asking for data + // about a specific uid. + timers.add(new TimerEntry(ent.getKey(), u.getUid(), + partialWakeTimer, totalTimeMicros)); + } + partialWakeLockTimeTotalMicros += totalTimeMicros; + } } } } @@ -1571,7 +1624,7 @@ public abstract class BatteryStats implements Parcelable { sb.append(prefix); sb.append(" Total full wakelock time: "); formatTimeMs(sb, (fullWakeLockTimeTotalMicros + 500) / 1000); - sb.append(", Total partial waklock time: "); formatTimeMs(sb, + sb.append(", Total partial wakelock time: "); formatTimeMs(sb, (partialWakeLockTimeTotalMicros + 500) / 1000); pw.println(sb.toString()); @@ -1676,9 +1729,26 @@ public abstract class BatteryStats implements Parcelable { pw.println(getDischargeAmountScreenOnSinceCharge()); pw.print(prefix); pw.print(" Amount discharged while screen off: "); pw.println(getDischargeAmountScreenOffSinceCharge()); - pw.println(" "); + pw.println(); + } + + if (timers.size() > 0) { + Collections.sort(timers, timerComparator); + pw.print(prefix); pw.println(" All partial wake locks:"); + for (int i=0; i<timers.size(); i++) { + TimerEntry timer = timers.get(i); + sb.setLength(0); + sb.append(" Wake lock #"); + sb.append(timer.mId); + sb.append(" "); + sb.append(timer.mName); + printWakeLock(sb, timer.mTimer, batteryRealtime, null, which, ": "); + sb.append(" realtime"); + pw.println(sb.toString()); + } + timers.clear(); + pw.println(); } - for (int iu=0; iu<NU; iu++) { final int uid = uidStats.keyAt(iu); diff --git a/core/java/com/android/internal/util/LocalLog.java b/core/java/com/android/internal/util/LocalLog.java new file mode 100644 index 0000000..f0e6171 --- /dev/null +++ b/core/java/com/android/internal/util/LocalLog.java @@ -0,0 +1,66 @@ +/* + * Copyright (C) 2012 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.internal.util; + +import java.io.PrintWriter; +import java.util.ArrayList; + +import android.util.Slog; + +/** + * Helper class for logging serious issues, which also keeps a small + * snapshot of the logged events that can be printed later, such as part + * of a system service's dumpsys output. + * @hide + */ +public class LocalLog { + private final String mTag; + private final int mMaxLines = 20; + private final ArrayList<String> mLines = new ArrayList<String>(mMaxLines); + + public LocalLog(String tag) { + mTag = tag; + } + + public void w(String msg) { + synchronized (mLines) { + Slog.w(mTag, msg); + if (mLines.size() >= mMaxLines) { + mLines.remove(0); + } + mLines.add(msg); + } + } + + public boolean dump(PrintWriter pw, String header, String prefix) { + synchronized (mLines) { + if (mLines.size() <= 0) { + return false; + } + if (header != null) { + pw.println(header); + } + for (int i=0; i<mLines.size(); i++) { + if (prefix != null) { + pw.print(prefix); + } + pw.println(mLines.get(i)); + } + return true; + } + } +} diff --git a/services/java/com/android/server/AlarmManagerService.java b/services/java/com/android/server/AlarmManagerService.java index 440f8e1..cbd00f3 100644 --- a/services/java/com/android/server/AlarmManagerService.java +++ b/services/java/com/android/server/AlarmManagerService.java @@ -22,6 +22,7 @@ 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; @@ -38,6 +39,7 @@ import android.os.UserHandle; import android.os.WorkSource; import android.text.TextUtils; import android.text.format.Time; +import android.util.Pair; import android.util.Slog; import android.util.TimeUtils; @@ -45,16 +47,18 @@ import java.io.FileDescriptor; import java.io.PrintWriter; import java.text.SimpleDateFormat; import java.util.ArrayList; +import java.util.Arrays; import java.util.Calendar; import java.util.Collections; import java.util.Comparator; import java.util.Date; import java.util.HashMap; import java.util.Iterator; -import java.util.LinkedList; import java.util.Map; import java.util.TimeZone; +import com.android.internal.util.LocalLog; + class AlarmManagerService extends IAlarmManager.Stub { // The threshold for how long an alarm can be late before we print a // warning message. The time duration is in milliseconds. @@ -79,7 +83,9 @@ class AlarmManagerService extends IAlarmManager.Stub { = new Intent().addFlags(Intent.FLAG_FROM_BACKGROUND); private final Context mContext; - + + private final LocalLog mLog = new LocalLog(TAG); + private Object mLock = new Object(); private final ArrayList<Alarm> mRtcWakeupAlarms = new ArrayList<Alarm>(); @@ -91,7 +97,7 @@ class AlarmManagerService extends IAlarmManager.Stub { private int mDescriptor; private int mBroadcastRefCount = 0; private PowerManager.WakeLock mWakeLock; - private LinkedList<PendingIntent> mInFlight = new LinkedList<PendingIntent>(); + private ArrayList<InFlight> mInFlight = new ArrayList<InFlight>(); private final AlarmThread mWaitThread = new AlarmThread(); private final AlarmHandler mHandler = new AlarmHandler(); private ClockReceiver mClockReceiver; @@ -99,18 +105,59 @@ class AlarmManagerService extends IAlarmManager.Stub { private final ResultReceiver mResultReceiver = new ResultReceiver(); private final PendingIntent mTimeTickSender; private final PendingIntent mDateChangeSender; - + + private static final class InFlight extends Intent { + final PendingIntent mPendingIntent; + final Pair<String, ComponentName> mTarget; + final BroadcastStats mBroadcastStats; + final FilterStats mFilterStats; + + InFlight(AlarmManagerService service, PendingIntent pendingIntent) { + mPendingIntent = pendingIntent; + Intent intent = pendingIntent.getIntent(); + mTarget = intent != null + ? new Pair<String, ComponentName>(intent.getAction(), intent.getComponent()) + : null; + mBroadcastStats = service.getStatsLocked(pendingIntent); + FilterStats fs = mBroadcastStats.filterStats.get(mTarget); + if (fs == null) { + fs = new FilterStats(mBroadcastStats, mTarget); + mBroadcastStats.filterStats.put(mTarget, fs); + } + mFilterStats = fs; + } + } + private static final class FilterStats { + final BroadcastStats mBroadcastStats; + final Pair<String, ComponentName> mTarget; + + long aggregateTime; int count; + int numWakeup; + long startTime; + int nesting; + + FilterStats(BroadcastStats broadcastStats, Pair<String, ComponentName> target) { + mBroadcastStats = broadcastStats; + mTarget = target; + } } private static final class BroadcastStats { + final String mPackageName; + long aggregateTime; + int count; int numWakeup; long startTime; int nesting; - HashMap<Intent.FilterComparison, FilterStats> filterStats - = new HashMap<Intent.FilterComparison, FilterStats>(); + final HashMap<Pair<String, ComponentName>, FilterStats> filterStats + = new HashMap<Pair<String, ComponentName>, FilterStats>(); + + BroadcastStats(String packageName) { + mPackageName = packageName; + } } private final HashMap<String, BroadcastStats> mBroadcastStats @@ -496,24 +543,104 @@ class AlarmManagerService extends IAlarmManager.Stub { dumpAlarmList(pw, mElapsedRealtimeAlarms, " ", "ELAPSED", now); } } - - pw.println(" "); + + pw.println(); pw.print(" Broadcast ref count: "); pw.println(mBroadcastRefCount); - + pw.println(); + + if (mLog.dump(pw, " Recent problems", " ")) { + pw.println(); + } + + final FilterStats[] topFilters = new FilterStats[10]; + final Comparator<FilterStats> comparator = new Comparator<FilterStats>() { + @Override + public int compare(FilterStats lhs, FilterStats rhs) { + if (lhs.aggregateTime < rhs.aggregateTime) { + return 1; + } else if (lhs.aggregateTime > rhs.aggregateTime) { + return -1; + } + return 0; + } + }; + int len = 0; + for (Map.Entry<String, BroadcastStats> be : mBroadcastStats.entrySet()) { + BroadcastStats bs = be.getValue(); + for (Map.Entry<Pair<String, ComponentName>, FilterStats> fe + : bs.filterStats.entrySet()) { + FilterStats fs = fe.getValue(); + int pos = len > 0 + ? Arrays.binarySearch(topFilters, 0, len, fs, comparator) : 0; + if (pos < 0) { + pos = -pos - 1; + } + if (pos < topFilters.length) { + int copylen = topFilters.length - pos - 1; + if (copylen > 0) { + System.arraycopy(topFilters, pos, topFilters, pos+1, copylen); + } + topFilters[pos] = fs; + if (len < topFilters.length) { + len++; + } + } + } + } + if (len > 0) { + pw.println(" Top Alarms:"); + for (int i=0; i<len; i++) { + FilterStats fs = topFilters[i]; + pw.print(" "); + if (fs.nesting > 0) pw.print("*ACTIVE* "); + TimeUtils.formatDuration(fs.aggregateTime, pw); + pw.print(" running, "); pw.print(fs.numWakeup); + pw.print(" wakeups, "); pw.print(fs.count); + pw.print(" alarms: "); 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.println(); + } + } + pw.println(" "); pw.println(" Alarm Stats:"); + final ArrayList<FilterStats> tmpFilters = new ArrayList<FilterStats>(); for (Map.Entry<String, BroadcastStats> be : mBroadcastStats.entrySet()) { BroadcastStats bs = be.getValue(); - pw.print(" "); pw.println(be.getKey()); - pw.print(" "); pw.print(bs.aggregateTime); - pw.print("ms running, "); pw.print(bs.numWakeup); - pw.println(" wakeups"); - for (Map.Entry<Intent.FilterComparison, FilterStats> fe + pw.print(" "); + if (bs.nesting > 0) pw.print("*ACTIVE* "); + pw.print(be.getKey()); + pw.print(" "); TimeUtils.formatDuration(bs.aggregateTime, pw); + pw.print(" running, "); pw.print(bs.numWakeup); + pw.println(" wakeups:"); + tmpFilters.clear(); + for (Map.Entry<Pair<String, ComponentName>, FilterStats> fe : bs.filterStats.entrySet()) { - pw.print(" "); pw.print(fe.getValue().count); - pw.print(" alarms: "); - pw.println(fe.getKey().getIntent().toShortString( - false, true, false, true)); + tmpFilters.add(fe.getValue()); + } + Collections.sort(tmpFilters, comparator); + for (int i=0; i<tmpFilters.size(); i++) { + FilterStats fs = tmpFilters.get(i); + pw.print(" "); + if (fs.nesting > 0) pw.print("*ACTIVE* "); + 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.println(); } } } @@ -708,18 +835,31 @@ class AlarmManagerService extends IAlarmManager.Stub { setWakelockWorkSource(alarm.operation); mWakeLock.acquire(); } - mInFlight.add(alarm.operation); + final InFlight inflight = new InFlight(AlarmManagerService.this, + alarm.operation); + mInFlight.add(inflight); mBroadcastRefCount++; - - BroadcastStats bs = getStatsLocked(alarm.operation); + + 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 == AlarmManager.ELAPSED_REALTIME_WAKEUP || alarm.type == AlarmManager.RTC_WAKEUP) { bs.numWakeup++; + fs.numWakeup++; ActivityManagerNative.noteWakeupAlarm( alarm.operation); } @@ -908,44 +1048,58 @@ class AlarmManagerService extends IAlarmManager.Stub { String pkg = pi.getTargetPackage(); BroadcastStats bs = mBroadcastStats.get(pkg); if (bs == null) { - bs = new BroadcastStats(); + bs = new BroadcastStats(pkg); mBroadcastStats.put(pkg, bs); } return bs; } - + class ResultReceiver implements PendingIntent.OnFinished { public void onSendFinished(PendingIntent pi, Intent intent, int resultCode, String resultData, Bundle resultExtras) { synchronized (mLock) { - BroadcastStats bs = getStatsLocked(pi); - if (bs != null) { + InFlight inflight = null; + for (int i=0; i<mInFlight.size(); i++) { + if (mInFlight.get(i).mPendingIntent == pi) { + inflight = mInFlight.remove(i); + break; + } + } + if (inflight != null) { + final long nowELAPSED = SystemClock.elapsedRealtime(); + BroadcastStats bs = inflight.mBroadcastStats; bs.nesting--; if (bs.nesting <= 0) { bs.nesting = 0; - bs.aggregateTime += SystemClock.elapsedRealtime() - - bs.startTime; - Intent.FilterComparison fc = new Intent.FilterComparison(intent); - FilterStats fs = bs.filterStats.get(fc); - if (fs == null) { - fs = new FilterStats(); - bs.filterStats.put(fc, fs); - } - fs.count++; + bs.aggregateTime += nowELAPSED - bs.startTime; + } + FilterStats fs = inflight.mFilterStats; + fs.nesting--; + if (fs.nesting <= 0) { + fs.nesting = 0; + fs.aggregateTime += nowELAPSED - fs.startTime; } + } else { + mLog.w("No in-flight alarm for " + pi + " " + intent); } - mInFlight.removeFirst(); mBroadcastRefCount--; if (mBroadcastRefCount == 0) { mWakeLock.release(); + if (mInFlight.size() > 0) { + mLog.w("Finished all broadcasts with " + mInFlight.size() + + " remaining inflights"); + for (int i=0; i<mInFlight.size(); i++) { + mLog.w(" Remaining #" + i + ": " + mInFlight.get(i)); + } + mInFlight.clear(); + } } else { // the next of our alarms is now in flight. reattribute the wakelock. - final PendingIntent nowInFlight = mInFlight.peekFirst(); - if (nowInFlight != null) { - setWakelockWorkSource(nowInFlight); + if (mInFlight.size() > 0) { + setWakelockWorkSource(mInFlight.get(0).mPendingIntent); } else { // should never happen - Slog.e(TAG, "Alarm wakelock still held but sent queue empty"); + mLog.w("Alarm wakelock still held but sent queue empty"); mWakeLock.setWorkSource(null); } } diff --git a/services/java/com/android/server/am/ActivityManagerService.java b/services/java/com/android/server/am/ActivityManagerService.java index 02640b5..82c9030 100644 --- a/services/java/com/android/server/am/ActivityManagerService.java +++ b/services/java/com/android/server/am/ActivityManagerService.java @@ -4764,6 +4764,18 @@ public final class ActivityManagerService extends ActivityManagerNative return false; } + public Intent getIntentForIntentSender(IIntentSender pendingResult) { + if (!(pendingResult instanceof PendingIntentRecord)) { + return null; + } + try { + PendingIntentRecord res = (PendingIntentRecord)pendingResult; + return res.key.requestIntent != null ? new Intent(res.key.requestIntent) : null; + } catch (ClassCastException e) { + } + return null; + } + public void setProcessLimit(int max) { enforceCallingPermission(android.Manifest.permission.SET_PROCESS_LIMIT, "setProcessLimit()"); |