summaryrefslogtreecommitdiffstats
path: root/core/java/com/android
diff options
context:
space:
mode:
authorThe Android Open Source Project <initial-contribution@android.com>2009-03-02 22:54:33 -0800
committerThe Android Open Source Project <initial-contribution@android.com>2009-03-02 22:54:33 -0800
commit3dec7d563a2f3e1eb967ce2054a00b6620e3558c (patch)
treeaa3b0365c47cb3c1607c0dc76c8d32b4046fc287 /core/java/com/android
parent15ab3eae2ec3d73b3e8aa60b33ae41445bf83f4b (diff)
downloadframeworks_base-3dec7d563a2f3e1eb967ce2054a00b6620e3558c.zip
frameworks_base-3dec7d563a2f3e1eb967ce2054a00b6620e3558c.tar.gz
frameworks_base-3dec7d563a2f3e1eb967ce2054a00b6620e3558c.tar.bz2
auto import from //depot/cupcake/@137055
Diffstat (limited to 'core/java/com/android')
-rw-r--r--core/java/com/android/internal/app/IBatteryStats.aidl2
-rw-r--r--core/java/com/android/internal/app/UsbStorageStopActivity.java2
-rw-r--r--core/java/com/android/internal/gadget/IGadgetService.aidl1
-rw-r--r--core/java/com/android/internal/logging/AndroidConfig.java11
-rw-r--r--core/java/com/android/internal/logging/AndroidHandler.java69
-rw-r--r--core/java/com/android/internal/net/DbSSLSessionCache.java269
-rw-r--r--core/java/com/android/internal/net/SSLSessionCache.java101
-rw-r--r--core/java/com/android/internal/os/BatteryStatsImpl.java323
-rw-r--r--core/java/com/android/internal/os/ZygoteInit.java83
-rw-r--r--core/java/com/android/internal/view/IInputConnectionWrapper.java16
-rw-r--r--core/java/com/android/internal/view/IInputContext.aidl2
-rw-r--r--core/java/com/android/internal/view/InputConnectionWrapper.java9
-rw-r--r--core/java/com/android/internal/view/menu/ExpandedMenuView.java5
-rw-r--r--core/java/com/android/internal/widget/EditableInputConnection.java15
-rw-r--r--core/java/com/android/internal/widget/TextProgressBar.java4
15 files changed, 746 insertions, 166 deletions
diff --git a/core/java/com/android/internal/app/IBatteryStats.aidl b/core/java/com/android/internal/app/IBatteryStats.aidl
index b502a6c..edda1d9 100644
--- a/core/java/com/android/internal/app/IBatteryStats.aidl
+++ b/core/java/com/android/internal/app/IBatteryStats.aidl
@@ -28,6 +28,8 @@ interface IBatteryStats {
void noteStopGps(int uid);
void noteScreenOn();
void noteScreenOff();
+ void notePhoneOn();
+ void notePhoneOff();
void setOnBattery(boolean onBattery);
long getAwakeTimeBattery();
long getAwakeTimePlugged();
diff --git a/core/java/com/android/internal/app/UsbStorageStopActivity.java b/core/java/com/android/internal/app/UsbStorageStopActivity.java
index 30523c4..557a523 100644
--- a/core/java/com/android/internal/app/UsbStorageStopActivity.java
+++ b/core/java/com/android/internal/app/UsbStorageStopActivity.java
@@ -54,7 +54,7 @@ public class UsbStorageStopActivity extends AlertActivity implements DialogInter
// Set up the "dialog"
final AlertController.AlertParams p = mAlertParams;
- p.mIconId = com.android.internal.R.drawable.stat_sys_warning;
+ p.mIconId = com.android.internal.R.drawable.ic_dialog_alert;
p.mTitle = getString(com.android.internal.R.string.usb_storage_stop_title);
p.mMessage = getString(com.android.internal.R.string.usb_storage_stop_message);
p.mPositiveButtonText = getString(com.android.internal.R.string.usb_storage_stop_button_mount);
diff --git a/core/java/com/android/internal/gadget/IGadgetService.aidl b/core/java/com/android/internal/gadget/IGadgetService.aidl
index a22f3f3..9c66b95 100644
--- a/core/java/com/android/internal/gadget/IGadgetService.aidl
+++ b/core/java/com/android/internal/gadget/IGadgetService.aidl
@@ -44,6 +44,7 @@ interface IGadgetService {
List<GadgetProviderInfo> getInstalledProviders();
GadgetProviderInfo getGadgetInfo(int gadgetId);
void bindGadgetId(int gadgetId, in ComponentName provider);
+ int[] getGadgetIds(in ComponentName provider);
}
diff --git a/core/java/com/android/internal/logging/AndroidConfig.java b/core/java/com/android/internal/logging/AndroidConfig.java
index d8be889..f8002c6 100644
--- a/core/java/com/android/internal/logging/AndroidConfig.java
+++ b/core/java/com/android/internal/logging/AndroidConfig.java
@@ -34,11 +34,14 @@ public class AndroidConfig {
super();
try {
- Logger.global.addHandler(new AndroidHandler());
- Logger.global.setLevel(Level.ALL);
+ Logger rootLogger = Logger.getLogger("");
+ rootLogger.addHandler(new AndroidHandler());
+ rootLogger.setLevel(Level.INFO);
+
+ // Turn down logging in Apache libraries.
+ Logger.getLogger("org.apache").setLevel(Level.WARNING);
} catch (Exception ex) {
ex.printStackTrace();
}
- }
-
+ }
}
diff --git a/core/java/com/android/internal/logging/AndroidHandler.java b/core/java/com/android/internal/logging/AndroidHandler.java
index a6a4c64..d9fcf60 100644
--- a/core/java/com/android/internal/logging/AndroidHandler.java
+++ b/core/java/com/android/internal/logging/AndroidHandler.java
@@ -18,14 +18,14 @@ package com.android.internal.logging;
import android.util.Log;
-import java.util.logging.Formatter;
-import java.util.logging.Handler;
-import java.util.logging.Level;
-import java.util.logging.LogRecord;
-import java.util.logging.SimpleFormatter;
+import java.util.logging.*;
+import java.util.Date;
+import java.text.MessageFormat;
+import java.io.PrintWriter;
+import java.io.StringWriter;
/**
- * Implements a {@link java.util.Logger} handler that writes to the Android log. The
+ * Implements a {@link java.util.logging.Logger} handler that writes to the Android log. The
* implementation is rather straightforward. The name of the logger serves as
* the log tag. Only the log levels need to be converted appropriately. For
* this purpose, the following mapping is being used:
@@ -81,8 +81,24 @@ public class AndroidHandler extends Handler {
/**
* Holds the formatter for all Android log handlers.
*/
- private static final Formatter THE_FORMATTER = new SimpleFormatter();
-
+ private static final Formatter THE_FORMATTER = new Formatter() {
+ @Override
+ public String format(LogRecord r) {
+ Throwable thrown = r.getThrown();
+ if (thrown != null) {
+ StringWriter sw = new StringWriter();
+ PrintWriter pw = new PrintWriter(sw);
+ sw.write(r.getMessage());
+ sw.write("\n");
+ thrown.printStackTrace(pw);
+ pw.flush();
+ return sw.toString();
+ } else {
+ return r.getMessage();
+ }
+ }
+ };
+
/**
* Constructs a new instance of the Android log handler.
*/
@@ -106,27 +122,40 @@ public class AndroidHandler extends Handler {
int level = getAndroidLevel(record.getLevel());
String tag = record.getLoggerName();
+ if (tag == null) {
+ // Anonymous logger.
+ tag = "null";
+ } else {
+ // Tags must be <= 23 characters.
+ int length = tag.length();
+ if (length > 23) {
+ // Most loggers use the full class name. Try dropping the
+ // package.
+ int lastPeriod = tag.lastIndexOf(".");
+ if (length - lastPeriod - 1 <= 23) {
+ tag = tag.substring(lastPeriod + 1);
+ } else {
+ // Use last 23 chars.
+ tag = tag.substring(tag.length() - 23);
+ }
+ }
+ }
+
if (!Log.isLoggable(tag, level)) {
return;
}
-
- String msg;
- try {
- msg = getFormatter().format(record);
- } catch (RuntimeException e) {
- Log.e("AndroidHandler", "Error formatting log record", e);
- msg = record.getMessage();
- }
- Log.println(level, tag, msg);
+
+ String message = getFormatter().format(record);
+ Log.println(level, tag, message);
} catch (RuntimeException e) {
- Log.e("AndroidHandler", "Error publishing log record", e);
+ Log.e("AndroidHandler", "Error logging message.", e);
}
}
/**
- * Converts a {@link java.util.Logger} logging level into an Android one.
+ * Converts a {@link java.util.logging.Logger} logging level into an Android one.
*
- * @param level The {@link java.util.Logger} logging level.
+ * @param level The {@link java.util.logging.Logger} logging level.
*
* @return The resulting Android logging level.
*/
diff --git a/core/java/com/android/internal/net/DbSSLSessionCache.java b/core/java/com/android/internal/net/DbSSLSessionCache.java
new file mode 100644
index 0000000..06e4ca8
--- /dev/null
+++ b/core/java/com/android/internal/net/DbSSLSessionCache.java
@@ -0,0 +1,269 @@
+// Copyright 2009 The Android Open Source Project
+
+package com.android.internal.net;
+
+import android.content.ContentValues;
+import android.content.Context;
+import android.database.Cursor;
+import android.database.SQLException;
+import android.database.sqlite.SQLiteDatabase;
+import android.database.sqlite.SQLiteOpenHelper;
+import android.util.Log;
+
+import org.apache.commons.codec.binary.Base64;
+import org.apache.harmony.xnet.provider.jsse.SSLClientSessionCache;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import javax.net.ssl.SSLSession;
+
+/**
+ * Hook into harmony SSL cache to persist the SSL sessions.
+ *
+ * Current implementation is suitable for saving a small number of hosts -
+ * like google services. It can be extended with expiration and more features
+ * to support more hosts.
+ *
+ * {@hide}
+ */
+public class DbSSLSessionCache implements SSLClientSessionCache {
+ private static final String TAG = "DbSSLSessionCache";
+
+ /**
+ * Table where sessions are stored.
+ */
+ public static final String SSL_CACHE_TABLE = "ssl_sessions";
+
+ private static final String SSL_CACHE_ID = "_id";
+
+ /**
+ * Key is host:port - port is not optional.
+ */
+ private static final String SSL_CACHE_HOSTPORT = "hostport";
+
+ /**
+ * Base64-encoded DER value of the session.
+ */
+ private static final String SSL_CACHE_SESSION = "session";
+
+ /**
+ * Time when the record was added - should be close to the time
+ * of the initial session negotiation.
+ */
+ private static final String SSL_CACHE_TIME_SEC = "time_sec";
+
+ public static final String DATABASE_NAME = "ssl_sessions.db";
+
+ public static final int DATABASE_VERSION = 2;
+
+ /** public for testing
+ */
+ public static final int SSL_CACHE_ID_COL = 0;
+ public static final int SSL_CACHE_HOSTPORT_COL = 1;
+ public static final int SSL_CACHE_SESSION_COL = 2;
+ public static final int SSL_CACHE_TIME_SEC_COL = 3;
+
+ public static final int MAX_CACHE_SIZE = 256;
+
+ private final Map<String, byte[]> mExternalCache =
+ new HashMap<String, byte[]>();
+
+
+ private DatabaseHelper mDatabaseHelper;
+
+ private boolean mNeedsCacheLoad = true;
+
+ public static final String[] PROJECTION = new String[] {
+ SSL_CACHE_ID,
+ SSL_CACHE_HOSTPORT,
+ SSL_CACHE_SESSION,
+ SSL_CACHE_TIME_SEC
+ };
+
+ /**
+ * Create a SslSessionCache instance, using the specified context to
+ * initialize the database.
+ *
+ * This constructor will use the default database - created for the application
+ * context.
+ *
+ * @param activityContext
+ */
+ public DbSSLSessionCache(Context activityContext) {
+ Context appContext = activityContext.getApplicationContext();
+ mDatabaseHelper = new DatabaseHelper(appContext);
+ }
+
+ /**
+ * Create a SslSessionCache that uses a specific database.
+ *
+ *
+ * @param database
+ */
+ public DbSSLSessionCache(DatabaseHelper database) {
+ this.mDatabaseHelper = database;
+ }
+
+ public void putSessionData(SSLSession session, byte[] der) {
+ if (mDatabaseHelper == null) {
+ return;
+ }
+ synchronized (this.getClass()) {
+ SQLiteDatabase db = mDatabaseHelper.getWritableDatabase();
+ if (mExternalCache.size() == MAX_CACHE_SIZE) {
+ // remove oldest.
+ // TODO: check if the new one is in cached already ( i.e. update ).
+ Cursor byTime = mDatabaseHelper.getReadableDatabase().query(SSL_CACHE_TABLE,
+ PROJECTION, null, null, null, null, SSL_CACHE_TIME_SEC);
+ if (byTime.moveToFirst()) {
+ // TODO: can I do byTime.deleteRow() ?
+ String hostPort = byTime.getString(SSL_CACHE_HOSTPORT_COL);
+ db.delete(SSL_CACHE_TABLE,
+ SSL_CACHE_HOSTPORT + "= ?" , new String[] { hostPort });
+ mExternalCache.remove(hostPort);
+ } else {
+ Log.w(TAG, "No rows found");
+ // something is wrong, clear it
+ clear();
+ }
+ }
+ // Serialize native session to standard DER encoding
+ long t0 = System.currentTimeMillis();
+
+ String b64 = new String(Base64.encodeBase64(der));
+ String key = session.getPeerHost() + ":" + session.getPeerPort();
+
+ ContentValues values = new ContentValues();
+ values.put(SSL_CACHE_HOSTPORT, key);
+ values.put(SSL_CACHE_SESSION, b64);
+ values.put(SSL_CACHE_TIME_SEC, System.currentTimeMillis() / 1000);
+
+ mExternalCache.put(key, der);
+
+ try {
+ db.insert(SSL_CACHE_TABLE, null /*nullColumnHack */ , values);
+ } catch(SQLException ex) {
+ // Ignore - nothing we can do to recover, and caller shouldn't
+ // be affected.
+ Log.w(TAG, "Ignoring SQL exception when caching session", ex);
+ }
+ if (Log.isLoggable(TAG, Log.DEBUG)) {
+ long t1 = System.currentTimeMillis();
+ Log.d(TAG, "New SSL session " + session.getPeerHost() +
+ " DER len: " + der.length + " " + (t1 - t0));
+ }
+ }
+
+ }
+
+ public byte[] getSessionData(String host, int port) {
+ // Current (simple) implementation does a single lookup to DB, then saves
+ // all entries to the cache.
+
+ // This works for google services - i.e. small number of certs.
+ // If we extend this to all processes - we should hold a separate cache
+ // or do lookups to DB each time.
+ if (mDatabaseHelper == null) {
+ return null;
+ }
+ synchronized(this.getClass()) {
+ if (mNeedsCacheLoad) {
+ // Don't try to load again, if something is wrong on the first
+ // request it'll likely be wrong each time.
+ mNeedsCacheLoad = false;
+ long t0 = System.currentTimeMillis();
+
+ Cursor cur = null;
+ try {
+ cur = mDatabaseHelper.getReadableDatabase().query(SSL_CACHE_TABLE,
+ PROJECTION, null, null, null, null, null);
+ if (cur.moveToFirst()) {
+ do {
+ String hostPort = cur.getString(SSL_CACHE_HOSTPORT_COL);
+ String value = cur.getString(SSL_CACHE_SESSION_COL);
+
+ if (hostPort == null || value == null) {
+ continue;
+ }
+ // TODO: blob support ?
+ byte[] der = Base64.decodeBase64(value.getBytes());
+ mExternalCache.put(hostPort, der);
+ } while (cur.moveToNext());
+
+ }
+ } catch (SQLException ex) {
+ Log.d(TAG, "Error loading SSL cached entries ", ex);
+ } finally {
+ if (cur != null) {
+ cur.close();
+ }
+ if (Log.isLoggable(TAG, Log.DEBUG)) {
+ long t1 = System.currentTimeMillis();
+ Log.d(TAG, "LOADED CACHED SSL " + (t1 - t0) + " ms");
+ }
+ }
+ }
+
+ String key = host + ":" + port;
+
+ return mExternalCache.get(key);
+ }
+ }
+
+ /**
+ * Reset the database and internal state.
+ * Used for testing or to free space.
+ */
+ public void clear() {
+ synchronized(this) {
+ try {
+ mExternalCache.clear();
+ mNeedsCacheLoad = true;
+ mDatabaseHelper.getWritableDatabase().delete(SSL_CACHE_TABLE,
+ null, null);
+ } catch (SQLException ex) {
+ Log.d(TAG, "Error removing SSL cached entries ", ex);
+ // ignore - nothing we can do about it
+ }
+ }
+ }
+
+ public byte[] getSessionData(byte[] id) {
+ // We support client side only - the cache will do nothing for
+ // server-side sessions.
+ return null;
+ }
+
+ /** Visible for testing.
+ */
+ public static class DatabaseHelper extends SQLiteOpenHelper {
+
+ public DatabaseHelper(Context context) {
+ super(context, DATABASE_NAME, null /* factory */, DATABASE_VERSION);
+ }
+
+ @Override
+ public void onCreate(SQLiteDatabase db) {
+ db.execSQL("CREATE TABLE " + SSL_CACHE_TABLE + " (" +
+ SSL_CACHE_ID + " INTEGER PRIMARY KEY AUTOINCREMENT," +
+ SSL_CACHE_HOSTPORT + " TEXT UNIQUE ON CONFLICT REPLACE," +
+ SSL_CACHE_SESSION + " TEXT," +
+ SSL_CACHE_TIME_SEC + " INTEGER" +
+ ");");
+
+ // No index - we load on startup, index would slow down inserts.
+ // If we want to scale this to lots of rows - we could use
+ // index, but then we'll hit DB a bit too often ( including
+ // negative hits )
+ }
+
+ @Override
+ public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
+ db.execSQL("DROP TABLE IF EXISTS " + SSL_CACHE_TABLE );
+ onCreate(db);
+ }
+
+ }
+
+}
diff --git a/core/java/com/android/internal/net/SSLSessionCache.java b/core/java/com/android/internal/net/SSLSessionCache.java
new file mode 100644
index 0000000..ec02fe5
--- /dev/null
+++ b/core/java/com/android/internal/net/SSLSessionCache.java
@@ -0,0 +1,101 @@
+// Copyright 2009 The Android Open Source Project
+package com.android.internal.net;
+
+import org.apache.harmony.xnet.provider.jsse.SSLClientSessionCache;
+import org.apache.harmony.xnet.provider.jsse.SSLContextImpl;
+
+import java.security.KeyManagementException;
+import java.security.NoSuchAlgorithmException;
+
+import javax.net.ssl.SSLContext;
+import javax.net.ssl.SSLSocketFactory;
+import javax.net.ssl.TrustManager;
+
+import android.content.ContentResolver;
+import android.content.Context;
+import android.provider.Settings;
+import android.util.Log;
+
+/**
+ * Utility class to configure SSL session caching.
+ *
+ *
+ *
+ * {@hide}
+ */
+public class SSLSessionCache {
+ private static final String TAG = "SSLSessionCache";
+
+ private static final String CACHE_TYPE_DB = "db";
+
+ private static boolean sInitializationDone = false;
+
+ // One per process
+ private static DbSSLSessionCache sDbCache;
+
+ /**
+ * Check settings for ssl session caching.
+ *
+ * @return false if disabled.
+ */
+ public static boolean isEnabled(ContentResolver resolver) {
+ String sslCache = Settings.Gservices.getString(resolver,
+ Settings.Gservices.SSL_SESSION_CACHE);
+
+ if (Log.isLoggable(TAG, Log.DEBUG)) {
+ Log.d(TAG, "enabled " + sslCache);
+ }
+
+ return CACHE_TYPE_DB.equals(sslCache);
+ }
+
+ /**
+ * Return the configured session cache, or null if not enabled.
+ */
+ public static SSLClientSessionCache getSessionCache(Context context) {
+ if (context == null) {
+ return null;
+ }
+ if (!sInitializationDone) {
+ if (isEnabled(context.getContentResolver())) {
+ sDbCache = new DbSSLSessionCache(context);
+ return sDbCache;
+ }
+ // Don't check again.
+ sInitializationDone = true;
+ }
+ return sDbCache;
+ }
+
+ /**
+ * Construct the factory, using default constructor if caching is disabled.
+ * Refactored here to avoid duplication, used in tests.
+ */
+ public static SSLSocketFactory getSocketFactory(Context androidContext,
+ TrustManager[] trustManager) {
+ try {
+ if (androidContext != null) {
+ SSLClientSessionCache sessionCache = getSessionCache(androidContext);
+
+ if (sessionCache != null) {
+ SSLContextImpl sslContext = new SSLContextImpl();
+ sslContext.engineInit(null /* kms */,
+ trustManager, new java.security.SecureRandom(),
+ sessionCache, null /* serverCache */);
+ return sslContext.engineGetSocketFactory();
+ }
+ }
+ // default
+ SSLContext context = SSLContext.getInstance("TLS");
+ context.init(null, trustManager, new java.security.SecureRandom());
+ return context.getSocketFactory();
+
+ } catch (NoSuchAlgorithmException e) {
+ throw new AssertionError(e);
+ } catch (KeyManagementException e) {
+ throw new AssertionError(e);
+ }
+ }
+
+
+}
diff --git a/core/java/com/android/internal/os/BatteryStatsImpl.java b/core/java/com/android/internal/os/BatteryStatsImpl.java
index 558a122..7eea8b7 100644
--- a/core/java/com/android/internal/os/BatteryStatsImpl.java
+++ b/core/java/com/android/internal/os/BatteryStatsImpl.java
@@ -23,6 +23,7 @@ import android.os.ParcelFormatException;
import android.os.Parcelable;
import android.os.SystemClock;
import android.util.Log;
+import android.util.Printer;
import android.util.SparseArray;
import java.io.File;
@@ -39,14 +40,14 @@ import java.util.Map;
* otherwise.
*/
public final class BatteryStatsImpl extends BatteryStats {
-
private static final String TAG = "BatteryStatsImpl";
+ private static final boolean DEBUG = false;
// In-memory Parcel magic number, used to detect attempts to unmarshall bad data
private static final int MAGIC = 0xBA757475; // 'BATSTATS'
// Current on-disk Parcel version
- private static final int VERSION = 23;
+ private static final int VERSION = 25;
private final File mFile;
private final File mBackupFile;
@@ -86,9 +87,11 @@ public final class BatteryStatsImpl extends BatteryStats {
long mLastRealtime;
boolean mScreenOn;
- long mLastScreenOnTimeMillis;
- long mBatteryScreenOnTimeMillis;
- long mPluggedScreenOnTimeMillis;
+ Timer mScreenOnTimer;
+
+ boolean mPhoneOn;
+ Timer mPhoneOnTimer;
+
/**
* These provide time bases that discount the time the device is plugged
* in to power.
@@ -132,16 +135,45 @@ public final class BatteryStatsImpl extends BatteryStats {
// Times are in microseconds for better accuracy when dividing by the
// lock count, and are in "battery realtime" units.
+ /**
+ * The total time we have accumulated since the start of the original
+ * boot, to the last time something interesting happened in the
+ * current run.
+ */
long mTotalTime;
- long mLoadedTotalTime;
- long mLastTotalTime;
- long mUpdateTime;
/**
- * The value of mTotalTime when unplug() was last called, initially 0.
+ * The total time we loaded for the previous runs. Subtract this from
+ * mTotalTime to find the time for the current run of the system.
*/
- long mUnpluggedTotalTime;
+ long mLoadedTime;
+
+ /**
+ * The run time of the last run of the system, as loaded from the
+ * saved data.
+ */
+ long mLastTime;
+
+ /**
+ * The value of mTotalTime when unplug() was last called. Subtract
+ * this from mTotalTime to find the time since the last unplug from
+ * power.
+ */
+ long mUnpluggedTime;
+ /**
+ * The last time at which we updated the timer. If mNesting is > 0,
+ * subtract this from the current battery time to find the amount of
+ * time we have been running since we last computed an update.
+ */
+ long mUpdateTime;
+
+ /**
+ * The total time at which the timer was acquired, to determine if
+ * was actually held for an interesting duration.
+ */
+ long mAcquireTime;
+
Timer(int type, ArrayList<Timer> timerPool,
ArrayList<Unpluggable> unpluggables, Parcel in) {
mType = type;
@@ -151,10 +183,10 @@ public final class BatteryStatsImpl extends BatteryStats {
mLastCount = in.readInt();
mUnpluggedCount = in.readInt();
mTotalTime = in.readLong();
- mLoadedTotalTime = in.readLong();
- mLastTotalTime = in.readLong();
+ mLoadedTime = in.readLong();
+ mLastTime = in.readLong();
mUpdateTime = in.readLong();
- mUnpluggedTotalTime = in.readLong();
+ mUnpluggedTime = in.readLong();
unpluggables.add(this);
}
@@ -171,21 +203,41 @@ public final class BatteryStatsImpl extends BatteryStats {
out.writeInt(mLastCount);
out.writeInt(mUnpluggedCount);
out.writeLong(computeRunTimeLocked(batteryRealtime));
- out.writeLong(mLoadedTotalTime);
- out.writeLong(mLastTotalTime);
+ out.writeLong(mLoadedTime);
+ out.writeLong(mLastTime);
out.writeLong(mUpdateTime);
- out.writeLong(mUnpluggedTotalTime);
+ out.writeLong(mUnpluggedTime);
}
public void unplug(long batteryUptime, long batteryRealtime) {
- mUnpluggedTotalTime = computeRunTimeLocked(batteryRealtime);
+ if (DEBUG && mType < 0) {
+ Log.v(TAG, "unplug #" + mType + ": realtime=" + batteryRealtime
+ + " old mUnpluggedTime=" + mUnpluggedTime
+ + " old mUnpluggedCount=" + mUnpluggedCount);
+ }
+ mUnpluggedTime = computeRunTimeLocked(batteryRealtime);
mUnpluggedCount = mCount;
+ if (DEBUG && mType < 0) {
+ Log.v(TAG, "unplug #" + mType
+ + ": new mUnpluggedTime=" + mUnpluggedTime
+ + " new mUnpluggedCount=" + mUnpluggedCount);
+ }
}
public void plug(long batteryUptime, long batteryRealtime) {
if (mNesting > 0) {
+ if (DEBUG && mType < 0) {
+ Log.v(TAG, "plug #" + mType + ": realtime=" + batteryRealtime
+ + " old mTotalTime=" + mTotalTime
+ + " old mUpdateTime=" + mUpdateTime);
+ }
mTotalTime = computeRunTimeLocked(batteryRealtime);
mUpdateTime = batteryRealtime;
+ if (DEBUG && mType < 0) {
+ Log.v(TAG, "plug #" + mType
+ + ": new mTotalTime=" + mTotalTime
+ + " old mUpdateTime=" + mUpdateTime);
+ }
}
}
@@ -207,16 +259,16 @@ public final class BatteryStatsImpl extends BatteryStats {
}
@Override
- public long getTotalTime(long now, int which) {
+ public long getTotalTime(long batteryRealtime, int which) {
long val;
if (which == STATS_LAST) {
- val = mLastTotalTime;
+ val = mLastTime;
} else {
- val = computeRunTimeLocked(now);
+ val = computeRunTimeLocked(batteryRealtime);
if (which == STATS_UNPLUGGED) {
- val -= mUnpluggedTotalTime;
+ val -= mUnpluggedTime;
} else if (which != STATS_TOTAL) {
- val -= mLoadedTotalTime;
+ val -= mLoadedTime;
}
}
@@ -245,22 +297,32 @@ public final class BatteryStatsImpl extends BatteryStats {
+ " mLoadedCount=" + mLoadedCount + " mLastCount=" + mLastCount
+ " mUnpluggedCount=" + mUnpluggedCount);
Log.i("foo", "mTotalTime=" + mTotalTime
- + " mLoadedTotalTime=" + mLoadedTotalTime);
- Log.i("foo", "mLastTotalTime=" + mLastTotalTime
- + " mUpdateTime=" + mUpdateTime);
+ + " mLoadedTime=" + mLoadedTime);
+ Log.i("foo", "mLastTime=" + mLastTime
+ + " mUnpluggedTime=" + mUnpluggedTime);
+ Log.i("foo", "mUpdateTime=" + mUpdateTime
+ + " mAcquireTime=" + mAcquireTime);
}
void startRunningLocked(BatteryStatsImpl stats) {
if (mNesting++ == 0) {
mUpdateTime = stats.getBatteryRealtimeLocked(
SystemClock.elapsedRealtime() * 1000);
- // Accumulate time to all currently active timers before adding
- // this new one to the pool.
- refreshTimersLocked(stats, mTimerPool);
- // Add this timer to the active pool
- mTimerPool.add(this);
+ if (mTimerPool != null) {
+ // Accumulate time to all currently active timers before adding
+ // this new one to the pool.
+ refreshTimersLocked(stats, mTimerPool);
+ // Add this timer to the active pool
+ mTimerPool.add(this);
+ }
// Increment the count
mCount++;
+ mAcquireTime = mTotalTime;
+ if (DEBUG && mType < 0) {
+ Log.v(TAG, "start #" + mType + ": mUpdateTime=" + mUpdateTime
+ + " mTotalTime=" + mTotalTime + " mCount=" + mCount
+ + " mAcquireTime=" + mAcquireTime);
+ }
}
}
@@ -270,11 +332,31 @@ public final class BatteryStatsImpl extends BatteryStats {
return;
}
if (--mNesting == 0) {
- // Accumulate time to all active counters, scaled by the total
- // active in the pool, before taking this one out of the pool.
- refreshTimersLocked(stats, mTimerPool);
- // Remove this timer from the active pool
- mTimerPool.remove(this);
+ 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, mTimerPool);
+ // Remove this timer from the active pool
+ mTimerPool.remove(this);
+ } else {
+ final long realtime = SystemClock.elapsedRealtime() * 1000;
+ final long batteryRealtime = stats.getBatteryRealtimeLocked(realtime);
+ mNesting = 1;
+ mTotalTime = computeRunTimeLocked(batteryRealtime);
+ mNesting = 0;
+ }
+
+ if (DEBUG && mType < 0) {
+ Log.v(TAG, "stop #" + mType + ": mUpdateTime=" + mUpdateTime
+ + " mTotalTime=" + mTotalTime + " mCount=" + mCount
+ + " mAcquireTime=" + mAcquireTime);
+ }
+
+ if (mTotalTime == mAcquireTime) {
+ // If there was no change in the time, then discard this
+ // count. A somewhat cheezy strategy, but hey.
+ mCount--;
+ }
}
}
@@ -297,24 +379,28 @@ public final class BatteryStatsImpl extends BatteryStats {
private long computeRunTimeLocked(long curBatteryRealtime) {
return mTotalTime + (mNesting > 0
- ? (curBatteryRealtime - mUpdateTime) / mTimerPool.size() : 0);
+ ? (curBatteryRealtime - mUpdateTime)
+ / (mTimerPool != null ? mTimerPool.size() : 1)
+ : 0);
}
- void writeSummaryFromParcelLocked(Parcel out, long curBatteryUptime) {
- long runTime = computeRunTimeLocked(curBatteryUptime);
+ void writeSummaryFromParcelLocked(Parcel out, long batteryRealtime) {
+ long runTime = computeRunTimeLocked(batteryRealtime);
// Divide by 1000 for backwards compatibility
out.writeLong((runTime + 500) / 1000);
- out.writeLong(((runTime - mLoadedTotalTime) + 500) / 1000);
+ out.writeLong(((runTime - mLoadedTime) + 500) / 1000);
out.writeInt(mCount);
out.writeInt(mCount - mLoadedCount);
}
void readSummaryFromParcelLocked(Parcel in) {
// Multiply by 1000 for backwards compatibility
- mTotalTime = mLoadedTotalTime = in.readLong() * 1000;
- mLastTotalTime = in.readLong();
+ mTotalTime = mLoadedTime = in.readLong() * 1000;
+ mLastTime = in.readLong() * 1000;
+ mUnpluggedTime = mTotalTime;
mCount = mLoadedCount = in.readInt();
mLastCount = in.readInt();
+ mUnpluggedCount = mCount;
mNesting = 0;
}
}
@@ -357,47 +443,40 @@ public final class BatteryStatsImpl extends BatteryStats {
mUidStats.get(uid).noteStopGps();
}
- /**
- * When the device screen or battery state changes, update the appropriate "screen on time"
- * counter.
- */
- private void updateScreenOnTimeLocked(boolean screenOn) {
+ public void noteScreenOnLocked() {
if (!mScreenOn) {
- Log.w(TAG, "updateScreenOnTime without mScreenOn, ignored");
- return;
- }
- long now = SystemClock.elapsedRealtime();
- long elapsed = now - mLastScreenOnTimeMillis;
- if (mOnBattery) {
- mBatteryScreenOnTimeMillis += elapsed;
- } else {
- mPluggedScreenOnTimeMillis += elapsed;
+ mScreenOn = true;
+ mScreenOnTimer.startRunningLocked(this);
}
- if (screenOn) {
- mLastScreenOnTimeMillis = now;
+ }
+
+ public void noteScreenOffLocked() {
+ if (mScreenOn) {
+ mScreenOn = false;
+ mScreenOnTimer.stopRunningLocked(this);
}
}
- public void noteScreenOnLocked() {
- mScreenOn = true;
- mLastScreenOnTimeMillis = SystemClock.elapsedRealtime();
+ public void notePhoneOnLocked() {
+ if (!mPhoneOn) {
+ mPhoneOn = true;
+ mPhoneOnTimer.startRunningLocked(this);
+ }
}
- public void noteScreenOffLocked() {
- if (!mScreenOn) {
- Log.w(TAG, "noteScreenOff without mScreenOn, ignored");
- return;
+ public void notePhoneOffLocked() {
+ if (mPhoneOn) {
+ mPhoneOn = false;
+ mPhoneOnTimer.stopRunningLocked(this);
}
- updateScreenOnTimeLocked(false);
- mScreenOn = false;
}
- @Override public long getBatteryScreenOnTime() {
- return mBatteryScreenOnTimeMillis;
+ @Override public long getScreenOnTime(long batteryRealtime, int which) {
+ return mScreenOnTimer.getTotalTime(batteryRealtime, which);
}
- @Override public long getPluggedScreenOnTime() {
- return mPluggedScreenOnTimeMillis;
+ @Override public long getPhoneOnTime(long batteryRealtime, int which) {
+ return mPhoneOnTimer.getTotalTime(batteryRealtime, which);
}
@Override public boolean getIsOnBattery() {
@@ -1381,6 +1460,8 @@ public final class BatteryStatsImpl extends BatteryStats {
mFile = new File(filename);
mBackupFile = new File(filename + ".bak");
mStartCount++;
+ mScreenOnTimer = new Timer(-1, null, mUnpluggables);
+ mPhoneOnTimer = new Timer(-2, null, mUnpluggables);
mOnBattery = mOnBatteryInternal = false;
mTrackBatteryPastUptime = 0;
mTrackBatteryPastRealtime = 0;
@@ -1407,10 +1488,6 @@ public final class BatteryStatsImpl extends BatteryStats {
public void setOnBattery(boolean onBattery) {
synchronized(this) {
if (mOnBattery != onBattery) {
- if (mScreenOn) {
- updateScreenOnTimeLocked(true);
- }
-
mOnBattery = mOnBatteryInternal = onBattery;
long uptime = SystemClock.uptimeMillis() * 1000;
@@ -1425,7 +1502,7 @@ public final class BatteryStatsImpl extends BatteryStats {
} else {
mTrackBatteryPastUptime += uptime - mTrackBatteryUptimeStart;
mTrackBatteryPastRealtime += realtime - mTrackBatteryRealtimeStart;
- doPlug(mUnpluggedBatteryUptime, mUnpluggedBatteryRealtime);
+ doPlug(getBatteryUptimeLocked(uptime), getBatteryRealtimeLocked(realtime));
}
if ((mLastWriteTime + (60 * 1000)) < mSecRealtime) {
if (mFile != null) {
@@ -1447,10 +1524,10 @@ public final class BatteryStatsImpl extends BatteryStats {
@Override
public long computeUptime(long curTime, int which) {
switch (which) {
- case STATS_TOTAL: return mUptime + (curTime-mUptimeStart);
- case STATS_LAST: return mLastUptime;
- case STATS_CURRENT: return (curTime-mUptimeStart);
- case STATS_UNPLUGGED: return (curTime-mTrackBatteryUptimeStart);
+ case STATS_TOTAL: return mUptime + (curTime-mUptimeStart);
+ case STATS_LAST: return mLastUptime;
+ case STATS_CURRENT: return (curTime-mUptimeStart);
+ case STATS_UNPLUGGED: return (curTime-mTrackBatteryUptimeStart);
}
return 0;
}
@@ -1458,26 +1535,25 @@ public final class BatteryStatsImpl extends BatteryStats {
@Override
public long computeRealtime(long curTime, int which) {
switch (which) {
- case STATS_TOTAL: return mRealtime + (curTime-mRealtimeStart);
- case STATS_LAST: return mLastRealtime;
- case STATS_CURRENT: return (curTime-mRealtimeStart);
- case STATS_UNPLUGGED: return (curTime-mTrackBatteryRealtimeStart);
+ case STATS_TOTAL: return mRealtime + (curTime-mRealtimeStart);
+ case STATS_LAST: return mLastRealtime;
+ case STATS_CURRENT: return (curTime-mRealtimeStart);
+ case STATS_UNPLUGGED: return (curTime-mTrackBatteryRealtimeStart);
}
return 0;
}
@Override
public long computeBatteryUptime(long curTime, int which) {
- long uptime = getBatteryUptime(curTime);
switch (which) {
- case STATS_TOTAL:
- return mBatteryUptime + uptime;
- case STATS_LAST:
- return mBatteryLastUptime;
- case STATS_CURRENT:
- return uptime;
- case STATS_UNPLUGGED:
- return getBatteryUptimeLocked(curTime) - mUnpluggedBatteryUptime;
+ case STATS_TOTAL:
+ return mBatteryUptime + getBatteryUptime(curTime);
+ case STATS_LAST:
+ return mBatteryLastUptime;
+ case STATS_CURRENT:
+ return getBatteryUptime(curTime);
+ case STATS_UNPLUGGED:
+ return getBatteryUptimeLocked(curTime) - mUnpluggedBatteryUptime;
}
return 0;
}
@@ -1485,14 +1561,14 @@ public final class BatteryStatsImpl extends BatteryStats {
@Override
public long computeBatteryRealtime(long curTime, int which) {
switch (which) {
- case STATS_TOTAL:
- return mBatteryRealtime + getBatteryRealtimeLocked(curTime);
- case STATS_LAST:
- return mBatteryLastRealtime;
- case STATS_CURRENT:
- return getBatteryRealtimeLocked(curTime);
- case STATS_UNPLUGGED:
- return getBatteryRealtimeLocked(curTime) - mUnpluggedBatteryRealtime;
+ case STATS_TOTAL:
+ return mBatteryRealtime + getBatteryRealtimeLocked(curTime);
+ case STATS_LAST:
+ return mBatteryLastRealtime;
+ case STATS_CURRENT:
+ return getBatteryRealtimeLocked(curTime);
+ case STATS_UNPLUGGED:
+ return getBatteryRealtimeLocked(curTime) - mUnpluggedBatteryRealtime;
}
return 0;
}
@@ -1688,9 +1764,10 @@ public final class BatteryStatsImpl extends BatteryStats {
mLastRealtime = in.readLong();
mStartCount++;
- mBatteryScreenOnTimeMillis = in.readLong();
- mPluggedScreenOnTimeMillis = in.readLong();
mScreenOn = false;
+ mScreenOnTimer.readSummaryFromParcelLocked(in);
+ mPhoneOn = false;
+ mPhoneOnTimer.readSummaryFromParcelLocked(in);
final int NU = in.readInt();
for (int iu = 0; iu < NU; iu++) {
@@ -1764,9 +1841,10 @@ public final class BatteryStatsImpl extends BatteryStats {
* @param out the Parcel to be written to.
*/
public void writeSummaryToParcel(Parcel out) {
- final long NOW = getBatteryUptimeLocked();
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);
@@ -1780,8 +1858,8 @@ public final class BatteryStatsImpl extends BatteryStats {
out.writeLong(computeRealtime(NOWREAL_SYS, STATS_TOTAL));
out.writeLong(computeRealtime(NOWREAL_SYS, STATS_CURRENT));
- out.writeLong(mBatteryScreenOnTimeMillis);
- out.writeLong(mPluggedScreenOnTimeMillis);
+ mScreenOnTimer.writeSummaryFromParcelLocked(out, NOWREAL);
+ mPhoneOnTimer.writeSummaryFromParcelLocked(out, NOWREAL);
final int NU = mUidStats.size();
out.writeInt(NU);
@@ -1798,19 +1876,19 @@ public final class BatteryStatsImpl extends BatteryStats {
Uid.Wakelock wl = ent.getValue();
if (wl.mTimerFull != null) {
out.writeInt(1);
- wl.mTimerFull.writeSummaryFromParcelLocked(out, NOW);
+ wl.mTimerFull.writeSummaryFromParcelLocked(out, NOWREAL);
} else {
out.writeInt(0);
}
if (wl.mTimerPartial != null) {
out.writeInt(1);
- wl.mTimerPartial.writeSummaryFromParcelLocked(out, NOW);
+ wl.mTimerPartial.writeSummaryFromParcelLocked(out, NOWREAL);
} else {
out.writeInt(0);
}
if (wl.mTimerWindow != null) {
out.writeInt(1);
- wl.mTimerWindow.writeSummaryFromParcelLocked(out, NOW);
+ wl.mTimerWindow.writeSummaryFromParcelLocked(out, NOWREAL);
} else {
out.writeInt(0);
}
@@ -1826,7 +1904,7 @@ public final class BatteryStatsImpl extends BatteryStats {
Uid.Sensor se = ent.getValue();
if (se.mTimer != null) {
out.writeInt(1);
- se.mTimer.writeSummaryFromParcelLocked(out, NOW);
+ se.mTimer.writeSummaryFromParcelLocked(out, NOWREAL);
} else {
out.writeInt(0);
}
@@ -1897,9 +1975,10 @@ public final class BatteryStatsImpl extends BatteryStats {
mBatteryLastUptime = in.readLong();
mBatteryRealtime = in.readLong();
mBatteryLastRealtime = in.readLong();
- mBatteryScreenOnTimeMillis = in.readLong();
- mPluggedScreenOnTimeMillis = in.readLong();
mScreenOn = false;
+ mScreenOnTimer = new Timer(-1, null, mUnpluggables, in);
+ mPhoneOn = false;
+ mPhoneOnTimer = new Timer(-2, null, mUnpluggables, in);
mUptime = in.readLong();
mUptimeStart = in.readLong();
mLastUptime = in.readLong();
@@ -1912,6 +1991,8 @@ public final class BatteryStatsImpl extends BatteryStats {
mTrackBatteryUptimeStart = in.readLong();
mTrackBatteryPastRealtime = in.readLong();
mTrackBatteryRealtimeStart = in.readLong();
+ mUnpluggedBatteryUptime = in.readLong();
+ mUnpluggedBatteryRealtime = in.readLong();
mLastWriteTime = in.readLong();
mPartialTimers.clear();
@@ -1945,8 +2026,8 @@ public final class BatteryStatsImpl extends BatteryStats {
out.writeLong(mBatteryLastUptime);
out.writeLong(mBatteryRealtime);
out.writeLong(mBatteryLastRealtime);
- out.writeLong(mBatteryScreenOnTimeMillis);
- out.writeLong(mPluggedScreenOnTimeMillis);
+ mScreenOnTimer.writeToParcel(out, batteryRealtime);
+ mPhoneOnTimer.writeToParcel(out, batteryRealtime);
out.writeLong(mUptime);
out.writeLong(mUptimeStart);
out.writeLong(mLastUptime);
@@ -1954,10 +2035,12 @@ public final class BatteryStatsImpl extends BatteryStats {
out.writeLong(mRealtimeStart);
out.writeLong(mLastRealtime);
out.writeInt(mOnBattery ? 1 : 0);
- out.writeLong(mTrackBatteryPastUptime);
+ out.writeLong(batteryUptime);
out.writeLong(mTrackBatteryUptimeStart);
- out.writeLong(mTrackBatteryPastRealtime);
+ out.writeLong(batteryRealtime);
out.writeLong(mTrackBatteryRealtimeStart);
+ out.writeLong(mUnpluggedBatteryUptime);
+ out.writeLong(mUnpluggedBatteryRealtime);
out.writeLong(mLastWriteTime);
int size = mUidStats.size();
@@ -1980,4 +2063,14 @@ public final class BatteryStatsImpl extends BatteryStats {
return new BatteryStatsImpl[size];
}
};
+
+ public void dumpLocked(Printer pw) {
+ if (DEBUG) {
+ Log.i(TAG, "*** Screen timer:");
+ mScreenOnTimer.logState();
+ Log.i(TAG, "*** Phone timer:");
+ mPhoneOnTimer.logState();
+ }
+ super.dumpLocked(pw);
+ }
}
diff --git a/core/java/com/android/internal/os/ZygoteInit.java b/core/java/com/android/internal/os/ZygoteInit.java
index f21b62f..ac8b589 100644
--- a/core/java/com/android/internal/os/ZygoteInit.java
+++ b/core/java/com/android/internal/os/ZygoteInit.java
@@ -19,6 +19,7 @@ package com.android.internal.os;
import android.content.pm.ActivityInfo;
import android.content.res.Resources;
import android.content.res.TypedArray;
+import android.content.res.ColorStateList;
import android.graphics.drawable.Drawable;
import android.net.LocalServerSocket;
import android.os.Debug;
@@ -335,32 +336,18 @@ public class ZygoteInit {
mResources.startPreloading();
if (PRELOAD_RESOURCES) {
Log.i(TAG, "Preloading resources...");
+
long startTime = SystemClock.uptimeMillis();
TypedArray ar = mResources.obtainTypedArray(
com.android.internal.R.array.preloaded_drawables);
- int N = ar.length();
- for (int i=0; i<N; i++) {
- if (Debug.getGlobalAllocSize() > PRELOAD_GC_THRESHOLD) {
- if (Config.LOGV) {
- Log.v(TAG, " GC at " + Debug.getGlobalAllocSize());
- }
- runtime.gcSoftReferences();
- runtime.runFinalizationSync();
- Debug.resetGlobalAllocSize();
- }
- int id = ar.getResourceId(i, 0);
- if (Config.LOGV) {
- Log.v(TAG, "Preloading resource #" + Integer.toHexString(id));
- }
- if (id != 0) {
- Drawable dr = mResources.getDrawable(id);
- if ((dr.getChangingConfigurations()&~ActivityInfo.CONFIG_FONT_SCALE) != 0) {
- Log.w(TAG, "Preloaded drawable resource #0x"
- + Integer.toHexString(id)
- + " that varies with configuration!!");
- }
- }
- }
+ int N = preloadDrawables(runtime, ar);
+ Log.i(TAG, "...preloaded " + N + " resources in "
+ + (SystemClock.uptimeMillis()-startTime) + "ms.");
+
+ startTime = SystemClock.uptimeMillis();
+ ar = mResources.obtainTypedArray(
+ com.android.internal.R.array.preloaded_color_state_lists);
+ N = preloadColorStateLists(runtime, ar);
Log.i(TAG, "...preloaded " + N + " resources in "
+ (SystemClock.uptimeMillis()-startTime) + "ms.");
}
@@ -372,6 +359,56 @@ public class ZygoteInit {
}
}
+ private static int preloadColorStateLists(VMRuntime runtime, TypedArray ar) {
+ int N = ar.length();
+ for (int i=0; i<N; i++) {
+ if (Debug.getGlobalAllocSize() > PRELOAD_GC_THRESHOLD) {
+ if (Config.LOGV) {
+ Log.v(TAG, " GC at " + Debug.getGlobalAllocSize());
+ }
+ runtime.gcSoftReferences();
+ runtime.runFinalizationSync();
+ Debug.resetGlobalAllocSize();
+ }
+ int id = ar.getResourceId(i, 0);
+ if (Config.LOGV) {
+ Log.v(TAG, "Preloading resource #" + Integer.toHexString(id));
+ }
+ if (id != 0) {
+ mResources.getColorStateList(id);
+ }
+ }
+ return N;
+ }
+
+
+ private static int preloadDrawables(VMRuntime runtime, TypedArray ar) {
+ int N = ar.length();
+ for (int i=0; i<N; i++) {
+ if (Debug.getGlobalAllocSize() > PRELOAD_GC_THRESHOLD) {
+ if (Config.LOGV) {
+ Log.v(TAG, " GC at " + Debug.getGlobalAllocSize());
+ }
+ runtime.gcSoftReferences();
+ runtime.runFinalizationSync();
+ Debug.resetGlobalAllocSize();
+ }
+ int id = ar.getResourceId(i, 0);
+ if (Config.LOGV) {
+ Log.v(TAG, "Preloading resource #" + Integer.toHexString(id));
+ }
+ if (id != 0) {
+ Drawable dr = mResources.getDrawable(id);
+ if ((dr.getChangingConfigurations()&~ActivityInfo.CONFIG_FONT_SCALE) != 0) {
+ Log.w(TAG, "Preloaded drawable resource #0x"
+ + Integer.toHexString(id)
+ + " (" + ar.getString(i) + ") that varies with configuration!!");
+ }
+ }
+ }
+ return N;
+ }
+
/**
* Runs several special GCs to try to clean up a few generations of
* softly- and final-reachable objects, along with any other garbage.
diff --git a/core/java/com/android/internal/view/IInputConnectionWrapper.java b/core/java/com/android/internal/view/IInputConnectionWrapper.java
index 4f98cee..8e65177 100644
--- a/core/java/com/android/internal/view/IInputConnectionWrapper.java
+++ b/core/java/com/android/internal/view/IInputConnectionWrapper.java
@@ -23,7 +23,8 @@ public class IInputConnectionWrapper extends IInputContext.Stub {
private static final int DO_COMMIT_TEXT = 50;
private static final int DO_COMMIT_COMPLETION = 55;
private static final int DO_SET_SELECTION = 57;
- private static final int DO_PERFORM_CONTEXT_MENU_ACTION = 58;
+ private static final int DO_PERFORM_EDITOR_ACTION = 58;
+ private static final int DO_PERFORM_CONTEXT_MENU_ACTION = 59;
private static final int DO_SET_COMPOSING_TEXT = 60;
private static final int DO_FINISH_COMPOSING_TEXT = 65;
private static final int DO_SEND_KEY_EVENT = 70;
@@ -97,6 +98,10 @@ public class IInputConnectionWrapper extends IInputContext.Stub {
dispatchMessage(obtainMessageII(DO_SET_SELECTION, start, end));
}
+ public void performEditorAction(int id) {
+ dispatchMessage(obtainMessageII(DO_PERFORM_EDITOR_ACTION, id, 0));
+ }
+
public void performContextMenuAction(int id) {
dispatchMessage(obtainMessageII(DO_PERFORM_CONTEXT_MENU_ACTION, id, 0));
}
@@ -235,6 +240,15 @@ public class IInputConnectionWrapper extends IInputContext.Stub {
ic.setSelection(msg.arg1, msg.arg2);
return;
}
+ case DO_PERFORM_EDITOR_ACTION: {
+ InputConnection ic = mInputConnection.get();
+ if (ic == null || !isActive()) {
+ Log.w(TAG, "performEditorAction on inactive InputConnection");
+ return;
+ }
+ ic.performEditorAction(msg.arg1);
+ return;
+ }
case DO_PERFORM_CONTEXT_MENU_ACTION: {
InputConnection ic = mInputConnection.get();
if (ic == null || !isActive()) {
diff --git a/core/java/com/android/internal/view/IInputContext.aidl b/core/java/com/android/internal/view/IInputContext.aidl
index 02b6044..02cb9e4 100644
--- a/core/java/com/android/internal/view/IInputContext.aidl
+++ b/core/java/com/android/internal/view/IInputContext.aidl
@@ -50,6 +50,8 @@ import com.android.internal.view.IInputContextCallback;
void setSelection(int start, int end);
+ void performEditorAction(int actionCode);
+
void performContextMenuAction(int id);
void beginBatchEdit();
diff --git a/core/java/com/android/internal/view/InputConnectionWrapper.java b/core/java/com/android/internal/view/InputConnectionWrapper.java
index 32d9f3d..b92cb45 100644
--- a/core/java/com/android/internal/view/InputConnectionWrapper.java
+++ b/core/java/com/android/internal/view/InputConnectionWrapper.java
@@ -250,6 +250,15 @@ public class InputConnectionWrapper implements InputConnection {
}
}
+ public boolean performEditorAction(int actionCode) {
+ try {
+ mIInputContext.performEditorAction(actionCode);
+ return true;
+ } catch (RemoteException e) {
+ return false;
+ }
+ }
+
public boolean performContextMenuAction(int id) {
try {
mIInputContext.performContextMenuAction(id);
diff --git a/core/java/com/android/internal/view/menu/ExpandedMenuView.java b/core/java/com/android/internal/view/menu/ExpandedMenuView.java
index c16c165..9e4b4ce 100644
--- a/core/java/com/android/internal/view/menu/ExpandedMenuView.java
+++ b/core/java/com/android/internal/view/menu/ExpandedMenuView.java
@@ -80,6 +80,11 @@ public final class ExpandedMenuView extends ListView implements ItemInvoker, Men
setChildrenDrawingCacheEnabled(false);
}
+ @Override
+ protected boolean recycleOnMeasure() {
+ return false;
+ }
+
public boolean invokeItem(MenuItemImpl item) {
return mMenu.performItemAction(item, 0);
}
diff --git a/core/java/com/android/internal/widget/EditableInputConnection.java b/core/java/com/android/internal/widget/EditableInputConnection.java
index 44cf0ed..f2ec064 100644
--- a/core/java/com/android/internal/widget/EditableInputConnection.java
+++ b/core/java/com/android/internal/widget/EditableInputConnection.java
@@ -59,7 +59,14 @@ public class EditableInputConnection extends BaseInputConnection {
final Editable content = getEditable();
if (content == null) return false;
KeyListener kl = mTextView.getKeyListener();
- if (kl != null) kl.clearMetaKeyState(mTextView, content, states);
+ if (kl != null) {
+ try {
+ kl.clearMetaKeyState(mTextView, content, states);
+ } catch (AbstractMethodError e) {
+ // This is an old listener that doesn't implement the
+ // new method.
+ }
+ }
return true;
}
@@ -71,6 +78,12 @@ public class EditableInputConnection extends BaseInputConnection {
return true;
}
+ public boolean performEditorAction(int actionCode) {
+ if (DEBUG) Log.v(TAG, "performEditorAction " + actionCode);
+ mTextView.onEditorAction(actionCode);
+ return true;
+ }
+
public boolean performContextMenuAction(int id) {
if (DEBUG) Log.v(TAG, "performContextMenuAction " + id);
mTextView.beginBatchEdit();
diff --git a/core/java/com/android/internal/widget/TextProgressBar.java b/core/java/com/android/internal/widget/TextProgressBar.java
index 5bf4601..aee7b76 100644
--- a/core/java/com/android/internal/widget/TextProgressBar.java
+++ b/core/java/com/android/internal/widget/TextProgressBar.java
@@ -115,8 +115,10 @@ public class TextProgressBar extends RelativeLayout implements OnChronometerTick
// Update the ProgressBar maximum relative to Chronometer base
mDuration = (int) (durationBase - mChronometer.getBase());
+ if (mDuration <= 0) {
+ mDuration = 1;
+ }
mProgressBar.setMax(mDuration);
-
}
/**