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 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 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 wTrack = mTracks[i]; - if (wTrack != 0) { - sp track = wTrack.promote(); - if (track != 0) { - track->dump(buffer, SIZE); - result.append(buffer); - } + sp track = mTracks[i]; + if (track != 0) { + track->dump(buffer, SIZE); + result.append(buffer); } } @@ -972,7 +969,7 @@ 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 < mActiveTracks.size(); ++i) { - wp wTrack = mTracks[i]; + wp wTrack = mActiveTracks[i]; if (wTrack != 0) { sp track = wTrack.promote(); if (track != 0) { diff --git a/location/java/com/android/internal/location/GpsLocationProvider.java b/location/java/com/android/internal/location/GpsLocationProvider.java index 887574a66bad1..f5950501d5107 100644 --- a/location/java/com/android/internal/location/GpsLocationProvider.java +++ b/location/java/com/android/internal/location/GpsLocationProvider.java @@ -412,6 +412,12 @@ public class GpsLocationProvider extends LocationProviderImpl { mNetworkThread = null; } + // The GpsEventThread does not wait for the GPS to shutdown + // so we need to report the GPS_STATUS_ENGINE_OFF event here + if (mNavigating) { + reportStatus(GPS_STATUS_ENGINE_OFF); + } + native_cleanup(); } @@ -797,8 +803,8 @@ public class GpsLocationProvider extends LocationProviderImpl { public void run() { if (Config.LOGD) Log.d(TAG, "GpsEventThread starting"); - // thread exits after disable() is called and navigation has stopped - while (mEnabled || mNavigating) { + // Exit as soon as disable() is called instead of waiting for the GPS to stop. + while (mEnabled) { // this will wait for an event from the GPS, // which will be reported via reportLocation or reportStatus native_wait_for_event(); diff --git a/media/tests/MediaFrameworkTest/AndroidManifest.xml b/media/tests/MediaFrameworkTest/AndroidManifest.xml index a32f5907f391f..d0ff9ce017647 100644 --- a/media/tests/MediaFrameworkTest/AndroidManifest.xml +++ b/media/tests/MediaFrameworkTest/AndroidManifest.xml @@ -18,6 +18,7 @@ package="com.android.mediaframeworktest"> + 1.0f) ratio = 1.0f; if ((newState & SCREEN_ON_BIT) == 0) { - int steps; if ((oldState & SCREEN_BRIGHT_BIT) != 0) { // was bright steps = ANIM_STEPS; @@ -1471,10 +1474,8 @@ class PowerManagerService extends IPowerManager.Stub implements LocalPowerManage // was dim steps = (int)(ANIM_STEPS*ratio*scale); } - mScreenBrightness.setTargetLocked(Power.BRIGHTNESS_OFF, - steps, INITIAL_SCREEN_BRIGHTNESS, nominalCurrentValue); + brightness = Power.BRIGHTNESS_OFF; } else { - int steps; if ((oldState & SCREEN_ON_BIT) != 0) { // was bright steps = (int)(ANIM_STEPS*(1.0f-ratio)*scale); @@ -1490,13 +1491,19 @@ class PowerManagerService extends IPowerManager.Stub implements LocalPowerManage // will then count going dim as turning off. mScreenOffTime = SystemClock.elapsedRealtime(); } - mScreenBrightness.setTargetLocked(Power.BRIGHTNESS_DIM, - steps, INITIAL_SCREEN_BRIGHTNESS, nominalCurrentValue); + brightness = Power.BRIGHTNESS_DIM; } - } else { - mScreenBrightness.setTargetLocked(preferredBrightness, - ANIM_STEPS, INITIAL_SCREEN_BRIGHTNESS, nominalCurrentValue); } + long identity = Binder.clearCallingIdentity(); + try { + mBatteryStats.noteScreenBrightness(brightness); + } catch (RemoteException e) { + // Nothing interesting to do. + } finally { + Binder.restoreCallingIdentity(identity); + } + mScreenBrightness.setTargetLocked(brightness, + steps, INITIAL_SCREEN_BRIGHTNESS, nominalCurrentValue); startAnimation = true; } else { if ((newState & SCREEN_BRIGHT_BIT) == 0) { @@ -1735,6 +1742,16 @@ class PowerManagerService extends IPowerManager.Stub implements LocalPowerManage mUserState |= SCREEN_BRIGHT; } + int uid = Binder.getCallingUid(); + long ident = Binder.clearCallingIdentity(); + try { + mBatteryStats.noteUserActivity(uid, eventType); + } catch (RemoteException e) { + // Ignore + } finally { + Binder.restoreCallingIdentity(ident); + } + reactivateWakeLocksLocked(); mWakeLockState = mLocks.gatherState(); setPowerState(mUserState | mWakeLockState, noChangeLights, true); @@ -1951,6 +1968,15 @@ class PowerManagerService extends IPowerManager.Stub implements LocalPowerManage synchronized (mLocks) { Log.d(TAG, "system ready!"); mDoneBooting = true; + long identity = Binder.clearCallingIdentity(); + try { + mBatteryStats.noteScreenBrightness(getPreferredBrightness()); + mBatteryStats.noteScreenOn(); + } catch (RemoteException e) { + // Nothing interesting to do. + } finally { + Binder.restoreCallingIdentity(identity); + } userActivity(SystemClock.uptimeMillis(), false, BUTTON_EVENT, true); updateWakeLockLocked(); mLocks.notifyAll(); diff --git a/services/java/com/android/server/WifiService.java b/services/java/com/android/server/WifiService.java index 8e1d053a675bb..54e77f0222380 100644 --- a/services/java/com/android/server/WifiService.java +++ b/services/java/com/android/server/WifiService.java @@ -47,6 +47,7 @@ import android.os.IBinder; import android.os.Looper; import android.os.Message; import android.os.PowerManager; +import android.os.Process; import android.os.RemoteException; import android.provider.Settings; import android.util.Log; @@ -167,6 +168,11 @@ public class WifiService extends IWifiManager.Stub { private char[] mScanResultBuffer; private boolean mNeedReconfig; + /* + * Last UID that asked to enable WIFI. + */ + private int mLastEnableUid = Process.myUid(); + /** * Number of allowed radio frequency channels in various regulatory domains. * This list is sufficient for 802.11b/g networks (2.4GHz range). @@ -239,7 +245,7 @@ public class WifiService extends IWifiManager.Stub { }, new IntentFilter(Intent.ACTION_AIRPLANE_MODE_CHANGED)); - setWifiEnabledBlocking(wifiEnabled, false); + setWifiEnabledBlocking(wifiEnabled, false, Process.myUid()); } /** @@ -455,7 +461,8 @@ public class WifiService extends IWifiManager.Stub { synchronized (mWifiHandler) { sWakeLock.acquire(); - sendEnableMessage(enable, true); + mLastEnableUid = Binder.getCallingUid(); + sendEnableMessage(enable, true, Binder.getCallingUid()); } return true; @@ -465,10 +472,11 @@ public class WifiService extends IWifiManager.Stub { * Enables/disables Wi-Fi synchronously. * @param enable {@code true} to turn Wi-Fi on, {@code false} to turn it off. * @param persist {@code true} if the setting should be persisted. + * @param uid The UID of the process making the request. * @return {@code true} if the operation succeeds (or if the existing state * is the same as the requested state) */ - private boolean setWifiEnabledBlocking(boolean enable, boolean persist) { + private boolean setWifiEnabledBlocking(boolean enable, boolean persist, int uid) { final int eventualWifiState = enable ? WIFI_STATE_ENABLED : WIFI_STATE_DISABLED; if (mWifiState == eventualWifiState) { @@ -478,18 +486,18 @@ public class WifiService extends IWifiManager.Stub { return false; } - setWifiEnabledState(enable ? WIFI_STATE_ENABLING : WIFI_STATE_DISABLING); + setWifiEnabledState(enable ? WIFI_STATE_ENABLING : WIFI_STATE_DISABLING, uid); if (enable) { if (!WifiNative.loadDriver()) { Log.e(TAG, "Failed to load Wi-Fi driver."); - setWifiEnabledState(WIFI_STATE_UNKNOWN); + setWifiEnabledState(WIFI_STATE_UNKNOWN, uid); return false; } if (!WifiNative.startSupplicant()) { WifiNative.unloadDriver(); Log.e(TAG, "Failed to start supplicant daemon."); - setWifiEnabledState(WIFI_STATE_UNKNOWN); + setWifiEnabledState(WIFI_STATE_UNKNOWN, uid); return false; } registerForBroadcasts(); @@ -503,7 +511,7 @@ public class WifiService extends IWifiManager.Stub { boolean failedToStopSupplicantOrUnloadDriver = false; if (!WifiNative.stopSupplicant()) { Log.e(TAG, "Failed to stop supplicant daemon."); - setWifiEnabledState(WIFI_STATE_UNKNOWN); + setWifiEnabledState(WIFI_STATE_UNKNOWN, uid); failedToStopSupplicantOrUnloadDriver = true; } @@ -513,7 +521,7 @@ public class WifiService extends IWifiManager.Stub { if (!WifiNative.unloadDriver()) { Log.e(TAG, "Failed to unload Wi-Fi driver."); if (!failedToStopSupplicantOrUnloadDriver) { - setWifiEnabledState(WIFI_STATE_UNKNOWN); + setWifiEnabledState(WIFI_STATE_UNKNOWN, uid); failedToStopSupplicantOrUnloadDriver = true; } } @@ -527,7 +535,7 @@ public class WifiService extends IWifiManager.Stub { if (persist) { persistWifiEnabled(enable); } - setWifiEnabledState(eventualWifiState); + setWifiEnabledState(eventualWifiState, uid); /* * Initialize the hidden networks state and the number of allowed @@ -541,15 +549,15 @@ public class WifiService extends IWifiManager.Stub { return true; } - private void setWifiEnabledState(int wifiState) { + private void setWifiEnabledState(int wifiState, int uid) { final int previousWifiState = mWifiState; long ident = Binder.clearCallingIdentity(); try { if (wifiState == WIFI_STATE_ENABLED) { - mBatteryStats.noteWifiOn(); + mBatteryStats.noteWifiOn(uid); } else if (wifiState == WIFI_STATE_DISABLED) { - mBatteryStats.noteWifiOff(); + mBatteryStats.noteWifiOff(uid); } } catch (RemoteException e) { } finally { @@ -1571,10 +1579,10 @@ public class WifiService extends IWifiManager.Stub { } }; - private void sendEnableMessage(boolean enable, boolean persist) { + private void sendEnableMessage(boolean enable, boolean persist, int uid) { Message msg = Message.obtain(mWifiHandler, (enable ? MESSAGE_ENABLE_WIFI : MESSAGE_DISABLE_WIFI), - (persist ? 1 : 0), 0); + (persist ? 1 : 0), uid); msg.sendToTarget(); } @@ -1602,7 +1610,7 @@ public class WifiService extends IWifiManager.Stub { if (wifiShouldBeEnabled) { if (wifiShouldBeStarted) { sWakeLock.acquire(); - sendEnableMessage(true, false); + sendEnableMessage(true, false, mLastEnableUid); sWakeLock.acquire(); sendStartMessage(strongestLockMode == WifiManager.WIFI_MODE_SCAN_ONLY); } else { @@ -1626,7 +1634,7 @@ public class WifiService extends IWifiManager.Stub { } } else { sWakeLock.acquire(); - sendEnableMessage(false, false); + sendEnableMessage(false, false, mLastEnableUid); } } } @@ -1671,7 +1679,7 @@ public class WifiService extends IWifiManager.Stub { switch (msg.what) { case MESSAGE_ENABLE_WIFI: - setWifiEnabledBlocking(true, msg.arg1 == 1); + setWifiEnabledBlocking(true, msg.arg1 == 1, msg.arg2); sWakeLock.release(); break; @@ -1684,7 +1692,7 @@ public class WifiService extends IWifiManager.Stub { case MESSAGE_DISABLE_WIFI: // a non-zero msg.arg1 value means the "enabled" setting // should be persisted - setWifiEnabledBlocking(false, msg.arg1 == 1); + setWifiEnabledBlocking(false, msg.arg1 == 1, msg.arg2); sWakeLock.release(); break; diff --git a/services/java/com/android/server/WindowManagerService.java b/services/java/com/android/server/WindowManagerService.java index 2e16157fa294c..0b1ddc846be5d 100644 --- a/services/java/com/android/server/WindowManagerService.java +++ b/services/java/com/android/server/WindowManagerService.java @@ -5085,6 +5085,11 @@ public class WindowManagerService extends IWindowManager.Stub implements Watchdo } else { eventType = LocalPowerManager.OTHER_EVENT; } + try { + mBatteryStats.noteInputEvent(); + } catch (RemoteException e) { + // Ignore + } mPowerManager.userActivity(curTime, false, eventType); switch (ev.classType) { case RawInputEvent.CLASS_KEYBOARD: @@ -7480,11 +7485,12 @@ public class WindowManagerService extends IWindowManager.Stub implements Watchdo final int dh = mDisplay.getHeight(); final int N = mWindows.size(); + int repeats = 0; int i; // FIRST LOOP: Perform a layout, if needed. - if (mLayoutNeeded) { + while (mLayoutNeeded) { mPolicy.beginLayoutLw(dw, dh); // First perform layout of any root windows (not attached @@ -7492,10 +7498,18 @@ public class WindowManagerService extends IWindowManager.Stub implements Watchdo int topAttached = -1; for (i = N-1; i >= 0; i--) { WindowState win = (WindowState) mWindows.get(i); - - boolean gone = win.mViewVisibility == View.GONE + + // Don't do layout of a window if it is not visible, or + // soon won't be visible, to avoid wasting time and funky + // changes while a window is animating away. + final AppWindowToken atoken = win.mAppToken; + final boolean gone = win.mViewVisibility == View.GONE || !win.mRelayoutCalled - || win.mRootToken.hidden; + || win.mRootToken.hidden + || (atoken != null && atoken.hiddenRequested) + || !win.mPolicyVisibility + || win.mAttachedHidden + || win.mExiting || win.mDestroying; // If this view is GONE, then skip it -- keep the current // frame, and let the caller know so they can ignore it @@ -7531,8 +7545,14 @@ public class WindowManagerService extends IWindowManager.Stub implements Watchdo } } - mPolicy.finishLayoutLw(); - mLayoutNeeded = false; + if (!mPolicy.finishLayoutLw()) { + mLayoutNeeded = false; + } else if (repeats > 2) { + Log.w(TAG, "Layout repeat aborted after too many iterations"); + mLayoutNeeded = false; + } else { + repeats++; + } } } diff --git a/services/java/com/android/server/am/BatteryStatsService.java b/services/java/com/android/server/am/BatteryStatsService.java index 2192e062c2284..9ad994c52c1d0 100644 --- a/services/java/com/android/server/am/BatteryStatsService.java +++ b/services/java/com/android/server/am/BatteryStatsService.java @@ -129,6 +129,13 @@ public final class BatteryStatsService extends IBatteryStats.Stub { } } + public void noteScreenBrightness(int brightness) { + enforceCallingPermission(); + synchronized (mStats) { + mStats.noteScreenBrightnessLocked(brightness); + } + } + public void noteScreenOff() { enforceCallingPermission(); synchronized (mStats) { @@ -136,6 +143,20 @@ public final class BatteryStatsService extends IBatteryStats.Stub { } } + public void noteInputEvent() { + enforceCallingPermission(); + synchronized (mStats) { + mStats.noteInputEventLocked(); + } + } + + public void noteUserActivity(int uid, int event) { + enforceCallingPermission(); + synchronized (mStats) { + mStats.noteUserActivityLocked(uid, event); + } + } + public void notePhoneOn() { enforceCallingPermission(); synchronized (mStats) { @@ -164,17 +185,17 @@ public final class BatteryStatsService extends IBatteryStats.Stub { } } - public void noteWifiOn() { + public void noteWifiOn(int uid) { enforceCallingPermission(); synchronized (mStats) { - mStats.noteWifiOnLocked(); + mStats.noteWifiOnLocked(uid); } } - public void noteWifiOff() { + public void noteWifiOff(int uid) { enforceCallingPermission(); synchronized (mStats) { - mStats.noteWifiOffLocked(); + mStats.noteWifiOffLocked(uid); } } diff --git a/telephony/java/com/android/internal/telephony/PhoneBase.java b/telephony/java/com/android/internal/telephony/PhoneBase.java index 580814f0a020d..4fb5f6119f708 100644 --- a/telephony/java/com/android/internal/telephony/PhoneBase.java +++ b/telephony/java/com/android/internal/telephony/PhoneBase.java @@ -16,15 +16,22 @@ package com.android.internal.telephony; +import android.app.ActivityManagerNative; +import android.app.IActivityManager; import android.content.Context; +import android.content.res.Configuration; import android.os.AsyncResult; import android.os.Handler; import android.os.Looper; import android.os.RegistrantList; +import android.os.SystemProperties; import android.telephony.ServiceState; +import android.util.Log; +import com.android.internal.R; import com.android.internal.telephony.test.SimulatedRadioControl; import java.util.List; +import java.util.Locale; /** * (Not for SDK use) @@ -109,6 +116,8 @@ public abstract class PhoneBase implements Phone { this.mContext = context; mLooper = Looper.myLooper(); + setLocaleByCarrier(); + setUnitTestMode(unitTestMode); } @@ -307,4 +316,89 @@ public abstract class PhoneBase implements Phone { } } + /** + * Set the locale by matching the carrier string in + * a string-array resource + */ + private void setLocaleByCarrier() { + String carrier = SystemProperties.get("ro.carrier"); + + if (null == carrier || 0 == carrier.length()) { + return; + } + + CharSequence[] carrierLocales = mContext. + getResources().getTextArray(R.array.carrier_locales); + + for (int i = 0; i < carrierLocales.length-1; i+=2) { + String c = carrierLocales[i].toString(); + String l = carrierLocales[i+1].toString(); + if (carrier.equals(c)) { + String language = l.substring(0, 2); + String country = ""; + if (l.length() >=5) { + country = l.substring(3, 5); + } + setSystemLocale(language, country); + return; + } + } + } + + /** + * Utility code to set the system locale if it's not set already + * @param langauge Two character language code desired + * @param country Two character country code desired + * + * {@hide} + */ + public void setSystemLocale(String language, String country) { + String l = SystemProperties.get("persist.sys.language"); + String c = SystemProperties.get("persist.sys.country"); + + if (null == language) { + return; // no match possible + } + language.toLowerCase(); + if (null != country) { + country = ""; + } + country = country.toUpperCase(); + + if((null == l || 0 == l.length()) && (null == c || 0 == c.length())) { + try { + // try to find a good match + String[] locales = mContext.getAssets().getLocales(); + final int N = locales.length; + String bestMatch = null; + for(int i = 0; i < N; i++) { + if (locales[i]!=null && locales[i].length() >= 2 && + locales[i].substring(0,2).equals(language)) { + if (locales[i].length() >= 5 && + locales[i].substring(3,5).equals(country)) { + bestMatch = locales[i]; + break; + } else if (null == bestMatch) { + bestMatch = locales[i]; + } + } + } + if (null != bestMatch) { + IActivityManager am = ActivityManagerNative.getDefault(); + Configuration config = am.getConfiguration(); + + if (bestMatch.length() >= 5) { + config.locale = new Locale(bestMatch.substring(0,2), + bestMatch.substring(3,5)); + } else { + config.locale = new Locale(bestMatch.substring(0,2)); + } + config.userSetLocale = true; + am.updateConfiguration(config); + } + } catch (Exception e) { + // Intentionally left blank + } + } + } } diff --git a/telephony/java/com/android/internal/telephony/gsm/SIMRecords.java b/telephony/java/com/android/internal/telephony/gsm/SIMRecords.java index a62f6cfd4d09d..4467536212ba8 100644 --- a/telephony/java/com/android/internal/telephony/gsm/SIMRecords.java +++ b/telephony/java/com/android/internal/telephony/gsm/SIMRecords.java @@ -27,10 +27,6 @@ import android.os.SystemProperties; import android.telephony.gsm.SmsMessage; import android.util.Log; import java.util.ArrayList; -import android.app.ActivityManagerNative; -import android.app.IActivityManager; -import java.util.Locale; -import android.content.res.Configuration; import static com.android.internal.telephony.TelephonyProperties.*; import com.android.internal.telephony.SimCard; @@ -554,48 +550,10 @@ public final class SIMRecords extends Handler implements SimConstants * @param mcc Mobile Country Code of the SIM */ private void setLocaleFromMccIfNeeded(int mcc) { - String language = SystemProperties.get("persist.sys.language"); - String country = SystemProperties.get("persist.sys.country"); - Log.d(LOG_TAG,"setLocaleFromMcc"); - if((language == null || language.length() == 0) && (country == null || country.length() == 0)) { - try { - language = MccTable.defaultLanguageForMcc(mcc); - country = MccTable.countryCodeForMcc(mcc).toUpperCase(); - // try to find a good match - String[] locales = phone.getContext().getAssets().getLocales(); - final int N = locales.length; - String bestMatch = null; - for(int i = 0; i < N; i++) { - Log.d(LOG_TAG," trying "+locales[i]); - if(locales[i]!=null && locales[i].length() >= 2 && - locales[i].substring(0,2).equals(language)) { - if(locales[i].length() >= 5 && - locales[i].substring(3,5).equals(country)) { - bestMatch = locales[i]; - break; - } else if(bestMatch == null) { - bestMatch = locales[i]; - } - } - } - Log.d(LOG_TAG," got bestmatch = "+bestMatch); - if(bestMatch != null) { - IActivityManager am = ActivityManagerNative.getDefault(); - Configuration config = am.getConfiguration(); + String language = MccTable.defaultLanguageForMcc(mcc); + String country = MccTable.countryCodeForMcc(mcc); - if(bestMatch.length() >= 5) { - config.locale = new Locale(bestMatch.substring(0,2), - bestMatch.substring(3,5)); - } else { - config.locale = new Locale(bestMatch.substring(0,2)); - } - config.userSetLocale = true; - am.updateConfiguration(config); - } - } catch (Exception e) { - // Intentionally left blank - } - } + phone.setSystemLocale(language, country); } //***** Overridden from Handler diff --git a/test-runner/android/test/ClassPathPackageInfoSource.java b/test-runner/android/test/ClassPathPackageInfoSource.java index 12bc7f3a00e45..877075f2d2af9 100644 --- a/test-runner/android/test/ClassPathPackageInfoSource.java +++ b/test-runner/android/test/ClassPathPackageInfoSource.java @@ -226,8 +226,11 @@ public class ClassPathPackageInfoSource { String className = apkClassNames.nextElement(); if (className.startsWith(packageName)) { + String subPackageName = packageName; int lastPackageSeparator = className.lastIndexOf('.'); - String subPackageName = className.substring(0, lastPackageSeparator); + if (lastPackageSeparator > 0) { + subPackageName = className.substring(0, lastPackageSeparator); + } if (subPackageName.length() > packageName.length()) { subpackageNames.add(subPackageName); } else if (isToplevelClass(className)) { diff --git a/test-runner/android/test/InstrumentationTestRunner.java b/test-runner/android/test/InstrumentationTestRunner.java index f038612cbd0ed..044f55581a3d9 100644 --- a/test-runner/android/test/InstrumentationTestRunner.java +++ b/test-runner/android/test/InstrumentationTestRunner.java @@ -300,16 +300,17 @@ public class InstrumentationTestRunner extends Instrumentation implements TestSu } if (testClassesArg == null) { - TestSuite testSuite = null; if (mPackageOfTests != null) { testSuiteBuilder.includePackages(mPackageOfTests); } else { - testSuite = getTestSuite(); - testSuiteBuilder.addTestSuite(testSuite); - } - - if (testSuite == null) { - testSuiteBuilder.includePackages(getTargetContext().getPackageName()); + TestSuite testSuite = getTestSuite(); + if (testSuite != null) { + testSuiteBuilder.addTestSuite(testSuite); + } else { + // no package or class bundle arguments were supplied, and no test suite + // provided so add all tests in application + testSuiteBuilder.includePackages(""); + } } } else { parseTestClasses(testClassesArg, testSuiteBuilder); diff --git a/tests/DumpRenderTree/results/layout_tests_crashed.txt b/tests/DumpRenderTree/assets/results/layout_tests_crashed.txt similarity index 100% rename from tests/DumpRenderTree/results/layout_tests_crashed.txt rename to tests/DumpRenderTree/assets/results/layout_tests_crashed.txt diff --git a/tests/DumpRenderTree/results/layout_tests_failed.txt b/tests/DumpRenderTree/assets/results/layout_tests_failed.txt similarity index 100% rename from tests/DumpRenderTree/results/layout_tests_failed.txt rename to tests/DumpRenderTree/assets/results/layout_tests_failed.txt diff --git a/tests/DumpRenderTree/results/layout_tests_nontext.txt b/tests/DumpRenderTree/assets/results/layout_tests_nontext.txt similarity index 100% rename from tests/DumpRenderTree/results/layout_tests_nontext.txt rename to tests/DumpRenderTree/assets/results/layout_tests_nontext.txt diff --git a/tests/DumpRenderTree/results/layout_tests_passed.txt b/tests/DumpRenderTree/assets/results/layout_tests_passed.txt similarity index 100% rename from tests/DumpRenderTree/results/layout_tests_passed.txt rename to tests/DumpRenderTree/assets/results/layout_tests_passed.txt diff --git a/tests/DumpRenderTree/run_layout_tests.py b/tests/DumpRenderTree/assets/run_layout_tests.py similarity index 100% rename from tests/DumpRenderTree/run_layout_tests.py rename to tests/DumpRenderTree/assets/run_layout_tests.py diff --git a/tests/DumpRenderTree/src/com/android/dumprendertree/LayoutTestsAutoTest.java b/tests/DumpRenderTree/src/com/android/dumprendertree/LayoutTestsAutoTest.java index a857e681aa5c2..39eae02940d21 100644 --- a/tests/DumpRenderTree/src/com/android/dumprendertree/LayoutTestsAutoTest.java +++ b/tests/DumpRenderTree/src/com/android/dumprendertree/LayoutTestsAutoTest.java @@ -42,6 +42,8 @@ import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.FileReader; import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; import java.util.Vector; //TestRecorder creates two files, one for passing tests @@ -122,6 +124,18 @@ public class LayoutTestsAutoTest extends ActivityInstrumentationTestCase2 mTestList; @@ -452,4 +466,28 @@ public class LayoutTestsAutoTest extends ActivityInstrumentationTestCase2 0 ) { + out.write(buf, 0, len); + } + out.close(); + in.close(); + } + }catch (IOException e) { + e.printStackTrace(); + } + + } + }