Merge "Resized thumbnails; async; extend MatrixCursor." into klp-dev
diff --git a/api/current.txt b/api/current.txt
index 2a81469..22e3517 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -1015,6 +1015,7 @@
     field public static final int summaryOff = 16843248; // 0x10101f0
     field public static final int summaryOn = 16843247; // 0x10101ef
     field public static final int supportsRtl = 16843695; // 0x10103af
+    field public static final int supportsSwitchingToNextInputMethod = 16843753; // 0x10103e9
     field public static final int supportsUploading = 16843419; // 0x101029b
     field public static final int switchMinWidth = 16843632; // 0x1010370
     field public static final int switchPadding = 16843633; // 0x1010371
@@ -10925,7 +10926,9 @@
 
   public final class CaptureRequest extends android.hardware.camera2.CameraMetadata implements android.os.Parcelable {
     method public void addTarget(android.view.Surface);
+    method public java.lang.Object getTag();
     method public void removeTarget(android.view.Surface);
+    method public void setTag(java.lang.Object);
     field public static final android.hardware.camera2.CameraMetadata.Key BLACK_LEVEL_LOCK;
     field public static final android.hardware.camera2.CameraMetadata.Key COLOR_CORRECTION_GAINS;
     field public static final android.hardware.camera2.CameraMetadata.Key COLOR_CORRECTION_MODE;
@@ -12599,6 +12602,7 @@
     ctor public MediaFormat();
     method public final boolean containsKey(java.lang.String);
     method public static final android.media.MediaFormat createAudioFormat(java.lang.String, int, int);
+    method public static final android.media.MediaFormat createSubtitleFormat(java.lang.String, java.lang.String);
     method public static final android.media.MediaFormat createVideoFormat(java.lang.String, int, int);
     method public final java.nio.ByteBuffer getByteBuffer(java.lang.String);
     method public final float getFloat(java.lang.String);
@@ -12621,6 +12625,7 @@
     field public static final java.lang.String KEY_HEIGHT = "height";
     field public static final java.lang.String KEY_IS_ADTS = "is-adts";
     field public static final java.lang.String KEY_I_FRAME_INTERVAL = "i-frame-interval";
+    field public static final java.lang.String KEY_LANGUAGE = "language";
     field public static final java.lang.String KEY_MAX_INPUT_SIZE = "max-input-size";
     field public static final java.lang.String KEY_MIME = "mime";
     field public static final java.lang.String KEY_SAMPLE_RATE = "sample-rate";
@@ -18109,8 +18114,14 @@
   public class ParcelFileDescriptor implements java.io.Closeable android.os.Parcelable {
     ctor public ParcelFileDescriptor(android.os.ParcelFileDescriptor);
     method public static android.os.ParcelFileDescriptor adoptFd(int);
+    method public boolean canDetectErrors();
+    method public void checkError(boolean) throws java.io.IOException;
     method public void close() throws java.io.IOException;
+    method public void closeWithError(java.lang.String) throws java.io.IOException;
     method public static android.os.ParcelFileDescriptor[] createPipe() throws java.io.IOException;
+    method public static android.os.ParcelFileDescriptor[] createReliablePipe() throws java.io.IOException;
+    method public static android.os.ParcelFileDescriptor[] createReliableSocketPair() throws java.io.IOException;
+    method public static android.os.ParcelFileDescriptor[] createSocketPair() throws java.io.IOException;
     method public int describeContents();
     method public int detachFd();
     method public static android.os.ParcelFileDescriptor dup(java.io.FileDescriptor) throws java.io.IOException;
@@ -18122,6 +18133,7 @@
     method public java.io.FileDescriptor getFileDescriptor();
     method public long getStatSize();
     method public static android.os.ParcelFileDescriptor open(java.io.File, int) throws java.io.FileNotFoundException;
+    method public static android.os.ParcelFileDescriptor open(java.io.File, int, android.os.Handler, android.os.ParcelFileDescriptor.OnCloseListener) throws java.io.IOException;
     method public void writeToParcel(android.os.Parcel, int);
     field public static final android.os.Parcelable.Creator CREATOR;
     field public static final int MODE_APPEND = 33554432; // 0x2000000
@@ -18129,8 +18141,8 @@
     field public static final int MODE_READ_ONLY = 268435456; // 0x10000000
     field public static final int MODE_READ_WRITE = 805306368; // 0x30000000
     field public static final int MODE_TRUNCATE = 67108864; // 0x4000000
-    field public static final int MODE_WORLD_READABLE = 1; // 0x1
-    field public static final int MODE_WORLD_WRITEABLE = 2; // 0x2
+    field public static final deprecated int MODE_WORLD_READABLE = 1; // 0x1
+    field public static final deprecated int MODE_WORLD_WRITEABLE = 2; // 0x2
     field public static final int MODE_WRITE_ONLY = 536870912; // 0x20000000
   }
 
@@ -18142,6 +18154,10 @@
     ctor public ParcelFileDescriptor.AutoCloseOutputStream(android.os.ParcelFileDescriptor);
   }
 
+  public static abstract interface ParcelFileDescriptor.OnCloseListener {
+    method public abstract void onClose(java.io.IOException, boolean);
+  }
+
   public class ParcelFormatException extends java.lang.RuntimeException {
     ctor public ParcelFormatException();
     ctor public ParcelFormatException(java.lang.String);
@@ -29492,19 +29508,18 @@
   public abstract class Transition implements java.lang.Cloneable {
     ctor public Transition();
     method public void addListener(android.view.transition.Transition.TransitionListener);
-    method protected void cancelTransition();
+    method protected void cancel();
     method protected abstract void captureValues(android.view.transition.TransitionValues, boolean);
     method public android.view.transition.Transition clone();
     method public long getDuration();
     method public android.animation.TimeInterpolator getInterpolator();
     method public java.util.ArrayList<android.view.transition.Transition.TransitionListener> getListeners();
+    method public java.lang.String getName();
     method public long getStartDelay();
     method public int[] getTargetIds();
     method public android.view.View[] getTargets();
+    method public java.lang.String[] getTransitionProperties();
     method protected android.view.transition.TransitionValues getTransitionValues(android.view.View, boolean);
-    method protected void onTransitionCancel();
-    method protected void onTransitionEnd();
-    method protected void onTransitionStart();
     method protected android.animation.Animator play(android.view.ViewGroup, android.view.transition.TransitionValues, android.view.transition.TransitionValues);
     method public void removeListener(android.view.transition.Transition.TransitionListener);
     method public android.view.transition.Transition setDuration(long);
@@ -29517,6 +29532,8 @@
   public static abstract interface Transition.TransitionListener {
     method public abstract void onTransitionCancel(android.view.transition.Transition);
     method public abstract void onTransitionEnd(android.view.transition.Transition);
+    method public abstract void onTransitionPause(android.view.transition.Transition);
+    method public abstract void onTransitionResume(android.view.transition.Transition);
     method public abstract void onTransitionStart(android.view.transition.Transition);
   }
 
@@ -29563,6 +29580,7 @@
     method protected android.animation.Animator appear(android.view.ViewGroup, android.view.transition.TransitionValues, int, android.view.transition.TransitionValues, int);
     method protected void captureValues(android.view.transition.TransitionValues, boolean);
     method protected android.animation.Animator disappear(android.view.ViewGroup, android.view.transition.TransitionValues, int, android.view.transition.TransitionValues, int);
+    method public boolean isVisible(android.view.transition.TransitionValues);
   }
 
 }
diff --git a/core/java/android/animation/TypeEvaluator.java b/core/java/android/animation/TypeEvaluator.java
index e738da1..2640457 100644
--- a/core/java/android/animation/TypeEvaluator.java
+++ b/core/java/android/animation/TypeEvaluator.java
@@ -19,7 +19,7 @@
 /**
  * Interface for use with the {@link ValueAnimator#setEvaluator(TypeEvaluator)} function. Evaluators
  * allow developers to create animations on arbitrary property types, by allowing them to supply
- * custom evaulators for types that are not automatically understood and used by the animation
+ * custom evaluators for types that are not automatically understood and used by the animation
  * system.
  *
  * @see ValueAnimator#setEvaluator(TypeEvaluator)
@@ -41,4 +41,4 @@
      */
     public T evaluate(float fraction, T startValue, T endValue);
 
-}
\ No newline at end of file
+}
diff --git a/core/java/android/app/ActivityThread.java b/core/java/android/app/ActivityThread.java
index 2a28b76..e6960b3 100644
--- a/core/java/android/app/ActivityThread.java
+++ b/core/java/android/app/ActivityThread.java
@@ -3865,7 +3865,7 @@
         }
     }
 
-    final void freeTextLayoutCachesIfNeeded(int configDiff) {
+    static void freeTextLayoutCachesIfNeeded(int configDiff) {
         if (configDiff != 0) {
             // Ask text layout engine to free its caches if there is a locale change
             boolean hasLocaleConfigChange = ((configDiff & ActivityInfo.CONFIG_LOCALE) != 0);
diff --git a/core/java/android/app/NativeActivity.java b/core/java/android/app/NativeActivity.java
index b84889f..4ca3747 100644
--- a/core/java/android/app/NativeActivity.java
+++ b/core/java/android/app/NativeActivity.java
@@ -175,16 +175,20 @@
                 ? savedInstanceState.getByteArray(KEY_NATIVE_SAVED_STATE) : null;
 
         mNativeHandle = loadNativeCode(path, funcname, Looper.myQueue(),
-                 getFilesDir().getAbsolutePath(), getObbDir().getAbsolutePath(),
-                 getExternalFilesDir(null).getAbsolutePath(),
-                 Build.VERSION.SDK_INT, getAssets(), nativeSavedState);
-        
+                getAbsolutePath(getFilesDir()), getAbsolutePath(getObbDir()),
+                getAbsolutePath(getExternalFilesDir(null)),
+                Build.VERSION.SDK_INT, getAssets(), nativeSavedState);
+
         if (mNativeHandle == 0) {
             throw new IllegalArgumentException("Unable to load native library: " + path);
         }
         super.onCreate(savedInstanceState);
     }
 
+    private static String getAbsolutePath(File file) {
+        return (file != null) ? file.getAbsolutePath() : null;
+    }
+
     @Override
     protected void onDestroy() {
         mDestroyed = true;
diff --git a/core/java/android/bluetooth/BluetoothA2dp.java b/core/java/android/bluetooth/BluetoothA2dp.java
index d7d8cdbe..e7e4a0f 100644
--- a/core/java/android/bluetooth/BluetoothA2dp.java
+++ b/core/java/android/bluetooth/BluetoothA2dp.java
@@ -388,6 +388,66 @@
     }
 
     /**
+     * Checks if Avrcp device supports the absolute volume feature.
+     *
+     * @return true if device supports absolute volume
+     * @hide
+     */
+    public boolean isAvrcpAbsoluteVolumeSupported() {
+        if (DBG) Log.d(TAG, "isAvrcpAbsoluteVolumeSupported");
+        if (mService != null && isEnabled()) {
+            try {
+                return mService.isAvrcpAbsoluteVolumeSupported();
+            } catch (RemoteException e) {
+                Log.e(TAG, "Error talking to BT service in isAvrcpAbsoluteVolumeSupported()", e);
+                return false;
+            }
+        }
+        if (mService == null) Log.w(TAG, "Proxy not attached to service");
+        return false;
+    }
+
+    /**
+     * Tells remote device to adjust volume. Only if absolute volume is supported.
+     *
+     * @param direction 1 to increase volume, or -1 to decrease volume
+     * @hide
+     */
+    public void adjustAvrcpAbsoluteVolume(int direction) {
+        if (DBG) Log.d(TAG, "adjustAvrcpAbsoluteVolume");
+        if (mService != null && isEnabled()) {
+            try {
+                mService.adjustAvrcpAbsoluteVolume(direction);
+                return;
+            } catch (RemoteException e) {
+                Log.e(TAG, "Error talking to BT service in adjustAvrcpAbsoluteVolume()", e);
+                return;
+            }
+        }
+        if (mService == null) Log.w(TAG, "Proxy not attached to service");
+    }
+
+    /**
+     * Tells remote device to set an absolute volume. Only if absolute volume is supported
+     *
+     * @param volume Absolute volume to be set on AVRCP side
+     * @hide
+     */
+    public void setAvrcpAbsoluteVolume(int volume) {
+        if (DBG) Log.d(TAG, "setAvrcpAbsoluteVolume");
+        if (mService != null && isEnabled()) {
+            try {
+                mService.setAvrcpAbsoluteVolume(volume);
+                return;
+            } catch (RemoteException e) {
+                Log.e(TAG, "Error talking to BT service in setAvrcpAbsoluteVolume()", e);
+                return;
+            }
+        }
+        if (mService == null) Log.w(TAG, "Proxy not attached to service");
+    }
+
+    /**
      * Check if A2DP profile is streaming music.
      *
      * <p>Requires {@link android.Manifest.permission#BLUETOOTH} permission.
diff --git a/core/java/android/bluetooth/BluetoothUuid.java b/core/java/android/bluetooth/BluetoothUuid.java
index fe66fbd..6609b98 100644
--- a/core/java/android/bluetooth/BluetoothUuid.java
+++ b/core/java/android/bluetooth/BluetoothUuid.java
@@ -56,6 +56,8 @@
             ParcelUuid.fromString("00001105-0000-1000-8000-00805f9b34fb");
     public static final ParcelUuid Hid =
             ParcelUuid.fromString("00001124-0000-1000-8000-00805f9b34fb");
+    public static final ParcelUuid Hogp =
+            ParcelUuid.fromString("00001812-0000-1000-8000-00805f9b34fb");
     public static final ParcelUuid PANU =
             ParcelUuid.fromString("00001115-0000-1000-8000-00805F9B34FB");
     public static final ParcelUuid NAP =
diff --git a/core/java/android/bluetooth/IBluetoothA2dp.aidl b/core/java/android/bluetooth/IBluetoothA2dp.aidl
index 1f10998..26ff9e27 100644
--- a/core/java/android/bluetooth/IBluetoothA2dp.aidl
+++ b/core/java/android/bluetooth/IBluetoothA2dp.aidl
@@ -32,5 +32,8 @@
     int getConnectionState(in BluetoothDevice device);
     boolean setPriority(in BluetoothDevice device, int priority);
     int getPriority(in BluetoothDevice device);
+    boolean isAvrcpAbsoluteVolumeSupported();
+    oneway void adjustAvrcpAbsoluteVolume(int direction);
+    oneway void setAvrcpAbsoluteVolume(int volume);
     boolean isA2dpPlaying(in BluetoothDevice device);
 }
diff --git a/core/java/android/content/ContentResolver.java b/core/java/android/content/ContentResolver.java
index 45fed2d..5cabfeef 100644
--- a/core/java/android/content/ContentResolver.java
+++ b/core/java/android/content/ContentResolver.java
@@ -2060,7 +2060,7 @@
 
     private final class ParcelFileDescriptorInner extends ParcelFileDescriptor {
         private final IContentProvider mContentProvider;
-        private boolean mReleaseProviderFlag = false;
+        private boolean mProviderReleased;
 
         ParcelFileDescriptorInner(ParcelFileDescriptor pfd, IContentProvider icp) {
             super(pfd);
@@ -2069,17 +2069,10 @@
 
         @Override
         public void close() throws IOException {
-            if(!mReleaseProviderFlag) {
-                super.close();
+            super.close();
+            if (!mProviderReleased) {
                 ContentResolver.this.releaseProvider(mContentProvider);
-                mReleaseProviderFlag = true;
-            }
-        }
-
-        @Override
-        protected void finalize() throws Throwable {
-            if (!mReleaseProviderFlag) {
-                close();
+                mProviderReleased = true;
             }
         }
     }
diff --git a/core/java/android/gesture/GestureOverlayView.java b/core/java/android/gesture/GestureOverlayView.java
index b6c260f..2d47f28 100644
--- a/core/java/android/gesture/GestureOverlayView.java
+++ b/core/java/android/gesture/GestureOverlayView.java
@@ -486,6 +486,7 @@
 
     @Override
     protected void onDetachedFromWindow() {
+        super.onDetachedFromWindow();
         cancelClearAnimation();
     }
 
diff --git a/core/java/android/hardware/ICameraService.aidl b/core/java/android/hardware/ICameraService.aidl
index 81e564e..fc54828 100644
--- a/core/java/android/hardware/ICameraService.aidl
+++ b/core/java/android/hardware/ICameraService.aidl
@@ -22,6 +22,7 @@
 import android.hardware.IProCameraCallbacks;
 import android.hardware.camera2.ICameraDeviceUser;
 import android.hardware.camera2.ICameraDeviceCallbacks;
+import android.hardware.camera2.utils.BinderHolder;
 import android.hardware.ICameraServiceListener;
 import android.hardware.CameraInfo;
 
@@ -37,17 +38,23 @@
 
     int getCameraInfo(int cameraId, out CameraInfo info);
 
-    ICamera connect(ICameraClient client, int cameraId,
+    int connect(ICameraClient client, int cameraId,
                     String clientPackageName,
-                    int clientUid);
+                    int clientUid,
+                    // Container for an ICamera object
+                    out BinderHolder device);
 
-    IProCameraUser connectPro(IProCameraCallbacks callbacks, int cameraId,
+    int connectPro(IProCameraCallbacks callbacks, int cameraId,
                               String clientPackageName,
-                              int clientUid);
+                              int clientUid,
+                              // Container for an IProCameraUser object
+                              out BinderHolder device);
 
-    ICameraDeviceUser connectDevice(ICameraDeviceCallbacks callbacks, int cameraId,
+    int connectDevice(ICameraDeviceCallbacks callbacks, int cameraId,
                               String clientPackageName,
-                              int clientUid);
+                              int clientUid,
+                              // Container for an ICameraDeviceUser object
+                              out BinderHolder device);
 
     int addListener(ICameraServiceListener listener);
     int removeListener(ICameraServiceListener listener);
diff --git a/core/java/android/hardware/camera2/CameraAccessException.java b/core/java/android/hardware/camera2/CameraAccessException.java
index 0089f26..e08d1e6 100644
--- a/core/java/android/hardware/camera2/CameraAccessException.java
+++ b/core/java/android/hardware/camera2/CameraAccessException.java
@@ -48,11 +48,18 @@
 
     /**
      * The camera device is removable and has been disconnected from the Android
-     * device, or the camera service has shut down the connection due to a
+     * device, or the camera id used with {@link android.hardware.camera2.CameraManager#openCamera}
+     * is no longer valid, or the camera service has shut down the connection due to a
      * higher-priority access request for the camera device.
      */
     public static final int CAMERA_DISCONNECTED = 4;
 
+    /**
+     * A deprecated HAL version is in use.
+     * @hide
+     */
+    public static final int CAMERA_DEPRECATED_HAL = 1000;
+
     // Make the eclipse warning about serializable exceptions go away
     private static final long serialVersionUID = 5630338637471475675L; // randomly generated
 
diff --git a/core/java/android/hardware/camera2/CameraManager.java b/core/java/android/hardware/camera2/CameraManager.java
index 1370654..b8ec4da 100644
--- a/core/java/android/hardware/camera2/CameraManager.java
+++ b/core/java/android/hardware/camera2/CameraManager.java
@@ -22,6 +22,7 @@
 import android.hardware.IProCameraUser;
 import android.hardware.camera2.utils.CameraBinderDecorator;
 import android.hardware.camera2.utils.CameraRuntimeException;
+import android.hardware.camera2.utils.BinderHolder;
 import android.os.IBinder;
 import android.os.RemoteException;
 import android.os.ServiceManager;
@@ -171,10 +172,10 @@
      *
      * @param cameraId The unique identifier of the camera device to open
      *
-     * @throws IllegalArgumentException if the cameraId does not match any
-     * currently connected camera device.
      * @throws CameraAccessException if the camera is disabled by device policy,
-     * or too many camera devices are already open.
+     * or too many camera devices are already open, or the cameraId does not match
+     * any currently available camera device.
+     *
      * @throws SecurityException if the application does not have permission to
      * access the camera
      *
@@ -192,16 +193,11 @@
                 android.hardware.camera2.impl.CameraDevice device =
                         new android.hardware.camera2.impl.CameraDevice(cameraId);
 
-                cameraUser = mCameraService.connectDevice(device.getCallbacks(),
+                BinderHolder holder = new BinderHolder();
+                mCameraService.connectDevice(device.getCallbacks(),
                         Integer.parseInt(cameraId),
-                        mContext.getPackageName(), USE_CALLING_UID);
-
-                // TODO: change ICameraService#connectDevice to return status_t
-                if (cameraUser == null) {
-                    // TEMPORARY CODE.
-                    // catch-all exception since we aren't yet getting the actual error code
-                    throw new IllegalStateException("Failed to open camera device");
-                }
+                        mContext.getPackageName(), USE_CALLING_UID, holder);
+                cameraUser = ICameraDeviceUser.Stub.asInterface(holder.getBinder());
 
                 // TODO: factor out listener to be non-nested, then move setter to constructor
                 device.setRemoteDevice(cameraUser);
@@ -214,12 +210,7 @@
             throw new IllegalArgumentException("Expected cameraId to be numeric, but it was: "
                     + cameraId);
         } catch (CameraRuntimeException e) {
-            if (e.getReason() == CameraAccessException.CAMERA_DISCONNECTED) {
-                throw new IllegalArgumentException("Invalid camera ID specified -- " +
-                        "perhaps the camera was physically disconnected", e);
-            } else {
-                throw e.asChecked();
-            }
+            throw e.asChecked();
         } catch (RemoteException e) {
             // impossible
             return null;
diff --git a/core/java/android/hardware/camera2/CaptureRequest.java b/core/java/android/hardware/camera2/CaptureRequest.java
index 1a10bdd..63d6134 100644
--- a/core/java/android/hardware/camera2/CaptureRequest.java
+++ b/core/java/android/hardware/camera2/CaptureRequest.java
@@ -53,6 +53,7 @@
 
     private final Object mLock = new Object();
     private final HashSet<Surface> mSurfaceSet = new HashSet<Surface>();
+    private Object mUserTag;
 
     /**
      * @hide
@@ -89,6 +90,42 @@
         }
     }
 
+    /**
+     * Set a tag for this request.
+     *
+     * <p>This tag is not used for anything by the camera device, but can be
+     * used by an application to easily identify a CaptureRequest when it is
+     * returned by
+     * {@link CameraDevice.CaptureListener#onCaptureComplete CaptureListener.onCaptureComplete}
+     *
+     * @param tag an arbitrary Object to store with this request
+     * @see #getTag
+     */
+    public void setTag(Object tag) {
+        synchronized (mLock) {
+            mUserTag = tag;
+        }
+    }
+
+    /**
+     * Retrieve the tag for this request, if any.
+     *
+     * <p>This tag is not used for anything by the camera device, but can be
+     * used by an application to easily identify a CaptureRequest when it is
+     * returned by
+     * {@link CameraDevice.CaptureListener#onCaptureComplete CaptureListener.onCaptureComplete}
+     * </p>
+     *
+     * @return the last tag Object set on this request, or {@code null} if
+     *     no tag has been set.
+     * @see #setTag
+     */
+    public Object getTag() {
+        synchronized (mLock) {
+            return mUserTag;
+        }
+    }
+
     public static final Parcelable.Creator<CaptureRequest> CREATOR =
             new Parcelable.Creator<CaptureRequest>() {
         @Override
diff --git a/core/java/android/hardware/camera2/utils/BinderHolder.aidl b/core/java/android/hardware/camera2/utils/BinderHolder.aidl
new file mode 100644
index 0000000..f39d645
--- /dev/null
+++ b/core/java/android/hardware/camera2/utils/BinderHolder.aidl
@@ -0,0 +1,20 @@
+/*
+ * Copyright (C) 2013 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.camera2.utils;
+
+/** @hide */
+parcelable BinderHolder;
diff --git a/core/java/android/hardware/camera2/utils/BinderHolder.java b/core/java/android/hardware/camera2/utils/BinderHolder.java
new file mode 100644
index 0000000..9eea390
--- /dev/null
+++ b/core/java/android/hardware/camera2/utils/BinderHolder.java
@@ -0,0 +1,74 @@
+/*
+ * Copyright (C) 2013 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.camera2.utils;
+
+import android.os.Parcel;
+import android.os.Parcelable;
+import android.os.IBinder;
+
+/**
+ * @hide
+ */
+public class BinderHolder implements Parcelable {
+    private IBinder mBinder = null;
+
+    @Override
+    public int describeContents() {
+        return 0;
+    }
+
+    @Override
+    public void writeToParcel(Parcel dest, int flags) {
+        dest.writeStrongBinder(mBinder);
+    }
+
+    public void readFromParcel(Parcel src) {
+        mBinder = src.readStrongBinder();
+    }
+
+    public static final Parcelable.Creator<BinderHolder> CREATOR =
+             new Parcelable.Creator<BinderHolder>() {
+         @Override
+         public BinderHolder createFromParcel(Parcel in) {
+             return new BinderHolder(in);
+         }
+
+         @Override
+         public BinderHolder[] newArray(int size) {
+             return new BinderHolder[size];
+         }
+    };
+
+    public IBinder getBinder() {
+        return mBinder;
+    }
+
+    public void setBinder(IBinder binder) {
+        mBinder = binder;
+    }
+
+    public BinderHolder() {}
+
+    public BinderHolder(IBinder binder) {
+        mBinder = binder;
+    }
+
+    private BinderHolder(Parcel in) {
+        mBinder = in.readStrongBinder();
+    }
+}
+
diff --git a/core/java/android/hardware/camera2/utils/CameraBinderDecorator.java b/core/java/android/hardware/camera2/utils/CameraBinderDecorator.java
index 586c759..fbe7ff4 100644
--- a/core/java/android/hardware/camera2/utils/CameraBinderDecorator.java
+++ b/core/java/android/hardware/camera2/utils/CameraBinderDecorator.java
@@ -19,6 +19,7 @@
 import static android.hardware.camera2.CameraAccessException.CAMERA_DISABLED;
 import static android.hardware.camera2.CameraAccessException.CAMERA_DISCONNECTED;
 import static android.hardware.camera2.CameraAccessException.CAMERA_IN_USE;
+import static android.hardware.camera2.CameraAccessException.CAMERA_DEPRECATED_HAL;
 
 import android.os.DeadObjectException;
 import android.os.RemoteException;
@@ -48,6 +49,7 @@
     public static final int EACCES = -13;
     public static final int EBUSY = -16;
     public static final int ENODEV = -19;
+    public static final int ENOTSUP = -129;
 
     private static class CameraBinderDecoratorListener implements Decorator.DecoratorListener {
 
@@ -75,9 +77,6 @@
                     case DEAD_OBJECT:
                         UncheckedThrow.throwAnyException(new CameraRuntimeException(
                                 CAMERA_DISCONNECTED));
-                        // TODO: Camera service (native side) should return
-                        // EACCES error
-                        // when there's a policy manager disabled causing this
                     case EACCES:
                         UncheckedThrow.throwAnyException(new CameraRuntimeException(
                                 CAMERA_DISABLED));
@@ -87,6 +86,9 @@
                     case ENODEV:
                         UncheckedThrow.throwAnyException(new CameraRuntimeException(
                                 CAMERA_DISCONNECTED));
+                    case ENOTSUP:
+                        UncheckedThrow.throwAnyException(new CameraRuntimeException(
+                                CAMERA_DEPRECATED_HAL));
                 }
 
                 /**
diff --git a/core/java/android/os/Parcel.java b/core/java/android/os/Parcel.java
index 12f7915..46b0150 100644
--- a/core/java/android/os/Parcel.java
+++ b/core/java/android/os/Parcel.java
@@ -1520,6 +1520,11 @@
         return fd != null ? new ParcelFileDescriptor(fd) : null;
     }
 
+    /** {@hide} */
+    public final FileDescriptor readRawFileDescriptor() {
+        return nativeReadFileDescriptor(mNativePtr);
+    }
+
     /*package*/ static native FileDescriptor openFileDescriptor(String file,
             int mode) throws FileNotFoundException;
     /*package*/ static native FileDescriptor dupFileDescriptor(FileDescriptor orig)
diff --git a/core/java/android/os/ParcelFileDescriptor.java b/core/java/android/os/ParcelFileDescriptor.java
index 3de362c..579971d 100644
--- a/core/java/android/os/ParcelFileDescriptor.java
+++ b/core/java/android/os/ParcelFileDescriptor.java
@@ -16,8 +16,25 @@
 
 package android.os;
 
+import static libcore.io.OsConstants.AF_UNIX;
+import static libcore.io.OsConstants.SEEK_SET;
+import static libcore.io.OsConstants.SOCK_STREAM;
+import static libcore.io.OsConstants.S_ISLNK;
+import static libcore.io.OsConstants.S_ISREG;
+
+import android.content.BroadcastReceiver;
+import android.content.ContentProvider;
+import android.util.Log;
+
 import dalvik.system.CloseGuard;
 
+import libcore.io.ErrnoException;
+import libcore.io.IoUtils;
+import libcore.io.Libcore;
+import libcore.io.Memory;
+import libcore.io.OsConstants;
+import libcore.io.StructStat;
+
 import java.io.Closeable;
 import java.io.File;
 import java.io.FileDescriptor;
@@ -27,36 +44,80 @@
 import java.io.IOException;
 import java.net.DatagramSocket;
 import java.net.Socket;
+import java.nio.ByteOrder;
 
 /**
  * The FileDescriptor returned by {@link Parcel#readFileDescriptor}, allowing
  * you to close it when done with it.
  */
 public class ParcelFileDescriptor implements Parcelable, Closeable {
-    private final FileDescriptor mFileDescriptor;
+    private static final String TAG = "ParcelFileDescriptor";
+
+    private final FileDescriptor mFd;
+
+    /**
+     * Optional socket used to communicate close events, status at close, and
+     * detect remote process crashes.
+     */
+    private FileDescriptor mCommFd;
 
     /**
      * Wrapped {@link ParcelFileDescriptor}, if any. Used to avoid
-     * double-closing {@link #mFileDescriptor}.
+     * double-closing {@link #mFd}.
      */
     private final ParcelFileDescriptor mWrapped;
 
+    /**
+     * Maximum {@link #mStatusBuf} size; longer status messages will be
+     * truncated.
+     */
+    private static final int MAX_STATUS = 1024;
+
+    /**
+     * Temporary buffer used by {@link #readCommStatus(FileDescriptor, byte[])},
+     * allocated on-demand.
+     */
+    private byte[] mStatusBuf;
+
+    /**
+     * Status read by {@link #checkError(boolean)}, or null if not read yet.
+     */
+    private Status mStatus;
+
     private volatile boolean mClosed;
 
     private final CloseGuard mGuard = CloseGuard.get();
 
     /**
-     * For use with {@link #open}: if {@link #MODE_CREATE} has been supplied
-     * and this file doesn't already exist, then create the file with
-     * permissions such that any application can read it.
+     * For use with {@link #open}: if {@link #MODE_CREATE} has been supplied and
+     * this file doesn't already exist, then create the file with permissions
+     * such that any application can read it.
+     *
+     * @deprecated Creating world-readable files is very dangerous, and likely
+     *             to cause security holes in applications. It is strongly
+     *             discouraged; instead, applications should use more formal
+     *             mechanism for interactions such as {@link ContentProvider},
+     *             {@link BroadcastReceiver}, and {@link android.app.Service}.
+     *             There are no guarantees that this access mode will remain on
+     *             a file, such as when it goes through a backup and restore.
      */
+    @Deprecated
     public static final int MODE_WORLD_READABLE = 0x00000001;
 
     /**
-     * For use with {@link #open}: if {@link #MODE_CREATE} has been supplied
-     * and this file doesn't already exist, then create the file with
-     * permissions such that any application can write it.
+     * For use with {@link #open}: if {@link #MODE_CREATE} has been supplied and
+     * this file doesn't already exist, then create the file with permissions
+     * such that any application can write it.
+     *
+     * @deprecated Creating world-writable files is very dangerous, and likely
+     *             to cause security holes in applications. It is strongly
+     *             discouraged; instead, applications should use more formal
+     *             mechanism for interactions such as {@link ContentProvider},
+     *             {@link BroadcastReceiver}, and {@link android.app.Service}.
+     *             There are no guarantees that this access mode will remain on
+     *             a file, such as when it goes through a backup and restore.
      */
+    @Deprecated
     public static final int MODE_WORLD_WRITEABLE = 0x00000002;
 
     /**
@@ -90,32 +151,102 @@
     public static final int MODE_APPEND = 0x02000000;
 
     /**
+     * Create a new ParcelFileDescriptor wrapped around another descriptor. By
+     * default all method calls are delegated to the wrapped descriptor.
+     */
+    public ParcelFileDescriptor(ParcelFileDescriptor wrapped) {
+        // We keep a strong reference to the wrapped PFD, and rely on its
+        // finalizer to trigger CloseGuard. All calls are delegated to wrapper.
+        mWrapped = wrapped;
+        mFd = null;
+        mCommFd = null;
+        mClosed = true;
+    }
+
+    /** {@hide} */
+    public ParcelFileDescriptor(FileDescriptor fd) {
+        this(fd, null);
+    }
+
+    /** {@hide} */
+    public ParcelFileDescriptor(FileDescriptor fd, FileDescriptor commChannel) {
+        if (fd == null) {
+            throw new NullPointerException("FileDescriptor must not be null");
+        }
+        mWrapped = null;
+        mFd = fd;
+        mCommFd = commChannel;
+        mGuard.open("close");
+    }
+
+    /**
      * Create a new ParcelFileDescriptor accessing a given file.
      *
      * @param file The file to be opened.
      * @param mode The desired access mode, must be one of
-     * {@link #MODE_READ_ONLY}, {@link #MODE_WRITE_ONLY}, or
-     * {@link #MODE_READ_WRITE}; may also be any combination of
-     * {@link #MODE_CREATE}, {@link #MODE_TRUNCATE},
-     * {@link #MODE_WORLD_READABLE}, and {@link #MODE_WORLD_WRITEABLE}.
-     *
-     * @return Returns a new ParcelFileDescriptor pointing to the given
-     * file.
-     *
-     * @throws FileNotFoundException Throws FileNotFoundException if the given
-     * file does not exist or can not be opened with the requested mode.
+     *            {@link #MODE_READ_ONLY}, {@link #MODE_WRITE_ONLY}, or
+     *            {@link #MODE_READ_WRITE}; may also be any combination of
+     *            {@link #MODE_CREATE}, {@link #MODE_TRUNCATE},
+     *            {@link #MODE_WORLD_READABLE}, and
+     *            {@link #MODE_WORLD_WRITEABLE}.
+     * @return a new ParcelFileDescriptor pointing to the given file.
+     * @throws FileNotFoundException if the given file does not exist or can not
+     *             be opened with the requested mode.
      */
-    public static ParcelFileDescriptor open(File file, int mode)
-            throws FileNotFoundException {
-        String path = file.getPath();
+    public static ParcelFileDescriptor open(File file, int mode) throws FileNotFoundException {
+        final FileDescriptor fd = openInternal(file, mode);
+        if (fd == null) return null;
 
-        if ((mode&MODE_READ_WRITE) == 0) {
+        return new ParcelFileDescriptor(fd);
+    }
+
+    /**
+     * Create a new ParcelFileDescriptor accessing a given file.
+     *
+     * @param file The file to be opened.
+     * @param mode The desired access mode, must be one of
+     *            {@link #MODE_READ_ONLY}, {@link #MODE_WRITE_ONLY}, or
+     *            {@link #MODE_READ_WRITE}; may also be any combination of
+     *            {@link #MODE_CREATE}, {@link #MODE_TRUNCATE},
+     *            {@link #MODE_WORLD_READABLE}, and
+     *            {@link #MODE_WORLD_WRITEABLE}.
+     * @param handler to call listener from; must not be null.
+     * @param listener to be invoked when the returned descriptor has been
+     *            closed; must not be null.
+     * @return a new ParcelFileDescriptor pointing to the given file.
+     * @throws FileNotFoundException if the given file does not exist or can not
+     *             be opened with the requested mode.
+     */
+    public static ParcelFileDescriptor open(
+            File file, int mode, Handler handler, OnCloseListener listener) throws IOException {
+        if (handler == null) {
+            throw new IllegalArgumentException("Handler must not be null");
+        }
+        if (listener == null) {
+            throw new IllegalArgumentException("Listener must not be null");
+        }
+
+        final FileDescriptor fd = openInternal(file, mode);
+        if (fd == null) return null;
+
+        final FileDescriptor[] comm = createCommSocketPair(true);
+        final ParcelFileDescriptor pfd = new ParcelFileDescriptor(fd, comm[0]);
+
+        // Kick off thread to watch for status updates
+        final ListenerBridge bridge = new ListenerBridge(comm[1], handler.getLooper(), listener);
+        bridge.start();
+
+        return pfd;
+    }
+
+    private static FileDescriptor openInternal(File file, int mode) throws FileNotFoundException {
+        if ((mode & MODE_READ_WRITE) == 0) {
             throw new IllegalArgumentException(
                     "Must specify MODE_READ_ONLY, MODE_WRITE_ONLY, or MODE_READ_WRITE");
         }
 
-        FileDescriptor fd = Parcel.openFileDescriptor(path, mode);
-        return fd != null ? new ParcelFileDescriptor(fd) : null;
+        final String path = file.getPath();
+        return Parcel.openFileDescriptor(path, mode);
     }
 
     /**
@@ -125,8 +256,12 @@
      * original file descriptor.
      */
     public static ParcelFileDescriptor dup(FileDescriptor orig) throws IOException {
-        FileDescriptor fd = Parcel.dupFileDescriptor(orig);
-        return fd != null ? new ParcelFileDescriptor(fd) : null;
+        try {
+            final FileDescriptor fd = Libcore.os.dup(orig);
+            return new ParcelFileDescriptor(fd);
+        } catch (ErrnoException e) {
+            throw e.rethrowAsIOException();
+        }
     }
 
     /**
@@ -136,7 +271,11 @@
      * original file descriptor.
      */
     public ParcelFileDescriptor dup() throws IOException {
-        return dup(getFileDescriptor());
+        if (mWrapped != null) {
+            return mWrapped.dup();
+        } else {
+            return dup(getFileDescriptor());
+        }
     }
 
     /**
@@ -150,12 +289,16 @@
      * for a dup of the given fd.
      */
     public static ParcelFileDescriptor fromFd(int fd) throws IOException {
-        FileDescriptor fdesc = getFileDescriptorFromFd(fd);
-        return new ParcelFileDescriptor(fdesc);
-    }
+        final FileDescriptor original = new FileDescriptor();
+        original.setInt$(fd);
 
-    // Extracts the file descriptor from the specified socket and returns it untouched
-    private static native FileDescriptor getFileDescriptorFromFd(int fd) throws IOException;
+        try {
+            final FileDescriptor dup = Libcore.os.dup(original);
+            return new ParcelFileDescriptor(dup);
+        } catch (ErrnoException e) {
+            throw e.rethrowAsIOException();
+        }
+    }
 
     /**
      * Take ownership of a raw native fd in to a new ParcelFileDescriptor.
@@ -168,13 +311,12 @@
      * for the given fd.
      */
     public static ParcelFileDescriptor adoptFd(int fd) {
-        FileDescriptor fdesc = getFileDescriptorFromFdNoDup(fd);
+        final FileDescriptor fdesc = new FileDescriptor();
+        fdesc.setInt$(fd);
+
         return new ParcelFileDescriptor(fdesc);
     }
 
-    // Extracts the file descriptor from the specified socket and returns it untouched
-    private static native FileDescriptor getFileDescriptorFromFdNoDup(int fd);
-
     /**
      * Create a new ParcelFileDescriptor from the specified Socket.  The new
      * ParcelFileDescriptor holds a dup of the original FileDescriptor in
@@ -212,15 +354,90 @@
      * is the write side.
      */
     public static ParcelFileDescriptor[] createPipe() throws IOException {
-        FileDescriptor[] fds = new FileDescriptor[2];
-        createPipeNative(fds);
-        ParcelFileDescriptor[] pfds = new ParcelFileDescriptor[2];
-        pfds[0] = new ParcelFileDescriptor(fds[0]);
-        pfds[1] = new ParcelFileDescriptor(fds[1]);
-        return pfds;
+        try {
+            final FileDescriptor[] fds = Libcore.os.pipe();
+            return new ParcelFileDescriptor[] {
+                    new ParcelFileDescriptor(fds[0]),
+                    new ParcelFileDescriptor(fds[1]) };
+        } catch (ErrnoException e) {
+            throw e.rethrowAsIOException();
+        }
     }
 
-    private static native void createPipeNative(FileDescriptor[] outFds) throws IOException;
+    /**
+     * Create two ParcelFileDescriptors structured as a data pipe. The first
+     * ParcelFileDescriptor in the returned array is the read side; the second
+     * is the write side.
+     * <p>
+     * The write end has the ability to deliver an error message through
+     * {@link #closeWithError(String)} which can be handled by the read end
+     * calling {@link #checkError(boolean)}, usually after detecting an EOF.
+     * This can also be used to detect remote crashes.
+     */
+    public static ParcelFileDescriptor[] createReliablePipe() throws IOException {
+        try {
+            final FileDescriptor[] comm = createCommSocketPair(false);
+            final FileDescriptor[] fds = Libcore.os.pipe();
+            return new ParcelFileDescriptor[] {
+                    new ParcelFileDescriptor(fds[0], comm[0]),
+                    new ParcelFileDescriptor(fds[1], comm[1]) };
+        } catch (ErrnoException e) {
+            throw e.rethrowAsIOException();
+        }
+    }
+
+    /**
+     * Create two ParcelFileDescriptors structured as a pair of sockets
+     * connected to each other. The two sockets are indistinguishable.
+     */
+    public static ParcelFileDescriptor[] createSocketPair() throws IOException {
+        try {
+            final FileDescriptor fd0 = new FileDescriptor();
+            final FileDescriptor fd1 = new FileDescriptor();
+            Libcore.os.socketpair(AF_UNIX, SOCK_STREAM, 0, fd0, fd1);
+            return new ParcelFileDescriptor[] {
+                    new ParcelFileDescriptor(fd0),
+                    new ParcelFileDescriptor(fd1) };
+        } catch (ErrnoException e) {
+            throw e.rethrowAsIOException();
+        }
+    }
+
+    /**
+     * Create two ParcelFileDescriptors structured as a pair of sockets
+     * connected to each other. The two sockets are indistinguishable.
+     * <p>
+     * Both ends have the ability to deliver an error message through
+     * {@link #closeWithError(String)} which can be detected by the other end
+     * calling {@link #checkError(boolean)}, usually after detecting an EOF.
+     * This can also be used to detect remote crashes.
+     */
+    public static ParcelFileDescriptor[] createReliableSocketPair() throws IOException {
+        try {
+            final FileDescriptor[] comm = createCommSocketPair(false);
+            final FileDescriptor fd0 = new FileDescriptor();
+            final FileDescriptor fd1 = new FileDescriptor();
+            Libcore.os.socketpair(AF_UNIX, SOCK_STREAM, 0, fd0, fd1);
+            return new ParcelFileDescriptor[] {
+                    new ParcelFileDescriptor(fd0, comm[0]),
+                    new ParcelFileDescriptor(fd1, comm[1]) };
+        } catch (ErrnoException e) {
+            throw e.rethrowAsIOException();
+        }
+    }
+
+    private static FileDescriptor[] createCommSocketPair(boolean blocking) throws IOException {
+        try {
+            final FileDescriptor comm1 = new FileDescriptor();
+            final FileDescriptor comm2 = new FileDescriptor();
+            Libcore.os.socketpair(AF_UNIX, SOCK_STREAM, 0, comm1, comm2);
+            IoUtils.setBlocking(comm1, blocking);
+            IoUtils.setBlocking(comm2, blocking);
+            return new FileDescriptor[] { comm1, comm2 };
+        } catch (ErrnoException e) {
+            throw e.rethrowAsIOException();
+        }
+    }
 
     /**
      * @hide Please use createPipe() or ContentProvider.openPipeHelper().
@@ -250,21 +467,51 @@
      * @return Returns the FileDescriptor associated with this object.
      */
     public FileDescriptor getFileDescriptor() {
-        return mFileDescriptor;
+        if (mWrapped != null) {
+            return mWrapped.getFileDescriptor();
+        } else {
+            return mFd;
+        }
     }
 
     /**
-     * Return the total size of the file representing this fd, as determined
-     * by stat().  Returns -1 if the fd is not a file.
+     * Return the total size of the file representing this fd, as determined by
+     * {@code stat()}. Returns -1 if the fd is not a file.
      */
-    public native long getStatSize();
+    public long getStatSize() {
+        if (mWrapped != null) {
+            return mWrapped.getStatSize();
+        } else {
+            try {
+                final StructStat st = Libcore.os.fstat(mFd);
+                if (S_ISREG(st.st_mode) || S_ISLNK(st.st_mode)) {
+                    return st.st_size;
+                } else {
+                    return -1;
+                }
+            } catch (ErrnoException e) {
+                Log.w(TAG, "fstat() failed: " + e);
+                return -1;
+            }
+        }
+    }
 
     /**
      * This is needed for implementing AssetFileDescriptor.AutoCloseOutputStream,
      * and I really don't think we want it to be public.
      * @hide
      */
-    public native long seekTo(long pos);
+    public long seekTo(long pos) throws IOException {
+        if (mWrapped != null) {
+            return mWrapped.seekTo(pos);
+        } else {
+            try {
+                return Libcore.os.lseek(mFd, pos, SEEK_SET);
+            } catch (ErrnoException e) {
+                throw e.rethrowAsIOException();
+            }
+        }
+    }
 
     /**
      * Return the native fd int for this ParcelFileDescriptor.  The
@@ -272,34 +519,39 @@
      * through this API.
      */
     public int getFd() {
-        if (mClosed) {
-            throw new IllegalStateException("Already closed");
+        if (mWrapped != null) {
+            return mWrapped.getFd();
+        } else {
+            if (mClosed) {
+                throw new IllegalStateException("Already closed");
+            }
+            return mFd.getInt$();
         }
-        return getFdNative();
     }
 
-    private native int getFdNative();
-
     /**
-     * Return the native fd int for this ParcelFileDescriptor and detach it
-     * from the object here.  You are now responsible for closing the fd in
-     * native code.
+     * Return the native fd int for this ParcelFileDescriptor and detach it from
+     * the object here. You are now responsible for closing the fd in native
+     * code.
+     * <p>
+     * You should not detach when the original creator of the descriptor is
+     * expecting a reliable signal through {@link #close()} or
+     * {@link #closeWithError(String)}.
+     *
+     * @see #canDetectErrors()
      */
     public int detachFd() {
-        if (mClosed) {
-            throw new IllegalStateException("Already closed");
-        }
         if (mWrapped != null) {
-            int fd = mWrapped.detachFd();
-            mClosed = true;
-            mGuard.close();
+            return mWrapped.detachFd();
+        } else {
+            if (mClosed) {
+                throw new IllegalStateException("Already closed");
+            }
+            final int fd = getFd();
+            Parcel.clearFileDescriptor(mFd);
+            writeCommStatusAndClose(Status.DETACHED, null);
             return fd;
         }
-        int fd = getFd();
-        mClosed = true;
-        mGuard.close();
-        Parcel.clearFileDescriptor(mFileDescriptor);
-        return fd;
     }
 
     /**
@@ -311,16 +563,176 @@
      */
     @Override
     public void close() throws IOException {
-        if (mClosed) return;
-        mClosed = true;
-        mGuard.close();
-
         if (mWrapped != null) {
-            // If this is a proxy to another file descriptor, just call through to its
-            // close method.
             mWrapped.close();
         } else {
-            Parcel.closeFileDescriptor(mFileDescriptor);
+            closeWithStatus(Status.OK, null);
+        }
+    }
+
+    /**
+     * Close the ParcelFileDescriptor, informing any peer that an error occurred
+     * while processing. If the creator of this descriptor is not observing
+     * errors, it will close normally.
+     *
+     * @param msg describing the error; must not be null.
+     */
+    public void closeWithError(String msg) throws IOException {
+        if (mWrapped != null) {
+            mWrapped.closeWithError(msg);
+        } else {
+            if (msg == null) {
+                throw new IllegalArgumentException("Message must not be null");
+            }
+            closeWithStatus(Status.ERROR, msg);
+        }
+    }
+
+    private void closeWithStatus(int status, String msg) throws IOException {
+        if (mWrapped != null) {
+            mWrapped.closeWithStatus(status, msg);
+        } else {
+            if (mClosed) return;
+            mClosed = true;
+            mGuard.close();
+            // Status MUST be sent before closing actual descriptor
+            writeCommStatusAndClose(status, msg);
+            IoUtils.closeQuietly(mFd);
+        }
+    }
+
+    private byte[] getOrCreateStatusBuffer() {
+        if (mStatusBuf == null) {
+            mStatusBuf = new byte[MAX_STATUS];
+        }
+        return mStatusBuf;
+    }
+
+    private void writeCommStatusAndClose(int status, String msg) {
+        if (mCommFd == null) {
+            // Not reliable, or someone already sent status
+            if (msg != null) {
+                Log.w(TAG, "Unable to inform peer: " + msg);
+            }
+            return;
+        }
+
+        if (status == Status.DETACHED) {
+            Log.w(TAG, "Peer expected signal when closed; unable to deliver after detach");
+        }
+
+        try {
+            try {
+                if (status != Status.SILENCE) {
+                    final byte[] buf = getOrCreateStatusBuffer();
+                    int writePtr = 0;
+
+                    Memory.pokeInt(buf, writePtr, status, ByteOrder.BIG_ENDIAN);
+                    writePtr += 4;
+
+                    if (msg != null) {
+                        final byte[] rawMsg = msg.getBytes();
+                        final int len = Math.min(rawMsg.length, buf.length - writePtr);
+                        System.arraycopy(rawMsg, 0, buf, writePtr, len);
+                        writePtr += len;
+                    }
+
+                    Libcore.os.write(mCommFd, buf, 0, writePtr);
+                }
+            } catch (ErrnoException e) {
+                // Reporting status is best-effort
+                Log.w(TAG, "Failed to report status: " + e);
+            }
+
+            if (status != Status.SILENCE) {
+                // Since we're about to close, read off any remote status. It's
+                // okay to remember missing here.
+                mStatus = readCommStatus(mCommFd, getOrCreateStatusBuffer());
+            }
+
+        } finally {
+            IoUtils.closeQuietly(mCommFd);
+            mCommFd = null;
+        }
+    }
+
+    private static Status readCommStatus(FileDescriptor comm, byte[] buf) {
+        try {
+            final int n = Libcore.os.read(comm, buf, 0, buf.length);
+            if (n == 0) {
+                // EOF means they're dead
+                return new Status(Status.DEAD);
+            } else {
+                final int status = Memory.peekInt(buf, 0, ByteOrder.BIG_ENDIAN);
+                if (status == Status.ERROR) {
+                    final String msg = new String(buf, 4, n - 4);
+                    return new Status(status, msg);
+                }
+                return new Status(status);
+            }
+        } catch (ErrnoException e) {
+            if (e.errno == OsConstants.EAGAIN) {
+                // Remote is still alive, but no status written yet
+                return null;
+            } else {
+                Log.d(TAG, "Failed to read status; assuming dead: " + e);
+                return new Status(Status.DEAD);
+            }
+        }
+    }
+
+    /**
+     * Indicates if this ParcelFileDescriptor can communicate and detect remote
+     * errors/crashes.
+     *
+     * @see #checkError(boolean)
+     */
+    public boolean canDetectErrors() {
+        if (mWrapped != null) {
+            return mWrapped.canDetectErrors();
+        } else {
+            return mCommFd != null;
+        }
+    }
+
+    /**
+     * Detect and throw if the other end of a pipe or socket pair encountered an
+     * error or crashed. This allows a reader to distinguish between a valid EOF
+     * and an error/crash.
+     * <p>
+     * If this ParcelFileDescriptor is unable to detect remote errors, it will
+     * return silently.
+     *
+     * @param throwIfDetached requests that an exception be thrown if the remote
+     *            side called {@link #detachFd()}. Once detached, the remote
+     *            side is unable to communicate any errors through
+     *            {@link #closeWithError(String)}. An application may pass true
+     *            if it needs a stronger guarantee that the stream was closed
+     *            normally and was not merely detached.
+     * @see #canDetectErrors()
+     */
+    public void checkError(boolean throwIfDetached) throws IOException {
+        if (mWrapped != null) {
+            mWrapped.checkError(throwIfDetached);
+        } else {
+            if (mStatus == null) {
+                if (mCommFd == null) {
+                    Log.w(TAG, "Peer didn't provide a comm channel; unable to check for errors");
+                    return;
+                }
+
+                // Try reading status; it might be null if nothing written yet.
+                // Either way, we keep comm open to write our status later.
+                mStatus = readCommStatus(mCommFd, getOrCreateStatusBuffer());
+            }
+
+            if (mStatus == null || mStatus.status == Status.OK
+                    || (mStatus.status == Status.DETACHED && !throwIfDetached)) {
+                // No status yet, or everything is peachy!
+                return;
+            } else {
+                throw mStatus.asIOException();
+            }
         }
     }
 
@@ -330,17 +742,17 @@
      * ParcelFileDescriptor.close()} for you when the stream is closed.
      */
     public static class AutoCloseInputStream extends FileInputStream {
-        private final ParcelFileDescriptor mFd;
+        private final ParcelFileDescriptor mPfd;
 
-        public AutoCloseInputStream(ParcelFileDescriptor fd) {
-            super(fd.getFileDescriptor());
-            mFd = fd;
+        public AutoCloseInputStream(ParcelFileDescriptor pfd) {
+            super(pfd.getFileDescriptor());
+            mPfd = pfd;
         }
 
         @Override
         public void close() throws IOException {
             try {
-                mFd.close();
+                mPfd.close();
             } finally {
                 super.close();
             }
@@ -353,17 +765,17 @@
      * ParcelFileDescriptor.close()} for you when the stream is closed.
      */
     public static class AutoCloseOutputStream extends FileOutputStream {
-        private final ParcelFileDescriptor mFd;
+        private final ParcelFileDescriptor mPfd;
 
-        public AutoCloseOutputStream(ParcelFileDescriptor fd) {
-            super(fd.getFileDescriptor());
-            mFd = fd;
+        public AutoCloseOutputStream(ParcelFileDescriptor pfd) {
+            super(pfd.getFileDescriptor());
+            mPfd = pfd;
         }
 
         @Override
         public void close() throws IOException {
             try {
-                mFd.close();
+                mPfd.close();
             } finally {
                 super.close();
             }
@@ -372,7 +784,11 @@
 
     @Override
     public String toString() {
-        return "{ParcelFileDescriptor: " + mFileDescriptor + "}";
+        if (mWrapped != null) {
+            return mWrapped.toString();
+        } else {
+            return "{ParcelFileDescriptor: " + mFd + "}";
+        }
     }
 
     @Override
@@ -382,32 +798,20 @@
         }
         try {
             if (!mClosed) {
-                close();
+                closeWithStatus(Status.LEAKED, null);
             }
         } finally {
             super.finalize();
         }
     }
 
-    public ParcelFileDescriptor(ParcelFileDescriptor descriptor) {
-        mWrapped = descriptor;
-        mFileDescriptor = mWrapped.mFileDescriptor;
-        mGuard.open("close");
-    }
-
-    /** {@hide} */
-    public ParcelFileDescriptor(FileDescriptor descriptor) {
-        if (descriptor == null) {
-            throw new NullPointerException("descriptor must not be null");
-        }
-        mWrapped = null;
-        mFileDescriptor = descriptor;
-        mGuard.open("close");
-    }
-
     @Override
     public int describeContents() {
-        return Parcelable.CONTENTS_FILE_DESCRIPTOR;
+        if (mWrapped != null) {
+            return mWrapped.describeContents();
+        } else {
+            return Parcelable.CONTENTS_FILE_DESCRIPTOR;
+        }
     }
 
     /**
@@ -417,12 +821,22 @@
      */
     @Override
     public void writeToParcel(Parcel out, int flags) {
-        out.writeFileDescriptor(mFileDescriptor);
-        if ((flags&PARCELABLE_WRITE_RETURN_VALUE) != 0 && !mClosed) {
-            try {
-                close();
-            } catch (IOException e) {
-                // Empty
+        if (mWrapped != null) {
+            mWrapped.writeToParcel(out, flags);
+        } else {
+            out.writeFileDescriptor(mFd);
+            if (mCommFd != null) {
+                out.writeInt(1);
+                out.writeFileDescriptor(mCommFd);
+            } else {
+                out.writeInt(0);
+            }
+            if ((flags & PARCELABLE_WRITE_RETURN_VALUE) != 0 && !mClosed) {
+                try {
+                    // Not a real close, so emit no status
+                    closeWithStatus(Status.SILENCE, null);
+                } catch (IOException e) {
+                }
             }
         }
     }
@@ -431,7 +845,12 @@
             = new Parcelable.Creator<ParcelFileDescriptor>() {
         @Override
         public ParcelFileDescriptor createFromParcel(Parcel in) {
-            return in.readFileDescriptor();
+            final FileDescriptor fd = in.readRawFileDescriptor();
+            FileDescriptor commChannel = null;
+            if (in.readInt() != 0) {
+                commChannel = in.readRawFileDescriptor();
+            }
+            return new ParcelFileDescriptor(fd, commChannel);
         }
 
         @Override
@@ -439,4 +858,111 @@
             return new ParcelFileDescriptor[size];
         }
     };
+
+    /**
+     * Callback indicating that a ParcelFileDescriptor has been closed.
+     */
+    public interface OnCloseListener {
+        /**
+         * Event indicating the ParcelFileDescriptor to which this listener was
+         * attached has been closed.
+         *
+         * @param e error state, or {@code null} if closed cleanly.
+         * @param fromDetach indicates if close event was result of
+         *            {@link ParcelFileDescriptor#detachFd()}. After detach the
+         *            remote side may continue reading/writing to the underlying
+         *            {@link FileDescriptor}, but they can no longer deliver
+         *            reliable close/error events.
+         */
+        public void onClose(IOException e, boolean fromDetach);
+    }
+
+    /**
+     * Internal class representing a remote status read by
+     * {@link ParcelFileDescriptor#readCommStatus(FileDescriptor, byte[])}.
+     */
+    private static class Status {
+        /** Special value indicating remote side died. */
+        public static final int DEAD = -2;
+        /** Special value indicating no status should be written. */
+        public static final int SILENCE = -1;
+
+        /** Remote reported that everything went better than expected. */
+        public static final int OK = 0;
+        /** Remote reported error; length and message follow. */
+        public static final int ERROR = 1;
+        /** Remote reported {@link #detachFd()} and went rogue. */
+        public static final int DETACHED = 2;
+        /** Remote reported their object was finalized. */
+        public static final int LEAKED = 3;
+
+        public final int status;
+        public final String msg;
+
+        public Status(int status) {
+            this(status, null);
+        }
+
+        public Status(int status, String msg) {
+            this.status = status;
+            this.msg = msg;
+        }
+
+        public IOException asIOException() {
+            switch (status) {
+                case DEAD:
+                    return new IOException("Remote side is dead");
+                case OK:
+                    return null;
+                case ERROR:
+                    return new IOException("Remote error: " + msg);
+                case DETACHED:
+                    return new IOException("Remote side is detached");
+                case LEAKED:
+                    return new IOException("Remote side was leaked");
+                default:
+                    return new IOException("Unknown status: " + status);
+            }
+        }
+    }
+
+    /**
+     * Bridge to watch for remote status, and deliver to listener. Currently
+     * requires that communication socket is <em>blocking</em>.
+     */
+    private static final class ListenerBridge extends Thread {
+        // TODO: switch to using Looper to avoid burning a thread
+
+        private FileDescriptor mCommFd;
+        private final Handler mHandler;
+
+        public ListenerBridge(FileDescriptor comm, Looper looper, final OnCloseListener listener) {
+            mCommFd = comm;
+            mHandler = new Handler(looper) {
+                @Override
+                public void handleMessage(Message msg) {
+                    final Status s = (Status) msg.obj;
+                    if (s.status == Status.DETACHED) {
+                        listener.onClose(null, true);
+                    } else if (s.status == Status.OK) {
+                        listener.onClose(null, false);
+                    } else {
+                        listener.onClose(s.asIOException(), false);
+                    }
+                }
+            };
+        }
+
+        @Override
+        public void run() {
+            try {
+                final byte[] buf = new byte[MAX_STATUS];
+                final Status status = readCommStatus(mCommFd, buf);
+                mHandler.obtainMessage(0, status).sendToTarget();
+            } finally {
+                IoUtils.closeQuietly(mCommFd);
+                mCommFd = null;
+            }
+        }
+    }
 }
diff --git a/core/java/android/text/format/DateUtils.java b/core/java/android/text/format/DateUtils.java
index 2b805a9..22675b4 100644
--- a/core/java/android/text/format/DateUtils.java
+++ b/core/java/android/text/format/DateUtils.java
@@ -816,9 +816,10 @@
      */
     public static Formatter formatDateRange(Context context, Formatter formatter, long startMillis,
                                             long endMillis, int flags, String timeZone) {
-        // icu4c will fall back to the locale's preferred 12/24 format,
+        // If we're being asked to format a time without being explicitly told whether to use
+        // the 12- or 24-hour clock, icu4c will fall back to the locale's preferred 12/24 format,
         // but we want to fall back to the user's preference.
-        if ((flags & (FORMAT_12HOUR | FORMAT_24HOUR)) == 0) {
+        if ((flags & (FORMAT_SHOW_TIME | FORMAT_12HOUR | FORMAT_24HOUR)) == FORMAT_SHOW_TIME) {
             flags |= DateFormat.is24HourFormat(context) ? FORMAT_24HOUR : FORMAT_12HOUR;
         }
 
diff --git a/core/java/android/view/DisplayList.java b/core/java/android/view/DisplayList.java
index 2d24c1e..43fd628 100644
--- a/core/java/android/view/DisplayList.java
+++ b/core/java/android/view/DisplayList.java
@@ -208,9 +208,22 @@
      * {@link #isValid()} will return false.
      *
      * @see #isValid()
+     * @see #reset()
      */
     public abstract void clear();
 
+
+    /**
+     * Reset native resources. This is called when cleaning up the state of display lists
+     * during destruction of hardware resources, to ensure that we do not hold onto
+     * obsolete resources after related resources are gone.
+     *
+     * @see #clear()
+     *
+     * @hide
+     */
+    public abstract void reset();
+
     /**
      * Sets the dirty flag. When a display list is dirty, {@link #clear()} should
      * be invoked whenever possible.
@@ -670,13 +683,4 @@
      * @see View#offsetTopAndBottom(int)
      */
     public abstract void offsetTopAndBottom(float offset);
-
-    /**
-     * Reset native resources. This is called when cleaning up the state of display lists
-     * during destruction of hardware resources, to ensure that we do not hold onto
-     * obsolete resources after related resources are gone.
-     *
-     * @hide
-     */
-    public abstract void reset();
 }
diff --git a/core/java/android/view/GLES20DisplayList.java b/core/java/android/view/GLES20DisplayList.java
index 8b2a2ef..c652bac 100644
--- a/core/java/android/view/GLES20DisplayList.java
+++ b/core/java/android/view/GLES20DisplayList.java
@@ -94,6 +94,7 @@
         if (hasNativeDisplayList()) {
             nReset(mFinalizer.mNativeDisplayList);
         }
+        clear();
     }
 
     @Override
diff --git a/core/java/android/view/GLES20Layer.java b/core/java/android/view/GLES20Layer.java
index 7ee628b..0e3311c 100644
--- a/core/java/android/view/GLES20Layer.java
+++ b/core/java/android/view/GLES20Layer.java
@@ -59,6 +59,9 @@
 
     @Override
     public void destroy() {
+        if (mDisplayList != null) {
+            mDisplayList.reset();
+        }
         if (mFinalizer != null) {
             mFinalizer.destroy();
             mFinalizer = null;
diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java
index 747e8ea..f05e372 100644
--- a/core/java/android/view/View.java
+++ b/core/java/android/view/View.java
@@ -12076,12 +12076,13 @@
      * @hide
      */
     public void resolvePadding() {
+        final int resolvedLayoutDirection = getLayoutDirection();
+
         if (!isRtlCompatibilityMode()) {
             // Post Jelly Bean MR1 case: we need to take the resolved layout direction into account.
             // If start / end padding are defined, they will be resolved (hence overriding) to
             // left / right or right / left depending on the resolved layout direction.
             // If start / end padding are not defined, use the left / right ones.
-            int resolvedLayoutDirection = getLayoutDirection();
             switch (resolvedLayoutDirection) {
                 case LAYOUT_DIRECTION_RTL:
                     if (mUserPaddingStart != UNDEFINED_PADDING) {
@@ -12110,11 +12111,10 @@
             }
 
             mUserPaddingBottom = (mUserPaddingBottom >= 0) ? mUserPaddingBottom : mPaddingBottom;
-
-            onRtlPropertiesChanged(resolvedLayoutDirection);
         }
 
         internalSetPadding(mUserPaddingLeft, mPaddingTop, mUserPaddingRight, mUserPaddingBottom);
+        onRtlPropertiesChanged(resolvedLayoutDirection);
 
         mPrivateFlags2 |= PFLAG2_PADDING_RESOLVED;
     }
@@ -12144,7 +12144,6 @@
         removeSendViewScrolledAccessibilityEventCallback();
 
         destroyDrawingCache();
-
         destroyLayer(false);
 
         cleanupDraw();
@@ -12162,7 +12161,7 @@
             mAttachInfo.mViewRootImpl.cancelInvalidate(this);
         } else {
             // Should never happen
-            clearDisplayList();
+            resetDisplayList();
         }
     }
 
@@ -12773,9 +12772,6 @@
                 mHardwareLayer.destroy();
                 mHardwareLayer = null;
 
-                if (mDisplayList != null) {
-                    mDisplayList.reset();
-                }
                 invalidate(true);
                 invalidateParentCaches();
             }
@@ -12796,7 +12792,7 @@
      * @hide
      */
     protected void destroyHardwareResources() {
-        clearDisplayList();
+        resetDisplayList();
         destroyLayer(true);
     }
 
@@ -13044,6 +13040,12 @@
         }
     }
 
+    private void resetDisplayList() {
+        if (mDisplayList != null) {
+            mDisplayList.reset();
+        }
+    }
+
     /**
      * <p>Calling this method is equivalent to calling <code>getDrawingCache(false)</code>.</p>
      *
diff --git a/core/java/android/view/ViewGroup.java b/core/java/android/view/ViewGroup.java
index f574efa..c874c82 100644
--- a/core/java/android/view/ViewGroup.java
+++ b/core/java/android/view/ViewGroup.java
@@ -5357,6 +5357,18 @@
     }
 
     /**
+     * Returns whether layout calls on this container are currently being
+     * suppressed, due to an earlier call to {@link #suppressLayout(boolean)}.
+     *
+     * @return true if layout calls are currently suppressed, false otherwise.
+     *
+     * @hide
+     */
+    public boolean isLayoutSuppressed() {
+        return mSuppressLayout;
+    }
+
+    /**
      * {@inheritDoc}
      */
     @Override
diff --git a/core/java/android/view/ViewRootImpl.java b/core/java/android/view/ViewRootImpl.java
index e90705c..f711e7a 100644
--- a/core/java/android/view/ViewRootImpl.java
+++ b/core/java/android/view/ViewRootImpl.java
@@ -614,15 +614,7 @@
     }
 
     void destroyHardwareResources() {
-        if (mAttachInfo.mHardwareRenderer != null) {
-            if (mAttachInfo.mHardwareRenderer.isEnabled()) {
-                mAttachInfo.mHardwareRenderer.destroyLayers(mView);
-            }
-            mAttachInfo.mHardwareRenderer.destroy(false);
-        }
-    }
-
-    void terminateHardwareResources() {
+        invalidateDisplayLists();
         if (mAttachInfo.mHardwareRenderer != null) {
             mAttachInfo.mHardwareRenderer.destroyHardwareResources(mView);
             mAttachInfo.mHardwareRenderer.destroy(false);
@@ -636,6 +628,7 @@
                 HardwareRenderer.trimMemory(ComponentCallbacks2.TRIM_MEMORY_MODERATE);
             }
         } else {
+            invalidateDisplayLists();
             if (mAttachInfo.mHardwareRenderer != null &&
                     mAttachInfo.mHardwareRenderer.isEnabled()) {
                 mAttachInfo.mHardwareRenderer.destroyLayers(mView);
@@ -2554,7 +2547,7 @@
         for (int i = 0; i < count; i++) {
             final DisplayList displayList = displayLists.get(i);
             if (displayList.isDirty()) {
-                displayList.clear();
+                displayList.reset();
             }
         }
 
diff --git a/core/java/android/view/WindowManagerGlobal.java b/core/java/android/view/WindowManagerGlobal.java
index b183bb6..3dd96f5 100644
--- a/core/java/android/view/WindowManagerGlobal.java
+++ b/core/java/android/view/WindowManagerGlobal.java
@@ -21,7 +21,6 @@
 import android.content.ComponentCallbacks2;
 import android.content.res.Configuration;
 import android.opengl.ManagedEGLContext;
-import android.os.Debug;
 import android.os.IBinder;
 import android.os.RemoteException;
 import android.os.ServiceManager;
@@ -29,7 +28,6 @@
 import android.util.AndroidRuntimeException;
 import android.util.ArraySet;
 import android.util.Log;
-import android.util.Slog;
 import android.view.inputmethod.InputMethodManager;
 import com.android.internal.util.FastPrintWriter;
 
@@ -385,7 +383,7 @@
                 // known windows
                 synchronized (mLock) {
                     for (int i = mRoots.size() - 1; i >= 0; --i) {
-                        mRoots.get(i).terminateHardwareResources();
+                        mRoots.get(i).destroyHardwareResources();
                     }
                 }
                 // Force a full memory flush
diff --git a/core/java/android/view/inputmethod/InputMethodInfo.java b/core/java/android/view/inputmethod/InputMethodInfo.java
index feaab3e..c440c7b 100644
--- a/core/java/android/view/inputmethod/InputMethodInfo.java
+++ b/core/java/android/view/inputmethod/InputMethodInfo.java
@@ -82,11 +82,16 @@
     private final boolean mIsAuxIme;
 
     /**
-     * Cavert: mForceDefault must be false for production. This flag is only for test.
+     * Caveat: mForceDefault must be false for production. This flag is only for test.
      */
     private final boolean mForceDefault;
 
     /**
+     * The flag whether this IME supports ways to switch to a next input method (e.g. globe key.)
+     */
+    private final boolean mSupportsSwitchingToNextInputMethod;
+
+    /**
      * Constructor.
      *
      * @param context The Context in which we are parsing the input method.
@@ -114,6 +119,7 @@
         ServiceInfo si = service.serviceInfo;
         mId = new ComponentName(si.packageName, si.name).flattenToShortString();
         boolean isAuxIme = true;
+        boolean supportsSwitchingToNextInputMethod = false; // false as default
         mForceDefault = false;
 
         PackageManager pm = context.getPackageManager();
@@ -149,6 +155,9 @@
                     com.android.internal.R.styleable.InputMethod_settingsActivity);
             isDefaultResId = sa.getResourceId(
                     com.android.internal.R.styleable.InputMethod_isDefault, 0);
+            supportsSwitchingToNextInputMethod = sa.getBoolean(
+                    com.android.internal.R.styleable.InputMethod_supportsSwitchingToNextInputMethod,
+                    false);
             sa.recycle();
 
             final int depth = parser.getDepth();
@@ -216,6 +225,7 @@
         mSettingsActivityName = settingsActivityComponent;
         mIsDefaultResId = isDefaultResId;
         mIsAuxIme = isAuxIme;
+        mSupportsSwitchingToNextInputMethod = supportsSwitchingToNextInputMethod;
     }
 
     InputMethodInfo(Parcel source) {
@@ -223,6 +233,7 @@
         mSettingsActivityName = source.readString();
         mIsDefaultResId = source.readInt();
         mIsAuxIme = source.readInt() == 1;
+        mSupportsSwitchingToNextInputMethod = source.readInt() == 1;
         mService = ResolveInfo.CREATOR.createFromParcel(source);
         source.readTypedList(mSubtypes, InputMethodSubtype.CREATOR);
         mForceDefault = false;
@@ -254,6 +265,7 @@
             mSubtypes.addAll(subtypes);
         }
         mForceDefault = forceDefault;
+        mSupportsSwitchingToNextInputMethod = true;
     }
 
     private static ResolveInfo buildDummyResolveInfo(String packageName, String className,
@@ -435,6 +447,14 @@
     }
 
     /**
+     * @return true if this input method supports ways to switch to a next input method.
+     * @hide
+     */
+    public boolean supportsSwitchingToNextInputMethod() {
+        return mSupportsSwitchingToNextInputMethod;
+    }
+
+    /**
      * Used to package this object into a {@link Parcel}.
      * 
      * @param dest The {@link Parcel} to be written.
@@ -446,6 +466,7 @@
         dest.writeString(mSettingsActivityName);
         dest.writeInt(mIsDefaultResId);
         dest.writeInt(mIsAuxIme ? 1 : 0);
+        dest.writeInt(mSupportsSwitchingToNextInputMethod ? 1 : 0);
         mService.writeToParcel(dest, flags);
         dest.writeTypedList(mSubtypes);
     }
diff --git a/core/java/android/view/transition/Fade.java b/core/java/android/view/transition/Fade.java
index 4fd60c1..45c21d8 100644
--- a/core/java/android/view/transition/Fade.java
+++ b/core/java/android/view/transition/Fade.java
@@ -19,6 +19,7 @@
 import android.animation.Animator;
 import android.animation.AnimatorListenerAdapter;
 import android.animation.ObjectAnimator;
+import android.animation.ValueAnimator;
 import android.util.Log;
 import android.view.View;
 import android.view.ViewGroup;
@@ -35,6 +36,7 @@
     private static boolean DBG = Transition.DBG && false;
 
     private static final String LOG_TAG = "Fade";
+    private static final String PROPNAME_ALPHA = "android:fade:alpha";
     private static final String PROPNAME_SCREEN_X = "android:fade:screenX";
     private static final String PROPNAME_SCREEN_Y = "android:fade:screenY";
 
@@ -74,20 +76,28 @@
     /**
      * Utility method to handle creating and running the Animator.
      */
-    private Animator runAnimation(View view, float startAlpha, float endAlpha,
-            Animator.AnimatorListener listener) {
+    private Animator createAnimation(View view, float startAlpha, float endAlpha,
+            AnimatorListenerAdapter listener) {
+        if (startAlpha == endAlpha) {
+            // run listener if we're noop'ing the animation, to get the end-state results now
+            if (listener != null) {
+                listener.onAnimationEnd(null);
+            }
+            return null;
+        }
         final ObjectAnimator anim = ObjectAnimator.ofFloat(view, "alpha", startAlpha, endAlpha);
         if (listener != null) {
             anim.addListener(listener);
+            anim.addPauseListener(listener);
         }
-        // TODO: Maybe extract a method into Transition to run an animation that handles the
-        // duration/startDelay stuff for all subclasses.
         return anim;
     }
 
     @Override
     protected void captureValues(TransitionValues values, boolean start) {
         super.captureValues(values, start);
+        float alpha = values.view.getAlpha();
+        values.values.put(PROPNAME_ALPHA, alpha);
         int[] loc = new int[2];
         values.view.getLocationOnScreen(loc);
         values.values.put(PROPNAME_SCREEN_X, loc[0]);
@@ -95,6 +105,23 @@
     }
 
     @Override
+    protected Animator play(ViewGroup sceneRoot, TransitionValues startValues,
+            TransitionValues endValues) {
+        Animator animator = super.play(sceneRoot, startValues, endValues);
+        if (animator == null && startValues != null && endValues != null) {
+            boolean endVisible = isVisible(endValues);
+            final View endView = endValues.view;
+            float endAlpha = endView.getAlpha();
+            float startAlpha = (Float) startValues.values.get(PROPNAME_ALPHA);
+            if ((endVisible && startAlpha < endAlpha && (mFadingMode & Fade.IN) != 0) ||
+                    (!endVisible && startAlpha > endAlpha && (mFadingMode & Fade.OUT) != 0)) {
+                animator = createAnimation(endView, startAlpha, endAlpha, null);
+            }
+        }
+        return animator;
+    }
+
+    @Override
     protected Animator appear(ViewGroup sceneRoot,
             TransitionValues startValues, int startVisibility,
             TransitionValues endValues, int endVisibility) {
@@ -102,15 +129,11 @@
             return null;
         }
         final View endView = endValues.view;
-        endView.setAlpha(0);
-        final Animator.AnimatorListener endListener = new AnimatorListenerAdapter() {
-            @Override
-            public void onAnimationEnd(Animator animation) {
-                // Always end animation with full alpha, in case it's canceled mid-stream
-                endView.setAlpha(1);
-            }
-        };
-        return runAnimation(endView, 0, 1, endListener);
+        // if alpha < 1, just fade it in from the current value
+        if (endView.getAlpha() == 1.0f) {
+            endView.setAlpha(0);
+        }
+        return createAnimation(endView, endView.getAlpha(), 1, null);
     }
 
     @Override
@@ -129,7 +152,7 @@
         }
         View overlayView = null;
         View viewToKeep = null;
-        if (endView == null) {
+        if (endView == null || endView.getParent() == null) {
             // view was removed: add the start view to the Overlay
             view = startView;
             overlayView = view;
@@ -167,7 +190,7 @@
             final View finalOverlayView = overlayView;
             final View finalViewToKeep = viewToKeep;
             final ViewGroup finalSceneRoot = sceneRoot;
-            final Animator.AnimatorListener endListener = new AnimatorListenerAdapter() {
+            final AnimatorListenerAdapter endListener = new AnimatorListenerAdapter() {
                 @Override
                 public void onAnimationEnd(Animator animation) {
                     finalView.setAlpha(startAlpha);
@@ -179,8 +202,22 @@
                         finalSceneRoot.getOverlay().remove(finalOverlayView);
                     }
                 }
+
+                @Override
+                public void onAnimationPause(Animator animation) {
+                    if (finalOverlayView != null) {
+                        finalSceneRoot.getOverlay().remove(finalOverlayView);
+                    }
+                }
+
+                @Override
+                public void onAnimationResume(Animator animation) {
+                    if (finalOverlayView != null) {
+                        finalSceneRoot.getOverlay().add(finalOverlayView);
+                    }
+                }
             };
-            return runAnimation(view, startAlpha, endAlpha, endListener);
+            return createAnimation(view, startAlpha, endAlpha, endListener);
         }
         if (viewToKeep != null) {
             // TODO: find a different way to do this, like just changing the view to be
@@ -193,12 +230,42 @@
             final View finalOverlayView = overlayView;
             final View finalViewToKeep = viewToKeep;
             final ViewGroup finalSceneRoot = sceneRoot;
-            final Animator.AnimatorListener endListener = new AnimatorListenerAdapter() {
+            final AnimatorListenerAdapter endListener = new AnimatorListenerAdapter() {
+                boolean mCanceled = false;
+                float mPausedAlpha = -1;
+
+                @Override
+                public void onAnimationPause(Animator animation) {
+                    if (finalViewToKeep != null && !mCanceled) {
+                        finalViewToKeep.setVisibility(finalVisibility);
+                    }
+                    mPausedAlpha = finalView.getAlpha();
+                    finalView.setAlpha(startAlpha);
+                }
+
+                @Override
+                public void onAnimationResume(Animator animation) {
+                    if (finalViewToKeep != null && !mCanceled) {
+                        finalViewToKeep.setVisibility(View.VISIBLE);
+                    }
+                    finalView.setAlpha(mPausedAlpha);
+                }
+
+                @Override
+                public void onAnimationCancel(Animator animation) {
+                    mCanceled = true;
+                    if (mPausedAlpha >= 0) {
+                        finalView.setAlpha(mPausedAlpha);
+                    }
+                }
+
                 @Override
                 public void onAnimationEnd(Animator animation) {
-                    finalView.setAlpha(startAlpha);
+                    if (!mCanceled) {
+                        finalView.setAlpha(startAlpha);
+                    }
                     // TODO: restore view offset from overlay repositioning
-                    if (finalViewToKeep != null) {
+                    if (finalViewToKeep != null && !mCanceled) {
                         finalViewToKeep.setVisibility(finalVisibility);
                     }
                     if (finalOverlayView != null) {
@@ -206,7 +273,7 @@
                     }
                 }
             };
-            return runAnimation(view, startAlpha, endAlpha, endListener);
+            return createAnimation(view, startAlpha, endAlpha, endListener);
         }
         return null;
     }
diff --git a/core/java/android/view/transition/Move.java b/core/java/android/view/transition/Move.java
index ceda5a5..ae7d759 100644
--- a/core/java/android/view/transition/Move.java
+++ b/core/java/android/view/transition/Move.java
@@ -25,8 +25,6 @@
 import android.graphics.Canvas;
 import android.graphics.Rect;
 import android.graphics.drawable.BitmapDrawable;
-import android.util.ArrayMap;
-import android.util.Log;
 import android.view.View;
 import android.view.ViewGroup;
 
@@ -42,6 +40,13 @@
     private static final String PROPNAME_PARENT = "android:move:parent";
     private static final String PROPNAME_WINDOW_X = "android:move:windowX";
     private static final String PROPNAME_WINDOW_Y = "android:move:windowY";
+    private static String[] sTransitionProperties = {
+            PROPNAME_BOUNDS,
+            PROPNAME_PARENT,
+            PROPNAME_WINDOW_X,
+            PROPNAME_WINDOW_Y
+    };
+
     int[] tempLocation = new int[2];
     boolean mResizeClip = false;
     boolean mReparent = false;
@@ -49,6 +54,11 @@
 
     private static RectEvaluator sRectEvaluator = new RectEvaluator();
 
+    @Override
+    public String[] getTransitionProperties() {
+        return sTransitionProperties;
+    }
+
     public void setResizeClip(boolean resizeClip) {
         mResizeClip = resizeClip;
     }
@@ -146,12 +156,33 @@
                     if (view.getParent() instanceof ViewGroup) {
                         final ViewGroup parent = (ViewGroup) view.getParent();
                         parent.suppressLayout(true);
-                        anim.addListener(new AnimatorListenerAdapter() {
+                        TransitionListener transitionListener = new TransitionListenerAdapter() {
+                            boolean mCanceled = false;
+
                             @Override
-                            public void onAnimationEnd(Animator animation) {
+                            public void onTransitionCancel(Transition transition) {
+                                parent.suppressLayout(false);
+                                mCanceled = true;
+                            }
+
+                            @Override
+                            public void onTransitionEnd(Transition transition) {
+                                if (!mCanceled) {
+                                    parent.suppressLayout(false);
+                                }
+                            }
+
+                            @Override
+                            public void onTransitionPause(Transition transition) {
                                 parent.suppressLayout(false);
                             }
-                        });
+
+                            @Override
+                            public void onTransitionResume(Transition transition) {
+                                parent.suppressLayout(true);
+                            }
+                        };
+                        addListener(transitionListener);
                     }
                     return anim;
                 } else {
@@ -191,12 +222,33 @@
                     if (view.getParent() instanceof ViewGroup) {
                         final ViewGroup parent = (ViewGroup) view.getParent();
                         parent.suppressLayout(true);
-                        anim.addListener(new AnimatorListenerAdapter() {
+                        TransitionListener transitionListener = new TransitionListenerAdapter() {
+                            boolean mCanceled = false;
+
                             @Override
-                            public void onAnimationEnd(Animator animation) {
+                            public void onTransitionCancel(Transition transition) {
+                                parent.suppressLayout(false);
+                                mCanceled = true;
+                            }
+
+                            @Override
+                            public void onTransitionEnd(Transition transition) {
+                                if (!mCanceled) {
+                                    parent.suppressLayout(false);
+                                }
+                            }
+
+                            @Override
+                            public void onTransitionPause(Transition transition) {
                                 parent.suppressLayout(false);
                             }
-                        });
+
+                            @Override
+                            public void onTransitionResume(Transition transition) {
+                                parent.suppressLayout(true);
+                            }
+                        };
+                        addListener(transitionListener);
                     }
                     anim.addListener(new AnimatorListenerAdapter() {
                         @Override
diff --git a/core/java/android/view/transition/Transition.java b/core/java/android/view/transition/Transition.java
index f99ddc0..0444843 100644
--- a/core/java/android/view/transition/Transition.java
+++ b/core/java/android/view/transition/Transition.java
@@ -22,7 +22,6 @@
 import android.util.ArrayMap;
 import android.util.Log;
 import android.util.LongSparseArray;
-import android.util.Pair;
 import android.util.SparseArray;
 import android.view.SurfaceView;
 import android.view.TextureView;
@@ -60,6 +59,8 @@
     private static final String LOG_TAG = "Transition";
     static final boolean DBG = false;
 
+    private String mName = getClass().getName();
+
     long mStartDelay = -1;
     long mDuration = -1;
     TimeInterpolator mInterpolator = null;
@@ -69,29 +70,29 @@
     private TransitionValuesMaps mEndValues = new TransitionValuesMaps();
     TransitionGroup mParent = null;
 
+    // Per-animator information used for later canceling when future transitions overlap
+    private static ThreadLocal<ArrayMap<Animator, AnimationInfo>> sRunningAnimators =
+            new ThreadLocal<ArrayMap<Animator, AnimationInfo>>();
+
     // Scene Root is set at play() time in the cloned Transition
     ViewGroup mSceneRoot = null;
 
-    // Used to carry data between setup() and play(), cleared before every scene transition
-    private ArrayList<TransitionValues> mPlayStartValuesList = new ArrayList<TransitionValues>();
-    private ArrayList<TransitionValues> mPlayEndValuesList = new ArrayList<TransitionValues>();
-
     // Track all animators in use in case the transition gets canceled and needs to
     // cancel running animators
     private ArrayList<Animator> mCurrentAnimators = new ArrayList<Animator>();
 
     // Number of per-target instances of this Transition currently running. This count is
-    // determined by calls to startTransition() and endTransition()
+    // determined by calls to start() and end()
     int mNumInstances = 0;
 
-
+    // Whether this transition is currently paused, due to a call to pause()
+    boolean mPaused = false;
 
     // The set of listeners to be sent transition lifecycle events.
     ArrayList<TransitionListener> mListeners = null;
 
     // The set of animators collected from calls to play(), to be run in runAnimations()
-    ArrayMap<Pair<TransitionValues, TransitionValues>, Animator> mAnimatorMap =
-            new ArrayMap<Pair<TransitionValues, TransitionValues>, Animator>();
+    ArrayList<Animator> mAnimators = new ArrayList<Animator>();
 
     /**
      * Constructs a Transition object with no target objects. A transition with
@@ -115,6 +116,14 @@
         return this;
     }
 
+    /**
+     * Returns the duration set on this transition. If no duration has been set,
+     * the returned value will be negative, indicating that resulting animators will
+     * retain their own durations.
+     *
+     * @return The duration set on this transition, if one has been set, otherwise
+     * returns a negative number.
+     */
     public long getDuration() {
         return mDuration;
     }
@@ -131,6 +140,14 @@
         mStartDelay = startDelay;
     }
 
+    /**
+     * Returns the startDelay set on this transition. If no startDelay has been set,
+     * the returned value will be negative, indicating that resulting animators will
+     * retain their own startDelays.
+     *
+     * @return The startDealy set on this transition, if one has been set, otherwise
+     * returns a negative number.
+     */
     public long getStartDelay() {
         return mStartDelay;
     }
@@ -147,11 +164,44 @@
         mInterpolator = interpolator;
     }
 
+    /**
+     * Returns the interpolator set on this transition. If no interpolator has been set,
+     * the returned value will be null, indicating that resulting animators will
+     * retain their own interpolators.
+     *
+     * @return The interpolator set on this transition, if one has been set, otherwise
+     * returns null.
+     */
     public TimeInterpolator getInterpolator() {
         return mInterpolator;
     }
 
     /**
+     * Returns the set of property names used stored in the {@link TransitionValues}
+     * object passed into {@link #captureValues(TransitionValues, boolean)} that
+     * this transition cares about for the purposes of canceling overlapping animations.
+     * When any transition is started on a given scene root, all transitions
+     * currently running on that same scene root are checked to see whether the
+     * properties on which they based their animations agree with the end values of
+     * the same properties in the new transition. If the end values are not equal,
+     * then the old animation is canceled since the new transition will start a new
+     * animation to these new values. If the values are equal, the old animation is
+     * allowed to continue and no new animation is started for that transition.
+     *
+     * <p>A transition does not need to override this method. However, not doing so
+     * will mean that the cancellation logic outlined in the previous paragraph
+     * will be skipped for that transition, possibly leading to artifacts as
+     * old transitions and new transitions on the same targets run in parallel,
+     * animating views toward potentially different end values.</p>
+     *
+     * @return An array of property names as described in the class documentation for
+     * {@link TransitionValues}. The default implementation returns <code>null</code>.
+     */
+    public String[] getTransitionProperties() {
+        return null;
+    }
+
+    /**
      * This method is called by the transition's parent (all the way up to the
      * topmost Transition in the hierarchy) with the sceneRoot and start/end
      * values that the transition may need to set up initial target values
@@ -210,8 +260,6 @@
         if (DBG) {
             Log.d(LOG_TAG, "play() for " + this);
         }
-        mPlayStartValuesList.clear();
-        mPlayEndValuesList.clear();
         ArrayMap<View, TransitionValues> endCopy =
                 new ArrayMap<View, TransitionValues>(endValues.viewValues);
         SparseArray<TransitionValues> endIdCopy =
@@ -316,6 +364,7 @@
             startValuesList.add(start);
             endValuesList.add(end);
         }
+        ArrayMap<Animator, AnimationInfo> runningAnimators = getRunningAnimators();
         for (int i = 0; i < startValuesList.size(); ++i) {
             TransitionValues start = startValuesList.get(i);
             TransitionValues end = endValuesList.get(i);
@@ -345,14 +394,46 @@
                     // TODO: what to do about targetIds and itemIds?
                     Animator animator = play(sceneRoot, start, end);
                     if (animator != null) {
-                        mAnimatorMap.put(new Pair(start, end), animator);
-                        // Note: we've already done the check against targetIDs in these lists
-                        mPlayStartValuesList.add(start);
-                        mPlayEndValuesList.add(end);
+                        // Save animation info for future cancellation purposes
+                        View view = null;
+                        TransitionValues infoValues = null;
+                        if (end != null) {
+                            view = end.view;
+                            String[] properties = getTransitionProperties();
+                            if (view != null && properties != null && properties.length > 0) {
+                                infoValues = new TransitionValues();
+                                infoValues.view = view;
+                                TransitionValues newValues = endValues.viewValues.get(view);
+                                if (newValues != null) {
+                                    for (int j = 0; j < properties.length; ++j) {
+                                        infoValues.values.put(properties[j],
+                                                newValues.values.get(properties[j]));
+                                    }
+                                }
+                                int numExistingAnims = runningAnimators.size();
+                                for (int j = 0; j < numExistingAnims; ++j) {
+                                    Animator anim = runningAnimators.keyAt(j);
+                                    AnimationInfo info = runningAnimators.get(anim);
+                                    if (info.values != null && info.view == view &&
+                                            ((info.name == null && getName() == null) ||
+                                            info.name.equals(getName()))) {
+                                        if (info.values.equals(infoValues)) {
+                                            // Favor the old animator
+                                            animator = null;
+                                            break;
+                                        }
+                                    }
+                                }
+                            }
+                        } else {
+                            view = (start != null) ? start.view : null;
+                        }
+                        if (animator != null) {
+                            AnimationInfo info = new AnimationInfo(view, getName(), infoValues);
+                            runningAnimators.put(animator, info);
+                            mAnimators.add(animator);
+                        }
                     }
-                } else if (DBG) {
-                    View view = (end != null) ? end.view : start.view;
-                    Log.d(LOG_TAG, "  No change for view " + view);
                 }
             }
         }
@@ -389,6 +470,15 @@
         return false;
     }
 
+    private static ArrayMap<Animator, AnimationInfo> getRunningAnimators() {
+        ArrayMap<Animator, AnimationInfo> runningAnimators = sRunningAnimators.get();
+        if (runningAnimators == null) {
+            runningAnimators = new ArrayMap<Animator, AnimationInfo>();
+            sRunningAnimators.set(runningAnimators);
+        }
+        return runningAnimators;
+    }
+
     /**
      * This is called internally once all animations have been set up by the
      * transition hierarchy. \
@@ -396,28 +486,27 @@
      * @hide
      */
     protected void runAnimations() {
-        if (DBG && mPlayStartValuesList.size() > 0) {
-            Log.d(LOG_TAG, "runAnimations (" + mPlayStartValuesList.size() + ") on " + this);
+        if (DBG) {
+            Log.d(LOG_TAG, "runAnimations() on " + this);
         }
-        startTransition();
-        // Now walk the list of TransitionValues, calling play for each pair
-        for (int i = 0; i < mPlayStartValuesList.size(); ++i) {
-            TransitionValues start = mPlayStartValuesList.get(i);
-            TransitionValues end = mPlayEndValuesList.get(i);
-            Animator anim = mAnimatorMap.get(new Pair(start, end));
+        start();
+        ArrayMap<Animator, AnimationInfo> runningAnimators = getRunningAnimators();
+        // Now start every Animator that was previously created for this transition in play()
+        for (Animator anim : mAnimators) {
             if (DBG) {
                 Log.d(LOG_TAG, "  anim: " + anim);
             }
-            startTransition();
-            runAnimator(anim);
+            if (runningAnimators.containsKey(anim)) {
+                start();
+                runAnimator(anim, runningAnimators);
+            }
         }
-        mPlayStartValuesList.clear();
-        mPlayEndValuesList.clear();
-        mAnimatorMap.clear();
-        endTransition();
+        mAnimators.clear();
+        end();
     }
 
-    private void runAnimator(Animator animator) {
+    private void runAnimator(Animator animator,
+            final ArrayMap<Animator, AnimationInfo> runningAnimators) {
         if (animator != null) {
             // TODO: could be a single listener instance for all of them since it uses the param
             animator.addListener(new AnimatorListenerAdapter() {
@@ -427,6 +516,7 @@
                 }
                 @Override
                 public void onAnimationEnd(Animator animation) {
+                    runningAnimators.remove(animation);
                     mCurrentAnimators.remove(animation);
                 }
             });
@@ -691,11 +781,112 @@
     }
 
     /**
+     * Pauses this transition, sending out calls to {@link
+     * TransitionListener#onTransitionPause(Transition)} to all listeners
+     * and pausing all running animators started by this transition.
+     *
+     * @hide
+     */
+    public void pause() {
+        ArrayMap<Animator, AnimationInfo> runningAnimators = getRunningAnimators();
+        int numOldAnims = runningAnimators.size();
+        for (int i = numOldAnims - 1; i >= 0; i--) {
+            Animator anim = runningAnimators.keyAt(i);
+            anim.pause();
+        }
+        if (mListeners != null && mListeners.size() > 0) {
+            ArrayList<TransitionListener> tmpListeners =
+                    (ArrayList<TransitionListener>) mListeners.clone();
+            int numListeners = tmpListeners.size();
+            for (int i = 0; i < numListeners; ++i) {
+                tmpListeners.get(i).onTransitionPause(this);
+            }
+        }
+        mPaused = true;
+    }
+
+    /**
+     * Resumes this transition, sending out calls to {@link
+     * TransitionListener#onTransitionPause(Transition)} to all listeners
+     * and pausing all running animators started by this transition.
+     *
+     * @hide
+     */
+    public void resume() {
+        if (mPaused) {
+            ArrayMap<Animator, AnimationInfo> runningAnimators = getRunningAnimators();
+            int numOldAnims = runningAnimators.size();
+            for (int i = numOldAnims - 1; i >= 0; i--) {
+                Animator anim = runningAnimators.keyAt(i);
+                anim.resume();
+            }
+            if (mListeners != null && mListeners.size() > 0) {
+                ArrayList<TransitionListener> tmpListeners =
+                        (ArrayList<TransitionListener>) mListeners.clone();
+                int numListeners = tmpListeners.size();
+                for (int i = 0; i < numListeners; ++i) {
+                    tmpListeners.get(i).onTransitionResume(this);
+                }
+            }
+            mPaused = false;
+        }
+    }
+
+    /**
      * Called by TransitionManager to play the transition. This calls
      * play() to set things up and create all of the animations and then
      * runAnimations() to actually start the animations.
      */
     void playTransition(ViewGroup sceneRoot) {
+        ArrayMap<Animator, AnimationInfo> runningAnimators = getRunningAnimators();
+        int numOldAnims = runningAnimators.size();
+        for (int i = numOldAnims - 1; i >= 0; i--) {
+            Animator anim = runningAnimators.keyAt(i);
+            if (anim != null) {
+                anim.resume();
+                AnimationInfo oldInfo = runningAnimators.get(anim);
+                if (oldInfo != null) {
+                    boolean cancel = false;
+                    TransitionValues oldValues = oldInfo.values;
+                    View oldView = oldInfo.view;
+                    TransitionValues newValues = mEndValues.viewValues != null ?
+                            mEndValues.viewValues.get(oldView) : null;
+                    if (oldValues == null || newValues == null) {
+                        if (oldValues != null || newValues != null) {
+                            cancel = true;
+                        }
+                    } else {
+                        for (String key : oldValues.values.keySet()) {
+                            Object oldValue = oldValues.values.get(key);
+                            Object newValue = newValues.values.get(key);
+                            if ((oldValue == null && newValue != null) ||
+                                    (oldValue != null && !oldValue.equals(newValue))) {
+                                cancel = true;
+                                if (DBG) {
+                                    Log.d(LOG_TAG, "Transition.play: oldValue != newValue for " +
+                                            key + ": old, new = " + oldValue + ", " + newValue);
+                                }
+                                break;
+                            }
+                        }
+                    }
+                    if (cancel) {
+                        if (anim.isRunning() || anim.isStarted()) {
+                            if (DBG) {
+                                Log.d(LOG_TAG, "Canceling anim " + anim);
+                            }
+                            anim.cancel();
+                        } else {
+                            if (DBG) {
+                                Log.d(LOG_TAG, "removing anim from info list: " + anim);
+                            }
+                            runningAnimators.remove(anim);
+                        }
+                    }
+                }
+            }
+        }
+
         // setup() must be called on entire transition hierarchy and set of views
         // before calling play() on anything; every transition needs a chance to set up
         // target views appropriately before transitions begin running
@@ -707,7 +898,7 @@
      * This is a utility method used by subclasses to handle standard parts of
      * setting up and running an Animator: it sets the {@link #getDuration()
      * duration} and the {@link #getStartDelay() startDelay}, starts the
-     * animation, and, when the animator ends, calls {@link #endTransition()}.
+     * animation, and, when the animator ends, calls {@link #end()}.
      *
      * @param animator The Animator to be run during this transition.
      *
@@ -716,7 +907,7 @@
     protected void animate(Animator animator) {
         // TODO: maybe pass auto-end as a boolean parameter?
         if (animator == null) {
-            endTransition();
+            end();
         } else {
             if (getDuration() >= 0) {
                 animator.setDuration(getDuration());
@@ -730,7 +921,7 @@
             animator.addListener(new AnimatorListenerAdapter() {
                 @Override
                 public void onAnimationEnd(Animator animation) {
-                    endTransition();
+                    end();
                     animation.removeListener(this);
                 }
             });
@@ -739,39 +930,14 @@
     }
 
     /**
-     * Subclasses may override to receive notice of when the transition starts.
-     * This is equivalent to listening for the
-     * {@link TransitionListener#onTransitionStart(Transition)} callback.
-     */
-    protected void onTransitionStart() {
-    }
-
-    /**
-     * Subclasses may override to receive notice of when the transition is
-     * canceled. This is equivalent to listening for the
-     * {@link TransitionListener#onTransitionCancel(Transition)} callback.
-     */
-    protected void onTransitionCancel() {
-    }
-
-    /**
-     * Subclasses may override to receive notice of when the transition ends.
-     * This is equivalent to listening for the
-     * {@link TransitionListener#onTransitionEnd(Transition)} callback.
-     */
-    protected void onTransitionEnd() {
-    }
-
-    /**
      * This method is called automatically by the transition and
      * TransitionGroup classes prior to a Transition subclass starting;
      * subclasses should not need to call it directly.
      *
      * @hide
      */
-    protected void startTransition() {
+    protected void start() {
         if (mNumInstances == 0) {
-            onTransitionStart();
             if (mListeners != null && mListeners.size() > 0) {
                 ArrayList<TransitionListener> tmpListeners =
                         (ArrayList<TransitionListener>) mListeners.clone();
@@ -790,15 +956,14 @@
      * a transition did nothing (returned a null Animator from
      * {@link Transition#play(ViewGroup, TransitionValues,
      * TransitionValues)}) or because the transition returned a valid
-     * Animator and endTransition() was called in the onAnimationEnd()
+     * Animator and end() was called in the onAnimationEnd()
      * callback of the AnimatorListener.
      *
      * @hide
      */
-    protected void endTransition() {
+    protected void end() {
         --mNumInstances;
         if (mNumInstances == 0) {
-            onTransitionEnd();
             if (mListeners != null && mListeners.size() > 0) {
                 ArrayList<TransitionListener> tmpListeners =
                         (ArrayList<TransitionListener>) mListeners.clone();
@@ -828,7 +993,7 @@
      * This method cancels a transition that is currently running.
      * Implementation TBD.
      */
-    protected void cancelTransition() {
+    protected void cancel() {
         // TODO: how does this work with instances?
         // TODO: this doesn't actually do *anything* yet
         int numAnimators = mCurrentAnimators.size();
@@ -836,7 +1001,6 @@
             Animator animator = mCurrentAnimators.get(i);
             animator.cancel();
         }
-        onTransitionCancel();
         if (mListeners != null && mListeners.size() > 0) {
             ArrayList<TransitionListener> tmpListeners =
                     (ArrayList<TransitionListener>) mListeners.clone();
@@ -901,11 +1065,28 @@
         Transition clone = null;
         try {
             clone = (Transition) super.clone();
+            clone.mAnimators = new ArrayList<Animator>();
         } catch (CloneNotSupportedException e) {}
 
         return clone;
     }
 
+    /**
+     * Returns the name of this Transition. This name is used internally to distinguish
+     * between different transitions to determine when interrupting transitions overlap.
+     * For example, a Move running on the same target view as another Move should determine
+     * whether the old transition is animating to different end values and should be
+     * canceled in favor of the new transition.
+     *
+     * <p>By default, a Transition's name is simply the value of {@link Class#getName()},
+     * but subclasses are free to override and return something different.</p>
+     *
+     * @return The name of this transition.
+     */
+    public String getName() {
+        return mName;
+    }
+
     String toString(String indent) {
         String result = indent + getClass().getSimpleName() + "@" +
                 Integer.toHexString(hashCode()) + ": ";
@@ -943,8 +1124,7 @@
 
     /**
      * A transition listener receives notifications from a transition.
-     * Notifications indicate transition lifecycle events: when the transition
-     * begins, ends, or is canceled.
+     * Notifications indicate transition lifecycle events.
      */
     public static interface TransitionListener {
         /**
@@ -957,7 +1137,7 @@
         /**
          * Notification about the end of the transition. Canceled transitions
          * will always notify listeners of both the cancellation and end
-         * events. That is, {@link #onTransitionEnd()} is always called,
+         * events. That is, {@link #onTransitionEnd(Transition)} is always called,
          * regardless of whether the transition was canceled or played
          * through to completion.
          *
@@ -967,10 +1147,38 @@
 
         /**
          * Notification about the cancellation of the transition.
+         * Note that cancel() may be called by a parent {@link TransitionGroup} on
+         * a child transition which has not yet started. This allows the child
+         * transition to restore state on target objects which was set at
+         * {@link #play(android.view.ViewGroup, TransitionValues, TransitionValues)
+         * play()} time.
          *
          * @param transition The transition which was canceled.
          */
         void onTransitionCancel(Transition transition);
+
+        /**
+         * Notification when a transition is paused.
+         * Note that play() may be called by a parent {@link TransitionGroup} on
+         * a child transition which has not yet started. This allows the child
+         * transition to restore state on target objects which was set at
+         * {@link #play(android.view.ViewGroup, TransitionValues, TransitionValues)
+         * play()} time.
+         *
+         * @param transition The transition which was paused.
+         */
+        void onTransitionPause(Transition transition);
+
+        /**
+         * Notification when a transition is resumed.
+         * Note that resume() may be called by a parent {@link TransitionGroup} on
+         * a child transition which has not yet started. This allows the child
+         * transition to restore state which may have changed in an earlier call
+         * to {@link #onTransitionPause(Transition)}.
+         *
+         * @param transition The transition which was resumed.
+         */
+        void onTransitionResume(Transition transition);
     }
 
     /**
@@ -991,6 +1199,32 @@
         @Override
         public void onTransitionCancel(Transition transition) {
         }
+
+        @Override
+        public void onTransitionPause(Transition transition) {
+        }
+
+        @Override
+        public void onTransitionResume(Transition transition) {
+        }
     }
 
+    /**
+     * Holds information about each animator used when a new transition starts
+     * while other transitions are still running to determine whether a running
+     * animation should be canceled or a new animation noop'd. The structure holds
+     * information about the state that an animation is going to, to be compared to
+     * end state of a new animation.
+     */
+    private static class AnimationInfo {
+        View view;
+        String name;
+        TransitionValues values;
+
+        AnimationInfo(View view, String name, TransitionValues values) {
+            this.view = view;
+            this.name = name;
+            this.values = values;
+        }
+    }
 }
diff --git a/core/java/android/view/transition/TransitionGroup.java b/core/java/android/view/transition/TransitionGroup.java
index 313e33e..b3bacde 100644
--- a/core/java/android/view/transition/TransitionGroup.java
+++ b/core/java/android/view/transition/TransitionGroup.java
@@ -164,7 +164,7 @@
         @Override
         public void onTransitionStart(Transition transition) {
             if (!mTransitionGroup.mStarted) {
-                mTransitionGroup.startTransition();
+                mTransitionGroup.start();
                 mTransitionGroup.mStarted = true;
             }
         }
@@ -175,7 +175,7 @@
             if (mTransitionGroup.mCurrentListeners == 0) {
                 // All child trans
                 mTransitionGroup.mStarted = false;
-                mTransitionGroup.endTransition();
+                mTransitionGroup.end();
             }
             transition.removeListener(this);
         }
@@ -233,12 +233,32 @@
         }
     }
 
+    /** @hide */
     @Override
-    protected void cancelTransition() {
-        super.cancelTransition();
+    public void pause() {
+        super.pause();
         int numTransitions = mTransitions.size();
         for (int i = 0; i < numTransitions; ++i) {
-            mTransitions.get(i).cancelTransition();
+            mTransitions.get(i).pause();
+        }
+    }
+
+    /** @hide */
+    @Override
+    public void resume() {
+        super.resume();
+        int numTransitions = mTransitions.size();
+        for (int i = 0; i < numTransitions; ++i) {
+            mTransitions.get(i).resume();
+        }
+    }
+
+    @Override
+    protected void cancel() {
+        super.cancel();
+        int numTransitions = mTransitions.size();
+        for (int i = 0; i < numTransitions; ++i) {
+            mTransitions.get(i).cancel();
         }
     }
 
diff --git a/core/java/android/view/transition/TransitionManager.java b/core/java/android/view/transition/TransitionManager.java
index 7836268..3cb6f68 100644
--- a/core/java/android/view/transition/TransitionManager.java
+++ b/core/java/android/view/transition/TransitionManager.java
@@ -18,6 +18,7 @@
 
 import android.util.ArrayMap;
 import android.util.Log;
+import android.view.View;
 import android.view.ViewGroup;
 import android.view.ViewTreeObserver;
 
@@ -45,8 +46,8 @@
     ArrayMap<Scene, Transition> mSceneTransitions = new ArrayMap<Scene, Transition>();
     ArrayMap<Scene, ArrayMap<Scene, Transition>> mScenePairTransitions =
             new ArrayMap<Scene, ArrayMap<Scene, Transition>>();
-    static ArrayMap<ViewGroup, Transition> sRunningTransitions =
-            new ArrayMap<ViewGroup, Transition>();
+    private static ThreadLocal<ArrayMap<ViewGroup, ArrayList<Transition>>> sRunningTransitions =
+            new ThreadLocal<ArrayMap<ViewGroup, ArrayList<Transition>>>();
     private static ArrayList<ViewGroup> sPendingTransitions = new ArrayList<ViewGroup>();
 
 
@@ -160,6 +161,16 @@
         sceneChangeRunTransition(sceneRoot, transitionClone);
     }
 
+    private static ArrayMap<ViewGroup, ArrayList<Transition>> getRunningTransitions() {
+        ArrayMap<ViewGroup, ArrayList<Transition>> runningTransitions =
+                sRunningTransitions.get();
+        if (runningTransitions == null) {
+            runningTransitions = new ArrayMap<ViewGroup, ArrayList<Transition>>();
+            sRunningTransitions.set(runningTransitions);
+        }
+        return runningTransitions;
+    }
+
     private static void sceneChangeRunTransition(final ViewGroup sceneRoot,
             final Transition transition) {
         if (transition != null) {
@@ -169,16 +180,31 @@
                     sceneRoot.getViewTreeObserver().removeOnPreDrawListener(this);
                     sPendingTransitions.remove(sceneRoot);
                     // Add to running list, handle end to remove it
-                    sRunningTransitions.put(sceneRoot, transition);
+                    final ArrayMap<ViewGroup, ArrayList<Transition>> runningTransitions =
+                            getRunningTransitions();
+                    ArrayList<Transition> currentTransitions = runningTransitions.get(sceneRoot);
+                    if (currentTransitions == null) {
+                        currentTransitions = new ArrayList<Transition>();
+                        runningTransitions.put(sceneRoot, currentTransitions);
+                    }
+                    currentTransitions.add(transition);
                     transition.addListener(new Transition.TransitionListenerAdapter() {
                         @Override
                         public void onTransitionEnd(Transition transition) {
-                            sRunningTransitions.remove(sceneRoot);
+                            ArrayList<Transition> currentTransitions =
+                                    runningTransitions.get(sceneRoot);
+                            currentTransitions.remove(transition);
                         }
                     });
                     transition.captureValues(sceneRoot, false);
                     transition.playTransition(sceneRoot);
-                    return true;
+
+                    // Returning false from onPreDraw() skips the current frame. This is
+                    // necessary to avoid artifacts caused by resetting target views
+                    // to their proper end states for capturing. Waiting until the next
+                    // frame to draw allows these views to have their mid-transition
+                    // values set on them again and avoid artifacts.
+                    return false;
                 }
             });
         }
@@ -187,16 +213,18 @@
     private static void sceneChangeSetup(ViewGroup sceneRoot, Transition transition) {
 
         // Capture current values
-        Transition runningTransition = sRunningTransitions.get(sceneRoot);
+        ArrayList<Transition> runningTransitions = getRunningTransitions().get(sceneRoot);
+
+        if (runningTransitions != null && runningTransitions.size() > 0) {
+            for (Transition runningTransition : runningTransitions) {
+                runningTransition.pause();
+            }
+        }
 
         if (transition != null) {
             transition.captureValues(sceneRoot, true);
         }
 
-        if (runningTransition != null) {
-            runningTransition.cancelTransition();
-        }
-
         // Notify previous scene that it is being exited
         Scene previousScene = sceneRoot.getCurrentScene();
         if (previousScene != null) {
diff --git a/core/java/android/view/transition/Visibility.java b/core/java/android/view/transition/Visibility.java
index 6d39ab6..96ea044 100644
--- a/core/java/android/view/transition/Visibility.java
+++ b/core/java/android/view/transition/Visibility.java
@@ -19,6 +19,7 @@
 import android.animation.Animator;
 import android.view.View;
 import android.view.ViewGroup;
+import android.view.ViewOverlay;
 import android.view.ViewParent;
 
 /**
@@ -38,6 +39,10 @@
 
     private static final String PROPNAME_VISIBILITY = "android:visibility:visibility";
     private static final String PROPNAME_PARENT = "android:visibility:parent";
+    private static String[] sTransitionProperties = {
+            PROPNAME_VISIBILITY,
+            PROPNAME_PARENT,
+    };
 
     private static class VisibilityInfo {
         boolean visibilityChange;
@@ -52,12 +57,42 @@
     private VisibilityInfo mTmpVisibilityInfo = new VisibilityInfo();
 
     @Override
+    public String[] getTransitionProperties() {
+        return sTransitionProperties;
+    }
+
+    @Override
     protected void captureValues(TransitionValues values, boolean start) {
         int visibility = values.view.getVisibility();
         values.values.put(PROPNAME_VISIBILITY, visibility);
         values.values.put(PROPNAME_PARENT, values.view.getParent());
     }
 
+    /**
+     * Returns whether the view is 'visible' according to the given values
+     * object. This is determined by testing the same properties in the values
+     * object that are used to determine whether the object is appearing or
+     * disappearing in the {@link
+     * #play(android.view.ViewGroup, TransitionValues, TransitionValues)}
+     * method. This method can be called by, for example, subclasses that want
+     * to know whether the object is visible in the same way that Visibility
+     * determines it for the actual animation.
+     *
+     * @param values The TransitionValues object that holds the information by
+     * which visibility is determined.
+     * @return True if the view reference by <code>values</code> is visible,
+     * false otherwise.
+     */
+    public boolean isVisible(TransitionValues values) {
+        if (values == null) {
+            return false;
+        }
+        int visibility = (Integer) values.values.get(PROPNAME_VISIBILITY);
+        View parent = (View) values.values.get(PROPNAME_PARENT);
+
+        return visibility == View.VISIBLE && parent != null;
+    }
+
     private boolean isHierarchyVisibilityChanging(ViewGroup sceneRoot, ViewGroup view) {
 
         if (view == sceneRoot) {
@@ -197,5 +232,4 @@
             TransitionValues endValues, int endVisibility) {
         return null;
     }
-
 }
diff --git a/core/java/android/webkit/WebView.java b/core/java/android/webkit/WebView.java
index 0224fbe..03bde70 100644
--- a/core/java/android/webkit/WebView.java
+++ b/core/java/android/webkit/WebView.java
@@ -780,7 +780,8 @@
      * {@link #loadUrl(String)} instead.
      *
      * @param url the URL of the resource to load
-     * @param postData the data will be passed to "POST" request
+     * @param postData the data will be passed to "POST" request, which must be
+     *     be "application/x-www-form-urlencoded" encoded.
      */
     public void postUrl(String url, byte[] postData) {
         checkThread();
diff --git a/core/java/android/widget/AbsListView.java b/core/java/android/widget/AbsListView.java
index 07198c75..285e6f2 100644
--- a/core/java/android/widget/AbsListView.java
+++ b/core/java/android/widget/AbsListView.java
@@ -1211,13 +1211,19 @@
     }
 
     /**
-     * Enables fast scrolling by letting the user quickly scroll through lists by
-     * dragging the fast scroll thumb. The adapter attached to the list may want
-     * to implement {@link SectionIndexer} if it wishes to display alphabet preview and
-     * jump between sections of the list.
+     * Specifies whether fast scrolling is enabled or disabled.
+     * <p>
+     * When fast scrolling is enabled, the user can quickly scroll through lists
+     * by dragging the fast scroll thumb.
+     * <p>
+     * If the adapter backing this list implements {@link SectionIndexer}, the
+     * fast scroller will display section header previews as the user scrolls.
+     * Additionally, the user will be able to quickly jump between sections by
+     * tapping along the length of the scroll bar.
+     *
      * @see SectionIndexer
      * @see #isFastScrollEnabled()
-     * @param enabled whether or not to enable fast scrolling
+     * @param enabled true to enable fast scrolling, false otherwise
      */
     public void setFastScrollEnabled(final boolean enabled) {
         if (mFastScrollEnabled != enabled) {
@@ -1252,13 +1258,16 @@
     }
 
     /**
-     * Set whether or not the fast scroller should always be shown in place of the
-     * standard scrollbars. Fast scrollers shown in this way will not fade out and will
-     * be a permanent fixture within the list. Best combined with an inset scroll bar style
-     * that will ensure enough padding. This will enable fast scrolling if it is not
+     * Set whether or not the fast scroller should always be shown in place of
+     * the standard scroll bars. This will enable fast scrolling if it is not
      * already enabled.
+     * <p>
+     * Fast scrollers shown in this way will not fade out and will be a
+     * permanent fixture within the list. This is best combined with an inset
+     * scroll bar style to ensure the scroll bar does not overlap content.
      *
-     * @param alwaysShow true if the fast scroller should always be displayed.
+     * @param alwaysShow true if the fast scroller should always be displayed,
+     *            false otherwise
      * @see #setScrollBarStyle(int)
      * @see #setFastScrollEnabled(boolean)
      */
@@ -1297,10 +1306,9 @@
     }
 
     /**
-     * Returns true if the fast scroller is set to always show on this view rather than
-     * fade out when not in use.
+     * Returns true if the fast scroller is set to always show on this view.
      *
-     * @return true if the fast scroller will always show.
+     * @return true if the fast scroller will always show
      * @see #setFastScrollAlwaysVisible(boolean)
      */
     public boolean isFastScrollAlwaysVisible() {
@@ -1316,7 +1324,8 @@
     }
 
     /**
-     * Returns the current state of the fast scroll feature.
+     * Returns true if the fast scroller is enabled.
+     *
      * @see #setFastScrollEnabled(boolean)
      * @return true if fast scroll is enabled, false otherwise
      */
diff --git a/core/java/android/widget/ListPopupWindow.java b/core/java/android/widget/ListPopupWindow.java
index 414c318..2b4e520 100644
--- a/core/java/android/widget/ListPopupWindow.java
+++ b/core/java/android/widget/ListPopupWindow.java
@@ -16,6 +16,9 @@
 
 package android.widget;
 
+import android.animation.Animator;
+import android.animation.AnimatorListenerAdapter;
+import android.animation.ObjectAnimator;
 import android.content.Context;
 import android.database.DataSetObserver;
 import android.graphics.Rect;
@@ -23,6 +26,7 @@
 import android.os.Handler;
 import android.text.TextUtils;
 import android.util.AttributeSet;
+import android.util.IntProperty;
 import android.util.Log;
 import android.view.KeyEvent;
 import android.view.MotionEvent;
@@ -31,6 +35,7 @@
 import android.view.View.OnTouchListener;
 import android.view.ViewGroup;
 import android.view.ViewParent;
+import android.view.animation.AccelerateDecelerateInterpolator;
 
 import java.util.Locale;
 
@@ -956,6 +961,33 @@
     }
 
     /**
+     * Receives motion events forwarded from a source view. This is used
+     * internally to implement support for drag-to-open.
+     *
+     * @param src view from which the event was forwarded
+     * @param srcEvent forwarded motion event in source-local coordinates
+     * @param activePointerId id of the pointer that activated forwarding
+     * @return whether the event was handled
+     * @hide
+     */
+    public boolean onForwardedEvent(View src, MotionEvent srcEvent, int activePointerId) {
+        final DropDownListView dst = mDropDownList;
+        if (dst == null || !dst.isShown()) {
+            return false;
+        }
+
+        // Convert event to local coordinates.
+        final MotionEvent dstEvent = MotionEvent.obtainNoHistory(srcEvent);
+        src.toGlobalMotionEvent(dstEvent);
+        dst.toLocalMotionEvent(dstEvent);
+
+        // Forward converted event, then recycle it.
+        final boolean handled = dst.onForwardedEvent(dstEvent, activePointerId);
+        dstEvent.recycle();
+        return handled;
+    }
+
+    /**
      * <p>Builds the popup window's content and returns the height the popup
      * should have. Returns -1 when the content already exists.</p>
      *
@@ -1130,6 +1162,27 @@
      */
     private static class DropDownListView extends ListView {
         private static final String TAG = ListPopupWindow.TAG + ".DropDownListView";
+
+        /** Duration in milliseconds of the drag-to-open click animation. */
+        private static final long CLICK_ANIM_DURATION = 150;
+
+        /** Target alpha value for drag-to-open click animation. */
+        private static final int CLICK_ANIM_ALPHA = 0x80;
+
+        /** Wrapper around Drawable's <code>alpha</code> property. */
+        private static final IntProperty<Drawable> DRAWABLE_ALPHA =
+                new IntProperty<Drawable>("alpha") {
+                    @Override
+                    public void setValue(Drawable object, int value) {
+                        object.setAlpha(value);
+                    }
+
+                    @Override
+                    public Integer get(Drawable object) {
+                        return object.getAlpha();
+                    }
+                };
+
         /*
          * WARNING: This is a workaround for a touch mode issue.
          *
@@ -1165,6 +1218,12 @@
          */
         private boolean mHijackFocus;
 
+        /** Whether to force drawing of the pressed state selector. */
+        private boolean mDrawsInPressedState;
+
+        /** Current drag-to-open click animation, if any. */
+        private Animator mClickAnimation;
+
         /**
          * <p>Creates a new list view wrapper.</p>
          *
@@ -1178,6 +1237,119 @@
         }
 
         /**
+         * Handles forwarded events.
+         *
+         * @param activePointerId id of the pointer that activated forwarding
+         * @return whether the event was handled
+         */
+        public boolean onForwardedEvent(MotionEvent event, int activePointerId) {
+            boolean handledEvent = true;
+            boolean clearPressedItem = false;
+
+            final int actionMasked = event.getActionMasked();
+            switch (actionMasked) {
+                case MotionEvent.ACTION_CANCEL:
+                    handledEvent = false;
+                    break;
+                case MotionEvent.ACTION_UP:
+                    handledEvent = false;
+                    // $FALL-THROUGH$
+                case MotionEvent.ACTION_MOVE:
+                    final int activeIndex = event.findPointerIndex(activePointerId);
+                    if (activeIndex < 0) {
+                        handledEvent = false;
+                        break;
+                    }
+
+                    final int x = (int) event.getX(activeIndex);
+                    final int y = (int) event.getY(activeIndex);
+                    final int position = pointToPosition(x, y);
+                    if (position == INVALID_POSITION) {
+                        clearPressedItem = true;
+                        break;
+                    }
+
+                    final View child = getChildAt(position - getFirstVisiblePosition());
+                    setPressedItem(child, position);
+                    handledEvent = true;
+
+                    if (actionMasked == MotionEvent.ACTION_UP) {
+                        clickPressedItem(child, position);
+                    }
+                    break;
+            }
+
+            // Failure to handle the event cancels forwarding.
+            if (!handledEvent || clearPressedItem) {
+                clearPressedItem();
+            }
+
+            return handledEvent;
+        }
+
+        /**
+         * Starts an alpha animation on the selector. When the animation ends,
+         * the list performs a click on the item.
+         */
+        private void clickPressedItem(final View child, final int position) {
+            final long id = getItemIdAtPosition(position);
+            final Animator anim = ObjectAnimator.ofInt(
+                    mSelector, DRAWABLE_ALPHA, 0xFF, CLICK_ANIM_ALPHA, 0xFF);
+            anim.setDuration(CLICK_ANIM_DURATION);
+            anim.setInterpolator(new AccelerateDecelerateInterpolator());
+            anim.addListener(new AnimatorListenerAdapter() {
+                    @Override
+                public void onAnimationEnd(Animator animation) {
+                    performItemClick(child, position, id);
+                }
+            });
+            anim.start();
+
+            if (mClickAnimation != null) {
+                mClickAnimation.cancel();
+            }
+            mClickAnimation = anim;
+        }
+
+        private void clearPressedItem() {
+            mDrawsInPressedState = false;
+            setPressed(false);
+            updateSelectorState();
+
+            if (mClickAnimation != null) {
+                mClickAnimation.cancel();
+                mClickAnimation = null;
+            }
+        }
+
+        private void setPressedItem(View child, int position) {
+            mDrawsInPressedState = true;
+
+            // Ordering is essential. First update the pressed state and layout
+            // the children. This will ensure the selector actually gets drawn.
+            setPressed(true);
+            layoutChildren();
+
+            // Ensure that keyboard focus starts from the last touched position.
+            setSelectedPositionInt(position);
+            positionSelector(position, child);
+
+            // Refresh the drawable state to reflect the new pressed state,
+            // which will also update the selector state.
+            refreshDrawableState();
+
+            if (mClickAnimation != null) {
+                mClickAnimation.cancel();
+                mClickAnimation = null;
+            }
+        }
+
+        @Override
+        boolean touchModeDrawsInPressedState() {
+            return mDrawsInPressedState || super.touchModeDrawsInPressedState();
+        }
+
+        /**
          * <p>Avoids jarring scrolling effect by ensuring that list elements
          * made of a text view fit on a single line.</p>
          *
diff --git a/core/java/android/widget/NumberPicker.java b/core/java/android/widget/NumberPicker.java
index 4a98f66..19cc3c2 100644
--- a/core/java/android/widget/NumberPicker.java
+++ b/core/java/android/widget/NumberPicker.java
@@ -1425,6 +1425,7 @@
 
     @Override
     protected void onDetachedFromWindow() {
+        super.onDetachedFromWindow();
         removeAllCallbacks();
     }
 
diff --git a/core/java/android/widget/SectionIndexer.java b/core/java/android/widget/SectionIndexer.java
index a1c71f4..f6333d1 100644
--- a/core/java/android/widget/SectionIndexer.java
+++ b/core/java/android/widget/SectionIndexer.java
@@ -17,38 +17,62 @@
 package android.widget;
 
 /**
- * Interface that should be implemented on Adapters to enable fast scrolling 
- * in an {@link AbsListView} between sections of the list. A section is a group of list items
- * to jump to that have something in common. For example, they may begin with the
- * same letter or they may be songs from the same artist. ExpandableListAdapters that
- * consider groups and sections as synonymous should account for collapsed groups and return
- * an appropriate section/position.
+ * Interface that may implemented on {@link Adapter}s to enable fast scrolling
+ * between sections of an {@link AbsListView}.
+ * <p>
+ * A section is a group of list items that have something in common. For
+ * example, they may begin with the same letter or they may be songs from the
+ * same artist.
+ * <p>
+ * {@link ExpandableListAdapter}s that consider groups and sections as
+ * synonymous should account for collapsed groups and return an appropriate
+ * section/position.
+ *
+ * @see AbsListView#setFastScrollEnabled(boolean)
  */
 public interface SectionIndexer {
     /**
-     * This provides the list view with an array of section objects. In the simplest
-     * case these are Strings, each containing one letter of the alphabet.
-     * They could be more complex objects that indicate the grouping for the adapter's
-     * consumption. The list view will call toString() on the objects to get the
-     * preview letter to display while scrolling.
-     * @return the array of objects that indicate the different sections of the list.
+     * Returns an array of objects representing sections of the list. The
+     * returned array and its contents should be non-null.
+     * <p>
+     * The list view will call toString() on the objects to get the preview text
+     * to display while scrolling. For example, an adapter may return an array
+     * of Strings representing letters of the alphabet. Or, it may return an
+     * array of objects whose toString() methods return their section titles.
+     *
+     * @return the array of section objects
      */
     Object[] getSections();
-    
+
     /**
-     * Provides the starting index in the list for a given section.
-     * @param section the index of the section to jump to.
-     * @return the starting position of that section. If the section is out of bounds, the
-     * position must be clipped to fall within the size of the list.
+     * Given the index of a section within the array of section objects, returns
+     * the starting position of that section within the adapter.
+     * <p>
+     * If the section's starting position is outside of the adapter bounds, the
+     * position must be clipped to fall within the size of the adapter.
+     *
+     * @param sectionIndex the index of the section within the array of section
+     *            objects
+     * @return the starting position of that section within the adapter,
+     *         constrained to fall within the adapter bounds
      */
-    int getPositionForSection(int section);
-    
+    int getPositionForSection(int sectionIndex);
+
     /**
-     * This is a reverse mapping to fetch the section index for a given position
-     * in the list.
-     * @param position the position for which to return the section
-     * @return the section index. If the position is out of bounds, the section index
+     * Given a position within the adapter, returns the index of the
+     * corresponding section within the array of section objects.
+     * <p>
+     * If the section index is outside of the section array bounds, the index
      * must be clipped to fall within the size of the section array.
+     * <p>
+     * For example, consider an indexer where the section at array index 0
+     * starts at adapter position 100. Calling this method with position 10,
+     * which is before the first section, must return index 0.
+     *
+     * @param position the position within the adapter for which to return the
+     *            corresponding section index
+     * @return the index of the corresponding section within the array of
+     *         section objects, constrained to fall within the array bounds
      */
-    int getSectionForPosition(int position);    
+    int getSectionForPosition(int position);
 }
diff --git a/core/java/android/widget/TimePicker.java b/core/java/android/widget/TimePicker.java
index e33c4d4..1c1d77a 100644
--- a/core/java/android/widget/TimePicker.java
+++ b/core/java/android/widget/TimePicker.java
@@ -22,10 +22,12 @@
 import android.content.res.TypedArray;
 import android.os.Parcel;
 import android.os.Parcelable;
+import android.text.format.DateFormat;
 import android.text.format.DateUtils;
 import android.util.AttributeSet;
 import android.view.LayoutInflater;
 import android.view.View;
+import android.view.ViewGroup;
 import android.view.accessibility.AccessibilityEvent;
 import android.view.accessibility.AccessibilityNodeInfo;
 import android.view.inputmethod.EditorInfo;
@@ -105,6 +107,9 @@
 
     private Locale mCurrentLocale;
 
+    private boolean mHourWithTwoDigit;
+    private char mHourFormat;
+
     /**
      * The callback interface used to indicate the time has been adjusted.
      */
@@ -164,7 +169,7 @@
         // divider (only for the new widget style)
         mDivider = (TextView) findViewById(R.id.divider);
         if (mDivider != null) {
-            mDivider.setText(R.string.time_picker_separator);
+            setDividerText();
         }
 
         // minute
@@ -235,6 +240,24 @@
             mAmPmSpinnerInput.setImeOptions(EditorInfo.IME_ACTION_DONE);
         }
 
+        if (isAmPmAtStart()) {
+            // Move the am/pm view to the beginning
+            ViewGroup amPmParent = (ViewGroup) findViewById(R.id.timePickerLayout);
+            amPmParent.removeView(amPmView);
+            amPmParent.addView(amPmView, 0);
+            // Swap layout margins if needed. They may be not symmetrical (Old Standard Theme for
+            // example and not for Holo Theme)
+            ViewGroup.MarginLayoutParams lp = (ViewGroup.MarginLayoutParams) amPmView.getLayoutParams();
+            final int startMargin = lp.getMarginStart();
+            final int endMargin = lp.getMarginEnd();
+            if (startMargin != endMargin) {
+                lp.setMarginStart(endMargin);
+                lp.setMarginEnd(startMargin);
+            }
+        }
+
+        getHourFormatData();
+
         // update controls to initial state
         updateHourControl();
         updateMinuteControl();
@@ -259,6 +282,35 @@
         }
     }
 
+    private void getHourFormatData() {
+        final Locale defaultLocale = Locale.getDefault();
+        final String bestDateTimePattern = DateFormat.getBestDateTimePattern(defaultLocale,
+                (mIs24HourView) ? "Hm" : "hm");
+        final int lengthPattern = bestDateTimePattern.length();
+        mHourWithTwoDigit = false;
+        char hourFormat = '\0';
+        // Check if the returned pattern is single or double 'H', 'h', 'K', 'k'. We also save
+        // the hour format that we found.
+        for (int i = 0; i < lengthPattern; i++) {
+            final char c = bestDateTimePattern.charAt(i);
+            if (c == 'H' || c == 'h' || c == 'K' || c == 'k') {
+                mHourFormat = c;
+                if (i + 1 < lengthPattern && c == bestDateTimePattern.charAt(i + 1)) {
+                    mHourWithTwoDigit = true;
+                }
+                break;
+            }
+        }
+    }
+
+    private boolean isAmPmAtStart() {
+        final Locale defaultLocale = Locale.getDefault();
+        final String bestDateTimePattern = DateFormat.getBestDateTimePattern(defaultLocale,
+                "hm" /* skeleton */);
+
+        return bestDateTimePattern.startsWith("a");
+    }
+
     @Override
     public void setEnabled(boolean enabled) {
         if (mIsEnabled == enabled) {
@@ -423,9 +475,11 @@
         if (mIs24HourView == is24HourView) {
             return;
         }
-        mIs24HourView = is24HourView;
-        // cache the current hour since spinner range changes
+        // cache the current hour since spinner range changes and BEFORE changing mIs24HourView!!
         int currentHour = getCurrentHour();
+        // Order is important here.
+        mIs24HourView = is24HourView;
+        getHourFormatData();
         updateHourControl();
         // set value after spinner range is updated
         setCurrentHour(currentHour);
@@ -458,6 +512,38 @@
         onTimeChanged();
     }
 
+    /**
+     * The time separator is defined in the Unicode CLDR and cannot be supposed to be ":".
+     *
+     * See http://unicode.org/cldr/trac/browser/trunk/common/main
+     *
+     * We pass the correct "skeleton" depending on 12 or 24 hours view and then extract the
+     * separator as the character which is just after the hour marker in the returned pattern.
+     */
+    private void setDividerText() {
+        final Locale defaultLocale = Locale.getDefault();
+        final String skeleton = (mIs24HourView) ? "Hm" : "hm";
+        final String bestDateTimePattern = DateFormat.getBestDateTimePattern(defaultLocale,
+                skeleton);
+        final String separatorText;
+        int hourIndex = bestDateTimePattern.lastIndexOf('H');
+        if (hourIndex == -1) {
+            hourIndex = bestDateTimePattern.lastIndexOf('h');
+        }
+        if (hourIndex == -1) {
+            // Default case
+            separatorText = ":";
+        } else {
+            int minuteIndex = bestDateTimePattern.indexOf('m', hourIndex + 1);
+            if  (minuteIndex == -1) {
+                separatorText = Character.toString(bestDateTimePattern.charAt(hourIndex + 1));
+            } else {
+                separatorText = bestDateTimePattern.substring(hourIndex + 1, minuteIndex);
+            }
+        }
+        mDivider.setText(separatorText);
+    }
+
     @Override
     public int getBaseline() {
         return mHourSpinner.getBaseline();
@@ -500,14 +586,25 @@
 
     private void updateHourControl() {
         if (is24HourView()) {
-            mHourSpinner.setMinValue(0);
-            mHourSpinner.setMaxValue(23);
-            mHourSpinner.setFormatter(NumberPicker.getTwoDigitFormatter());
+            // 'k' means 1-24 hour
+            if (mHourFormat == 'k') {
+                mHourSpinner.setMinValue(1);
+                mHourSpinner.setMaxValue(24);
+            } else {
+                mHourSpinner.setMinValue(0);
+                mHourSpinner.setMaxValue(23);
+            }
         } else {
-            mHourSpinner.setMinValue(1);
-            mHourSpinner.setMaxValue(12);
-            mHourSpinner.setFormatter(null);
+            // 'K' means 0-11 hour
+            if (mHourFormat == 'K') {
+                mHourSpinner.setMinValue(0);
+                mHourSpinner.setMaxValue(11);
+            } else {
+                mHourSpinner.setMinValue(1);
+                mHourSpinner.setMaxValue(12);
+            }
         }
+        mHourSpinner.setFormatter(mHourWithTwoDigit ? NumberPicker.getTwoDigitFormatter() : null);
     }
 
     private void updateMinuteControl() {
diff --git a/core/java/com/android/internal/view/menu/ActionMenuPresenter.java b/core/java/com/android/internal/view/menu/ActionMenuPresenter.java
index ff9678c..863d8cc 100644
--- a/core/java/com/android/internal/view/menu/ActionMenuPresenter.java
+++ b/core/java/com/android/internal/view/menu/ActionMenuPresenter.java
@@ -30,9 +30,7 @@
 import android.view.ViewConfiguration;
 import android.view.View.MeasureSpec;
 import android.view.ViewGroup;
-import android.widget.AbsListView;
 import android.widget.ImageButton;
-import android.widget.ListPopupWindow;
 
 import com.android.internal.view.ActionBarPolicy;
 import com.android.internal.view.menu.ActionMenuView.ActionMenuChildView;
@@ -694,32 +692,43 @@
         }
 
         @Override
-        public boolean onTouchObserved(View v, MotionEvent ev) {
-            if (ev.getActionMasked() == MotionEvent.ACTION_MOVE && v.isEnabled()
-                    && !v.pointInView(ev.getX(), ev.getY(), mScaledTouchSlop)) {
-                mActivePointerId = ev.getPointerId(0);
-                v.performClick();
-                return true;
-            }
-
-            return false;
-        }
-
-        @Override
-        public boolean onTouchForwarded(View v, MotionEvent ev) {
-            if (!v.isEnabled() || mOverflowPopup == null || !mOverflowPopup.isShowing()) {
+        public boolean onTouchObserved(View src, MotionEvent srcEvent) {
+            if (!src.isEnabled()) {
                 return false;
             }
 
-            if (mActivePointerId != MotionEvent.INVALID_POINTER_ID) {
-                if (mOverflowPopup.forwardMotionEvent(v, ev, mActivePointerId)) {
+            // Always start forwarding events when the source view is touched.
+            mActivePointerId = srcEvent.getPointerId(0);
+            src.performClick();
+            return true;
+        }
+
+        @Override
+        public boolean onTouchForwarded(View src, MotionEvent srcEvent) {
+            final OverflowPopup popup = mOverflowPopup;
+            if (popup != null && popup.isShowing()) {
+                final int activePointerId = mActivePointerId;
+                if (activePointerId != MotionEvent.INVALID_POINTER_ID && src.isEnabled()
+                        && popup.forwardMotionEvent(src, srcEvent, activePointerId)) {
+                    // Handled the motion event, continue forwarding.
                     return true;
                 }
 
-                mActivePointerId = MotionEvent.INVALID_POINTER_ID;
+                final int activePointerIndex = srcEvent.findPointerIndex(activePointerId);
+                if (activePointerIndex >= 0) {
+                    final float x = srcEvent.getX(activePointerIndex);
+                    final float y = srcEvent.getY(activePointerIndex);
+                    if (src.pointInView(x, y, mScaledTouchSlop)) {
+                        // The user is touching the source view. Cancel
+                        // forwarding, but don't dismiss the popup.
+                        return false;
+                    }
+                }
+
+                popup.dismiss();
             }
 
-            mOverflowPopup.dismiss();
+            // Cancel forwarding.
             return false;
         }
     }
diff --git a/core/java/com/android/internal/view/menu/MenuPopupHelper.java b/core/java/com/android/internal/view/menu/MenuPopupHelper.java
index 945f42b..9b266df 100644
--- a/core/java/com/android/internal/view/menu/MenuPopupHelper.java
+++ b/core/java/com/android/internal/view/menu/MenuPopupHelper.java
@@ -27,7 +27,6 @@
 import android.view.View.MeasureSpec;
 import android.view.ViewGroup;
 import android.view.ViewTreeObserver;
-import android.widget.AbsListView;
 import android.widget.AdapterView;
 import android.widget.BaseAdapter;
 import android.widget.FrameLayout;
@@ -48,8 +47,6 @@
 
     static final int ITEM_LAYOUT = com.android.internal.R.layout.popup_menu_item_layout;
 
-    private final int[] mTempLocation = new int[2];
-
     private final Context mContext;
     private final LayoutInflater mInflater;
     private final MenuBuilder mMenu;
@@ -162,67 +159,20 @@
         return mPopup != null && mPopup.isShowing();
     }
 
-    public boolean forwardMotionEvent(View v, MotionEvent ev, int activePointerId) {
+    /**
+     * Forwards motion events from a source view to the popup window.
+     *
+     * @param src view from which the event was forwarded
+     * @param event forwarded motion event in source-local coordinates
+     * @param activePointerId id of the pointer that activated forwarding
+     * @return whether the event was handled
+     */
+    public boolean forwardMotionEvent(View src, MotionEvent event, int activePointerId) {
         if (mPopup == null || !mPopup.isShowing()) {
             return false;
         }
 
-        final AbsListView dstView = mPopup.getListView();
-        if (dstView == null || !dstView.isShown()) {
-            return false;
-        }
-
-        boolean cancelForwarding = false;
-        final int actionMasked = ev.getActionMasked();
-        switch (actionMasked) {
-            case MotionEvent.ACTION_CANCEL:
-                cancelForwarding = true;
-                break;
-            case MotionEvent.ACTION_UP:
-                cancelForwarding = true;
-                // $FALL-THROUGH$
-            case MotionEvent.ACTION_MOVE:
-                final int activeIndex = ev.findPointerIndex(activePointerId);
-                if (activeIndex < 0) {
-                    return false;
-                }
-
-                final int[] location = mTempLocation;
-                int x = (int) ev.getX(activeIndex);
-                int y = (int) ev.getY(activeIndex);
-
-                // Convert to global coordinates.
-                v.getLocationOnScreen(location);
-                x += location[0];
-                y += location[1];
-
-                // Convert to local coordinates.
-                dstView.getLocationOnScreen(location);
-                x -= location[0];
-                y -= location[1];
-
-                final int position = dstView.pointToPosition(x, y);
-                if (position >= 0) {
-                    final int childCount = dstView.getChildCount();
-                    final int firstVisiblePosition = dstView.getFirstVisiblePosition();
-                    final int index = position - firstVisiblePosition;
-                    if (index < childCount) {
-                        final View child = dstView.getChildAt(index);
-                        if (actionMasked == MotionEvent.ACTION_UP) {
-                            // Touch ended, click highlighted item.
-                            final long id = dstView.getItemIdAtPosition(position);
-                            dstView.performItemClick(child, position, id);
-                        } else if (actionMasked == MotionEvent.ACTION_MOVE) {
-                            // TODO: Highlight touched item, activate after
-                            // long-hover. Consider forwarding events as HOVER and
-                            // letting ListView handle this.
-                        }
-                    }
-                }
-                break;
-        }
-
-        return true;
+        return mPopup.onForwardedEvent(src, event, activePointerId);
     }
 
     @Override
diff --git a/core/jni/Android.mk b/core/jni/Android.mk
index 0efa227..65b3678 100644
--- a/core/jni/Android.mk
+++ b/core/jni/Android.mk
@@ -63,7 +63,6 @@
 	android_os_FileUtils.cpp \
 	android_os_MemoryFile.cpp \
 	android_os_MessageQueue.cpp \
-	android_os_ParcelFileDescriptor.cpp \
 	android_os_Parcel.cpp \
 	android_os_SELinux.cpp \
 	android_os_SystemClock.cpp \
diff --git a/core/jni/AndroidRuntime.cpp b/core/jni/AndroidRuntime.cpp
index 91fdcc2..63310ab 100644
--- a/core/jni/AndroidRuntime.cpp
+++ b/core/jni/AndroidRuntime.cpp
@@ -135,7 +135,6 @@
 extern int register_android_os_Debug(JNIEnv* env);
 extern int register_android_os_MessageQueue(JNIEnv* env);
 extern int register_android_os_Parcel(JNIEnv* env);
-extern int register_android_os_ParcelFileDescriptor(JNIEnv *env);
 extern int register_android_os_SELinux(JNIEnv* env);
 extern int register_android_os_SystemProperties(JNIEnv *env);
 extern int register_android_os_SystemClock(JNIEnv* env);
@@ -1178,7 +1177,6 @@
     REG_JNI(register_android_os_FileObserver),
     REG_JNI(register_android_os_FileUtils),
     REG_JNI(register_android_os_MessageQueue),
-    REG_JNI(register_android_os_ParcelFileDescriptor),
     REG_JNI(register_android_os_SELinux),
     REG_JNI(register_android_os_Trace),
     REG_JNI(register_android_os_UEventObserver),
diff --git a/core/jni/android/graphics/Bitmap.cpp b/core/jni/android/graphics/Bitmap.cpp
index b03d12a..0ea3bf7 100644
--- a/core/jni/android/graphics/Bitmap.cpp
+++ b/core/jni/android/graphics/Bitmap.cpp
@@ -222,8 +222,12 @@
         }

     }

 

-    SkBitmap bitmap;

+    // ARGB_4444 is a deprecated format, convert automatically to 8888

+    if (config == SkBitmap::kARGB_4444_Config) {

+        config = SkBitmap::kARGB_8888_Config;

+    }

 

+    SkBitmap bitmap;

     bitmap.setConfig(config, width, height);

 

     jbyteArray buff = GraphicsJNI::allocateJavaPixelRef(env, &bitmap, NULL);

@@ -232,8 +236,7 @@
     }

 

     if (jColors != NULL) {

-        GraphicsJNI::SetPixels(env, jColors, offset, stride,

-                               0, 0, width, height, bitmap);

+        GraphicsJNI::SetPixels(env, jColors, offset, stride, 0, 0, width, height, bitmap);

     }

 

     return GraphicsJNI::createBitmap(env, new SkBitmap(bitmap), buff, isMutable, NULL, NULL);

diff --git a/core/jni/android_app_NativeActivity.cpp b/core/jni/android_app_NativeActivity.cpp
index f768ce8..5418006 100644
--- a/core/jni/android_app_NativeActivity.cpp
+++ b/core/jni/android_app_NativeActivity.cpp
@@ -306,19 +306,23 @@
         code->internalDataPath = code->internalDataPathObj.string();
         env->ReleaseStringUTFChars(internalDataDir, dirStr);
     
-        dirStr = env->GetStringUTFChars(externalDataDir, NULL);
-        code->externalDataPathObj = dirStr;
+        if (externalDataDir != NULL) {
+            dirStr = env->GetStringUTFChars(externalDataDir, NULL);
+            code->externalDataPathObj = dirStr;
+            env->ReleaseStringUTFChars(externalDataDir, dirStr);
+        }
         code->externalDataPath = code->externalDataPathObj.string();
-        env->ReleaseStringUTFChars(externalDataDir, dirStr);
 
         code->sdkVersion = sdkVersion;
         
         code->assetManager = assetManagerForJavaObject(env, jAssetMgr);
 
-        dirStr = env->GetStringUTFChars(obbDir, NULL);
-        code->obbPathObj = dirStr;
+        if (obbDir != NULL) {
+            dirStr = env->GetStringUTFChars(obbDir, NULL);
+            code->obbPathObj = dirStr;
+            env->ReleaseStringUTFChars(obbDir, dirStr);
+        }
         code->obbPath = code->obbPathObj.string();
-        env->ReleaseStringUTFChars(obbDir, dirStr);
 
         jbyte* rawSavedState = NULL;
         jsize rawSavedSize = 0;
diff --git a/core/jni/android_os_ParcelFileDescriptor.cpp b/core/jni/android_os_ParcelFileDescriptor.cpp
deleted file mode 100644
index 99a2d04..0000000
--- a/core/jni/android_os_ParcelFileDescriptor.cpp
+++ /dev/null
@@ -1,151 +0,0 @@
-/*
- * Copyright (C) 2008 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-//#define LOG_NDEBUG 0
-
-#include "JNIHelp.h"
-
-#include <fcntl.h>
-#include <sys/stat.h>
-#include <stdio.h>
-
-#include <utils/Log.h>
-
-#include <android_runtime/AndroidRuntime.h>
-
-namespace android
-{
-
-static struct parcel_file_descriptor_offsets_t
-{
-    jfieldID mFileDescriptor;
-} gParcelFileDescriptorOffsets;
-
-static jobject android_os_ParcelFileDescriptor_getFileDescriptorFromFd(JNIEnv* env,
-    jobject clazz, jint origfd)
-{
-    int fd = dup(origfd);
-    if (fd < 0) {
-        jniThrowException(env, "java/io/IOException", strerror(errno));
-        return NULL;
-    }
-    return jniCreateFileDescriptor(env, fd);
-}
-
-static jobject android_os_ParcelFileDescriptor_getFileDescriptorFromFdNoDup(JNIEnv* env,
-    jobject clazz, jint fd)
-{
-    return jniCreateFileDescriptor(env, fd);
-}
-
-static void android_os_ParcelFileDescriptor_createPipeNative(JNIEnv* env,
-    jobject clazz, jobjectArray outFds)
-{
-    int fds[2];
-    if (pipe(fds) < 0) {
-        int therr = errno;
-        jniThrowException(env, "java/io/IOException", strerror(therr));
-        return;
-    }
-
-    for (int i=0; i<2; i++) {
-        jobject fdObj = jniCreateFileDescriptor(env, fds[i]);
-        env->SetObjectArrayElement(outFds, i, fdObj);
-    }
-}
-
-static jint getFd(JNIEnv* env, jobject clazz)
-{
-    jobject descriptor = env->GetObjectField(clazz, gParcelFileDescriptorOffsets.mFileDescriptor);
-    if (descriptor == NULL) return -1;
-    return jniGetFDFromFileDescriptor(env, descriptor);
-}
-
-static jlong android_os_ParcelFileDescriptor_getStatSize(JNIEnv* env,
-    jobject clazz)
-{
-    jint fd = getFd(env, clazz);
-    if (fd < 0) {
-        jniThrowException(env, "java/lang/IllegalArgumentException", "bad file descriptor");
-        return -1;
-    }
-
-    struct stat st;
-    if (fstat(fd, &st) != 0) {
-        return -1;
-    }
-
-    if (S_ISREG(st.st_mode) || S_ISLNK(st.st_mode)) {
-        return st.st_size;
-    }
-
-    return -1;
-}
-
-static jlong android_os_ParcelFileDescriptor_seekTo(JNIEnv* env,
-    jobject clazz, jlong pos)
-{
-    jint fd = getFd(env, clazz);
-    if (fd < 0) {
-        jniThrowException(env, "java/lang/IllegalArgumentException", "bad file descriptor");
-        return -1;
-    }
-
-    return lseek(fd, pos, SEEK_SET);
-}
-
-static jlong android_os_ParcelFileDescriptor_getFdNative(JNIEnv* env, jobject clazz)
-{
-    jint fd = getFd(env, clazz);
-    if (fd < 0) {
-        jniThrowException(env, "java/lang/IllegalArgumentException", "bad file descriptor");
-        return -1;
-    }
-
-    return fd;
-}
-
-static const JNINativeMethod gParcelFileDescriptorMethods[] = {
-    {"getFileDescriptorFromFd", "(I)Ljava/io/FileDescriptor;",
-        (void*)android_os_ParcelFileDescriptor_getFileDescriptorFromFd},
-    {"getFileDescriptorFromFdNoDup", "(I)Ljava/io/FileDescriptor;",
-        (void*)android_os_ParcelFileDescriptor_getFileDescriptorFromFdNoDup},
-    {"createPipeNative", "([Ljava/io/FileDescriptor;)V",
-        (void*)android_os_ParcelFileDescriptor_createPipeNative},
-    {"getStatSize", "()J",
-        (void*)android_os_ParcelFileDescriptor_getStatSize},
-    {"seekTo", "(J)J",
-        (void*)android_os_ParcelFileDescriptor_seekTo},
-    {"getFdNative", "()I",
-        (void*)android_os_ParcelFileDescriptor_getFdNative}
-};
-
-const char* const kParcelFileDescriptorPathName = "android/os/ParcelFileDescriptor";
-
-int register_android_os_ParcelFileDescriptor(JNIEnv* env)
-{
-    jclass clazz = env->FindClass(kParcelFileDescriptorPathName);
-    LOG_FATAL_IF(clazz == NULL, "Unable to find class android.os.ParcelFileDescriptor");
-    gParcelFileDescriptorOffsets.mFileDescriptor = env->GetFieldID(clazz, "mFileDescriptor", "Ljava/io/FileDescriptor;");
-    LOG_FATAL_IF(gParcelFileDescriptorOffsets.mFileDescriptor == NULL,
-                 "Unable to find mFileDescriptor field in android.os.ParcelFileDescriptor");
-
-    return AndroidRuntime::registerNativeMethods(
-        env, kParcelFileDescriptorPathName,
-        gParcelFileDescriptorMethods, NELEM(gParcelFileDescriptorMethods));
-}
-
-}
diff --git a/core/res/res/layout/time_picker.xml b/core/res/res/layout/time_picker.xml
index a78cd85..4fa94f3 100644
--- a/core/res/res/layout/time_picker.xml
+++ b/core/res/res/layout/time_picker.xml
@@ -20,6 +20,7 @@
 <!-- Layout of time picker-->
 
 <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    android:id="@+id/timePickerLayout"
     android:orientation="horizontal"
     android:layout_gravity="center_horizontal"
     android:layout_width="wrap_content"
diff --git a/core/res/res/layout/time_picker_holo.xml b/core/res/res/layout/time_picker_holo.xml
index 7d8900e..c6b7d3a 100644
--- a/core/res/res/layout/time_picker_holo.xml
+++ b/core/res/res/layout/time_picker_holo.xml
@@ -20,14 +20,19 @@
 <!-- Layout of time picker -->
 
 <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    android:id="@+id/timePickerLayout"
     android:orientation="horizontal"
     android:layout_gravity="center_horizontal"
     android:layout_width="wrap_content"
-    android:layout_height="wrap_content">
+    android:layout_height="wrap_content"
+    android:paddingStart="8dip"
+    android:paddingEnd="8dip">
 
     <LinearLayout android:orientation="horizontal"
         android:layout_width="wrap_content"
         android:layout_height="wrap_content"
+        android:paddingStart="8dip"
+        android:paddingEnd="8dip"
         android:layoutDirection="ltr">
 
         <!-- hour -->
@@ -37,8 +42,6 @@
             android:layout_height="wrap_content"
             android:layout_marginTop="16dip"
             android:layout_marginBottom="16dip"
-            android:layout_marginStart="16dip"
-            android:layout_marginEnd="6dip"
             android:focusable="true"
             android:focusableInTouchMode="true"
             />
@@ -48,6 +51,8 @@
             android:id="@+id/divider"
             android:layout_width="wrap_content"
             android:layout_height="wrap_content"
+            android:layout_marginStart="6dip"
+            android:layout_marginEnd="6dip"
             android:layout_gravity="center_vertical"
             android:importantForAccessibility="no"
             />
@@ -59,8 +64,6 @@
             android:layout_height="wrap_content"
             android:layout_marginTop="16dip"
             android:layout_marginBottom="16dip"
-            android:layout_marginStart="6dip"
-            android:layout_marginEnd="8dip"
             android:focusable="true"
             android:focusableInTouchMode="true"
             />
@@ -75,7 +78,7 @@
         android:layout_marginTop="16dip"
         android:layout_marginBottom="16dip"
         android:layout_marginStart="8dip"
-        android:layout_marginEnd="16dip"
+        android:layout_marginEnd="8dip"
         android:focusable="true"
         android:focusableInTouchMode="true"
         />
diff --git a/core/res/res/values-af/strings.xml b/core/res/res/values-af/strings.xml
index a9d4b0a..fbeb5b1 100644
--- a/core/res/res/values-af/strings.xml
+++ b/core/res/res/values-af/strings.xml
@@ -1579,4 +1579,6 @@
     <item quantity="one" msgid="4835639969503729874">"Verkeerde PIN. Probeer weer oor 1 sekonde."</item>
     <item quantity="other" msgid="8030607343223287654">"Verkeerde PIN. Probeer weer oor <xliff:g id="COUNT">%d</xliff:g> sekondes."</item>
   </plurals>
+    <string name="transient_navigation_confirmation" msgid="4907844043611123426">"Sleep rand van skerm om balk te wys"</string>
+    <string name="transient_navigation_confirmation_long" msgid="8061685920508086697">"Sleep van rand van skerm af om stelselbalk te wys"</string>
 </resources>
diff --git a/core/res/res/values-am/strings.xml b/core/res/res/values-am/strings.xml
index 8fc907a..aaeb2d6 100644
--- a/core/res/res/values-am/strings.xml
+++ b/core/res/res/values-am/strings.xml
@@ -314,7 +314,7 @@
     <string name="permlab_stopAppSwitches" msgid="4138608610717425573">"የትግበራ መቀያየርን ተከላከል"</string>
     <string name="permdesc_stopAppSwitches" msgid="8262195802582255021">"ተጠቃሚው ከሌላ መተግበሪያ ከመቀየር ይከላከላል።"</string>
     <string name="permlab_getTopActivityInfo" msgid="2537922311411546016">"የአሁኑ የመተግበሪያ መረጃ ያግኙ"</string>
-    <string name="permdesc_getTopActivityInfo" msgid="8153651434145132505">"ያዢው በማያ ገጹ ፊት ላይ ስላለው የአሁኑ መተግበሪያ የግል መረጃ እንዲያመጣ ያስችለዋል።"</string>
+    <string name="permdesc_getTopActivityInfo" msgid="8153651434145132505">"ያዢው በአሁኑ መተግበሪያ እና በማያ ገጹ ፊት ላይ ስላሉ መተግበሪያዎች የግል መረጃ እንዲያመጣ ያስችለዋል።"</string>
     <string name="permlab_runSetActivityWatcher" msgid="892239094867182656">"ሁሉንም መተግበሪያ ማስነሻ አሳይ እና ተቆጣጠር"</string>
     <string name="permdesc_runSetActivityWatcher" msgid="6003603162578577406">"እንቅስቃሴዎችን ስርዓቱ እንዴት እንደሚያስጀምር ለመከታተል እና ለመቆጣጠር ለመተግበሪያው ይፈቅዳሉ፡፡ ተንኮል አዘል መተግበሪያዎች የስርዓቱን ክብረ ገመና ሙሉለሙሉ ሊያጋልጡ ይችላሉ፡፡ ይህ ፍቃድ የሚያስፈልገው ለግንባታ ብቻ ነው፤ ለመደበኛ አጠቃቀም ፈጽሞ አይደለም፡፡"</string>
     <string name="permlab_broadcastPackageRemoved" msgid="2576333434893532475">"አካታች የተወገደለት ስርጭት ላክ"</string>
@@ -1579,4 +1579,6 @@
     <item quantity="one" msgid="4835639969503729874">"ትክክል ያልሆነ ፒን። በ1 ሰከንድ ውስጥ እንደገና ይሞክሩ።"</item>
     <item quantity="other" msgid="8030607343223287654">"ትክክል ያልሆነ ፒን። በ<xliff:g id="COUNT">%d</xliff:g> ሰከንዶች ውስጥ እንደገና ይሞክሩ።"</item>
   </plurals>
+    <string name="transient_navigation_confirmation" msgid="4907844043611123426">"አሞሌውን ለማሳየት የማያ ገጹን ጠርዝ ላይ ያንሸራትቱ"</string>
+    <string name="transient_navigation_confirmation_long" msgid="8061685920508086697">"አሞሌውን ለማሳየት ከማያ ገጹ ጠርዝ ጀምረው ያንሸራትቱ"</string>
 </resources>
diff --git a/core/res/res/values-ar/strings.xml b/core/res/res/values-ar/strings.xml
index 03cc7b8..172b36e 100644
--- a/core/res/res/values-ar/strings.xml
+++ b/core/res/res/values-ar/strings.xml
@@ -1579,4 +1579,6 @@
     <item quantity="one" msgid="4835639969503729874">"رقم التعريف الشخصي غير صحيح، الرجاء إعادة المحاولة بعد ثانية واحدة."</item>
     <item quantity="other" msgid="8030607343223287654">"رقم التعريف الشخصي غير صحيح، الرجاء إعادة المحاولة بعد <xliff:g id="COUNT">%d</xliff:g> من الثواني."</item>
   </plurals>
+    <string name="transient_navigation_confirmation" msgid="4907844043611123426">"مرر سريعًا لحافة الشاشة لإظهار الشريط"</string>
+    <string name="transient_navigation_confirmation_long" msgid="8061685920508086697">"مرر سريعًا من حافة الشاشة لإظهار شريط النظام"</string>
 </resources>
diff --git a/core/res/res/values-be/strings.xml b/core/res/res/values-be/strings.xml
index 83a54b6..72d6483 100644
--- a/core/res/res/values-be/strings.xml
+++ b/core/res/res/values-be/strings.xml
@@ -1653,4 +1653,8 @@
     <skip />
     <!-- no translation found for restr_pin_countdown:one (4835639969503729874) -->
     <!-- no translation found for restr_pin_countdown:other (8030607343223287654) -->
+    <!-- no translation found for transient_navigation_confirmation (4907844043611123426) -->
+    <skip />
+    <!-- no translation found for transient_navigation_confirmation_long (8061685920508086697) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-bg/strings.xml b/core/res/res/values-bg/strings.xml
index 38ea228..febae04 100644
--- a/core/res/res/values-bg/strings.xml
+++ b/core/res/res/values-bg/strings.xml
@@ -1579,4 +1579,8 @@
     <item quantity="one" msgid="4835639969503729874">"Неправилен ПИН код. Опитайте отново след 1 секунда."</item>
     <item quantity="other" msgid="8030607343223287654">"Неправилен ПИН код. Опитайте отново след <xliff:g id="COUNT">%d</xliff:g> секунди."</item>
   </plurals>
+    <!-- no translation found for transient_navigation_confirmation (4907844043611123426) -->
+    <skip />
+    <!-- no translation found for transient_navigation_confirmation_long (8061685920508086697) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-ca/strings.xml b/core/res/res/values-ca/strings.xml
index dae5009..a5748b4 100644
--- a/core/res/res/values-ca/strings.xml
+++ b/core/res/res/values-ca/strings.xml
@@ -314,7 +314,7 @@
     <string name="permlab_stopAppSwitches" msgid="4138608610717425573">"impedir els canvis d\'aplicació"</string>
     <string name="permdesc_stopAppSwitches" msgid="8262195802582255021">"Impedeix que l\'usuari canviï a una altra aplicació."</string>
     <string name="permlab_getTopActivityInfo" msgid="2537922311411546016">"obtenció d\'informació de l\'aplicació actual"</string>
-    <string name="permdesc_getTopActivityInfo" msgid="8153651434145132505">"Permet que el titular recuperi informació privada sobre l\'aplicació i els serveis actual al primer pla de la pantalla."</string>
+    <string name="permdesc_getTopActivityInfo" msgid="8153651434145132505">"Permet que el titular recuperi informació privada sobre l\'aplicació i els serveis actuals al primer pla de la pantalla."</string>
     <string name="permlab_runSetActivityWatcher" msgid="892239094867182656">"supervisa i controla tots els inicis d\'aplicacions"</string>
     <string name="permdesc_runSetActivityWatcher" msgid="6003603162578577406">"Permet que l\'aplicació supervisi i controli com el sistema inicia activitats. Les aplicacions malicioses poden comprometre totalment el sistema. Aquest permís només és necessari per al desenvolupament, mai per a l\'ús normal."</string>
     <string name="permlab_broadcastPackageRemoved" msgid="2576333434893532475">"enviar difusió d\'eliminació de paquet"</string>
@@ -1579,4 +1579,8 @@
     <item quantity="one" msgid="4835639969503729874">"PIN incorrecte. Torna-ho a provar d\'aquí a 1 segon."</item>
     <item quantity="other" msgid="8030607343223287654">"PIN incorrecte. Torna-ho a provar d\'aquí a <xliff:g id="COUNT">%d</xliff:g> segons."</item>
   </plurals>
+    <!-- no translation found for transient_navigation_confirmation (4907844043611123426) -->
+    <skip />
+    <!-- no translation found for transient_navigation_confirmation_long (8061685920508086697) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-cs/strings.xml b/core/res/res/values-cs/strings.xml
index 8e16e3a..55d45da 100644
--- a/core/res/res/values-cs/strings.xml
+++ b/core/res/res/values-cs/strings.xml
@@ -1579,4 +1579,6 @@
     <item quantity="one" msgid="4835639969503729874">"Nesprávný kód PIN. Zkuste to znovu za jednu sekundu."</item>
     <item quantity="other" msgid="8030607343223287654">"Nesprávný kód PIN. Zkuste to znovu za <xliff:g id="COUNT">%d</xliff:g> s."</item>
   </plurals>
+    <string name="transient_navigation_confirmation" msgid="4907844043611123426">"Panel zobrazíte přejetím kraje obr."</string>
+    <string name="transient_navigation_confirmation_long" msgid="8061685920508086697">"Systémový panel zobrazíte přejetím přes okraj obrazovky"</string>
 </resources>
diff --git a/core/res/res/values-da/strings.xml b/core/res/res/values-da/strings.xml
index 9a053b8..f8e6e7c 100644
--- a/core/res/res/values-da/strings.xml
+++ b/core/res/res/values-da/strings.xml
@@ -245,9 +245,9 @@
     <string name="permdesc_expandStatusBar" msgid="6917549437129401132">"Tillader, at appen kan udvide og skjule statusbjælken."</string>
     <string name="permlab_processOutgoingCalls" msgid="3906007831192990946">"omdirigere udgående opkald"</string>
     <string name="permdesc_processOutgoingCalls" msgid="5331318931937402040">"Tillader, at appen kan behandle udgående opkald og ændre det nummer, der skal ringes til. Med denne tilladelse kan appen overvåge, omdirigere eller forhindre udgående opkald."</string>
-    <string name="permlab_receiveSms" msgid="8673471768947895082">"modtage tekstbeskeder (SMS)"</string>
+    <string name="permlab_receiveSms" msgid="8673471768947895082">"modtage tekstbeskeder (sms)"</string>
     <string name="permdesc_receiveSms" msgid="6424387754228766939">"Tillader, at appen kan modtage og behandle sms-beskeder. Det betyder, at appen kan overvåge eller slette de beskeder, der sendes til din enhed, uden at vise dem til dig."</string>
-    <string name="permlab_receiveMms" msgid="1821317344668257098">"modtage tekstbeskeder (MMS)"</string>
+    <string name="permlab_receiveMms" msgid="1821317344668257098">"modtage tekstbeskeder (mms)"</string>
     <string name="permdesc_receiveMms" msgid="533019437263212260">"Tillader, at appen kan modtage og behandle mms-beskeder. Det betyder, at appen kan overvåge eller slette de beskeder, der sendes til din enhed, uden at vise dem til dig."</string>
     <string name="permlab_receiveEmergencyBroadcast" msgid="1803477660846288089">"modtage nødudsendelser"</string>
     <string name="permdesc_receiveEmergencyBroadcast" msgid="848524070262431974">"Tillader, at appen kan modtage og behandle nødtransmissioner. Denne tilladelse er kun tilgængelig for systemapps."</string>
@@ -257,10 +257,10 @@
     <string name="permdesc_sendSms" msgid="7094729298204937667">"Tillader, at appen kan sende sms-beskeder. Dette kan resultere i uventede opkrævninger. Skadelige apps kan koste dig penge ved at sende beskeder uden din bekræftelse."</string>
     <string name="permlab_sendRespondViaMessageRequest" msgid="8713889105305943200">"send hændelser, hvor der skal svares pr. besked"</string>
     <string name="permdesc_sendRespondViaMessageRequest" msgid="7107648548468778734">"Tillader, at appen kan sende anmodninger til andre apps til beskeder for at håndtere hændelser, hvor der skal svares pr. besked."</string>
-    <string name="permlab_readSms" msgid="8745086572213270480">"læse dine tekstbeskeder (SMS eller MMS)"</string>
+    <string name="permlab_readSms" msgid="8745086572213270480">"læse dine tekstbeskeder (sms eller mms)"</string>
     <string name="permdesc_readSms" product="tablet" msgid="2467981548684735522">"Tillader, at appen kan læse de sms-beskeder, der er gemt på din tablet eller dit SIM-kort. Med denne tilladelse kan appen læse alle sms-beskeder, uanset indhold eller fortrolighed."</string>
     <string name="permdesc_readSms" product="default" msgid="3695967533457240550">"Tillader, at appen kan læse de sms-beskeder, der er gemt på din telefon eller dit SIM-kort. Med denne tilladelse kan appen læse alle sms-beskeder, uanset indhold eller fortrolighed."</string>
-    <string name="permlab_writeSms" msgid="3216950472636214774">"redigere dine tekstbeskeder (SMS eller MMS)"</string>
+    <string name="permlab_writeSms" msgid="3216950472636214774">"redigere dine tekstbeskeder (sms eller mms)"</string>
     <string name="permdesc_writeSms" product="tablet" msgid="5160413947794501538">"Tillader, at appen kan skrive til sms-beskeder, der er gemt på din tablet eller på SIM-kortet. Ondsindede apps kan slette dine beskeder."</string>
     <string name="permdesc_writeSms" product="default" msgid="7268668709052328567">"Tillader, at appen kan skrive til sms-beskeder, der er gemt på din telefon eller dit SIM-kort. Ondsindede apps kan slette dine beskeder."</string>
     <string name="permlab_receiveWapPush" msgid="5991398711936590410">"modtage tekstbeskeder (WAP)"</string>
@@ -1579,4 +1579,6 @@
     <item quantity="one" msgid="4835639969503729874">"Forkert pinkode. Prøv igen om 1 sekund."</item>
     <item quantity="other" msgid="8030607343223287654">"Forkert pinkode. Prøv igen om <xliff:g id="COUNT">%d</xliff:g> sekunder."</item>
   </plurals>
+    <string name="transient_navigation_confirmation" msgid="4907844043611123426">"Stryg fra skærmkanten for at se bjælken"</string>
+    <string name="transient_navigation_confirmation_long" msgid="8061685920508086697">"Stryg med fingeren fra skærmens kant for at se systembjælken"</string>
 </resources>
diff --git a/core/res/res/values-de/strings.xml b/core/res/res/values-de/strings.xml
index 7e4d274..1c67f7f 100644
--- a/core/res/res/values-de/strings.xml
+++ b/core/res/res/values-de/strings.xml
@@ -1579,4 +1579,6 @@
     <item quantity="one" msgid="4835639969503729874">"Falsche PIN. In 1 Sek. erneut versuchen."</item>
     <item quantity="other" msgid="8030607343223287654">"Falsche PIN. In <xliff:g id="COUNT">%d</xliff:g> Sek. erneut versuchen."</item>
   </plurals>
+    <string name="transient_navigation_confirmation" msgid="4907844043611123426">"Zum Einblenden der Leiste vom Rand weg wischen"</string>
+    <string name="transient_navigation_confirmation_long" msgid="8061685920508086697">"Zum Einblenden der Systemleiste vom Rand weg wischen"</string>
 </resources>
diff --git a/core/res/res/values-el/strings.xml b/core/res/res/values-el/strings.xml
index 7c46560..a01ef71 100644
--- a/core/res/res/values-el/strings.xml
+++ b/core/res/res/values-el/strings.xml
@@ -1579,4 +1579,6 @@
     <item quantity="one" msgid="4835639969503729874">"Λάθος PIN. Προσπαθήστε ξανά σε 1 δευτερόλεπτο."</item>
     <item quantity="other" msgid="8030607343223287654">"Λάθος PIN. Προσπαθήστε ξανά σε <xliff:g id="COUNT">%d</xliff:g> δευτερόλεπτα."</item>
   </plurals>
+    <string name="transient_navigation_confirmation" msgid="4907844043611123426">"Σύρετε την άκρη για εμφάν.γραμμής"</string>
+    <string name="transient_navigation_confirmation_long" msgid="8061685920508086697">"Σύρετε από την άκρη της οθόνης για να εμφανίσετε τη γραμμή συστήματος"</string>
 </resources>
diff --git a/core/res/res/values-en-rGB/strings.xml b/core/res/res/values-en-rGB/strings.xml
index 22281c1..8a3f354 100644
--- a/core/res/res/values-en-rGB/strings.xml
+++ b/core/res/res/values-en-rGB/strings.xml
@@ -1579,4 +1579,6 @@
     <item quantity="one" msgid="4835639969503729874">"Incorrect PIN. Try again in 1 second."</item>
     <item quantity="other" msgid="8030607343223287654">"Incorrect PIN. Try again in <xliff:g id="COUNT">%d</xliff:g> seconds."</item>
   </plurals>
+    <string name="transient_navigation_confirmation" msgid="4907844043611123426">"Swipe edge of screen to reveal bar"</string>
+    <string name="transient_navigation_confirmation_long" msgid="8061685920508086697">"Swipe from edge of screen to reveal system bar"</string>
 </resources>
diff --git a/core/res/res/values-es-rUS/strings.xml b/core/res/res/values-es-rUS/strings.xml
index 9c1156bc..c7fe85e 100644
--- a/core/res/res/values-es-rUS/strings.xml
+++ b/core/res/res/values-es-rUS/strings.xml
@@ -1579,4 +1579,8 @@
     <item quantity="one" msgid="4835639969503729874">"PIN incorrecto. Reintentar en 1 s"</item>
     <item quantity="other" msgid="8030607343223287654">"PIN incorrecto. Reintentar en <xliff:g id="COUNT">%d</xliff:g> s"</item>
   </plurals>
+    <!-- no translation found for transient_navigation_confirmation (4907844043611123426) -->
+    <skip />
+    <!-- no translation found for transient_navigation_confirmation_long (8061685920508086697) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-es/strings.xml b/core/res/res/values-es/strings.xml
index d64a07a..fa38dbc 100644
--- a/core/res/res/values-es/strings.xml
+++ b/core/res/res/values-es/strings.xml
@@ -1579,4 +1579,6 @@
     <item quantity="one" msgid="4835639969503729874">"PIN incorrecto. Inténtalo de nuevo dentro de 1 segundo."</item>
     <item quantity="other" msgid="8030607343223287654">"PIN incorrecto. Inténtalo de nuevo dentro de <xliff:g id="COUNT">%d</xliff:g> segundos."</item>
   </plurals>
+    <string name="transient_navigation_confirmation" msgid="4907844043611123426">"Deslizar borde para mostrar barra"</string>
+    <string name="transient_navigation_confirmation_long" msgid="8061685920508086697">"Desliza el borde de la pantalla para mostrar la barra del sistema"</string>
 </resources>
diff --git a/core/res/res/values-et/strings.xml b/core/res/res/values-et/strings.xml
index 386ea2d..28e3ea1 100644
--- a/core/res/res/values-et/strings.xml
+++ b/core/res/res/values-et/strings.xml
@@ -1579,4 +1579,8 @@
     <item quantity="one" msgid="4835639969503729874">"Vale PIN-kood. Proovige 1 s pärast."</item>
     <item quantity="other" msgid="8030607343223287654">"Vale PIN-kood. Proovige <xliff:g id="COUNT">%d</xliff:g> s pärast."</item>
   </plurals>
+    <!-- no translation found for transient_navigation_confirmation (4907844043611123426) -->
+    <skip />
+    <!-- no translation found for transient_navigation_confirmation_long (8061685920508086697) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-fa/strings.xml b/core/res/res/values-fa/strings.xml
index 136e027..f6fa564 100644
--- a/core/res/res/values-fa/strings.xml
+++ b/core/res/res/values-fa/strings.xml
@@ -1579,4 +1579,8 @@
     <item quantity="one" msgid="4835639969503729874">"پین نادرست است. امتحان در ۱ ثانیه."</item>
     <item quantity="other" msgid="8030607343223287654">"پین نادرست است. امتحان در <xliff:g id="COUNT">%d</xliff:g> ثانیه."</item>
   </plurals>
+    <!-- no translation found for transient_navigation_confirmation (4907844043611123426) -->
+    <skip />
+    <!-- no translation found for transient_navigation_confirmation_long (8061685920508086697) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-fi/strings.xml b/core/res/res/values-fi/strings.xml
index 098be12..6089da6 100644
--- a/core/res/res/values-fi/strings.xml
+++ b/core/res/res/values-fi/strings.xml
@@ -1579,4 +1579,8 @@
     <item quantity="one" msgid="4835639969503729874">"Väärä PIN. Yritä uudelleen yhden sekunnin kuluttua."</item>
     <item quantity="other" msgid="8030607343223287654">"Väärä PIN. Yritä uudelleen <xliff:g id="COUNT">%d</xliff:g> sekunnin kuluttua."</item>
   </plurals>
+    <!-- no translation found for transient_navigation_confirmation (4907844043611123426) -->
+    <skip />
+    <!-- no translation found for transient_navigation_confirmation_long (8061685920508086697) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-fr/strings.xml b/core/res/res/values-fr/strings.xml
index 9103e58..24a5107 100644
--- a/core/res/res/values-fr/strings.xml
+++ b/core/res/res/values-fr/strings.xml
@@ -1579,4 +1579,8 @@
     <item quantity="one" msgid="4835639969503729874">"PIN erroné. Réessayez dans 1 seconde."</item>
     <item quantity="other" msgid="8030607343223287654">"PIN erroné. Réessayez dans <xliff:g id="COUNT">%d</xliff:g> secondes."</item>
   </plurals>
+    <!-- no translation found for transient_navigation_confirmation (4907844043611123426) -->
+    <skip />
+    <!-- no translation found for transient_navigation_confirmation_long (8061685920508086697) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-hi/strings.xml b/core/res/res/values-hi/strings.xml
index 07376ef..89cfc70 100644
--- a/core/res/res/values-hi/strings.xml
+++ b/core/res/res/values-hi/strings.xml
@@ -1579,4 +1579,6 @@
     <item quantity="one" msgid="4835639969503729874">"गलत PIN. 1 सेकंड में पुनः प्रयास करें."</item>
     <item quantity="other" msgid="8030607343223287654">"गलत PIN. <xliff:g id="COUNT">%d</xliff:g> सेकंड में पुनः प्रयास करें."</item>
   </plurals>
+    <string name="transient_navigation_confirmation" msgid="4907844043611123426">"बार को प्रदर्शित करने के लिए स्क्रीन के किनारे को स्वाइप करें"</string>
+    <string name="transient_navigation_confirmation_long" msgid="8061685920508086697">"सिस्टम बार को प्रदर्शित करने के लिए स्क्रीन के किनारे से स्वाइप करें"</string>
 </resources>
diff --git a/core/res/res/values-hr/strings.xml b/core/res/res/values-hr/strings.xml
index 4cea5a6..a1175f0 100644
--- a/core/res/res/values-hr/strings.xml
+++ b/core/res/res/values-hr/strings.xml
@@ -1579,4 +1579,8 @@
     <item quantity="one" msgid="4835639969503729874">"PIN nije točan. Ponovite za 1 s."</item>
     <item quantity="other" msgid="8030607343223287654">"PIN nije točan. Ponovite za <xliff:g id="COUNT">%d</xliff:g> s."</item>
   </plurals>
+    <!-- no translation found for transient_navigation_confirmation (4907844043611123426) -->
+    <skip />
+    <!-- no translation found for transient_navigation_confirmation_long (8061685920508086697) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-hu/strings.xml b/core/res/res/values-hu/strings.xml
index 5e0fbc2..9bf05c0 100644
--- a/core/res/res/values-hu/strings.xml
+++ b/core/res/res/values-hu/strings.xml
@@ -1579,4 +1579,8 @@
     <item quantity="one" msgid="4835639969503729874">"Helytelen PIN kód. Próbálja újra 1 másodperc múlva."</item>
     <item quantity="other" msgid="8030607343223287654">"Helytelen PIN kód. Próbálja újra <xliff:g id="COUNT">%d</xliff:g> másodperc múlva."</item>
   </plurals>
+    <!-- no translation found for transient_navigation_confirmation (4907844043611123426) -->
+    <skip />
+    <!-- no translation found for transient_navigation_confirmation_long (8061685920508086697) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-in/strings.xml b/core/res/res/values-in/strings.xml
index 1df979b..6ff0e95 100644
--- a/core/res/res/values-in/strings.xml
+++ b/core/res/res/values-in/strings.xml
@@ -625,7 +625,7 @@
     <string name="permlab_sdcardRead" product="default" msgid="8235341515605559677">"akses uji coba ke penyimpanan yang dilindungi"</string>
     <string name="permdesc_sdcardRead" product="nosdcard" msgid="3642473292348132072">"Memungkinkan aplikasi menguji izin penyimpanan USB yang akan tersedia di perangkat mendatang."</string>
     <string name="permdesc_sdcardRead" product="default" msgid="5914402684685848828">"Memungkinkan aplikasi menguji izin untuk kartu SD yang akan tersedia pada perangkat yang akan datang."</string>
-    <string name="permlab_sdcardWrite" product="nosdcard" msgid="8485979062254666748">"ubah/hapus konten pympanan USB"</string>
+    <string name="permlab_sdcardWrite" product="nosdcard" msgid="8485979062254666748">"ubah/hapus isi penyimpanan USB"</string>
     <string name="permlab_sdcardWrite" product="default" msgid="8805693630050458763">"mengubah atau menghapus konten kartu SD Anda"</string>
     <string name="permdesc_sdcardWrite" product="nosdcard" msgid="6175406299445710888">"Mengizinkan apl menulis ke penyimpanan USB."</string>
     <string name="permdesc_sdcardWrite" product="default" msgid="4337417790936632090">"Memungkinkan apl menulis ke kartu SD."</string>
@@ -1579,4 +1579,8 @@
     <item quantity="one" msgid="4835639969503729874">"PIN salah. Coba lagi dalam 1 detik."</item>
     <item quantity="other" msgid="8030607343223287654">"PIN salah. Coba lagi dalam <xliff:g id="COUNT">%d</xliff:g> detik."</item>
   </plurals>
+    <!-- no translation found for transient_navigation_confirmation (4907844043611123426) -->
+    <skip />
+    <!-- no translation found for transient_navigation_confirmation_long (8061685920508086697) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-it/strings.xml b/core/res/res/values-it/strings.xml
index 82cb917..dfac858 100644
--- a/core/res/res/values-it/strings.xml
+++ b/core/res/res/values-it/strings.xml
@@ -1579,4 +1579,6 @@
     <item quantity="one" msgid="4835639969503729874">"PIN errato. Riprova tra 1 s."</item>
     <item quantity="other" msgid="8030607343223287654">"PIN errato. Riprova tra <xliff:g id="COUNT">%d</xliff:g> s."</item>
   </plurals>
+    <string name="transient_navigation_confirmation" msgid="4907844043611123426">"Scorri bordo schermo per visual. barra"</string>
+    <string name="transient_navigation_confirmation_long" msgid="8061685920508086697">"Fai scorrere il dito dal bordo dello schermo per visualizzare la barra di sistema"</string>
 </resources>
diff --git a/core/res/res/values-iw/strings.xml b/core/res/res/values-iw/strings.xml
index cef252a..418bd60 100644
--- a/core/res/res/values-iw/strings.xml
+++ b/core/res/res/values-iw/strings.xml
@@ -1579,4 +1579,8 @@
     <item quantity="one" msgid="4835639969503729874">"מספר PIN שגוי. נסה שוב בעוד שניה."</item>
     <item quantity="other" msgid="8030607343223287654">"מספר PIN שגוי. נסה שוב בעוד <xliff:g id="COUNT">%d</xliff:g> שניות."</item>
   </plurals>
+    <!-- no translation found for transient_navigation_confirmation (4907844043611123426) -->
+    <skip />
+    <!-- no translation found for transient_navigation_confirmation_long (8061685920508086697) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-ja/strings.xml b/core/res/res/values-ja/strings.xml
index de0369c..8d43e5c 100644
--- a/core/res/res/values-ja/strings.xml
+++ b/core/res/res/values-ja/strings.xml
@@ -1579,4 +1579,8 @@
     <item quantity="one" msgid="4835639969503729874">"PINが正しくありません。1秒後にもう一度お試しください。"</item>
     <item quantity="other" msgid="8030607343223287654">"PINが正しくありません。<xliff:g id="COUNT">%d</xliff:g>秒後にもう一度お試しください。"</item>
   </plurals>
+    <!-- no translation found for transient_navigation_confirmation (4907844043611123426) -->
+    <skip />
+    <!-- no translation found for transient_navigation_confirmation_long (8061685920508086697) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-ko/strings.xml b/core/res/res/values-ko/strings.xml
index 6477258..8ba74f7 100644
--- a/core/res/res/values-ko/strings.xml
+++ b/core/res/res/values-ko/strings.xml
@@ -1579,4 +1579,8 @@
     <item quantity="one" msgid="4835639969503729874">"잘못된 PIN입니다. 1초 뒤에 다시 시도하세요."</item>
     <item quantity="other" msgid="8030607343223287654">"잘못된 PIN입니다. <xliff:g id="COUNT">%d</xliff:g>초 뒤에 다시 시도하세요."</item>
   </plurals>
+    <!-- no translation found for transient_navigation_confirmation (4907844043611123426) -->
+    <skip />
+    <!-- no translation found for transient_navigation_confirmation_long (8061685920508086697) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-lt/strings.xml b/core/res/res/values-lt/strings.xml
index 1158a26..cfe8a1c 100644
--- a/core/res/res/values-lt/strings.xml
+++ b/core/res/res/values-lt/strings.xml
@@ -314,7 +314,7 @@
     <string name="permlab_stopAppSwitches" msgid="4138608610717425573">"neleisti perjungti programų"</string>
     <string name="permdesc_stopAppSwitches" msgid="8262195802582255021">"Neleidžiama naudotojui perjungti į kitą programą."</string>
     <string name="permlab_getTopActivityInfo" msgid="2537922311411546016">"gauti esamos programos informaciją"</string>
-    <string name="permdesc_getTopActivityInfo" msgid="8153651434145132505">"Savininkui leidžiama gauti privačią informaciją apie dabartinę programą ir paslaugas, naudojamas ekrano priekiniame plane."</string>
+    <string name="permdesc_getTopActivityInfo" msgid="8153651434145132505">"Savininkui leidžiama gauti privačios informacijos apie dabartinę programą ir paslaugas, naudojamas ekrano priekiniame plane."</string>
     <string name="permlab_runSetActivityWatcher" msgid="892239094867182656">"stebėti ir valdyti visų programų paleidimą"</string>
     <string name="permdesc_runSetActivityWatcher" msgid="6003603162578577406">"Leidžiama programai stebėti ir valdyti, kaip sistema paleidžia veiklą. Kenkėjiškos programos gali visiškai pažeisti sistemą. Šis leidimas reikalingas tik kuriant ir jo niekada nereikia naudojant įprastai."</string>
     <string name="permlab_broadcastPackageRemoved" msgid="2576333434893532475">"siųsti pašalinto paketo perdavimą"</string>
@@ -1579,4 +1579,6 @@
     <item quantity="one" msgid="4835639969503729874">"Netinkamas PIN kodas. Band. po 1 sek."</item>
     <item quantity="other" msgid="8030607343223287654">"Netinkamas PIN kodas. Band. po <xliff:g id="COUNT">%d</xliff:g> sek."</item>
   </plurals>
+    <string name="transient_navigation_confirmation" msgid="4907844043611123426">"Perbr. ekr. kr., kad atsir. juost."</string>
+    <string name="transient_navigation_confirmation_long" msgid="8061685920508086697">"Perbraukite iš ekrano krašto, kad atsirastų sistemos juosta"</string>
 </resources>
diff --git a/core/res/res/values-lv/strings.xml b/core/res/res/values-lv/strings.xml
index 12acf7a..3fdcde2 100644
--- a/core/res/res/values-lv/strings.xml
+++ b/core/res/res/values-lv/strings.xml
@@ -1579,4 +1579,6 @@
     <item quantity="one" msgid="4835639969503729874">"PIN nav pareizs. Mēģiniet pēc 1 s."</item>
     <item quantity="other" msgid="8030607343223287654">"PIN nav pareizs. Mēģiniet pēc <xliff:g id="COUNT">%d</xliff:g> s."</item>
   </plurals>
+    <string name="transient_navigation_confirmation" msgid="4907844043611123426">"Velciet no malas, lai atvērtu joslu"</string>
+    <string name="transient_navigation_confirmation_long" msgid="8061685920508086697">"Velciet no ekrāna malas, lai atvērtu sistēmas joslu."</string>
 </resources>
diff --git a/core/res/res/values-ms/strings.xml b/core/res/res/values-ms/strings.xml
index bb12579..26e797a 100644
--- a/core/res/res/values-ms/strings.xml
+++ b/core/res/res/values-ms/strings.xml
@@ -654,7 +654,7 @@
     <string name="permlab_invokeCarrierSetup" msgid="3699600833975117478">"gunakan apl konfigurasi yang disediakan oleh pembawa"</string>
     <string name="permdesc_invokeCarrierSetup" msgid="4159549152529111920">"Membenarkan pemegang menggunakan apl konfigurasi yang diberikan oleh pembawa. Tidak sekali-kali diperlukan untuk apl biasa."</string>
     <string name="permlab_accessNetworkConditions" msgid="8206077447838909516">"dengar pemerhatian mengenai keadaan rangkaian"</string>
-    <string name="permdesc_accessNetworkConditions" msgid="6899102075825272211">"Membenarkan aplikasi mendengar pemerhantian tentang keadaan rangkaian. Tidak sekali-kali diperlukan untuk apl biasa."</string>
+    <string name="permdesc_accessNetworkConditions" msgid="6899102075825272211">"Membenarkan aplikasi mendengar pemerhatian tentang keadaan rangkaian. Tidak sekali-kali diperlukan untuk apl biasa."</string>
     <string name="policylab_limitPassword" msgid="4497420728857585791">"Tetapkan peraturan kata laluan"</string>
     <string name="policydesc_limitPassword" msgid="3252114203919510394">"Mengawal panjang dan aksara yang dibenarkan dalam kata laluan buka kunci skrin."</string>
     <string name="policylab_watchLogin" msgid="914130646942199503">"Memantau percubaan buka kunci skrin"</string>
@@ -1579,4 +1579,8 @@
     <item quantity="one" msgid="4835639969503729874">"PIN salah. Cuba lagi dalam masa 1 saat."</item>
     <item quantity="other" msgid="8030607343223287654">"PIN salah. Cuba lagi dalam masa <xliff:g id="COUNT">%d</xliff:g> saat."</item>
   </plurals>
+    <!-- no translation found for transient_navigation_confirmation (4907844043611123426) -->
+    <skip />
+    <!-- no translation found for transient_navigation_confirmation_long (8061685920508086697) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-nb/strings.xml b/core/res/res/values-nb/strings.xml
index e55e6db..9b9d58e 100644
--- a/core/res/res/values-nb/strings.xml
+++ b/core/res/res/values-nb/strings.xml
@@ -1579,4 +1579,6 @@
     <item quantity="one" msgid="4835639969503729874">"Feil PIN-kode. Prøv på nytt om 1 sekund."</item>
     <item quantity="other" msgid="8030607343223287654">"Feil PIN-kode. Prøv på nytt om <xliff:g id="COUNT">%d</xliff:g> sekunder."</item>
   </plurals>
+    <string name="transient_navigation_confirmation" msgid="4907844043611123426">"Sveip på kanten av skjermen for å få frem feltet"</string>
+    <string name="transient_navigation_confirmation_long" msgid="8061685920508086697">"Sveip fra kanten på skjermen for å få frem systemfeltet"</string>
 </resources>
diff --git a/core/res/res/values-nl/strings.xml b/core/res/res/values-nl/strings.xml
index d48ccb8..c219fde 100644
--- a/core/res/res/values-nl/strings.xml
+++ b/core/res/res/values-nl/strings.xml
@@ -1579,4 +1579,6 @@
     <item quantity="one" msgid="4835639969503729874">"Onjuiste pincode. Probeer het over één seconde opnieuw."</item>
     <item quantity="other" msgid="8030607343223287654">"Onjuiste pincode. Probeer het over <xliff:g id="COUNT">%d</xliff:g> seconden opnieuw."</item>
   </plurals>
+    <string name="transient_navigation_confirmation" msgid="4907844043611123426">"Veeg vanaf de rand voor de balk"</string>
+    <string name="transient_navigation_confirmation_long" msgid="8061685920508086697">"Veeg vanaf de rand van het scherm om de systeembalk weer te geven"</string>
 </resources>
diff --git a/core/res/res/values-pl/strings.xml b/core/res/res/values-pl/strings.xml
index 297bc53..2d4db29 100644
--- a/core/res/res/values-pl/strings.xml
+++ b/core/res/res/values-pl/strings.xml
@@ -1579,4 +1579,8 @@
     <item quantity="one" msgid="4835639969503729874">"Nieprawidłowy PIN. Spróbuj ponownie za 1 s."</item>
     <item quantity="other" msgid="8030607343223287654">"Nieprawidłowy PIN. Spróbuj ponownie za <xliff:g id="COUNT">%d</xliff:g> s."</item>
   </plurals>
+    <!-- no translation found for transient_navigation_confirmation (4907844043611123426) -->
+    <skip />
+    <!-- no translation found for transient_navigation_confirmation_long (8061685920508086697) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-pt-rPT/strings.xml b/core/res/res/values-pt-rPT/strings.xml
index 00eb416..b55a374a 100644
--- a/core/res/res/values-pt-rPT/strings.xml
+++ b/core/res/res/values-pt-rPT/strings.xml
@@ -1579,4 +1579,8 @@
     <item quantity="one" msgid="4835639969503729874">"PIN incorreto. Tente novamente em 1 seg."</item>
     <item quantity="other" msgid="8030607343223287654">"PIN incorreto. Tente novamente em <xliff:g id="COUNT">%d</xliff:g> seg."</item>
   </plurals>
+    <!-- no translation found for transient_navigation_confirmation (4907844043611123426) -->
+    <skip />
+    <!-- no translation found for transient_navigation_confirmation_long (8061685920508086697) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-pt/strings.xml b/core/res/res/values-pt/strings.xml
index e5285b1..4fd2b05 100644
--- a/core/res/res/values-pt/strings.xml
+++ b/core/res/res/values-pt/strings.xml
@@ -1579,4 +1579,8 @@
     <item quantity="one" msgid="4835639969503729874">"PIN incorreto. Tente novamente em 1 segundo."</item>
     <item quantity="other" msgid="8030607343223287654">"PIN incorreto. Tente novamente em <xliff:g id="COUNT">%d</xliff:g> segundos."</item>
   </plurals>
+    <!-- no translation found for transient_navigation_confirmation (4907844043611123426) -->
+    <skip />
+    <!-- no translation found for transient_navigation_confirmation_long (8061685920508086697) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-rm/strings.xml b/core/res/res/values-rm/strings.xml
index 363fb94..7afb03e 100644
--- a/core/res/res/values-rm/strings.xml
+++ b/core/res/res/values-rm/strings.xml
@@ -2592,4 +2592,8 @@
     <skip />
     <!-- no translation found for restr_pin_countdown:one (4835639969503729874) -->
     <!-- no translation found for restr_pin_countdown:other (8030607343223287654) -->
+    <!-- no translation found for transient_navigation_confirmation (4907844043611123426) -->
+    <skip />
+    <!-- no translation found for transient_navigation_confirmation_long (8061685920508086697) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-ro/strings.xml b/core/res/res/values-ro/strings.xml
index 6fbecc8..24d6d21 100644
--- a/core/res/res/values-ro/strings.xml
+++ b/core/res/res/values-ro/strings.xml
@@ -314,7 +314,7 @@
     <string name="permlab_stopAppSwitches" msgid="4138608610717425573">"împiedicare comutare între aplicaţii"</string>
     <string name="permdesc_stopAppSwitches" msgid="8262195802582255021">"Împiedică trecerea utilizatorului la o altă aplicaţie."</string>
     <string name="permlab_getTopActivityInfo" msgid="2537922311411546016">"obținere informații despre aplicația curentă"</string>
-    <string name="permdesc_getTopActivityInfo" msgid="8153651434145132505">"Permite titularului să recupereze informații private despre aplicația și serviciile curente în prim-planul ecranului."</string>
+    <string name="permdesc_getTopActivityInfo" msgid="8153651434145132505">"Permite titularului să afișeze informații private despre aplicația și serviciile curente în prim-planul ecranului."</string>
     <string name="permlab_runSetActivityWatcher" msgid="892239094867182656">"monitorizare şi control asupra lansării tuturor aplicaţiilor"</string>
     <string name="permdesc_runSetActivityWatcher" msgid="6003603162578577406">"Permite aplicaţiei să monitorizeze şi să controleze modul în care sistemul lansează activităţi. Aplicaţiile rău intenţionate pot să compromită sistemul în întregime. Această permisiune este necesară doar pentru dezvoltare şi niciodată pentru utilizarea normală."</string>
     <string name="permlab_broadcastPackageRemoved" msgid="2576333434893532475">"trimitere mesaj difuzat privind extragerea din pachet"</string>
@@ -1579,4 +1579,8 @@
     <item quantity="one" msgid="4835639969503729874">"PIN incorect. Reîncercați în 1 sec."</item>
     <item quantity="other" msgid="8030607343223287654">"PIN incorect. Reîncercați în <xliff:g id="COUNT">%d</xliff:g> sec."</item>
   </plurals>
+    <!-- no translation found for transient_navigation_confirmation (4907844043611123426) -->
+    <skip />
+    <!-- no translation found for transient_navigation_confirmation_long (8061685920508086697) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-ru/strings.xml b/core/res/res/values-ru/strings.xml
index add1291..7730768 100644
--- a/core/res/res/values-ru/strings.xml
+++ b/core/res/res/values-ru/strings.xml
@@ -1579,4 +1579,8 @@
     <item quantity="one" msgid="4835639969503729874">"Неверный PIN-код. Повторите попытку через 1 сек."</item>
     <item quantity="other" msgid="8030607343223287654">"Неверный PIN-код. Повторите попытку через <xliff:g id="COUNT">%d</xliff:g> сек."</item>
   </plurals>
+    <!-- no translation found for transient_navigation_confirmation (4907844043611123426) -->
+    <skip />
+    <!-- no translation found for transient_navigation_confirmation_long (8061685920508086697) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-sk/strings.xml b/core/res/res/values-sk/strings.xml
index c33a7ea..ad333ac 100644
--- a/core/res/res/values-sk/strings.xml
+++ b/core/res/res/values-sk/strings.xml
@@ -1579,4 +1579,8 @@
     <item quantity="one" msgid="4835639969503729874">"Nespr. PIN. Skús. o 1 s"</item>
     <item quantity="other" msgid="8030607343223287654">"Nespr. PIN. Skús. o <xliff:g id="COUNT">%d</xliff:g> s"</item>
   </plurals>
+    <!-- no translation found for transient_navigation_confirmation (4907844043611123426) -->
+    <skip />
+    <!-- no translation found for transient_navigation_confirmation_long (8061685920508086697) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-sl/strings.xml b/core/res/res/values-sl/strings.xml
index 45cb215..2a68043 100644
--- a/core/res/res/values-sl/strings.xml
+++ b/core/res/res/values-sl/strings.xml
@@ -314,7 +314,7 @@
     <string name="permlab_stopAppSwitches" msgid="4138608610717425573">"preprečevanje preklopa programov"</string>
     <string name="permdesc_stopAppSwitches" msgid="8262195802582255021">"Uporabniku preprečuje preklop v drug program."</string>
     <string name="permlab_getTopActivityInfo" msgid="2537922311411546016">"pridobivanje podatkov o trenutni aplikaciji"</string>
-    <string name="permdesc_getTopActivityInfo" msgid="8153651434145132505">"Imetniku dovoli prenos zasebnih podatkov o trenutni aplikaciji in storitvah v ospredju zaslona."</string>
+    <string name="permdesc_getTopActivityInfo" msgid="8153651434145132505">"Imetniku dovoli pridobivanje zasebnih podatkov o trenutni aplikaciji in storitvah v ospredju zaslona."</string>
     <string name="permlab_runSetActivityWatcher" msgid="892239094867182656">"spremljanje in nadzor vseh zagonov programov"</string>
     <string name="permdesc_runSetActivityWatcher" msgid="6003603162578577406">"Programu omogoča spremljanje in nadziranje načina, kako sistem zažene dejavnosti. Zlonamerni programi lahko v celoti ogrozijo varnost sistema. To dovoljenje je potrebno samo za razvoj, vendar nikoli za običajno uporabo."</string>
     <string name="permlab_broadcastPackageRemoved" msgid="2576333434893532475">"pošiljanje oddaje brez paketa"</string>
@@ -1579,4 +1579,6 @@
     <item quantity="one" msgid="4835639969503729874">"Napačen PIN. Poskusite znova čez eno sekundo."</item>
     <item quantity="other" msgid="8030607343223287654">"Napačen PIN. Poskusite znova čez <xliff:g id="COUNT">%d</xliff:g> s."</item>
   </plurals>
+    <string name="transient_navigation_confirmation" msgid="4907844043611123426">"Povlecite z roba za prikaz vrstice"</string>
+    <string name="transient_navigation_confirmation_long" msgid="8061685920508086697">"Sistemsko vrstico prikažete tako, da povlečete z roba zaslona"</string>
 </resources>
diff --git a/core/res/res/values-sr/strings.xml b/core/res/res/values-sr/strings.xml
index 404590d..f0ad556 100644
--- a/core/res/res/values-sr/strings.xml
+++ b/core/res/res/values-sr/strings.xml
@@ -1579,4 +1579,8 @@
     <item quantity="one" msgid="4835639969503729874">"Нетачан PIN. Покушајте опет за 1 сек."</item>
     <item quantity="other" msgid="8030607343223287654">"Нетачан PIN. Покушајте опет за <xliff:g id="COUNT">%d</xliff:g> сек."</item>
   </plurals>
+    <!-- no translation found for transient_navigation_confirmation (4907844043611123426) -->
+    <skip />
+    <!-- no translation found for transient_navigation_confirmation_long (8061685920508086697) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-sv/strings.xml b/core/res/res/values-sv/strings.xml
index 221ddb6..3806a45 100644
--- a/core/res/res/values-sv/strings.xml
+++ b/core/res/res/values-sv/strings.xml
@@ -1579,4 +1579,8 @@
     <item quantity="one" msgid="4835639969503729874">"Fel pinkod. Försök igenom en sekund."</item>
     <item quantity="other" msgid="8030607343223287654">"Fel pinkod. Försök igenom om <xliff:g id="COUNT">%d</xliff:g> sekunder."</item>
   </plurals>
+    <!-- no translation found for transient_navigation_confirmation (4907844043611123426) -->
+    <skip />
+    <!-- no translation found for transient_navigation_confirmation_long (8061685920508086697) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-sw/strings.xml b/core/res/res/values-sw/strings.xml
index 767bf44..298a651 100644
--- a/core/res/res/values-sw/strings.xml
+++ b/core/res/res/values-sw/strings.xml
@@ -560,8 +560,8 @@
     <string name="permdesc_setTime" product="tablet" msgid="1896341438151152881">"Inaruhusu programu kubadilisha wakati wa saa ya kompyuta kibao."</string>
     <string name="permdesc_setTime" product="default" msgid="1855702730738020">"Inaruhusu programu kubadilisha wakati wa saa ya simu."</string>
     <string name="permlab_setTimeZone" msgid="2945079801013077340">"weka saa za eneo"</string>
-    <string name="permdesc_setTimeZone" product="tablet" msgid="1676983712315827645">"Inaruhusu programu kubadilisha  majira ya saa ya kompyuta kibao."</string>
-    <string name="permdesc_setTimeZone" product="default" msgid="4499943488436633398">"Inaruhusu programu kubadilisha  majira ya saa ya simu."</string>
+    <string name="permdesc_setTimeZone" product="tablet" msgid="1676983712315827645">"Huruhusu programu kubadilisha saa za eneo katika kompyuta kibao."</string>
+    <string name="permdesc_setTimeZone" product="default" msgid="4499943488436633398">"Huruhusu programu kubadilisha saa za eneo katika simu."</string>
     <string name="permlab_accountManagerService" msgid="4829262349691386986">"tenda kama Huduma ya Meneja wa Akaunti"</string>
     <string name="permdesc_accountManagerService" msgid="1948455552333615954">"Huruhusu programu kupiga simu kwa Wathibitishaji Akaunti."</string>
     <string name="permlab_getAccounts" msgid="1086795467760122114">"pata akaunti kwenye kifaa"</string>
@@ -1579,4 +1579,6 @@
     <item quantity="one" msgid="4835639969503729874">"PIN sio sahihi. Jaribu tena baada ya sekunde 1."</item>
     <item quantity="other" msgid="8030607343223287654">"PIN sio sahihi. Jaribu tena baada ya sekunde <xliff:g id="COUNT">%d</xliff:g>."</item>
   </plurals>
+    <string name="transient_navigation_confirmation" msgid="4907844043611123426">"Telezesha kidole kutoka ukingo wa skrini ili kuonyesha upau"</string>
+    <string name="transient_navigation_confirmation_long" msgid="8061685920508086697">"Telezesha kidole kutoka ukingo wa skrini ili kuonyesha upau wa mfumo"</string>
 </resources>
diff --git a/core/res/res/values-th/strings.xml b/core/res/res/values-th/strings.xml
index 03d0907..d49d7c5 100644
--- a/core/res/res/values-th/strings.xml
+++ b/core/res/res/values-th/strings.xml
@@ -1579,4 +1579,8 @@
     <item quantity="one" msgid="4835639969503729874">"PIN ไม่ถูกต้อง โปรดลองอีกครั้งในอีก 1 วินาที"</item>
     <item quantity="other" msgid="8030607343223287654">"PIN ไม่ถูกต้อง โปรดลองอีกครั้งในอีก <xliff:g id="COUNT">%d</xliff:g> วินาที"</item>
   </plurals>
+    <!-- no translation found for transient_navigation_confirmation (4907844043611123426) -->
+    <skip />
+    <!-- no translation found for transient_navigation_confirmation_long (8061685920508086697) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-tl/strings.xml b/core/res/res/values-tl/strings.xml
index e3f9775..c43918c 100644
--- a/core/res/res/values-tl/strings.xml
+++ b/core/res/res/values-tl/strings.xml
@@ -1579,4 +1579,8 @@
     <item quantity="one" msgid="4835639969503729874">"Mali ang PIN. Subukang muli pagkalipas ng 1 segundo."</item>
     <item quantity="other" msgid="8030607343223287654">"Mali ang PIN. Subukang muli pagkalipas ng <xliff:g id="COUNT">%d</xliff:g> (na) segundo."</item>
   </plurals>
+    <!-- no translation found for transient_navigation_confirmation (4907844043611123426) -->
+    <skip />
+    <!-- no translation found for transient_navigation_confirmation_long (8061685920508086697) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-tr/strings.xml b/core/res/res/values-tr/strings.xml
index 925fea7..ab50621 100644
--- a/core/res/res/values-tr/strings.xml
+++ b/core/res/res/values-tr/strings.xml
@@ -1579,4 +1579,8 @@
     <item quantity="one" msgid="4835639969503729874">"Yanlış PIN. 1 saniye içinde tekrar deneyin."</item>
     <item quantity="other" msgid="8030607343223287654">"Yanlış PIN. <xliff:g id="COUNT">%d</xliff:g> saniye içinde tekrar deneyin."</item>
   </plurals>
+    <!-- no translation found for transient_navigation_confirmation (4907844043611123426) -->
+    <skip />
+    <!-- no translation found for transient_navigation_confirmation_long (8061685920508086697) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-uk/strings.xml b/core/res/res/values-uk/strings.xml
index 41ca8c6..de4267f 100644
--- a/core/res/res/values-uk/strings.xml
+++ b/core/res/res/values-uk/strings.xml
@@ -1579,4 +1579,6 @@
     <item quantity="one" msgid="4835639969503729874">"Неправильний PIN. Повторіть через 1 с."</item>
     <item quantity="other" msgid="8030607343223287654">"Неправильний PIN. Повторіть через <xliff:g id="COUNT">%d</xliff:g> с."</item>
   </plurals>
+    <string name="transient_navigation_confirmation" msgid="4907844043611123426">"Гортайте від краю, щоб відкрити панель"</string>
+    <string name="transient_navigation_confirmation_long" msgid="8061685920508086697">"Проведіть пальцем від краю екрана, щоб з’явилась навігаційна панель"</string>
 </resources>
diff --git a/core/res/res/values-vi/strings.xml b/core/res/res/values-vi/strings.xml
index ef96b32..2fa022a 100644
--- a/core/res/res/values-vi/strings.xml
+++ b/core/res/res/values-vi/strings.xml
@@ -1579,4 +1579,8 @@
     <item quantity="one" msgid="4835639969503729874">"Mã PIN không đúng. Hãy thử lại sau 1 giây nữa."</item>
     <item quantity="other" msgid="8030607343223287654">"Mã PIN không đúng. Hãy thử lại sau <xliff:g id="COUNT">%d</xliff:g> giây nữa."</item>
   </plurals>
+    <!-- no translation found for transient_navigation_confirmation (4907844043611123426) -->
+    <skip />
+    <!-- no translation found for transient_navigation_confirmation_long (8061685920508086697) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-zh-rCN/strings.xml b/core/res/res/values-zh-rCN/strings.xml
index b4af5d0..5f2757e 100644
--- a/core/res/res/values-zh-rCN/strings.xml
+++ b/core/res/res/values-zh-rCN/strings.xml
@@ -1579,4 +1579,8 @@
     <item quantity="one" msgid="4835639969503729874">"PIN 码错误。请在1秒钟后重试。"</item>
     <item quantity="other" msgid="8030607343223287654">"PIN 码错误。请在<xliff:g id="COUNT">%d</xliff:g>秒钟后重试。"</item>
   </plurals>
+    <!-- no translation found for transient_navigation_confirmation (4907844043611123426) -->
+    <skip />
+    <!-- no translation found for transient_navigation_confirmation_long (8061685920508086697) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-zh-rTW/strings.xml b/core/res/res/values-zh-rTW/strings.xml
index 062e415..f0d4bb7 100644
--- a/core/res/res/values-zh-rTW/strings.xml
+++ b/core/res/res/values-zh-rTW/strings.xml
@@ -314,7 +314,7 @@
     <string name="permlab_stopAppSwitches" msgid="4138608610717425573">"防止切換應用程式"</string>
     <string name="permdesc_stopAppSwitches" msgid="8262195802582255021">"防止使用者切換到其他應用程式。"</string>
     <string name="permlab_getTopActivityInfo" msgid="2537922311411546016">"取得目前的應用程式資訊"</string>
-    <string name="permdesc_getTopActivityInfo" msgid="8153651434145132505">"允許應用程式針對目前在螢幕前景運作的應用程式與服務擷取相關私人資訊。"</string>
+    <string name="permdesc_getTopActivityInfo" msgid="8153651434145132505">"允許應用程式擷取目前在螢幕前景運作的應用程式和服務的不公開資訊。"</string>
     <string name="permlab_runSetActivityWatcher" msgid="892239094867182656">"監視及控制所有應用程式的啟動程序"</string>
     <string name="permdesc_runSetActivityWatcher" msgid="6003603162578577406">"允許應用程式監視和控制系統啟動活動的方式。請注意,惡意應用程式可能利用此功能破壞整個系統。這個權限只有開發人員才需要,一般使用者不需使用這個權限。"</string>
     <string name="permlab_broadcastPackageRemoved" msgid="2576333434893532475">"傳送程式已移除廣播"</string>
@@ -1579,4 +1579,8 @@
     <item quantity="one" msgid="4835639969503729874">"PIN 不正確,請於 1 秒後再試一次。"</item>
     <item quantity="other" msgid="8030607343223287654">"PIN 不正確,請於 <xliff:g id="COUNT">%d</xliff:g> 秒後再試一次。"</item>
   </plurals>
+    <!-- no translation found for transient_navigation_confirmation (4907844043611123426) -->
+    <skip />
+    <!-- no translation found for transient_navigation_confirmation_long (8061685920508086697) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-zu/strings.xml b/core/res/res/values-zu/strings.xml
index 538299b..015c31d 100644
--- a/core/res/res/values-zu/strings.xml
+++ b/core/res/res/values-zu/strings.xml
@@ -1579,4 +1579,6 @@
     <item quantity="one" msgid="4835639969503729874">"I-PIN engalungile. Zama futhi esekhondini elingu-1."</item>
     <item quantity="other" msgid="8030607343223287654">"I-PIN engalungile. Zama futhi emasekhondini angu-<xliff:g id="COUNT">%d</xliff:g>."</item>
   </plurals>
+    <string name="transient_navigation_confirmation" msgid="4907844043611123426">"Swayipha kunqenqema lwesikrini ukuze uveze ibha"</string>
+    <string name="transient_navigation_confirmation_long" msgid="8061685920508086697">"Swayipha kusukela kunqenqema ukuze uveze ibha yesistimu"</string>
 </resources>
diff --git a/core/res/res/values/attrs.xml b/core/res/res/values/attrs.xml
index 03e9045..50ea08b 100644
--- a/core/res/res/values/attrs.xml
+++ b/core/res/res/values/attrs.xml
@@ -2378,6 +2378,9 @@
         <!-- Set to true in all of the configurations for which this input
              method should be considered an option as the default. -->
         <attr name="isDefault" format="boolean" />
+        <!-- Set to true if this input method supports ways to switch to
+             a next input method (e.g. a globe key.). -->
+        <attr name="supportsSwitchingToNextInputMethod" format="boolean" />
     </declare-styleable>
 
     <!-- This is the subtype of InputMethod. Subtype can describe locales (e.g. en_US, fr_FR...)
diff --git a/core/res/res/values/donottranslate.xml b/core/res/res/values/donottranslate.xml
index b49e7bd..a7288e1 100644
--- a/core/res/res/values/donottranslate.xml
+++ b/core/res/res/values/donottranslate.xml
@@ -24,8 +24,6 @@
     <bool name="lockscreen_isPortrait">true</bool>
     <!-- @hide DO NOT TRANSLATE. Control aspect ratio of lock pattern -->
     <string name="lock_pattern_view_aspect">square</string>
-    <!-- @hide DO NOT TRANSLATE. Separator between the hour and minute elements in a TimePicker widget -->
-    <string name="time_picker_separator">:</string>
     <!-- @hide DO NOT TRANSLATE. ICU pattern for "Mon, 14 January" -->
     <string name="icu_abbrev_wday_month_day_no_year">eeeMMMMd</string>
     <!-- @hide DO NOT TRANSLATE. date formatting pattern for system ui.-->
diff --git a/core/res/res/values/public.xml b/core/res/res/values/public.xml
index 80c9184..f2ec04f 100644
--- a/core/res/res/values/public.xml
+++ b/core/res/res/values/public.xml
@@ -2072,5 +2072,6 @@
   <public type="attr" name="isAsciiCapable" />
   <public type="attr" name="customRoots" />
   <public type="attr" name="autoMirrored" />
+  <public type="attr" name="supportsSwitchingToNextInputMethod" />
 
 </resources>
diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml
index 14ae1e6..ca93d1c 100755
--- a/core/res/res/values/symbols.xml
+++ b/core/res/res/values/symbols.xml
@@ -217,6 +217,7 @@
   <java-symbol type="id" name="pin_new_text" />
   <java-symbol type="id" name="pin_confirm_text" />
   <java-symbol type="id" name="pin_error_message" />
+  <java-symbol type="id" name="timePickerLayout" />
 
   <java-symbol type="attr" name="actionModeShareDrawable" />
   <java-symbol type="attr" name="alertDialogCenterButtons" />
@@ -773,7 +774,6 @@
   <java-symbol type="string" name="time_picker_increment_hour_button" />
   <java-symbol type="string" name="time_picker_increment_minute_button" />
   <java-symbol type="string" name="time_picker_increment_set_pm_button" />
-  <java-symbol type="string" name="time_picker_separator" />
   <java-symbol type="string" name="upload_file" />
   <java-symbol type="string" name="user_switched" />
   <java-symbol type="string" name="volume_alarm" />
diff --git a/docs/downloads/design/roboto-1.100141.zip b/docs/downloads/design/roboto-1.100141.zip
new file mode 100644
index 0000000..93dfda7
--- /dev/null
+++ b/docs/downloads/design/roboto-1.100141.zip
Binary files differ
diff --git a/docs/html/design/downloads/index.jd b/docs/html/design/downloads/index.jd
index b13ba62..6d9a60d 100644
--- a/docs/html/design/downloads/index.jd
+++ b/docs/html/design/downloads/index.jd
@@ -102,7 +102,7 @@
 
 <p>
   <a class="download-button"  onClick="_gaq.push(['_trackEvent', 'Design', 'Download', 'Roboto ZIP']);"
-    href="https://github.com/google/roboto/archive/latest-hinted.zip">Roboto</a>
+    href="{@docRoot}downloads/design/roboto-1.100141.zip">Roboto</a>
   <a class="download-button"  onClick="_gaq.push(['_trackEvent', 'Design', 'Download', 'Roboto Specemin Book']);"
     href="{@docRoot}downloads/design/Roboto_Specimen_Book_20111129.pdf">Specimen Book</a>
 </p>
diff --git a/docs/html/design/style/typography.jd b/docs/html/design/style/typography.jd
index 0d681ab..818af4c 100644
--- a/docs/html/design/style/typography.jd
+++ b/docs/html/design/style/typography.jd
@@ -12,7 +12,7 @@
 
 <p>
   <a class="download-button"  onClick="_gaq.push(['_trackEvent', 'Design', 'Download', 'Roboto ZIP']);"
-    href="https://github.com/google/roboto/archive/latest-hinted.zip">Download Roboto</a>
+    href="{@docRoot}downloads/design/roboto-1.100141.zip">Download Roboto</a>
 </p>
 
 <p>The Android design language relies on traditional typographic tools such as scale, space, rhythm,
diff --git a/libs/hwui/Caches.cpp b/libs/hwui/Caches.cpp
index df966e1..c0b3bfc 100644
--- a/libs/hwui/Caches.cpp
+++ b/libs/hwui/Caches.cpp
@@ -226,6 +226,8 @@
 
     patchCache.clear();
 
+    clearGarbage();
+
     mInitialized = false;
 }
 
@@ -331,6 +333,11 @@
 void Caches::flush(FlushMode mode) {
     FLUSH_LOGD("Flushing caches (mode %d)", mode);
 
+    // We must stop tasks before clearing caches
+    if (mode > kFlushMode_Layers) {
+        tasks.stop();
+    }
+
     switch (mode) {
         case kFlushMode_Full:
             textureCache.clear();
@@ -338,13 +345,13 @@
             dropShadowCache.clear();
             gradientCache.clear();
             fontRenderer->clear();
+            fboCache.clear();
             dither.clear();
             // fall through
         case kFlushMode_Moderate:
             fontRenderer->flush();
             textureCache.flush();
             pathCache.clear();
-            tasks.stop();
             // fall through
         case kFlushMode_Layers:
             layerCache.clear();
diff --git a/location/java/android/location/LocationRequest.java b/location/java/android/location/LocationRequest.java
index ee748d39..c9162fe 100644
--- a/location/java/android/location/LocationRequest.java
+++ b/location/java/android/location/LocationRequest.java
@@ -146,7 +146,7 @@
     private long mExpireAt = Long.MAX_VALUE;  // no expiry
     private int mNumUpdates = Integer.MAX_VALUE;  // no expiry
     private float mSmallestDisplacement = 0.0f;    // meters
-    private WorkSource mWorkSource = new WorkSource();
+    private WorkSource mWorkSource = null;
     private boolean mHideFromAppOps = false; // True if this request shouldn't be counted by AppOps
 
     private String mProvider = LocationManager.FUSED_PROVIDER;  // for deprecated APIs that explicitly request a provider
@@ -498,7 +498,16 @@
         return mSmallestDisplacement;
     }
 
-    /** @hide */
+    /**
+     * Sets the WorkSource to use for power blaming of this location request.
+     *
+     * <p>No permissions are required to make this call, however the LocationManager
+     * will throw a SecurityException when requesting location updates if the caller
+     * doesn't have the {@link android.Manifest.permission#UPDATE_DEVICE_STATS} permission.
+     *
+     * @param workSource WorkSource defining power blame for this location request.
+     * @hide
+     */
     public void setWorkSource(WorkSource workSource) {
         mWorkSource = workSource;
     }
@@ -508,7 +517,20 @@
         return mWorkSource;
     }
 
-    /** @hide */
+    /**
+     * Sets whether or not this location request should be hidden from AppOps.
+     *
+     * <p>Hiding a location request from AppOps will remove user visibility in the UI as to this
+     * request's existence.  It does not affect power blaming in the Battery page.
+     *
+     * <p>No permissions are required to make this call, however the LocationManager
+     * will throw a SecurityException when requesting location updates if the caller
+     * doesn't have the {@link android.Manifest.permission#UPDATE_APP_OPS_STATS} permission.
+     *
+     * @param hideFromAppOps If true AppOps won't keep track of this location request.
+     * @see android.app.AppOpsManager
+     * @hide
+     */
     public void setHideFromAppOps(boolean hideFromAppOps) {
         mHideFromAppOps = hideFromAppOps;
     }
@@ -564,7 +586,7 @@
             request.setHideFromAppOps(in.readInt() != 0);
             String provider = in.readString();
             if (provider != null) request.setProvider(provider);
-            WorkSource workSource = in.readParcelable(WorkSource.class.getClassLoader());
+            WorkSource workSource = in.readParcelable(null);
             if (workSource != null) request.setWorkSource(workSource);
             return request;
         }
diff --git a/media/java/android/media/AudioManager.java b/media/java/android/media/AudioManager.java
index 14cdbb7..ef02cfd 100644
--- a/media/java/android/media/AudioManager.java
+++ b/media/java/android/media/AudioManager.java
@@ -2387,6 +2387,35 @@
         }
     }
 
+    /**
+     * @hide
+     * Notifies AudioService that it is connected to an A2DP device that supports absolute volume,
+     * so that AudioService can send volume change events to the A2DP device, rather than handling
+     * them.
+     */
+    public void avrcpSupportsAbsoluteVolume(String address, boolean support) {
+        IAudioService service = getService();
+        try {
+            service.avrcpSupportsAbsoluteVolume(address, support);
+        } catch (RemoteException e) {
+            Log.e(TAG, "Dead object in avrcpSupportsAbsoluteVolume", e);
+        }
+    }
+
+    /**
+     * @hide
+     * Notifies AudioService of the volume set on the A2DP device as a callback, so AudioService
+     * is able to update the UI.
+     */
+    public void avrcpUpdateVolume(int oldVolume, int volume) {
+        IAudioService service = getService();
+        try {
+            service.avrcpUpdateVolume(oldVolume, volume);
+        } catch (RemoteException e) {
+            Log.e(TAG, "Dead object in avrcpUpdateVolume", e);
+        }
+    }
+
      /**
       * {@hide}
       */
diff --git a/media/java/android/media/AudioService.java b/media/java/android/media/AudioService.java
index 290866e..470c571 100644
--- a/media/java/android/media/AudioService.java
+++ b/media/java/android/media/AudioService.java
@@ -460,6 +460,12 @@
 
     private final MediaFocusControl mMediaFocusControl;
 
+    // Reference to BluetoothA2dp to query for AbsoluteVolume.
+    private BluetoothA2dp mA2dp;
+    private final Object mA2dpAvrcpLock = new Object();
+    // If absolute volume is supported in AVRCP device
+    private boolean mAvrcpAbsVolSupported = false;
+
     ///////////////////////////////////////////////////////////////////////////
     // Construction
     ///////////////////////////////////////////////////////////////////////////
@@ -901,6 +907,15 @@
         int oldIndex = mStreamStates[streamType].getIndex(device);
 
         if (adjustVolume && (direction != AudioManager.ADJUST_SAME)) {
+            // Check if volume update should be send to AVRCP
+            synchronized (mA2dpAvrcpLock) {
+                if (mA2dp != null && mAvrcpAbsVolSupported) {
+                    mA2dp.adjustAvrcpAbsoluteVolume(direction);
+                    return;
+                    // No need to send volume update, because we will update the volume with a
+                    // callback from Avrcp.
+                }
+            }
             if ((direction == AudioManager.ADJUST_RAISE) &&
                     !checkSafeMediaVolume(streamTypeAlias, aliasIndex + step, device)) {
                 Log.e(TAG, "adjustStreamVolume() safe volume index = "+oldIndex);
@@ -998,6 +1013,15 @@
 
             index = rescaleIndex(index * 10, streamType, streamTypeAlias);
 
+            synchronized (mA2dpAvrcpLock) {
+                if (mA2dp != null && mAvrcpAbsVolSupported) {
+                    mA2dp.setAvrcpAbsoluteVolume(index);
+                    return;
+                    // No need to send volume update, because we will update the volume with a
+                    // callback from Avrcp.
+                }
+            }
+
             flags &= ~AudioManager.FLAG_FIXED_VOLUME;
             if ((streamTypeAlias == AudioSystem.STREAM_MUSIC) &&
                     ((device & mFixedVolumeDevices) != 0)) {
@@ -2268,21 +2292,23 @@
             List<BluetoothDevice> deviceList;
             switch(profile) {
             case BluetoothProfile.A2DP:
-                BluetoothA2dp a2dp = (BluetoothA2dp) proxy;
-                deviceList = a2dp.getConnectedDevices();
-                if (deviceList.size() > 0) {
-                    btDevice = deviceList.get(0);
-                    synchronized (mConnectedDevices) {
-                        int state = a2dp.getConnectionState(btDevice);
-                        int delay = checkSendBecomingNoisyIntent(
-                                                AudioSystem.DEVICE_OUT_BLUETOOTH_A2DP,
-                                                (state == BluetoothA2dp.STATE_CONNECTED) ? 1 : 0);
-                        queueMsgUnderWakeLock(mAudioHandler,
-                                MSG_SET_A2DP_CONNECTION_STATE,
-                                state,
-                                0,
-                                btDevice,
-                                delay);
+                synchronized (mA2dpAvrcpLock) {
+                    mA2dp = (BluetoothA2dp) proxy;
+                    deviceList = mA2dp.getConnectedDevices();
+                    if (deviceList.size() > 0) {
+                        btDevice = deviceList.get(0);
+                        synchronized (mConnectedDevices) {
+                            int state = mA2dp.getConnectionState(btDevice);
+                            int delay = checkSendBecomingNoisyIntent(
+                                                    AudioSystem.DEVICE_OUT_BLUETOOTH_A2DP,
+                                                    (state == BluetoothA2dp.STATE_CONNECTED) ? 1 : 0);
+                            queueMsgUnderWakeLock(mAudioHandler,
+                                    MSG_SET_A2DP_CONNECTION_STATE,
+                                    state,
+                                    0,
+                                    btDevice,
+                                    delay);
+                        }
                     }
                 }
                 break;
@@ -2344,10 +2370,13 @@
         public void onServiceDisconnected(int profile) {
             switch(profile) {
             case BluetoothProfile.A2DP:
-                synchronized (mConnectedDevices) {
-                    if (mConnectedDevices.containsKey(AudioSystem.DEVICE_OUT_BLUETOOTH_A2DP)) {
-                        makeA2dpDeviceUnavailableNow(
-                                mConnectedDevices.get(AudioSystem.DEVICE_OUT_BLUETOOTH_A2DP));
+                synchronized (mA2dpAvrcpLock) {
+                    mA2dp = null;
+                    synchronized (mConnectedDevices) {
+                        if (mConnectedDevices.containsKey(AudioSystem.DEVICE_OUT_BLUETOOTH_A2DP)) {
+                            makeA2dpDeviceUnavailableNow(
+                                    mConnectedDevices.get(AudioSystem.DEVICE_OUT_BLUETOOTH_A2DP));
+                        }
                     }
                 }
                 break;
@@ -3697,6 +3726,7 @@
 
     private void onSetA2dpConnectionState(BluetoothDevice btDevice, int state)
     {
+        if (DEBUG_VOL) Log.d(TAG, "onSetA2dpConnectionState btDevice="+btDevice+" state="+state);
         if (btDevice == null) {
             return;
         }
@@ -3704,6 +3734,20 @@
         if (!BluetoothAdapter.checkBluetoothAddress(address)) {
             address = "";
         }
+
+        // Disable absolute volume, if device is disconnected
+        synchronized (mA2dpAvrcpLock) {
+            if (state == BluetoothProfile.STATE_DISCONNECTED && mAvrcpAbsVolSupported) {
+                mAvrcpAbsVolSupported = false;
+                sendMsg(mAudioHandler,
+                        MSG_SET_DEVICE_VOLUME,
+                        SENDMSG_QUEUE,
+                        getDeviceForStream(AudioSystem.STREAM_MUSIC),
+                        0,
+                        mStreamStates[AudioSystem.STREAM_MUSIC],
+                        0);
+            }
+        }
         synchronized (mConnectedDevices) {
             boolean isConnected =
                 (mConnectedDevices.containsKey(AudioSystem.DEVICE_OUT_BLUETOOTH_A2DP) &&
@@ -3754,6 +3798,31 @@
         }
     }
 
+    public void avrcpSupportsAbsoluteVolume(String address, boolean support) {
+        // address is not used for now, but may be used when multiple a2dp devices are supported
+        synchronized (mA2dpAvrcpLock) {
+            mAvrcpAbsVolSupported = support;
+            if (support) {
+                VolumeStreamState streamState = mStreamStates[AudioSystem.STREAM_MUSIC];
+                int device = getDeviceForStream(AudioSystem.STREAM_MUSIC);
+                streamState.setIndex(streamState.getMaxIndex(), device);
+                sendMsg(mAudioHandler,
+                        MSG_SET_DEVICE_VOLUME,
+                        SENDMSG_QUEUE,
+                        device,
+                        0,
+                        streamState,
+                        0);
+            }
+        }
+    }
+
+    public void avrcpUpdateVolume(int oldVolume, int volume) {
+        mStreamStates[AudioSystem.STREAM_MUSIC].
+                        setIndex(volume, getDeviceForStream(AudioSystem.STREAM_MUSIC));
+        sendVolumeUpdate(AudioSystem.STREAM_MUSIC, oldVolume, volume, AudioManager.FLAG_SHOW_UI);
+    }
+
     private boolean handleDeviceConnection(boolean connected, int device, String params) {
         synchronized (mConnectedDevices) {
             boolean isConnected = (mConnectedDevices.containsKey(device) &&
diff --git a/media/java/android/media/IAudioService.aidl b/media/java/android/media/IAudioService.aidl
index b4c8a04..903927b 100644
--- a/media/java/android/media/IAudioService.aidl
+++ b/media/java/android/media/IAudioService.aidl
@@ -98,6 +98,10 @@
 
     oneway void reloadAudioSettings();
 
+    oneway void avrcpSupportsAbsoluteVolume(String address, boolean support);
+
+    oneway void avrcpUpdateVolume(int oldVolume, int volume);
+
     void setSpeakerphoneOn(boolean on);
 
     boolean isSpeakerphoneOn();
diff --git a/media/java/android/media/ImageReader.java b/media/java/android/media/ImageReader.java
index 8ddc094..f3356c9 100644
--- a/media/java/android/media/ImageReader.java
+++ b/media/java/android/media/ImageReader.java
@@ -20,7 +20,6 @@
 import android.graphics.PixelFormat;
 import android.os.Handler;
 import android.os.Looper;
-import android.os.Message;
 import android.view.Surface;
 
 import java.lang.ref.WeakReference;
@@ -130,11 +129,26 @@
     }
 
     /**
-     * <p>Get the next Image from the ImageReader's queue. Returns {@code null}
-     * if no new image is available.</p>
+     * <p>
+     * Get the next Image from the ImageReader's queue. Returns {@code null} if
+     * no new image is available.
+     * </p>
+     * <p>
+     * This operation will fail by throwing an
+     * {@link Surface.OutOfResourcesException OutOfResourcesException} if too
+     * many images have been acquired with {@link #getNextImage}. In particular
+     * a sequence of {@link #getNextImage} calls greater than {@link #getMaxImages}
+     * without calling {@link Image#close} or {@link #releaseImage} in-between
+     * will exhaust the underlying queue. At such a time,
+     * {@link Surface.OutOfResourcesException OutOfResourcesException} will be
+     * thrown until more images are released with {@link Image#close} or
+     * {@link #releaseImage}.
+     * </p>
      *
      * @return a new frame of image data, or {@code null} if no image data is
-     * available.
+     *         available.
+     * @throws Surface.OutOfResourcesException if too many images are currently
+     *         acquired
      */
     public Image getNextImage() {
         SurfaceImage si = new SurfaceImage();
@@ -172,6 +186,8 @@
      * @param listener the listener that will be run
      * @param handler The handler on which the listener should be invoked, or null
      * if the listener should be invoked on the calling thread's looper.
+     *
+     * @throws IllegalArgumentException if no handler specified and the calling thread has no looper
      */
    public void setImageAvailableListener(OnImageAvailableListener listener, Handler handler) {
         mImageListener = listener;
@@ -260,8 +276,9 @@
      * Called from Native code when an Event happens.
      */
     private static void postEventFromNative(Object selfRef) {
-        WeakReference weakSelf = (WeakReference)selfRef;
-        final ImageReader ir = (ImageReader)weakSelf.get();
+        @SuppressWarnings("unchecked")
+        WeakReference<ImageReader> weakSelf = (WeakReference<ImageReader>)selfRef;
+        final ImageReader ir = weakSelf.get();
         if (ir == null) {
             return;
         }
diff --git a/media/java/android/media/MediaFormat.java b/media/java/android/media/MediaFormat.java
index 3fbaf69..278d661 100644
--- a/media/java/android/media/MediaFormat.java
+++ b/media/java/android/media/MediaFormat.java
@@ -26,7 +26,7 @@
  *
  * The format of the media data is specified as string/value pairs.
  *
- * Keys common to all formats, <b>all keys not marked optional are mandatory</b>:
+ * Keys common to all audio/video formats, <b>all keys not marked optional are mandatory</b>:
  *
  * <table>
  * <tr><th>Name</th><th>Value Type</th><th>Description</th></tr>
@@ -57,6 +57,11 @@
  * <tr><td>{@link #KEY_FLAC_COMPRESSION_LEVEL}</td><td>Integer</td><td><b>encoder-only</b>, optional, if content is FLAC audio, specifies the desired compression level.</td></tr>
  * </table>
  *
+ * Subtitle formats have the following keys:
+ * <table>
+ * <tr><td>{@link #KEY_MIME}</td><td>String</td><td>The type of the format.</td></tr>
+ * <tr><td>{@link #KEY_LANGUAGE}</td><td>String</td><td>The language of the content.</td></tr>
+ * </table>
  */
 public final class MediaFormat {
     private Map<String, Object> mMap;
@@ -68,6 +73,12 @@
     public static final String KEY_MIME = "mime";
 
     /**
+     * A key describing the language of the content.
+     * The associated value is a string.
+     */
+    public static final String KEY_LANGUAGE = "language";
+
+    /**
      * A key describing the sample rate of an audio format.
      * The associated value is an integer
      */
@@ -277,6 +288,23 @@
     }
 
     /**
+     * Creates a minimal subtitle format.
+     * @param mime The mime type of the content.
+     * @param language The language of the content.  Specify "und" if language
+     *        information is only included in the content (similarly, if there
+     *        are multiple language tracks in the content.)
+     */
+    public static final MediaFormat createSubtitleFormat(
+            String mime,
+            String language) {
+        MediaFormat format = new MediaFormat();
+        format.setString(KEY_MIME, mime);
+        format.setString(KEY_LANGUAGE, language);
+
+        return format;
+    }
+
+    /**
      * Creates a minimal video format.
      * @param mime The mime type of the content.
      * @param width The width of the content (in pixels)
diff --git a/media/jni/android_media_ImageReader.cpp b/media/jni/android_media_ImageReader.cpp
index cd589de..7d914d2 100644
--- a/media/jni/android_media_ImageReader.cpp
+++ b/media/jni/android_media_ImageReader.cpp
@@ -44,6 +44,9 @@
 
 using namespace android;
 
+static const char* const OutOfResourcesException =
+    "android/view/Surface$OutOfResourcesException";
+
 enum {
     IMAGE_READER_MAX_NUM_PLANES = 3,
 };
@@ -609,7 +612,8 @@
     nativeFormat = Image_getPixelFormat(env, format);
 
     sp<BufferQueue> bq = new BufferQueue();
-    sp<CpuConsumer> consumer = new CpuConsumer(bq, true, maxImages);
+    sp<CpuConsumer> consumer = new CpuConsumer(bq, maxImages,
+                                               /*controlledByApp*/true);
     // TODO: throw dvm exOutOfMemoryError?
     if (consumer == NULL) {
         jniThrowRuntimeException(env, "Failed to allocate native CpuConsumer");
@@ -702,7 +706,17 @@
     status_t res = consumer->lockNextBuffer(buffer);
     if (res != NO_ERROR) {
         if (res != BAD_VALUE /*no buffers*/) {
-            ALOGE("%s Fail to lockNextBuffer with error: %d ", __FUNCTION__, res);
+            if (res == NOT_ENOUGH_DATA) {
+                jniThrowException(env, OutOfResourcesException,
+                          "Too many outstanding images, close existing images"
+                          " to be able to acquire more.");
+            } else {
+                ALOGE("%s Fail to lockNextBuffer with error: %d ",
+                      __FUNCTION__, res);
+                jniThrowExceptionFmt(env, "java/lang/IllegalStateException",
+                          "Unknown error (%d) when we tried to lock buffer.",
+                          res);
+            }
         }
         return false;
     }
@@ -714,6 +728,7 @@
         ALOGE("crop left: %d, top = %d", lt.x, lt.y);
         jniThrowException(env, "java/lang/UnsupportedOperationException",
                           "crop left top corner need to at origin");
+        return false;
     }
 
     // Check if the producer buffer configurations match what ImageReader configured.
diff --git a/media/jni/android_media_MediaDrm.cpp b/media/jni/android_media_MediaDrm.cpp
index 16a1e48..60142cd 100644
--- a/media/jni/android_media_MediaDrm.cpp
+++ b/media/jni/android_media_MediaDrm.cpp
@@ -753,7 +753,9 @@
 
     status_t err = drm->provideKeyResponse(sessionId, response, keySetId);
 
-    throwExceptionAsNecessary(env, err, "Failed to handle key response");
+    if (throwExceptionAsNecessary(env, err, "Failed to handle key response")) {
+        return NULL;
+    }
     return VectorToJByteArray(env, keySetId);
 }
 
@@ -1104,7 +1106,9 @@
 
     status_t err = drm->encrypt(sessionId, keyId, input, iv, output);
 
-    throwExceptionAsNecessary(env, err, "Failed to encrypt");
+    if (throwExceptionAsNecessary(env, err, "Failed to encrypt")) {
+        return NULL;
+    }
 
     return VectorToJByteArray(env, output);
 }
@@ -1132,7 +1136,9 @@
     Vector<uint8_t> output;
 
     status_t err = drm->decrypt(sessionId, keyId, input, iv, output);
-    throwExceptionAsNecessary(env, err, "Failed to decrypt");
+    if (throwExceptionAsNecessary(env, err, "Failed to decrypt")) {
+        return NULL;
+    }
 
     return VectorToJByteArray(env, output);
 }
@@ -1160,7 +1166,9 @@
 
     status_t err = drm->sign(sessionId, keyId, message, signature);
 
-    throwExceptionAsNecessary(env, err, "Failed to sign");
+    if (throwExceptionAsNecessary(env, err, "Failed to sign")) {
+        return NULL;
+    }
 
     return VectorToJByteArray(env, signature);
 }
diff --git a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/integration/CameraBinderTest.java b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/integration/CameraBinderTest.java
index 9057f60..624bbaa 100644
--- a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/integration/CameraBinderTest.java
+++ b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/integration/CameraBinderTest.java
@@ -25,6 +25,8 @@
 import android.hardware.camera2.CameraMetadata;
 import android.hardware.camera2.ICameraDeviceCallbacks;
 import android.hardware.camera2.ICameraDeviceUser;
+import android.hardware.camera2.utils.BinderHolder;
+import android.hardware.camera2.utils.CameraBinderDecorator;
 import android.os.Binder;
 import android.os.IBinder;
 import android.os.RemoteException;
@@ -109,9 +111,11 @@
 
             String clientPackageName = getContext().getPackageName();
 
-            ICamera cameraUser = mUtils.getCameraService().connect(dummyCallbacks, cameraId,
-                    clientPackageName,
-                    CameraBinderTestUtils.USE_CALLING_UID);
+            BinderHolder holder = new BinderHolder();
+            CameraBinderDecorator.newInstance(mUtils.getCameraService())
+                    .connect(dummyCallbacks, cameraId, clientPackageName,
+                    CameraBinderTestUtils.USE_CALLING_UID, holder);
+            ICamera cameraUser = ICamera.Stub.asInterface(holder.getBinder());
             assertNotNull(String.format("Camera %s was null", cameraId), cameraUser);
 
             Log.v(TAG, String.format("Camera %s connected", cameraId));
@@ -131,9 +135,11 @@
 
             String clientPackageName = getContext().getPackageName();
 
-            IProCameraUser cameraUser = mUtils.getCameraService().connectPro(dummyCallbacks,
-                    cameraId,
-                    clientPackageName, CameraBinderTestUtils.USE_CALLING_UID);
+            BinderHolder holder = new BinderHolder();
+            CameraBinderDecorator.newInstance(mUtils.getCameraService())
+                    .connectPro(dummyCallbacks, cameraId,
+                    clientPackageName, CameraBinderTestUtils.USE_CALLING_UID, holder);
+            IProCameraUser cameraUser = IProCameraUser.Stub.asInterface(holder.getBinder());
             assertNotNull(String.format("Camera %s was null", cameraId), cameraUser);
 
             Log.v(TAG, String.format("Camera %s connected", cameraId));
@@ -161,9 +167,11 @@
 
             String clientPackageName = getContext().getPackageName();
 
-            ICameraDeviceUser cameraUser = mUtils.getCameraService().connectDevice(dummyCallbacks,
-                    cameraId,
-                    clientPackageName, CameraBinderTestUtils.USE_CALLING_UID);
+            BinderHolder holder = new BinderHolder();
+            CameraBinderDecorator.newInstance(mUtils.getCameraService())
+                    .connectDevice(dummyCallbacks, cameraId,
+                    clientPackageName, CameraBinderTestUtils.USE_CALLING_UID, holder);
+            ICameraDeviceUser cameraUser = ICameraDeviceUser.Stub.asInterface(holder.getBinder());
             assertNotNull(String.format("Camera %s was null", cameraId), cameraUser);
 
             Log.v(TAG, String.format("Camera %s connected", cameraId));
diff --git a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/integration/CameraDeviceBinderTest.java b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/integration/CameraDeviceBinderTest.java
index bdf14ff..5225e23 100644
--- a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/integration/CameraDeviceBinderTest.java
+++ b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/integration/CameraDeviceBinderTest.java
@@ -22,6 +22,7 @@
 import android.hardware.camera2.CaptureRequest;
 import android.hardware.camera2.ICameraDeviceCallbacks;
 import android.hardware.camera2.ICameraDeviceUser;
+import android.hardware.camera2.utils.BinderHolder;
 import android.os.RemoteException;
 import android.test.AndroidTestCase;
 import android.test.suitebuilder.annotation.SmallTest;
@@ -39,8 +40,8 @@
     private static String TAG = "CameraDeviceBinderTest";
     // Number of streaming callbacks need to check.
     private static int NUM_CALLBACKS_CHECKED = 10;
-    // Wait for capture result timeout value: 1000ms
-    private final static int WAIT_FOR_COMPLETE_TIMEOUT_MS = 1000;
+    // Wait for capture result timeout value: 1500ms
+    private final static int WAIT_FOR_COMPLETE_TIMEOUT_MS = 1500;
 
     private int mCameraId;
     private ICameraDeviceUser mCameraUser;
@@ -129,8 +130,10 @@
 
         mMockCb = spy(dummyCallbacks);
 
-        mCameraUser = mUtils.getCameraService().connectDevice(mMockCb, mCameraId,
-                clientPackageName, CameraBinderTestUtils.USE_CALLING_UID);
+        BinderHolder holder = new BinderHolder();
+        mUtils.getCameraService().connectDevice(mMockCb, mCameraId,
+                clientPackageName, CameraBinderTestUtils.USE_CALLING_UID, holder);
+        mCameraUser = ICameraDeviceUser.Stub.asInterface(holder.getBinder());
         assertNotNull(String.format("Camera %s was null", mCameraId), mCameraUser);
         createDefaultSurface();
 
diff --git a/packages/SystemUI/res/values-af/strings.xml b/packages/SystemUI/res/values-af/strings.xml
index 9b2c127..2bed730 100644
--- a/packages/SystemUI/res/values-af/strings.xml
+++ b/packages/SystemUI/res/values-af/strings.xml
@@ -201,6 +201,4 @@
     <string name="quick_settings_brightness_dialog_auto_brightness_label" msgid="5064982743784071218">"OUTO"</string>
     <string name="status_bar_help_title" msgid="1199237744086469217">"Kennisgewings verskyn hier"</string>
     <string name="status_bar_help_text" msgid="7874607155052076323">"Verkry enige tyd toegang tot hulle deur af te sleep.\nSleep weer af vir stelselkontroles."</string>
-    <string name="hiding_navigation_confirmation_message" msgid="3227814171674734332">"Sleep rand van skerm om balk te wys"</string>
-    <string name="hiding_navigation_confirmation_message_long" msgid="7854368870786524950">"Sleep van rand van skerm af om stelselbalk te wys"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-am/strings.xml b/packages/SystemUI/res/values-am/strings.xml
index 4aa452d..ebbad16 100644
--- a/packages/SystemUI/res/values-am/strings.xml
+++ b/packages/SystemUI/res/values-am/strings.xml
@@ -164,7 +164,7 @@
     <string name="status_bar_settings_signal_meter_wifi_nossid" msgid="6557486452774597820">"Wi-Fi ተያይዟል"</string>
     <string name="gps_notification_searching_text" msgid="8574247005642736060">"ለGPS በመፈለግ ላይ"</string>
     <string name="gps_notification_found_text" msgid="4619274244146446464">"በ GPS የተዘጋጀ ሥፍራ"</string>
-    <string name="accessibility_location_active" msgid="2427290146138169014">"ገባሪ የአካባቢ ጥያቄዎች"</string>
+    <string name="accessibility_location_active" msgid="2427290146138169014">"የአካባቢ ጥያቄዎች ነቅተዋል"</string>
     <string name="accessibility_clear_all" msgid="5235938559247164925">"ሁሉንም ማሳወቂያዎች አጽዳ"</string>
     <string name="status_bar_notification_inspect_item_title" msgid="1163547729015390250">"የመተግበሪያ መረጃ"</string>
     <string name="accessibility_rotation_lock_off" msgid="4062780228931590069">"ማያ ገጽ በራስ ሰር ይዞራል።"</string>
@@ -201,6 +201,4 @@
     <string name="quick_settings_brightness_dialog_auto_brightness_label" msgid="5064982743784071218">"ራስ-ሰር"</string>
     <string name="status_bar_help_title" msgid="1199237744086469217">"ማሳወቂያዎች እዚህ ላይ ይታያሉ"</string>
     <string name="status_bar_help_text" msgid="7874607155052076323">"ወደ ታች በማንሸራተት በማንኛውም ጊዜ ይድረሱባቸው።\nSwipe የስርዓት መቆጣጠሪያዎችን ለማምጣት እንደገና ወደ ታች ያንሸራትቱ።"</string>
-    <string name="hiding_navigation_confirmation_message" msgid="3227814171674734332">"አሞሌውን ለማሳየት የማያ ገጹን ጠርዝ ላይ ያንሸራትቱ"</string>
-    <string name="hiding_navigation_confirmation_message_long" msgid="7854368870786524950">"አሞሌውን ለማሳየት ከማያ ገጹ ጠርዝ ጀምረው ያንሸራትቱ"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-ar/strings.xml b/packages/SystemUI/res/values-ar/strings.xml
index f7f5e37..7aac94e 100644
--- a/packages/SystemUI/res/values-ar/strings.xml
+++ b/packages/SystemUI/res/values-ar/strings.xml
@@ -201,6 +201,4 @@
     <string name="quick_settings_brightness_dialog_auto_brightness_label" msgid="5064982743784071218">"تلقائي"</string>
     <string name="status_bar_help_title" msgid="1199237744086469217">"تظهر الإشعارات هنا"</string>
     <string name="status_bar_help_text" msgid="7874607155052076323">"يمكنك الدخول إليها في أي وقت بالتمرير السريع إلى أسفل.\nيمكنك التمرير السريع إلى أسفل مرة أخرى للوصول إلى عناصر تحكم النظام."</string>
-    <string name="hiding_navigation_confirmation_message" msgid="3227814171674734332">"مرر سريعًا لحافة الشاشة لإظهار الشريط"</string>
-    <string name="hiding_navigation_confirmation_message_long" msgid="7854368870786524950">"مرر سريعًا من حافة الشاشة لإظهار شريط النظام"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-be/strings.xml b/packages/SystemUI/res/values-be/strings.xml
index aaca584..76d0580 100644
--- a/packages/SystemUI/res/values-be/strings.xml
+++ b/packages/SystemUI/res/values-be/strings.xml
@@ -206,8 +206,4 @@
     <string name="quick_settings_brightness_dialog_auto_brightness_label" msgid="5064982743784071218">"АЎТА"</string>
     <string name="status_bar_help_title" msgid="1199237744086469217">"Апавяшчэнні з\'яўляюцца тут"</string>
     <string name="status_bar_help_text" msgid="7874607155052076323">"Атрымлівайце доступ да іх у любы час, праводзячы пальцам уніз.\nПравядзіце пальцам уніз яшчэ раз, каб атрымаць доступ да сродкаў кіравання сістэмай."</string>
-    <!-- no translation found for hiding_navigation_confirmation_message (3227814171674734332) -->
-    <skip />
-    <!-- no translation found for hiding_navigation_confirmation_message_long (7854368870786524950) -->
-    <skip />
 </resources>
diff --git a/packages/SystemUI/res/values-bg/strings.xml b/packages/SystemUI/res/values-bg/strings.xml
index b10f5ff..605dd97 100644
--- a/packages/SystemUI/res/values-bg/strings.xml
+++ b/packages/SystemUI/res/values-bg/strings.xml
@@ -164,8 +164,7 @@
     <string name="status_bar_settings_signal_meter_wifi_nossid" msgid="6557486452774597820">"Wi-Fi: Има връзка"</string>
     <string name="gps_notification_searching_text" msgid="8574247005642736060">"Търси се GPS"</string>
     <string name="gps_notification_found_text" msgid="4619274244146446464">"Местоположението е зададено от GPS"</string>
-    <!-- no translation found for accessibility_location_active (2427290146138169014) -->
-    <skip />
+    <string name="accessibility_location_active" msgid="2427290146138169014">"Активни заявки за местоположение"</string>
     <string name="accessibility_clear_all" msgid="5235938559247164925">"Изчистване на всички известия."</string>
     <string name="status_bar_notification_inspect_item_title" msgid="1163547729015390250">"Информация за приложението"</string>
     <string name="accessibility_rotation_lock_off" msgid="4062780228931590069">"Екранът ще се завърта автоматично."</string>
@@ -202,6 +201,4 @@
     <string name="quick_settings_brightness_dialog_auto_brightness_label" msgid="5064982743784071218">"АВТ."</string>
     <string name="status_bar_help_title" msgid="1199237744086469217">"Известията се показват тук"</string>
     <string name="status_bar_help_text" msgid="7874607155052076323">"Осъществявайте достъп до тях по всяко време, като прекарате пръст надолу.\nНаправете го отново за системните контроли."</string>
-    <string name="hiding_navigation_confirmation_message" msgid="3227814171674734332">"Прекарайте пръст по ръба на екрана, за да се покаже лентата"</string>
-    <string name="hiding_navigation_confirmation_message_long" msgid="7854368870786524950">"Прекарайте пръст от ръба на екрана, за да се покаже системната лента"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-ca/strings.xml b/packages/SystemUI/res/values-ca/strings.xml
index 0a95005..83e7020 100644
--- a/packages/SystemUI/res/values-ca/strings.xml
+++ b/packages/SystemUI/res/values-ca/strings.xml
@@ -166,8 +166,7 @@
     <string name="status_bar_settings_signal_meter_wifi_nossid" msgid="6557486452774597820">"Wi-Fi: connectada"</string>
     <string name="gps_notification_searching_text" msgid="8574247005642736060">"S\'està cercant un GPS"</string>
     <string name="gps_notification_found_text" msgid="4619274244146446464">"S\'ha establert la ubicació per GPS"</string>
-    <!-- no translation found for accessibility_location_active (2427290146138169014) -->
-    <skip />
+    <string name="accessibility_location_active" msgid="2427290146138169014">"Sol·licituds d\'ubicació actives"</string>
     <string name="accessibility_clear_all" msgid="5235938559247164925">"Esborra totes les notificacions."</string>
     <string name="status_bar_notification_inspect_item_title" msgid="1163547729015390250">"Informació de l\'aplicació"</string>
     <string name="accessibility_rotation_lock_off" msgid="4062780228931590069">"La pantalla girarà automàticament."</string>
@@ -204,6 +203,4 @@
     <string name="quick_settings_brightness_dialog_auto_brightness_label" msgid="5064982743784071218">"AUTOMÀTICA"</string>
     <string name="status_bar_help_title" msgid="1199237744086469217">"Les notificacions apareixen aquí"</string>
     <string name="status_bar_help_text" msgid="7874607155052076323">"Accedeix-hi en qualsevol moment: només has de fer lliscar el dit cap avall.\nTorna a fer lliscar el dit cap avall per fer que es mostrin els controls del sistema."</string>
-    <string name="hiding_navigation_confirmation_message" msgid="3227814171674734332">"Fes lliscar el dit per la vora de la pantalla perquè es mostri la barra"</string>
-    <string name="hiding_navigation_confirmation_message_long" msgid="7854368870786524950">"Fes lliscar el dit des de la vora de la pantalla perquè es mostri la barra del sistema"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-cs/strings.xml b/packages/SystemUI/res/values-cs/strings.xml
index 178238f..4497735 100644
--- a/packages/SystemUI/res/values-cs/strings.xml
+++ b/packages/SystemUI/res/values-cs/strings.xml
@@ -203,6 +203,4 @@
     <string name="quick_settings_brightness_dialog_auto_brightness_label" msgid="5064982743784071218">"AUTOMATICKY"</string>
     <string name="status_bar_help_title" msgid="1199237744086469217">"Zde se zobrazují oznámení"</string>
     <string name="status_bar_help_text" msgid="7874607155052076323">"Můžete je kdykoli zobrazit tím, že přejedete prstem dolů.\nPřejedete-li prstem dolů ještě jednou, zobrazí se ovládací prvky systému."</string>
-    <string name="hiding_navigation_confirmation_message" msgid="3227814171674734332">"Panel zobrazíte přejetím přes okraj obrazovky"</string>
-    <string name="hiding_navigation_confirmation_message_long" msgid="7854368870786524950">"Systémový panel zobrazíte přejetím přes okraj obrazovky"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-da/strings.xml b/packages/SystemUI/res/values-da/strings.xml
index 1c772b5..be42612 100644
--- a/packages/SystemUI/res/values-da/strings.xml
+++ b/packages/SystemUI/res/values-da/strings.xml
@@ -164,8 +164,7 @@
     <string name="status_bar_settings_signal_meter_wifi_nossid" msgid="6557486452774597820">"Wi-Fi er forbundet"</string>
     <string name="gps_notification_searching_text" msgid="8574247005642736060">"Søger efter GPS"</string>
     <string name="gps_notification_found_text" msgid="4619274244146446464">"Placeringen er angivet ved hjælp af GPS"</string>
-    <!-- no translation found for accessibility_location_active (2427290146138169014) -->
-    <skip />
+    <string name="accessibility_location_active" msgid="2427290146138169014">"Aktive placeringsanmodninger"</string>
     <string name="accessibility_clear_all" msgid="5235938559247164925">"Ryd alle meddelelser."</string>
     <string name="status_bar_notification_inspect_item_title" msgid="1163547729015390250">"Oplysninger om appen"</string>
     <string name="accessibility_rotation_lock_off" msgid="4062780228931590069">"Skærmen roterer automatisk."</string>
@@ -202,6 +201,4 @@
     <string name="quick_settings_brightness_dialog_auto_brightness_label" msgid="5064982743784071218">"AUTO"</string>
     <string name="status_bar_help_title" msgid="1199237744086469217">"Underretninger vises her"</string>
     <string name="status_bar_help_text" msgid="7874607155052076323">"Få adgang til dem når som helst ved at stryge ned.\nStryg ned igen for at komme til systemindstillingerne."</string>
-    <string name="hiding_navigation_confirmation_message" msgid="3227814171674734332">"Stryg fra skærmkanten for at se bjælken"</string>
-    <string name="hiding_navigation_confirmation_message_long" msgid="7854368870786524950">"Stryg med fingeren fra skærmens kant for at få vist systembjælken"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-de/strings.xml b/packages/SystemUI/res/values-de/strings.xml
index 86ea82d..052990c 100644
--- a/packages/SystemUI/res/values-de/strings.xml
+++ b/packages/SystemUI/res/values-de/strings.xml
@@ -166,8 +166,7 @@
     <string name="status_bar_settings_signal_meter_wifi_nossid" msgid="6557486452774597820">"WLAN verbunden"</string>
     <string name="gps_notification_searching_text" msgid="8574247005642736060">"GPS wird gesucht"</string>
     <string name="gps_notification_found_text" msgid="4619274244146446464">"Standort durch GPS festgelegt"</string>
-    <!-- no translation found for accessibility_location_active (2427290146138169014) -->
-    <skip />
+    <string name="accessibility_location_active" msgid="2427290146138169014">"Standortanfragen aktiv"</string>
     <string name="accessibility_clear_all" msgid="5235938559247164925">"Alle Benachrichtigungen löschen"</string>
     <string name="status_bar_notification_inspect_item_title" msgid="1163547729015390250">"App-Details"</string>
     <string name="accessibility_rotation_lock_off" msgid="4062780228931590069">"Bildschirm wird automatisch gedreht."</string>
@@ -204,6 +203,4 @@
     <string name="quick_settings_brightness_dialog_auto_brightness_label" msgid="5064982743784071218">"AUTO"</string>
     <string name="status_bar_help_title" msgid="1199237744086469217">"Benachrichtigungen erscheinen hier"</string>
     <string name="status_bar_help_text" msgid="7874607155052076323">"Greifen Sie jederzeit auf sie zu, indem Sie nach unten wischen.\nWischen Sie für Systemeinstellungen erneut nach unten."</string>
-    <string name="hiding_navigation_confirmation_message" msgid="3227814171674734332">"Zum Einblenden der Leiste vom Rand weg wischen"</string>
-    <string name="hiding_navigation_confirmation_message_long" msgid="7854368870786524950">"Zum Einblenden der Systemleiste vom Display-Rand weg wischen"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-el/strings.xml b/packages/SystemUI/res/values-el/strings.xml
index f965773..d23b8d5 100644
--- a/packages/SystemUI/res/values-el/strings.xml
+++ b/packages/SystemUI/res/values-el/strings.xml
@@ -203,6 +203,4 @@
     <string name="quick_settings_brightness_dialog_auto_brightness_label" msgid="5064982743784071218">"ΑΥΤΟΜΑΤΗ"</string>
     <string name="status_bar_help_title" msgid="1199237744086469217">"Οι ειδοποιήσεις εμφανίζονται εδώ"</string>
     <string name="status_bar_help_text" msgid="7874607155052076323">"Μεταβείτε σε αυτές ανά πάσα στιγμή σύροντας προς τα κάτω.\nΣύρετε ξανά προς τα κάτω για τα στοιχεία ελέγχου συστήματος."</string>
-    <string name="hiding_navigation_confirmation_message" msgid="3227814171674734332">"Σύρετε από την άκρη της οθόνης για να εμφανίσετε τη γραμμή"</string>
-    <string name="hiding_navigation_confirmation_message_long" msgid="7854368870786524950">"Σύρετε από την άκρη της οθόνης για να εμφανίσετε τη γραμμή συστήματος"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-en-rGB/strings.xml b/packages/SystemUI/res/values-en-rGB/strings.xml
index a7d621352..2ac1040 100644
--- a/packages/SystemUI/res/values-en-rGB/strings.xml
+++ b/packages/SystemUI/res/values-en-rGB/strings.xml
@@ -201,6 +201,4 @@
     <string name="quick_settings_brightness_dialog_auto_brightness_label" msgid="5064982743784071218">"AUTO"</string>
     <string name="status_bar_help_title" msgid="1199237744086469217">"Notifications appear here"</string>
     <string name="status_bar_help_text" msgid="7874607155052076323">"Access them any time by swiping down.\nSwipe down again for system controls."</string>
-    <string name="hiding_navigation_confirmation_message" msgid="3227814171674734332">"Swipe edge of screen to reveal bar"</string>
-    <string name="hiding_navigation_confirmation_message_long" msgid="7854368870786524950">"Swipe from edge of screen to reveal system bar"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-es-rUS/strings.xml b/packages/SystemUI/res/values-es-rUS/strings.xml
index bdd0363..d11d413 100644
--- a/packages/SystemUI/res/values-es-rUS/strings.xml
+++ b/packages/SystemUI/res/values-es-rUS/strings.xml
@@ -166,8 +166,7 @@
     <string name="status_bar_settings_signal_meter_wifi_nossid" msgid="6557486452774597820">"Wi-Fi conectado"</string>
     <string name="gps_notification_searching_text" msgid="8574247005642736060">"Buscando GPS"</string>
     <string name="gps_notification_found_text" msgid="4619274244146446464">"La ubicación se estableció por GPS"</string>
-    <!-- no translation found for accessibility_location_active (2427290146138169014) -->
-    <skip />
+    <string name="accessibility_location_active" msgid="2427290146138169014">"Solicitudes de ubicación activas"</string>
     <string name="accessibility_clear_all" msgid="5235938559247164925">"Eliminar todas las notificaciones"</string>
     <string name="status_bar_notification_inspect_item_title" msgid="1163547729015390250">"Información de la aplicación"</string>
     <string name="accessibility_rotation_lock_off" msgid="4062780228931590069">"La pantalla girará automáticamente."</string>
@@ -204,6 +203,4 @@
     <string name="quick_settings_brightness_dialog_auto_brightness_label" msgid="5064982743784071218">"AUTOMÁTICO"</string>
     <string name="status_bar_help_title" msgid="1199237744086469217">"Las notificaciones aparecen aquí."</string>
     <string name="status_bar_help_text" msgid="7874607155052076323">"Desliza el dedo hacia abajo para acceder al contenido.\nVuelve a deslizar el dedo hacia abajo para acceder a los controles del sistema."</string>
-    <string name="hiding_navigation_confirmation_message" msgid="3227814171674734332">"Desliza el dedo desde el borde de la pantalla para mostrar la barra."</string>
-    <string name="hiding_navigation_confirmation_message_long" msgid="7854368870786524950">"Desliza el dedo desde el borde de la pantalla para mostrar la barra del sistema."</string>
 </resources>
diff --git a/packages/SystemUI/res/values-es/strings.xml b/packages/SystemUI/res/values-es/strings.xml
index a81a2b4..068af45 100644
--- a/packages/SystemUI/res/values-es/strings.xml
+++ b/packages/SystemUI/res/values-es/strings.xml
@@ -201,6 +201,4 @@
     <string name="quick_settings_brightness_dialog_auto_brightness_label" msgid="5064982743784071218">"AUTO"</string>
     <string name="status_bar_help_title" msgid="1199237744086469217">"Las notificaciones aparecen aquí"</string>
     <string name="status_bar_help_text" msgid="7874607155052076323">"Desliza el dedo hacia abajo para acceder al contenido.\nVuelve a deslizar el dedo hacia abajo para acceder a los controles del sistema."</string>
-    <string name="hiding_navigation_confirmation_message" msgid="3227814171674734332">"Desliza el borde de la pantalla para mostrar la barra"</string>
-    <string name="hiding_navigation_confirmation_message_long" msgid="7854368870786524950">"Desliza el borde de la pantalla para mostrar la barra del sistema"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-et/strings.xml b/packages/SystemUI/res/values-et/strings.xml
index c4fda13..28ece65 100644
--- a/packages/SystemUI/res/values-et/strings.xml
+++ b/packages/SystemUI/res/values-et/strings.xml
@@ -201,6 +201,4 @@
     <string name="quick_settings_brightness_dialog_auto_brightness_label" msgid="5064982743784071218">"AUTOMAATNE"</string>
     <string name="status_bar_help_title" msgid="1199237744086469217">"Märguanded ilmuvad siia"</string>
     <string name="status_bar_help_text" msgid="7874607155052076323">"Juurdepääs igal ajal sõrmega alla pühkides.\nSüsteemi juhtnuppude jaoks pühkige uuesti alla."</string>
-    <string name="hiding_navigation_confirmation_message" msgid="3227814171674734332">"Riba kuvamiseks pühkige ekraani serva"</string>
-    <string name="hiding_navigation_confirmation_message_long" msgid="7854368870786524950">"Süsteemiriba kuvamiseks pühkige ekraani servast"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-fa/strings.xml b/packages/SystemUI/res/values-fa/strings.xml
index a84b9b4..2ba0427 100644
--- a/packages/SystemUI/res/values-fa/strings.xml
+++ b/packages/SystemUI/res/values-fa/strings.xml
@@ -201,6 +201,4 @@
     <string name="quick_settings_brightness_dialog_auto_brightness_label" msgid="5064982743784071218">"خودکار"</string>
     <string name="status_bar_help_title" msgid="1199237744086469217">"اعلان‌ها در اینجا نمایش داده می‌شوند"</string>
     <string name="status_bar_help_text" msgid="7874607155052076323">"با کشیدن انگشت به طرف پایین به آنها دسترسی پیدا کنید.\nبرای کنترل‌های سیستم دوباره انگشت خود را به سمت پایین بکشید."</string>
-    <string name="hiding_navigation_confirmation_message" msgid="3227814171674734332">"برای نمایش نوار، انگشت خود را از لبه‌ صفحه به داخل بکشید"</string>
-    <string name="hiding_navigation_confirmation_message_long" msgid="7854368870786524950">"برای نمایش نوار سیستم، انگشت خود را از لبه‌ صفحه به داخل بکشید"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-fi/strings.xml b/packages/SystemUI/res/values-fi/strings.xml
index f2cce06..b652cb0 100644
--- a/packages/SystemUI/res/values-fi/strings.xml
+++ b/packages/SystemUI/res/values-fi/strings.xml
@@ -201,6 +201,4 @@
     <string name="quick_settings_brightness_dialog_auto_brightness_label" msgid="5064982743784071218">"AUTO"</string>
     <string name="status_bar_help_title" msgid="1199237744086469217">"Ilmoitukset näkyvät tässä"</string>
     <string name="status_bar_help_text" msgid="7874607155052076323">"Näet ilmoitukset liu\'uttamalla sormea alas ruudulla.\nVoit palauttaa järjestelmän ohjaimet näkyviin liu\'uttamalla sormea alas uudelleen."</string>
-    <string name="hiding_navigation_confirmation_message" msgid="3227814171674734332">"Tuo palkki näkyviin liu\'uttamalla ruudun reunasta"</string>
-    <string name="hiding_navigation_confirmation_message_long" msgid="7854368870786524950">"Tuo järjestelmäpalkki näkyviin liu\'uttamalla ruudun reunasta"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-fr/strings.xml b/packages/SystemUI/res/values-fr/strings.xml
index 7fe1143..d00e4a3 100644
--- a/packages/SystemUI/res/values-fr/strings.xml
+++ b/packages/SystemUI/res/values-fr/strings.xml
@@ -166,8 +166,7 @@
     <string name="status_bar_settings_signal_meter_wifi_nossid" msgid="6557486452774597820">"Connecté au Wi-Fi"</string>
     <string name="gps_notification_searching_text" msgid="8574247005642736060">"Recherche de GPS..."</string>
     <string name="gps_notification_found_text" msgid="4619274244146446464">"Position définie par GPS"</string>
-    <!-- no translation found for accessibility_location_active (2427290146138169014) -->
-    <skip />
+    <string name="accessibility_location_active" msgid="2427290146138169014">"Demandes de localisation actives"</string>
     <string name="accessibility_clear_all" msgid="5235938559247164925">"Supprimer toutes les notifications"</string>
     <string name="status_bar_notification_inspect_item_title" msgid="1163547729015390250">"Informations sur l\'application"</string>
     <string name="accessibility_rotation_lock_off" msgid="4062780228931590069">"L\'écran pivote automatiquement."</string>
@@ -204,6 +203,4 @@
     <string name="quick_settings_brightness_dialog_auto_brightness_label" msgid="5064982743784071218">"AUTOMATIQUE"</string>
     <string name="status_bar_help_title" msgid="1199237744086469217">"Les notifications s’affichent ici"</string>
     <string name="status_bar_help_text" msgid="7874607155052076323">"Accédez-y à tout moment en faisant glisser le doigt vers le bas.\nRépétez l\'opération pour accéder aux commandes du système."</string>
-    <string name="hiding_navigation_confirmation_message" msgid="3227814171674734332">"Faites glisser le doigt sur le côté de l\'écran pour afficher la barre."</string>
-    <string name="hiding_navigation_confirmation_message_long" msgid="7854368870786524950">"Faites glisser le doigt à partir d\'un côté de l\'écran pour afficher la barre système."</string>
 </resources>
diff --git a/packages/SystemUI/res/values-hi/strings.xml b/packages/SystemUI/res/values-hi/strings.xml
index a1de7a1..45b5813 100644
--- a/packages/SystemUI/res/values-hi/strings.xml
+++ b/packages/SystemUI/res/values-hi/strings.xml
@@ -201,6 +201,4 @@
     <string name="quick_settings_brightness_dialog_auto_brightness_label" msgid="5064982743784071218">"स्वत:"</string>
     <string name="status_bar_help_title" msgid="1199237744086469217">"सूचनाएं यहां दिखाई देती हैं"</string>
     <string name="status_bar_help_text" msgid="7874607155052076323">"नीचे स्वाइप करके उन तक कभी भी पहुंचें.\nसिस्टम नियंत्रणों के लिए पुन: नीचे स्वाइप करें."</string>
-    <string name="hiding_navigation_confirmation_message" msgid="3227814171674734332">"बार को प्रदर्शित करने के लिए स्क्रीन के किनारे को स्वाइप करें"</string>
-    <string name="hiding_navigation_confirmation_message_long" msgid="7854368870786524950">"सिस्टम बार को प्रदर्शित करने के लिए स्क्रीन के किनारे से स्वाइप करें"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-hr/strings.xml b/packages/SystemUI/res/values-hr/strings.xml
index f8ff35d..9f8559c 100644
--- a/packages/SystemUI/res/values-hr/strings.xml
+++ b/packages/SystemUI/res/values-hr/strings.xml
@@ -201,6 +201,4 @@
     <string name="quick_settings_brightness_dialog_auto_brightness_label" msgid="5064982743784071218">"AUTOMATSKI"</string>
     <string name="status_bar_help_title" msgid="1199237744086469217">"Obavijesti se prikazuju ovdje"</string>
     <string name="status_bar_help_text" msgid="7874607155052076323">"Pristupite im u bilo kojem trenutku tako da prstom trznete prema dolje. \nPonovo prstom trznite prema dolje za kontrole sustava."</string>
-    <string name="hiding_navigation_confirmation_message" msgid="3227814171674734332">"Prijeđite prstom po rubu zaslona da bi se prikazala traka"</string>
-    <string name="hiding_navigation_confirmation_message_long" msgid="7854368870786524950">"Prijeđite prstom od ruba zaslona da bi se prikazala traka sustava"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-hu/strings.xml b/packages/SystemUI/res/values-hu/strings.xml
index 118baed..f2dcd93 100644
--- a/packages/SystemUI/res/values-hu/strings.xml
+++ b/packages/SystemUI/res/values-hu/strings.xml
@@ -201,6 +201,4 @@
     <string name="quick_settings_brightness_dialog_auto_brightness_label" msgid="5064982743784071218">"automatikus"</string>
     <string name="status_bar_help_title" msgid="1199237744086469217">"Az értesítések itt jelennek meg."</string>
     <string name="status_bar_help_text" msgid="7874607155052076323">"Bármikor elérheti őket, ha lefelé húzza az ujját.\nHúzza le az ujját még egyszer a rendszerbeállítások eléréséhez."</string>
-    <string name="hiding_navigation_confirmation_message" msgid="3227814171674734332">"Csúsztassa ujját a képernyő szélén a sáv megjelenítéséhez"</string>
-    <string name="hiding_navigation_confirmation_message_long" msgid="7854368870786524950">"Csúsztassa ujját a képernyő szélétől a rendszersáv megjelenítéséhez"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-in/strings.xml b/packages/SystemUI/res/values-in/strings.xml
index 013bd99..6846056 100644
--- a/packages/SystemUI/res/values-in/strings.xml
+++ b/packages/SystemUI/res/values-in/strings.xml
@@ -164,8 +164,7 @@
     <string name="status_bar_settings_signal_meter_wifi_nossid" msgid="6557486452774597820">"Wi-Fi tersambung"</string>
     <string name="gps_notification_searching_text" msgid="8574247005642736060">"Menelusuri GPS"</string>
     <string name="gps_notification_found_text" msgid="4619274244146446464">"Lokasi yang disetel oleh GPS"</string>
-    <!-- no translation found for accessibility_location_active (2427290146138169014) -->
-    <skip />
+    <string name="accessibility_location_active" msgid="2427290146138169014">"Permintaan lokasi aktif"</string>
     <string name="accessibility_clear_all" msgid="5235938559247164925">"Menghapus semua pemberitahuan."</string>
     <string name="status_bar_notification_inspect_item_title" msgid="1163547729015390250">"Info aplikasi"</string>
     <string name="accessibility_rotation_lock_off" msgid="4062780228931590069">"Layar akan diputar secara otomatis."</string>
@@ -202,6 +201,4 @@
     <string name="quick_settings_brightness_dialog_auto_brightness_label" msgid="5064982743784071218">"OTOMATIS"</string>
     <string name="status_bar_help_title" msgid="1199237744086469217">"Pemberitahuan muncul di sini"</string>
     <string name="status_bar_help_text" msgid="7874607155052076323">"Akses kapan saja dengan menggesek ke bawah.\nGesek ke bawah sekali lagi untuk kontrol sistem."</string>
-    <string name="hiding_navigation_confirmation_message" msgid="3227814171674734332">"Gesek tepi layar untuk membuka bilah"</string>
-    <string name="hiding_navigation_confirmation_message_long" msgid="7854368870786524950">"Gesek dari bagian tepi layar untuk membuka bilah sistem"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-it/strings.xml b/packages/SystemUI/res/values-it/strings.xml
index ff539be..a889342 100644
--- a/packages/SystemUI/res/values-it/strings.xml
+++ b/packages/SystemUI/res/values-it/strings.xml
@@ -203,6 +203,4 @@
     <string name="quick_settings_brightness_dialog_auto_brightness_label" msgid="5064982743784071218">"AUTO"</string>
     <string name="status_bar_help_title" msgid="1199237744086469217">"Le notifiche vengono visualizzate qui"</string>
     <string name="status_bar_help_text" msgid="7874607155052076323">"Puoi accedervi in qualsiasi momento scorrendo verso il basso.\nFai scorrere di nuovo verso il basso per visualizzare i controlli del sistema."</string>
-    <string name="hiding_navigation_confirmation_message" msgid="3227814171674734332">"Fai scorrere il bordo dello schermo per visualizzare la barra"</string>
-    <string name="hiding_navigation_confirmation_message_long" msgid="7854368870786524950">"Fai scorrere il dito dal bordo dello schermo per visualizzare la barra di sistema"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-iw/strings.xml b/packages/SystemUI/res/values-iw/strings.xml
index c80ad7c..899f092 100644
--- a/packages/SystemUI/res/values-iw/strings.xml
+++ b/packages/SystemUI/res/values-iw/strings.xml
@@ -164,8 +164,7 @@
     <string name="status_bar_settings_signal_meter_wifi_nossid" msgid="6557486452774597820">"Wi-Fi מחובר"</string>
     <string name="gps_notification_searching_text" msgid="8574247005642736060">"מחפש GPS"</string>
     <string name="gps_notification_found_text" msgid="4619274244146446464">"מיקום מוגדר על ידי GPS"</string>
-    <!-- no translation found for accessibility_location_active (2427290146138169014) -->
-    <skip />
+    <string name="accessibility_location_active" msgid="2427290146138169014">"בקשות מיקום פעילות"</string>
     <string name="accessibility_clear_all" msgid="5235938559247164925">"נקה את כל ההתראות."</string>
     <string name="status_bar_notification_inspect_item_title" msgid="1163547729015390250">"פרטי יישום"</string>
     <string name="accessibility_rotation_lock_off" msgid="4062780228931590069">"המסך יסתובב באופן אוטומטי."</string>
@@ -202,6 +201,4 @@
     <string name="quick_settings_brightness_dialog_auto_brightness_label" msgid="5064982743784071218">"אוטומטי"</string>
     <string name="status_bar_help_title" msgid="1199237744086469217">"הודעות מופיעות כאן"</string>
     <string name="status_bar_help_text" msgid="7874607155052076323">"גש אליהם בכל עת על ידי החלקה למטה.\nהחלק למטה שוב למעבר למרכז הבקרה של המערכת."</string>
-    <string name="hiding_navigation_confirmation_message" msgid="3227814171674734332">"החלק מקצה המסך כדי להציג את הסרגל"</string>
-    <string name="hiding_navigation_confirmation_message_long" msgid="7854368870786524950">"החלק מקצה המסך כדי להציג את סרגל המערכת"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-ja/strings.xml b/packages/SystemUI/res/values-ja/strings.xml
index 73aa558..e92e8be 100644
--- a/packages/SystemUI/res/values-ja/strings.xml
+++ b/packages/SystemUI/res/values-ja/strings.xml
@@ -166,8 +166,7 @@
     <string name="status_bar_settings_signal_meter_wifi_nossid" msgid="6557486452774597820">"Wi-Fi接続済み"</string>
     <string name="gps_notification_searching_text" msgid="8574247005642736060">"GPSで検索中"</string>
     <string name="gps_notification_found_text" msgid="4619274244146446464">"GPSにより現在地が設定されました"</string>
-    <!-- no translation found for accessibility_location_active (2427290146138169014) -->
-    <skip />
+    <string name="accessibility_location_active" msgid="2427290146138169014">"現在地リクエストがアクティブ"</string>
     <string name="accessibility_clear_all" msgid="5235938559247164925">"通知をすべて消去。"</string>
     <string name="status_bar_notification_inspect_item_title" msgid="1163547729015390250">"アプリ情報"</string>
     <string name="accessibility_rotation_lock_off" msgid="4062780228931590069">"画面は自動的に回転します。"</string>
@@ -204,6 +203,4 @@
     <string name="quick_settings_brightness_dialog_auto_brightness_label" msgid="5064982743784071218">"自動"</string>
     <string name="status_bar_help_title" msgid="1199237744086469217">"ここに通知が表示されます"</string>
     <string name="status_bar_help_text" msgid="7874607155052076323">"下にスワイプすると、いつでも通知を表示できます。\nシステムを管理するにはもう一度下にスワイプしてください。"</string>
-    <string name="hiding_navigation_confirmation_message" msgid="3227814171674734332">"バーを表示するには、画面の端からスワイプします"</string>
-    <string name="hiding_navigation_confirmation_message_long" msgid="7854368870786524950">"システムバーを表示するには、画面の端からスワイプします"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-ko/strings.xml b/packages/SystemUI/res/values-ko/strings.xml
index 403c94b..6319184 100644
--- a/packages/SystemUI/res/values-ko/strings.xml
+++ b/packages/SystemUI/res/values-ko/strings.xml
@@ -164,8 +164,7 @@
     <string name="status_bar_settings_signal_meter_wifi_nossid" msgid="6557486452774597820">"Wi-Fi 연결됨"</string>
     <string name="gps_notification_searching_text" msgid="8574247005642736060">"GPS 검색 중"</string>
     <string name="gps_notification_found_text" msgid="4619274244146446464">"GPS에서 위치 설정"</string>
-    <!-- no translation found for accessibility_location_active (2427290146138169014) -->
-    <skip />
+    <string name="accessibility_location_active" msgid="2427290146138169014">"위치 요청 있음"</string>
     <string name="accessibility_clear_all" msgid="5235938559247164925">"모든 알림 지우기"</string>
     <string name="status_bar_notification_inspect_item_title" msgid="1163547729015390250">"앱 정보"</string>
     <string name="accessibility_rotation_lock_off" msgid="4062780228931590069">"화면이 자동으로 회전됩니다."</string>
@@ -202,6 +201,4 @@
     <string name="quick_settings_brightness_dialog_auto_brightness_label" msgid="5064982743784071218">"자동"</string>
     <string name="status_bar_help_title" msgid="1199237744086469217">"알림이 여기에 표시됨"</string>
     <string name="status_bar_help_text" msgid="7874607155052076323">"아래로 스와이프하여 언제든 액세스하세요.\n한 번 더 아래로 스와이프하면 시스템 관리로 이동합니다."</string>
-    <string name="hiding_navigation_confirmation_message" msgid="3227814171674734332">"화면 가장자리에서 스와이프하여 표시줄 표시"</string>
-    <string name="hiding_navigation_confirmation_message_long" msgid="7854368870786524950">"화면 가장자리에서 스와이프하여 시스템 표시줄 표시"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-lt/strings.xml b/packages/SystemUI/res/values-lt/strings.xml
index 11b67ed..4400d37 100644
--- a/packages/SystemUI/res/values-lt/strings.xml
+++ b/packages/SystemUI/res/values-lt/strings.xml
@@ -164,8 +164,7 @@
     <string name="status_bar_settings_signal_meter_wifi_nossid" msgid="6557486452774597820">"Prisij. prie „Wi-Fi“"</string>
     <string name="gps_notification_searching_text" msgid="8574247005642736060">"Ieškoma GPS"</string>
     <string name="gps_notification_found_text" msgid="4619274244146446464">"GPS nustatyta vieta"</string>
-    <!-- no translation found for accessibility_location_active (2427290146138169014) -->
-    <skip />
+    <string name="accessibility_location_active" msgid="2427290146138169014">"Vietovės užklausos aktyvios"</string>
     <string name="accessibility_clear_all" msgid="5235938559247164925">"Išvalyti visus pranešimus."</string>
     <string name="status_bar_notification_inspect_item_title" msgid="1163547729015390250">"Programos informacija"</string>
     <string name="accessibility_rotation_lock_off" msgid="4062780228931590069">"Ekranas bus sukamas automatiškai."</string>
@@ -202,6 +201,4 @@
     <string name="quick_settings_brightness_dialog_auto_brightness_label" msgid="5064982743784071218">"AUTOMATINIS"</string>
     <string name="status_bar_help_title" msgid="1199237744086469217">"Pranešimai rodomi čia"</string>
     <string name="status_bar_help_text" msgid="7874607155052076323">"Perbraukę žemyn bet kuriuo metu pasieksite pranešimus.\nJei norite naudoti sistemos valdiklius, perbraukite žemyn dar kartą."</string>
-    <string name="hiding_navigation_confirmation_message" msgid="3227814171674734332">"Jei norite, kad būtų rodoma juosta, perbraukite ekrano krašte"</string>
-    <string name="hiding_navigation_confirmation_message_long" msgid="7854368870786524950">"Jei norite, kad būtų rodoma sistemos juosta, perbraukite iš ekrano krašto"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-lv/strings.xml b/packages/SystemUI/res/values-lv/strings.xml
index 85ab3fd..b2bee8c 100644
--- a/packages/SystemUI/res/values-lv/strings.xml
+++ b/packages/SystemUI/res/values-lv/strings.xml
@@ -164,8 +164,7 @@
     <string name="status_bar_settings_signal_meter_wifi_nossid" msgid="6557486452774597820">"Izv. sav. ar Wi-Fi"</string>
     <string name="gps_notification_searching_text" msgid="8574247005642736060">"Notiek GPS meklēšana..."</string>
     <string name="gps_notification_found_text" msgid="4619274244146446464">"GPS iestatītā atrašanās vieta"</string>
-    <!-- no translation found for accessibility_location_active (2427290146138169014) -->
-    <skip />
+    <string name="accessibility_location_active" msgid="2427290146138169014">"Aktīvi atrašanās vietu pieprasījumi"</string>
     <string name="accessibility_clear_all" msgid="5235938559247164925">"Notīrīt visus paziņojumus"</string>
     <string name="status_bar_notification_inspect_item_title" msgid="1163547729015390250">"Informācija par lietotni"</string>
     <string name="accessibility_rotation_lock_off" msgid="4062780228931590069">"Ekrāns tiks pagriezts automātiski."</string>
@@ -202,6 +201,4 @@
     <string name="quick_settings_brightness_dialog_auto_brightness_label" msgid="5064982743784071218">"AUTOMĀTISKI"</string>
     <string name="status_bar_help_title" msgid="1199237744086469217">"Šeit tiek rādīti paziņojumi"</string>
     <string name="status_bar_help_text" msgid="7874607155052076323">"Piekļūstiet tiem jebkurā laikā, velkot uz leju.\nVēlreiz velciet, lai tiktu parādītas sistēmas vadīklas."</string>
-    <string name="hiding_navigation_confirmation_message" msgid="3227814171674734332">"Velciet no ekrāna malas, lai piekļūtu joslai."</string>
-    <string name="hiding_navigation_confirmation_message_long" msgid="7854368870786524950">"Velciet no ekrāna malas, lai piekļūtu sistēmas joslai."</string>
 </resources>
diff --git a/packages/SystemUI/res/values-ms/strings.xml b/packages/SystemUI/res/values-ms/strings.xml
index b6b3577..9c76eae 100644
--- a/packages/SystemUI/res/values-ms/strings.xml
+++ b/packages/SystemUI/res/values-ms/strings.xml
@@ -201,6 +201,4 @@
     <string name="quick_settings_brightness_dialog_auto_brightness_label" msgid="5064982743784071218">"AUTO"</string>
     <string name="status_bar_help_title" msgid="1199237744086469217">"Pemberitahuan dipaparkan di sini"</string>
     <string name="status_bar_help_text" msgid="7874607155052076323">"Akses panel pada bila-bila masa dengan meleret ke bawah.\nLeret ke bawah sekali lagi untuk mendapatkan kawalan sistem."</string>
-    <string name="hiding_navigation_confirmation_message" msgid="3227814171674734332">"Leret ke bahagian tepi skrin untuk menampakkan bar"</string>
-    <string name="hiding_navigation_confirmation_message_long" msgid="7854368870786524950">"Leret dari tepi skrin untuk menampakkan bar sistem"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-nb/strings.xml b/packages/SystemUI/res/values-nb/strings.xml
index 6f7d727..d850cf3 100644
--- a/packages/SystemUI/res/values-nb/strings.xml
+++ b/packages/SystemUI/res/values-nb/strings.xml
@@ -164,8 +164,7 @@
     <string name="status_bar_settings_signal_meter_wifi_nossid" msgid="6557486452774597820">"Wi-Fi tilkoblet"</string>
     <string name="gps_notification_searching_text" msgid="8574247005642736060">"Søker etter GPS"</string>
     <string name="gps_notification_found_text" msgid="4619274244146446464">"Posisjon angitt av GPS"</string>
-    <!-- no translation found for accessibility_location_active (2427290146138169014) -->
-    <skip />
+    <string name="accessibility_location_active" msgid="2427290146138169014">"Aktive stedsforespørsler"</string>
     <string name="accessibility_clear_all" msgid="5235938559247164925">"Fjern alle varslinger."</string>
     <string name="status_bar_notification_inspect_item_title" msgid="1163547729015390250">"Info om app"</string>
     <string name="accessibility_rotation_lock_off" msgid="4062780228931590069">"Skjermen roterer automatisk."</string>
@@ -202,6 +201,4 @@
     <string name="quick_settings_brightness_dialog_auto_brightness_label" msgid="5064982743784071218">"AUTO"</string>
     <string name="status_bar_help_title" msgid="1199237744086469217">"Varslene vises her"</string>
     <string name="status_bar_help_text" msgid="7874607155052076323">"Bruk dem når som helst ved å sveipe nedover.\nSveip nedover igjen for å gå til systemkontrollene."</string>
-    <string name="hiding_navigation_confirmation_message" msgid="3227814171674734332">"Sveip på kanten av skjermen for å få frem feltet"</string>
-    <string name="hiding_navigation_confirmation_message_long" msgid="7854368870786524950">"Sveip fra kanten på skjermen for å få frem systemfeltet"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-nl/strings.xml b/packages/SystemUI/res/values-nl/strings.xml
index 02a5b45..5b6ebab 100644
--- a/packages/SystemUI/res/values-nl/strings.xml
+++ b/packages/SystemUI/res/values-nl/strings.xml
@@ -201,6 +201,4 @@
     <string name="quick_settings_brightness_dialog_auto_brightness_label" msgid="5064982743784071218">"AUTOMATISCH"</string>
     <string name="status_bar_help_title" msgid="1199237744086469217">"Meldingen worden hier weergegeven"</string>
     <string name="status_bar_help_text" msgid="7874607155052076323">"U kunt de meldingen op elk gewenst moment openen door met uw vinger omlaag te vegen.\nVeeg nogmaals met uw vinger omlaag om de systeembesturingselementen weer te geven."</string>
-    <string name="hiding_navigation_confirmation_message" msgid="3227814171674734332">"Veeg vanaf de rand om balk weer te geven"</string>
-    <string name="hiding_navigation_confirmation_message_long" msgid="7854368870786524950">"Veeg vanaf de rand van het scherm om de systeembalk weer te geven"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-pl/strings.xml b/packages/SystemUI/res/values-pl/strings.xml
index d17c45e..6bff7af 100644
--- a/packages/SystemUI/res/values-pl/strings.xml
+++ b/packages/SystemUI/res/values-pl/strings.xml
@@ -164,8 +164,7 @@
     <string name="status_bar_settings_signal_meter_wifi_nossid" msgid="6557486452774597820">"Wi-Fi: połączono"</string>
     <string name="gps_notification_searching_text" msgid="8574247005642736060">"Wyszukiwanie sygnału GPS"</string>
     <string name="gps_notification_found_text" msgid="4619274244146446464">"Lokalizacja z GPSa"</string>
-    <!-- no translation found for accessibility_location_active (2427290146138169014) -->
-    <skip />
+    <string name="accessibility_location_active" msgid="2427290146138169014">"Prośby o lokalizację są aktywne"</string>
     <string name="accessibility_clear_all" msgid="5235938559247164925">"Usuń wszystkie powiadomienia."</string>
     <string name="status_bar_notification_inspect_item_title" msgid="1163547729015390250">"O aplikacji"</string>
     <string name="accessibility_rotation_lock_off" msgid="4062780228931590069">"Ekran zostanie obrócony automatycznie."</string>
@@ -202,6 +201,4 @@
     <string name="quick_settings_brightness_dialog_auto_brightness_label" msgid="5064982743784071218">"AUTOMATYCZNA"</string>
     <string name="status_bar_help_title" msgid="1199237744086469217">"Tutaj pokazują się powiadomienia"</string>
     <string name="status_bar_help_text" msgid="7874607155052076323">"Możesz je otworzyć w dowolnej chwili, przesuwając w dół.\nPrzesuń jeszcze raz w dół, by otworzyć ustawienia systemowe."</string>
-    <string name="hiding_navigation_confirmation_message" msgid="3227814171674734332">"Przesuń palcem od krawędzi ekranu, by odkryć pasek"</string>
-    <string name="hiding_navigation_confirmation_message_long" msgid="7854368870786524950">"Przesuń palcem od krawędzi ekranu, by odkryć pasek systemu"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-pt-rPT/strings.xml b/packages/SystemUI/res/values-pt-rPT/strings.xml
index b520319..6aa94e0 100644
--- a/packages/SystemUI/res/values-pt-rPT/strings.xml
+++ b/packages/SystemUI/res/values-pt-rPT/strings.xml
@@ -164,8 +164,7 @@
     <string name="status_bar_settings_signal_meter_wifi_nossid" msgid="6557486452774597820">"Wi-Fi ligado"</string>
     <string name="gps_notification_searching_text" msgid="8574247005642736060">"A procurar GPS"</string>
     <string name="gps_notification_found_text" msgid="4619274244146446464">"Localização definida por GPS"</string>
-    <!-- no translation found for accessibility_location_active (2427290146138169014) -->
-    <skip />
+    <string name="accessibility_location_active" msgid="2427290146138169014">"Pedidos de localização ativos"</string>
     <string name="accessibility_clear_all" msgid="5235938559247164925">"Limpar todas as notificações."</string>
     <string name="status_bar_notification_inspect_item_title" msgid="1163547729015390250">"Informações da aplicação"</string>
     <string name="accessibility_rotation_lock_off" msgid="4062780228931590069">"O ecrã será rodado automaticamente."</string>
@@ -202,6 +201,4 @@
     <string name="quick_settings_brightness_dialog_auto_brightness_label" msgid="5064982743784071218">"AUTOMÁTICO"</string>
     <string name="status_bar_help_title" msgid="1199237744086469217">"As notificações são apresentadas aqui"</string>
     <string name="status_bar_help_text" msgid="7874607155052076323">"Pode aceder em qualquer altura, deslizando rapidamente para baixo com o dedo.\nDeslize novamente para baixo para aceder aos controlos do sistema."</string>
-    <string name="hiding_navigation_confirmation_message" msgid="3227814171674734332">"Deslize da extremidade do ecrã para revelar a barra"</string>
-    <string name="hiding_navigation_confirmation_message_long" msgid="7854368870786524950">"Deslize da extremidade do ecrã para revelar a barra do sistema"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-pt/strings.xml b/packages/SystemUI/res/values-pt/strings.xml
index 2a2f336..aa972fb 100644
--- a/packages/SystemUI/res/values-pt/strings.xml
+++ b/packages/SystemUI/res/values-pt/strings.xml
@@ -166,8 +166,7 @@
     <string name="status_bar_settings_signal_meter_wifi_nossid" msgid="6557486452774597820">"Wi-Fi conectado"</string>
     <string name="gps_notification_searching_text" msgid="8574247005642736060">"Buscando GPS"</string>
     <string name="gps_notification_found_text" msgid="4619274244146446464">"Local definido por GPS"</string>
-    <!-- no translation found for accessibility_location_active (2427290146138169014) -->
-    <skip />
+    <string name="accessibility_location_active" msgid="2427290146138169014">"Solicitações de localização ativas"</string>
     <string name="accessibility_clear_all" msgid="5235938559247164925">"Limpar todas as notificações."</string>
     <string name="status_bar_notification_inspect_item_title" msgid="1163547729015390250">"Informações do aplicativo"</string>
     <string name="accessibility_rotation_lock_off" msgid="4062780228931590069">"A tela girará automaticamente."</string>
@@ -204,6 +203,4 @@
     <string name="quick_settings_brightness_dialog_auto_brightness_label" msgid="5064982743784071218">"AUTO"</string>
     <string name="status_bar_help_title" msgid="1199237744086469217">"As notificações aparecem aqui"</string>
     <string name="status_bar_help_text" msgid="7874607155052076323">"Acesse a qualquer momento deslizando para baixo.\nDeslize para baixo novamente para acessar os controles do sistema."</string>
-    <string name="hiding_navigation_confirmation_message" msgid="3227814171674734332">"Deslize a borda da tela para ver a barra"</string>
-    <string name="hiding_navigation_confirmation_message_long" msgid="7854368870786524950">"Deslize a partir da borda da tela ver a barra do sistema"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-rm/strings.xml b/packages/SystemUI/res/values-rm/strings.xml
index 22a857e..05b7453 100644
--- a/packages/SystemUI/res/values-rm/strings.xml
+++ b/packages/SystemUI/res/values-rm/strings.xml
@@ -372,8 +372,4 @@
     <skip />
     <!-- no translation found for status_bar_help_text (7874607155052076323) -->
     <skip />
-    <!-- no translation found for hiding_navigation_confirmation_message (3227814171674734332) -->
-    <skip />
-    <!-- no translation found for hiding_navigation_confirmation_message_long (7854368870786524950) -->
-    <skip />
 </resources>
diff --git a/packages/SystemUI/res/values-ro/strings.xml b/packages/SystemUI/res/values-ro/strings.xml
index 375d12c..9c5ad00 100644
--- a/packages/SystemUI/res/values-ro/strings.xml
+++ b/packages/SystemUI/res/values-ro/strings.xml
@@ -164,8 +164,7 @@
     <string name="status_bar_settings_signal_meter_wifi_nossid" msgid="6557486452774597820">"Wi-Fi conectat"</string>
     <string name="gps_notification_searching_text" msgid="8574247005642736060">"Se caută GPS"</string>
     <string name="gps_notification_found_text" msgid="4619274244146446464">"Locaţie setată prin GPS"</string>
-    <!-- no translation found for accessibility_location_active (2427290146138169014) -->
-    <skip />
+    <string name="accessibility_location_active" msgid="2427290146138169014">"Solicitări locație active"</string>
     <string name="accessibility_clear_all" msgid="5235938559247164925">"Ștergeţi toate notificările."</string>
     <string name="status_bar_notification_inspect_item_title" msgid="1163547729015390250">"Informaţii despre aplicaţie"</string>
     <string name="accessibility_rotation_lock_off" msgid="4062780228931590069">"Ecranul se va roti în mod automat."</string>
@@ -202,6 +201,4 @@
     <string name="quick_settings_brightness_dialog_auto_brightness_label" msgid="5064982743784071218">"AUTOMAT"</string>
     <string name="status_bar_help_title" msgid="1199237744086469217">"Notificările se afişează aici"</string>
     <string name="status_bar_help_text" msgid="7874607155052076323">"Accesaţi-le oricând glisând în jos.\nGlisaţi în jos din nou pentru comenzile sistemului."</string>
-    <string name="hiding_navigation_confirmation_message" msgid="3227814171674734332">"Glisați dinspre marginea ecranului pentru a afișa bara"</string>
-    <string name="hiding_navigation_confirmation_message_long" msgid="7854368870786524950">"Glisați dinspre marginea ecranului pentru a afișa bara de sistem"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-ru/strings.xml b/packages/SystemUI/res/values-ru/strings.xml
index 15adf90..3020624 100644
--- a/packages/SystemUI/res/values-ru/strings.xml
+++ b/packages/SystemUI/res/values-ru/strings.xml
@@ -166,8 +166,7 @@
     <string name="status_bar_settings_signal_meter_wifi_nossid" msgid="6557486452774597820">"Wi-Fi подключено"</string>
     <string name="gps_notification_searching_text" msgid="8574247005642736060">"Поиск GPS"</string>
     <string name="gps_notification_found_text" msgid="4619274244146446464">"Координаты по GPS"</string>
-    <!-- no translation found for accessibility_location_active (2427290146138169014) -->
-    <skip />
+    <string name="accessibility_location_active" msgid="2427290146138169014">"Есть активные запросы на определение местоположения"</string>
     <string name="accessibility_clear_all" msgid="5235938559247164925">"Удалить все уведомления"</string>
     <string name="status_bar_notification_inspect_item_title" msgid="1163547729015390250">"О приложении"</string>
     <string name="accessibility_rotation_lock_off" msgid="4062780228931590069">"Экран будет поворачиваться автоматически."</string>
@@ -206,6 +205,4 @@
     <string name="quick_settings_brightness_dialog_auto_brightness_label" msgid="5064982743784071218">"АВТОНАСТРОЙКА"</string>
     <string name="status_bar_help_title" msgid="1199237744086469217">"Это панель уведомлений"</string>
     <string name="status_bar_help_text" msgid="7874607155052076323">"Ее можно открыть, пролистнув экран вниз.\nЧтобы открыть настройки, проведите пальцем вниз ещё раз."</string>
-    <string name="hiding_navigation_confirmation_message" msgid="3227814171674734332">"Чтобы открыть панель, проведите пальцем от края к центру экрана"</string>
-    <string name="hiding_navigation_confirmation_message_long" msgid="7854368870786524950">"Чтобы открыть панель навигации, проведите пальцем от края к центру экрана"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-sk/strings.xml b/packages/SystemUI/res/values-sk/strings.xml
index bb70f36..59af9ab 100644
--- a/packages/SystemUI/res/values-sk/strings.xml
+++ b/packages/SystemUI/res/values-sk/strings.xml
@@ -166,8 +166,7 @@
     <string name="status_bar_settings_signal_meter_wifi_nossid" msgid="6557486452774597820">"Wi-Fi: pripojené"</string>
     <string name="gps_notification_searching_text" msgid="8574247005642736060">"Vyhľadávanie satelitov GPS"</string>
     <string name="gps_notification_found_text" msgid="4619274244146446464">"Poloha nastavená pomocou GPS"</string>
-    <!-- no translation found for accessibility_location_active (2427290146138169014) -->
-    <skip />
+    <string name="accessibility_location_active" msgid="2427290146138169014">"Žiadosti o polohu sú aktívne"</string>
     <string name="accessibility_clear_all" msgid="5235938559247164925">"Vymazať všetky upozornenia."</string>
     <string name="status_bar_notification_inspect_item_title" msgid="1163547729015390250">"Informácie o aplikácii"</string>
     <string name="accessibility_rotation_lock_off" msgid="4062780228931590069">"Obrazovka sa automaticky otočí."</string>
@@ -204,6 +203,4 @@
     <string name="quick_settings_brightness_dialog_auto_brightness_label" msgid="5064982743784071218">"AUTOMATICKY"</string>
     <string name="status_bar_help_title" msgid="1199237744086469217">"Tu sa zobrazujú upozornenia"</string>
     <string name="status_bar_help_text" msgid="7874607155052076323">"Môžete ich kedykoľvek zobraziť tak, že posuniete prstom nadol.\nAk posuniete prstom nadol ešte raz, zobrazia sa ovládacie prvky systému."</string>
-    <string name="hiding_navigation_confirmation_message" msgid="3227814171674734332">"Panel zobrazíte posunutím cez okraj obrazovky"</string>
-    <string name="hiding_navigation_confirmation_message_long" msgid="7854368870786524950">"Systémový panel zobrazíte posunutím cez okraj obrazovky"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-sl/strings.xml b/packages/SystemUI/res/values-sl/strings.xml
index 46a5826..338ff44 100644
--- a/packages/SystemUI/res/values-sl/strings.xml
+++ b/packages/SystemUI/res/values-sl/strings.xml
@@ -164,8 +164,7 @@
     <string name="status_bar_settings_signal_meter_wifi_nossid" msgid="6557486452774597820">"Wi-Fi povezan"</string>
     <string name="gps_notification_searching_text" msgid="8574247005642736060">"Iskanje GPS-a"</string>
     <string name="gps_notification_found_text" msgid="4619274244146446464">"Lokacija nastavljena z GPS-om"</string>
-    <!-- no translation found for accessibility_location_active (2427290146138169014) -->
-    <skip />
+    <string name="accessibility_location_active" msgid="2427290146138169014">"Aktivne zahteve za lokacijo"</string>
     <string name="accessibility_clear_all" msgid="5235938559247164925">"Izbriši vsa obvestila."</string>
     <string name="status_bar_notification_inspect_item_title" msgid="1163547729015390250">"Podatki o aplikaciji"</string>
     <string name="accessibility_rotation_lock_off" msgid="4062780228931590069">"Zaslon se bo samodejno zasukal."</string>
@@ -202,6 +201,4 @@
     <string name="quick_settings_brightness_dialog_auto_brightness_label" msgid="5064982743784071218">"SAMODEJNO"</string>
     <string name="status_bar_help_title" msgid="1199237744086469217">"Obvestila so prikazana tukaj"</string>
     <string name="status_bar_help_text" msgid="7874607155052076323">"Do njih lahko kadar koli dostopate tako, da povlečete navzdol.\nZa prikaz sistemskih kontrolnikov znova povlecite navzdol."</string>
-    <string name="hiding_navigation_confirmation_message" msgid="3227814171674734332">"Vrstico prikažete tako, da povlečete z roba zaslona"</string>
-    <string name="hiding_navigation_confirmation_message_long" msgid="7854368870786524950">"Sistemsko vrstico prikažete tako, da povlečete z roba zaslona"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-sr/strings.xml b/packages/SystemUI/res/values-sr/strings.xml
index 163bc06..b501d69 100644
--- a/packages/SystemUI/res/values-sr/strings.xml
+++ b/packages/SystemUI/res/values-sr/strings.xml
@@ -201,6 +201,4 @@
     <string name="quick_settings_brightness_dialog_auto_brightness_label" msgid="5064982743784071218">"АУТОМАТСКА"</string>
     <string name="status_bar_help_title" msgid="1199237744086469217">"Обавештења се појављују овде"</string>
     <string name="status_bar_help_text" msgid="7874607155052076323">"Приступите им у било ком тренутку листањем надоле.\nПоново листајте надоле да би се приказале системске контроле."</string>
-    <string name="hiding_navigation_confirmation_message" msgid="3227814171674734332">"Превуците по ивици екрана да би се приказала трака"</string>
-    <string name="hiding_navigation_confirmation_message_long" msgid="7854368870786524950">"Превуците од ивице екрана да би се приказала системска трака"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-sv/strings.xml b/packages/SystemUI/res/values-sv/strings.xml
index c5335f4..560a00e 100644
--- a/packages/SystemUI/res/values-sv/strings.xml
+++ b/packages/SystemUI/res/values-sv/strings.xml
@@ -164,8 +164,7 @@
     <string name="status_bar_settings_signal_meter_wifi_nossid" msgid="6557486452774597820">"Wi-Fi-ansluten"</string>
     <string name="gps_notification_searching_text" msgid="8574247005642736060">"Sökning efter GPS pågår"</string>
     <string name="gps_notification_found_text" msgid="4619274244146446464">"Platsen har identifierats av GPS"</string>
-    <!-- no translation found for accessibility_location_active (2427290146138169014) -->
-    <skip />
+    <string name="accessibility_location_active" msgid="2427290146138169014">"Det finns aktiva platsbegäranden"</string>
     <string name="accessibility_clear_all" msgid="5235938559247164925">"Ta bort alla meddelanden."</string>
     <string name="status_bar_notification_inspect_item_title" msgid="1163547729015390250">"Info om appen"</string>
     <string name="accessibility_rotation_lock_off" msgid="4062780228931590069">"Skärmen roteras automatiskt."</string>
@@ -202,6 +201,4 @@
     <string name="quick_settings_brightness_dialog_auto_brightness_label" msgid="5064982743784071218">"AUTO"</string>
     <string name="status_bar_help_title" msgid="1199237744086469217">"Meddelanden visas här"</string>
     <string name="status_bar_help_text" msgid="7874607155052076323">"Du kommer åt dem när som helst genom att dra nedåt.\nDra nedåt igen om du vill visa systemkontroller."</string>
-    <string name="hiding_navigation_confirmation_message" msgid="3227814171674734332">"Dra från kanten av skärmen om du vill visa fältet"</string>
-    <string name="hiding_navigation_confirmation_message_long" msgid="7854368870786524950">"Dra från kanten av skärmen om du vill visa systemfältet"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-sw/strings.xml b/packages/SystemUI/res/values-sw/strings.xml
index a0fb0a8..e3338de 100644
--- a/packages/SystemUI/res/values-sw/strings.xml
+++ b/packages/SystemUI/res/values-sw/strings.xml
@@ -199,6 +199,4 @@
     <string name="quick_settings_brightness_dialog_auto_brightness_label" msgid="5064982743784071218">"KIOTOMATIKI"</string>
     <string name="status_bar_help_title" msgid="1199237744086469217">"Arifa zitaonekana hapa"</string>
     <string name="status_bar_help_text" msgid="7874607155052076323">"Zifikie wakati wowote kwa kutelezesha chini.\nTelezesha chini tena kupata vidhibiti vya mfumo."</string>
-    <string name="hiding_navigation_confirmation_message" msgid="3227814171674734332">"Telezesha kidole kutoka ukingo wa skrini ili kuonyesha upau"</string>
-    <string name="hiding_navigation_confirmation_message_long" msgid="7854368870786524950">"Telezesha kidole kutoka ukingo wa skrini ili kuonyesha upau wa mfumo"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-th/strings.xml b/packages/SystemUI/res/values-th/strings.xml
index 2552e5c..3127eb3 100644
--- a/packages/SystemUI/res/values-th/strings.xml
+++ b/packages/SystemUI/res/values-th/strings.xml
@@ -201,6 +201,4 @@
     <string name="quick_settings_brightness_dialog_auto_brightness_label" msgid="5064982743784071218">"อัตโนมัติ"</string>
     <string name="status_bar_help_title" msgid="1199237744086469217">"การแจ้งเตือนจะแสดงขึ้นที่นี่"</string>
     <string name="status_bar_help_text" msgid="7874607155052076323">"เข้าถึงได้ทุกเมื่อด้วยการกวาดนิ้วลง\nกวาดนิ้วลงอีกครั้งสำหรับการควบคุมระบบ"</string>
-    <string name="hiding_navigation_confirmation_message" msgid="3227814171674734332">"กวาดขอบของหน้าจอเพื่อแสดงแถบ"</string>
-    <string name="hiding_navigation_confirmation_message_long" msgid="7854368870786524950">"กวาดจากขอบของหน้าจอเพื่อแสดงแถบระบบ"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-tl/strings.xml b/packages/SystemUI/res/values-tl/strings.xml
index dfc6c7d..9d4d9de 100644
--- a/packages/SystemUI/res/values-tl/strings.xml
+++ b/packages/SystemUI/res/values-tl/strings.xml
@@ -201,6 +201,4 @@
     <string name="quick_settings_brightness_dialog_auto_brightness_label" msgid="5064982743784071218">"AUTO"</string>
     <string name="status_bar_help_title" msgid="1199237744086469217">"Dito lumalabas ang mga notification"</string>
     <string name="status_bar_help_text" msgid="7874607155052076323">"I-access ang mga ito anumang oras sa pamamagitan ng pag-swipe pababa.\nMuling mag-swipe pababa para sa mga kontrol ng system."</string>
-    <string name="hiding_navigation_confirmation_message" msgid="3227814171674734332">"Mag-swipe sa gilid ng screen upang ipakita ang bar"</string>
-    <string name="hiding_navigation_confirmation_message_long" msgid="7854368870786524950">"Mag-swipe mula sa gilid ng screen upang ipakita ang system bar"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-tr/strings.xml b/packages/SystemUI/res/values-tr/strings.xml
index f7b34de..b885344 100644
--- a/packages/SystemUI/res/values-tr/strings.xml
+++ b/packages/SystemUI/res/values-tr/strings.xml
@@ -164,8 +164,7 @@
     <string name="status_bar_settings_signal_meter_wifi_nossid" msgid="6557486452774597820">"Kablosuz bağlandı"</string>
     <string name="gps_notification_searching_text" msgid="8574247005642736060">"GPS aranıyor"</string>
     <string name="gps_notification_found_text" msgid="4619274244146446464">"Konum GPS ile belirlendi"</string>
-    <!-- no translation found for accessibility_location_active (2427290146138169014) -->
-    <skip />
+    <string name="accessibility_location_active" msgid="2427290146138169014">"Konum bilgisi istekleri etkin"</string>
     <string name="accessibility_clear_all" msgid="5235938559247164925">"Tüm bildirimleri temizle"</string>
     <string name="status_bar_notification_inspect_item_title" msgid="1163547729015390250">"Uygulama bilgileri"</string>
     <string name="accessibility_rotation_lock_off" msgid="4062780228931590069">"Ekran otomatik olarak dönecektir."</string>
@@ -202,6 +201,4 @@
     <string name="quick_settings_brightness_dialog_auto_brightness_label" msgid="5064982743784071218">"OTOMATİK"</string>
     <string name="status_bar_help_title" msgid="1199237744086469217">"Bildirimler burada görünür"</string>
     <string name="status_bar_help_text" msgid="7874607155052076323">"Aşağıya hızlıca kaydırarak bunlara istediğiniz zaman erişebilirsiniz.\nSistem denetimleri için tekrar hızlıca aşağı kaydırın."</string>
-    <string name="hiding_navigation_confirmation_message" msgid="3227814171674734332">"Çubuğu görüntülemek için ekranın kenarından hızlıca kaydırın"</string>
-    <string name="hiding_navigation_confirmation_message_long" msgid="7854368870786524950">"Sistem çubuğunu görüntülemek için ekranın kenarından hızlıca kaydırın"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-uk/strings.xml b/packages/SystemUI/res/values-uk/strings.xml
index 23e276b..1f3c131 100644
--- a/packages/SystemUI/res/values-uk/strings.xml
+++ b/packages/SystemUI/res/values-uk/strings.xml
@@ -164,8 +164,7 @@
     <string name="status_bar_settings_signal_meter_wifi_nossid" msgid="6557486452774597820">"Wi-Fi під’єднано"</string>
     <string name="gps_notification_searching_text" msgid="8574247005642736060">"Виконується пошук GPS-сигналу"</string>
     <string name="gps_notification_found_text" msgid="4619274244146446464">"Місцезнаходження встановлено за допомогою GPS"</string>
-    <!-- no translation found for accessibility_location_active (2427290146138169014) -->
-    <skip />
+    <string name="accessibility_location_active" msgid="2427290146138169014">"Запити про місцезнаходження активні"</string>
     <string name="accessibility_clear_all" msgid="5235938559247164925">"Очистити всі сповіщення."</string>
     <string name="status_bar_notification_inspect_item_title" msgid="1163547729015390250">"Інформація про програму"</string>
     <string name="accessibility_rotation_lock_off" msgid="4062780228931590069">"Екран обертатиметься автоматично."</string>
@@ -202,6 +201,4 @@
     <string name="quick_settings_brightness_dialog_auto_brightness_label" msgid="5064982743784071218">"АВТО"</string>
     <string name="status_bar_help_title" msgid="1199237744086469217">"Сповіщення з’являються тут"</string>
     <string name="status_bar_help_text" msgid="7874607155052076323">"Отримуйте до них доступ будь-коли, провівши пальцем униз.\nЗнову проведіть униз, щоб відкрити елементи керування системи."</string>
-    <string name="hiding_navigation_confirmation_message" msgid="3227814171674734332">"Гортайте від краю екрана, щоб з’явилась панель"</string>
-    <string name="hiding_navigation_confirmation_message_long" msgid="7854368870786524950">"Проведіть пальцем від краю екрана, щоб з’явилась навігаційна панель"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-vi/strings.xml b/packages/SystemUI/res/values-vi/strings.xml
index 31fc2c8..01ec999 100644
--- a/packages/SystemUI/res/values-vi/strings.xml
+++ b/packages/SystemUI/res/values-vi/strings.xml
@@ -164,8 +164,7 @@
     <string name="status_bar_settings_signal_meter_wifi_nossid" msgid="6557486452774597820">"Đã kết nối Wi-Fi"</string>
     <string name="gps_notification_searching_text" msgid="8574247005642736060">"Đang tìm kiếm GPS"</string>
     <string name="gps_notification_found_text" msgid="4619274244146446464">"Vị trí đặt bởi GPS"</string>
-    <!-- no translation found for accessibility_location_active (2427290146138169014) -->
-    <skip />
+    <string name="accessibility_location_active" msgid="2427290146138169014">"Yêu cầu về thông tin vị trí hiện hoạt"</string>
     <string name="accessibility_clear_all" msgid="5235938559247164925">"Xóa tất cả thông báo."</string>
     <string name="status_bar_notification_inspect_item_title" msgid="1163547729015390250">"Thông tin về ứng dụng"</string>
     <string name="accessibility_rotation_lock_off" msgid="4062780228931590069">"Màn hình sẽ xoay tự động."</string>
@@ -202,6 +201,4 @@
     <string name="quick_settings_brightness_dialog_auto_brightness_label" msgid="5064982743784071218">"TỰ ĐỘNG"</string>
     <string name="status_bar_help_title" msgid="1199237744086469217">"Thông báo xuất hiện tại đây"</string>
     <string name="status_bar_help_text" msgid="7874607155052076323">"Truy cập vào chúng bất kỳ lúc nào bằng cách vuốt xuống.\nVuốt lại xuống để hiển thị các điều khiển hệ thống."</string>
-    <string name="hiding_navigation_confirmation_message" msgid="3227814171674734332">"Vuốt cạnh màn hình để hiển thị thanh"</string>
-    <string name="hiding_navigation_confirmation_message_long" msgid="7854368870786524950">"Vuốt từ cạnh màn hình để hiển thị thanh hệ thống"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-zh-rCN/strings.xml b/packages/SystemUI/res/values-zh-rCN/strings.xml
index b8b56c9..867cb17 100644
--- a/packages/SystemUI/res/values-zh-rCN/strings.xml
+++ b/packages/SystemUI/res/values-zh-rCN/strings.xml
@@ -166,8 +166,7 @@
     <string name="status_bar_settings_signal_meter_wifi_nossid" msgid="6557486452774597820">"WLAN 已连接"</string>
     <string name="gps_notification_searching_text" msgid="8574247005642736060">"正在搜索 GPS"</string>
     <string name="gps_notification_found_text" msgid="4619274244146446464">"已通过 GPS 确定位置"</string>
-    <!-- no translation found for accessibility_location_active (2427290146138169014) -->
-    <skip />
+    <string name="accessibility_location_active" msgid="2427290146138169014">"应用发出了有效位置信息请求"</string>
     <string name="accessibility_clear_all" msgid="5235938559247164925">"清除所有通知。"</string>
     <string name="status_bar_notification_inspect_item_title" msgid="1163547729015390250">"应用信息"</string>
     <string name="accessibility_rotation_lock_off" msgid="4062780228931590069">"屏幕会自动旋转。"</string>
@@ -204,6 +203,4 @@
     <string name="quick_settings_brightness_dialog_auto_brightness_label" msgid="5064982743784071218">"自动"</string>
     <string name="status_bar_help_title" msgid="1199237744086469217">"通知会显示在这里"</string>
     <string name="status_bar_help_text" msgid="7874607155052076323">"向下滑动可随时查看通知。\n再次向下滑动可使用系统控制功能。"</string>
-    <string name="hiding_navigation_confirmation_message" msgid="3227814171674734332">"从屏幕边缘向里滑可显示系统栏"</string>
-    <string name="hiding_navigation_confirmation_message_long" msgid="7854368870786524950">"从屏幕边缘向里滑动即可显示系统栏"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-zh-rTW/strings.xml b/packages/SystemUI/res/values-zh-rTW/strings.xml
index a0bb92a..1d5b2ac 100644
--- a/packages/SystemUI/res/values-zh-rTW/strings.xml
+++ b/packages/SystemUI/res/values-zh-rTW/strings.xml
@@ -203,6 +203,4 @@
     <string name="quick_settings_brightness_dialog_auto_brightness_label" msgid="5064982743784071218">"自動"</string>
     <string name="status_bar_help_title" msgid="1199237744086469217">"系統會在這裡顯示通知"</string>
     <string name="status_bar_help_text" msgid="7874607155052076323">"向下滑動即可隨時存取通知。\n再次向下滑動即可使用系統控制項。"</string>
-    <string name="hiding_navigation_confirmation_message" msgid="3227814171674734332">"從螢幕邊緣向內滑動即可顯示導覽列"</string>
-    <string name="hiding_navigation_confirmation_message_long" msgid="7854368870786524950">"從螢幕邊緣向內滑動即可顯示導覽列"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-zu/strings.xml b/packages/SystemUI/res/values-zu/strings.xml
index 53e7db0..662d3cb 100644
--- a/packages/SystemUI/res/values-zu/strings.xml
+++ b/packages/SystemUI/res/values-zu/strings.xml
@@ -201,6 +201,4 @@
     <string name="quick_settings_brightness_dialog_auto_brightness_label" msgid="5064982743784071218">"OKUZENZAKALELAYO"</string>
     <string name="status_bar_help_title" msgid="1199237744086469217">"Izaziso zivela lapha"</string>
     <string name="status_bar_help_text" msgid="7874607155052076323">"Kufinyelele noma kunini ngokuswayiphela phansi.\nSwayiphela phansi futhi ngezilawuli zesistimu."</string>
-    <string name="hiding_navigation_confirmation_message" msgid="3227814171674734332">"Swayipha kunqenqema lwesikrini ukuze uveze ibha"</string>
-    <string name="hiding_navigation_confirmation_message_long" msgid="7854368870786524950">"Swayipha kusuka kunqenqema ukuze uveze ibha yesistimu"</string>
 </resources>
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/BarTransitions.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/BarTransitions.java
index 74b14b0..199c65a 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/BarTransitions.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/BarTransitions.java
@@ -21,16 +21,19 @@
 import android.content.res.Resources;
 import android.graphics.drawable.ColorDrawable;
 import android.graphics.drawable.Drawable;
+import android.util.Log;
 import android.view.View;
 
 import com.android.systemui.R;
 
 public class BarTransitions {
+    private static final boolean DEBUG = false;
 
     public static final int MODE_NORMAL = 0;
     public static final int MODE_TRANSIENT = 1;
     public static final int MODE_TRANSPARENT = 2;
 
+    private final String mTag;
     private final View mTarget;
     private final Drawable mOpaque;
     private final Drawable mTransient;
@@ -39,6 +42,7 @@
     private int mMode;
 
     public BarTransitions(Context context, View target, Drawable transparent) {
+        mTag = "BarTransitions." + target.getClass().getSimpleName();
         mTarget = target;
         final Resources res = context.getResources();
         mOpaque = new ColorDrawable(res.getColor(R.drawable.status_bar_background));
@@ -56,9 +60,17 @@
     public void transitionTo(int mode) {
         mMode = mode;
         if (!ActivityManager.isHighEndGfx()) return;
+        if (DEBUG) Log.d(mTag, "transitionTo " + modeToString(mode));
         Drawable background = mode == MODE_TRANSIENT ? mTransient
                 : mode == MODE_TRANSPARENT ? mTransparent
                 : mOpaque;
         mTarget.setBackground(background);
     }
+
+    public static String modeToString(int mode) {
+        if (mode == MODE_NORMAL) return "MODE_NORMAL";
+        if (mode == MODE_TRANSIENT) return "MODE_TRANSIENT";
+        if (mode == MODE_TRANSPARENT) return "MODE_TRANSPARENT";
+        throw new IllegalArgumentException("Unknown mode " + mode);
+    }
 }
diff --git a/policy/src/com/android/internal/policy/impl/BarController.java b/policy/src/com/android/internal/policy/impl/BarController.java
new file mode 100644
index 0000000..fb76e20
--- /dev/null
+++ b/policy/src/com/android/internal/policy/impl/BarController.java
@@ -0,0 +1,186 @@
+/*
+ * Copyright (C) 2013 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.internal.policy.impl;
+
+import android.app.StatusBarManager;
+import android.os.Handler;
+import android.os.RemoteException;
+import android.os.ServiceManager;
+import android.util.Slog;
+import android.view.View;
+import android.view.WindowManagerPolicy.WindowState;
+
+import com.android.internal.statusbar.IStatusBarService;
+
+import java.io.PrintWriter;
+
+/**
+ * Controls state/behavior specific to a system bar window.
+ */
+public class BarController {
+    private static final boolean DEBUG = false;
+
+    private static final int TRANSIENT_BAR_NONE = 0;
+    private static final int TRANSIENT_BAR_SHOWING = 1;
+    private static final int TRANSIENT_BAR_HIDING = 2;
+
+    private final String mTag;
+    private final int mTransientFlag;
+    private final int mStatusBarManagerId;
+    private final Handler mHandler;
+    private final Object mServiceAquireLock = new Object();
+    private IStatusBarService mStatusBarService;
+
+    private WindowState mWin;
+    private int mTransientBarState;
+    private boolean mPendingShow;
+
+    public BarController(String tag, int transientFlag, int statusBarManagerId) {
+        mTag = "BarController." + tag;
+        mTransientFlag = transientFlag;
+        mStatusBarManagerId = statusBarManagerId;
+        mHandler = new Handler();
+    }
+
+    public void setWindow(WindowState win) {
+        mWin = win;
+    }
+
+    public void showTransient() {
+        if (mWin != null) {
+            setTransientBarState(TRANSIENT_BAR_SHOWING);
+        }
+    }
+
+    public boolean isTransientShowing() {
+        return mTransientBarState == TRANSIENT_BAR_SHOWING;
+    }
+
+    public void adjustSystemUiVisibilityLw(int visibility) {
+        if (mWin != null && mTransientBarState == TRANSIENT_BAR_SHOWING &&
+                (visibility & mTransientFlag) == 0) {
+            setTransientBarState(TRANSIENT_BAR_HIDING);
+            setBarShowingLw(false);
+        }
+    }
+
+    public boolean setBarShowingLw(final boolean show) {
+        if (mWin == null) return false;
+
+        mHandler.post(new Runnable() {
+            @Override
+            public void run() {
+                try {
+                    IStatusBarService statusbar = getStatusBarService();
+                    if (statusbar != null) {
+                        statusbar.setWindowState(mStatusBarManagerId, show
+                                ? StatusBarManager.WINDOW_STATE_SHOWING
+                                : StatusBarManager.WINDOW_STATE_HIDING);
+                    }
+                } catch (RemoteException e) {
+                    // re-acquire status bar service next time it is needed.
+                    mStatusBarService = null;
+                }
+            }
+        });
+        if (show && mTransientBarState == TRANSIENT_BAR_HIDING) {
+            mPendingShow = true;
+            return false;
+        }
+        return show ? mWin.showLw(true) : mWin.hideLw(true);
+    }
+
+    public boolean checkHiddenLw() {
+        if (mWin != null && mTransientBarState == TRANSIENT_BAR_HIDING && !mWin.isVisibleLw()) {
+            // Finished animating out, clean up and reset style
+            setTransientBarState(TRANSIENT_BAR_NONE);
+            if (mPendingShow) {
+                setBarShowingLw(true);
+                mPendingShow = false;
+            }
+            return true;
+        }
+        return false;
+    }
+
+    public boolean checkShowTransientBarLw() {
+        if (mTransientBarState == TRANSIENT_BAR_SHOWING) {
+            if (DEBUG) Slog.d(mTag, "Not showing transient bar, already shown");
+            return false;
+        } else if (mWin == null) {
+            if (DEBUG) Slog.d(mTag, "Not showing transient bar, bar doesn't exist");
+            return false;
+        } else if (mWin.isDisplayedLw()) {
+            if (DEBUG) Slog.d(mTag, "Not showing transient bar, bar already visible");
+            return false;
+        } else {
+            return true;
+        }
+    }
+
+    public int updateVisibilityLw(boolean allowed, int oldVis, int vis) {
+        if (mWin == null) return vis;
+
+        if (mTransientBarState == TRANSIENT_BAR_SHOWING) { // transient bar requested
+            if (allowed) {
+                vis |= mTransientFlag;
+                if ((oldVis & mTransientFlag) == 0) {
+                    setBarShowingLw(true);
+                }
+            } else {
+                setTransientBarState(TRANSIENT_BAR_NONE);  // request denied
+            }
+        }
+        if (mTransientBarState != TRANSIENT_BAR_NONE) {
+            vis |= mTransientFlag;  // ignore clear requests until transition completes
+            vis &= ~View.SYSTEM_UI_FLAG_LOW_PROFILE;  // never show transient bars in low profile
+        }
+        return vis;
+    }
+
+    private void setTransientBarState(int state) {
+        if (mWin != null && state != mTransientBarState) {
+            mTransientBarState = state;
+            if (DEBUG) Slog.d(mTag, "New state: " + transientBarStateToString(state));
+        }
+    }
+
+    private IStatusBarService getStatusBarService() {
+        synchronized (mServiceAquireLock) {
+            if (mStatusBarService == null) {
+                mStatusBarService = IStatusBarService.Stub.asInterface(
+                        ServiceManager.getService("statusbar"));
+            }
+            return mStatusBarService;
+        }
+    }
+
+    private static String transientBarStateToString(int state) {
+        if (state == TRANSIENT_BAR_HIDING) return "TRANSIENT_BAR_HIDING";
+        if (state == TRANSIENT_BAR_SHOWING) return "TRANSIENT_BAR_SHOWING";
+        if (state == TRANSIENT_BAR_NONE) return "TRANSIENT_BAR_NONE";
+        throw new IllegalArgumentException("Unknown state " + state);
+    }
+
+    public void dump(PrintWriter pw, String prefix) {
+        if (mWin != null) {
+            pw.print(prefix); pw.print(mTag); pw.print(' ');
+            pw.print("mTransientBar"); pw.print('=');
+            pw.println(transientBarStateToString(mTransientBarState));
+        }
+    }
+}
diff --git a/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java b/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java
index 22b5f03..11e33dc 100644
--- a/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java
+++ b/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java
@@ -553,11 +553,10 @@
     }
     MyOrientationListener mOrientationListener;
 
-    private static final int TRANSIENT_BAR_NONE = 0;
-    private static final int TRANSIENT_BAR_SHOWING = 1;
-    private static final int TRANSIENT_BAR_HIDING = 2;
-    private int mStatusTransientBar;
-    private int mNavigationTransientBar;
+    private final BarController mStatusBarController = new BarController("StatusBar",
+            View.STATUS_BAR_TRANSIENT, StatusBarManager.WINDOW_STATUS_BAR);
+    private final BarController mNavigationBarController = new BarController("NavigationBar",
+            View.NAVIGATION_BAR_TRANSIENT, StatusBarManager.WINDOW_NAVIGATION_BAR);
     private TransientNavigationConfirmation mTransientNavigationConfirmation;
 
     private SystemGesturesPointerEventListener mSystemGestures;
@@ -1716,6 +1715,7 @@
                     }
                 }
                 mStatusBar = win;
+                mStatusBarController.setWindow(win);
                 break;
             case TYPE_NAVIGATION_BAR:
                 mContext.enforceCallingOrSelfPermission(
@@ -1727,6 +1727,7 @@
                     }
                 }
                 mNavigationBar = win;
+                mNavigationBarController.setWindow(win);
                 if (DEBUG_LAYOUT) Slog.i(TAG, "NAVIGATION BAR: " + mNavigationBar);
                 break;
             case TYPE_NAVIGATION_BAR_PANEL:
@@ -1765,6 +1766,7 @@
     public void removeWindowLw(WindowState win) {
         if (mStatusBar == win) {
             mStatusBar = null;
+            mStatusBarController.setWindow(null);
         } else if (mKeyguard == win) {
             Log.v(TAG, "Removing keyguard window (Did it crash?)");
             mKeyguard = null;
@@ -1774,6 +1776,7 @@
             mKeyguardScrim = null;
         } if (mNavigationBar == win) {
             mNavigationBar = null;
+            mNavigationBarController.setWindow(null);
         }
     }
 
@@ -2548,16 +2551,9 @@
 
     @Override
     public int adjustSystemUiVisibilityLw(int visibility) {
-        if (mStatusBar != null && mStatusTransientBar == TRANSIENT_BAR_SHOWING &&
-                0 == (visibility & View.STATUS_BAR_TRANSIENT)) {
-            mStatusTransientBar = TRANSIENT_BAR_HIDING;
-            setBarShowingLw(mStatusBar, false);
-        }
-        if (mNavigationBar != null && mNavigationTransientBar == TRANSIENT_BAR_SHOWING &&
-                0 == (visibility & View.NAVIGATION_BAR_TRANSIENT)) {
-            mNavigationTransientBar = TRANSIENT_BAR_HIDING;
-            setBarShowingLw(mNavigationBar, false);
-        }
+        mStatusBarController.adjustSystemUiVisibilityLw(visibility);
+        mNavigationBarController.adjustSystemUiVisibilityLw(visibility);
+
         // Reset any bits in mForceClearingStatusBarVisibility that
         // are now clear.
         mResettingSystemUiFlags &= visibility;
@@ -2714,7 +2710,7 @@
 
             boolean updateSysUiVisibility = false;
             if (mNavigationBar != null) {
-                boolean transientNavBarShowing = mNavigationTransientBar == TRANSIENT_BAR_SHOWING;
+                boolean transientNavBarShowing = mNavigationBarController.isTransientShowing();
                 // Force the navigation bar to its appropriate place and
                 // size.  We need to do this directly, instead of relying on
                 // it to bubble up from the nav bar, because this needs to
@@ -2727,15 +2723,15 @@
                     mTmpNavigationFrame.set(0, top, displayWidth, displayHeight - overscanBottom);
                     mStableBottom = mStableFullscreenBottom = mTmpNavigationFrame.top;
                     if (transientNavBarShowing || navTransparent) {
-                        setBarShowingLw(mNavigationBar, true);
+                        mNavigationBarController.setBarShowingLw(true);
                     } else if (navVisible) {
-                        setBarShowingLw(mNavigationBar, true);
+                        mNavigationBarController.setBarShowingLw(true);
                         mDockBottom = mTmpNavigationFrame.top;
                         mRestrictedScreenHeight = mDockBottom - mRestrictedScreenTop;
                         mRestrictedOverscanScreenHeight = mDockBottom - mRestrictedOverscanScreenTop;
                     } else {
                         // We currently want to hide the navigation UI.
-                        setBarShowingLw(mNavigationBar, false);
+                        mNavigationBarController.setBarShowingLw(false);
                     }
                     if (navVisible && !navTransparent && !mNavigationBar.isAnimatingLw()) {
                         // If the opaque nav bar is currently requested to be visible,
@@ -2750,15 +2746,15 @@
                     mTmpNavigationFrame.set(left, 0, displayWidth - overscanRight, displayHeight);
                     mStableRight = mStableFullscreenRight = mTmpNavigationFrame.left;
                     if (transientNavBarShowing || navTransparent) {
-                        setBarShowingLw(mNavigationBar, true);
+                        mNavigationBarController.setBarShowingLw(true);
                     } else if (navVisible) {
-                        setBarShowingLw(mNavigationBar, true);
+                        mNavigationBarController.setBarShowingLw(true);
                         mDockRight = mTmpNavigationFrame.left;
                         mRestrictedScreenWidth = mDockRight - mRestrictedScreenLeft;
                         mRestrictedOverscanScreenWidth = mDockRight - mRestrictedOverscanScreenLeft;
                     } else {
                         // We currently want to hide the navigation UI.
-                        setBarShowingLw(mNavigationBar, false);
+                        mNavigationBarController.setBarShowingLw(false);
                     }
                     if (navVisible && !navTransparent && !mNavigationBar.isAnimatingLw()) {
                         // If the nav bar is currently requested to be visible,
@@ -2778,9 +2774,7 @@
                 mNavigationBar.computeFrameLw(mTmpNavigationFrame, mTmpNavigationFrame,
                         mTmpNavigationFrame, mTmpNavigationFrame, mTmpNavigationFrame);
                 if (DEBUG_LAYOUT) Slog.i(TAG, "mNavigationBar frame: " + mTmpNavigationFrame);
-                if (mNavigationTransientBar == TRANSIENT_BAR_HIDING && !mNavigationBar.isVisibleLw()) {
-                    // Finished animating out, clean up and reset alpha
-                    mNavigationTransientBar = TRANSIENT_BAR_NONE;
+                if (mNavigationBarController.checkHiddenLw()) {
                     updateSysUiVisibility = true;
                 }
             }
@@ -2838,10 +2832,7 @@
                     // we can tell the app that it is covered by it.
                     mSystemTop = mUnrestrictedScreenTop + mStatusBarHeight;
                 }
-
-                if (mStatusTransientBar == TRANSIENT_BAR_HIDING && !mStatusBar.isVisibleLw()) {
-                    // Finished animating out, clean up and reset alpha
-                    mStatusTransientBar = TRANSIENT_BAR_NONE;
+                if (mStatusBarController.checkHiddenLw()) {
                     updateSysUiVisibility = true;
                 }
             }
@@ -3410,7 +3401,9 @@
                     + " top=" + mTopFullscreenOpaqueWindowState);
             if (mForceStatusBar || mForceStatusBarFromKeyguard) {
                 if (DEBUG_LAYOUT) Slog.v(TAG, "Showing status bar: forced");
-                if (setBarShowingLw(mStatusBar, true)) changes |= FINISH_LAYOUT_REDO_LAYOUT;
+                if (mStatusBarController.setBarShowingLw(true)) {
+                    changes |= FINISH_LAYOUT_REDO_LAYOUT;
+                }
             } else if (mTopFullscreenOpaqueWindowState != null) {
                 if (localLOGV) {
                     Slog.d(TAG, "frame: " + mTopFullscreenOpaqueWindowState.getFrameLw()
@@ -3424,20 +3417,22 @@
                 // and mTopIsFullscreen is that that mTopIsFullscreen is set only if the window
                 // has the FLAG_FULLSCREEN set.  Not sure if there is another way that to be the
                 // case though.
-                if (mStatusTransientBar == TRANSIENT_BAR_SHOWING) {
-                    if (setBarShowingLw(mStatusBar, true)) {
+                if (mStatusBarController.isTransientShowing()) {
+                    if (mStatusBarController.setBarShowingLw(true)) {
                         changes |= FINISH_LAYOUT_REDO_LAYOUT;
                     }
                 } else if (topIsFullscreen) {
                     if (DEBUG_LAYOUT) Slog.v(TAG, "** HIDING status bar");
-                    if (setBarShowingLw(mStatusBar, false)) {
+                    if (mStatusBarController.setBarShowingLw(false)) {
                         changes |= FINISH_LAYOUT_REDO_LAYOUT;
                     } else {
                         if (DEBUG_LAYOUT) Slog.v(TAG, "Status bar already hiding");
                     }
                 } else {
                     if (DEBUG_LAYOUT) Slog.v(TAG, "** SHOWING status bar: top is not fullscreen");
-                    if (setBarShowingLw(mStatusBar, true)) changes |= FINISH_LAYOUT_REDO_LAYOUT;
+                    if (mStatusBarController.setBarShowingLw(true)) {
+                        changes |= FINISH_LAYOUT_REDO_LAYOUT;
+                    }
                 }
             }
         }
@@ -3882,7 +3877,7 @@
             case KeyEvent.KEYCODE_POWER: {
                 result &= ~ACTION_PASS_TO_USER;
                 if (down) {
-                    if (isScreenOn && isNavigationBarTransient(mLastSystemUiFlags)) {
+                    if (isScreenOn && isTransientNavigationAllowed(mLastSystemUiFlags)) {
                         mTransientNavigationConfirmation.unconfirmLastPackage();
                     }
                     if (isScreenOn && !mPowerKeyTriggered
@@ -4153,36 +4148,21 @@
 
     private void requestTransientBars(WindowState swipeTarget) {
         synchronized (mWindowManagerFuncs.getWindowManagerLock()) {
-            boolean sb = checkShowTransientBar("status", mStatusTransientBar, mStatusBar);
-            boolean nb = checkShowTransientBar("nav", mNavigationTransientBar, mNavigationBar);
+            boolean sb = mStatusBarController.checkShowTransientBarLw();
+            boolean nb = mNavigationBarController.checkShowTransientBarLw();
             if (sb || nb) {
                 WindowState barTarget = sb ? mStatusBar : mNavigationBar;
                 if (sb ^ nb && barTarget != swipeTarget) {
                     if (DEBUG) Slog.d(TAG, "Not showing transient bar, wrong swipe target");
                     return;
                 }
-                mStatusTransientBar = sb ? TRANSIENT_BAR_SHOWING : mStatusTransientBar;
-                mNavigationTransientBar = nb ? TRANSIENT_BAR_SHOWING : mNavigationTransientBar;
+                if (sb) mStatusBarController.showTransient();
+                if (nb) mNavigationBarController.showTransient();
                 updateSystemUiVisibilityLw();
             }
         }
     }
 
-    private boolean checkShowTransientBar(String tag, int transientBar, WindowState win) {
-        if (transientBar == TRANSIENT_BAR_SHOWING) {
-            if (DEBUG) Slog.d(TAG, "Not showing " + tag + " transient bar, already shown");
-            return false;
-        } else if (win == null) {
-            if (DEBUG) Slog.d(TAG, "Not showing " + tag + " transient bar, bar doesn't exist");
-            return false;
-        } else if (win.isDisplayedLw()) {
-            if (DEBUG) Slog.d(TAG, "Not showing " + tag + " transient bar, bar already visible");
-            return false;
-        } else {
-            return true;
-        }
-    }
-
     @Override
     public void screenTurnedOff(int why) {
         EventLog.writeEvent(70000, 0);
@@ -5057,106 +5037,62 @@
         if (ImmersiveModeTesting.enabled) {
             vis = ImmersiveModeTesting.applyForced(mFocusedWindow, vis);
         }
+
+        // prevent status bar interaction from clearing certain flags
         boolean statusBarHasFocus = mFocusedWindow.getAttrs().type == TYPE_STATUS_BAR;
         if (statusBarHasFocus) {
-            // prevent status bar interaction from clearing certain flags
             int flags = View.SYSTEM_UI_FLAG_FULLSCREEN
                     | View.SYSTEM_UI_FLAG_HIDE_NAVIGATION
                     | View.SYSTEM_UI_FLAG_ALLOW_TRANSIENT;
             vis = (vis & ~flags) | (mLastSystemUiFlags & flags);
         }
-        if (mStatusTransientBar == TRANSIENT_BAR_SHOWING) {
-            // status transient bar requested
-            boolean transientAllowed =
-                    (vis & View.SYSTEM_UI_FLAG_ALLOW_TRANSIENT) != 0;
-            boolean hideStatusBarWM =
-                    (mFocusedWindow.getAttrs().flags
-                            & WindowManager.LayoutParams.FLAG_FULLSCREEN) != 0;
-            boolean hideStatusBarSysui =
-                    (vis & View.SYSTEM_UI_FLAG_FULLSCREEN) != 0;
 
-            boolean transientStatusBarAllowed =
-                    hideStatusBarWM
-                    || (hideStatusBarSysui && transientAllowed)
-                    || statusBarHasFocus;
+        // update status bar
+        boolean transientAllowed =
+                (vis & View.SYSTEM_UI_FLAG_ALLOW_TRANSIENT) != 0;
+        boolean hideStatusBarWM =
+                (mFocusedWindow.getAttrs().flags
+                        & WindowManager.LayoutParams.FLAG_FULLSCREEN) != 0;
+        boolean hideStatusBarSysui =
+                (vis & View.SYSTEM_UI_FLAG_FULLSCREEN) != 0;
 
-            if (mStatusBar == null || !transientStatusBarAllowed) {
-                mStatusTransientBar = TRANSIENT_BAR_NONE;
-                if (mStatusBar != null && hideStatusBarSysui) {
-                    // clear the clearable flags instead
-                    int newVal = mResettingSystemUiFlags | View.SYSTEM_UI_CLEARABLE_FLAGS;
-                    if (newVal != mResettingSystemUiFlags) {
-                        mResettingSystemUiFlags = newVal;
-                        mWindowManagerFuncs.reevaluateStatusBarVisibility();
-                    }
-                }
-            } else {
-                // show status transient bar
-                vis |= View.STATUS_BAR_TRANSIENT;
-                if ((mLastSystemUiFlags & View.STATUS_BAR_TRANSIENT) == 0) {
-                    vis &= ~View.SYSTEM_UI_FLAG_LOW_PROFILE;
-                    setBarShowingLw(mStatusBar, true);
-                }
+        boolean transientStatusBarAllowed =
+                mStatusBar != null && (
+                hideStatusBarWM
+                || (hideStatusBarSysui && transientAllowed)
+                || statusBarHasFocus);
+
+        if (mStatusBarController.isTransientShowing()
+                && !transientStatusBarAllowed && hideStatusBarSysui) {
+            // clear the clearable flags instead
+            int newVal = mResettingSystemUiFlags | View.SYSTEM_UI_CLEARABLE_FLAGS;
+            if (newVal != mResettingSystemUiFlags) {
+                mResettingSystemUiFlags = newVal;
+                mWindowManagerFuncs.reevaluateStatusBarVisibility();
             }
         }
-        boolean oldTransientNav = isNavigationBarTransient(oldVis);
-        boolean isTransientNav = isNavigationBarTransient(vis);
+
+        vis = mStatusBarController.updateVisibilityLw(transientStatusBarAllowed, oldVis, vis);
+
+        // update navigation bar
+        boolean oldTransientNav = isTransientNavigationAllowed(oldVis);
+        boolean isTransientNav = isTransientNavigationAllowed(vis);
         if (mFocusedWindow != null && oldTransientNav != isTransientNav) {
             final int uid = getCurrentUserId();
             final String pkg = mFocusedWindow.getOwningPackage();
             mTransientNavigationConfirmation.transientNavigationChanged(uid, pkg, isTransientNav);
         }
-        if (mNavigationTransientBar == TRANSIENT_BAR_SHOWING) {
-            // navigation transient bar requested
-            if (!isTransientNav) {
-                mNavigationTransientBar = TRANSIENT_BAR_NONE;
-            } else {
-                // show navigation transient bar
-                vis |= View.NAVIGATION_BAR_TRANSIENT;
-                if ((mLastSystemUiFlags & View.NAVIGATION_BAR_TRANSIENT) == 0) {
-                    setBarShowingLw(mNavigationBar, true);
-                }
-            }
-        }
-        if (mStatusTransientBar != TRANSIENT_BAR_NONE
-                || mNavigationTransientBar != TRANSIENT_BAR_NONE) {
-            vis &= ~View.SYSTEM_UI_FLAG_LOW_PROFILE;
-        }
+        vis = mNavigationBarController.updateVisibilityLw(isTransientNav, oldVis, vis);
+
         return vis;
     }
 
-    private boolean isNavigationBarTransient(int vis) {
+    private boolean isTransientNavigationAllowed(int vis) {
         return mNavigationBar != null
                 && (vis & View.SYSTEM_UI_FLAG_HIDE_NAVIGATION) != 0
                 && (vis & View.SYSTEM_UI_FLAG_ALLOW_TRANSIENT) != 0;
     }
 
-    private boolean setBarShowingLw(WindowState win, final boolean show) {
-        final int window =
-                  win == mStatusBar ? StatusBarManager.WINDOW_STATUS_BAR
-                : win == mNavigationBar ? StatusBarManager.WINDOW_NAVIGATION_BAR
-                : 0;
-        if (window != 0) {
-            mHandler.post(new Runnable() {
-                @Override
-                public void run() {
-                    try {
-                        IStatusBarService statusbar = getStatusBarService();
-                        if (statusbar != null) {
-                            statusbar.setWindowState(window, show
-                                    ? StatusBarManager.WINDOW_STATE_SHOWING
-                                    : StatusBarManager.WINDOW_STATE_HIDING);
-                        }
-                    } catch (RemoteException e) {
-                        // re-acquire status bar service next time it is needed.
-                        mStatusBarService = null;
-                    }
-                }
-            });
-        }
-        return show ? win.showLw(true) : win.hideLw(true);
-    }
-
     // Temporary helper that allows testing immersive mode on existing apps
     // TODO remove
     private static final class ImmersiveModeTesting {
@@ -5417,18 +5353,7 @@
         pw.print(prefix); pw.print("mDemoHdmiRotation="); pw.print(mDemoHdmiRotation);
                 pw.print(" mDemoHdmiRotationLock="); pw.println(mDemoHdmiRotationLock);
         pw.print(prefix); pw.print("mUndockedHdmiRotation="); pw.println(mUndockedHdmiRotation);
-        dumpTransient(pw, prefix,
-                mStatusBar, "mStatusTransientBar", mStatusTransientBar);
-        dumpTransient(pw, prefix,
-                mNavigationBar, "mNavigationTransientBar", mNavigationTransientBar);
-    }
-
-    private void dumpTransient(PrintWriter pw, String pre, WindowState win, String var, int val) {
-        if (win != null) {
-            pw.print(pre); pw.print(var); pw.print('=');
-            pw.println(val == TRANSIENT_BAR_HIDING ? "HIDING"
-                     : val == TRANSIENT_BAR_SHOWING ? "SHOWING"
-                     : "NONE");
-        }
+        mStatusBarController.dump(pw, prefix);
+        mNavigationBarController.dump(pw, prefix);
     }
 }
diff --git a/services/input/InputReader.h b/services/input/InputReader.h
index 98daaf5..a8bb636 100644
--- a/services/input/InputReader.h
+++ b/services/input/InputReader.h
@@ -1285,6 +1285,9 @@
             if (haveSizeBias) {
                 *outSize += sizeBias;
             }
+            if (*outSize < 0) {
+                *outSize = 0;
+            }
         }
     } mCalibration;
 
diff --git a/services/java/com/android/server/content/SyncManager.java b/services/java/com/android/server/content/SyncManager.java
index ee5b890..a6b69a2 100644
--- a/services/java/com/android/server/content/SyncManager.java
+++ b/services/java/com/android/server/content/SyncManager.java
@@ -2889,11 +2889,12 @@
             // determine if we need to set or cancel the alarm
             boolean shouldSet = false;
             boolean shouldCancel = false;
-            final boolean alarmIsActive = mAlarmScheduleTime != null;
+            final boolean alarmIsActive = (mAlarmScheduleTime != null) && (now < mAlarmScheduleTime);
             final boolean needAlarm = alarmTime != Long.MAX_VALUE;
             if (needAlarm) {
-                // Need the alarm if it's currently not set, or if our time is before the currently
-                // set time.
+                // Need the alarm if
+                //  - it's currently not set
+                //  - if the alarm is set in the past.
                 if (!alarmIsActive || alarmTime < mAlarmScheduleTime) {
                     shouldSet = true;
                 }
@@ -2910,7 +2911,7 @@
                             + " secs from now");
                 }
                 mAlarmScheduleTime = alarmTime;
-                mAlarmService.set(AlarmManager.ELAPSED_REALTIME_WAKEUP, alarmTime,
+                mAlarmService.setExact(AlarmManager.ELAPSED_REALTIME_WAKEUP, alarmTime,
                         mSyncAlarmIntent);
             } else if (shouldCancel) {
                 mAlarmScheduleTime = null;
diff --git a/services/java/com/android/server/content/SyncStorageEngine.java b/services/java/com/android/server/content/SyncStorageEngine.java
index 25529a6..e3693f8 100644
--- a/services/java/com/android/server/content/SyncStorageEngine.java
+++ b/services/java/com/android/server/content/SyncStorageEngine.java
@@ -53,6 +53,7 @@
 import java.io.File;
 import java.io.FileInputStream;
 import java.io.FileOutputStream;
+import java.io.IOException;
 import java.util.ArrayList;
 import java.util.Calendar;
 import java.util.HashMap;
@@ -71,7 +72,7 @@
 
     private static final String TAG = "SyncManager";
     private static final boolean DEBUG = true;
-    private static final boolean DEBUG_FILE = true;
+    private static final String TAG_FILE = "SyncManagerFile";
 
     private static final String XML_ATTR_NEXT_AUTHORITY_ID = "nextAuthorityId";
     private static final String XML_ATTR_LISTEN_FOR_TICKLES = "listen-for-tickles";
@@ -420,9 +421,12 @@
         File systemDir = new File(dataDir, "system");
         File syncDir = new File(systemDir, "sync");
         syncDir.mkdirs();
+
+        maybeDeleteLegacyPendingInfoLocked(syncDir);
+
         mAccountInfoFile = new AtomicFile(new File(syncDir, "accounts.xml"));
         mStatusFile = new AtomicFile(new File(syncDir, "status.bin"));
-        mPendingFile = new AtomicFile(new File(syncDir, "pending.bin"));
+        mPendingFile = new AtomicFile(new File(syncDir, "pending.xml"));
         mStatisticsFile = new AtomicFile(new File(syncDir, "stats.bin"));
 
         readAccountInfoLocked();
@@ -676,7 +680,8 @@
                         continue;
                     }
                     for (AuthorityInfo authorityInfo : accountInfo.authorities.values()) {
-                        if (providerName != null && !providerName.equals(authorityInfo.authority)) {
+                        if (providerName != null
+                                && !providerName.equals(authorityInfo.authority)) {
                             continue;
                         }
                         if (authorityInfo.backoffTime != nextSyncTime
@@ -774,10 +779,12 @@
         }
         synchronized (mAuthorities) {
             if (toUpdate.period <= 0 && add) {
-                Log.e(TAG, "period < 0, should never happen in updateOrRemovePeriodicSync: add-" + add);
+                Log.e(TAG, "period < 0, should never happen in updateOrRemovePeriodicSync: add-"
+                        + add);
             }
             if (toUpdate.extras == null) {
-                Log.e(TAG, "period < 0, should never happen in updateOrRemovePeriodicSync: add-" + add);
+                Log.e(TAG, "null extras, should never happen in updateOrRemovePeriodicSync: add-"
+                        + add);
             }
             try {
                 AuthorityInfo authority =
@@ -806,7 +813,7 @@
                     if (!alreadyPresent) {
                         authority.periodicSyncs.add(new PeriodicSync(toUpdate));
                         SyncStatusInfo status = getOrCreateSyncStatusLocked(authority.ident);
-                        status.setPeriodicSyncTime(authority.periodicSyncs.size() - 1, 0);
+                        status.setPeriodicSyncTime(authority.periodicSyncs.size() - 1, 0L);
                     }
                 } else {
                     // Remove any periodic syncs that match the authority and extras.
@@ -824,7 +831,8 @@
                             if (status != null) {
                                 status.removePeriodicSyncTime(i);
                             } else {
-                                Log.e(TAG, "Tried removing sync status on remove periodic sync but did not find it.");
+                                Log.e(TAG, "Tried removing sync status on remove periodic sync but"
+                                        + "did not find it.");
                             }
                         } else {
                             i++;
@@ -942,7 +950,7 @@
             op = new PendingOperation(op);
             op.authorityId = authority.ident;
             mPendingOperations.add(op);
-            writePendingOperationsLocked();
+            appendPendingOperationLocked(op);
 
             SyncStatusInfo status = getOrCreateSyncStatusLocked(authority.ident);
             status.pending = true;
@@ -1660,7 +1668,9 @@
         FileInputStream fis = null;
         try {
             fis = mAccountInfoFile.openRead();
-            if (DEBUG_FILE) Log.v(TAG, "Reading " + mAccountInfoFile.getBaseFile());
+            if (Log.isLoggable(TAG_FILE, Log.VERBOSE)) {
+                Log.v(TAG, "Reading " + mAccountInfoFile.getBaseFile());
+            }
             XmlPullParser parser = Xml.newPullParser();
             parser.setInput(fis, null);
             int eventType = parser.getEventType();
@@ -1745,6 +1755,20 @@
     }
 
     /**
+     * Ensure the old pending.bin is deleted, as it has been changed to pending.xml.
+     * pending.xml was used starting in KLP.
+     * @param syncDir directory where the sync files are located.
+     */
+    private void maybeDeleteLegacyPendingInfoLocked(File syncDir) {
+        File file = new File(syncDir, "pending.bin");
+        if (!file.exists()) {
+            return;
+        } else {
+            file.delete();
+        }
+    }
+
+    /**
      * some authority names have changed. copy over their settings and delete the old ones
      * @return true if a change was made
      */
@@ -1832,18 +1856,21 @@
                 syncable = "unknown";
             }
             authority = mAuthorities.get(id);
-            if (DEBUG_FILE) Log.v(TAG, "Adding authority: account="
-                    + accountName + " auth=" + authorityName
-                    + " user=" + userId
-                    + " enabled=" + enabled
-                    + " syncable=" + syncable);
+            if (Log.isLoggable(TAG_FILE, Log.VERBOSE)) {
+                Log.v(TAG, "Adding authority: account="
+                        + accountName + " auth=" + authorityName
+                        + " user=" + userId
+                        + " enabled=" + enabled
+                        + " syncable=" + syncable);
+            }
             if (authority == null) {
-                if (DEBUG_FILE) {
+                if (Log.isLoggable(TAG_FILE, Log.VERBOSE)) {
                     Log.v(TAG, "Creating entry");
                 }
                 if (accountName != null && accountType != null) {
                     authority = getOrCreateAuthorityLocked(
-                            new Account(accountName, accountType), userId, authorityName, id, false);
+                            new Account(accountName, accountType), userId, authorityName, id,
+                                false);
                 } else {
                     authority = getOrCreateAuthorityLocked(
                             new ComponentName(packageName, className), userId, id, false);
@@ -1943,7 +1970,9 @@
      * Write all account information to the account file.
      */
     private void writeAccountInfoLocked() {
-        if (DEBUG_FILE) Log.v(TAG, "Writing new " + mAccountInfoFile.getBaseFile());
+        if (Log.isLoggable(TAG_FILE, Log.VERBOSE)) {
+            Log.v(TAG, "Writing new " + mAccountInfoFile.getBaseFile());
+        }
         FileOutputStream fos = null;
 
         try {
@@ -2041,7 +2070,9 @@
             final boolean hasType = db.getVersion() >= 11;
 
             // Copy in all of the status information, as well as accounts.
-            if (DEBUG_FILE) Log.v(TAG, "Reading legacy sync accounts db");
+            if (Log.isLoggable(TAG_FILE, Log.VERBOSE)) {
+                Log.v(TAG, "Reading legacy sync accounts db");
+            }
             SQLiteQueryBuilder qb = new SQLiteQueryBuilder();
             qb.setTables("stats, status");
             HashMap<String,String> map = new HashMap<String,String>();
@@ -2151,7 +2182,9 @@
      * Read all sync status back in to the initial engine state.
      */
     private void readStatusLocked() {
-        if (DEBUG_FILE) Log.v(TAG, "Reading " + mStatusFile.getBaseFile());
+        if (Log.isLoggable(TAG_FILE, Log.VERBOSE)) {
+            Log.v(TAG, "Reading " + mStatusFile.getBaseFile());
+        }
         try {
             byte[] data = mStatusFile.readFully();
             Parcel in = Parcel.obtain();
@@ -2163,8 +2196,10 @@
                     SyncStatusInfo status = new SyncStatusInfo(in);
                     if (mAuthorities.indexOfKey(status.authorityId) >= 0) {
                         status.pending = false;
-                        if (DEBUG_FILE) Log.v(TAG, "Adding status for id "
-                                + status.authorityId);
+                        if (Log.isLoggable(TAG_FILE, Log.VERBOSE)) {
+                            Log.v(TAG, "Adding status for id "
+                                    + status.authorityId);
+                        }
                         mSyncStatus.put(status.authorityId, status);
                     }
                 } else {
@@ -2182,7 +2217,9 @@
      * Write all sync status to the sync status file.
      */
     private void writeStatusLocked() {
-        if (DEBUG_FILE) Log.v(TAG, "Writing new " + mStatusFile.getBaseFile());
+        if (Log.isLoggable(TAG_FILE, Log.VERBOSE)) {
+            Log.v(TAG, "Writing new " + mStatusFile.getBaseFile());
+        }
 
         // The file is being written, so we don't need to have a scheduled
         // write until the next change.
@@ -2211,103 +2248,97 @@
         }
     }
 
-    public static final int PENDING_OPERATION_VERSION = 4;
+    public static final int PENDING_OPERATION_VERSION = 3;
 
-    /**
-     * Read all pending operations back in to the initial engine state.
-     */
+    /** Read all pending operations back in to the initial engine state. */
     private void readPendingOperationsLocked() {
-        if (DEBUG_FILE) Log.v(TAG, "Reading " + mPendingFile.getBaseFile());
-        try {
-            readPendingAsXml();
-        } catch (XmlPullParserException e) {
-            Log.d(TAG, "Error parsing pending as xml, trying as parcel.");
-            try {
-                readPendingAsParcelled();
-            } catch (java.io.IOException e1) {
-                Log.i(TAG, "No initial pending operations");
+        FileInputStream fis = null;
+        if (!mPendingFile.getBaseFile().exists()) {
+            if (Log.isLoggable(TAG_FILE, Log.VERBOSE)) {
+                Log.v(TAG_FILE, "No pending operation file.");
+                return;
             }
         }
-    }
-
-    private void readPendingAsXml() throws XmlPullParserException {
-        FileInputStream fis = null;
         try {
             fis = mPendingFile.openRead();
-            XmlPullParser parser = Xml.newPullParser();
+            XmlPullParser parser;
+            parser = Xml.newPullParser();
             parser.setInput(fis, null);
+
             int eventType = parser.getEventType();
             while (eventType != XmlPullParser.START_TAG &&
                     eventType != XmlPullParser.END_DOCUMENT) {
                 eventType = parser.next();
             }
-            if (eventType == XmlPullParser.END_DOCUMENT) return;
+            if (eventType == XmlPullParser.END_DOCUMENT) return; // Nothing to read.
 
             String tagName = parser.getName();
-            if ("pending".equals(tagName)) {
-                int version = -1;
-                String versionString = parser.getAttributeValue(null, "version");
-                if (versionString == null ||
-                        Integer.parseInt(versionString) != PENDING_OPERATION_VERSION) {
-                    Log.w(TAG, "Unknown pending operation version "
-                            + version + "; trying to read as binary.");
-                    throw new XmlPullParserException("Unknown version.");
-                }
-                eventType = parser.next();
+            do {
                 PendingOperation pop = null;
-                do {
-                    if (eventType == XmlPullParser.START_TAG) {
-                        try {
-                            tagName = parser.getName();
-                            if (parser.getDepth() == 2 && "op".equals(tagName)) {
-                                int authorityId = Integer.valueOf(parser.getAttributeValue(
-                                        null, XML_ATTR_AUTHORITYID));
-                                boolean expedited = Boolean.valueOf(parser.getAttributeValue(
-                                        null, XML_ATTR_EXPEDITED));
-                                int syncSource = Integer.valueOf(parser.getAttributeValue(
-                                        null, XML_ATTR_SOURCE));
-                                int reason = Integer.valueOf(parser.getAttributeValue(
-                                        null, XML_ATTR_REASON));
-                                AuthorityInfo authority = mAuthorities.get(authorityId);
-                                if (DEBUG_FILE) {
-                                    Log.v(TAG, authorityId + " " + expedited + " " + syncSource + " " + reason);
-                                }
-                                if (authority != null) {
-                                    pop = new PendingOperation(
-                                            authority.account, authority.userId, reason, syncSource,
-                                            authority.authority, new Bundle(), expedited);
-                                    pop.authorityId = authorityId;
-                                    pop.flatExtras = null; // No longer used.
-                                    mPendingOperations.add(pop);
-                                    if (DEBUG_FILE) Log.v(TAG, "Adding pending op: account=" + pop.account
-                                            + " auth=" + pop.authority
+                if (eventType == XmlPullParser.START_TAG) {
+                    try {
+                        tagName = parser.getName();
+                        if (parser.getDepth() == 1 && "op".equals(tagName)) {
+                            // Verify version.
+                            String versionString =
+                                    parser.getAttributeValue(null, XML_ATTR_VERSION);
+                            if (versionString == null ||
+                                    Integer.parseInt(versionString) != PENDING_OPERATION_VERSION) {
+                                Log.w(TAG, "Unknown pending operation version " + versionString);
+                                throw new java.io.IOException("Unknown version.");
+                            }
+                            int authorityId = Integer.valueOf(parser.getAttributeValue(
+                                    null, XML_ATTR_AUTHORITYID));
+                            boolean expedited = Boolean.valueOf(parser.getAttributeValue(
+                                    null, XML_ATTR_EXPEDITED));
+                            int syncSource = Integer.valueOf(parser.getAttributeValue(
+                                    null, XML_ATTR_SOURCE));
+                            int reason = Integer.valueOf(parser.getAttributeValue(
+                                    null, XML_ATTR_REASON));
+                            AuthorityInfo authority = mAuthorities.get(authorityId);
+                            if (Log.isLoggable(TAG_FILE, Log.VERBOSE)) {
+                                Log.v(TAG_FILE, authorityId + " " + expedited + " " + syncSource + " "
+                                        + reason);
+                            }
+                            if (authority != null) {
+                                pop = new PendingOperation(
+                                        authority.account, authority.userId, reason,
+                                        syncSource, authority.authority, new Bundle(),
+                                        expedited);
+                                pop.flatExtras = null; // No longer used.
+                                mPendingOperations.add(pop);
+                                if (Log.isLoggable(TAG_FILE, Log.VERBOSE)) {
+                                    Log.v(TAG_FILE, "Adding pending op: "
+                                            + pop.authority
                                             + " src=" + pop.syncSource
                                             + " reason=" + pop.reason
                                             + " expedited=" + pop.expedited);
-                                } else {
-                                    // Skip non-existent authority;
-                                    pop = null;
-                                    if (DEBUG_FILE) {
-                                        Log.v(TAG, "No authority found for " + authorityId
-                                                + ", skipping");
-                                    }
                                 }
-                            } else if (parser.getDepth() == 3 &&
-                                        pop != null &&
-                                        "extra".equals(tagName)) {
-                                    parseExtra(parser, pop.extras);
+                            } else {
+                                // Skip non-existent authority.
+                                pop = null;
+                                if (Log.isLoggable(TAG_FILE, Log.VERBOSE)) {
+                                    Log.v(TAG_FILE, "No authority found for " + authorityId
+                                            + ", skipping");
+                                }
                             }
-                        } catch (NumberFormatException e) {
-                            Log.d(TAG, "Invalid data in xml file.", e);
+                        } else if (parser.getDepth() == 2 &&
+                                pop != null &&
+                                "extra".equals(tagName)) {
+                            parseExtra(parser, pop.extras);
                         }
+                    } catch (NumberFormatException e) {
+                        Log.d(TAG, "Invalid data in xml file.", e);
                     }
-                    eventType = parser.next();
-                } while(eventType != XmlPullParser.END_DOCUMENT);
-            }
+                }
+                eventType = parser.next();
+            } while(eventType != XmlPullParser.END_DOCUMENT);
         } catch (java.io.IOException e) {
-            if (fis == null) Log.i(TAG, "No initial pending operations.");
-            else Log.w(TAG, "Error reading pending data.", e);
-            return;
+            Log.w(TAG_FILE, "Error reading pending data.", e);
+        } catch (XmlPullParserException e) {
+            if (Log.isLoggable(TAG_FILE, Log.VERBOSE)) {
+                Log.w(TAG_FILE, "Error parsing pending ops xml.", e);
+            }
         } finally {
             if (fis != null) {
                 try {
@@ -2316,57 +2347,96 @@
             }
         }
     }
+
+    private static final String XML_ATTR_AUTHORITYID = "authority_id";
+    private static final String XML_ATTR_SOURCE = "source";
+    private static final String XML_ATTR_EXPEDITED = "expedited";
+    private static final String XML_ATTR_REASON = "reason";
+    private static final String XML_ATTR_VERSION = "version";
+
     /**
-     * Old format of reading pending.bin as a parcelled file. Replaced in lieu of JSON because
-     * persisting parcels is unsafe.
-     * @throws java.io.IOException
+     * Write all currently pending ops to the pending ops file.
      */
-    private void readPendingAsParcelled() throws java.io.IOException {
-        byte[] data = mPendingFile.readFully();
-        Parcel in = Parcel.obtain();
-        in.unmarshall(data, 0, data.length);
-        in.setDataPosition(0);
-        final int SIZE = in.dataSize();
-        while (in.dataPosition() < SIZE) {
-            int version = in.readInt();
-            if (version != 3 && version != 1) {
-                Log.w(TAG, "Unknown pending operation version "
-                        + version + "; dropping all ops");
-                break;
-            }
-            int authorityId = in.readInt();
-            int syncSource = in.readInt();
-            byte[] flatExtras = in.createByteArray();
-            boolean expedited;
-            if (version == PENDING_OPERATION_VERSION) {
-                expedited = in.readInt() != 0;
-            } else {
-                expedited = false;
-            }
-            int reason = in.readInt();
-            AuthorityInfo authority = mAuthorities.get(authorityId);
-            if (authority != null) {
-                Bundle extras;
-                if (flatExtras != null) {
-                    extras = unflattenBundle(flatExtras);
-                } else {
-                    // if we are unable to parse the extras for whatever reason convert this
-                    // to a regular sync by creating an empty extras
-                    extras = new Bundle();
+    private void writePendingOperationsLocked() {
+        final int N = mPendingOperations.size();
+        FileOutputStream fos = null;
+        try {
+            if (N == 0) {
+                if (Log.isLoggable(TAG_FILE, Log.VERBOSE)) {
+                    Log.v(TAG_FILE, "Truncating " + mPendingFile.getBaseFile());
                 }
-                PendingOperation op = new PendingOperation(
-                        authority.account, authority.userId, reason, syncSource,
-                        authority.authority, extras, expedited);
-                op.authorityId = authorityId;
-                op.flatExtras = flatExtras;
-                if (DEBUG_FILE) Log.v(TAG, "Adding pending op: account=" + op.account
-                        + " auth=" + op.authority
-                        + " src=" + op.syncSource
-                        + " reason=" + op.reason
-                        + " expedited=" + op.expedited
-                        + " extras=" + op.extras);
-                mPendingOperations.add(op);
+                mPendingFile.truncate();
+                return;
             }
+            if (Log.isLoggable(TAG_FILE, Log.VERBOSE)) {
+                Log.v(TAG_FILE, "Writing new " + mPendingFile.getBaseFile());
+            }
+            fos = mPendingFile.startWrite();
+            XmlSerializer out = new FastXmlSerializer();
+            out.setOutput(fos, "utf-8");
+
+            for (int i = 0; i < N; i++) {
+                PendingOperation pop = mPendingOperations.get(i);
+                writePendingOperationLocked(pop, out);
+            }
+            out.endDocument();
+            mPendingFile.finishWrite(fos);
+        } catch (java.io.IOException e1) {
+            Log.w(TAG, "Error writing pending operations", e1);
+            if (fos != null) {
+                mPendingFile.failWrite(fos);
+            }
+        }
+    }
+
+    /** Write all currently pending ops to the pending ops file. */
+     private void writePendingOperationLocked(PendingOperation pop, XmlSerializer out)
+             throws IOException {
+         // Pending operation.
+         out.startTag(null, "op");
+
+         out.attribute(null, XML_ATTR_VERSION, Integer.toString(PENDING_OPERATION_VERSION));
+         out.attribute(null, XML_ATTR_AUTHORITYID, Integer.toString(pop.authorityId));
+         out.attribute(null, XML_ATTR_SOURCE, Integer.toString(pop.syncSource));
+         out.attribute(null, XML_ATTR_EXPEDITED, Boolean.toString(pop.expedited));
+         out.attribute(null, XML_ATTR_REASON, Integer.toString(pop.reason));
+         extrasToXml(out, pop.extras);
+
+         out.endTag(null, "op");
+     }
+
+    /**
+     * Append the given operation to the pending ops file; if unable to,
+     * write all pending ops.
+     */
+    private void appendPendingOperationLocked(PendingOperation op) {
+        if (Log.isLoggable(TAG_FILE, Log.VERBOSE)) {
+            Log.v(TAG, "Appending to " + mPendingFile.getBaseFile());
+        }
+        FileOutputStream fos = null;
+        try {
+            fos = mPendingFile.openAppend();
+        } catch (java.io.IOException e) {
+            if (Log.isLoggable(TAG_FILE, Log.VERBOSE)) {
+                Log.v(TAG, "Failed append; writing full file");
+            }
+            writePendingOperationsLocked();
+            return;
+        }
+
+        try {
+            XmlSerializer out = new FastXmlSerializer();
+            out.setOutput(fos, "utf-8");
+            writePendingOperationLocked(op, out);
+            out.endDocument();
+            mPendingFile.finishWrite(fos);
+        } catch (java.io.IOException e1) {
+            Log.w(TAG, "Error writing appending operation", e1);
+            mPendingFile.failWrite(fos);
+        } finally {
+            try {
+                fos.close();
+            } catch (IOException e) {}
         }
     }
 
@@ -2399,54 +2469,6 @@
         return bundle;
     }
 
-    private static final String XML_ATTR_AUTHORITYID = "authority_id";
-    private static final String XML_ATTR_SOURCE = "source";
-    private static final String XML_ATTR_EXPEDITED = "expedited";
-    private static final String XML_ATTR_REASON = "reason";
-    /**
-     * Write all currently pending ops to the pending ops file. TODO: Change this from xml
-     * so that we can append to this file as before.
-     */
-    private void writePendingOperationsLocked() {
-        final int N = mPendingOperations.size();
-        FileOutputStream fos = null;
-        try {
-            if (N == 0) {
-                if (DEBUG_FILE) Log.v(TAG, "Truncating " + mPendingFile.getBaseFile());
-                mPendingFile.truncate();
-                return;
-            }
-            if (DEBUG_FILE) Log.v(TAG, "Writing new " + mPendingFile.getBaseFile());
-            fos = mPendingFile.startWrite();
-            XmlSerializer out = new FastXmlSerializer();
-            out.setOutput(fos, "utf-8");
-            out.startDocument(null, true);
-            out.setFeature("http://xmlpull.org/v1/doc/features.html#indent-output", true);
-
-            out.startTag(null, "pending");
-            out.attribute(null, "version", Integer.toString(PENDING_OPERATION_VERSION));
-
-            for (int i = 0; i < N; i++) {
-                PendingOperation pop = mPendingOperations.get(i);
-                out.startTag(null, "op");
-                out.attribute(null, XML_ATTR_AUTHORITYID, Integer.toString(pop.authorityId));
-                out.attribute(null, XML_ATTR_SOURCE, Integer.toString(pop.syncSource));
-                out.attribute(null, XML_ATTR_EXPEDITED, Boolean.toString(pop.expedited));
-                out.attribute(null, XML_ATTR_REASON, Integer.toString(pop.reason));
-                extrasToXml(out, pop.extras);
-                out.endTag(null, "op");
-             }
-             out.endTag(null, "pending");
-             out.endDocument();
-             mPendingFile.finishWrite(fos);
-        } catch (java.io.IOException e1) {
-            Log.w(TAG, "Error writing pending operations", e1);
-            if (fos != null) {
-                mPendingFile.failWrite(fos);
-            }
-        }
-    }
-
     private void extrasToXml(XmlSerializer out, Bundle extras) throws java.io.IOException {
         for (String key : extras.keySet()) {
             out.startTag(null, "extra");
@@ -2479,35 +2501,6 @@
         }
     }
 
-//    /**
-//     * Update the pending ops file, if e
-//     */
-//    private void appendPendingOperationLocked(PendingOperation op) {
-//        if (DEBUG_FILE) Log.v(TAG, "Appending to " + mPendingFile.getBaseFile());
-//        FileOutputStream fos = null;
-//        try {
-//            fos = mPendingFile.openAppend();
-//        } catch (java.io.IOException e) {
-//            if (DEBUG_FILE) Log.v(TAG, "Failed append; writing full file");
-//            writePendingOperationsLocked();
-//            return;
-//        }
-//
-//        try {
-//            Parcel out = Parcel.obtain();
-//            writePendingOperationLocked(op, out);
-//            fos.write(out.marshall());
-//            out.recycle();
-//        } catch (java.io.IOException e1) {
-//            Log.w(TAG, "Error writing pending operations", e1);
-//        } finally {
-//            try {
-//                fos.close();
-//            } catch (java.io.IOException e2) {
-//            }
-//        }
-//    }
-
     private void requestSync(Account account, int userId, int reason, String authority,
             Bundle extras) {
         // If this is happening in the system process, then call the syncrequest listener
@@ -2568,7 +2561,9 @@
      * Write all sync statistics to the sync status file.
      */
     private void writeStatisticsLocked() {
-        if (DEBUG_FILE) Log.v(TAG, "Writing new " + mStatisticsFile.getBaseFile());
+        if (Log.isLoggable(TAG_FILE, Log.VERBOSE)) {
+            Log.v(TAG, "Writing new " + mStatisticsFile.getBaseFile());
+        }
 
         // The file is being written, so we don't need to have a scheduled
         // write until the next change.
@@ -2611,7 +2606,7 @@
         sb.append("Pending Ops: ").append(mPendingOperations.size()).append(" operation(s)\n");
         for (PendingOperation pop : mPendingOperations) {
             sb.append("(" + pop.account)
-                .append(", " + pop.userId)
+                .append(", u" + pop.userId)
                 .append(", " + pop.authority)
                 .append(", " + pop.extras)
                 .append(")\n");
diff --git a/services/java/com/android/server/wifi/WifiService.java b/services/java/com/android/server/wifi/WifiService.java
index db030f1..c215f40 100644
--- a/services/java/com/android/server/wifi/WifiService.java
+++ b/services/java/com/android/server/wifi/WifiService.java
@@ -345,6 +345,12 @@
         return mBatchedScanSupported;
     }
 
+    public void pollBatchedScan() {
+        enforceChangePermission();
+        if (mBatchedScanSupported == false) return;
+        mWifiStateMachine.requestBatchedScanPoll();
+    }
+
     /**
      * see {@link android.net.wifi.WifiManager#requestBatchedScan()}
      */
diff --git a/services/tests/servicestests/src/com/android/server/content/SyncStorageEngineTest.java b/services/tests/servicestests/src/com/android/server/content/SyncStorageEngineTest.java
index dff6661..e44652f 100644
--- a/services/tests/servicestests/src/com/android/server/content/SyncStorageEngineTest.java
+++ b/services/tests/servicestests/src/com/android/server/content/SyncStorageEngineTest.java
@@ -67,7 +67,7 @@
 
     /**
      * Test that we handle the case of a history row being old enough to purge before the
-     * correcponding sync is finished. This can happen if the clock changes while we are syncing.
+     * corresponding sync is finished. This can happen if the clock changes while we are syncing.
      *
      */
     // TODO: this test causes AidlTest to fail. Omit for now
@@ -104,6 +104,17 @@
         engine.clearAndReadState();
 
         assert(engine.getPendingOperationCount() == 1);
+        List<SyncStorageEngine.PendingOperation> pops = engine.getPendingOperations();
+        SyncStorageEngine.PendingOperation popRetrieved = pops.get(0);
+        assertEquals(pop.account, popRetrieved.account);
+        assertEquals(pop.reason, popRetrieved.reason);
+        assertEquals(pop.userId, popRetrieved.userId);
+        assertEquals(pop.syncSource, popRetrieved.syncSource);
+        assertEquals(pop.authority, popRetrieved.authority);
+        assertEquals(pop.expedited, popRetrieved.expedited);
+        assertEquals(pop.serviceName, popRetrieved.serviceName);
+        assert(android.content.PeriodicSync.syncExtrasEquals(pop.extras, popRetrieved.extras));
+
     }
 
     /**
diff --git a/wifi/java/android/net/wifi/BatchedScanSettings.java b/wifi/java/android/net/wifi/BatchedScanSettings.java
index 82945d6..44a2ab4 100644
--- a/wifi/java/android/net/wifi/BatchedScanSettings.java
+++ b/wifi/java/android/net/wifi/BatchedScanSettings.java
@@ -51,6 +51,7 @@
     public final static int MAX_AP_FOR_DISTANCE = MAX_AP_PER_SCAN;
     public final static int DEFAULT_AP_FOR_DISTANCE = 0;
 
+    public final static int MAX_WIFI_CHANNEL = 196;
 
     /** The expected number of scans per batch.  Note that the firmware may drop scans
      *  leading to fewer scans during the normal batch scan duration.  This value need not
@@ -113,7 +114,7 @@
         for (String channel : channelSet) {
             try {
                 int i = Integer.parseInt(channel);
-                if (i > 0 && i < 197) continue;
+                if (i > 0 && i <= MAX_WIFI_CHANNEL) continue;
             } catch (NumberFormatException e) {}
             if (channel.equals("A") || channel.equals("B")) continue;
             return false;
diff --git a/wifi/java/android/net/wifi/IWifiManager.aidl b/wifi/java/android/net/wifi/IWifiManager.aidl
index c8cf323..4f68ca0 100644
--- a/wifi/java/android/net/wifi/IWifiManager.aidl
+++ b/wifi/java/android/net/wifi/IWifiManager.aidl
@@ -124,5 +124,7 @@
     List<BatchedScanResult> getBatchedScanResults(String callingPackage);
 
     boolean isBatchedScanSupported();
+
+    void pollBatchedScan();
 }
 
diff --git a/wifi/java/android/net/wifi/WifiManager.java b/wifi/java/android/net/wifi/WifiManager.java
index 01ca378..a15b664 100644
--- a/wifi/java/android/net/wifi/WifiManager.java
+++ b/wifi/java/android/net/wifi/WifiManager.java
@@ -840,6 +840,32 @@
     }
 
     /**
+     * Force a re-reading of batched scan results.  This will attempt
+     * to read more information from the chip, but will do so at the expense
+     * of previous data.  Rate limited to the current scan frequency.
+     *
+     * pollBatchedScan will always wait 1 period from the start of the batch
+     * before trying to read from the chip, so if your #scans/batch == 1 this will
+     * have no effect.
+     *
+     * If you had already waited 1 period before calling, this should have
+     * immediate (though async) effect.
+     *
+     * If you call before that 1 period is up this will set up a timer and fetch
+     * results when the 1 period is up.
+     *
+     * Servicing a pollBatchedScan request (immediate or after timed delay) starts a
+     * new batch, so if you were doing 10 scans/batch and called in the 4th scan, you
+     * would get data in the 4th and then again 10 scans later.
+     * @hide
+     */
+    public void pollBatchedScan() {
+        try {
+            mService.pollBatchedScan();
+        } catch (RemoteException e) { }
+    }
+
+    /**
      * Return dynamic information about the current Wi-Fi connection, if any is active.
      * @return the Wi-Fi information, contained in {@link WifiInfo}.
      */
diff --git a/wifi/java/android/net/wifi/WifiMonitor.java b/wifi/java/android/net/wifi/WifiMonitor.java
index f6d5c98..a80238b 100644
--- a/wifi/java/android/net/wifi/WifiMonitor.java
+++ b/wifi/java/android/net/wifi/WifiMonitor.java
@@ -506,13 +506,14 @@
                     Log.d(TAG, "Event [" + eventStr + "]");
                 }
 
+                String iface = "p2p0";
                 WifiMonitor m = null;
                 mStateMachine = null;
 
                 if (eventStr.startsWith("IFNAME=")) {
                     int space = eventStr.indexOf(' ');
                     if (space != -1) {
-                        String iface = eventStr.substring(7,space);
+                        iface = eventStr.substring(7,space);
                         m = mWifiMonitorSingleton.getMonitor(iface);
                         if (m == null && iface.startsWith("p2p-")) {
                             // p2p interfaces are created dynamically, but we have
@@ -520,20 +521,20 @@
                             // for it explicitly, and send messages there ..
                             m = mWifiMonitorSingleton.getMonitor("p2p0");
                         }
-                        if (m != null) {
-                            if (m.mMonitoring) {
-                                mStateMachine = m.mWifiStateMachine;
-                                eventStr = eventStr.substring(space + 1);
-                            }
-                            else {
-                                if (DBG) Log.d(TAG, "Dropping event because monitor (" + iface +
-                                        ") is stopped");
-                                continue;
-                            }
-                        }
-                        else {
-                            eventStr = eventStr.substring(space + 1);
-                        }
+                        eventStr = eventStr.substring(space + 1);
+                    }
+                } else {
+                    // events without prefix belong to p2p0 monitor
+                    m = mWifiMonitorSingleton.getMonitor("p2p0");
+                }
+
+                if (m != null) {
+                    if (m.mMonitoring) {
+                        mStateMachine = m.mWifiStateMachine;
+                    } else {
+                        if (DBG) Log.d(TAG, "Dropping event because monitor (" + iface +
+                                            ") is stopped");
+                        continue;
                     }
                 }
 
diff --git a/wifi/java/android/net/wifi/WifiNative.java b/wifi/java/android/net/wifi/WifiNative.java
index 0359076..c3ed03c 100644
--- a/wifi/java/android/net/wifi/WifiNative.java
+++ b/wifi/java/android/net/wifi/WifiNative.java
@@ -82,8 +82,13 @@
 
     public WifiNative(String interfaceName) {
         mInterfaceName = interfaceName;
-        mInterfacePrefix = "IFNAME=" + interfaceName + " ";
         mTAG = "WifiNative-" + interfaceName;
+        if (!interfaceName.equals("p2p0")) {
+            mInterfacePrefix = "IFNAME=" + interfaceName + " ";
+        } else {
+            // commands for p2p0 interface don't need prefix
+            mInterfacePrefix = "";
+        }
     }
 
     public boolean connectToSupplicant() {
@@ -221,8 +226,9 @@
 
     /**
      * Format of command
-     * DRIVER WLS_BATCHING SET SCAN_FRQ=x BESTN=y CHANNEL=<z, w, t> RTT=s
+     * DRIVER WLS_BATCHING SET SCAN_FRQ=x MSCAN=r BESTN=y CHANNEL=<z, w, t> RTT=s
      * where x is an ascii representation of an integer number of seconds between scans
+     *       r is an ascii representation of an integer number of scans per batch
      *       y is an ascii representation of an integer number of the max AP to remember per scan
      *       z, w, t represent a 1..n size list of channel numbers and/or 'A', 'B' values
      *           indicating entire ranges of channels
@@ -235,8 +241,9 @@
     public String setBatchedScanSettings(BatchedScanSettings settings) {
         if (settings == null) return doStringCommand("DRIVER WLS_BATCHING STOP");
         String cmd = "DRIVER WLS_BATCHING SET SCAN_FRQ=" + settings.scanIntervalSec;
+        cmd += " MSCAN=" + settings.maxScansPerBatch;
         if (settings.maxApPerScan != BatchedScanSettings.UNSPECIFIED) {
-            cmd += " BESTN " + settings.maxApPerScan;
+            cmd += " BESTN=" + settings.maxApPerScan;
         }
         if (settings.channelSet != null && !settings.channelSet.isEmpty()) {
             cmd += " CHANNEL=<";
diff --git a/wifi/java/android/net/wifi/WifiStateMachine.java b/wifi/java/android/net/wifi/WifiStateMachine.java
index 764c00a..8b7b8ae 100644
--- a/wifi/java/android/net/wifi/WifiStateMachine.java
+++ b/wifi/java/android/net/wifi/WifiStateMachine.java
@@ -127,6 +127,8 @@
     private final List<BatchedScanResult> mBatchedScanResults =
             new ArrayList<BatchedScanResult>();
     private int mBatchedScanOwnerUid = UNKNOWN_SCAN_SOURCE;
+    private int mExpectedBatchedScans = 0;
+    private long mBatchedScanMinPollTime = 0;
 
     /* Chipset supports background scan */
     private final boolean mBackgroundScanSupported;
@@ -366,8 +368,9 @@
      * arg1 = responsible UID
      * obj = the new settings
      */
-    public static final int CMD_SET_BATCH_SCAN            = BASE + 135;
+    public static final int CMD_SET_BATCHED_SCAN          = BASE + 135;
     public static final int CMD_START_NEXT_BATCHED_SCAN   = BASE + 136;
+    public static final int CMD_POLL_BATCHED_SCAN         = BASE + 137;
 
     public static final int CONNECT_MODE                   = 1;
     public static final int SCAN_ONLY_MODE                 = 2;
@@ -766,7 +769,7 @@
      * start or stop batched scanning using the given settings
      */
     public void setBatchedScanSettings(BatchedScanSettings settings, int callingUid) {
-        sendMessage(CMD_SET_BATCH_SCAN, callingUid, 0, settings);
+        sendMessage(CMD_SET_BATCHED_SCAN, callingUid, 0, settings);
     }
 
     public List<BatchedScanResult> syncGetBatchedScanResultsList() {
@@ -780,6 +783,10 @@
         }
     }
 
+    public void requestBatchedScanPoll() {
+        sendMessage(CMD_POLL_BATCHED_SCAN);
+    }
+
     private void startBatchedScan() {
         // first grab any existing data
         retrieveBatchedScanData();
@@ -789,8 +796,8 @@
         String scansExpected = mWifiNative.setBatchedScanSettings(mBatchedScanSettings);
 
         try {
-            int expected = Integer.parseInt(scansExpected);
-            setNextBatchedAlarm(expected);
+            mExpectedBatchedScans = Integer.parseInt(scansExpected);
+            setNextBatchedAlarm(mExpectedBatchedScans);
         } catch (NumberFormatException e) {
             loge("Exception parsing WifiNative.setBatchedScanSettings response " + e);
         }
@@ -803,9 +810,27 @@
 
     private void startNextBatchedScan() {
         // first grab any existing data
-        int nextCount = retrieveBatchedScanData();
+        retrieveBatchedScanData();
 
-        setNextBatchedAlarm(nextCount);
+        setNextBatchedAlarm(mExpectedBatchedScans);
+    }
+
+    private void handleBatchedScanPollRequest() {
+        // if there is no appropriate PollTime that's because we either aren't
+        // batching or we've already set a time for a poll request
+        if (mBatchedScanMinPollTime == 0) return;
+        if (mBatchedScanSettings == null) return;
+
+        long now = System.currentTimeMillis();
+
+        if (now > mBatchedScanMinPollTime) {
+            // do the poll and reset our timers
+            startNextBatchedScan();
+        } else {
+            mAlarmManager.set(AlarmManager.RTC_WAKEUP, mBatchedScanMinPollTime,
+                    mBatchedScanIntervalIntent);
+            mBatchedScanMinPollTime = 0;
+        }
     }
 
     // return true if new/different
@@ -832,6 +857,9 @@
 
         if (mBatchedScanSettings == null || scansExpected < 1) return;
 
+        mBatchedScanMinPollTime = System.currentTimeMillis() +
+                mBatchedScanSettings.scanIntervalSec * 1000;
+
         if (mBatchedScanSettings.maxScansPerBatch < scansExpected) {
             scansExpected = mBatchedScanSettings.maxScansPerBatch;
         }
@@ -876,22 +904,18 @@
      *   etc
      *   "----"
      */
-    private int retrieveBatchedScanData() {
+    private void retrieveBatchedScanData() {
         String rawData = mWifiNative.getBatchedScanResults();
+        mBatchedScanMinPollTime = 0;
         if (rawData == null) {
             loge("Unexpected null BatchedScanResults");
-            return 0;
+            return;
         }
 
-        int nextCount = 0;
         int scanCount = 0;
-        final String END_OF_SCAN = "====";
-        final String END_OF_BATCH = "%%%%";
         final String END_OF_BATCHES = "----";
         final String SCANCOUNT = "scancount=";
-        final String NEXTCOUNT = "nextcount=";
         final String TRUNCATED = "trunc";
-        final String APCOUNT = "apcount=";
         final String AGE = "age=";
         final String DIST = "dist=";
         final String DISTSD = "distsd=";
@@ -905,16 +929,7 @@
         }
         if (scanCount == 0) {
             loge("scanCount not found");
-            return 0;
-        }
-        if (splitData[n].startsWith(NEXTCOUNT)) {
-            try {
-                nextCount = Integer.parseInt(splitData[n++].substring(NEXTCOUNT.length()));
-            } catch (NumberFormatException e) {}
-        }
-        if (nextCount == 0) {
-            loge("nextCount not found");
-            return 0;
+            return;
         }
 
         final Intent intent = new Intent(WifiManager.BATCHED_SCAN_RESULTS_AVAILABLE_ACTION);
@@ -942,9 +957,9 @@
                         if (mBatchedScanResults.size() > 0) {
                             mContext.sendStickyBroadcastAsUser(intent, UserHandle.ALL);
                         }
-                        return nextCount;
+                        return;
                     }
-                    if ((splitData[n].equals(END_OF_SCAN)) || splitData[n].equals(END_OF_BATCH)) {
+                    if ((splitData[n].equals(END_STR)) || splitData[n].equals(DELIMITER_STR)) {
                         if (bssid != null) {
                             batchedScanResult.scanResults.add(new ScanResult(
                                     wifiSsid, bssid, "", level, freq, tsf, dist, distSd));
@@ -955,7 +970,7 @@
                             tsf = 0;
                             dist = distSd = ScanResult.UNSPECIFIED;
                         }
-                        if (splitData[n].equals(END_OF_BATCH)) {
+                        if (splitData[n].equals(END_STR)) {
                             if (batchedScanResult.scanResults.size() != 0) {
                                 mBatchedScanResults.add(batchedScanResult);
                                 batchedScanResult = new BatchedScanResult();
@@ -1010,7 +1025,7 @@
                 rawData = mWifiNative.getBatchedScanResults();
                 if (rawData == null) {
                     loge("Unexpected null BatchedScanResults");
-                    return nextCount;
+                    return;
                 }
                 splitData = rawData.split("\n");
                 if (splitData.length == 0 || splitData[0].equals("ok")) {
@@ -1018,7 +1033,7 @@
                     if (mBatchedScanResults.size() > 0) {
                         mContext.sendStickyBroadcastAsUser(intent, UserHandle.ALL);
                     }
-                    return nextCount;
+                    return;
                 }
                 n = 0;
             }
@@ -2266,9 +2281,11 @@
                         sendMessageAtFrontOfQueue(CMD_SET_COUNTRY_CODE, countryCode);
                     }
                     break;
-                case CMD_SET_BATCH_SCAN:
+                case CMD_SET_BATCHED_SCAN:
                     recordBatchedScanSettings((BatchedScanSettings)message.obj);
                     break;
+                case CMD_POLL_BATCHED_SCAN:
+                    handleBatchedScanPollRequest();
                 case CMD_START_NEXT_BATCHED_SCAN:
                     startNextBatchedScan();
                     break;
@@ -2808,7 +2825,7 @@
                     noteScanStart(message.arg1, (WorkSource) message.obj);
                     startScanNative(WifiNative.SCAN_WITH_CONNECTION_SETUP);
                     break;
-                case CMD_SET_BATCH_SCAN:
+                case CMD_SET_BATCHED_SCAN:
                     recordBatchedScanSettings((BatchedScanSettings)message.obj);
                     startBatchedScan();
                     break;