Merge commit 'goog/readonly-p4-master'
This commit is contained in:
@@ -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 {
|
||||
|
||||
@@ -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<String, ? extends BatteryStats.Uid.Wakelock> wakelocks = u.getWakelockStats();
|
||||
if (wakelocks.size() > 0) {
|
||||
for (Map.Entry<String, ? extends BatteryStats.Uid.Wakelock> 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<NUM_SCREEN_BRIGHTNESS_BINS; i++) {
|
||||
args[i] = getScreenBrightnessTime(i, batteryRealtime, which) / 1000;
|
||||
}
|
||||
dumpLine(pw, 0 /* uid */, category, SCREEN_BRIGHTNESS_DATA, args);
|
||||
|
||||
// Dump signal strength stats
|
||||
Object[] args = new Object[NUM_SIGNAL_STRENGTH_BINS];
|
||||
args = new Object[NUM_SIGNAL_STRENGTH_BINS];
|
||||
for (int i=0; i<NUM_SIGNAL_STRENGTH_BINS; i++) {
|
||||
args[i] = getPhoneSignalStrengthTime(i, batteryRealtime, which) / 1000;
|
||||
}
|
||||
dumpLine(pw, 0 /* uid */, category, SIGNAL_STRENGTH_DATA, args);
|
||||
dumpLine(pw, 0 /* uid */, category, SIGNAL_STRENGTH_TIME_DATA, args);
|
||||
for (int i=0; i<NUM_SIGNAL_STRENGTH_BINS; i++) {
|
||||
args[i] = getPhoneSignalStrengthCount(i, which);
|
||||
}
|
||||
dumpLine(pw, 0 /* uid */, category, SIGNAL_STRENGTH_COUNT_DATA, args);
|
||||
|
||||
// Dump network type stats
|
||||
args = new Object[NUM_DATA_CONNECTION_TYPES];
|
||||
for (int i=0; i<NUM_DATA_CONNECTION_TYPES; i++) {
|
||||
args[i] = getPhoneDataConnectionTime(i, batteryRealtime, which) / 1000;
|
||||
}
|
||||
dumpLine(pw, 0 /* uid */, category, DATA_CONNECTION_DATA, args);
|
||||
dumpLine(pw, 0 /* uid */, category, DATA_CONNECTION_TIME_DATA, args);
|
||||
for (int i=0; i<NUM_DATA_CONNECTION_TYPES; i++) {
|
||||
args[i] = getPhoneDataConnectionCount(i, which);
|
||||
}
|
||||
dumpLine(pw, 0 /* uid */, category, DATA_CONNECTION_COUNT_DATA, args);
|
||||
|
||||
if (which == STATS_UNPLUGGED) {
|
||||
dumpLine(pw, 0 /* uid */, category, BATTERY_DATA, getUnpluggedStartLevel(),
|
||||
getPluggedStartLevel());
|
||||
}
|
||||
|
||||
SparseArray<? extends Uid> 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<Uid.NUM_USER_ACTIVITY_TYPES; i++) {
|
||||
int val = u.getUserActivityCount(i, which);
|
||||
args[i] = val;
|
||||
if (val != 0) hasData = true;
|
||||
}
|
||||
if (hasData) {
|
||||
dumpLine(pw, 0 /* uid */, category, USER_ACTIVITY_DATA, args);
|
||||
}
|
||||
}
|
||||
|
||||
Map<String, ? extends BatteryStats.Uid.Wakelock> wakelocks = u.getWakelockStats();
|
||||
if (wakelocks.size() > 0) {
|
||||
for (Map.Entry<String, ? extends BatteryStats.Uid.Wakelock> 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<NUM_SCREEN_BRIGHTNESS_BINS; i++) {
|
||||
final long time = getScreenBrightnessTime(i, batteryRealtime, which);
|
||||
if (time == 0) {
|
||||
continue;
|
||||
}
|
||||
if (didOne) sb.append(", ");
|
||||
didOne = true;
|
||||
sb.append(SCREEN_BRIGHTNESS_NAMES[i]);
|
||||
sb.append(" ");
|
||||
sb.append(formatTimeMs(time/1000));
|
||||
sb.append("(");
|
||||
sb.append(formatRatioLocked(time, screenOnTime));
|
||||
sb.append(")");
|
||||
}
|
||||
if (!didOne) sb.append("No activity");
|
||||
pw.println(sb.toString());
|
||||
|
||||
// Calculate total network and wakelock times across all uids.
|
||||
long rxTotal = 0;
|
||||
long txTotal = 0;
|
||||
long fullWakeLockTimeTotalMicros = 0;
|
||||
long partialWakeLockTimeTotalMicros = 0;
|
||||
|
||||
for (int iu = 0; iu < NU; iu++) {
|
||||
Uid u = uidStats.valueAt(iu);
|
||||
rxTotal += u.getTcpBytesReceived(which);
|
||||
txTotal += u.getTcpBytesSent(which);
|
||||
|
||||
Map<String, ? extends BatteryStats.Uid.Wakelock> wakelocks = u.getWakelockStats();
|
||||
if (wakelocks.size() > 0) {
|
||||
for (Map.Entry<String, ? extends BatteryStats.Uid.Wakelock> 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<NUM_SIGNAL_STRENGTH_BINS; i++) {
|
||||
final long time = getPhoneSignalStrengthTime(i, batteryRealtime, which);
|
||||
if (time == 0) {
|
||||
@@ -789,13 +1016,15 @@ public abstract class BatteryStats implements Parcelable {
|
||||
sb.append(formatTimeMs(time/1000));
|
||||
sb.append("(");
|
||||
sb.append(formatRatioLocked(time, whichBatteryRealtime));
|
||||
sb.append(")");
|
||||
sb.append(") ");
|
||||
sb.append(getPhoneSignalStrengthCount(i, which));
|
||||
sb.append("x");
|
||||
}
|
||||
if (!didOne) sb.append("No activity");
|
||||
pw.println(sb.toString());
|
||||
|
||||
sb.setLength(0);
|
||||
sb.append(" Data types: ");
|
||||
sb.append(" Radio types: ");
|
||||
didOne = false;
|
||||
for (int i=0; i<NUM_DATA_CONNECTION_TYPES; i++) {
|
||||
final long time = getPhoneDataConnectionTime(i, batteryRealtime, which);
|
||||
@@ -809,11 +1038,21 @@ public abstract class BatteryStats implements Parcelable {
|
||||
sb.append(formatTimeMs(time/1000));
|
||||
sb.append("(");
|
||||
sb.append(formatRatioLocked(time, whichBatteryRealtime));
|
||||
sb.append(")");
|
||||
sb.append(") ");
|
||||
sb.append(getPhoneDataConnectionCount(i, which));
|
||||
sb.append("x");
|
||||
}
|
||||
if (!didOne) sb.append("No activity");
|
||||
pw.println(sb.toString());
|
||||
|
||||
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)+ ")");
|
||||
|
||||
pw.println(" ");
|
||||
|
||||
if (which == STATS_UNPLUGGED) {
|
||||
@@ -828,12 +1067,10 @@ public abstract class BatteryStats implements Parcelable {
|
||||
pw.println(prefix + " Last discharge cycle end level: " +
|
||||
getPluggedStartLevel());
|
||||
}
|
||||
pw.println(" ");
|
||||
}
|
||||
|
||||
pw.println(" ");
|
||||
|
||||
SparseArray<? extends Uid> 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);
|
||||
@@ -844,12 +1081,41 @@ public abstract class BatteryStats implements Parcelable {
|
||||
long tcpSent = u.getTcpBytesSent(which);
|
||||
long fullWifiLockOnTime = u.getFullWifiLockTime(batteryRealtime, which);
|
||||
long scanWifiLockOnTime = u.getScanWifiLockTime(batteryRealtime, which);
|
||||
long wifiTurnedOnTime = u.getWifiTurnedOnTime(batteryRealtime, which);
|
||||
|
||||
if (tcpReceived != 0 || tcpSent != 0) {
|
||||
pw.println(prefix + " Network: " + tcpReceived + " bytes received, "
|
||||
+ tcpSent + " bytes sent");
|
||||
pw.println(prefix + " Network: " + formatBytesLocked(tcpReceived) + " received, "
|
||||
+ formatBytesLocked(tcpSent) + " sent");
|
||||
}
|
||||
if (fullWifiLockOnTime != 0 || scanWifiLockOnTime != 0) {
|
||||
|
||||
if (u.hasUserActivity()) {
|
||||
boolean hasData = false;
|
||||
for (int i=0; i<NUM_SCREEN_BRIGHTNESS_BINS; i++) {
|
||||
int val = u.getUserActivityCount(i, which);
|
||||
if (val != 0) {
|
||||
if (!hasData) {
|
||||
sb.setLength(0);
|
||||
sb.append(" User activity: ");
|
||||
hasData = true;
|
||||
} else {
|
||||
sb.append(", ");
|
||||
}
|
||||
sb.append(val);
|
||||
sb.append(" ");
|
||||
sb.append(Uid.USER_ACTIVITY_TYPES[i]);
|
||||
}
|
||||
}
|
||||
if (hasData) {
|
||||
pw.println(sb.toString());
|
||||
}
|
||||
}
|
||||
|
||||
if (fullWifiLockOnTime != 0 || scanWifiLockOnTime != 0
|
||||
|| wifiTurnedOnTime != 0) {
|
||||
pw.println(prefix + " Turned Wifi On Time: "
|
||||
+ formatTimeMs(wifiTurnedOnTime / 1000)
|
||||
+ "(" + formatRatioLocked(wifiTurnedOnTime,
|
||||
whichBatteryRealtime)+ ")");
|
||||
pw.println(prefix + " Full Wifi Lock Time: "
|
||||
+ formatTimeMs(fullWifiLockOnTime / 1000)
|
||||
+ "(" + formatRatioLocked(fullWifiLockOnTime,
|
||||
|
||||
@@ -18,6 +18,8 @@ package android.os;
|
||||
|
||||
/** @hide */
|
||||
public interface LocalPowerManager {
|
||||
// Note: be sure to update BatteryStats if adding or modifying event constants.
|
||||
|
||||
public static final int OTHER_EVENT = 0;
|
||||
public static final int CHEEK_EVENT = 1;
|
||||
public static final int TOUCH_EVENT = 2; // touch events are TOUCH for 300ms, and then either
|
||||
|
||||
@@ -24,6 +24,7 @@
|
||||
|
||||
package android.server;
|
||||
|
||||
import android.bluetooth.BluetoothClass;
|
||||
import android.bluetooth.BluetoothDevice;
|
||||
import android.bluetooth.BluetoothError;
|
||||
import android.bluetooth.BluetoothHeadset;
|
||||
@@ -970,8 +971,8 @@ public class BluetoothDeviceService extends IBluetoothDevice.Stub {
|
||||
*/
|
||||
public synchronized int getRemoteClass(String address) {
|
||||
if (!BluetoothDevice.checkBluetoothAddress(address)) {
|
||||
mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
|
||||
return -1;
|
||||
mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
|
||||
return BluetoothClass.ERROR;
|
||||
}
|
||||
return getRemoteClassNative(address);
|
||||
}
|
||||
@@ -1254,4 +1255,3 @@ public class BluetoothDeviceService extends IBluetoothDevice.Stub {
|
||||
Log.d(TAG, msg);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -618,7 +618,9 @@ extends Layout
|
||||
* - is class HY: a breakpoint
|
||||
* except when followed by a digit.
|
||||
*
|
||||
* Ideographs are class ID: breakpoints when adjacent.
|
||||
* Ideographs are class ID: breakpoints when adjacent,
|
||||
* except for NS (non-starters), which can be broken
|
||||
* after but not before.
|
||||
*/
|
||||
|
||||
if (c == ' ' || c == '\t' ||
|
||||
@@ -627,8 +629,8 @@ extends Layout
|
||||
(j + 1 >= 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') {
|
||||
|
||||
@@ -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");
|
||||
};
|
||||
|
||||
86
core/java/android/util/FinitePool.java
Normal file
86
core/java/android/util/FinitePool.java
Normal file
@@ -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<T extends Poolable<T>> implements Pool<T> {
|
||||
/**
|
||||
* Factory used to create new pool objects
|
||||
*/
|
||||
private final PoolableManager<T> 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<T> manager) {
|
||||
mManager = manager;
|
||||
mLimit = 0;
|
||||
mInfinite = true;
|
||||
}
|
||||
|
||||
FinitePool(PoolableManager<T> 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);
|
||||
}
|
||||
}
|
||||
25
core/java/android/util/Pool.java
Normal file
25
core/java/android/util/Pool.java
Normal file
@@ -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<T extends Poolable<T>> {
|
||||
public abstract T acquire();
|
||||
public abstract void release(T element);
|
||||
}
|
||||
41
core/java/android/util/PoolFactory.java
Normal file
41
core/java/android/util/PoolFactory.java
Normal file
@@ -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 <T extends Poolable<T>> Pool<T> simplePool(PoolableManager<T> manager) {
|
||||
return new FinitePool<T>(manager);
|
||||
}
|
||||
|
||||
public static <T extends Poolable<T>> Pool<T> finitePool(PoolableManager<T> manager, int limit) {
|
||||
return new FinitePool<T>(manager, limit);
|
||||
}
|
||||
|
||||
public static <T extends Poolable<T>> Pool<T> synchronizedPool(Pool<T> pool) {
|
||||
return new SynchronizedPool<T>(pool);
|
||||
}
|
||||
|
||||
public static <T extends Poolable<T>> Pool<T> synchronizedPool(Pool<T> pool, Object lock) {
|
||||
return new SynchronizedPool<T>(pool, lock);
|
||||
}
|
||||
}
|
||||
25
core/java/android/util/Poolable.java
Normal file
25
core/java/android/util/Poolable.java
Normal file
@@ -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<T> {
|
||||
void setNextPoolable(T element);
|
||||
T getNextPoolable();
|
||||
}
|
||||
27
core/java/android/util/PoolableManager.java
Normal file
27
core/java/android/util/PoolableManager.java
Normal file
@@ -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 extends Poolable<T>> {
|
||||
T newInstance();
|
||||
|
||||
void onAcquired(T element);
|
||||
void onReleased(T element);
|
||||
}
|
||||
48
core/java/android/util/SynchronizedPool.java
Normal file
48
core/java/android/util/SynchronizedPool.java
Normal file
@@ -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<T extends Poolable<T>> implements Pool<T> {
|
||||
private final Pool<T> mPool;
|
||||
private final Object mLock;
|
||||
|
||||
public SynchronizedPool(Pool<T> pool) {
|
||||
mPool = pool;
|
||||
mLock = this;
|
||||
}
|
||||
|
||||
public SynchronizedPool(Pool<T> 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);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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<VelocityTracker> {
|
||||
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<VelocityTracker> sPool = PoolFactory.synchronizedPool(
|
||||
PoolFactory.finitePool(new PoolableManager<VelocityTracker>() {
|
||||
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() {
|
||||
}
|
||||
|
||||
|
||||
@@ -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<InvalidateInfo> {
|
||||
private static final int POOL_LIMIT = 10;
|
||||
private static final Object sLock = new Object();
|
||||
private static final Pool<InvalidateInfo> sPool = PoolFactory.synchronizedPool(
|
||||
PoolFactory.finitePool(new PoolableManager<InvalidateInfo>() {
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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() <em>must</em> 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.
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
/**
|
||||
* <p>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
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user