Skip to content

Commit ba4ac51

Browse files
Dianne HackbornAndroid (Google) Code Review
authored andcommitted
Merge "Improve debugging for issue #7586414: AlarmManager wakelocks held" into jb-mr1.1-dev
2 parents 6f3b20c + 8103890 commit ba4ac51

File tree

7 files changed

+400
-52
lines changed

7 files changed

+400
-52
lines changed

core/java/android/app/ActivityManagerNative.java

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1701,6 +1701,21 @@ public boolean onTransact(int code, Parcel data, Parcel reply, int flags)
17011701
return true;
17021702
}
17031703

1704+
case GET_INTENT_FOR_INTENT_SENDER_TRANSACTION: {
1705+
data.enforceInterface(IActivityManager.descriptor);
1706+
IIntentSender r = IIntentSender.Stub.asInterface(
1707+
data.readStrongBinder());
1708+
Intent intent = getIntentForIntentSender(r);
1709+
reply.writeNoException();
1710+
if (intent != null) {
1711+
reply.writeInt(1);
1712+
intent.writeToParcel(reply, Parcelable.PARCELABLE_WRITE_RETURN_VALUE);
1713+
} else {
1714+
reply.writeInt(0);
1715+
}
1716+
return true;
1717+
}
1718+
17041719
case UPDATE_PERSISTENT_CONFIGURATION_TRANSACTION: {
17051720
data.enforceInterface(IActivityManager.descriptor);
17061721
Configuration config = Configuration.CREATOR.createFromParcel(data);
@@ -3977,6 +3992,20 @@ public boolean isIntentSenderAnActivity(IIntentSender sender) throws RemoteExcep
39773992
return res;
39783993
}
39793994

3995+
public Intent getIntentForIntentSender(IIntentSender sender) throws RemoteException {
3996+
Parcel data = Parcel.obtain();
3997+
Parcel reply = Parcel.obtain();
3998+
data.writeInterfaceToken(IActivityManager.descriptor);
3999+
data.writeStrongBinder(sender.asBinder());
4000+
mRemote.transact(GET_INTENT_FOR_INTENT_SENDER_TRANSACTION, data, reply, 0);
4001+
reply.readException();
4002+
Intent res = reply.readInt() != 0
4003+
? Intent.CREATOR.createFromParcel(reply) : null;
4004+
data.recycle();
4005+
reply.recycle();
4006+
return res;
4007+
}
4008+
39804009
public void updatePersistentConfiguration(Configuration values) throws RemoteException
39814010
{
39824011
Parcel data = Parcel.obtain();

core/java/android/app/IActivityManager.java

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -341,6 +341,8 @@ public void setPackageAskScreenCompat(String packageName, boolean ask)
341341

342342
public boolean isIntentSenderAnActivity(IIntentSender sender) throws RemoteException;
343343

344+
public Intent getIntentForIntentSender(IIntentSender sender) throws RemoteException;
345+
344346
public void updatePersistentConfiguration(Configuration values) throws RemoteException;
345347

346348
public long[] getProcessPss(int[] pids) throws RemoteException;
@@ -621,4 +623,5 @@ private WaitResult(Parcel source) {
621623
int REQUEST_BUG_REPORT_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+157;
622624
int INPUT_DISPATCHING_TIMED_OUT_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+158;
623625
int CLEAR_PENDING_BACKUP_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+159;
626+
int GET_INTENT_FOR_INTENT_SENDER_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+160;
624627
}

core/java/android/app/PendingIntent.java

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -789,6 +789,20 @@ public boolean isActivity() {
789789
}
790790
}
791791

792+
/**
793+
* @hide
794+
* Return the Intent of this PendingIntent.
795+
*/
796+
public Intent getIntent() {
797+
try {
798+
return ActivityManagerNative.getDefault()
799+
.getIntentForIntentSender(mTarget);
800+
} catch (RemoteException e) {
801+
// Should never happen.
802+
return null;
803+
}
804+
}
805+
792806
/**
793807
* Comparison operator on two PendingIntent objects, such that true
794808
* is returned then they both represent the same operation from the

core/java/android/os/BatteryStats.java

Lines changed: 83 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,8 @@
1818

1919
import java.io.PrintWriter;
2020
import java.util.ArrayList;
21+
import java.util.Collections;
22+
import java.util.Comparator;
2123
import java.util.Formatter;
2224
import java.util.List;
2325
import java.util.Map;
@@ -1127,8 +1129,10 @@ private static final String printWakeLock(StringBuilder sb, Timer timer,
11271129
if (totalTimeMillis != 0) {
11281130
sb.append(linePrefix);
11291131
formatTimeMs(sb, totalTimeMillis);
1130-
if (name != null) sb.append(name);
1131-
sb.append(' ');
1132+
if (name != null) {
1133+
sb.append(name);
1134+
sb.append(' ');
1135+
}
11321136
sb.append('(');
11331137
sb.append(count);
11341138
sb.append(" times)");
@@ -1440,8 +1444,21 @@ public final void dumpCheckinLocked(PrintWriter pw, int which, int reqUid) {
14401444
}
14411445
}
14421446

1447+
static final class TimerEntry {
1448+
final String mName;
1449+
final int mId;
1450+
final BatteryStats.Timer mTimer;
1451+
final long mTime;
1452+
TimerEntry(String name, int id, BatteryStats.Timer timer, long time) {
1453+
mName = name;
1454+
mId = id;
1455+
mTimer = timer;
1456+
mTime = time;
1457+
}
1458+
}
1459+
14431460
@SuppressWarnings("unused")
1444-
public final void dumpLocked(PrintWriter pw, String prefix, int which, int reqUid) {
1461+
public final void dumpLocked(PrintWriter pw, String prefix, final int which, int reqUid) {
14451462
final long rawUptime = SystemClock.uptimeMillis() * 1000;
14461463
final long rawRealtime = SystemClock.elapsedRealtime() * 1000;
14471464
final long batteryUptime = getBatteryUptime(rawUptime);
@@ -1516,19 +1533,43 @@ public final void dumpLocked(PrintWriter pw, String prefix, int which, int reqUi
15161533
long txTotal = 0;
15171534
long fullWakeLockTimeTotalMicros = 0;
15181535
long partialWakeLockTimeTotalMicros = 0;
1519-
1536+
1537+
final Comparator<TimerEntry> timerComparator = new Comparator<TimerEntry>() {
1538+
@Override
1539+
public int compare(TimerEntry lhs, TimerEntry rhs) {
1540+
long lhsTime = lhs.mTime;
1541+
long rhsTime = rhs.mTime;
1542+
if (lhsTime < rhsTime) {
1543+
return 1;
1544+
}
1545+
if (lhsTime > rhsTime) {
1546+
return -1;
1547+
}
1548+
return 0;
1549+
}
1550+
};
1551+
15201552
if (reqUid < 0) {
15211553
Map<String, ? extends BatteryStats.Timer> kernelWakelocks = getKernelWakelockStats();
15221554
if (kernelWakelocks.size() > 0) {
1555+
final ArrayList<TimerEntry> timers = new ArrayList<TimerEntry>();
15231556
for (Map.Entry<String, ? extends BatteryStats.Timer> ent : kernelWakelocks.entrySet()) {
1524-
1557+
BatteryStats.Timer timer = ent.getValue();
1558+
long totalTimeMillis = computeWakeLock(timer, batteryRealtime, which);
1559+
if (totalTimeMillis > 0) {
1560+
timers.add(new TimerEntry(ent.getKey(), 0, timer, totalTimeMillis));
1561+
}
1562+
}
1563+
Collections.sort(timers, timerComparator);
1564+
for (int i=0; i<timers.size(); i++) {
1565+
TimerEntry timer = timers.get(i);
15251566
String linePrefix = ": ";
15261567
sb.setLength(0);
15271568
sb.append(prefix);
15281569
sb.append(" Kernel Wake lock ");
1529-
sb.append(ent.getKey());
1530-
linePrefix = printWakeLock(sb, ent.getValue(), batteryRealtime, null, which,
1531-
linePrefix);
1570+
sb.append(timer.mName);
1571+
linePrefix = printWakeLock(sb, timer.mTimer, batteryRealtime, null,
1572+
which, linePrefix);
15321573
if (!linePrefix.equals(": ")) {
15331574
sb.append(" realtime");
15341575
// Only print out wake locks that were held
@@ -1537,7 +1578,9 @@ public final void dumpLocked(PrintWriter pw, String prefix, int which, int reqUi
15371578
}
15381579
}
15391580
}
1540-
1581+
1582+
final ArrayList<TimerEntry> timers = new ArrayList<TimerEntry>();
1583+
15411584
for (int iu = 0; iu < NU; iu++) {
15421585
Uid u = uidStats.valueAt(iu);
15431586
rxTotal += u.getTcpBytesReceived(which);
@@ -1557,8 +1600,18 @@ public final void dumpLocked(PrintWriter pw, String prefix, int which, int reqUi
15571600

15581601
Timer partialWakeTimer = wl.getWakeTime(WAKE_TYPE_PARTIAL);
15591602
if (partialWakeTimer != null) {
1560-
partialWakeLockTimeTotalMicros += partialWakeTimer.getTotalTimeLocked(
1603+
long totalTimeMicros = partialWakeTimer.getTotalTimeLocked(
15611604
batteryRealtime, which);
1605+
if (totalTimeMicros > 0) {
1606+
if (reqUid < 0) {
1607+
// Only show the ordered list of all wake
1608+
// locks if the caller is not asking for data
1609+
// about a specific uid.
1610+
timers.add(new TimerEntry(ent.getKey(), u.getUid(),
1611+
partialWakeTimer, totalTimeMicros));
1612+
}
1613+
partialWakeLockTimeTotalMicros += totalTimeMicros;
1614+
}
15621615
}
15631616
}
15641617
}
@@ -1571,7 +1624,7 @@ public final void dumpLocked(PrintWriter pw, String prefix, int which, int reqUi
15711624
sb.append(prefix);
15721625
sb.append(" Total full wakelock time: "); formatTimeMs(sb,
15731626
(fullWakeLockTimeTotalMicros + 500) / 1000);
1574-
sb.append(", Total partial waklock time: "); formatTimeMs(sb,
1627+
sb.append(", Total partial wakelock time: "); formatTimeMs(sb,
15751628
(partialWakeLockTimeTotalMicros + 500) / 1000);
15761629
pw.println(sb.toString());
15771630

@@ -1676,9 +1729,26 @@ public final void dumpLocked(PrintWriter pw, String prefix, int which, int reqUi
16761729
pw.println(getDischargeAmountScreenOnSinceCharge());
16771730
pw.print(prefix); pw.print(" Amount discharged while screen off: ");
16781731
pw.println(getDischargeAmountScreenOffSinceCharge());
1679-
pw.println(" ");
1732+
pw.println();
1733+
}
1734+
1735+
if (timers.size() > 0) {
1736+
Collections.sort(timers, timerComparator);
1737+
pw.print(prefix); pw.println(" All partial wake locks:");
1738+
for (int i=0; i<timers.size(); i++) {
1739+
TimerEntry timer = timers.get(i);
1740+
sb.setLength(0);
1741+
sb.append(" Wake lock #");
1742+
sb.append(timer.mId);
1743+
sb.append(" ");
1744+
sb.append(timer.mName);
1745+
printWakeLock(sb, timer.mTimer, batteryRealtime, null, which, ": ");
1746+
sb.append(" realtime");
1747+
pw.println(sb.toString());
1748+
}
1749+
timers.clear();
1750+
pw.println();
16801751
}
1681-
16821752

16831753
for (int iu=0; iu<NU; iu++) {
16841754
final int uid = uidStats.keyAt(iu);
Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
/*
2+
* Copyright (C) 2012 The Android Open Source Project
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package com.android.internal.util;
18+
19+
import java.io.PrintWriter;
20+
import java.util.ArrayList;
21+
22+
import android.util.Slog;
23+
24+
/**
25+
* Helper class for logging serious issues, which also keeps a small
26+
* snapshot of the logged events that can be printed later, such as part
27+
* of a system service's dumpsys output.
28+
* @hide
29+
*/
30+
public class LocalLog {
31+
private final String mTag;
32+
private final int mMaxLines = 20;
33+
private final ArrayList<String> mLines = new ArrayList<String>(mMaxLines);
34+
35+
public LocalLog(String tag) {
36+
mTag = tag;
37+
}
38+
39+
public void w(String msg) {
40+
synchronized (mLines) {
41+
Slog.w(mTag, msg);
42+
if (mLines.size() >= mMaxLines) {
43+
mLines.remove(0);
44+
}
45+
mLines.add(msg);
46+
}
47+
}
48+
49+
public boolean dump(PrintWriter pw, String header, String prefix) {
50+
synchronized (mLines) {
51+
if (mLines.size() <= 0) {
52+
return false;
53+
}
54+
if (header != null) {
55+
pw.println(header);
56+
}
57+
for (int i=0; i<mLines.size(); i++) {
58+
if (prefix != null) {
59+
pw.print(prefix);
60+
}
61+
pw.println(mLines.get(i));
62+
}
63+
return true;
64+
}
65+
}
66+
}

0 commit comments

Comments
 (0)