Merge "Hide deprecated MediaRecorder.java APIs"
diff --git a/core/java/android/os/Trace.java b/core/java/android/os/Trace.java
new file mode 100644
index 0000000..af94a37
--- /dev/null
+++ b/core/java/android/os/Trace.java
@@ -0,0 +1,94 @@
+/*
+ * 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.
+ */
+
+package android.os;
+
+/**
+ * Writes trace events to the kernel trace buffer.  These trace events can be
+ * collected using the "atrace" program for offline analysis.
+ *
+ * This tracing mechanism is independent of the method tracing mechanism
+ * offered by {@link Debug#startMethodTracing}.  In particular, it enables
+ * tracing of events that occur across processes.
+ *
+ * @hide
+ */
+public final class Trace {
+    // These tags must be kept in sync with frameworks/native/include/utils/Trace.h.
+    public static final long TRACE_TAG_NEVER = 0;
+    public static final long TRACE_TAG_ALWAYS = 1L << 0;
+    public static final long TRACE_TAG_GRAPHICS = 1L << 1;
+    public static final long TRACE_TAG_INPUT = 1L << 2;
+    public static final long TRACE_TAG_VIEW = 1L << 3;
+
+    private static final long sEnabledTags = nativeGetEnabledTags();
+
+    private static native long nativeGetEnabledTags();
+    private static native void nativeTraceCounter(long tag, String name, int value);
+    private static native void nativeTraceBegin(long tag, String name);
+    private static native void nativeTraceEnd(long tag);
+
+    private Trace() {
+    }
+
+    /**
+     * Returns true if a trace tag is enabled.
+     *
+     * @param traceTag The trace tag to check.
+     * @return True if the trace tag is valid.
+     */
+    public static boolean isTagEnabled(long traceTag) {
+        return (sEnabledTags & traceTag) != 0;
+    }
+
+    /**
+     * Writes trace message to indicate the value of a given counter.
+     *
+     * @param traceTag The trace tag.
+     * @param counterName The counter name to appear in the trace.
+     * @param counterValue The counter value.
+     */
+    public static void traceCounter(long traceTag, String counterName, int counterValue) {
+        if ((sEnabledTags & traceTag) != 0) {
+            nativeTraceCounter(traceTag, counterName, counterValue);
+        }
+    }
+
+    /**
+     * Writes a trace message to indicate that a given method has begun.
+     * Must be followed by a call to {@link #traceEnd} using the same tag.
+     *
+     * @param traceTag The trace tag.
+     * @param methodName The method name to appear in the trace.
+     */
+    public static void traceBegin(long traceTag, String methodName) {
+        if ((sEnabledTags & traceTag) != 0) {
+            nativeTraceBegin(traceTag, methodName);
+        }
+    }
+
+    /**
+     * Writes a trace message to indicate that the current method has ended.
+     * Must be called exactly once for each call to {@link #traceBegin} using the same tag.
+     *
+     * @param traceTag The trace tag.
+     */
+    public static void traceEnd(long traceTag) {
+        if ((sEnabledTags & traceTag) != 0) {
+            nativeTraceEnd(traceTag);
+        }
+    }
+}
diff --git a/core/java/android/view/ViewRootImpl.java b/core/java/android/view/ViewRootImpl.java
index 72365c7..4472f8c 100644
--- a/core/java/android/view/ViewRootImpl.java
+++ b/core/java/android/view/ViewRootImpl.java
@@ -51,6 +51,7 @@
 import android.os.RemoteException;
 import android.os.SystemClock;
 import android.os.SystemProperties;
+import android.os.Trace;
 import android.util.AndroidRuntimeException;
 import android.util.DisplayMetrics;
 import android.util.EventLog;
@@ -960,7 +961,12 @@
             }
         }
 
-        performTraversals();
+        Trace.traceBegin(Trace.TRACE_TAG_VIEW, "performTraversals");
+        try {
+            performTraversals();
+        } finally {
+            Trace.traceEnd(Trace.TRACE_TAG_VIEW);
+        }
 
         if (ViewDebug.DEBUG_LATENCY) {
             long now = System.nanoTime();
@@ -1919,7 +1925,13 @@
 
         final boolean fullRedrawNeeded = mFullRedrawNeeded;
         mFullRedrawNeeded = false;
-        draw(fullRedrawNeeded);
+
+        Trace.traceBegin(Trace.TRACE_TAG_VIEW, "draw");
+        try {
+            draw(fullRedrawNeeded);
+        } finally {
+            Trace.traceEnd(Trace.TRACE_TAG_VIEW);
+        }
 
         if (ViewDebug.DEBUG_LATENCY) {
             long now = System.nanoTime();
@@ -2897,17 +2909,22 @@
             q.mDeliverTimeNanos = System.nanoTime();
         }
 
-        if (q.mEvent instanceof KeyEvent) {
-            deliverKeyEvent(q);
-        } else {
-            final int source = q.mEvent.getSource();
-            if ((source & InputDevice.SOURCE_CLASS_POINTER) != 0) {
-                deliverPointerEvent(q);
-            } else if ((source & InputDevice.SOURCE_CLASS_TRACKBALL) != 0) {
-                deliverTrackballEvent(q);
+        Trace.traceBegin(Trace.TRACE_TAG_VIEW, "deliverInputEvent");
+        try {
+            if (q.mEvent instanceof KeyEvent) {
+                deliverKeyEvent(q);
             } else {
-                deliverGenericMotionEvent(q);
+                final int source = q.mEvent.getSource();
+                if ((source & InputDevice.SOURCE_CLASS_POINTER) != 0) {
+                    deliverPointerEvent(q);
+                } else if ((source & InputDevice.SOURCE_CLASS_TRACKBALL) != 0) {
+                    deliverTrackballEvent(q);
+                } else {
+                    deliverGenericMotionEvent(q);
+                }
             }
+        } finally {
+            Trace.traceEnd(Trace.TRACE_TAG_VIEW);
         }
     }
 
diff --git a/core/jni/Android.mk b/core/jni/Android.mk
index 642988b..543e32d 100644
--- a/core/jni/Android.mk
+++ b/core/jni/Android.mk
@@ -69,6 +69,7 @@
 	android_os_StatFs.cpp \
 	android_os_SystemClock.cpp \
 	android_os_SystemProperties.cpp \
+	android_os_Trace.cpp \
 	android_os_UEventObserver.cpp \
 	android_net_LocalSocketImpl.cpp \
 	android_net_NetUtils.cpp \
diff --git a/core/jni/AndroidRuntime.cpp b/core/jni/AndroidRuntime.cpp
index de9fd33..a512679 100644
--- a/core/jni/AndroidRuntime.cpp
+++ b/core/jni/AndroidRuntime.cpp
@@ -136,6 +136,7 @@
 extern int register_android_os_StatFs(JNIEnv *env);
 extern int register_android_os_SystemProperties(JNIEnv *env);
 extern int register_android_os_SystemClock(JNIEnv* env);
+extern int register_android_os_Trace(JNIEnv* env);
 extern int register_android_os_FileObserver(JNIEnv *env);
 extern int register_android_os_FileUtils(JNIEnv *env);
 extern int register_android_os_UEventObserver(JNIEnv* env);
@@ -1151,6 +1152,7 @@
     REG_JNI(register_android_os_ParcelFileDescriptor),
     REG_JNI(register_android_os_Power),
     REG_JNI(register_android_os_StatFs),
+    REG_JNI(register_android_os_Trace),
     REG_JNI(register_android_os_UEventObserver),
     REG_JNI(register_android_net_LocalSocketImpl),
     REG_JNI(register_android_net_NetworkUtils),
diff --git a/core/jni/android_os_Trace.cpp b/core/jni/android_os_Trace.cpp
new file mode 100644
index 0000000..af8edae
--- /dev/null
+++ b/core/jni/android_os_Trace.cpp
@@ -0,0 +1,72 @@
+/*
+ * 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.
+ */
+
+#define LOG_TAG "Trace"
+
+#include <JNIHelp.h>
+#include <ScopedUtfChars.h>
+
+#include <utils/Trace.h>
+#include <cutils/log.h>
+
+namespace android {
+
+static jlong android_os_Trace_nativeGetEnabledTags(JNIEnv* env, jclass clazz) {
+    return Tracer::getEnabledTags();
+}
+
+static void android_os_Trace_nativeTraceCounter(JNIEnv* env, jclass clazz,
+        jlong tag, jstring nameStr, jint value) {
+    ScopedUtfChars name(env, nameStr);
+    Tracer::traceCounter(tag, name.c_str(), value);
+}
+
+static void android_os_Trace_nativeTraceBegin(JNIEnv* env, jclass clazz,
+        jlong tag, jstring nameStr) {
+    ScopedUtfChars name(env, nameStr);
+    Tracer::traceBegin(tag, name.c_str());
+}
+
+static void android_os_Trace_nativeTraceEnd(JNIEnv* env, jclass clazz,
+        jlong tag) {
+    Tracer::traceEnd(tag);
+}
+
+static JNINativeMethod gTraceMethods[] = {
+    /* name, signature, funcPtr */
+    { "nativeGetEnabledTags",
+            "()J",
+            (void*)android_os_Trace_nativeGetEnabledTags },
+    { "nativeTraceCounter",
+            "(JLjava/lang/String;I)V",
+            (void*)android_os_Trace_nativeTraceCounter },
+    { "nativeTraceBegin",
+            "(JLjava/lang/String;)V",
+            (void*)android_os_Trace_nativeTraceBegin },
+    { "nativeTraceEnd",
+            "(J)V",
+            (void*)android_os_Trace_nativeTraceEnd },
+};
+
+int register_android_os_Trace(JNIEnv* env) {
+    int res = jniRegisterNativeMethods(env, "android/os/Trace",
+            gTraceMethods, NELEM(gTraceMethods));
+    LOG_FATAL_IF(res < 0, "Unable to register native methods.");
+
+    return 0;
+}
+
+} // namespace android
diff --git a/libs/hwui/DisplayListRenderer.cpp b/libs/hwui/DisplayListRenderer.cpp
index d9b0e5a..18d0a70 100644
--- a/libs/hwui/DisplayListRenderer.cpp
+++ b/libs/hwui/DisplayListRenderer.cpp
@@ -1071,7 +1071,6 @@
 void DisplayListRenderer::finish() {
     insertRestoreToCount();
     insertTranlate();
-    OpenGLRenderer::finish();
 }
 
 void DisplayListRenderer::interrupt() {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarView.java
index d33ed3f..6574c7d 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarView.java
@@ -304,6 +304,8 @@
         if (DEBUG) {
             Slog.d(TAG, "reorient(): rot=" + mDisplay.getRotation());
         }
+
+        setNavigationIconHints(mNavigationIconHints, true);
     }
 
     @Override
diff --git a/services/input/InputDispatcher.cpp b/services/input/InputDispatcher.cpp
index 149c0d3..da3548f 100644
--- a/services/input/InputDispatcher.cpp
+++ b/services/input/InputDispatcher.cpp
@@ -15,6 +15,7 @@
  */
 
 #define LOG_TAG "InputDispatcher"
+#define ATRACE_TAG ATRACE_TAG_INPUT
 
 //#define LOG_NDEBUG 0
 
@@ -44,6 +45,7 @@
 
 #include "InputDispatcher.h"
 
+#include <utils/Trace.h>
 #include <cutils/log.h>
 #include <androidfw/PowerManager.h>
 
@@ -280,6 +282,7 @@
         } else {
             // Inbound queue has at least one entry.
             mPendingEvent = mInboundQueue.dequeueAtHead();
+            traceInboundQueueLengthLocked();
         }
 
         // Poke user activity for this event.
@@ -379,6 +382,7 @@
 bool InputDispatcher::enqueueInboundEventLocked(EventEntry* entry) {
     bool needWake = mInboundQueue.isEmpty();
     mInboundQueue.enqueueAtTail(entry);
+    traceInboundQueueLengthLocked();
 
     switch (entry->type) {
     case EventEntry::TYPE_KEY: {
@@ -572,6 +576,7 @@
         EventEntry* entry = mInboundQueue.dequeueAtHead();
         releaseInboundEventLocked(entry);
     }
+    traceInboundQueueLengthLocked();
 }
 
 void InputDispatcher::releasePendingEventLocked() {
@@ -1867,6 +1872,7 @@
 
     // Enqueue the dispatch entry.
     connection->outboundQueue.enqueueAtTail(dispatchEntry);
+    traceOutboundQueueLengthLocked(connection);
 }
 
 void InputDispatcher::startDispatchCycleLocked(nsecs_t currentTime,
@@ -1978,7 +1984,9 @@
 
         // Re-enqueue the event on the wait queue.
         connection->outboundQueue.dequeue(dispatchEntry);
+        traceOutboundQueueLengthLocked(connection);
         connection->waitQueue.enqueueAtTail(dispatchEntry);
+        traceWaitQueueLengthLocked(connection);
     }
 }
 
@@ -2009,7 +2017,9 @@
 
     // Clear the dispatch queues.
     drainDispatchQueueLocked(&connection->outboundQueue);
+    traceOutboundQueueLengthLocked(connection);
     drainDispatchQueueLocked(&connection->waitQueue);
+    traceWaitQueueLengthLocked(connection);
 
     // The connection appears to be unrecoverably broken.
     // Ignore already broken or zombie connections.
@@ -3311,8 +3321,10 @@
         // a few things.
         if (dispatchEntry == connection->findWaitQueueEntry(seq)) {
             connection->waitQueue.dequeue(dispatchEntry);
+            traceWaitQueueLengthLocked(connection);
             if (restartEvent && connection->status == Connection::STATUS_NORMAL) {
                 connection->outboundQueue.enqueueAtHead(dispatchEntry);
+                traceOutboundQueueLengthLocked(connection);
             } else {
                 releaseDispatchEntryLocked(dispatchEntry);
             }
@@ -3498,6 +3510,28 @@
     // TODO Write some statistics about how long we spend waiting.
 }
 
+void InputDispatcher::traceInboundQueueLengthLocked() {
+    if (ATRACE_ENABLED()) {
+        ATRACE_INT("iq", mInboundQueue.count());
+    }
+}
+
+void InputDispatcher::traceOutboundQueueLengthLocked(const sp<Connection>& connection) {
+    if (ATRACE_ENABLED()) {
+        char counterName[40];
+        snprintf(counterName, sizeof(counterName), "oq:%s", connection->getWindowName());
+        ATRACE_INT(counterName, connection->outboundQueue.count());
+    }
+}
+
+void InputDispatcher::traceWaitQueueLengthLocked(const sp<Connection>& connection) {
+    if (ATRACE_ENABLED()) {
+        char counterName[40];
+        snprintf(counterName, sizeof(counterName), "wq:%s", connection->getWindowName());
+        ATRACE_INT(counterName, connection->waitQueue.count());
+    }
+}
+
 void InputDispatcher::dump(String8& dump) {
     AutoMutex _l(mLock);
 
@@ -4014,6 +4048,16 @@
 InputDispatcher::Connection::~Connection() {
 }
 
+const char* InputDispatcher::Connection::getWindowName() const {
+    if (inputWindowHandle != NULL) {
+        return inputWindowHandle->getName().string();
+    }
+    if (monitor) {
+        return "monitor";
+    }
+    return "?";
+}
+
 const char* InputDispatcher::Connection::getStatusLabel() const {
     switch (status) {
     case STATUS_NORMAL:
diff --git a/services/input/InputDispatcher.h b/services/input/InputDispatcher.h
index 4b36480..91f7554 100644
--- a/services/input/InputDispatcher.h
+++ b/services/input/InputDispatcher.h
@@ -805,6 +805,7 @@
 
         inline const char* getInputChannelName() const { return inputChannel->getName().string(); }
 
+        const char* getWindowName() const;
         const char* getStatusLabel() const;
 
         DispatchEntry* findWaitQueueEntry(uint32_t seq);
@@ -1069,6 +1070,9 @@
     // Statistics gathering.
     void updateDispatchStatisticsLocked(nsecs_t currentTime, const EventEntry* entry,
             int32_t injectionResult, nsecs_t timeSpentWaitingForApplication);
+    void traceInboundQueueLengthLocked();
+    void traceOutboundQueueLengthLocked(const sp<Connection>& connection);
+    void traceWaitQueueLengthLocked(const sp<Connection>& connection);
 };
 
 /* Enqueues and dispatches input events, endlessly. */