diff --git a/core/java/android/bluetooth/BluetoothDevice.java b/core/java/android/bluetooth/BluetoothDevice.java
index abf08cbfc7658..951b4b0ab471c 100644
--- a/core/java/android/bluetooth/BluetoothDevice.java
+++ b/core/java/android/bluetooth/BluetoothDevice.java
@@ -485,7 +485,8 @@ public class BluetoothDevice {
* Get the major, minor and servics classes of a remote device.
* These classes are encoded as a 32-bit integer. See BluetoothClass.
* @param address remote device
- * @return 32-bit class suitable for use with BluetoothClass.
+ * @return 32-bit class suitable for use with BluetoothClass, or
+ * BluetoothClass.ERROR on error
*/
public int getRemoteClass(String address) {
try {
diff --git a/core/java/android/os/BatteryStats.java b/core/java/android/os/BatteryStats.java
index b0ae0e60b42e9..17594d410d701 100644
--- a/core/java/android/os/BatteryStats.java
+++ b/core/java/android/os/BatteryStats.java
@@ -40,19 +40,26 @@ public abstract class BatteryStats implements Parcelable {
*/
public static final int SENSOR = 3;
+ /**
+ * A constant indicating a a wifi turn on timer
+ *
+ * {@hide}
+ */
+ public static final int WIFI_TURNED_ON = 4;
+
/**
* A constant indicating a full wifi lock timer
*
* {@hide}
*/
- public static final int FULL_WIFI_LOCK = 4;
+ public static final int FULL_WIFI_LOCK = 5;
/**
* A constant indicating a scan wifi lock timer
*
* {@hide}
*/
- public static final int SCAN_WIFI_LOCK = 5;
+ public static final int SCAN_WIFI_LOCK = 6;
/**
* Include all of the data in the stats, including previously saved data.
@@ -77,7 +84,11 @@ public abstract class BatteryStats implements Parcelable {
/**
* Bump the version on this if the checkin format changes.
*/
- private static final int BATTERY_STATS_CHECKIN_VERSION = 1;
+ private static final int BATTERY_STATS_CHECKIN_VERSION = 3;
+
+ private static final long BYTES_PER_KB = 1024;
+ private static final long BYTES_PER_MB = 1048576; // 1024^2
+ private static final long BYTES_PER_GB = 1073741824; //1024^3
// TODO: Update this list if you add/change any stats above.
private static final String[] STAT_NAMES = { "total", "last", "current", "unplugged" };
@@ -87,15 +98,38 @@ public abstract class BatteryStats implements Parcelable {
private static final String SENSOR_DATA = "sensor";
private static final String WAKELOCK_DATA = "wakelock";
private static final String NETWORK_DATA = "network";
+ private static final String USER_ACTIVITY_DATA = "useract";
private static final String BATTERY_DATA = "battery";
private static final String WIFI_LOCK_DATA = "wifilock";
private static final String MISC_DATA = "misc";
- private static final String SIGNAL_STRENGTH_DATA = "signal";
- private static final String DATA_CONNECTION_DATA = "dataconn";
+ private static final String SCREEN_BRIGHTNESS_DATA = "brightness";
+ private static final String SIGNAL_STRENGTH_TIME_DATA = "sigtime";
+ private static final String SIGNAL_STRENGTH_COUNT_DATA = "sigcnt";
+ private static final String DATA_CONNECTION_TIME_DATA = "dconntime";
+ private static final String DATA_CONNECTION_COUNT_DATA = "dconncnt";
private final StringBuilder mFormatBuilder = new StringBuilder(8);
private final Formatter mFormatter = new Formatter(mFormatBuilder);
+ /**
+ * State for keeping track of counting information.
+ */
+ public static abstract class Counter {
+
+ /**
+ * Returns the count associated with this Counter for the
+ * selected type of statistics.
+ *
+ * @param which one of STATS_TOTAL, STATS_LAST, or STATS_CURRENT
+ */
+ public abstract int getCount(int which);
+
+ /**
+ * Temporary for debugging.
+ */
+ public abstract void logState(Printer pw, String prefix);
+ }
+
/**
* State for keeping track of timing information.
*/
@@ -180,13 +214,29 @@ public abstract class BatteryStats implements Parcelable {
*/
public abstract long getTcpBytesSent(int which);
+ public abstract void noteWifiTurnedOnLocked();
+ public abstract void noteWifiTurnedOffLocked();
public abstract void noteFullWifiLockAcquiredLocked();
public abstract void noteFullWifiLockReleasedLocked();
public abstract void noteScanWifiLockAcquiredLocked();
public abstract void noteScanWifiLockReleasedLocked();
+ public abstract long getWifiTurnedOnTime(long batteryRealtime, int which);
public abstract long getFullWifiLockTime(long batteryRealtime, int which);
public abstract long getScanWifiLockTime(long batteryRealtime, int which);
+ /**
+ * Note that these must match the constants in android.os.LocalPowerManager.
+ */
+ static final String[] USER_ACTIVITY_TYPES = {
+ "other", "cheek", "touch", "long_touch", "touch_up", "button", "unknown"
+ };
+
+ public static final int NUM_USER_ACTIVITY_TYPES = 7;
+
+ public abstract void noteUserActivityLocked(int type);
+ public abstract boolean hasUserActivity();
+ public abstract int getUserActivityCount(int type, int which);
+
public static abstract class Sensor {
// Magic sensor number for the GPS.
public static final int GPS = -10000;
@@ -285,6 +335,29 @@ public abstract class BatteryStats implements Parcelable {
*/
public abstract long getScreenOnTime(long batteryRealtime, int which);
+ public static final int SCREEN_BRIGHTNESS_DARK = 0;
+ public static final int SCREEN_BRIGHTNESS_DIM = 1;
+ public static final int SCREEN_BRIGHTNESS_MEDIUM = 2;
+ public static final int SCREEN_BRIGHTNESS_LIGHT = 3;
+ public static final int SCREEN_BRIGHTNESS_BRIGHT = 4;
+
+ static final String[] SCREEN_BRIGHTNESS_NAMES = {
+ "dark", "dim", "medium", "light", "bright"
+ };
+
+ public static final int NUM_SCREEN_BRIGHTNESS_BINS = 5;
+
+ /**
+ * Returns the time in milliseconds that the screen has been on with
+ * the given brightness
+ *
+ * {@hide}
+ */
+ public abstract long getScreenBrightnessTime(int brightnessBin,
+ long batteryRealtime, int which);
+
+ public abstract int getInputEventCount(int which);
+
/**
* Returns the time in milliseconds that the phone has been on while the device was
* running on battery.
@@ -314,6 +387,13 @@ public abstract class BatteryStats implements Parcelable {
public abstract long getPhoneSignalStrengthTime(int strengthBin,
long batteryRealtime, int which);
+ /**
+ * Returns the number of times the phone has entered the given signal strength.
+ *
+ * {@hide}
+ */
+ public abstract int getPhoneSignalStrengthCount(int strengthBin, int which);
+
public static final int DATA_CONNECTION_NONE = 0;
public static final int DATA_CONNECTION_GPRS = 1;
public static final int DATA_CONNECTION_EDGE = 2;
@@ -335,6 +415,14 @@ public abstract class BatteryStats implements Parcelable {
public abstract long getPhoneDataConnectionTime(int dataType,
long batteryRealtime, int which);
+ /**
+ * Returns the number of times the phone has entered the given data
+ * connection type.
+ *
+ * {@hide}
+ */
+ public abstract int getPhoneDataConnectionCount(int dataType, int which);
+
/**
* Returns the time in milliseconds that wifi has been on while the device was
* running on battery.
@@ -482,6 +570,23 @@ public abstract class BatteryStats implements Parcelable {
return mFormatBuilder.toString();
}
+ private final String formatBytesLocked(long bytes) {
+ mFormatBuilder.setLength(0);
+
+ if (bytes < BYTES_PER_KB) {
+ return bytes + "B";
+ } else if (bytes < BYTES_PER_MB) {
+ mFormatter.format("%.2fKB", bytes / (double) BYTES_PER_KB);
+ return mFormatBuilder.toString();
+ } else if (bytes < BYTES_PER_GB){
+ mFormatter.format("%.2fMB", bytes / (double) BYTES_PER_MB);
+ return mFormatBuilder.toString();
+ } else {
+ mFormatter.format("%.2fGB", bytes / (double) BYTES_PER_GB);
+ return mFormatBuilder.toString();
+ }
+ }
+
/**
*
* @param sb a StringBuilder object.
@@ -590,40 +695,89 @@ public abstract class BatteryStats implements Parcelable {
StringBuilder sb = new StringBuilder(128);
+ SparseArray extends Uid> uidStats = getUidStats();
+ final int NU = uidStats.size();
+
String category = STAT_NAMES[which];
// Dump "battery" stat
dumpLine(pw, 0 /* uid */, category, BATTERY_DATA,
which == STATS_TOTAL ? getStartCount() : "N/A",
- whichBatteryUptime / 1000, whichBatteryRealtime / 1000,
- totalUptime / 1000, totalRealtime / 1000);
+ whichBatteryRealtime / 1000, whichBatteryUptime / 1000,
+ totalRealtime / 1000, totalUptime / 1000);
+
+ // Calculate total network and wakelock times across all uids.
+ long rxTotal = 0;
+ long txTotal = 0;
+ long fullWakeLockTimeTotal = 0;
+ long partialWakeLockTimeTotal = 0;
+
+ for (int iu = 0; iu < NU; iu++) {
+ Uid u = uidStats.valueAt(iu);
+ rxTotal += u.getTcpBytesReceived(which);
+ txTotal += u.getTcpBytesSent(which);
+
+ Map wakelocks = u.getWakelockStats();
+ if (wakelocks.size() > 0) {
+ for (Map.Entry ent
+ : wakelocks.entrySet()) {
+ Uid.Wakelock wl = ent.getValue();
+
+ Timer fullWakeTimer = wl.getWakeTime(WAKE_TYPE_FULL);
+ if (fullWakeTimer != null) {
+ fullWakeLockTimeTotal += fullWakeTimer.getTotalTime(batteryRealtime, which);
+ }
+
+ Timer partialWakeTimer = wl.getWakeTime(WAKE_TYPE_PARTIAL);
+ if (partialWakeTimer != null) {
+ partialWakeLockTimeTotal += partialWakeTimer.getTotalTime(
+ batteryRealtime, which);
+ }
+ }
+ }
+ }
// Dump misc stats
dumpLine(pw, 0 /* uid */, category, MISC_DATA,
screenOnTime / 1000, phoneOnTime / 1000, wifiOnTime / 1000,
- wifiRunningTime / 1000, bluetoothOnTime / 1000);
+ wifiRunningTime / 1000, bluetoothOnTime / 1000, rxTotal, txTotal,
+ fullWakeLockTimeTotal, partialWakeLockTimeTotal,
+ getInputEventCount(which));
+
+ // Dump screen brightness stats
+ Object[] args = new Object[NUM_SCREEN_BRIGHTNESS_BINS];
+ for (int i=0; i uidStats = getUidStats();
- final int NU = uidStats.size();
for (int iu = 0; iu < NU; iu++) {
final int uid = uidStats.keyAt(iu);
Uid u = uidStats.valueAt(iu);
@@ -632,14 +786,29 @@ public abstract class BatteryStats implements Parcelable {
long tx = u.getTcpBytesSent(which);
long fullWifiLockOnTime = u.getFullWifiLockTime(batteryRealtime, which);
long scanWifiLockOnTime = u.getScanWifiLockTime(batteryRealtime, which);
+ long wifiTurnedOnTime = u.getWifiTurnedOnTime(batteryRealtime, which);
if (rx > 0 || tx > 0) dumpLine(pw, uid, category, NETWORK_DATA, rx, tx);
- if (fullWifiLockOnTime != 0 || scanWifiLockOnTime != 0) {
+ if (fullWifiLockOnTime != 0 || scanWifiLockOnTime != 0
+ || wifiTurnedOnTime != 0) {
dumpLine(pw, uid, category, WIFI_LOCK_DATA,
- fullWifiLockOnTime, scanWifiLockOnTime);
+ fullWifiLockOnTime, scanWifiLockOnTime, wifiTurnedOnTime);
}
+ if (u.hasUserActivity()) {
+ args = new Object[Uid.NUM_USER_ACTIVITY_TYPES];
+ boolean hasData = false;
+ for (int i=0; i wakelocks = u.getWakelockStats();
if (wakelocks.size() > 0) {
for (Map.Entry ent
@@ -741,20 +910,24 @@ public abstract class BatteryStats implements Parcelable {
final long totalUptime = computeUptime(rawUptime, which);
StringBuilder sb = new StringBuilder(128);
+
+ SparseArray extends Uid> uidStats = getUidStats();
+ final int NU = uidStats.size();
pw.println(prefix
- + " Time on battery: " + formatTimeMs(whichBatteryUptime / 1000)
- + "(" + formatRatioLocked(whichBatteryUptime, totalRealtime)
- + ") uptime, "
+ + " Time on battery: "
+ formatTimeMs(whichBatteryRealtime / 1000) + "("
+ formatRatioLocked(whichBatteryRealtime, totalRealtime)
- + ") realtime");
+ + ") realtime, "
+ + formatTimeMs(whichBatteryUptime / 1000)
+ + "(" + formatRatioLocked(whichBatteryUptime, totalRealtime)
+ + ") uptime");
pw.println(prefix
- + " Total: "
- + formatTimeMs(totalUptime / 1000)
- + "uptime, "
+ + " Total run time: "
+ formatTimeMs(totalRealtime / 1000)
- + "realtime");
+ + "realtime, "
+ + formatTimeMs(totalUptime / 1000)
+ + "uptime, ");
final long screenOnTime = getScreenOnTime(batteryRealtime, which);
final long phoneOnTime = getPhoneOnTime(batteryRealtime, which);
@@ -764,19 +937,73 @@ public abstract class BatteryStats implements Parcelable {
pw.println(prefix
+ " Screen on: " + formatTimeMs(screenOnTime / 1000)
+ "(" + formatRatioLocked(screenOnTime, whichBatteryRealtime)
- + "), Phone on: " + formatTimeMs(phoneOnTime / 1000)
- + "(" + formatRatioLocked(phoneOnTime, whichBatteryRealtime));
+ + "), Input events: " + getInputEventCount(which)
+ + ", Active phone call: " + formatTimeMs(phoneOnTime / 1000)
+ + "(" + formatRatioLocked(phoneOnTime, whichBatteryRealtime) + ")");
+ sb.setLength(0);
+ sb.append(" Screen brightnesses: ");
+ boolean didOne = false;
+ for (int i=0; i wakelocks = u.getWakelockStats();
+ if (wakelocks.size() > 0) {
+ for (Map.Entry ent
+ : wakelocks.entrySet()) {
+ Uid.Wakelock wl = ent.getValue();
+
+ Timer fullWakeTimer = wl.getWakeTime(WAKE_TYPE_FULL);
+ if (fullWakeTimer != null) {
+ fullWakeLockTimeTotalMicros += fullWakeTimer.getTotalTime(
+ batteryRealtime, which);
+ }
+
+ Timer partialWakeTimer = wl.getWakeTime(WAKE_TYPE_PARTIAL);
+ if (partialWakeTimer != null) {
+ partialWakeLockTimeTotalMicros += partialWakeTimer.getTotalTime(
+ batteryRealtime, which);
+ }
+ }
+ }
+ }
+
pw.println(prefix
- + " Wifi on: " + formatTimeMs(wifiOnTime / 1000)
- + "(" + formatRatioLocked(wifiOnTime, whichBatteryRealtime)
- + "), Wifi running: " + formatTimeMs(wifiRunningTime / 1000)
- + "(" + formatRatioLocked(wifiRunningTime, whichBatteryRealtime)
- + "), Bluetooth on: " + formatTimeMs(bluetoothOnTime / 1000)
- + "(" + formatRatioLocked(bluetoothOnTime, whichBatteryRealtime)+ ")");
+ + " Total received: " + formatBytesLocked(rxTotal)
+ + ", Total sent: " + formatBytesLocked(txTotal));
+ pw.println(prefix
+ + " Total full wakelock time: " + formatTimeMs(
+ (fullWakeLockTimeTotalMicros + 500) / 1000)
+ + ", Total partial waklock time: " + formatTimeMs(
+ (partialWakeLockTimeTotalMicros + 500) / 1000));
sb.setLength(0);
- sb.append(" Signal strengths: ");
- boolean didOne = false;
+ sb.append(" Signal levels: ");
+ didOne = false;
for (int i=0; i uidStats = getUidStats();
- final int NU = uidStats.size();
for (int iu=0; iu= next || !Character.isDigit(chs[j + 1 - start]))) ||
((c == '/' || c == '-') &&
(j + 1 >= next || !Character.isDigit(chs[j + 1 - start]))) ||
- (c >= FIRST_CJK && isIdeographic(c) &&
- j + 1 < next && isIdeographic(chs[j + 1 - start]))) {
+ (c >= FIRST_CJK && isIdeographic(c, true) &&
+ j + 1 < next && isIdeographic(chs[j + 1 - start], false))) {
okwidth = w;
ok = j + 1;
@@ -807,8 +809,12 @@ extends Layout
* as being Ideographic (class ID) by the Unicode Line Breaking Algorithm
* (http://www.unicode.org/unicode/reports/tr14/), and is therefore OK
* to break between a pair of.
+ *
+ * @param includeNonStarters also return true for category NS
+ * (non-starters), which can be broken
+ * after but not before.
*/
- private static final boolean isIdeographic(char c) {
+ private static final boolean isIdeographic(char c, boolean includeNonStarters) {
if (c >= '\u2E80' && c <= '\u2FFF') {
return true; // CJK, KANGXI RADICALS, DESCRIPTION SYMBOLS
}
@@ -816,9 +822,52 @@ extends Layout
return true; // IDEOGRAPHIC SPACE
}
if (c >= '\u3040' && c <= '\u309F') {
+ if (!includeNonStarters) {
+ switch (c) {
+ case '\u3041': // # HIRAGANA LETTER SMALL A
+ case '\u3043': // # HIRAGANA LETTER SMALL I
+ case '\u3045': // # HIRAGANA LETTER SMALL U
+ case '\u3047': // # HIRAGANA LETTER SMALL E
+ case '\u3049': // # HIRAGANA LETTER SMALL O
+ case '\u3063': // # HIRAGANA LETTER SMALL TU
+ case '\u3083': // # HIRAGANA LETTER SMALL YA
+ case '\u3085': // # HIRAGANA LETTER SMALL YU
+ case '\u3087': // # HIRAGANA LETTER SMALL YO
+ case '\u308E': // # HIRAGANA LETTER SMALL WA
+ case '\u3095': // # HIRAGANA LETTER SMALL KA
+ case '\u3096': // # HIRAGANA LETTER SMALL KE
+ case '\u309B': // # KATAKANA-HIRAGANA VOICED SOUND MARK
+ case '\u309C': // # KATAKANA-HIRAGANA SEMI-VOICED SOUND MARK
+ case '\u309D': // # HIRAGANA ITERATION MARK
+ case '\u309E': // # HIRAGANA VOICED ITERATION MARK
+ return false;
+ }
+ }
return true; // Hiragana (except small characters)
}
if (c >= '\u30A0' && c <= '\u30FF') {
+ if (!includeNonStarters) {
+ switch (c) {
+ case '\u30A0': // # KATAKANA-HIRAGANA DOUBLE HYPHEN
+ case '\u30A1': // # KATAKANA LETTER SMALL A
+ case '\u30A3': // # KATAKANA LETTER SMALL I
+ case '\u30A5': // # KATAKANA LETTER SMALL U
+ case '\u30A7': // # KATAKANA LETTER SMALL E
+ case '\u30A9': // # KATAKANA LETTER SMALL O
+ case '\u30C3': // # KATAKANA LETTER SMALL TU
+ case '\u30E3': // # KATAKANA LETTER SMALL YA
+ case '\u30E5': // # KATAKANA LETTER SMALL YU
+ case '\u30E7': // # KATAKANA LETTER SMALL YO
+ case '\u30EE': // # KATAKANA LETTER SMALL WA
+ case '\u30F5': // # KATAKANA LETTER SMALL KA
+ case '\u30F6': // # KATAKANA LETTER SMALL KE
+ case '\u30FB': // # KATAKANA MIDDLE DOT
+ case '\u30FC': // # KATAKANA-HIRAGANA PROLONGED SOUND MARK
+ case '\u30FD': // # KATAKANA ITERATION MARK
+ case '\u30FE': // # KATAKANA VOICED ITERATION MARK
+ return false;
+ }
+ }
return true; // Katakana (except small characters)
}
if (c >= '\u3400' && c <= '\u4DB5') {
diff --git a/core/java/android/text/method/QwertyKeyListener.java b/core/java/android/text/method/QwertyKeyListener.java
index 21bc2a6311b64..e420c27516e30 100644
--- a/core/java/android/text/method/QwertyKeyListener.java
+++ b/core/java/android/text/method/QwertyKeyListener.java
@@ -405,23 +405,34 @@ public class QwertyKeyListener extends BaseKeyListener {
PICKER_SETS.put('<', "\u00AB");
PICKER_SETS.put('>', "\u00BB");
PICKER_SETS.put('?', "\u00BF");
- PICKER_SETS.put('A', "\u00C0\u00C1\u00C2\u00C4\u00C6\u00C3\u00C5");
- PICKER_SETS.put('C', "\u00C7");
- PICKER_SETS.put('E', "\u00C8\u00C9\u00CA\u00CB");
- PICKER_SETS.put('I', "\u00CC\u00CD\u00CE\u00CF");
- PICKER_SETS.put('N', "\u00D1");
- PICKER_SETS.put('O', "\u00D8\u0152\u00D5\u00D2\u00D3\u00D4\u00D6");
- PICKER_SETS.put('U', "\u00D9\u00DA\u00DB\u00DC");
+ PICKER_SETS.put('A', "\u00C0\u00C1\u00C2\u00C4\u00C6\u00C3\u00C5\u0104\u0100");
+ PICKER_SETS.put('C', "\u00C7\u0106\u010C");
+ PICKER_SETS.put('D', "\u010E");
+ PICKER_SETS.put('E', "\u00C8\u00C9\u00CA\u00CB\u0118\u011A\u0112");
+ PICKER_SETS.put('L', "\u0141");
+ PICKER_SETS.put('I', "\u00CC\u00CD\u00CE\u00CF\u012A");
+ PICKER_SETS.put('N', "\u00D1\u0143\u0147");
+ PICKER_SETS.put('O', "\u00D8\u0152\u00D5\u00D2\u00D3\u00D4\u00D6\u014C");
+ PICKER_SETS.put('R', "\u0158");
+ PICKER_SETS.put('S', "\u015A\u0160");
+ PICKER_SETS.put('T', "\u0164");
+ PICKER_SETS.put('U', "\u00D9\u00DA\u00DB\u00DC\u016E\u016A");
PICKER_SETS.put('Y', "\u00DD\u0178");
- PICKER_SETS.put('a', "\u00E0\u00E1\u00E2\u00E4\u00E6\u00E3\u00E5");
- PICKER_SETS.put('c', "\u00E7");
- PICKER_SETS.put('e', "\u00E8\u00E9\u00EA\u00EB");
- PICKER_SETS.put('i', "\u00EC\u00ED\u00EE\u00EF");
- PICKER_SETS.put('n', "\u00F1");
- PICKER_SETS.put('o', "\u00F8\u0153\u00F5\u00F2\u00F3\u00F4\u00F6");
- PICKER_SETS.put('s', "\u00A7\u00DF");
- PICKER_SETS.put('u', "\u00F9\u00FA\u00FB\u00FC");
+ PICKER_SETS.put('Z', "\u0179\u017B\u017D");
+ PICKER_SETS.put('a', "\u00E0\u00E1\u00E2\u00E4\u00E6\u00E3\u00E5\u0105\u0101");
+ PICKER_SETS.put('c', "\u00E7\u0107\u010D");
+ PICKER_SETS.put('d', "\u010F");
+ PICKER_SETS.put('e', "\u00E8\u00E9\u00EA\u00EB\u0119\u011B\u0113");
+ PICKER_SETS.put('i', "\u00EC\u00ED\u00EE\u00EF\u012B");
+ PICKER_SETS.put('l', "\u0142");
+ PICKER_SETS.put('n', "\u00F1\u0144\u0148");
+ PICKER_SETS.put('o', "\u00F8\u0153\u00F5\u00F2\u00F3\u00F4\u00F6\u014D");
+ PICKER_SETS.put('r', "\u0159");
+ PICKER_SETS.put('s', "\u00A7\u00DF\u015B\u0161");
+ PICKER_SETS.put('t', "\u0165");
+ PICKER_SETS.put('u', "\u00F9\u00FA\u00FB\u00FC\u016F\u016B");
PICKER_SETS.put('y', "\u00FD\u00FF");
+ PICKER_SETS.put('z', "\u017A\u017C\u017E");
PICKER_SETS.put(KeyCharacterMap.PICKER_DIALOG_INPUT,
"\u2026\u00A5\u2022\u00AE\u00A9\u00B1");
};
diff --git a/core/java/android/util/FinitePool.java b/core/java/android/util/FinitePool.java
new file mode 100644
index 0000000000000..3ef82930e9a90
--- /dev/null
+++ b/core/java/android/util/FinitePool.java
@@ -0,0 +1,86 @@
+/*
+ * Copyright (C) 2009 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.util;
+
+/**
+ * @hide
+ */
+class FinitePool> implements Pool {
+ /**
+ * Factory used to create new pool objects
+ */
+ private final PoolableManager mManager;
+ /**
+ * Maximum number of objects in the pool
+ */
+ private final int mLimit;
+ /**
+ * If true, mLimit is ignored
+ */
+ private final boolean mInfinite;
+
+ /**
+ * Next object to acquire
+ */
+ private T mRoot;
+ /**
+ * Number of objects in the pool
+ */
+ private int mPoolCount;
+
+ FinitePool(PoolableManager manager) {
+ mManager = manager;
+ mLimit = 0;
+ mInfinite = true;
+ }
+
+ FinitePool(PoolableManager manager, int limit) {
+ if (limit <= 0) throw new IllegalArgumentException("The pool limit must be > 0");
+
+ mManager = manager;
+ mLimit = limit;
+ mInfinite = false;
+ }
+
+ public T acquire() {
+ T element;
+
+ if (mRoot != null) {
+ element = mRoot;
+ mRoot = element.getNextPoolable();
+ mPoolCount--;
+ } else {
+ element = mManager.newInstance();
+ }
+
+ if (element != null) {
+ element.setNextPoolable(null);
+ mManager.onAcquired(element);
+ }
+
+ return element;
+ }
+
+ public void release(T element) {
+ if (mInfinite || mPoolCount < mLimit) {
+ mPoolCount++;
+ element.setNextPoolable(mRoot);
+ mRoot = element;
+ }
+ mManager.onReleased(element);
+ }
+}
diff --git a/core/java/android/util/Pool.java b/core/java/android/util/Pool.java
new file mode 100644
index 0000000000000..8cd4f3ed07a05
--- /dev/null
+++ b/core/java/android/util/Pool.java
@@ -0,0 +1,25 @@
+/*
+ * Copyright (C) 2009 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.util;
+
+/**
+ * @hide
+ */
+public interface Pool> {
+ public abstract T acquire();
+ public abstract void release(T element);
+}
diff --git a/core/java/android/util/PoolFactory.java b/core/java/android/util/PoolFactory.java
new file mode 100644
index 0000000000000..4f72bf7c4b169
--- /dev/null
+++ b/core/java/android/util/PoolFactory.java
@@ -0,0 +1,41 @@
+/*
+ * Copyright (C) 2009 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.util;
+
+/**
+ * @hide
+ */
+public class PoolFactory {
+ private PoolFactory() {
+ }
+
+ public static > Pool simplePool(PoolableManager manager) {
+ return new FinitePool(manager);
+ }
+
+ public static > Pool finitePool(PoolableManager manager, int limit) {
+ return new FinitePool(manager, limit);
+ }
+
+ public static > Pool synchronizedPool(Pool pool) {
+ return new SynchronizedPool(pool);
+ }
+
+ public static > Pool synchronizedPool(Pool pool, Object lock) {
+ return new SynchronizedPool(pool, lock);
+ }
+}
diff --git a/core/java/android/util/Poolable.java b/core/java/android/util/Poolable.java
new file mode 100644
index 0000000000000..fd9bd9b7f136d
--- /dev/null
+++ b/core/java/android/util/Poolable.java
@@ -0,0 +1,25 @@
+/*
+ * Copyright (C) 2009 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.util;
+
+/**
+ * @hide
+ */
+public interface Poolable {
+ void setNextPoolable(T element);
+ T getNextPoolable();
+}
diff --git a/core/java/android/util/PoolableManager.java b/core/java/android/util/PoolableManager.java
new file mode 100644
index 0000000000000..8773e6339b31c
--- /dev/null
+++ b/core/java/android/util/PoolableManager.java
@@ -0,0 +1,27 @@
+/*
+ * Copyright (C) 2009 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.util;
+
+/**
+ * @hide
+ */
+public interface PoolableManager> {
+ T newInstance();
+
+ void onAcquired(T element);
+ void onReleased(T element);
+}
diff --git a/core/java/android/util/SynchronizedPool.java b/core/java/android/util/SynchronizedPool.java
new file mode 100644
index 0000000000000..651e0c335e8b6
--- /dev/null
+++ b/core/java/android/util/SynchronizedPool.java
@@ -0,0 +1,48 @@
+/*
+ * Copyright (C) 2009 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.util;
+
+/**
+ *
+ * @hide
+ */
+class SynchronizedPool> implements Pool {
+ private final Pool mPool;
+ private final Object mLock;
+
+ public SynchronizedPool(Pool pool) {
+ mPool = pool;
+ mLock = this;
+ }
+
+ public SynchronizedPool(Pool pool, Object lock) {
+ mPool = pool;
+ mLock = lock;
+ }
+
+ public T acquire() {
+ synchronized (mLock) {
+ return mPool.acquire();
+ }
+ }
+
+ public void release(T element) {
+ synchronized (mLock) {
+ mPool.release(element);
+ }
+ }
+}
diff --git a/core/java/android/view/VelocityTracker.java b/core/java/android/view/VelocityTracker.java
index c80167ef5542f..256525a8b3f69 100644
--- a/core/java/android/view/VelocityTracker.java
+++ b/core/java/android/view/VelocityTracker.java
@@ -18,6 +18,10 @@ package android.view;
import android.util.Config;
import android.util.Log;
+import android.util.Poolable;
+import android.util.Pool;
+import android.util.PoolFactory;
+import android.util.PoolableManager;
/**
* Helper for tracking the velocity of touch events, for implementing
@@ -28,52 +32,72 @@ import android.util.Log;
* {@link #computeCurrentVelocity(int)} and then {@link #getXVelocity()}
* and {@link #getXVelocity()}.
*/
-public final class VelocityTracker {
+public final class VelocityTracker implements Poolable {
static final String TAG = "VelocityTracker";
static final boolean DEBUG = false;
static final boolean localLOGV = DEBUG || Config.LOGV;
-
+
static final int NUM_PAST = 10;
static final int LONGEST_PAST_TIME = 200;
-
+
static final VelocityTracker[] mPool = new VelocityTracker[1];
-
+ private static final Pool sPool = PoolFactory.synchronizedPool(
+ PoolFactory.finitePool(new PoolableManager() {
+ public VelocityTracker newInstance() {
+ return new VelocityTracker();
+ }
+
+ public void onAcquired(VelocityTracker element) {
+ element.clear();
+ }
+
+ public void onReleased(VelocityTracker element) {
+ }
+ }, 2));
+
final float mPastX[] = new float[NUM_PAST];
final float mPastY[] = new float[NUM_PAST];
final long mPastTime[] = new long[NUM_PAST];
-
+
float mYVelocity;
float mXVelocity;
-
+
+ private VelocityTracker mNext;
+
/**
* Retrieve a new VelocityTracker object to watch the velocity of a
* motion. Be sure to call {@link #recycle} when done. You should
* generally only maintain an active object while tracking a movement,
* so that the VelocityTracker can be re-used elsewhere.
- *
+ *
* @return Returns a new VelocityTracker.
*/
static public VelocityTracker obtain() {
- synchronized (mPool) {
- VelocityTracker vt = mPool[0];
- if (vt != null) {
- vt.clear();
- return vt;
- }
- return new VelocityTracker();
- }
+ return sPool.acquire();
}
-
+
/**
* Return a VelocityTracker object back to be re-used by others. You must
* not touch the object after calling this function.
*/
public void recycle() {
- synchronized (mPool) {
- mPool[0] = this;
- }
+ sPool.release(this);
}
-
+
+ /**
+ * @hide
+ */
+ public void setNextPoolable(VelocityTracker element) {
+ mNext = element;
+ }
+
+ /**
+ * @hide
+ */
+ public VelocityTracker getNextPoolable() {
+ return mNext;
+ }
+
private VelocityTracker() {
}
diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java
index 04447ca4719df..8a6521924bdb2 100644
--- a/core/java/android/view/View.java
+++ b/core/java/android/view/View.java
@@ -45,6 +45,10 @@ import android.util.AttributeSet;
import android.util.EventLog;
import android.util.Log;
import android.util.SparseArray;
+import android.util.Poolable;
+import android.util.Pool;
+import android.util.PoolFactory;
+import android.util.PoolableManager;
import android.view.ContextMenu.ContextMenuInfo;
import android.view.animation.Animation;
import android.view.inputmethod.InputConnection;
@@ -5531,7 +5535,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback {
(mBGDrawable != null && mBGDrawable.getOpacity() == PixelFormat.OPAQUE);
if (width <= 0 || height <= 0 ||
- (width * height * (opaque ? 2 : 4) >= // Projected bitmap size in bytes
+ (width * height * (opaque ? 2 : 4) > // Projected bitmap size in bytes
ViewConfiguration.get(mContext).getScaledMaximumDrawingCacheSize())) {
destroyDrawingCache();
return;
@@ -5627,6 +5631,62 @@ public class View implements Drawable.Callback, KeyEvent.Callback {
}
}
+ /**
+ * Create a snapshot of the view into a bitmap. We should probably make
+ * some form of this public, but should think about the API.
+ */
+ /*package*/ Bitmap createSnapshot(Bitmap.Config quality, int backgroundColor) {
+ final int width = mRight - mLeft;
+ final int height = mBottom - mTop;
+
+ Bitmap bitmap = Bitmap.createBitmap(width, height, quality);
+ if (bitmap == null) {
+ throw new OutOfMemoryError();
+ }
+
+ Canvas canvas;
+ final AttachInfo attachInfo = mAttachInfo;
+ if (attachInfo != null) {
+ canvas = attachInfo.mCanvas;
+ if (canvas == null) {
+ canvas = new Canvas();
+ }
+ canvas.setBitmap(bitmap);
+ // Temporarily clobber the cached Canvas in case one of our children
+ // is also using a drawing cache. Without this, the children would
+ // steal the canvas by attaching their own bitmap to it and bad, bad
+ // things would happen (invisible views, corrupted drawings, etc.)
+ attachInfo.mCanvas = null;
+ } else {
+ // This case should hopefully never or seldom happen
+ canvas = new Canvas(bitmap);
+ }
+
+ if ((backgroundColor&0xff000000) != 0) {
+ bitmap.eraseColor(backgroundColor);
+ }
+
+ computeScroll();
+ final int restoreCount = canvas.save();
+ canvas.translate(-mScrollX, -mScrollY);
+
+ // Fast path for layouts with no backgrounds
+ if ((mPrivateFlags & SKIP_DRAW) == SKIP_DRAW) {
+ dispatchDraw(canvas);
+ } else {
+ draw(canvas);
+ }
+
+ canvas.restoreToCount(restoreCount);
+
+ if (attachInfo != null) {
+ // Restore the cached Canvas for our siblings
+ attachInfo.mCanvas = canvas;
+ }
+
+ return bitmap;
+ }
+
/**
* Indicates whether this View is currently in edit mode. A View is usually
* in edit mode when displayed within a developer tool. For instance, if
@@ -7827,26 +7887,24 @@ public class View implements Drawable.Callback, KeyEvent.Callback {
* For performance purposes, this class also implements a pool of up to
* POOL_LIMIT objects that get reused. This reduces memory allocations
* whenever possible.
- *
- * The pool is implemented as a linked list of InvalidateInfo object with
- * the root pointing to the next available InvalidateInfo. If the root
- * is null (i.e. when all instances from the pool have been acquired),
- * then a new InvalidateInfo is created and returned to the caller.
- *
- * An InvalidateInfo is sent back to the pool by calling its release()
- * method. If the pool is full the object is simply discarded.
- *
- * This implementation follows the object pool pattern used in the
- * MotionEvent class.
*/
- static class InvalidateInfo {
+ static class InvalidateInfo implements Poolable {
private static final int POOL_LIMIT = 10;
- private static final Object sLock = new Object();
+ private static final Pool sPool = PoolFactory.synchronizedPool(
+ PoolFactory.finitePool(new PoolableManager() {
+ public InvalidateInfo newInstance() {
+ return new InvalidateInfo();
+ }
- private static int sAcquiredCount = 0;
- private static InvalidateInfo sRoot;
+ public void onAcquired(InvalidateInfo element) {
+ }
- private InvalidateInfo next;
+ public void onReleased(InvalidateInfo element) {
+ }
+ }, POOL_LIMIT)
+ );
+
+ private InvalidateInfo mNext;
View target;
@@ -7855,28 +7913,20 @@ public class View implements Drawable.Callback, KeyEvent.Callback {
int right;
int bottom;
+ public void setNextPoolable(InvalidateInfo element) {
+ mNext = element;
+ }
+
+ public InvalidateInfo getNextPoolable() {
+ return mNext;
+ }
+
static InvalidateInfo acquire() {
- synchronized (sLock) {
- if (sRoot == null) {
- return new InvalidateInfo();
- }
-
- InvalidateInfo info = sRoot;
- sRoot = info.next;
- sAcquiredCount--;
-
- return info;
- }
+ return sPool.acquire();
}
void release() {
- synchronized (sLock) {
- if (sAcquiredCount < POOL_LIMIT) {
- sAcquiredCount++;
- next = sRoot;
- sRoot = this;
- }
- }
+ sPool.release(this);
}
}
diff --git a/core/java/android/view/ViewDebug.java b/core/java/android/view/ViewDebug.java
index f604bc56a06e7..c1e9ed8efa0b2 100644
--- a/core/java/android/view/ViewDebug.java
+++ b/core/java/android/view/ViewDebug.java
@@ -741,22 +741,18 @@ public class ViewDebug {
final CountDownLatch latch = new CountDownLatch(1);
final Bitmap[] cache = new Bitmap[1];
- final boolean hasCache = captureView.isDrawingCacheEnabled();
- final boolean willNotCache = captureView.willNotCacheDrawing();
-
- if (willNotCache) {
- // TODO: Should happen on the UI thread
- captureView.setWillNotCacheDrawing(false);
- }
-
root.post(new Runnable() {
public void run() {
try {
- if (!hasCache) {
- captureView.buildDrawingCache();
+ cache[0] = captureView.createSnapshot(
+ Bitmap.Config.ARGB_8888, 0);
+ } catch (OutOfMemoryError e) {
+ try {
+ cache[0] = captureView.createSnapshot(
+ Bitmap.Config.ARGB_4444, 0);
+ } catch (OutOfMemoryError e2) {
+ Log.w("View", "Out of memory for bitmap");
}
-
- cache[0] = captureView.getDrawingCache();
} finally {
latch.countDown();
}
@@ -776,20 +772,15 @@ public class ViewDebug {
if (out != null) {
out.close();
}
+ cache[0].recycle();
}
+ } else {
+ Log.w("View", "Failed to create capture bitmap!");
+ clientStream.close();
}
} catch (InterruptedException e) {
Log.w("View", "Could not complete the capture of the view " + captureView);
Thread.currentThread().interrupt();
- } finally {
- if (willNotCache) {
- // TODO: Should happen on the UI thread
- captureView.setWillNotCacheDrawing(true);
- }
- if (!hasCache) {
- // TODO: Should happen on the UI thread
- captureView.destroyDrawingCache();
- }
}
}
}
diff --git a/core/java/android/view/WindowManagerPolicy.java b/core/java/android/view/WindowManagerPolicy.java
index 220869c1d236e..13719323cb68b 100644
--- a/core/java/android/view/WindowManagerPolicy.java
+++ b/core/java/android/view/WindowManagerPolicy.java
@@ -580,8 +580,11 @@ public interface WindowManagerPolicy {
* Called when layout of the windows is finished. After this function has
* returned, all windows given to layoutWindow() must have had a
* frame assigned.
+ *
+ * @return Return true if layout state may have changed (so that another
+ * layout will be performed).
*/
- public void finishLayoutLw();
+ public boolean finishLayoutLw();
/**
* Called when animation of the windows is about to start.
diff --git a/core/java/android/webkit/WebView.java b/core/java/android/webkit/WebView.java
index 653720500a25d..7bf3f4ce75362 100644
--- a/core/java/android/webkit/WebView.java
+++ b/core/java/android/webkit/WebView.java
@@ -4503,14 +4503,19 @@ public class WebView extends AbsoluteLayout
int scrollYDelta = 0;
- if (rect.bottom > screenBottom && rect.top > screenTop) {
- if (rect.height() > height) {
- scrollYDelta += (rect.top - screenTop);
+ if (rect.bottom > screenBottom) {
+ int oneThirdOfScreenHeight = height / 3;
+ if (rect.height() > 2 * oneThirdOfScreenHeight) {
+ // If the rectangle is too tall to fit in the bottom two thirds
+ // of the screen, place it at the top.
+ scrollYDelta = rect.top - screenTop;
} else {
- scrollYDelta += (rect.bottom - screenBottom);
+ // If the rectangle will still fit on screen, we want its
+ // top to be in the top third of the screen.
+ scrollYDelta = rect.top - (screenTop + oneThirdOfScreenHeight);
}
} else if (rect.top < screenTop) {
- scrollYDelta -= (screenTop - rect.top);
+ scrollYDelta = rect.top - screenTop;
}
int width = getWidth() - getVerticalScrollbarWidth();
diff --git a/core/java/android/widget/AutoCompleteTextView.java b/core/java/android/widget/AutoCompleteTextView.java
index a17c78d4aa2bd..bc9589073a4ad 100644
--- a/core/java/android/widget/AutoCompleteTextView.java
+++ b/core/java/android/widget/AutoCompleteTextView.java
@@ -885,6 +885,22 @@ public class AutoCompleteTextView extends EditText implements Filter.FilterListe
return result;
}
+ /**
+ * Set the horizontal offset with respect to {@link #setDropDownAnchor(int)}
+ * @hide pending API council review
+ */
+ public void setDropDownHorizontalOffset(int horizontalOffset) {
+ mDropDownHorizontalOffset = horizontalOffset;
+ }
+
+ /**
+ * Set the vertical offset with respect to {@link #setDropDownAnchor(int)}
+ * @hide pending API council review
+ */
+ public void setDropDownVerticalOffset(int verticalOffset) {
+ mDropDownVerticalOffset = verticalOffset;
+ }
+
/**
* Used for lazy instantiation of the anchor view from the id we have. If the value of
* the id is NO_ID or we can't find a view for the given id, we return this TextView as
diff --git a/core/java/android/widget/FrameLayout.java b/core/java/android/widget/FrameLayout.java
index 47db6f2745382..80fbf9eddecfd 100644
--- a/core/java/android/widget/FrameLayout.java
+++ b/core/java/android/widget/FrameLayout.java
@@ -24,6 +24,7 @@ import android.graphics.Region;
import android.graphics.drawable.Drawable;
import android.util.AttributeSet;
import android.view.View;
+import android.view.ViewDebug;
import android.view.ViewGroup;
import android.view.Gravity;
import android.widget.RemoteViews.RemoteView;
@@ -45,21 +46,31 @@ import android.widget.RemoteViews.RemoteView;
*/
@RemoteView
public class FrameLayout extends ViewGroup {
+ @ViewDebug.ExportedProperty
boolean mMeasureAllChildren = false;
+ @ViewDebug.ExportedProperty
private Drawable mForeground;
+ @ViewDebug.ExportedProperty
private int mForegroundPaddingLeft = 0;
+ @ViewDebug.ExportedProperty
private int mForegroundPaddingTop = 0;
+ @ViewDebug.ExportedProperty
private int mForegroundPaddingRight = 0;
+ @ViewDebug.ExportedProperty
private int mForegroundPaddingBottom = 0;
private final Rect mSelfBounds = new Rect();
private final Rect mOverlayBounds = new Rect();
+ @ViewDebug.ExportedProperty
private int mForegroundGravity = Gravity.FILL;
/** {@hide} */
+ @ViewDebug.ExportedProperty
protected boolean mForegroundInPadding = true;
+ boolean mForegroundBoundsChanged = false;
+
public FrameLayout(Context context) {
super(context);
}
@@ -269,6 +280,8 @@ public class FrameLayout extends ViewGroup {
final int parentTop = mPaddingTop + mForegroundPaddingTop;
final int parentBottom = bottom - top - mPaddingBottom - mForegroundPaddingBottom;
+ mForegroundBoundsChanged = true;
+
for (int i = 0; i < count; i++) {
final View child = getChildAt(i);
if (child.getVisibility() != GONE) {
@@ -328,22 +341,7 @@ public class FrameLayout extends ViewGroup {
@Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
super.onSizeChanged(w, h, oldw, oldh);
-
- final Drawable foreground = mForeground;
- if (foreground != null) {
- final Rect selfBounds = mSelfBounds;
- final Rect overlayBounds = mOverlayBounds;
-
- if (mForegroundInPadding) {
- selfBounds.set(0, 0, w, h);
- } else {
- selfBounds.set(mPaddingLeft, mPaddingTop, w - mPaddingRight, h - mPaddingBottom);
- }
-
- Gravity.apply(mForegroundGravity, foreground.getIntrinsicWidth(),
- foreground.getIntrinsicHeight(), selfBounds, overlayBounds);
- foreground.setBounds(overlayBounds);
- }
+ mForegroundBoundsChanged = true;
}
/**
@@ -354,7 +352,29 @@ public class FrameLayout extends ViewGroup {
super.draw(canvas);
if (mForeground != null) {
- mForeground.draw(canvas);
+ final Drawable foreground = mForeground;
+ if (mForegroundBoundsChanged) {
+ mForegroundBoundsChanged = false;
+ if (foreground != null) {
+ final Rect selfBounds = mSelfBounds;
+ final Rect overlayBounds = mOverlayBounds;
+
+ final int w = mRight-mLeft;
+ final int h = mBottom-mTop;
+
+ if (mForegroundInPadding) {
+ selfBounds.set(0, 0, w, h);
+ } else {
+ selfBounds.set(mPaddingLeft, mPaddingTop, w - mPaddingRight, h - mPaddingBottom);
+ }
+
+ Gravity.apply(mForegroundGravity, foreground.getIntrinsicWidth(),
+ foreground.getIntrinsicHeight(), selfBounds, overlayBounds);
+ foreground.setBounds(overlayBounds);
+ }
+ }
+
+ foreground.draw(canvas);
}
}
diff --git a/core/java/com/android/internal/app/IBatteryStats.aidl b/core/java/com/android/internal/app/IBatteryStats.aidl
index fff8dcf17ee0d..bb0c9120cef60 100644
--- a/core/java/com/android/internal/app/IBatteryStats.aidl
+++ b/core/java/com/android/internal/app/IBatteryStats.aidl
@@ -27,13 +27,16 @@ interface IBatteryStats {
void noteStartGps(int uid);
void noteStopGps(int uid);
void noteScreenOn();
+ void noteScreenBrightness(int brightness);
void noteScreenOff();
+ void noteInputEvent();
+ void noteUserActivity(int uid, int event);
void notePhoneOn();
void notePhoneOff();
void notePhoneSignalStrength(int asu);
void notePhoneDataConnectionState(int dataType, boolean hasData);
- void noteWifiOn();
- void noteWifiOff();
+ void noteWifiOn(int uid);
+ void noteWifiOff(int uid);
void noteWifiRunning();
void noteWifiStopped();
void noteBluetoothOn();
diff --git a/core/java/com/android/internal/os/BatteryStatsImpl.java b/core/java/com/android/internal/os/BatteryStatsImpl.java
index 9e07fd8425941..808508042997d 100644
--- a/core/java/com/android/internal/os/BatteryStatsImpl.java
+++ b/core/java/com/android/internal/os/BatteryStatsImpl.java
@@ -48,7 +48,7 @@ public final class BatteryStatsImpl extends BatteryStats {
private static final int MAGIC = 0xBA757475; // 'BATSTATS'
// Current on-disk Parcel version
- private static final int VERSION = 29;
+ private static final int VERSION = 32;
private final File mFile;
private final File mBackupFile;
@@ -90,6 +90,11 @@ public final class BatteryStatsImpl extends BatteryStats {
boolean mScreenOn;
Timer mScreenOnTimer;
+ int mScreenBrightnessBin = -1;
+ final Timer[] mScreenBrightnessTimer = new Timer[NUM_SCREEN_BRIGHTNESS_BINS];
+
+ Counter mInputEventCounter;
+
boolean mPhoneOn;
Timer mPhoneOnTimer;
@@ -101,6 +106,7 @@ public final class BatteryStatsImpl extends BatteryStats {
boolean mWifiOn;
Timer mWifiOnTimer;
+ int mWifiOnUid = -1;
boolean mWifiRunning;
Timer mWifiRunningTimer;
@@ -140,6 +146,99 @@ public final class BatteryStatsImpl extends BatteryStats {
void plug(long batteryUptime, long batteryRealtime);
}
+ /**
+ * State for keeping track of counting information.
+ */
+ public static final class Counter extends BatteryStats.Counter implements Unpluggable {
+ int mCount;
+ int mLoadedCount;
+ int mLastCount;
+ int mUnpluggedCount;
+ int mPluggedCount;
+
+ Counter(ArrayList unpluggables, Parcel in) {
+ mPluggedCount = mCount = in.readInt();
+ mLoadedCount = in.readInt();
+ mLastCount = in.readInt();
+ mUnpluggedCount = in.readInt();
+ unpluggables.add(this);
+ }
+
+ Counter(ArrayList unpluggables) {
+ unpluggables.add(this);
+ }
+
+ public void writeToParcel(Parcel out) {
+ out.writeInt(mCount);
+ out.writeInt(mLoadedCount);
+ out.writeInt(mLastCount);
+ out.writeInt(mUnpluggedCount);
+ }
+
+ public void unplug(long batteryUptime, long batteryRealtime) {
+ mUnpluggedCount = mCount = mPluggedCount;
+ }
+
+ public void plug(long batteryUptime, long batteryRealtime) {
+ mPluggedCount = mCount;
+ }
+
+ /**
+ * Writes a possibly null Counter to a Parcel.
+ *
+ * @param out the Parcel to be written to.
+ * @param counter a Counter, or null.
+ */
+ public static void writeCounterToParcel(Parcel out, Counter counter) {
+ if (counter == null) {
+ out.writeInt(0); // indicates null
+ return;
+ }
+ out.writeInt(1); // indicates non-null
+
+ counter.writeToParcel(out);
+ }
+
+ @Override
+ public int getCount(int which) {
+ int val;
+ if (which == STATS_LAST) {
+ val = mLastCount;
+ } else {
+ val = mCount;
+ if (which == STATS_UNPLUGGED) {
+ val -= mUnpluggedCount;
+ } else if (which != STATS_TOTAL) {
+ val -= mLoadedCount;
+ }
+ }
+
+ return val;
+ }
+
+ public void logState(Printer pw, String prefix) {
+ pw.println(prefix + "mCount=" + mCount
+ + " mLoadedCount=" + mLoadedCount + " mLastCount=" + mLastCount
+ + " mUnpluggedCount=" + mUnpluggedCount
+ + " mPluggedCount=" + mPluggedCount);
+ }
+
+ void stepLocked() {
+ mCount++;
+ }
+
+ void writeSummaryFromParcelLocked(Parcel out) {
+ out.writeInt(mCount);
+ out.writeInt(mCount - mLoadedCount);
+ }
+
+ void readSummaryFromParcelLocked(Parcel in) {
+ mCount = mLoadedCount = in.readInt();
+ mLastCount = in.readInt();
+ mUnpluggedCount = mPluggedCount = mCount;
+ }
+ }
+
/**
* State for keeping track of timing information.
*/
@@ -469,6 +568,9 @@ public final class BatteryStatsImpl extends BatteryStats {
if (!mScreenOn) {
mScreenOn = true;
mScreenOnTimer.startRunningLocked(this);
+ if (mScreenBrightnessBin >= 0) {
+ mScreenBrightnessTimer[mScreenBrightnessBin].startRunningLocked(this);
+ }
}
}
@@ -476,6 +578,36 @@ public final class BatteryStatsImpl extends BatteryStats {
if (mScreenOn) {
mScreenOn = false;
mScreenOnTimer.stopRunningLocked(this);
+ if (mScreenBrightnessBin >= 0) {
+ mScreenBrightnessTimer[mScreenBrightnessBin].stopRunningLocked(this);
+ }
+ }
+ }
+
+ public void noteScreenBrightnessLocked(int brightness) {
+ // Bin the brightness.
+ int bin = brightness / (256/NUM_SCREEN_BRIGHTNESS_BINS);
+ if (bin < 0) bin = 0;
+ else if (bin >= NUM_SCREEN_BRIGHTNESS_BINS) bin = NUM_SCREEN_BRIGHTNESS_BINS-1;
+ if (mScreenBrightnessBin != bin) {
+ if (mScreenOn) {
+ if (mScreenBrightnessBin >= 0) {
+ mScreenBrightnessTimer[mScreenBrightnessBin].stopRunningLocked(this);
+ }
+ mScreenBrightnessTimer[bin].startRunningLocked(this);
+ }
+ mScreenBrightnessBin = bin;
+ }
+ }
+
+ public void noteInputEventLocked() {
+ mInputEventCounter.stepLocked();
+ }
+
+ public void noteUserActivityLocked(int uid, int event) {
+ Uid u = mUidStats.get(uid);
+ if (u != null) {
+ u.noteUserActivityLocked(event);
}
}
@@ -537,18 +669,38 @@ public final class BatteryStatsImpl extends BatteryStats {
}
}
- public void noteWifiOnLocked() {
+ public void noteWifiOnLocked(int uid) {
if (!mWifiOn) {
mWifiOn = true;
mWifiOnTimer.startRunningLocked(this);
}
+ if (mWifiOnUid != uid) {
+ if (mWifiOnUid >= 0) {
+ Uid u = mUidStats.get(mWifiOnUid);
+ if (u != null) {
+ u.noteWifiTurnedOffLocked();
+ }
+ }
+ mWifiOnUid = uid;
+ Uid u = mUidStats.get(uid);
+ if (u != null) {
+ u.noteWifiTurnedOnLocked();
+ }
+ }
}
- public void noteWifiOffLocked() {
+ public void noteWifiOffLocked(int uid) {
if (mWifiOn) {
mWifiOn = false;
mWifiOnTimer.stopRunningLocked(this);
}
+ if (mWifiOnUid >= 0) {
+ Uid u = mUidStats.get(mWifiOnUid);
+ if (u != null) {
+ u.noteWifiTurnedOffLocked();
+ }
+ mWifiOnUid = -1;
+ }
}
public void noteWifiRunningLocked() {
@@ -611,6 +763,16 @@ public final class BatteryStatsImpl extends BatteryStats {
return mScreenOnTimer.getTotalTime(batteryRealtime, which);
}
+ @Override public long getScreenBrightnessTime(int brightnessBin,
+ long batteryRealtime, int which) {
+ return mScreenBrightnessTimer[brightnessBin].getTotalTime(
+ batteryRealtime, which);
+ }
+
+ @Override public int getInputEventCount(int which) {
+ return mInputEventCounter.getCount(which);
+ }
+
@Override public long getPhoneOnTime(long batteryRealtime, int which) {
return mPhoneOnTimer.getTotalTime(batteryRealtime, which);
}
@@ -621,12 +783,20 @@ public final class BatteryStatsImpl extends BatteryStats {
batteryRealtime, which);
}
+ @Override public int getPhoneSignalStrengthCount(int dataType, int which) {
+ return mPhoneDataConnectionsTimer[dataType].getCount(which);
+ }
+
@Override public long getPhoneDataConnectionTime(int dataType,
long batteryRealtime, int which) {
return mPhoneDataConnectionsTimer[dataType].getTotalTime(
batteryRealtime, which);
}
+ @Override public int getPhoneDataConnectionCount(int dataType, int which) {
+ return mPhoneDataConnectionsTimer[dataType].getCount(which);
+ }
+
@Override public long getWifiOnTime(long batteryRealtime, int which) {
return mWifiOnTimer.getTotalTime(batteryRealtime, which);
}
@@ -665,12 +835,17 @@ public final class BatteryStatsImpl extends BatteryStats {
long mStartedTcpBytesReceived = -1;
long mStartedTcpBytesSent = -1;
+ boolean mWifiTurnedOn;
+ Timer mWifiTurnedOnTimer;
+
boolean mFullWifiLockOut;
Timer mFullWifiLockTimer;
boolean mScanWifiLockOut;
Timer mScanWifiLockTimer;
+ Counter[] mUserActivityCounters;
+
/**
* The statistics we have collected for this uid's wake locks.
*/
@@ -693,6 +868,7 @@ public final class BatteryStatsImpl extends BatteryStats {
public Uid(int uid) {
mUid = uid;
+ mWifiTurnedOnTimer = new Timer(WIFI_TURNED_ON, null, mUnpluggables);
mFullWifiLockTimer = new Timer(FULL_WIFI_LOCK, null, mUnpluggables);
mScanWifiLockTimer = new Timer(SCAN_WIFI_LOCK, null, mUnpluggables);
}
@@ -754,6 +930,22 @@ public final class BatteryStatsImpl extends BatteryStats {
}
}
+ @Override
+ public void noteWifiTurnedOnLocked() {
+ if (!mWifiTurnedOn) {
+ mWifiTurnedOn = true;
+ mWifiTurnedOnTimer.startRunningLocked(BatteryStatsImpl.this);
+ }
+ }
+
+ @Override
+ public void noteWifiTurnedOffLocked() {
+ if (mWifiTurnedOn) {
+ mWifiTurnedOn = false;
+ mWifiTurnedOnTimer.stopRunningLocked(BatteryStatsImpl.this);
+ }
+ }
+
@Override
public void noteFullWifiLockAcquiredLocked() {
if (!mFullWifiLockOut) {
@@ -785,6 +977,12 @@ public final class BatteryStatsImpl extends BatteryStats {
mScanWifiLockTimer.stopRunningLocked(BatteryStatsImpl.this);
}
}
+
+ @Override
+ public long getWifiTurnedOnTime(long batteryRealtime, int which) {
+ return mWifiTurnedOnTimer.getTotalTime(batteryRealtime, which);
+ }
+
@Override
public long getFullWifiLockTime(long batteryRealtime, int which) {
return mFullWifiLockTimer.getTotalTime(batteryRealtime, which);
@@ -795,6 +993,36 @@ public final class BatteryStatsImpl extends BatteryStats {
return mScanWifiLockTimer.getTotalTime(batteryRealtime, which);
}
+ @Override
+ public void noteUserActivityLocked(int type) {
+ if (mUserActivityCounters == null) {
+ initUserActivityLocked();
+ }
+ if (type < 0) type = 0;
+ else if (type >= NUM_USER_ACTIVITY_TYPES) type = NUM_USER_ACTIVITY_TYPES-1;
+ mUserActivityCounters[type].stepLocked();
+ }
+
+ @Override
+ public boolean hasUserActivity() {
+ return mUserActivityCounters != null;
+ }
+
+ @Override
+ public int getUserActivityCount(int type, int which) {
+ if (mUserActivityCounters == null) {
+ return 0;
+ }
+ return mUserActivityCounters[type].getCount(which);
+ }
+
+ void initUserActivityLocked() {
+ mUserActivityCounters = new Counter[NUM_USER_ACTIVITY_TYPES];
+ for (int i=0; i= 0
? (NetStat.getUidTxBytes(mUid) - mStartedTcpBytesSent) : 0);
@@ -835,8 +1063,17 @@ public final class BatteryStatsImpl extends BatteryStats {
out.writeLong(computeCurrentTcpBytesSent());
out.writeLong(mTcpBytesReceivedAtLastUnplug);
out.writeLong(mTcpBytesSentAtLastUnplug);
+ mWifiTurnedOnTimer.writeToParcel(out, batteryRealtime);
mFullWifiLockTimer.writeToParcel(out, batteryRealtime);
mScanWifiLockTimer.writeToParcel(out, batteryRealtime);
+ if (mUserActivityCounters == null) {
+ out.writeInt(0);
+ } else {
+ out.writeInt(1);
+ for (int i=0; i unpluggables, Parcel in) {
@@ -882,10 +1119,20 @@ public final class BatteryStatsImpl extends BatteryStats {
mCurrentTcpBytesSent = in.readLong();
mTcpBytesReceivedAtLastUnplug = in.readLong();
mTcpBytesSentAtLastUnplug = in.readLong();
+ mWifiTurnedOn = false;
+ mWifiTurnedOnTimer = new Timer(WIFI_TURNED_ON, null, mUnpluggables, in);
mFullWifiLockOut = false;
mFullWifiLockTimer = new Timer(FULL_WIFI_LOCK, null, mUnpluggables, in);
mScanWifiLockOut = false;
mScanWifiLockTimer = new Timer(SCAN_WIFI_LOCK, null, mUnpluggables, in);
+ if (in.readInt() == 0) {
+ mUserActivityCounters = null;
+ } else {
+ mUserActivityCounters = new Counter[NUM_USER_ACTIVITY_TYPES];
+ for (int i=0; i 0) {
@@ -2265,13 +2545,17 @@ public final class BatteryStatsImpl extends BatteryStats {
mBatteryLastRealtime = in.readLong();
mScreenOn = false;
mScreenOnTimer = new Timer(-1, null, mUnpluggables, in);
+ for (int i=0; i>>>>>>>>>>>>> AndroidRuntime START <<<<<<<<<<<<<<\n");
-
- JNIEnv* env;
+ int result = -1;
JavaVMInitArgs initArgs;
JavaVMOption opt;
char propBuf[PROPERTY_VALUE_MAX];
@@ -506,24 +512,10 @@ void AndroidRuntime::start(const char* className, const bool startSystemServer)
char enableAssertBuf[sizeof("-ea:")-1 + PROPERTY_VALUE_MAX];
char jniOptsBuf[sizeof("-Xjniopts:")-1 + PROPERTY_VALUE_MAX];
char* stackTraceFile = NULL;
- char* slashClassName = NULL;
- char* cp;
bool checkJni = false;
bool logStdio = false;
enum { kEMDefault, kEMIntPortable, kEMIntFast } executionMode = kEMDefault;
- blockSigpipe();
-
- /*
- * 'startSystemServer == true' means runtime is obslete and not run from
- * init.rc anymore, so we print out the boot start event here.
- */
- if (startSystemServer) {
- /* track our progress through the boot sequence */
- const int LOG_BOOT_PROGRESS_START = 3000;
- LOG_EVENT_LONG(LOG_BOOT_PROGRESS_START,
- ns2ms(systemTime(SYSTEM_TIME_MONOTONIC)));
- }
property_get("dalvik.vm.checkjni", propBuf, "");
if (strcmp(propBuf, "true") == 0) {
@@ -556,19 +548,6 @@ void AndroidRuntime::start(const char* className, const bool startSystemServer)
strcpy(jniOptsBuf, "-Xjniopts:");
property_get("dalvik.vm.jniopts", jniOptsBuf+10, "");
- const char* rootDir = getenv("ANDROID_ROOT");
- if (rootDir == NULL) {
- rootDir = "/system";
- if (!hasDir("/system")) {
- LOG_FATAL("No root directory specified, and /android does not exist.");
- return;
- }
- setenv("ANDROID_ROOT", rootDir, 1);
- }
-
- const char* kernelHack = getenv("LD_ASSUME_KERNEL");
- //LOGD("Found LD_ASSUME_KERNEL='%s'\n", kernelHack);
-
/* route exit() to our handler */
opt.extraInfo = (void*) runtime_exit;
opt.optionString = "exit";
@@ -759,11 +738,61 @@ void AndroidRuntime::start(const char* className, const bool startSystemServer)
* If this call succeeds, the VM is ready, and we can start issuing
* JNI calls.
*/
- if (JNI_CreateJavaVM(&mJavaVM, &env, &initArgs) < 0) {
+ if (JNI_CreateJavaVM(pJavaVM, pEnv, &initArgs) < 0) {
LOGE("JNI_CreateJavaVM failed\n");
goto bail;
}
+ result = 0;
+
+bail:
+ free(stackTraceFile);
+ return result;
+}
+
+/*
+ * Start the Android runtime. This involves starting the virtual machine
+ * and calling the "static void main(String[] args)" method in the class
+ * named by "className".
+ */
+void AndroidRuntime::start(const char* className, const bool startSystemServer)
+{
+ LOGD("\n>>>>>>>>>>>>>> AndroidRuntime START <<<<<<<<<<<<<<\n");
+
+ char* slashClassName = NULL;
+ char* cp;
+ JNIEnv* env;
+
+ blockSigpipe();
+
+ /*
+ * 'startSystemServer == true' means runtime is obslete and not run from
+ * init.rc anymore, so we print out the boot start event here.
+ */
+ if (startSystemServer) {
+ /* track our progress through the boot sequence */
+ const int LOG_BOOT_PROGRESS_START = 3000;
+ LOG_EVENT_LONG(LOG_BOOT_PROGRESS_START,
+ ns2ms(systemTime(SYSTEM_TIME_MONOTONIC)));
+ }
+
+ const char* rootDir = getenv("ANDROID_ROOT");
+ if (rootDir == NULL) {
+ rootDir = "/system";
+ if (!hasDir("/system")) {
+ LOG_FATAL("No root directory specified, and /android does not exist.");
+ goto bail;
+ }
+ setenv("ANDROID_ROOT", rootDir, 1);
+ }
+
+ //const char* kernelHack = getenv("LD_ASSUME_KERNEL");
+ //LOGD("Found LD_ASSUME_KERNEL='%s'\n", kernelHack);
+
+ /* start the virtual machine */
+ if (startVm(&mJavaVM, &env) != 0)
+ goto bail;
+
/*
* Register android functions.
*/
@@ -833,7 +862,6 @@ void AndroidRuntime::start(const char* className, const bool startSystemServer)
bail:
free(slashClassName);
- free(stackTraceFile);
}
void AndroidRuntime::start()
diff --git a/core/jni/android_server_BluetoothDeviceService.cpp b/core/jni/android_server_BluetoothDeviceService.cpp
index 796da1536b1c2..a0e0b84aed668 100644
--- a/core/jni/android_server_BluetoothDeviceService.cpp
+++ b/core/jni/android_server_BluetoothDeviceService.cpp
@@ -44,6 +44,8 @@
namespace android {
+#define BLUETOOTH_CLASS_ERROR 0xFF000000
+
#ifdef HAVE_BLUETOOTH
// We initialize these variables when we load class
// android.server.BluetoothDeviceService
@@ -724,11 +726,11 @@ static jstring lastUsedNative(JNIEnv *env, jobject obj, jstring address) {
}
static jint getRemoteClassNative(JNIEnv *env, jobject object, jstring address) {
+ jint result = BLUETOOTH_CLASS_ERROR;
#ifdef HAVE_BLUETOOTH
LOGV(__FUNCTION__);
native_data_t *nat = get_native_data(env, object);
if (nat) {
- jint ret = 0;
const char *c_address = env->GetStringUTFChars(address, NULL);
LOGV("... address = %s", c_address);
@@ -744,17 +746,15 @@ static jint getRemoteClassNative(JNIEnv *env, jobject object, jstring address) {
DBusError err;
dbus_error_init(&err);
if (!dbus_message_get_args(reply, &err,
- DBUS_TYPE_UINT32, &ret,
+ DBUS_TYPE_UINT32, &result,
DBUS_TYPE_INVALID)) {
LOG_AND_FREE_DBUS_ERROR_WITH_MSG(&err, reply);
}
dbus_message_unref(reply);
}
-
- return ret;
}
#endif
- return 0;
+ return result;
}
static jbyteArray getRemoteFeaturesNative(JNIEnv *env, jobject object,
diff --git a/core/res/res/values-ja/strings.xml b/core/res/res/values-ja/strings.xml
index ccc7f198ac3a6..29e4a6d994a0b 100644
--- a/core/res/res/values-ja/strings.xml
+++ b/core/res/res/values-ja/strings.xml
@@ -572,7 +572,7 @@
"%1$s %2$s"
"%1$s %2$s"
"%2$s、%1$s"
- "yyyy'/'MMMM'/'d"
+ "MMMMd'日 'yyyy"
"yyyy'年'MMMM'月'd'日'"
"MMM'/'d' 'yyyy'年'"
"d'/'MMM'/'yyyy"
@@ -586,16 +586,16 @@
"%Y年%B%-d日"
- "%Y年%B月"
+ "%Y年%B"
"%H:%M:%S"
"%Y/%B/%-d %H:%M:%S"
- "%2$s月%3$s日~%7$s月%8$s日"
+ "%2$s/%3$s~%7$s/%8$s"
"%2$s/%3$s%1$s~%7$s/%8$s%6$s"
- "%9$s年%2$s月%3$s日~%7$s月%8$s日"
+ "%2$s/%3$s~%7$s/%8$s, %9$s"
"%9$s/%2$s/%3$s%1$s~%7$s/%8$s%6$s"
- "%2$s月%3$s日%5$s~%7$s月%8$s日%10$s"
+ "%2$s/%3$s %5$s~%7$s/%8$s %10$s"
"%2$s/%3$s%1$s%5$s~%7$s/%8$s%6$s%10$s"
- "%4$s年%2$s月%3$s日 %5$s~%9$s年%7$s月%8$s日 %10$s"
+ "%4$s/%2$s/%3$s %5$s~%9$s/%7$s/%8$s %10$s"
"%4$s/%2$s/%3$s%1$s%5$s~%9$s/%7$s/%8$s%6$s%10$s"
"%2$s/%3$s~%7$s/%8$s"
"%2$s/%3$s%1$s~%7$s/%8$s%6$s"
@@ -607,7 +607,7 @@
"%4$s/%2$s/%3$s%1$s%5$s~%9$s/%7$s/%8$s%6$s%10$s"
"%2$s月%3$s日~%8$s日"
"%2$s/%3$s%1$s~%7$s/%8$s%6$s"
- "%9$s年%2$s月%3$s日~%8$s日"
+ "%2$s/%3$s - %8$s, %9$s"
"%4$s/%2$s/%3$s%1$s~%9$s/%7$s/%8$s%6$s"
"%2$s/%3$s%5$s~%7$s/%8$s%10$s"
"%2$s/%3$s%1$s%5$s~%7$s/%8$s%6$s%10$s"
@@ -665,18 +665,18 @@
"10月"
"11月"
"12月"
- "1月"
- "2月"
- "3月"
- "4月"
- "5月"
- "6月"
- "7月"
- "8月"
- "9月"
- "10月"
- "11月"
- "12月"
+ "1"
+ "2"
+ "3"
+ "4"
+ "5"
+ "6"
+ "7"
+ "8"
+ "9"
+ "10"
+ "11"
+ "12"
"1"
"2"
"3"
diff --git a/core/res/res/values-zh-rCN/arrays.xml b/core/res/res/values-zh-rCN/arrays.xml
deleted file mode 100644
index 16da6d91e49fb..0000000000000
--- a/core/res/res/values-zh-rCN/arrays.xml
+++ /dev/null
@@ -1,32 +0,0 @@
-
-
-
-
-
-
- - 39937795
- - 116387224
-
-
-
- - 2
-
-
-
diff --git a/core/res/res/values-zh-rTW/arrays.xml b/core/res/res/values-zh-rTW/arrays.xml
deleted file mode 100644
index be0795b84af01..0000000000000
--- a/core/res/res/values-zh-rTW/arrays.xml
+++ /dev/null
@@ -1,32 +0,0 @@
-
-
-
-
-
-
- - 25022112
- - 121478019
-
-
-
- - 3
-
-
-
diff --git a/core/res/res/values/strings.xml b/core/res/res/values/strings.xml
index f45d2e462bfe6..3282482671b3b 100644
--- a/core/res/res/values/strings.xml
+++ b/core/res/res/values/strings.xml
@@ -2321,5 +2321,8 @@
Create contact\nusing %s
-
+
+
+
+
diff --git a/docs/html/sdk/1.0_r1/upgrading.jd b/docs/html/sdk/1.0_r1/upgrading.jd
index 480bff384a9f5..d6d5dc486c59e 100644
--- a/docs/html/sdk/1.0_r1/upgrading.jd
+++ b/docs/html/sdk/1.0_r1/upgrading.jd
@@ -133,11 +133,17 @@ to place 3rd jar files, which are now automatically handled by the Ant script.
Migrate your applications
-After updating your SDK, you will likely encounter breakages in your code, due to
-framework and API changes. You'll need to update your code to match changes in the Android APIs.
+If (and only if) you have written apps in an SDK released previous to
+the Android 1.0 SDK, you will need to migrate your applications. After
+updating your SDK, you may encounter breakages in your code, due to
+framework and API changes. You'll need to update your code to match
+changes in the Android APIs.
One way to start is to open your project in Eclipse and see where the ADT
-identifies errors in your application.
+identifies errors in your application. You can also look up
+specific changes in the Android APIs in the Overview of Changes and
+API Diffs Report, both available in the documentation included with the
+Android 1.0 SDK package.
If you have additional trouble updating your code, visit the
Android Developers Group
diff --git a/docs/html/sdk/1.0_r2/upgrading.jd b/docs/html/sdk/1.0_r2/upgrading.jd
index df9b6579273b0..409e30e8c1959 100644
--- a/docs/html/sdk/1.0_r2/upgrading.jd
+++ b/docs/html/sdk/1.0_r2/upgrading.jd
@@ -133,11 +133,17 @@ to place 3rd jar files, which are now automatically handled by the Ant script.
Migrate your applications
-After updating your SDK, you will likely encounter breakages in your code, due to
-framework and API changes. You'll need to update your code to match changes in the Android APIs.
+If (and only if) you have written apps in an SDK released previous to
+the Android 1.0 SDK, you will need to migrate your applications. After
+updating your SDK, you may encounter breakages in your code, due to
+framework and API changes. You'll need to update your code to match
+changes in the Android APIs.
One way to start is to open your project in Eclipse and see where the ADT
-identifies errors in your application.
+identifies errors in your application. You can also look up
+specific changes in the Android APIs in the Overview of Changes and
+API Diffs Report, both available in the documentation included with the
+Android 1.0 SDK package.
If you have additional trouble updating your code, visit the
Android Developers Group
diff --git a/docs/html/sdk/1.1_r1/upgrading.jd b/docs/html/sdk/1.1_r1/upgrading.jd
index 2ad6757c0904d..19095c0be948e 100644
--- a/docs/html/sdk/1.1_r1/upgrading.jd
+++ b/docs/html/sdk/1.1_r1/upgrading.jd
@@ -131,11 +131,11 @@ framework and API changes. You'll need to update your code to match the
latest APIs.
One way to start is to open your project in Eclipse and see where the ADT
-identifies errors in your application. From there, you can lookup
-specific API changes in the Android 1.0 APIs in the
-
-Overview of Changes and
-API Diffs Report.
+identifies errors in your application. You can also look up
+specific changes in the Android APIs in the
+Android 1.1 Version
+Notes document.
+
If you have additional trouble updating your code, visit the
Android Developers Group
diff --git a/docs/html/sdk/1.5_r1/upgrading.jd b/docs/html/sdk/1.5_r1/upgrading.jd
index 23cb82c29fa07..63b7a3ce559c4 100644
--- a/docs/html/sdk/1.5_r1/upgrading.jd
+++ b/docs/html/sdk/1.5_r1/upgrading.jd
@@ -131,11 +131,12 @@ framework and API changes. You'll need to update your code to match the
latest APIs.
One way to start is to open your project in Eclipse and see where the ADT
-identifies errors in your application. From there, you can lookup
-specific API changes in the Android 1.0 APIs in the
-
-Overview of Changes and
-API Diffs Report.
+identifies errors in your application. You can also look up
+specific changes in the Android APIs in the
+
+Android 1.5 Version Notes
+
+document.
If you have additional trouble updating your code, visit the
Android Developers Group
diff --git a/include/android_runtime/AndroidRuntime.h b/include/android_runtime/AndroidRuntime.h
index 78bef91e8595b..0304309963cef 100644
--- a/include/android_runtime/AndroidRuntime.h
+++ b/include/android_runtime/AndroidRuntime.h
@@ -98,6 +98,7 @@ public:
private:
static int startReg(JNIEnv* env);
+ int startVm(JavaVM** pJavaVM, JNIEnv** pEnv);
Vector mOptions;
diff --git a/libs/audioflinger/AudioFlinger.cpp b/libs/audioflinger/AudioFlinger.cpp
index 106936215cca1..43df7ddfdb2b6 100644
--- a/libs/audioflinger/AudioFlinger.cpp
+++ b/libs/audioflinger/AudioFlinger.cpp
@@ -958,13 +958,10 @@ status_t AudioFlinger::MixerThread::dumpTracks(int fd, const Vector& a
result.append(buffer);
result.append(" Name Clien Typ Fmt Chn Buf S M F SRate LeftV RighV Serv User\n");
for (size_t i = 0; i < mTracks.size(); ++i) {
- wp