diff options
92 files changed, 3648 insertions, 1073 deletions
diff --git a/api/current.txt b/api/current.txt index e24dd3b50bac..e15c1d742497 100644 --- a/api/current.txt +++ b/api/current.txt @@ -4293,7 +4293,9 @@ package android.app { public static class Notification.Builder { ctor public Notification.Builder(android.content.Context); method public android.app.Notification.Builder addAction(int, java.lang.CharSequence, android.app.PendingIntent); + method public android.app.Notification.Builder addExtras(android.os.Bundle); method public android.app.Notification build(); + method public android.os.Bundle getExtras(); method public deprecated android.app.Notification getNotification(); method public android.app.Notification.Builder setAutoCancel(boolean); method public android.app.Notification.Builder setContent(android.widget.RemoteViews); @@ -9924,6 +9926,7 @@ package android.graphics { method public void cubicTo(float, float, float, float, float, float); method public android.graphics.Path.FillType getFillType(); method public void incReserve(int); + method public boolean isConvex(); method public boolean isEmpty(); method public boolean isInverseFillType(); method public boolean isRect(android.graphics.RectF); diff --git a/cmds/bootanimation/BootAnimation.cpp b/cmds/bootanimation/BootAnimation.cpp index e12e961ccdb7..41afa3921a27 100644 --- a/cmds/bootanimation/BootAnimation.cpp +++ b/cmds/bootanimation/BootAnimation.cpp @@ -36,7 +36,6 @@ #include <ui/Rect.h> #include <ui/Region.h> #include <ui/DisplayInfo.h> -#include <ui/FramebufferNativeWindow.h> #include <gui/ISurfaceComposer.h> #include <gui/Surface.h> diff --git a/cmds/pm/src/com/android/commands/pm/Pm.java b/cmds/pm/src/com/android/commands/pm/Pm.java index 9ad2e76642a1..d513a1002540 100644 --- a/cmds/pm/src/com/android/commands/pm/Pm.java +++ b/cmds/pm/src/com/android/commands/pm/Pm.java @@ -18,6 +18,7 @@ package com.android.commands.pm; import android.app.ActivityManager; import android.app.ActivityManagerNative; +import android.app.IActivityManager; import android.content.ComponentName; import android.content.pm.ApplicationInfo; import android.content.pm.ContainerEncryptionParams; @@ -1089,13 +1090,16 @@ public final class Pm { public void runListUsers() { try { + IActivityManager am = ActivityManagerNative.getDefault(); + List<UserInfo> users = mUm.getUsers(false); if (users == null) { System.err.println("Error: couldn't get users"); } else { System.out.println("Users:"); for (int i = 0; i < users.size(); i++) { - System.out.println("\t" + users.get(i).toString()); + String running = am.isUserRunning(users.get(i).id, false) ? " running" : ""; + System.out.println("\t" + users.get(i).toString() + running); } } } catch (RemoteException e) { diff --git a/core/java/android/app/ActivityThread.java b/core/java/android/app/ActivityThread.java index 3258585ad583..ce2d80691270 100644 --- a/core/java/android/app/ActivityThread.java +++ b/core/java/android/app/ActivityThread.java @@ -71,6 +71,7 @@ import android.os.Trace; import android.os.UserHandle; import android.transition.Scene; import android.transition.TransitionManager; +import android.provider.Settings; import android.util.AndroidRuntimeException; import android.util.ArrayMap; import android.util.DisplayMetrics; @@ -110,6 +111,7 @@ import java.io.PrintWriter; import java.lang.ref.WeakReference; import java.net.InetAddress; import java.security.Security; +import java.text.DateFormat; import java.util.ArrayList; import java.util.List; import java.util.Locale; @@ -1103,6 +1105,11 @@ public final class ActivityThread { public void scheduleInstallProvider(ProviderInfo provider) { sendMessage(H.INSTALL_PROVIDER, provider); } + + @Override + public final void updateTimePrefs(boolean is24Hour) { + DateFormat.set24HourTimePref(is24Hour); + } } private class H extends Handler { @@ -1152,6 +1159,7 @@ public final class ActivityThread { public static final int REQUEST_ASSIST_CONTEXT_EXTRAS = 143; public static final int TRANSLUCENT_CONVERSION_COMPLETE = 144; public static final int INSTALL_PROVIDER = 145; + String codeToString(int code) { if (DEBUG_MESSAGES) { switch (code) { @@ -4215,6 +4223,11 @@ public final class ActivityThread { Log.e(TAG, "Unable to setupGraphicsSupport due to missing cache directory"); } } + + + final boolean is24Hr = "24".equals(mCoreSettings.getString(Settings.System.TIME_12_24)); + DateFormat.set24HourTimePref(is24Hr); + /** * For system applications on userdebug/eng builds, log stack * traces of disk and network access to dropbox for analysis. diff --git a/core/java/android/app/ApplicationThreadNative.java b/core/java/android/app/ApplicationThreadNative.java index 20198f9c2034..f1c632e4e727 100644 --- a/core/java/android/app/ApplicationThreadNative.java +++ b/core/java/android/app/ApplicationThreadNative.java @@ -630,6 +630,15 @@ public abstract class ApplicationThreadNative extends Binder reply.writeNoException(); return true; } + + case UPDATE_TIME_PREFS_TRANSACTION: + { + data.enforceInterface(IApplicationThread.descriptor); + byte is24Hour = data.readByte(); + updateTimePrefs(is24Hour == (byte) 1); + reply.writeNoException(); + return true; + } } return super.onTransact(code, data, reply, flags); @@ -1273,4 +1282,13 @@ class ApplicationThreadProxy implements IApplicationThread { mRemote.transact(SCHEDULE_INSTALL_PROVIDER_TRANSACTION, data, null, IBinder.FLAG_ONEWAY); data.recycle(); } + + @Override + public void updateTimePrefs(boolean is24Hour) throws RemoteException { + Parcel data = Parcel.obtain(); + data.writeInterfaceToken(IApplicationThread.descriptor); + data.writeByte(is24Hour ? (byte) 1 : (byte) 0); + mRemote.transact(UPDATE_TIME_PREFS_TRANSACTION, data, null, IBinder.FLAG_ONEWAY); + data.recycle(); + } } diff --git a/core/java/android/app/IApplicationThread.java b/core/java/android/app/IApplicationThread.java index 1ea9d877bca7..ac8ac8fe827f 100644 --- a/core/java/android/app/IApplicationThread.java +++ b/core/java/android/app/IApplicationThread.java @@ -139,6 +139,7 @@ public interface IApplicationThread extends IInterface { throws RemoteException; void setProcessState(int state) throws RemoteException; void scheduleInstallProvider(ProviderInfo provider) throws RemoteException; + void updateTimePrefs(boolean is24Hour) throws RemoteException; String descriptor = "android.app.IApplicationThread"; @@ -192,4 +193,5 @@ public interface IApplicationThread extends IInterface { int SCHEDULE_TRANSLUCENT_CONVERSION_COMPLETE_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+48; int SET_PROCESS_STATE_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+49; int SCHEDULE_INSTALL_PROVIDER_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+50; + int UPDATE_TIME_PREFS_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+51; } diff --git a/core/java/android/app/Notification.java b/core/java/android/app/Notification.java index b067cd004770..12a8ff6b9859 100644 --- a/core/java/android/app/Notification.java +++ b/core/java/android/app/Notification.java @@ -612,6 +612,13 @@ public class Notification implements Parcelable public static final String EXTRA_AS_HEADS_UP = "headsup"; /** + * Extra added from {@link Notification.Builder} to indicate that the remote views were inflated + * from the builder, as opposed to being created directly from the application. + * @hide + */ + public static final String EXTRA_BUILDER_REMOTE_VIEWS = "android.builderRemoteViews"; + + /** * Value for {@link #EXTRA_AS_HEADS_UP}. * @hide */ @@ -1273,6 +1280,7 @@ public class Notification implements Parcelable private boolean mShowWhen = true; private int mVisibility = VISIBILITY_PRIVATE; private Notification mPublicVersion = null; + private boolean mQuantumTheme; /** * Constructs a new Builder with the defaults: @@ -1300,6 +1308,9 @@ public class Notification implements Parcelable mWhen = System.currentTimeMillis(); mAudioStreamType = STREAM_DEFAULT; mPriority = PRIORITY_DEFAULT; + + // TODO: Decide on targetSdk from calling app whether to use quantum theme. + mQuantumTheme = true; } /** @@ -1680,12 +1691,31 @@ public class Notification implements Parcelable } /** - * Add metadata to this notification. + * Merge additional metadata into this notification. + * + * <p>Values within the Bundle will replace existing extras values in this Builder. * - * A reference to the Bundle is held for the lifetime of this Builder, and the Bundle's + * @see Notification#extras + */ + public Builder addExtras(Bundle bag) { + if (mExtras == null) { + mExtras = new Bundle(bag); + } else { + mExtras.putAll(bag); + } + return this; + } + + /** + * Set metadata for this notification. + * + * <p>A reference to the Bundle is held for the lifetime of this Builder, and the Bundle's * current contents are copied into the Notification each time {@link #build()} is * called. * + * <p>Replaces any existing extras values with those from the provided Bundle. + * Use {@link #addExtras} to merge in metadata instead. + * * @see Notification#extras */ public Builder setExtras(Bundle bag) { @@ -1694,6 +1724,23 @@ public class Notification implements Parcelable } /** + * Get the current metadata Bundle used by this notification Builder. + * + * <p>The returned Bundle is shared with this Builder. + * + * <p>The current contents of this Bundle are copied into the Notification each time + * {@link #build()} is called. + * + * @see Notification#extras + */ + public Bundle getExtras() { + if (mExtras == null) { + mExtras = new Bundle(); + } + return mExtras; + } + + /** * Add an action to this notification. Actions are typically displayed by * the system as a button adjacent to the notification content. * <p> @@ -1771,7 +1818,7 @@ public class Notification implements Parcelable contentView.setImageViewBitmap(R.id.icon, mLargeIcon); smallIconImageViewId = R.id.right_icon; } - if (mPriority < PRIORITY_LOW) { + if (!mQuantumTheme && mPriority < PRIORITY_LOW) { contentView.setInt(R.id.icon, "setBackgroundResource", R.drawable.notification_template_icon_low_bg); contentView.setInt(R.id.status_bar_latest_event_content, @@ -1885,7 +1932,7 @@ public class Notification implements Parcelable if (mContentView != null) { return mContentView; } else { - return applyStandardTemplate(R.layout.notification_template_base, true); // no more special large_icon flavor + return applyStandardTemplate(getBaseLayoutResource(), true); // no more special large_icon flavor } } @@ -1906,21 +1953,21 @@ public class Notification implements Parcelable private RemoteViews makeBigContentView() { if (mActions.size() == 0) return null; - return applyStandardTemplateWithActions(R.layout.notification_template_big_base); + return applyStandardTemplateWithActions(getBigBaseLayoutResource()); } - private RemoteViews makeHEadsUpContentView() { + private RemoteViews makeHeadsUpContentView() { if (mActions.size() == 0) return null; - return applyStandardTemplateWithActions(R.layout.notification_template_big_base); + return applyStandardTemplateWithActions(getBigBaseLayoutResource()); } private RemoteViews generateActionButton(Action action) { final boolean tombstone = (action.actionIntent == null); RemoteViews button = new RemoteViews(mContext.getPackageName(), - tombstone ? R.layout.notification_action_tombstone - : R.layout.notification_action); + tombstone ? getActionTombstoneLayoutResource() + : getActionLayoutResource()); button.setTextViewCompoundDrawablesRelative(R.id.action0, action.icon, 0, 0, 0); button.setTextViewText(R.id.action0, action.title); if (!tombstone) { @@ -1956,7 +2003,7 @@ public class Notification implements Parcelable n.defaults = mDefaults; n.flags = mFlags; n.bigContentView = makeBigContentView(); - n.headsUpContentView = makeHEadsUpContentView(); + n.headsUpContentView = makeHeadsUpContentView(); if (mLedOnMs != 0 || mLedOffMs != 0) { n.flags |= FLAG_SHOW_LIGHTS; } @@ -1989,7 +2036,7 @@ public class Notification implements Parcelable * this Notification object. * @hide */ - public void addExtras(Bundle extras) { + public void populateExtras(Bundle extras) { // Store original information used in the construction of this object extras.putCharSequence(EXTRA_TITLE, mContentTitle); extras.putCharSequence(EXTRA_TEXT, mContentText); @@ -2001,6 +2048,7 @@ public class Notification implements Parcelable extras.putBoolean(EXTRA_PROGRESS_INDETERMINATE, mProgressIndeterminate); extras.putBoolean(EXTRA_SHOW_CHRONOMETER, mUseChronometer); extras.putBoolean(EXTRA_SHOW_WHEN, mShowWhen); + extras.putBoolean(EXTRA_BUILDER_REMOTE_VIEWS, mContentView == null); if (mLargeIcon != null) { extras.putParcelable(EXTRA_LARGE_ICON, mLargeIcon); } @@ -2027,7 +2075,7 @@ public class Notification implements Parcelable n.extras = mExtras != null ? new Bundle(mExtras) : new Bundle(); - addExtras(n.extras); + populateExtras(n.extras); if (mStyle != null) { mStyle.addExtras(n.extras); } @@ -2044,6 +2092,49 @@ public class Notification implements Parcelable build().cloneInto(n, true); return n; } + + + private int getBaseLayoutResource() { + return mQuantumTheme + ? R.layout.notification_template_quantum_base + : R.layout.notification_template_base; + } + + private int getBigBaseLayoutResource() { + return mQuantumTheme + ? R.layout.notification_template_quantum_big_base + : R.layout.notification_template_big_base; + } + + private int getBigPictureLayoutResource() { + return mQuantumTheme + ? R.layout.notification_template_quantum_big_picture + : R.layout.notification_template_big_picture; + } + + private int getBigTextLayoutResource() { + return mQuantumTheme + ? R.layout.notification_template_quantum_big_text + : R.layout.notification_template_big_text; + } + + private int getInboxLayoutResource() { + return mQuantumTheme + ? R.layout.notification_template_quantum_inbox + : R.layout.notification_template_inbox; + } + + private int getActionLayoutResource() { + return mQuantumTheme + ? R.layout.notification_quantum_action + : R.layout.notification_action; + } + + private int getActionTombstoneLayoutResource() { + return mQuantumTheme + ? R.layout.notification_quantum_action_tombstone + : R.layout.notification_action_tombstone; + } } /** @@ -2213,7 +2304,7 @@ public class Notification implements Parcelable } private RemoteViews makeBigContentView() { - RemoteViews contentView = getStandardView(R.layout.notification_template_big_picture); + RemoteViews contentView = getStandardView(mBuilder.getBigPictureLayoutResource()); contentView.setImageViewBitmap(R.id.big_picture, mPicture); @@ -2312,7 +2403,7 @@ public class Notification implements Parcelable final boolean hadThreeLines = (mBuilder.mContentText != null && mBuilder.mSubText != null); mBuilder.mContentText = null; - RemoteViews contentView = getStandardView(R.layout.notification_template_big_text); + RemoteViews contentView = getStandardView(mBuilder.getBigTextLayoutResource()); if (hadThreeLines) { // vertical centering @@ -2406,7 +2497,7 @@ public class Notification implements Parcelable private RemoteViews makeBigContentView() { // Remove the content text so line3 disappears unless you have a summary mBuilder.mContentText = null; - RemoteViews contentView = getStandardView(R.layout.notification_template_inbox); + RemoteViews contentView = getStandardView(mBuilder.getInboxLayoutResource()); contentView.setViewVisibility(R.id.text2, View.GONE); diff --git a/core/java/android/content/Intent.java b/core/java/android/content/Intent.java index 3fdb6e722132..f0b7ca80ea18 100644 --- a/core/java/android/content/Intent.java +++ b/core/java/android/content/Intent.java @@ -3334,6 +3334,15 @@ public class Intent implements Parcelable, Cloneable { public static final String EXTRA_SHUTDOWN_USERSPACE_ONLY = "android.intent.extra.SHUTDOWN_USERSPACE_ONLY"; + /** + * Optional boolean extra for {@link #ACTION_TIME_CHANGED} that indicates the + * user has set their time format preferences to the 24 hour format. + * + * @hide for internal use only. + */ + public static final String EXTRA_TIME_PREF_24_HOUR_FORMAT = + "android.intent.extra.TIME_PREF_24_HOUR_FORMAT"; + // --------------------------------------------------------------------- // --------------------------------------------------------------------- // Intent flags (see mFlags variable). diff --git a/core/java/android/content/res/ColorStateList.java b/core/java/android/content/res/ColorStateList.java index 2893522d17c5..419abf212379 100644 --- a/core/java/android/content/res/ColorStateList.java +++ b/core/java/android/content/res/ColorStateList.java @@ -315,6 +315,24 @@ public class ColorStateList implements Parcelable { return mDefaultColor; } + /** + * Return the states in this {@link ColorStateList}. + * @return the states in this {@link ColorStateList} + * @hide + */ + public int[][] getStates() { + return mStateSpecs; + } + + /** + * Return the colors in this {@link ColorStateList}. + * @return the colors in this {@link ColorStateList} + * @hide + */ + public int[] getColors() { + return mColors; + } + @Override public String toString() { return "ColorStateList{" + diff --git a/core/java/android/content/res/Resources.java b/core/java/android/content/res/Resources.java index da6ae56d0c60..5c2707206fb5 100644 --- a/core/java/android/content/res/Resources.java +++ b/core/java/android/content/res/Resources.java @@ -1625,7 +1625,7 @@ public class Resources { String locale = null; if (mConfiguration.locale != null) { - locale = localeToLanguageTag(mConfiguration.locale); + locale = adjustLanguageTag(localeToLanguageTag(mConfiguration.locale)); } int width, height; if (mMetrics.widthPixels >= mMetrics.heightPixels) { @@ -1713,6 +1713,41 @@ public class Resources { } /** + * {@code Locale.toLanguageTag} will transform the obsolete (and deprecated) + * language codes "in", "ji" and "iw" to "id", "yi" and "he" respectively. + * + * All released versions of android prior to "L" used the deprecated language + * tags, so we will need to support them for backwards compatibility. + * + * Note that this conversion needs to take place *after* the call to + * {@code toLanguageTag} because that will convert all the deprecated codes to + * the new ones, even if they're set manually. + */ + private static String adjustLanguageTag(String languageTag) { + final int separator = languageTag.indexOf('-'); + final String language; + final String remainder; + + if (separator == -1) { + language = languageTag; + remainder = ""; + } else { + language = languageTag.substring(0, separator); + remainder = languageTag.substring(separator); + } + + if ("id".equals(language)) { + return "in" + remainder; + } else if ("yi".equals(language)) { + return "ji" + remainder; + } else if ("he".equals(language)) { + return "iw" + remainder; + } else { + return languageTag; + } + } + + /** * Update the system resources configuration if they have previously * been initialized. * diff --git a/core/java/android/net/CaptivePortalTracker.java b/core/java/android/net/CaptivePortalTracker.java index 5b6f154b9692..89c17c7f7a9b 100644 --- a/core/java/android/net/CaptivePortalTracker.java +++ b/core/java/android/net/CaptivePortalTracker.java @@ -421,6 +421,13 @@ public class CaptivePortalTracker extends StateMachine { case ConnectivityManager.TYPE_WIFI: WifiInfo currentWifiInfo = mWifiManager.getConnectionInfo(); if (currentWifiInfo != null) { + // NOTE: getSSID()'s behavior changed in API 17; before that, SSIDs were not + // surrounded by double quotation marks (thus violating the Javadoc), but this + // was changed to match the Javadoc in API 17. Since clients may have started + // sanitizing the output of this method since API 17 was released, we should + // not change it here as it would become impossible to tell whether the SSID is + // simply being surrounded by quotes due to the API, or whether those quotes + // are actually part of the SSID. latencyBroadcast.putExtra(EXTRA_SSID, currentWifiInfo.getSSID()); latencyBroadcast.putExtra(EXTRA_BSSID, currentWifiInfo.getBSSID()); } else { diff --git a/core/java/android/nfc/tech/Ndef.java b/core/java/android/nfc/tech/Ndef.java index 8240ea6abc56..5852ce4ab9dc 100644 --- a/core/java/android/nfc/tech/Ndef.java +++ b/core/java/android/nfc/tech/Ndef.java @@ -277,6 +277,8 @@ public final class Ndef extends BasicTagTechnology { throw new TagLostException(); } return msg; + } else if (!tagService.isPresent(serviceHandle)) { + throw new TagLostException(); } else { return null; } diff --git a/core/java/android/os/BatteryStats.java b/core/java/android/os/BatteryStats.java index a965e00f3ed2..cc4bb51e0690 100644 --- a/core/java/android/os/BatteryStats.java +++ b/core/java/android/os/BatteryStats.java @@ -217,11 +217,11 @@ public abstract class BatteryStats implements Parcelable { * Returns the total time in microseconds associated with this Timer for the * selected type of statistics. * - * @param batteryRealtime system realtime on battery in microseconds + * @param elapsedRealtimeUs current elapsed realtime of system in microseconds * @param which one of STATS_TOTAL, STATS_LAST, or STATS_CURRENT * @return a time in microseconds */ - public abstract long getTotalTimeLocked(long batteryRealtime, int which); + public abstract long getTotalTimeLocked(long elapsedRealtimeUs, int which); /** * Temporary for debugging. @@ -295,14 +295,13 @@ public abstract class BatteryStats implements Parcelable { public abstract void noteVideoTurnedOffLocked(long elapsedRealtime); public abstract void noteActivityResumedLocked(long elapsedRealtime); public abstract void noteActivityPausedLocked(long elapsedRealtime); - public abstract long getWifiRunningTime(long batteryRealtime, int which); - public abstract long getFullWifiLockTime(long batteryRealtime, int which); - public abstract long getWifiScanTime(long batteryRealtime, int which); - public abstract long getWifiBatchedScanTime(int csphBin, long batteryRealtime, int which); - public abstract long getWifiMulticastTime(long batteryRealtime, - int which); - public abstract long getAudioTurnedOnTime(long batteryRealtime, int which); - public abstract long getVideoTurnedOnTime(long batteryRealtime, int which); + public abstract long getWifiRunningTime(long elapsedRealtimeUs, int which); + public abstract long getFullWifiLockTime(long elapsedRealtimeUs, int which); + public abstract long getWifiScanTime(long elapsedRealtimeUs, int which); + public abstract long getWifiBatchedScanTime(int csphBin, long elapsedRealtimeUs, int which); + public abstract long getWifiMulticastTime(long elapsedRealtimeUs, int which); + public abstract long getAudioTurnedOnTime(long elapsedRealtimeUs, int which); + public abstract long getVideoTurnedOnTime(long elapsedRealtimeUs, int which); public abstract Timer getForegroundActivityTimer(); public abstract Timer getVibratorOnTimer(); @@ -831,7 +830,7 @@ public abstract class BatteryStats implements Parcelable { * * {@hide} */ - public abstract long getScreenOnTime(long batteryRealtime, int which); + public abstract long getScreenOnTime(long elapsedRealtimeUs, int which); /** * Returns the number of times the screen was turned on. @@ -863,7 +862,7 @@ public abstract class BatteryStats implements Parcelable { * {@hide} */ public abstract long getScreenBrightnessTime(int brightnessBin, - long batteryRealtime, int which); + long elapsedRealtimeUs, int which); public abstract int getInputEventCount(int which); @@ -873,7 +872,7 @@ public abstract class BatteryStats implements Parcelable { * * {@hide} */ - public abstract long getPhoneOnTime(long batteryRealtime, int which); + public abstract long getPhoneOnTime(long elapsedRealtimeUs, int which); /** * Returns the number of times a phone call was activated. @@ -889,7 +888,7 @@ public abstract class BatteryStats implements Parcelable { * {@hide} */ public abstract long getPhoneSignalStrengthTime(int strengthBin, - long batteryRealtime, int which); + long elapsedRealtimeUs, int which); /** * Returns the time in microseconds that the phone has been trying to @@ -898,7 +897,7 @@ public abstract class BatteryStats implements Parcelable { * {@hide} */ public abstract long getPhoneSignalScanningTime( - long batteryRealtime, int which); + long elapsedRealtimeUs, int which); /** * Returns the number of times the phone has entered the given signal strength. @@ -913,7 +912,7 @@ public abstract class BatteryStats implements Parcelable { * * {@hide} */ - public abstract long getMobileRadioActiveTime(long batteryRealtime, int which); + public abstract long getMobileRadioActiveTime(long elapsedRealtimeUs, int which); /** * Returns the number of times that the mobile network has transitioned to the @@ -971,7 +970,7 @@ public abstract class BatteryStats implements Parcelable { * {@hide} */ public abstract long getPhoneDataConnectionTime(int dataType, - long batteryRealtime, int which); + long elapsedRealtimeUs, int which); /** * Returns the number of times the phone has entered the given data @@ -1030,7 +1029,7 @@ public abstract class BatteryStats implements Parcelable { * * {@hide} */ - public abstract long getWifiOnTime(long batteryRealtime, int which); + public abstract long getWifiOnTime(long elapsedRealtimeUs, int which); /** * Returns the time in microseconds that wifi has been on and the driver has @@ -1038,7 +1037,7 @@ public abstract class BatteryStats implements Parcelable { * * {@hide} */ - public abstract long getGlobalWifiRunningTime(long batteryRealtime, int which); + public abstract long getGlobalWifiRunningTime(long elapsedRealtimeUs, int which); public static final int WIFI_STATE_OFF = 0; public static final int WIFI_STATE_OFF_SCANNING = 1; @@ -1062,7 +1061,7 @@ public abstract class BatteryStats implements Parcelable { * {@hide} */ public abstract long getWifiStateTime(int wifiState, - long batteryRealtime, int which); + long elapsedRealtimeUs, int which); /** * Returns the number of times that WiFi has entered the given state. @@ -1077,7 +1076,7 @@ public abstract class BatteryStats implements Parcelable { * * {@hide} */ - public abstract long getBluetoothOnTime(long batteryRealtime, int which); + public abstract long getBluetoothOnTime(long elapsedRealtimeUs, int which); public abstract int getBluetoothPingCount(); @@ -1099,7 +1098,7 @@ public abstract class BatteryStats implements Parcelable { * {@hide} */ public abstract long getBluetoothStateTime(int bluetoothState, - long batteryRealtime, int which); + long elapsedRealtimeUs, int which); /** * Returns the number of times that Bluetooth has entered the given active state. @@ -1212,6 +1211,22 @@ public abstract class BatteryStats implements Parcelable { public abstract long computeBatteryRealtime(long curTime, int which); /** + * Returns the total, last, or current battery screen off uptime in microseconds. + * + * @param curTime the elapsed realtime in microseconds. + * @param which one of STATS_TOTAL, STATS_LAST, or STATS_CURRENT. + */ + public abstract long computeBatteryScreenOffUptime(long curTime, int which); + + /** + * Returns the total, last, or current battery screen off realtime in microseconds. + * + * @param curTime the current elapsed realtime in microseconds. + * @param which one of STATS_TOTAL, STATS_LAST, or STATS_CURRENT. + */ + public abstract long computeBatteryScreenOffRealtime(long curTime, int which); + + /** * Returns the total, last, or current uptime in microseconds. * * @param curTime the current elapsed realtime in microseconds. @@ -1262,28 +1277,28 @@ public abstract class BatteryStats implements Parcelable { } } - private final static void formatTime(StringBuilder sb, long time) { + public final static void formatTime(StringBuilder sb, long time) { long sec = time / 100; formatTimeRaw(sb, sec); sb.append((time - (sec * 100)) * 10); sb.append("ms "); } - private final static void formatTimeMs(StringBuilder sb, long time) { + public final static void formatTimeMs(StringBuilder sb, long time) { long sec = time / 1000; formatTimeRaw(sb, sec); sb.append(time - (sec * 1000)); sb.append("ms "); } - private final static void formatTimeMsNoSpace(StringBuilder sb, long time) { + public final static void formatTimeMsNoSpace(StringBuilder sb, long time) { long sec = time / 1000; formatTimeRaw(sb, sec); sb.append(time - (sec * 1000)); sb.append("ms"); } - private final String formatRatioLocked(long num, long den) { + public final String formatRatioLocked(long num, long den) { if (den == 0L) { return "--%"; } @@ -1293,7 +1308,7 @@ public abstract class BatteryStats implements Parcelable { return mFormatBuilder.toString(); } - private final String formatBytesLocked(long bytes) { + final String formatBytesLocked(long bytes) { mFormatBuilder.setLength(0); if (bytes < BYTES_PER_KB) { @@ -1310,10 +1325,10 @@ public abstract class BatteryStats implements Parcelable { } } - private static long computeWakeLock(Timer timer, long batteryRealtime, int which) { + private static long computeWakeLock(Timer timer, long elapsedRealtimeUs, int which) { if (timer != null) { // Convert from microseconds to milliseconds with rounding - long totalTimeMicros = timer.getTotalTimeLocked(batteryRealtime, which); + long totalTimeMicros = timer.getTotalTimeLocked(elapsedRealtimeUs, which); long totalTimeMillis = (totalTimeMicros + 500) / 1000; return totalTimeMillis; } @@ -1324,17 +1339,17 @@ public abstract class BatteryStats implements Parcelable { * * @param sb a StringBuilder object. * @param timer a Timer object contining the wakelock times. - * @param batteryRealtime the current on-battery time in microseconds. + * @param elapsedRealtimeUs the current on-battery time in microseconds. * @param name the name of the wakelock. * @param which which one of STATS_TOTAL, STATS_LAST, or STATS_CURRENT. * @param linePrefix a String to be prepended to each line of output. * @return the line prefix */ private static final String printWakeLock(StringBuilder sb, Timer timer, - long batteryRealtime, String name, int which, String linePrefix) { + long elapsedRealtimeUs, String name, int which, String linePrefix) { if (timer != null) { - long totalTimeMillis = computeWakeLock(timer, batteryRealtime, which); + long totalTimeMillis = computeWakeLock(timer, elapsedRealtimeUs, which); int count = timer.getCountLocked(which); if (totalTimeMillis != 0) { @@ -1358,18 +1373,18 @@ public abstract class BatteryStats implements Parcelable { * * @param sb a StringBuilder object. * @param timer a Timer object contining the wakelock times. - * @param now the current time in microseconds. + * @param elapsedRealtimeUs the current time in microseconds. * @param name the name of the wakelock. * @param which which one of STATS_TOTAL, STATS_LAST, or STATS_CURRENT. * @param linePrefix a String to be prepended to each line of output. * @return the line prefix */ - private static final String printWakeLockCheckin(StringBuilder sb, Timer timer, long now, - String name, int which, String linePrefix) { + private static final String printWakeLockCheckin(StringBuilder sb, Timer timer, + long elapsedRealtimeUs, String name, int which, String linePrefix) { long totalTimeMicros = 0; int count = 0; if (timer != null) { - totalTimeMicros = timer.getTotalTimeLocked(now, which); + totalTimeMicros = timer.getTotalTimeLocked(elapsedRealtimeUs, which); count = timer.getCountLocked(which); } sb.append(linePrefix); @@ -1411,16 +1426,18 @@ public abstract class BatteryStats implements Parcelable { final long rawUptime = SystemClock.uptimeMillis() * 1000; final long rawRealtime = SystemClock.elapsedRealtime() * 1000; final long batteryUptime = getBatteryUptime(rawUptime); - final long batteryRealtime = getBatteryRealtime(rawRealtime); final long whichBatteryUptime = computeBatteryUptime(rawUptime, which); final long whichBatteryRealtime = computeBatteryRealtime(rawRealtime, which); + final long whichBatteryScreenOffUptime = computeBatteryScreenOffUptime(rawUptime, which); + final long whichBatteryScreenOffRealtime = computeBatteryScreenOffRealtime(rawRealtime, + which); final long totalRealtime = computeRealtime(rawRealtime, which); final long totalUptime = computeUptime(rawUptime, which); - final long screenOnTime = getScreenOnTime(batteryRealtime, which); - final long phoneOnTime = getPhoneOnTime(batteryRealtime, which); - final long wifiOnTime = getWifiOnTime(batteryRealtime, which); - final long wifiRunningTime = getGlobalWifiRunningTime(batteryRealtime, which); - final long bluetoothOnTime = getBluetoothOnTime(batteryRealtime, which); + final long screenOnTime = getScreenOnTime(rawRealtime, which); + final long phoneOnTime = getPhoneOnTime(rawRealtime, which); + final long wifiOnTime = getWifiOnTime(rawRealtime, which); + final long wifiRunningTime = getGlobalWifiRunningTime(rawRealtime, which); + final long bluetoothOnTime = getBluetoothOnTime(rawRealtime, which); StringBuilder sb = new StringBuilder(128); @@ -1434,7 +1451,8 @@ public abstract class BatteryStats implements Parcelable { which == STATS_SINCE_CHARGED ? getStartCount() : "N/A", whichBatteryRealtime / 1000, whichBatteryUptime / 1000, totalRealtime / 1000, totalUptime / 1000, - getStartClockTime()); + getStartClockTime(), + whichBatteryScreenOffRealtime / 1000, whichBatteryScreenOffUptime / 1000); // Calculate wakelock times across all uids. long fullWakeLockTimeTotal = 0; @@ -1451,13 +1469,14 @@ public abstract class BatteryStats implements Parcelable { Timer fullWakeTimer = wl.getWakeTime(WAKE_TYPE_FULL); if (fullWakeTimer != null) { - fullWakeLockTimeTotal += fullWakeTimer.getTotalTimeLocked(batteryRealtime, which); + fullWakeLockTimeTotal += fullWakeTimer.getTotalTimeLocked(rawRealtime, + which); } Timer partialWakeTimer = wl.getWakeTime(WAKE_TYPE_PARTIAL); if (partialWakeTimer != null) { partialWakeLockTimeTotal += partialWakeTimer.getTotalTimeLocked( - batteryRealtime, which); + rawRealtime, which); } } } @@ -1483,23 +1502,23 @@ public abstract class BatteryStats implements Parcelable { wifiRunningTime / 1000, bluetoothOnTime / 1000, mobileRxTotalBytes, mobileTxTotalBytes, wifiRxTotalBytes, wifiTxTotalBytes, fullWakeLockTimeTotal, partialWakeLockTimeTotal, - getInputEventCount(which), getMobileRadioActiveTime(batteryRealtime, which)); + getInputEventCount(which), getMobileRadioActiveTime(rawRealtime, which)); // Dump screen brightness stats Object[] args = new Object[NUM_SCREEN_BRIGHTNESS_BINS]; for (int i=0; i<NUM_SCREEN_BRIGHTNESS_BINS; i++) { - args[i] = getScreenBrightnessTime(i, batteryRealtime, which) / 1000; + args[i] = getScreenBrightnessTime(i, rawRealtime, which) / 1000; } dumpLine(pw, 0 /* uid */, category, SCREEN_BRIGHTNESS_DATA, args); // Dump signal strength stats args = new Object[SignalStrength.NUM_SIGNAL_STRENGTH_BINS]; for (int i=0; i<SignalStrength.NUM_SIGNAL_STRENGTH_BINS; i++) { - args[i] = getPhoneSignalStrengthTime(i, batteryRealtime, which) / 1000; + args[i] = getPhoneSignalStrengthTime(i, rawRealtime, which) / 1000; } dumpLine(pw, 0 /* uid */, category, SIGNAL_STRENGTH_TIME_DATA, args); dumpLine(pw, 0 /* uid */, category, SIGNAL_SCANNING_TIME_DATA, - getPhoneSignalScanningTime(batteryRealtime, which) / 1000); + getPhoneSignalScanningTime(rawRealtime, which) / 1000); for (int i=0; i<SignalStrength.NUM_SIGNAL_STRENGTH_BINS; i++) { args[i] = getPhoneSignalStrengthCount(i, which); } @@ -1508,7 +1527,7 @@ public abstract class BatteryStats implements Parcelable { // Dump network type stats args = new Object[NUM_DATA_CONNECTION_TYPES]; for (int i=0; i<NUM_DATA_CONNECTION_TYPES; i++) { - args[i] = getPhoneDataConnectionTime(i, batteryRealtime, which) / 1000; + args[i] = getPhoneDataConnectionTime(i, rawRealtime, which) / 1000; } dumpLine(pw, 0 /* uid */, category, DATA_CONNECTION_TIME_DATA, args); for (int i=0; i<NUM_DATA_CONNECTION_TYPES; i++) { @@ -1519,7 +1538,7 @@ public abstract class BatteryStats implements Parcelable { // Dump wifi state stats args = new Object[NUM_WIFI_STATES]; for (int i=0; i<NUM_WIFI_STATES; i++) { - args[i] = getWifiStateTime(i, batteryRealtime, which) / 1000; + args[i] = getWifiStateTime(i, rawRealtime, which) / 1000; } dumpLine(pw, 0 /* uid */, category, WIFI_STATE_TIME_DATA, args); for (int i=0; i<NUM_WIFI_STATES; i++) { @@ -1530,7 +1549,7 @@ public abstract class BatteryStats implements Parcelable { // Dump bluetooth state stats args = new Object[NUM_BLUETOOTH_STATES]; for (int i=0; i<NUM_BLUETOOTH_STATES; i++) { - args[i] = getBluetoothStateTime(i, batteryRealtime, which) / 1000; + args[i] = getBluetoothStateTime(i, rawRealtime, which) / 1000; } dumpLine(pw, 0 /* uid */, category, BLUETOOTH_STATE_TIME_DATA, args); for (int i=0; i<NUM_BLUETOOTH_STATES; i++) { @@ -1559,7 +1578,7 @@ public abstract class BatteryStats implements Parcelable { if (kernelWakelocks.size() > 0) { for (Map.Entry<String, ? extends BatteryStats.Timer> ent : kernelWakelocks.entrySet()) { sb.setLength(0); - printWakeLockCheckin(sb, ent.getValue(), batteryRealtime, null, which, ""); + printWakeLockCheckin(sb, ent.getValue(), rawRealtime, null, which, ""); dumpLine(pw, 0 /* uid */, category, KERNEL_WAKELOCK_DATA, ent.getKey(), sb.toString()); @@ -1639,9 +1658,9 @@ public abstract class BatteryStats implements Parcelable { int mobileActiveCount = u.getMobileRadioActiveCount(which); long wifiPacketsRx = u.getNetworkActivityPackets(NETWORK_WIFI_RX_DATA, which); long wifiPacketsTx = u.getNetworkActivityPackets(NETWORK_WIFI_TX_DATA, which); - long fullWifiLockOnTime = u.getFullWifiLockTime(batteryRealtime, which); - long wifiScanTime = u.getWifiScanTime(batteryRealtime, which); - long uidWifiRunningTime = u.getWifiRunningTime(batteryRealtime, which); + long fullWifiLockOnTime = u.getFullWifiLockTime(rawRealtime, which); + long wifiScanTime = u.getWifiScanTime(rawRealtime, which); + long uidWifiRunningTime = u.getWifiRunningTime(rawRealtime, which); if (mobileBytesRx > 0 || mobileBytesTx > 0 || wifiBytesRx > 0 || wifiBytesTx > 0 || mobilePacketsRx > 0 || mobilePacketsTx > 0 || wifiPacketsRx > 0 @@ -1680,11 +1699,11 @@ public abstract class BatteryStats implements Parcelable { String linePrefix = ""; sb.setLength(0); linePrefix = printWakeLockCheckin(sb, wl.getWakeTime(WAKE_TYPE_FULL), - batteryRealtime, "f", which, linePrefix); + rawRealtime, "f", which, linePrefix); linePrefix = printWakeLockCheckin(sb, wl.getWakeTime(WAKE_TYPE_PARTIAL), - batteryRealtime, "p", which, linePrefix); + rawRealtime, "p", which, linePrefix); linePrefix = printWakeLockCheckin(sb, wl.getWakeTime(WAKE_TYPE_WINDOW), - batteryRealtime, "w", which, linePrefix); + rawRealtime, "w", which, linePrefix); // Only log if we had at lease one wakelock... if (sb.length() > 0) { @@ -1706,7 +1725,7 @@ public abstract class BatteryStats implements Parcelable { Timer timer = se.getSensorTime(); if (timer != null) { // Convert from microseconds to milliseconds with rounding - long totalTime = (timer.getTotalTimeLocked(batteryRealtime, which) + 500) / 1000; + long totalTime = (timer.getTotalTimeLocked(rawRealtime, which) + 500) / 1000; int count = timer.getCountLocked(which); if (totalTime != 0) { dumpLine(pw, uid, category, SENSOR_DATA, sensorNumber, totalTime, count); @@ -1718,7 +1737,7 @@ public abstract class BatteryStats implements Parcelable { Timer vibTimer = u.getVibratorOnTimer(); if (vibTimer != null) { // Convert from microseconds to milliseconds with rounding - long totalTime = (vibTimer.getTotalTimeLocked(batteryRealtime, which) + 500) / 1000; + long totalTime = (vibTimer.getTotalTimeLocked(rawRealtime, which) + 500) / 1000; int count = vibTimer.getCountLocked(which); if (totalTime != 0) { dumpLine(pw, uid, category, VIBRATOR_DATA, totalTime, count); @@ -1728,7 +1747,7 @@ public abstract class BatteryStats implements Parcelable { Timer fgTimer = u.getForegroundActivityTimer(); if (fgTimer != null) { // Convert from microseconds to milliseconds with rounding - long totalTime = (fgTimer.getTotalTimeLocked(batteryRealtime, which) + 500) / 1000; + long totalTime = (fgTimer.getTotalTimeLocked(rawRealtime, which) + 500) / 1000; int count = fgTimer.getCountLocked(which); if (totalTime != 0) { dumpLine(pw, uid, category, FOREGROUND_DATA, totalTime, count); @@ -1806,13 +1825,15 @@ public abstract class BatteryStats implements Parcelable { final long rawUptime = SystemClock.uptimeMillis() * 1000; final long rawRealtime = SystemClock.elapsedRealtime() * 1000; final long batteryUptime = getBatteryUptime(rawUptime); - final long batteryRealtime = getBatteryRealtime(rawRealtime); final long whichBatteryUptime = computeBatteryUptime(rawUptime, which); final long whichBatteryRealtime = computeBatteryRealtime(rawRealtime, which); final long totalRealtime = computeRealtime(rawRealtime, which); final long totalUptime = computeUptime(rawUptime, which); - + final long whichBatteryScreenOffUptime = computeBatteryScreenOffUptime(rawUptime, which); + final long whichBatteryScreenOffRealtime = computeBatteryScreenOffRealtime(rawRealtime, + which); + StringBuilder sb = new StringBuilder(128); SparseArray<? extends Uid> uidStats = getUidStats(); @@ -1830,6 +1851,17 @@ public abstract class BatteryStats implements Parcelable { pw.println(sb.toString()); sb.setLength(0); sb.append(prefix); + sb.append(" Time on battery screen off: "); + formatTimeMs(sb, whichBatteryScreenOffRealtime / 1000); sb.append("("); + sb.append(formatRatioLocked(whichBatteryScreenOffRealtime, totalRealtime)); + sb.append(") realtime, "); + formatTimeMs(sb, whichBatteryScreenOffUptime / 1000); + sb.append("("); + sb.append(formatRatioLocked(whichBatteryScreenOffUptime, totalRealtime)); + sb.append(") uptime"); + pw.println(sb.toString()); + sb.setLength(0); + sb.append(prefix); sb.append(" Total run time: "); formatTimeMs(sb, totalRealtime / 1000); sb.append("realtime, "); @@ -1839,11 +1871,11 @@ public abstract class BatteryStats implements Parcelable { pw.print(" Start clock time: "); pw.println(DateFormat.format("yyyy-MM-dd-HH-mm-ss", getStartClockTime()).toString()); - final long screenOnTime = getScreenOnTime(batteryRealtime, which); - final long phoneOnTime = getPhoneOnTime(batteryRealtime, which); - final long wifiRunningTime = getGlobalWifiRunningTime(batteryRealtime, which); - final long wifiOnTime = getWifiOnTime(batteryRealtime, which); - final long bluetoothOnTime = getBluetoothOnTime(batteryRealtime, which); + final long screenOnTime = getScreenOnTime(rawRealtime, which); + final long phoneOnTime = getPhoneOnTime(rawRealtime, which); + final long wifiRunningTime = getGlobalWifiRunningTime(rawRealtime, which); + final long wifiOnTime = getWifiOnTime(rawRealtime, which); + final long bluetoothOnTime = getBluetoothOnTime(rawRealtime, which); sb.setLength(0); sb.append(prefix); sb.append(" Screen on: "); formatTimeMs(sb, screenOnTime / 1000); @@ -1863,7 +1895,7 @@ public abstract class BatteryStats implements Parcelable { sb.append(" Screen brightnesses:"); boolean didOne = false; for (int i=0; i<NUM_SCREEN_BRIGHTNESS_BINS; i++) { - final long time = getScreenBrightnessTime(i, batteryRealtime, which); + final long time = getScreenBrightnessTime(i, rawRealtime, which); if (time == 0) { continue; } @@ -1905,7 +1937,7 @@ public abstract class BatteryStats implements Parcelable { 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); + long totalTimeMillis = computeWakeLock(timer, rawRealtime, which); if (totalTimeMillis > 0) { timers.add(new TimerEntry(ent.getKey(), 0, timer, totalTimeMillis)); } @@ -1918,7 +1950,7 @@ public abstract class BatteryStats implements Parcelable { sb.append(prefix); sb.append(" Kernel Wake lock "); sb.append(timer.mName); - linePrefix = printWakeLock(sb, timer.mTimer, batteryRealtime, null, + linePrefix = printWakeLock(sb, timer.mTimer, rawRealtime, null, which, linePrefix); if (!linePrefix.equals(": ")) { sb.append(" realtime"); @@ -1943,13 +1975,13 @@ public abstract class BatteryStats implements Parcelable { Timer fullWakeTimer = wl.getWakeTime(WAKE_TYPE_FULL); if (fullWakeTimer != null) { fullWakeLockTimeTotalMicros += fullWakeTimer.getTotalTimeLocked( - batteryRealtime, which); + rawRealtime, which); } Timer partialWakeTimer = wl.getWakeTime(WAKE_TYPE_PARTIAL); if (partialWakeTimer != null) { long totalTimeMicros = partialWakeTimer.getTotalTimeLocked( - batteryRealtime, which); + rawRealtime, which); if (totalTimeMicros > 0) { if (reqUid < 0) { // Only show the ordered list of all wake @@ -2000,7 +2032,7 @@ public abstract class BatteryStats implements Parcelable { sb.append(" Signal levels:"); didOne = false; for (int i=0; i<SignalStrength.NUM_SIGNAL_STRENGTH_BINS; i++) { - final long time = getPhoneSignalStrengthTime(i, batteryRealtime, which); + final long time = getPhoneSignalStrengthTime(i, rawRealtime, which); if (time == 0) { continue; } @@ -2022,7 +2054,7 @@ public abstract class BatteryStats implements Parcelable { sb.setLength(0); sb.append(prefix); sb.append(" Signal scanning time: "); - formatTimeMsNoSpace(sb, getPhoneSignalScanningTime(batteryRealtime, which) / 1000); + formatTimeMsNoSpace(sb, getPhoneSignalScanningTime(rawRealtime, which) / 1000); pw.println(sb.toString()); sb.setLength(0); @@ -2030,7 +2062,7 @@ public abstract class BatteryStats implements Parcelable { sb.append(" Radio types:"); didOne = false; for (int i=0; i<NUM_DATA_CONNECTION_TYPES; i++) { - final long time = getPhoneDataConnectionTime(i, batteryRealtime, which); + final long time = getPhoneDataConnectionTime(i, rawRealtime, which); if (time == 0) { continue; } @@ -2052,7 +2084,7 @@ public abstract class BatteryStats implements Parcelable { sb.setLength(0); sb.append(prefix); sb.append(" Mobile radio active time: "); - final long mobileActiveTime = getMobileRadioActiveTime(batteryRealtime, which); + final long mobileActiveTime = getMobileRadioActiveTime(rawRealtime, which); formatTimeMs(sb, mobileActiveTime / 1000); sb.append("("); sb.append(formatRatioLocked(mobileActiveTime, whichBatteryRealtime)); sb.append(") "); sb.append(getMobileRadioActiveCount(which)); @@ -2091,7 +2123,7 @@ public abstract class BatteryStats implements Parcelable { sb.append(" Wifi states:"); didOne = false; for (int i=0; i<NUM_WIFI_STATES; i++) { - final long time = getWifiStateTime(i, batteryRealtime, which); + final long time = getWifiStateTime(i, rawRealtime, which); if (time == 0) { continue; } @@ -2121,7 +2153,7 @@ public abstract class BatteryStats implements Parcelable { sb.append(" Bluetooth states:"); didOne = false; for (int i=0; i<NUM_BLUETOOTH_STATES; i++) { - final long time = getBluetoothStateTime(i, batteryRealtime, which); + final long time = getBluetoothStateTime(i, rawRealtime, which); if (time == 0) { continue; } @@ -2270,7 +2302,7 @@ public abstract class BatteryStats implements Parcelable { UserHandle.formatUid(sb, timer.mId); sb.append(" "); sb.append(timer.mName); - printWakeLock(sb, timer.mTimer, batteryRealtime, null, which, ": "); + printWakeLock(sb, timer.mTimer, rawRealtime, null, which, ": "); sb.append(" realtime"); pw.println(sb.toString()); } @@ -2302,9 +2334,9 @@ public abstract class BatteryStats implements Parcelable { int uidMobileActiveCount = u.getMobileRadioActiveCount(which); long wifiRxPackets = u.getNetworkActivityPackets(NETWORK_WIFI_RX_DATA, which); long wifiTxPackets = u.getNetworkActivityPackets(NETWORK_WIFI_TX_DATA, which); - long fullWifiLockOnTime = u.getFullWifiLockTime(batteryRealtime, which); - long wifiScanTime = u.getWifiScanTime(batteryRealtime, which); - long uidWifiRunningTime = u.getWifiRunningTime(batteryRealtime, which); + long fullWifiLockOnTime = u.getFullWifiLockTime(rawRealtime, which); + long wifiScanTime = u.getWifiScanTime(rawRealtime, which); + long uidWifiRunningTime = u.getWifiRunningTime(rawRealtime, which); if (mobileRxBytes > 0 || mobileTxBytes > 0 || mobileRxPackets > 0 || mobileTxPackets > 0) { @@ -2391,11 +2423,11 @@ public abstract class BatteryStats implements Parcelable { sb.append(prefix); sb.append(" Wake lock "); sb.append(ent.getKey()); - linePrefix = printWakeLock(sb, wl.getWakeTime(WAKE_TYPE_FULL), batteryRealtime, + linePrefix = printWakeLock(sb, wl.getWakeTime(WAKE_TYPE_FULL), rawRealtime, "full", which, linePrefix); - linePrefix = printWakeLock(sb, wl.getWakeTime(WAKE_TYPE_PARTIAL), batteryRealtime, + linePrefix = printWakeLock(sb, wl.getWakeTime(WAKE_TYPE_PARTIAL), rawRealtime, "partial", which, linePrefix); - linePrefix = printWakeLock(sb, wl.getWakeTime(WAKE_TYPE_WINDOW), batteryRealtime, + linePrefix = printWakeLock(sb, wl.getWakeTime(WAKE_TYPE_WINDOW), rawRealtime, "window", which, linePrefix); if (!linePrefix.equals(": ")) { sb.append(" realtime"); @@ -2405,11 +2437,11 @@ public abstract class BatteryStats implements Parcelable { count++; } totalFull += computeWakeLock(wl.getWakeTime(WAKE_TYPE_FULL), - batteryRealtime, which); + rawRealtime, which); totalPartial += computeWakeLock(wl.getWakeTime(WAKE_TYPE_PARTIAL), - batteryRealtime, which); + rawRealtime, which); totalWindow += computeWakeLock(wl.getWakeTime(WAKE_TYPE_WINDOW), - batteryRealtime, which); + rawRealtime, which); } if (count > 1) { if (totalFull != 0 || totalPartial != 0 || totalWindow != 0) { @@ -2465,7 +2497,7 @@ public abstract class BatteryStats implements Parcelable { if (timer != null) { // Convert from microseconds to milliseconds with rounding long totalTime = (timer.getTotalTimeLocked( - batteryRealtime, which) + 500) / 1000; + rawRealtime, which) + 500) / 1000; int count = timer.getCountLocked(which); //timer.logState(); if (totalTime != 0) { @@ -2489,7 +2521,7 @@ public abstract class BatteryStats implements Parcelable { if (vibTimer != null) { // Convert from microseconds to milliseconds with rounding long totalTime = (vibTimer.getTotalTimeLocked( - batteryRealtime, which) + 500) / 1000; + rawRealtime, which) + 500) / 1000; int count = vibTimer.getCountLocked(which); //timer.logState(); if (totalTime != 0) { @@ -2508,7 +2540,7 @@ public abstract class BatteryStats implements Parcelable { Timer fgTimer = u.getForegroundActivityTimer(); if (fgTimer != null) { // Convert from microseconds to milliseconds with rounding - long totalTime = (fgTimer.getTotalTimeLocked(batteryRealtime, which) + 500) / 1000; + long totalTime = (fgTimer.getTotalTimeLocked(rawRealtime, which) + 500) / 1000; int count = fgTimer.getCountLocked(which); if (totalTime != 0) { sb.setLength(0); diff --git a/core/java/android/view/DisplayList.java b/core/java/android/view/DisplayList.java index 3060e6e44a25..0ae36c1656c9 100644 --- a/core/java/android/view/DisplayList.java +++ b/core/java/android/view/DisplayList.java @@ -239,16 +239,6 @@ public class DisplayList { } /** - * After calling this method {@link #isValid()} will return false. - * TODO: Have Editor stop using this - * - * @see #isValid() - */ - public void markInvalid() { - mValid = false; - } - - /** * Reset native resources. This is called when cleaning up the state of display lists * during destruction of hardware resources, to ensure that we do not hold onto * obsolete resources after related resources are gone. diff --git a/core/java/android/view/SurfaceView.java b/core/java/android/view/SurfaceView.java index 9b23b3527968..1f211c21f0b0 100644 --- a/core/java/android/view/SurfaceView.java +++ b/core/java/android/view/SurfaceView.java @@ -255,8 +255,9 @@ public class SurfaceView extends View { updateWindow(false, false); } + /** @hide */ @Override - protected void onDetachedFromWindow() { + protected void onDetachedFromWindowInternal() { if (mGlobalListenersAdded) { ViewTreeObserver observer = getViewTreeObserver(); observer.removeOnScrollChangedListener(mScrollChangedListener); @@ -278,7 +279,7 @@ public class SurfaceView extends View { mSession = null; mLayout.token = null; - super.onDetachedFromWindow(); + super.onDetachedFromWindowInternal(); } @Override diff --git a/core/java/android/view/TextureView.java b/core/java/android/view/TextureView.java index ef0d80d73cde..3cfe5e916937 100644 --- a/core/java/android/view/TextureView.java +++ b/core/java/android/view/TextureView.java @@ -228,10 +228,11 @@ public class TextureView extends View { } } + /** @hide */ @Override - protected void onDetachedFromWindow() { - super.onDetachedFromWindow(); + protected void onDetachedFromWindowInternal() { destroySurface(); + super.onDetachedFromWindowInternal(); } private void destroySurface() { diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java index a57b3111cae7..827c4ccd1f1f 100644 --- a/core/java/android/view/View.java +++ b/core/java/android/view/View.java @@ -10838,11 +10838,14 @@ public class View implements Drawable.Callback, KeyEvent.Callback, * Sets the outline of the view, which defines the shape of the shadow it * casts, and can used for clipping. * <p> + * The outline path of a View must be {@link android.graphics.Path#isConvex() convex}. + * <p> * If the outline is not set, or {@link Path#isEmpty()}, shadows will be * cast from the bounds of the View, and clipToOutline will be ignored. * - * @param outline The new outline of the view. Must be non-null. + * @param outline The new outline of the view. Must be non-null, and convex. * + * @see #setCastsShadow(boolean) * @see #getOutline(Path) * @see #getClipToOutline() * @see #setClipToOutline(boolean) @@ -10851,6 +10854,9 @@ public class View implements Drawable.Callback, KeyEvent.Callback, if (outline == null) { throw new IllegalArgumentException("Path must be non-null"); } + if (!outline.isConvex()) { + throw new IllegalArgumentException("Path must be convex"); + } // always copy the path since caller may reuse if (mOutline == null) { mOutline = new Path(outline); @@ -13110,6 +13116,19 @@ public class View implements Drawable.Callback, KeyEvent.Callback, * @see #onAttachedToWindow() */ protected void onDetachedFromWindow() { + } + + /** + * This is a framework-internal mirror of onDetachedFromWindow() that's called + * after onDetachedFromWindow(). + * + * If you override this you *MUST* call super.onDetachedFromWindowInternal()! + * The super method should be called at the end of the overriden method to ensure + * subclasses are destroyed first + * + * @hide + */ + protected void onDetachedFromWindowInternal() { mPrivateFlags &= ~PFLAG_CANCEL_NEXT_UP_EVENT; mPrivateFlags3 &= ~PFLAG3_IS_LAID_OUT; @@ -13297,6 +13316,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback, } onDetachedFromWindow(); + onDetachedFromWindowInternal(); ListenerInfo li = mListenerInfo; final CopyOnWriteArrayList<OnAttachStateChangeListener> listeners = diff --git a/core/java/android/view/ViewGroup.java b/core/java/android/view/ViewGroup.java index cf5e8cfc84aa..9c5032379dfd 100644 --- a/core/java/android/view/ViewGroup.java +++ b/core/java/android/view/ViewGroup.java @@ -515,7 +515,8 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager private void initFromAttributes( Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) { - final TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.ViewGroup); + final TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.ViewGroup, defStyleAttr, + defStyleRes); final int N = a.getIndexCount(); for (int i = 0; i < N; i++) { @@ -2637,6 +2638,7 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager for (int i = 0; i < count; i++) { children[i].dispatchDetachedFromWindow(); } + clearDisappearingChildren(); super.dispatchDetachedFromWindow(); } @@ -5304,8 +5306,17 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager * this if you don't want animations for exiting views to stack up. */ public void clearDisappearingChildren() { - if (mDisappearingChildren != null) { - mDisappearingChildren.clear(); + final ArrayList<View> disappearingChildren = mDisappearingChildren; + if (disappearingChildren != null) { + final int count = disappearingChildren.size(); + for (int i = 0; i < count; i++) { + final View view = disappearingChildren.get(i); + if (view.mAttachInfo != null) { + view.dispatchDetachedFromWindow(); + } + view.clearAnimation(); + } + disappearingChildren.clear(); invalidate(); } } diff --git a/core/java/android/view/ViewRootImpl.java b/core/java/android/view/ViewRootImpl.java index 3af1c4fcfdf7..18517c56cbf3 100644 --- a/core/java/android/view/ViewRootImpl.java +++ b/core/java/android/view/ViewRootImpl.java @@ -2901,7 +2901,7 @@ public final class ViewRootImpl implements ViewParent, } } } - + /** * Return true if child is an ancestor of parent, (or equal to the parent). */ diff --git a/core/java/android/view/inputmethod/InputMethodInfo.java b/core/java/android/view/inputmethod/InputMethodInfo.java index 9f2bf3383985..f8160c88f974 100644 --- a/core/java/android/view/inputmethod/InputMethodInfo.java +++ b/core/java/android/view/inputmethod/InputMethodInfo.java @@ -37,6 +37,7 @@ import android.util.Printer; import android.util.Slog; import android.util.Xml; import android.view.inputmethod.InputMethodSubtype.InputMethodSubtypeBuilder; +import android.view.inputmethod.InputMethodSubtypeArray; import java.io.IOException; import java.util.ArrayList; @@ -86,9 +87,9 @@ public final class InputMethodInfo implements Parcelable { final int mIsDefaultResId; /** - * The array of the subtypes. + * An array-like container of the subtypes. */ - private final ArrayList<InputMethodSubtype> mSubtypes = new ArrayList<InputMethodSubtype>(); + private final InputMethodSubtypeArray mSubtypes; private final boolean mIsAuxIme; @@ -138,6 +139,7 @@ public final class InputMethodInfo implements Parcelable { int isDefaultResId = 0; XmlResourceParser parser = null; + final ArrayList<InputMethodSubtype> subtypes = new ArrayList<InputMethodSubtype>(); try { parser = si.loadXmlMetaData(pm, InputMethod.SERVICE_META_DATA); if (parser == null) { @@ -206,7 +208,7 @@ public final class InputMethodInfo implements Parcelable { if (!subtype.isAuxiliary()) { isAuxIme = false; } - mSubtypes.add(subtype); + subtypes.add(subtype); } } } catch (NameNotFoundException e) { @@ -216,7 +218,7 @@ public final class InputMethodInfo implements Parcelable { if (parser != null) parser.close(); } - if (mSubtypes.size() == 0) { + if (subtypes.size() == 0) { isAuxIme = false; } @@ -225,14 +227,15 @@ public final class InputMethodInfo implements Parcelable { final int N = additionalSubtypes.size(); for (int i = 0; i < N; ++i) { final InputMethodSubtype subtype = additionalSubtypes.get(i); - if (!mSubtypes.contains(subtype)) { - mSubtypes.add(subtype); + if (!subtypes.contains(subtype)) { + subtypes.add(subtype); } else { Slog.w(TAG, "Duplicated subtype definition found: " + subtype.getLocale() + ", " + subtype.getMode()); } } } + mSubtypes = new InputMethodSubtypeArray(subtypes); mSettingsActivityName = settingsActivityComponent; mIsDefaultResId = isDefaultResId; mIsAuxIme = isAuxIme; @@ -246,7 +249,7 @@ public final class InputMethodInfo implements Parcelable { mIsAuxIme = source.readInt() == 1; mSupportsSwitchingToNextInputMethod = source.readInt() == 1; mService = ResolveInfo.CREATOR.createFromParcel(source); - source.readTypedList(mSubtypes, InputMethodSubtype.CREATOR); + mSubtypes = new InputMethodSubtypeArray(source); mForceDefault = false; } @@ -272,9 +275,7 @@ public final class InputMethodInfo implements Parcelable { mSettingsActivityName = settingsActivity; mIsDefaultResId = isDefaultResId; mIsAuxIme = isAuxIme; - if (subtypes != null) { - mSubtypes.addAll(subtypes); - } + mSubtypes = new InputMethodSubtypeArray(subtypes); mForceDefault = forceDefault; mSupportsSwitchingToNextInputMethod = true; } @@ -364,7 +365,7 @@ public final class InputMethodInfo implements Parcelable { * composed of {@link #getPackageName} and the class name returned here. * * <p>A null will be returned if there is no settings activity associated - * with the input method. + * with the input method.</p> */ public String getSettingsActivity() { return mSettingsActivityName; @@ -374,7 +375,7 @@ public final class InputMethodInfo implements Parcelable { * Return the count of the subtypes of Input Method. */ public int getSubtypeCount() { - return mSubtypes.size(); + return mSubtypes.getCount(); } /** @@ -479,7 +480,7 @@ public final class InputMethodInfo implements Parcelable { dest.writeInt(mIsAuxIme ? 1 : 0); dest.writeInt(mSupportsSwitchingToNextInputMethod ? 1 : 0); mService.writeToParcel(dest, flags); - dest.writeTypedList(mSubtypes); + mSubtypes.writeToParcel(dest); } /** diff --git a/core/java/android/view/inputmethod/InputMethodSubtypeArray.java b/core/java/android/view/inputmethod/InputMethodSubtypeArray.java new file mode 100644 index 000000000000..5bef71fcd73b --- /dev/null +++ b/core/java/android/view/inputmethod/InputMethodSubtypeArray.java @@ -0,0 +1,278 @@ +/* + * Copyright (C) 2007-2014 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.view.inputmethod; + +import android.os.Parcel; +import android.os.Parcelable; +import android.util.AndroidRuntimeException; +import android.util.Slog; + +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.util.List; +import java.util.zip.GZIPInputStream; +import java.util.zip.GZIPOutputStream; + +/** + * An array-like container that stores multiple instances of {@link InputMethodSubtype}. + * + * <p>This container is designed to reduce the risk of {@link TransactionTooLargeException} + * when one or more instancess of {@link InputMethodInfo} are transferred through IPC. + * Basically this class does following three tasks.</p> + * <ul> + * <li>Applying compression for the marshalled data</li> + * <li>Lazily unmarshalling objects</li> + * <li>Caching the marshalled data when appropriate</li> + * </ul> + * + * @hide + */ +public class InputMethodSubtypeArray { + private final static String TAG = "InputMethodSubtypeArray"; + + /** + * Create a new instance of {@link InputMethodSubtypeArray} from an existing list of + * {@link InputMethodSubtype}. + * + * @param subtypes A list of {@link InputMethodSubtype} from which + * {@link InputMethodSubtypeArray} will be created. + */ + public InputMethodSubtypeArray(final List<InputMethodSubtype> subtypes) { + if (subtypes == null) { + mCount = 0; + return; + } + mCount = subtypes.size(); + mInstance = subtypes.toArray(new InputMethodSubtype[mCount]); + } + + /** + * Unmarshall an instance of {@link InputMethodSubtypeArray} from a given {@link Parcel} + * object. + * + * @param source A {@link Parcel} object from which {@link InputMethodSubtypeArray} will be + * unmarshalled. + */ + public InputMethodSubtypeArray(final Parcel source) { + mCount = source.readInt(); + if (mCount > 0) { + mDecompressedSize = source.readInt(); + mCompressedData = source.createByteArray(); + } + } + + /** + * Marshall the instance into a given {@link Parcel} object. + * + * <p>This methods may take a bit additional time to compress data lazily when called + * first time.</p> + * + * @param source A {@link Parcel} object to which {@link InputMethodSubtypeArray} will be + * marshalled. + */ + public void writeToParcel(final Parcel dest) { + if (mCount == 0) { + dest.writeInt(mCount); + return; + } + + byte[] compressedData = mCompressedData; + int decompressedSize = mDecompressedSize; + if (compressedData == null && decompressedSize == 0) { + synchronized (mLockObject) { + compressedData = mCompressedData; + decompressedSize = mDecompressedSize; + if (compressedData == null && decompressedSize == 0) { + final byte[] decompressedData = marshall(mInstance); + compressedData = compress(decompressedData); + if (compressedData == null) { + decompressedSize = -1; + Slog.i(TAG, "Failed to compress data."); + } else { + decompressedSize = decompressedData.length; + } + mDecompressedSize = decompressedSize; + mCompressedData = compressedData; + } + } + } + + if (compressedData != null && decompressedSize > 0) { + dest.writeInt(mCount); + dest.writeInt(decompressedSize); + dest.writeByteArray(compressedData); + } else { + Slog.i(TAG, "Unexpected state. Behaving as an empty array."); + dest.writeInt(0); + } + } + + /** + * Return {@link InputMethodSubtype} specified with the given index. + * + * <p>This methods may take a bit additional time to decompress data lazily when called + * first time.</p> + * + * @param index The index of {@link InputMethodSubtype}. + */ + public InputMethodSubtype get(final int index) { + if (index < 0 || mCount <= index) { + throw new ArrayIndexOutOfBoundsException(); + } + InputMethodSubtype[] instance = mInstance; + if (instance == null) { + synchronized (mLockObject) { + instance = mInstance; + if (instance == null) { + final byte[] decompressedData = + decompress(mCompressedData, mDecompressedSize); + // Clear the compressed data until {@link #getMarshalled()} is called. + mCompressedData = null; + mDecompressedSize = 0; + if (decompressedData != null) { + instance = unmarshall(decompressedData); + } else { + Slog.e(TAG, "Failed to decompress data. Returns null as fallback."); + instance = new InputMethodSubtype[mCount]; + } + mInstance = instance; + } + } + } + return instance[index]; + } + + /** + * Return the number of {@link InputMethodSubtype} objects. + */ + public int getCount() { + return mCount; + } + + private final Object mLockObject = new Object(); + private final int mCount; + + private volatile InputMethodSubtype[] mInstance; + private volatile byte[] mCompressedData; + private volatile int mDecompressedSize; + + private static byte[] marshall(final InputMethodSubtype[] array) { + Parcel parcel = null; + try { + parcel = Parcel.obtain(); + parcel.writeTypedArray(array, 0); + return parcel.marshall(); + } finally { + if (parcel != null) { + parcel.recycle(); + parcel = null; + } + } + } + + private static InputMethodSubtype[] unmarshall(final byte[] data) { + Parcel parcel = null; + try { + parcel = Parcel.obtain(); + parcel.unmarshall(data, 0, data.length); + parcel.setDataPosition(0); + return parcel.createTypedArray(InputMethodSubtype.CREATOR); + } finally { + if (parcel != null) { + parcel.recycle(); + parcel = null; + } + } + } + + private static byte[] compress(final byte[] data) { + ByteArrayOutputStream resultStream = null; + GZIPOutputStream zipper = null; + try { + resultStream = new ByteArrayOutputStream(); + zipper = new GZIPOutputStream(resultStream); + zipper.write(data); + } catch(IOException e) { + return null; + } finally { + try { + if (zipper != null) { + zipper.close(); + } + } catch (IOException e) { + zipper = null; + Slog.e(TAG, "Failed to close the stream.", e); + // swallowed, not propagated back to the caller + } + try { + if (resultStream != null) { + resultStream.close(); + } + } catch (IOException e) { + resultStream = null; + Slog.e(TAG, "Failed to close the stream.", e); + // swallowed, not propagated back to the caller + } + } + return resultStream != null ? resultStream.toByteArray() : null; + } + + private static byte[] decompress(final byte[] data, final int expectedSize) { + ByteArrayInputStream inputStream = null; + GZIPInputStream unzipper = null; + try { + inputStream = new ByteArrayInputStream(data); + unzipper = new GZIPInputStream(inputStream); + final byte [] result = new byte[expectedSize]; + int totalReadBytes = 0; + while (totalReadBytes < result.length) { + final int restBytes = result.length - totalReadBytes; + final int readBytes = unzipper.read(result, totalReadBytes, restBytes); + if (readBytes < 0) { + break; + } + totalReadBytes += readBytes; + } + if (expectedSize != totalReadBytes) { + return null; + } + return result; + } catch(IOException e) { + return null; + } finally { + try { + if (unzipper != null) { + unzipper.close(); + } + } catch (IOException e) { + Slog.e(TAG, "Failed to close the stream.", e); + // swallowed, not propagated back to the caller + } + try { + if (inputStream != null) { + inputStream.close(); + } + } catch (IOException e) { + Slog.e(TAG, "Failed to close the stream.", e); + // swallowed, not propagated back to the caller + } + } + } +} diff --git a/core/java/android/webkit/WebView.java b/core/java/android/webkit/WebView.java index 826bcecd51c9..81d36a4db1ff 100644 --- a/core/java/android/webkit/WebView.java +++ b/core/java/android/webkit/WebView.java @@ -2139,10 +2139,11 @@ public class WebView extends AbsoluteLayout mProvider.getViewDelegate().onAttachedToWindow(); } + /** @hide */ @Override - protected void onDetachedFromWindow() { + protected void onDetachedFromWindowInternal() { mProvider.getViewDelegate().onDetachedFromWindow(); - super.onDetachedFromWindow(); + super.onDetachedFromWindowInternal(); } @Override diff --git a/core/java/android/widget/Editor.java b/core/java/android/widget/Editor.java index 84c158649c28..98b43b32d537 100644 --- a/core/java/android/widget/Editor.java +++ b/core/java/android/widget/Editor.java @@ -137,7 +137,16 @@ public class Editor { InputContentType mInputContentType; InputMethodState mInputMethodState; - DisplayList[] mTextDisplayLists; + private static class TextDisplayList { + DisplayList displayList; + boolean isDirty; + public TextDisplayList(String name) { + isDirty = true; + displayList = DisplayList.create(name); + } + boolean needsRecord() { return isDirty || !displayList.isValid(); } + } + TextDisplayList[] mTextDisplayLists; boolean mFrozenWithFocus; boolean mSelectionMoved; @@ -262,7 +271,7 @@ public class Editor { mTextView.removeCallbacks(mShowSuggestionRunnable); } - invalidateTextDisplayList(); + destroyDisplayListsData(); if (mSpellChecker != null) { mSpellChecker.closeSession(); @@ -277,6 +286,19 @@ public class Editor { mTemporaryDetach = false; } + private void destroyDisplayListsData() { + HardwareRenderer renderer = mTextView.getHardwareRenderer(); + if (mTextDisplayLists != null) { + for (int i = 0; i < mTextDisplayLists.length; i++) { + DisplayList displayList = mTextDisplayLists[i] != null + ? mTextDisplayLists[i].displayList : null; + if (displayList != null && displayList.isValid()) { + displayList.destroyDisplayListData(renderer); + } + } + } + } + private void showError() { if (mTextView.getWindowToken() == null) { mShowErrorAfterAttach = true; @@ -1320,7 +1342,7 @@ public class Editor { if (layout instanceof DynamicLayout) { if (mTextDisplayLists == null) { - mTextDisplayLists = new DisplayList[ArrayUtils.idealObjectArraySize(0)]; + mTextDisplayLists = new TextDisplayList[ArrayUtils.idealObjectArraySize(0)]; } DynamicLayout dynamicLayout = (DynamicLayout) layout; @@ -1344,13 +1366,13 @@ public class Editor { searchStartIndex = blockIndex + 1; } - DisplayList blockDisplayList = mTextDisplayLists[blockIndex]; - if (blockDisplayList == null) { - blockDisplayList = mTextDisplayLists[blockIndex] = - DisplayList.create("Text " + blockIndex); + if (mTextDisplayLists[blockIndex] == null) { + mTextDisplayLists[blockIndex] = + new TextDisplayList("Text " + blockIndex); } - final boolean blockDisplayListIsInvalid = !blockDisplayList.isValid(); + final boolean blockDisplayListIsInvalid = mTextDisplayLists[blockIndex].needsRecord(); + DisplayList blockDisplayList = mTextDisplayLists[blockIndex].displayList; if (i >= indexFirstChangedBlock || blockDisplayListIsInvalid) { final int blockBeginLine = endOfPreviousBlock + 1; final int top = layout.getLineTop(blockBeginLine); @@ -1421,7 +1443,7 @@ public class Editor { // No available index found, the pool has to grow int newSize = ArrayUtils.idealIntArraySize(length + 1); - DisplayList[] displayLists = new DisplayList[newSize]; + TextDisplayList[] displayLists = new TextDisplayList[newSize]; System.arraycopy(mTextDisplayLists, 0, displayLists, 0, length); mTextDisplayLists = displayLists; return length; @@ -1460,7 +1482,7 @@ public class Editor { while (i < numberOfBlocks) { final int blockIndex = blockIndices[i]; if (blockIndex != DynamicLayout.INVALID_BLOCK_INDEX) { - mTextDisplayLists[blockIndex].markInvalid(); + mTextDisplayLists[blockIndex].isDirty = true; } if (blockEndLines[i] >= lastLine) break; i++; @@ -1471,7 +1493,7 @@ public class Editor { void invalidateTextDisplayList() { if (mTextDisplayLists != null) { for (int i = 0; i < mTextDisplayLists.length; i++) { - if (mTextDisplayLists[i] != null) mTextDisplayLists[i].markInvalid(); + if (mTextDisplayLists[i] != null) mTextDisplayLists[i].isDirty = true; } } } diff --git a/core/java/android/widget/TextView.java b/core/java/android/widget/TextView.java index e5cb16fa65e3..687036ca14ef 100644 --- a/core/java/android/widget/TextView.java +++ b/core/java/android/widget/TextView.java @@ -4729,10 +4729,9 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener if (mEditor != null) mEditor.onAttachedToWindow(); } + /** @hide */ @Override - protected void onDetachedFromWindow() { - super.onDetachedFromWindow(); - + protected void onDetachedFromWindowInternal() { if (mPreDrawRegistered) { getViewTreeObserver().removeOnPreDrawListener(this); mPreDrawRegistered = false; @@ -4741,6 +4740,8 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener resetResolvedDrawables(); if (mEditor != null) mEditor.onDetachedFromWindow(); + + super.onDetachedFromWindowInternal(); } @Override diff --git a/core/java/com/android/internal/os/BatteryStatsHelper.java b/core/java/com/android/internal/os/BatteryStatsHelper.java index 6f959372a96b..1dd1f5e16d30 100644 --- a/core/java/com/android/internal/os/BatteryStatsHelper.java +++ b/core/java/com/android/internal/os/BatteryStatsHelper.java @@ -79,6 +79,8 @@ public class BatteryStatsHelper { private int mStatsType = BatteryStats.STATS_SINCE_CHARGED; private int mAsUser = 0; + long mRawRealtime; + long mRawUptime; long mBatteryRealtime; long mBatteryUptime; long mTypeBatteryRealtime; @@ -157,7 +159,7 @@ public class BatteryStatsHelper { SystemClock.uptimeMillis() * 1000); } - public void refreshStats(int statsType, int asUser, long rawRealtimeNano, long rawUptimeNano) { + public void refreshStats(int statsType, int asUser, long rawRealtimeUs, long rawUptimeUs) { // Initialize mStats if necessary. getStats(); @@ -182,14 +184,16 @@ public class BatteryStatsHelper { mStatsType = statsType; mAsUser = asUser; - mBatteryUptime = mStats.getBatteryUptime(rawUptimeNano); - mBatteryRealtime = mStats.getBatteryRealtime(rawRealtimeNano); - mTypeBatteryUptime = mStats.computeBatteryUptime(rawUptimeNano, mStatsType); - mTypeBatteryRealtime = mStats.computeBatteryRealtime(rawRealtimeNano, mStatsType); + mRawUptime = rawUptimeUs; + mRawRealtime = rawRealtimeUs; + mBatteryUptime = mStats.getBatteryUptime(rawUptimeUs); + mBatteryRealtime = mStats.getBatteryRealtime(rawRealtimeUs); + mTypeBatteryUptime = mStats.computeBatteryUptime(rawUptimeUs, mStatsType); + mTypeBatteryRealtime = mStats.computeBatteryRealtime(rawRealtimeUs, mStatsType); if (DEBUG) { - Log.d(TAG, "Raw time: realtime=" + (rawRealtimeNano/1000) + " uptime=" - + (rawUptimeNano/1000)); + Log.d(TAG, "Raw time: realtime=" + (rawRealtimeUs/1000) + " uptime=" + + (rawUptimeUs/1000)); Log.d(TAG, "Battery time: realtime=" + (mBatteryRealtime/1000) + " uptime=" + (mBatteryUptime/1000)); Log.d(TAG, "Battery type time: realtime=" + (mTypeBatteryRealtime/1000) + " uptime=" @@ -266,7 +270,7 @@ public class BatteryStatsHelper { final double mobilePowerPerPacket = getMobilePowerPerPacket(); final double mobilePowerPerMs = getMobilePowerPerMs(); final double wifiPowerPerPacket = getWifiPowerPerPacket(); - long appWakelockTime = 0; + long appWakelockTimeUs = 0; BatterySipper osApp = null; mStatsPeriod = mTypeBatteryRealtime; SparseArray<? extends Uid> uidStats = mStats.getUidStats(); @@ -342,11 +346,11 @@ public class BatteryStatsHelper { // are canceled when the user turns the screen off. BatteryStats.Timer timer = wakelock.getWakeTime(BatteryStats.WAKE_TYPE_PARTIAL); if (timer != null) { - wakelockTime += timer.getTotalTimeLocked(mBatteryRealtime, which); + wakelockTime += timer.getTotalTimeLocked(mRawRealtime, which); } } + appWakelockTimeUs += wakelockTime; wakelockTime /= 1000; // convert to millis - appWakelockTime += wakelockTime; // Add cost of holding a wake lock p = (wakelockTime @@ -387,7 +391,7 @@ public class BatteryStatsHelper { power += p; // Add cost of keeping WIFI running. - long wifiRunningTimeMs = u.getWifiRunningTime(mBatteryRealtime, which) / 1000; + long wifiRunningTimeMs = u.getWifiRunningTime(mRawRealtime, which) / 1000; mAppWifiRunning += wifiRunningTimeMs; p = (wifiRunningTimeMs * mPowerProfile.getAveragePower(PowerProfile.POWER_WIFI_ON)) / (60*60*1000); @@ -396,14 +400,14 @@ public class BatteryStatsHelper { power += p; // Add cost of WIFI scans - long wifiScanTimeMs = u.getWifiScanTime(mBatteryRealtime, which) / 1000; + long wifiScanTimeMs = u.getWifiScanTime(mRawRealtime, which) / 1000; p = (wifiScanTimeMs * mPowerProfile.getAveragePower(PowerProfile.POWER_WIFI_SCAN)) / (60*60*1000); if (DEBUG) Log.d(TAG, "UID " + u.getUid() + ": wifi scan " + wifiScanTimeMs + " power=" + makemAh(p)); power += p; for (int bin = 0; bin < BatteryStats.Uid.NUM_WIFI_BATCHED_SCAN_BINS; bin++) { - long batchScanTimeMs = u.getWifiBatchedScanTime(bin, mBatteryRealtime, which) / 1000; + long batchScanTimeMs = u.getWifiBatchedScanTime(bin, mRawRealtime, which) / 1000; p = ((batchScanTimeMs * mPowerProfile.getAveragePower(PowerProfile.POWER_WIFI_BATCHED_SCAN, bin)) ) / (60*60*1000); @@ -419,7 +423,7 @@ public class BatteryStatsHelper { Uid.Sensor sensor = sensorEntry.getValue(); int sensorHandle = sensor.getHandle(); BatteryStats.Timer timer = sensor.getSensorTime(); - long sensorTime = timer.getTotalTimeLocked(mBatteryRealtime, which) / 1000; + long sensorTime = timer.getTotalTimeLocked(mRawRealtime, which) / 1000; double multiplier = 0; switch (sensorHandle) { case Uid.Sensor.GPS: @@ -505,8 +509,8 @@ public class BatteryStatsHelper { // this remainder to the OS, if possible. if (osApp != null) { long wakeTimeMillis = mBatteryUptime / 1000; - wakeTimeMillis -= appWakelockTime - + (mStats.getScreenOnTime(mBatteryRealtime, which) / 1000); + wakeTimeMillis -= (appWakelockTimeUs / 1000) + + (mStats.getScreenOnTime(mRawRealtime, which) / 1000); if (wakeTimeMillis > 0) { double power = (wakeTimeMillis * mPowerProfile.getAveragePower(PowerProfile.POWER_CPU_AWAKE)) @@ -523,7 +527,7 @@ public class BatteryStatsHelper { } private void addPhoneUsage() { - long phoneOnTimeMs = mStats.getPhoneOnTime(mBatteryRealtime, mStatsType) / 1000; + long phoneOnTimeMs = mStats.getPhoneOnTime(mRawRealtime, mStatsType) / 1000; double phoneOnPower = mPowerProfile.getAveragePower(PowerProfile.POWER_RADIO_ACTIVE) * phoneOnTimeMs / (60*60*1000); if (phoneOnPower != 0) { @@ -533,14 +537,14 @@ public class BatteryStatsHelper { private void addScreenUsage() { double power = 0; - long screenOnTimeMs = mStats.getScreenOnTime(mBatteryRealtime, mStatsType) / 1000; + long screenOnTimeMs = mStats.getScreenOnTime(mRawRealtime, mStatsType) / 1000; power += screenOnTimeMs * mPowerProfile.getAveragePower(PowerProfile.POWER_SCREEN_ON); final double screenFullPower = mPowerProfile.getAveragePower(PowerProfile.POWER_SCREEN_FULL); for (int i = 0; i < BatteryStats.NUM_SCREEN_BRIGHTNESS_BINS; i++) { double screenBinPower = screenFullPower * (i + 0.5f) / BatteryStats.NUM_SCREEN_BRIGHTNESS_BINS; - long brightnessTime = mStats.getScreenBrightnessTime(i, mBatteryRealtime, mStatsType) + long brightnessTime = mStats.getScreenBrightnessTime(i, mRawRealtime, mStatsType) / 1000; double p = screenBinPower*brightnessTime; if (DEBUG && p != 0) { @@ -561,7 +565,7 @@ public class BatteryStatsHelper { long signalTimeMs = 0; long noCoverageTimeMs = 0; for (int i = 0; i < BINS; i++) { - long strengthTimeMs = mStats.getPhoneSignalStrengthTime(i, mBatteryRealtime, mStatsType) + long strengthTimeMs = mStats.getPhoneSignalStrengthTime(i, mRawRealtime, mStatsType) / 1000; double p = (strengthTimeMs * mPowerProfile.getAveragePower(PowerProfile.POWER_RADIO_ON, i)) / (60*60*1000); @@ -575,7 +579,7 @@ public class BatteryStatsHelper { noCoverageTimeMs = strengthTimeMs; } } - long scanningTimeMs = mStats.getPhoneSignalScanningTime(mBatteryRealtime, mStatsType) + long scanningTimeMs = mStats.getPhoneSignalScanningTime(mRawRealtime, mStatsType) / 1000; double p = (scanningTimeMs * mPowerProfile.getAveragePower( PowerProfile.POWER_RADIO_SCANNING)) @@ -584,7 +588,7 @@ public class BatteryStatsHelper { Log.d(TAG, "Cell radio scanning: time=" + scanningTimeMs + " power=" + makemAh(p)); } power += p; - long radioActiveTimeUs = mStats.getMobileRadioActiveTime(mBatteryRealtime, mStatsType); + long radioActiveTimeUs = mStats.getMobileRadioActiveTime(mRawRealtime, mStatsType); long remainingActiveTime = (radioActiveTimeUs - mAppMobileActive) / 1000; if (remainingActiveTime > 0) { power += getMobilePowerPerMs() * remainingActiveTime; @@ -624,8 +628,8 @@ public class BatteryStatsHelper { } private void addWiFiUsage() { - long onTimeMs = mStats.getWifiOnTime(mBatteryRealtime, mStatsType) / 1000; - long runningTimeMs = mStats.getGlobalWifiRunningTime(mBatteryRealtime, mStatsType) / 1000; + long onTimeMs = mStats.getWifiOnTime(mRawRealtime, mStatsType) / 1000; + long runningTimeMs = mStats.getGlobalWifiRunningTime(mRawRealtime, mStatsType) / 1000; if (DEBUG) Log.d(TAG, "WIFI runningTime=" + runningTimeMs + " app runningTime=" + mAppWifiRunning); runningTimeMs -= mAppWifiRunning; @@ -646,7 +650,7 @@ public class BatteryStatsHelper { private void addIdleUsage() { long idleTimeMs = (mTypeBatteryRealtime - - mStats.getScreenOnTime(mBatteryRealtime, mStatsType)) / 1000; + - mStats.getScreenOnTime(mRawRealtime, mStatsType)) / 1000; double idlePower = (idleTimeMs * mPowerProfile.getAveragePower(PowerProfile.POWER_CPU_IDLE)) / (60*60*1000); if (DEBUG && idlePower != 0) { @@ -658,7 +662,7 @@ public class BatteryStatsHelper { } private void addBluetoothUsage() { - long btOnTimeMs = mStats.getBluetoothOnTime(mBatteryRealtime, mStatsType) / 1000; + long btOnTimeMs = mStats.getBluetoothOnTime(mRawRealtime, mStatsType) / 1000; double btPower = btOnTimeMs * mPowerProfile.getAveragePower(PowerProfile.POWER_BLUETOOTH_ON) / (60*60*1000); if (DEBUG && btPower != 0) { @@ -704,7 +708,7 @@ public class BatteryStatsHelper { final long mobileData = mobileRx + mobileTx; final long radioDataUptimeMs - = mStats.getMobileRadioActiveTime(mBatteryRealtime, mStatsType) / 1000; + = mStats.getMobileRadioActiveTime(mRawRealtime, mStatsType) / 1000; final double mobilePps = (mobileData != 0 && radioDataUptimeMs != 0) ? (mobileData / (double)radioDataUptimeMs) : (((double)MOBILE_BPS) / 8 / 2048); diff --git a/core/java/com/android/internal/os/BatteryStatsImpl.java b/core/java/com/android/internal/os/BatteryStatsImpl.java index fdb090b44e4c..fd93604e5a7e 100644 --- a/core/java/com/android/internal/os/BatteryStatsImpl.java +++ b/core/java/com/android/internal/os/BatteryStatsImpl.java @@ -87,7 +87,7 @@ public final class BatteryStatsImpl extends BatteryStats { private static final int MAGIC = 0xBA757475; // 'BATSTATS' // Current on-disk Parcel version - private static final int VERSION = 94 + (USE_OLD_HISTORY ? 1000 : 0); + private static final int VERSION = 97 + (USE_OLD_HISTORY ? 1000 : 0); // Maximum number of items we will record in the history. private static final int MAX_HISTORY_ITEMS = 2000; @@ -174,7 +174,15 @@ public final class BatteryStatsImpl extends BatteryStats { // These are the objects that will want to do something when the device // is unplugged from power. - final ArrayList<Unpluggable> mUnpluggables = new ArrayList<Unpluggable>(); + final TimeBase mOnBatteryTimeBase = new TimeBase(); + + // These are the objects that will want to do something when the device + // is unplugged from power *and* the screen is off. + final TimeBase mOnBatteryScreenOffTimeBase = new TimeBase(); + + // Set to true when we want to distribute CPU across wakelocks for the next + // CPU update, even if we aren't currently running wake locks. + boolean mDistributeWakelockCpu; boolean mShuttingDown; @@ -217,11 +225,6 @@ public final class BatteryStatsImpl extends BatteryStats { long mStartClockTime; - long mBatteryUptime; - long mBatteryLastUptime; - long mBatteryRealtime; - long mBatteryLastRealtime; - long mUptime; long mUptimeStart; long mLastUptime; @@ -296,13 +299,6 @@ public final class BatteryStatsImpl extends BatteryStats { */ boolean mOnBattery; boolean mOnBatteryInternal; - long mTrackBatteryPastUptime; - long mTrackBatteryUptimeStart; - long mTrackBatteryPastRealtime; - long mTrackBatteryRealtimeStart; - - long mUnpluggedBatteryUptime; - long mUnpluggedBatteryRealtime; /* * These keep track of battery levels (1-100) at the last plug event and the last unplug event. @@ -391,35 +387,235 @@ public final class BatteryStatsImpl extends BatteryStats { mHandler = null; } - public static interface Unpluggable { - void unplug(long elapsedRealtime, long batteryUptime, long batteryRealtime); - void plug(long elapsedRealtime, long batteryUptime, long batteryRealtime); + public static interface TimeBaseObs { + void onTimeStarted(long elapsedRealtime, long baseUptime, long baseRealtime); + void onTimeStopped(long elapsedRealtime, long baseUptime, long baseRealtime); + } + + static class TimeBase { + private final ArrayList<TimeBaseObs> mObservers = new ArrayList<TimeBaseObs>(); + + private long mUptime; + private long mLastUptime; + private long mRealtime; + private long mLastRealtime; + + private boolean mRunning; + + private long mPastUptime; + private long mUptimeStart; + private long mPastRealtime; + private long mRealtimeStart; + private long mUnpluggedUptime; + private long mUnpluggedRealtime; + + public void dump(PrintWriter pw, String prefix) { + StringBuilder sb = new StringBuilder(128); + pw.print(prefix); pw.print("mRunning="); pw.println(mRunning); + sb.setLength(0); + sb.append(prefix); + sb.append("mUptime="); + formatTimeMs(sb, mUptime / 1000); sb.append("mLastUptime="); + formatTimeMs(sb, mLastUptime / 1000); + pw.println(sb.toString()); + sb.setLength(0); + sb.append(prefix); + sb.append("mRealtime="); + formatTimeMs(sb, mRealtime / 1000); sb.append("mLastRealtime="); + formatTimeMs(sb, mLastRealtime / 1000); + pw.println(sb.toString()); + sb.setLength(0); + sb.append(prefix); + sb.append("mPastUptime="); + formatTimeMs(sb, mPastUptime / 1000); sb.append("mUptimeStart="); + formatTimeMs(sb, mUptimeStart / 1000); + sb.append("mUnpluggedUptime="); formatTimeMs(sb, mUnpluggedUptime / 1000); + pw.println(sb.toString()); + sb.setLength(0); + sb.append(prefix); + sb.append("mPastRealtime="); + formatTimeMs(sb, mPastRealtime / 1000); sb.append("mRealtimeStart="); + formatTimeMs(sb, mRealtimeStart / 1000); + sb.append("mUnpluggedRealtime="); formatTimeMs(sb, mUnpluggedRealtime / 1000); + pw.println(sb.toString()); + } + + public void add(TimeBaseObs observer) { + mObservers.add(observer); + } + + public void remove(TimeBaseObs observer) { + if (!mObservers.remove(observer)) { + Slog.wtf(TAG, "Removed unknown observer: " + observer); + } + } + + public void init(long uptime, long realtime) { + mRealtime = 0; + mUptime = 0; + mPastUptime = 0; + mPastRealtime = 0; + mUptimeStart = uptime; + mRealtimeStart = realtime; + mUnpluggedUptime = getUptime(mUptimeStart); + mUnpluggedRealtime = getRealtime(mRealtimeStart); + } + + public void reset(long uptime, long realtime) { + if (!mRunning) { + mPastUptime = 0; + mPastRealtime = 0; + } else { + mUptimeStart = uptime; + mRealtimeStart = realtime; + mUnpluggedUptime = getUptime(uptime); + mUnpluggedRealtime = getRealtime(realtime); + } + } + + public long computeUptime(long curTime, int which) { + switch (which) { + case STATS_SINCE_CHARGED: + return mUptime + getUptime(curTime); + case STATS_LAST: + return mLastUptime; + case STATS_CURRENT: + return getUptime(curTime); + case STATS_SINCE_UNPLUGGED: + return getUptime(curTime) - mUnpluggedUptime; + } + return 0; + } + + public long computeRealtime(long curTime, int which) { + switch (which) { + case STATS_SINCE_CHARGED: + return mRealtime + getRealtime(curTime); + case STATS_LAST: + return mLastRealtime; + case STATS_CURRENT: + return getRealtime(curTime); + case STATS_SINCE_UNPLUGGED: + return getRealtime(curTime) - mUnpluggedRealtime; + } + return 0; + } + + public long getUptime(long curTime) { + long time = mPastUptime; + if (mRunning) { + time += curTime - mUptimeStart; + } + return time; + } + + public long getRealtime(long curTime) { + long time = mPastRealtime; + if (mRunning) { + time += curTime - mRealtimeStart; + } + return time; + } + + public long getUptimeStart() { + return mUptimeStart; + } + + public long getRealtimeStart() { + return mRealtimeStart; + } + + public boolean isRunning() { + return mRunning; + } + + public boolean setRunning(boolean running, long uptime, long realtime) { + if (mRunning != running) { + mRunning = running; + if (running) { + mUptimeStart = uptime; + mRealtimeStart = realtime; + long batteryUptime = mUnpluggedUptime = getUptime(uptime); + long batteryRealtime = mUnpluggedRealtime = getRealtime(realtime); + + for (int i = mObservers.size() - 1; i >= 0; i--) { + mObservers.get(i).onTimeStarted(realtime, batteryUptime, batteryRealtime); + } + } else { + mPastUptime += uptime - mUptimeStart; + mPastRealtime += realtime - mRealtimeStart; + + long batteryUptime = getUptime(uptime); + long batteryRealtime = getRealtime(realtime); + + for (int i = mObservers.size() - 1; i >= 0; i--) { + mObservers.get(i).onTimeStopped(realtime, batteryUptime, batteryRealtime); + } + } + return true; + } + return false; + } + + public void readSummaryFromParcel(Parcel in) { + mUptime = in.readLong(); + mRealtime = in.readLong(); + } + + public void writeSummaryToParcel(Parcel out, long uptime, long realtime) { + out.writeLong(computeUptime(uptime, STATS_SINCE_CHARGED)); + out.writeLong(computeRealtime(realtime, STATS_SINCE_CHARGED)); + } + + public void readFromParcel(Parcel in) { + mRunning = false; + mUptime = in.readLong(); + mLastUptime = 0; + mPastUptime = in.readLong(); + mUptimeStart = in.readLong(); + mPastRealtime = in.readLong(); + mRealtimeStart = in.readLong(); + mUnpluggedUptime = in.readLong(); + mUnpluggedRealtime = in.readLong(); + } + + public void writeToParcel(Parcel out, long uptime, long realtime) { + final long runningUptime = getUptime(uptime); + final long runningRealtime = getRealtime(realtime); + out.writeLong(mUptime); + out.writeLong(runningUptime); + out.writeLong(mUptimeStart); + out.writeLong(runningRealtime); + out.writeLong(mRealtimeStart); + out.writeLong(mUnpluggedUptime); + out.writeLong(mUnpluggedRealtime); + } } /** * State for keeping track of counting information. */ - public static class Counter extends BatteryStats.Counter implements Unpluggable { + public static class Counter extends BatteryStats.Counter implements TimeBaseObs { final AtomicInteger mCount = new AtomicInteger(); - final ArrayList<Unpluggable> mUnpluggables; + final TimeBase mTimeBase; int mLoadedCount; int mLastCount; int mUnpluggedCount; int mPluggedCount; - Counter(ArrayList<Unpluggable> unpluggables, Parcel in) { - mUnpluggables = unpluggables; + Counter(TimeBase timeBase, Parcel in) { + mTimeBase = timeBase; mPluggedCount = in.readInt(); mCount.set(mPluggedCount); mLoadedCount = in.readInt(); mLastCount = 0; mUnpluggedCount = in.readInt(); - unpluggables.add(this); + timeBase.add(this); } - Counter(ArrayList<Unpluggable> unpluggables) { - mUnpluggables = unpluggables; - unpluggables.add(this); + Counter(TimeBase timeBase) { + mTimeBase = timeBase; + timeBase.add(this); } public void writeToParcel(Parcel out) { @@ -428,12 +624,12 @@ public final class BatteryStatsImpl extends BatteryStats { out.writeInt(mUnpluggedCount); } - public void unplug(long elapsedRealtime, long batteryUptime, long batteryRealtime) { + public void onTimeStarted(long elapsedRealtime, long baseUptime, long baseRealtime) { mUnpluggedCount = mPluggedCount; mCount.set(mPluggedCount); } - public void plug(long elapsedRealtime, long batteryUptime, long batteryRealtime) { + public void onTimeStopped(long elapsedRealtime, long baseUptime, long baseRealtime) { mPluggedCount = mCount.get(); } @@ -493,7 +689,7 @@ public final class BatteryStatsImpl extends BatteryStats { } void detach() { - mUnpluggables.remove(this); + mTimeBase.remove(this); } void writeSummaryFromParcelLocked(Parcel out) { @@ -510,12 +706,12 @@ public final class BatteryStatsImpl extends BatteryStats { } public static class SamplingCounter extends Counter { - SamplingCounter(ArrayList<Unpluggable> unpluggables, Parcel in) { - super(unpluggables, in); + SamplingCounter(TimeBase timeBase, Parcel in) { + super(timeBase, in); } - SamplingCounter(ArrayList<Unpluggable> unpluggables) { - super(unpluggables); + SamplingCounter(TimeBase timeBase) { + super(timeBase); } public void addCountAtomic(long count) { @@ -523,27 +719,27 @@ public final class BatteryStatsImpl extends BatteryStats { } } - public static class LongSamplingCounter implements Unpluggable { - final ArrayList<Unpluggable> mUnpluggables; + public static class LongSamplingCounter implements TimeBaseObs { + final TimeBase mTimeBase; long mCount; long mLoadedCount; long mLastCount; long mUnpluggedCount; long mPluggedCount; - LongSamplingCounter(ArrayList<Unpluggable> unpluggables, Parcel in) { - mUnpluggables = unpluggables; + LongSamplingCounter(TimeBase timeBase, Parcel in) { + mTimeBase = timeBase; mPluggedCount = in.readLong(); mCount = mPluggedCount; mLoadedCount = in.readLong(); mLastCount = 0; mUnpluggedCount = in.readLong(); - unpluggables.add(this); + timeBase.add(this); } - LongSamplingCounter(ArrayList<Unpluggable> unpluggables) { - mUnpluggables = unpluggables; - unpluggables.add(this); + LongSamplingCounter(TimeBase timeBase) { + mTimeBase = timeBase; + timeBase.add(this); } public void writeToParcel(Parcel out) { @@ -553,13 +749,13 @@ public final class BatteryStatsImpl extends BatteryStats { } @Override - public void unplug(long elapsedRealtime, long batteryUptime, long batteryRealtime) { + public void onTimeStarted(long elapsedRealtime, long baseUptime, long baseRealtime) { mUnpluggedCount = mPluggedCount; mCount = mPluggedCount; } @Override - public void plug(long elapsedRealtime, long batteryUptime, long batteryRealtime) { + public void onTimeStopped(long elapsedRealtime, long baseUptime, long baseRealtime) { mPluggedCount = mCount; } @@ -595,7 +791,7 @@ public final class BatteryStatsImpl extends BatteryStats { } void detach() { - mUnpluggables.remove(this); + mTimeBase.remove(this); } void writeSummaryFromParcelLocked(Parcel out) { @@ -613,9 +809,9 @@ public final class BatteryStatsImpl extends BatteryStats { /** * State for keeping track of timing information. */ - public static abstract class Timer extends BatteryStats.Timer implements Unpluggable { + public static abstract class Timer extends BatteryStats.Timer implements TimeBaseObs { final int mType; - final ArrayList<Unpluggable> mUnpluggables; + final TimeBase mTimeBase; int mCount; int mLoadedCount; @@ -654,12 +850,12 @@ public final class BatteryStatsImpl extends BatteryStats { /** * Constructs from a parcel. * @param type - * @param unpluggables + * @param timeBase * @param in */ - Timer(int type, ArrayList<Unpluggable> unpluggables, Parcel in) { + Timer(int type, TimeBase timeBase, Parcel in) { mType = type; - mUnpluggables = unpluggables; + mTimeBase = timeBase; mCount = in.readInt(); mLoadedCount = in.readInt(); @@ -669,13 +865,13 @@ public final class BatteryStatsImpl extends BatteryStats { mLoadedTime = in.readLong(); mLastTime = 0; mUnpluggedTime = in.readLong(); - unpluggables.add(this); + timeBase.add(this); } - Timer(int type, ArrayList<Unpluggable> unpluggables) { + Timer(int type, TimeBase timeBase) { mType = type; - mUnpluggables = unpluggables; - unpluggables.add(this); + mTimeBase = timeBase; + timeBase.add(this); } protected abstract long computeRunTimeLocked(long curBatteryRealtime); @@ -686,7 +882,7 @@ public final class BatteryStatsImpl extends BatteryStats { * Clear state of this timer. Returns true if the timer is inactive * so can be completely dropped. */ - boolean reset(BatteryStatsImpl stats, boolean detachIfReset) { + boolean reset(boolean detachIfReset) { mTotalTime = mLoadedTime = mLastTime = 0; mCount = mLoadedCount = mLastCount = 0; if (detachIfReset) { @@ -696,25 +892,25 @@ public final class BatteryStatsImpl extends BatteryStats { } void detach() { - mUnpluggables.remove(this); + mTimeBase.remove(this); } - public void writeToParcel(Parcel out, long batteryRealtime) { + public void writeToParcel(Parcel out, long elapsedRealtimeUs) { out.writeInt(mCount); out.writeInt(mLoadedCount); out.writeInt(mUnpluggedCount); - out.writeLong(computeRunTimeLocked(batteryRealtime)); + out.writeLong(computeRunTimeLocked(mTimeBase.getRealtime(elapsedRealtimeUs))); out.writeLong(mLoadedTime); out.writeLong(mUnpluggedTime); } - public void unplug(long elapsedRealtime, long batteryUptime, long batteryRealtime) { + public void onTimeStarted(long elapsedRealtime, long timeBaseUptime, long baseRealtime) { if (DEBUG && mType < 0) { - Log.v(TAG, "unplug #" + mType + ": realtime=" + batteryRealtime + Log.v(TAG, "unplug #" + mType + ": realtime=" + baseRealtime + " old mUnpluggedTime=" + mUnpluggedTime + " old mUnpluggedCount=" + mUnpluggedCount); } - mUnpluggedTime = computeRunTimeLocked(batteryRealtime); + mUnpluggedTime = computeRunTimeLocked(baseRealtime); mUnpluggedCount = mCount; if (DEBUG && mType < 0) { Log.v(TAG, "unplug #" + mType @@ -723,12 +919,12 @@ public final class BatteryStatsImpl extends BatteryStats { } } - public void plug(long elapsedRealtime, long batteryUptime, long batteryRealtime) { + public void onTimeStopped(long elapsedRealtime, long baseUptime, long baseRealtime) { if (DEBUG && mType < 0) { - Log.v(TAG, "plug #" + mType + ": realtime=" + batteryRealtime + Log.v(TAG, "plug #" + mType + ": realtime=" + baseRealtime + " old mTotalTime=" + mTotalTime); } - mTotalTime = computeRunTimeLocked(batteryRealtime); + mTotalTime = computeRunTimeLocked(baseRealtime); mCount = computeCurrentCountLocked(); if (DEBUG && mType < 0) { Log.v(TAG, "plug #" + mType @@ -742,24 +938,23 @@ public final class BatteryStatsImpl extends BatteryStats { * @param out the Parcel to be written to. * @param timer a Timer, or null. */ - public static void writeTimerToParcel(Parcel out, Timer timer, - long batteryRealtime) { + public static void writeTimerToParcel(Parcel out, Timer timer, long elapsedRealtimeUs) { if (timer == null) { out.writeInt(0); // indicates null return; } out.writeInt(1); // indicates non-null - timer.writeToParcel(out, batteryRealtime); + timer.writeToParcel(out, elapsedRealtimeUs); } @Override - public long getTotalTimeLocked(long batteryRealtime, int which) { + public long getTotalTimeLocked(long elapsedRealtimeUs, int which) { long val; if (which == STATS_LAST) { val = mLastTime; } else { - val = computeRunTimeLocked(batteryRealtime); + val = computeRunTimeLocked(mTimeBase.getRealtime(elapsedRealtimeUs)); if (which == STATS_SINCE_UNPLUGGED) { val -= mUnpluggedTime; } else if (which != STATS_SINCE_CHARGED) { @@ -798,16 +993,15 @@ public final class BatteryStatsImpl extends BatteryStats { } - void writeSummaryFromParcelLocked(Parcel out, long batteryRealtime) { - long runTime = computeRunTimeLocked(batteryRealtime); - // Divide by 1000 for backwards compatibility - out.writeLong((runTime + 500) / 1000); + void writeSummaryFromParcelLocked(Parcel out, long elapsedRealtimeUs) { + long runTime = computeRunTimeLocked(mTimeBase.getRealtime(elapsedRealtimeUs)); + out.writeLong(runTime); out.writeInt(mCount); } void readSummaryFromParcelLocked(Parcel in) { // Multiply by 1000 for backwards compatibility - mTotalTime = mLoadedTime = in.readLong() * 1000; + mTotalTime = mLoadedTime = in.readLong(); mLastTime = 0; mUnpluggedTime = mTotalTime; mCount = mLoadedCount = in.readInt(); @@ -844,7 +1038,7 @@ public final class BatteryStatsImpl extends BatteryStats { /** * Whether we are currently in a discharge cycle. */ - boolean mInDischarge; + boolean mTimeBaseRunning; /** * Whether we are currently recording reported values. @@ -856,21 +1050,20 @@ public final class BatteryStatsImpl extends BatteryStats { */ int mUpdateVersion; - SamplingTimer(ArrayList<Unpluggable> unpluggables, boolean inDischarge, Parcel in) { - super(0, unpluggables, in); + SamplingTimer(TimeBase timeBase, Parcel in) { + super(0, timeBase, in); mCurrentReportedCount = in.readInt(); mUnpluggedReportedCount = in.readInt(); mCurrentReportedTotalTime = in.readLong(); mUnpluggedReportedTotalTime = in.readLong(); mTrackingReportedValues = in.readInt() == 1; - mInDischarge = inDischarge; + mTimeBaseRunning = timeBase.isRunning(); } - SamplingTimer(ArrayList<Unpluggable> unpluggables, boolean inDischarge, - boolean trackReportedValues) { - super(0, unpluggables); + SamplingTimer(TimeBase timeBase, boolean trackReportedValues) { + super(0, timeBase); mTrackingReportedValues = trackReportedValues; - mInDischarge = inDischarge; + mTimeBaseRunning = timeBase.isRunning(); } public void setStale() { @@ -888,7 +1081,7 @@ public final class BatteryStatsImpl extends BatteryStats { } public void updateCurrentReportedCount(int count) { - if (mInDischarge && mUnpluggedReportedCount == 0) { + if (mTimeBaseRunning && mUnpluggedReportedCount == 0) { // Updating the reported value for the first time. mUnpluggedReportedCount = count; // If we are receiving an update update mTrackingReportedValues; @@ -898,7 +1091,7 @@ public final class BatteryStatsImpl extends BatteryStats { } public void updateCurrentReportedTotalTime(long totalTime) { - if (mInDischarge && mUnpluggedReportedTotalTime == 0) { + if (mTimeBaseRunning && mUnpluggedReportedTotalTime == 0) { // Updating the reported value for the first time. mUnpluggedReportedTotalTime = totalTime; // If we are receiving an update update mTrackingReportedValues; @@ -907,18 +1100,18 @@ public final class BatteryStatsImpl extends BatteryStats { mCurrentReportedTotalTime = totalTime; } - public void unplug(long elapsedRealtime, long batteryUptime, long batteryRealtime) { - super.unplug(elapsedRealtime, batteryUptime, batteryRealtime); + public void onTimeStarted(long elapsedRealtime, long baseUptime, long baseRealtime) { + super.onTimeStarted(elapsedRealtime, baseUptime, baseRealtime); if (mTrackingReportedValues) { mUnpluggedReportedTotalTime = mCurrentReportedTotalTime; mUnpluggedReportedCount = mCurrentReportedCount; } - mInDischarge = true; + mTimeBaseRunning = true; } - public void plug(long elapsedRealtime, long batteryUptime, long batteryRealtime) { - super.plug(elapsedRealtime, batteryUptime, batteryRealtime); - mInDischarge = false; + public void onTimeStopped(long elapsedRealtime, long baseUptime, long baseRealtime) { + super.onTimeStopped(elapsedRealtime, baseUptime, baseRealtime); + mTimeBaseRunning = false; } public void logState(Printer pw, String prefix) { @@ -930,17 +1123,17 @@ public final class BatteryStatsImpl extends BatteryStats { } protected long computeRunTimeLocked(long curBatteryRealtime) { - return mTotalTime + (mInDischarge && mTrackingReportedValues + return mTotalTime + (mTimeBaseRunning && mTrackingReportedValues ? mCurrentReportedTotalTime - mUnpluggedReportedTotalTime : 0); } protected int computeCurrentCountLocked() { - return mCount + (mInDischarge && mTrackingReportedValues + return mCount + (mTimeBaseRunning && mTrackingReportedValues ? mCurrentReportedCount - mUnpluggedReportedCount : 0); } - public void writeToParcel(Parcel out, long batteryRealtime) { - super.writeToParcel(out, batteryRealtime); + public void writeToParcel(Parcel out, long elapsedRealtimeUs) { + super.writeToParcel(out, elapsedRealtimeUs); out.writeInt(mCurrentReportedCount); out.writeInt(mUnpluggedReportedCount); out.writeLong(mCurrentReportedTotalTime); @@ -948,8 +1141,8 @@ public final class BatteryStatsImpl extends BatteryStats { out.writeInt(mTrackingReportedValues ? 1 : 0); } - boolean reset(BatteryStatsImpl stats, boolean detachIfReset) { - super.reset(stats, detachIfReset); + boolean reset(boolean detachIfReset) { + super.reset(detachIfReset); setStale(); return true; } @@ -991,45 +1184,43 @@ public final class BatteryStatsImpl extends BatteryStats { */ boolean mInDischarge; - BatchTimer(Uid uid, int type, ArrayList<Unpluggable> unpluggables, - boolean inDischarge, Parcel in) { - super(type, unpluggables, in); + BatchTimer(Uid uid, int type, TimeBase timeBase, Parcel in) { + super(type, timeBase, in); mUid = uid; mLastAddedTime = in.readLong(); mLastAddedDuration = in.readLong(); - mInDischarge = inDischarge; + mInDischarge = timeBase.isRunning(); } - BatchTimer(Uid uid, int type, ArrayList<Unpluggable> unpluggables, - boolean inDischarge) { - super(type, unpluggables); + BatchTimer(Uid uid, int type, TimeBase timeBase) { + super(type, timeBase); mUid = uid; - mInDischarge = inDischarge; + mInDischarge = timeBase.isRunning(); } @Override - public void writeToParcel(Parcel out, long batteryRealtime) { - super.writeToParcel(out, batteryRealtime); + public void writeToParcel(Parcel out, long elapsedRealtimeUs) { + super.writeToParcel(out, elapsedRealtimeUs); out.writeLong(mLastAddedTime); out.writeLong(mLastAddedDuration); } @Override - public void plug(long elapsedRealtime, long batteryUptime, long batteryRealtime) { + public void onTimeStopped(long elapsedRealtime, long baseUptime, long baseRealtime) { recomputeLastDuration(SystemClock.elapsedRealtime() * 1000, false); mInDischarge = false; - super.plug(elapsedRealtime, batteryUptime, batteryRealtime); + super.onTimeStopped(elapsedRealtime, baseUptime, baseRealtime); } @Override - public void unplug(long elapsedRealtime, long batteryUptime, long batteryRealtime) { + public void onTimeStarted(long elapsedRealtime, long baseUptime, long baseRealtime) { recomputeLastDuration(elapsedRealtime, false); mInDischarge = true; // If we are still within the last added duration, then re-added whatever remains. if (mLastAddedTime == elapsedRealtime) { mTotalTime += mLastAddedDuration; } - super.unplug(elapsedRealtime, batteryUptime, batteryRealtime); + super.onTimeStarted(elapsedRealtime, baseUptime, baseRealtime); } @Override @@ -1095,11 +1286,11 @@ public final class BatteryStatsImpl extends BatteryStats { } @Override - boolean reset(BatteryStatsImpl stats, boolean detachIfReset) { + boolean reset(boolean detachIfReset) { final long now = SystemClock.elapsedRealtime() * 1000; recomputeLastDuration(now, true); boolean stillActive = mLastAddedTime == now; - super.reset(stats, !stillActive && detachIfReset); + super.reset(!stillActive && detachIfReset); return !stillActive; } } @@ -1135,16 +1326,16 @@ public final class BatteryStatsImpl extends BatteryStats { boolean mInList; StopwatchTimer(Uid uid, int type, ArrayList<StopwatchTimer> timerPool, - ArrayList<Unpluggable> unpluggables, Parcel in) { - super(type, unpluggables, in); + TimeBase timeBase, Parcel in) { + super(type, timeBase, in); mUid = uid; mTimerPool = timerPool; mUpdateTime = in.readLong(); } StopwatchTimer(Uid uid, int type, ArrayList<StopwatchTimer> timerPool, - ArrayList<Unpluggable> unpluggables) { - super(type, unpluggables); + TimeBase timeBase) { + super(type, timeBase); mUid = uid; mTimerPool = timerPool; } @@ -1153,18 +1344,18 @@ public final class BatteryStatsImpl extends BatteryStats { mTimeout = timeout; } - public void writeToParcel(Parcel out, long batteryRealtime) { - super.writeToParcel(out, batteryRealtime); + public void writeToParcel(Parcel out, long elapsedRealtimeUs) { + super.writeToParcel(out, elapsedRealtimeUs); out.writeLong(mUpdateTime); } - public void plug(long elapsedRealtime, long batteryUptime, long batteryRealtime) { + public void onTimeStopped(long elapsedRealtime, long baseUptime, long baseRealtime) { if (mNesting > 0) { if (DEBUG && mType < 0) { Log.v(TAG, "old mUpdateTime=" + mUpdateTime); } - super.plug(elapsedRealtime, batteryUptime, batteryRealtime); - mUpdateTime = batteryRealtime; + super.onTimeStopped(elapsedRealtime, baseUptime, baseRealtime); + mUpdateTime = baseRealtime; if (DEBUG && mType < 0) { Log.v(TAG, "new mUpdateTime=" + mUpdateTime); } @@ -1177,14 +1368,14 @@ public final class BatteryStatsImpl extends BatteryStats { + " mAcquireTime=" + mAcquireTime); } - void startRunningLocked(BatteryStatsImpl stats, long elapsedRealtime) { + void startRunningLocked(long elapsedRealtimeMs) { if (mNesting++ == 0) { - final long batteryRealtime = stats.getBatteryRealtimeLocked(elapsedRealtime * 1000); + final long batteryRealtime = mTimeBase.getRealtime(elapsedRealtimeMs * 1000); mUpdateTime = batteryRealtime; if (mTimerPool != null) { // Accumulate time to all currently active timers before adding // this new one to the pool. - refreshTimersLocked(stats, batteryRealtime, mTimerPool, null); + refreshTimersLocked(batteryRealtime, mTimerPool, null); // Add this timer to the active pool mTimerPool.add(this); } @@ -1203,12 +1394,12 @@ public final class BatteryStatsImpl extends BatteryStats { return mNesting > 0; } - long checkpointRunningLocked(BatteryStatsImpl stats, long elapsedRealtime) { + long checkpointRunningLocked(long elapsedRealtimeMs) { if (mNesting > 0) { // We are running... - final long batteryRealtime = stats.getBatteryRealtimeLocked(elapsedRealtime * 1000); + final long batteryRealtime = mTimeBase.getRealtime(elapsedRealtimeMs * 1000); if (mTimerPool != null) { - return refreshTimersLocked(stats, batteryRealtime, mTimerPool, this); + return refreshTimersLocked(batteryRealtime, mTimerPool, this); } final long heldTime = batteryRealtime - mUpdateTime; mUpdateTime = batteryRealtime; @@ -1218,17 +1409,17 @@ public final class BatteryStatsImpl extends BatteryStats { return 0; } - void stopRunningLocked(BatteryStatsImpl stats, long elapsedRealtime) { + void stopRunningLocked(long elapsedRealtimeMs) { // Ignore attempt to stop a timer that isn't running if (mNesting == 0) { return; } if (--mNesting == 0) { - final long batteryRealtime = stats.getBatteryRealtimeLocked(elapsedRealtime * 1000); + final long batteryRealtime = mTimeBase.getRealtime(elapsedRealtimeMs * 1000); if (mTimerPool != null) { // Accumulate time to all active counters, scaled by the total // active in the pool, before taking this one out of the pool. - refreshTimersLocked(stats, batteryRealtime, mTimerPool, null); + refreshTimersLocked(batteryRealtime, mTimerPool, null); // Remove this timer from the active pool mTimerPool.remove(this); } else { @@ -1253,8 +1444,8 @@ public final class BatteryStatsImpl extends BatteryStats { // Update the total time for all other running Timers with the same type as this Timer // due to a change in timer count - private static long refreshTimersLocked(final BatteryStatsImpl stats, - long batteryRealtime, final ArrayList<StopwatchTimer> pool, StopwatchTimer self) { + private static long refreshTimersLocked(long batteryRealtime, + final ArrayList<StopwatchTimer> pool, StopwatchTimer self) { long selfTime = 0; final int N = pool.size(); for (int i=N-1; i>= 0; i--) { @@ -1288,12 +1479,11 @@ public final class BatteryStatsImpl extends BatteryStats { return mCount; } - boolean reset(BatteryStatsImpl stats, boolean detachIfReset) { + boolean reset(boolean detachIfReset) { boolean canDetach = mNesting <= 0; - super.reset(stats, canDetach && detachIfReset); + super.reset(canDetach && detachIfReset); if (mNesting > 0) { - mUpdateTime = stats.getBatteryRealtimeLocked( - SystemClock.elapsedRealtime() * 1000); + mUpdateTime = mTimeBase.getRealtime(SystemClock.elapsedRealtime() * 1000); } mAcquireTime = mTotalTime; return canDetach; @@ -1456,8 +1646,7 @@ public final class BatteryStatsImpl extends BatteryStats { public SamplingTimer getKernelWakelockTimerLocked(String name) { SamplingTimer kwlt = mKernelWakelockStats.get(name); if (kwlt == null) { - kwlt = new SamplingTimer(mUnpluggables, mOnBatteryInternal, - true /* track reported values */); + kwlt = new SamplingTimer(mOnBatteryScreenOffTimeBase, true /* track reported values */); mKernelWakelockStats.put(name, kwlt); } return kwlt; @@ -1953,24 +2142,31 @@ public final class BatteryStatsImpl extends BatteryStats { mHistoryOverflow = false; } - public void doUnplugLocked(long elapsedRealtime, long batteryUptime, long batteryRealtime) { - for (int i = mUnpluggables.size() - 1; i >= 0; i--) { - mUnpluggables.get(i).unplug(elapsedRealtime, batteryUptime, batteryRealtime); + public void updateTimeBasesLocked(boolean unplugged, boolean screenOff, long uptime, + long realtime) { + if (mOnBatteryTimeBase.setRunning(unplugged, uptime, realtime)) { + if (unplugged) { + // Track bt headset ping count + mBluetoothPingStart = getCurrentBluetoothPingCount(); + mBluetoothPingCount = 0; + } else { + // Track bt headset ping count + mBluetoothPingCount = getBluetoothPingCount(); + mBluetoothPingStart = -1; + } } - // Track bt headset ping count - mBluetoothPingStart = getCurrentBluetoothPingCount(); - mBluetoothPingCount = 0; - } - - public void doPlugLocked(long elapsedRealtime, long batteryUptime, long batteryRealtime) { - for (int i = mUnpluggables.size() - 1; i >= 0; i--) { - mUnpluggables.get(i).plug(elapsedRealtime, batteryUptime, batteryRealtime); + boolean unpluggedScreenOff = unplugged && screenOff; + if (unpluggedScreenOff != mOnBatteryScreenOffTimeBase.isRunning()) { + updateKernelWakelocksLocked(); + requestWakelockCpuUpdate(); + if (!unpluggedScreenOff) { + // We are switching to no longer tracking wake locks, but we want + // the next CPU update we receive to take them in to account. + mDistributeWakelockCpu = true; + } + mOnBatteryScreenOffTimeBase.setRunning(unpluggedScreenOff, uptime, realtime); } - - // Track bt headset ping count - mBluetoothPingCount = getBluetoothPingCount(); - mBluetoothPingStart = -1; } public void addIsolatedUidLocked(int isolatedUid, int appUid) { @@ -2033,6 +2229,13 @@ public final class BatteryStatsImpl extends BatteryStats { addHistoryEventLocked(SystemClock.elapsedRealtime(), code, name, uid); } + private void requestWakelockCpuUpdate() { + if (!mHandler.hasMessages(MSG_UPDATE_WAKELOCKS)) { + Message m = mHandler.obtainMessage(MSG_UPDATE_WAKELOCKS); + mHandler.sendMessageDelayed(m, DELAY_UPDATE_WAKELOCKS); + } + } + public void noteStartWakeLocked(int uid, int pid, String name, String historyName, int type, boolean unimportantForLogging) { uid = mapUid(uid); @@ -2063,10 +2266,7 @@ public final class BatteryStatsImpl extends BatteryStats { mWakeLockNesting++; } if (uid >= 0) { - if (!mHandler.hasMessages(MSG_UPDATE_WAKELOCKS)) { - Message m = mHandler.obtainMessage(MSG_UPDATE_WAKELOCKS); - mHandler.sendMessageDelayed(m, DELAY_UPDATE_WAKELOCKS); - } + requestWakelockCpuUpdate(); getUidStatsLocked(uid).noteStartWakeLocked(pid, name, type, elapsedRealtime); } } @@ -2084,10 +2284,7 @@ public final class BatteryStatsImpl extends BatteryStats { } } if (uid >= 0) { - if (!mHandler.hasMessages(MSG_UPDATE_WAKELOCKS)) { - Message m = mHandler.obtainMessage(MSG_UPDATE_WAKELOCKS); - mHandler.sendMessageDelayed(m, DELAY_UPDATE_WAKELOCKS); - } + requestWakelockCpuUpdate(); getUidStatsLocked(uid).noteStopWakeLocked(pid, name, type, elapsedRealtime); } } @@ -2110,16 +2307,19 @@ public final class BatteryStatsImpl extends BatteryStats { public int startAddingCpuLocked() { mHandler.removeMessages(MSG_UPDATE_WAKELOCKS); - if (mScreenOn) { - return 0; - } - final int N = mPartialTimers.size(); if (N == 0) { mLastPartialTimers.clear(); + mDistributeWakelockCpu = false; return 0; } + if (!mOnBatteryScreenOffTimeBase.isRunning() && !mDistributeWakelockCpu) { + return 0; + } + + mDistributeWakelockCpu = false; + // How many timers should consume CPU? Only want to include ones // that have already been in the list. for (int i=0; i<N; i++) { @@ -2305,16 +2505,17 @@ public final class BatteryStatsImpl extends BatteryStats { + Integer.toHexString(mHistoryCur.states)); addHistoryRecordLocked(elapsedRealtime); mScreenOn = true; - mScreenOnTimer.startRunningLocked(this, elapsedRealtime); + mScreenOnTimer.startRunningLocked(elapsedRealtime); if (mScreenBrightnessBin >= 0) { - mScreenBrightnessTimer[mScreenBrightnessBin].startRunningLocked(this, - elapsedRealtime); + mScreenBrightnessTimer[mScreenBrightnessBin].startRunningLocked(elapsedRealtime); } + updateTimeBasesLocked(mOnBatteryTimeBase.isRunning(), false, + SystemClock.uptimeMillis() * 1000, elapsedRealtime * 1000); + // Fake a wake lock, so we consider the device waked as long // as the screen is on. - noteStartWakeLocked(Process.myUid(), Process.myPid(), "screen", null, - WAKE_TYPE_PARTIAL, false); + noteStartWakeLocked(-1, -1, "screen", null, WAKE_TYPE_PARTIAL, false); // Update discharge amounts. if (mOnBatteryInternal) { @@ -2331,14 +2532,16 @@ public final class BatteryStatsImpl extends BatteryStats { + Integer.toHexString(mHistoryCur.states)); addHistoryRecordLocked(elapsedRealtime); mScreenOn = false; - mScreenOnTimer.stopRunningLocked(this, elapsedRealtime); + mScreenOnTimer.stopRunningLocked(elapsedRealtime); if (mScreenBrightnessBin >= 0) { - mScreenBrightnessTimer[mScreenBrightnessBin].stopRunningLocked(this, - elapsedRealtime); + mScreenBrightnessTimer[mScreenBrightnessBin].stopRunningLocked(elapsedRealtime); } - noteStopWakeLocked(-1, -1, "dummy", WAKE_TYPE_PARTIAL); - + noteStopWakeLocked(-1, -1, "screen", WAKE_TYPE_PARTIAL); + + updateTimeBasesLocked(mOnBatteryTimeBase.isRunning(), true, + SystemClock.uptimeMillis() * 1000, elapsedRealtime * 1000); + // Update discharge amounts. if (mOnBatteryInternal) { updateDischargeScreenLevelsLocked(true, false); @@ -2360,10 +2563,9 @@ public final class BatteryStatsImpl extends BatteryStats { addHistoryRecordLocked(elapsedRealtime); if (mScreenOn) { if (mScreenBrightnessBin >= 0) { - mScreenBrightnessTimer[mScreenBrightnessBin].stopRunningLocked(this, - elapsedRealtime); + mScreenBrightnessTimer[mScreenBrightnessBin].stopRunningLocked(elapsedRealtime); } - mScreenBrightnessTimer[bin].startRunningLocked(this, elapsedRealtime); + mScreenBrightnessTimer[bin].startRunningLocked(elapsedRealtime); } mScreenBrightnessBin = bin; } @@ -2391,12 +2593,12 @@ public final class BatteryStatsImpl extends BatteryStats { addHistoryRecordLocked(elapsedRealtime); mMobileRadioActive = active; if (active) { - mMobileRadioActiveTimer.startRunningLocked(this, elapsedRealtime); - mMobileRadioActivePerAppTimer.startRunningLocked(this, elapsedRealtime); + mMobileRadioActiveTimer.startRunningLocked(elapsedRealtime); + mMobileRadioActivePerAppTimer.startRunningLocked(elapsedRealtime); } else { updateNetworkActivityLocked(NET_UPDATE_MOBILE, elapsedRealtime); - mMobileRadioActiveTimer.stopRunningLocked(this, elapsedRealtime); - mMobileRadioActivePerAppTimer.stopRunningLocked(this, elapsedRealtime); + mMobileRadioActiveTimer.stopRunningLocked(elapsedRealtime); + mMobileRadioActivePerAppTimer.stopRunningLocked(elapsedRealtime); } } } @@ -2410,7 +2612,7 @@ public final class BatteryStatsImpl extends BatteryStats { + Integer.toHexString(mHistoryCur.states)); addHistoryRecordLocked(elapsedRealtime); mPhoneOn = true; - mPhoneOnTimer.startRunningLocked(this, elapsedRealtime); + mPhoneOnTimer.startRunningLocked(elapsedRealtime); } } @@ -2422,7 +2624,7 @@ public final class BatteryStatsImpl extends BatteryStats { + Integer.toHexString(mHistoryCur.states)); addHistoryRecordLocked(elapsedRealtime); mPhoneOn = false; - mPhoneOnTimer.stopRunningLocked(this, elapsedRealtime); + mPhoneOnTimer.stopRunningLocked(elapsedRealtime); } } @@ -2433,7 +2635,7 @@ public final class BatteryStatsImpl extends BatteryStats { continue; } while (mPhoneSignalStrengthsTimer[i].isRunningLocked()) { - mPhoneSignalStrengthsTimer[i].stopRunningLocked(this, elapsedRealtime); + mPhoneSignalStrengthsTimer[i].stopRunningLocked(elapsedRealtime); } } } @@ -2488,7 +2690,7 @@ public final class BatteryStatsImpl extends BatteryStats { newHistory = true; if (DEBUG_HISTORY) Slog.v(TAG, "Phone started scanning to: " + Integer.toHexString(mHistoryCur.states)); - mPhoneSignalScanningTimer.startRunningLocked(this, elapsedRealtime); + mPhoneSignalScanningTimer.startRunningLocked(elapsedRealtime); } } @@ -2499,7 +2701,7 @@ public final class BatteryStatsImpl extends BatteryStats { if (DEBUG_HISTORY) Slog.v(TAG, "Phone stopped scanning to: " + Integer.toHexString(mHistoryCur.states)); newHistory = true; - mPhoneSignalScanningTimer.stopRunningLocked(this, elapsedRealtime); + mPhoneSignalScanningTimer.stopRunningLocked(elapsedRealtime); } } @@ -2514,13 +2716,12 @@ public final class BatteryStatsImpl extends BatteryStats { if (mPhoneSignalStrengthBin != strengthBin) { if (mPhoneSignalStrengthBin >= 0) { - mPhoneSignalStrengthsTimer[mPhoneSignalStrengthBin].stopRunningLocked(this, + mPhoneSignalStrengthsTimer[mPhoneSignalStrengthBin].stopRunningLocked( elapsedRealtime); } if (strengthBin >= 0) { if (!mPhoneSignalStrengthsTimer[strengthBin].isRunningLocked()) { - mPhoneSignalStrengthsTimer[strengthBin].startRunningLocked(this, - elapsedRealtime); + mPhoneSignalStrengthsTimer[strengthBin].startRunningLocked(elapsedRealtime); } mHistoryCur.states = (mHistoryCur.states&~HistoryItem.STATE_SIGNAL_STRENGTH_MASK) | (strengthBin << HistoryItem.STATE_SIGNAL_STRENGTH_SHIFT); @@ -2615,11 +2816,11 @@ public final class BatteryStatsImpl extends BatteryStats { + Integer.toHexString(mHistoryCur.states)); addHistoryRecordLocked(elapsedRealtime); if (mPhoneDataConnectionType >= 0) { - mPhoneDataConnectionsTimer[mPhoneDataConnectionType].stopRunningLocked(this, + mPhoneDataConnectionsTimer[mPhoneDataConnectionType].stopRunningLocked( elapsedRealtime); } mPhoneDataConnectionType = bin; - mPhoneDataConnectionsTimer[bin].startRunningLocked(this, elapsedRealtime); + mPhoneDataConnectionsTimer[bin].startRunningLocked(elapsedRealtime); } } @@ -2631,7 +2832,7 @@ public final class BatteryStatsImpl extends BatteryStats { + Integer.toHexString(mHistoryCur.states)); addHistoryRecordLocked(elapsedRealtime); mWifiOn = true; - mWifiOnTimer.startRunningLocked(this, elapsedRealtime); + mWifiOnTimer.startRunningLocked(elapsedRealtime); } } @@ -2643,7 +2844,7 @@ public final class BatteryStatsImpl extends BatteryStats { + Integer.toHexString(mHistoryCur.states)); addHistoryRecordLocked(elapsedRealtime); mWifiOn = false; - mWifiOnTimer.stopRunningLocked(this, elapsedRealtime); + mWifiOnTimer.stopRunningLocked(elapsedRealtime); } if (mWifiOnUid >= 0) { getUidStatsLocked(mWifiOnUid).noteWifiStoppedLocked(elapsedRealtime); @@ -2660,7 +2861,7 @@ public final class BatteryStatsImpl extends BatteryStats { + Integer.toHexString(mHistoryCur.states)); addHistoryRecordLocked(SystemClock.elapsedRealtime()); mAudioOn = true; - mAudioOnTimer.startRunningLocked(this, elapsedRealtime); + mAudioOnTimer.startRunningLocked(elapsedRealtime); } getUidStatsLocked(uid).noteAudioTurnedOnLocked(elapsedRealtime); } @@ -2674,7 +2875,7 @@ public final class BatteryStatsImpl extends BatteryStats { + Integer.toHexString(mHistoryCur.states)); addHistoryRecordLocked(SystemClock.elapsedRealtime()); mAudioOn = false; - mAudioOnTimer.stopRunningLocked(this, elapsedRealtime); + mAudioOnTimer.stopRunningLocked(elapsedRealtime); } getUidStatsLocked(uid).noteAudioTurnedOffLocked(elapsedRealtime); } @@ -2688,7 +2889,7 @@ public final class BatteryStatsImpl extends BatteryStats { + Integer.toHexString(mHistoryCur.states)); addHistoryRecordLocked(SystemClock.elapsedRealtime()); mVideoOn = true; - mVideoOnTimer.startRunningLocked(this, elapsedRealtime); + mVideoOnTimer.startRunningLocked(elapsedRealtime); } getUidStatsLocked(uid).noteVideoTurnedOnLocked(elapsedRealtime); } @@ -2702,7 +2903,7 @@ public final class BatteryStatsImpl extends BatteryStats { + Integer.toHexString(mHistoryCur.states)); addHistoryRecordLocked(SystemClock.elapsedRealtime()); mVideoOn = false; - mVideoOnTimer.stopRunningLocked(this, elapsedRealtime); + mVideoOnTimer.stopRunningLocked(elapsedRealtime); } getUidStatsLocked(uid).noteVideoTurnedOffLocked(elapsedRealtime); } @@ -2735,7 +2936,7 @@ public final class BatteryStatsImpl extends BatteryStats { + Integer.toHexString(mHistoryCur.states)); addHistoryRecordLocked(SystemClock.elapsedRealtime()); mGlobalWifiRunning = true; - mGlobalWifiRunningTimer.startRunningLocked(this, elapsedRealtime); + mGlobalWifiRunningTimer.startRunningLocked(elapsedRealtime); int N = ws.size(); for (int i=0; i<N; i++) { int uid = mapUid(ws.get(i)); @@ -2772,7 +2973,7 @@ public final class BatteryStatsImpl extends BatteryStats { + Integer.toHexString(mHistoryCur.states)); addHistoryRecordLocked(elapsedRealtime); mGlobalWifiRunning = false; - mGlobalWifiRunningTimer.stopRunningLocked(this, elapsedRealtime); + mGlobalWifiRunningTimer.stopRunningLocked(elapsedRealtime); int N = ws.size(); for (int i=0; i<N; i++) { int uid = mapUid(ws.get(i)); @@ -2788,10 +2989,10 @@ public final class BatteryStatsImpl extends BatteryStats { if (mWifiState != wifiState) { final long elapsedRealtime = SystemClock.elapsedRealtime(); if (mWifiState >= 0) { - mWifiStateTimer[mWifiState].stopRunningLocked(this, elapsedRealtime); + mWifiStateTimer[mWifiState].stopRunningLocked(elapsedRealtime); } mWifiState = wifiState; - mWifiStateTimer[wifiState].startRunningLocked(this, elapsedRealtime); + mWifiStateTimer[wifiState].startRunningLocked(elapsedRealtime); } } @@ -2803,7 +3004,7 @@ public final class BatteryStatsImpl extends BatteryStats { + Integer.toHexString(mHistoryCur.states)); addHistoryRecordLocked(elapsedRealtime); mBluetoothOn = true; - mBluetoothOnTimer.startRunningLocked(this, elapsedRealtime); + mBluetoothOnTimer.startRunningLocked(elapsedRealtime); } } @@ -2815,7 +3016,7 @@ public final class BatteryStatsImpl extends BatteryStats { + Integer.toHexString(mHistoryCur.states)); addHistoryRecordLocked(elapsedRealtime); mBluetoothOn = false; - mBluetoothOnTimer.stopRunningLocked(this, elapsedRealtime); + mBluetoothOnTimer.stopRunningLocked(elapsedRealtime); } } @@ -2824,11 +3025,10 @@ public final class BatteryStatsImpl extends BatteryStats { if (mBluetoothState != bluetoothState) { final long elapsedRealtime = SystemClock.elapsedRealtime(); if (mBluetoothState >= 0) { - mBluetoothStateTimer[mBluetoothState].stopRunningLocked(this, - elapsedRealtime); + mBluetoothStateTimer[mBluetoothState].stopRunningLocked(elapsedRealtime); } mBluetoothState = bluetoothState; - mBluetoothStateTimer[bluetoothState].startRunningLocked(this, elapsedRealtime); + mBluetoothStateTimer[bluetoothState].startRunningLocked(elapsedRealtime); } } @@ -3033,8 +3233,8 @@ public final class BatteryStatsImpl extends BatteryStats { updateNetworkActivityLocked(NET_UPDATE_ALL, SystemClock.elapsedRealtime()); } - @Override public long getScreenOnTime(long batteryRealtime, int which) { - return mScreenOnTimer.getTotalTimeLocked(batteryRealtime, which); + @Override public long getScreenOnTime(long elapsedRealtimeUs, int which) { + return mScreenOnTimer.getTotalTimeLocked(elapsedRealtimeUs, which); } @Override public int getScreenOnCount(int which) { @@ -3042,17 +3242,17 @@ public final class BatteryStatsImpl extends BatteryStats { } @Override public long getScreenBrightnessTime(int brightnessBin, - long batteryRealtime, int which) { + long elapsedRealtimeUs, int which) { return mScreenBrightnessTimer[brightnessBin].getTotalTimeLocked( - batteryRealtime, which); + elapsedRealtimeUs, which); } @Override public int getInputEventCount(int which) { return mInputEventCounter.getCountLocked(which); } - @Override public long getPhoneOnTime(long batteryRealtime, int which) { - return mPhoneOnTimer.getTotalTimeLocked(batteryRealtime, which); + @Override public long getPhoneOnTime(long elapsedRealtimeUs, int which) { + return mPhoneOnTimer.getTotalTimeLocked(elapsedRealtimeUs, which); } @Override public int getPhoneOnCount(int which) { @@ -3060,15 +3260,15 @@ public final class BatteryStatsImpl extends BatteryStats { } @Override public long getPhoneSignalStrengthTime(int strengthBin, - long batteryRealtime, int which) { + long elapsedRealtimeUs, int which) { return mPhoneSignalStrengthsTimer[strengthBin].getTotalTimeLocked( - batteryRealtime, which); + elapsedRealtimeUs, which); } @Override public long getPhoneSignalScanningTime( - long batteryRealtime, int which) { + long elapsedRealtimeUs, int which) { return mPhoneSignalScanningTimer.getTotalTimeLocked( - batteryRealtime, which); + elapsedRealtimeUs, which); } @Override public int getPhoneSignalStrengthCount(int strengthBin, int which) { @@ -3076,17 +3276,17 @@ public final class BatteryStatsImpl extends BatteryStats { } @Override public long getPhoneDataConnectionTime(int dataType, - long batteryRealtime, int which) { + long elapsedRealtimeUs, int which) { return mPhoneDataConnectionsTimer[dataType].getTotalTimeLocked( - batteryRealtime, which); + elapsedRealtimeUs, which); } @Override public int getPhoneDataConnectionCount(int dataType, int which) { return mPhoneDataConnectionsTimer[dataType].getCountLocked(which); } - @Override public long getMobileRadioActiveTime(long batteryRealtime, int which) { - return mMobileRadioActiveTimer.getTotalTimeLocked(batteryRealtime, which); + @Override public long getMobileRadioActiveTime(long elapsedRealtimeUs, int which) { + return mMobileRadioActiveTimer.getTotalTimeLocked(elapsedRealtimeUs, which); } @Override public int getMobileRadioActiveCount(int which) { @@ -3101,32 +3301,32 @@ public final class BatteryStatsImpl extends BatteryStats { return (int)mMobileRadioActiveUnknownCount.getCountLocked(which); } - @Override public long getWifiOnTime(long batteryRealtime, int which) { - return mWifiOnTimer.getTotalTimeLocked(batteryRealtime, which); + @Override public long getWifiOnTime(long elapsedRealtimeUs, int which) { + return mWifiOnTimer.getTotalTimeLocked(elapsedRealtimeUs, which); } - @Override public long getGlobalWifiRunningTime(long batteryRealtime, int which) { - return mGlobalWifiRunningTimer.getTotalTimeLocked(batteryRealtime, which); + @Override public long getGlobalWifiRunningTime(long elapsedRealtimeUs, int which) { + return mGlobalWifiRunningTimer.getTotalTimeLocked(elapsedRealtimeUs, which); } @Override public long getWifiStateTime(int wifiState, - long batteryRealtime, int which) { + long elapsedRealtimeUs, int which) { return mWifiStateTimer[wifiState].getTotalTimeLocked( - batteryRealtime, which); + elapsedRealtimeUs, which); } @Override public int getWifiStateCount(int wifiState, int which) { return mWifiStateTimer[wifiState].getCountLocked(which); } - @Override public long getBluetoothOnTime(long batteryRealtime, int which) { - return mBluetoothOnTimer.getTotalTimeLocked(batteryRealtime, which); + @Override public long getBluetoothOnTime(long elapsedRealtimeUs, int which) { + return mBluetoothOnTimer.getTotalTimeLocked(elapsedRealtimeUs, which); } @Override public long getBluetoothStateTime(int bluetoothState, - long batteryRealtime, int which) { + long elapsedRealtimeUs, int which) { return mBluetoothStateTimer[bluetoothState].getTotalTimeLocked( - batteryRealtime, which); + elapsedRealtimeUs, which); } @Override public int getBluetoothStateCount(int bluetoothState, int which) { @@ -3231,14 +3431,14 @@ public final class BatteryStatsImpl extends BatteryStats { public Uid(int uid) { mUid = uid; mWifiRunningTimer = new StopwatchTimer(Uid.this, WIFI_RUNNING, - mWifiRunningTimers, mUnpluggables); + mWifiRunningTimers, mOnBatteryTimeBase); mFullWifiLockTimer = new StopwatchTimer(Uid.this, FULL_WIFI_LOCK, - mFullWifiLockTimers, mUnpluggables); + mFullWifiLockTimers, mOnBatteryTimeBase); mWifiScanTimer = new StopwatchTimer(Uid.this, WIFI_SCAN, - mWifiScanTimers, mUnpluggables); + mWifiScanTimers, mOnBatteryTimeBase); mWifiBatchedScanTimer = new StopwatchTimer[NUM_WIFI_BATCHED_SCAN_BINS]; mWifiMulticastTimer = new StopwatchTimer(Uid.this, WIFI_MULTICAST_ENABLED, - mWifiMulticastTimers, mUnpluggables); + mWifiMulticastTimers, mOnBatteryTimeBase); } @Override @@ -3267,67 +3467,67 @@ public final class BatteryStatsImpl extends BatteryStats { } @Override - public void noteWifiRunningLocked(long elapsedRealtime) { + public void noteWifiRunningLocked(long elapsedRealtimeMs) { if (!mWifiRunning) { mWifiRunning = true; if (mWifiRunningTimer == null) { mWifiRunningTimer = new StopwatchTimer(Uid.this, WIFI_RUNNING, - mWifiRunningTimers, mUnpluggables); + mWifiRunningTimers, mOnBatteryTimeBase); } - mWifiRunningTimer.startRunningLocked(BatteryStatsImpl.this, elapsedRealtime); + mWifiRunningTimer.startRunningLocked(elapsedRealtimeMs); } } @Override - public void noteWifiStoppedLocked(long elapsedRealtime) { + public void noteWifiStoppedLocked(long elapsedRealtimeMs) { if (mWifiRunning) { mWifiRunning = false; - mWifiRunningTimer.stopRunningLocked(BatteryStatsImpl.this, elapsedRealtime); + mWifiRunningTimer.stopRunningLocked(elapsedRealtimeMs); } } @Override - public void noteFullWifiLockAcquiredLocked(long elapsedRealtime) { + public void noteFullWifiLockAcquiredLocked(long elapsedRealtimeMs) { if (!mFullWifiLockOut) { mFullWifiLockOut = true; if (mFullWifiLockTimer == null) { mFullWifiLockTimer = new StopwatchTimer(Uid.this, FULL_WIFI_LOCK, - mFullWifiLockTimers, mUnpluggables); + mFullWifiLockTimers, mOnBatteryTimeBase); } - mFullWifiLockTimer.startRunningLocked(BatteryStatsImpl.this, elapsedRealtime); + mFullWifiLockTimer.startRunningLocked(elapsedRealtimeMs); } } @Override - public void noteFullWifiLockReleasedLocked(long elapsedRealtime) { + public void noteFullWifiLockReleasedLocked(long elapsedRealtimeMs) { if (mFullWifiLockOut) { mFullWifiLockOut = false; - mFullWifiLockTimer.stopRunningLocked(BatteryStatsImpl.this, elapsedRealtime); + mFullWifiLockTimer.stopRunningLocked(elapsedRealtimeMs); } } @Override - public void noteWifiScanStartedLocked(long elapsedRealtime) { + public void noteWifiScanStartedLocked(long elapsedRealtimeMs) { if (!mWifiScanStarted) { mWifiScanStarted = true; if (mWifiScanTimer == null) { mWifiScanTimer = new StopwatchTimer(Uid.this, WIFI_SCAN, - mWifiScanTimers, mUnpluggables); + mWifiScanTimers, mOnBatteryTimeBase); } - mWifiScanTimer.startRunningLocked(BatteryStatsImpl.this, elapsedRealtime); + mWifiScanTimer.startRunningLocked(elapsedRealtimeMs); } } @Override - public void noteWifiScanStoppedLocked(long elapsedRealtime) { + public void noteWifiScanStoppedLocked(long elapsedRealtimeMs) { if (mWifiScanStarted) { mWifiScanStarted = false; - mWifiScanTimer.stopRunningLocked(BatteryStatsImpl.this, elapsedRealtime); + mWifiScanTimer.stopRunningLocked(elapsedRealtimeMs); } } @Override - public void noteWifiBatchedScanStartedLocked(int csph, long elapsedRealtime) { + public void noteWifiBatchedScanStartedLocked(int csph, long elapsedRealtimeMs) { int bin = 0; while (csph > 8 && bin < NUM_WIFI_BATCHED_SCAN_BINS) { csph = csph >> 3; @@ -3338,67 +3538,66 @@ public final class BatteryStatsImpl extends BatteryStats { if (mWifiBatchedScanBinStarted != NO_BATCHED_SCAN_STARTED) { mWifiBatchedScanTimer[mWifiBatchedScanBinStarted]. - stopRunningLocked(BatteryStatsImpl.this, elapsedRealtime); + stopRunningLocked(elapsedRealtimeMs); } mWifiBatchedScanBinStarted = bin; if (mWifiBatchedScanTimer[bin] == null) { makeWifiBatchedScanBin(bin, null); } - mWifiBatchedScanTimer[bin].startRunningLocked(BatteryStatsImpl.this, elapsedRealtime); + mWifiBatchedScanTimer[bin].startRunningLocked(elapsedRealtimeMs); } @Override - public void noteWifiBatchedScanStoppedLocked(long elapsedRealtime) { + public void noteWifiBatchedScanStoppedLocked(long elapsedRealtimeMs) { if (mWifiBatchedScanBinStarted != NO_BATCHED_SCAN_STARTED) { mWifiBatchedScanTimer[mWifiBatchedScanBinStarted]. - stopRunningLocked(BatteryStatsImpl.this, elapsedRealtime); + stopRunningLocked(elapsedRealtimeMs); mWifiBatchedScanBinStarted = NO_BATCHED_SCAN_STARTED; } } @Override - public void noteWifiMulticastEnabledLocked(long elapsedRealtime) { + public void noteWifiMulticastEnabledLocked(long elapsedRealtimeMs) { if (!mWifiMulticastEnabled) { mWifiMulticastEnabled = true; if (mWifiMulticastTimer == null) { mWifiMulticastTimer = new StopwatchTimer(Uid.this, WIFI_MULTICAST_ENABLED, - mWifiMulticastTimers, mUnpluggables); + mWifiMulticastTimers, mOnBatteryTimeBase); } - mWifiMulticastTimer.startRunningLocked(BatteryStatsImpl.this, elapsedRealtime); + mWifiMulticastTimer.startRunningLocked(elapsedRealtimeMs); } } @Override - public void noteWifiMulticastDisabledLocked(long elapsedRealtime) { + public void noteWifiMulticastDisabledLocked(long elapsedRealtimeMs) { if (mWifiMulticastEnabled) { mWifiMulticastEnabled = false; - mWifiMulticastTimer.stopRunningLocked(BatteryStatsImpl.this, elapsedRealtime); + mWifiMulticastTimer.stopRunningLocked(elapsedRealtimeMs); } } public StopwatchTimer createAudioTurnedOnTimerLocked() { if (mAudioTurnedOnTimer == null) { mAudioTurnedOnTimer = new StopwatchTimer(Uid.this, AUDIO_TURNED_ON, - null, mUnpluggables); + null, mOnBatteryTimeBase); } return mAudioTurnedOnTimer; } @Override - public void noteAudioTurnedOnLocked(long elapsedRealtime) { + public void noteAudioTurnedOnLocked(long elapsedRealtimeMs) { if (!mAudioTurnedOn) { mAudioTurnedOn = true; - createAudioTurnedOnTimerLocked().startRunningLocked(BatteryStatsImpl.this, - elapsedRealtime); + createAudioTurnedOnTimerLocked().startRunningLocked(elapsedRealtimeMs); } } @Override - public void noteAudioTurnedOffLocked(long elapsedRealtime) { + public void noteAudioTurnedOffLocked(long elapsedRealtimeMs) { if (mAudioTurnedOn) { mAudioTurnedOn = false; if (mAudioTurnedOnTimer != null) { - mAudioTurnedOnTimer.stopRunningLocked(BatteryStatsImpl.this, elapsedRealtime); + mAudioTurnedOnTimer.stopRunningLocked(elapsedRealtimeMs); } } } @@ -3406,26 +3605,25 @@ public final class BatteryStatsImpl extends BatteryStats { public StopwatchTimer createVideoTurnedOnTimerLocked() { if (mVideoTurnedOnTimer == null) { mVideoTurnedOnTimer = new StopwatchTimer(Uid.this, VIDEO_TURNED_ON, - null, mUnpluggables); + null, mOnBatteryTimeBase); } return mVideoTurnedOnTimer; } @Override - public void noteVideoTurnedOnLocked(long elapsedRealtime) { + public void noteVideoTurnedOnLocked(long elapsedRealtimeMs) { if (!mVideoTurnedOn) { mVideoTurnedOn = true; - createVideoTurnedOnTimerLocked().startRunningLocked(BatteryStatsImpl.this, - elapsedRealtime); + createVideoTurnedOnTimerLocked().startRunningLocked(elapsedRealtimeMs); } } @Override - public void noteVideoTurnedOffLocked(long elapsedRealtime) { + public void noteVideoTurnedOffLocked(long elapsedRealtimeMs) { if (mVideoTurnedOn) { mVideoTurnedOn = false; if (mVideoTurnedOnTimer != null) { - mVideoTurnedOnTimer.stopRunningLocked(BatteryStatsImpl.this, elapsedRealtime); + mVideoTurnedOnTimer.stopRunningLocked(elapsedRealtimeMs); } } } @@ -3433,29 +3631,27 @@ public final class BatteryStatsImpl extends BatteryStats { public StopwatchTimer createForegroundActivityTimerLocked() { if (mForegroundActivityTimer == null) { mForegroundActivityTimer = new StopwatchTimer( - Uid.this, FOREGROUND_ACTIVITY, null, mUnpluggables); + Uid.this, FOREGROUND_ACTIVITY, null, mOnBatteryTimeBase); } return mForegroundActivityTimer; } @Override - public void noteActivityResumedLocked(long elapsedRealtime) { + public void noteActivityResumedLocked(long elapsedRealtimeMs) { // We always start, since we want multiple foreground PIDs to nest - createForegroundActivityTimerLocked().startRunningLocked(BatteryStatsImpl.this, - elapsedRealtime); + createForegroundActivityTimerLocked().startRunningLocked(elapsedRealtimeMs); } @Override - public void noteActivityPausedLocked(long elapsedRealtime) { + public void noteActivityPausedLocked(long elapsedRealtimeMs) { if (mForegroundActivityTimer != null) { - mForegroundActivityTimer.stopRunningLocked(BatteryStatsImpl.this, elapsedRealtime); + mForegroundActivityTimer.stopRunningLocked(elapsedRealtimeMs); } } public BatchTimer createVibratorOnTimerLocked() { if (mVibratorOnTimer == null) { - mVibratorOnTimer = new BatchTimer(Uid.this, VIBRATOR_ON, - mUnpluggables, BatteryStatsImpl.this.mOnBatteryInternal); + mVibratorOnTimer = new BatchTimer(Uid.this, VIBRATOR_ON, mOnBatteryTimeBase); } return mVibratorOnTimer; } @@ -3471,61 +3667,60 @@ public final class BatteryStatsImpl extends BatteryStats { } @Override - public long getWifiRunningTime(long batteryRealtime, int which) { + public long getWifiRunningTime(long elapsedRealtimeUs, int which) { if (mWifiRunningTimer == null) { return 0; } - return mWifiRunningTimer.getTotalTimeLocked(batteryRealtime, which); + return mWifiRunningTimer.getTotalTimeLocked(elapsedRealtimeUs, which); } @Override - public long getFullWifiLockTime(long batteryRealtime, int which) { + public long getFullWifiLockTime(long elapsedRealtimeUs, int which) { if (mFullWifiLockTimer == null) { return 0; } - return mFullWifiLockTimer.getTotalTimeLocked(batteryRealtime, which); + return mFullWifiLockTimer.getTotalTimeLocked(elapsedRealtimeUs, which); } @Override - public long getWifiScanTime(long batteryRealtime, int which) { + public long getWifiScanTime(long elapsedRealtimeUs, int which) { if (mWifiScanTimer == null) { return 0; } - return mWifiScanTimer.getTotalTimeLocked(batteryRealtime, which); + return mWifiScanTimer.getTotalTimeLocked(elapsedRealtimeUs, which); } @Override - public long getWifiBatchedScanTime(int csphBin, long batteryRealtime, int which) { + public long getWifiBatchedScanTime(int csphBin, long elapsedRealtimeUs, int which) { if (csphBin < 0 || csphBin >= NUM_WIFI_BATCHED_SCAN_BINS) return 0; if (mWifiBatchedScanTimer[csphBin] == null) { return 0; } - return mWifiBatchedScanTimer[csphBin].getTotalTimeLocked(batteryRealtime, which); + return mWifiBatchedScanTimer[csphBin].getTotalTimeLocked(elapsedRealtimeUs, which); } @Override - public long getWifiMulticastTime(long batteryRealtime, int which) { + public long getWifiMulticastTime(long elapsedRealtimeUs, int which) { if (mWifiMulticastTimer == null) { return 0; } - return mWifiMulticastTimer.getTotalTimeLocked(batteryRealtime, - which); + return mWifiMulticastTimer.getTotalTimeLocked(elapsedRealtimeUs, which); } @Override - public long getAudioTurnedOnTime(long batteryRealtime, int which) { + public long getAudioTurnedOnTime(long elapsedRealtimeUs, int which) { if (mAudioTurnedOnTimer == null) { return 0; } - return mAudioTurnedOnTimer.getTotalTimeLocked(batteryRealtime, which); + return mAudioTurnedOnTimer.getTotalTimeLocked(elapsedRealtimeUs, which); } @Override - public long getVideoTurnedOnTime(long batteryRealtime, int which) { + public long getVideoTurnedOnTime(long elapsedRealtimeUs, int which) { if (mVideoTurnedOnTimer == null) { return 0; } - return mVideoTurnedOnTimer.getTotalTimeLocked(batteryRealtime, which); + return mVideoTurnedOnTimer.getTotalTimeLocked(elapsedRealtimeUs, which); } @Override @@ -3574,10 +3769,10 @@ public final class BatteryStatsImpl extends BatteryStats { } if (in == null) { mWifiBatchedScanTimer[i] = new StopwatchTimer(this, WIFI_BATCHED_SCAN, collected, - mUnpluggables); + mOnBatteryTimeBase); } else { mWifiBatchedScanTimer[i] = new StopwatchTimer(this, WIFI_BATCHED_SCAN, collected, - mUnpluggables, in); + mOnBatteryTimeBase, in); } } @@ -3585,7 +3780,7 @@ public final class BatteryStatsImpl extends BatteryStats { void initUserActivityLocked() { mUserActivityCounters = new Counter[NUM_USER_ACTIVITY_TYPES]; for (int i=0; i<NUM_USER_ACTIVITY_TYPES; i++) { - mUserActivityCounters[i] = new Counter(mUnpluggables); + mUserActivityCounters[i] = new Counter(mOnBatteryTimeBase); } } @@ -3651,11 +3846,11 @@ public final class BatteryStatsImpl extends BatteryStats { mNetworkByteActivityCounters = new LongSamplingCounter[NUM_NETWORK_ACTIVITY_TYPES]; mNetworkPacketActivityCounters = new LongSamplingCounter[NUM_NETWORK_ACTIVITY_TYPES]; for (int i = 0; i < NUM_NETWORK_ACTIVITY_TYPES; i++) { - mNetworkByteActivityCounters[i] = new LongSamplingCounter(mUnpluggables); - mNetworkPacketActivityCounters[i] = new LongSamplingCounter(mUnpluggables); + mNetworkByteActivityCounters[i] = new LongSamplingCounter(mOnBatteryTimeBase); + mNetworkPacketActivityCounters[i] = new LongSamplingCounter(mOnBatteryTimeBase); } - mMobileRadioActiveTime = new LongSamplingCounter(mUnpluggables); - mMobileRadioActiveCount = new LongSamplingCounter(mUnpluggables); + mMobileRadioActiveTime = new LongSamplingCounter(mOnBatteryTimeBase); + mMobileRadioActiveCount = new LongSamplingCounter(mOnBatteryTimeBase); } /** @@ -3666,42 +3861,42 @@ public final class BatteryStatsImpl extends BatteryStats { boolean active = false; if (mWifiRunningTimer != null) { - active |= !mWifiRunningTimer.reset(BatteryStatsImpl.this, false); + active |= !mWifiRunningTimer.reset(false); active |= mWifiRunning; } if (mFullWifiLockTimer != null) { - active |= !mFullWifiLockTimer.reset(BatteryStatsImpl.this, false); + active |= !mFullWifiLockTimer.reset(false); active |= mFullWifiLockOut; } if (mWifiScanTimer != null) { - active |= !mWifiScanTimer.reset(BatteryStatsImpl.this, false); + active |= !mWifiScanTimer.reset(false); active |= mWifiScanStarted; } if (mWifiBatchedScanTimer != null) { for (int i = 0; i < NUM_WIFI_BATCHED_SCAN_BINS; i++) { if (mWifiBatchedScanTimer[i] != null) { - active |= !mWifiBatchedScanTimer[i].reset(BatteryStatsImpl.this, false); + active |= !mWifiBatchedScanTimer[i].reset(false); } } active |= (mWifiBatchedScanBinStarted != NO_BATCHED_SCAN_STARTED); } if (mWifiMulticastTimer != null) { - active |= !mWifiMulticastTimer.reset(BatteryStatsImpl.this, false); + active |= !mWifiMulticastTimer.reset(false); active |= mWifiMulticastEnabled; } if (mAudioTurnedOnTimer != null) { - active |= !mAudioTurnedOnTimer.reset(BatteryStatsImpl.this, false); + active |= !mAudioTurnedOnTimer.reset(false); active |= mAudioTurnedOn; } if (mVideoTurnedOnTimer != null) { - active |= !mVideoTurnedOnTimer.reset(BatteryStatsImpl.this, false); + active |= !mVideoTurnedOnTimer.reset(false); active |= mVideoTurnedOn; } if (mForegroundActivityTimer != null) { - active |= !mForegroundActivityTimer.reset(BatteryStatsImpl.this, false); + active |= !mForegroundActivityTimer.reset(false); } if (mVibratorOnTimer != null) { - if (mVibratorOnTimer.reset(BatteryStatsImpl.this, false)) { + if (mVibratorOnTimer.reset(false)) { mVibratorOnTimer.detach(); mVibratorOnTimer = null; } else { @@ -3830,19 +4025,19 @@ public final class BatteryStatsImpl extends BatteryStats { return !active; } - void writeToParcelLocked(Parcel out, long batteryRealtime) { + void writeToParcelLocked(Parcel out, long elapsedRealtimeUs) { out.writeInt(mWakelockStats.size()); for (Map.Entry<String, Uid.Wakelock> wakelockEntry : mWakelockStats.entrySet()) { out.writeString(wakelockEntry.getKey()); Uid.Wakelock wakelock = wakelockEntry.getValue(); - wakelock.writeToParcelLocked(out, batteryRealtime); + wakelock.writeToParcelLocked(out, elapsedRealtimeUs); } out.writeInt(mSensorStats.size()); for (Map.Entry<Integer, Uid.Sensor> sensorEntry : mSensorStats.entrySet()) { out.writeInt(sensorEntry.getKey()); Uid.Sensor sensor = sensorEntry.getValue(); - sensor.writeToParcelLocked(out, batteryRealtime); + sensor.writeToParcelLocked(out, elapsedRealtimeUs); } out.writeInt(mProcessStats.size()); @@ -3861,57 +4056,57 @@ public final class BatteryStatsImpl extends BatteryStats { if (mWifiRunningTimer != null) { out.writeInt(1); - mWifiRunningTimer.writeToParcel(out, batteryRealtime); + mWifiRunningTimer.writeToParcel(out, elapsedRealtimeUs); } else { out.writeInt(0); } if (mFullWifiLockTimer != null) { out.writeInt(1); - mFullWifiLockTimer.writeToParcel(out, batteryRealtime); + mFullWifiLockTimer.writeToParcel(out, elapsedRealtimeUs); } else { out.writeInt(0); } if (mWifiScanTimer != null) { out.writeInt(1); - mWifiScanTimer.writeToParcel(out, batteryRealtime); + mWifiScanTimer.writeToParcel(out, elapsedRealtimeUs); } else { out.writeInt(0); } for (int i = 0; i < NUM_WIFI_BATCHED_SCAN_BINS; i++) { if (mWifiBatchedScanTimer[i] != null) { out.writeInt(1); - mWifiBatchedScanTimer[i].writeToParcel(out, batteryRealtime); + mWifiBatchedScanTimer[i].writeToParcel(out, elapsedRealtimeUs); } else { out.writeInt(0); } } if (mWifiMulticastTimer != null) { out.writeInt(1); - mWifiMulticastTimer.writeToParcel(out, batteryRealtime); + mWifiMulticastTimer.writeToParcel(out, elapsedRealtimeUs); } else { out.writeInt(0); } if (mAudioTurnedOnTimer != null) { out.writeInt(1); - mAudioTurnedOnTimer.writeToParcel(out, batteryRealtime); + mAudioTurnedOnTimer.writeToParcel(out, elapsedRealtimeUs); } else { out.writeInt(0); } if (mVideoTurnedOnTimer != null) { out.writeInt(1); - mVideoTurnedOnTimer.writeToParcel(out, batteryRealtime); + mVideoTurnedOnTimer.writeToParcel(out, elapsedRealtimeUs); } else { out.writeInt(0); } if (mForegroundActivityTimer != null) { out.writeInt(1); - mForegroundActivityTimer.writeToParcel(out, batteryRealtime); + mForegroundActivityTimer.writeToParcel(out, elapsedRealtimeUs); } else { out.writeInt(0); } if (mVibratorOnTimer != null) { out.writeInt(1); - mVibratorOnTimer.writeToParcel(out, batteryRealtime); + mVibratorOnTimer.writeToParcel(out, elapsedRealtimeUs); } else { out.writeInt(0); } @@ -3936,13 +4131,13 @@ public final class BatteryStatsImpl extends BatteryStats { } } - void readFromParcelLocked(ArrayList<Unpluggable> unpluggables, Parcel in) { + void readFromParcelLocked(TimeBase timeBase, TimeBase screenOffTimeBase, Parcel in) { int numWakelocks = in.readInt(); mWakelockStats.clear(); for (int j = 0; j < numWakelocks; j++) { String wakelockName = in.readString(); Uid.Wakelock wakelock = new Wakelock(); - wakelock.readFromParcelLocked(unpluggables, in); + wakelock.readFromParcelLocked(timeBase, screenOffTimeBase, in); // We will just drop some random set of wakelocks if // the previous run of the system was an older version // that didn't impose a limit. @@ -3954,7 +4149,7 @@ public final class BatteryStatsImpl extends BatteryStats { for (int k = 0; k < numSensors; k++) { int sensorNumber = in.readInt(); Uid.Sensor sensor = new Sensor(sensorNumber); - sensor.readFromParcelLocked(mUnpluggables, in); + sensor.readFromParcelLocked(mOnBatteryTimeBase, in); mSensorStats.put(sensorNumber, sensor); } @@ -3979,21 +4174,21 @@ public final class BatteryStatsImpl extends BatteryStats { mWifiRunning = false; if (in.readInt() != 0) { mWifiRunningTimer = new StopwatchTimer(Uid.this, WIFI_RUNNING, - mWifiRunningTimers, mUnpluggables, in); + mWifiRunningTimers, mOnBatteryTimeBase, in); } else { mWifiRunningTimer = null; } mFullWifiLockOut = false; if (in.readInt() != 0) { mFullWifiLockTimer = new StopwatchTimer(Uid.this, FULL_WIFI_LOCK, - mFullWifiLockTimers, mUnpluggables, in); + mFullWifiLockTimers, mOnBatteryTimeBase, in); } else { mFullWifiLockTimer = null; } mWifiScanStarted = false; if (in.readInt() != 0) { mWifiScanTimer = new StopwatchTimer(Uid.this, WIFI_SCAN, - mWifiScanTimers, mUnpluggables, in); + mWifiScanTimers, mOnBatteryTimeBase, in); } else { mWifiScanTimer = null; } @@ -4008,40 +4203,39 @@ public final class BatteryStatsImpl extends BatteryStats { mWifiMulticastEnabled = false; if (in.readInt() != 0) { mWifiMulticastTimer = new StopwatchTimer(Uid.this, WIFI_MULTICAST_ENABLED, - mWifiMulticastTimers, mUnpluggables, in); + mWifiMulticastTimers, mOnBatteryTimeBase, in); } else { mWifiMulticastTimer = null; } mAudioTurnedOn = false; if (in.readInt() != 0) { mAudioTurnedOnTimer = new StopwatchTimer(Uid.this, AUDIO_TURNED_ON, - null, mUnpluggables, in); + null, mOnBatteryTimeBase, in); } else { mAudioTurnedOnTimer = null; } mVideoTurnedOn = false; if (in.readInt() != 0) { mVideoTurnedOnTimer = new StopwatchTimer(Uid.this, VIDEO_TURNED_ON, - null, mUnpluggables, in); + null, mOnBatteryTimeBase, in); } else { mVideoTurnedOnTimer = null; } if (in.readInt() != 0) { mForegroundActivityTimer = new StopwatchTimer( - Uid.this, FOREGROUND_ACTIVITY, null, mUnpluggables, in); + Uid.this, FOREGROUND_ACTIVITY, null, mOnBatteryTimeBase, in); } else { mForegroundActivityTimer = null; } if (in.readInt() != 0) { - mVibratorOnTimer = new BatchTimer(Uid.this, VIBRATOR_ON, - mUnpluggables, BatteryStatsImpl.this.mOnBatteryInternal, in); + mVibratorOnTimer = new BatchTimer(Uid.this, VIBRATOR_ON, mOnBatteryTimeBase, in); } else { mVibratorOnTimer = null; } if (in.readInt() != 0) { mUserActivityCounters = new Counter[NUM_USER_ACTIVITY_TYPES]; for (int i=0; i<NUM_USER_ACTIVITY_TYPES; i++) { - mUserActivityCounters[i] = new Counter(mUnpluggables, in); + mUserActivityCounters[i] = new Counter(mOnBatteryTimeBase, in); } } else { mUserActivityCounters = null; @@ -4051,11 +4245,13 @@ public final class BatteryStatsImpl extends BatteryStats { mNetworkPacketActivityCounters = new LongSamplingCounter[NUM_NETWORK_ACTIVITY_TYPES]; for (int i = 0; i < NUM_NETWORK_ACTIVITY_TYPES; i++) { - mNetworkByteActivityCounters[i] = new LongSamplingCounter(mUnpluggables, in); - mNetworkPacketActivityCounters[i] = new LongSamplingCounter(mUnpluggables, in); + mNetworkByteActivityCounters[i] + = new LongSamplingCounter(mOnBatteryTimeBase, in); + mNetworkPacketActivityCounters[i] + = new LongSamplingCounter(mOnBatteryTimeBase, in); } - mMobileRadioActiveTime = new LongSamplingCounter(mUnpluggables, in); - mMobileRadioActiveCount = new LongSamplingCounter(mUnpluggables, in); + mMobileRadioActiveTime = new LongSamplingCounter(mOnBatteryTimeBase, in); + mMobileRadioActiveCount = new LongSamplingCounter(mOnBatteryTimeBase, in); } else { mNetworkByteActivityCounters = null; mNetworkPacketActivityCounters = null; @@ -4089,24 +4285,24 @@ public final class BatteryStatsImpl extends BatteryStats { * return a new Timer, or null. */ private StopwatchTimer readTimerFromParcel(int type, ArrayList<StopwatchTimer> pool, - ArrayList<Unpluggable> unpluggables, Parcel in) { + TimeBase timeBase, Parcel in) { if (in.readInt() == 0) { return null; } - return new StopwatchTimer(Uid.this, type, pool, unpluggables, in); + return new StopwatchTimer(Uid.this, type, pool, timeBase, in); } boolean reset() { boolean wlactive = false; if (mTimerFull != null) { - wlactive |= !mTimerFull.reset(BatteryStatsImpl.this, false); + wlactive |= !mTimerFull.reset(false); } if (mTimerPartial != null) { - wlactive |= !mTimerPartial.reset(BatteryStatsImpl.this, false); + wlactive |= !mTimerPartial.reset(false); } if (mTimerWindow != null) { - wlactive |= !mTimerWindow.reset(BatteryStatsImpl.this, false); + wlactive |= !mTimerWindow.reset(false); } if (!wlactive) { if (mTimerFull != null) { @@ -4125,19 +4321,19 @@ public final class BatteryStatsImpl extends BatteryStats { return !wlactive; } - void readFromParcelLocked(ArrayList<Unpluggable> unpluggables, Parcel in) { + void readFromParcelLocked(TimeBase timeBase, TimeBase screenOffTimeBase, Parcel in) { mTimerPartial = readTimerFromParcel(WAKE_TYPE_PARTIAL, - mPartialTimers, unpluggables, in); + mPartialTimers, screenOffTimeBase, in); mTimerFull = readTimerFromParcel(WAKE_TYPE_FULL, - mFullTimers, unpluggables, in); + mFullTimers, timeBase, in); mTimerWindow = readTimerFromParcel(WAKE_TYPE_WINDOW, - mWindowTimers, unpluggables, in); + mWindowTimers, timeBase, in); } - void writeToParcelLocked(Parcel out, long batteryRealtime) { - Timer.writeTimerToParcel(out, mTimerPartial, batteryRealtime); - Timer.writeTimerToParcel(out, mTimerFull, batteryRealtime); - Timer.writeTimerToParcel(out, mTimerWindow, batteryRealtime); + void writeToParcelLocked(Parcel out, long elapsedRealtimeUs) { + Timer.writeTimerToParcel(out, mTimerPartial, elapsedRealtimeUs); + Timer.writeTimerToParcel(out, mTimerFull, elapsedRealtimeUs); + Timer.writeTimerToParcel(out, mTimerWindow, elapsedRealtimeUs); } @Override @@ -4159,8 +4355,7 @@ public final class BatteryStatsImpl extends BatteryStats { mHandle = handle; } - private StopwatchTimer readTimerFromParcel(ArrayList<Unpluggable> unpluggables, - Parcel in) { + private StopwatchTimer readTimerFromParcel(TimeBase timeBase, Parcel in) { if (in.readInt() == 0) { return null; } @@ -4170,23 +4365,23 @@ public final class BatteryStatsImpl extends BatteryStats { pool = new ArrayList<StopwatchTimer>(); mSensorTimers.put(mHandle, pool); } - return new StopwatchTimer(Uid.this, 0, pool, unpluggables, in); + return new StopwatchTimer(Uid.this, 0, pool, timeBase, in); } boolean reset() { - if (mTimer.reset(BatteryStatsImpl.this, true)) { + if (mTimer.reset(true)) { mTimer = null; return true; } return false; } - void readFromParcelLocked(ArrayList<Unpluggable> unpluggables, Parcel in) { - mTimer = readTimerFromParcel(unpluggables, in); + void readFromParcelLocked(TimeBase timeBase, Parcel in) { + mTimer = readTimerFromParcel(timeBase, in); } - void writeToParcelLocked(Parcel out, long batteryRealtime) { - Timer.writeTimerToParcel(out, mTimer, batteryRealtime); + void writeToParcelLocked(Parcel out, long elapsedRealtimeUs) { + Timer.writeTimerToParcel(out, mTimer, elapsedRealtimeUs); } @Override @@ -4203,7 +4398,7 @@ public final class BatteryStatsImpl extends BatteryStats { /** * The statistics associated with a particular process. */ - public final class Proc extends BatteryStats.Uid.Proc implements Unpluggable { + public final class Proc extends BatteryStats.Uid.Proc implements TimeBaseObs { /** * Remains true until removed from the stats. */ @@ -4294,27 +4489,27 @@ public final class BatteryStatsImpl extends BatteryStats { ArrayList<ExcessivePower> mExcessivePower; Proc() { - mUnpluggables.add(this); + mOnBatteryTimeBase.add(this); mSpeedBins = new SamplingCounter[getCpuSpeedSteps()]; } - public void unplug(long elapsedRealtime, long batteryUptime, long batteryRealtime) { + public void onTimeStarted(long elapsedRealtime, long baseUptime, long baseRealtime) { mUnpluggedUserTime = mUserTime; mUnpluggedSystemTime = mSystemTime; mUnpluggedForegroundTime = mForegroundTime; mUnpluggedStarts = mStarts; } - public void plug(long elapsedRealtime, long batteryUptime, long batteryRealtime) { + public void onTimeStopped(long elapsedRealtime, long baseUptime, long baseRealtime) { } void detach() { mActive = false; - mUnpluggables.remove(this); + mOnBatteryTimeBase.remove(this); for (int i = 0; i < mSpeedBins.length; i++) { SamplingCounter c = mSpeedBins[i]; if (c != null) { - mUnpluggables.remove(c); + mOnBatteryTimeBase.remove(c); mSpeedBins[i] = null; } } @@ -4443,7 +4638,7 @@ public final class BatteryStatsImpl extends BatteryStats { mSpeedBins = new SamplingCounter[bins >= steps ? bins : steps]; for (int i = 0; i < bins; i++) { if (in.readInt() != 0) { - mSpeedBins[i] = new SamplingCounter(mUnpluggables, in); + mSpeedBins[i] = new SamplingCounter(mOnBatteryTimeBase, in); } } @@ -4543,7 +4738,7 @@ public final class BatteryStatsImpl extends BatteryStats { if (amt != 0) { SamplingCounter c = mSpeedBins[i]; if (c == null) { - mSpeedBins[i] = c = new SamplingCounter(mUnpluggables); + mSpeedBins[i] = c = new SamplingCounter(mOnBatteryTimeBase); } c.addCountAtomic(values[i]); } @@ -4564,7 +4759,7 @@ public final class BatteryStatsImpl extends BatteryStats { /** * The statistics associated with a particular package. */ - public final class Pkg extends BatteryStats.Uid.Pkg implements Unpluggable { + public final class Pkg extends BatteryStats.Uid.Pkg implements TimeBaseObs { /** * Number of times this package has done something that could wake up the * device from sleep. @@ -4595,18 +4790,18 @@ public final class BatteryStatsImpl extends BatteryStats { final HashMap<String, Serv> mServiceStats = new HashMap<String, Serv>(); Pkg() { - mUnpluggables.add(this); + mOnBatteryScreenOffTimeBase.add(this); } - public void unplug(long elapsedRealtime, long batteryUptime, long batteryRealtime) { + public void onTimeStarted(long elapsedRealtime, long baseUptime, long baseRealtime) { mUnpluggedWakeups = mWakeups; } - public void plug(long elapsedRealtime, long batteryUptime, long batteryRealtime) { + public void onTimeStopped(long elapsedRealtime, long baseUptime, long baseRealtime) { } void detach() { - mUnpluggables.remove(this); + mOnBatteryScreenOffTimeBase.remove(this); } void readFromParcelLocked(Parcel in) { @@ -4665,7 +4860,7 @@ public final class BatteryStatsImpl extends BatteryStats { /** * The statistics associated with a particular service. */ - public final class Serv extends BatteryStats.Uid.Pkg.Serv implements Unpluggable { + public final class Serv extends BatteryStats.Uid.Pkg.Serv implements TimeBaseObs { /** * Total time (ms in battery uptime) the service has been left started. */ @@ -4757,20 +4952,22 @@ public final class BatteryStatsImpl extends BatteryStats { int mUnpluggedLaunches; Serv() { - mUnpluggables.add(this); + mOnBatteryTimeBase.add(this); } - public void unplug(long elapsedRealtime, long batteryUptime, long batteryRealtime) { - mUnpluggedStartTime = getStartTimeToNowLocked(batteryUptime); + public void onTimeStarted(long elapsedRealtime, long baseUptime, + long baseRealtime) { + mUnpluggedStartTime = getStartTimeToNowLocked(baseUptime); mUnpluggedStarts = mStarts; mUnpluggedLaunches = mLaunches; } - public void plug(long elapsedRealtime, long batteryUptime, long batteryRealtime) { + public void onTimeStopped(long elapsedRealtime, long baseUptime, + long baseRealtime) { } void detach() { - mUnpluggables.remove(this); + mOnBatteryTimeBase.remove(this); } void readFromParcelLocked(Parcel in) { @@ -5005,7 +5202,7 @@ public final class BatteryStatsImpl extends BatteryStats { t = wl.mTimerPartial; if (t == null) { t = new StopwatchTimer(Uid.this, WAKE_TYPE_PARTIAL, - mPartialTimers, mUnpluggables); + mPartialTimers, mOnBatteryScreenOffTimeBase); wl.mTimerPartial = t; } return t; @@ -5013,7 +5210,7 @@ public final class BatteryStatsImpl extends BatteryStats { t = wl.mTimerFull; if (t == null) { t = new StopwatchTimer(Uid.this, WAKE_TYPE_FULL, - mFullTimers, mUnpluggables); + mFullTimers, mOnBatteryTimeBase); wl.mTimerFull = t; } return t; @@ -5021,7 +5218,7 @@ public final class BatteryStatsImpl extends BatteryStats { t = wl.mTimerWindow; if (t == null) { t = new StopwatchTimer(Uid.this, WAKE_TYPE_WINDOW, - mWindowTimers, mUnpluggables); + mWindowTimers, mOnBatteryTimeBase); wl.mTimerWindow = t; } return t; @@ -5048,33 +5245,33 @@ public final class BatteryStatsImpl extends BatteryStats { timers = new ArrayList<StopwatchTimer>(); mSensorTimers.put(sensor, timers); } - t = new StopwatchTimer(Uid.this, BatteryStats.SENSOR, timers, mUnpluggables); + t = new StopwatchTimer(Uid.this, BatteryStats.SENSOR, timers, mOnBatteryTimeBase); se.mTimer = t; return t; } - public void noteStartWakeLocked(int pid, String name, int type, long elapsedRealtime) { + public void noteStartWakeLocked(int pid, String name, int type, long elapsedRealtimeMs) { StopwatchTimer t = getWakeTimerLocked(name, type); if (t != null) { - t.startRunningLocked(BatteryStatsImpl.this, elapsedRealtime); + t.startRunningLocked(elapsedRealtimeMs); } if (pid >= 0 && type == WAKE_TYPE_PARTIAL) { Pid p = getPidStatsLocked(pid); if (p.mWakeStart == 0) { - p.mWakeStart = elapsedRealtime; + p.mWakeStart = elapsedRealtimeMs; } } } - public void noteStopWakeLocked(int pid, String name, int type, long elapsedRealtime) { + public void noteStopWakeLocked(int pid, String name, int type, long elapsedRealtimeMs) { StopwatchTimer t = getWakeTimerLocked(name, type); if (t != null) { - t.stopRunningLocked(BatteryStatsImpl.this, elapsedRealtime); + t.stopRunningLocked(elapsedRealtimeMs); } if (pid >= 0 && type == WAKE_TYPE_PARTIAL) { Pid p = mPids.get(pid); if (p != null && p.mWakeStart != 0) { - p.mWakeSum += elapsedRealtime - p.mWakeStart; + p.mWakeSum += elapsedRealtimeMs - p.mWakeStart; p.mWakeStart = 0; } } @@ -5094,32 +5291,32 @@ public final class BatteryStatsImpl extends BatteryStats { } } - public void noteStartSensor(int sensor, long elapsedRealtime) { + public void noteStartSensor(int sensor, long elapsedRealtimeMs) { StopwatchTimer t = getSensorTimerLocked(sensor, true); if (t != null) { - t.startRunningLocked(BatteryStatsImpl.this, elapsedRealtime); + t.startRunningLocked(elapsedRealtimeMs); } } - public void noteStopSensor(int sensor, long elapsedRealtime) { + public void noteStopSensor(int sensor, long elapsedRealtimeMs) { // Don't create a timer if one doesn't already exist StopwatchTimer t = getSensorTimerLocked(sensor, false); if (t != null) { - t.stopRunningLocked(BatteryStatsImpl.this, elapsedRealtime); + t.stopRunningLocked(elapsedRealtimeMs); } } - public void noteStartGps(long elapsedRealtime) { + public void noteStartGps(long elapsedRealtimeMs) { StopwatchTimer t = getSensorTimerLocked(Sensor.GPS, true); if (t != null) { - t.startRunningLocked(BatteryStatsImpl.this, elapsedRealtime); + t.startRunningLocked(elapsedRealtimeMs); } } - public void noteStopGps(long elapsedRealtime) { + public void noteStopGps(long elapsedRealtimeMs) { StopwatchTimer t = getSensorTimerLocked(Sensor.GPS, false); if (t != null) { - t.stopRunningLocked(BatteryStatsImpl.this, elapsedRealtime); + t.stopRunningLocked(elapsedRealtimeMs); } } @@ -5132,46 +5329,46 @@ public final class BatteryStatsImpl extends BatteryStats { mFile = new JournaledFile(new File(filename), new File(filename + ".tmp")); mHandler = new MyHandler(handler.getLooper()); mStartCount++; - mScreenOnTimer = new StopwatchTimer(null, -1, null, mUnpluggables); + mScreenOnTimer = new StopwatchTimer(null, -1, null, mOnBatteryTimeBase); for (int i=0; i<NUM_SCREEN_BRIGHTNESS_BINS; i++) { - mScreenBrightnessTimer[i] = new StopwatchTimer(null, -100-i, null, mUnpluggables); + mScreenBrightnessTimer[i] = new StopwatchTimer(null, -100-i, null, mOnBatteryTimeBase); } - mInputEventCounter = new Counter(mUnpluggables); - mPhoneOnTimer = new StopwatchTimer(null, -2, null, mUnpluggables); + mInputEventCounter = new Counter(mOnBatteryTimeBase); + mPhoneOnTimer = new StopwatchTimer(null, -2, null, mOnBatteryTimeBase); for (int i=0; i<SignalStrength.NUM_SIGNAL_STRENGTH_BINS; i++) { - mPhoneSignalStrengthsTimer[i] = new StopwatchTimer(null, -200-i, null, mUnpluggables); + mPhoneSignalStrengthsTimer[i] = new StopwatchTimer(null, -200-i, null, + mOnBatteryTimeBase); } - mPhoneSignalScanningTimer = new StopwatchTimer(null, -200+1, null, mUnpluggables); + mPhoneSignalScanningTimer = new StopwatchTimer(null, -200+1, null, mOnBatteryTimeBase); for (int i=0; i<NUM_DATA_CONNECTION_TYPES; i++) { - mPhoneDataConnectionsTimer[i] = new StopwatchTimer(null, -300-i, null, mUnpluggables); + mPhoneDataConnectionsTimer[i] = new StopwatchTimer(null, -300-i, null, + mOnBatteryTimeBase); } for (int i = 0; i < NUM_NETWORK_ACTIVITY_TYPES; i++) { - mNetworkByteActivityCounters[i] = new LongSamplingCounter(mUnpluggables); - mNetworkPacketActivityCounters[i] = new LongSamplingCounter(mUnpluggables); - } - mMobileRadioActiveTimer = new StopwatchTimer(null, -400, null, mUnpluggables); - mMobileRadioActivePerAppTimer = new StopwatchTimer(null, -401, null, mUnpluggables); - mMobileRadioActiveUnknownTime = new LongSamplingCounter(mUnpluggables); - mMobileRadioActiveUnknownCount = new LongSamplingCounter(mUnpluggables); - mWifiOnTimer = new StopwatchTimer(null, -3, null, mUnpluggables); - mGlobalWifiRunningTimer = new StopwatchTimer(null, -4, null, mUnpluggables); + mNetworkByteActivityCounters[i] = new LongSamplingCounter(mOnBatteryTimeBase); + mNetworkPacketActivityCounters[i] = new LongSamplingCounter(mOnBatteryTimeBase); + } + mMobileRadioActiveTimer = new StopwatchTimer(null, -400, null, mOnBatteryTimeBase); + mMobileRadioActivePerAppTimer = new StopwatchTimer(null, -401, null, mOnBatteryTimeBase); + mMobileRadioActiveUnknownTime = new LongSamplingCounter(mOnBatteryTimeBase); + mMobileRadioActiveUnknownCount = new LongSamplingCounter(mOnBatteryTimeBase); + mWifiOnTimer = new StopwatchTimer(null, -3, null, mOnBatteryTimeBase); + mGlobalWifiRunningTimer = new StopwatchTimer(null, -4, null, mOnBatteryTimeBase); for (int i=0; i<NUM_WIFI_STATES; i++) { - mWifiStateTimer[i] = new StopwatchTimer(null, -600-i, null, mUnpluggables); + mWifiStateTimer[i] = new StopwatchTimer(null, -600-i, null, mOnBatteryTimeBase); } - mBluetoothOnTimer = new StopwatchTimer(null, -5, null, mUnpluggables); + mBluetoothOnTimer = new StopwatchTimer(null, -5, null, mOnBatteryTimeBase); for (int i=0; i< NUM_BLUETOOTH_STATES; i++) { - mBluetoothStateTimer[i] = new StopwatchTimer(null, -500-i, null, mUnpluggables); + mBluetoothStateTimer[i] = new StopwatchTimer(null, -500-i, null, mOnBatteryTimeBase); } - mAudioOnTimer = new StopwatchTimer(null, -6, null, mUnpluggables); - mVideoOnTimer = new StopwatchTimer(null, -7, null, mUnpluggables); + mAudioOnTimer = new StopwatchTimer(null, -6, null, mOnBatteryTimeBase); + mVideoOnTimer = new StopwatchTimer(null, -7, null, mOnBatteryTimeBase); mOnBattery = mOnBatteryInternal = false; - initTimes(); - mTrackBatteryPastUptime = 0; - mTrackBatteryPastRealtime = 0; - mUptimeStart = mTrackBatteryUptimeStart = SystemClock.uptimeMillis() * 1000; - mRealtimeStart = mTrackBatteryRealtimeStart = SystemClock.elapsedRealtime() * 1000; - mUnpluggedBatteryUptime = getBatteryUptimeLocked(mUptimeStart); - mUnpluggedBatteryRealtime = getBatteryRealtimeLocked(mRealtimeStart); + long uptime = SystemClock.uptimeMillis() * 1000; + long realtime = SystemClock.elapsedRealtime() * 1000; + initTimes(uptime, realtime); + mUptimeStart = uptime; + mRealtimeStart = realtime; mDischargeStartLevel = 0; mDischargeUnplugLevel = 0; mDischargeCurrentLevel = 0; @@ -5347,14 +5544,12 @@ public final class BatteryStatsImpl extends BatteryStats { return mScreenOn; } - void initTimes() { + void initTimes(long uptime, long realtime) { mStartClockTime = System.currentTimeMillis(); - mBatteryRealtime = mTrackBatteryPastUptime = 0; - mBatteryUptime = mTrackBatteryPastRealtime = 0; - mUptimeStart = mTrackBatteryUptimeStart = SystemClock.uptimeMillis() * 1000; - mRealtimeStart = mTrackBatteryRealtimeStart = SystemClock.elapsedRealtime() * 1000; - mUnpluggedBatteryUptime = getBatteryUptimeLocked(mUptimeStart); - mUnpluggedBatteryRealtime = getBatteryRealtimeLocked(mRealtimeStart); + mOnBatteryTimeBase.init(uptime, realtime); + mOnBatteryScreenOffTimeBase.init(uptime, realtime); + mUptimeStart = uptime; + mRealtimeStart = realtime; } void initDischarge() { @@ -5375,14 +5570,9 @@ public final class BatteryStatsImpl extends BatteryStats { pullPendingStateUpdatesLocked(); addHistoryRecordLocked(mSecRealtime); mDischargeCurrentLevel = mDischargeUnplugLevel = mHistoryCur.batteryLevel; - if ((mHistoryCur.states&HistoryItem.STATE_BATTERY_PLUGGED_FLAG) != 0) { - mTrackBatteryPastUptime = 0; - mTrackBatteryPastRealtime = 0; - } else { - mTrackBatteryUptimeStart = uptime; - mTrackBatteryRealtimeStart = realtime; - mUnpluggedBatteryUptime = getBatteryUptimeLocked(uptime); - mUnpluggedBatteryRealtime = getBatteryRealtimeLocked(realtime); + mOnBatteryTimeBase.reset(uptime, realtime); + mOnBatteryScreenOffTimeBase.reset(uptime, realtime); + if ((mHistoryCur.states&HistoryItem.STATE_BATTERY_PLUGGED_FLAG) == 0) { if (mScreenOn) { mDischargeScreenOnUnplugLevel = mHistoryCur.batteryLevel; mDischargeScreenOffUnplugLevel = 0; @@ -5398,38 +5588,38 @@ public final class BatteryStatsImpl extends BatteryStats { private void resetAllStatsLocked() { mStartCount = 0; - initTimes(); - mScreenOnTimer.reset(this, false); + initTimes(SystemClock.uptimeMillis() * 1000, SystemClock.elapsedRealtime() * 1000); + mScreenOnTimer.reset(false); for (int i=0; i<NUM_SCREEN_BRIGHTNESS_BINS; i++) { - mScreenBrightnessTimer[i].reset(this, false); + mScreenBrightnessTimer[i].reset(false); } mInputEventCounter.reset(false); - mPhoneOnTimer.reset(this, false); - mAudioOnTimer.reset(this, false); - mVideoOnTimer.reset(this, false); + mPhoneOnTimer.reset(false); + mAudioOnTimer.reset(false); + mVideoOnTimer.reset(false); for (int i=0; i<SignalStrength.NUM_SIGNAL_STRENGTH_BINS; i++) { - mPhoneSignalStrengthsTimer[i].reset(this, false); + mPhoneSignalStrengthsTimer[i].reset(false); } - mPhoneSignalScanningTimer.reset(this, false); + mPhoneSignalScanningTimer.reset(false); for (int i=0; i<NUM_DATA_CONNECTION_TYPES; i++) { - mPhoneDataConnectionsTimer[i].reset(this, false); + mPhoneDataConnectionsTimer[i].reset(false); } for (int i = 0; i < NUM_NETWORK_ACTIVITY_TYPES; i++) { mNetworkByteActivityCounters[i].reset(false); mNetworkPacketActivityCounters[i].reset(false); } - mMobileRadioActiveTimer.reset(this, false); - mMobileRadioActivePerAppTimer.reset(this, false); + mMobileRadioActiveTimer.reset(false); + mMobileRadioActivePerAppTimer.reset(false); mMobileRadioActiveUnknownTime.reset(false); mMobileRadioActiveUnknownCount.reset(false); - mWifiOnTimer.reset(this, false); - mGlobalWifiRunningTimer.reset(this, false); + mWifiOnTimer.reset(false); + mGlobalWifiRunningTimer.reset(false); for (int i=0; i<NUM_WIFI_STATES; i++) { - mWifiStateTimer[i].reset(this, false); + mWifiStateTimer[i].reset(false); } - mBluetoothOnTimer.reset(this, false); + mBluetoothOnTimer.reset(false); for (int i=0; i< NUM_BLUETOOTH_STATES; i++) { - mBluetoothStateTimer[i].reset(this, false); + mBluetoothStateTimer[i].reset(false); } for (int i=0; i<mUidStats.size(); i++) { @@ -5441,7 +5631,7 @@ public final class BatteryStatsImpl extends BatteryStats { if (mKernelWakelockStats.size() > 0) { for (SamplingTimer timer : mKernelWakelockStats.values()) { - mUnpluggables.remove(timer); + mOnBatteryScreenOffTimeBase.remove(timer); } mKernelWakelockStats.clear(); } @@ -5491,12 +5681,6 @@ public final class BatteryStatsImpl extends BatteryStats { } } - void setOnBattery(boolean onBattery, int oldStatus, int level) { - synchronized(this) { - setOnBatteryLocked(onBattery, oldStatus, level); - } - } - public void pullPendingStateUpdatesLocked() { updateKernelWakelocksLocked(); updateNetworkActivityLocked(NET_UPDATE_ALL, SystemClock.elapsedRealtime()); @@ -5535,10 +5719,6 @@ public final class BatteryStatsImpl extends BatteryStats { if (DEBUG_HISTORY) Slog.v(TAG, "Battery unplugged to: " + Integer.toHexString(mHistoryCur.states)); addHistoryRecordLocked(mSecRealtime); - mTrackBatteryUptimeStart = uptime; - mTrackBatteryRealtimeStart = realtime; - mUnpluggedBatteryUptime = getBatteryUptimeLocked(uptime); - mUnpluggedBatteryRealtime = getBatteryRealtimeLocked(realtime); mDischargeCurrentLevel = mDischargeUnplugLevel = level; if (mScreenOn) { mDischargeScreenOnUnplugLevel = level; @@ -5549,7 +5729,7 @@ public final class BatteryStatsImpl extends BatteryStats { } mDischargeAmountScreenOn = 0; mDischargeAmountScreenOff = 0; - doUnplugLocked(realtime, mUnpluggedBatteryUptime, mUnpluggedBatteryRealtime); + updateTimeBasesLocked(true, !mScreenOn, uptime, realtime); if (reset) { initActiveHistoryEventsLocked(mSecRealtime); } @@ -5560,15 +5740,13 @@ public final class BatteryStatsImpl extends BatteryStats { if (DEBUG_HISTORY) Slog.v(TAG, "Battery plugged to: " + Integer.toHexString(mHistoryCur.states)); addHistoryRecordLocked(mSecRealtime); - mTrackBatteryPastUptime += uptime - mTrackBatteryUptimeStart; - mTrackBatteryPastRealtime += realtime - mTrackBatteryRealtimeStart; mDischargeCurrentLevel = level; if (level < mDischargeUnplugLevel) { mLowDischargeAmountSinceCharge += mDischargeUnplugLevel-level-1; mHighDischargeAmountSinceCharge += mDischargeUnplugLevel-level; } updateDischargeScreenLevelsLocked(mScreenOn, mScreenOn); - doPlugLocked(realtime, getBatteryUptimeLocked(uptime), getBatteryRealtimeLocked(realtime)); + updateTimeBasesLocked(false, !mScreenOn, uptime, realtime); } if (doWrite || (mLastWriteTime + (60 * 1000)) < mSecRealtime) { if (mFile != null) { @@ -5667,8 +5845,8 @@ public final class BatteryStatsImpl extends BatteryStats { SamplingTimer kwlt = mKernelWakelockStats.get(name); if (kwlt == null) { - kwlt = new SamplingTimer(mUnpluggables, mOnBatteryInternal, - true /* track reported values */); + kwlt = new SamplingTimer(mOnBatteryScreenOffTimeBase, + true /* track reported val */); mKernelWakelockStats.put(name, kwlt); } kwlt.updateCurrentReportedCount(kws.mCount); @@ -5691,7 +5869,7 @@ public final class BatteryStatsImpl extends BatteryStats { static final int NET_UPDATE_WIFI = 1<<1; static final int NET_UPDATE_ALL = 0xffff; - private void updateNetworkActivityLocked(int which, long elapsedRealtime) { + private void updateNetworkActivityLocked(int which, long elapsedRealtimeMs) { if (!SystemProperties.getBoolean(PROP_QTAGUID_ENABLED, false)) return; if ((which&NET_UPDATE_MOBILE) != 0 && mMobileIfaces.length > 0) { @@ -5713,8 +5891,8 @@ public final class BatteryStatsImpl extends BatteryStats { null, null, mTmpNetworkStats); mTmpNetworkStats = delta; - long radioTime = mMobileRadioActivePerAppTimer.checkpointRunningLocked(this, - elapsedRealtime); + long radioTime = mMobileRadioActivePerAppTimer.checkpointRunningLocked( + elapsedRealtimeMs); long totalPackets = delta.getTotalPackets(); final int size = delta.size(); @@ -5823,7 +6001,7 @@ public final class BatteryStatsImpl extends BatteryStats { case STATS_SINCE_CHARGED: return mUptime + (curTime-mUptimeStart); case STATS_LAST: return mLastUptime; case STATS_CURRENT: return (curTime-mUptimeStart); - case STATS_SINCE_UNPLUGGED: return (curTime-mTrackBatteryUptimeStart); + case STATS_SINCE_UNPLUGGED: return (curTime- mOnBatteryTimeBase.getUptimeStart()); } return 0; } @@ -5834,69 +6012,43 @@ public final class BatteryStatsImpl extends BatteryStats { case STATS_SINCE_CHARGED: return mRealtime + (curTime-mRealtimeStart); case STATS_LAST: return mLastRealtime; case STATS_CURRENT: return (curTime-mRealtimeStart); - case STATS_SINCE_UNPLUGGED: return (curTime-mTrackBatteryRealtimeStart); + case STATS_SINCE_UNPLUGGED: return (curTime- mOnBatteryTimeBase.getRealtimeStart()); } return 0; } @Override public long computeBatteryUptime(long curTime, int which) { - switch (which) { - case STATS_SINCE_CHARGED: - return mBatteryUptime + getBatteryUptime(curTime); - case STATS_LAST: - return mBatteryLastUptime; - case STATS_CURRENT: - return getBatteryUptime(curTime); - case STATS_SINCE_UNPLUGGED: - return getBatteryUptimeLocked(curTime) - mUnpluggedBatteryUptime; - } - return 0; + return mOnBatteryTimeBase.computeUptime(curTime, which); } @Override public long computeBatteryRealtime(long curTime, int which) { - switch (which) { - case STATS_SINCE_CHARGED: - return mBatteryRealtime + getBatteryRealtimeLocked(curTime); - case STATS_LAST: - return mBatteryLastRealtime; - case STATS_CURRENT: - return getBatteryRealtimeLocked(curTime); - case STATS_SINCE_UNPLUGGED: - return getBatteryRealtimeLocked(curTime) - mUnpluggedBatteryRealtime; - } - return 0; + return mOnBatteryTimeBase.computeRealtime(curTime, which); } - long getBatteryUptimeLocked(long curTime) { - long time = mTrackBatteryPastUptime; - if (mOnBatteryInternal) { - time += curTime - mTrackBatteryUptimeStart; - } - return time; + @Override + public long computeBatteryScreenOffUptime(long curTime, int which) { + return mOnBatteryScreenOffTimeBase.computeUptime(curTime, which); + } + + @Override + public long computeBatteryScreenOffRealtime(long curTime, int which) { + return mOnBatteryScreenOffTimeBase.computeRealtime(curTime, which); } long getBatteryUptimeLocked() { - return getBatteryUptime(SystemClock.uptimeMillis() * 1000); + return mOnBatteryTimeBase.getUptime(SystemClock.uptimeMillis() * 1000); } @Override public long getBatteryUptime(long curTime) { - return getBatteryUptimeLocked(curTime); - } - - long getBatteryRealtimeLocked(long curTime) { - long time = mTrackBatteryPastRealtime; - if (mOnBatteryInternal) { - time += curTime - mTrackBatteryRealtimeStart; - } - return time; + return mOnBatteryTimeBase.getUptime(curTime); } @Override public long getBatteryRealtime(long curTime) { - return getBatteryRealtimeLocked(curTime); + return mOnBatteryTimeBase.getRealtime(curTime); } @Override @@ -6074,7 +6226,7 @@ public final class BatteryStatsImpl extends BatteryStats { time = (time*uidRunningTime)/totalRunningTime; SamplingCounter uidSc = uidProc.mSpeedBins[sb]; if (uidSc == null) { - uidSc = new SamplingCounter(mUnpluggables); + uidSc = new SamplingCounter(mOnBatteryTimeBase); uidProc.mSpeedBins[sb] = uidSc; } uidSc.mCount.addAndGet((int)time); @@ -6358,11 +6510,11 @@ public final class BatteryStatsImpl extends BatteryStats { readHistory(in, true); mStartCount = in.readInt(); - mBatteryUptime = in.readLong(); - mBatteryRealtime = in.readLong(); mUptime = in.readLong(); mRealtime = in.readLong(); mStartClockTime = in.readLong(); + mOnBatteryTimeBase.readSummaryFromParcel(in); + mOnBatteryScreenOffTimeBase.readSummaryFromParcel(in); mDischargeUnplugLevel = in.readInt(); mDischargeCurrentLevel = in.readInt(); mLowDischargeAmountSinceCharge = in.readInt(); @@ -6546,7 +6698,7 @@ public final class BatteryStatsImpl extends BatteryStats { p.mSpeedBins = new SamplingCounter[NSB]; for (int i=0; i<NSB; i++) { if (in.readInt() != 0) { - p.mSpeedBins[i] = new SamplingCounter(mUnpluggables); + p.mSpeedBins[i] = new SamplingCounter(mOnBatteryTimeBase); p.mSpeedBins[i].readSummaryFromParcelLocked(in); } } @@ -6591,55 +6743,53 @@ public final class BatteryStatsImpl extends BatteryStats { final long NOW_SYS = SystemClock.uptimeMillis() * 1000; final long NOWREAL_SYS = SystemClock.elapsedRealtime() * 1000; - final long NOW = getBatteryUptimeLocked(NOW_SYS); - final long NOWREAL = getBatteryRealtimeLocked(NOWREAL_SYS); out.writeInt(VERSION); writeHistory(out, true); out.writeInt(mStartCount); - out.writeLong(computeBatteryUptime(NOW_SYS, STATS_SINCE_CHARGED)); - out.writeLong(computeBatteryRealtime(NOWREAL_SYS, STATS_SINCE_CHARGED)); out.writeLong(computeUptime(NOW_SYS, STATS_SINCE_CHARGED)); out.writeLong(computeRealtime(NOWREAL_SYS, STATS_SINCE_CHARGED)); out.writeLong(mStartClockTime); + mOnBatteryTimeBase.writeSummaryToParcel(out, NOW_SYS, NOWREAL_SYS); + mOnBatteryScreenOffTimeBase.writeSummaryToParcel(out, NOW_SYS, NOWREAL_SYS); out.writeInt(mDischargeUnplugLevel); out.writeInt(mDischargeCurrentLevel); out.writeInt(getLowDischargeAmountSinceCharge()); out.writeInt(getHighDischargeAmountSinceCharge()); out.writeInt(getDischargeAmountScreenOnSinceCharge()); out.writeInt(getDischargeAmountScreenOffSinceCharge()); - - mScreenOnTimer.writeSummaryFromParcelLocked(out, NOWREAL); + + mScreenOnTimer.writeSummaryFromParcelLocked(out, NOWREAL_SYS); for (int i=0; i<NUM_SCREEN_BRIGHTNESS_BINS; i++) { - mScreenBrightnessTimer[i].writeSummaryFromParcelLocked(out, NOWREAL); + mScreenBrightnessTimer[i].writeSummaryFromParcelLocked(out, NOWREAL_SYS); } mInputEventCounter.writeSummaryFromParcelLocked(out); - mPhoneOnTimer.writeSummaryFromParcelLocked(out, NOWREAL); + mPhoneOnTimer.writeSummaryFromParcelLocked(out, NOWREAL_SYS); for (int i=0; i<SignalStrength.NUM_SIGNAL_STRENGTH_BINS; i++) { - mPhoneSignalStrengthsTimer[i].writeSummaryFromParcelLocked(out, NOWREAL); + mPhoneSignalStrengthsTimer[i].writeSummaryFromParcelLocked(out, NOWREAL_SYS); } - mPhoneSignalScanningTimer.writeSummaryFromParcelLocked(out, NOWREAL); + mPhoneSignalScanningTimer.writeSummaryFromParcelLocked(out, NOWREAL_SYS); for (int i=0; i<NUM_DATA_CONNECTION_TYPES; i++) { - mPhoneDataConnectionsTimer[i].writeSummaryFromParcelLocked(out, NOWREAL); + mPhoneDataConnectionsTimer[i].writeSummaryFromParcelLocked(out, NOWREAL_SYS); } for (int i = 0; i < NUM_NETWORK_ACTIVITY_TYPES; i++) { mNetworkByteActivityCounters[i].writeSummaryFromParcelLocked(out); mNetworkPacketActivityCounters[i].writeSummaryFromParcelLocked(out); } - mMobileRadioActiveTimer.writeSummaryFromParcelLocked(out, NOWREAL); - mMobileRadioActivePerAppTimer.writeSummaryFromParcelLocked(out, NOWREAL); + mMobileRadioActiveTimer.writeSummaryFromParcelLocked(out, NOWREAL_SYS); + mMobileRadioActivePerAppTimer.writeSummaryFromParcelLocked(out, NOWREAL_SYS); mMobileRadioActiveUnknownTime.writeSummaryFromParcelLocked(out); mMobileRadioActiveUnknownCount.writeSummaryFromParcelLocked(out); - mWifiOnTimer.writeSummaryFromParcelLocked(out, NOWREAL); - mGlobalWifiRunningTimer.writeSummaryFromParcelLocked(out, NOWREAL); + mWifiOnTimer.writeSummaryFromParcelLocked(out, NOWREAL_SYS); + mGlobalWifiRunningTimer.writeSummaryFromParcelLocked(out, NOWREAL_SYS); for (int i=0; i<NUM_WIFI_STATES; i++) { - mWifiStateTimer[i].writeSummaryFromParcelLocked(out, NOWREAL); + mWifiStateTimer[i].writeSummaryFromParcelLocked(out, NOWREAL_SYS); } - mBluetoothOnTimer.writeSummaryFromParcelLocked(out, NOWREAL); + mBluetoothOnTimer.writeSummaryFromParcelLocked(out, NOWREAL_SYS); for (int i=0; i< NUM_BLUETOOTH_STATES; i++) { - mBluetoothStateTimer[i].writeSummaryFromParcelLocked(out, NOWREAL); + mBluetoothStateTimer[i].writeSummaryFromParcelLocked(out, NOWREAL_SYS); } out.writeInt(mKernelWakelockStats.size()); @@ -6648,7 +6798,7 @@ public final class BatteryStatsImpl extends BatteryStats { if (kwlt != null) { out.writeInt(1); out.writeString(ent.getKey()); - ent.getValue().writeSummaryFromParcelLocked(out, NOWREAL); + ent.getValue().writeSummaryFromParcelLocked(out, NOWREAL_SYS); } else { out.writeInt(0); } @@ -6663,57 +6813,57 @@ public final class BatteryStatsImpl extends BatteryStats { if (u.mWifiRunningTimer != null) { out.writeInt(1); - u.mWifiRunningTimer.writeSummaryFromParcelLocked(out, NOWREAL); + u.mWifiRunningTimer.writeSummaryFromParcelLocked(out, NOWREAL_SYS); } else { out.writeInt(0); } if (u.mFullWifiLockTimer != null) { out.writeInt(1); - u.mFullWifiLockTimer.writeSummaryFromParcelLocked(out, NOWREAL); + u.mFullWifiLockTimer.writeSummaryFromParcelLocked(out, NOWREAL_SYS); } else { out.writeInt(0); } if (u.mWifiScanTimer != null) { out.writeInt(1); - u.mWifiScanTimer.writeSummaryFromParcelLocked(out, NOWREAL); + u.mWifiScanTimer.writeSummaryFromParcelLocked(out, NOWREAL_SYS); } else { out.writeInt(0); } for (int i = 0; i < Uid.NUM_WIFI_BATCHED_SCAN_BINS; i++) { if (u.mWifiBatchedScanTimer[i] != null) { out.writeInt(1); - u.mWifiBatchedScanTimer[i].writeSummaryFromParcelLocked(out, NOWREAL); + u.mWifiBatchedScanTimer[i].writeSummaryFromParcelLocked(out, NOWREAL_SYS); } else { out.writeInt(0); } } if (u.mWifiMulticastTimer != null) { out.writeInt(1); - u.mWifiMulticastTimer.writeSummaryFromParcelLocked(out, NOWREAL); + u.mWifiMulticastTimer.writeSummaryFromParcelLocked(out, NOWREAL_SYS); } else { out.writeInt(0); } if (u.mAudioTurnedOnTimer != null) { out.writeInt(1); - u.mAudioTurnedOnTimer.writeSummaryFromParcelLocked(out, NOWREAL); + u.mAudioTurnedOnTimer.writeSummaryFromParcelLocked(out, NOWREAL_SYS); } else { out.writeInt(0); } if (u.mVideoTurnedOnTimer != null) { out.writeInt(1); - u.mVideoTurnedOnTimer.writeSummaryFromParcelLocked(out, NOWREAL); + u.mVideoTurnedOnTimer.writeSummaryFromParcelLocked(out, NOWREAL_SYS); } else { out.writeInt(0); } if (u.mForegroundActivityTimer != null) { out.writeInt(1); - u.mForegroundActivityTimer.writeSummaryFromParcelLocked(out, NOWREAL); + u.mForegroundActivityTimer.writeSummaryFromParcelLocked(out, NOWREAL_SYS); } else { out.writeInt(0); } if (u.mVibratorOnTimer != null) { out.writeInt(1); - u.mVibratorOnTimer.writeSummaryFromParcelLocked(out, NOWREAL); + u.mVibratorOnTimer.writeSummaryFromParcelLocked(out, NOWREAL_SYS); } else { out.writeInt(0); } @@ -6748,19 +6898,19 @@ public final class BatteryStatsImpl extends BatteryStats { Uid.Wakelock wl = ent.getValue(); if (wl.mTimerFull != null) { out.writeInt(1); - wl.mTimerFull.writeSummaryFromParcelLocked(out, NOWREAL); + wl.mTimerFull.writeSummaryFromParcelLocked(out, NOWREAL_SYS); } else { out.writeInt(0); } if (wl.mTimerPartial != null) { out.writeInt(1); - wl.mTimerPartial.writeSummaryFromParcelLocked(out, NOWREAL); + wl.mTimerPartial.writeSummaryFromParcelLocked(out, NOWREAL_SYS); } else { out.writeInt(0); } if (wl.mTimerWindow != null) { out.writeInt(1); - wl.mTimerWindow.writeSummaryFromParcelLocked(out, NOWREAL); + wl.mTimerWindow.writeSummaryFromParcelLocked(out, NOWREAL_SYS); } else { out.writeInt(0); } @@ -6776,7 +6926,7 @@ public final class BatteryStatsImpl extends BatteryStats { Uid.Sensor se = ent.getValue(); if (se.mTimer != null) { out.writeInt(1); - se.mTimer.writeSummaryFromParcelLocked(out, NOWREAL); + se.mTimer.writeSummaryFromParcelLocked(out, NOWREAL_SYS); } else { out.writeInt(0); } @@ -6823,7 +6973,8 @@ public final class BatteryStatsImpl extends BatteryStats { : ps.mServiceStats.entrySet()) { out.writeString(sent.getKey()); BatteryStatsImpl.Uid.Pkg.Serv ss = sent.getValue(); - long time = ss.getStartTimeToNowLocked(NOW); + long time = ss.getStartTimeToNowLocked( + mOnBatteryTimeBase.getUptime(NOW_SYS)); out.writeLong(time); out.writeInt(ss.mStarts); out.writeInt(ss.mLaunches); @@ -6847,66 +6998,60 @@ public final class BatteryStatsImpl extends BatteryStats { readHistory(in, false); mStartCount = in.readInt(); - mBatteryUptime = in.readLong(); - mBatteryLastUptime = 0; - mBatteryRealtime = in.readLong(); - mBatteryLastRealtime = 0; mStartClockTime = in.readLong(); + mUptime = in.readLong(); + mUptimeStart = in.readLong(); + mLastUptime = 0; + mRealtime = in.readLong(); + mRealtimeStart = in.readLong(); + mLastRealtime = 0; + mOnBattery = in.readInt() != 0; + mOnBatteryInternal = false; // we are no longer really running. + mOnBatteryTimeBase.readFromParcel(in); + mOnBatteryScreenOffTimeBase.readFromParcel(in); + mScreenOn = false; - mScreenOnTimer = new StopwatchTimer(null, -1, null, mUnpluggables, in); + mScreenOnTimer = new StopwatchTimer(null, -1, null, mOnBatteryTimeBase, in); for (int i=0; i<NUM_SCREEN_BRIGHTNESS_BINS; i++) { - mScreenBrightnessTimer[i] = new StopwatchTimer(null, -100-i, - null, mUnpluggables, in); + mScreenBrightnessTimer[i] = new StopwatchTimer(null, -100-i, null, mOnBatteryTimeBase, + in); } - mInputEventCounter = new Counter(mUnpluggables, in); + mInputEventCounter = new Counter(mOnBatteryTimeBase, in); mPhoneOn = false; - mPhoneOnTimer = new StopwatchTimer(null, -2, null, mUnpluggables, in); + mPhoneOnTimer = new StopwatchTimer(null, -2, null, mOnBatteryTimeBase, in); for (int i=0; i<SignalStrength.NUM_SIGNAL_STRENGTH_BINS; i++) { mPhoneSignalStrengthsTimer[i] = new StopwatchTimer(null, -200-i, - null, mUnpluggables, in); + null, mOnBatteryTimeBase, in); } - mPhoneSignalScanningTimer = new StopwatchTimer(null, -200+1, null, mUnpluggables, in); + mPhoneSignalScanningTimer = new StopwatchTimer(null, -200+1, null, mOnBatteryTimeBase, in); for (int i=0; i<NUM_DATA_CONNECTION_TYPES; i++) { mPhoneDataConnectionsTimer[i] = new StopwatchTimer(null, -300-i, - null, mUnpluggables, in); + null, mOnBatteryTimeBase, in); } for (int i = 0; i < NUM_NETWORK_ACTIVITY_TYPES; i++) { - mNetworkByteActivityCounters[i] = new LongSamplingCounter(mUnpluggables, in); - mNetworkPacketActivityCounters[i] = new LongSamplingCounter(mUnpluggables, in); + mNetworkByteActivityCounters[i] = new LongSamplingCounter(mOnBatteryTimeBase, in); + mNetworkPacketActivityCounters[i] = new LongSamplingCounter(mOnBatteryTimeBase, in); } mMobileRadioActive = false; - mMobileRadioActiveTimer = new StopwatchTimer(null, -400, null, mUnpluggables, in); - mMobileRadioActivePerAppTimer = new StopwatchTimer(null, -401, null, mUnpluggables, in); - mMobileRadioActiveUnknownTime = new LongSamplingCounter(mUnpluggables, in); - mMobileRadioActiveUnknownCount = new LongSamplingCounter(mUnpluggables, in); + mMobileRadioActiveTimer = new StopwatchTimer(null, -400, null, mOnBatteryTimeBase, in); + mMobileRadioActivePerAppTimer = new StopwatchTimer(null, -401, null, mOnBatteryTimeBase, + in); + mMobileRadioActiveUnknownTime = new LongSamplingCounter(mOnBatteryTimeBase, in); + mMobileRadioActiveUnknownCount = new LongSamplingCounter(mOnBatteryTimeBase, in); mWifiOn = false; - mWifiOnTimer = new StopwatchTimer(null, -2, null, mUnpluggables, in); + mWifiOnTimer = new StopwatchTimer(null, -2, null, mOnBatteryTimeBase, in); mGlobalWifiRunning = false; - mGlobalWifiRunningTimer = new StopwatchTimer(null, -2, null, mUnpluggables, in); + mGlobalWifiRunningTimer = new StopwatchTimer(null, -2, null, mOnBatteryTimeBase, in); for (int i=0; i<NUM_WIFI_STATES; i++) { mWifiStateTimer[i] = new StopwatchTimer(null, -600-i, - null, mUnpluggables, in); + null, mOnBatteryTimeBase, in); } mBluetoothOn = false; - mBluetoothOnTimer = new StopwatchTimer(null, -2, null, mUnpluggables, in); + mBluetoothOnTimer = new StopwatchTimer(null, -2, null, mOnBatteryTimeBase, in); for (int i=0; i< NUM_BLUETOOTH_STATES; i++) { mBluetoothStateTimer[i] = new StopwatchTimer(null, -500-i, - null, mUnpluggables, in); + null, mOnBatteryTimeBase, in); } - mUptime = in.readLong(); - mUptimeStart = in.readLong(); - mLastUptime = 0; - mRealtime = in.readLong(); - mRealtimeStart = in.readLong(); - mLastRealtime = 0; - mOnBattery = in.readInt() != 0; - mOnBatteryInternal = false; // we are no longer really running. - mTrackBatteryPastUptime = in.readLong(); - mTrackBatteryUptimeStart = in.readLong(); - mTrackBatteryPastRealtime = in.readLong(); - mTrackBatteryRealtimeStart = in.readLong(); - mUnpluggedBatteryUptime = in.readLong(); - mUnpluggedBatteryRealtime = in.readLong(); mDischargeUnplugLevel = in.readInt(); mDischargeCurrentLevel = in.readInt(); mLowDischargeAmountSinceCharge = in.readInt(); @@ -6926,7 +7071,7 @@ public final class BatteryStatsImpl extends BatteryStats { if (in.readInt() != 0) { String wakelockName = in.readString(); in.readInt(); // Extra 0/1 written by Timer.writeTimerToParcel - SamplingTimer kwlt = new SamplingTimer(mUnpluggables, mOnBattery, in); + SamplingTimer kwlt = new SamplingTimer(mOnBatteryTimeBase, in); mKernelWakelockStats.put(wakelockName, kwlt); } } @@ -6947,7 +7092,7 @@ public final class BatteryStatsImpl extends BatteryStats { for (int i = 0; i < numUids; i++) { int uid = in.readInt(); Uid u = new Uid(uid); - u.readFromParcelLocked(mUnpluggables, in); + u.readFromParcelLocked(mOnBatteryTimeBase, mOnBatteryScreenOffTimeBase, in); mUidStats.append(uid, u); } } @@ -6967,58 +7112,53 @@ public final class BatteryStatsImpl extends BatteryStats { final long uSecUptime = SystemClock.uptimeMillis() * 1000; final long uSecRealtime = SystemClock.elapsedRealtime() * 1000; - final long batteryUptime = getBatteryUptimeLocked(uSecUptime); - final long batteryRealtime = getBatteryRealtimeLocked(uSecRealtime); + final long batteryRealtime = mOnBatteryTimeBase.getRealtime(uSecRealtime); + final long batteryScreenOffRealtime = mOnBatteryScreenOffTimeBase.getRealtime(uSecRealtime); out.writeInt(MAGIC); writeHistory(out, false); out.writeInt(mStartCount); - out.writeLong(mBatteryUptime); - out.writeLong(mBatteryRealtime); out.writeLong(mStartClockTime); - mScreenOnTimer.writeToParcel(out, batteryRealtime); + out.writeLong(mUptime); + out.writeLong(mUptimeStart); + out.writeLong(mRealtime); + out.writeLong(mRealtimeStart); + out.writeInt(mOnBattery ? 1 : 0); + mOnBatteryTimeBase.writeToParcel(out, uSecUptime, uSecRealtime); + mOnBatteryScreenOffTimeBase.writeToParcel(out, uSecUptime, uSecRealtime); + + mScreenOnTimer.writeToParcel(out, uSecRealtime); for (int i=0; i<NUM_SCREEN_BRIGHTNESS_BINS; i++) { - mScreenBrightnessTimer[i].writeToParcel(out, batteryRealtime); + mScreenBrightnessTimer[i].writeToParcel(out, uSecRealtime); } mInputEventCounter.writeToParcel(out); - mPhoneOnTimer.writeToParcel(out, batteryRealtime); + mPhoneOnTimer.writeToParcel(out, uSecRealtime); for (int i=0; i<SignalStrength.NUM_SIGNAL_STRENGTH_BINS; i++) { - mPhoneSignalStrengthsTimer[i].writeToParcel(out, batteryRealtime); + mPhoneSignalStrengthsTimer[i].writeToParcel(out, uSecRealtime); } - mPhoneSignalScanningTimer.writeToParcel(out, batteryRealtime); + mPhoneSignalScanningTimer.writeToParcel(out, uSecRealtime); for (int i=0; i<NUM_DATA_CONNECTION_TYPES; i++) { - mPhoneDataConnectionsTimer[i].writeToParcel(out, batteryRealtime); + mPhoneDataConnectionsTimer[i].writeToParcel(out, uSecRealtime); } for (int i = 0; i < NUM_NETWORK_ACTIVITY_TYPES; i++) { mNetworkByteActivityCounters[i].writeToParcel(out); mNetworkPacketActivityCounters[i].writeToParcel(out); } - mMobileRadioActiveTimer.writeToParcel(out, batteryRealtime); - mMobileRadioActivePerAppTimer.writeToParcel(out, batteryRealtime); + mMobileRadioActiveTimer.writeToParcel(out, uSecRealtime); + mMobileRadioActivePerAppTimer.writeToParcel(out, uSecRealtime); mMobileRadioActiveUnknownTime.writeToParcel(out); mMobileRadioActiveUnknownCount.writeToParcel(out); - mWifiOnTimer.writeToParcel(out, batteryRealtime); - mGlobalWifiRunningTimer.writeToParcel(out, batteryRealtime); + mWifiOnTimer.writeToParcel(out, uSecRealtime); + mGlobalWifiRunningTimer.writeToParcel(out, uSecRealtime); for (int i=0; i<NUM_WIFI_STATES; i++) { - mWifiStateTimer[i].writeToParcel(out, batteryRealtime); + mWifiStateTimer[i].writeToParcel(out, uSecRealtime); } - mBluetoothOnTimer.writeToParcel(out, batteryRealtime); + mBluetoothOnTimer.writeToParcel(out, uSecRealtime); for (int i=0; i< NUM_BLUETOOTH_STATES; i++) { - mBluetoothStateTimer[i].writeToParcel(out, batteryRealtime); + mBluetoothStateTimer[i].writeToParcel(out, uSecRealtime); } - out.writeLong(mUptime); - out.writeLong(mUptimeStart); - out.writeLong(mRealtime); - out.writeLong(mRealtimeStart); - out.writeInt(mOnBattery ? 1 : 0); - out.writeLong(batteryUptime); - out.writeLong(mTrackBatteryUptimeStart); - out.writeLong(batteryRealtime); - out.writeLong(mTrackBatteryRealtimeStart); - out.writeLong(mUnpluggedBatteryUptime); - out.writeLong(mUnpluggedBatteryRealtime); out.writeInt(mDischargeUnplugLevel); out.writeInt(mDischargeCurrentLevel); out.writeInt(mLowDischargeAmountSinceCharge); @@ -7038,7 +7178,7 @@ public final class BatteryStatsImpl extends BatteryStats { if (kwlt != null) { out.writeInt(1); out.writeString(ent.getKey()); - Timer.writeTimerToParcel(out, kwlt, batteryRealtime); + Timer.writeTimerToParcel(out, kwlt, uSecRealtime); } else { out.writeInt(0); } @@ -7056,7 +7196,7 @@ public final class BatteryStatsImpl extends BatteryStats { out.writeInt(mUidStats.keyAt(i)); Uid uid = mUidStats.valueAt(i); - uid.writeToParcelLocked(out, batteryRealtime); + uid.writeToParcelLocked(out, uSecRealtime); } } else { out.writeInt(0); @@ -7082,6 +7222,10 @@ public final class BatteryStatsImpl extends BatteryStats { public void dumpLocked(Context context, PrintWriter pw, boolean isUnpluggedOnly, int reqUid, boolean historyOnly) { if (DEBUG) { + pw.println("mOnBatteryTimeBase:"); + mOnBatteryTimeBase.dump(pw, " "); + pw.println("mOnBatteryScreenOffTimeBase:"); + mOnBatteryScreenOffTimeBase.dump(pw, " "); Printer pr = new PrintWriterPrinter(pw); pr.println("*** Screen timer:"); mScreenOnTimer.logState(pr, " "); diff --git a/core/java/com/android/internal/view/IInputMethodManager.aidl b/core/java/com/android/internal/view/IInputMethodManager.aidl index 325a27d70a3c..e51345cb619b 100644 --- a/core/java/com/android/internal/view/IInputMethodManager.aidl +++ b/core/java/com/android/internal/view/IInputMethodManager.aidl @@ -32,7 +32,9 @@ import com.android.internal.view.IInputMethodClient; * this file. */ interface IInputMethodManager { + // TODO: Use ParceledListSlice instead List<InputMethodInfo> getInputMethodList(); + // TODO: Use ParceledListSlice instead List<InputMethodInfo> getEnabledInputMethodList(); List<InputMethodSubtype> getEnabledInputMethodSubtypeList(in String imiId, boolean allowsImplicitlySelectedSubtypes); diff --git a/core/jni/android/graphics/Path.cpp b/core/jni/android/graphics/Path.cpp index 429f177c9d9d..e580d36ac867 100644 --- a/core/jni/android/graphics/Path.cpp +++ b/core/jni/android/graphics/Path.cpp @@ -72,11 +72,16 @@ public: *dst = *src; } + static jboolean isConvex(JNIEnv* env, jobject clazz, jlong objHandle) { + SkPath* obj = reinterpret_cast<SkPath*>(objHandle); + return obj->isConvex(); + } + static jint getFillType(JNIEnv* env, jobject clazz, jlong objHandle) { SkPath* obj = reinterpret_cast<SkPath*>(objHandle); return obj->getFillType(); } - + static void setFillType(JNIEnv* env, jobject clazz, jlong pathHandle, jint ftHandle) { SkPath* path = reinterpret_cast<SkPath*>(pathHandle); SkPath::FillType ft = static_cast<SkPath::FillType>(ftHandle); @@ -524,6 +529,7 @@ static JNINativeMethod methods[] = { {"native_reset","(J)V", (void*) SkPathGlue::reset}, {"native_rewind","(J)V", (void*) SkPathGlue::rewind}, {"native_set","(JJ)V", (void*) SkPathGlue::assign}, + {"native_isConvex","(J)Z", (void*) SkPathGlue::isConvex}, {"native_getFillType","(J)I", (void*) SkPathGlue::getFillType}, {"native_setFillType","(JI)V", (void*) SkPathGlue::setFillType}, {"native_isEmpty","(J)Z", (void*) SkPathGlue::isEmpty}, diff --git a/core/res/res/drawable/notification_quantum_background.xml b/core/res/res/drawable/notification_quantum_background.xml new file mode 100644 index 000000000000..f33e2e36621c --- /dev/null +++ b/core/res/res/drawable/notification_quantum_background.xml @@ -0,0 +1,21 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- + ~ Copyright (C) 2014 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 + --> + +<shape xmlns:android="http://schemas.android.com/apk/res/android"> + <solid android:color="#ffffffff" /> + <corners android:radius="2dp" /> +</shape>
\ No newline at end of file diff --git a/core/res/res/drawable/notification_quantum_bg.xml b/core/res/res/drawable/notification_quantum_bg.xml new file mode 100644 index 000000000000..608115e631e9 --- /dev/null +++ b/core/res/res/drawable/notification_quantum_bg.xml @@ -0,0 +1,21 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- + ~ Copyright (C) 2014 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 + --> + +<selector xmlns:android="http://schemas.android.com/apk/res/android"> + <item android:state_pressed="true" android:drawable="@drawable/notification_quantum_press" /> + <item android:state_pressed="false" android:drawable="@drawable/notification_quantum_background" /> +</selector>
\ No newline at end of file diff --git a/core/res/res/drawable/notification_quantum_press.xml b/core/res/res/drawable/notification_quantum_press.xml new file mode 100644 index 000000000000..4999f55cc0f6 --- /dev/null +++ b/core/res/res/drawable/notification_quantum_press.xml @@ -0,0 +1,21 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- + ~ Copyright (C) 2014 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 + --> + +<shape xmlns:android="http://schemas.android.com/apk/res/android"> + <solid android:color="#ffcccccc" /> + <corners android:radius="2dp" /> +</shape>
\ No newline at end of file diff --git a/core/res/res/layout/notification_quantum_action.xml b/core/res/res/layout/notification_quantum_action.xml new file mode 100644 index 000000000000..775182f4a699 --- /dev/null +++ b/core/res/res/layout/notification_quantum_action.xml @@ -0,0 +1,31 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- + ~ Copyright (C) 2014 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 + --> + +<Button xmlns:android="http://schemas.android.com/apk/res/android" + style="?android:attr/borderlessButtonStyle" + android:id="@+id/action0" + android:layout_width="0dp" + android:layout_height="48dp" + android:layout_weight="1" + android:gravity="start|center_vertical" + android:drawablePadding="8dp" + android:paddingStart="8dp" + android:textColor="#555555" + android:textSize="14dp" + android:singleLine="true" + android:ellipsize="end" + /> diff --git a/core/res/res/layout/notification_quantum_action_list.xml b/core/res/res/layout/notification_quantum_action_list.xml new file mode 100644 index 000000000000..a8aef97e48ab --- /dev/null +++ b/core/res/res/layout/notification_quantum_action_list.xml @@ -0,0 +1,30 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- Copyright (C) 2014 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. +--> + +<LinearLayout + xmlns:android="http://schemas.android.com/apk/res/android" + android:id="@+id/actions" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:orientation="horizontal" + android:visibility="gone" + android:layout_marginBottom="8dp" + android:showDividers="middle" + android:divider="?android:attr/listDivider" + android:dividerPadding="12dp" + > + <!-- actions will be added here --> +</LinearLayout> diff --git a/core/res/res/layout/notification_quantum_action_tombstone.xml b/core/res/res/layout/notification_quantum_action_tombstone.xml new file mode 100644 index 000000000000..9104991585fb --- /dev/null +++ b/core/res/res/layout/notification_quantum_action_tombstone.xml @@ -0,0 +1,33 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- + ~ Copyright (C) 2014 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 + --> + +<Button xmlns:android="http://schemas.android.com/apk/res/android" + style="?android:attr/borderlessButtonStyle" + android:id="@+id/action0" + android:layout_width="0dp" + android:layout_height="48dp" + android:layout_weight="1" + android:gravity="start|center_vertical" + android:drawablePadding="8dp" + android:paddingStart="8dp" + android:textColor="#555555" + android:textSize="14dp" + android:singleLine="true" + android:ellipsize="end" + android:alpha="0.5" + android:enabled="false" + /> diff --git a/core/res/res/layout/notification_template_quantum_base.xml b/core/res/res/layout/notification_template_quantum_base.xml new file mode 100644 index 000000000000..3e97b2aecc0c --- /dev/null +++ b/core/res/res/layout/notification_template_quantum_base.xml @@ -0,0 +1,137 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- + ~ Copyright (C) 2014 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 + --> + +<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:internal="http://schemas.android.com/apk/prv/res/android" + android:background="@android:drawable/notification_quantum_bg" + android:id="@+id/status_bar_latest_event_content" + android:layout_width="match_parent" + android:layout_height="64dp" + internal:layout_minHeight="64dp" + internal:layout_maxHeight="64dp" + > + <ImageView android:id="@+id/icon" + android:layout_width="@dimen/notification_large_icon_width" + android:layout_height="@dimen/notification_large_icon_height" + android:scaleType="center" + /> + <LinearLayout + android:layout_width="match_parent" + android:layout_height="wrap_content" + + android:layout_gravity="fill_vertical" + android:layout_marginStart="@dimen/notification_large_icon_width" + android:minHeight="@dimen/notification_large_icon_height" + android:orientation="vertical" + android:paddingEnd="8dp" + android:paddingTop="2dp" + android:paddingBottom="2dp" + android:gravity="top" + > + <LinearLayout + android:id="@+id/line1" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:paddingTop="6dp" + android:layout_marginStart="8dp" + android:orientation="horizontal" + > + <TextView android:id="@+id/title" + android:textAppearance="@style/TextAppearance.StatusBar.Quantum.EventContent.Title" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:singleLine="true" + android:ellipsize="marquee" + android:fadingEdge="horizontal" + android:layout_weight="1" + /> + <ViewStub android:id="@+id/time" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:layout_weight="0" + android:visibility="gone" + android:layout="@layout/notification_template_part_time" + /> + <ViewStub android:id="@+id/chronometer" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:layout_weight="0" + android:visibility="gone" + android:layout="@layout/notification_template_part_chronometer" + /> + </LinearLayout> + <TextView android:id="@+id/text2" + android:textAppearance="@style/TextAppearance.StatusBar.Quantum.EventContent.Line2" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:layout_marginTop="-2dp" + android:layout_marginBottom="-2dp" + android:layout_marginStart="8dp" + android:singleLine="true" + android:fadingEdge="horizontal" + android:ellipsize="marquee" + android:visibility="gone" + /> + <ProgressBar + android:id="@android:id/progress" + android:layout_width="match_parent" + android:layout_height="12dp" + android:layout_marginStart="8dp" + android:visibility="gone" + style="?android:attr/progressBarStyleHorizontal" + /> + <LinearLayout + android:id="@+id/line3" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:orientation="horizontal" + android:gravity="center_vertical" + android:layout_marginStart="8dp" + > + <TextView android:id="@+id/text" + android:textAppearance="@style/TextAppearance.StatusBar.Quantum.EventContent" + android:layout_width="0dp" + android:layout_height="wrap_content" + android:layout_weight="1" + android:layout_gravity="center" + android:singleLine="true" + android:ellipsize="marquee" + android:fadingEdge="horizontal" + /> + <TextView android:id="@+id/info" + android:textAppearance="@style/TextAppearance.StatusBar.Quantum.EventContent.Info" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:layout_gravity="center" + android:layout_weight="0" + android:singleLine="true" + android:gravity="center" + android:paddingStart="8dp" + /> + <ImageView android:id="@+id/right_icon" + android:layout_width="16dp" + android:layout_height="16dp" + android:layout_gravity="center" + android:layout_weight="0" + android:layout_marginStart="8dp" + android:scaleType="centerInside" + android:visibility="gone" + android:drawableAlpha="153" + /> + </LinearLayout> + </LinearLayout> +</FrameLayout> diff --git a/core/res/res/layout/notification_template_quantum_big_base.xml b/core/res/res/layout/notification_template_quantum_big_base.xml new file mode 100644 index 000000000000..d86004580d0f --- /dev/null +++ b/core/res/res/layout/notification_template_quantum_big_base.xml @@ -0,0 +1,167 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- + ~ Copyright (C) 2014 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 + --> + +<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:internal="http://schemas.android.com/apk/prv/res/android" + android:background="@android:drawable/notification_quantum_bg" + android:id="@+id/status_bar_latest_event_content" + android:layout_width="match_parent" + android:layout_height="wrap_content" + internal:layout_minHeight="65dp" + internal:layout_maxHeight="unbounded" + > + <ImageView android:id="@+id/icon" + android:layout_width="@dimen/notification_large_icon_width" + android:layout_height="@dimen/notification_large_icon_height" + android:scaleType="center" + /> + <LinearLayout + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:layout_gravity="fill_vertical" + android:minHeight="@dimen/notification_large_icon_height" + android:orientation="vertical" + android:gravity="top" + > + <LinearLayout + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:layout_marginStart="@dimen/notification_large_icon_width" + android:minHeight="@dimen/notification_large_icon_height" + android:paddingTop="2dp" + android:orientation="vertical" + > + <LinearLayout + android:id="@+id/line1" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:paddingTop="6dp" + android:layout_marginEnd="8dp" + android:layout_marginStart="8dp" + android:orientation="horizontal" + > + <TextView android:id="@+id/title" + android:textAppearance="@style/TextAppearance.StatusBar.Quantum.EventContent.Title" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:singleLine="true" + android:ellipsize="marquee" + android:fadingEdge="horizontal" + android:layout_weight="1" + /> + <ViewStub android:id="@+id/time" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:layout_weight="0" + android:visibility="gone" + android:layout="@layout/notification_template_part_time" + /> + <ViewStub android:id="@+id/chronometer" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:layout_weight="0" + android:visibility="gone" + android:layout="@layout/notification_template_part_chronometer" + /> + </LinearLayout> + <TextView android:id="@+id/text2" + android:textAppearance="@style/TextAppearance.StatusBar.Quantum.EventContent.Line2" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:layout_marginTop="-2dp" + android:layout_marginBottom="-2dp" + android:layout_marginStart="8dp" + android:layout_marginEnd="8dp" + android:singleLine="true" + android:fadingEdge="horizontal" + android:ellipsize="marquee" + android:visibility="gone" + /> + <TextView android:id="@+id/big_text" + android:textAppearance="@style/TextAppearance.StatusBar.Quantum.EventContent" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:layout_marginStart="8dp" + android:layout_marginEnd="8dp" + android:singleLine="false" + android:visibility="gone" + /> + <LinearLayout + android:id="@+id/line3" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:layout_marginStart="8dp" + android:layout_marginEnd="8dp" + android:orientation="horizontal" + android:gravity="center_vertical" + > + <TextView android:id="@+id/text" + android:textAppearance="@style/TextAppearance.StatusBar.Quantum.EventContent" + android:layout_width="0dp" + android:layout_height="wrap_content" + android:layout_weight="1" + android:layout_gravity="center" + android:singleLine="true" + android:ellipsize="marquee" + android:fadingEdge="horizontal" + /> + <TextView android:id="@+id/info" + android:textAppearance="@style/TextAppearance.StatusBar.Quantum.EventContent.Info" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:layout_gravity="center" + android:layout_weight="0" + android:singleLine="true" + android:gravity="center" + android:paddingStart="8dp" + /> + <ImageView android:id="@+id/right_icon" + android:layout_width="16dp" + android:layout_height="16dp" + android:layout_gravity="center" + android:layout_weight="0" + android:layout_marginStart="8dp" + android:scaleType="centerInside" + android:visibility="gone" + android:drawableAlpha="153" + /> + </LinearLayout> + <ProgressBar + android:id="@android:id/progress" + android:layout_width="match_parent" + android:layout_height="12dp" + android:layout_marginBottom="8dp" + android:layout_marginStart="8dp" + android:layout_marginEnd="8dp" + android:visibility="gone" + style="?android:attr/progressBarStyleHorizontal" + /> + </LinearLayout> + <ImageView + android:layout_width="match_parent" + android:layout_height="1dp" + android:id="@+id/action_divider" + android:visibility="gone" + android:background="?android:attr/dividerHorizontal" /> + <include + layout="@layout/notification_quantum_action_list" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:layout_marginStart="@dimen/notification_large_icon_width" + /> + </LinearLayout> +</FrameLayout> diff --git a/core/res/res/layout/notification_template_quantum_big_picture.xml b/core/res/res/layout/notification_template_quantum_big_picture.xml new file mode 100644 index 000000000000..e49c3bd9265f --- /dev/null +++ b/core/res/res/layout/notification_template_quantum_big_picture.xml @@ -0,0 +1,62 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- + ~ Copyright (C) 2014 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 + --> + +<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:internal="http://schemas.android.com/apk/prv/res/android" + android:background="@android:drawable/notification_quantum_bg" + android:id="@+id/status_bar_latest_event_content" + android:layout_width="match_parent" + android:layout_height="match_parent" + internal:layout_minHeight="65dp" + internal:layout_maxHeight="unbounded" + > + <ImageView + android:id="@+id/big_picture" + android:layout_width="match_parent" + android:layout_height="192dp" + android:layout_marginTop="64dp" + android:layout_gravity="bottom" + android:scaleType="centerCrop" + /> + <ImageView + android:layout_width="match_parent" + android:layout_height="6dp" + android:layout_marginTop="64dp" + android:scaleType="fitXY" + android:src="@drawable/title_bar_shadow" + /> + <include layout="@layout/notification_template_quantum_base" + android:layout_width="match_parent" + android:layout_height="wrap_content" + /> + <FrameLayout + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:layout_marginTop="208dp" + android:paddingStart="64dp" + android:layout_gravity="bottom" + android:background="#CCEEEEEE" + > + <include + layout="@layout/notification_quantum_action_list" + android:id="@+id/actions" + android:layout_gravity="bottom" + android:layout_width="match_parent" + android:layout_height="wrap_content" + /> + </FrameLayout> +</FrameLayout> diff --git a/core/res/res/layout/notification_template_quantum_big_text.xml b/core/res/res/layout/notification_template_quantum_big_text.xml new file mode 100644 index 000000000000..585be8038bd0 --- /dev/null +++ b/core/res/res/layout/notification_template_quantum_big_text.xml @@ -0,0 +1,182 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- + ~ Copyright (C) 2014 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 + --> +<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:internal="http://schemas.android.com/apk/prv/res/android" + android:background="@android:drawable/notification_quantum_bg" + android:id="@+id/status_bar_latest_event_content" + android:layout_width="match_parent" + android:layout_height="wrap_content" + internal:layout_minHeight="65dp" + internal:layout_maxHeight="unbounded" + > + <ImageView android:id="@+id/icon" + android:layout_width="@dimen/notification_large_icon_width" + android:layout_height="@dimen/notification_large_icon_height" + android:scaleType="center" + /> + <LinearLayout + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:layout_gravity="fill_vertical" + android:layout_marginStart="@dimen/notification_large_icon_width" + android:orientation="vertical" + android:paddingTop="0dp" + android:paddingBottom="2dp" + android:gravity="top" + > + <LinearLayout + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:minHeight="@dimen/notification_large_icon_height" + android:orientation="vertical" + android:layout_marginStart="8dp" + android:layout_marginEnd="8dp" + android:layout_weight="1" + > + <LinearLayout + android:id="@+id/line1" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:paddingTop="8dp" + android:orientation="horizontal" + android:layout_gravity="top" + android:layout_weight="0" + > + <TextView android:id="@+id/title" + android:textAppearance="@style/TextAppearance.StatusBar.Quantum.EventContent.Title" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:singleLine="true" + android:ellipsize="marquee" + android:fadingEdge="horizontal" + android:layout_weight="1" + /> + <ViewStub android:id="@+id/time" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:layout_weight="0" + android:visibility="gone" + android:layout="@layout/notification_template_part_time" + /> + <ViewStub android:id="@+id/chronometer" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:layout_weight="0" + android:visibility="gone" + android:layout="@layout/notification_template_part_chronometer" + /> + </LinearLayout> + <TextView android:id="@+id/text2" + android:textAppearance="@style/TextAppearance.StatusBar.Quantum.EventContent.Line2" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:layout_marginTop="-2dp" + android:layout_marginBottom="-2dp" + android:layout_marginEnd="8dp" + android:singleLine="true" + android:fadingEdge="horizontal" + android:ellipsize="marquee" + android:layout_weight="0" + android:visibility="gone" + /> + <ProgressBar + android:id="@android:id/progress" + android:layout_width="match_parent" + android:layout_height="12dp" + android:layout_marginBottom="8dp" + android:layout_marginEnd="8dp" + android:visibility="gone" + android:layout_weight="0" + style="?android:attr/progressBarStyleHorizontal" + /> + <TextView android:id="@+id/big_text" + android:textAppearance="@style/TextAppearance.StatusBar.Quantum.EventContent" + android:layout_width="match_parent" + android:layout_height="0dp" + android:layout_marginBottom="10dp" + android:layout_marginEnd="8dp" + android:singleLine="false" + android:visibility="gone" + android:maxLines="8" + android:ellipsize="end" + android:layout_weight="1" + /> + </LinearLayout> + <ImageView + android:layout_width="match_parent" + android:layout_height="1dip" + android:id="@+id/action_divider" + android:visibility="gone" + android:background="?android:attr/dividerHorizontal" /> + <include + layout="@layout/notification_quantum_action_list" + android:layout_width="match_parent" + android:layout_height="0dp" + android:visibility="gone" + android:layout_weight="1" + /> + <ImageView + android:layout_width="match_parent" + android:layout_height="1dp" + android:id="@+id/overflow_divider" + android:layout_marginBottom="8dp" + android:visibility="visible" + android:background="?android:attr/dividerHorizontal" /> + <LinearLayout + android:id="@+id/line3" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:layout_marginStart="8dp" + android:layout_marginBottom="8dp" + android:layout_marginEnd="8dp" + android:orientation="horizontal" + android:layout_weight="0" + android:gravity="center_vertical" + > + <TextView android:id="@+id/text" + android:textAppearance="@style/TextAppearance.StatusBar.Quantum.EventContent" + android:layout_width="0dp" + android:layout_height="wrap_content" + android:layout_weight="1" + android:layout_gravity="center" + android:singleLine="true" + android:ellipsize="marquee" + android:fadingEdge="horizontal" + /> + <TextView android:id="@+id/info" + android:textAppearance="@style/TextAppearance.StatusBar.Quantum.EventContent.Info" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:layout_gravity="center" + android:layout_weight="0" + android:singleLine="true" + android:gravity="center" + android:paddingStart="8dp" + /> + <ImageView android:id="@+id/right_icon" + android:layout_width="16dp" + android:layout_height="16dp" + android:layout_gravity="center" + android:layout_weight="0" + android:layout_marginStart="8dp" + android:scaleType="centerInside" + android:visibility="gone" + android:drawableAlpha="153" + /> + </LinearLayout> + </LinearLayout> +</FrameLayout> diff --git a/core/res/res/layout/notification_template_quantum_inbox.xml b/core/res/res/layout/notification_template_quantum_inbox.xml new file mode 100644 index 000000000000..31ed50878f3a --- /dev/null +++ b/core/res/res/layout/notification_template_quantum_inbox.xml @@ -0,0 +1,266 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- + ~ Copyright (C) 2014 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 + --> + +<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:internal="http://schemas.android.com/apk/prv/res/android" + android:id="@+id/status_bar_latest_event_content" + android:background="@android:drawable/notification_quantum_bg" + android:layout_width="match_parent" + android:layout_height="wrap_content" + internal:layout_minHeight="65dp" + internal:layout_maxHeight="unbounded" + > + <ImageView android:id="@+id/icon" + android:layout_width="@dimen/notification_large_icon_width" + android:layout_height="@dimen/notification_large_icon_height" + android:scaleType="center" + /> + <LinearLayout + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:layout_gravity="fill_vertical" + android:layout_marginStart="@dimen/notification_large_icon_width" + android:minHeight="@dimen/notification_large_icon_height" + android:orientation="vertical" + android:paddingTop="0dp" + android:paddingBottom="2dp" + android:gravity="top" + > + <LinearLayout + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:minHeight="@dimen/notification_large_icon_height" + android:paddingTop="2dp" + android:orientation="vertical" + > + <LinearLayout + android:id="@+id/line1" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:layout_marginStart="8dp" + android:layout_marginEnd="8dp" + android:paddingTop="6dp" + android:orientation="horizontal" + android:layout_weight="0" + > + <TextView android:id="@+id/title" + android:textAppearance="@style/TextAppearance.StatusBar.Quantum.EventContent.Title" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:singleLine="true" + android:ellipsize="marquee" + android:fadingEdge="horizontal" + android:layout_weight="1" + /> + <ViewStub android:id="@+id/time" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:layout_weight="0" + android:visibility="gone" + android:layout="@layout/notification_template_part_time" + /> + <ViewStub android:id="@+id/chronometer" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:layout_weight="0" + android:visibility="gone" + android:layout="@layout/notification_template_part_chronometer" + /> + </LinearLayout> + <TextView android:id="@+id/text2" + android:textAppearance="@style/TextAppearance.StatusBar.Quantum.EventContent.Line2" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:layout_marginTop="-2dp" + android:layout_marginBottom="-2dp" + android:layout_marginStart="8dp" + android:layout_marginEnd="8dp" + android:singleLine="true" + android:fadingEdge="horizontal" + android:ellipsize="marquee" + android:visibility="gone" + android:layout_weight="0" + /> + <ProgressBar + android:id="@android:id/progress" + android:layout_width="match_parent" + android:layout_height="12dp" + android:layout_marginStart="8dp" + android:layout_marginEnd="8dp" + android:visibility="gone" + android:layout_weight="0" + style="?android:attr/progressBarStyleHorizontal" + /> + <TextView android:id="@+id/inbox_text0" + android:textAppearance="@style/TextAppearance.StatusBar.Quantum.EventContent" + android:layout_width="match_parent" + android:layout_height="0dp" + android:layout_marginStart="8dp" + android:layout_marginEnd="8dp" + android:singleLine="true" + android:ellipsize="end" + android:visibility="gone" + android:layout_weight="1" + /> + <TextView android:id="@+id/inbox_text1" + android:textAppearance="@style/TextAppearance.StatusBar.Quantum.EventContent" + android:layout_width="match_parent" + android:layout_height="0dp" + android:layout_marginStart="8dp" + android:layout_marginEnd="8dp" + android:singleLine="true" + android:ellipsize="end" + android:visibility="gone" + android:layout_weight="1" + /> + <TextView android:id="@+id/inbox_text2" + android:textAppearance="@style/TextAppearance.StatusBar.Quantum.EventContent" + android:layout_width="match_parent" + android:layout_height="0dp" + android:layout_marginStart="8dp" + android:layout_marginEnd="8dp" + android:singleLine="true" + android:ellipsize="end" + android:visibility="gone" + android:layout_weight="1" + /> + <TextView android:id="@+id/inbox_text3" + android:textAppearance="@style/TextAppearance.StatusBar.Quantum.EventContent" + android:layout_width="match_parent" + android:layout_height="0dp" + android:layout_marginStart="8dp" + android:layout_marginEnd="8dp" + android:singleLine="true" + android:ellipsize="end" + android:visibility="gone" + android:layout_weight="1" + /> + <TextView android:id="@+id/inbox_text4" + android:textAppearance="@style/TextAppearance.StatusBar.Quantum.EventContent" + android:layout_width="match_parent" + android:layout_height="0dp" + android:layout_marginStart="8dp" + android:singleLine="true" + android:ellipsize="end" + android:visibility="gone" + android:layout_weight="1" + /> + <TextView android:id="@+id/inbox_text5" + android:textAppearance="@style/TextAppearance.StatusBar.Quantum.EventContent" + android:layout_width="match_parent" + android:layout_height="0dp" + android:layout_marginStart="8dp" + android:layout_marginEnd="8dp" + android:singleLine="true" + android:ellipsize="end" + android:visibility="gone" + android:layout_weight="1" + /> + <TextView android:id="@+id/inbox_text6" + android:textAppearance="@style/TextAppearance.StatusBar.Quantum.EventContent" + android:layout_width="match_parent" + android:layout_height="0dp" + android:layout_marginStart="8dp" + android:layout_marginEnd="8dp" + android:singleLine="true" + android:ellipsize="end" + android:visibility="gone" + android:layout_weight="1" + /> + <TextView android:id="@+id/inbox_more" + android:textAppearance="@style/TextAppearance.StatusBar.Quantum.EventContent" + android:layout_width="match_parent" + android:layout_height="0dp" + android:layout_marginStart="8dp" + android:layout_marginEnd="8dp" + android:singleLine="true" + android:ellipsize="end" + android:visibility="gone" + android:layout_weight="1" + android:text="@android:string/ellipsis" + /> + <FrameLayout + android:id="@+id/inbox_end_pad" + android:layout_width="match_parent" + android:layout_height="8dip" + android:visibility="gone" + android:layout_weight="0" + /> + </LinearLayout> + <ImageView + android:layout_width="match_parent" + android:layout_height="1dip" + android:id="@+id/action_divider" + android:visibility="gone" + android:background="?android:attr/dividerHorizontal" /> + <include + layout="@layout/notification_quantum_action_list" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:layout_weight="0" + /> + <ImageView + android:layout_width="match_parent" + android:layout_height="1dip" + android:id="@+id/overflow_divider" + android:visibility="visible" + android:background="?android:attr/dividerHorizontal" /> + <LinearLayout + android:id="@+id/line3" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:layout_marginTop="8dp" + android:layout_marginStart="8dp" + android:layout_marginBottom="8dp" + android:layout_marginEnd="8dp" + android:orientation="horizontal" + android:layout_weight="0" + android:gravity="center_vertical" + > + <TextView android:id="@+id/text" + android:textAppearance="@style/TextAppearance.StatusBar.Quantum.EventContent" + android:layout_width="0dp" + android:layout_height="wrap_content" + android:layout_weight="1" + android:layout_gravity="center" + android:singleLine="true" + android:ellipsize="marquee" + android:fadingEdge="horizontal" + /> + <TextView android:id="@+id/info" + android:textAppearance="@style/TextAppearance.StatusBar.Quantum.EventContent.Info" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:layout_gravity="center" + android:layout_weight="0" + android:singleLine="true" + android:gravity="center" + android:paddingStart="8dp" + /> + <ImageView android:id="@+id/right_icon" + android:layout_width="16dp" + android:layout_height="16dp" + android:layout_gravity="center" + android:layout_weight="0" + android:layout_marginStart="8dp" + android:scaleType="centerInside" + android:visibility="gone" + android:drawableAlpha="153" + /> + </LinearLayout> + </LinearLayout> +</FrameLayout> diff --git a/core/res/res/values-iw/strings.xml b/core/res/res/values-iw/strings.xml index 096c4eddb87f..d3e1cddbd698 100644 --- a/core/res/res/values-iw/strings.xml +++ b/core/res/res/values-iw/strings.xml @@ -605,7 +605,7 @@ <string name="permlab_accessNetworkState" msgid="4951027964348974773">"הצג חיבורי רשת"</string> <string name="permdesc_accessNetworkState" msgid="8318964424675960975">"מאפשר לאפליקציה להציג מידע לגבי חיבורי רשת, למשל, אילו רשתות קיימות ומחוברות."</string> <string name="permlab_createNetworkSockets" msgid="8018758136404323658">"גישת רשת מלאה"</string> - <string name="permdesc_createNetworkSockets" msgid="3403062187779724185">"מאפשר לאפליקציה ליצור Sockets ולהשתמש בפרוטוקולי רשת מותאמים אישית. הדפדפן ואפליקציות אחרות מספקות אמצעים לשליחת נתונים לאינטרנט, כך שאישור זה אינו נחוץ לשליחת נתונים לאינטרנט."</string> + <string name="permdesc_createNetworkSockets" msgid="3403062187779724185">"מאפשר לאפליקציה ליצור Sockets ולהשתמש בפרוטוקולי רשת מותאמים אישית. הדפדפן, כמו אפליקציות אחרות, מספק אמצעים לשליחת נתונים לאינטרנט, כך שאישור זה אינו נחוץ לשליחת נתונים לאינטרנט."</string> <string name="permlab_writeApnSettings" msgid="505660159675751896">"שנה/עכב הגדרות רשת ותנועה"</string> <string name="permdesc_writeApnSettings" msgid="5333798886412714193">"מאפשר לאפליקציה לשנות את הגדרות הרשת ולעכב ולבדוק את כל תנועת הרשת, לדוגמה, לשנות את ה-proxy והיציאה של כל רשת APN. אפליקציות זדוניות עלולות לעקוב אחר חבילות רשת, לבצע הפניה מחדש שלהן או לשנות אותן, ללא ידיעתך."</string> <string name="permlab_changeNetworkState" msgid="958884291454327309">"שנה את קישוריות הרשת"</string> diff --git a/core/res/res/values-zh-rTW/strings.xml b/core/res/res/values-zh-rTW/strings.xml index ad2f63c931be..544fd5b5e15b 100644 --- a/core/res/res/values-zh-rTW/strings.xml +++ b/core/res/res/values-zh-rTW/strings.xml @@ -1138,7 +1138,7 @@ <string name="chooseUsbActivity" msgid="6894748416073583509">"選取要以 USB 裝置存取的應用程式"</string> <string name="noApplications" msgid="2991814273936504689">"沒有應用程式可執行這項操作。"</string> <string name="aerr_title" msgid="1905800560317137752"></string> - <string name="aerr_application" msgid="932628488013092776">"很抱歉,<xliff:g id="APPLICATION">%1$s</xliff:g> 已停止。"</string> + <string name="aerr_application" msgid="932628488013092776">"很抱歉,<xliff:g id="APPLICATION">%1$s</xliff:g>已停止運作。"</string> <string name="aerr_process" msgid="4507058997035697579">"很抱歉,處理程序 <xliff:g id="PROCESS">%1$s</xliff:g> 已停止。"</string> <string name="anr_title" msgid="4351948481459135709"></string> <string name="anr_activity_application" msgid="1904477189057199066">"<xliff:g id="APPLICATION">%2$s</xliff:g> 沒有回應。\n\n您要結束嗎?"</string> diff --git a/core/res/res/values/styles.xml b/core/res/res/values/styles.xml index e525ef71190c..be875ffb2b04 100644 --- a/core/res/res/values/styles.xml +++ b/core/res/res/values/styles.xml @@ -271,6 +271,33 @@ please see styles_device_defaults.xml. <item name="android:textColor">#CCCCCC</item> </style> + <style name="TextAppearance.StatusBar.Quantum"> + </style> + <style name="TextAppearance.StatusBar.Quantum.EventContent"> + <item name="android:textColor">#888888</item> + <item name="android:textSize">@dimen/notification_text_size</item> + </style> + <style name="TextAppearance.StatusBar.Quantum.EventContent.Title"> + <item name="android:textColor">#000000</item> + <item name="android:fontFamily">sans-serif-light</item> + <item name="android:textSize">@dimen/notification_title_text_size</item> + <item name="android:textStyle">bold</item> + </style> + <style name="TextAppearance.StatusBar.Quantum.EventContent.Line2"> + <item name="android:textSize">@dimen/notification_subtext_size</item> + </style> + <style name="TextAppearance.StatusBar.Quantum.EventContent.Info"> + <item name="android:textSize">@dimen/notification_subtext_size</item> + <item name="android:textColor">#888888</item> + </style> + <style name="TextAppearance.StatusBar.Quantum.EventContent.Time"> + <item name="android:textSize">@dimen/notification_subtext_size</item> + <item name="android:textColor">#888888</item> + </style> + <style name="TextAppearance.StatusBar.Quantum.EventContent.Emphasis"> + <item name="android:textColor">#555555</item> + </style> + <style name="TextAppearance.Small.CalendarViewWeekDayView"> <item name="android:textStyle">bold</item> </style> diff --git a/core/res/res/values/styles_micro.xml b/core/res/res/values/styles_micro.xml index b368b6577d82..52d90bce3ff9 100644 --- a/core/res/res/values/styles_micro.xml +++ b/core/res/res/values/styles_micro.xml @@ -25,9 +25,10 @@ <item name="android:solidColor">@android:color/transparent</item> <item name="android:selectionDivider">@android:drawable/numberpicker_selection_divider</item> <item name="android:selectionDividerHeight">0dip</item> - <item name="android:selectionDividersDistance">0dip</item> + <item name="android:selectionDividersDistance">104dip</item> <item name="android:internalMinWidth">64dip</item> <item name="android:internalMaxHeight">180dip</item> <item name="virtualButtonPressedDrawable">?android:attr/selectableItemBackground</item> + <item name="android:descendantFocusability">blocksDescendants</item> </style> </resources> diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml index a4f97629ae34..3a45d8c342db 100644 --- a/core/res/res/values/symbols.xml +++ b/core/res/res/values/symbols.xml @@ -1627,7 +1627,16 @@ <java-symbol type="integer" name="config_maxResolverActivityColumns" /> <java-symbol type="array" name="config_notificationScorers" /> - <!-- From SystemUI --> + <java-symbol type="layout" name="notification_quantum_action" /> + <java-symbol type="layout" name="notification_quantum_action_list" /> + <java-symbol type="layout" name="notification_quantum_action_tombstone" /> + <java-symbol type="layout" name="notification_template_quantum_base" /> + <java-symbol type="layout" name="notification_template_quantum_big_base" /> + <java-symbol type="layout" name="notification_template_quantum_big_picture" /> + <java-symbol type="layout" name="notification_template_quantum_big_text" /> + <java-symbol type="layout" name="notification_template_quantum_inbox" /> + + <!-- From SystemUI --> <java-symbol type="anim" name="push_down_in" /> <java-symbol type="anim" name="push_down_out" /> <java-symbol type="anim" name="push_up_in" /> diff --git a/core/res/res/values/themes_micro.xml b/core/res/res/values/themes_micro.xml index 42f64fe643ff..7c0b7bc1103d 100644 --- a/core/res/res/values/themes_micro.xml +++ b/core/res/res/values/themes_micro.xml @@ -14,7 +14,8 @@ limitations under the License. --> <resources> - <style name="Theme.Micro" parent="Theme.Holo"> + <style name="Theme.Micro" parent="Theme.Holo.NoActionBar"> + <item name="textViewStyle">@android:style/Widget.Micro.TextView</item> <item name="numberPickerStyle">@android:style/Widget.Micro.NumberPicker</item> <item name="windowAnimationStyle">@android:style/Animation.SwipeDismiss</item> <item name="windowIsFloating">false</item> @@ -31,7 +32,7 @@ <item name="windowSwipeToDismiss">true</item> </style> <style name="Theme.Micro.Light" parent="Theme.Holo.Light"> - <item name="numberPickerStyle">@android:style/Widget.Micro.NumberPicker</item> + <item name="numberPickerStyle">@android:style/Widget.Micro.NumberPicker</item> <item name="windowAnimationStyle">@android:style/Animation.SwipeDismiss</item> <item name="windowIsFloating">false</item> <item name="windowIsTranslucent">true</item> @@ -47,7 +48,7 @@ </style> <style name="Theme.Micro.Light.DarkActionBar" parent="Theme.Holo.Light.DarkActionBar"> <item name="textViewStyle">@android:style/Widget.Micro.TextView</item> - <item name="numberPickerStyle">@android:style/Widget.Micro.NumberPicker</item> + <item name="numberPickerStyle">@android:style/Widget.Micro.NumberPicker</item> <item name="windowAnimationStyle">@android:style/Animation.SwipeDismiss</item> <item name="windowIsFloating">false</item> <item name="windowIsTranslucent">true</item> diff --git a/core/tests/inputmethodtests/run_core_inputmethod_test.sh b/core/tests/inputmethodtests/run_core_inputmethod_test.sh index 5e123ec20a2f..b0b119b47004 100755 --- a/core/tests/inputmethodtests/run_core_inputmethod_test.sh +++ b/core/tests/inputmethodtests/run_core_inputmethod_test.sh @@ -21,4 +21,4 @@ if [[ $rebuild == true ]]; then $COMMAND fi -adb shell am instrument -w -e class android.os.InputMethodTest com.android.frameworks.coretests.inputmethod/android.test.InstrumentationTestRunner +adb shell am instrument -w -e class android.os.InputMethodTest,android.os.InputMethodSubtypeArrayTest com.android.frameworks.coretests.inputmethod/android.test.InstrumentationTestRunner diff --git a/core/tests/inputmethodtests/src/android/os/InputMethodSubtypeArrayTest.java b/core/tests/inputmethodtests/src/android/os/InputMethodSubtypeArrayTest.java new file mode 100644 index 000000000000..1e0a9190558e --- /dev/null +++ b/core/tests/inputmethodtests/src/android/os/InputMethodSubtypeArrayTest.java @@ -0,0 +1,77 @@ +/* + * Copyright (C) 2014 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; + +import android.test.InstrumentationTestCase; +import android.test.suitebuilder.annotation.SmallTest; +import android.view.inputmethod.InputMethodSubtype; +import android.view.inputmethod.InputMethodSubtypeArray; +import android.view.inputmethod.InputMethodSubtype.InputMethodSubtypeBuilder; + +import java.util.ArrayList; + +public class InputMethodSubtypeArrayTest extends InstrumentationTestCase { + @SmallTest + public void testInstanciate() throws Exception { + final ArrayList<InputMethodSubtype> subtypes = new ArrayList<InputMethodSubtype>(); + subtypes.add(createDummySubtype(0, "en_US")); + subtypes.add(createDummySubtype(1, "en_US")); + subtypes.add(createDummySubtype(2, "ja_JP")); + + final InputMethodSubtypeArray array = new InputMethodSubtypeArray(subtypes); + assertEquals(subtypes.size(), array.getCount()); + assertEquals(subtypes.get(0), array.get(0)); + assertEquals(subtypes.get(1), array.get(1)); + assertEquals(subtypes.get(2), array.get(2)); + + final InputMethodSubtypeArray clonedArray = cloneViaParcel(array); + assertEquals(subtypes.size(), clonedArray.getCount()); + assertEquals(subtypes.get(0), clonedArray.get(0)); + assertEquals(subtypes.get(1), clonedArray.get(1)); + assertEquals(subtypes.get(2), clonedArray.get(2)); + + final InputMethodSubtypeArray clonedClonedArray = cloneViaParcel(clonedArray); + assertEquals(clonedArray.getCount(), clonedClonedArray.getCount()); + assertEquals(clonedArray.get(0), clonedClonedArray.get(0)); + assertEquals(clonedArray.get(1), clonedClonedArray.get(1)); + assertEquals(clonedArray.get(2), clonedClonedArray.get(2)); + } + + InputMethodSubtypeArray cloneViaParcel(final InputMethodSubtypeArray original) { + Parcel parcel = null; + try { + parcel = Parcel.obtain(); + original.writeToParcel(parcel); + parcel.setDataPosition(0); + return new InputMethodSubtypeArray(parcel); + } finally { + if (parcel != null) { + parcel.recycle(); + } + } + } + + private static InputMethodSubtype createDummySubtype(final int id, final String locale) { + final InputMethodSubtypeBuilder builder = new InputMethodSubtypeBuilder(); + return builder.setSubtypeNameResId(0) + .setSubtypeIconResId(0) + .setSubtypeId(id) + .setSubtypeLocale(locale) + .setIsAsciiCapable(true) + .build(); + } +} diff --git a/data/keyboards/Vendor_18d1_Product_2c40.kl b/data/keyboards/Vendor_18d1_Product_2c40.kl new file mode 100644 index 000000000000..903f13b6418e --- /dev/null +++ b/data/keyboards/Vendor_18d1_Product_2c40.kl @@ -0,0 +1,42 @@ +# Copyright (C) 2013 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. + +# Odie + +key 304 BUTTON_A +key 305 BUTTON_B +key 307 BUTTON_X +key 308 BUTTON_Y +key 310 BUTTON_L1 +key 311 BUTTON_R1 +key 316 BUTTON_MODE +key 317 BUTTON_THUMBL +key 318 BUTTON_THUMBR + +key 158 BACK WAKE_DROPPED +key 172 HOME + +axis 0x00 X +axis 0x01 Y +axis 0x02 Z +axis 0x05 RZ +axis 0x09 RTRIGGER +axis 0x0a LTRIGGER +axis 0x10 HAT_X +axis 0x11 HAT_Y + +led 0x00 CONTROLLER_1 +led 0x01 CONTROLLER_2 +led 0x02 CONTROLLER_3 +led 0x03 CONTROLLER_4 diff --git a/graphics/java/android/graphics/Path.java b/graphics/java/android/graphics/Path.java index 2ce73acd12d3..c07a6dabbabc 100644 --- a/graphics/java/android/graphics/Path.java +++ b/graphics/java/android/graphics/Path.java @@ -168,6 +168,21 @@ public class Path { } /** + * Returns the path's convexity, as defined by the content of the path. + * <p> + * A path is convex if it has a single contour, and only ever curves in a + * single direction. + * <p> + * This function will calculate the convexity of the path from its control + * points, and cache the result. + * + * @return True if the path is convex. + */ + public boolean isConvex() { + return native_isConvex(mNativePath); + } + + /** * Enum for the ways a path may be filled. */ public enum FillType { @@ -224,7 +239,7 @@ public class Path { public void setFillType(FillType ft) { native_setFillType(mNativePath, ft.nativeInt); } - + /** * Returns true if the filltype is one of the INVERSE variants * @@ -232,18 +247,18 @@ public class Path { */ public boolean isInverseFillType() { final int ft = native_getFillType(mNativePath); - return (ft & 2) != 0; + return (ft & FillType.INVERSE_WINDING.nativeInt) != 0; } - + /** * Toggles the INVERSE state of the filltype */ public void toggleInverseFillType() { int ft = native_getFillType(mNativePath); - ft ^= 2; + ft ^= FillType.INVERSE_WINDING.nativeInt; native_setFillType(mNativePath, ft); } - + /** * Returns true if the path is empty (contains no lines or curves) * @@ -719,6 +734,7 @@ public class Path { private static native void native_reset(long nPath); private static native void native_rewind(long nPath); private static native void native_set(long native_dst, long native_src); + private static native boolean native_isConvex(long nPath); private static native int native_getFillType(long nPath); private static native void native_setFillType(long nPath, int ft); private static native boolean native_isEmpty(long nPath); diff --git a/libs/hwui/DisplayList.cpp b/libs/hwui/DisplayList.cpp index 112f8d3f5deb..0f7648698d27 100644 --- a/libs/hwui/DisplayList.cpp +++ b/libs/hwui/DisplayList.cpp @@ -109,6 +109,9 @@ void DisplayList::destroyDisplayListDeferred(DisplayList* displayList) { void DisplayList::setData(DisplayListData* data) { delete mDisplayListData; mDisplayListData = data; + if (mDisplayListData) { + Caches::getInstance().registerFunctors(mDisplayListData->functorCount); + } } /** @@ -488,6 +491,8 @@ void DisplayList::replay(ReplayStateStruct& replayStruct, const int level) { replayStruct.mDrawGlStatus); } +#define SHADOW_DELTA 2.0f + template <class T> void DisplayList::iterate3dChildren(ChildrenSelectMode mode, OpenGLRenderer& renderer, T& handler, const int level) { @@ -501,34 +506,66 @@ void DisplayList::iterate3dChildren(ChildrenSelectMode mode, OpenGLRenderer& ren int rootRestoreTo = renderer.save(SkCanvas::kMatrix_SaveFlag | SkCanvas::kClip_SaveFlag); LinearAllocator& alloc = handler.allocator(); ClipRectOp* clipOp = new (alloc) ClipRectOp(0, 0, mWidth, mHeight, - SkRegion::kIntersect_Op); // clip to 3d root bounds for now + SkRegion::kIntersect_Op); // clip to 3d root bounds handler(clipOp, PROPERTY_SAVECOUNT, mClipToBounds); - for (size_t i = 0; i < m3dNodes.size(); i++) { - const float zValue = m3dNodes[i].key; - DrawDisplayListOp* childOp = m3dNodes[i].value; + /** + * Draw shadows and (potential) casters mostly in order, but allow the shadows of casters + * with very similar Z heights to draw together. + * + * This way, if Views A & B have the same Z height and are both casting shadows, the shadows are + * underneath both, and neither's shadow is drawn on top of the other. + */ + const size_t nonNegativeIndex = findNonNegativeIndex(m3dNodes); + size_t drawIndex, shadowIndex, endIndex; + if (mode == kNegativeZChildren) { + drawIndex = 0; + endIndex = nonNegativeIndex; + shadowIndex = endIndex; // draw no shadows + } else { + drawIndex = nonNegativeIndex; + endIndex = m3dNodes.size(); + shadowIndex = drawIndex; // potentially draw shadow for each pos Z child + } + float lastCasterZ = 0.0f; + while (shadowIndex < endIndex || drawIndex < endIndex) { + if (shadowIndex < endIndex) { + DrawDisplayListOp* casterOp = m3dNodes[shadowIndex].value; + DisplayList* caster = casterOp->mDisplayList; + const float casterZ = m3dNodes[shadowIndex].key; + // attempt to render the shadow if the caster about to be drawn is its caster, + // OR if its caster's Z value is similar to the previous potential caster + if (shadowIndex == drawIndex || casterZ - lastCasterZ < SHADOW_DELTA) { + + if (caster->mCastsShadow && caster->mAlpha > 0.0f) { + mat4 shadowMatrix(casterOp->mTransformFromCompositingAncestor); + caster->applyViewPropertyTransforms(shadowMatrix); + + DisplayListOp* shadowOp = new (alloc) DrawShadowOp(shadowMatrix, + caster->mAlpha, &(caster->mOutline), caster->mWidth, caster->mHeight); + handler(shadowOp, PROPERTY_SAVECOUNT, mClipToBounds); + } - if (mode == kPositiveZChildren && zValue < 0.0f) continue; - if (mode == kNegativeZChildren && zValue > 0.0f) break; + lastCasterZ = casterZ; // must do this even if current caster not casting a shadow + shadowIndex++; + continue; + } + } + // only the actual child DL draw needs to be in save/restore, + // since it modifies the renderer's matrix + int restoreTo = renderer.save(SkCanvas::kMatrix_SaveFlag); + + DrawDisplayListOp* childOp = m3dNodes[drawIndex].value; DisplayList* child = childOp->mDisplayList; - if (mode == kPositiveZChildren && zValue > 0.0f - && child->mCastsShadow && child->mAlpha > 0.0f) { - /* draw shadow with parent matrix applied, passing in the child's total matrix - * TODO: consider depth in more complex scenarios (neg z, added shadow depth) - */ - mat4 shadowMatrix(childOp->mTransformFromCompositingAncestor); - child->applyViewPropertyTransforms(shadowMatrix); - - DisplayListOp* shadowOp = new (alloc) DrawShadowOp(shadowMatrix, - child->mAlpha, &(child->mOutline), child->mWidth, child->mHeight); - handler(shadowOp, PROPERTY_SAVECOUNT, mClipToBounds); - } renderer.concatMatrix(childOp->mTransformFromCompositingAncestor); childOp->mSkipInOrderDraw = false; // this is horrible, I'm so sorry everyone handler(childOp, renderer.getSaveCount() - 1, mClipToBounds); childOp->mSkipInOrderDraw = true; + + renderer.restoreToCount(restoreTo); + drawIndex++; } handler(new (alloc) RestoreToCountOp(rootRestoreTo), PROPERTY_SAVECOUNT, mClipToBounds); } @@ -567,7 +604,7 @@ void DisplayList::iterateProjectedChildren(OpenGLRenderer& renderer, T& handler, template <class T> void DisplayList::iterate(OpenGLRenderer& renderer, T& handler, const int level) { if (CC_UNLIKELY(mDestroyed)) { // temporary debug logging - ALOGW("Error: %s is drawing after destruction, size %d", getName()); + ALOGW("Error: %s is drawing after destruction", getName()); CRASH(); } if (mDisplayListData->isEmpty() || mAlpha <= 0) { diff --git a/libs/hwui/DisplayList.h b/libs/hwui/DisplayList.h index aba40b662533..a3577d411198 100644 --- a/libs/hwui/DisplayList.h +++ b/libs/hwui/DisplayList.h @@ -550,6 +550,13 @@ public: private: typedef key_value_pair_t<float, DrawDisplayListOp*> ZDrawDisplayListOpPair; + static size_t findNonNegativeIndex(const Vector<ZDrawDisplayListOpPair>& nodes) { + for (size_t i = 0; i < nodes.size(); i++) { + if (nodes[i].key >= 0.0f) return i; + } + return nodes.size(); + } + enum ChildrenSelectMode { kNegativeZChildren, kPositiveZChildren diff --git a/libs/hwui/DisplayListRenderer.cpp b/libs/hwui/DisplayListRenderer.cpp index 5abfe79e08d8..3b1d5677238b 100644 --- a/libs/hwui/DisplayListRenderer.cpp +++ b/libs/hwui/DisplayListRenderer.cpp @@ -32,9 +32,9 @@ namespace android { namespace uirenderer { DisplayListRenderer::DisplayListRenderer(): - mCaches(Caches::getInstance()), + mCaches(Caches::getInstance()), mDisplayListData(0), mTranslateX(0.0f), mTranslateY(0.0f), mHasTranslate(false), - mRestoreSaveCount(-1), mDisplayListData(0) { + mRestoreSaveCount(-1) { } DisplayListRenderer::~DisplayListRenderer() { diff --git a/libs/hwui/DisplayListRenderer.h b/libs/hwui/DisplayListRenderer.h index 6c11e5976ae3..1fb72ce319d5 100644 --- a/libs/hwui/DisplayListRenderer.h +++ b/libs/hwui/DisplayListRenderer.h @@ -300,8 +300,6 @@ private: DefaultKeyedVector<const SkRegion*, const SkRegion*> mRegionMap; DefaultKeyedVector<SkiaShader*, SkiaShader*> mShaderMap; - int mRestoreSaveCount; - Caches& mCaches; DisplayListData* mDisplayListData; @@ -309,6 +307,8 @@ private: float mTranslateY; bool mHasTranslate; + int mRestoreSaveCount; + friend class DisplayList; }; // class DisplayListRenderer diff --git a/media/jni/Android.mk b/media/jni/Android.mk index 35327c0a3be7..ed98b9630af7 100644 --- a/media/jni/Android.mk +++ b/media/jni/Android.mk @@ -38,6 +38,7 @@ LOCAL_SHARED_LIBRARIES := \ libcamera_client \ libmtp \ libusbhost \ + libjhead \ libexif \ libstagefright_amrnb_common \ diff --git a/opengl/java/android/opengl/GLSurfaceView.java b/opengl/java/android/opengl/GLSurfaceView.java index 5a2e261fa3a4..a9322b993101 100644 --- a/opengl/java/android/opengl/GLSurfaceView.java +++ b/opengl/java/android/opengl/GLSurfaceView.java @@ -595,13 +595,9 @@ public class GLSurfaceView extends SurfaceView implements SurfaceHolder.Callback mDetached = false; } - /** - * This method is used as part of the View class and is not normally - * called or subclassed by clients of GLSurfaceView. - * Must not be called before a renderer has been set. - */ + /** @hide */ @Override - protected void onDetachedFromWindow() { + protected void onDetachedFromWindowInternal() { if (LOG_ATTACH_DETACH) { Log.d(TAG, "onDetachedFromWindow"); } @@ -609,7 +605,7 @@ public class GLSurfaceView extends SurfaceView implements SurfaceHolder.Callback mGLThread.requestExitAndWait(); } mDetached = true; - super.onDetachedFromWindow(); + super.onDetachedFromWindowInternal(); } // ---------------------------------------------------------------------- diff --git a/packages/SystemUI/res/drawable-hdpi/ic_qs_color_space_alpha.png b/packages/SystemUI/res/drawable-hdpi/ic_qs_color_space_alpha.png Binary files differnew file mode 100644 index 000000000000..fe6dc5296dbd --- /dev/null +++ b/packages/SystemUI/res/drawable-hdpi/ic_qs_color_space_alpha.png diff --git a/packages/SystemUI/res/drawable-hdpi/ic_qs_contrast_alpha.png b/packages/SystemUI/res/drawable-hdpi/ic_qs_contrast_alpha.png Binary files differnew file mode 100644 index 000000000000..0f9dfc7fdcec --- /dev/null +++ b/packages/SystemUI/res/drawable-hdpi/ic_qs_contrast_alpha.png diff --git a/packages/SystemUI/res/drawable-hdpi/ic_qs_inversion_alpha.png b/packages/SystemUI/res/drawable-hdpi/ic_qs_inversion_alpha.png Binary files differnew file mode 100644 index 000000000000..aea75c105bd1 --- /dev/null +++ b/packages/SystemUI/res/drawable-hdpi/ic_qs_inversion_alpha.png diff --git a/packages/SystemUI/res/drawable-ldpi/ic_qs_color_space_alpha.png b/packages/SystemUI/res/drawable-ldpi/ic_qs_color_space_alpha.png Binary files differnew file mode 100644 index 000000000000..46d2a16c5eee --- /dev/null +++ b/packages/SystemUI/res/drawable-ldpi/ic_qs_color_space_alpha.png diff --git a/packages/SystemUI/res/drawable-ldpi/ic_qs_contrast_alpha.png b/packages/SystemUI/res/drawable-ldpi/ic_qs_contrast_alpha.png Binary files differnew file mode 100644 index 000000000000..704b4ecf79c0 --- /dev/null +++ b/packages/SystemUI/res/drawable-ldpi/ic_qs_contrast_alpha.png diff --git a/packages/SystemUI/res/drawable-ldpi/ic_qs_inversion_alpha.png b/packages/SystemUI/res/drawable-ldpi/ic_qs_inversion_alpha.png Binary files differnew file mode 100644 index 000000000000..d56efb5081f4 --- /dev/null +++ b/packages/SystemUI/res/drawable-ldpi/ic_qs_inversion_alpha.png diff --git a/packages/SystemUI/res/drawable-mdpi/ic_qs_color_space_alpha.png b/packages/SystemUI/res/drawable-mdpi/ic_qs_color_space_alpha.png Binary files differnew file mode 100644 index 000000000000..18b6029649c8 --- /dev/null +++ b/packages/SystemUI/res/drawable-mdpi/ic_qs_color_space_alpha.png diff --git a/packages/SystemUI/res/drawable-mdpi/ic_qs_contrast_alpha.png b/packages/SystemUI/res/drawable-mdpi/ic_qs_contrast_alpha.png Binary files differnew file mode 100644 index 000000000000..a4dd0878879d --- /dev/null +++ b/packages/SystemUI/res/drawable-mdpi/ic_qs_contrast_alpha.png diff --git a/packages/SystemUI/res/drawable-mdpi/ic_qs_inversion_alpha.png b/packages/SystemUI/res/drawable-mdpi/ic_qs_inversion_alpha.png Binary files differnew file mode 100644 index 000000000000..b6ea14e6dbdb --- /dev/null +++ b/packages/SystemUI/res/drawable-mdpi/ic_qs_inversion_alpha.png diff --git a/packages/SystemUI/res/drawable-xhdpi/ic_qs_color_space_alpha.png b/packages/SystemUI/res/drawable-xhdpi/ic_qs_color_space_alpha.png Binary files differnew file mode 100644 index 000000000000..95cf67f008d6 --- /dev/null +++ b/packages/SystemUI/res/drawable-xhdpi/ic_qs_color_space_alpha.png diff --git a/packages/SystemUI/res/drawable-xhdpi/ic_qs_contrast_alpha.png b/packages/SystemUI/res/drawable-xhdpi/ic_qs_contrast_alpha.png Binary files differnew file mode 100644 index 000000000000..9331e529ea20 --- /dev/null +++ b/packages/SystemUI/res/drawable-xhdpi/ic_qs_contrast_alpha.png diff --git a/packages/SystemUI/res/drawable-xhdpi/ic_qs_inversion_alpha.png b/packages/SystemUI/res/drawable-xhdpi/ic_qs_inversion_alpha.png Binary files differnew file mode 100644 index 000000000000..efd8b9ee2201 --- /dev/null +++ b/packages/SystemUI/res/drawable-xhdpi/ic_qs_inversion_alpha.png diff --git a/packages/SystemUI/res/drawable-xxhdpi/ic_qs_color_space_alpha.png b/packages/SystemUI/res/drawable-xxhdpi/ic_qs_color_space_alpha.png Binary files differnew file mode 100644 index 000000000000..7f441c812b76 --- /dev/null +++ b/packages/SystemUI/res/drawable-xxhdpi/ic_qs_color_space_alpha.png diff --git a/packages/SystemUI/res/drawable-xxhdpi/ic_qs_contrast_alpha.png b/packages/SystemUI/res/drawable-xxhdpi/ic_qs_contrast_alpha.png Binary files differnew file mode 100644 index 000000000000..82c3842ff3d9 --- /dev/null +++ b/packages/SystemUI/res/drawable-xxhdpi/ic_qs_contrast_alpha.png diff --git a/packages/SystemUI/res/drawable-xxhdpi/ic_qs_inversion_alpha.png b/packages/SystemUI/res/drawable-xxhdpi/ic_qs_inversion_alpha.png Binary files differnew file mode 100644 index 000000000000..ce9bae257d8b --- /dev/null +++ b/packages/SystemUI/res/drawable-xxhdpi/ic_qs_inversion_alpha.png diff --git a/packages/SystemUI/res/drawable/ic_qs_color_space_off.xml b/packages/SystemUI/res/drawable/ic_qs_color_space_off.xml new file mode 100644 index 000000000000..cf34ba6421dc --- /dev/null +++ b/packages/SystemUI/res/drawable/ic_qs_color_space_off.xml @@ -0,0 +1,20 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- + Copyright (C) 2014 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. +--> + +<bitmap xmlns:android="http://schemas.android.com/apk/res/android" + android:src="@drawable/ic_qs_color_space_alpha" + android:tint="@color/ic_qs_off" /> diff --git a/packages/SystemUI/res/drawable/ic_qs_color_space_on.xml b/packages/SystemUI/res/drawable/ic_qs_color_space_on.xml new file mode 100644 index 000000000000..180668887ea1 --- /dev/null +++ b/packages/SystemUI/res/drawable/ic_qs_color_space_on.xml @@ -0,0 +1,20 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- + Copyright (C) 2014 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. +--> + +<bitmap xmlns:android="http://schemas.android.com/apk/res/android" + android:src="@drawable/ic_qs_color_space_alpha" + android:tint="@color/ic_qs_on" /> diff --git a/packages/SystemUI/res/drawable/ic_qs_contrast_off.xml b/packages/SystemUI/res/drawable/ic_qs_contrast_off.xml new file mode 100644 index 000000000000..5f65d8aceee4 --- /dev/null +++ b/packages/SystemUI/res/drawable/ic_qs_contrast_off.xml @@ -0,0 +1,20 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- + Copyright (C) 2014 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. +--> + +<bitmap xmlns:android="http://schemas.android.com/apk/res/android" + android:src="@drawable/ic_qs_contrast_alpha" + android:tint="@color/ic_qs_off" /> diff --git a/packages/SystemUI/res/drawable/ic_qs_contrast_on.xml b/packages/SystemUI/res/drawable/ic_qs_contrast_on.xml new file mode 100644 index 000000000000..a01892905b75 --- /dev/null +++ b/packages/SystemUI/res/drawable/ic_qs_contrast_on.xml @@ -0,0 +1,20 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- + Copyright (C) 2014 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. +--> + +<bitmap xmlns:android="http://schemas.android.com/apk/res/android" + android:src="@drawable/ic_qs_contrast_alpha" + android:tint="@color/ic_qs_on" /> diff --git a/packages/SystemUI/res/drawable/ic_qs_inversion_off.xml b/packages/SystemUI/res/drawable/ic_qs_inversion_off.xml new file mode 100644 index 000000000000..9018a90e34a7 --- /dev/null +++ b/packages/SystemUI/res/drawable/ic_qs_inversion_off.xml @@ -0,0 +1,20 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- + Copyright (C) 2014 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. +--> + +<bitmap xmlns:android="http://schemas.android.com/apk/res/android" + android:src="@drawable/ic_qs_inversion_alpha" + android:tint="@color/ic_qs_off" /> diff --git a/packages/SystemUI/res/drawable/ic_qs_inversion_on.xml b/packages/SystemUI/res/drawable/ic_qs_inversion_on.xml new file mode 100644 index 000000000000..91102019fa0a --- /dev/null +++ b/packages/SystemUI/res/drawable/ic_qs_inversion_on.xml @@ -0,0 +1,20 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- + Copyright (C) 2014 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. +--> + +<bitmap xmlns:android="http://schemas.android.com/apk/res/android" + android:src="@drawable/ic_qs_inversion_alpha" + android:tint="@color/ic_qs_on" /> diff --git a/packages/SystemUI/res/drawable/notification_icon_legacy_bg.xml b/packages/SystemUI/res/drawable/notification_icon_legacy_bg.xml new file mode 100644 index 000000000000..4ac67c3e4765 --- /dev/null +++ b/packages/SystemUI/res/drawable/notification_icon_legacy_bg.xml @@ -0,0 +1,22 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- + ~ Copyright (C) 2014 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 + --> + +<shape xmlns:android="http://schemas.android.com/apk/res/android" + android:shape="oval"> + <solid + android:color="@color/notification_icon_legacy_bg_color"/> +</shape> diff --git a/packages/SystemUI/res/drawable/notification_icon_legacy_bg_inset.xml b/packages/SystemUI/res/drawable/notification_icon_legacy_bg_inset.xml new file mode 100644 index 000000000000..96c557366189 --- /dev/null +++ b/packages/SystemUI/res/drawable/notification_icon_legacy_bg_inset.xml @@ -0,0 +1,21 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- + ~ Copyright (C) 2014 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 + --> + +<inset xmlns:android="http://schemas.android.com/apk/res/android" + android:drawable="@drawable/notification_icon_legacy_bg" android:insetBottom="8dp" + android:insetLeft="8dp" android:insetRight="8dp" android:insetTop="8dp" + android:visible="true"/> diff --git a/packages/SystemUI/res/values-lt/strings.xml b/packages/SystemUI/res/values-lt/strings.xml index 797f713b69fa..29ca84a93fc3 100644 --- a/packages/SystemUI/res/values-lt/strings.xml +++ b/packages/SystemUI/res/values-lt/strings.xml @@ -69,7 +69,7 @@ <string name="screenshot_failed_title" msgid="705781116746922771">"Nepavyko užfiksuoti ekrano kopijos."</string> <string name="screenshot_failed_text" msgid="8134011269572415402">"Nepavyko išsaugoti ekrano kopijos. Gali būti naudojama atmintis."</string> <string name="usb_preference_title" msgid="6551050377388882787">"USB failo perdavimo parinktys"</string> - <string name="use_mtp_button_title" msgid="4333504413563023626">"Įmontuoti kaip medijos grotuvą (MTP)"</string> + <string name="use_mtp_button_title" msgid="4333504413563023626">"Įmontuoti kaip medijos leistuvą (MTP)"</string> <string name="use_ptp_button_title" msgid="7517127540301625751">"Įmontuoti kaip fotoaparatą (PTP)"</string> <string name="installer_cd_button_title" msgid="2312667578562201583">"Įdiegti „Mac“ skirtą „Android“ perkėl. priem. pr."</string> <string name="accessibility_back" msgid="567011538994429120">"Atgal"</string> diff --git a/packages/SystemUI/res/values-zh-rTW/strings.xml b/packages/SystemUI/res/values-zh-rTW/strings.xml index 83fdd12962f9..bf2d7ce2b0bc 100644 --- a/packages/SystemUI/res/values-zh-rTW/strings.xml +++ b/packages/SystemUI/res/values-zh-rTW/strings.xml @@ -199,7 +199,7 @@ <string name="quick_settings_wifi_label" msgid="9135344704899546041">"Wi-Fi"</string> <string name="quick_settings_wifi_not_connected" msgid="7171904845345573431">"未連線"</string> <string name="quick_settings_wifi_no_network" msgid="2221993077220856376">"沒有網路"</string> - <string name="quick_settings_wifi_off_label" msgid="7558778100843885864">"關閉 Wi-Fi"</string> + <string name="quick_settings_wifi_off_label" msgid="7558778100843885864">"Wi-Fi:關閉"</string> <string name="quick_settings_remote_display_no_connection_label" msgid="372107699274391290">"投放螢幕"</string> <string name="quick_settings_brightness_dialog_title" msgid="8599674057673605368">"亮度"</string> <string name="quick_settings_brightness_dialog_auto_brightness_label" msgid="5064982743784071218">"自動"</string> diff --git a/packages/SystemUI/res/values/colors.xml b/packages/SystemUI/res/values/colors.xml index e525fbb01bb4..a59dc75989e0 100644 --- a/packages/SystemUI/res/values/colors.xml +++ b/packages/SystemUI/res/values/colors.xml @@ -39,4 +39,12 @@ <color name="status_bar_clock_color">#FFFFFFFF</color> <drawable name="notification_item_background_color">#ff111111</drawable> <drawable name="notification_item_background_color_pressed">#ff454545</drawable> + <color name="notification_icon_legacy_bg_color">#ff4285F4</color> + <color name="notification_action_legacy_color_filter">#ff555555</color> + + <!-- Tint color for inactive Quick Settings icons. --> + <color name="ic_qs_off">#ff404040</color> + + <!-- Tint color for active Quick Settings icons. --> + <color name="ic_qs_on">#ffffffff</color> </resources> diff --git a/packages/SystemUI/src/com/android/systemui/ImageUtils.java b/packages/SystemUI/src/com/android/systemui/ImageUtils.java new file mode 100644 index 000000000000..540ba20c143a --- /dev/null +++ b/packages/SystemUI/src/com/android/systemui/ImageUtils.java @@ -0,0 +1,82 @@ +/* + * Copyright (C) 2014 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.systemui; + +import android.graphics.Bitmap; + +/** + * Utility class for image analysis and processing. + */ +public class ImageUtils { + + // Amount (max is 255) that two channels can differ before the color is no longer "gray". + private static final int TOLERANCE = 20; + + // Alpha amount for which values below are considered transparent. + private static final int ALPHA_TOLERANCE = 50; + + private int[] mTempBuffer; + + /** + * Checks whether a bitmap is grayscale. Grayscale here means "very close to a perfect + * gray". + */ + public boolean isGrayscale(Bitmap bitmap) { + final int height = bitmap.getHeight(); + final int width = bitmap.getWidth(); + int size = height*width; + + ensureBufferSize(size); + bitmap.getPixels(mTempBuffer, 0, width, 0, 0, width, height); + for (int i = 0; i < size; i++) { + if (!isGrayscale(mTempBuffer[i])) { + return false; + } + } + return true; + } + + /** + * Makes sure that {@code mTempBuffer} has at least length {@code size}. + */ + private void ensureBufferSize(int size) { + if (mTempBuffer == null || mTempBuffer.length < size) { + mTempBuffer = new int[size]; + } + } + + /** + * Classifies a color as grayscale or not. Grayscale here means "very close to a perfect + * gray"; if all three channels are approximately equal, this will return true. + * + * Note that really transparent colors are always grayscale. + */ + public boolean isGrayscale(int color) { + int alpha = 0xFF & (color >> 24); + if (alpha < ALPHA_TOLERANCE) { + return true; + } + + int r = 0xFF & (color >> 16); + int g = 0xFF & (color >> 8); + int b = 0xFF & color; + + return Math.abs(r - g) < TOLERANCE + && Math.abs(r - b) < TOLERANCE + && Math.abs(g - b) < TOLERANCE; + } +} diff --git a/packages/SystemUI/src/com/android/systemui/power/PowerDialogWarnings.java b/packages/SystemUI/src/com/android/systemui/power/PowerDialogWarnings.java new file mode 100644 index 000000000000..feec87cc609f --- /dev/null +++ b/packages/SystemUI/src/com/android/systemui/power/PowerDialogWarnings.java @@ -0,0 +1,218 @@ +/* + * Copyright (C) 2014 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.systemui.power; + +import android.app.AlertDialog; +import android.content.ContentResolver; +import android.content.Context; +import android.content.DialogInterface; +import android.content.Intent; +import android.media.AudioManager; +import android.media.Ringtone; +import android.media.RingtoneManager; +import android.net.Uri; +import android.os.SystemClock; +import android.os.UserHandle; +import android.provider.Settings; +import android.util.Slog; +import android.view.View; +import android.view.WindowManager; +import android.widget.TextView; + +import com.android.systemui.R; + +import java.io.PrintWriter; + +public class PowerDialogWarnings implements PowerUI.WarningsUI { + private static final String TAG = PowerUI.TAG + ".Dialog"; + private static final boolean DEBUG = PowerUI.DEBUG; + + private final Context mContext; + + private int mBatteryLevel; + private int mBucket; + private long mScreenOffTime; + + private AlertDialog mInvalidChargerDialog; + private AlertDialog mLowBatteryDialog; + private TextView mBatteryLevelTextView; + + public PowerDialogWarnings(Context context) { + mContext = context; + } + + @Override + public void dump(PrintWriter pw) { + pw.print("mInvalidChargerDialog="); + pw.println(mInvalidChargerDialog == null ? "null" : mInvalidChargerDialog.toString()); + pw.print("mLowBatteryDialog="); + pw.println(mLowBatteryDialog == null ? "null" : mLowBatteryDialog.toString()); + } + + @Override + public void update(int batteryLevel, int bucket, long screenOffTime) { + mBatteryLevel = batteryLevel; + mBucket = bucket; + mScreenOffTime = screenOffTime; + } + + @Override + public boolean isInvalidChargerWarningShowing() { + return mInvalidChargerDialog != null; + } + + @Override + public void updateLowBatteryWarning() { + if (mBatteryLevelTextView != null) { + showLowBatteryWarning(false /*playSound*/); + } + } + + @Override + public void dismissLowBatteryWarning() { + if (mLowBatteryDialog != null) { + Slog.i(TAG, "closing low battery warning: level=" + mBatteryLevel); + mLowBatteryDialog.dismiss(); + } + } + + @Override + public void showLowBatteryWarning(boolean playSound) { + Slog.i(TAG, + ((mBatteryLevelTextView == null) ? "showing" : "updating") + + " low battery warning: level=" + mBatteryLevel + + " [" + mBucket + "]"); + + CharSequence levelText = mContext.getString( + R.string.battery_low_percent_format, mBatteryLevel); + + if (mBatteryLevelTextView != null) { + mBatteryLevelTextView.setText(levelText); + } else { + View v = View.inflate(mContext, R.layout.battery_low, null); + mBatteryLevelTextView = (TextView)v.findViewById(R.id.level_percent); + + mBatteryLevelTextView.setText(levelText); + + AlertDialog.Builder b = new AlertDialog.Builder(mContext); + b.setCancelable(true); + b.setTitle(R.string.battery_low_title); + b.setView(v); + b.setIconAttribute(android.R.attr.alertDialogIcon); + b.setPositiveButton(android.R.string.ok, null); + + final Intent intent = new Intent(Intent.ACTION_POWER_USAGE_SUMMARY); + intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK + | Intent.FLAG_ACTIVITY_MULTIPLE_TASK + | Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS + | Intent.FLAG_ACTIVITY_NO_HISTORY); + if (intent.resolveActivity(mContext.getPackageManager()) != null) { + b.setNegativeButton(R.string.battery_low_why, + new DialogInterface.OnClickListener() { + @Override + public void onClick(DialogInterface dialog, int which) { + mContext.startActivityAsUser(intent, UserHandle.CURRENT); + dismissLowBatteryWarning(); + } + }); + } + + AlertDialog d = b.create(); + d.setOnDismissListener(new DialogInterface.OnDismissListener() { + @Override + public void onDismiss(DialogInterface dialog) { + mLowBatteryDialog = null; + mBatteryLevelTextView = null; + } + }); + d.getWindow().setType(WindowManager.LayoutParams.TYPE_SYSTEM_ALERT); + d.getWindow().getAttributes().privateFlags |= + WindowManager.LayoutParams.PRIVATE_FLAG_SHOW_FOR_ALL_USERS; + d.show(); + mLowBatteryDialog = d; + if (playSound) { + playLowBatterySound(); + } + } + } + + private void playLowBatterySound() { + final ContentResolver cr = mContext.getContentResolver(); + + final int silenceAfter = Settings.Global.getInt(cr, + Settings.Global.LOW_BATTERY_SOUND_TIMEOUT, 0); + final long offTime = SystemClock.elapsedRealtime() - mScreenOffTime; + if (silenceAfter > 0 + && mScreenOffTime > 0 + && offTime > silenceAfter) { + Slog.i(TAG, "screen off too long (" + offTime + "ms, limit " + silenceAfter + + "ms): not waking up the user with low battery sound"); + return; + } + + if (DEBUG) { + Slog.d(TAG, "playing low battery sound. pick-a-doop!"); // WOMP-WOMP is deprecated + } + + if (Settings.Global.getInt(cr, Settings.Global.POWER_SOUNDS_ENABLED, 1) == 1) { + final String soundPath = Settings.Global.getString(cr, + Settings.Global.LOW_BATTERY_SOUND); + if (soundPath != null) { + final Uri soundUri = Uri.parse("file://" + soundPath); + if (soundUri != null) { + final Ringtone sfx = RingtoneManager.getRingtone(mContext, soundUri); + if (sfx != null) { + sfx.setStreamType(AudioManager.STREAM_SYSTEM); + sfx.play(); + } + } + } + } + } + + @Override + public void dismissInvalidChargerWarning() { + if (mInvalidChargerDialog != null) { + mInvalidChargerDialog.dismiss(); + } + } + + @Override + public void showInvalidChargerWarning() { + Slog.d(TAG, "showing invalid charger dialog"); + + dismissLowBatteryWarning(); + + AlertDialog.Builder b = new AlertDialog.Builder(mContext); + b.setCancelable(true); + b.setMessage(R.string.invalid_charger); + b.setIconAttribute(android.R.attr.alertDialogIcon); + b.setPositiveButton(android.R.string.ok, null); + + AlertDialog d = b.create(); + d.setOnDismissListener(new DialogInterface.OnDismissListener() { + public void onDismiss(DialogInterface dialog) { + mInvalidChargerDialog = null; + mBatteryLevelTextView = null; + } + }); + + d.getWindow().setType(WindowManager.LayoutParams.TYPE_SYSTEM_ALERT); + d.show(); + mInvalidChargerDialog = d; + } +} diff --git a/packages/SystemUI/src/com/android/systemui/power/PowerUI.java b/packages/SystemUI/src/com/android/systemui/power/PowerUI.java index 28c2772f5c9f..0fb0f8b02c65 100644 --- a/packages/SystemUI/src/com/android/systemui/power/PowerUI.java +++ b/packages/SystemUI/src/com/android/systemui/power/PowerUI.java @@ -16,29 +16,17 @@ package com.android.systemui.power; -import android.app.AlertDialog; import android.content.BroadcastReceiver; -import android.content.ContentResolver; import android.content.Context; -import android.content.DialogInterface; import android.content.Intent; import android.content.IntentFilter; -import android.media.AudioManager; -import android.media.Ringtone; -import android.media.RingtoneManager; -import android.net.Uri; import android.os.BatteryManager; import android.os.Handler; import android.os.PowerManager; import android.os.SystemClock; -import android.os.UserHandle; import android.provider.Settings; import android.util.Slog; -import android.view.View; -import android.view.WindowManager; -import android.widget.TextView; -import com.android.systemui.R; import com.android.systemui.SystemUI; import java.io.FileDescriptor; @@ -50,19 +38,17 @@ public class PowerUI extends SystemUI { static final boolean DEBUG = false; - Handler mHandler = new Handler(); + private WarningsUI mWarnings; - int mBatteryLevel = 100; - int mBatteryStatus = BatteryManager.BATTERY_STATUS_UNKNOWN; - int mPlugType = 0; - int mInvalidCharger = 0; + private final Handler mHandler = new Handler(); - int mLowBatteryAlertCloseLevel; - int[] mLowBatteryReminderLevels = new int[2]; + private int mBatteryLevel = 100; + private int mBatteryStatus = BatteryManager.BATTERY_STATUS_UNKNOWN; + private int mPlugType = 0; + private int mInvalidCharger = 0; - AlertDialog mInvalidChargerDialog; - AlertDialog mLowBatteryDialog; - TextView mBatteryLevelTextView; + private int mLowBatteryAlertCloseLevel; + private final int[] mLowBatteryReminderLevels = new int[2]; private long mScreenOffTime = -1; @@ -77,6 +63,7 @@ public class PowerUI extends SystemUI { final PowerManager pm = (PowerManager) mContext.getSystemService(Context.POWER_SERVICE); mScreenOffTime = pm.isScreenOn() ? -1 : SystemClock.elapsedRealtime(); + mWarnings = new PowerDialogWarnings(mContext); // Register for Intent broadcasts for... IntentFilter filter = new IntentFilter(); @@ -145,13 +132,14 @@ public class PowerUI extends SystemUI { Slog.d(TAG, "plugged " + oldPlugged + " --> " + plugged); } + mWarnings.update(mBatteryLevel, bucket, mScreenOffTime); if (oldInvalidCharger == 0 && mInvalidCharger != 0) { Slog.d(TAG, "showing invalid charger warning"); - showInvalidChargerDialog(); + mWarnings.showInvalidChargerWarning(); return; } else if (oldInvalidCharger != 0 && mInvalidCharger == 0) { - dismissInvalidChargerDialog(); - } else if (mInvalidChargerDialog != null) { + mWarnings.dismissInvalidChargerWarning(); + } else if (mWarnings.isInvalidChargerWarningShowing()) { // if invalid charger is showing, don't show low battery return; } @@ -160,16 +148,13 @@ public class PowerUI extends SystemUI { && (bucket < oldBucket || oldPlugged) && mBatteryStatus != BatteryManager.BATTERY_STATUS_UNKNOWN && bucket < 0) { - showLowBatteryWarning(); - // only play SFX when the dialog comes up or the bucket changes - if (bucket != oldBucket || oldPlugged) { - playLowBatterySound(); - } + final boolean playSound = bucket != oldBucket || oldPlugged; + mWarnings.showLowBatteryWarning(playSound); } else if (plugged || (bucket > oldBucket && bucket > 0)) { - dismissLowBatteryWarning(); - } else if (mBatteryLevelTextView != null) { - showLowBatteryWarning(); + mWarnings.dismissLowBatteryWarning(); + } else { + mWarnings.updateLowBatteryWarning(); } } else if (Intent.ACTION_SCREEN_OFF.equals(action)) { mScreenOffTime = SystemClock.elapsedRealtime(); @@ -181,142 +166,11 @@ public class PowerUI extends SystemUI { } }; - void dismissLowBatteryWarning() { - if (mLowBatteryDialog != null) { - Slog.i(TAG, "closing low battery warning: level=" + mBatteryLevel); - mLowBatteryDialog.dismiss(); - } - } - - void showLowBatteryWarning() { - Slog.i(TAG, - ((mBatteryLevelTextView == null) ? "showing" : "updating") - + " low battery warning: level=" + mBatteryLevel - + " [" + findBatteryLevelBucket(mBatteryLevel) + "]"); - - CharSequence levelText = mContext.getString( - R.string.battery_low_percent_format, mBatteryLevel); - - if (mBatteryLevelTextView != null) { - mBatteryLevelTextView.setText(levelText); - } else { - View v = View.inflate(mContext, R.layout.battery_low, null); - mBatteryLevelTextView = (TextView)v.findViewById(R.id.level_percent); - - mBatteryLevelTextView.setText(levelText); - - AlertDialog.Builder b = new AlertDialog.Builder(mContext); - b.setCancelable(true); - b.setTitle(R.string.battery_low_title); - b.setView(v); - b.setIconAttribute(android.R.attr.alertDialogIcon); - b.setPositiveButton(android.R.string.ok, null); - - final Intent intent = new Intent(Intent.ACTION_POWER_USAGE_SUMMARY); - intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK - | Intent.FLAG_ACTIVITY_MULTIPLE_TASK - | Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS - | Intent.FLAG_ACTIVITY_NO_HISTORY); - if (intent.resolveActivity(mContext.getPackageManager()) != null) { - b.setNegativeButton(R.string.battery_low_why, - new DialogInterface.OnClickListener() { - @Override - public void onClick(DialogInterface dialog, int which) { - mContext.startActivityAsUser(intent, UserHandle.CURRENT); - dismissLowBatteryWarning(); - } - }); - } - - AlertDialog d = b.create(); - d.setOnDismissListener(new DialogInterface.OnDismissListener() { - @Override - public void onDismiss(DialogInterface dialog) { - mLowBatteryDialog = null; - mBatteryLevelTextView = null; - } - }); - d.getWindow().setType(WindowManager.LayoutParams.TYPE_SYSTEM_ALERT); - d.getWindow().getAttributes().privateFlags |= - WindowManager.LayoutParams.PRIVATE_FLAG_SHOW_FOR_ALL_USERS; - d.show(); - mLowBatteryDialog = d; - } - } - - void playLowBatterySound() { - final ContentResolver cr = mContext.getContentResolver(); - - final int silenceAfter = Settings.Global.getInt(cr, - Settings.Global.LOW_BATTERY_SOUND_TIMEOUT, 0); - final long offTime = SystemClock.elapsedRealtime() - mScreenOffTime; - if (silenceAfter > 0 - && mScreenOffTime > 0 - && offTime > silenceAfter) { - Slog.i(TAG, "screen off too long (" + offTime + "ms, limit " + silenceAfter - + "ms): not waking up the user with low battery sound"); - return; - } - - if (DEBUG) { - Slog.d(TAG, "playing low battery sound. pick-a-doop!"); // WOMP-WOMP is deprecated - } - - if (Settings.Global.getInt(cr, Settings.Global.POWER_SOUNDS_ENABLED, 1) == 1) { - final String soundPath = Settings.Global.getString(cr, - Settings.Global.LOW_BATTERY_SOUND); - if (soundPath != null) { - final Uri soundUri = Uri.parse("file://" + soundPath); - if (soundUri != null) { - final Ringtone sfx = RingtoneManager.getRingtone(mContext, soundUri); - if (sfx != null) { - sfx.setStreamType(AudioManager.STREAM_SYSTEM); - sfx.play(); - } - } - } - } - } - - void dismissInvalidChargerDialog() { - if (mInvalidChargerDialog != null) { - mInvalidChargerDialog.dismiss(); - } - } - - void showInvalidChargerDialog() { - Slog.d(TAG, "showing invalid charger dialog"); - - dismissLowBatteryWarning(); - - AlertDialog.Builder b = new AlertDialog.Builder(mContext); - b.setCancelable(true); - b.setMessage(R.string.invalid_charger); - b.setIconAttribute(android.R.attr.alertDialogIcon); - b.setPositiveButton(android.R.string.ok, null); - - AlertDialog d = b.create(); - d.setOnDismissListener(new DialogInterface.OnDismissListener() { - public void onDismiss(DialogInterface dialog) { - mInvalidChargerDialog = null; - mBatteryLevelTextView = null; - } - }); - - d.getWindow().setType(WindowManager.LayoutParams.TYPE_SYSTEM_ALERT); - d.show(); - mInvalidChargerDialog = d; - } - public void dump(FileDescriptor fd, PrintWriter pw, String[] args) { pw.print("mLowBatteryAlertCloseLevel="); pw.println(mLowBatteryAlertCloseLevel); pw.print("mLowBatteryReminderLevels="); pw.println(Arrays.toString(mLowBatteryReminderLevels)); - pw.print("mInvalidChargerDialog="); - pw.println(mInvalidChargerDialog == null ? "null" : mInvalidChargerDialog.toString()); - pw.print("mLowBatteryDialog="); - pw.println(mLowBatteryDialog == null ? "null" : mLowBatteryDialog.toString()); pw.print("mBatteryLevel="); pw.println(Integer.toString(mBatteryLevel)); pw.print("mBatteryStatus="); @@ -338,6 +192,18 @@ public class PowerUI extends SystemUI { Settings.Global.LOW_BATTERY_SOUND_TIMEOUT, 0)); pw.print("bucket: "); pw.println(Integer.toString(findBatteryLevelBucket(mBatteryLevel))); + mWarnings.dump(pw); + } + + public interface WarningsUI { + void update(int batteryLevel, int bucket, long screenOffTime); + void dismissLowBatteryWarning(); + void showLowBatteryWarning(boolean playSound); + void dismissInvalidChargerWarning(); + void showInvalidChargerWarning(); + void updateLowBatteryWarning(); + boolean isInvalidChargerWarningShowing(); + void dump(PrintWriter pw); } } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java index fb117432db15..eb07d888610b 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java @@ -28,9 +28,15 @@ import android.content.IntentFilter; import android.content.pm.ApplicationInfo; import android.content.pm.PackageManager; import android.content.pm.PackageManager.NameNotFoundException; +import android.content.res.ColorStateList; import android.content.res.Configuration; import android.database.ContentObserver; +import android.graphics.Color; +import android.graphics.PorterDuff; import android.graphics.Rect; +import android.graphics.drawable.AnimationDrawable; +import android.graphics.drawable.BitmapDrawable; +import android.graphics.drawable.Drawable; import android.net.Uri; import android.os.Build; import android.os.Handler; @@ -44,9 +50,13 @@ import android.provider.Settings; import android.service.dreams.DreamService; import android.service.dreams.IDreamManager; import android.service.notification.StatusBarNotification; +import android.text.SpannableStringBuilder; +import android.text.Spanned; import android.text.TextUtils; +import android.text.style.TextAppearanceSpan; import android.util.Log; import android.util.SparseBooleanArray; +import android.view.ContextThemeWrapper; import android.view.Display; import android.view.IWindowManager; import android.view.LayoutInflater; @@ -57,6 +67,7 @@ import android.view.ViewGroup; import android.view.ViewGroup.LayoutParams; import android.view.WindowManager; import android.view.WindowManagerGlobal; +import android.widget.Button; import android.widget.ImageView; import android.widget.LinearLayout; import android.widget.PopupMenu; @@ -67,6 +78,7 @@ import com.android.internal.statusbar.IStatusBarService; import com.android.internal.statusbar.StatusBarIcon; import com.android.internal.statusbar.StatusBarIconList; import com.android.internal.widget.SizeAdaptiveLayout; +import com.android.systemui.ImageUtils; import com.android.systemui.R; import com.android.systemui.RecentsComponent; import com.android.systemui.SearchPanelView; @@ -76,6 +88,7 @@ import com.android.systemui.statusbar.policy.NotificationRowLayout; import java.util.ArrayList; import java.util.Locale; +import java.util.Stack; public abstract class BaseStatusBar extends SystemUI implements CommandQueue.Callbacks { @@ -140,6 +153,8 @@ public abstract class BaseStatusBar extends SystemUI implements // public mode, private notifications, etc private boolean mLockscreenPublicMode = false; private final SparseBooleanArray mUsersAllowingPrivateNotifications = new SparseBooleanArray(); + private Context mLightThemeContext; + private ImageUtils mImageUtils = new ImageUtils(); // UI-specific methods @@ -261,6 +276,8 @@ public abstract class BaseStatusBar extends SystemUI implements true, mLockscreenSettingsObserver, UserHandle.USER_ALL); + mLightThemeContext = new RemoteViewsThemeContextWrapper(mContext, + android.R.style.Theme_Holo_Light); mBarService = IStatusBarService.Stub.asInterface( ServiceManager.getService(Context.STATUS_BAR_SERVICE)); @@ -412,6 +429,158 @@ public abstract class BaseStatusBar extends SystemUI implements } } + private void processLegacyHoloNotification(StatusBarNotification sbn, View content) { + + // TODO: Also skip processing if it is a holo-style notification. + // If the notification is custom, we can't process it. + if (!sbn.getNotification().extras.getBoolean(Notification.EXTRA_BUILDER_REMOTE_VIEWS)) { + return; + } + + processLegacyHoloLargeIcon(content); + processLegacyHoloActions(content); + processLegacyNotificationIcon(content); + processLegacyTextViews(content); + } + + /** + * @return the context to be used for the inflation of the specified {@code sbn}; this is + * dependent whether the notification is quantum-style or holo-style + */ + private Context getInflationContext(StatusBarNotification sbn) { + + // TODO: Adjust this logic when we change the theme of the status bar windows. + if (sbn.getNotification().extras.getBoolean(Notification.EXTRA_BUILDER_REMOTE_VIEWS)) { + return mLightThemeContext; + } else { + return mContext; + } + } + + private void processLegacyNotificationIcon(View content) { + View v = content.findViewById(com.android.internal.R.id.right_icon); + if (v != null & v instanceof ImageView) { + ImageView iv = (ImageView) v; + Drawable d = iv.getDrawable(); + if (isMonochrome(d)) { + d.mutate(); + d.setColorFilter(mLightThemeContext.getResources().getColor( + R.color.notification_action_legacy_color_filter), PorterDuff.Mode.MULTIPLY); + } + } + } + + private void processLegacyHoloLargeIcon(View content) { + View v = content.findViewById(com.android.internal.R.id.icon); + if (v != null & v instanceof ImageView) { + ImageView iv = (ImageView) v; + if (isMonochrome(iv.getDrawable())) { + iv.setBackground(mLightThemeContext.getResources().getDrawable( + R.drawable.notification_icon_legacy_bg_inset)); + } + } + } + + private boolean isMonochrome(Drawable d) { + if (d == null) { + return false; + } else if (d instanceof BitmapDrawable) { + BitmapDrawable bd = (BitmapDrawable) d; + return bd.getBitmap() != null && mImageUtils.isGrayscale(bd.getBitmap()); + } else if (d instanceof AnimationDrawable) { + AnimationDrawable ad = (AnimationDrawable) d; + int count = ad.getNumberOfFrames(); + return count > 0 && isMonochrome(ad.getFrame(0)); + } else { + return false; + } + } + + private void processLegacyHoloActions(View content) { + View v = content.findViewById(com.android.internal.R.id.actions); + if (v != null & v instanceof ViewGroup) { + ViewGroup vg = (ViewGroup) v; + int childCount = vg.getChildCount(); + for (int i = 0; i < childCount; i++) { + View child = vg.getChildAt(i); + if (child instanceof Button) { + Button button = (Button) child; + Drawable[] compoundDrawables = button.getCompoundDrawablesRelative(); + if (isMonochrome(compoundDrawables[0])) { + Drawable d = compoundDrawables[0]; + d.mutate(); + d.setColorFilter(mLightThemeContext.getResources().getColor( + R.color.notification_action_legacy_color_filter), + PorterDuff.Mode.MULTIPLY); + } + } + } + } + } + + private void processLegacyTextViews(View content) { + Stack<View> viewStack = new Stack<View>(); + viewStack.push(content); + while(!viewStack.isEmpty()) { + View current = viewStack.pop(); + if(current instanceof ViewGroup){ + ViewGroup currentGroup = (ViewGroup) current; + int numChildren = currentGroup.getChildCount(); + for(int i=0;i<numChildren;i++){ + viewStack.push(currentGroup.getChildAt(i)); + } + } + if (current instanceof TextView) { + processLegacyTextView((TextView) current); + } + } + } + + private void processLegacyTextView(TextView textView) { + if (textView.getText() instanceof Spanned) { + Spanned ss = (Spanned) textView.getText(); + Object[] spans = ss.getSpans(0, ss.length(), Object.class); + SpannableStringBuilder builder = new SpannableStringBuilder(ss.toString()); + for (Object span : spans) { + Object resultSpan = span; + if (span instanceof TextAppearanceSpan) { + resultSpan = processTextAppearanceSpan((TextAppearanceSpan) span); + } + builder.setSpan(resultSpan, ss.getSpanStart(span), ss.getSpanEnd(span), + ss.getSpanFlags(span)); + } + textView.setText(builder); + } + } + + private TextAppearanceSpan processTextAppearanceSpan(TextAppearanceSpan span) { + ColorStateList colorStateList = span.getTextColor(); + if (colorStateList != null) { + int[] colors = colorStateList.getColors(); + boolean changed = false; + for (int i = 0; i < colors.length; i++) { + if (mImageUtils.isGrayscale(colors[i])) { + colors[i] = processColor(colors[i]); + changed = true; + } + } + if (changed) { + return new TextAppearanceSpan( + span.getFamily(), span.getTextStyle(), span.getTextSize(), + new ColorStateList(colorStateList.getStates(), colors), + span.getLinkTextColor()); + } + } + return span; + } + + private int processColor(int color) { + return Color.argb(Color.alpha(color), + 255 - Color.red(color), + 255 - Color.green(color), + 255 - Color.blue(color)); + } + private void startApplicationDetailsActivity(String packageName) { Intent intent = new Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS, Uri.fromParts("package", packageName, null)); @@ -748,9 +917,11 @@ public abstract class BaseStatusBar extends SystemUI implements View contentViewLocal = null; View bigContentViewLocal = null; try { - contentViewLocal = contentView.apply(mContext, expanded, mOnClickHandler); + contentViewLocal = contentView.apply(getInflationContext(sbn), expanded, + mOnClickHandler); if (bigContentView != null) { - bigContentViewLocal = bigContentView.apply(mContext, expanded, mOnClickHandler); + bigContentViewLocal = bigContentView.apply(getInflationContext(sbn), expanded, + mOnClickHandler); } } catch (RuntimeException e) { @@ -780,7 +951,7 @@ public abstract class BaseStatusBar extends SystemUI implements View publicViewLocal = null; if (publicNotification != null) { try { - publicViewLocal = publicNotification.contentView.apply(mContext, + publicViewLocal = publicNotification.contentView.apply(getInflationContext(sbn), expandedPublic, mOnClickHandler); if (publicViewLocal != null) { @@ -831,6 +1002,13 @@ public abstract class BaseStatusBar extends SystemUI implements row.setDrawingCacheEnabled(true); applyLegacyRowBackground(sbn, content); + processLegacyHoloNotification(sbn, contentViewLocal); + if (bigContentViewLocal != null) { + processLegacyHoloNotification(sbn, bigContentViewLocal); + } + if (publicViewLocal != null) { + processLegacyHoloNotification(sbn, publicViewLocal); + } if (MULTIUSER_DEBUG) { TextView debug = (TextView) row.findViewById(R.id.debug_info); @@ -1245,12 +1423,17 @@ public abstract class BaseStatusBar extends SystemUI implements : null; // Reapply the RemoteViews - contentView.reapply(mContext, entry.expanded, mOnClickHandler); + contentView.reapply(getInflationContext(notification), entry.expanded, mOnClickHandler); + processLegacyHoloNotification(notification, entry.expanded); if (bigContentView != null && entry.getBigContentView() != null) { - bigContentView.reapply(mContext, entry.getBigContentView(), mOnClickHandler); + bigContentView.reapply(getInflationContext(notification), entry.getBigContentView(), + mOnClickHandler); + processLegacyHoloNotification(notification, entry.getBigContentView()); } if (publicContentView != null && entry.getPublicContentView() != null) { - publicContentView.reapply(mContext, entry.getPublicContentView(), mOnClickHandler); + publicContentView.reapply(getInflationContext(notification), + entry.getPublicContentView(), mOnClickHandler); + processLegacyHoloNotification(notification, entry.getPublicContentView()); } // update the contentIntent final PendingIntent contentIntent = notification.getNotification().contentIntent; @@ -1330,4 +1513,35 @@ public abstract class BaseStatusBar extends SystemUI implements } mContext.unregisterReceiver(mBroadcastReceiver); } + + /** + * A custom context theme wrapper that applies a platform theme to a created package context. + * This is useful if you want to inflate {@link RemoteViews} with a custom theme (normally, the + * theme used there is the default platform theme). + */ + private static class RemoteViewsThemeContextWrapper extends ContextThemeWrapper { + + private int mThemeRes; + + private RemoteViewsThemeContextWrapper(Context base, int themeres) { + super(base, themeres); + mThemeRes = themeres; + } + + @Override + public Context createPackageContextAsUser(String packageName, int flags, UserHandle user) + throws NameNotFoundException { + Context c = super.createPackageContextAsUser(packageName, flags, user); + c.setTheme(mThemeRes); + return c; + } + + @Override + public Context createPackageContext(String packageName, int flags) + throws NameNotFoundException { + Context c = super.createPackageContext(packageName, flags); + c.setTheme(mThemeRes); + return c; + } + } } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/QuickSettingsModel.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/QuickSettingsModel.java index 48ee1ce46865..174cad8c324e 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/QuickSettingsModel.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/QuickSettingsModel.java @@ -996,8 +996,8 @@ class QuickSettingsModel implements BluetoothStateChangeCallback, mInversionState.toggled = enabled; mInversionState.type = type; // TODO: Add real icon assets. - mInversionState.iconId = enabled ? R.drawable.ic_qs_bluetooth_on - : R.drawable.ic_qs_bluetooth_off; + mInversionState.iconId = enabled ? R.drawable.ic_qs_inversion_on + : R.drawable.ic_qs_inversion_off; mInversionState.label = res.getString(R.string.quick_settings_inversion_label); mInversionCallback.refreshView(mInversionTile, mInversionState); } @@ -1026,8 +1026,8 @@ class QuickSettingsModel implements BluetoothStateChangeCallback, mContrastState.contrast = contrast; mContrastState.brightness = brightness; // TODO: Add real icon assets. - mContrastState.iconId = enabled ? R.drawable.ic_qs_bluetooth_on - : R.drawable.ic_qs_bluetooth_off; + mContrastState.iconId = enabled ? R.drawable.ic_qs_contrast_on + : R.drawable.ic_qs_contrast_off; mContrastState.label = res.getString(R.string.quick_settings_contrast_label); mContrastCallback.refreshView(mContrastTile, mContrastState); } @@ -1053,8 +1053,8 @@ class QuickSettingsModel implements BluetoothStateChangeCallback, mColorSpaceState.toggled = enabled; mColorSpaceState.type = type; // TODO: Add real icon assets. - mColorSpaceState.iconId = enabled ? R.drawable.ic_qs_bluetooth_on - : R.drawable.ic_qs_bluetooth_off; + mColorSpaceState.iconId = enabled ? R.drawable.ic_qs_color_space_on + : R.drawable.ic_qs_color_space_off; mColorSpaceState.label = res.getString(R.string.quick_settings_color_space_label); mColorSpaceCallback.refreshView(mColorSpaceTile, mColorSpaceState); } diff --git a/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java b/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java index abc3fb1fcc21..8cd6e06f1717 100644 --- a/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java +++ b/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java @@ -372,6 +372,7 @@ public class PhoneWindowManager implements WindowManagerPolicy { static final Rect mTmpNavigationFrame = new Rect(); WindowState mTopFullscreenOpaqueWindowState; + boolean mHideWindowBehindKeyguard; boolean mTopIsFullscreen; boolean mForceStatusBar; boolean mForceStatusBarFromKeyguard; @@ -3355,6 +3356,7 @@ public class PhoneWindowManager implements WindowManagerPolicy { @Override public void beginPostLayoutPolicyLw(int displayWidth, int displayHeight) { mTopFullscreenOpaqueWindowState = null; + mHideWindowBehindKeyguard = false; mForceStatusBar = false; mForceStatusBarFromKeyguard = false; mForcingShowNavBar = false; @@ -3391,7 +3393,7 @@ public class PhoneWindowManager implements WindowManagerPolicy { if (attrs.type == TYPE_KEYGUARD) { mShowingLockscreen = true; } - boolean applyWindow = attrs.type >= FIRST_APPLICATION_WINDOW + boolean appWindow = attrs.type >= FIRST_APPLICATION_WINDOW && attrs.type <= LAST_APPLICATION_WINDOW; if (attrs.type == TYPE_DREAM) { // If the lockscreen was showing when the dream started then wait @@ -3399,30 +3401,35 @@ public class PhoneWindowManager implements WindowManagerPolicy { if (!mDreamingLockscreen || (win.isVisibleLw() && win.hasDrawnLw())) { mShowingDream = true; - applyWindow = true; + appWindow = true; } } - if (applyWindow - && attrs.x == 0 && attrs.y == 0 - && attrs.width == WindowManager.LayoutParams.MATCH_PARENT - && attrs.height == WindowManager.LayoutParams.MATCH_PARENT) { - if (DEBUG_LAYOUT) Slog.v(TAG, "Fullscreen window: " + win); - mTopFullscreenOpaqueWindowState = win; - if ((fl & FLAG_SHOW_WHEN_LOCKED) != 0) { - if (DEBUG_LAYOUT) Slog.v(TAG, "Setting mHideLockScreen to true by win " + win); - mHideLockScreen = true; - mForceStatusBarFromKeyguard = false; - } - if ((fl & FLAG_DISMISS_KEYGUARD) != 0 - && mDismissKeyguard == DISMISS_KEYGUARD_NONE) { - if (DEBUG_LAYOUT) Slog.v(TAG, "Setting mDismissKeyguard true by win " + win); - mDismissKeyguard = mWinDismissingKeyguard == win ? - DISMISS_KEYGUARD_CONTINUE : DISMISS_KEYGUARD_START; - mWinDismissingKeyguard = win; - mForceStatusBarFromKeyguard = mShowingLockscreen && isKeyguardSecure(); - } - if ((fl & FLAG_ALLOW_LOCK_WHILE_SCREEN_ON) != 0) { - mAllowLockscreenWhenOn = true; + + final boolean showWhenLocked = (fl & FLAG_SHOW_WHEN_LOCKED) != 0; + if (appWindow) { + if (attrs.x == 0 && attrs.y == 0 + && attrs.width == WindowManager.LayoutParams.MATCH_PARENT + && attrs.height == WindowManager.LayoutParams.MATCH_PARENT) { + if (DEBUG_LAYOUT) Slog.v(TAG, "Fullscreen window: " + win); + mTopFullscreenOpaqueWindowState = win; + if (showWhenLocked && !mHideWindowBehindKeyguard) { + if (DEBUG_LAYOUT) Slog.v(TAG, "Setting mHideLockScreen to true by win " + win); + mHideLockScreen = true; + mForceStatusBarFromKeyguard = false; + } + if ((fl & FLAG_DISMISS_KEYGUARD) != 0 + && mDismissKeyguard == DISMISS_KEYGUARD_NONE) { + if (DEBUG_LAYOUT) Slog.v(TAG, "Setting mDismissKeyguard true by win " + win); + mDismissKeyguard = mWinDismissingKeyguard == win ? + DISMISS_KEYGUARD_CONTINUE : DISMISS_KEYGUARD_START; + mWinDismissingKeyguard = win; + mForceStatusBarFromKeyguard = mShowingLockscreen && isKeyguardSecure(); + } + if ((fl & FLAG_ALLOW_LOCK_WHILE_SCREEN_ON) != 0) { + mAllowLockscreenWhenOn = true; + } + } else if (!showWhenLocked) { + mHideWindowBehindKeyguard = true; } } } @@ -3509,7 +3516,7 @@ public class PhoneWindowManager implements WindowManagerPolicy { if (mKeyguard != null) { if (localLOGV) Slog.v(TAG, "finishPostLayoutPolicyLw: mHideKeyguard=" + mHideLockScreen); - if (mDismissKeyguard != DISMISS_KEYGUARD_NONE && !mKeyguardDelegate.isSecure()) { + if (mDismissKeyguard != DISMISS_KEYGUARD_NONE && !isKeyguardSecure()) { if (mKeyguard.hideLw(true)) { changes |= FINISH_LAYOUT_REDO_LAYOUT | FINISH_LAYOUT_REDO_CONFIG diff --git a/rs/java/android/renderscript/RenderScript.java b/rs/java/android/renderscript/RenderScript.java index 4dd60459179f..d4fa5a709f25 100644 --- a/rs/java/android/renderscript/RenderScript.java +++ b/rs/java/android/renderscript/RenderScript.java @@ -1000,6 +1000,14 @@ public class RenderScript { } } + void validateObject(BaseObj o) { + if (o != null) { + if (o.mRS != this) { + throw new RSIllegalArgumentException("Attempting to use an object across contexts."); + } + } + } + void validate() { if (mContext == 0) { throw new RSInvalidStateException("Calling RS with no Context active."); diff --git a/rs/java/android/renderscript/Script.java b/rs/java/android/renderscript/Script.java index a1f228718436..0e46f94a583e 100644 --- a/rs/java/android/renderscript/Script.java +++ b/rs/java/android/renderscript/Script.java @@ -128,6 +128,9 @@ public class Script extends BaseObj { * */ protected void forEach(int slot, Allocation ain, Allocation aout, FieldPacker v) { + mRS.validate(); + mRS.validateObject(ain); + mRS.validateObject(aout); if (ain == null && aout == null) { throw new RSIllegalArgumentException( "At least one of ain or aout is required to be non-null."); @@ -152,6 +155,9 @@ public class Script extends BaseObj { * */ protected void forEach(int slot, Allocation ain, Allocation aout, FieldPacker v, LaunchOptions sc) { + mRS.validate(); + mRS.validateObject(ain); + mRS.validateObject(aout); if (ain == null && aout == null) { throw new RSIllegalArgumentException( "At least one of ain or aout is required to be non-null."); @@ -187,6 +193,7 @@ public class Script extends BaseObj { */ public void bindAllocation(Allocation va, int slot) { mRS.validate(); + mRS.validateObject(va); if (va != null) { if (mRS.getApplicationContext().getApplicationInfo().targetSdkVersion >= 20) { final Type t = va.mType; @@ -263,6 +270,8 @@ public class Script extends BaseObj { * */ public void setVar(int index, BaseObj o) { + mRS.validate(); + mRS.validateObject(o); mRS.nScriptSetVarObj(getID(mRS), index, (o == null) ? 0 : o.getID(mRS)); } diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java index 0b0b4efb3e2a..d91086156b9e 100644 --- a/services/core/java/com/android/server/am/ActivityManagerService.java +++ b/services/core/java/com/android/server/am/ActivityManagerService.java @@ -1073,6 +1073,8 @@ public final class ActivityManagerService extends ActivityManagerNative static final int IMMERSIVE_MODE_LOCK_MSG = 37; static final int PERSIST_URI_GRANTS_MSG = 38; static final int REQUEST_ALL_PSS_MSG = 39; + static final int START_RELATED_USERS_MSG = 40; + static final int UPDATE_TIME = 41; static final int FIRST_ACTIVITY_STACK_MSG = 100; static final int FIRST_BROADCAST_QUEUE_MSG = 200; @@ -1686,6 +1688,27 @@ public final class ActivityManagerService extends ActivityManagerNative requestPssAllProcsLocked(SystemClock.uptimeMillis(), true, false); break; } + case START_RELATED_USERS_MSG: { + synchronized (ActivityManagerService.this) { + startRelatedUsersLocked(); + } + break; + } + case UPDATE_TIME: { + synchronized (ActivityManagerService.this) { + for (int i = mLruProcesses.size() - 1 ; i >= 0 ; i--) { + ProcessRecord r = mLruProcesses.get(i); + if (r.thread != null) { + try { + r.thread.updateTimePrefs(msg.arg1 == 0 ? false : true); + } catch (RemoteException ex) { + Slog.w(TAG, "Failed to update preferences for: " + r.info.processName); + } + } + } + } + break; + } } } }; @@ -5164,10 +5187,11 @@ public final class ActivityManagerService extends ActivityManagerNative userId); } } + scheduleStartRelatedUsersLocked(); } } } - + final void ensureBootCompleted() { boolean booting; boolean enableScreen; @@ -5177,7 +5201,7 @@ public final class ActivityManagerService extends ActivityManagerNative enableScreen = !mBooted; mBooted = true; } - + if (booting) { finishBooting(); } @@ -9204,8 +9228,13 @@ public final class ActivityManagerService extends ActivityManagerNative ActivityInfo ai = ris.get(i).activityInfo; ComponentName comp = new ComponentName(ai.packageName, ai.name); if (lastDoneReceivers.contains(comp)) { + // We already did the pre boot receiver for this app with the current + // platform version, so don't do it again... ris.remove(i); i--; + // ...however, do keep it as one that has been done, so we don't + // forget about it when rewriting the file of last done receivers. + doneReceivers.add(comp); } } @@ -13433,11 +13462,20 @@ public final class ActivityManagerService extends ActivityManagerNative * of all currently running processes. This message will get queued up before the broadcast * happens. */ - if (intent.ACTION_TIMEZONE_CHANGED.equals(intent.getAction())) { + if (Intent.ACTION_TIMEZONE_CHANGED.equals(intent.getAction())) { mHandler.sendEmptyMessage(UPDATE_TIME_ZONE); } - if (intent.ACTION_CLEAR_DNS_CACHE.equals(intent.getAction())) { + /* + * If the user set the time, let all running processes know. + */ + if (Intent.ACTION_TIME_CHANGED.equals(intent.getAction())) { + final int is24Hour = intent.getBooleanExtra( + Intent.EXTRA_TIME_PREF_24_HOUR_FORMAT, false) ? 1 : 0; + mHandler.sendMessage(mHandler.obtainMessage(UPDATE_TIME, is24Hour, 0)); + } + + if (Intent.ACTION_CLEAR_DNS_CACHE.equals(intent.getAction())) { mHandler.sendEmptyMessage(CLEAR_DNS_CACHE_MSG); } @@ -16105,6 +16143,8 @@ public final class ActivityManagerService extends ActivityManagerNative throw new SecurityException(msg); } + if (DEBUG_MU) Slog.i(TAG_MU, "starting userid:" + userId + " fore:" + foreground); + final long ident = Binder.clearCallingIdentity(); try { synchronized (this) { @@ -16365,6 +16405,32 @@ public final class ActivityManagerService extends ActivityManagerNative } } + void scheduleStartRelatedUsersLocked() { + if (!mHandler.hasMessages(START_RELATED_USERS_MSG)) { + mHandler.sendMessageDelayed(mHandler.obtainMessage(START_RELATED_USERS_MSG), + DateUtils.SECOND_IN_MILLIS); + } + } + + void startRelatedUsersLocked() { + if (DEBUG_MU) Slog.i(TAG_MU, "startRelatedUsersLocked"); + List<UserInfo> relatedUsers = getUserManagerLocked().getRelatedUsers(mCurrentUserId); + List<UserInfo> toStart = new ArrayList<UserInfo>(relatedUsers.size()); + for (UserInfo relatedUser : relatedUsers) { + if ((relatedUser.flags & UserInfo.FLAG_INITIALIZED) == UserInfo.FLAG_INITIALIZED) { + toStart.add(relatedUser); + } + } + final int n = toStart.size(); + int i = 0; + for (; i < n && i < (MAX_RUNNING_USERS - 1); ++i) { + startUserInBackground(toStart.get(i).id); + } + if (i < n) { + Slog.w(TAG_MU, "More related users than MAX_RUNNING_USERS"); + } + } + void finishUserSwitch(UserStartedState uss) { synchronized (this) { if (uss.mState == UserStartedState.STATE_BOOTING @@ -16379,6 +16445,9 @@ public final class ActivityManagerService extends ActivityManagerNative android.Manifest.permission.RECEIVE_BOOT_COMPLETED, AppOpsManager.OP_NONE, true, false, MY_PID, Process.SYSTEM_UID, userId); } + + startRelatedUsersLocked(); + int num = mUserLru.size(); int i = 0; while (num > MAX_RUNNING_USERS && i < mUserLru.size()) { @@ -16430,6 +16499,7 @@ public final class ActivityManagerService extends ActivityManagerNative } private int stopUserLocked(final int userId, final IStopUserCallback callback) { + if (DEBUG_MU) Slog.i(TAG_MU, "stopUserLocked userId=" + userId); if (mCurrentUserId == userId) { return ActivityManager.USER_OP_IS_CURRENT; } diff --git a/services/core/java/com/android/server/am/CoreSettingsObserver.java b/services/core/java/com/android/server/am/CoreSettingsObserver.java index 10ea67c34465..4c887dd8e9d1 100644 --- a/services/core/java/com/android/server/am/CoreSettingsObserver.java +++ b/services/core/java/com/android/server/am/CoreSettingsObserver.java @@ -37,11 +37,16 @@ final class CoreSettingsObserver extends ContentObserver { private static final String LOG_TAG = CoreSettingsObserver.class.getSimpleName(); // mapping form property name to its type - private static final Map<String, Class<?>> sCoreSettingToTypeMap = new HashMap< + private static final Map<String, Class<?>> sSecureSettingToTypeMap = new HashMap< + String, Class<?>>(); + private static final Map<String, Class<?>> sSystemSettingToTypeMap = new HashMap< String, Class<?>>(); static { - sCoreSettingToTypeMap.put(Settings.Secure.LONG_PRESS_TIMEOUT, int.class); - // add other core settings here... + sSecureSettingToTypeMap.put(Settings.Secure.LONG_PRESS_TIMEOUT, int.class); + // add other secure settings here... + + sSystemSettingToTypeMap.put(Settings.System.TIME_12_24, String.class); + // add other system settings here... } private final Bundle mCoreSettings = new Bundle(); @@ -67,39 +72,62 @@ final class CoreSettingsObserver extends ContentObserver { } private void sendCoreSettings() { - populateCoreSettings(mCoreSettings); + populateSettings(mCoreSettings, sSecureSettingToTypeMap); + populateSettings(mCoreSettings, sSystemSettingToTypeMap); mActivityManagerService.onCoreSettingsChange(mCoreSettings); } private void beginObserveCoreSettings() { - for (String setting : sCoreSettingToTypeMap.keySet()) { + for (String setting : sSecureSettingToTypeMap.keySet()) { Uri uri = Settings.Secure.getUriFor(setting); mActivityManagerService.mContext.getContentResolver().registerContentObserver( uri, false, this); } + + for (String setting : sSystemSettingToTypeMap.keySet()) { + Uri uri = Settings.System.getUriFor(setting); + mActivityManagerService.mContext.getContentResolver().registerContentObserver( + uri, false, this); + } } - private void populateCoreSettings(Bundle snapshot) { + private void populateSettings(Bundle snapshot, Map<String, Class<?>> map) { Context context = mActivityManagerService.mContext; - for (Map.Entry<String, Class<?>> entry : sCoreSettingToTypeMap.entrySet()) { + for (Map.Entry<String, Class<?>> entry : map.entrySet()) { String setting = entry.getKey(); Class<?> type = entry.getValue(); try { if (type == String.class) { - String value = Settings.Secure.getString(context.getContentResolver(), - setting); + final String value; + if (map == sSecureSettingToTypeMap) { + value = Settings.Secure.getString(context.getContentResolver(), setting); + } else { + value = Settings.System.getString(context.getContentResolver(), setting); + } snapshot.putString(setting, value); } else if (type == int.class) { - int value = Settings.Secure.getInt(context.getContentResolver(), - setting); + final int value; + if (map == sSecureSettingToTypeMap) { + value = Settings.Secure.getInt(context.getContentResolver(), setting); + } else { + value = Settings.System.getInt(context.getContentResolver(), setting); + } snapshot.putInt(setting, value); } else if (type == float.class) { - float value = Settings.Secure.getFloat(context.getContentResolver(), - setting); + final float value; + if (map == sSecureSettingToTypeMap) { + value = Settings.Secure.getFloat(context.getContentResolver(), setting); + } else { + value = Settings.System.getFloat(context.getContentResolver(), setting); + } snapshot.putFloat(setting, value); } else if (type == long.class) { - long value = Settings.Secure.getLong(context.getContentResolver(), - setting); + final long value; + if (map == sSecureSettingToTypeMap) { + value = Settings.Secure.getLong(context.getContentResolver(), setting); + } else { + value = Settings.System.getLong(context.getContentResolver(), setting); + } snapshot.putLong(setting, value); } } catch (SettingNotFoundException snfe) { diff --git a/tools/aidl/Type.cpp b/tools/aidl/Type.cpp index d572af6d2aab..2267750623ad 100644 --- a/tools/aidl/Type.cpp +++ b/tools/aidl/Type.cpp @@ -1,5 +1,7 @@ #include "Type.h" +#include <sys/types.h> + Namespace NAMES; Type* VOID_TYPE; |