summaryrefslogtreecommitdiffstats
path: root/core
diff options
context:
space:
mode:
Diffstat (limited to 'core')
-rw-r--r--core/java/android/content/SyncManager.java6
-rw-r--r--core/java/android/os/BatteryStats.java3
-rw-r--r--core/java/android/os/IPowerManager.aidl5
-rw-r--r--core/java/android/os/PowerManager.java29
-rw-r--r--core/java/android/os/WorkSource.aidl18
-rw-r--r--core/java/android/os/WorkSource.java311
-rw-r--r--core/java/com/android/internal/app/IBatteryStats.aidl10
-rw-r--r--core/java/com/android/internal/os/BatteryStatsImpl.java67
-rw-r--r--core/res/AndroidManifest.xml2
9 files changed, 443 insertions, 8 deletions
diff --git a/core/java/android/content/SyncManager.java b/core/java/android/content/SyncManager.java
index d0b67cc..3e44fcf 100644
--- a/core/java/android/content/SyncManager.java
+++ b/core/java/android/content/SyncManager.java
@@ -45,6 +45,7 @@ import android.os.Process;
import android.os.RemoteException;
import android.os.SystemClock;
import android.os.SystemProperties;
+import android.os.WorkSource;
import android.provider.Settings;
import android.text.format.DateUtils;
import android.text.format.Time;
@@ -126,8 +127,8 @@ public class SyncManager implements OnAccountsUpdateListener {
private static final int INITIALIZATION_UNBIND_DELAY_MS = 5000;
- private static final String SYNC_WAKE_LOCK = "SyncManagerSyncWakeLock";
- private static final String HANDLE_SYNC_ALARM_WAKE_LOCK = "SyncManagerHandleSyncAlarmWakeLock";
+ private static final String SYNC_WAKE_LOCK = "*sync*";
+ private static final String HANDLE_SYNC_ALARM_WAKE_LOCK = "SyncManagerHandleSyncAlarm";
private Context mContext;
@@ -1695,6 +1696,7 @@ public class SyncManager implements OnAccountsUpdateListener {
Log.v(TAG, "runStateIdle: setting mActiveSyncContext to " + mActiveSyncContext);
}
mSyncStorageEngine.setActiveSync(mActiveSyncContext);
+ mSyncWakeLock.setWorkSource(new WorkSource(syncAdapterInfo.uid));
if (!activeSyncContext.bindToSyncAdapter(syncAdapterInfo)) {
Log.e(TAG, "Bind attempt failed to " + syncAdapterInfo);
mActiveSyncContext.close();
diff --git a/core/java/android/os/BatteryStats.java b/core/java/android/os/BatteryStats.java
index f5b1e57..f182a7a 100644
--- a/core/java/android/os/BatteryStats.java
+++ b/core/java/android/os/BatteryStats.java
@@ -404,6 +404,7 @@ public abstract class BatteryStats implements Parcelable {
public static final byte CMD_UPDATE = 0;
public static final byte CMD_START = 1;
+ public static final byte CMD_OVERFLOW = 2;
public byte cmd;
@@ -1703,6 +1704,8 @@ public abstract class BatteryStats implements Parcelable {
pw.print(" ");
if (rec.cmd == HistoryItem.CMD_START) {
pw.println(" START");
+ } else if (rec.cmd == HistoryItem.CMD_OVERFLOW) {
+ pw.println(" *OVERFLOW*");
} else {
if (rec.batteryLevel < 10) pw.print("00");
else if (rec.batteryLevel < 100) pw.print("0");
diff --git a/core/java/android/os/IPowerManager.aidl b/core/java/android/os/IPowerManager.aidl
index 01cc408..0067e94 100644
--- a/core/java/android/os/IPowerManager.aidl
+++ b/core/java/android/os/IPowerManager.aidl
@@ -17,10 +17,13 @@
package android.os;
+import android.os.WorkSource;
+
/** @hide */
interface IPowerManager
{
- void acquireWakeLock(int flags, IBinder lock, String tag);
+ void acquireWakeLock(int flags, IBinder lock, String tag, in WorkSource ws);
+ void updateWakeLockWorkSource(IBinder lock, in WorkSource ws);
void goToSleep(long time);
void goToSleepWithReason(long time, int reason);
void releaseWakeLock(IBinder lock, int flags);
diff --git a/core/java/android/os/PowerManager.java b/core/java/android/os/PowerManager.java
index f4ca8bc..3876a3e 100644
--- a/core/java/android/os/PowerManager.java
+++ b/core/java/android/os/PowerManager.java
@@ -209,6 +209,7 @@ public class PowerManager
int mCount = 0;
boolean mRefCounted = true;
boolean mHeld = false;
+ WorkSource mWorkSource;
WakeLock(int flags, String tag)
{
@@ -247,7 +248,7 @@ public class PowerManager
synchronized (mToken) {
if (!mRefCounted || mCount++ == 0) {
try {
- mService.acquireWakeLock(mFlags, mToken, mTag);
+ mService.acquireWakeLock(mFlags, mToken, mTag, mWorkSource);
} catch (RemoteException e) {
}
mHeld = true;
@@ -313,6 +314,32 @@ public class PowerManager
}
}
+ public void setWorkSource(WorkSource ws) {
+ synchronized (mToken) {
+ if (ws != null && ws.size() == 0) {
+ ws = null;
+ }
+ boolean changed = true;
+ if (ws == null) {
+ mWorkSource = null;
+ } else if (mWorkSource == null) {
+ changed = mWorkSource != null;
+ mWorkSource = new WorkSource(ws);
+ } else {
+ changed = mWorkSource.diff(ws);
+ if (changed) {
+ mWorkSource.set(ws);
+ }
+ }
+ if (changed && mHeld) {
+ try {
+ mService.updateWakeLockWorkSource(mToken, mWorkSource);
+ } catch (RemoteException e) {
+ }
+ }
+ }
+ }
+
public String toString() {
synchronized (mToken) {
return "WakeLock{"
diff --git a/core/java/android/os/WorkSource.aidl b/core/java/android/os/WorkSource.aidl
new file mode 100644
index 0000000..1e7fabc
--- /dev/null
+++ b/core/java/android/os/WorkSource.aidl
@@ -0,0 +1,18 @@
+/* Copyright 2010, 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 android.os;
+
+parcelable WorkSource;
diff --git a/core/java/android/os/WorkSource.java b/core/java/android/os/WorkSource.java
new file mode 100644
index 0000000..bba1984
--- /dev/null
+++ b/core/java/android/os/WorkSource.java
@@ -0,0 +1,311 @@
+package android.os;
+
+/**
+ * Describes the source of some work that may be done by someone else.
+ * Currently the public representation of what a work source is is not
+ * defined; this is an opaque container.
+ */
+public class WorkSource implements Parcelable {
+ int mNum;
+ int[] mUids;
+
+ /**
+ * Internal statics to avoid object allocations in some operations.
+ * The WorkSource object itself is not thread safe, but we need to
+ * hold sTmpWorkSource lock while working with these statics.
+ */
+ static final WorkSource sTmpWorkSource = new WorkSource(0);
+ /**
+ * For returning newbie work from a modification operation.
+ */
+ static WorkSource sNewbWork;
+ /**
+ * For returning gone work form a modification operation.
+ */
+ static WorkSource sGoneWork;
+
+ /**
+ * Create an empty work source.
+ */
+ public WorkSource() {
+ mNum = 0;
+ }
+
+ /**
+ * Create a new WorkSource that is a copy of an existing one.
+ * If <var>orig</var> is null, an empty WorkSource is created.
+ */
+ public WorkSource(WorkSource orig) {
+ if (orig == null) {
+ mNum = 0;
+ return;
+ }
+ mNum = orig.mNum;
+ if (orig.mUids != null) {
+ mUids = orig.mUids.clone();
+ } else {
+ mUids = null;
+ }
+ }
+
+ /** @hide */
+ public WorkSource(int uid) {
+ mNum = 1;
+ mUids = new int[] { uid, 0 };
+ }
+
+ WorkSource(Parcel in) {
+ mNum = in.readInt();
+ mUids = in.createIntArray();
+ }
+
+ /** @hide */
+ public int size() {
+ return mNum;
+ }
+
+ /** @hide */
+ public int get(int index) {
+ return mUids[index];
+ }
+
+ /**
+ * Clear this WorkSource to be empty.
+ */
+ public void clear() {
+ mNum = 0;
+ }
+
+ /**
+ * Compare this WorkSource with another.
+ * @param other The WorkSource to compare against.
+ * @return If there is a difference, true is returned.
+ */
+ public boolean diff(WorkSource other) {
+ int N = mNum;
+ if (N != other.mNum) {
+ return true;
+ }
+ final int[] uids1 = mUids;
+ final int[] uids2 = other.mUids;
+ for (int i=0; i<N; i++) {
+ if (uids1[i] != uids2[i]) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ /**
+ * Replace the current contents of this work source with the given
+ * work source. If <var>other</var> is null, the current work source
+ * will be made empty.
+ */
+ public void set(WorkSource other) {
+ if (other == null) {
+ mNum = 0;
+ return;
+ }
+ mNum = other.mNum;
+ if (other.mUids != null) {
+ if (mUids != null && mUids.length >= mNum) {
+ System.arraycopy(other.mUids, 0, mUids, 0, mNum);
+ } else {
+ mUids = other.mUids.clone();
+ }
+ } else {
+ mUids = null;
+ }
+ }
+
+ /** @hide */
+ public void set(int uid) {
+ mNum = 1;
+ if (mUids == null) mUids = new int[2];
+ mUids[0] = uid;
+ }
+
+ /** @hide */
+ public WorkSource[] setReturningDiffs(WorkSource other) {
+ synchronized (sTmpWorkSource) {
+ sNewbWork = null;
+ sGoneWork = null;
+ updateLocked(other, true, true);
+ if (sNewbWork != null || sGoneWork != null) {
+ WorkSource[] diffs = new WorkSource[2];
+ diffs[0] = sNewbWork;
+ diffs[1] = sGoneWork;
+ return diffs;
+ }
+ return null;
+ }
+ }
+
+ /**
+ * Merge the contents of <var>other</var> WorkSource in to this one.
+ *
+ * @param other The other WorkSource whose contents are to be merged.
+ * @return Returns true if any new sources were added.
+ */
+ public boolean add(WorkSource other) {
+ synchronized (sTmpWorkSource) {
+ return updateLocked(other, false, false);
+ }
+ }
+
+ /** @hide */
+ public WorkSource addReturningNewbs(WorkSource other) {
+ synchronized (sTmpWorkSource) {
+ sNewbWork = null;
+ updateLocked(other, false, true);
+ return sNewbWork;
+ }
+ }
+
+ /** @hide */
+ public boolean add(int uid) {
+ synchronized (sTmpWorkSource) {
+ sTmpWorkSource.mUids[0] = uid;
+ return updateLocked(sTmpWorkSource, false, false);
+ }
+ }
+
+ /** @hide */
+ public WorkSource addReturningNewbs(int uid) {
+ synchronized (sTmpWorkSource) {
+ sNewbWork = null;
+ sTmpWorkSource.mUids[0] = uid;
+ updateLocked(sTmpWorkSource, false, true);
+ return sNewbWork;
+ }
+ }
+
+ public boolean remove(WorkSource other) {
+ int N1 = mNum;
+ final int[] uids1 = mUids;
+ final int N2 = other.mNum;
+ final int[] uids2 = other.mUids;
+ boolean changed = false;
+ int i1 = 0;
+ for (int i2=0; i2<N2 && i1<N1; i2++) {
+ if (uids2[i2] == uids1[i1]) {
+ N1--;
+ if (i1 < N1) System.arraycopy(uids1, i1, uids1, i1-1, N1-i1);
+ }
+ while (i1 < N1 && uids2[i2] > uids1[i1]) {
+ i1++;
+ }
+ }
+
+ mNum = N1;
+
+ return changed;
+ }
+
+ private boolean updateLocked(WorkSource other, boolean set, boolean returnNewbs) {
+ int N1 = mNum;
+ int[] uids1 = mUids;
+ final int N2 = other.mNum;
+ final int[] uids2 = other.mUids;
+ boolean changed = false;
+ int i1 = 0;
+ for (int i2=0; i2<N2; i2++) {
+ if (i1 >= N1 || uids2[i2] < uids1[i1]) {
+ // Need to insert a new uid.
+ changed = true;
+ if (uids1 == null) {
+ uids1 = new int[4];
+ uids1[0] = uids2[i2];
+ } else if (i1 >= uids1.length) {
+ int[] newuids = new int[(uids1.length*3)/2];
+ if (i1 > 0) System.arraycopy(uids1, 0, newuids, 0, i1);
+ if (i1 < N1) System.arraycopy(uids1, i1, newuids, i1+1, N1-i1);
+ uids1 = newuids;
+ uids1[i1] = uids2[i2];
+ } else {
+ if (i1 < N1) System.arraycopy(uids1, i1, uids1, i1+1, N1-i1);
+ uids1[i1] = uids2[i2];
+ }
+ if (returnNewbs) {
+ if (sNewbWork == null) {
+ sNewbWork = new WorkSource(uids2[i2]);
+ } else {
+ sNewbWork.addLocked(uids2[i2]);
+ }
+ }
+ N1++;
+ i1++;
+ } else {
+ if (!set) {
+ // Skip uids that already exist or are not in 'other'.
+ do {
+ i1++;
+ } while (i1 < N1 && uids2[i2] >= uids1[i1]);
+ } else {
+ // Remove any uids that don't exist in 'other'.
+ int start = i1;
+ while (i1 < N1 && uids2[i2] > uids1[i1]) {
+ if (sGoneWork == null) {
+ sGoneWork = new WorkSource(uids1[i1]);
+ } else {
+ sGoneWork.addLocked(uids1[i1]);
+ }
+ i1++;
+ }
+ if (start < i1) {
+ System.arraycopy(uids1, i1, uids1, start, i1-start);
+ N1 -= i1-start;
+ i1 = start;
+ }
+ // If there is a matching uid, skip it.
+ if (i1 < N1 && uids2[i1] == uids1[i1]) {
+ i1++;
+ }
+ }
+ }
+ }
+
+ mNum = N1;
+ mUids = uids1;
+
+ return changed;
+ }
+
+ private void addLocked(int uid) {
+ if (mUids == null) {
+ mUids = new int[4];
+ mUids[0] = uid;
+ mNum = 1;
+ return;
+ }
+ if (mNum >= mUids.length) {
+ int[] newuids = new int[(mNum*3)/2];
+ System.arraycopy(mUids, 0, newuids, 0, mNum);
+ mUids = newuids;
+ }
+
+ mUids[mNum] = uid;
+ mNum++;
+ }
+
+ @Override
+ public int describeContents() {
+ return 0;
+ }
+
+ @Override
+ public void writeToParcel(Parcel dest, int flags) {
+ dest.writeInt(mNum);
+ dest.writeIntArray(mUids);
+ }
+
+ public static final Parcelable.Creator<WorkSource> CREATOR
+ = new Parcelable.Creator<WorkSource>() {
+ public WorkSource createFromParcel(Parcel in) {
+ return new WorkSource(in);
+ }
+ public WorkSource[] newArray(int size) {
+ return new WorkSource[size];
+ }
+ };
+}
diff --git a/core/java/com/android/internal/app/IBatteryStats.aidl b/core/java/com/android/internal/app/IBatteryStats.aidl
index 1620778..bd87a0d 100644
--- a/core/java/com/android/internal/app/IBatteryStats.aidl
+++ b/core/java/com/android/internal/app/IBatteryStats.aidl
@@ -18,6 +18,7 @@ package com.android.internal.app;
import com.android.internal.os.BatteryStatsImpl;
+import android.os.WorkSource;
import android.telephony.SignalStrength;
interface IBatteryStats {
@@ -33,6 +34,9 @@ interface IBatteryStats {
SensorService.cpp */
void noteStopSensor(int uid, int sensor);
+ void noteStartWakelockFromSource(in WorkSource ws, int pid, String name, int type);
+ void noteStopWakelockFromSource(in WorkSource ws, int pid, String name, int type);
+
void noteStartGps(int uid);
void noteStopGps(int uid);
void noteScreenOn();
@@ -57,6 +61,12 @@ interface IBatteryStats {
void noteScanWifiLockReleased(int uid);
void noteWifiMulticastEnabled(int uid);
void noteWifiMulticastDisabled(int uid);
+ void noteFullWifiLockAcquiredFromSource(in WorkSource ws);
+ void noteFullWifiLockReleasedFromSource(in WorkSource ws);
+ void noteScanWifiLockAcquiredFromSource(in WorkSource ws);
+ void noteScanWifiLockReleasedFromSource(in WorkSource ws);
+ void noteWifiMulticastEnabledFromSource(in WorkSource ws);
+ void noteWifiMulticastDisabledFromSource(in WorkSource ws);
void setBatteryState(int status, int health, int plugType, int level, int temp, int volt);
long getAwakeTimeBattery();
long getAwakeTimePlugged();
diff --git a/core/java/com/android/internal/os/BatteryStatsImpl.java b/core/java/com/android/internal/os/BatteryStatsImpl.java
index 0ef1ea5..753dbf0 100644
--- a/core/java/com/android/internal/os/BatteryStatsImpl.java
+++ b/core/java/com/android/internal/os/BatteryStatsImpl.java
@@ -29,6 +29,7 @@ import android.os.ParcelFormatException;
import android.os.Parcelable;
import android.os.Process;
import android.os.SystemClock;
+import android.os.WorkSource;
import android.telephony.ServiceState;
import android.telephony.SignalStrength;
import android.telephony.TelephonyManager;
@@ -68,12 +69,12 @@ public final class BatteryStatsImpl extends BatteryStats {
private static final int VERSION = 50;
// Maximum number of items we will record in the history.
- private static final int MAX_HISTORY_ITEMS = 1000;
+ private static final int MAX_HISTORY_ITEMS = 2000;
// The maximum number of names wakelocks we will keep track of
// per uid; once the limit is reached, we batch the remaining wakelocks
// in to one common name.
- private static final int MAX_WAKELOCKS_PER_UID = 20;
+ private static final int MAX_WAKELOCKS_PER_UID = 30;
private static final String BATCHED_WAKELOCK_NAME = "*overflow*";
@@ -1171,7 +1172,7 @@ public final class BatteryStatsImpl extends BatteryStats {
// If the current time is basically the same as the last time,
// just collapse into one record.
if (mHistoryEnd != null && mHistoryEnd.cmd == HistoryItem.CMD_UPDATE
- && (mHistoryBaseTime+curTime) < (mHistoryEnd.time+100)) {
+ && (mHistoryBaseTime+curTime) < (mHistoryEnd.time+500)) {
// If the current is the same as the one before, then we no
// longer need the entry.
if (mHistoryLastEnd != null && mHistoryLastEnd.cmd == HistoryItem.CMD_UPDATE
@@ -1187,6 +1188,10 @@ public final class BatteryStatsImpl extends BatteryStats {
return;
}
+ if (mNumHistoryItems == MAX_HISTORY_ITEMS) {
+ addHistoryRecordLocked(curTime, HistoryItem.CMD_OVERFLOW);
+ }
+
if (mNumHistoryItems >= MAX_HISTORY_ITEMS) {
// Once we've reached the maximum number of items, we only
// record changes to the battery level.
@@ -1327,6 +1332,20 @@ public final class BatteryStatsImpl extends BatteryStats {
}
}
+ public void noteStartWakeFromSourceLocked(WorkSource ws, int pid, String name, int type) {
+ int N = ws.size();
+ for (int i=0; i<N; i++) {
+ noteStartWakeLocked(ws.get(i), pid, name, type);
+ }
+ }
+
+ public void noteStopWakeFromSourceLocked(WorkSource ws, int pid, String name, int type) {
+ int N = ws.size();
+ for (int i=0; i<N; i++) {
+ noteStopWakeLocked(ws.get(i), pid, name, type);
+ }
+ }
+
public int startAddingCpuLocked() {
mHandler.removeMessages(MSG_UPDATE_WAKELOCKS);
@@ -1947,6 +1966,48 @@ public final class BatteryStatsImpl extends BatteryStats {
getUidStatsLocked(uid).noteWifiMulticastDisabledLocked();
}
+ public void noteFullWifiLockAcquiredFromSourceLocked(WorkSource ws) {
+ int N = ws.size();
+ for (int i=0; i<N; i++) {
+ noteFullWifiLockAcquiredLocked(ws.get(i));
+ }
+ }
+
+ public void noteFullWifiLockReleasedFromSourceLocked(WorkSource ws) {
+ int N = ws.size();
+ for (int i=0; i<N; i++) {
+ noteFullWifiLockReleasedLocked(ws.get(i));
+ }
+ }
+
+ public void noteScanWifiLockAcquiredFromSourceLocked(WorkSource ws) {
+ int N = ws.size();
+ for (int i=0; i<N; i++) {
+ noteScanWifiLockAcquiredLocked(ws.get(i));
+ }
+ }
+
+ public void noteScanWifiLockReleasedFromSourceLocked(WorkSource ws) {
+ int N = ws.size();
+ for (int i=0; i<N; i++) {
+ noteScanWifiLockReleasedLocked(ws.get(i));
+ }
+ }
+
+ public void noteWifiMulticastEnabledFromSourceLocked(WorkSource ws) {
+ int N = ws.size();
+ for (int i=0; i<N; i++) {
+ noteWifiMulticastEnabledLocked(ws.get(i));
+ }
+ }
+
+ public void noteWifiMulticastDisabledFromSourceLocked(WorkSource ws) {
+ int N = ws.size();
+ for (int i=0; i<N; i++) {
+ noteWifiMulticastDisabledLocked(ws.get(i));
+ }
+ }
+
@Override public long getScreenOnTime(long batteryRealtime, int which) {
return mScreenOnTimer.getTotalTimeLocked(batteryRealtime, which);
}
diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml
index a9e4971..9b9b4be 100644
--- a/core/res/AndroidManifest.xml
+++ b/core/res/AndroidManifest.xml
@@ -930,7 +930,7 @@
<permission android:name="android.permission.UPDATE_DEVICE_STATS"
android:label="@string/permlab_batteryStats"
android:description="@string/permdesc_batteryStats"
- android:protectionLevel="signature" />
+ android:protectionLevel="signatureOrSystem" />
<!-- Allows an application to open windows that are for use by parts
of the system user interface. Not for use by third party apps. -->