diff options
Diffstat (limited to 'core')
-rw-r--r-- | core/java/android/content/SyncManager.java | 6 | ||||
-rw-r--r-- | core/java/android/os/BatteryStats.java | 3 | ||||
-rw-r--r-- | core/java/android/os/IPowerManager.aidl | 5 | ||||
-rw-r--r-- | core/java/android/os/PowerManager.java | 29 | ||||
-rw-r--r-- | core/java/android/os/WorkSource.aidl | 18 | ||||
-rw-r--r-- | core/java/android/os/WorkSource.java | 311 | ||||
-rw-r--r-- | core/java/com/android/internal/app/IBatteryStats.aidl | 10 | ||||
-rw-r--r-- | core/java/com/android/internal/os/BatteryStatsImpl.java | 67 | ||||
-rw-r--r-- | core/res/AndroidManifest.xml | 2 |
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. --> |