Merge "heads up notifications, v0.1"
diff --git a/api/current.txt b/api/current.txt
index 80952e3..3318e06 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -35600,6 +35600,7 @@
method public int getResponseCode() throws java.io.IOException;
method public java.lang.String getResponseMessage() throws java.io.IOException;
method public void setChunkedStreamingMode(int);
+ method public void setFixedLengthStreamingMode(long);
method public void setFixedLengthStreamingMode(int);
method public static void setFollowRedirects(boolean);
method public void setInstanceFollowRedirects(boolean);
@@ -35643,6 +35644,7 @@
field public static final int HTTP_VERSION = 505; // 0x1f9
field protected int chunkLength;
field protected int fixedContentLength;
+ field protected long fixedContentLengthLong;
field protected boolean instanceFollowRedirects;
field protected java.lang.String method;
field protected int responseCode;
diff --git a/core/java/android/content/pm/PackageParser.java b/core/java/android/content/pm/PackageParser.java
index 8f0c62d..810a521 100644
--- a/core/java/android/content/pm/PackageParser.java
+++ b/core/java/android/content/pm/PackageParser.java
@@ -1569,7 +1569,7 @@
currentKey = parsePublicKey(encodedKey);
definedKeySets.put(currentKey, new HashSet<String>());
sa.recycle();
- } else if (tagname.equals("keyset")) {
+ } else if (tagname.equals("keyset")) {
final TypedArray sa = res.obtainAttributes(attrs,
com.android.internal.R.styleable.KeySet);
final String name = sa.getNonResourceString(
diff --git a/core/java/android/hardware/Sensor.java b/core/java/android/hardware/Sensor.java
index 5cc1150..c3e9cb7 100644
--- a/core/java/android/hardware/Sensor.java
+++ b/core/java/android/hardware/Sensor.java
@@ -204,37 +204,71 @@
// TODO(): The following arrays are fragile and error-prone. This needs to be refactored.
// Note: This needs to be updated, whenever a new sensor is added.
- private static int[] sSensorReportingModes = {
- REPORTING_MODE_CONTINUOUS, REPORTING_MODE_CONTINUOUS, REPORTING_MODE_CONTINUOUS,
- REPORTING_MODE_CONTINUOUS, REPORTING_MODE_ON_CHANGE, REPORTING_MODE_CONTINUOUS,
- REPORTING_MODE_ON_CHANGE, REPORTING_MODE_ON_CHANGE, REPORTING_MODE_CONTINUOUS,
- REPORTING_MODE_CONTINUOUS, REPORTING_MODE_CONTINUOUS, REPORTING_MODE_ON_CHANGE,
- REPORTING_MODE_ON_CHANGE, REPORTING_MODE_CONTINUOUS, REPORTING_MODE_CONTINUOUS,
- REPORTING_MODE_CONTINUOUS, REPORTING_MODE_ONE_SHOT };
-
- // Note: This needs to be updated, whenever a new sensor is added.
- // Holds the maximum length of the values array associated with {@link SensorEvent} or
- // {@link TriggerEvent} for the Sensor
- private static int[] sMaxLengthValuesArray = {
- 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 5, 3, 3,
- 6, 4, 6, 1 };
+ // Holds the reporting mode and maximum length of the values array
+ // associated with
+ // {@link SensorEvent} or {@link TriggerEvent} for the Sensor
+ private static final int[] sSensorReportingModes = {
+ 0, 0, // padding because sensor types start at 1
+ REPORTING_MODE_CONTINUOUS, 3, // SENSOR_TYPE_ACCELEROMETER
+ REPORTING_MODE_CONTINUOUS, 3, // SENSOR_TYPE_GEOMAGNETIC_FIELD
+ REPORTING_MODE_CONTINUOUS, 3, // SENSOR_TYPE_ORIENTATION
+ REPORTING_MODE_CONTINUOUS, 3, // SENSOR_TYPE_GYROSCOPE
+ REPORTING_MODE_ON_CHANGE, 3, // SENSOR_TYPE_LIGHT
+ REPORTING_MODE_CONTINUOUS, 3, // SENSOR_TYPE_PRESSURE
+ REPORTING_MODE_ON_CHANGE, 3, // SENSOR_TYPE_TEMPERATURE
+ REPORTING_MODE_ON_CHANGE, 3, // SENSOR_TYPE_PROXIMITY
+ REPORTING_MODE_CONTINUOUS, 3, // SENSOR_TYPE_GRAVITY
+ REPORTING_MODE_CONTINUOUS, 3, // SENSOR_TYPE_LINEAR_ACCELERATION
+ REPORTING_MODE_CONTINUOUS, 5, // SENSOR_TYPE_ROTATION_VECTOR
+ REPORTING_MODE_ON_CHANGE, 3, // SENSOR_TYPE_RELATIVE_HUMIDITY
+ REPORTING_MODE_ON_CHANGE, 3, // SENSOR_TYPE_AMBIENT_TEMPERATURE
+ REPORTING_MODE_CONTINUOUS, 6, // SENSOR_TYPE_MAGNETIC_FIELD_UNCALIBRATED
+ REPORTING_MODE_CONTINUOUS, 4, // SENSOR_TYPE_GAME_ROTATION_VECTOR
+ REPORTING_MODE_CONTINUOUS, 6, // SENSOR_TYPE_GYROSCOPE_UNCALIBRATED
+ REPORTING_MODE_ONE_SHOT, 1, // SENSOR_TYPE_SIGNIFICANT_MOTION
+ // added post 4.3
+ REPORTING_MODE_ON_CHANGE, 1, // SENSOR_TYPE_STEP_DETECTOR
+ REPORTING_MODE_ON_CHANGE, 1, // SENSOR_TYPE_STEP_COUNTER
+ REPORTING_MODE_CONTINUOUS, 5 // SENSOR_TYPE_GEOMAGNETIC_ROTATION_VECTOR
+ };
static int getReportingMode(Sensor sensor) {
- // mType starts from offset 1.
- return sSensorReportingModes[sensor.mType - 1];
+ int offset = sensor.mType * 2;
+ if (offset >= sSensorReportingModes.length) {
+ // we don't know about this sensor, so this is probably a
+ // vendor-defined sensor, in that case, we figure out the reporting
+ // mode from the sensor meta-data.
+ int minDelay = sensor.mMinDelay;
+ if (minDelay == 0) {
+ return REPORTING_MODE_ON_CHANGE;
+ } else if (minDelay < 0) {
+ return REPORTING_MODE_ONE_SHOT;
+ } else {
+ return REPORTING_MODE_CONTINUOUS;
+ }
+ }
+ return sSensorReportingModes[offset];
}
static int getMaxLengthValuesArray(Sensor sensor, int sdkLevel) {
- // mType starts from offset 1.
- int len = sMaxLengthValuesArray[sensor.mType - 1];
-
+ int type = sensor.mType;
// RotationVector length has changed to 3 to 5 for API level 18
// Set it to 3 for backward compatibility.
- if (sensor.getType() == Sensor.TYPE_ROTATION_VECTOR &&
+ if (type == Sensor.TYPE_ROTATION_VECTOR &&
sdkLevel <= Build.VERSION_CODES.JELLY_BEAN_MR1) {
- len = 3;
+ return 3;
}
- return len;
+ int offset = type * 2 + 1;
+ if (offset >= sSensorReportingModes.length) {
+ // we don't know about this sensor, so this is probably a
+ // vendor-defined sensor, in that case, we don't know how many value
+ // it has
+ // so we return the maximum and assume the app will know.
+ // FIXME: sensor HAL should advertise how much data is returned per
+ // sensor
+ return 16;
+ }
+ return sSensorReportingModes[offset];
}
/* Some of these fields are set only by the native bindings in
diff --git a/core/java/android/os/BatteryStats.java b/core/java/android/os/BatteryStats.java
index 8e0935d..12646bd 100644
--- a/core/java/android/os/BatteryStats.java
+++ b/core/java/android/os/BatteryStats.java
@@ -1803,8 +1803,8 @@
for (int i=0; i<timers.size(); i++) {
TimerEntry timer = timers.get(i);
sb.setLength(0);
- sb.append(" Wake lock #");
- sb.append(timer.mId);
+ sb.append(" Wake lock ");
+ UserHandle.formatUid(sb, timer.mId);
sb.append(" ");
sb.append(timer.mName);
printWakeLock(sb, timer.mTimer, batteryRealtime, null, which, ": ");
@@ -1822,8 +1822,11 @@
}
Uid u = uidStats.valueAt(iu);
-
- pw.println(prefix + " #" + uid + ":");
+
+ pw.print(prefix);
+ pw.print(" ");
+ UserHandle.formatUid(pw, uid);
+ pw.println(":");
boolean uidActivity = false;
long mobileRxBytes = u.getNetworkActivityCount(NETWORK_MOBILE_RX_BYTES, which);
diff --git a/core/java/android/os/UserHandle.java b/core/java/android/os/UserHandle.java
index d205253..6e693a4 100644
--- a/core/java/android/os/UserHandle.java
+++ b/core/java/android/os/UserHandle.java
@@ -168,8 +168,11 @@
if (appId >= Process.FIRST_ISOLATED_UID && appId <= Process.LAST_ISOLATED_UID) {
sb.append('i');
sb.append(appId - Process.FIRST_ISOLATED_UID);
- } else {
+ } else if (appId >= Process.FIRST_APPLICATION_UID) {
sb.append('a');
+ sb.append(appId - Process.FIRST_APPLICATION_UID);
+ } else {
+ sb.append('s');
sb.append(appId);
}
}
@@ -190,8 +193,11 @@
if (appId >= Process.FIRST_ISOLATED_UID && appId <= Process.LAST_ISOLATED_UID) {
pw.print('i');
pw.print(appId - Process.FIRST_ISOLATED_UID);
- } else {
+ } else if (appId >= Process.FIRST_APPLICATION_UID) {
pw.print('a');
+ pw.print(appId - Process.FIRST_APPLICATION_UID);
+ } else {
+ pw.print('s');
pw.print(appId);
}
}
diff --git a/core/java/android/view/GLES20Canvas.java b/core/java/android/view/GLES20Canvas.java
index a441c39..4adee14 100644
--- a/core/java/android/view/GLES20Canvas.java
+++ b/core/java/android/view/GLES20Canvas.java
@@ -781,7 +781,7 @@
int modifier = paint != null ? setupColorFilter(paint) : MODIFIER_NONE;
try {
final int nativePaint = paint == null ? 0 : paint.mNativePaint;
- nDrawPatch(mRenderer, bitmap.mNativeBitmap, patch.mNativeChunk,
+ nDrawPatch(mRenderer, bitmap.mNativeBitmap, bitmap.mBuffer, patch.mNativeChunk,
dst.left, dst.top, dst.right, dst.bottom, nativePaint);
} finally {
if (modifier != MODIFIER_NONE) nResetModifiers(mRenderer, modifier);
@@ -796,14 +796,14 @@
int modifier = paint != null ? setupColorFilter(paint) : MODIFIER_NONE;
try {
final int nativePaint = paint == null ? 0 : paint.mNativePaint;
- nDrawPatch(mRenderer, bitmap.mNativeBitmap, patch.mNativeChunk,
+ nDrawPatch(mRenderer, bitmap.mNativeBitmap, bitmap.mBuffer, patch.mNativeChunk,
dst.left, dst.top, dst.right, dst.bottom, nativePaint);
} finally {
if (modifier != MODIFIER_NONE) nResetModifiers(mRenderer, modifier);
}
}
- private static native void nDrawPatch(int renderer, int bitmap, int chunk,
+ private static native void nDrawPatch(int renderer, int bitmap, byte[] buffer, int chunk,
float left, float top, float right, float bottom, int paint);
@Override
@@ -813,13 +813,13 @@
int modifiers = paint != null ? setupModifiers(bitmap, paint) : MODIFIER_NONE;
try {
final int nativePaint = paint == null ? 0 : paint.mNativePaint;
- nDrawBitmap(mRenderer, bitmap.mNativeBitmap, left, top, nativePaint);
+ nDrawBitmap(mRenderer, bitmap.mNativeBitmap, bitmap.mBuffer, left, top, nativePaint);
} finally {
if (modifiers != MODIFIER_NONE) nResetModifiers(mRenderer, modifiers);
}
}
- private static native void nDrawBitmap(int renderer, int bitmap,
+ private static native void nDrawBitmap(int renderer, int bitmap, byte[] buffer,
float left, float top, int paint);
@Override
@@ -829,13 +829,15 @@
int modifiers = paint != null ? setupModifiers(bitmap, paint) : MODIFIER_NONE;
try {
final int nativePaint = paint == null ? 0 : paint.mNativePaint;
- nDrawBitmap(mRenderer, bitmap.mNativeBitmap, matrix.native_instance, nativePaint);
+ nDrawBitmap(mRenderer, bitmap.mNativeBitmap, bitmap.mBuffer,
+ matrix.native_instance, nativePaint);
} finally {
if (modifiers != MODIFIER_NONE) nResetModifiers(mRenderer, modifiers);
}
}
- private static native void nDrawBitmap(int renderer, int bitmap, int matrix, int paint);
+ private static native void nDrawBitmap(int renderer, int bitmap, byte[] buffer,
+ int matrix, int paint);
@Override
public void drawBitmap(Bitmap bitmap, Rect src, Rect dst, Paint paint) {
@@ -857,7 +859,7 @@
bottom = src.bottom;
}
- nDrawBitmap(mRenderer, bitmap.mNativeBitmap, left, top, right, bottom,
+ nDrawBitmap(mRenderer, bitmap.mNativeBitmap, bitmap.mBuffer, left, top, right, bottom,
dst.left, dst.top, dst.right, dst.bottom, nativePaint);
} finally {
if (modifiers != MODIFIER_NONE) nResetModifiers(mRenderer, modifiers);
@@ -884,14 +886,14 @@
bottom = src.bottom;
}
- nDrawBitmap(mRenderer, bitmap.mNativeBitmap, left, top, right, bottom,
+ nDrawBitmap(mRenderer, bitmap.mNativeBitmap, bitmap.mBuffer, left, top, right, bottom,
dst.left, dst.top, dst.right, dst.bottom, nativePaint);
} finally {
if (modifiers != MODIFIER_NONE) nResetModifiers(mRenderer, modifiers);
}
}
- private static native void nDrawBitmap(int renderer, int bitmap,
+ private static native void nDrawBitmap(int renderer, int bitmap, byte[] buffer,
float srcLeft, float srcTop, float srcRight, float srcBottom,
float left, float top, float right, float bottom, int paint);
@@ -960,15 +962,15 @@
int modifiers = paint != null ? setupModifiers(bitmap, paint) : MODIFIER_NONE;
try {
- final int nativePaint = paint == null ? 0 : paint.mNativePaint;
- nDrawBitmapMesh(mRenderer, bitmap.mNativeBitmap, meshWidth, meshHeight,
+ final int nativePaint = paint == null ? 0 : paint.mNativePaint;
+ nDrawBitmapMesh(mRenderer, bitmap.mNativeBitmap, bitmap.mBuffer, meshWidth, meshHeight,
verts, vertOffset, colors, colorOffset, nativePaint);
} finally {
if (modifiers != MODIFIER_NONE) nResetModifiers(mRenderer, modifiers);
}
}
- private static native void nDrawBitmapMesh(int renderer, int bitmap,
+ private static native void nDrawBitmapMesh(int renderer, int bitmap, byte[] buffer,
int meshWidth, int meshHeight, float[] verts, int vertOffset,
int[] colors, int colorOffset, int paint);
diff --git a/core/java/android/widget/FastScroller.java b/core/java/android/widget/FastScroller.java
index d452f58..594b130 100644
--- a/core/java/android/widget/FastScroller.java
+++ b/core/java/android/widget/FastScroller.java
@@ -1037,7 +1037,12 @@
final int sectionCount = mSections.length;
final int positionsInSection;
if (section < sectionCount - 1) {
- final int nextSectionPos = mSectionIndexer.getPositionForSection(section + 1);
+ final int nextSectionPos;
+ if (section + 1 < sectionCount) {
+ nextSectionPos = mSectionIndexer.getPositionForSection(section + 1);
+ } else {
+ nextSectionPos = totalItemCount - 1;
+ }
positionsInSection = nextSectionPos - sectionPos;
} else {
positionsInSection = totalItemCount - sectionPos;
diff --git a/core/java/android/widget/SectionIndexer.java b/core/java/android/widget/SectionIndexer.java
index 24f894c..a1c71f4 100644
--- a/core/java/android/widget/SectionIndexer.java
+++ b/core/java/android/widget/SectionIndexer.java
@@ -20,7 +20,9 @@
* Interface that should be implemented on Adapters to enable fast scrolling
* in an {@link AbsListView} between sections of the list. A section is a group of list items
* to jump to that have something in common. For example, they may begin with the
- * same letter or they may be songs from the same artist.
+ * same letter or they may be songs from the same artist. ExpandableListAdapters that
+ * consider groups and sections as synonymous should account for collapsed groups and return
+ * an appropriate section/position.
*/
public interface SectionIndexer {
/**
diff --git a/core/java/com/android/internal/app/AlertController.java b/core/java/com/android/internal/app/AlertController.java
index 43a02cf..fe532b0 100644
--- a/core/java/com/android/internal/app/AlertController.java
+++ b/core/java/com/android/internal/app/AlertController.java
@@ -572,7 +572,7 @@
if (whichButtons == BIT_BUTTON_POSITIVE) {
centerButton(mButtonPositive);
} else if (whichButtons == BIT_BUTTON_NEGATIVE) {
- centerButton(mButtonNeutral);
+ centerButton(mButtonNegative);
} else if (whichButtons == BIT_BUTTON_NEUTRAL) {
centerButton(mButtonNeutral);
}
diff --git a/core/java/com/android/internal/inputmethod/InputMethodUtils.java b/core/java/com/android/internal/inputmethod/InputMethodUtils.java
index 4e21324..78389c5 100644
--- a/core/java/com/android/internal/inputmethod/InputMethodUtils.java
+++ b/core/java/com/android/internal/inputmethod/InputMethodUtils.java
@@ -432,6 +432,17 @@
}
}
+ public static CharSequence getImeAndSubtypeDisplayName(Context context, InputMethodInfo imi,
+ InputMethodSubtype subtype) {
+ final CharSequence imiLabel = imi.loadLabel(context.getPackageManager());
+ return subtype != null
+ ? TextUtils.concat(subtype.getDisplayName(context,
+ imi.getPackageName(), imi.getServiceInfo().applicationInfo),
+ (TextUtils.isEmpty(imiLabel) ?
+ "" : " - " + imiLabel))
+ : imiLabel;
+ }
+
/**
* Utility class for putting and getting settings for InputMethod
* TODO: Move all putters and getters of settings to this class.
diff --git a/core/jni/android_hardware_SensorManager.cpp b/core/jni/android_hardware_SensorManager.cpp
index 6374494..ae0113b 100644
--- a/core/jni/android_hardware_SensorManager.cpp
+++ b/core/jni/android_hardware_SensorManager.cpp
@@ -142,7 +142,13 @@
while ((n = q->read(buffer, 16)) > 0) {
for (int i=0 ; i<n ; i++) {
- env->SetFloatArrayRegion(mScratch, 0, 16, buffer[i].data);
+ if (buffer[i].type == SENSOR_TYPE_STEP_COUNTER) {
+ // step-counter returns a uint64, but the java API only deals with floats
+ float value = float(buffer[i].u64.step_counter);
+ env->SetFloatArrayRegion(mScratch, 0, 1, &value);
+ } else {
+ env->SetFloatArrayRegion(mScratch, 0, 16, buffer[i].data);
+ }
env->CallVoidMethod(mReceiverObject,
gBaseEventQueueClassInfo.dispatchSensorEvent,
diff --git a/core/jni/android_view_GLES20Canvas.cpp b/core/jni/android_view_GLES20Canvas.cpp
index 87ebbd2..70a4daa 100644
--- a/core/jni/android_view_GLES20Canvas.cpp
+++ b/core/jni/android_view_GLES20Canvas.cpp
@@ -377,20 +377,31 @@
// ----------------------------------------------------------------------------
static void android_view_GLES20Canvas_drawBitmap(JNIEnv* env, jobject clazz,
- OpenGLRenderer* renderer, SkBitmap* bitmap, jfloat left, jfloat top, SkPaint* paint) {
+ OpenGLRenderer* renderer, SkBitmap* bitmap, jbyteArray buffer,
+ jfloat left, jfloat top, SkPaint* paint) {
+ // This object allows the renderer to allocate a global JNI ref to the buffer object.
+ JavaHeapBitmapRef bitmapRef(env, bitmap, buffer);
+
renderer->drawBitmap(bitmap, left, top, paint);
}
static void android_view_GLES20Canvas_drawBitmapRect(JNIEnv* env, jobject clazz,
- OpenGLRenderer* renderer, SkBitmap* bitmap,
+ OpenGLRenderer* renderer, SkBitmap* bitmap, jbyteArray buffer,
float srcLeft, float srcTop, float srcRight, float srcBottom,
float dstLeft, float dstTop, float dstRight, float dstBottom, SkPaint* paint) {
+ // This object allows the renderer to allocate a global JNI ref to the buffer object.
+ JavaHeapBitmapRef bitmapRef(env, bitmap, buffer);
+
renderer->drawBitmap(bitmap, srcLeft, srcTop, srcRight, srcBottom,
dstLeft, dstTop, dstRight, dstBottom, paint);
}
static void android_view_GLES20Canvas_drawBitmapMatrix(JNIEnv* env, jobject clazz,
- OpenGLRenderer* renderer, SkBitmap* bitmap, SkMatrix* matrix, SkPaint* paint) {
+ OpenGLRenderer* renderer, SkBitmap* bitmap, jbyteArray buffer,
+ SkMatrix* matrix, SkPaint* paint) {
+ // This object allows the renderer to allocate a global JNI ref to the buffer object.
+ JavaHeapBitmapRef bitmapRef(env, bitmap, buffer);
+
renderer->drawBitmap(bitmap, matrix, paint);
}
@@ -420,8 +431,12 @@
}
static void android_view_GLES20Canvas_drawBitmapMesh(JNIEnv* env, jobject clazz,
- OpenGLRenderer* renderer, SkBitmap* bitmap, jint meshWidth, jint meshHeight,
- jfloatArray vertices, jint offset, jintArray colors, jint colorOffset, SkPaint* paint) {
+ OpenGLRenderer* renderer, SkBitmap* bitmap, jbyteArray buffer,
+ jint meshWidth, jint meshHeight, jfloatArray vertices, jint offset, jintArray colors,
+ jint colorOffset, SkPaint* paint) {
+ // This object allows the renderer to allocate a global JNI ref to the buffer object.
+ JavaHeapBitmapRef bitmapRef(env, bitmap, buffer);
+
jfloat* verticesArray = vertices ? env->GetFloatArrayElements(vertices, NULL) + offset : NULL;
jint* colorsArray = colors ? env->GetIntArrayElements(colors, NULL) + colorOffset : NULL;
@@ -432,8 +447,11 @@
}
static void android_view_GLES20Canvas_drawPatch(JNIEnv* env, jobject clazz,
- OpenGLRenderer* renderer, SkBitmap* bitmap, Res_png_9patch* patch,
+ OpenGLRenderer* renderer, SkBitmap* bitmap, jbyteArray buffer, Res_png_9patch* patch,
float left, float top, float right, float bottom, SkPaint* paint) {
+ // This object allows the renderer to allocate a global JNI ref to the buffer object.
+ JavaHeapBitmapRef bitmapRef(env, bitmap, buffer);
+
renderer->drawPatch(bitmap, patch, left, top, right, bottom, paint);
}
@@ -1018,14 +1036,14 @@
{ "nGetMatrix", "(II)V", (void*) android_view_GLES20Canvas_getMatrix },
{ "nConcatMatrix", "(II)V", (void*) android_view_GLES20Canvas_concatMatrix },
- { "nDrawBitmap", "(IIFFI)V", (void*) android_view_GLES20Canvas_drawBitmap },
- { "nDrawBitmap", "(IIFFFFFFFFI)V", (void*) android_view_GLES20Canvas_drawBitmapRect },
- { "nDrawBitmap", "(IIII)V", (void*) android_view_GLES20Canvas_drawBitmapMatrix },
+ { "nDrawBitmap", "(II[BFFI)V", (void*) android_view_GLES20Canvas_drawBitmap },
+ { "nDrawBitmap", "(II[BFFFFFFFFI)V",(void*) android_view_GLES20Canvas_drawBitmapRect },
+ { "nDrawBitmap", "(II[BII)V", (void*) android_view_GLES20Canvas_drawBitmapMatrix },
{ "nDrawBitmap", "(I[IIIFFIIZI)V", (void*) android_view_GLES20Canvas_drawBitmapData },
- { "nDrawBitmapMesh", "(IIII[FI[III)V", (void*) android_view_GLES20Canvas_drawBitmapMesh },
+ { "nDrawBitmapMesh", "(II[BII[FI[III)V",(void*) android_view_GLES20Canvas_drawBitmapMesh },
- { "nDrawPatch", "(IIIFFFFI)V", (void*) android_view_GLES20Canvas_drawPatch },
+ { "nDrawPatch", "(II[BIFFFFI)V", (void*) android_view_GLES20Canvas_drawPatch },
{ "nDrawColor", "(III)V", (void*) android_view_GLES20Canvas_drawColor },
{ "nDrawRect", "(IFFFFI)V", (void*) android_view_GLES20Canvas_drawRect },
diff --git a/docs/html/about/dashboards/index.jd b/docs/html/about/dashboards/index.jd
index 43eead9..880d7e9 100644
--- a/docs/html/about/dashboards/index.jd
+++ b/docs/html/about/dashboards/index.jd
@@ -57,7 +57,7 @@
</div>
-<p style="clear:both"><em>Data collected during a 14-day period ending on June 3, 2013.
+<p style="clear:both"><em>Data collected during a 14-day period ending on July 8, 2013.
<br/>Any versions with less than 0.1% distribution are not shown.</em>
</p>
@@ -83,7 +83,7 @@
</div>
-<p style="clear:both"><em>Data collected during a 14-day period ending on June 3, 2013
+<p style="clear:both"><em>Data collected during a 14-day period ending on July 8, 2013
<br/>Any screen configurations with less than 0.1% distribution are not shown.</em></p>
@@ -130,7 +130,7 @@
-<p style="clear:both"><em>Data collected during a 14-day period ending on June 3, 2013</em></p>
+<p style="clear:both"><em>Data collected during a 14-day period ending on July 8, 2013</em></p>
@@ -148,7 +148,7 @@
var VERSION_DATA =
[
{
- "chart": "//chart.googleapis.com/chart?chl=Eclair%7CFroyo%7CGingerbread%7CHoneycomb%7CIce%20Cream%20Sandwich%7CJelly%20Bean&chd=t%3A1.6%2C3.2%2C36.5%2C0.1%2C25.6%2C33.0&chf=bg%2Cs%2C00000000&chco=c4df9b%2C6fad0c&cht=p&chs=500x250",
+ "chart": "//chart.googleapis.com/chart?chl=Eclair%7CFroyo%7CGingerbread%7CHoneycomb%7CIce%20Cream%20Sandwich%7CJelly%20Bean&chco=c4df9b%2C6fad0c&chd=t%3A1.5%2C3.1%2C34.1%2C0.1%2C23.3%2C37.9&chf=bg%2Cs%2C00000000&chs=500x250&cht=p",
"data": [
{
"api": 4,
@@ -158,22 +158,17 @@
{
"api": 7,
"name": "Eclair",
- "perc": "1.5"
+ "perc": "1.4"
},
{
"api": 8,
"name": "Froyo",
- "perc": "3.2"
- },
- {
- "api": 9,
- "name": "Gingerbread",
- "perc": "0.1"
+ "perc": "3.1"
},
{
"api": 10,
"name": "Gingerbread",
- "perc": "36.4"
+ "perc": "34.1"
},
{
"api": 13,
@@ -183,17 +178,17 @@
{
"api": 15,
"name": "Ice Cream Sandwich",
- "perc": "25.6"
+ "perc": "23.3"
},
{
"api": 16,
"name": "Jelly Bean",
- "perc": "29.0"
+ "perc": "32.3"
},
{
"api": 17,
"name": "Jelly Bean",
- "perc": "4.0"
+ "perc": "5.6"
}
]
}
@@ -210,16 +205,16 @@
"Large": {
"hdpi": "0.4",
"ldpi": "0.6",
- "mdpi": "3.0",
+ "mdpi": "3.2",
"tvdpi": "1.0",
- "xhdpi": "0.6"
+ "xhdpi": "0.5"
},
"Normal": {
- "hdpi": "36.0",
+ "hdpi": "34.9",
"ldpi": "0.1",
"mdpi": "16.0",
- "xhdpi": "24.5",
- "xxhdpi": "3.3"
+ "xhdpi": "24.0",
+ "xxhdpi": "4.9"
},
"Small": {
"hdpi": "0.1",
@@ -227,12 +222,12 @@
},
"Xlarge": {
"hdpi": "0.2",
- "mdpi": "4.2",
+ "mdpi": "4.1",
"xhdpi": "0.1"
}
},
- "densitychart": "//chart.googleapis.com/chart?chl=ldpi%7Cmdpi%7Ctvdpi%7Chdpi%7Cxhdpi%7Cxxhdpi&chd=t%3A10.6%2C23.2%2C1.0%2C36.7%2C25.2%2C3.3&chf=bg%2Cs%2C00000000&chco=c4df9b%2C6fad0c&cht=p&chs=400x250",
- "layoutchart": "//chart.googleapis.com/chart?chl=Xlarge%7CLarge%7CNormal%7CSmall&chd=t%3A4.5%2C5.6%2C79.9%2C10.0&chf=bg%2Cs%2C00000000&chco=c4df9b%2C6fad0c&cht=p&chs=400x250"
+ "densitychart": "//chart.googleapis.com/chart?chl=ldpi%7Cmdpi%7Ctvdpi%7Chdpi%7Cxhdpi%7Cxxhdpi&chco=c4df9b%2C6fad0c&chd=t%3A10.7%2C23.3%2C1.0%2C35.6%2C24.6%2C4.9&chf=bg%2Cs%2C00000000&chs=400x250&cht=p",
+ "layoutchart": "//chart.googleapis.com/chart?chl=Xlarge%7CLarge%7CNormal%7CSmall&chco=c4df9b%2C6fad0c&chd=t%3A4.4%2C5.7%2C79.9%2C10.1&chf=bg%2Cs%2C00000000&chs=400x250&cht=p"
}
];
diff --git a/docs/html/distribute/googleplay/quality/tablet.jd b/docs/html/distribute/googleplay/quality/tablet.jd
index 03c180b..5a707be 100644
--- a/docs/html/distribute/googleplay/quality/tablet.jd
+++ b/docs/html/distribute/googleplay/quality/tablet.jd
@@ -25,9 +25,7 @@
</ol>
</div></div>
-<p>Before you publish an app on Google Play, it's important to make sure that
-the app meets the basic expectations of tablet users through compelling features
-and an intuitive, well-designed UI. </p>
+<p>Before you publish an app on Google Play, it's important to make sure that the app meets the basic expectations of tablet users through compelling features and an intuitive, well-designed UI. </p>
<p>Tablets are a growing part of the Android installed base that offers new
opportunities for <a
@@ -258,32 +256,34 @@
<h2 id="use-tablet-icons">4. Use Icons and other assets that are designed
for tablet screens</h2>
-<p>So that your app looks its best, make sure to use icons and other bitmap
-assets that are created specifically for the densities used by tablet screens.
-Specifically, you should create sets of alternative bitmap drawables for each
-density in the range commonly supported by tablets.</p>
+<p>To ensure your app looks its best, provide icons and other bitmap
+assets for each density in the range commonly supported by tablets. Specifically, you should
+design your icons for the action bar, notifications, and launcher according to the
+<a href="{@docRoot}design/style/iconography.html">Iconography</a> guidelines and
+provide them in multiple densities, so they appear at the appropriate size on all screens
+without blurring or other scaling artifacts.</p>
<p class="table-caption"><strong>Table 1</strong>. Raw asset sizes for icon types.<table>
<tr>
-<th>Density </th>
-<th colspa>Launcher</th>
+<th>Density</th>
+<th>Launcher</th>
<th>Action Bar</th>
<th>Small/Contextual</th>
<th>Notification</th>
</tr>
<tr>
<td><code>mdpi</code></td>
-<td>48x48px</td>
-<td>32x32px</td>
-<td>16x16px</td>
-<td>24x24px</td>
+<td>48x48 px</td>
+<td>32x32 px</td>
+<td>16x16 px</td>
+<td>24x24 px</td>
</tr>
<tr>
<td><code>hdpi</code></td>
-<td>72x72px</td>
-<td>48x48px</td>
-<td>24x24px</td>
-<td>36x36px</td>
+<td>72x72 px</td>
+<td>48x48 px</td>
+<td>24x24 px</td>
+<td>36x36 px</td>
</tr>
<tr>
<td><code>tvdpi</code></td>
@@ -294,34 +294,42 @@
</tr>
<tr>
<td><code>xhdpi</code></td>
-<td>96x96px</td>
-<td>64x64px</td>
-<td>32x32px</td>
-<td>48x48px</td>
+<td>96x96 px</td>
+<td>64x64 px</td>
+<td>32x32 px</td>
+<td>48x48 px</td>
+</tr>
+<tr>
+<td><code>xxhdpi</code></td>
+<td>144x144 px</td>
+<td>96x96 px</td>
+<td>48x48 px</td>
+<td>74x74 px</td>
</tr>
</table>
-<p>Other points to consider: </p>
+<p>Your app should supply a version of each icon and bitmap asset that's optimized
+for <strong>at least one</strong> the following common tablet screen densities:</p>
<ul>
-<li>Icons in the action bar, notifications, and launcher should be designed
-according to the icon design guidelines and have the same physical size on
-tablets as on phones.</li>
-<li>Use density-specific <a
-href="{@docRoot}guide/topics/resources/providing-resources.html#AlternativeResources">
-resource qualifiers</a> to ensure that the proper set of alternative resources
-gets loaded.</li>
+ <li><code>hdpi</code></li>
+ <li><code>xhdpi</code></li>
+ <li><code>xxhdpi</code></li>
</ul>
-<p style="margin-bottom:.5em;">At a minimum, your app should supply sets of
- custom drawables and assets for common tablet screen densities,
- tagged with these qualifiers as appropriate:</p>
+<p>Other tips:</p>
<ul>
- <li><code>hdpi</code>, OR</li>
- <li><code>xhdpi</code>, OR</li>
- <li><code>xxhdpi</code></li>
+<li>When possible, use vector shapes for your icon designs so you can scale them
+without loss of detail and edge crispness.</li>
+<li>Use density-specific <a
+href="{@docRoot}guide/topics/resources/providing-resources.html#AlternativeResources">
+resource qualifiers</a> to ensure that the proper icons are loaded for each screen density.</li>
+<li>Tablets and other large screen devices often request a launcher icon that is one density
+size larger than the device's actual density, so you should provide your launcher
+icon at the highest density possible. For example, if a tablet has an {@code xhdpi} screen,
+it will request the {@code xxhdpi} version of the launcher icon.</li>
</ul>
<div class="rel-resources">
@@ -331,8 +339,8 @@
<ul>
<li>
- <a href="{@docRoot}design/style/iconography.html">Iconography</a>— Android
- Design document that shows how to use various types of icons.
+ <a href="{@docRoot}design/style/iconography.html">Iconography</a>—
+ Design guidelines and tips about how to create various types of icons.
</li>
<li>
diff --git a/docs/html/guide/topics/graphics/hardware-accel.jd b/docs/html/guide/topics/graphics/hardware-accel.jd
index 8ba6676..54ef20c 100644
--- a/docs/html/guide/topics/graphics/hardware-accel.jd
+++ b/docs/html/guide/topics/graphics/hardware-accel.jd
@@ -164,7 +164,7 @@
draws views without hardware acceleration as well. The following sections describe the
software-based and hardware-accelerated drawing models.</p>
-<h3>Software-based drawing model</h3>
+<h3 id="software-model">Software-based drawing model</h3>
<p>In the software drawing model, views are drawn with the following two steps:</p>
<ol>
<li>Invalidate the hierarchy</li>
@@ -196,7 +196,7 @@
android.view.View#invalidate invalidate()} when their properties change, such as the background
color or the text in a {@link android.widget.TextView}.</p>
- <h3>Hardware accelerated drawing model</h3>
+ <h3 id="hardware-model">Hardware accelerated drawing model</h3>
<p>The Android system still uses {@link android.view.View#invalidate invalidate()} and {@link
android.view.View#draw draw()} to request screen updates and to render views, but handles the
actual drawing differently. Instead of executing the drawing commands immediately, the Android
diff --git a/docs/html/sdk/installing/studio-tips.jd b/docs/html/sdk/installing/studio-tips.jd
index a686efd..12d2527 100644
--- a/docs/html/sdk/installing/studio-tips.jd
+++ b/docs/html/sdk/installing/studio-tips.jd
@@ -10,6 +10,8 @@
>Eclipse Compatibility Mode</a></li>
<li><a href="http://confluence.jetbrains.com/display/IntelliJIDEA/FAQ+on+Migrating+to+IntelliJ+IDEA" class="external-link"
>FAQ on Migrating</a></li>
+ <li><a href="http://android-developers.blogspot.com/2013/06/adding-backend-to-your-app-in-android.html"
+ class="external-link">Adding a Backend to Your App In Android Studio</a></li>
</ul>
</div>
</div>
diff --git a/graphics/java/android/graphics/Bitmap.java b/graphics/java/android/graphics/Bitmap.java
index 106f4bd..50231da 100644
--- a/graphics/java/android/graphics/Bitmap.java
+++ b/graphics/java/android/graphics/Bitmap.java
@@ -45,9 +45,13 @@
/**
* Backing buffer for the Bitmap.
+ * Made public for quick access from drawing methods -- do NOT modify
+ * from outside this class
+ *
+ * @hide
*/
@SuppressWarnings("UnusedDeclaration") // native code only
- private byte[] mBuffer;
+ public byte[] mBuffer;
@SuppressWarnings({"FieldCanBeLocal", "UnusedDeclaration"}) // Keep to finalize native resources
private final BitmapFinalizer mFinalizer;
diff --git a/libs/hwui/ResourceCache.cpp b/libs/hwui/ResourceCache.cpp
index 58fa21c..3f77021 100644
--- a/libs/hwui/ResourceCache.cpp
+++ b/libs/hwui/ResourceCache.cpp
@@ -62,7 +62,7 @@
}
void ResourceCache::incrementRefcount(SkBitmap* bitmapResource) {
- SkSafeRef(bitmapResource->pixelRef());
+ bitmapResource->pixelRef()->globalRef();
SkSafeRef(bitmapResource->getColorTable());
incrementRefcount((void*) bitmapResource, kBitmap);
}
@@ -100,7 +100,7 @@
}
void ResourceCache::incrementRefcountLocked(SkBitmap* bitmapResource) {
- SkSafeRef(bitmapResource->pixelRef());
+ bitmapResource->pixelRef()->globalRef();
SkSafeRef(bitmapResource->getColorTable());
incrementRefcountLocked((void*) bitmapResource, kBitmap);
}
@@ -133,7 +133,7 @@
}
void ResourceCache::decrementRefcount(SkBitmap* bitmapResource) {
- SkSafeUnref(bitmapResource->pixelRef());
+ bitmapResource->pixelRef()->globalUnref();
SkSafeUnref(bitmapResource->getColorTable());
decrementRefcount((void*) bitmapResource);
}
@@ -174,7 +174,7 @@
}
void ResourceCache::decrementRefcountLocked(SkBitmap* bitmapResource) {
- SkSafeUnref(bitmapResource->pixelRef());
+ bitmapResource->pixelRef()->globalUnref();
SkSafeUnref(bitmapResource->getColorTable());
decrementRefcountLocked((void*) bitmapResource);
}
diff --git a/packages/InputDevices/res/raw/keyboard_layout_english_us_colemak.kcm b/packages/InputDevices/res/raw/keyboard_layout_english_us_colemak.kcm
new file mode 100644
index 0000000..72e6d04
--- /dev/null
+++ b/packages/InputDevices/res/raw/keyboard_layout_english_us_colemak.kcm
@@ -0,0 +1,330 @@
+# Copyright (C) 2012 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.
+
+#
+# English (US), Colemak keyboard layout.
+# Unlike the default (generic) keyboard layout, English (US) does not contain any
+# special ALT characters.
+#
+
+type OVERLAY
+
+map key 18 F
+map key 19 P
+map key 20 G
+map key 21 J
+map key 22 L
+map key 23 U
+map key 24 Y
+map key 25 SEMICOLON
+map key 31 R
+map key 32 S
+map key 33 T
+map key 34 D
+map key 36 N
+map key 37 E
+map key 38 I
+map key 39 O
+map key 49 K
+map key 58 DEL
+
+### ROW 1
+
+key GRAVE {
+ label: '`'
+ base: '`'
+ shift: '~'
+}
+
+key 1 {
+ label: '1'
+ base: '1'
+ shift: '!'
+}
+
+key 2 {
+ label: '2'
+ base: '2'
+ shift: '@'
+}
+
+key 3 {
+ label: '3'
+ base: '3'
+ shift: '#'
+}
+
+key 4 {
+ label: '4'
+ base: '4'
+ shift: '$'
+}
+
+key 5 {
+ label: '5'
+ base: '5'
+ shift: '%'
+}
+
+key 6 {
+ label: '6'
+ base: '6'
+ shift: '^'
+}
+
+key 7 {
+ label: '7'
+ base: '7'
+ shift: '&'
+}
+
+key 8 {
+ label: '8'
+ base: '8'
+ shift: '*'
+}
+
+key 9 {
+ label: '9'
+ base: '9'
+ shift: '('
+}
+
+key 0 {
+ label: '0'
+ base: '0'
+ shift: ')'
+}
+
+key MINUS {
+ label: '-'
+ base: '-'
+ shift: '_'
+}
+
+key EQUALS {
+ label: '='
+ base: '='
+ shift: '+'
+}
+
+### ROW 2
+
+key Q {
+ label: 'Q'
+ base: 'q'
+ shift, capslock: 'Q'
+}
+
+key W {
+ label: 'W'
+ base: 'w'
+ shift, capslock: 'W'
+}
+
+key F {
+ label: 'F'
+ base: 'f'
+ shift, capslock: 'F'
+}
+
+key P {
+ label: 'P'
+ base: 'p'
+ shift, capslock: 'P'
+}
+
+key G {
+ label: 'G'
+ base: 'g'
+ shift, capslock: 'G'
+}
+
+key J {
+ label: 'J'
+ base: 'j'
+ shift, capslock: 'J'
+}
+
+key L {
+ label: 'L'
+ base: 'l'
+ shift, capslock: 'L'
+}
+
+key U {
+ label: 'U'
+ base: 'u'
+ shift, capslock: 'U'
+}
+
+key Y {
+ label: 'Y'
+ base: 'y'
+ shift, capslock: 'Y'
+}
+
+key SEMICOLON {
+ label: ';'
+ base: ';'
+ shift, capslock: ':'
+}
+
+key LEFT_BRACKET {
+ label: '['
+ base: '['
+ shift: '{'
+}
+
+key RIGHT_BRACKET {
+ label: ']'
+ base: ']'
+ shift: '}'
+}
+
+key BACKSLASH {
+ label: '\\'
+ base: '\\'
+ shift: '|'
+}
+
+### ROW 3
+
+key A {
+ label: 'A'
+ base: 'a'
+ shift, capslock: 'A'
+}
+
+key R {
+ label: 'R'
+ base: 'r'
+ shift, capslock: 'R'
+}
+
+key S {
+ label: 'S'
+ base: 's'
+ shift, capslock: 'S'
+}
+
+key T {
+ label: 'T'
+ base: 't'
+ shift, capslock: 'T'
+}
+
+key D {
+ label: 'D'
+ base: 'd'
+ shift, capslock: 'D'
+}
+
+key H {
+ label: 'H'
+ base: 'h'
+ shift, capslock: 'H'
+}
+
+key N {
+ label: 'N'
+ base: 'n'
+ shift, capslock: 'N'
+}
+
+key E {
+ label: 'E'
+ base: 'e'
+ shift, capslock: 'E'
+}
+
+key I {
+ label: 'I'
+ base: 'i'
+ shift, capslock: 'I'
+}
+
+key O {
+ label: 'O'
+ base: 'o'
+ shift: 'O'
+}
+
+key APOSTROPHE {
+ label: '\''
+ base: '\''
+ shift: '"'
+}
+
+### ROW 4
+
+key Z {
+ label: 'Z'
+ base: 'z'
+ shift, capslock: 'Z'
+}
+
+key X {
+ label: 'X'
+ base: 'x'
+ shift, capslock: 'X'
+}
+
+key C {
+ label: 'C'
+ base: 'c'
+ shift, capslock: 'C'
+}
+
+key V {
+ label: 'V'
+ base: 'v'
+ shift, capslock: 'V'
+}
+
+key B {
+ label: 'B'
+ base: 'b'
+ shift, capslock: 'B'
+}
+
+key K {
+ label: 'K'
+ base: 'k'
+ shift, capslock: 'K'
+}
+
+key M {
+ label: 'M'
+ base: 'm'
+ shift, capslock: 'M'
+}
+
+key COMMA {
+ label: ','
+ base: ','
+ shift: '<'
+}
+
+key PERIOD {
+ label: '.'
+ base: '.'
+ shift: '>'
+}
+
+key SLASH {
+ label: '/'
+ base: '/'
+ shift: '?'
+}
diff --git a/packages/InputDevices/res/values/strings.xml b/packages/InputDevices/res/values/strings.xml
index 32c665a..54c18f1 100644
--- a/packages/InputDevices/res/values/strings.xml
+++ b/packages/InputDevices/res/values/strings.xml
@@ -15,6 +15,9 @@
<!-- US English (International style) keyboard layout label. [CHAR LIMIT=35] -->
<string name="keyboard_layout_english_us_intl">English (US), International style</string>
+ <!-- US English (Colemak style) keyboard layout label. [CHAR LIMIT=35] -->
+ <string name="keyboard_layout_english_us_colemak_label">English (US), Colemak style</string>
+
<!-- US English (Dvorak style) keyboard layout label. [CHAR LIMIT=35] -->
<string name="keyboard_layout_english_us_dvorak_label">English (US), Dvorak style</string>
diff --git a/packages/InputDevices/res/xml/keyboard_layouts.xml b/packages/InputDevices/res/xml/keyboard_layouts.xml
index ffd1a23..1f48a36 100644
--- a/packages/InputDevices/res/xml/keyboard_layouts.xml
+++ b/packages/InputDevices/res/xml/keyboard_layouts.xml
@@ -12,6 +12,10 @@
android:label="@string/keyboard_layout_english_us_intl"
android:keyboardLayout="@raw/keyboard_layout_english_us_intl" />
+ <keyboard-layout android:name="keyboard_layout_english_us_colemak"
+ android:label="@string/keyboard_layout_english_us_colemak_label"
+ android:keyboardLayout="@raw/keyboard_layout_english_us_colemak" />
+
<keyboard-layout android:name="keyboard_layout_english_us_dvorak"
android:label="@string/keyboard_layout_english_us_dvorak_label"
android:keyboardLayout="@raw/keyboard_layout_english_us_dvorak" />
diff --git a/packages/Keyguard/src/com/android/keyguard/KeyguardViewManager.java b/packages/Keyguard/src/com/android/keyguard/KeyguardViewManager.java
index a1d11cd..35bea26 100644
--- a/packages/Keyguard/src/com/android/keyguard/KeyguardViewManager.java
+++ b/packages/Keyguard/src/com/android/keyguard/KeyguardViewManager.java
@@ -171,8 +171,6 @@
private void maybeCreateKeyguardLocked(boolean enableScreenRotation, boolean force,
Bundle options) {
- final boolean isActivity = (mContext instanceof Activity); // for test activity
-
if (mKeyguardHost != null) {
mKeyguardHost.saveHierarchyState(mStateContainer);
}
@@ -190,9 +188,6 @@
if (!mNeedsInput) {
flags |= WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM;
}
- if (ActivityManager.isHighEndGfx()) {
- flags |= WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED;
- }
final int stretch = ViewGroup.LayoutParams.MATCH_PARENT;
final int type = WindowManager.LayoutParams.TYPE_KEYGUARD;
@@ -209,11 +204,8 @@
WindowManager.LayoutParams.PRIVATE_FLAG_FORCE_HARDWARE_ACCELERATED;
}
lp.privateFlags |= WindowManager.LayoutParams.PRIVATE_FLAG_SET_NEEDS_MENU_KEY;
- if (isActivity) {
- lp.privateFlags |= WindowManager.LayoutParams.PRIVATE_FLAG_SHOW_FOR_ALL_USERS;
- }
lp.inputFeatures |= WindowManager.LayoutParams.INPUT_FEATURE_DISABLE_USER_ACTIVITY;
- lp.setTitle(isActivity ? "KeyguardMock" : "Keyguard");
+ lp.setTitle("Keyguard");
mWindowLayoutParams = lp;
mViewManager.addView(mKeyguardHost, lp);
}
@@ -233,9 +225,6 @@
if (v != null) {
mKeyguardHost.removeView(v);
}
- // TODO: Remove once b/7094175 is fixed
- if (false) Slog.d(TAG, "inflateKeyguardView: b/7094175 mContext.config="
- + mContext.getResources().getConfiguration());
final LayoutInflater inflater = LayoutInflater.from(mContext);
View view = inflater.inflate(R.layout.keyguard_host_view, mKeyguardHost, true);
mKeyguardView = (KeyguardHostView) view.findViewById(R.id.keyguard_host_view);
diff --git a/services/java/com/android/server/InputMethodManagerService.java b/services/java/com/android/server/InputMethodManagerService.java
index 6e24d68..1c1b002 100644
--- a/services/java/com/android/server/InputMethodManagerService.java
+++ b/services/java/com/android/server/InputMethodManagerService.java
@@ -1511,23 +1511,16 @@
final InputMethodInfo imi = mMethodMap.get(mCurMethodId);
if (imi != null && iconVisibility && needsToShowImeSwitchOngoingNotification()) {
// Used to load label
- final PackageManager pm = mContext.getPackageManager();
final CharSequence title = mRes.getText(
com.android.internal.R.string.select_input_method);
- final CharSequence imiLabel = imi.loadLabel(pm);
- final CharSequence summary = mCurrentSubtype != null
- ? TextUtils.concat(mCurrentSubtype.getDisplayName(mContext,
- imi.getPackageName(), imi.getServiceInfo().applicationInfo),
- (TextUtils.isEmpty(imiLabel) ?
- "" : " - " + imiLabel))
- : imiLabel;
+ final CharSequence summary = InputMethodUtils.getImeAndSubtypeDisplayName(
+ mContext, imi, mCurrentSubtype);
mImeSwitcherNotification.setLatestEventInfo(
mContext, title, summary, mImeSwitchPendingIntent);
if (mNotificationManager != null) {
if (DEBUG) {
- Slog.d(TAG, "--- show notification: label = " + imiLabel
- + ", summary = " + summary);
+ Slog.d(TAG, "--- show notification: label = " + summary);
}
mNotificationManager.notifyAsUser(null,
com.android.internal.R.string.select_input_method,
diff --git a/services/java/com/android/server/am/ActivityManagerService.java b/services/java/com/android/server/am/ActivityManagerService.java
index 0bd0d8e..39ce0c6 100644
--- a/services/java/com/android/server/am/ActivityManagerService.java
+++ b/services/java/com/android/server/am/ActivityManagerService.java
@@ -1795,7 +1795,7 @@
return;
}
- mActivityManagerService.dumpProcessTracker(fd, pw, args);
+ mActivityManagerService.mProcessTracker.dump(fd, pw, args);
}
}
@@ -1821,7 +1821,7 @@
: mBatteryStatsService.getActiveStatistics().getIsOnBattery();
mBatteryStatsService.getActiveStatistics().setCallback(this);
- mProcessTracker = new ProcessTracker(new File(systemDir, "procstats"));
+ mProcessTracker = new ProcessTracker(this, new File(systemDir, "procstats"));
mUsageStatsService = new UsageStatsService(new File(systemDir, "usagestats").toString());
mAppOpsService = new AppOpsService(new File(systemDir, "appops.xml"));
@@ -10186,7 +10186,7 @@
TimeUtils.formatDuration(mLastPowerCheckUptime, pw);
pw.println("");
pw.println(" mGoingToSleep=" + mStackSupervisor.mGoingToSleep);
- pw.println(" mLaunchingActivity=" + getFocusedStack().mLaunchingActivity);
+ pw.println(" mLaunchingActivity=" + mStackSupervisor.mLaunchingActivity);
pw.println(" mAdjSeq=" + mAdjSeq + " mLruSeq=" + mLruSeq);
pw.println(" mNumNonCachedProcs=" + mNumNonCachedProcs
+ " (" + mLruProcesses.size() + " total)"
@@ -11345,12 +11345,6 @@
return false;
}
- final void dumpProcessTracker(FileDescriptor fd, PrintWriter pw, String[] args) {
- synchronized (this) {
- mProcessTracker.dumpLocked(fd, pw, args);
- }
- }
-
private final boolean removeDyingProviderLocked(ProcessRecord proc,
ContentProviderRecord cpr, boolean always) {
final boolean inLaunching = mLaunchingProviders.contains(cpr);
diff --git a/services/java/com/android/server/am/ActivityStack.java b/services/java/com/android/server/am/ActivityStack.java
index de220e5..98b3ce9 100644
--- a/services/java/com/android/server/am/ActivityStack.java
+++ b/services/java/com/android/server/am/ActivityStack.java
@@ -70,7 +70,6 @@
import android.os.Looper;
import android.os.Message;
import android.os.PowerManager;
-import android.os.Process;
import android.os.RemoteException;
import android.os.SystemClock;
import android.os.UserHandle;
@@ -103,9 +102,6 @@
// from the application in order to get its saved state.
static final int STOP_TIMEOUT = 10*1000;
- // How long we can hold the launch wake lock before giving up.
- static final int LAUNCH_TIMEOUT = 10*1000;
-
// How long we wait until giving up on an activity telling us it has
// finished destroying itself.
static final int DESTROY_TIMEOUT = 10*1000;
@@ -122,10 +118,6 @@
// is being started.
static final boolean SHOW_APP_STARTING_PREVIEW = true;
- // For debugging to make sure the caller when acquiring/releasing our
- // wake lock is the system process.
- static final boolean VALIDATE_WAKE_LOCK_CALLER = true;
-
enum ActivityState {
INITIALIZING,
RESUMED,
@@ -168,14 +160,6 @@
final ArrayList<ActivityRecord> mNoAnimActivities = new ArrayList<ActivityRecord>();
/**
- * We don't want to allow the device to go to sleep while in the process
- * of launching an activity. This is primarily to allow alarm intent
- * receivers to launch an activity and get that to run before the device
- * goes back to sleep.
- */
- final PowerManager.WakeLock mLaunchingActivity;
-
- /**
* When we are in the process of pausing an activity, before starting the
* next one, this variable holds the activity that is currently being paused.
*/
@@ -226,8 +210,7 @@
/** Run all ActivityStacks through this */
final ActivityStackSupervisor mStackSupervisor;
- static final int PAUSE_TIMEOUT_MSG = ActivityManagerService.FIRST_ACTIVITY_STACK_MSG;
- static final int LAUNCH_TIMEOUT_MSG = ActivityManagerService.FIRST_ACTIVITY_STACK_MSG + 1;
+ static final int PAUSE_TIMEOUT_MSG = ActivityManagerService.FIRST_ACTIVITY_STACK_MSG + 1;
static final int DESTROY_TIMEOUT_MSG = ActivityManagerService.FIRST_ACTIVITY_STACK_MSG + 2;
static final int LAUNCH_TICK_MSG = ActivityManagerService.FIRST_ACTIVITY_STACK_MSG + 3;
static final int STOP_TIMEOUT_MSG = ActivityManagerService.FIRST_ACTIVITY_STACK_MSG + 4;
@@ -286,23 +269,6 @@
activityDestroyedLocked(r != null ? r.appToken : null);
}
} break;
- case LAUNCH_TIMEOUT_MSG: {
- if (mService.mDidDexOpt) {
- mService.mDidDexOpt = false;
- mHandler.sendEmptyMessageDelayed(LAUNCH_TIMEOUT_MSG, LAUNCH_TIMEOUT);
- return;
- }
- synchronized (mService) {
- if (mLaunchingActivity.isHeld()) {
- Slog.w(TAG, "Launch timeout has expired, giving up wake lock!");
- if (VALIDATE_WAKE_LOCK_CALLER
- && Binder.getCallingUid() != Process.myUid()) {
- throw new IllegalStateException("Calling must be system uid");
- }
- mLaunchingActivity.release();
- }
- }
- } break;
case STOP_TIMEOUT_MSG: {
ActivityRecord r = (ActivityRecord)msg.obj;
// We don't at this point know if the activity is fullscreen,
@@ -339,12 +305,6 @@
mStackSupervisor = service.mStackSupervisor;
mContext = context;
PowerManager pm = (PowerManager)context.getSystemService(Context.POWER_SERVICE);
- if (VALIDATE_WAKE_LOCK_CALLER && Binder.getCallingUid() != Process.myUid()) {
- throw new IllegalStateException("Calling must be system uid");
- }
- mLaunchingActivity =
- pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "ActivityManager-Launch");
- mLaunchingActivity.setReferenceCounted(false);
mStackId = stackId;
mCurrentUser = service.mCurrentUserId;
}
@@ -628,16 +588,6 @@
r.displayStartTime = r.fullyDrawnStartTime = 0;
}
- void stopIfSleepingLocked() {
- if (mLaunchingActivity.isHeld()) {
- if (VALIDATE_WAKE_LOCK_CALLER && Binder.getCallingUid() != Process.myUid()) {
- throw new IllegalStateException("Calling must be system uid");
- }
- mLaunchingActivity.release();
- mService.mHandler.removeMessages(LAUNCH_TIMEOUT_MSG);
- }
- }
-
void awakeFromSleepingLocked() {
// Ensure activities are no longer sleeping.
for (int taskNdx = mTaskHistory.size() - 1; taskNdx >= 0; --taskNdx) {
@@ -762,14 +712,7 @@
// If we are not going to sleep, we want to ensure the device is
// awake until the next activity is started.
if (!mService.isSleepingOrShuttingDown()) {
- if (VALIDATE_WAKE_LOCK_CALLER && Binder.getCallingUid() != Process.myUid()) {
- throw new IllegalStateException("Calling must be system uid");
- }
- mLaunchingActivity.acquire();
- if (!mHandler.hasMessages(LAUNCH_TIMEOUT_MSG)) {
- // To be safe, don't allow the wake lock to be held for too long.
- mHandler.sendEmptyMessageDelayed(LAUNCH_TIMEOUT_MSG, LAUNCH_TIMEOUT);
- }
+ mStackSupervisor.acquireLaunchWakelock();
}
if (mPausingActivity != null) {
@@ -2140,29 +2083,6 @@
}
}
- final ActivityRecord activityIdleInternalLocked(final IBinder token) {
- if (localLOGV) Slog.v(TAG, "Activity idle: " + token);
-
- // Get the activity record.
- ActivityRecord res = isInStackLocked(token);
- if (res != null) {
- // No longer need to keep the device awake.
- if (mResumedActivity == res && mLaunchingActivity.isHeld()) {
- mHandler.removeMessages(LAUNCH_TIMEOUT_MSG);
- if (VALIDATE_WAKE_LOCK_CALLER && Binder.getCallingUid() != Process.myUid()) {
- throw new IllegalStateException("Calling must be system uid");
- }
- mLaunchingActivity.release();
- }
-
- // If this activity is fullscreen, set up to hide those under it.
- if (DEBUG_VISBILITY) Slog.v(TAG, "Idle activity for " + res);
- mStackSupervisor.ensureActivitiesVisibleLocked(null, 0);
- }
-
- return res;
- }
-
/**
* @return Returns true if the activity is being finished, false if for
* some reason it is being left as-is.
diff --git a/services/java/com/android/server/am/ActivityStackSupervisor.java b/services/java/com/android/server/am/ActivityStackSupervisor.java
index 9afac2c..63f91ac 100644
--- a/services/java/com/android/server/am/ActivityStackSupervisor.java
+++ b/services/java/com/android/server/am/ActivityStackSupervisor.java
@@ -62,6 +62,7 @@
import android.os.Message;
import android.os.ParcelFileDescriptor;
import android.os.PowerManager;
+import android.os.Process;
import android.os.RemoteException;
import android.os.SystemClock;
import android.os.UserHandle;
@@ -98,10 +99,18 @@
/** How long we can hold the sleep wake lock before giving up. */
static final int SLEEP_TIMEOUT = 5*1000;
+ // How long we can hold the launch wake lock before giving up.
+ static final int LAUNCH_TIMEOUT = 10*1000;
+
static final int IDLE_TIMEOUT_MSG = FIRST_SUPERVISOR_STACK_MSG;
static final int IDLE_NOW_MSG = FIRST_SUPERVISOR_STACK_MSG + 1;
static final int RESUME_TOP_ACTIVITY_MSG = FIRST_SUPERVISOR_STACK_MSG + 2;
static final int SLEEP_TIMEOUT_MSG = FIRST_SUPERVISOR_STACK_MSG + 3;
+ static final int LAUNCH_TIMEOUT_MSG = FIRST_SUPERVISOR_STACK_MSG + 4;
+
+ // For debugging to make sure the caller when acquiring/releasing our
+ // wake lock is the system process.
+ static final boolean VALIDATE_WAKE_LOCK_CALLER = false;
final ActivityManagerService mService;
final Context mContext;
@@ -183,6 +192,14 @@
boolean mSleepTimeout = false;
/**
+ * We don't want to allow the device to go to sleep while in the process
+ * of launching an activity. This is primarily to allow alarm intent
+ * receivers to launch an activity and get that to run before the device
+ * goes back to sleep.
+ */
+ final PowerManager.WakeLock mLaunchingActivity;
+
+ /**
* Set when the system is going to sleep, until we have
* successfully paused the current activity and released our wake lock.
* At that point the system is allowed to actually sleep.
@@ -197,6 +214,12 @@
PowerManager pm = (PowerManager)context.getSystemService(Context.POWER_SERVICE);
mGoingToSleep = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "ActivityManager-Sleep");
mHandler = new ActivityStackSupervisorHandler(looper);
+ if (VALIDATE_WAKE_LOCK_CALLER && Binder.getCallingUid() != Process.myUid()) {
+ throw new IllegalStateException("Calling must be system uid");
+ }
+ mLaunchingActivity =
+ pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "ActivityManager-Launch");
+ mLaunchingActivity.setReferenceCounted(false);
}
void setWindowManager(WindowManagerService wm) {
@@ -388,7 +411,11 @@
boolean allResumedActivitiesIdle() {
for (int stackNdx = mStacks.size() - 1; stackNdx >= 0; --stackNdx) {
- final ActivityRecord resumedActivity = mStacks.get(stackNdx).mResumedActivity;
+ final ActivityStack stack = mStacks.get(stackNdx);
+ if (!isFrontStack(stack)) {
+ continue;
+ }
+ final ActivityRecord resumedActivity = stack.mResumedActivity;
if (resumedActivity == null || !resumedActivity.idle) {
return false;
}
@@ -1666,13 +1693,22 @@
return ActivityManager.START_SUCCESS;
}
+ void acquireLaunchWakelock() {
+ if (VALIDATE_WAKE_LOCK_CALLER && Binder.getCallingUid() != Process.myUid()) {
+ throw new IllegalStateException("Calling must be system uid");
+ }
+ mLaunchingActivity.acquire();
+ if (!mHandler.hasMessages(LAUNCH_TIMEOUT_MSG)) {
+ // To be safe, don't allow the wake lock to be held for too long.
+ mHandler.sendEmptyMessageDelayed(LAUNCH_TIMEOUT_MSG, LAUNCH_TIMEOUT);
+ }
+ }
+
// Checked.
final ActivityRecord activityIdleInternalLocked(final IBinder token, boolean fromTimeout,
Configuration config) {
if (localLOGV) Slog.v(TAG, "Activity idle: " + token);
- ActivityRecord res = null;
-
ArrayList<ActivityRecord> stops = null;
ArrayList<ActivityRecord> finishes = null;
ArrayList<UserStartedState> startingUsers = null;
@@ -1689,41 +1725,50 @@
Debug.getCallers(4));
mHandler.removeMessages(IDLE_TIMEOUT_MSG, r);
r.finishLaunchTickingLocked();
- res = r.task.stack.activityIdleInternalLocked(token);
- if (res != null) {
- if (fromTimeout) {
- reportActivityLaunchedLocked(fromTimeout, r, -1, -1);
- }
-
- // This is a hack to semi-deal with a race condition
- // in the client where it can be constructed with a
- // newer configuration from when we asked it to launch.
- // We'll update with whatever configuration it now says
- // it used to launch.
- if (config != null) {
- r.configuration = config;
- }
-
- // We are now idle. If someone is waiting for a thumbnail from
- // us, we can now deliver.
- r.idle = true;
- if (allResumedActivitiesIdle()) {
- mService.scheduleAppGcsLocked();
- mService.requestPssLocked(r.app, SystemClock.uptimeMillis(), false);
- }
- if (r.thumbnailNeeded && r.app != null && r.app.thread != null) {
- sendThumbnail = r.app.thread;
- r.thumbnailNeeded = false;
- }
-
- //Slog.i(TAG, "IDLE: mBooted=" + mBooted + ", fromTimeout=" + fromTimeout);
- if (!mService.mBooted && isFrontStack(r.task.stack)) {
- mService.mBooted = true;
- enableScreen = true;
- }
- } else if (fromTimeout) {
- reportActivityLaunchedLocked(fromTimeout, null, -1, -1);
+ if (fromTimeout) {
+ reportActivityLaunchedLocked(fromTimeout, r, -1, -1);
}
+
+ // This is a hack to semi-deal with a race condition
+ // in the client where it can be constructed with a
+ // newer configuration from when we asked it to launch.
+ // We'll update with whatever configuration it now says
+ // it used to launch.
+ if (config != null) {
+ r.configuration = config;
+ }
+
+ // We are now idle. If someone is waiting for a thumbnail from
+ // us, we can now deliver.
+ r.idle = true;
+
+ if (r.thumbnailNeeded && r.app != null && r.app.thread != null) {
+ sendThumbnail = r.app.thread;
+ r.thumbnailNeeded = false;
+ }
+
+ //Slog.i(TAG, "IDLE: mBooted=" + mBooted + ", fromTimeout=" + fromTimeout);
+ if (!mService.mBooted && isFrontStack(r.task.stack)) {
+ mService.mBooted = true;
+ enableScreen = true;
+ }
+ }
+
+ if (allResumedActivitiesIdle()) {
+ if (r != null) {
+ mService.scheduleAppGcsLocked();
+ mService.requestPssLocked(r.app, SystemClock.uptimeMillis(), false);
+ }
+
+ if (mLaunchingActivity.isHeld()) {
+ mHandler.removeMessages(LAUNCH_TIMEOUT_MSG);
+ if (VALIDATE_WAKE_LOCK_CALLER &&
+ Binder.getCallingUid() != Process.myUid()) {
+ throw new IllegalStateException("Calling must be system uid");
+ }
+ mLaunchingActivity.release();
+ }
+ ensureActivitiesVisibleLocked(null, 0);
}
// Atomically retrieve all of the other things to do.
@@ -1814,7 +1859,7 @@
resumeTopActivitiesLocked();
}
- return res;
+ return r;
}
void handleAppDiedLocked(ProcessRecord app, boolean restarting) {
@@ -1882,7 +1927,7 @@
void findTaskToMoveToFrontLocked(int taskId, int flags, Bundle options) {
for (int stackNdx = mStacks.size() - 1; stackNdx >= 0; --stackNdx) {
if (mStacks.get(stackNdx).findTaskToMoveToFrontLocked(taskId, flags, options)) {
- if (DEBUG_STACK) Slog.d(TAG, "findTaskToMoveToFront: moved to front of stack=" +
+ if (DEBUG_STACK) Slog.d(TAG, "findTaskToMoveToFront: moved to front of stack=" +
mStacks.get(stackNdx));
return;
}
@@ -1956,11 +2001,12 @@
scheduleSleepTimeout();
if (!mGoingToSleep.isHeld()) {
mGoingToSleep.acquire();
- for (int stackNdx = mStacks.size() - 1; stackNdx >= 0; --stackNdx) {
- final ActivityStack stack = mStacks.get(stackNdx);
- if (stack.mResumedActivity != null) {
- stack.stopIfSleepingLocked();
+ if (mLaunchingActivity.isHeld()) {
+ if (VALIDATE_WAKE_LOCK_CALLER && Binder.getCallingUid() != Process.myUid()) {
+ throw new IllegalStateException("Calling must be system uid");
}
+ mLaunchingActivity.release();
+ mService.mHandler.removeMessages(LAUNCH_TIMEOUT_MSG);
}
}
}
@@ -2423,8 +2469,8 @@
synchronized (mService) {
activityIdleInternalLocked(r != null ? r.appToken : null, true, null);
}
- }
-
+ }
+
@Override
public void handleMessage(Message msg) {
switch (msg.what) {
@@ -2459,6 +2505,23 @@
}
}
} break;
+ case LAUNCH_TIMEOUT_MSG: {
+ if (mService.mDidDexOpt) {
+ mService.mDidDexOpt = false;
+ mHandler.sendEmptyMessageDelayed(LAUNCH_TIMEOUT_MSG, LAUNCH_TIMEOUT);
+ return;
+ }
+ synchronized (mService) {
+ if (mLaunchingActivity.isHeld()) {
+ Slog.w(TAG, "Launch timeout has expired, giving up wake lock!");
+ if (VALIDATE_WAKE_LOCK_CALLER
+ && Binder.getCallingUid() != Process.myUid()) {
+ throw new IllegalStateException("Calling must be system uid");
+ }
+ mLaunchingActivity.release();
+ }
+ }
+ } break;
}
}
}
diff --git a/services/java/com/android/server/am/ProcessRecord.java b/services/java/com/android/server/am/ProcessRecord.java
index 1671d24..14f4102 100644
--- a/services/java/com/android/server/am/ProcessRecord.java
+++ b/services/java/com/android/server/am/ProcessRecord.java
@@ -425,8 +425,14 @@
} else {
sb.append('u');
sb.append(userId);
- sb.append('a');
- sb.append(UserHandle.getAppId(info.uid));
+ int appId = UserHandle.getAppId(info.uid);
+ if (appId >= Process.FIRST_APPLICATION_UID) {
+ sb.append('a');
+ sb.append(appId - Process.FIRST_APPLICATION_UID);
+ } else {
+ sb.append('s');
+ sb.append(appId);
+ }
if (uid != info.uid) {
sb.append('i');
sb.append(UserHandle.getAppId(uid) - Process.FIRST_ISOLATED_UID);
diff --git a/services/java/com/android/server/am/ProcessTracker.java b/services/java/com/android/server/am/ProcessTracker.java
index 488582d..0ea93e8 100644
--- a/services/java/com/android/server/am/ProcessTracker.java
+++ b/services/java/com/android/server/am/ProcessTracker.java
@@ -140,9 +140,12 @@
static final int MAX_HISTORIC_STATES = 4; // Maximum number of historic states we will keep.
static final String STATE_FILE_PREFIX = "state-"; // Prefix to use for state filenames.
+ static final String STATE_FILE_SUFFIX = ".bin"; // Suffix to use for state filenames.
+ static final String STATE_FILE_CHECKIN_SUFFIX = ".ci"; // State files that have checked in.
static long WRITE_PERIOD = 30*60*1000; // Write file every 30 minutes or so.
static long COMMIT_PERIOD = 24*60*60*1000; // Commit current stats every day.
+ final Object mLock;
final File mBaseDir;
State mState;
boolean mCommitPending;
@@ -694,7 +697,7 @@
mTimePeriodStartClock).toString();
if (mBaseDir != null) {
mFile = new AtomicFile(new File(mBaseDir,
- STATE_FILE_PREFIX + mTimePeriodStartClockStr));
+ STATE_FILE_PREFIX + mTimePeriodStartClockStr + STATE_FILE_SUFFIX));
}
}
@@ -1255,8 +1258,7 @@
return ps;
}
- void dumpLocked(PrintWriter pw, String reqPackage, boolean dumpAll) {
- final long now = SystemClock.uptimeMillis();
+ void dumpLocked(PrintWriter pw, String reqPackage, long now, boolean dumpAll) {
ArrayMap<String, SparseArray<PackageState>> pkgMap = mPackages.getMap();
boolean printedHeader = false;
for (int ip=0; ip<pkgMap.size(); ip++) {
@@ -1318,29 +1320,53 @@
}
}
- dumpFilteredProcesses(pw, "Processes running while critical mem:", " ",
- new int[] {ADJ_SCREEN_OFF, ADJ_SCREEN_ON},
- new int[] {ADJ_MEM_FACTOR_CRITICAL},
- new int[] {STATE_PERSISTENT, STATE_TOP, STATE_FOREGROUND, STATE_VISIBLE,
- STATE_PERCEPTIBLE, STATE_BACKUP, STATE_SERVICE, STATE_HOME, STATE_PREVIOUS},
- now, reqPackage);
- dumpFilteredProcesses(pw, "Processes running while low mem:", " ",
- new int[] {ADJ_SCREEN_OFF, ADJ_SCREEN_ON},
- new int[] {ADJ_MEM_FACTOR_LOW},
- new int[] {STATE_PERSISTENT, STATE_TOP, STATE_FOREGROUND, STATE_VISIBLE,
- STATE_PERCEPTIBLE, STATE_BACKUP, STATE_SERVICE, STATE_HOME, STATE_PREVIOUS},
- now, reqPackage);
- dumpFilteredProcesses(pw, "Processes running while moderate mem:", " ",
- new int[] {ADJ_SCREEN_OFF, ADJ_SCREEN_ON},
- new int[] {ADJ_MEM_FACTOR_MODERATE},
- new int[] {STATE_PERSISTENT, STATE_TOP, STATE_FOREGROUND, STATE_VISIBLE,
- STATE_PERCEPTIBLE, STATE_BACKUP, STATE_SERVICE, STATE_HOME, STATE_PREVIOUS},
- now, reqPackage);
- dumpFilteredProcesses(pw, "Processes running while normal mem:", " ",
- new int[] {ADJ_SCREEN_OFF, ADJ_SCREEN_ON},
- new int[] {ADJ_MEM_FACTOR_NORMAL},
- new int[] {STATE_PERSISTENT, STATE_TOP, STATE_FOREGROUND, STATE_VISIBLE,
- STATE_PERCEPTIBLE, STATE_BACKUP, STATE_SERVICE, STATE_HOME, STATE_PREVIOUS},
+ if (reqPackage == null) {
+ ArrayMap<String, SparseArray<ProcessState>> procMap = mProcesses.getMap();
+ printedHeader = false;
+ for (int ip=0; ip<procMap.size(); ip++) {
+ String procName = procMap.keyAt(ip);
+ SparseArray<ProcessState> uids = procMap.valueAt(ip);
+ for (int iu=0; iu<uids.size(); iu++) {
+ int uid = uids.keyAt(iu);
+ ProcessState proc = uids.valueAt(iu);
+ if (proc.mDurationsTableSize == 0 && proc.mCurState == STATE_NOTHING
+ && proc.mPssTableSize == 0) {
+ continue;
+ }
+ if (!printedHeader) {
+ pw.println("Process Stats:");
+ printedHeader = true;
+ }
+ pw.print(" * "); pw.print(procName); pw.print(" / ");
+ UserHandle.formatUid(pw, uid);
+ pw.print(" ("); pw.print(proc.mDurationsTableSize);
+ pw.print(" entries)"); pw.println(":");
+ dumpProcessState(pw, " ", proc, ALL_SCREEN_ADJ, ALL_MEM_ADJ,
+ ALL_PROC_STATES, now);
+ dumpProcessPss(pw, " ", proc, ALL_SCREEN_ADJ, ALL_MEM_ADJ,
+ ALL_PROC_STATES);
+ }
+ }
+
+ pw.println();
+ pw.println("Summary:");
+ dumpSummaryLocked(pw, reqPackage, now);
+ }
+
+ if (dumpAll) {
+ pw.println();
+ pw.println("Internal state:");
+ pw.print(" mFile="); pw.println(mFile.getBaseFile());
+ pw.print(" Num long arrays: "); pw.println(mLongs.size());
+ pw.print(" Next long entry: "); pw.println(mNextLong);
+ pw.print(" mRunning="); pw.println(mRunning);
+ }
+ }
+
+ void dumpSummaryLocked(PrintWriter pw, String reqPackage, long now) {
+ dumpFilteredSummaryLocked(pw, null, " ", ALL_SCREEN_ADJ, ALL_MEM_ADJ,
+ new int[] { STATE_PERSISTENT, STATE_TOP, STATE_FOREGROUND, STATE_VISIBLE,
+ STATE_PERCEPTIBLE, STATE_BACKUP, STATE_SERVICE, STATE_HOME, STATE_PREVIOUS },
now, reqPackage);
pw.println();
pw.println("Run time Stats:");
@@ -1352,26 +1378,20 @@
pw.print(" Total elapsed time: ");
TimeUtils.formatDuration(
(mRunning ? SystemClock.elapsedRealtime() : mTimePeriodEndRealtime)
- - mTimePeriodStartRealtime, pw);
+ - mTimePeriodStartRealtime, pw);
pw.println();
- if (dumpAll) {
- pw.println();
- pw.println("Internal state:");
- pw.print(" mFile="); pw.println(mFile.getBaseFile());
- pw.print(" Num long arrays: "); pw.println(mLongs.size());
- pw.print(" Next long entry: "); pw.println(mNextLong);
- pw.print(" mRunning="); pw.println(mRunning);
- }
}
- void dumpFilteredProcesses(PrintWriter pw, String header, String prefix,
+ void dumpFilteredSummaryLocked(PrintWriter pw, String header, String prefix,
int[] screenStates, int[] memStates, int[] procStates, long now, String reqPackage) {
ArrayList<ProcessState> procs = collectProcessesLocked(screenStates, memStates,
procStates, now, reqPackage);
if (procs.size() > 0) {
- pw.println();
- pw.println(header);
- dumpProcessList(pw, prefix, procs, screenStates, memStates, procStates, now);
+ if (header != null) {
+ pw.println();
+ pw.println(header);
+ }
+ dumpProcessSummary(pw, prefix, procs, screenStates, memStates, procStates, now);
}
}
@@ -1542,7 +1562,8 @@
}
}
- public ProcessTracker(File file) {
+ public ProcessTracker(Object lock, File file) {
+ mLock = lock;
mBaseDir = file;
mBaseDir.mkdirs();
mState = new State(mBaseDir, this);
@@ -1637,27 +1658,34 @@
mState.writeStateLocked(sync, commitPending);
}
- private ArrayList<String> getCommittedFiles(int minNum) {
+ private ArrayList<String> getCommittedFiles(int minNum, boolean inclAll) {
File[] files = mBaseDir.listFiles();
if (files == null || files.length <= minNum) {
return null;
}
ArrayList<String> filesArray = new ArrayList<String>(files.length);
- String currentFile = mState.mFile.getBaseFile().toString();
+ String currentFile = mState.mFile.getBaseFile().getPath();
if (DEBUG) Slog.d(TAG, "Collecting " + files.length + " files except: " + currentFile);
for (int i=0; i<files.length; i++) {
File file = files[i];
- if (DEBUG) Slog.d(TAG, "Collecting: " + file);
- if (!file.toString().equals(currentFile)) {
- filesArray.add(files[i].toString());
+ String fileStr = file.getPath();
+ if (DEBUG) Slog.d(TAG, "Collecting: " + fileStr);
+ if (!inclAll && fileStr.endsWith(STATE_FILE_CHECKIN_SUFFIX)) {
+ if (DEBUG) Slog.d(TAG, "Skipping: already checked in");
+ continue;
}
+ if (fileStr.equals(currentFile)) {
+ if (DEBUG) Slog.d(TAG, "Skipping: current stats");
+ continue;
+ }
+ filesArray.add(fileStr);
}
Collections.sort(filesArray);
return filesArray;
}
public void trimHistoricStatesWriteLocked() {
- ArrayList<String> filesArray = getCommittedFiles(MAX_HISTORIC_STATES);
+ ArrayList<String> filesArray = getCommittedFiles(MAX_HISTORIC_STATES, true);
if (filesArray == null) {
return;
}
@@ -1803,6 +1831,76 @@
pw.println();
}
+ static final class ProcessDataCollection {
+ final int[] screenStates;
+ final int[] memStates;
+ final int[] procStates;
+
+ long totalTime;
+ long numPss;
+ long minPss;
+ long avgPss;
+ long maxPss;
+
+ ProcessDataCollection(int[] _screenStates, int[] _memStates, int[] _procStates) {
+ screenStates = _screenStates;
+ memStates = _memStates;
+ procStates = _procStates;
+ }
+
+ void print(PrintWriter pw, boolean full) {
+ TimeUtils.formatDuration(totalTime, pw);
+ if (numPss > 0) {
+ pw.print(" (");
+ printSizeValue(pw, minPss * 1024);
+ pw.print("-");
+ printSizeValue(pw, avgPss * 1024);
+ pw.print("-");
+ printSizeValue(pw, maxPss * 1024);
+ if (full) {
+ pw.print(" over ");
+ pw.print(numPss);
+ }
+ pw.print(")");
+ }
+ }
+ }
+
+ static void computeProcessData(ProcessState proc, ProcessDataCollection data, long now) {
+ data.totalTime = 0;
+ data.numPss = data.minPss = data.avgPss = data.maxPss = 0;
+ for (int is=0; is<data.screenStates.length; is++) {
+ for (int im=0; im<data.memStates.length; im++) {
+ for (int ip=0; ip<data.procStates.length; ip++) {
+ int bucket = ((data.screenStates[is] + data.memStates[im]) * STATE_COUNT)
+ + data.procStates[ip];
+ data.totalTime += proc.getDuration(bucket, now);
+ long samples = proc.getPssSampleCount(bucket);
+ if (samples > 0) {
+ long minPss = proc.getPssMinimum(bucket);
+ long avgPss = proc.getPssAverage(bucket);
+ long maxPss = proc.getPssMaximum(bucket);
+ if (data.numPss == 0) {
+ data.minPss = minPss;
+ data.avgPss = avgPss;
+ data.maxPss = maxPss;
+ } else {
+ if (minPss < data.minPss) {
+ data.minPss = minPss;
+ }
+ data.avgPss = (long)( ((data.avgPss*(double)data.numPss)
+ + (avgPss*(double)samples)) / (data.numPss+samples) );
+ if (maxPss > data.maxPss) {
+ data.maxPss = maxPss;
+ }
+ }
+ data.numPss += samples;
+ }
+ }
+ }
+ }
+ }
+
static long computeProcessTimeLocked(ProcessState proc, int[] screenStates, int[] memStates,
int[] procStates, long now) {
long totalTime = 0;
@@ -1818,7 +1916,7 @@
for (int is=0; is<screenStates.length; is++) {
for (int im=0; im<memStates.length; im++) {
for (int ip=0; ip<procStates.length; ip++) {
- int bucket = ((screenStates[is]+ memStates[im]) * STATE_COUNT)
+ int bucket = ((screenStates[is] + memStates[im]) * STATE_COUNT)
+ procStates[ip];
totalTime += proc.getDuration(bucket, now);
}
@@ -1910,12 +2008,12 @@
pw.print(STATE_NAMES[procStates[ip]]); pw.print(": ");
pw.print(count);
pw.print(" samples ");
- pw.print(proc.getPssMinimum(bucket));
- pw.print("kB ");
- pw.print(proc.getPssAverage(bucket));
- pw.print("kB ");
- pw.print(proc.getPssMaximum(bucket));
- pw.println("kB");
+ printSizeValue(pw, proc.getPssMinimum(bucket) * 1024);
+ pw.print(" ");
+ printSizeValue(pw, proc.getPssAverage(bucket) * 1024);
+ pw.print(" ");
+ printSizeValue(pw, proc.getPssMaximum(bucket) * 1024);
+ pw.println();
}
}
}
@@ -2017,6 +2115,94 @@
}
}
+ static void dumpProcessSummaryDetails(PrintWriter pw, ProcessState proc, String prefix,
+ String label, int[] screenStates, int[] memStates, int[] procStates,
+ long now, boolean full) {
+ ProcessDataCollection totals = new ProcessDataCollection(screenStates,
+ memStates, procStates);
+ computeProcessData(proc, totals, now);
+ if (totals.totalTime != 0 || totals.numPss != 0) {
+ if (prefix != null) {
+ pw.print(prefix);
+ }
+ if (label != null) {
+ pw.print(label);
+ }
+ totals.print(pw, full);
+ if (prefix != null) {
+ pw.println();
+ }
+ }
+ }
+
+ static void dumpProcessSummary(PrintWriter pw, String prefix, ArrayList<ProcessState> procs,
+ int[] screenStates, int[] memStates, int[] procStates, long now) {
+ for (int i=procs.size()-1; i>=0; i--) {
+ ProcessState proc = procs.get(i);
+ pw.print(prefix);
+ pw.print("* ");
+ pw.print(proc.mName);
+ pw.print(" / ");
+ UserHandle.formatUid(pw, proc.mUid);
+ pw.println(":");
+ dumpProcessSummaryDetails(pw, proc, prefix, " TOTAL: ", screenStates, memStates,
+ procStates, now, true);
+ dumpProcessSummaryDetails(pw, proc, prefix, " Persistent: ", screenStates, memStates,
+ new int[] {STATE_PERSISTENT}, now, true);
+ dumpProcessSummaryDetails(pw, proc, prefix, " Top: ", screenStates, memStates,
+ new int[] {STATE_TOP}, now, true);
+ dumpProcessSummaryDetails(pw, proc, prefix, " Foreground: ", screenStates, memStates,
+ new int[] {STATE_FOREGROUND, STATE_VISIBLE, STATE_PERCEPTIBLE}, now, true);
+ dumpProcessSummaryDetails(pw, proc, prefix, " Backup: ", screenStates, memStates,
+ new int[] {STATE_BACKUP}, now, true);
+ dumpProcessSummaryDetails(pw, proc, prefix, " Service: ", screenStates, memStates,
+ new int[] {STATE_SERVICE}, now, true);
+ dumpProcessSummaryDetails(pw, proc, prefix, " Home: ", screenStates, memStates,
+ new int[] {STATE_HOME}, now, true);
+ dumpProcessSummaryDetails(pw, proc, prefix, " Previous: ", screenStates, memStates,
+ new int[] {STATE_PREVIOUS}, now, true);
+ dumpProcessSummaryDetails(pw, proc, prefix, " (Cached): ", screenStates, memStates,
+ new int[] {STATE_CACHED}, now, true);
+ }
+ }
+
+ private static void printSizeValue(PrintWriter pw, long number) {
+ float result = number;
+ String suffix = "";
+ if (result > 900) {
+ suffix = "KB";
+ result = result / 1024;
+ }
+ if (result > 900) {
+ suffix = "MB";
+ result = result / 1024;
+ }
+ if (result > 900) {
+ suffix = "GB";
+ result = result / 1024;
+ }
+ if (result > 900) {
+ suffix = "TB";
+ result = result / 1024;
+ }
+ if (result > 900) {
+ suffix = "PB";
+ result = result / 1024;
+ }
+ String value;
+ if (result < 1) {
+ value = String.format("%.2f", result);
+ } else if (result < 10) {
+ value = String.format("%.2f", result);
+ } else if (result < 100) {
+ value = String.format("%.2f", result);
+ } else {
+ value = String.format("%.0f", result);
+ }
+ pw.print(value);
+ pw.print(suffix);
+ }
+
static void dumpProcessListCsv(PrintWriter pw, ArrayList<ProcessState> procs,
boolean sepScreenStates, int[] screenStates, boolean sepMemStates, int[] memStates,
boolean sepProcStates, int[] procStates, long now) {
@@ -2171,7 +2357,7 @@
static private void dumpHelp(PrintWriter pw) {
pw.println("Process stats (procstats) dump options:");
pw.println(" [--checkin|-c|--csv] [--csv-screen] [--csv-proc] [--csv-mem]");
- pw.println(" [--include-committed] [--commit] [--write] [-h] [<package.name>]");
+ pw.println(" [--details] [--current] [--commit] [--write] [-h] [<package.name>]");
pw.println(" --checkin: perform a checkin: print and delete old committed states.");
pw.println(" --c: print only state in checkin format.");
pw.println(" --csv: output data suitable for putting in a spreadsheet.");
@@ -2179,7 +2365,8 @@
pw.println(" --csv-mem: norm, mod, low, crit.");
pw.println(" --csv-proc: pers, top, fore, vis, precept, backup,");
pw.println(" service, home, prev, cached");
- pw.println(" --include-committed: also dump any old committed states.");
+ pw.println(" --details: dump all execution details, not just summary.");
+ pw.println(" --current: only dump current state.");
pw.println(" --commit: commit current stats to disk and reset to start new stats.");
pw.println(" --write: write current in-memory stats to disk.");
pw.println(" --read: replace current stats with last-written stats.");
@@ -2188,13 +2375,14 @@
pw.println(" <package.name>: optional name of package to filter output by.");
}
- public void dumpLocked(FileDescriptor fd, PrintWriter pw, String[] args) {
+ public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
final long now = SystemClock.uptimeMillis();
boolean isCheckin = false;
boolean isCompact = false;
boolean isCsv = false;
- boolean includeCommitted = false;
+ boolean currentOnly = false;
+ boolean dumpDetails = false;
boolean dumpAll = false;
String reqPackage = null;
boolean csvSepScreenStats = false;
@@ -2264,8 +2452,10 @@
return;
}
csvSepProcStats = sep[0];
- } else if ("--include-committed".equals(arg)) {
- includeCommitted = true;
+ } else if ("--details".equals(arg)) {
+ dumpDetails = true;
+ } else if ("--current".equals(arg)) {
+ currentOnly = true;
} else if ("--commit".equals(arg)) {
mState.writeStateLocked(true, true);
pw.println("Process stats committed.");
@@ -2282,8 +2472,8 @@
dumpHelp(pw);
return;
} else if ("-a".equals(arg)) {
+ dumpDetails = true;
dumpAll = true;
- includeCommitted = true;
} else if (arg.length() > 0 && arg.charAt(0) == '-'){
pw.println("Unknown option: " + arg);
dumpHelp(pw);
@@ -2294,9 +2484,11 @@
IPackageManager pm = AppGlobals.getPackageManager();
if (pm.getPackageUid(arg, UserHandle.getCallingUserId()) >= 0) {
reqPackage = arg;
- // We will automatically include all committed state,
- // since we are going to end up with much less printed.
- includeCommitted = true;
+ // Include all details, since we know we are only going to
+ // be dumping a smaller set of data. In fact only the details
+ // container per-package data, so that are needed to be able
+ // to dump anything at all when filtering by package.
+ dumpDetails = true;
}
} catch (RemoteException e) {
}
@@ -2330,70 +2522,94 @@
}
}
pw.println();
- dumpFilteredProcessesCsvLocked(pw, null,
- csvSepScreenStats, csvScreenStats, csvSepMemStats, csvMemStats,
- csvSepProcStats, csvProcStats, now, reqPackage);
- /*
- dumpFilteredProcessesCsvLocked(pw, "Processes running while critical mem:",
- false, new int[] {ADJ_SCREEN_OFF, ADJ_SCREEN_ON},
- true, new int[] {ADJ_MEM_FACTOR_CRITICAL},
- true, new int[] {STATE_PERSISTENT, STATE_TOP, STATE_FOREGROUND, STATE_VISIBLE,
- STATE_PERCEPTIBLE, STATE_BACKUP, STATE_SERVICE, STATE_HOME,
- STATE_PREVIOUS, STATE_CACHED},
- now, reqPackage);
- dumpFilteredProcessesCsvLocked(pw, "Processes running over all mem:",
- false, new int[] {ADJ_SCREEN_OFF, ADJ_SCREEN_ON},
- false, new int[] {ADJ_MEM_FACTOR_CRITICAL, ADJ_MEM_FACTOR_LOW,
- ADJ_MEM_FACTOR_MODERATE, ADJ_MEM_FACTOR_MODERATE},
- true, new int[] {STATE_PERSISTENT, STATE_TOP, STATE_FOREGROUND, STATE_VISIBLE,
- STATE_PERCEPTIBLE, STATE_BACKUP, STATE_SERVICE, STATE_HOME,
- STATE_PREVIOUS, STATE_CACHED},
- now, reqPackage);
- */
+ synchronized (mLock) {
+ dumpFilteredProcessesCsvLocked(pw, null,
+ csvSepScreenStats, csvScreenStats, csvSepMemStats, csvMemStats,
+ csvSepProcStats, csvProcStats, now, reqPackage);
+ /*
+ dumpFilteredProcessesCsvLocked(pw, "Processes running while critical mem:",
+ false, new int[] {ADJ_SCREEN_OFF, ADJ_SCREEN_ON},
+ true, new int[] {ADJ_MEM_FACTOR_CRITICAL},
+ true, new int[] {STATE_PERSISTENT, STATE_TOP, STATE_FOREGROUND, STATE_VISIBLE,
+ STATE_PERCEPTIBLE, STATE_BACKUP, STATE_SERVICE, STATE_HOME,
+ STATE_PREVIOUS, STATE_CACHED},
+ now, reqPackage);
+ dumpFilteredProcessesCsvLocked(pw, "Processes running over all mem:",
+ false, new int[] {ADJ_SCREEN_OFF, ADJ_SCREEN_ON},
+ false, new int[] {ADJ_MEM_FACTOR_CRITICAL, ADJ_MEM_FACTOR_LOW,
+ ADJ_MEM_FACTOR_MODERATE, ADJ_MEM_FACTOR_MODERATE},
+ true, new int[] {STATE_PERSISTENT, STATE_TOP, STATE_FOREGROUND, STATE_VISIBLE,
+ STATE_PERCEPTIBLE, STATE_BACKUP, STATE_SERVICE, STATE_HOME,
+ STATE_PREVIOUS, STATE_CACHED},
+ now, reqPackage);
+ */
+ }
return;
}
boolean sepNeeded = false;
- if (includeCommitted || isCheckin) {
- ArrayList<String> files = getCommittedFiles(0);
- if (files != null) {
- for (int i=0; i<files.size(); i++) {
- if (DEBUG) Slog.d(TAG, "Retrieving state: " + files.get(i));
- try {
- State state = new State(files.get(i));
- if (isCheckin || isCompact) {
- state.dumpCheckinLocked(pw, reqPackage);
- } else {
- if (sepNeeded) {
- pw.println();
+ if (!currentOnly || isCheckin) {
+ mWriteLock.lock();
+ try {
+ ArrayList<String> files = getCommittedFiles(0, !isCheckin);
+ if (files != null) {
+ for (int i=0; i<files.size(); i++) {
+ if (DEBUG) Slog.d(TAG, "Retrieving state: " + files.get(i));
+ try {
+ State state = new State(files.get(i));
+ String fileStr = state.mFile.getBaseFile().getPath();
+ boolean checkedIn = fileStr.endsWith(STATE_FILE_CHECKIN_SUFFIX);
+ if (isCheckin || isCompact) {
+ // Don't really need to lock because we uniquely own this object.
+ state.dumpCheckinLocked(pw, reqPackage);
} else {
- sepNeeded = true;
+ if (sepNeeded) {
+ pw.println();
+ } else {
+ sepNeeded = true;
+ }
+ pw.print("COMMITTED STATS FROM ");
+ pw.print(state.mTimePeriodStartClockStr);
+ if (checkedIn) pw.print(" (checked in)");
+ pw.println(":");
+ // Don't really need to lock because we uniquely own this object.
+ if (dumpDetails) {
+ state.dumpLocked(pw, reqPackage, now, dumpAll);
+ } else {
+ state.dumpSummaryLocked(pw, reqPackage, now);
+ }
}
- pw.print("COMMITTED STATS FROM ");
- pw.print(state.mTimePeriodStartClockStr);
- pw.println(":");
- state.dumpLocked(pw, reqPackage, dumpAll);
+ if (isCheckin) {
+ // Rename file suffix to mark that it has checked in.
+ state.mFile.getBaseFile().renameTo(new File(
+ fileStr + STATE_FILE_CHECKIN_SUFFIX));
+ }
+ } catch (Throwable e) {
+ pw.print("**** FAILURE DUMPING STATE: "); pw.println(files.get(i));
+ e.printStackTrace(pw);
}
- if (isCheckin) {
- state.mFile.delete();
- }
- } catch (Throwable e) {
- pw.print("**** FAILURE DUMPING STATE: "); pw.println(files.get(i));
- e.printStackTrace(pw);
+ if (DEBUG) Slog.d(TAG, "Deleting state: " + files.get(i));
}
- if (DEBUG) Slog.d(TAG, "Deleting state: " + files.get(i));
}
+ } finally {
+ mWriteLock.unlock();
}
}
if (!isCheckin) {
- if (isCompact) {
- mState.dumpCheckinLocked(pw, reqPackage);
- } else {
- if (sepNeeded) {
- pw.println();
- pw.println("CURRENT STATS:");
+ synchronized (mLock) {
+ if (isCompact) {
+ mState.dumpCheckinLocked(pw, reqPackage);
+ } else {
+ if (sepNeeded) {
+ pw.println();
+ pw.println("CURRENT STATS:");
+ }
+ if (dumpDetails) {
+ mState.dumpLocked(pw, reqPackage, now, dumpAll);
+ } else {
+ mState.dumpSummaryLocked(pw, reqPackage, now);
+ }
}
- mState.dumpLocked(pw, reqPackage, dumpAll);
}
}
}
diff --git a/services/java/com/android/server/pm/KeySetManager.java b/services/java/com/android/server/pm/KeySetManager.java
index cc2473b..3480b19 100644
--- a/services/java/com/android/server/pm/KeySetManager.java
+++ b/services/java/com/android/server/pm/KeySetManager.java
@@ -42,7 +42,10 @@
static final String TAG = "KeySetManager";
- private static final long KEYSET_NOT_FOUND = -1;
+ /** Sentinel value returned when a {@code KeySet} is not found. */
+ public static final long KEYSET_NOT_FOUND = -1;
+
+ /** Sentinel value returned when public key is not found. */
private static final long PUBLIC_KEY_NOT_FOUND = -1;
private final Object mLockObject = new Object();
@@ -418,6 +421,21 @@
pw.print(" ["); pw.print(keySetPackage); pw.println("]");
if (pkg.keySetData != null) {
boolean printedLabel = false;
+ for (Map.Entry<String, Long> entry : pkg.keySetData.getAliases().entrySet()) {
+ if (!printedLabel) {
+ pw.print(" KeySets Aliases: ");
+ printedLabel = true;
+ } else {
+ pw.print(", ");
+ }
+ pw.print(entry.getKey());
+ pw.print('=');
+ pw.print(Long.toString(entry.getValue()));
+ }
+ if (printedLabel) {
+ pw.println("");
+ }
+ printedLabel = false;
for (long keySetId : pkg.keySetData.getDefinedKeySets()) {
if (!printedLabel) {
pw.print(" Defined KeySets: ");
@@ -433,12 +451,12 @@
printedLabel = false;
for (long keySetId : pkg.keySetData.getSigningKeySets()) {
if (!printedLabel) {
- pw.print(" Signing KeySets:");
+ pw.print(" Signing KeySets: ");
printedLabel = true;
} else {
pw.print(", ");
}
- pw.print(" "); pw.print(Long.toString(keySetId));
+ pw.print(Long.toString(keySetId));
}
if (printedLabel) {
pw.println("");
@@ -566,4 +584,4 @@
mPublicKeys.put(identifier, pub);
}
}
-}
\ No newline at end of file
+}
diff --git a/services/java/com/android/server/power/ShutdownThread.java b/services/java/com/android/server/power/ShutdownThread.java
index ba321bc..88a27f5 100644
--- a/services/java/com/android/server/power/ShutdownThread.java
+++ b/services/java/com/android/server/power/ShutdownThread.java
@@ -297,7 +297,9 @@
// First send the high-level shut down broadcast.
mActionDone = false;
- mContext.sendOrderedBroadcastAsUser(new Intent(Intent.ACTION_SHUTDOWN),
+ Intent intent = new Intent(Intent.ACTION_SHUTDOWN);
+ intent.addFlags(Intent.FLAG_RECEIVER_FOREGROUND);
+ mContext.sendOrderedBroadcastAsUser(intent,
UserHandle.ALL, null, br, mHandler, 0, null, null);
final long endTime = SystemClock.elapsedRealtime() + MAX_BROADCAST_TIME;
diff --git a/services/java/com/android/server/wm/WindowState.java b/services/java/com/android/server/wm/WindowState.java
index 7c6da92..dd19f89 100644
--- a/services/java/com/android/server/wm/WindowState.java
+++ b/services/java/com/android/server/wm/WindowState.java
@@ -363,7 +363,32 @@
mSubLayer = mPolicy.subWindowTypeToLayerLw(a.type);
mAttachedWindow = attachedWindow;
if (WindowManagerService.DEBUG_ADD_REMOVE) Slog.v(TAG, "Adding " + this + " to " + mAttachedWindow);
- mAttachedWindow.mChildWindows.add(this);
+
+ int children_size = mAttachedWindow.mChildWindows.size();
+ if (children_size == 0) {
+ mAttachedWindow.mChildWindows.add(this);
+ } else {
+ for (int i = 0; i < children_size; i++) {
+ WindowState child = (WindowState)mAttachedWindow.mChildWindows.get(i);
+ if (this.mSubLayer < child.mSubLayer) {
+ mAttachedWindow.mChildWindows.add(i, this);
+ break;
+ } else if (this.mSubLayer > child.mSubLayer) {
+ continue;
+ }
+
+ if (this.mBaseLayer <= child.mBaseLayer) {
+ mAttachedWindow.mChildWindows.add(i, this);
+ break;
+ } else {
+ continue;
+ }
+ }
+ if (children_size == mAttachedWindow.mChildWindows.size()) {
+ mAttachedWindow.mChildWindows.add(this);
+ }
+ }
+
mLayoutAttached = mAttrs.type !=
WindowManager.LayoutParams.TYPE_APPLICATION_ATTACHED_DIALOG;
mIsImWindow = attachedWindow.mAttrs.type == TYPE_INPUT_METHOD