Merge "Put a bandaid on a segfault in timed audio track handling."
diff --git a/core/java/android/hardware/SensorManager.java b/core/java/android/hardware/SensorManager.java
index aeb5d92..3fdf246 100644
--- a/core/java/android/hardware/SensorManager.java
+++ b/core/java/android/hardware/SensorManager.java
@@ -616,6 +616,7 @@
             Message msg = Message.obtain();
             msg.what = 0;
             msg.obj = t;
+            msg.setAsynchronous(true);
             mHandler.sendMessage(msg);
         }
     }
diff --git a/core/java/android/os/Handler.java b/core/java/android/os/Handler.java
index af2fa9b..610b3550 100644
--- a/core/java/android/os/Handler.java
+++ b/core/java/android/os/Handler.java
@@ -513,7 +513,7 @@
      * message queue.
      */
     public final void removeMessages(int what) {
-        mQueue.removeMessages(this, what, null, true);
+        mQueue.removeMessages(this, what, null);
     }
 
     /**
@@ -522,7 +522,7 @@
      * all messages will be removed.
      */
     public final void removeMessages(int what, Object object) {
-        mQueue.removeMessages(this, what, object, true);
+        mQueue.removeMessages(this, what, object);
     }
 
     /**
@@ -539,7 +539,7 @@
      * the message queue.
      */
     public final boolean hasMessages(int what) {
-        return mQueue.removeMessages(this, what, null, false);
+        return mQueue.hasMessages(this, what, null);
     }
 
     /**
@@ -547,7 +547,7 @@
      * whose obj is 'object' in the message queue.
      */
     public final boolean hasMessages(int what, Object object) {
-        return mQueue.removeMessages(this, what, object, false);
+        return mQueue.hasMessages(this, what, object);
     }
 
     // if we can get rid of this method, the handler need not remember its loop
diff --git a/core/java/android/os/Looper.java b/core/java/android/os/Looper.java
index 5607f7f..a06aadb6 100644
--- a/core/java/android/os/Looper.java
+++ b/core/java/android/os/Looper.java
@@ -55,13 +55,13 @@
 
     // sThreadLocal.get() will return null unless you've called prepare().
     static final ThreadLocal<Looper> sThreadLocal = new ThreadLocal<Looper>();
+    private static Looper sMainLooper;  // guarded by Looper.class
 
     final MessageQueue mQueue;
     final Thread mThread;
     volatile boolean mRun;
 
-    private Printer mLogging = null;
-    private static Looper mMainLooper = null;  // guarded by Looper.class
+    private Printer mLogging;
 
      /** Initialize the current thread as a looper.
       * This gives you a chance to create handlers that then reference
@@ -70,10 +70,14 @@
       * {@link #quit()}.
       */
     public static void prepare() {
+        prepare(true);
+    }
+
+    private static void prepare(boolean quitAllowed) {
         if (sThreadLocal.get() != null) {
             throw new RuntimeException("Only one Looper may be created per thread");
         }
-        sThreadLocal.set(new Looper());
+        sThreadLocal.set(new Looper(quitAllowed));
     }
 
     /**
@@ -83,19 +87,21 @@
      * to call this function yourself.  See also: {@link #prepare()}
      */
     public static void prepareMainLooper() {
-        prepare();
-        setMainLooper(myLooper());
-        myLooper().mQueue.mQuitAllowed = false;
-    }
-
-    private synchronized static void setMainLooper(Looper looper) {
-        mMainLooper = looper;
+        prepare(false);
+        synchronized (Looper.class) {
+            if (sMainLooper != null) {
+                throw new IllegalStateException("The main Looper has already been prepared.");
+            }
+            sMainLooper = myLooper();
+        }
     }
 
     /** Returns the application's main looper, which lives in the main thread of the application.
      */
-    public synchronized static Looper getMainLooper() {
-        return mMainLooper;
+    public static Looper getMainLooper() {
+        synchronized (Looper.class) {
+            return sMainLooper;
+        }
     }
 
     /**
@@ -103,63 +109,61 @@
      * {@link #quit()} to end the loop.
      */
     public static void loop() {
-        Looper me = myLooper();
+        final Looper me = myLooper();
         if (me == null) {
             throw new RuntimeException("No Looper; Looper.prepare() wasn't called on this thread.");
         }
-        MessageQueue queue = me.mQueue;
-        
+        final MessageQueue queue = me.mQueue;
+
         // Make sure the identity of this thread is that of the local process,
         // and keep track of what that identity token actually is.
         Binder.clearCallingIdentity();
         final long ident = Binder.clearCallingIdentity();
-        
-        while (true) {
+
+        for (;;) {
             Message msg = queue.next(); // might block
-            if (msg != null) {
-                if (msg.target == null) {
-                    // No target is a magic identifier for the quit message.
-                    return;
-                }
-
-                long wallStart = 0;
-                long threadStart = 0;
-
-                // This must be in a local variable, in case a UI event sets the logger
-                Printer logging = me.mLogging;
-                if (logging != null) {
-                    logging.println(">>>>> Dispatching to " + msg.target + " " +
-                            msg.callback + ": " + msg.what);
-                    wallStart = SystemClock.currentTimeMicro();
-                    threadStart = SystemClock.currentThreadTimeMicro();
-                }
-
-                msg.target.dispatchMessage(msg);
-
-                if (logging != null) {
-                    long wallTime = SystemClock.currentTimeMicro() - wallStart;
-                    long threadTime = SystemClock.currentThreadTimeMicro() - threadStart;
-
-                    logging.println("<<<<< Finished to " + msg.target + " " + msg.callback);
-                    if (logging instanceof Profiler) {
-                        ((Profiler) logging).profile(msg, wallStart, wallTime,
-                                threadStart, threadTime);
-                    }
-                }
-
-                // Make sure that during the course of dispatching the
-                // identity of the thread wasn't corrupted.
-                final long newIdent = Binder.clearCallingIdentity();
-                if (ident != newIdent) {
-                    Log.wtf(TAG, "Thread identity changed from 0x"
-                            + Long.toHexString(ident) + " to 0x"
-                            + Long.toHexString(newIdent) + " while dispatching to "
-                            + msg.target.getClass().getName() + " "
-                            + msg.callback + " what=" + msg.what);
-                }
-                
-                msg.recycle();
+            if (msg == null) {
+                // No message indicates that the message queue is quitting.
+                return;
             }
+
+            long wallStart = 0;
+            long threadStart = 0;
+
+            // This must be in a local variable, in case a UI event sets the logger
+            Printer logging = me.mLogging;
+            if (logging != null) {
+                logging.println(">>>>> Dispatching to " + msg.target + " " +
+                        msg.callback + ": " + msg.what);
+                wallStart = SystemClock.currentTimeMicro();
+                threadStart = SystemClock.currentThreadTimeMicro();
+            }
+
+            msg.target.dispatchMessage(msg);
+
+            if (logging != null) {
+                long wallTime = SystemClock.currentTimeMicro() - wallStart;
+                long threadTime = SystemClock.currentThreadTimeMicro() - threadStart;
+
+                logging.println("<<<<< Finished to " + msg.target + " " + msg.callback);
+                if (logging instanceof Profiler) {
+                    ((Profiler) logging).profile(msg, wallStart, wallTime,
+                            threadStart, threadTime);
+                }
+            }
+
+            // Make sure that during the course of dispatching the
+            // identity of the thread wasn't corrupted.
+            final long newIdent = Binder.clearCallingIdentity();
+            if (ident != newIdent) {
+                Log.wtf(TAG, "Thread identity changed from 0x"
+                        + Long.toHexString(ident) + " to 0x"
+                        + Long.toHexString(newIdent) + " while dispatching to "
+                        + msg.target.getClass().getName() + " "
+                        + msg.callback + " what=" + msg.what);
+            }
+
+            msg.recycle();
         }
     }
 
@@ -193,18 +197,61 @@
         return myLooper().mQueue;
     }
 
-    private Looper() {
-        mQueue = new MessageQueue();
+    private Looper(boolean quitAllowed) {
+        mQueue = new MessageQueue(quitAllowed);
         mRun = true;
         mThread = Thread.currentThread();
     }
 
+    /**
+     * Quits the looper.
+     *
+     * Causes the {@link #loop} method to terminate as soon as possible.
+     */
     public void quit() {
-        Message msg = Message.obtain();
-        // NOTE: By enqueueing directly into the message queue, the
-        // message is left with a null target.  This is how we know it is
-        // a quit message.
-        mQueue.enqueueMessage(msg, 0);
+        mQueue.quit();
+    }
+
+    /**
+     * Posts a synchronization barrier to the Looper's message queue.
+     *
+     * Message processing occurs as usual until the message queue encounters the
+     * synchronization barrier that has been posted.  When the barrier is encountered,
+     * later synchronous messages in the queue are stalled (prevented from being executed)
+     * until the barrier is released by calling {@link #removeSyncBarrier} and specifying
+     * the token that identifies the synchronization barrier.
+     *
+     * This method is used to immediately postpone execution of all subsequently posted
+     * synchronous messages until a condition is met that releases the barrier.
+     * Asynchronous messages (see {@link Message#isAsynchronous} are exempt from the barrier
+     * and continue to be processed as usual.
+     *
+     * This call must be always matched by a call to {@link #removeSyncBarrier} with
+     * the same token to ensure that the message queue resumes normal operation.
+     * Otherwise the application will probably hang!
+     *
+     * @return A token that uniquely identifies the barrier.  This token must be
+     * passed to {@link #removeSyncBarrier} to release the barrier.
+     *
+     * @hide
+     */
+    public final int postSyncBarrier() {
+        return mQueue.enqueueSyncBarrier(SystemClock.uptimeMillis());
+    }
+
+
+    /**
+     * Removes a synchronization barrier.
+     *
+     * @param token The synchronization barrier token that was returned by
+     * {@link #postSyncBarrier}.
+     *
+     * @throws IllegalStateException if the barrier was not found.
+     *
+     * @hide
+     */
+    public final void removeSyncBarrier(int token) {
+        mQueue.removeSyncBarrier(token);
     }
 
     /**
diff --git a/core/java/android/os/MessageQueue.java b/core/java/android/os/MessageQueue.java
index 11dc124..64027ef 100644
--- a/core/java/android/os/MessageQueue.java
+++ b/core/java/android/os/MessageQueue.java
@@ -30,21 +30,24 @@
  * {@link Looper#myQueue() Looper.myQueue()}.
  */
 public class MessageQueue {
+    // True if the message queue can be quit.
+    private final boolean mQuitAllowed;
+
+    @SuppressWarnings("unused")
+    private int mPtr; // used by native code
+
     Message mMessages;
     private final ArrayList<IdleHandler> mIdleHandlers = new ArrayList<IdleHandler>();
     private IdleHandler[] mPendingIdleHandlers;
     private boolean mQuiting;
-    boolean mQuitAllowed = true;
 
     // Indicates whether next() is blocked waiting in pollOnce() with a non-zero timeout.
     private boolean mBlocked;
 
-    // Indicates the barrier nesting level.
-    private int mBarrierNestCount;
+    // The next barrier token.
+    // Barriers are indicated by messages with a null target whose arg1 field carries the token.
+    private int mNextBarrierToken;
 
-    @SuppressWarnings("unused")
-    private int mPtr; // used by native code
-    
     private native void nativeInit();
     private native void nativeDestroy();
     private native void nativePollOnce(int ptr, int timeoutMillis);
@@ -97,56 +100,11 @@
         }
     }
 
-    /**
-     * Acquires a synchronization barrier.
-     *
-     * While a synchronization barrier is active, only asynchronous messages are
-     * permitted to execute.  Synchronous messages are retained but are not executed
-     * until the synchronization barrier is released.
-     *
-     * This method is used to immediately postpone execution of all synchronous messages
-     * until a condition is met that releases the barrier.  Asynchronous messages are
-     * exempt from the barrier and continue to be executed as usual.
-     *
-     * This call nests and must be matched by an equal number of calls to
-     * {@link #releaseSyncBarrier}.
-     *
-     * @hide
-     */
-    public final void acquireSyncBarrier() {
-        synchronized (this) {
-            mBarrierNestCount += 1;
-        }
-    }
-
-    /**
-     * Releases a synchronization barrier.
-     *
-     * This class undoes one invocation of {@link #acquireSyncBarrier}.
-     *
-     * @throws IllegalStateException if the barrier is not acquired.
-     *
-     * @hide
-     */
-    public final void releaseSyncBarrier() {
-        synchronized (this) {
-            if (mBarrierNestCount == 0) {
-                throw new IllegalStateException("The message queue synchronization barrier "
-                        + "has not been acquired.");
-            }
-
-            mBarrierNestCount -= 1;
-            if (!mBlocked || mMessages == null) {
-                return;
-            }
-        }
-        nativeWake(mPtr);
-    }
-
-    MessageQueue() {
+    MessageQueue(boolean quitAllowed) {
+        mQuitAllowed = quitAllowed;
         nativeInit();
     }
-    
+
     @Override
     protected void finalize() throws Throwable {
         try {
@@ -167,26 +125,26 @@
             nativePollOnce(mPtr, nextPollTimeoutMillis);
 
             synchronized (this) {
+                if (mQuiting) {
+                    return null;
+                }
+
                 // Try to retrieve the next message.  Return if found.
                 final long now = SystemClock.uptimeMillis();
-
                 Message prevMsg = null;
                 Message msg = mMessages;
-                for (;;) {
-                    if (msg == null) {
-                        // No more messages.
-                        nextPollTimeoutMillis = -1;
-                        break;
-                    }
-
-                    final long when = msg.when;
-                    if (now < when) {
+                if (msg != null && msg.target == null) {
+                    // Stalled by a barrier.  Find the next asynchronous message in the queue.
+                    do {
+                        prevMsg = msg;
+                        msg = msg.next;
+                    } while (msg != null && !msg.isAsynchronous());
+                }
+                if (msg != null) {
+                    if (now < msg.when) {
                         // Next message is not ready.  Set a timeout to wake up when it is ready.
-                        nextPollTimeoutMillis = (int) Math.min(when - now, Integer.MAX_VALUE);
-                        break;
-                    }
-
-                    if (mBarrierNestCount == 0 || msg.isAsynchronous()) {
+                        nextPollTimeoutMillis = (int) Math.min(msg.when - now, Integer.MAX_VALUE);
+                    } else {
                         // Got a message.
                         mBlocked = false;
                         if (prevMsg != null) {
@@ -199,16 +157,16 @@
                         msg.markInUse();
                         return msg;
                     }
-
-                    // We have a message that we could return except that it is
-                    // blocked by the sync barrier.  In particular, this means that
-                    // we are not idle yet, so we do not want to run the idle handlers.
-                    prevMsg = msg;
-                    msg = msg.next;
+                } else {
+                    // No more messages.
+                    nextPollTimeoutMillis = -1;
                 }
 
                 // If first time idle, then get the number of idlers to run.
-                if (pendingIdleHandlerCount < 0 && msg == mMessages) {
+                // Idle handles only run if the queue is empty or if the first message
+                // in the queue (possibly a barrier) is due to be handled in the future.
+                if (pendingIdleHandlerCount < 0
+                        && (mMessages == null || now < mMessages.when)) {
                     pendingIdleHandlerCount = mIdleHandlers.size();
                 }
                 if (pendingIdleHandlerCount <= 0) {
@@ -252,27 +210,94 @@
         }
     }
 
+    final void quit() {
+        if (!mQuitAllowed) {
+            throw new RuntimeException("Main thread not allowed to quit.");
+        }
+
+        synchronized (this) {
+            if (mQuiting) {
+                return;
+            }
+            mQuiting = true;
+        }
+        nativeWake(mPtr);
+    }
+
+    final int enqueueSyncBarrier(long when) {
+        // Enqueue a new sync barrier token.
+        // We don't need to wake the queue because the purpose of a barrier is to stall it.
+        synchronized (this) {
+            final int token = mNextBarrierToken++;
+            final Message msg = Message.obtain();
+            msg.arg1 = token;
+
+            Message prev = null;
+            Message p = mMessages;
+            if (when != 0) {
+                while (p != null && p.when <= when) {
+                    prev = p;
+                    p = p.next;
+                }
+            }
+            if (prev != null) { // invariant: p == prev.next
+                msg.next = p;
+                prev.next = msg;
+            } else {
+                msg.next = p;
+                mMessages = msg;
+            }
+            return token;
+        }
+    }
+
+    final void removeSyncBarrier(int token) {
+        // Remove a sync barrier token from the queue.
+        // If the queue is no longer stalled by a barrier then wake it.
+        final boolean needWake;
+        synchronized (this) {
+            Message prev = null;
+            Message p = mMessages;
+            while (p != null && (p.target != null || p.arg1 != token)) {
+                prev = p;
+                p = p.next;
+            }
+            if (p == null) {
+                throw new IllegalStateException("The specified message queue synchronization "
+                        + " barrier token has not been posted or has already been removed.");
+            }
+            if (prev != null) {
+                prev.next = p.next;
+                needWake = false;
+            } else {
+                mMessages = p.next;
+                needWake = mMessages == null || mMessages.target != null;
+            }
+            p.recycle();
+        }
+        if (needWake) {
+            nativeWake(mPtr);
+        }
+    }
+
     final boolean enqueueMessage(Message msg, long when) {
         if (msg.isInUse()) {
-            throw new AndroidRuntimeException(msg
-                    + " This message is already in use.");
+            throw new AndroidRuntimeException(msg + " This message is already in use.");
         }
-        if (msg.target == null && !mQuitAllowed) {
-            throw new RuntimeException("Main thread not allowed to quit");
+        if (msg.target == null) {
+            throw new AndroidRuntimeException("Message must have a target.");
         }
-        final boolean needWake;
+
+        boolean needWake;
         synchronized (this) {
             if (mQuiting) {
                 RuntimeException e = new RuntimeException(
-                    msg.target + " sending message to a Handler on a dead thread");
+                        msg.target + " sending message to a Handler on a dead thread");
                 Log.w("MessageQueue", e.getMessage(), e);
                 return false;
-            } else if (msg.target == null) {
-                mQuiting = true;
             }
 
             msg.when = when;
-            //Log.d("MessageQueue", "Enqueing: " + msg);
             Message p = mMessages;
             if (p == null || when == 0 || when < p.when) {
                 // New head, wake up the event queue if blocked.
@@ -281,18 +306,22 @@
                 needWake = mBlocked;
             } else {
                 // Inserted within the middle of the queue.  Usually we don't have to wake
-                // up the event queue unless the message is asynchronous and it might be
-                // possible for it to be returned out of sequence relative to an earlier
-                // synchronous message at the head of the queue.
-                Message prev = null;
-                while (p != null && p.when <= when) {
+                // up the event queue unless there is a barrier at the head of the queue
+                // and the message is the earliest asynchronous message in the queue.
+                needWake = mBlocked && p.target == null && msg.isAsynchronous();
+                Message prev;
+                for (;;) {
                     prev = p;
                     p = p.next;
+                    if (p == null || when < p.when) {
+                        break;
+                    }
+                    if (needWake && p.isAsynchronous()) {
+                        needWake = false;
+                    }
                 }
-                msg.next = prev.next;
+                msg.next = p; // invariant: p == prev.next
                 prev.next = msg;
-                needWake = mBlocked && mBarrierNestCount != 0 && msg.isAsynchronous()
-                        && !mMessages.isAsynchronous();
             }
         }
         if (needWake) {
@@ -301,17 +330,34 @@
         return true;
     }
 
-    final boolean removeMessages(Handler h, int what, Object object,
-            boolean doRemove) {
+    final boolean hasMessages(Handler h, int what, Object object) {
+        if (h == null) {
+            return false;
+        }
+
         synchronized (this) {
             Message p = mMessages;
-            boolean found = false;
+            while (p != null) {
+                if (p.target == h && p.what == what && (object == null || p.obj == object)) {
+                    return true;
+                }
+                p = p.next;
+            }
+            return false;
+        }
+    }
+
+    final void removeMessages(Handler h, int what, Object object) {
+        if (h == null) {
+            return;
+        }
+
+        synchronized (this) {
+            Message p = mMessages;
 
             // Remove all messages at front.
             while (p != null && p.target == h && p.what == what
                    && (object == null || p.obj == object)) {
-                if (!doRemove) return true;
-                found = true;
                 Message n = p.next;
                 mMessages = n;
                 p.recycle();
@@ -324,8 +370,6 @@
                 if (n != null) {
                     if (n.target == h && n.what == what
                         && (object == null || n.obj == object)) {
-                        if (!doRemove) return true;
-                        found = true;
                         Message nn = n.next;
                         n.recycle();
                         p.next = nn;
@@ -334,13 +378,11 @@
                 }
                 p = n;
             }
-            
-            return found;
         }
     }
 
     final void removeMessages(Handler h, Runnable r, Object object) {
-        if (r == null) {
+        if (h == null || r == null) {
             return;
         }
 
@@ -374,6 +416,10 @@
     }
 
     final void removeCallbacksAndMessages(Handler h, Object object) {
+        if (h == null) {
+            return;
+        }
+
         synchronized (this) {
             Message p = mMessages;
 
@@ -401,16 +447,4 @@
             }
         }
     }
-
-    /*
-    private void dumpQueue_l()
-    {
-        Message p = mMessages;
-        System.out.println(this + "  queue is:");
-        while (p != null) {
-            System.out.println("            " + p);
-            p = p.next;
-        }
-    }
-    */
 }
diff --git a/core/java/android/view/Choreographer.java b/core/java/android/view/Choreographer.java
index a74b737..42c3913 100644
--- a/core/java/android/view/Choreographer.java
+++ b/core/java/android/view/Choreographer.java
@@ -235,8 +235,9 @@
                 if (isRunningOnLooperThreadLocked()) {
                     doScheduleVsyncLocked();
                 } else {
-                    mHandler.sendMessageAtFrontOfQueue(
-                            mHandler.obtainMessage(MSG_DO_SCHEDULE_VSYNC));
+                    Message msg = mHandler.obtainMessage(MSG_DO_SCHEDULE_VSYNC);
+                    msg.setAsynchronous(true);
+                    mHandler.sendMessageAtFrontOfQueue(msg);
                 }
             } else {
                 final long now = SystemClock.uptimeMillis();
@@ -244,7 +245,9 @@
                 if (DEBUG) {
                     Log.d(TAG, "Scheduling animation in " + (nextAnimationTime - now) + " ms.");
                 }
-                mHandler.sendEmptyMessageAtTime(MSG_DO_ANIMATION, nextAnimationTime);
+                Message msg = mHandler.obtainMessage(MSG_DO_ANIMATION);
+                msg.setAsynchronous(true);
+                mHandler.sendMessageAtTime(msg, nextAnimationTime);
             }
         }
     }
@@ -258,7 +261,9 @@
                 if (DEBUG) {
                     Log.d(TAG, "Scheduling draw immediately.");
                 }
-                mHandler.sendEmptyMessage(MSG_DO_DRAW);
+                Message msg = mHandler.obtainMessage(MSG_DO_DRAW);
+                msg.setAsynchronous(true);
+                mHandler.sendMessage(msg);
             }
         }
     }
diff --git a/core/java/android/view/SurfaceView.java b/core/java/android/view/SurfaceView.java
index 6726c56e..c658a80 100644
--- a/core/java/android/view/SurfaceView.java
+++ b/core/java/android/view/SurfaceView.java
@@ -384,7 +384,7 @@
         if (!mHaveFrame) {
             return;
         }
-        ViewRootImpl viewRoot = (ViewRootImpl) getRootView().getParent();
+        ViewRootImpl viewRoot = getViewRootImpl();
         if (viewRoot != null) {
             mTranslator = viewRoot.mTranslator;
         }
diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java
index 6b7244a..6c27c9f 100644
--- a/core/java/android/view/View.java
+++ b/core/java/android/view/View.java
@@ -601,6 +601,8 @@
  * @attr ref android.R.styleable#View_paddingLeft
  * @attr ref android.R.styleable#View_paddingRight
  * @attr ref android.R.styleable#View_paddingTop
+ * @attr ref android.R.styleable#View_paddingStart
+ * @attr ref android.R.styleable#View_paddingEnd
  * @attr ref android.R.styleable#View_saveEnabled
  * @attr ref android.R.styleable#View_rotation
  * @attr ref android.R.styleable#View_rotationX
@@ -5440,12 +5442,6 @@
         return true;
     }
 
-    /** Gets the ViewAncestor, or null if not attached. */
-    /*package*/ ViewRootImpl getViewRootImpl() {
-        View root = getRootView();
-        return root != null ? (ViewRootImpl)root.getParent() : null;
-    }
-
     /**
      * Call this to try to give focus to a specific view or to one of its descendants. This is a
      * special variant of {@link #requestFocus() } that will allow views that are not focuable in
@@ -8683,6 +8679,18 @@
     }
 
     /**
+     * Gets the view root associated with the View.
+     * @return The view root, or null if none.
+     * @hide
+     */
+    public ViewRootImpl getViewRootImpl() {
+        if (mAttachInfo != null) {
+            return mAttachInfo.mViewRootImpl;
+        }
+        return null;
+    }
+
+    /**
      * <p>Causes the Runnable to be added to the message queue.
      * The runnable will be run on the user interface thread.</p>
      * 
@@ -8696,17 +8704,13 @@
      *         looper processing the message queue is exiting.
      */
     public boolean post(Runnable action) {
-        Handler handler;
-        AttachInfo attachInfo = mAttachInfo;
+        final AttachInfo attachInfo = mAttachInfo;
         if (attachInfo != null) {
-            handler = attachInfo.mHandler;
-        } else {
-            // Assume that post will succeed later
-            ViewRootImpl.getRunQueue().post(action);
-            return true;
+            return attachInfo.mHandler.post(action);
         }
-
-        return handler.post(action);
+        // Assume that post will succeed later
+        ViewRootImpl.getRunQueue().post(action);
+        return true;
     }
 
     /**
@@ -8729,17 +8733,13 @@
      *         occurs then the message will be dropped.
      */
     public boolean postDelayed(Runnable action, long delayMillis) {
-        Handler handler;
-        AttachInfo attachInfo = mAttachInfo;
+        final AttachInfo attachInfo = mAttachInfo;
         if (attachInfo != null) {
-            handler = attachInfo.mHandler;
-        } else {
-            // Assume that post will succeed later
-            ViewRootImpl.getRunQueue().postDelayed(action, delayMillis);
-            return true;
+            return attachInfo.mHandler.postDelayed(action, delayMillis);
         }
-
-        return handler.postDelayed(action, delayMillis);
+        // Assume that post will succeed later
+        ViewRootImpl.getRunQueue().postDelayed(action, delayMillis);
+        return true;
     }
 
     /**
@@ -8756,17 +8756,13 @@
      *         (for instance, if the Runnable was not in the queue already.)
      */
     public boolean removeCallbacks(Runnable action) {
-        Handler handler;
-        AttachInfo attachInfo = mAttachInfo;
+        final AttachInfo attachInfo = mAttachInfo;
         if (attachInfo != null) {
-            handler = attachInfo.mHandler;
+            attachInfo.mHandler.removeCallbacks(action);
         } else {
             // Assume that post will succeed later
             ViewRootImpl.getRunQueue().removeCallbacks(action);
-            return true;
         }
-
-        handler.removeCallbacks(action);
         return true;
     }
 
@@ -8815,12 +8811,9 @@
     public void postInvalidateDelayed(long delayMilliseconds) {
         // We try only with the AttachInfo because there's no point in invalidating
         // if we are not attached to our window
-        AttachInfo attachInfo = mAttachInfo;
+        final AttachInfo attachInfo = mAttachInfo;
         if (attachInfo != null) {
-            Message msg = Message.obtain();
-            msg.what = AttachInfo.INVALIDATE_MSG;
-            msg.obj = this;
-            attachInfo.mHandler.sendMessageDelayed(msg, delayMilliseconds);
+            attachInfo.mViewRootImpl.dispatchInvalidateDelayed(this, delayMilliseconds);
         }
     }
 
@@ -8843,7 +8836,7 @@
 
         // We try only with the AttachInfo because there's no point in invalidating
         // if we are not attached to our window
-        AttachInfo attachInfo = mAttachInfo;
+        final AttachInfo attachInfo = mAttachInfo;
         if (attachInfo != null) {
             final AttachInfo.InvalidateInfo info = AttachInfo.InvalidateInfo.acquire();
             info.target = this;
@@ -8852,10 +8845,7 @@
             info.right = right;
             info.bottom = bottom;
 
-            final Message msg = Message.obtain();
-            msg.what = AttachInfo.INVALIDATE_RECT_MSG;
-            msg.obj = info;
-            attachInfo.mHandler.sendMessageDelayed(msg, delayMilliseconds);
+            attachInfo.mViewRootImpl.dispatchInvalidateRectDelayed(info, delayMilliseconds);
         }
     }
 
@@ -9700,7 +9690,7 @@
         }
 
         if (mAttachInfo != null) {
-            mAttachInfo.mHandler.removeMessages(AttachInfo.INVALIDATE_MSG, this);
+            mAttachInfo.mViewRootImpl.cancelInvalidate(this);
         }
 
         mCurrentAnimation = null;
@@ -14989,24 +14979,17 @@
         Canvas mCanvas;
 
         /**
+         * The view root impl.
+         */
+        final ViewRootImpl mViewRootImpl;
+
+        /**
          * A Handler supplied by a view's {@link android.view.ViewRootImpl}. This
          * handler can be used to pump events in the UI events queue.
          */
         final Handler mHandler;
 
         /**
-         * Identifier for messages requesting the view to be invalidated.
-         * Such messages should be sent to {@link #mHandler}.
-         */
-        static final int INVALIDATE_MSG = 0x1;
-
-        /**
-         * Identifier for messages requesting the view to invalidate a region.
-         * Such messages should be sent to {@link #mHandler}.
-         */
-        static final int INVALIDATE_RECT_MSG = 0x2;
-
-        /**
          * Temporary for use in computing invalidate rectangles while
          * calling up the hierarchy.
          */
@@ -15034,10 +15017,11 @@
          * @param handler the events handler the view must use
          */
         AttachInfo(IWindowSession session, IWindow window,
-                Handler handler, Callbacks effectPlayer) {
+                ViewRootImpl viewRootImpl, Handler handler, Callbacks effectPlayer) {
             mSession = session;
             mWindow = window;
             mWindowToken = window.asBinder();
+            mViewRootImpl = viewRootImpl;
             mHandler = handler;
             mRootCallbacks = effectPlayer;
         }
diff --git a/core/java/android/view/ViewDebug.java b/core/java/android/view/ViewDebug.java
index c1db572..2a17845 100644
--- a/core/java/android/view/ViewDebug.java
+++ b/core/java/android/view/ViewDebug.java
@@ -375,7 +375,7 @@
     }
 
     private static BufferedWriter sHierarchyTraces;
-    private static ViewRootImpl sHierarhcyRoot;
+    private static ViewRootImpl sHierarchyRoot;
     private static String sHierarchyTracePrefix;
 
     /**
@@ -855,7 +855,7 @@
             return;
         }
 
-        if (sHierarhcyRoot != null) {
+        if (sHierarchyRoot != null) {
             throw new IllegalStateException("You must call stopHierarchyTracing() before running" +
                 " a new trace!");
         }
@@ -874,7 +874,7 @@
             return;
         }
 
-        sHierarhcyRoot = (ViewRootImpl) view.getRootView().getParent();
+        sHierarchyRoot = view.getViewRootImpl();
     }
 
     /**
@@ -896,7 +896,7 @@
             return;
         }
 
-        if (sHierarhcyRoot == null || sHierarchyTraces == null) {
+        if (sHierarchyRoot == null || sHierarchyTraces == null) {
             throw new IllegalStateException("You must call startHierarchyTracing() before" +
                 " stopHierarchyTracing()!");
         }
@@ -921,7 +921,7 @@
             return;
         }
 
-        View view = sHierarhcyRoot.getView();
+        View view = sHierarchyRoot.getView();
         if (view instanceof ViewGroup) {
             ViewGroup group = (ViewGroup) view;
             dumpViewHierarchy(group, out, 0);
@@ -932,7 +932,7 @@
             }
         }
 
-        sHierarhcyRoot = null;
+        sHierarchyRoot = null;
     }
 
     static void dispatchCommand(View view, String command, String parameters,
diff --git a/core/java/android/view/ViewRootImpl.java b/core/java/android/view/ViewRootImpl.java
index fbcb423..d41d168 100644
--- a/core/java/android/view/ViewRootImpl.java
+++ b/core/java/android/view/ViewRootImpl.java
@@ -61,6 +61,7 @@
 import android.util.Pools;
 import android.util.Slog;
 import android.util.TypedValue;
+import android.view.View.AttachInfo;
 import android.view.View.MeasureSpec;
 import android.view.accessibility.AccessibilityEvent;
 import android.view.accessibility.AccessibilityInteractionClient;
@@ -96,7 +97,7 @@
  * {@hide}
  */
 @SuppressWarnings({"EmptyCatchBlock", "PointlessBooleanExpression"})
-public final class ViewRootImpl extends Handler implements ViewParent,
+public final class ViewRootImpl implements ViewParent,
         View.AttachInfo.Callbacks, HardwareRenderer.HardwareDrawCallbacks {
     private static final String TAG = "ViewRootImpl";
     private static final boolean DBG = false;
@@ -212,6 +213,7 @@
     final Rect mVisRect; // used to retrieve visible rect of focused view.
 
     boolean mTraversalScheduled;
+    int mTraversalBarrier;
     long mLastTraversalFinishedTimeNanos;
     long mLastDrawFinishedTimeNanos;
     boolean mWillDrawSoon;
@@ -379,7 +381,7 @@
             new AccessibilityInteractionConnectionManager();
         mAccessibilityManager.addAccessibilityStateChangeListener(
                 mAccessibilityInteractionConnectionManager);
-        mAttachInfo = new View.AttachInfo(sWindowSession, mWindow, this, this);
+        mAttachInfo = new View.AttachInfo(sWindowSession, mWindow, this, mHandler, this);
         mViewConfiguration = ViewConfiguration.get(context);
         mDensity = context.getResources().getDisplayMetrics().densityDpi;
         mFallbackEventHandler = PolicyManager.makeNewFallbackEventHandler(context);
@@ -838,22 +840,28 @@
     public void scheduleTraversals() {
         if (!mTraversalScheduled) {
             mTraversalScheduled = true;
+            mTraversalBarrier = mHandler.getLooper().postSyncBarrier();
             scheduleFrame();
         }
     }
 
     public void unscheduleTraversals() {
-        mTraversalScheduled = false;
+        if (mTraversalScheduled) {
+            mTraversalScheduled = false;
+            mHandler.getLooper().removeSyncBarrier(mTraversalBarrier);
+        }
     }
 
     void scheduleFrame() {
         if (!mFrameScheduled) {
-            mChoreographer.postDrawCallback(mFrameRunnable);
             mFrameScheduled = true;
+            mChoreographer.postDrawCallback(mFrameRunnable);
         }
     }
 
     void unscheduleFrame() {
+        unscheduleTraversals();
+
         if (mFrameScheduled) {
             mFrameScheduled = false;
             mChoreographer.removeDrawCallback(mFrameRunnable);
@@ -868,6 +876,7 @@
 
         if (mTraversalScheduled) {
             mTraversalScheduled = false;
+            mHandler.getLooper().removeSyncBarrier(mTraversalBarrier);
             doTraversal();
         }
     }
@@ -1929,7 +1938,7 @@
                 sFirstDrawComplete = true;
                 final int count = sFirstDrawHandlers.size();
                 for (int i = 0; i< count; i++) {
-                    post(sFirstDrawHandlers.get(i));
+                    mHandler.post(sFirstDrawHandlers.get(i));
                 }
             }
         }
@@ -2441,283 +2450,289 @@
         }
     }
 
-    public final static int DIE = 1001;
-    public final static int RESIZED = 1002;
-    public final static int RESIZED_REPORT = 1003;
-    public final static int WINDOW_FOCUS_CHANGED = 1004;
-    public final static int DISPATCH_KEY = 1005;
-    public final static int DISPATCH_APP_VISIBILITY = 1008;
-    public final static int DISPATCH_GET_NEW_SURFACE = 1009;
-    public final static int IME_FINISHED_EVENT = 1010;
-    public final static int DISPATCH_KEY_FROM_IME = 1011;
-    public final static int FINISH_INPUT_CONNECTION = 1012;
-    public final static int CHECK_FOCUS = 1013;
-    public final static int CLOSE_SYSTEM_DIALOGS = 1014;
-    public final static int DISPATCH_DRAG_EVENT = 1015;
-    public final static int DISPATCH_DRAG_LOCATION_EVENT = 1016;
-    public final static int DISPATCH_SYSTEM_UI_VISIBILITY = 1017;
-    public final static int DISPATCH_GENERIC_MOTION = 1018;
-    public final static int UPDATE_CONFIGURATION = 1019;
-    public final static int DO_PERFORM_ACCESSIBILITY_ACTION = 1020;
-    public final static int DO_FIND_ACCESSIBLITY_NODE_INFO_BY_ACCESSIBILITY_ID = 1021;
-    public final static int DO_FIND_ACCESSIBLITY_NODE_INFO_BY_VIEW_ID = 1022;
-    public final static int DO_FIND_ACCESSIBLITY_NODE_INFO_BY_TEXT = 1023;
-    public final static int DO_PROCESS_INPUT_EVENTS = 1024;
+    private final static int MSG_INVALIDATE = 1;
+    private final static int MSG_INVALIDATE_RECT = 2;
+    private final static int MSG_DIE = 3;
+    private final static int MSG_RESIZED = 4;
+    private final static int MSG_RESIZED_REPORT = 5;
+    private final static int MSG_WINDOW_FOCUS_CHANGED = 6;
+    private final static int MSG_DISPATCH_KEY = 7;
+    private final static int MSG_DISPATCH_APP_VISIBILITY = 8;
+    private final static int MSG_DISPATCH_GET_NEW_SURFACE = 9;
+    private final static int MSG_IME_FINISHED_EVENT = 10;
+    private final static int MSG_DISPATCH_KEY_FROM_IME = 11;
+    private final static int MSG_FINISH_INPUT_CONNECTION = 12;
+    private final static int MSG_CHECK_FOCUS = 13;
+    private final static int MSG_CLOSE_SYSTEM_DIALOGS = 14;
+    private final static int MSG_DISPATCH_DRAG_EVENT = 15;
+    private final static int MSG_DISPATCH_DRAG_LOCATION_EVENT = 16;
+    private final static int MSG_DISPATCH_SYSTEM_UI_VISIBILITY = 17;
+    private final static int MSG_UPDATE_CONFIGURATION = 18;
+    private final static int MSG_PERFORM_ACCESSIBILITY_ACTION = 19;
+    private final static int MSG_FIND_ACCESSIBLITY_NODE_INFO_BY_ACCESSIBILITY_ID = 20;
+    private final static int MSG_FIND_ACCESSIBLITY_NODE_INFO_BY_VIEW_ID = 21;
+    private final static int MSG_FIND_ACCESSIBLITY_NODE_INFO_BY_TEXT = 22;
+    private final static int MSG_PROCESS_INPUT_EVENTS = 23;
 
-    @Override
-    public String getMessageName(Message message) {
-        switch (message.what) {
-            case DIE:
-                return "DIE";
-            case RESIZED:
-                return "RESIZED";
-            case RESIZED_REPORT:
-                return "RESIZED_REPORT";
-            case WINDOW_FOCUS_CHANGED:
-                return "WINDOW_FOCUS_CHANGED";
-            case DISPATCH_KEY:
-                return "DISPATCH_KEY";
-            case DISPATCH_APP_VISIBILITY:
-                return "DISPATCH_APP_VISIBILITY";
-            case DISPATCH_GET_NEW_SURFACE:
-                return "DISPATCH_GET_NEW_SURFACE";
-            case IME_FINISHED_EVENT:
-                return "IME_FINISHED_EVENT";
-            case DISPATCH_KEY_FROM_IME:
-                return "DISPATCH_KEY_FROM_IME";
-            case FINISH_INPUT_CONNECTION:
-                return "FINISH_INPUT_CONNECTION";
-            case CHECK_FOCUS:
-                return "CHECK_FOCUS";
-            case CLOSE_SYSTEM_DIALOGS:
-                return "CLOSE_SYSTEM_DIALOGS";
-            case DISPATCH_DRAG_EVENT:
-                return "DISPATCH_DRAG_EVENT";
-            case DISPATCH_DRAG_LOCATION_EVENT:
-                return "DISPATCH_DRAG_LOCATION_EVENT";
-            case DISPATCH_SYSTEM_UI_VISIBILITY:
-                return "DISPATCH_SYSTEM_UI_VISIBILITY";
-            case DISPATCH_GENERIC_MOTION:
-                return "DISPATCH_GENERIC_MOTION";
-            case UPDATE_CONFIGURATION:
-                return "UPDATE_CONFIGURATION";
-            case DO_PERFORM_ACCESSIBILITY_ACTION:
-                return "DO_PERFORM_ACCESSIBILITY_ACTION";
-            case DO_FIND_ACCESSIBLITY_NODE_INFO_BY_ACCESSIBILITY_ID:
-                return "DO_FIND_ACCESSIBLITY_NODE_INFO_BY_ACCESSIBILITY_ID";
-            case DO_FIND_ACCESSIBLITY_NODE_INFO_BY_VIEW_ID:
-                return "DO_FIND_ACCESSIBLITY_NODE_INFO_BY_VIEW_ID";
-            case DO_FIND_ACCESSIBLITY_NODE_INFO_BY_TEXT:
-                return "DO_FIND_ACCESSIBLITY_NODE_INFO_BY_TEXT";
-            case DO_PROCESS_INPUT_EVENTS:
-                return "DO_PROCESS_INPUT_EVENTS";
+    final class ViewRootHandler extends Handler {
+        @Override
+        public String getMessageName(Message message) {
+            switch (message.what) {
+                case MSG_INVALIDATE:
+                    return "MSG_INVALIDATE";
+                case MSG_INVALIDATE_RECT:
+                    return "MSG_INVALIDATE_RECT";
+                case MSG_DIE:
+                    return "MSG_DIE";
+                case MSG_RESIZED:
+                    return "MSG_RESIZED";
+                case MSG_RESIZED_REPORT:
+                    return "MSG_RESIZED_REPORT";
+                case MSG_WINDOW_FOCUS_CHANGED:
+                    return "MSG_WINDOW_FOCUS_CHANGED";
+                case MSG_DISPATCH_KEY:
+                    return "MSG_DISPATCH_KEY";
+                case MSG_DISPATCH_APP_VISIBILITY:
+                    return "MSG_DISPATCH_APP_VISIBILITY";
+                case MSG_DISPATCH_GET_NEW_SURFACE:
+                    return "MSG_DISPATCH_GET_NEW_SURFACE";
+                case MSG_IME_FINISHED_EVENT:
+                    return "MSG_IME_FINISHED_EVENT";
+                case MSG_DISPATCH_KEY_FROM_IME:
+                    return "MSG_DISPATCH_KEY_FROM_IME";
+                case MSG_FINISH_INPUT_CONNECTION:
+                    return "MSG_FINISH_INPUT_CONNECTION";
+                case MSG_CHECK_FOCUS:
+                    return "MSG_CHECK_FOCUS";
+                case MSG_CLOSE_SYSTEM_DIALOGS:
+                    return "MSG_CLOSE_SYSTEM_DIALOGS";
+                case MSG_DISPATCH_DRAG_EVENT:
+                    return "MSG_DISPATCH_DRAG_EVENT";
+                case MSG_DISPATCH_DRAG_LOCATION_EVENT:
+                    return "MSG_DISPATCH_DRAG_LOCATION_EVENT";
+                case MSG_DISPATCH_SYSTEM_UI_VISIBILITY:
+                    return "MSG_DISPATCH_SYSTEM_UI_VISIBILITY";
+                case MSG_UPDATE_CONFIGURATION:
+                    return "MSG_UPDATE_CONFIGURATION";
+                case MSG_PERFORM_ACCESSIBILITY_ACTION:
+                    return "MSG_PERFORM_ACCESSIBILITY_ACTION";
+                case MSG_FIND_ACCESSIBLITY_NODE_INFO_BY_ACCESSIBILITY_ID:
+                    return "MSG_FIND_ACCESSIBLITY_NODE_INFO_BY_ACCESSIBILITY_ID";
+                case MSG_FIND_ACCESSIBLITY_NODE_INFO_BY_VIEW_ID:
+                    return "MSG_FIND_ACCESSIBLITY_NODE_INFO_BY_VIEW_ID";
+                case MSG_FIND_ACCESSIBLITY_NODE_INFO_BY_TEXT:
+                    return "MSG_FIND_ACCESSIBLITY_NODE_INFO_BY_TEXT";
+                case MSG_PROCESS_INPUT_EVENTS:
+                    return "MSG_PROCESS_INPUT_EVENTS";
+            }
+            return super.getMessageName(message);
         }
-        return super.getMessageName(message);
-    }
 
-    @Override
-    public void handleMessage(Message msg) {
-        switch (msg.what) {
-        case View.AttachInfo.INVALIDATE_MSG:
-            ((View) msg.obj).invalidate();
-            break;
-        case View.AttachInfo.INVALIDATE_RECT_MSG:
-            final View.AttachInfo.InvalidateInfo info = (View.AttachInfo.InvalidateInfo) msg.obj;
-            info.target.invalidate(info.left, info.top, info.right, info.bottom);
-            info.release();
-            break;
-        case IME_FINISHED_EVENT:
-            handleImeFinishedEvent(msg.arg1, msg.arg2 != 0);
-            break;
-        case DO_PROCESS_INPUT_EVENTS:
-            mProcessInputEventsScheduled = false;
-            doProcessInputEvents();
-            break;
-        case DISPATCH_APP_VISIBILITY:
-            handleAppVisibility(msg.arg1 != 0);
-            break;
-        case DISPATCH_GET_NEW_SURFACE:
-            handleGetNewSurface();
-            break;
-        case RESIZED:
-            ResizedInfo ri = (ResizedInfo)msg.obj;
-
-            if (mWinFrame.width() == msg.arg1 && mWinFrame.height() == msg.arg2
-                    && mPendingContentInsets.equals(ri.coveredInsets)
-                    && mPendingVisibleInsets.equals(ri.visibleInsets)
-                    && ((ResizedInfo)msg.obj).newConfig == null) {
+        @Override
+        public void handleMessage(Message msg) {
+            switch (msg.what) {
+            case MSG_INVALIDATE:
+                ((View) msg.obj).invalidate();
                 break;
-            }
-            // fall through...
-        case RESIZED_REPORT:
-            if (mAdded) {
-                Configuration config = ((ResizedInfo)msg.obj).newConfig;
-                if (config != null) {
-                    updateConfiguration(config, false);
-                }
-                mWinFrame.left = 0;
-                mWinFrame.right = msg.arg1;
-                mWinFrame.top = 0;
-                mWinFrame.bottom = msg.arg2;
-                mPendingContentInsets.set(((ResizedInfo)msg.obj).coveredInsets);
-                mPendingVisibleInsets.set(((ResizedInfo)msg.obj).visibleInsets);
-                if (msg.what == RESIZED_REPORT) {
-                    mReportNextDraw = true;
-                }
+            case MSG_INVALIDATE_RECT:
+                final View.AttachInfo.InvalidateInfo info = (View.AttachInfo.InvalidateInfo) msg.obj;
+                info.target.invalidate(info.left, info.top, info.right, info.bottom);
+                info.release();
+                break;
+            case MSG_IME_FINISHED_EVENT:
+                handleImeFinishedEvent(msg.arg1, msg.arg2 != 0);
+                break;
+            case MSG_PROCESS_INPUT_EVENTS:
+                mProcessInputEventsScheduled = false;
+                doProcessInputEvents();
+                break;
+            case MSG_DISPATCH_APP_VISIBILITY:
+                handleAppVisibility(msg.arg1 != 0);
+                break;
+            case MSG_DISPATCH_GET_NEW_SURFACE:
+                handleGetNewSurface();
+                break;
+            case MSG_RESIZED:
+                ResizedInfo ri = (ResizedInfo)msg.obj;
 
-                if (mView != null) {
-                    forceLayout(mView);
+                if (mWinFrame.width() == msg.arg1 && mWinFrame.height() == msg.arg2
+                        && mPendingContentInsets.equals(ri.coveredInsets)
+                        && mPendingVisibleInsets.equals(ri.visibleInsets)
+                        && ((ResizedInfo)msg.obj).newConfig == null) {
+                    break;
                 }
-                requestLayout();
-            }
-            break;
-        case WINDOW_FOCUS_CHANGED: {
-            if (mAdded) {
-                boolean hasWindowFocus = msg.arg1 != 0;
-                mAttachInfo.mHasWindowFocus = hasWindowFocus;
-                
-                profileRendering(hasWindowFocus);
+                // fall through...
+            case MSG_RESIZED_REPORT:
+                if (mAdded) {
+                    Configuration config = ((ResizedInfo)msg.obj).newConfig;
+                    if (config != null) {
+                        updateConfiguration(config, false);
+                    }
+                    mWinFrame.left = 0;
+                    mWinFrame.right = msg.arg1;
+                    mWinFrame.top = 0;
+                    mWinFrame.bottom = msg.arg2;
+                    mPendingContentInsets.set(((ResizedInfo)msg.obj).coveredInsets);
+                    mPendingVisibleInsets.set(((ResizedInfo)msg.obj).visibleInsets);
+                    if (msg.what == MSG_RESIZED_REPORT) {
+                        mReportNextDraw = true;
+                    }
 
-                if (hasWindowFocus) {
-                    boolean inTouchMode = msg.arg2 != 0;
-                    ensureTouchModeLocally(inTouchMode);
+                    if (mView != null) {
+                        forceLayout(mView);
+                    }
+                    requestLayout();
+                }
+                break;
+            case MSG_WINDOW_FOCUS_CHANGED: {
+                if (mAdded) {
+                    boolean hasWindowFocus = msg.arg1 != 0;
+                    mAttachInfo.mHasWindowFocus = hasWindowFocus;
 
-                    if (mAttachInfo.mHardwareRenderer != null &&
-                            mSurface != null && mSurface.isValid()) {
-                        mFullRedrawNeeded = true;
-                        try {
-                            mAttachInfo.mHardwareRenderer.initializeIfNeeded(mWidth, mHeight,
-                                    mHolder);
-                        } catch (Surface.OutOfResourcesException e) {
-                            Log.e(TAG, "OutOfResourcesException locking surface", e);
+                    profileRendering(hasWindowFocus);
+
+                    if (hasWindowFocus) {
+                        boolean inTouchMode = msg.arg2 != 0;
+                        ensureTouchModeLocally(inTouchMode);
+
+                        if (mAttachInfo.mHardwareRenderer != null &&
+                                mSurface != null && mSurface.isValid()) {
+                            mFullRedrawNeeded = true;
                             try {
-                                if (!sWindowSession.outOfMemory(mWindow)) {
-                                    Slog.w(TAG, "No processes killed for memory; killing self");
-                                    Process.killProcess(Process.myPid());
+                                mAttachInfo.mHardwareRenderer.initializeIfNeeded(mWidth, mHeight,
+                                        mHolder);
+                            } catch (Surface.OutOfResourcesException e) {
+                                Log.e(TAG, "OutOfResourcesException locking surface", e);
+                                try {
+                                    if (!sWindowSession.outOfMemory(mWindow)) {
+                                        Slog.w(TAG, "No processes killed for memory; killing self");
+                                        Process.killProcess(Process.myPid());
+                                    }
+                                } catch (RemoteException ex) {
                                 }
-                            } catch (RemoteException ex) {
+                                // Retry in a bit.
+                                sendMessageDelayed(obtainMessage(msg.what, msg.arg1, msg.arg2), 500);
+                                return;
                             }
-                            // Retry in a bit.
-                            sendMessageDelayed(obtainMessage(msg.what, msg.arg1, msg.arg2), 500);
-                            return;
                         }
                     }
-                }
 
-                mLastWasImTarget = WindowManager.LayoutParams
-                        .mayUseInputMethod(mWindowAttributes.flags);
+                    mLastWasImTarget = WindowManager.LayoutParams
+                            .mayUseInputMethod(mWindowAttributes.flags);
 
-                InputMethodManager imm = InputMethodManager.peekInstance();
-                if (mView != null) {
-                    if (hasWindowFocus && imm != null && mLastWasImTarget) {
-                        imm.startGettingWindowFocus(mView);
+                    InputMethodManager imm = InputMethodManager.peekInstance();
+                    if (mView != null) {
+                        if (hasWindowFocus && imm != null && mLastWasImTarget) {
+                            imm.startGettingWindowFocus(mView);
+                        }
+                        mAttachInfo.mKeyDispatchState.reset();
+                        mView.dispatchWindowFocusChanged(hasWindowFocus);
                     }
-                    mAttachInfo.mKeyDispatchState.reset();
-                    mView.dispatchWindowFocusChanged(hasWindowFocus);
-                }
 
-                // Note: must be done after the focus change callbacks,
-                // so all of the view state is set up correctly.
-                if (hasWindowFocus) {
-                    if (imm != null && mLastWasImTarget) {
-                        imm.onWindowFocus(mView, mView.findFocus(),
-                                mWindowAttributes.softInputMode,
-                                !mHasHadWindowFocus, mWindowAttributes.flags);
-                    }
-                    // Clear the forward bit.  We can just do this directly, since
-                    // the window manager doesn't care about it.
-                    mWindowAttributes.softInputMode &=
-                            ~WindowManager.LayoutParams.SOFT_INPUT_IS_FORWARD_NAVIGATION;
-                    ((WindowManager.LayoutParams)mView.getLayoutParams())
-                            .softInputMode &=
+                    // Note: must be done after the focus change callbacks,
+                    // so all of the view state is set up correctly.
+                    if (hasWindowFocus) {
+                        if (imm != null && mLastWasImTarget) {
+                            imm.onWindowFocus(mView, mView.findFocus(),
+                                    mWindowAttributes.softInputMode,
+                                    !mHasHadWindowFocus, mWindowAttributes.flags);
+                        }
+                        // Clear the forward bit.  We can just do this directly, since
+                        // the window manager doesn't care about it.
+                        mWindowAttributes.softInputMode &=
                                 ~WindowManager.LayoutParams.SOFT_INPUT_IS_FORWARD_NAVIGATION;
-                    mHasHadWindowFocus = true;
-                }
+                        ((WindowManager.LayoutParams)mView.getLayoutParams())
+                                .softInputMode &=
+                                    ~WindowManager.LayoutParams.SOFT_INPUT_IS_FORWARD_NAVIGATION;
+                        mHasHadWindowFocus = true;
+                    }
 
-                if (hasWindowFocus && mView != null) {
-                    sendAccessibilityEvents();
+                    if (hasWindowFocus && mView != null) {
+                        sendAccessibilityEvents();
+                    }
                 }
+            } break;
+            case MSG_DIE:
+                doDie();
+                break;
+            case MSG_DISPATCH_KEY: {
+                KeyEvent event = (KeyEvent)msg.obj;
+                enqueueInputEvent(event, null, 0, true);
+            } break;
+            case MSG_DISPATCH_KEY_FROM_IME: {
+                if (LOCAL_LOGV) Log.v(
+                    TAG, "Dispatching key "
+                    + msg.obj + " from IME to " + mView);
+                KeyEvent event = (KeyEvent)msg.obj;
+                if ((event.getFlags()&KeyEvent.FLAG_FROM_SYSTEM) != 0) {
+                    // The IME is trying to say this event is from the
+                    // system!  Bad bad bad!
+                    //noinspection UnusedAssignment
+                    event = KeyEvent.changeFlags(event, event.getFlags() & ~KeyEvent.FLAG_FROM_SYSTEM);
+                }
+                enqueueInputEvent(event, null, QueuedInputEvent.FLAG_DELIVER_POST_IME, true);
+            } break;
+            case MSG_FINISH_INPUT_CONNECTION: {
+                InputMethodManager imm = InputMethodManager.peekInstance();
+                if (imm != null) {
+                    imm.reportFinishInputConnection((InputConnection)msg.obj);
+                }
+            } break;
+            case MSG_CHECK_FOCUS: {
+                InputMethodManager imm = InputMethodManager.peekInstance();
+                if (imm != null) {
+                    imm.checkFocus();
+                }
+            } break;
+            case MSG_CLOSE_SYSTEM_DIALOGS: {
+                if (mView != null) {
+                    mView.onCloseSystemDialogs((String)msg.obj);
+                }
+            } break;
+            case MSG_DISPATCH_DRAG_EVENT:
+            case MSG_DISPATCH_DRAG_LOCATION_EVENT: {
+                DragEvent event = (DragEvent)msg.obj;
+                event.mLocalState = mLocalDragState;    // only present when this app called startDrag()
+                handleDragEvent(event);
+            } break;
+            case MSG_DISPATCH_SYSTEM_UI_VISIBILITY: {
+                handleDispatchSystemUiVisibilityChanged((SystemUiVisibilityInfo)msg.obj);
+            } break;
+            case MSG_UPDATE_CONFIGURATION: {
+                Configuration config = (Configuration)msg.obj;
+                if (config.isOtherSeqNewer(mLastConfiguration)) {
+                    config = mLastConfiguration;
+                }
+                updateConfiguration(config, false);
+            } break;
+            case MSG_FIND_ACCESSIBLITY_NODE_INFO_BY_ACCESSIBILITY_ID: {
+                if (mView != null) {
+                    getAccessibilityInteractionController()
+                        .findAccessibilityNodeInfoByAccessibilityIdUiThread(msg);
+                }
+            } break;
+            case MSG_PERFORM_ACCESSIBILITY_ACTION: {
+                if (mView != null) {
+                    getAccessibilityInteractionController()
+                        .perfromAccessibilityActionUiThread(msg);
+                }
+            } break;
+            case MSG_FIND_ACCESSIBLITY_NODE_INFO_BY_VIEW_ID: {
+                if (mView != null) {
+                    getAccessibilityInteractionController()
+                        .findAccessibilityNodeInfoByViewIdUiThread(msg);
+                }
+            } break;
+            case MSG_FIND_ACCESSIBLITY_NODE_INFO_BY_TEXT: {
+                if (mView != null) {
+                    getAccessibilityInteractionController()
+                        .findAccessibilityNodeInfosByTextUiThread(msg);
+                }
+            } break;
             }
-        } break;
-        case DIE:
-            doDie();
-            break;
-        case DISPATCH_KEY: {
-            KeyEvent event = (KeyEvent)msg.obj;
-            enqueueInputEvent(event, null, 0, true);
-        } break;
-        case DISPATCH_KEY_FROM_IME: {
-            if (LOCAL_LOGV) Log.v(
-                TAG, "Dispatching key "
-                + msg.obj + " from IME to " + mView);
-            KeyEvent event = (KeyEvent)msg.obj;
-            if ((event.getFlags()&KeyEvent.FLAG_FROM_SYSTEM) != 0) {
-                // The IME is trying to say this event is from the
-                // system!  Bad bad bad!
-                //noinspection UnusedAssignment
-                event = KeyEvent.changeFlags(event, event.getFlags() & ~KeyEvent.FLAG_FROM_SYSTEM);
-            }
-            enqueueInputEvent(event, null, QueuedInputEvent.FLAG_DELIVER_POST_IME, true);
-        } break;
-        case FINISH_INPUT_CONNECTION: {
-            InputMethodManager imm = InputMethodManager.peekInstance();
-            if (imm != null) {
-                imm.reportFinishInputConnection((InputConnection)msg.obj);
-            }
-        } break;
-        case CHECK_FOCUS: {
-            InputMethodManager imm = InputMethodManager.peekInstance();
-            if (imm != null) {
-                imm.checkFocus();
-            }
-        } break;
-        case CLOSE_SYSTEM_DIALOGS: {
-            if (mView != null) {
-                mView.onCloseSystemDialogs((String)msg.obj);
-            }
-        } break;
-        case DISPATCH_DRAG_EVENT:
-        case DISPATCH_DRAG_LOCATION_EVENT: {
-            DragEvent event = (DragEvent)msg.obj;
-            event.mLocalState = mLocalDragState;    // only present when this app called startDrag()
-            handleDragEvent(event);
-        } break;
-        case DISPATCH_SYSTEM_UI_VISIBILITY: {
-            handleDispatchSystemUiVisibilityChanged((SystemUiVisibilityInfo)msg.obj);
-        } break;
-        case UPDATE_CONFIGURATION: {
-            Configuration config = (Configuration)msg.obj;
-            if (config.isOtherSeqNewer(mLastConfiguration)) {
-                config = mLastConfiguration;
-            }
-            updateConfiguration(config, false);
-        } break;
-        case DO_FIND_ACCESSIBLITY_NODE_INFO_BY_ACCESSIBILITY_ID: {
-            if (mView != null) {
-                getAccessibilityInteractionController()
-                    .findAccessibilityNodeInfoByAccessibilityIdUiThread(msg);
-            }
-        } break;
-        case DO_PERFORM_ACCESSIBILITY_ACTION: {
-            if (mView != null) {
-                getAccessibilityInteractionController()
-                    .perfromAccessibilityActionUiThread(msg);
-            }
-        } break;
-        case DO_FIND_ACCESSIBLITY_NODE_INFO_BY_VIEW_ID: {
-            if (mView != null) {
-                getAccessibilityInteractionController()
-                    .findAccessibilityNodeInfoByViewIdUiThread(msg);
-            }
-        } break;
-        case DO_FIND_ACCESSIBLITY_NODE_INFO_BY_TEXT: {
-            if (mView != null) {
-                getAccessibilityInteractionController()
-                    .findAccessibilityNodeInfosByTextUiThread(msg);
-            }
-        } break;
         }
     }
+    final ViewRootHandler mHandler = new ViewRootHandler();
 
     /**
      * Something in the current window tells us we need to change the touch mode.  For
@@ -3684,7 +3699,7 @@
         if (immediate) {
             doDie();
         } else {
-            sendEmptyMessage(DIE);
+            mHandler.sendEmptyMessage(MSG_DIE);
         }
     }
 
@@ -3721,8 +3736,8 @@
     }
 
     public void requestUpdateConfiguration(Configuration config) {
-        Message msg = obtainMessage(UPDATE_CONFIGURATION, config);
-        sendMessage(msg);
+        Message msg = mHandler.obtainMessage(MSG_UPDATE_CONFIGURATION, config);
+        mHandler.sendMessage(msg);
     }
 
     private void destroyHardwareRenderer() {
@@ -3734,10 +3749,15 @@
     }
 
     void dispatchImeFinishedEvent(int seq, boolean handled) {
-        Message msg = obtainMessage(IME_FINISHED_EVENT);
+        Message msg = mHandler.obtainMessage(MSG_IME_FINISHED_EVENT);
         msg.arg1 = seq;
         msg.arg2 = handled ? 1 : 0;
-        sendMessage(msg);
+        mHandler.sendMessage(msg);
+    }
+
+    public void dispatchFinishInputConnection(InputConnection connection) {
+        Message msg = mHandler.obtainMessage(MSG_FINISH_INPUT_CONNECTION, connection);
+        mHandler.sendMessage(msg);
     }
 
     public void dispatchResized(int w, int h, Rect coveredInsets,
@@ -3746,7 +3766,7 @@
                 + " h=" + h + " coveredInsets=" + coveredInsets.toShortString()
                 + " visibleInsets=" + visibleInsets.toShortString()
                 + " reportDraw=" + reportDraw);
-        Message msg = obtainMessage(reportDraw ? RESIZED_REPORT :RESIZED);
+        Message msg = mHandler.obtainMessage(reportDraw ? MSG_RESIZED_REPORT :MSG_RESIZED);
         if (mTranslator != null) {
             mTranslator.translateRectInScreenToAppWindow(coveredInsets);
             mTranslator.translateRectInScreenToAppWindow(visibleInsets);
@@ -3760,7 +3780,7 @@
         ri.visibleInsets = new Rect(visibleInsets);
         ri.newConfig = newConfig;
         msg.obj = ri;
-        sendMessage(msg);
+        mHandler.sendMessage(msg);
     }
 
     /**
@@ -3857,7 +3877,7 @@
     private void scheduleProcessInputEvents() {
         if (!mProcessInputEventsScheduled) {
             mProcessInputEventsScheduled = true;
-            sendEmptyMessage(DO_PROCESS_INPUT_EVENTS);
+            mHandler.sendEmptyMessage(MSG_PROCESS_INPUT_EVENTS);
         }
     }
 
@@ -3874,7 +3894,7 @@
         // so we can clear the pending flag immediately.
         if (mProcessInputEventsScheduled) {
             mProcessInputEventsScheduled = false;
-            removeMessages(DO_PROCESS_INPUT_EVENTS);
+            mHandler.removeMessages(MSG_PROCESS_INPUT_EVENTS);
         }
     }
 
@@ -3960,47 +3980,69 @@
     }
     WindowInputEventReceiver mInputEventReceiver;
 
+    public void dispatchInvalidateDelayed(View view, long delayMilliseconds) {
+        Message msg = mHandler.obtainMessage(MSG_INVALIDATE, view);
+        mHandler.sendMessageDelayed(msg, delayMilliseconds);
+    }
+
+    public void cancelInvalidate(View view) {
+        mHandler.removeMessages(MSG_INVALIDATE, view);
+    }
+
+    public void dispatchInvalidateRectDelayed(AttachInfo.InvalidateInfo info,
+            long delayMilliseconds) {
+        final Message msg = mHandler.obtainMessage(MSG_INVALIDATE_RECT, info);
+        mHandler.sendMessageDelayed(msg, delayMilliseconds);
+    }
+
     public void dispatchKey(KeyEvent event) {
-        Message msg = obtainMessage(DISPATCH_KEY, event);
-        sendMessage(msg);
+        Message msg = mHandler.obtainMessage(MSG_DISPATCH_KEY, event);
+        msg.setAsynchronous(true);
+        mHandler.sendMessage(msg);
+    }
+
+    public void dispatchKeyFromIme(KeyEvent event) {
+        Message msg = mHandler.obtainMessage(MSG_DISPATCH_KEY_FROM_IME, event);
+        msg.setAsynchronous(true);
+        mHandler.sendMessage(msg);
     }
 
     public void dispatchAppVisibility(boolean visible) {
-        Message msg = obtainMessage(DISPATCH_APP_VISIBILITY);
+        Message msg = mHandler.obtainMessage(MSG_DISPATCH_APP_VISIBILITY);
         msg.arg1 = visible ? 1 : 0;
-        sendMessage(msg);
+        mHandler.sendMessage(msg);
     }
 
     public void dispatchGetNewSurface() {
-        Message msg = obtainMessage(DISPATCH_GET_NEW_SURFACE);
-        sendMessage(msg);
+        Message msg = mHandler.obtainMessage(MSG_DISPATCH_GET_NEW_SURFACE);
+        mHandler.sendMessage(msg);
     }
 
     public void windowFocusChanged(boolean hasFocus, boolean inTouchMode) {
         Message msg = Message.obtain();
-        msg.what = WINDOW_FOCUS_CHANGED;
+        msg.what = MSG_WINDOW_FOCUS_CHANGED;
         msg.arg1 = hasFocus ? 1 : 0;
         msg.arg2 = inTouchMode ? 1 : 0;
-        sendMessage(msg);
+        mHandler.sendMessage(msg);
     }
 
     public void dispatchCloseSystemDialogs(String reason) {
         Message msg = Message.obtain();
-        msg.what = CLOSE_SYSTEM_DIALOGS;
+        msg.what = MSG_CLOSE_SYSTEM_DIALOGS;
         msg.obj = reason;
-        sendMessage(msg);
+        mHandler.sendMessage(msg);
     }
 
     public void dispatchDragEvent(DragEvent event) {
         final int what;
         if (event.getAction() == DragEvent.ACTION_DRAG_LOCATION) {
-            what = DISPATCH_DRAG_LOCATION_EVENT;
-            removeMessages(what);
+            what = MSG_DISPATCH_DRAG_LOCATION_EVENT;
+            mHandler.removeMessages(what);
         } else {
-            what = DISPATCH_DRAG_EVENT;
+            what = MSG_DISPATCH_DRAG_EVENT;
         }
-        Message msg = obtainMessage(what, event);
-        sendMessage(msg);
+        Message msg = mHandler.obtainMessage(what, event);
+        mHandler.sendMessage(msg);
     }
 
     public void dispatchSystemUiVisibilityChanged(int seq, int globalVisibility,
@@ -4010,7 +4052,14 @@
         args.globalVisibility = globalVisibility;
         args.localValue = localValue;
         args.localChanges = localChanges;
-        sendMessage(obtainMessage(DISPATCH_SYSTEM_UI_VISIBILITY, args));
+        mHandler.sendMessage(mHandler.obtainMessage(MSG_DISPATCH_SYSTEM_UI_VISIBILITY, args));
+    }
+
+    public void dispatchCheckFocus() {
+        if (!mHandler.hasMessages(MSG_CHECK_FOCUS)) {
+            // This will result in a call to checkFocus() below.
+            mHandler.sendEmptyMessage(MSG_CHECK_FOCUS);
+        }
     }
 
     /**
@@ -4041,7 +4090,7 @@
         }
         if (!mSendWindowContentChangedAccessibilityEvent.mIsPending) {
             mSendWindowContentChangedAccessibilityEvent.mIsPending = true;
-            postDelayed(mSendWindowContentChangedAccessibilityEvent,
+            mHandler.postDelayed(mSendWindowContentChangedAccessibilityEvent,
                     ViewConfiguration.getSendRecurringAccessibilityEventsInterval());
         }
     }
@@ -4052,7 +4101,7 @@
      */
     private void removeSendWindowContentChangedCallback() {
         if (mSendWindowContentChangedAccessibilityEvent != null) {
-            removeCallbacks(mSendWindowContentChangedAccessibilityEvent);
+            mHandler.removeCallbacks(mSendWindowContentChangedAccessibilityEvent);
         }
     }
 
@@ -4512,6 +4561,9 @@
     }
 
     /**
+     * The run queue is used to enqueue pending work from Views when no Handler is
+     * attached.  The work is executed during the next call to performTraversals on
+     * the thread.
      * @hide
      */
     static final class RunQueue {
@@ -4770,8 +4822,8 @@
                 long accessibilityNodeId, int interactionId,
                 IAccessibilityInteractionConnectionCallback callback, int interrogatingPid,
                 long interrogatingTid) {
-            Message message = Message.obtain();
-            message.what = DO_FIND_ACCESSIBLITY_NODE_INFO_BY_ACCESSIBILITY_ID;
+            Message message = mHandler.obtainMessage();
+            message.what = MSG_FIND_ACCESSIBLITY_NODE_INFO_BY_ACCESSIBILITY_ID;
             message.arg1 = interrogatingPid;
             SomeArgs args = mPool.acquire();
             args.argi1 = AccessibilityNodeInfo.getAccessibilityViewId(accessibilityNodeId);
@@ -4785,11 +4837,10 @@
             // client can handle the message to generate the result.
             if (interrogatingPid == Process.myPid()
                     && interrogatingTid == Looper.getMainLooper().getThread().getId()) {
-                message.setTarget(ViewRootImpl.this);
                 AccessibilityInteractionClient.getInstanceForThread(
                         interrogatingTid).setSameThreadMessage(message);
             } else {
-                sendMessage(message);
+                mHandler.sendMessage(message);
             }
         }
 
@@ -4828,8 +4879,8 @@
         public void findAccessibilityNodeInfoByViewIdClientThread(long accessibilityNodeId,
                 int viewId, int interactionId, IAccessibilityInteractionConnectionCallback callback,
                 int interrogatingPid, long interrogatingTid) {
-            Message message = Message.obtain();
-            message.what = DO_FIND_ACCESSIBLITY_NODE_INFO_BY_VIEW_ID;
+            Message message = mHandler.obtainMessage();
+            message.what = MSG_FIND_ACCESSIBLITY_NODE_INFO_BY_VIEW_ID;
             message.arg1 = AccessibilityNodeInfo.getAccessibilityViewId(accessibilityNodeId);
             SomeArgs args = mPool.acquire();
             args.argi1 = viewId;
@@ -4842,11 +4893,10 @@
             // client can handle the message to generate the result.
             if (interrogatingPid == Process.myPid()
                     && interrogatingTid == Looper.getMainLooper().getThread().getId()) {
-                message.setTarget(ViewRootImpl.this);
                 AccessibilityInteractionClient.getInstanceForThread(
                         interrogatingTid).setSameThreadMessage(message);
             } else {
-                sendMessage(message);
+                mHandler.sendMessage(message);
             }
         }
 
@@ -4885,8 +4935,8 @@
                 String text, int interactionId,
                 IAccessibilityInteractionConnectionCallback callback, int interrogatingPid,
                 long interrogatingTid) {
-            Message message = Message.obtain();
-            message.what = DO_FIND_ACCESSIBLITY_NODE_INFO_BY_TEXT;
+            Message message = mHandler.obtainMessage();
+            message.what = MSG_FIND_ACCESSIBLITY_NODE_INFO_BY_TEXT;
             SomeArgs args = mPool.acquire();
             args.arg1 = text;
             args.argi1 = AccessibilityNodeInfo.getAccessibilityViewId(accessibilityNodeId);
@@ -4900,11 +4950,10 @@
             // client can handle the message to generate the result.
             if (interrogatingPid == Process.myPid()
                     && interrogatingTid == Looper.getMainLooper().getThread().getId()) {
-                message.setTarget(ViewRootImpl.this);
                 AccessibilityInteractionClient.getInstanceForThread(
                         interrogatingTid).setSameThreadMessage(message);
             } else {
-                sendMessage(message);
+                mHandler.sendMessage(message);
             }
         }
 
@@ -4971,8 +5020,8 @@
         public void performAccessibilityActionClientThread(long accessibilityNodeId, int action,
                 int interactionId, IAccessibilityInteractionConnectionCallback callback,
                 int interogatingPid, long interrogatingTid) {
-            Message message = Message.obtain();
-            message.what = DO_PERFORM_ACCESSIBILITY_ACTION;
+            Message message = mHandler.obtainMessage();
+            message.what = MSG_PERFORM_ACCESSIBILITY_ACTION;
             message.arg1 = AccessibilityNodeInfo.getAccessibilityViewId(accessibilityNodeId);
             message.arg2 = AccessibilityNodeInfo.getVirtualDescendantId(accessibilityNodeId);
             SomeArgs args = mPool.acquire();
@@ -4986,11 +5035,10 @@
             // client can handle the message to generate the result.
             if (interogatingPid == Process.myPid()
                     && interrogatingTid == Looper.getMainLooper().getThread().getId()) {
-                message.setTarget(ViewRootImpl.this);
                 AccessibilityInteractionClient.getInstanceForThread(
                         interrogatingTid).setSameThreadMessage(message);
             } else {
-                sendMessage(message);
+                mHandler.sendMessage(message);
             }
         }
 
diff --git a/core/java/android/view/inputmethod/BaseInputConnection.java b/core/java/android/view/inputmethod/BaseInputConnection.java
index bd02d62..89aba3c 100644
--- a/core/java/android/view/inputmethod/BaseInputConnection.java
+++ b/core/java/android/view/inputmethod/BaseInputConnection.java
@@ -19,7 +19,6 @@
 import android.content.Context;
 import android.content.res.TypedArray;
 import android.os.Bundle;
-import android.os.Handler;
 import android.os.SystemClock;
 import android.text.Editable;
 import android.text.NoCopySpan;
@@ -497,15 +496,14 @@
      */
     public boolean sendKeyEvent(KeyEvent event) {
         synchronized (mIMM.mH) {
-            Handler h = mTargetView != null ? mTargetView.getHandler() : null;
-            if (h == null) {
+            ViewRootImpl viewRootImpl = mTargetView != null ? mTargetView.getViewRootImpl() : null;
+            if (viewRootImpl == null) {
                 if (mIMM.mServedView != null) {
-                    h = mIMM.mServedView.getHandler();
+                    viewRootImpl = mIMM.mServedView.getViewRootImpl();
                 }
             }
-            if (h != null) {
-                h.sendMessage(h.obtainMessage(ViewRootImpl.DISPATCH_KEY_FROM_IME,
-                        event));
+            if (viewRootImpl != null) {
+                viewRootImpl.dispatchKeyFromIme(event);
             }
         }
         return false;
diff --git a/core/java/android/view/inputmethod/InputMethodManager.java b/core/java/android/view/inputmethod/InputMethodManager.java
index b1d7a18..c51d244 100644
--- a/core/java/android/view/inputmethod/InputMethodManager.java
+++ b/core/java/android/view/inputmethod/InputMethodManager.java
@@ -675,11 +675,10 @@
             // longer the input target, so it can reset its state.  Schedule
             // this call on its window's Handler so it will be on the correct
             // thread and outside of our lock.
-            Handler vh = mServedView.getHandler();
-            if (vh != null) {
+            ViewRootImpl viewRootImpl = mServedView.getViewRootImpl();
+            if (viewRootImpl != null) {
                 // This will result in a call to reportFinishInputConnection() below.
-                vh.sendMessage(vh.obtainMessage(ViewRootImpl.FINISH_INPUT_CONNECTION,
-                        mServedInputConnection));
+                viewRootImpl.dispatchFinishInputConnection(mServedInputConnection);
             }
         }
     }
@@ -1130,13 +1129,12 @@
     }
 
     static void scheduleCheckFocusLocked(View view) {
-        Handler vh = view.getHandler();
-        if (vh != null && !vh.hasMessages(ViewRootImpl.CHECK_FOCUS)) {
-            // This will result in a call to checkFocus() below.
-            vh.sendMessage(vh.obtainMessage(ViewRootImpl.CHECK_FOCUS));
+        ViewRootImpl viewRootImpl = view.getViewRootImpl();
+        if (viewRootImpl != null) {
+            viewRootImpl.dispatchCheckFocus();
         }
     }
-    
+
     /**
      * @hide
      */
diff --git a/core/java/android/widget/TextView.java b/core/java/android/widget/TextView.java
index 688b37f..1241c0f 100644
--- a/core/java/android/widget/TextView.java
+++ b/core/java/android/widget/TextView.java
@@ -3807,21 +3807,21 @@
             }
         }
 
-        Handler h = getHandler();
-        if (h != null) {
+        ViewRootImpl viewRootImpl = getViewRootImpl();
+        if (viewRootImpl != null) {
             long eventTime = SystemClock.uptimeMillis();
-            h.sendMessage(h.obtainMessage(ViewRootImpl.DISPATCH_KEY_FROM_IME,
+            viewRootImpl.dispatchKeyFromIme(
                     new KeyEvent(eventTime, eventTime,
                     KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_ENTER, 0, 0,
                     KeyCharacterMap.VIRTUAL_KEYBOARD, 0,
                     KeyEvent.FLAG_SOFT_KEYBOARD | KeyEvent.FLAG_KEEP_TOUCH_MODE
-                    | KeyEvent.FLAG_EDITOR_ACTION)));
-            h.sendMessage(h.obtainMessage(ViewRootImpl.DISPATCH_KEY_FROM_IME,
+                    | KeyEvent.FLAG_EDITOR_ACTION));
+            viewRootImpl.dispatchKeyFromIme(
                     new KeyEvent(SystemClock.uptimeMillis(), eventTime,
                     KeyEvent.ACTION_UP, KeyEvent.KEYCODE_ENTER, 0, 0,
                     KeyCharacterMap.VIRTUAL_KEYBOARD, 0,
                     KeyEvent.FLAG_SOFT_KEYBOARD | KeyEvent.FLAG_KEEP_TOUCH_MODE
-                    | KeyEvent.FLAG_EDITOR_ACTION)));
+                    | KeyEvent.FLAG_EDITOR_ACTION));
         }
     }
 
diff --git a/core/java/android/widget/ZoomButtonsController.java b/core/java/android/widget/ZoomButtonsController.java
index f3d891d..02dc27b 100644
--- a/core/java/android/widget/ZoomButtonsController.java
+++ b/core/java/android/widget/ZoomButtonsController.java
@@ -501,7 +501,7 @@
 
         } else {
 
-            ViewRootImpl viewRoot = getOwnerViewRootImpl();
+            ViewRootImpl viewRoot = mOwnerView.getViewRootImpl();
             if (viewRoot != null) {
                 viewRoot.dispatchKey(event);
             }
@@ -526,20 +526,6 @@
         }
     }
 
-    private ViewRootImpl getOwnerViewRootImpl() {
-        View rootViewOfOwner = mOwnerView.getRootView();
-        if (rootViewOfOwner == null) {
-            return null;
-        }
-
-        ViewParent parentOfRootView = rootViewOfOwner.getParent();
-        if (parentOfRootView instanceof ViewRootImpl) {
-            return (ViewRootImpl) parentOfRootView;
-        } else {
-            return null;
-        }
-    }
-
     /**
      * @hide The ZoomButtonsController implements the OnTouchListener, but this
      *       does not need to be shown in its public API.
diff --git a/core/java/com/android/internal/widget/PasswordEntryKeyboardHelper.java b/core/java/com/android/internal/widget/PasswordEntryKeyboardHelper.java
index 2e7810f..26518eb 100644
--- a/core/java/com/android/internal/widget/PasswordEntryKeyboardHelper.java
+++ b/core/java/com/android/internal/widget/PasswordEntryKeyboardHelper.java
@@ -147,7 +147,7 @@
     }
 
     private void sendKeyEventsToTarget(int character) {
-        Handler handler = mTargetView.getHandler();
+        ViewRootImpl viewRootImpl = mTargetView.getViewRootImpl();
         KeyEvent[] events = KeyCharacterMap.load(KeyCharacterMap.VIRTUAL_KEYBOARD).getEvents(
                 new char[] { (char) character });
         if (events != null) {
@@ -156,22 +156,22 @@
                 KeyEvent event = events[i];
                 event = KeyEvent.changeFlags(event, event.getFlags()
                         | KeyEvent.FLAG_SOFT_KEYBOARD | KeyEvent.FLAG_KEEP_TOUCH_MODE);
-                handler.sendMessage(handler.obtainMessage(ViewRootImpl.DISPATCH_KEY, event));
+                viewRootImpl.dispatchKey(event);
             }
         }
     }
 
     public void sendDownUpKeyEvents(int keyEventCode) {
         long eventTime = SystemClock.uptimeMillis();
-        Handler handler = mTargetView.getHandler();
-        handler.sendMessage(handler.obtainMessage(ViewRootImpl.DISPATCH_KEY_FROM_IME,
+        ViewRootImpl viewRootImpl = mTargetView.getViewRootImpl();
+        viewRootImpl.dispatchKeyFromIme(
                 new KeyEvent(eventTime, eventTime, KeyEvent.ACTION_DOWN, keyEventCode, 0, 0,
                         KeyCharacterMap.VIRTUAL_KEYBOARD, 0,
-                    KeyEvent.FLAG_SOFT_KEYBOARD|KeyEvent.FLAG_KEEP_TOUCH_MODE)));
-        handler.sendMessage(handler.obtainMessage(ViewRootImpl.DISPATCH_KEY_FROM_IME,
+                    KeyEvent.FLAG_SOFT_KEYBOARD|KeyEvent.FLAG_KEEP_TOUCH_MODE));
+        viewRootImpl.dispatchKeyFromIme(
                 new KeyEvent(eventTime, eventTime, KeyEvent.ACTION_UP, keyEventCode, 0, 0,
                         KeyCharacterMap.VIRTUAL_KEYBOARD, 0,
-                        KeyEvent.FLAG_SOFT_KEYBOARD|KeyEvent.FLAG_KEEP_TOUCH_MODE)));
+                        KeyEvent.FLAG_SOFT_KEYBOARD|KeyEvent.FLAG_KEEP_TOUCH_MODE));
     }
 
     public void onKey(int primaryCode, int[] keyCodes) {
diff --git a/core/jni/android_view_InputEventReceiver.cpp b/core/jni/android_view_InputEventReceiver.cpp
index 47b3f66..ee41398 100644
--- a/core/jni/android_view_InputEventReceiver.cpp
+++ b/core/jni/android_view_InputEventReceiver.cpp
@@ -275,7 +275,7 @@
     sp<NativeInputEventReceiver> receiver =
             reinterpret_cast<NativeInputEventReceiver*>(receiverPtr);
     status_t status = receiver->consumeEvents(true /*consumeBatches*/);
-    if (status) {
+    if (status && status != DEAD_OBJECT) {
         String8 message;
         message.appendFormat("Failed to consume batched input event.  status=%d", status);
         jniThrowRuntimeException(env, message.string());
diff --git a/core/res/res/values-af/strings.xml b/core/res/res/values-af/strings.xml
index 840323e..2a8218a 100644
--- a/core/res/res/values-af/strings.xml
+++ b/core/res/res/values-af/strings.xml
@@ -975,6 +975,11 @@
     <skip />
     <string name="wifi_watchdog_network_disabled" msgid="7904214231651546347">"Kon nie aan Wi-Fikoppel nie"</string>
     <string name="wifi_watchdog_network_disabled_detailed" msgid="5548780776418332675">" het \'n swak internetverbinding."</string>
+    <string name="wifi_p2p_dialog_title" msgid="97611782659324517">"Wi-Fi Direct"</string>
+    <string name="wifi_p2p_turnon_message" msgid="2909250942299627244">"Begin Wi-Fi Direct. Dit sal die Wi-Fi-kliënt/warmkol afskakel."</string>
+    <string name="wifi_p2p_failed_message" msgid="3763669677935623084">"Kon nie Wi-Fi Direct begin nie."</string>
+    <string name="wifi_p2p_enabled_notification_title" msgid="2068321881673734886">"Wi-Fi Direk is aan"</string>
+    <string name="wifi_p2p_enabled_notification_message" msgid="1638949953993894335">"Raak vir instellings"</string>
     <string name="accept" msgid="1645267259272829559">"Aanvaar"</string>
     <string name="decline" msgid="2112225451706137894">"Weier"</string>
     <string name="wifi_p2p_invitation_sent_title" msgid="1318975185112070734">"Uitnodiging gestuur"</string>
diff --git a/core/res/res/values-am/strings.xml b/core/res/res/values-am/strings.xml
index 905b90c..b700c8e 100644
--- a/core/res/res/values-am/strings.xml
+++ b/core/res/res/values-am/strings.xml
@@ -973,6 +973,11 @@
     <skip />
     <string name="wifi_watchdog_network_disabled" msgid="7904214231651546347">"ወደ Wi-Fi ለማያያዝ አልተቻለም"</string>
     <string name="wifi_watchdog_network_disabled_detailed" msgid="5548780776418332675">" ደካማ የበይነመረብ ግንኙነት ኣለው።"</string>
+    <string name="wifi_p2p_dialog_title" msgid="97611782659324517">"Wi-Fi ቀጥታ"</string>
+    <string name="wifi_p2p_turnon_message" msgid="2909250942299627244">"የWi-Fi በቀጥታ  ጀምር።ይህ የWi-Fi ደንበኛ /ድረስ ነጥብ  ያጠፋል።"</string>
+    <string name="wifi_p2p_failed_message" msgid="3763669677935623084">"በቀጥታ Wi-Fi ማስጀመር አልተቻለም።"</string>
+    <string name="wifi_p2p_enabled_notification_title" msgid="2068321881673734886">"የWi-Fi ቀጥታ በርቷል"</string>
+    <string name="wifi_p2p_enabled_notification_message" msgid="1638949953993894335">"ለቅንብሮች ንካ"</string>
     <string name="accept" msgid="1645267259272829559">"ተቀበል"</string>
     <string name="decline" msgid="2112225451706137894">"ውድቅ አድርግ"</string>
     <string name="wifi_p2p_invitation_sent_title" msgid="1318975185112070734">"ግብዣ ተልኳል"</string>
diff --git a/core/res/res/values-ar/strings.xml b/core/res/res/values-ar/strings.xml
index a7c37e7..0d254f9 100644
--- a/core/res/res/values-ar/strings.xml
+++ b/core/res/res/values-ar/strings.xml
@@ -973,6 +973,11 @@
     <skip />
     <string name="wifi_watchdog_network_disabled" msgid="7904214231651546347">"تعذر الاتصال بـ Wi-Fi"</string>
     <string name="wifi_watchdog_network_disabled_detailed" msgid="5548780776418332675">" لديها اتصال إنترنت رديء."</string>
+    <string name="wifi_p2p_dialog_title" msgid="97611782659324517">"اتصال Wi-Fi مباشر"</string>
+    <string name="wifi_p2p_turnon_message" msgid="2909250942299627244">"ابدأ Wi-Fi Direct. يؤدي هذا إلى إيقاف عميل/نقطة اتصال Wi-Fi."</string>
+    <string name="wifi_p2p_failed_message" msgid="3763669677935623084">"تعذر بدء Wi-Fi Direct."</string>
+    <string name="wifi_p2p_enabled_notification_title" msgid="2068321881673734886">"تم تشغيل اتصال Wi-Fi المباشر"</string>
+    <string name="wifi_p2p_enabled_notification_message" msgid="1638949953993894335">"المس للحصول على الإعدادات"</string>
     <string name="accept" msgid="1645267259272829559">"قبول"</string>
     <string name="decline" msgid="2112225451706137894">"رفض"</string>
     <string name="wifi_p2p_invitation_sent_title" msgid="1318975185112070734">"تم إرسال الدعوة"</string>
diff --git a/core/res/res/values-be/strings.xml b/core/res/res/values-be/strings.xml
index 4a226a1..c87b405 100644
--- a/core/res/res/values-be/strings.xml
+++ b/core/res/res/values-be/strings.xml
@@ -973,6 +973,11 @@
     <skip />
     <string name="wifi_watchdog_network_disabled" msgid="7904214231651546347">"Немагчыма падключыцца да Wi-Fi"</string>
     <string name="wifi_watchdog_network_disabled_detailed" msgid="5548780776418332675">" дрэннае падключэнне да Інтэрнэту."</string>
+    <string name="wifi_p2p_dialog_title" msgid="97611782659324517">"Wi-Fi Direct"</string>
+    <string name="wifi_p2p_turnon_message" msgid="2909250942299627244">"Пачаць работу Wi-Fi Direct. Гэта адключыць кліента або кропку доступу Wi-Fi."</string>
+    <string name="wifi_p2p_failed_message" msgid="3763669677935623084">"Немагчыма запусціць Wi-Fi Direct."</string>
+    <string name="wifi_p2p_enabled_notification_title" msgid="2068321881673734886">"Wi-Fi Direct уключаны"</string>
+    <string name="wifi_p2p_enabled_notification_message" msgid="1638949953993894335">"Дакраніцеся, каб наладзіць"</string>
     <string name="accept" msgid="1645267259272829559">"Прыняць"</string>
     <string name="decline" msgid="2112225451706137894">"Адхіліць"</string>
     <string name="wifi_p2p_invitation_sent_title" msgid="1318975185112070734">"Запрашэнне адпраўлена"</string>
diff --git a/core/res/res/values-bg/strings.xml b/core/res/res/values-bg/strings.xml
index f311a28..8d5df3e 100644
--- a/core/res/res/values-bg/strings.xml
+++ b/core/res/res/values-bg/strings.xml
@@ -973,6 +973,11 @@
     <skip />
     <string name="wifi_watchdog_network_disabled" msgid="7904214231651546347">"Не можа да се свърже с Wi-Fi"</string>
     <string name="wifi_watchdog_network_disabled_detailed" msgid="5548780776418332675">" има лоша връзка с интернет."</string>
+    <string name="wifi_p2p_dialog_title" msgid="97611782659324517">"Wi-Fi Direct"</string>
+    <string name="wifi_p2p_turnon_message" msgid="2909250942299627244">"Стартиране на Wi-Fi Direct. Това ще изключи клиентската програма/точката за достъп до Wi-Fi."</string>
+    <string name="wifi_p2p_failed_message" msgid="3763669677935623084">"Wi-Fi Direct не можа да се стартира."</string>
+    <string name="wifi_p2p_enabled_notification_title" msgid="2068321881673734886">"Wi-Fi Direct е включено"</string>
+    <string name="wifi_p2p_enabled_notification_message" msgid="1638949953993894335">"Докоснете за настройки"</string>
     <string name="accept" msgid="1645267259272829559">"Приемам"</string>
     <string name="decline" msgid="2112225451706137894">"Отхвърлям"</string>
     <string name="wifi_p2p_invitation_sent_title" msgid="1318975185112070734">"Поканата е изпратена"</string>
diff --git a/core/res/res/values-ca/strings.xml b/core/res/res/values-ca/strings.xml
index 95dae9d..58e4ee7 100644
--- a/core/res/res/values-ca/strings.xml
+++ b/core/res/res/values-ca/strings.xml
@@ -973,6 +973,11 @@
     <skip />
     <string name="wifi_watchdog_network_disabled" msgid="7904214231651546347">"No s\'ha pogut connectar a la Wi-Fi"</string>
     <string name="wifi_watchdog_network_disabled_detailed" msgid="5548780776418332675">" té una mala connexió a Internet."</string>
+    <string name="wifi_p2p_dialog_title" msgid="97611782659324517">"Wi-Fi Direct"</string>
+    <string name="wifi_p2p_turnon_message" msgid="2909250942299627244">"Inicia Wi-Fi Direct. Això desactivarà el client/la zona Wi-Fi."</string>
+    <string name="wifi_p2p_failed_message" msgid="3763669677935623084">"No s\'ha pogut iniciar Wi-Fi Direct."</string>
+    <string name="wifi_p2p_enabled_notification_title" msgid="2068321881673734886">"Wi-Fi Direct està activat"</string>
+    <string name="wifi_p2p_enabled_notification_message" msgid="1638949953993894335">"Toca per accedir a la configuració"</string>
     <string name="accept" msgid="1645267259272829559">"Accepta"</string>
     <string name="decline" msgid="2112225451706137894">"Rebutja"</string>
     <string name="wifi_p2p_invitation_sent_title" msgid="1318975185112070734">"S\'ha enviat la invitació"</string>
diff --git a/core/res/res/values-cs/strings.xml b/core/res/res/values-cs/strings.xml
index c01526d..6ae237c 100644
--- a/core/res/res/values-cs/strings.xml
+++ b/core/res/res/values-cs/strings.xml
@@ -973,6 +973,11 @@
     <skip />
     <string name="wifi_watchdog_network_disabled" msgid="7904214231651546347">"Připojení k síti Wi-Fi se nezdařilo"</string>
     <string name="wifi_watchdog_network_disabled_detailed" msgid="5548780776418332675">" má pomalé připojení k internetu."</string>
+    <string name="wifi_p2p_dialog_title" msgid="97611782659324517">"Přímé připojení sítě Wi-Fi"</string>
+    <string name="wifi_p2p_turnon_message" msgid="2909250942299627244">"Spustit přímé připojení sítě Wi-Fi. Tato možnost vypne provoz sítě Wi-Fi v režimu klient/hotspot."</string>
+    <string name="wifi_p2p_failed_message" msgid="3763669677935623084">"Přímé připojení sítě Wi-Fi se nepodařilo spustit."</string>
+    <string name="wifi_p2p_enabled_notification_title" msgid="2068321881673734886">"Přímé připojení sítě Wi-Fi je zapnuto"</string>
+    <string name="wifi_p2p_enabled_notification_message" msgid="1638949953993894335">"Nastavení otevřete dotykem"</string>
     <string name="accept" msgid="1645267259272829559">"Přijmout"</string>
     <string name="decline" msgid="2112225451706137894">"Odmítnout"</string>
     <string name="wifi_p2p_invitation_sent_title" msgid="1318975185112070734">"Pozvánka odeslána."</string>
diff --git a/core/res/res/values-da/strings.xml b/core/res/res/values-da/strings.xml
index 4904a99..8e5df07 100644
--- a/core/res/res/values-da/strings.xml
+++ b/core/res/res/values-da/strings.xml
@@ -757,7 +757,7 @@
     <string name="permlab_addVoicemail" msgid="5525660026090959044">"tilføj telefonsvarer"</string>
     <string name="permdesc_addVoicemail" msgid="6604508651428252437">"Tillader, at appen kan tilføje beskeder på din telefonsvarer."</string>
     <string name="permlab_writeGeolocationPermissions" msgid="5962224158955273932">"skifte tilladelser til geografisk placering i Browser"</string>
-    <string name="permdesc_writeGeolocationPermissions" msgid="1083743234522638747">"Tillader, at appen kan ændre browserens tilladelser angående geografisk placering. Ondsindede apps kan benytte dette til at sende oplysninger om placering til vilkårlige websteder."</string>
+    <string name="permdesc_writeGeolocationPermissions" msgid="1083743234522638747">"Tillader, at appen kan ændre browserens tilladelser angående geografisk placering. Ondsindede apps kan benytte dette til at sende oplysninger om placering til vilkårlige websites."</string>
     <string name="permlab_packageVerificationAgent" msgid="5568139100645829117">"bekræft pakker"</string>
     <string name="permdesc_packageVerificationAgent" msgid="8437590190990843381">"Tillader, at appen kan bekræfte, at en pakke kan installeres."</string>
     <string name="permlab_bindPackageVerifier" msgid="4187786793360326654">"bind til en bekræftelse af pakker"</string>
@@ -973,6 +973,11 @@
     <skip />
     <string name="wifi_watchdog_network_disabled" msgid="7904214231651546347">"Kunne ikke oprette forbindelse til Wi-Fi"</string>
     <string name="wifi_watchdog_network_disabled_detailed" msgid="5548780776418332675">" har en dårlig internetforbindelse."</string>
+    <string name="wifi_p2p_dialog_title" msgid="97611782659324517">"Wi-Fi Direct"</string>
+    <string name="wifi_p2p_turnon_message" msgid="2909250942299627244">"Start Wi-Fi Direct. Dette slår Wi-Fi-klient/hotspot fra."</string>
+    <string name="wifi_p2p_failed_message" msgid="3763669677935623084">"Wi-Fi Direct kunne ikke startes."</string>
+    <string name="wifi_p2p_enabled_notification_title" msgid="2068321881673734886">"Wi-Fi Direct er slået til"</string>
+    <string name="wifi_p2p_enabled_notification_message" msgid="1638949953993894335">"Tryk for indstillinger"</string>
     <string name="accept" msgid="1645267259272829559">"Accepter"</string>
     <string name="decline" msgid="2112225451706137894">"Afvis"</string>
     <string name="wifi_p2p_invitation_sent_title" msgid="1318975185112070734">"Invitationen er sendt"</string>
diff --git a/core/res/res/values-de/strings.xml b/core/res/res/values-de/strings.xml
index 20ef4d7..5ed2fd5 100644
--- a/core/res/res/values-de/strings.xml
+++ b/core/res/res/values-de/strings.xml
@@ -973,6 +973,11 @@
     <skip />
     <string name="wifi_watchdog_network_disabled" msgid="7904214231651546347">"Es konnte keine WLAN-Verbindung hergestellt werden."</string>
     <string name="wifi_watchdog_network_disabled_detailed" msgid="5548780776418332675">" hat eine schlechte Internetverbindung."</string>
+    <string name="wifi_p2p_dialog_title" msgid="97611782659324517">"Wi-Fi Direct"</string>
+    <string name="wifi_p2p_turnon_message" msgid="2909250942299627244">"Wi-Fi Direct-Betrieb starten. Hierdurch wird der WLAN-Client-/-Hotspot-Betrieb deaktiviert."</string>
+    <string name="wifi_p2p_failed_message" msgid="3763669677935623084">"Starten von Wi-Fi Direct nicht möglich"</string>
+    <string name="wifi_p2p_enabled_notification_title" msgid="2068321881673734886">"Wi-Fi Direct ist aktiviert."</string>
+    <string name="wifi_p2p_enabled_notification_message" msgid="1638949953993894335">"Zum Aufrufen der Einstellungen berühren"</string>
     <string name="accept" msgid="1645267259272829559">"Akzeptieren"</string>
     <string name="decline" msgid="2112225451706137894">"Ablehnen"</string>
     <string name="wifi_p2p_invitation_sent_title" msgid="1318975185112070734">"Einladung gesendet"</string>
diff --git a/core/res/res/values-el/strings.xml b/core/res/res/values-el/strings.xml
index 200f702..94b9921 100644
--- a/core/res/res/values-el/strings.xml
+++ b/core/res/res/values-el/strings.xml
@@ -973,6 +973,11 @@
     <skip />
     <string name="wifi_watchdog_network_disabled" msgid="7904214231651546347">"Δεν είναι δυνατή η σύνδεση στο Wi-Fi"</string>
     <string name="wifi_watchdog_network_disabled_detailed" msgid="5548780776418332675">" έχει κακή σύνδεση στο Διαδίκτυο."</string>
+    <string name="wifi_p2p_dialog_title" msgid="97611782659324517">"Wi-Fi Direct"</string>
+    <string name="wifi_p2p_turnon_message" msgid="2909250942299627244">"Ξεκινήστε τη λειτουργία Wi-Fi Direct. Θα απενεργοποιηθεί η λειτουργία πελάτη/φορητού σημείου πρόσβασης Wi-Fi."</string>
+    <string name="wifi_p2p_failed_message" msgid="3763669677935623084">"Δεν ήταν δυνατή η εκκίνηση του Wi-Fi Direct."</string>
+    <string name="wifi_p2p_enabled_notification_title" msgid="2068321881673734886">"Το Wi-Fi Direct έχει ενεργοποιηθεί"</string>
+    <string name="wifi_p2p_enabled_notification_message" msgid="1638949953993894335">"Αγγίξτε για ρυθμίσεις"</string>
     <string name="accept" msgid="1645267259272829559">"Αποδοχή"</string>
     <string name="decline" msgid="2112225451706137894">"Απόρριψη"</string>
     <string name="wifi_p2p_invitation_sent_title" msgid="1318975185112070734">"Η πρόσκληση στάλθηκε"</string>
diff --git a/core/res/res/values-en-rGB/strings.xml b/core/res/res/values-en-rGB/strings.xml
index 2859942..d150409 100644
--- a/core/res/res/values-en-rGB/strings.xml
+++ b/core/res/res/values-en-rGB/strings.xml
@@ -973,6 +973,11 @@
     <skip />
     <string name="wifi_watchdog_network_disabled" msgid="7904214231651546347">"Couldn\'t connect to Wi-Fi"</string>
     <string name="wifi_watchdog_network_disabled_detailed" msgid="5548780776418332675">" has a poor Internet connection."</string>
+    <string name="wifi_p2p_dialog_title" msgid="97611782659324517">"Wi-Fi Direct"</string>
+    <string name="wifi_p2p_turnon_message" msgid="2909250942299627244">"Start Wi-Fi Direct. This will turn off Wi-Fi client/hotspot."</string>
+    <string name="wifi_p2p_failed_message" msgid="3763669677935623084">"Couldn\'t start Wi-Fi Direct."</string>
+    <string name="wifi_p2p_enabled_notification_title" msgid="2068321881673734886">"Wi-Fi Direct is on"</string>
+    <string name="wifi_p2p_enabled_notification_message" msgid="1638949953993894335">"Touch for settings"</string>
     <string name="accept" msgid="1645267259272829559">"Accept"</string>
     <string name="decline" msgid="2112225451706137894">"Decline"</string>
     <string name="wifi_p2p_invitation_sent_title" msgid="1318975185112070734">"Invitation sent"</string>
diff --git a/core/res/res/values-es-rUS/strings.xml b/core/res/res/values-es-rUS/strings.xml
index dbc96e7..d4193f8 100644
--- a/core/res/res/values-es-rUS/strings.xml
+++ b/core/res/res/values-es-rUS/strings.xml
@@ -973,6 +973,11 @@
     <skip />
     <string name="wifi_watchdog_network_disabled" msgid="7904214231651546347">"No se pudo conectar a la red Wi-Fi."</string>
     <string name="wifi_watchdog_network_disabled_detailed" msgid="5548780776418332675">" tiene una mala conexión a Internet."</string>
+    <string name="wifi_p2p_dialog_title" msgid="97611782659324517">"Wi-Fi Direct"</string>
+    <string name="wifi_p2p_turnon_message" msgid="2909250942299627244">"Iniciar Wi-Fi Direct. Se desactivará el funcionamiento de la zona o del cliente Wi-Fi."</string>
+    <string name="wifi_p2p_failed_message" msgid="3763669677935623084">"No se pudo iniciar Wi-Fi Direct."</string>
+    <string name="wifi_p2p_enabled_notification_title" msgid="2068321881673734886">"Se activó Wi-Fi Direct."</string>
+    <string name="wifi_p2p_enabled_notification_message" msgid="1638949953993894335">"Tocar para ajustar los parámetros de configuración"</string>
     <string name="accept" msgid="1645267259272829559">"Aceptar"</string>
     <string name="decline" msgid="2112225451706137894">"Rechazar"</string>
     <string name="wifi_p2p_invitation_sent_title" msgid="1318975185112070734">"Se envió la invitación."</string>
diff --git a/core/res/res/values-es/strings.xml b/core/res/res/values-es/strings.xml
index d3c55a6..1625435 100644
--- a/core/res/res/values-es/strings.xml
+++ b/core/res/res/values-es/strings.xml
@@ -973,6 +973,11 @@
     <skip />
     <string name="wifi_watchdog_network_disabled" msgid="7904214231651546347">"No se ha podido establecer conexión con la red Wi-Fi."</string>
     <string name="wifi_watchdog_network_disabled_detailed" msgid="5548780776418332675">" tiene una conexión inestable a Internet."</string>
+    <string name="wifi_p2p_dialog_title" msgid="97611782659324517">"Wi-Fi Direct"</string>
+    <string name="wifi_p2p_turnon_message" msgid="2909250942299627244">"Iniciar Wi-Fi Direct. Se desactivará el funcionamiento de la zona o del cliente Wi-Fi."</string>
+    <string name="wifi_p2p_failed_message" msgid="3763669677935623084">"No se ha podido iniciar Wi-Fi Direct."</string>
+    <string name="wifi_p2p_enabled_notification_title" msgid="2068321881673734886">"Wi-Fi Direct activado"</string>
+    <string name="wifi_p2p_enabled_notification_message" msgid="1638949953993894335">"Toca para acceder a Ajustes"</string>
     <string name="accept" msgid="1645267259272829559">"Aceptar"</string>
     <string name="decline" msgid="2112225451706137894">"Rechazar"</string>
     <string name="wifi_p2p_invitation_sent_title" msgid="1318975185112070734">"Invitación enviada"</string>
diff --git a/core/res/res/values-et/strings.xml b/core/res/res/values-et/strings.xml
index c3a6169..0b1f1b9 100644
--- a/core/res/res/values-et/strings.xml
+++ b/core/res/res/values-et/strings.xml
@@ -973,6 +973,11 @@
     <skip />
     <string name="wifi_watchdog_network_disabled" msgid="7904214231651546347">"Ei saanud WiFi-ga ühendust"</string>
     <string name="wifi_watchdog_network_disabled_detailed" msgid="5548780776418332675">" on halb Interneti-ühendus."</string>
+    <string name="wifi_p2p_dialog_title" msgid="97611782659324517">"WiFi Direct"</string>
+    <string name="wifi_p2p_turnon_message" msgid="2909250942299627244">"Käivitage WiFi otseühendus. See lülitab välja WiFi kliendi/leviala."</string>
+    <string name="wifi_p2p_failed_message" msgid="3763669677935623084">"WiFi otseühenduse käivitamine ebaõnnestus."</string>
+    <string name="wifi_p2p_enabled_notification_title" msgid="2068321881673734886">"WiFi Direct on sees"</string>
+    <string name="wifi_p2p_enabled_notification_message" msgid="1638949953993894335">"Puuted seadete jaoks"</string>
     <string name="accept" msgid="1645267259272829559">"Nõustu"</string>
     <string name="decline" msgid="2112225451706137894">"Keeldu"</string>
     <string name="wifi_p2p_invitation_sent_title" msgid="1318975185112070734">"Kutse on saadetud"</string>
diff --git a/core/res/res/values-fa/strings.xml b/core/res/res/values-fa/strings.xml
index 87eee68..c1eaac0 100644
--- a/core/res/res/values-fa/strings.xml
+++ b/core/res/res/values-fa/strings.xml
@@ -973,6 +973,11 @@
     <skip />
     <string name="wifi_watchdog_network_disabled" msgid="7904214231651546347">"اتصال به Wi-Fi ممکن نیست"</string>
     <string name="wifi_watchdog_network_disabled_detailed" msgid="5548780776418332675">" اتصال اینترنتی ضعیفی دارد."</string>
+    <string name="wifi_p2p_dialog_title" msgid="97611782659324517">"Wi-Fi Direct"</string>
+    <string name="wifi_p2p_turnon_message" msgid="2909250942299627244">"Wi-Fi Direct را شروع کنید. این کار نقطه اتصال/سرویس گیرنده Wi-Fi را غیرفعال خواهد کرد."</string>
+    <string name="wifi_p2p_failed_message" msgid="3763669677935623084">"Wi-Fi Direct شروع نشد."</string>
+    <string name="wifi_p2p_enabled_notification_title" msgid="2068321881673734886">"Wi-Fi Direct روشن است"</string>
+    <string name="wifi_p2p_enabled_notification_message" msgid="1638949953993894335">"لمس کردن برای تنظیمات"</string>
     <string name="accept" msgid="1645267259272829559">"پذیرش"</string>
     <string name="decline" msgid="2112225451706137894">"عدم پذیرش"</string>
     <string name="wifi_p2p_invitation_sent_title" msgid="1318975185112070734">"دعوت‌نامه ارسال شد"</string>
diff --git a/core/res/res/values-fi/strings.xml b/core/res/res/values-fi/strings.xml
index 5ab7158..7f4d017 100644
--- a/core/res/res/values-fi/strings.xml
+++ b/core/res/res/values-fi/strings.xml
@@ -973,6 +973,11 @@
     <skip />
     <string name="wifi_watchdog_network_disabled" msgid="7904214231651546347">"Wifi-yhteyden muodostaminen epäonnistui"</string>
     <string name="wifi_watchdog_network_disabled_detailed" msgid="5548780776418332675">" : huono internetyhteys."</string>
+    <string name="wifi_p2p_dialog_title" msgid="97611782659324517">"Suora wifi-yhteys"</string>
+    <string name="wifi_p2p_turnon_message" msgid="2909250942299627244">"Käynnistä suora wifi-yhteys. Wifi-asiakas/-hotspot poistetaan käytöstä."</string>
+    <string name="wifi_p2p_failed_message" msgid="3763669677935623084">"Suoran wifi-yhteyden käynnistäminen epäonnistui."</string>
+    <string name="wifi_p2p_enabled_notification_title" msgid="2068321881673734886">"Wi-Fi Direct on käytössä"</string>
+    <string name="wifi_p2p_enabled_notification_message" msgid="1638949953993894335">"Tarkastele asetuksia koskettamalla"</string>
     <string name="accept" msgid="1645267259272829559">"Hyväksy"</string>
     <string name="decline" msgid="2112225451706137894">"Hylkää"</string>
     <string name="wifi_p2p_invitation_sent_title" msgid="1318975185112070734">"Kutsu lähetetty."</string>
diff --git a/core/res/res/values-fr/strings.xml b/core/res/res/values-fr/strings.xml
index 6067350..b01e857 100644
--- a/core/res/res/values-fr/strings.xml
+++ b/core/res/res/values-fr/strings.xml
@@ -973,6 +973,11 @@
     <skip />
     <string name="wifi_watchdog_network_disabled" msgid="7904214231651546347">"Impossible de se connecter au Wi-Fi."</string>
     <string name="wifi_watchdog_network_disabled_detailed" msgid="5548780776418332675">" dispose d\'une mauvaise connexion Internet."</string>
+    <string name="wifi_p2p_dialog_title" msgid="97611782659324517">"Wi-Fi Direct"</string>
+    <string name="wifi_p2p_turnon_message" msgid="2909250942299627244">"Lancer le Wi-Fi Direct. Cela désactive le fonctionnement du Wi-Fi client ou via un point d\'accès."</string>
+    <string name="wifi_p2p_failed_message" msgid="3763669677935623084">"Impossible d\'activer le Wi-Fi Direct."</string>
+    <string name="wifi_p2p_enabled_notification_title" msgid="2068321881673734886">"Wi-Fi Direct activé"</string>
+    <string name="wifi_p2p_enabled_notification_message" msgid="1638949953993894335">"Appuyez pour accéder aux paramètres."</string>
     <string name="accept" msgid="1645267259272829559">"Accepter"</string>
     <string name="decline" msgid="2112225451706137894">"Refuser"</string>
     <string name="wifi_p2p_invitation_sent_title" msgid="1318975185112070734">"Invitation envoyée"</string>
diff --git a/core/res/res/values-hi/strings.xml b/core/res/res/values-hi/strings.xml
index 1aaedbd..5401333 100644
--- a/core/res/res/values-hi/strings.xml
+++ b/core/res/res/values-hi/strings.xml
@@ -973,6 +973,11 @@
     <skip />
     <string name="wifi_watchdog_network_disabled" msgid="7904214231651546347">"Wi-Fi से कनेक्‍ट नहीं हो सका"</string>
     <string name="wifi_watchdog_network_disabled_detailed" msgid="5548780776418332675">" के पास एक कमज़ोर इंटरनेट कनेक्‍शन है."</string>
+    <string name="wifi_p2p_dialog_title" msgid="97611782659324517">"Wi-Fi प्रत्यक्ष"</string>
+    <string name="wifi_p2p_turnon_message" msgid="2909250942299627244">"Wi-Fi डायरेक्ट प्रारंभ करें. इससे Wi-Fi क्‍लाइंट/हॉटस्पॉट कार्यवाही बंद हो जाएगी."</string>
+    <string name="wifi_p2p_failed_message" msgid="3763669677935623084">"Wi-Fi डायरेक्ट प्रारंभ नहीं किया जा सका."</string>
+    <string name="wifi_p2p_enabled_notification_title" msgid="2068321881673734886">"Wi-Fi प्रत्यक्ष चालू है"</string>
+    <string name="wifi_p2p_enabled_notification_message" msgid="1638949953993894335">"सेटिंग के लिए स्‍पर्श करें"</string>
     <string name="accept" msgid="1645267259272829559">"स्वीकार करें"</string>
     <string name="decline" msgid="2112225451706137894">"अस्वीकार करें"</string>
     <string name="wifi_p2p_invitation_sent_title" msgid="1318975185112070734">"आमंत्रण भेजा गया"</string>
diff --git a/core/res/res/values-hr/strings.xml b/core/res/res/values-hr/strings.xml
index 0775984..146b809 100644
--- a/core/res/res/values-hr/strings.xml
+++ b/core/res/res/values-hr/strings.xml
@@ -973,6 +973,11 @@
     <skip />
     <string name="wifi_watchdog_network_disabled" msgid="7904214231651546347">"Ne može se spojiti na Wi-Fi"</string>
     <string name="wifi_watchdog_network_disabled_detailed" msgid="5548780776418332675">" ima lošu internetsku vezu."</string>
+    <string name="wifi_p2p_dialog_title" msgid="97611782659324517">"Izravni Wi-Fi"</string>
+    <string name="wifi_p2p_turnon_message" msgid="2909250942299627244">"Pokreni izravan rad s Wi-Fi mrežom. To će isključiti rad s Wi-Fi klijentom/žarišnom točkom."</string>
+    <string name="wifi_p2p_failed_message" msgid="3763669677935623084">"Pokretanje izravne Wi-Fi veze nije moguće."</string>
+    <string name="wifi_p2p_enabled_notification_title" msgid="2068321881673734886">"Wi-Fi Direct uključen"</string>
+    <string name="wifi_p2p_enabled_notification_message" msgid="1638949953993894335">"Dodirnite za postavke"</string>
     <string name="accept" msgid="1645267259272829559">"Prihvaćam"</string>
     <string name="decline" msgid="2112225451706137894">"Odbaci"</string>
     <string name="wifi_p2p_invitation_sent_title" msgid="1318975185112070734">"Pozivnica je poslana"</string>
diff --git a/core/res/res/values-hu/strings.xml b/core/res/res/values-hu/strings.xml
index e125ba8..f688ce4 100644
--- a/core/res/res/values-hu/strings.xml
+++ b/core/res/res/values-hu/strings.xml
@@ -973,6 +973,11 @@
     <skip />
     <string name="wifi_watchdog_network_disabled" msgid="7904214231651546347">"Nem sikerült csatlakozni a Wi-Fi hálózathoz"</string>
     <string name="wifi_watchdog_network_disabled_detailed" msgid="5548780776418332675">" rossz internetkapcsolattal rendelkezik."</string>
+    <string name="wifi_p2p_dialog_title" msgid="97611782659324517">"Wi-Fi Direct"</string>
+    <string name="wifi_p2p_turnon_message" msgid="2909250942299627244">"Wi-Fi Direct elindítása. A Wi-Fi kliens/hotspot ettől leáll."</string>
+    <string name="wifi_p2p_failed_message" msgid="3763669677935623084">"Nem sikerült elindítani a Wi-Fi Direct kapcsolatot."</string>
+    <string name="wifi_p2p_enabled_notification_title" msgid="2068321881673734886">"A Wi-Fi Direct be van kapcsolva"</string>
+    <string name="wifi_p2p_enabled_notification_message" msgid="1638949953993894335">"A beállításokhoz érintse meg"</string>
     <string name="accept" msgid="1645267259272829559">"Elfogadás"</string>
     <string name="decline" msgid="2112225451706137894">"Elutasítás"</string>
     <string name="wifi_p2p_invitation_sent_title" msgid="1318975185112070734">"Meghívó elküldve"</string>
diff --git a/core/res/res/values-in/strings.xml b/core/res/res/values-in/strings.xml
index 72fcb50..19f7dbf 100644
--- a/core/res/res/values-in/strings.xml
+++ b/core/res/res/values-in/strings.xml
@@ -973,6 +973,11 @@
     <skip />
     <string name="wifi_watchdog_network_disabled" msgid="7904214231651546347">"Tidak dapat tersambung ke Wi-Fi"</string>
     <string name="wifi_watchdog_network_disabled_detailed" msgid="5548780776418332675">" memiliki sambungan internet yang buruk."</string>
+    <string name="wifi_p2p_dialog_title" msgid="97611782659324517">"Wi-Fi Langsung"</string>
+    <string name="wifi_p2p_turnon_message" msgid="2909250942299627244">"Memulai Wi-Fi Langsung. Opsi ini akan mematikan hotspot/klien Wi-Fi."</string>
+    <string name="wifi_p2p_failed_message" msgid="3763669677935623084">"Tidak dapat memulai Wi-Fi Langsung."</string>
+    <string name="wifi_p2p_enabled_notification_title" msgid="2068321881673734886">"Wi-Fi Langsung aktif"</string>
+    <string name="wifi_p2p_enabled_notification_message" msgid="1638949953993894335">"Sentuh untuk setelan"</string>
     <string name="accept" msgid="1645267259272829559">"Terima"</string>
     <string name="decline" msgid="2112225451706137894">"Tolak"</string>
     <string name="wifi_p2p_invitation_sent_title" msgid="1318975185112070734">"Undangan terkirim"</string>
diff --git a/core/res/res/values-it/strings.xml b/core/res/res/values-it/strings.xml
index ec9457b..3631850 100644
--- a/core/res/res/values-it/strings.xml
+++ b/core/res/res/values-it/strings.xml
@@ -973,6 +973,11 @@
     <skip />
     <string name="wifi_watchdog_network_disabled" msgid="7904214231651546347">"Impossibile connettersi alla rete Wi-Fi"</string>
     <string name="wifi_watchdog_network_disabled_detailed" msgid="5548780776418332675">" ha una connessione Internet debole."</string>
+    <string name="wifi_p2p_dialog_title" msgid="97611782659324517">"Wi-Fi Direct"</string>
+    <string name="wifi_p2p_turnon_message" msgid="2909250942299627244">"Avvia Wi-Fi Direct. Verrà disattivato il client/hotspot Wi-Fi."</string>
+    <string name="wifi_p2p_failed_message" msgid="3763669677935623084">"Avvio di Wi-Fi Direct non riuscito."</string>
+    <string name="wifi_p2p_enabled_notification_title" msgid="2068321881673734886">"Wi-Fi Direct è attivo"</string>
+    <string name="wifi_p2p_enabled_notification_message" msgid="1638949953993894335">"Tocca per le impostazioni"</string>
     <string name="accept" msgid="1645267259272829559">"Accetto"</string>
     <string name="decline" msgid="2112225451706137894">"Rifiuto"</string>
     <string name="wifi_p2p_invitation_sent_title" msgid="1318975185112070734">"Invito inviato"</string>
diff --git a/core/res/res/values-iw/strings.xml b/core/res/res/values-iw/strings.xml
index 5fc15c7..ec8274f 100644
--- a/core/res/res/values-iw/strings.xml
+++ b/core/res/res/values-iw/strings.xml
@@ -973,6 +973,11 @@
     <skip />
     <string name="wifi_watchdog_network_disabled" msgid="7904214231651546347">"אין אפשרות להתחבר ל-Wi-Fi"</string>
     <string name="wifi_watchdog_network_disabled_detailed" msgid="5548780776418332675">" אינו מחובר היטב לאינטרנט."</string>
+    <string name="wifi_p2p_dialog_title" msgid="97611782659324517">"Wi-Fi ישיר"</string>
+    <string name="wifi_p2p_turnon_message" msgid="2909250942299627244">"הפעל Wi-Fi ישיר. פעולה זו תכבה את הלקוח/הנקודה החמה של ה-Wi-Fi."</string>
+    <string name="wifi_p2p_failed_message" msgid="3763669677935623084">"לא ניתן להפעיל Wi-Fi ישיר"</string>
+    <string name="wifi_p2p_enabled_notification_title" msgid="2068321881673734886">"Wi-Fi ישיר מופעל"</string>
+    <string name="wifi_p2p_enabled_notification_message" msgid="1638949953993894335">"גע עבור הגדרות"</string>
     <string name="accept" msgid="1645267259272829559">"קבל"</string>
     <string name="decline" msgid="2112225451706137894">"דחה"</string>
     <string name="wifi_p2p_invitation_sent_title" msgid="1318975185112070734">"ההזמנה נשלחה"</string>
diff --git a/core/res/res/values-ja/strings.xml b/core/res/res/values-ja/strings.xml
index 63b8c73..e03d6cc 100644
--- a/core/res/res/values-ja/strings.xml
+++ b/core/res/res/values-ja/strings.xml
@@ -216,7 +216,7 @@
     <string name="permlab_removeTasks" msgid="6821513401870377403">"実行中のアプリの停止"</string>
     <string name="permdesc_removeTasks" msgid="1394714352062635493">"タスクの削除とアプリの終了をアプリに許可します。この許可を悪意のあるアプリケーションに利用されると、他のアプリの動作が妨害される恐れがあります。"</string>
     <string name="permlab_setScreenCompatibility" msgid="6975387118861842061">"画面互換性の設定"</string>
-    <string name="permdesc_setScreenCompatibility" msgid="692043618693917374">"他のアプリケーションの画面互換性モードをコントロールすることをアプリに許可します。この許可を悪意のあるアプリケーションに利用されると、他のアプリケーションの動作が中断される恐れがあります。"</string>
+    <string name="permdesc_setScreenCompatibility" msgid="692043618693917374">"他のアプリの画面互換性モードをコントロールすることをアプリに許可します。この許可を悪意のあるアプリに利用されると、他のアプリの動作が中断される恐れがあります。"</string>
     <string name="permlab_setDebugApp" msgid="3022107198686584052">"アプリのデバッグの有効化"</string>
     <string name="permdesc_setDebugApp" msgid="4474512416299013256">"別のアプリをデバッグモードにすることをアプリに許可します。この許可を悪意のあるアプリに利用されると、他のアプリが強制終了される恐れがあります。"</string>
     <string name="permlab_changeConfiguration" msgid="8214475779521218295">"UI設定の変更"</string>
@@ -973,6 +973,11 @@
     <skip />
     <string name="wifi_watchdog_network_disabled" msgid="7904214231651546347">"Wi-Fiに接続できませんでした"</string>
     <string name="wifi_watchdog_network_disabled_detailed" msgid="5548780776418332675">" はインターネット接続に問題があります。"</string>
+    <string name="wifi_p2p_dialog_title" msgid="97611782659324517">"Wi-Fi Direct"</string>
+    <string name="wifi_p2p_turnon_message" msgid="2909250942299627244">"Wi-Fi Directを開始します。これによりWi-Fiクライアント/アクセスポイントがOFFになります。"</string>
+    <string name="wifi_p2p_failed_message" msgid="3763669677935623084">"Wi-Fi Directを開始できませんでした。"</string>
+    <string name="wifi_p2p_enabled_notification_title" msgid="2068321881673734886">"Wi-Fi DirectはONです"</string>
+    <string name="wifi_p2p_enabled_notification_message" msgid="1638949953993894335">"設定を表示するにはタップしてください"</string>
     <string name="accept" msgid="1645267259272829559">"同意する"</string>
     <string name="decline" msgid="2112225451706137894">"同意しない"</string>
     <string name="wifi_p2p_invitation_sent_title" msgid="1318975185112070734">"招待状を送信しました"</string>
diff --git a/core/res/res/values-ko/strings.xml b/core/res/res/values-ko/strings.xml
index f97cbdc..85c6f32 100644
--- a/core/res/res/values-ko/strings.xml
+++ b/core/res/res/values-ko/strings.xml
@@ -973,6 +973,11 @@
     <skip />
     <string name="wifi_watchdog_network_disabled" msgid="7904214231651546347">"Wi-Fi에 연결할 수 없습니다"</string>
     <string name="wifi_watchdog_network_disabled_detailed" msgid="5548780776418332675">" 인터넷 연결 상태가 좋지 않습니다."</string>
+    <string name="wifi_p2p_dialog_title" msgid="97611782659324517">"Wi-Fi Direct"</string>
+    <string name="wifi_p2p_turnon_message" msgid="2909250942299627244">"Wi-Fi Direct 작업을 시작합니다. 이 작업을 하면 Wi-Fi 클라이언트/핫스팟 작업이 중지됩니다."</string>
+    <string name="wifi_p2p_failed_message" msgid="3763669677935623084">"Wi-Fi Direct를 시작하지 못했습니다."</string>
+    <string name="wifi_p2p_enabled_notification_title" msgid="2068321881673734886">"Wi-Fi Direct 켜짐"</string>
+    <string name="wifi_p2p_enabled_notification_message" msgid="1638949953993894335">"설정으로 이동하려면 터치하세요."</string>
     <string name="accept" msgid="1645267259272829559">"동의"</string>
     <string name="decline" msgid="2112225451706137894">"거부"</string>
     <string name="wifi_p2p_invitation_sent_title" msgid="1318975185112070734">"초대장을 보냈습니다."</string>
diff --git a/core/res/res/values-lt/strings.xml b/core/res/res/values-lt/strings.xml
index a1694af..593c44d 100644
--- a/core/res/res/values-lt/strings.xml
+++ b/core/res/res/values-lt/strings.xml
@@ -973,6 +973,11 @@
     <skip />
     <string name="wifi_watchdog_network_disabled" msgid="7904214231651546347">"Nepavyko prisijungti prie „Wi-Fi“"</string>
     <string name="wifi_watchdog_network_disabled_detailed" msgid="5548780776418332675">" turi prastą interneto ryšį."</string>
+    <string name="wifi_p2p_dialog_title" msgid="97611782659324517">"Tiesioginis „Wi-Fi“ ryšys"</string>
+    <string name="wifi_p2p_turnon_message" msgid="2909250942299627244">"Paleiskite „Wi-Fi Direct“. Bus išjungta „Wi-Fi“ programa / viešosios interneto prieigos taškas."</string>
+    <string name="wifi_p2p_failed_message" msgid="3763669677935623084">"Nepavyko paleisti „Wi-Fi Direct“."</string>
+    <string name="wifi_p2p_enabled_notification_title" msgid="2068321881673734886">"„Wi-Fi Direct“ įjungta"</string>
+    <string name="wifi_p2p_enabled_notification_message" msgid="1638949953993894335">"Jei norite peržiūrėti nustatymus, palieskite"</string>
     <string name="accept" msgid="1645267259272829559">"Sutikti"</string>
     <string name="decline" msgid="2112225451706137894">"Atmesti"</string>
     <string name="wifi_p2p_invitation_sent_title" msgid="1318975185112070734">"Pakvietimas išsiųstas"</string>
diff --git a/core/res/res/values-lv/strings.xml b/core/res/res/values-lv/strings.xml
index aeec70b..33089b3 100644
--- a/core/res/res/values-lv/strings.xml
+++ b/core/res/res/values-lv/strings.xml
@@ -973,6 +973,11 @@
     <skip />
     <string name="wifi_watchdog_network_disabled" msgid="7904214231651546347">"Nevarēja izveidot savienojumu ar Wi-Fi."</string>
     <string name="wifi_watchdog_network_disabled_detailed" msgid="5548780776418332675">" ir slikts interneta savienojums."</string>
+    <string name="wifi_p2p_dialog_title" msgid="97611782659324517">"Wi-Fi Direct"</string>
+    <string name="wifi_p2p_turnon_message" msgid="2909250942299627244">"Palaist programmu Wi-Fi Direct. Tādējādi tiks izslēgta Wi-Fi klienta/tīklāja darbība."</string>
+    <string name="wifi_p2p_failed_message" msgid="3763669677935623084">"Nevarēja palaist programmu Wi-Fi Direct."</string>
+    <string name="wifi_p2p_enabled_notification_title" msgid="2068321881673734886">"Wi-Fi Direct ir ieslēgts"</string>
+    <string name="wifi_p2p_enabled_notification_message" msgid="1638949953993894335">"Pieskarieties, lai piekļūtu iestatījumiem."</string>
     <string name="accept" msgid="1645267259272829559">"Piekrist"</string>
     <string name="decline" msgid="2112225451706137894">"Noraidīt"</string>
     <string name="wifi_p2p_invitation_sent_title" msgid="1318975185112070734">"Ielūgums ir nosūtīts."</string>
diff --git a/core/res/res/values-ms/strings.xml b/core/res/res/values-ms/strings.xml
index 0610e88..a913258 100644
--- a/core/res/res/values-ms/strings.xml
+++ b/core/res/res/values-ms/strings.xml
@@ -973,6 +973,11 @@
     <skip />
     <string name="wifi_watchdog_network_disabled" msgid="7904214231651546347">"Tidak boleh menyambung kepada Wi-Fi"</string>
     <string name="wifi_watchdog_network_disabled_detailed" msgid="5548780776418332675">" mempunyai sambungan internet yang kurang baik."</string>
+    <string name="wifi_p2p_dialog_title" msgid="97611782659324517">"Wi-Fi Langsung"</string>
+    <string name="wifi_p2p_turnon_message" msgid="2909250942299627244">"Mulakan Wi-Fi Langsung. Hal ini akan mematikan pengendalian klien/liputan Wi-Fi."</string>
+    <string name="wifi_p2p_failed_message" msgid="3763669677935623084">"Tidak dapat memulakan Wi-Fi Langsung."</string>
+    <string name="wifi_p2p_enabled_notification_title" msgid="2068321881673734886">"Wi-Fi Direct dihidupkan"</string>
+    <string name="wifi_p2p_enabled_notification_message" msgid="1638949953993894335">"Sentuh untuk tetapan"</string>
     <string name="accept" msgid="1645267259272829559">"Terima"</string>
     <string name="decline" msgid="2112225451706137894">"Tolak"</string>
     <string name="wifi_p2p_invitation_sent_title" msgid="1318975185112070734">"Jemputan dihantar"</string>
diff --git a/core/res/res/values-nb/strings.xml b/core/res/res/values-nb/strings.xml
index e82718e..52f254f 100644
--- a/core/res/res/values-nb/strings.xml
+++ b/core/res/res/values-nb/strings.xml
@@ -973,6 +973,11 @@
     <skip />
     <string name="wifi_watchdog_network_disabled" msgid="7904214231651546347">"Kan ikke koble til Wi-Fi"</string>
     <string name="wifi_watchdog_network_disabled_detailed" msgid="5548780776418332675">" har en dårlig Internett-tilkobling."</string>
+    <string name="wifi_p2p_dialog_title" msgid="97611782659324517">"Wi-Fi Direct"</string>
+    <string name="wifi_p2p_turnon_message" msgid="2909250942299627244">"Start Wi-Fi Direct. Dette deaktiverer Wi-Fi-klienten/-sonen."</string>
+    <string name="wifi_p2p_failed_message" msgid="3763669677935623084">"Kunne ikke starte Wi-Fi Direct."</string>
+    <string name="wifi_p2p_enabled_notification_title" msgid="2068321881673734886">"Wi-Fi Direct er slått på"</string>
+    <string name="wifi_p2p_enabled_notification_message" msgid="1638949953993894335">"Berør for å se innstillinger"</string>
     <string name="accept" msgid="1645267259272829559">"Godta"</string>
     <string name="decline" msgid="2112225451706137894">"Avslå"</string>
     <string name="wifi_p2p_invitation_sent_title" msgid="1318975185112070734">"Invitasjonen er sendt"</string>
diff --git a/core/res/res/values-nl/strings.xml b/core/res/res/values-nl/strings.xml
index ef4dd6a..b383018 100644
--- a/core/res/res/values-nl/strings.xml
+++ b/core/res/res/values-nl/strings.xml
@@ -973,6 +973,11 @@
     <skip />
     <string name="wifi_watchdog_network_disabled" msgid="7904214231651546347">"Kan geen verbinding maken met Wi-Fi"</string>
     <string name="wifi_watchdog_network_disabled_detailed" msgid="5548780776418332675">" heeft een slechte internetverbinding."</string>
+    <string name="wifi_p2p_dialog_title" msgid="97611782659324517">"Wi-Fi Direct"</string>
+    <string name="wifi_p2p_turnon_message" msgid="2909250942299627244">"Wifi Direct starten. Hierdoor wordt de wifi-client/hotspot uitgeschakeld."</string>
+    <string name="wifi_p2p_failed_message" msgid="3763669677935623084">"Kan Wifi Direct niet starten."</string>
+    <string name="wifi_p2p_enabled_notification_title" msgid="2068321881673734886">"Wi-Fi Direct is actief"</string>
+    <string name="wifi_p2p_enabled_notification_message" msgid="1638949953993894335">"Aanraken voor instellingen"</string>
     <string name="accept" msgid="1645267259272829559">"Accepteren"</string>
     <string name="decline" msgid="2112225451706137894">"Weigeren"</string>
     <string name="wifi_p2p_invitation_sent_title" msgid="1318975185112070734">"Uitnodiging verzonden"</string>
diff --git a/core/res/res/values-pl/strings.xml b/core/res/res/values-pl/strings.xml
index f231d89..57f05c2 100644
--- a/core/res/res/values-pl/strings.xml
+++ b/core/res/res/values-pl/strings.xml
@@ -216,7 +216,7 @@
     <string name="permlab_removeTasks" msgid="6821513401870377403">"zatrzymywanie uruchomionych aplikacji"</string>
     <string name="permdesc_removeTasks" msgid="1394714352062635493">"Umożliwia aplikacji usuwanie zadań i kończenie powiązanych z nimi aplikacji. Złośliwe aplikacje mogą zakłócić działanie innych aplikacji."</string>
     <string name="permlab_setScreenCompatibility" msgid="6975387118861842061">"ustaw zgodność ekranu"</string>
-    <string name="permdesc_setScreenCompatibility" msgid="692043618693917374">"Pozwala aplikacji na sterowanie trybem zgodności ekranu innych aplikacji. Złośliwe aplikacje mogą zmienić zachowanie innych aplikacji."</string>
+    <string name="permdesc_setScreenCompatibility" msgid="692043618693917374">"Pozwala aplikacji na sterowanie trybem zgodności ekranu innych aplikacji. Złośliwe aplikacje mogą zmienić zachowanie innych programów."</string>
     <string name="permlab_setDebugApp" msgid="3022107198686584052">"włączenie debugowania aplikacji"</string>
     <string name="permdesc_setDebugApp" msgid="4474512416299013256">"Pozwala aplikacji na włączenie debugowania innej aplikacji. Złośliwe aplikacje mogą to wykorzystać do kończenia pracy innych programów."</string>
     <string name="permlab_changeConfiguration" msgid="8214475779521218295">"zmienianie ustawień interfejsu użytkownika"</string>
@@ -973,6 +973,11 @@
     <skip />
     <string name="wifi_watchdog_network_disabled" msgid="7904214231651546347">"Nie można połączyć się z siecią Wi-Fi."</string>
     <string name="wifi_watchdog_network_disabled_detailed" msgid="5548780776418332675">" ma powolne połączenie internetowe."</string>
+    <string name="wifi_p2p_dialog_title" msgid="97611782659324517">"Wi-Fi Direct"</string>
+    <string name="wifi_p2p_turnon_message" msgid="2909250942299627244">"Uruchom Wi-Fi Direct. Spowoduje to wyłączenie klienta lub punktu dostępu Wi-Fi."</string>
+    <string name="wifi_p2p_failed_message" msgid="3763669677935623084">"Nie można uruchomić Wi-Fi Direct."</string>
+    <string name="wifi_p2p_enabled_notification_title" msgid="2068321881673734886">"Wi-Fi Direct włączone"</string>
+    <string name="wifi_p2p_enabled_notification_message" msgid="1638949953993894335">"Dotknij, aby zmienić ustawienia"</string>
     <string name="accept" msgid="1645267259272829559">"Akceptuj"</string>
     <string name="decline" msgid="2112225451706137894">"Odrzuć"</string>
     <string name="wifi_p2p_invitation_sent_title" msgid="1318975185112070734">"Wysłano zaproszenie"</string>
diff --git a/core/res/res/values-pt-rPT/strings.xml b/core/res/res/values-pt-rPT/strings.xml
index f3f060090..e3ce856 100644
--- a/core/res/res/values-pt-rPT/strings.xml
+++ b/core/res/res/values-pt-rPT/strings.xml
@@ -973,6 +973,11 @@
     <skip />
     <string name="wifi_watchdog_network_disabled" msgid="7904214231651546347">"Não foi possível ligar a Wi-Fi"</string>
     <string name="wifi_watchdog_network_disabled_detailed" msgid="5548780776418332675">" tem uma ligação à internet fraca."</string>
+    <string name="wifi_p2p_dialog_title" msgid="97611782659324517">"Wi-Fi Direct"</string>
+    <string name="wifi_p2p_turnon_message" msgid="2909250942299627244">"Iniciar o Wi-Fi Direct. Esta opção desativará o cliente/zona Wi-Fi."</string>
+    <string name="wifi_p2p_failed_message" msgid="3763669677935623084">"Não foi possível iniciar o Wi-Fi Direct."</string>
+    <string name="wifi_p2p_enabled_notification_title" msgid="2068321881673734886">"O Wi-Fi Direct está ativado"</string>
+    <string name="wifi_p2p_enabled_notification_message" msgid="1638949953993894335">"Toque para aceder às definições"</string>
     <string name="accept" msgid="1645267259272829559">"Aceitar"</string>
     <string name="decline" msgid="2112225451706137894">"Recusar"</string>
     <string name="wifi_p2p_invitation_sent_title" msgid="1318975185112070734">"Convite enviado"</string>
diff --git a/core/res/res/values-pt/strings.xml b/core/res/res/values-pt/strings.xml
index b49c36b..13b2099 100644
--- a/core/res/res/values-pt/strings.xml
+++ b/core/res/res/values-pt/strings.xml
@@ -973,6 +973,11 @@
     <skip />
     <string name="wifi_watchdog_network_disabled" msgid="7904214231651546347">"Não foi possível se conectar a redes Wi-Fi"</string>
     <string name="wifi_watchdog_network_disabled_detailed" msgid="5548780776418332675">" tem uma conexão de baixa qualidade com a Internet."</string>
+    <string name="wifi_p2p_dialog_title" msgid="97611782659324517">"Wi-Fi Direct"</string>
+    <string name="wifi_p2p_turnon_message" msgid="2909250942299627244">"Iniciar o Wi-Fi Direct. Isso desativará o ponto de acesso/cliente Wi-Fi."</string>
+    <string name="wifi_p2p_failed_message" msgid="3763669677935623084">"Não foi possível iniciar o Wi-Fi Direct."</string>
+    <string name="wifi_p2p_enabled_notification_title" msgid="2068321881673734886">"Wi-Fi Direct ativado"</string>
+    <string name="wifi_p2p_enabled_notification_message" msgid="1638949953993894335">"Tocar para acessar configurações"</string>
     <string name="accept" msgid="1645267259272829559">"Aceitar"</string>
     <string name="decline" msgid="2112225451706137894">"Recusar"</string>
     <string name="wifi_p2p_invitation_sent_title" msgid="1318975185112070734">"Convite enviado"</string>
diff --git a/core/res/res/values-rm/strings.xml b/core/res/res/values-rm/strings.xml
index 1447c0e..9c8b847 100644
--- a/core/res/res/values-rm/strings.xml
+++ b/core/res/res/values-rm/strings.xml
@@ -1418,6 +1418,16 @@
     <skip />
     <!-- no translation found for wifi_watchdog_network_disabled_detailed (5548780776418332675) -->
     <skip />
+    <!-- no translation found for wifi_p2p_dialog_title (97611782659324517) -->
+    <skip />
+    <!-- no translation found for wifi_p2p_turnon_message (2909250942299627244) -->
+    <skip />
+    <!-- no translation found for wifi_p2p_failed_message (3763669677935623084) -->
+    <skip />
+    <!-- no translation found for wifi_p2p_enabled_notification_title (2068321881673734886) -->
+    <skip />
+    <!-- no translation found for wifi_p2p_enabled_notification_message (1638949953993894335) -->
+    <skip />
     <!-- no translation found for accept (1645267259272829559) -->
     <skip />
     <!-- no translation found for decline (2112225451706137894) -->
diff --git a/core/res/res/values-ro/strings.xml b/core/res/res/values-ro/strings.xml
index f241e8e..2f57660 100644
--- a/core/res/res/values-ro/strings.xml
+++ b/core/res/res/values-ro/strings.xml
@@ -973,6 +973,11 @@
     <skip />
     <string name="wifi_watchdog_network_disabled" msgid="7904214231651546347">"Nu se poate conecta la Wi-Fi"</string>
     <string name="wifi_watchdog_network_disabled_detailed" msgid="5548780776418332675">" are o conexiune la internet slabă."</string>
+    <string name="wifi_p2p_dialog_title" msgid="97611782659324517">"Wi-Fi Direct"</string>
+    <string name="wifi_p2p_turnon_message" msgid="2909250942299627244">"Porniţi Wi-Fi Direct. Acest lucru va dezactiva clientul/hotspotul Wi-Fi."</string>
+    <string name="wifi_p2p_failed_message" msgid="3763669677935623084">"Wi-Fi Direct nu a putut porni."</string>
+    <string name="wifi_p2p_enabled_notification_title" msgid="2068321881673734886">"Wi-Fi Direct este activat"</string>
+    <string name="wifi_p2p_enabled_notification_message" msgid="1638949953993894335">"Atingeţi pentru setări"</string>
     <string name="accept" msgid="1645267259272829559">"Acceptaţi"</string>
     <string name="decline" msgid="2112225451706137894">"Refuzaţi"</string>
     <string name="wifi_p2p_invitation_sent_title" msgid="1318975185112070734">"Invitaţia a fost trimisă."</string>
diff --git a/core/res/res/values-ru/strings.xml b/core/res/res/values-ru/strings.xml
index 809da83..70a165f 100644
--- a/core/res/res/values-ru/strings.xml
+++ b/core/res/res/values-ru/strings.xml
@@ -973,6 +973,11 @@
     <skip />
     <string name="wifi_watchdog_network_disabled" msgid="7904214231651546347">"Не удалось подключиться к сети Wi-Fi"</string>
     <string name="wifi_watchdog_network_disabled_detailed" msgid="5548780776418332675">" – плохое интернет-соединение."</string>
+    <string name="wifi_p2p_dialog_title" msgid="97611782659324517">"Wi-Fi Direct"</string>
+    <string name="wifi_p2p_turnon_message" msgid="2909250942299627244">"Начать соединение через Wi-Fi Direct. Модуль Wi-Fi будет отключен."</string>
+    <string name="wifi_p2p_failed_message" msgid="3763669677935623084">"Не удалось запустить Wi-Fi Direct."</string>
+    <string name="wifi_p2p_enabled_notification_title" msgid="2068321881673734886">"Wi-Fi Direct включен"</string>
+    <string name="wifi_p2p_enabled_notification_message" msgid="1638949953993894335">"Нажмите, чтобы открыть настройки"</string>
     <string name="accept" msgid="1645267259272829559">"Принять"</string>
     <string name="decline" msgid="2112225451706137894">"Отклонить"</string>
     <string name="wifi_p2p_invitation_sent_title" msgid="1318975185112070734">"Приглашение отправлено"</string>
diff --git a/core/res/res/values-sk/strings.xml b/core/res/res/values-sk/strings.xml
index 7d75949..35be0d7 100644
--- a/core/res/res/values-sk/strings.xml
+++ b/core/res/res/values-sk/strings.xml
@@ -973,6 +973,11 @@
     <skip />
     <string name="wifi_watchdog_network_disabled" msgid="7904214231651546347">"Nepodarilo sa pripojiť k sieti Wi-Fi"</string>
     <string name="wifi_watchdog_network_disabled_detailed" msgid="5548780776418332675">" má nekvalitné internetové pripojenie."</string>
+    <string name="wifi_p2p_dialog_title" msgid="97611782659324517">"Priame pripojenie Wi-Fi"</string>
+    <string name="wifi_p2p_turnon_message" msgid="2909250942299627244">"Spustiť priame pripojenie siete Wi-Fi. Táto možnosť vypne sieť Wi-Fi v režime klient alebo hotspot."</string>
+    <string name="wifi_p2p_failed_message" msgid="3763669677935623084">"Priame pripojenie siete Wi-Fi sa nepodarilo spustiť"</string>
+    <string name="wifi_p2p_enabled_notification_title" msgid="2068321881673734886">"Priame pripojenie siete Wi-Fi je zapnuté"</string>
+    <string name="wifi_p2p_enabled_notification_message" msgid="1638949953993894335">"Nastavenia otvoríte dotykom"</string>
     <string name="accept" msgid="1645267259272829559">"Prijať"</string>
     <string name="decline" msgid="2112225451706137894">"Odmietnuť"</string>
     <string name="wifi_p2p_invitation_sent_title" msgid="1318975185112070734">"Pozvánka bola odoslaná"</string>
diff --git a/core/res/res/values-sl/strings.xml b/core/res/res/values-sl/strings.xml
index e152a2f..9ff0aad 100644
--- a/core/res/res/values-sl/strings.xml
+++ b/core/res/res/values-sl/strings.xml
@@ -973,6 +973,11 @@
     <skip />
     <string name="wifi_watchdog_network_disabled" msgid="7904214231651546347">"Z omrežjem Wi-Fi se ni mogoče povezati"</string>
     <string name="wifi_watchdog_network_disabled_detailed" msgid="5548780776418332675">" ima slabo internetno povezavo."</string>
+    <string name="wifi_p2p_dialog_title" msgid="97611782659324517">"Wi-Fi Direct"</string>
+    <string name="wifi_p2p_turnon_message" msgid="2909250942299627244">"Zaženite Wi-Fi Direct. S tem boste izklopili odjemalca/dostopno točko Wi-Fi."</string>
+    <string name="wifi_p2p_failed_message" msgid="3763669677935623084">"Wi-Fi Direct ni bilo mogoče zagnati."</string>
+    <string name="wifi_p2p_enabled_notification_title" msgid="2068321881673734886">"Wi-Fi Direct je vklopljen"</string>
+    <string name="wifi_p2p_enabled_notification_message" msgid="1638949953993894335">"Dotaknite se za nastavitve"</string>
     <string name="accept" msgid="1645267259272829559">"Sprejmi"</string>
     <string name="decline" msgid="2112225451706137894">"Zavrni"</string>
     <string name="wifi_p2p_invitation_sent_title" msgid="1318975185112070734">"Povabilo je poslano"</string>
diff --git a/core/res/res/values-sr/strings.xml b/core/res/res/values-sr/strings.xml
index 7f1dbcd..a8a75ef 100644
--- a/core/res/res/values-sr/strings.xml
+++ b/core/res/res/values-sr/strings.xml
@@ -973,6 +973,11 @@
     <skip />
     <string name="wifi_watchdog_network_disabled" msgid="7904214231651546347">"Није било могуће повезати са Wi-Fi мрежом"</string>
     <string name="wifi_watchdog_network_disabled_detailed" msgid="5548780776418332675">" има лошу интернет везу."</string>
+    <string name="wifi_p2p_dialog_title" msgid="97611782659324517">"Wi-Fi Direct"</string>
+    <string name="wifi_p2p_turnon_message" msgid="2909250942299627244">"Покрените Wi-Fi Direct. Тиме ћете искључити клијента/хотспот за Wi-Fi."</string>
+    <string name="wifi_p2p_failed_message" msgid="3763669677935623084">"Није могуће покренути Wi-Fi Direct."</string>
+    <string name="wifi_p2p_enabled_notification_title" msgid="2068321881673734886">"Wi-Fi Direct је укључен"</string>
+    <string name="wifi_p2p_enabled_notification_message" msgid="1638949953993894335">"Додирните за подешавања"</string>
     <string name="accept" msgid="1645267259272829559">"Прихвати"</string>
     <string name="decline" msgid="2112225451706137894">"Одбиј"</string>
     <string name="wifi_p2p_invitation_sent_title" msgid="1318975185112070734">"Позивница је послата"</string>
diff --git a/core/res/res/values-sv/strings.xml b/core/res/res/values-sv/strings.xml
index 10ecffc..55f82da7 100644
--- a/core/res/res/values-sv/strings.xml
+++ b/core/res/res/values-sv/strings.xml
@@ -973,6 +973,11 @@
     <skip />
     <string name="wifi_watchdog_network_disabled" msgid="7904214231651546347">"Det gick inte att ansluta till Wi-Fi"</string>
     <string name="wifi_watchdog_network_disabled_detailed" msgid="5548780776418332675">" har en dålig Internetanslutning."</string>
+    <string name="wifi_p2p_dialog_title" msgid="97611782659324517">"Wi-Fi direkt"</string>
+    <string name="wifi_p2p_turnon_message" msgid="2909250942299627244">"Starta direkt Wi-Fi-användning. Detta inaktiverar Wi-Fi-användning med klient/trådlös surfzon."</string>
+    <string name="wifi_p2p_failed_message" msgid="3763669677935623084">"Det gick inte att starta Wi-Fi direkt."</string>
+    <string name="wifi_p2p_enabled_notification_title" msgid="2068321881673734886">"Wi-Fi Direct är aktiverat"</string>
+    <string name="wifi_p2p_enabled_notification_message" msgid="1638949953993894335">"Tryck om du vill visa inställningar"</string>
     <string name="accept" msgid="1645267259272829559">"Godkänn"</string>
     <string name="decline" msgid="2112225451706137894">"Avvisa"</string>
     <string name="wifi_p2p_invitation_sent_title" msgid="1318975185112070734">"Inbjudan har skickats"</string>
diff --git a/core/res/res/values-sw/strings.xml b/core/res/res/values-sw/strings.xml
index d245685..0a9f97c6 100644
--- a/core/res/res/values-sw/strings.xml
+++ b/core/res/res/values-sw/strings.xml
@@ -973,6 +973,11 @@
     <skip />
     <string name="wifi_watchdog_network_disabled" msgid="7904214231651546347">"Haikuweza kuunganisha kwa Mtandao-Hewa"</string>
     <string name="wifi_watchdog_network_disabled_detailed" msgid="5548780776418332675">" ina muunganisho duni wa Mtandao."</string>
+    <string name="wifi_p2p_dialog_title" msgid="97611782659324517">"Mtandao hewa Moja kwa moja"</string>
+    <string name="wifi_p2p_turnon_message" msgid="2909250942299627244">"Anzisha Wi-Fi Moja kwa Moja. Hii itazima mteja/mtandao-hewa wa Wi-Fi."</string>
+    <string name="wifi_p2p_failed_message" msgid="3763669677935623084">"Haikuweza kuanzisha Wi-Fi Moja kwa Moja."</string>
+    <string name="wifi_p2p_enabled_notification_title" msgid="2068321881673734886">"Wi-Fi ya Moja kwa Moja imewashwa"</string>
+    <string name="wifi_p2p_enabled_notification_message" msgid="1638949953993894335">"Gusa kwa ajili ya mipangilio"</string>
     <string name="accept" msgid="1645267259272829559">"Kubali"</string>
     <string name="decline" msgid="2112225451706137894">"Kataa"</string>
     <string name="wifi_p2p_invitation_sent_title" msgid="1318975185112070734">"Mwaliko umetumwa"</string>
diff --git a/core/res/res/values-th/strings.xml b/core/res/res/values-th/strings.xml
index 97f1c70..a44c6a8 100644
--- a/core/res/res/values-th/strings.xml
+++ b/core/res/res/values-th/strings.xml
@@ -973,6 +973,11 @@
     <skip />
     <string name="wifi_watchdog_network_disabled" msgid="7904214231651546347">"ไม่สามารถเชื่อมต่อ Wi-Fi"</string>
     <string name="wifi_watchdog_network_disabled_detailed" msgid="5548780776418332675">" มีสัญญาณอินเทอร์เน็ตไม่ดี"</string>
+    <string name="wifi_p2p_dialog_title" msgid="97611782659324517">"Wi-Fi Direct"</string>
+    <string name="wifi_p2p_turnon_message" msgid="2909250942299627244">"เริ่มการทำงาน WiFi Direct ซึ่งจะเป็นการปิดการทำงาน WiFi ไคลเอ็นต์/ฮอตสปอต"</string>
+    <string name="wifi_p2p_failed_message" msgid="3763669677935623084">"ไม่สามารถเริ่ม WiFi Direct ได้"</string>
+    <string name="wifi_p2p_enabled_notification_title" msgid="2068321881673734886">"เปิด Wi-Fi Direct อยู่"</string>
+    <string name="wifi_p2p_enabled_notification_message" msgid="1638949953993894335">"แตะเพื่อตั้งค่า"</string>
     <string name="accept" msgid="1645267259272829559">"ยอมรับ"</string>
     <string name="decline" msgid="2112225451706137894">"ปฏิเสธ"</string>
     <string name="wifi_p2p_invitation_sent_title" msgid="1318975185112070734">"ส่งข้อความเชิญแล้ว"</string>
diff --git a/core/res/res/values-tl/strings.xml b/core/res/res/values-tl/strings.xml
index f59cde4..ae164f0 100644
--- a/core/res/res/values-tl/strings.xml
+++ b/core/res/res/values-tl/strings.xml
@@ -973,6 +973,11 @@
     <skip />
     <string name="wifi_watchdog_network_disabled" msgid="7904214231651546347">"Hindi makakonekta sa Wi-Fi"</string>
     <string name="wifi_watchdog_network_disabled_detailed" msgid="5548780776418332675">" ay mayroong mahinang koneksyon sa Internet."</string>
+    <string name="wifi_p2p_dialog_title" msgid="97611782659324517">"Wi-Fi Direct"</string>
+    <string name="wifi_p2p_turnon_message" msgid="2909250942299627244">"Simulan ang Wi-Fi Direct. I-o-off nito ang client/hotspot ng Wi-Fi."</string>
+    <string name="wifi_p2p_failed_message" msgid="3763669677935623084">"Hindi masimulan ang Wi-Fi Direct"</string>
+    <string name="wifi_p2p_enabled_notification_title" msgid="2068321881673734886">"Ang Wi-Fi Direct ay naka-on"</string>
+    <string name="wifi_p2p_enabled_notification_message" msgid="1638949953993894335">"Pindutin para sa mga setting"</string>
     <string name="accept" msgid="1645267259272829559">"Tanggapin"</string>
     <string name="decline" msgid="2112225451706137894">"Tanggihan"</string>
     <string name="wifi_p2p_invitation_sent_title" msgid="1318975185112070734">"Naipadala ang imbitasyon"</string>
diff --git a/core/res/res/values-tr/strings.xml b/core/res/res/values-tr/strings.xml
index bcaa9a8..289cba5 100644
--- a/core/res/res/values-tr/strings.xml
+++ b/core/res/res/values-tr/strings.xml
@@ -973,6 +973,11 @@
     <skip />
     <string name="wifi_watchdog_network_disabled" msgid="7904214231651546347">"Kablosuz bağlantısı kurulamadı"</string>
     <string name="wifi_watchdog_network_disabled_detailed" msgid="5548780776418332675">" İnternet bağlantısı zayıf."</string>
+    <string name="wifi_p2p_dialog_title" msgid="97611782659324517">"Kablosuz Doğrudan Bağlantı"</string>
+    <string name="wifi_p2p_turnon_message" msgid="2909250942299627244">"Kablosuz Doğrudan Bağlantıyı başlat. Bu işlem, Kablosuz istemci/hotspot kullanımını kapatacak."</string>
+    <string name="wifi_p2p_failed_message" msgid="3763669677935623084">"Kablosuz Doğrudan bağlantı başlatılamadı."</string>
+    <string name="wifi_p2p_enabled_notification_title" msgid="2068321881673734886">"Kablosuz Doğrudan özelliği açık"</string>
+    <string name="wifi_p2p_enabled_notification_message" msgid="1638949953993894335">"Ayarlar için dokunun"</string>
     <string name="accept" msgid="1645267259272829559">"Kabul et"</string>
     <string name="decline" msgid="2112225451706137894">"Reddet"</string>
     <string name="wifi_p2p_invitation_sent_title" msgid="1318975185112070734">"Davetiye gönderildi"</string>
diff --git a/core/res/res/values-uk/strings.xml b/core/res/res/values-uk/strings.xml
index 6288aa1..fa5832c 100644
--- a/core/res/res/values-uk/strings.xml
+++ b/core/res/res/values-uk/strings.xml
@@ -973,6 +973,11 @@
     <skip />
     <string name="wifi_watchdog_network_disabled" msgid="7904214231651546347">"Не вдалося під’єднатися до мережі Wi-Fi"</string>
     <string name="wifi_watchdog_network_disabled_detailed" msgid="5548780776418332675">" має погане з’єднання з Інтернетом."</string>
+    <string name="wifi_p2p_dialog_title" msgid="97611782659324517">"Wi-Fi Direct"</string>
+    <string name="wifi_p2p_turnon_message" msgid="2909250942299627244">"Запустити Wi-Fi Direct. Це вимкне з’єднання Wi-Fi клієнт/точка доступу."</string>
+    <string name="wifi_p2p_failed_message" msgid="3763669677935623084">"Не вдалося запустити Wi-Fi Direct."</string>
+    <string name="wifi_p2p_enabled_notification_title" msgid="2068321881673734886">"Wi-Fi Direct увімкнено"</string>
+    <string name="wifi_p2p_enabled_notification_message" msgid="1638949953993894335">"Торкніться, щоб побачити налаштування"</string>
     <string name="accept" msgid="1645267259272829559">"Прийняти"</string>
     <string name="decline" msgid="2112225451706137894">"Відхилити"</string>
     <string name="wifi_p2p_invitation_sent_title" msgid="1318975185112070734">"Запрошення надіслано"</string>
diff --git a/core/res/res/values-vi/strings.xml b/core/res/res/values-vi/strings.xml
index ba81838..26fcfd9 100644
--- a/core/res/res/values-vi/strings.xml
+++ b/core/res/res/values-vi/strings.xml
@@ -973,6 +973,11 @@
     <skip />
     <string name="wifi_watchdog_network_disabled" msgid="7904214231651546347">"Không thể kết nối với Wi-Fi"</string>
     <string name="wifi_watchdog_network_disabled_detailed" msgid="5548780776418332675">" có kết nối Internet không tốt."</string>
+    <string name="wifi_p2p_dialog_title" msgid="97611782659324517">"Wi-Fi Direct"</string>
+    <string name="wifi_p2p_turnon_message" msgid="2909250942299627244">"Khởi động Wi-Fi Direct. Việc này sẽ tắt hoạt động của ứng dụng khách/điểm phát sóng Wi-Fi."</string>
+    <string name="wifi_p2p_failed_message" msgid="3763669677935623084">"Không thể khởi động Wi-Fi Direct."</string>
+    <string name="wifi_p2p_enabled_notification_title" msgid="2068321881673734886">"Wi-Fi Direct được bật"</string>
+    <string name="wifi_p2p_enabled_notification_message" msgid="1638949953993894335">"Chạm để cài đặt"</string>
     <string name="accept" msgid="1645267259272829559">"Đồng ý"</string>
     <string name="decline" msgid="2112225451706137894">"Từ chối"</string>
     <string name="wifi_p2p_invitation_sent_title" msgid="1318975185112070734">"Đã gửi thư mời"</string>
diff --git a/core/res/res/values-zh-rCN/strings.xml b/core/res/res/values-zh-rCN/strings.xml
index cbfc222..e1e3c41 100644
--- a/core/res/res/values-zh-rCN/strings.xml
+++ b/core/res/res/values-zh-rCN/strings.xml
@@ -973,6 +973,11 @@
     <skip />
     <string name="wifi_watchdog_network_disabled" msgid="7904214231651546347">"无法连接到 Wi-Fi"</string>
     <string name="wifi_watchdog_network_disabled_detailed" msgid="5548780776418332675">" 互联网连接状况不佳。"</string>
+    <string name="wifi_p2p_dialog_title" msgid="97611782659324517">"Wi-Fi Direct"</string>
+    <string name="wifi_p2p_turnon_message" msgid="2909250942299627244">"启动 Wi-Fi Direct。此操作将会关闭 Wi-Fi 客户端/热点。"</string>
+    <string name="wifi_p2p_failed_message" msgid="3763669677935623084">"无法启动 Wi-Fi Direct。"</string>
+    <string name="wifi_p2p_enabled_notification_title" msgid="2068321881673734886">"已启用 Wi-Fi Direct"</string>
+    <string name="wifi_p2p_enabled_notification_message" msgid="1638949953993894335">"通过触摸进行设置"</string>
     <string name="accept" msgid="1645267259272829559">"接受"</string>
     <string name="decline" msgid="2112225451706137894">"拒绝"</string>
     <string name="wifi_p2p_invitation_sent_title" msgid="1318975185112070734">"邀请已发送"</string>
diff --git a/core/res/res/values-zh-rTW/strings.xml b/core/res/res/values-zh-rTW/strings.xml
index 4d6042c..b5cad7c 100644
--- a/core/res/res/values-zh-rTW/strings.xml
+++ b/core/res/res/values-zh-rTW/strings.xml
@@ -973,6 +973,11 @@
     <skip />
     <string name="wifi_watchdog_network_disabled" msgid="7904214231651546347">"無法連線至 Wi-Fi"</string>
     <string name="wifi_watchdog_network_disabled_detailed" msgid="5548780776418332675">" 的網際網路連線狀況不佳。"</string>
+    <string name="wifi_p2p_dialog_title" msgid="97611782659324517">"Wi-Fi Direct"</string>
+    <string name="wifi_p2p_turnon_message" msgid="2909250942299627244">"啟動 WiFi Direct 作業,這會關閉 WiFi 用戶端/無線基地台作業。"</string>
+    <string name="wifi_p2p_failed_message" msgid="3763669677935623084">"無法啟動 WiFi Direct。"</string>
+    <string name="wifi_p2p_enabled_notification_title" msgid="2068321881673734886">"Wi-Fi Direct 已開啟"</string>
+    <string name="wifi_p2p_enabled_notification_message" msgid="1638949953993894335">"輕觸即可設定"</string>
     <string name="accept" msgid="1645267259272829559">"接受"</string>
     <string name="decline" msgid="2112225451706137894">"拒絕"</string>
     <string name="wifi_p2p_invitation_sent_title" msgid="1318975185112070734">"邀請函已傳送"</string>
diff --git a/core/res/res/values-zu/strings.xml b/core/res/res/values-zu/strings.xml
index c90fe76..f7e7bc4f 100644
--- a/core/res/res/values-zu/strings.xml
+++ b/core/res/res/values-zu/strings.xml
@@ -973,6 +973,11 @@
     <skip />
     <string name="wifi_watchdog_network_disabled" msgid="7904214231651546347">"Ayikwazanga ukuxhuma kwi-Wi-Fi"</string>
     <string name="wifi_watchdog_network_disabled_detailed" msgid="5548780776418332675">" inoxhumano oluphansi lwe-inthanethi."</string>
+    <string name="wifi_p2p_dialog_title" msgid="97611782659324517">"I-WiFi Eqondile"</string>
+    <string name="wifi_p2p_turnon_message" msgid="2909250942299627244">"Qala ukusebenza kwe-WiFi Okuqondile. Lokhu kuzocima ikhasimende le-WiFi/Ukusebenza okwe-hotspot"</string>
+    <string name="wifi_p2p_failed_message" msgid="3763669677935623084">"Yehlulekile ukuqala i-Wi-Fi Ngqo"</string>
+    <string name="wifi_p2p_enabled_notification_title" msgid="2068321881673734886">"I-Wi-Fi Direct ivulekile"</string>
+    <string name="wifi_p2p_enabled_notification_message" msgid="1638949953993894335">"Thinta ukuze uthole izilungiselelo"</string>
     <string name="accept" msgid="1645267259272829559">"Yamukela"</string>
     <string name="decline" msgid="2112225451706137894">"Nqaba"</string>
     <string name="wifi_p2p_invitation_sent_title" msgid="1318975185112070734">"Isimemo sithunyelwe"</string>
diff --git a/data/fonts/DroidNaskh-Bold.ttf b/data/fonts/DroidNaskh-Bold.ttf
index 6b7d4f0..692b796 100644
--- a/data/fonts/DroidNaskh-Bold.ttf
+++ b/data/fonts/DroidNaskh-Bold.ttf
Binary files differ
diff --git a/data/fonts/DroidNaskh-Regular.ttf b/data/fonts/DroidNaskh-Regular.ttf
index d11e1ae..da9a45f 100644
--- a/data/fonts/DroidNaskh-Regular.ttf
+++ b/data/fonts/DroidNaskh-Regular.ttf
Binary files differ
diff --git a/data/fonts/DroidSansFallback.ttf b/data/fonts/DroidSansFallback.ttf
index 2379b2d..cfbc66a 100644
--- a/data/fonts/DroidSansFallback.ttf
+++ b/data/fonts/DroidSansFallback.ttf
Binary files differ
diff --git a/data/fonts/DroidSansFallbackFull.ttf b/data/fonts/DroidSansFallbackFull.ttf
index 41b015d..0cacabe 100644
--- a/data/fonts/DroidSansFallbackFull.ttf
+++ b/data/fonts/DroidSansFallbackFull.ttf
Binary files differ
diff --git a/services/audioflinger/AudioPolicyService.cpp b/services/audioflinger/AudioPolicyService.cpp
index 041b5a8..364fd22 100644
--- a/services/audioflinger/AudioPolicyService.cpp
+++ b/services/audioflinger/AudioPolicyService.cpp
@@ -116,19 +116,7 @@
 
     // release audio pre processing resources
     for (size_t i = 0; i < mInputSources.size(); i++) {
-        InputSourceDesc *source = mInputSources.valueAt(i);
-        Vector <EffectDesc *> effects = source->mEffects;
-        for (size_t j = 0; j < effects.size(); j++) {
-            delete effects[j]->mName;
-            Vector <effect_param_t *> params = effects[j]->mParams;
-            for (size_t k = 0; k < params.size(); k++) {
-                delete params[k];
-            }
-            params.clear();
-            delete effects[j];
-        }
-        effects.clear();
-        delete source;
+        delete mInputSources.valueAt(i);
     }
     mInputSources.clear();
 
@@ -1243,7 +1231,7 @@
             node = node->next;
             continue;
         }
-        EffectDesc *effect = new EffectDesc(*effects[i]);
+        EffectDesc *effect = new EffectDesc(*effects[i]);   // deep copy
         loadEffectParameters(node, effect->mParams);
         ALOGV("loadInputSource() adding effect %s uuid %08x", effect->mName, effect->mUuid.timeLow);
         source->mEffects.add(effect);
@@ -1294,11 +1282,7 @@
         ALOGW("loadEffect() invalid uuid %s", node->value);
         return NULL;
     }
-    EffectDesc *effect = new EffectDesc();
-    effect->mName = strdup(root->name);
-    memcpy(&effect->mUuid, &uuid, sizeof(effect_uuid_t));
-
-    return effect;
+    return new EffectDesc(root->name, uuid);
 }
 
 status_t AudioPolicyService::loadEffects(cnode *root, Vector <EffectDesc *>& effects)
diff --git a/services/audioflinger/AudioPolicyService.h b/services/audioflinger/AudioPolicyService.h
index fdaf576..679fd30 100644
--- a/services/audioflinger/AudioPolicyService.h
+++ b/services/audioflinger/AudioPolicyService.h
@@ -233,8 +233,33 @@
 
     class EffectDesc {
     public:
-        EffectDesc() {}
-        virtual ~EffectDesc() {}
+        EffectDesc(const char *name, const effect_uuid_t& uuid) :
+                        mName(strdup(name)),
+                        mUuid(uuid) { }
+        EffectDesc(const EffectDesc& orig) :
+                        mName(strdup(orig.mName)),
+                        mUuid(orig.mUuid) {
+                            // deep copy mParams
+                            for (size_t k = 0; k < orig.mParams.size(); k++) {
+                                effect_param_t *origParam = orig.mParams[k];
+                                // psize and vsize are rounded up to an int boundary for allocation
+                                size_t origSize = sizeof(effect_param_t) +
+                                                  ((origParam->psize + 3) & ~3) +
+                                                  ((origParam->vsize + 3) & ~3);
+                                effect_param_t *dupParam = (effect_param_t *) malloc(origSize);
+                                memcpy(dupParam, origParam, origSize);
+                                // This works because the param buffer allocation is also done by
+                                // multiples of 4 bytes originally. In theory we should memcpy only
+                                // the actual param size, that is without rounding vsize.
+                                mParams.add(dupParam);
+                            }
+                        }
+        /*virtual*/ ~EffectDesc() {
+            free(mName);
+            for (size_t k = 0; k < mParams.size(); k++) {
+                free(mParams[k]);
+            }
+        }
         char *mName;
         effect_uuid_t mUuid;
         Vector <effect_param_t *> mParams;
@@ -243,7 +268,11 @@
     class InputSourceDesc {
     public:
         InputSourceDesc() {}
-        virtual ~InputSourceDesc() {}
+        /*virtual*/ ~InputSourceDesc() {
+            for (size_t j = 0; j < mEffects.size(); j++) {
+                delete mEffects[j];
+            }
+        }
         Vector <EffectDesc *> mEffects;
     };
 
diff --git a/services/java/com/android/server/am/ActivityManagerService.java b/services/java/com/android/server/am/ActivityManagerService.java
index 7852123..8a5e7fc 100644
--- a/services/java/com/android/server/am/ActivityManagerService.java
+++ b/services/java/com/android/server/am/ActivityManagerService.java
@@ -138,7 +138,6 @@
 import java.lang.IllegalStateException;
 import java.lang.ref.WeakReference;
 import java.util.ArrayList;
-import java.util.Arrays;
 import java.util.Collection;
 import java.util.Collections;
 import java.util.Comparator;
@@ -2752,7 +2751,13 @@
         }
 
         // Just in case...
-        mMainStack.appDiedLocked(app);
+        if (mMainStack.mPausingActivity != null && mMainStack.mPausingActivity.app == app) {
+            if (DEBUG_PAUSE) Slog.v(TAG, "App died while pausing: " +mMainStack.mPausingActivity);
+            mMainStack.mPausingActivity = null;
+        }
+        if (mMainStack.mLastPausedActivity != null && mMainStack.mLastPausedActivity.app == app) {
+            mMainStack.mLastPausedActivity = null;
+        }
 
         // Remove this application's activities from active lists.
         mMainStack.removeHistoryRecordsForAppLocked(app);
@@ -6488,7 +6493,7 @@
                 mMainStack.stopIfSleepingLocked();
                 final long endTime = System.currentTimeMillis() + timeout;
                 while (mMainStack.mResumedActivity != null
-                        || mMainStack.mPausingActivities.size() > 0) {
+                        || mMainStack.mPausingActivity != null) {
                     long delay = endTime - System.currentTimeMillis();
                     if (delay <= 0) {
                         Slog.w(TAG, "Activity manager shutdown timed out");
@@ -8295,13 +8300,8 @@
         }
 
         pw.println(" ");
-        if (mMainStack.mPausingActivities.size() > 0) {
-            pw.println("  mPausingActivities: " + Arrays.toString(
-                    mMainStack.mPausingActivities.toArray()));
-        }
-        if (mMainStack.mInputPausedActivities.size() > 0) {
-            pw.println("  mInputPausedActivities: " + Arrays.toString(
-                    mMainStack.mInputPausedActivities.toArray()));
+        if (mMainStack.mPausingActivity != null) {
+            pw.println("  mPausingActivity: " + mMainStack.mPausingActivity);
         }
         pw.println("  mResumedActivity: " + mMainStack.mResumedActivity);
         pw.println("  mFocusedActivity: " + mFocusedActivity);
@@ -13876,13 +13876,7 @@
     private final ActivityRecord resumedAppLocked() {
         ActivityRecord resumedActivity = mMainStack.mResumedActivity;
         if (resumedActivity == null || resumedActivity.app == null) {
-            for (int i=mMainStack.mPausingActivities.size()-1; i>=0; i--) {
-                ActivityRecord r = mMainStack.mPausingActivities.get(i);
-                if (r.app != null) {
-                    resumedActivity = r;
-                    break;
-                }
-            }
+            resumedActivity = mMainStack.mPausingActivity;
             if (resumedActivity == null || resumedActivity.app == null) {
                 resumedActivity = mMainStack.topRunningActivityLocked(null);
             }
diff --git a/services/java/com/android/server/am/ActivityRecord.java b/services/java/com/android/server/am/ActivityRecord.java
index 977ee84..cdab6c6 100644
--- a/services/java/com/android/server/am/ActivityRecord.java
+++ b/services/java/com/android/server/am/ActivityRecord.java
@@ -602,7 +602,6 @@
     
     public void windowsDrawn() {
         synchronized(service) {
-            stack.reportActivityDrawnLocked(this);
             if (launchTime != 0) {
                 final long curTime = SystemClock.uptimeMillis();
                 final long thisTime = curTime - launchTime;
@@ -691,9 +690,7 @@
             // Hmmm, who might we be waiting for?
             r = stack.mResumedActivity;
             if (r == null) {
-                if (stack.mPausingActivities.size() > 0) {
-                    r = stack.mPausingActivities.get(stack.mPausingActivities.size()-1);
-                }
+                r = stack.mPausingActivity;
             }
             // Both of those null?  Fall back to 'this' again
             if (r == null) {
diff --git a/services/java/com/android/server/am/ActivityStack.java b/services/java/com/android/server/am/ActivityStack.java
index e8c8275..7b8bc26 100644
--- a/services/java/com/android/server/am/ActivityStack.java
+++ b/services/java/com/android/server/am/ActivityStack.java
@@ -227,13 +227,7 @@
      * 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.
      */
-    final ArrayList<ActivityRecord> mPausingActivities = new ArrayList<ActivityRecord>();
-
-    /**
-     * These activities currently have their input paused, as they want for
-     * the next top activity to have its windows visible.
-     */
-    final ArrayList<ActivityRecord> mInputPausedActivities = new ArrayList<ActivityRecord>();
+    ActivityRecord mPausingActivity = null;
 
     /**
      * This is the last activity that we put into the paused state.  This is
@@ -813,9 +807,9 @@
                 startPausingLocked(false, true);
                 return;
             }
-            if (mPausingActivities.size() > 0) {
+            if (mPausingActivity != null) {
                 // Still waiting for something to pause; can't sleep yet.
-                if (DEBUG_PAUSE) Slog.v(TAG, "Sleep still waiting to pause " + mPausingActivities);
+                if (DEBUG_PAUSE) Slog.v(TAG, "Sleep still waiting to pause " + mPausingActivity);
                 return;
             }
 
@@ -878,6 +872,11 @@
     }
 
     private final void startPausingLocked(boolean userLeaving, boolean uiSleeping) {
+        if (mPausingActivity != null) {
+            RuntimeException e = new RuntimeException();
+            Slog.e(TAG, "Trying to pause when pause is already pending for "
+                  + mPausingActivity, e);
+        }
         ActivityRecord prev = mResumedActivity;
         if (prev == null) {
             RuntimeException e = new RuntimeException();
@@ -885,25 +884,19 @@
             resumeTopActivityLocked(null);
             return;
         }
-        if (mPausingActivities.contains(prev)) {
-            RuntimeException e = new RuntimeException();
-            Slog.e(TAG, "Trying to pause when pause when already pausing " + prev, e);
-        }
         if (DEBUG_STATES) Slog.v(TAG, "Moving to PAUSING: " + prev);
         else if (DEBUG_PAUSE) Slog.v(TAG, "Start pausing: " + prev);
         mResumedActivity = null;
-        mPausingActivities.add(prev);
+        mPausingActivity = prev;
         mLastPausedActivity = prev;
         prev.state = ActivityState.PAUSING;
         prev.task.touchActiveTime();
         prev.updateThumbnail(screenshotActivities(prev), null);
 
         mService.updateCpuStats();
-        ActivityRecord pausing;
         
         if (prev.app != null && prev.app.thread != null) {
             if (DEBUG_PAUSE) Slog.v(TAG, "Enqueueing pending pause: " + prev);
-            pausing = prev;
             try {
                 EventLog.writeEvent(EventLogTags.AM_PAUSE_ACTIVITY,
                         System.identityHashCode(prev),
@@ -916,14 +909,12 @@
             } catch (Exception e) {
                 // Ignore exception, if process died other code will cleanup.
                 Slog.w(TAG, "Exception thrown during pause", e);
-                mPausingActivities.remove(prev);
+                mPausingActivity = null;
                 mLastPausedActivity = null;
-                pausing = null;
             }
         } else {
-            mPausingActivities.remove(prev);
+            mPausingActivity = null;
             mLastPausedActivity = null;
-            pausing = null;
         }
 
         // If we are not going to sleep, we want to ensure the device is
@@ -937,28 +928,18 @@
             }
         }
 
-        if (pausing != null) {
+
+        if (mPausingActivity != null) {
             // Have the window manager pause its key dispatching until the new
             // activity has started.  If we're pausing the activity just because
             // the screen is being turned off and the UI is sleeping, don't interrupt
             // key dispatch; the same activity will pick it up again on wakeup.
             if (!uiSleeping) {
-                pausing.pauseKeyDispatchingLocked();
-                mInputPausedActivities.add(prev);
+                prev.pauseKeyDispatchingLocked();
             } else {
                 if (DEBUG_PAUSE) Slog.v(TAG, "Key dispatch not paused for screen off");
             }
 
-            if (pausing.configDestroy) {
-                // The previous is being paused because the configuration
-                // is changing, which means it is actually stopping...
-                // To juggle the fact that we are also starting a new
-                // instance right now, we need to first completely stop
-                // the current instance before starting the new one.
-                if (DEBUG_PAUSE) Slog.v(TAG, "Destroying at pause: " + prev);
-                destroyActivityLocked(pausing, true, false, "pause-config");
-            }
-
             // Schedule a pause timeout in case the app doesn't respond.
             // We don't give it much time because this directly impacts the
             // responsiveness seen by the user.
@@ -970,10 +951,7 @@
             // This activity failed to schedule the
             // pause, so just treat it as being paused now.
             if (DEBUG_PAUSE) Slog.v(TAG, "Activity not running, resuming next.");
-        }
-
-        if (!mService.isSleeping()) {
-            resumeTopActivityLocked(pausing);
+            resumeTopActivityLocked(null);
         }
     }
     
@@ -988,17 +966,16 @@
             if (index >= 0) {
                 r = mHistory.get(index);
                 mHandler.removeMessages(PAUSE_TIMEOUT_MSG, r);
-                if (mPausingActivities.contains(r)) {
+                if (mPausingActivity == r) {
                     if (DEBUG_STATES) Slog.v(TAG, "Moving to PAUSED: " + r
                             + (timeout ? " (due to timeout)" : " (pause complete)"));
                     r.state = ActivityState.PAUSED;
-                    completePauseLocked(r);
+                    completePauseLocked();
                 } else {
-                    ActivityRecord old = mPausingActivities.size() > 0
-                            ? mPausingActivities.get(0) : null;
                     EventLog.writeEvent(EventLogTags.AM_FAILED_TO_PAUSE,
                             System.identityHashCode(r), r.shortComponentName, 
-                            old != null ? old.shortComponentName : "(none)");
+                            mPausingActivity != null
+                                ? mPausingActivity.shortComponentName : "(none)");
                 }
             }
         }
@@ -1024,14 +1001,8 @@
                 ProcessRecord fgApp = null;
                 if (mResumedActivity != null) {
                     fgApp = mResumedActivity.app;
-                } else {
-                    for (int i=mPausingActivities.size()-1; i>=0; i--) {
-                        ActivityRecord pausing = mPausingActivities.get(i);
-                        if (pausing.app == r.app) {
-                            fgApp = pausing.app;
-                            break;
-                        }
-                    }
+                } else if (mPausingActivity != null) {
+                    fgApp = mPausingActivity.app;
                 }
                 if (r.app != null && fgApp != null && r.app != fgApp
                         && r.lastVisibleTime > mService.mPreviousProcessVisibleTime
@@ -1043,49 +1014,58 @@
         }
     }
 
-    private final void completePauseLocked(ActivityRecord prev) {
+    private final void completePauseLocked() {
+        ActivityRecord prev = mPausingActivity;
         if (DEBUG_PAUSE) Slog.v(TAG, "Complete pause: " + prev);
         
-        if (prev.finishing) {
-            if (DEBUG_PAUSE) Slog.v(TAG, "Executing finish of activity: " + prev);
-            prev = finishCurrentActivityLocked(prev, FINISH_AFTER_VISIBLE);
-        } else if (prev.app != null) {
-            if (DEBUG_PAUSE) Slog.v(TAG, "Enqueueing pending stop: " + prev);
-            if (prev.waitingVisible) {
-                prev.waitingVisible = false;
-                mWaitingVisibleActivities.remove(prev);
-                if (DEBUG_SWITCH || DEBUG_PAUSE) Slog.v(
-                        TAG, "Complete pause, no longer waiting: " + prev);
-            }
-            if (prev.configDestroy) {
-                // The previous is being paused because the configuration
-                // is changing, which means it is actually stopping...
-                // To juggle the fact that we are also starting a new
-                // instance right now, we need to first completely stop
-                // the current instance before starting the new one.
-                if (DEBUG_PAUSE) Slog.v(TAG, "Destroying after pause: " + prev);
-                destroyActivityLocked(prev, true, false, "pause-config");
-            } else {
-                mStoppingActivities.add(prev);
-                if (mStoppingActivities.size() > 3) {
-                    // If we already have a few activities waiting to stop,
-                    // then give up on things going idle and start clearing
-                    // them out.
-                    if (DEBUG_PAUSE) Slog.v(TAG, "To many pending stops, forcing idle");
-                    scheduleIdleLocked();
-                } else {
-                    checkReadyForSleepLocked();
+        if (prev != null) {
+            if (prev.finishing) {
+                if (DEBUG_PAUSE) Slog.v(TAG, "Executing finish of activity: " + prev);
+                prev = finishCurrentActivityLocked(prev, FINISH_AFTER_VISIBLE);
+            } else if (prev.app != null) {
+                if (DEBUG_PAUSE) Slog.v(TAG, "Enqueueing pending stop: " + prev);
+                if (prev.waitingVisible) {
+                    prev.waitingVisible = false;
+                    mWaitingVisibleActivities.remove(prev);
+                    if (DEBUG_SWITCH || DEBUG_PAUSE) Slog.v(
+                            TAG, "Complete pause, no longer waiting: " + prev);
                 }
+                if (prev.configDestroy) {
+                    // The previous is being paused because the configuration
+                    // is changing, which means it is actually stopping...
+                    // To juggle the fact that we are also starting a new
+                    // instance right now, we need to first completely stop
+                    // the current instance before starting the new one.
+                    if (DEBUG_PAUSE) Slog.v(TAG, "Destroying after pause: " + prev);
+                    destroyActivityLocked(prev, true, false, "pause-config");
+                } else {
+                    mStoppingActivities.add(prev);
+                    if (mStoppingActivities.size() > 3) {
+                        // If we already have a few activities waiting to stop,
+                        // then give up on things going idle and start clearing
+                        // them out.
+                        if (DEBUG_PAUSE) Slog.v(TAG, "To many pending stops, forcing idle");
+                        scheduleIdleLocked();
+                    } else {
+                        checkReadyForSleepLocked();
+                    }
+                }
+            } else {
+                if (DEBUG_PAUSE) Slog.v(TAG, "App died during pause, not stopping: " + prev);
+                prev = null;
             }
-        } else {
-            if (DEBUG_PAUSE) Slog.v(TAG, "App died during pause, not stopping: " + prev);
-            prev = null;
+            mPausingActivity = null;
         }
-        mPausingActivities.remove(prev);
 
-        if (mService.isSleeping()) {
+        if (!mService.isSleeping()) {
+            resumeTopActivityLocked(prev);
+        } else {
             checkReadyForSleepLocked();
         }
+        
+        if (prev != null) {
+            prev.resumeKeyDispatchingLocked();
+        }
 
         if (prev.app != null && prev.cpuTimeAtResume > 0
                 && mService.mBatteryStatsService.isOnBattery()) {
@@ -1142,9 +1122,7 @@
         if (mMainStack) {
             mService.setFocusedActivityLocked(next);
         }
-        if (mInputPausedActivities.remove(next)) {
-            next.resumeKeyDispatchingLocked();
-        }
+        next.resumeKeyDispatchingLocked();
         ensureActivitiesVisibleLocked(null, 0);
         mService.mWindowManager.executeAppTransition();
         mNoAnimActivities.clear();
@@ -1374,6 +1352,13 @@
 
         if (DEBUG_SWITCH) Slog.v(TAG, "Resuming " + next);
 
+        // If we are currently pausing an activity, then don't do anything
+        // until that is done.
+        if (mPausingActivity != null) {
+            if (DEBUG_SWITCH) Slog.v(TAG, "Skip resume: pausing=" + mPausingActivity);
+            return false;
+        }
+
         // Okay we are now going to start a switch, to 'next'.  We may first
         // have to pause the current activity, but this is an important point
         // where we have decided to go to 'next' so keep track of that.
@@ -2455,7 +2440,7 @@
         
         err = startActivityUncheckedLocked(r, sourceRecord,
                 grantedUriPermissions, grantedMode, onlyIfNeeded, true);
-        if (mDismissKeyguardOnNextActivity && mPausingActivities.size() == 0) {
+        if (mDismissKeyguardOnNextActivity && mPausingActivity == null) {
             // Someone asked to have the keyguard dismissed on the next
             // activity start, but we are not actually doing an activity
             // switch...  just dismiss the keyguard now, because we
@@ -3126,18 +3111,7 @@
         }
         mService.notifyAll();
     }
-
-    void reportActivityDrawnLocked(ActivityRecord r) {
-        if (mResumedActivity == r) {
-            // Once the resumed activity has been drawn, we can stop
-            // pausing input on all other activities.
-            for (int i=mInputPausedActivities.size()-1; i>=0; i--) {
-                mInputPausedActivities.get(i).resumeKeyDispatchingLocked();
-            }
-            mInputPausedActivities.clear();
-        }
-    }
-
+    
     void reportActivityVisibleLocked(ActivityRecord r) {
         for (int i=mWaitingActivityVisible.size()-1; i>=0; i--) {
             WaitResult w = mWaitingActivityVisible.get(i);
@@ -3196,9 +3170,7 @@
                     mService.setFocusedActivityLocked(topRunningActivityLocked(null));
                 }
             }
-            if (mInputPausedActivities.remove(r)) {
-                r.resumeKeyDispatchingLocked();
-            }
+            r.resumeKeyDispatchingLocked();
             try {
                 r.stopped = false;
                 if (DEBUG_STATES) Slog.v(TAG, "Moving to STOPPING: " + r
@@ -3524,7 +3496,7 @@
             // Tell window manager to prepare for this one to be removed.
             mService.mWindowManager.setAppVisibility(r.appToken, false);
                 
-            if (!mPausingActivities.contains(r)) {
+            if (mPausingActivity == null) {
                 if (DEBUG_PAUSE) Slog.v(TAG, "Finish needs to pause: " + r);
                 if (DEBUG_USER_LEAVING) Slog.v(TAG, "finish() => pause with userLeaving=false");
                 startPausingLocked(false, false);
@@ -3608,20 +3580,6 @@
         return r;
     }
 
-    final void appDiedLocked(ProcessRecord app) {
-        for (int i=mPausingActivities.size()-1; i>=0; i--) {
-            ActivityRecord r = mPausingActivities.get(i);
-            if (r.app == app) {
-                if (DEBUG_PAUSE) Slog.v(TAG, "App died while pausing: " + r);
-                mPausingActivities.remove(i);
-                mHandler.removeMessages(PAUSE_TIMEOUT_MSG, r);
-            }
-        }
-        if (mLastPausedActivity != null && mLastPausedActivity.app == app) {
-            mLastPausedActivity = null;
-        }
-    }
-
     /**
      * Perform the common clean-up of an activity record.  This is called both
      * as part of destroyActivityLocked() (when destroying the client-side
diff --git a/tools/layoutlib/bridge/src/android/view/AttachInfo_Accessor.java b/tools/layoutlib/bridge/src/android/view/AttachInfo_Accessor.java
index 96de51c..97d9969 100644
--- a/tools/layoutlib/bridge/src/android/view/AttachInfo_Accessor.java
+++ b/tools/layoutlib/bridge/src/android/view/AttachInfo_Accessor.java
@@ -29,7 +29,7 @@
 
     public static void setAttachInfo(View view) {
         AttachInfo info = new AttachInfo(new BridgeWindowSession(), new BridgeWindow(),
-                new Handler(), null);
+                new ViewRootImpl(view.getContext()), new Handler(), null);
         info.mHasWindowFocus = true;
         info.mWindowVisibility = View.VISIBLE;
         info.mInTouchMode = false; // this is so that we can display selections.