Merge "Serializing display lists"
diff --git a/api/current.txt b/api/current.txt
index 4157c6f..e9c5727 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -21,6 +21,7 @@
     field public static final deprecated java.lang.String BIND_CARRIER_MESSAGING_SERVICE = "android.permission.BIND_CARRIER_MESSAGING_SERVICE";
     field public static final java.lang.String BIND_CARRIER_SERVICES = "android.permission.BIND_CARRIER_SERVICES";
     field public static final java.lang.String BIND_CHOOSER_TARGET_SERVICE = "android.permission.BIND_CHOOSER_TARGET_SERVICE";
+    field public static final java.lang.String BIND_CONDITION_PROVIDER_SERVICE = "android.permission.BIND_CONDITION_PROVIDER_SERVICE";
     field public static final java.lang.String BIND_DEVICE_ADMIN = "android.permission.BIND_DEVICE_ADMIN";
     field public static final java.lang.String BIND_DREAM_SERVICE = "android.permission.BIND_DREAM_SERVICE";
     field public static final java.lang.String BIND_INCALL_SERVICE = "android.permission.BIND_INCALL_SERVICE";
@@ -18114,7 +18115,7 @@
     method public boolean importFile(int, java.lang.String);
     method public boolean importFile(int, android.os.ParcelFileDescriptor);
     method public boolean open(android.hardware.usb.UsbDeviceConnection);
-    method public boolean sendObject(int, android.os.ParcelFileDescriptor);
+    method public boolean sendObject(int, int, android.os.ParcelFileDescriptor);
     method public android.mtp.MtpObjectInfo sendObjectInfo(android.mtp.MtpObjectInfo);
   }
 
@@ -28743,6 +28744,49 @@
 
 package android.service.notification {
 
+  public class Condition implements android.os.Parcelable {
+    ctor public Condition(android.net.Uri, java.lang.String, java.lang.String, java.lang.String, int, int, int);
+    method public android.service.notification.Condition copy();
+    method public int describeContents();
+    method public static boolean isValidId(android.net.Uri, java.lang.String);
+    method public static android.net.Uri.Builder newId(android.content.Context);
+    method public static java.lang.String relevanceToString(int);
+    method public static java.lang.String stateToString(int);
+    method public void writeToParcel(android.os.Parcel, int);
+    field public static final android.os.Parcelable.Creator<android.service.notification.Condition> CREATOR;
+    field public static final int FLAG_RELEVANT_ALWAYS = 2; // 0x2
+    field public static final int FLAG_RELEVANT_NOW = 1; // 0x1
+    field public static final java.lang.String SCHEME = "condition";
+    field public static final int STATE_ERROR = 3; // 0x3
+    field public static final int STATE_FALSE = 0; // 0x0
+    field public static final int STATE_TRUE = 1; // 0x1
+    field public static final int STATE_UNKNOWN = 2; // 0x2
+    field public final int flags;
+    field public final int icon;
+    field public final android.net.Uri id;
+    field public final java.lang.String line1;
+    field public final java.lang.String line2;
+    field public final int state;
+    field public final java.lang.String summary;
+  }
+
+  public abstract class ConditionProviderService extends android.app.Service {
+    ctor public ConditionProviderService();
+    method public final void notifyCondition(android.service.notification.Condition);
+    method public final void notifyConditions(android.service.notification.Condition...);
+    method public android.os.IBinder onBind(android.content.Intent);
+    method public abstract void onConnected();
+    method public abstract void onRequestConditions(int);
+    method public abstract void onSubscribe(android.net.Uri);
+    method public abstract void onUnsubscribe(android.net.Uri);
+    field public static final java.lang.String EXTRA_CONDITION_ID = "android.content.automatic.conditionId";
+    field public static final java.lang.String EXTRA_RULE_NAME = "android.content.automatic.ruleName";
+    field public static final java.lang.String META_DATA_CONFIGURATION_ACTIVITY = "android.service.zen.automatic.configurationActivity";
+    field public static final java.lang.String META_DATA_DEFAULT_CONDITION_ID = "android.service.zen.automatic.defaultConditionId";
+    field public static final java.lang.String META_DATA_RULE_TYPE = "android.service.zen.automatic.ruleType";
+    field public static final java.lang.String SERVICE_INTERFACE = "android.service.notification.ConditionProviderService";
+  }
+
   public abstract class NotificationListenerService extends android.app.Service {
     ctor public NotificationListenerService();
     method public final void cancelAllNotifications();
@@ -30635,6 +30679,7 @@
     field public static final java.lang.String KEY_AUTO_RETRY_ENABLED_BOOL = "auto_retry_enabled_bool";
     field public static final java.lang.String KEY_CARRIER_ALLOW_TURNOFF_IMS_BOOL = "carrier_allow_turnoff_ims_bool";
     field public static final java.lang.String KEY_CARRIER_SETTINGS_ENABLE_BOOL = "carrier_settings_enable_bool";
+    field public static final java.lang.String KEY_CARRIER_USE_IMS_FIRST_FOR_EMERGENCY_BOOL = "carrier_use_ims_first_for_emergency_bool";
     field public static final java.lang.String KEY_CARRIER_VOLTE_AVAILABLE_BOOL = "carrier_volte_available_bool";
     field public static final java.lang.String KEY_CARRIER_VOLTE_PROVISIONING_REQUIRED_BOOL = "carrier_volte_provisioning_required_bool";
     field public static final java.lang.String KEY_CARRIER_VOLTE_TTY_SUPPORTED_BOOL = "carrier_volte_tty_supported_bool";
diff --git a/api/system-current.txt b/api/system-current.txt
index 33ce543..e234970 100644
--- a/api/system-current.txt
+++ b/api/system-current.txt
@@ -19627,7 +19627,7 @@
     method public boolean importFile(int, java.lang.String);
     method public boolean importFile(int, android.os.ParcelFileDescriptor);
     method public boolean open(android.hardware.usb.UsbDeviceConnection);
-    method public boolean sendObject(int, android.os.ParcelFileDescriptor);
+    method public boolean sendObject(int, int, android.os.ParcelFileDescriptor);
     method public android.mtp.MtpObjectInfo sendObjectInfo(android.mtp.MtpObjectInfo);
   }
 
@@ -30868,6 +30868,11 @@
     method public abstract void onRequestConditions(int);
     method public abstract void onSubscribe(android.net.Uri);
     method public abstract void onUnsubscribe(android.net.Uri);
+    field public static final java.lang.String EXTRA_CONDITION_ID = "android.content.automatic.conditionId";
+    field public static final java.lang.String EXTRA_RULE_NAME = "android.content.automatic.ruleName";
+    field public static final java.lang.String META_DATA_CONFIGURATION_ACTIVITY = "android.service.zen.automatic.configurationActivity";
+    field public static final java.lang.String META_DATA_DEFAULT_CONDITION_ID = "android.service.zen.automatic.defaultConditionId";
+    field public static final java.lang.String META_DATA_RULE_TYPE = "android.service.zen.automatic.ruleType";
     field public static final java.lang.String SERVICE_INTERFACE = "android.service.notification.ConditionProviderService";
   }
 
@@ -32905,6 +32910,7 @@
     field public static final java.lang.String KEY_AUTO_RETRY_ENABLED_BOOL = "auto_retry_enabled_bool";
     field public static final java.lang.String KEY_CARRIER_ALLOW_TURNOFF_IMS_BOOL = "carrier_allow_turnoff_ims_bool";
     field public static final java.lang.String KEY_CARRIER_SETTINGS_ENABLE_BOOL = "carrier_settings_enable_bool";
+    field public static final java.lang.String KEY_CARRIER_USE_IMS_FIRST_FOR_EMERGENCY_BOOL = "carrier_use_ims_first_for_emergency_bool";
     field public static final java.lang.String KEY_CARRIER_VOLTE_AVAILABLE_BOOL = "carrier_volte_available_bool";
     field public static final java.lang.String KEY_CARRIER_VOLTE_PROVISIONING_REQUIRED_BOOL = "carrier_volte_provisioning_required_bool";
     field public static final java.lang.String KEY_CARRIER_VOLTE_TTY_SUPPORTED_BOOL = "carrier_volte_tty_supported_bool";
diff --git a/cmds/dpm/src/com/android/commands/dpm/Dpm.java b/cmds/dpm/src/com/android/commands/dpm/Dpm.java
index f9b3419..471fa3b 100644
--- a/cmds/dpm/src/com/android/commands/dpm/Dpm.java
+++ b/cmds/dpm/src/com/android/commands/dpm/Dpm.java
@@ -107,7 +107,7 @@
 
     private void runSetDeviceOwner() throws RemoteException {
         ComponentName component = parseComponentName(nextArgRequired());
-        mDevicePolicyManager.setActiveAdmin(component, true /*refreshing*/, UserHandle.USER_OWNER);
+        mDevicePolicyManager.setActiveAdmin(component, true /*refreshing*/, UserHandle.USER_SYSTEM);
 
         String packageName = component.getPackageName();
         try {
@@ -117,7 +117,7 @@
             }
         } catch (Exception e) {
             // Need to remove the admin that we just added.
-            mDevicePolicyManager.removeActiveAdmin(component, UserHandle.USER_OWNER);
+            mDevicePolicyManager.removeActiveAdmin(component, UserHandle.USER_SYSTEM);
             throw e;
         }
         System.out.println("Success: Device owner set to package " + packageName);
diff --git a/cmds/pm/src/com/android/commands/pm/Pm.java b/cmds/pm/src/com/android/commands/pm/Pm.java
index 68c11ad..3f0a444 100644
--- a/cmds/pm/src/com/android/commands/pm/Pm.java
+++ b/cmds/pm/src/com/android/commands/pm/Pm.java
@@ -988,6 +988,7 @@
             case INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_ASK: return "ask";
             case INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_ALWAYS: return "always";
             case INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_NEVER: return "never";
+            case INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_ALWAYS_ASK : return "always ask";
         }
         return "Unknown link state: " + state;
     }
diff --git a/core/java/android/animation/AnimationHandler.java b/core/java/android/animation/AnimationHandler.java
new file mode 100644
index 0000000..7778c35
--- /dev/null
+++ b/core/java/android/animation/AnimationHandler.java
@@ -0,0 +1,316 @@
+/*
+ * Copyright (C) 2015 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.animation;
+
+import android.os.SystemClock;
+import android.util.ArrayMap;
+import android.view.Choreographer;
+
+import java.util.ArrayList;
+
+/**
+ * This custom, static handler handles the timing pulse that is shared by all active
+ * ValueAnimators. This approach ensures that the setting of animation values will happen on the
+ * same thread that animations start on, and that all animations will share the same times for
+ * calculating their values, which makes synchronizing animations possible.
+ *
+ * The handler uses the Choreographer by default for doing periodic callbacks. A custom
+ * AnimationFrameCallbackProvider can be set on the handler to provide timing pulse that
+ * may be independent of UI frame update. This could be useful in testing.
+ *
+ * @hide
+ */
+public class AnimationHandler {
+    /**
+     * Internal per-thread collections used to avoid set collisions as animations start and end
+     * while being processed.
+     * @hide
+     */
+    private final ArrayMap<AnimationFrameCallback, Long> mDelayedCallbackStartTime =
+            new ArrayMap<>();
+    private final ArrayList<AnimationFrameCallback> mAnimationCallbacks =
+            new ArrayList<>();
+    private final ArrayList<AnimationFrameCallback> mCommitCallbacks =
+            new ArrayList<>();
+    private AnimationFrameCallbackProvider mProvider;
+
+    private final Choreographer.FrameCallback mFrameCallback = new Choreographer.FrameCallback() {
+        @Override
+        public void doFrame(long frameTimeNanos) {
+            doAnimationFrame(getProvider().getFrameTime());
+            if (mAnimationCallbacks.size() > 0) {
+                getProvider().postFrameCallback(this);
+            }
+        }
+    };
+
+    public final static ThreadLocal<AnimationHandler> sAnimatorHandler = new ThreadLocal<>();
+    private boolean mListDirty = false;
+
+    public static AnimationHandler getInstance() {
+        if (sAnimatorHandler.get() == null) {
+            sAnimatorHandler.set(new AnimationHandler());
+        }
+        return sAnimatorHandler.get();
+    }
+
+    /**
+     * By default, the Choreographer is used to provide timing for frame callbacks. A custom
+     * provider can be used here to provide different timing pulse.
+     */
+    public void setProvider(AnimationFrameCallbackProvider provider) {
+        if (provider == null) {
+            mProvider = new MyFrameCallbackProvider();
+        } else {
+            mProvider = provider;
+        }
+    }
+
+    private AnimationFrameCallbackProvider getProvider() {
+        if (mProvider == null) {
+            mProvider = new MyFrameCallbackProvider();
+        }
+        return mProvider;
+    }
+
+    /**
+     * Register to get a callback on the next frame after the delay.
+     */
+    public void addAnimationFrameCallback(final AnimationFrameCallback callback, long delay) {
+        if (mAnimationCallbacks.size() == 0) {
+            getProvider().postFrameCallback(mFrameCallback);
+        }
+        if (!mAnimationCallbacks.contains(callback)) {
+            mAnimationCallbacks.add(callback);
+        }
+
+        if (delay > 0) {
+            mDelayedCallbackStartTime.put(callback, (SystemClock.uptimeMillis() + delay));
+        }
+    }
+
+    /**
+     * Register to get a one shot callback for frame commit timing. Frame commit timing is the
+     * time *after* traversals are done, as opposed to the animation frame timing, which is
+     * before any traversals. This timing can be used to adjust the start time of an animation
+     * when expensive traversals create big delta between the animation frame timing and the time
+     * that animation is first shown on screen.
+     *
+     * Note this should only be called when the animation has already registered to receive
+     * animation frame callbacks. This callback will be guaranteed to happen *after* the next
+     * animation frame callback.
+     */
+    public void addOneShotCommitCallback(final AnimationFrameCallback callback) {
+        if (!mCommitCallbacks.contains(callback)) {
+            mCommitCallbacks.add(callback);
+        }
+    }
+
+    /**
+     * Removes the given callback from the list, so it will no longer be called for frame related
+     * timing.
+     */
+    public void removeCallback(AnimationFrameCallback callback) {
+        mCommitCallbacks.remove(callback);
+        mDelayedCallbackStartTime.remove(callback);
+        int id = mAnimationCallbacks.indexOf(callback);
+        if (id >= 0) {
+            mAnimationCallbacks.set(id, null);
+            mListDirty = true;
+        }
+    }
+
+    private void doAnimationFrame(long frameTime) {
+        int size = mAnimationCallbacks.size();
+        long currentTime = SystemClock.uptimeMillis();
+        for (int i = 0; i < size; i++) {
+            final AnimationFrameCallback callback = mAnimationCallbacks.get(i);
+            if (callback == null) {
+                continue;
+            }
+            if (isCallbackDue(callback, currentTime)) {
+                callback.doAnimationFrame(frameTime);
+                if (mCommitCallbacks.contains(callback)) {
+                    getProvider().postCommitCallback(new Runnable() {
+                        @Override
+                        public void run() {
+                            commitAnimationFrame(callback, getProvider().getFrameTime());
+                        }
+                    });
+                }
+            }
+        }
+        cleanUpList();
+    }
+
+    private void commitAnimationFrame(AnimationFrameCallback callback, long frameTime) {
+        if (!mDelayedCallbackStartTime.containsKey(callback) &&
+                mCommitCallbacks.contains(callback)) {
+            callback.commitAnimationFrame(frameTime);
+            mCommitCallbacks.remove(callback);
+        }
+    }
+
+    /**
+     * Remove the callbacks from mDelayedCallbackStartTime once they have passed the initial delay
+     * so that they can start getting frame callbacks.
+     *
+     * @return true if they have passed the initial delay or have no delay, false otherwise.
+     */
+    private boolean isCallbackDue(AnimationFrameCallback callback, long currentTime) {
+        Long startTime = mDelayedCallbackStartTime.get(callback);
+        if (startTime == null) {
+            return true;
+        }
+        if (startTime < currentTime) {
+            mDelayedCallbackStartTime.remove(callback);
+            return true;
+        }
+        return false;
+    }
+
+    /**
+     * Return the number of callbacks that have registered for frame callbacks.
+     */
+    public static int getAnimationCount() {
+        AnimationHandler handler = sAnimatorHandler.get();
+        if (handler == null) {
+            return 0;
+        }
+        return handler.getCallbackSize();
+    }
+
+    public static void setFrameDelay(long delay) {
+        getInstance().getProvider().setFrameDelay(delay);
+    }
+
+    public static long getFrameDelay() {
+        return getInstance().getProvider().getFrameDelay();
+    }
+
+    void autoCancelBasedOn(ObjectAnimator objectAnimator) {
+        for (int i = mAnimationCallbacks.size() - 1; i >= 0; i--) {
+            AnimationFrameCallback cb = mAnimationCallbacks.get(i);
+            if (cb == null) {
+                continue;
+            }
+            if (objectAnimator.shouldAutoCancel(cb)) {
+                ((Animator) mAnimationCallbacks.get(i)).cancel();
+            }
+        }
+    }
+
+    private void cleanUpList() {
+        if (mListDirty) {
+            for (int i = mAnimationCallbacks.size() - 1; i >= 0; i--) {
+                if (mAnimationCallbacks.get(i) == null) {
+                    mAnimationCallbacks.remove(i);
+                }
+            }
+            mListDirty = false;
+        }
+    }
+
+    private int getCallbackSize() {
+        int count = 0;
+        int size = mAnimationCallbacks.size();
+        for (int i = size - 1; i >= 0; i--) {
+            if (mAnimationCallbacks.get(i) != null) {
+                count++;
+            }
+        }
+        return count;
+    }
+
+    /**
+     * Default provider of timing pulse that uses Choreographer for frame callbacks.
+     */
+    private class MyFrameCallbackProvider implements AnimationFrameCallbackProvider {
+
+        final Choreographer mChoreographer = Choreographer.getInstance();
+
+        @Override
+        public void postFrameCallback(Choreographer.FrameCallback callback) {
+            mChoreographer.postFrameCallback(callback);
+        }
+
+        @Override
+        public void postCommitCallback(Runnable runnable) {
+            mChoreographer.postCallback(Choreographer.CALLBACK_COMMIT, runnable, null);
+        }
+
+        @Override
+        public long getFrameTime() {
+            return mChoreographer.getFrameTime();
+        }
+
+        @Override
+        public long getFrameDelay() {
+            return Choreographer.getFrameDelay();
+        }
+
+        @Override
+        public void setFrameDelay(long delay) {
+            Choreographer.setFrameDelay(delay);
+        }
+    }
+
+    /**
+     * Callbacks that receives notifications for animation timing and frame commit timing.
+     */
+    interface AnimationFrameCallback {
+        /**
+         * Run animation based on the frame time.
+         * @param frameTime The frame start time, in the {@link SystemClock#uptimeMillis()} time
+         *                  base.
+         */
+        void doAnimationFrame(long frameTime);
+
+        /**
+         * This notifies the callback of frame commit time. Frame commit time is the time after
+         * traversals happen, as opposed to the normal animation frame time that is before
+         * traversals. This is used to compensate expensive traversals that happen as the
+         * animation starts. When traversals take a long time to complete, the rendering of the
+         * initial frame will be delayed (by a long time). But since the startTime of the
+         * animation is set before the traversal, by the time of next frame, a lot of time would
+         * have passed since startTime was set, the animation will consequently skip a few frames
+         * to respect the new frameTime. By having the commit time, we can adjust the start time to
+         * when the first frame was drawn (after any expensive traversals) so that no frames
+         * will be skipped.
+         *
+         * @param frameTime The frame time after traversals happen, if any, in the
+         *                  {@link SystemClock#uptimeMillis()} time base.
+         */
+        void commitAnimationFrame(long frameTime);
+    }
+
+    /**
+     * The intention for having this interface is to increase the testability of ValueAnimator.
+     * Specifically, we can have a custom implementation of the interface below and provide
+     * timing pulse without using Choreographer. That way we could use any arbitrary interval for
+     * our timing pulse in the tests.
+     *
+     * @hide
+     */
+    public interface AnimationFrameCallbackProvider {
+        void postFrameCallback(Choreographer.FrameCallback callback);
+        void postCommitCallback(Runnable runnable);
+        long getFrameTime();
+        long getFrameDelay();
+        void setFrameDelay(long delay);
+    }
+}
diff --git a/core/java/android/animation/ObjectAnimator.java b/core/java/android/animation/ObjectAnimator.java
index f9333739..26c886e 100644
--- a/core/java/android/animation/ObjectAnimator.java
+++ b/core/java/android/animation/ObjectAnimator.java
@@ -25,6 +25,7 @@
 import android.util.Property;
 
 import java.lang.ref.WeakReference;
+import java.util.ArrayList;
 
 /**
  * This subclass of {@link ValueAnimator} provides support for animating properties on target objects.
@@ -809,37 +810,7 @@
 
     @Override
     public void start() {
-        // See if any of the current active/pending animators need to be canceled
-        AnimationHandler handler = sAnimationHandler.get();
-        if (handler != null) {
-            int numAnims = handler.mAnimations.size();
-            for (int i = numAnims - 1; i >= 0; i--) {
-                if (handler.mAnimations.get(i) instanceof ObjectAnimator) {
-                    ObjectAnimator anim = (ObjectAnimator) handler.mAnimations.get(i);
-                    if (anim.mAutoCancel && hasSameTargetAndProperties(anim)) {
-                        anim.cancel();
-                    }
-                }
-            }
-            numAnims = handler.mPendingAnimations.size();
-            for (int i = numAnims - 1; i >= 0; i--) {
-                if (handler.mPendingAnimations.get(i) instanceof ObjectAnimator) {
-                    ObjectAnimator anim = (ObjectAnimator) handler.mPendingAnimations.get(i);
-                    if (anim.mAutoCancel && hasSameTargetAndProperties(anim)) {
-                        anim.cancel();
-                    }
-                }
-            }
-            numAnims = handler.mDelayedAnims.size();
-            for (int i = numAnims - 1; i >= 0; i--) {
-                if (handler.mDelayedAnims.get(i) instanceof ObjectAnimator) {
-                    ObjectAnimator anim = (ObjectAnimator) handler.mDelayedAnims.get(i);
-                    if (anim.mAutoCancel && hasSameTargetAndProperties(anim)) {
-                        anim.cancel();
-                    }
-                }
-            }
-        }
+        AnimationHandler.getInstance().autoCancelBasedOn(this);
         if (DBG) {
             Log.d(LOG_TAG, "Anim target, duration: " + getTarget() + ", " + getDuration());
             for (int i = 0; i < mValues.length; ++i) {
@@ -852,6 +823,20 @@
         super.start();
     }
 
+    boolean shouldAutoCancel(AnimationHandler.AnimationFrameCallback anim) {
+        if (anim == null) {
+            return false;
+        }
+
+        if (anim instanceof ObjectAnimator) {
+            ObjectAnimator objAnim = (ObjectAnimator) anim;
+            if (objAnim.mAutoCancel && hasSameTargetAndProperties(objAnim)) {
+                return true;
+            }
+        }
+        return false;
+    }
+
     /**
      * This function is called immediately before processing the first animation
      * frame of an animation. If there is a nonzero <code>startDelay</code>, the
diff --git a/core/java/android/animation/TimeAnimator.java b/core/java/android/animation/TimeAnimator.java
index 1ba68df..113a21f 100644
--- a/core/java/android/animation/TimeAnimator.java
+++ b/core/java/android/animation/TimeAnimator.java
@@ -37,7 +37,7 @@
     }
 
     @Override
-    boolean animationFrame(long currentTime) {
+    boolean animateBasedOnTime(long currentTime) {
         if (mListener != null) {
             long totalTime = currentTime - mStartTime;
             long deltaTime = (mPreviousTime < 0) ? 0 : (currentTime - mPreviousTime);
@@ -52,7 +52,7 @@
         long currentTime = AnimationUtils.currentAnimationTimeMillis();
         mStartTime = Math.max(mStartTime, currentTime - playTime);
         mStartTimeCommitted = true; // do not allow start time to be compensated for jank
-        animationFrame(currentTime);
+        animateBasedOnTime(currentTime);
     }
 
     /**
diff --git a/core/java/android/animation/ValueAnimator.java b/core/java/android/animation/ValueAnimator.java
index 35a8816..da9a8c8 100644
--- a/core/java/android/animation/ValueAnimator.java
+++ b/core/java/android/animation/ValueAnimator.java
@@ -21,7 +21,6 @@
 import android.os.Trace;
 import android.util.AndroidRuntimeException;
 import android.util.Log;
-import android.view.Choreographer;
 import android.view.animation.AccelerateDecelerateInterpolator;
 import android.view.animation.AnimationUtils;
 import android.view.animation.LinearInterpolator;
@@ -64,7 +63,7 @@
  * </div>
  */
 @SuppressWarnings("unchecked")
-public class ValueAnimator extends Animator {
+public class ValueAnimator extends Animator implements AnimationHandler.AnimationFrameCallback {
     private static final String TAG = "ValueAnimator";
     private static final boolean DEBUG = false;
 
@@ -74,14 +73,6 @@
     private static float sDurationScale = 1.0f;
 
     /**
-     * Values used with internal variable mPlayingState to indicate the current state of an
-     * animation.
-     */
-    static final int STOPPED    = 0; // Not yet playing
-    static final int RUNNING    = 1; // Playing normally
-    static final int SEEKED     = 2; // Seeked to some time value
-
-    /**
      * Internal variables
      * NOTE: This object implements the clone() method, making a deep copy of any referenced
      * objects. As other non-trivial fields are added to this class, make sure to add logic
@@ -130,15 +121,6 @@
      */
     private boolean mResumed = false;
 
-
-    // The static sAnimationHandler processes the internal timing loop on which all animations
-    // are based
-    /**
-     * @hide
-     */
-    protected static ThreadLocal<AnimationHandler> sAnimationHandler =
-            new ThreadLocal<AnimationHandler>();
-
     // The time interpolator to be used if none is set on the animation
     private static final TimeInterpolator sDefaultInterpolator =
             new AccelerateDecelerateInterpolator();
@@ -170,25 +152,9 @@
     private float mCurrentFraction = 0f;
 
     /**
-     * Tracks whether a startDelay'd animation has begun playing through the startDelay.
+     * Tracks the time (in milliseconds) when the last frame arrived.
      */
-    private boolean mStartedDelay = false;
-
-    /**
-     * Tracks the time at which the animation began playing through its startDelay. This is
-     * different from the mStartTime variable, which is used to track when the animation became
-     * active (which is when the startDelay expired and the animation was added to the active
-     * animations list).
-     */
-    private long mDelayStartTime;
-
-    /**
-     * Flag that represents the current state of the animation. Used to figure out when to start
-     * an animation (if state == STOPPED). Also used to end an animation that
-     * has been cancel()'d or end()'d since the last animation frame. Possible values are
-     * STOPPED, RUNNING, SEEKED.
-     */
-    int mPlayingState = STOPPED;
+    private long mLastFrameTime = 0;
 
     /**
      * Additional playing state to indicate whether an animator has been start()'d. There is
@@ -219,16 +185,21 @@
      */
     boolean mInitialized = false;
 
+    /**
+     * Flag that tracks whether animation has been requested to end.
+     */
+    private boolean mAnimationEndRequested = false;
+
     //
     // Backing variables
     //
 
     // How long the animation should last in ms
-    private long mDuration = (long)(300 * sDurationScale);
     private long mUnscaledDuration = 300;
+    private long mDuration = (long)(mUnscaledDuration * sDurationScale);
 
     // The amount of time in ms to delay starting the animation after start() is called
-    private long mStartDelay = 0;
+    long mStartDelay = 0;
     private long mUnscaledStartDelay = 0;
 
     // The number of times the animation will repeat. The default is 0, which means the animation
@@ -285,7 +256,6 @@
      */
     public static final int INFINITE = -1;
 
-
     /**
      * @hide
      */
@@ -539,7 +509,6 @@
         }
     }
 
-
     /**
      * Sets the length of the animation. The default duration is 300 milliseconds.
      *
@@ -644,9 +613,8 @@
         long currentTime = AnimationUtils.currentAnimationTimeMillis();
         mStartTime = currentTime - seekTime;
         mStartTimeCommitted = true; // do not allow start time to be compensated for jank
-        if (mPlayingState != RUNNING) {
+        if (!mRunning) {
             mSeekFraction = fraction;
-            mPlayingState = SEEKED;
         }
         if (mPlayingBackwards) {
             fraction = 1f - fraction;
@@ -662,168 +630,13 @@
      * @return The current position in time of the animation.
      */
     public long getCurrentPlayTime() {
-        if (!mInitialized || mPlayingState == STOPPED) {
+        if (!mInitialized || !mStarted) {
             return 0;
         }
         return AnimationUtils.currentAnimationTimeMillis() - mStartTime;
     }
 
     /**
-     * This custom, static handler handles the timing pulse that is shared by
-     * all active animations. This approach ensures that the setting of animation
-     * values will happen on the UI thread and that all animations will share
-     * the same times for calculating their values, which makes synchronizing
-     * animations possible.
-     *
-     * The handler uses the Choreographer for executing periodic callbacks.
-     *
-     * @hide
-     */
-    @SuppressWarnings("unchecked")
-    protected static class AnimationHandler {
-        // The per-thread list of all active animations
-        /** @hide */
-        protected final ArrayList<ValueAnimator> mAnimations = new ArrayList<ValueAnimator>();
-
-        // Used in doAnimationFrame() to avoid concurrent modifications of mAnimations
-        private final ArrayList<ValueAnimator> mTmpAnimations = new ArrayList<ValueAnimator>();
-
-        // The per-thread set of animations to be started on the next animation frame
-        /** @hide */
-        protected final ArrayList<ValueAnimator> mPendingAnimations = new ArrayList<ValueAnimator>();
-
-        /**
-         * Internal per-thread collections used to avoid set collisions as animations start and end
-         * while being processed.
-         * @hide
-         */
-        protected final ArrayList<ValueAnimator> mDelayedAnims = new ArrayList<ValueAnimator>();
-        private final ArrayList<ValueAnimator> mEndingAnims = new ArrayList<ValueAnimator>();
-        private final ArrayList<ValueAnimator> mReadyAnims = new ArrayList<ValueAnimator>();
-
-        private final Choreographer mChoreographer;
-        private boolean mAnimationScheduled;
-        private long mLastFrameTime;
-
-        private AnimationHandler() {
-            mChoreographer = Choreographer.getInstance();
-        }
-
-        /**
-         * Start animating on the next frame.
-         */
-        public void start() {
-            scheduleAnimation();
-        }
-
-        void doAnimationFrame(long frameTime) {
-            mLastFrameTime = frameTime;
-
-            // mPendingAnimations holds any animations that have requested to be started
-            // We're going to clear mPendingAnimations, but starting animation may
-            // cause more to be added to the pending list (for example, if one animation
-            // starting triggers another starting). So we loop until mPendingAnimations
-            // is empty.
-            while (mPendingAnimations.size() > 0) {
-                ArrayList<ValueAnimator> pendingCopy =
-                        (ArrayList<ValueAnimator>) mPendingAnimations.clone();
-                mPendingAnimations.clear();
-                int count = pendingCopy.size();
-                for (int i = 0; i < count; ++i) {
-                    ValueAnimator anim = pendingCopy.get(i);
-                    // If the animation has a startDelay, place it on the delayed list
-                    if (anim.mStartDelay == 0) {
-                        anim.startAnimation(this);
-                    } else {
-                        mDelayedAnims.add(anim);
-                    }
-                }
-            }
-
-            // Next, process animations currently sitting on the delayed queue, adding
-            // them to the active animations if they are ready
-            int numDelayedAnims = mDelayedAnims.size();
-            for (int i = 0; i < numDelayedAnims; ++i) {
-                ValueAnimator anim = mDelayedAnims.get(i);
-                if (anim.delayedAnimationFrame(frameTime)) {
-                    mReadyAnims.add(anim);
-                }
-            }
-            int numReadyAnims = mReadyAnims.size();
-            if (numReadyAnims > 0) {
-                for (int i = 0; i < numReadyAnims; ++i) {
-                    ValueAnimator anim = mReadyAnims.get(i);
-                    anim.startAnimation(this);
-                    anim.mRunning = true;
-                    mDelayedAnims.remove(anim);
-                }
-                mReadyAnims.clear();
-            }
-
-            // Now process all active animations. The return value from animationFrame()
-            // tells the handler whether it should now be ended
-            int numAnims = mAnimations.size();
-            for (int i = 0; i < numAnims; ++i) {
-                mTmpAnimations.add(mAnimations.get(i));
-            }
-            for (int i = 0; i < numAnims; ++i) {
-                ValueAnimator anim = mTmpAnimations.get(i);
-                if (mAnimations.contains(anim) && anim.doAnimationFrame(frameTime)) {
-                    mEndingAnims.add(anim);
-                }
-            }
-            mTmpAnimations.clear();
-            if (mEndingAnims.size() > 0) {
-                for (int i = 0; i < mEndingAnims.size(); ++i) {
-                    mEndingAnims.get(i).endAnimation(this);
-                }
-                mEndingAnims.clear();
-            }
-
-            // Schedule final commit for the frame.
-            mChoreographer.postCallback(Choreographer.CALLBACK_COMMIT, mCommit, null);
-
-            // If there are still active or delayed animations, schedule a future call to
-            // onAnimate to process the next frame of the animations.
-            if (!mAnimations.isEmpty() || !mDelayedAnims.isEmpty()) {
-                scheduleAnimation();
-            }
-        }
-
-        void commitAnimationFrame(long frameTime) {
-            final long adjustment = frameTime - mLastFrameTime;
-            final int numAnims = mAnimations.size();
-            for (int i = 0; i < numAnims; ++i) {
-                mAnimations.get(i).commitAnimationFrame(adjustment);
-            }
-        }
-
-        private void scheduleAnimation() {
-            if (!mAnimationScheduled) {
-                mChoreographer.postCallback(Choreographer.CALLBACK_ANIMATION, mAnimate, null);
-                mAnimationScheduled = true;
-            }
-        }
-
-        // Called by the Choreographer.
-        final Runnable mAnimate = new Runnable() {
-            @Override
-            public void run() {
-                mAnimationScheduled = false;
-                doAnimationFrame(mChoreographer.getFrameTime());
-            }
-        };
-
-        // Called by the Choreographer.
-        final Runnable mCommit = new Runnable() {
-            @Override
-            public void run() {
-                commitAnimationFrame(mChoreographer.getFrameTime());
-            }
-        };
-    }
-
-    /**
      * The amount of time, in milliseconds, to delay starting the animation after
      * {@link #start()} is called.
      *
@@ -859,7 +672,7 @@
      * @return the requested time between frames, in milliseconds
      */
     public static long getFrameDelay() {
-        return Choreographer.getFrameDelay();
+        return AnimationHandler.getInstance().getFrameDelay();
     }
 
     /**
@@ -875,7 +688,7 @@
      * @param frameDelay the requested time between frames, in milliseconds
      */
     public static void setFrameDelay(long frameDelay) {
-        Choreographer.setFrameDelay(frameDelay);
+        AnimationHandler.getInstance().setFrameDelay(frameDelay);
     }
 
     /**
@@ -1104,24 +917,13 @@
                 mPlayingBackwards = (mCurrentIteration % 2) != 0;
             }
         }
-        int prevPlayingState = mPlayingState;
-        mPlayingState = STOPPED;
         mStarted = true;
-        mStartedDelay = false;
         mPaused = false;
+        mRunning = false;
+        mAnimationEndRequested = false;
         updateScaledDuration(); // in case the scale factor has changed since creation time
-        AnimationHandler animationHandler = getOrCreateAnimationHandler();
-        animationHandler.mPendingAnimations.add(this);
-        if (mStartDelay == 0) {
-            // This sets the initial value of the animation, prior to actually starting it running
-            if (prevPlayingState != SEEKED) {
-                setCurrentPlayTime(0);
-            }
-            mPlayingState = STOPPED;
-            mRunning = true;
-            notifyStartListeners();
-        }
-        animationHandler.start();
+        AnimationHandler animationHandler = AnimationHandler.getInstance();
+        animationHandler.addAnimationFrameCallback(this, mStartDelay);
     }
 
     @Override
@@ -1131,41 +933,48 @@
 
     @Override
     public void cancel() {
+        if (Looper.myLooper() == null) {
+            throw new AndroidRuntimeException("Animators may only be run on Looper threads");
+        }
+
+        // If end has already been requested, through a previous end() or cancel() call, no-op
+        // until animation starts again.
+        if (mAnimationEndRequested) {
+            return;
+        }
+
         // Only cancel if the animation is actually running or has been started and is about
         // to run
-        AnimationHandler handler = getOrCreateAnimationHandler();
-        if (mPlayingState != STOPPED
-                || handler.mPendingAnimations.contains(this)
-                || handler.mDelayedAnims.contains(this)) {
-            // Only notify listeners if the animator has actually started
-            if ((mStarted || mRunning) && mListeners != null) {
-                if (!mRunning) {
-                    // If it's not yet running, then start listeners weren't called. Call them now.
-                    notifyStartListeners();
-                }
-                ArrayList<AnimatorListener> tmpListeners =
-                        (ArrayList<AnimatorListener>) mListeners.clone();
-                for (AnimatorListener listener : tmpListeners) {
-                    listener.onAnimationCancel(this);
-                }
+        // Only notify listeners if the animator has actually started
+        if ((mStarted || mRunning) && mListeners != null) {
+            if (!mRunning) {
+                // If it's not yet running, then start listeners weren't called. Call them now.
+                notifyStartListeners();
             }
-            endAnimation(handler);
+            ArrayList<AnimatorListener> tmpListeners =
+                    (ArrayList<AnimatorListener>) mListeners.clone();
+            for (AnimatorListener listener : tmpListeners) {
+                listener.onAnimationCancel(this);
+            }
         }
+        endAnimation();
+
     }
 
     @Override
     public void end() {
-        AnimationHandler handler = getOrCreateAnimationHandler();
-        if (!handler.mAnimations.contains(this) && !handler.mPendingAnimations.contains(this)) {
+        if (Looper.myLooper() == null) {
+            throw new AndroidRuntimeException("Animators may only be run on Looper threads");
+        }
+        if (!mRunning) {
             // Special case if the animation has not yet started; get it ready for ending
-            mStartedDelay = false;
-            startAnimation(handler);
+            startAnimation();
             mStarted = true;
         } else if (!mInitialized) {
             initAnimation();
         }
         animateValue(mPlayingBackwards ? 0f : 1f);
-        endAnimation(handler);
+        endAnimation();
     }
 
     @Override
@@ -1188,7 +997,7 @@
 
     @Override
     public boolean isRunning() {
-        return (mPlayingState == RUNNING || mRunning);
+        return mRunning;
     }
 
     @Override
@@ -1206,7 +1015,7 @@
     @Override
     public void reverse() {
         mPlayingBackwards = !mPlayingBackwards;
-        if (mPlayingState == RUNNING) {
+        if (mRunning) {
             long currentTime = AnimationUtils.currentAnimationTimeMillis();
             long currentPlayTime = currentTime - mStartTime;
             long timeLeft = mDuration - currentPlayTime;
@@ -1231,13 +1040,15 @@
     /**
      * Called internally to end an animation by removing it from the animations list. Must be
      * called on the UI thread.
-     * @hide
      */
-    protected void endAnimation(AnimationHandler handler) {
-        handler.mAnimations.remove(this);
-        handler.mPendingAnimations.remove(this);
-        handler.mDelayedAnims.remove(this);
-        mPlayingState = STOPPED;
+    private void endAnimation() {
+        if (mAnimationEndRequested) {
+            return;
+        }
+        AnimationHandler handler = AnimationHandler.getInstance();
+        handler.removeCallback(this);
+
+        mAnimationEndRequested = true;
         mPaused = false;
         if ((mStarted || mRunning) && mListeners != null) {
             if (!mRunning) {
@@ -1267,16 +1078,14 @@
      * Called internally to start an animation by adding it to the active animations list. Must be
      * called on the UI thread.
      */
-    private void startAnimation(AnimationHandler handler) {
+    private void startAnimation() {
         if (Trace.isTagEnabled(Trace.TRACE_TAG_VIEW)) {
             Trace.asyncTraceBegin(Trace.TRACE_TAG_VIEW, getNameForTrace(),
                     System.identityHashCode(this));
         }
         initAnimation();
-        handler.mAnimations.add(this);
-        if (mStartDelay > 0 && mListeners != null) {
-            // Listeners were already notified in start() if startDelay is 0; this is
-            // just for delayed animations
+        mRunning = true;
+        if (mListeners != null) {
             notifyStartListeners();
         }
     }
@@ -1288,53 +1097,16 @@
         return "animator";
     }
 
-
-    /**
-     * Internal function called to process an animation frame on an animation that is currently
-     * sleeping through its <code>startDelay</code> phase. The return value indicates whether it
-     * should be woken up and put on the active animations queue.
-     *
-     * @param currentTime The current animation time, used to calculate whether the animation
-     * has exceeded its <code>startDelay</code> and should be started.
-     * @return True if the animation's <code>startDelay</code> has been exceeded and the animation
-     * should be added to the set of active animations.
-     */
-    private boolean delayedAnimationFrame(long currentTime) {
-        if (!mStartedDelay) {
-            mStartedDelay = true;
-            mDelayStartTime = currentTime;
-        }
-        if (mPaused) {
-            if (mPauseTime < 0) {
-                mPauseTime = currentTime;
-            }
-            return false;
-        } else if (mResumed) {
-            mResumed = false;
-            if (mPauseTime > 0) {
-                // Offset by the duration that the animation was paused
-                mDelayStartTime += (currentTime - mPauseTime);
-            }
-        }
-        long deltaTime = currentTime - mDelayStartTime;
-        if (deltaTime > mStartDelay) {
-            // startDelay ended - start the anim and record the mStartTime appropriately
-            mStartTime = mDelayStartTime + mStartDelay;
-            mStartTimeCommitted = true; // do not allow start time to be compensated for jank
-            mPlayingState = RUNNING;
-            return true;
-        }
-        return false;
-    }
-
     /**
      * Applies an adjustment to the animation to compensate for jank between when
      * the animation first ran and when the frame was drawn.
+     * @hide
      */
-    void commitAnimationFrame(long adjustment) {
+    public void commitAnimationFrame(long frameTime) {
         if (!mStartTimeCommitted) {
             mStartTimeCommitted = true;
-            if (mPlayingState == RUNNING && adjustment > 0) {
+            long adjustment = frameTime - mLastFrameTime;
+            if (adjustment > 0) {
                 mStartTime += adjustment;
                 if (DEBUG) {
                     Log.d(TAG, "Adjusted start time by " + adjustment + " ms: " + toString());
@@ -1353,13 +1125,11 @@
      *
      * @param currentTime The current time, as tracked by the static timing handler
      * @return true if the animation's duration, including any repetitions due to
-     * <code>repeatCount</code>, has been exceeded and the animation should be ended.
+     * <code>repeatCount</code> has been exceeded and the animation should be ended.
      */
-    boolean animationFrame(long currentTime) {
+    boolean animateBasedOnTime(long currentTime) {
         boolean done = false;
-        switch (mPlayingState) {
-        case RUNNING:
-        case SEEKED:
+        if (mRunning) {
             float fraction = mDuration > 0 ? (float)(currentTime - mStartTime) / mDuration : 1f;
             if (mDuration == 0 && mRepeatCount != INFINITE) {
                 // Skip to the end
@@ -1394,9 +1164,7 @@
                 fraction = 1f - fraction;
             }
             animateValue(fraction);
-            break;
         }
-
         return done;
     }
 
@@ -1405,10 +1173,15 @@
      *
      * @param frameTime The frame time.
      * @return true if the animation has ended.
+     * @hide
      */
-    final boolean doAnimationFrame(long frameTime) {
-        if (mPlayingState == STOPPED) {
-            mPlayingState = RUNNING;
+    public final void doAnimationFrame(long frameTime) {
+        mLastFrameTime = frameTime;
+        AnimationHandler handler = AnimationHandler.getInstance();
+        if (!mRunning) {
+            // First frame
+            handler.addOneShotCommitCallback(this);
+            startAnimation();
             if (mSeekFraction < 0) {
                 mStartTime = frameTime;
             } else {
@@ -1422,7 +1195,7 @@
             if (mPauseTime < 0) {
                 mPauseTime = frameTime;
             }
-            return false;
+            return;
         } else if (mResumed) {
             mResumed = false;
             if (mPauseTime > 0) {
@@ -1430,13 +1203,18 @@
                 mStartTime += (frameTime - mPauseTime);
                 mStartTimeCommitted = false; // allow start time to be compensated for jank
             }
+            handler.addOneShotCommitCallback(this);
         }
         // The frame time might be before the start time during the first frame of
         // an animation.  The "current time" must always be on or after the start
         // time to avoid animating frames at negative time intervals.  In practice, this
         // is very rare and only happens when seeking backwards.
         final long currentTime = Math.max(frameTime, mStartTime);
-        return animationFrame(currentTime);
+        boolean finished = animateBasedOnTime(currentTime);
+
+        if (finished) {
+            endAnimation();
+        }
     }
 
     /**
@@ -1488,8 +1266,6 @@
         anim.mReversing = false;
         anim.mCurrentIteration = 0;
         anim.mInitialized = false;
-        anim.mPlayingState = STOPPED;
-        anim.mStartedDelay = false;
         anim.mStarted = false;
         anim.mRunning = false;
         anim.mPaused = false;
@@ -1497,9 +1273,10 @@
         anim.mStartListenersCalled = false;
         anim.mStartTime = 0;
         anim.mStartTimeCommitted = false;
+        anim.mAnimationEndRequested = false;
         anim.mPauseTime = 0;
+        anim.mLastFrameTime = 0;
         anim.mCurrentFraction = 0;
-        anim.mDelayStartTime = 0;
 
         PropertyValuesHolder[] oldValues = mValues;
         if (oldValues != null) {
@@ -1540,32 +1317,7 @@
      * @hide
      */
     public static int getCurrentAnimationsCount() {
-        AnimationHandler handler = sAnimationHandler.get();
-        return handler != null ? handler.mAnimations.size() : 0;
-    }
-
-    /**
-     * Clear all animations on this thread, without canceling or ending them.
-     * This should be used with caution.
-     *
-     * @hide
-     */
-    public static void clearAllAnimations() {
-        AnimationHandler handler = sAnimationHandler.get();
-        if (handler != null) {
-            handler.mAnimations.clear();
-            handler.mPendingAnimations.clear();
-            handler.mDelayedAnims.clear();
-        }
-    }
-
-    private static AnimationHandler getOrCreateAnimationHandler() {
-        AnimationHandler handler = sAnimationHandler.get();
-        if (handler == null) {
-            handler = new AnimationHandler();
-            sAnimationHandler.set(handler);
-        }
-        return handler;
+        return AnimationHandler.getAnimationCount();
     }
 
     @Override
diff --git a/core/java/android/app/ActivityThread.java b/core/java/android/app/ActivityThread.java
index fe79629..412e3cd 100644
--- a/core/java/android/app/ActivityThread.java
+++ b/core/java/android/app/ActivityThread.java
@@ -1727,7 +1727,8 @@
             String[] libDirs, int displayId, Configuration overrideConfiguration,
             LoadedApk pkgInfo) {
         return mResourcesManager.getTopLevelResources(resDir, splitResDirs, overlayDirs, libDirs,
-                displayId, overrideConfiguration, pkgInfo.getCompatibilityInfo());
+                displayId, overrideConfiguration, pkgInfo.getCompatibilityInfo(),
+                pkgInfo.getClassLoader());
     }
 
     final Handler getHandler() {
diff --git a/core/java/android/app/ContextImpl.java b/core/java/android/app/ContextImpl.java
index 235f294..fca5567 100644
--- a/core/java/android/app/ContextImpl.java
+++ b/core/java/android/app/ContextImpl.java
@@ -1838,7 +1838,7 @@
                 resources = mResourcesManager.getTopLevelResources(packageInfo.getResDir(),
                         packageInfo.getSplitResDirs(), packageInfo.getOverlayDirs(),
                         packageInfo.getApplicationInfo().sharedLibraryFiles, displayId,
-                        overrideConfiguration, compatInfo);
+                        overrideConfiguration, compatInfo, packageInfo.getClassLoader());
             }
         }
         mResources = resources;
diff --git a/core/java/android/app/ResourcesManager.java b/core/java/android/app/ResourcesManager.java
index 2117597..1605b3e 100644
--- a/core/java/android/app/ResourcesManager.java
+++ b/core/java/android/app/ResourcesManager.java
@@ -157,7 +157,8 @@
      */
     Resources getTopLevelResources(String resDir, String[] splitResDirs,
             String[] overlayDirs, String[] libDirs, int displayId,
-            Configuration overrideConfiguration, CompatibilityInfo compatInfo) {
+            Configuration overrideConfiguration, CompatibilityInfo compatInfo,
+            ClassLoader classLoader) {
         final float scale = compatInfo.applicationScale;
         Configuration overrideConfigCopy = (overrideConfiguration != null)
                 ? new Configuration(overrideConfiguration) : null;
@@ -237,7 +238,7 @@
         } else {
             config = getConfiguration();
         }
-        r = new Resources(assets, dm, config, compatInfo);
+        r = new Resources(assets, dm, config, compatInfo, classLoader);
         if (DEBUG) Slog.i(TAG, "Created app resources " + resDir + " " + r + ": "
                 + r.getConfiguration() + " appScale=" + r.getCompatibilityInfo().applicationScale);
 
diff --git a/core/java/android/app/backup/FullBackup.java b/core/java/android/app/backup/FullBackup.java
index 7718a36..9ea2ba2 100644
--- a/core/java/android/app/backup/FullBackup.java
+++ b/core/java/android/app/backup/FullBackup.java
@@ -401,7 +401,19 @@
                             activeSet.add(canonicalJournalPath);
                             if (Log.isLoggable(TAG_XML_PARSER, Log.VERBOSE)) {
                                 Log.v(TAG_XML_PARSER, "...automatically generated "
-                                        + canonicalJournalPath + ". Ignore if nonexistant.");
+                                        + canonicalJournalPath + ". Ignore if nonexistent.");
+                            }
+                        }
+
+                        // Special case for sharedpref files (not dirs) also add ".xml" suffix file.
+                        if ("sharedpref".equals(domainFromXml) && !canonicalFile.isDirectory() &&
+                            !canonicalFile.getCanonicalPath().endsWith(".xml")) {
+                            final String canonicalXmlPath =
+                                    canonicalFile.getCanonicalPath() + ".xml";
+                            activeSet.add(canonicalXmlPath);
+                            if (Log.isLoggable(TAG_XML_PARSER, Log.VERBOSE)) {
+                                Log.v(TAG_XML_PARSER, "...automatically generated "
+                                        + canonicalXmlPath + ". Ignore if nonexistent.");
                             }
                         }
                 }
diff --git a/core/java/android/content/pm/ActivityInfo.java b/core/java/android/content/pm/ActivityInfo.java
index 83092a9..a59f429 100644
--- a/core/java/android/content/pm/ActivityInfo.java
+++ b/core/java/android/content/pm/ActivityInfo.java
@@ -273,10 +273,10 @@
     public static final int FLAG_RESUME_WHILE_PAUSING = 0x4000;
     /**
      * @hide Bit in {@link #flags}: If set, this component will only be seen
-     * by the primary user.  Only works with broadcast receivers.  Set from the
-     * android.R.attr#primaryUserOnly attribute.
+     * by the system user.  Only works with broadcast receivers.  Set from the
+     * android.R.attr#systemUserOnly attribute.
      */
-    public static final int FLAG_PRIMARY_USER_ONLY = 0x20000000;
+    public static final int FLAG_SYSTEM_USER_ONLY = 0x20000000;
     /**
      * Bit in {@link #flags}: If set, a single instance of the receiver will
      * run for all users on the device.  Set from the
diff --git a/core/java/android/content/pm/AppsQueryHelper.java b/core/java/android/content/pm/AppsQueryHelper.java
new file mode 100644
index 0000000..56b3173
--- /dev/null
+++ b/core/java/android/content/pm/AppsQueryHelper.java
@@ -0,0 +1,153 @@
+/*
+ * Copyright (C) 2015 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.content.pm;
+
+import android.Manifest;
+import android.app.AppGlobals;
+import android.content.Context;
+import android.content.Intent;
+import android.os.RemoteException;
+import android.os.UserHandle;
+import android.util.ArraySet;
+
+import com.android.internal.annotations.VisibleForTesting;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Helper class for querying installed applications using multiple criteria.
+ *
+ * @hide
+ */
+public class AppsQueryHelper {
+
+    /**
+     * Return apps without launcher icon
+     */
+    public static int GET_NON_LAUNCHABLE_APPS = 1;
+
+    /**
+     * Return apps with {@link android.Manifest.permission#INTERACT_ACROSS_USERS} permission
+     */
+    public static int GET_APPS_WITH_INTERACT_ACROSS_USERS_PERM = 1 << 1;
+
+    private final Context mContext;
+    private List<ApplicationInfo> mAllApps;
+
+    public AppsQueryHelper(Context context) {
+        mContext = context;
+    }
+
+    /**
+     * Return a List of all packages that satisfy a specified criteria.
+     * @param flags search flags. Use any combination of {@link #GET_NON_LAUNCHABLE_APPS},
+     * {@link #GET_APPS_WITH_INTERACT_ACROSS_USERS_PERM}
+     * @param systemAppsOnly if true, only system apps will be returned
+     * @param user user, whose apps are queried
+     */
+    public List<String> queryApps(int flags, boolean systemAppsOnly, UserHandle user) {
+        boolean nonLaunchableApps = (flags & GET_NON_LAUNCHABLE_APPS) > 0;
+        boolean interactAcrossUsers = (flags & GET_APPS_WITH_INTERACT_ACROSS_USERS_PERM) > 0;
+        if (mAllApps == null) {
+            mAllApps = getAllApps(user.getIdentifier());
+        }
+
+        List<String> result = new ArrayList<>();
+        if (flags == 0) {
+            final int allAppsSize = mAllApps.size();
+            for (int i = 0; i < allAppsSize; i++) {
+                final ApplicationInfo appInfo = mAllApps.get(i);
+                if (systemAppsOnly && !appInfo.isSystemApp()) {
+                    continue;
+                }
+                result.add(appInfo.packageName);
+            }
+            return result;
+        }
+
+        if (nonLaunchableApps) {
+            Intent intent = new Intent(Intent.ACTION_MAIN).addCategory(Intent.CATEGORY_LAUNCHER);
+            final List<ResolveInfo> resolveInfos = queryIntentActivitiesAsUser(intent,
+                    user.getIdentifier());
+
+            ArraySet<String> appsWithLaunchers = new ArraySet<>();
+            final int resolveInfosSize = resolveInfos.size();
+            for (int i = 0; i < resolveInfosSize; i++) {
+                appsWithLaunchers.add(resolveInfos.get(i).activityInfo.packageName);
+            }
+            final int allAppsSize = mAllApps.size();
+            for (int i = 0; i < allAppsSize; i++) {
+                final ApplicationInfo appInfo = mAllApps.get(i);
+                if (systemAppsOnly && !appInfo.isSystemApp()) {
+                    continue;
+                }
+                final String packageName = appInfo.packageName;
+                if (!appsWithLaunchers.contains(packageName)) {
+                    result.add(packageName);
+                }
+            }
+        }
+
+        if (interactAcrossUsers) {
+            final List<PackageInfo> packagesHoldingPermissions = getPackagesHoldingPermission(
+                    Manifest.permission.INTERACT_ACROSS_USERS, user.getIdentifier());
+            final int packagesHoldingPermissionsSize = packagesHoldingPermissions.size();
+            for (int i = 0; i < packagesHoldingPermissionsSize; i++) {
+                PackageInfo packageInfo = packagesHoldingPermissions.get(i);
+                if (systemAppsOnly && !packageInfo.applicationInfo.isSystemApp()) {
+                    continue;
+                }
+                if (!result.contains(packageInfo.packageName)) {
+                    result.add(packageInfo.packageName);
+                }
+            }
+        }
+
+        return result;
+    }
+
+    @VisibleForTesting
+    @SuppressWarnings("unchecked")
+    protected List<ApplicationInfo> getAllApps(int userId) {
+        try {
+            return AppGlobals.getPackageManager().getInstalledApplications(
+                    PackageManager.GET_UNINSTALLED_PACKAGES
+                            | PackageManager.GET_DISABLED_COMPONENTS, userId).getList();
+        } catch (RemoteException e) {
+            throw new IllegalStateException("Package manager has died", e);
+        }
+    }
+
+    @VisibleForTesting
+    protected List<ResolveInfo> queryIntentActivitiesAsUser(Intent intent, int userId) {
+        return mContext.getPackageManager()
+                .queryIntentActivitiesAsUser(intent, PackageManager.GET_DISABLED_COMPONENTS
+                        | PackageManager.GET_UNINSTALLED_PACKAGES, userId);
+    }
+
+    @VisibleForTesting
+    @SuppressWarnings("unchecked")
+    protected List<PackageInfo> getPackagesHoldingPermission(String perm, int userId) {
+        try {
+            return AppGlobals.getPackageManager().getPackagesHoldingPermissions(new String[]{perm},
+                    0, userId).getList();
+        } catch (RemoteException e) {
+            throw new IllegalStateException("Package manager has died", e);
+        }
+    }
+}
diff --git a/core/java/android/content/pm/PackageParser.java b/core/java/android/content/pm/PackageParser.java
index 502f735..968f9b2 100644
--- a/core/java/android/content/pm/PackageParser.java
+++ b/core/java/android/content/pm/PackageParser.java
@@ -3138,8 +3138,8 @@
             a.info.flags |= ActivityInfo.FLAG_IMMERSIVE;
         }
 
-        if (sa.getBoolean(R.styleable.AndroidManifestActivity_primaryUserOnly, false)) {
-            a.info.flags |= ActivityInfo.FLAG_PRIMARY_USER_ONLY;
+        if (sa.getBoolean(R.styleable.AndroidManifestActivity_systemUserOnly, false)) {
+            a.info.flags |= ActivityInfo.FLAG_SYSTEM_USER_ONLY;
         }
 
         if (!receiver) {
diff --git a/core/java/android/content/pm/UserInfo.java b/core/java/android/content/pm/UserInfo.java
index 38f971a..2aae1de 100644
--- a/core/java/android/content/pm/UserInfo.java
+++ b/core/java/android/content/pm/UserInfo.java
@@ -129,6 +129,15 @@
     }
 
     /**
+     * Returns true if the user is a split system user.
+     * <p>If {@link UserManager#isSplitSystemUser split system user mode} is not enabled,
+     * the method always returns false.
+     */
+    public boolean isSystemOnly() {
+        return id == UserHandle.USER_SYSTEM && UserManager.isSplitSystemUser();
+    }
+
+    /**
      * @return true if this user can be switched to.
      **/
     public boolean supportsSwitchTo() {
diff --git a/core/java/android/content/res/Resources.java b/core/java/android/content/res/Resources.java
index ae92108..e29bd2c 100644
--- a/core/java/android/content/res/Resources.java
+++ b/core/java/android/content/res/Resources.java
@@ -20,6 +20,7 @@
 import android.annotation.ColorInt;
 import android.annotation.StyleRes;
 import android.annotation.StyleableRes;
+import android.graphics.drawable.DrawableInflater;
 import android.icu.text.PluralRules;
 import com.android.internal.util.GrowingArrayUtils;
 import com.android.internal.util.XmlUtils;
@@ -142,6 +143,9 @@
     private final ConfigurationBoundResourceCache<StateListAnimator> mStateListAnimatorCache =
             new ConfigurationBoundResourceCache<>(this);
 
+    /** Used to inflate drawable objects from XML. */
+    private DrawableInflater mDrawableInflater;
+
     private TypedValue mTmpValue = new TypedValue();
     private boolean mPreloading;
 
@@ -150,6 +154,7 @@
     private final XmlBlock[] mCachedXmlBlocks = new XmlBlock[4];
 
     final AssetManager mAssets;
+    final ClassLoader mClassLoader;
     final DisplayMetrics mMetrics = new DisplayMetrics();
 
     private final Configuration mConfiguration = new Configuration();
@@ -204,6 +209,17 @@
     }
 
     /**
+     * @return the inflater used to create drawable objects
+     * @hide Pending API finalization.
+     */
+    public final DrawableInflater getDrawableInflater() {
+        if (mDrawableInflater == null) {
+            mDrawableInflater = new DrawableInflater(this, mClassLoader);
+        }
+        return mDrawableInflater;
+    }
+
+    /**
      * Used by AnimatorInflater.
      *
      * @hide
@@ -245,7 +261,7 @@
      *               selecting/computing resource values (optional).
      */
     public Resources(AssetManager assets, DisplayMetrics metrics, Configuration config) {
-        this(assets, metrics, config, CompatibilityInfo.DEFAULT_COMPATIBILITY_INFO);
+        this(assets, metrics, config, CompatibilityInfo.DEFAULT_COMPATIBILITY_INFO, null);
     }
 
     /**
@@ -257,11 +273,15 @@
      * @param config Desired device configuration to consider when
      *               selecting/computing resource values (optional).
      * @param compatInfo this resource's compatibility info. Must not be null.
+     * @param classLoader class loader for the package used to load custom
+     *                    resource classes, may be {@code null} to use system
+     *                    class loader
      * @hide
      */
     public Resources(AssetManager assets, DisplayMetrics metrics, Configuration config,
-            CompatibilityInfo compatInfo) {
+            CompatibilityInfo compatInfo, @Nullable ClassLoader classLoader) {
         mAssets = assets;
+        mClassLoader = classLoader == null ? ClassLoader.getSystemClassLoader() : classLoader;
         mMetrics.setToDefaults();
         if (compatInfo != null) {
             mCompatibilityInfo = compatInfo;
@@ -2803,6 +2823,7 @@
 
     private Resources() {
         mAssets = AssetManager.getSystem();
+        mClassLoader = ClassLoader.getSystemClassLoader();
         // NOTE: Intentionally leaving this uninitialized (all values set
         // to zero), so that anyone who tries to do something that requires
         // metrics will get a very wrong value.
diff --git a/core/java/android/hardware/camera2/CameraDevice.java b/core/java/android/hardware/camera2/CameraDevice.java
index 4a71aa0..20b0be1 100644
--- a/core/java/android/hardware/camera2/CameraDevice.java
+++ b/core/java/android/hardware/camera2/CameraDevice.java
@@ -480,8 +480,11 @@
      * the configurations in the tables below are also guaranteed for creating a reprocessable
      * capture session if the camera device supports YUV reprocessing or PRIVATE reprocessing.
      * However, not all output targets used to create a reprocessable session may be used in a
-     * {@link CaptureRequest} simultaneously. The guaranteed output targets that can be included
-     * in a {@link CaptureRequest} simultaneously are listed in the tables under
+     * {@link CaptureRequest} simultaneously. For devices that support only 1 output target in a
+     * reprocess {@link CaptureRequest}, submitting a reprocess {@link CaptureRequest} with multiple
+     * output targets will result in a {@link CaptureFailure}. For devices that support multiple
+     * output targets in a reprocess {@link CaptureRequest}, the guaranteed output targets that can
+     * be included in a {@link CaptureRequest} simultaneously are listed in the tables under
      * {@link #createCaptureSession createCaptureSession}. For example, with a FULL-capability
      * ({@link CameraCharacteristics#INFO_SUPPORTED_HARDWARE_LEVEL} {@code == }
      * {@link CameraMetadata#INFO_SUPPORTED_HARDWARE_LEVEL_FULL FULL}) device that supports PRIVATE
@@ -532,8 +535,6 @@
      * <tr> <td>{@code PRIV}/{@code YUV}</td><td id="rb">{@code MAXIMUM}</td> <td>Same as input</td><td id="rb">{@code MAXIMUM}</td> <td>{@code PRIV}</td><td id="rb">{@code PREVIEW}</td> <td>{@code YUV}</td><td id="rb">{@code RECORD}</td> <td></td><td id="rb"></td> <td>High-resolution ZSL in-app video processing with regular preview.</td> </tr>
      * <tr> <td>{@code PRIV}</td><td id="rb">{@code MAXIMUM}</td> <td>{@code PRIV}</td><td id="rb">{@code MAXIMUM}</td> <td>{@code PRIV}</td><td id="rb">{@code PREVIEW}</td> <td>{@code YUV}</td><td id="rb">{@code MAXIMUM}</td> <td></td><td id="rb"></td> <td>Maximum-resolution ZSL in-app processing with regular preview.</td> </tr>
      * <tr> <td>{@code PRIV}</td><td id="rb">{@code MAXIMUM}</td> <td>{@code PRIV}</td><td id="rb">{@code MAXIMUM}</td> <td>{@code YUV}</td><td id="rb">{@code PREVIEW}</td> <td>{@code YUV}</td><td id="rb">{@code MAXIMUM}</td> <td></td><td id="rb"></td> <td>Maximum-resolution two-input ZSL in-app processing.</td> </tr>
-     * <tr> <td>{@code PRIV}/{@code YUV}</td><td id="rb">{@code MAXIMUM}</td> <td>Same as input</td><td id="rb">{@code MAXIMUM}</td> <td>{@code PRIV}</td><td id="rb">{@code PREVIEW}</td> <td>{@code YUV}</td><td id="rb">{@code RECORD}</td> <td>{@code JPEG}</td><td id="rb">{@code RECORD}</td> <td>High-resolution ZSL in-app video processing and video snapshot with regular preview.</td> </tr>
-     * <tr> <td>{@code PRIV}</td><td id="rb">{@code MAXIMUM}</td> <td>{@code PRIV}</td><td id="rb">{@code MAXIMUM}</td> <td>{@code YUV}</td><td id="rb">{@code PREVIEW}</td> <td>{@code PRIV}</td><td id="rb">{@code PREVIEW}</td> <td>{@code YUV}</td><td id="rb">{@code MAXIMUM}</td> <td>Maximum-resolution two-input ZSL in-app processing with regular preview.</td> </tr>
      * <tr> <td>{@code PRIV}/{@code YUV}</td><td id="rb">{@code MAXIMUM}</td> <td>Same as input</td><td id="rb">{@code MAXIMUM}</td> <td>{@code PRIV}</td><td id="rb">{@code PREVIEW}</td> <td>{@code YUV}</td><td id="rb">{@code PREVIEW}</td> <td>{@code JPEG}</td><td id="rb">{@code MAXIMUM}</td> <td>ZSL still capture and in-app processing.</td> </tr>
      * </table><br>
      * </p>
@@ -711,7 +712,9 @@
      * provide input images to camera device via {@link android.media.ImageWriter#queueInputImage}.
      * The application must use the capture result of one of those output images to create a
      * reprocess capture request so that the camera device can use the information to achieve
-     * optimal reprocess image quality.
+     * optimal reprocess image quality. For camera devices that support only 1 output
+     * {@link Surface}, submitting a reprocess {@link CaptureRequest} with multiple
+     * output targets will result in a {@link CaptureFailure}.
      *
      * @param inputResult The capture result of the output image or one of the output images used
      *                       to generate the reprocess input image for this capture request.
diff --git a/core/java/android/hardware/location/ActivityRecognitionHardware.java b/core/java/android/hardware/location/ActivityRecognitionHardware.java
index 5d3953a..8acd1ff 100644
--- a/core/java/android/hardware/location/ActivityRecognitionHardware.java
+++ b/core/java/android/hardware/location/ActivityRecognitionHardware.java
@@ -30,20 +30,34 @@
  * @hide
  */
 public class ActivityRecognitionHardware extends IActivityRecognitionHardware.Stub {
-    private static final String TAG = "ActivityRecognitionHardware";
+    private static final String TAG = "ActivityRecognitionHW";
+    private static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG);
 
     private static final String HARDWARE_PERMISSION = Manifest.permission.LOCATION_HARDWARE;
+    private static final String ENFORCE_HW_PERMISSION_MESSAGE = "Permission '"
+            + HARDWARE_PERMISSION + "' not granted to access ActivityRecognitionHardware";
+
     private static final int INVALID_ACTIVITY_TYPE = -1;
     private static final int NATIVE_SUCCESS_RESULT = 0;
+    private static final int EVENT_TYPE_DISABLED = 0;
+    private static final int EVENT_TYPE_ENABLED = 1;
 
-    private static ActivityRecognitionHardware sSingletonInstance = null;
+    /**
+     * Contains the number of supported Event Types.
+     *
+     * NOTE: increment this counter every time a new EVENT_TYPE_ is added to
+     *       com.android.location.provider.ActivityRecognitionProvider
+     */
+    private static final int EVENT_TYPE_COUNT = 3;
+
+    private static ActivityRecognitionHardware sSingletonInstance;
     private static final Object sSingletonInstanceLock = new Object();
 
     private final Context mContext;
+    private final int mSupportedActivitiesCount;
     private final String[] mSupportedActivities;
-
-    private final RemoteCallbackList<IActivityRecognitionHardwareSink> mSinks =
-            new RemoteCallbackList<IActivityRecognitionHardwareSink>();
+    private final int[][] mSupportedActivitiesEnabledEvents;
+    private final SinkList mSinks = new SinkList();
 
     private static class Event {
         public int activity;
@@ -56,6 +70,8 @@
 
         mContext = context;
         mSupportedActivities = fetchSupportedActivities();
+        mSupportedActivitiesCount = mSupportedActivities.length;
+        mSupportedActivitiesEnabledEvents = new int[mSupportedActivitiesCount][EVENT_TYPE_COUNT];
     }
 
     public static ActivityRecognitionHardware getInstance(Context context) {
@@ -107,7 +123,11 @@
         }
 
         int result = nativeEnableActivityEvent(activityType, eventType, reportLatencyNs);
-        return result == NATIVE_SUCCESS_RESULT;
+        if (result == NATIVE_SUCCESS_RESULT) {
+            mSupportedActivitiesEnabledEvents[activityType][eventType] = EVENT_TYPE_ENABLED;
+            return true;
+        }
+        return false;
     }
 
     @Override
@@ -120,7 +140,11 @@
         }
 
         int result = nativeDisableActivityEvent(activityType, eventType);
-        return result == NATIVE_SUCCESS_RESULT;
+        if (result == NATIVE_SUCCESS_RESULT) {
+            mSupportedActivitiesEnabledEvents[activityType][eventType] = EVENT_TYPE_DISABLED;
+            return true;
+        }
+        return false;
     }
 
     @Override
@@ -135,7 +159,7 @@
      */
     private void onActivityChanged(Event[] events) {
         if (events == null || events.length == 0) {
-            Log.d(TAG, "No events to broadcast for onActivityChanged.");
+            if (DEBUG) Log.d(TAG, "No events to broadcast for onActivityChanged.");
             return;
         }
 
@@ -161,7 +185,6 @@
             }
         }
         mSinks.finishBroadcast();
-
     }
 
     private String getActivityName(int activityType) {
@@ -193,10 +216,7 @@
     }
 
     private void checkPermissions() {
-        String message = String.format(
-                "Permission '%s' not granted to access ActivityRecognitionHardware",
-                HARDWARE_PERMISSION);
-        mContext.enforceCallingPermission(HARDWARE_PERMISSION, message);
+        mContext.enforceCallingPermission(HARDWARE_PERMISSION, ENFORCE_HW_PERMISSION_MESSAGE);
     }
 
     private String[] fetchSupportedActivities() {
@@ -208,6 +228,39 @@
         return new String[0];
     }
 
+    private class SinkList extends RemoteCallbackList<IActivityRecognitionHardwareSink> {
+        @Override
+        public void onCallbackDied(IActivityRecognitionHardwareSink callback) {
+            int callbackCount = mSinks.getRegisteredCallbackCount();
+            if (DEBUG) Log.d(TAG, "RegisteredCallbackCount: " + callbackCount);
+            if (callbackCount != 0) {
+                return;
+            }
+            // currently there is only one client for this, so if all its sinks have died, we clean
+            // up after them, this ensures that the AR HAL is not out of sink
+            for (int activity = 0; activity < mSupportedActivitiesCount; ++activity) {
+                for (int event = 0; event < EVENT_TYPE_COUNT; ++event) {
+                    disableActivityEventIfEnabled(activity, event);
+                }
+            }
+        }
+
+        private void disableActivityEventIfEnabled(int activityType, int eventType) {
+            if (mSupportedActivitiesEnabledEvents[activityType][eventType] != EVENT_TYPE_ENABLED) {
+                return;
+            }
+
+            int result = nativeDisableActivityEvent(activityType, eventType);
+            mSupportedActivitiesEnabledEvents[activityType][eventType] = EVENT_TYPE_DISABLED;
+            String message = String.format(
+                    "DisableActivityEvent: activityType=%d, eventType=%d, result=%d",
+                    activityType,
+                    eventType,
+                    result);
+            Log.e(TAG, message);
+        }
+    }
+
     // native bindings
     static { nativeClassInit(); }
 
diff --git a/core/java/android/hardware/usb/UsbManager.java b/core/java/android/hardware/usb/UsbManager.java
index 3b3ee52..a23a6cb 100644
--- a/core/java/android/hardware/usb/UsbManager.java
+++ b/core/java/android/hardware/usb/UsbManager.java
@@ -70,6 +70,8 @@
      * <li> {@link #USB_FUNCTION_MIDI} boolean extra indicating whether the
      * MIDI function is enabled
      * </ul>
+     * If the sticky intent has not been found, that indicates USB is disconnected,
+     * USB is not configued, MTP function is enabled, and all the other functions are disabled.
      *
      * {@hide}
      */
@@ -592,7 +594,7 @@
 
     /** @hide */
     public static String addFunction(String functions, String function) {
-        if ("none".equals(functions)) {
+        if (USB_FUNCTION_NONE.equals(functions)) {
             return function;
         }
         if (!containsFunction(functions, function)) {
@@ -613,7 +615,7 @@
             }
         }
         if (split.length == 1 && split[0] == null) {
-            return "none";
+            return USB_FUNCTION_NONE;
         }
         StringBuilder builder = new StringBuilder();
         for (int i = 0; i < split.length; i++) {
diff --git a/core/java/android/net/NetworkScorerAppManager.java b/core/java/android/net/NetworkScorerAppManager.java
index 29daf35..ec76b8a 100644
--- a/core/java/android/net/NetworkScorerAppManager.java
+++ b/core/java/android/net/NetworkScorerAppManager.java
@@ -94,8 +94,9 @@
 
         PackageManager pm = context.getPackageManager();
         // Only apps installed under the primary user of the device can be scorers.
+        // TODO: http://b/23422763
         List<ResolveInfo> receivers =
-                pm.queryBroadcastReceivers(SCORE_INTENT, 0 /* flags */, UserHandle.USER_OWNER);
+                pm.queryBroadcastReceivers(SCORE_INTENT, 0 /* flags */, UserHandle.USER_SYSTEM);
         for (ResolveInfo receiver : receivers) {
             // This field is a misnomer, see android.content.pm.ResolveInfo#activityInfo
             final ActivityInfo receiverInfo = receiver.activityInfo;
diff --git a/core/java/android/os/BatteryStats.java b/core/java/android/os/BatteryStats.java
index 80169a9..4ad9d6d 100644
--- a/core/java/android/os/BatteryStats.java
+++ b/core/java/android/os/BatteryStats.java
@@ -169,7 +169,7 @@
     /**
      * Current version of checkin data format.
      */
-    static final String CHECKIN_VERSION = "14";
+    static final String CHECKIN_VERSION = "15";
 
     /**
      * Old version, we hit 9 and ran out of room, need to remove.
diff --git a/core/java/android/service/notification/Condition.java b/core/java/android/service/notification/Condition.java
index 80bdbf1..2c7bf65 100644
--- a/core/java/android/service/notification/Condition.java
+++ b/core/java/android/service/notification/Condition.java
@@ -16,7 +16,6 @@
 
 package android.service.notification;
 
-import android.annotation.SystemApi;
 import android.content.Context;
 import android.net.Uri;
 import android.os.Parcel;
@@ -26,10 +25,7 @@
 
 /**
  * Condition information from condition providers.
- *
- * @hide
  */
-@SystemApi
 public class Condition implements Parcelable {
 
     public static final String SCHEME = "condition";
diff --git a/core/java/android/service/notification/ConditionProviderService.java b/core/java/android/service/notification/ConditionProviderService.java
index 03ee726..2a8fb2c 100644
--- a/core/java/android/service/notification/ConditionProviderService.java
+++ b/core/java/android/service/notification/ConditionProviderService.java
@@ -17,9 +17,9 @@
 package android.service.notification;
 
 import android.annotation.SdkConstant;
-import android.annotation.SystemApi;
 import android.app.INotificationManager;
 import android.app.Service;
+import android.content.ComponentName;
 import android.content.Context;
 import android.content.Intent;
 import android.net.Uri;
@@ -33,7 +33,10 @@
  * A service that provides conditions about boolean state.
  * <p>To extend this class, you must declare the service in your manifest file with
  * the {@link android.Manifest.permission#BIND_CONDITION_PROVIDER_SERVICE} permission
- * and include an intent filter with the {@link #SERVICE_INTERFACE} action. For example:</p>
+ * and include an intent filter with the {@link #SERVICE_INTERFACE} action. If you want users to be
+ * able to create and update conditions for this service to monitor, include the
+ * {@link #META_DATA_RULE_TYPE}, {@link #META_DATA_DEFAULT_CONDITION_ID}, and
+ * {@link #META_DATA_CONFIGURATION_ACTIVITY} tags. For example:</p>
  * <pre>
  * &lt;service android:name=".MyConditionProvider"
  *          android:label="&#64;string/service_name"
@@ -41,11 +44,21 @@
  *     &lt;intent-filter>
  *         &lt;action android:name="android.service.notification.ConditionProviderService" />
  *     &lt;/intent-filter>
+ *     &lt;meta-data
+ *               android:name="android.service.zen.automatic.ruleType"
+ *               android:value="@string/my_condition_rule">
+ *           &lt;/meta-data>
+ *           &lt;meta-data
+ *               android:name="android.service.zen.automatic.defaultConditionId"
+ *               android:value="condition://com.my.package/mycondition">
+ *           &lt;/meta-data>
+ *           &lt;meta-data
+ *               android:name="android.service.zen.automatic.configurationActivity"
+ *               android:value="com.my.package/.MyConditionConfigurationActivity">
+ *           &lt;/meta-data>
  * &lt;/service></pre>
  *
- * @hide
  */
-@SystemApi
 public abstract class ConditionProviderService extends Service {
     private final String TAG = ConditionProviderService.class.getSimpleName()
             + "[" + getClass().getSimpleName() + "]";
@@ -62,9 +75,63 @@
     public static final String SERVICE_INTERFACE
             = "android.service.notification.ConditionProviderService";
 
+    /**
+     * The name of the {@code meta-data} tag containing a localized name of the type of zen rules
+     * provided by this service.
+     */
+    public static final String META_DATA_RULE_TYPE = "android.service.zen.automatic.ruleType";
+
+    /**
+     * The name of the {@code meta-data} tag containing a default Condition {@link Uri} that can
+     * be parsed by this service.
+     */
+    public static final String META_DATA_DEFAULT_CONDITION_ID =
+            "android.service.zen.automatic.defaultConditionId";
+
+    /**
+     * The name of the {@code meta-data} tag containing the {@link ComponentName} of an activity
+     * that allows users to configure the conditions provided by this service.
+     */
+    public static final String META_DATA_CONFIGURATION_ACTIVITY =
+            "android.service.zen.automatic.configurationActivity";
+
+    /**
+     * A condition {@link Uri} extra passed to {@link #META_DATA_CONFIGURATION_ACTIVITY}. If the
+     * condition Uri is modified by that activity, it must be included in the result Intent extras
+     * in order to be persisted.
+     */
+    public static final String EXTRA_CONDITION_ID = "android.content.automatic.conditionId";
+
+    /**
+     * A String rule name extra passed to {@link #META_DATA_CONFIGURATION_ACTIVITY}. This extra is
+     * informative only, and will be ignored if included in the result Intent extras.
+     */
+    public static final String EXTRA_RULE_NAME = "android.content.automatic.ruleName";
+
+    /**
+     * Called when this service is connected.
+     */
     abstract public void onConnected();
+
+    /**
+     * Called when the system wants to know the state of Conditions managed by this provider.
+     *
+     * Implementations should evaluate the state of all subscribed conditions, and provide updates
+     * by calling {@link #notifyCondition(Condition)} or {@link #notifyConditions(Condition...)}.
+     * @param relevance
+     */
     abstract public void onRequestConditions(int relevance);
+
+    /**
+     * Called by the system when there is a new {@link Condition} to be managed by this provider.
+     * @param conditionId the Uri describing the criteria of the condition.
+     */
     abstract public void onSubscribe(Uri conditionId);
+
+    /**
+     * Called by the system when a {@link Condition} has been deleted.
+     * @param conditionId the Uri describing the criteria of the deleted condition.
+     */
     abstract public void onUnsubscribe(Uri conditionId);
 
     private final INotificationManager getNotificationInterface() {
@@ -75,11 +142,19 @@
         return mNoMan;
     }
 
+    /**
+     * Informs the notification manager that the state of a Condition has changed.
+     * @param condition the condition that has changed.
+     */
     public final void notifyCondition(Condition condition) {
         if (condition == null) return;
         notifyConditions(new Condition[]{ condition });
     }
 
+    /**
+     * Informs the notification manager that the state of one or more Conditions has changed.
+     * @param conditions the changed conditions.
+     */
     public final void notifyConditions(Condition... conditions) {
         if (!isBound() || conditions == null) return;
         try {
diff --git a/core/java/android/text/Layout.java b/core/java/android/text/Layout.java
index cf937e1..f9387b3 100644
--- a/core/java/android/text/Layout.java
+++ b/core/java/android/text/Layout.java
@@ -1115,13 +1115,18 @@
      */
     public int getOffsetForHorizontal(int line, float horiz) {
         // TODO: use Paint.getOffsetForAdvance to avoid binary search
-        int max = getLineEnd(line) - 1;
-        int min = getLineStart(line);
+        final int lineEndOffset = getLineEnd(line);
+        final int max;
+        if (line == getLineCount() - 1) {
+            max = lineEndOffset;
+        } else {
+            max = mPaint.getTextRunCursor(mText, 0, mText.length(),
+                    isRtlCharAt(lineEndOffset) ? Paint.DIRECTION_RTL : Paint.DIRECTION_LTR,
+                    lineEndOffset, Paint.CURSOR_BEFORE);
+        }
+        final int min = getLineStart(line);
         Directions dirs = getLineDirections(line);
 
-        if (line == getLineCount() - 1)
-            max++;
-
         int best = min;
         float bestdist = Math.abs(getPrimaryHorizontal(best) - horiz);
 
diff --git a/core/java/android/view/ContextThemeWrapper.java b/core/java/android/view/ContextThemeWrapper.java
index ce50091..ea0873d 100644
--- a/core/java/android/view/ContextThemeWrapper.java
+++ b/core/java/android/view/ContextThemeWrapper.java
@@ -19,12 +19,13 @@
 import android.annotation.StyleRes;
 import android.content.Context;
 import android.content.ContextWrapper;
+import android.content.res.AssetManager;
 import android.content.res.Configuration;
 import android.content.res.Resources;
 
 /**
- * A ContextWrapper that allows you to modify the theme from what is in the 
- * wrapped context. 
+ * A context wrapper that allows you to modify or replace the theme of the
+ * wrapped context.
  */
 public class ContextThemeWrapper extends ContextWrapper {
     private int mThemeResource;
@@ -33,15 +34,42 @@
     private Configuration mOverrideConfiguration;
     private Resources mResources;
 
+    /**
+     * Creates a new context wrapper with no theme and no base context.
+     * <p>
+     * <stong>Note:</strong> A base context <strong>must</strong> be attached
+     * using {@link #attachBaseContext(Context)} before calling any other
+     * method on the newly constructed context wrapper.
+     */
     public ContextThemeWrapper() {
         super(null);
     }
 
+    /**
+     * Creates a new context wrapper with the specified theme.
+     * <p>
+     * The specified theme will be applied on top of the base context's theme.
+     * Any attributes not explicitly defined in the theme identified by
+     * <var>themeResId</var> will retain their original values.
+     *
+     * @param base the base context
+     * @param themeResId the resource ID of the theme to be applied on top of
+     *                   the base context's theme
+     */
     public ContextThemeWrapper(Context base, @StyleRes int themeResId) {
         super(base);
         mThemeResource = themeResId;
     }
 
+    /**
+     * Creates a new context wrapper with the specified theme.
+     * <p>
+     * Unlike {@link #ContextThemeWrapper(Context, int)}, the theme passed to
+     * this constructor will completely replace the base context's theme.
+     *
+     * @param base the base context
+     * @param theme the theme against which resources should be inflated
+     */
     public ContextThemeWrapper(Context base, Resources.Theme theme) {
         super(base);
         mTheme = theme;
@@ -60,11 +88,12 @@
      * information.
      *
      * <p>This method can only be called once, and must be called before any
-     * calls to {@link #getResources()} are made.
+     * calls to {@link #getResources()} or {@link #getAssets()} are made.
      */
     public void applyOverrideConfiguration(Configuration overrideConfiguration) {
         if (mResources != null) {
-            throw new IllegalStateException("getResources() has already been called");
+            throw new IllegalStateException(
+                    "getResources() or getAssets() has already been called");
         }
         if (mOverrideConfiguration != null) {
             throw new IllegalStateException("Override configuration has already been set");
@@ -73,20 +102,25 @@
     }
 
     @Override
-    public Resources getResources() {
-        if (mResources != null) {
-            return mResources;
-        }
-        if (mOverrideConfiguration == null) {
-            mResources = super.getResources();
-            return mResources;
-        } else {
-            Context resc = createConfigurationContext(mOverrideConfiguration);
-            mResources = resc.getResources();
-            return mResources;
-        }
+    public AssetManager getAssets() {
+        // Ensure we're returning assets with the correct configuration.
+        return getResources().getAssets();
     }
-    
+
+    @Override
+    public Resources getResources() {
+        if (mResources == null) {
+            if (mOverrideConfiguration == null) {
+                mResources = super.getResources();
+            } else {
+                final Context resContext = createConfigurationContext(mOverrideConfiguration);
+                mResources = resContext.getResources();
+            }
+        }
+
+        return mResources;
+    }
+
     @Override
     public void setTheme(int resid) {
         if (mThemeResource != resid) {
@@ -94,14 +128,15 @@
             initializeTheme();
         }
     }
-    
+
     /** @hide */
     @Override
     public int getThemeResId() {
         return mThemeResource;
     }
 
-    @Override public Resources.Theme getTheme() {
+    @Override
+    public Resources.Theme getTheme() {
         if (mTheme != null) {
             return mTheme;
         }
@@ -113,7 +148,8 @@
         return mTheme;
     }
 
-    @Override public Object getSystemService(String name) {
+    @Override
+    public Object getSystemService(String name) {
         if (LAYOUT_INFLATER_SERVICE.equals(name)) {
             if (mInflater == null) {
                 mInflater = LayoutInflater.from(getBaseContext()).cloneInContext(this);
@@ -122,27 +158,27 @@
         }
         return getBaseContext().getSystemService(name);
     }
-    
+
     /**
      * Called by {@link #setTheme} and {@link #getTheme} to apply a theme
-     * resource to the current Theme object.  Can override to change the
-     * default (simple) behavior.  This method will not be called in multiple
+     * resource to the current Theme object. May be overridden to change the
+     * default (simple) behavior. This method will not be called in multiple
      * threads simultaneously.
      *
-     * @param theme The Theme object being modified.
-     * @param resid The theme style resource being applied to <var>theme</var>.
-     * @param first Set to true if this is the first time a style is being
-     *              applied to <var>theme</var>.
+     * @param theme the theme being modified
+     * @param resId the style resource being applied to <var>theme</var>
+     * @param first {@code true} if this is the first time a style is being
+     *              applied to <var>theme</var>
      */
-    protected void onApplyThemeResource(Resources.Theme theme, int resid, boolean first) {
-        theme.applyStyle(resid, true);
+    protected void onApplyThemeResource(Resources.Theme theme, int resId, boolean first) {
+        theme.applyStyle(resId, true);
     }
 
     private void initializeTheme() {
         final boolean first = mTheme == null;
         if (first) {
             mTheme = getResources().newTheme();
-            Resources.Theme theme = getBaseContext().getTheme();
+            final Resources.Theme theme = getBaseContext().getTheme();
             if (theme != null) {
                 mTheme.setTo(theme);
             }
diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java
index b17f88f..16d9bf3 100644
--- a/core/java/android/view/View.java
+++ b/core/java/android/view/View.java
@@ -576,6 +576,53 @@
  * often used as a convenience to store data related to views in the views
  * themselves rather than by putting them in a separate structure.
  * </p>
+ * <p>
+ * Tags may be specified with character sequence values in layout XML as either
+ * a single tag using the {@link android.R.styleable#View_tag android:tag}
+ * attribute or multiple tags using the {@code &lt;tag&gt;} child element:
+ * <pre>
+ *     &ltView ...
+ *           android:tag="@string/mytag_value" /&gt;
+ *     &ltView ...&gt;
+ *         &lttag android:id="@+id/mytag"
+ *              android:value="@string/mytag_value" /&gt;
+ *     &lt/View>
+ * </pre>
+ * </p>
+ * <p>
+ * Tags may also be specified with arbitrary objects from code using
+ * {@link #setTag(Object)} or {@link #setTag(int, Object)}.
+ * </p>
+ *
+ * <a name="Themes"></a>
+ * <h3>Themes</h3>
+ * <p>
+ * By default, Views are created using the theme of the Context object supplied
+ * to their constructor; however, a different theme may be specified by using
+ * the {@link android.R.styleable#View_theme android:theme} attribute in layout
+ * XML or by passing a {@link ContextThemeWrapper} to the constructor from
+ * code.
+ * </p>
+ * <p>
+ * When the {@link android.R.styleable#View_theme android:theme} attribute is
+ * used in XML, the specified theme is applied on top of the inflation
+ * context's theme (see {@link LayoutInflater}) and used for the view itself as
+ * well as any child elements.
+ * </p>
+ * <p>
+ * In the following example, both views will be created using the Material dark
+ * color scheme; however, because an overlay theme is used which only defines a
+ * subset of attributes, the value of
+ * {@link android.R.styleable#Theme_colorAccent android:colorAccent} defined on
+ * the inflation context's theme (e.g. the Activity theme) will be preserved.
+ * <pre>
+ *     &ltLinearLayout
+ *             ...
+ *             android:theme="@android:theme/ThemeOverlay.Material.Dark"&gt;
+ *         &ltView ...&gt;
+ *     &lt/LinearLayout&gt;
+ * </pre>
+ * </p>
  *
  * <a name="Properties"></a>
  * <h3>Properties</h3>
@@ -699,6 +746,7 @@
  * @attr ref android.R.styleable#View_translationY
  * @attr ref android.R.styleable#View_translationZ
  * @attr ref android.R.styleable#View_visibility
+ * @attr ref android.R.styleable#View_theme
  *
  * @see android.view.ViewGroup
  */
@@ -753,6 +801,11 @@
     private static boolean sIgnoreMeasureCache = false;
 
     /**
+     * Ignore an optimization that skips unnecessary EXACTLY layout passes.
+     */
+    private static boolean sAlwaysRemeasureExactly = false;
+
+    /**
      * This view does not want keystrokes. Use with TAKES_FOCUS_MASK when
      * calling setFlags.
      */
@@ -3817,6 +3870,11 @@
             // specifically apps that use some popular open source libraries.
             sUseZeroUnspecifiedMeasureSpec = targetSdkVersion < M;
 
+            // Old versions of the platform would give different results from
+            // LinearLayout measurement passes using EXACTLY and non-EXACTLY
+            // modes, so we always need to run an additional EXACTLY pass.
+            sAlwaysRemeasureExactly = targetSdkVersion <= M;
+
             sCompatibilityDone = true;
         }
     }
@@ -18772,17 +18830,27 @@
         long key = (long) widthMeasureSpec << 32 | (long) heightMeasureSpec & 0xffffffffL;
         if (mMeasureCache == null) mMeasureCache = new LongSparseLongArray(2);
 
-        if ((mPrivateFlags & PFLAG_FORCE_LAYOUT) == PFLAG_FORCE_LAYOUT ||
-                widthMeasureSpec != mOldWidthMeasureSpec ||
-                heightMeasureSpec != mOldHeightMeasureSpec) {
+        final boolean forceLayout = (mPrivateFlags & PFLAG_FORCE_LAYOUT) == PFLAG_FORCE_LAYOUT;
 
+        // Optimize layout by avoiding an extra EXACTLY pass when the view is
+        // already measured as the correct size. In API 23 and below, this
+        // extra pass is required to make LinearLayout re-distribute weight.
+        final boolean specChanged = widthMeasureSpec != mOldWidthMeasureSpec
+                || heightMeasureSpec != mOldHeightMeasureSpec;
+        final boolean isSpecExactly = MeasureSpec.getMode(widthMeasureSpec) == MeasureSpec.EXACTLY
+                && MeasureSpec.getMode(heightMeasureSpec) == MeasureSpec.EXACTLY;
+        final boolean matchesSpecSize = getMeasuredWidth() == MeasureSpec.getSize(widthMeasureSpec)
+                && getMeasuredHeight() == MeasureSpec.getSize(heightMeasureSpec);
+        final boolean needsLayout = specChanged
+                && (sAlwaysRemeasureExactly || !isSpecExactly || !matchesSpecSize);
+
+        if (forceLayout || needsLayout) {
             // first clears the measured dimension flag
             mPrivateFlags &= ~PFLAG_MEASURED_DIMENSION_SET;
 
             resolveRtlPropertiesIfNeeded();
 
-            int cacheIndex = (mPrivateFlags & PFLAG_FORCE_LAYOUT) == PFLAG_FORCE_LAYOUT ? -1 :
-                    mMeasureCache.indexOfKey(key);
+            int cacheIndex = forceLayout ? -1 : mMeasureCache.indexOfKey(key);
             if (cacheIndex < 0 || sIgnoreMeasureCache) {
                 // measure ourselves, this should set the measured dimension flag back
                 onMeasure(widthMeasureSpec, heightMeasureSpec);
diff --git a/core/java/android/view/WindowManagerInternal.java b/core/java/android/view/WindowManagerInternal.java
index 7b4640b..a6d9932 100644
--- a/core/java/android/view/WindowManagerInternal.java
+++ b/core/java/android/view/WindowManagerInternal.java
@@ -120,6 +120,13 @@
     }
 
     /**
+      * An interface to be notified about hardware keyboard status.
+      */
+    public interface OnHardKeyboardStatusChangeListener {
+        public void onHardKeyboardStatusChange(boolean available);
+    }
+
+    /**
      * Request that the window manager call
      * {@link DisplayManagerInternal#performTraversalInTransactionFromWindowManager}
      * within a surface transaction at a later time.
@@ -231,4 +238,29 @@
      * @param listener The listener to register.
      */
     public abstract void registerAppTransitionListener(AppTransitionListener listener);
+
+    /**
+     * Retrieves a height of input method window.
+     */
+    public abstract int getInputMethodWindowVisibleHeight();
+
+    /**
+      * Saves last input method window for transition.
+      *
+      * Note that it is assumed that this method is called only by InputMethodManagerService.
+      */
+    public abstract void saveLastInputMethodWindowForTransition();
+
+    /**
+      * Returns true when the hardware keyboard is available.
+      */
+    public abstract boolean isHardKeyboardAvailable();
+
+    /**
+      * Sets the callback listener for hardware keyboard status changes.
+      *
+      * @param listener The listener to set.
+      */
+    public abstract void setOnHardKeyboardStatusChangeListener(
+        OnHardKeyboardStatusChangeListener listener);
 }
diff --git a/core/java/android/widget/AdapterView.java b/core/java/android/widget/AdapterView.java
index 6962711..0cc1b25 100644
--- a/core/java/android/widget/AdapterView.java
+++ b/core/java/android/widget/AdapterView.java
@@ -612,7 +612,7 @@
         View listItem = view;
         try {
             View v;
-            while (!(v = (View) listItem.getParent()).equals(this)) {
+            while ((v = (View) listItem.getParent()) != null && !v.equals(this)) {
                 listItem = v;
             }
         } catch (ClassCastException e) {
@@ -620,11 +620,13 @@
             return INVALID_POSITION;
         }
 
-        // Search the children for the list item
-        final int childCount = getChildCount();
-        for (int i = 0; i < childCount; i++) {
-            if (getChildAt(i).equals(listItem)) {
-                return mFirstPosition + i;
+        if (listItem != null) {
+            // Search the children for the list item
+            final int childCount = getChildCount();
+            for (int i = 0; i < childCount; i++) {
+                if (getChildAt(i).equals(listItem)) {
+                    return mFirstPosition + i;
+                }
             }
         }
 
diff --git a/core/java/android/widget/Editor.java b/core/java/android/widget/Editor.java
index 150b407..fddc40f 100644
--- a/core/java/android/widget/Editor.java
+++ b/core/java/android/widget/Editor.java
@@ -107,6 +107,7 @@
 import android.widget.TextView.Drawables;
 import android.widget.TextView.OnEditorActionListener;
 
+import com.android.internal.annotations.VisibleForTesting;
 import com.android.internal.util.ArrayUtils;
 import com.android.internal.util.GrowingArrayUtils;
 import com.android.internal.util.Preconditions;
@@ -2632,7 +2633,8 @@
         }
     }
 
-    private class SuggestionsPopupWindow extends PinnedPopupWindow implements OnItemClickListener {
+    @VisibleForTesting
+    public class SuggestionsPopupWindow extends PinnedPopupWindow implements OnItemClickListener {
         private static final int MAX_NUMBER_SUGGESTIONS = SuggestionSpan.SUGGESTIONS_MAX_SIZE;
         private static final int ADD_TO_DICTIONARY = -1;
         private static final int DELETE_TEXT = -2;
@@ -2798,6 +2800,11 @@
             return suggestionSpans;
         }
 
+        @VisibleForTesting
+        public ViewGroup getContentViewForTesting() {
+            return mContentView;
+        }
+
         @Override
         public void show() {
             if (!(mTextView.getText() instanceof Editable)) return;
@@ -5103,6 +5110,11 @@
         return 0 <= start && start <= end && end <= text.length();
     }
 
+    @VisibleForTesting
+    public SuggestionsPopupWindow getSuggestionsPopupWindowForTesting() {
+        return mSuggestionsPopupWindow;
+    }
+
     /**
      * An InputFilter that monitors text input to maintain undo history. It does not modify the
      * text being typed (and hence always returns null from the filter() method).
diff --git a/core/java/android/widget/ImageView.java b/core/java/android/widget/ImageView.java
index 20fe61d..b53af0c 100644
--- a/core/java/android/widget/ImageView.java
+++ b/core/java/android/widget/ImageView.java
@@ -72,6 +72,8 @@
  */
 @RemoteView
 public class ImageView extends View {
+    private static final String LOG_TAG = "ImageView";
+
     // settable by the client
     private Uri mUri;
     private int mResource = 0;
@@ -87,7 +89,7 @@
     private boolean mHasColorFilter = false;
     private Xfermode mXfermode;
     private int mAlpha = 255;
-    private int mViewAlphaScale = 256;
+    private final int mViewAlphaScale = 256;
     private boolean mColorMod = false;
 
     private Drawable mDrawable = null;
@@ -105,8 +107,8 @@
     private Matrix mDrawMatrix = null;
 
     // Avoid allocations...
-    private RectF mTempSrc = new RectF();
-    private RectF mTempDst = new RectF();
+    private final RectF mTempSrc = new RectF();
+    private final RectF mTempDst = new RectF();
 
     private boolean mCropToPadding;
 
@@ -116,6 +118,9 @@
     // AdjustViewBounds behavior will be in compatibility mode for older apps.
     private boolean mAdjustViewBoundsCompat = false;
 
+    /** Whether to pass Resources when creating the source from a stream. */
+    private boolean mUseCorrectStreamDensity;
+
     private static final ScaleType[] sScaleTypeArray = {
         ScaleType.MATRIX,
         ScaleType.FIT_XY,
@@ -147,30 +152,21 @@
         initImageView();
 
         final TypedArray a = context.obtainStyledAttributes(
-                attrs, com.android.internal.R.styleable.ImageView, defStyleAttr, defStyleRes);
+                attrs, R.styleable.ImageView, defStyleAttr, defStyleRes);
 
-        Drawable d = a.getDrawable(com.android.internal.R.styleable.ImageView_src);
+        final Drawable d = a.getDrawable(R.styleable.ImageView_src);
         if (d != null) {
             setImageDrawable(d);
         }
 
-        mBaselineAlignBottom = a.getBoolean(
-                com.android.internal.R.styleable.ImageView_baselineAlignBottom, false);
+        mBaselineAlignBottom = a.getBoolean(R.styleable.ImageView_baselineAlignBottom, false);
+        mBaseline = a.getDimensionPixelSize(R.styleable.ImageView_baseline, -1);
 
-        mBaseline = a.getDimensionPixelSize(
-                com.android.internal.R.styleable.ImageView_baseline, -1);
+        setAdjustViewBounds(a.getBoolean(R.styleable.ImageView_adjustViewBounds, false));
+        setMaxWidth(a.getDimensionPixelSize(R.styleable.ImageView_maxWidth, Integer.MAX_VALUE));
+        setMaxHeight(a.getDimensionPixelSize(R.styleable.ImageView_maxHeight, Integer.MAX_VALUE));
 
-        setAdjustViewBounds(
-            a.getBoolean(com.android.internal.R.styleable.ImageView_adjustViewBounds,
-            false));
-
-        setMaxWidth(a.getDimensionPixelSize(
-                com.android.internal.R.styleable.ImageView_maxWidth, Integer.MAX_VALUE));
-        
-        setMaxHeight(a.getDimensionPixelSize(
-                com.android.internal.R.styleable.ImageView_maxHeight, Integer.MAX_VALUE));
-        
-        final int index = a.getInt(com.android.internal.R.styleable.ImageView_scaleType, -1);
+        final int index = a.getInt(R.styleable.ImageView_scaleType, -1);
         if (index >= 0) {
             setScaleType(sScaleTypeArray[index]);
         }
@@ -193,24 +189,26 @@
 
         applyImageTint();
 
-        final int alpha = a.getInt(com.android.internal.R.styleable.ImageView_drawableAlpha, 255);
+        final int alpha = a.getInt(R.styleable.ImageView_drawableAlpha, 255);
         if (alpha != 255) {
-            setAlpha(alpha);
+            setImageAlpha(alpha);
         }
 
         mCropToPadding = a.getBoolean(
-                com.android.internal.R.styleable.ImageView_cropToPadding, false);
-        
+                R.styleable.ImageView_cropToPadding, false);
+
         a.recycle();
 
         //need inflate syntax/reader for matrix
     }
 
     private void initImageView() {
-        mMatrix     = new Matrix();
-        mScaleType  = ScaleType.FIT_CENTER;
-        mAdjustViewBoundsCompat = mContext.getApplicationInfo().targetSdkVersion <=
-                Build.VERSION_CODES.JELLY_BEAN_MR1;
+        mMatrix = new Matrix();
+        mScaleType = ScaleType.FIT_CENTER;
+
+        final int targetSdkVersion = mContext.getApplicationInfo().targetSdkVersion;
+        mAdjustViewBoundsCompat = targetSdkVersion <= Build.VERSION_CODES.JELLY_BEAN_MR1;
+        mUseCorrectStreamDensity = targetSdkVersion > Build.VERSION_CODES.M;
     }
 
     @Override
@@ -258,7 +256,8 @@
     @Override
     public void onPopulateAccessibilityEventInternal(AccessibilityEvent event) {
         super.onPopulateAccessibilityEventInternal(event);
-        CharSequence contentDescription = getContentDescription();
+
+        final CharSequence contentDescription = getContentDescription();
         if (!TextUtils.isEmpty(contentDescription)) {
             event.getText().add(contentDescription);
         }
@@ -269,7 +268,7 @@
      * to preserve the aspect ratio of its drawable
      *
      * @return whether to adjust the bounds of this view
-     * to presrve the original aspect ratio of the drawable
+     * to preserve the original aspect ratio of the drawable
      *
      * @see #setAdjustViewBounds(boolean)
      *
@@ -291,7 +290,7 @@
      *
      * @param adjustViewBounds Whether to adjust the bounds of this view
      * to preserve the original aspect ratio of the drawable.
-     * 
+     *
      * @see #getAdjustViewBounds()
      *
      * @attr ref android.R.styleable#ImageView_adjustViewBounds
@@ -323,14 +322,14 @@
      * of 100 x 100 while preserving the original aspect ratio, do the following: 1) set
      * adjustViewBounds to true 2) set maxWidth and maxHeight to 100 3) set the height and width
      * layout params to WRAP_CONTENT.
-     * 
+     *
      * <p>
      * Note that this view could be still smaller than 100 x 100 using this approach if the original
      * image is small. To set an image to a fixed size, specify that size in the layout params and
      * then use {@link #setScaleType(android.widget.ImageView.ScaleType)} to determine how to fit
      * the image within the bounds.
      * </p>
-     * 
+     *
      * @param maxWidth maximum width for this view
      *
      * @see #getMaxWidth()
@@ -361,14 +360,14 @@
      * maximum of 100 x 100 while preserving the original aspect ratio, do the following: 1) set
      * adjustViewBounds to true 2) set maxWidth and maxHeight to 100 3) set the height and width
      * layout params to WRAP_CONTENT.
-     * 
+     *
      * <p>
      * Note that this view could be still smaller than 100 x 100 using this approach if the original
      * image is small. To set an image to a fixed size, specify that size in the layout params and
      * then use {@link #setScaleType(android.widget.ImageView.ScaleType)} to determine how to fit
      * the image within the bounds.
      * </p>
-     * 
+     *
      * @param maxHeight maximum height for this view
      *
      * @see #getMaxHeight()
@@ -436,9 +435,7 @@
      */
     @android.view.RemotableViewMethod
     public void setImageURI(@Nullable Uri uri) {
-        if (mResource != 0 ||
-                (mUri != uri &&
-                 (uri == null || mUri == null || !uri.equals(mUri)))) {
+        if (mResource != 0 || (mUri != uri && (uri == null || mUri == null || !uri.equals(mUri)))) {
             updateDrawable(null);
             mResource = 0;
             mUri = uri;
@@ -457,7 +454,7 @@
 
     /**
      * Sets a drawable as the content of this ImageView.
-     * 
+     *
      * @param drawable the Drawable to set, or {@code null} to clear the
      *                 content
      */
@@ -577,7 +574,7 @@
 
     /**
      * Sets a Bitmap as the content of this ImageView.
-     * 
+     *
      * @param bm The bitmap to set
      */
     @android.view.RemotableViewMethod
@@ -609,7 +606,7 @@
     }
 
     /**
-     * Sets the image level, when it is constructed from a 
+     * Sets the image level, when it is constructed from a
      * {@link android.graphics.drawable.LevelListDrawable}.
      *
      * @param level The new level for the image.
@@ -675,7 +672,7 @@
          * From XML, use this syntax: <code>android:scaleType="centerInside"</code>.
          */
         CENTER_INSIDE (7);
-        
+
         ScaleType(int ni) {
             nativeInt = ni;
         }
@@ -685,9 +682,9 @@
     /**
      * Controls how the image should be resized or moved to match the size
      * of this ImageView.
-     * 
+     *
      * @param scaleType The desired scaling mode.
-     * 
+     *
      * @attr ref android.R.styleable#ImageView_scaleType
      */
     public void setScaleType(ScaleType scaleType) {
@@ -698,13 +695,13 @@
         if (mScaleType != scaleType) {
             mScaleType = scaleType;
 
-            setWillNotCacheDrawing(mScaleType == ScaleType.CENTER);            
+            setWillNotCacheDrawing(mScaleType == ScaleType.CENTER);
 
             requestLayout();
             invalidate();
         }
     }
-    
+
     /**
      * Return the current scale type in use by this ImageView.
      *
@@ -734,7 +731,7 @@
      * Adds a transformation {@link Matrix} that is applied
      * to the view's drawable when it is drawn.  Allows custom scaling,
      * translation, and perspective distortion.
-     * 
+     *
      * @param matrix the transformation parameters in matrix form
      */
     public void setImageMatrix(Matrix matrix) {
@@ -787,8 +784,8 @@
             return;
         }
 
-        Resources rsrc = getResources();
-        if (rsrc == null) {
+        final Resources res = getResources();
+        if (res == null) {
             return;
         }
 
@@ -798,12 +795,12 @@
             try {
                 d = mContext.getDrawable(mResource);
             } catch (Exception e) {
-                Log.w("ImageView", "Unable to find resource: " + mResource, e);
+                Log.w(LOG_TAG, "Unable to find resource: " + mResource, e);
                 // Don't try again.
                 mUri = null;
             }
         } else if (mUri != null) {
-            String scheme = mUri.getScheme();
+            final String scheme = mUri.getScheme();
             if (ContentResolver.SCHEME_ANDROID_RESOURCE.equals(scheme)) {
                 try {
                     // Load drawable through Resources, to get the source density information
@@ -811,31 +808,32 @@
                             mContext.getContentResolver().getResourceId(mUri);
                     d = r.r.getDrawable(r.id, mContext.getTheme());
                 } catch (Exception e) {
-                    Log.w("ImageView", "Unable to open content: " + mUri, e);
+                    Log.w(LOG_TAG, "Unable to open content: " + mUri, e);
                 }
             } else if (ContentResolver.SCHEME_CONTENT.equals(scheme)
                     || ContentResolver.SCHEME_FILE.equals(scheme)) {
                 InputStream stream = null;
                 try {
                     stream = mContext.getContentResolver().openInputStream(mUri);
-                    d = Drawable.createFromStream(stream, null);
+                    d = Drawable.createFromResourceStream(
+                            mUseCorrectStreamDensity ? res : null, null, stream, null);
                 } catch (Exception e) {
-                    Log.w("ImageView", "Unable to open content: " + mUri, e);
+                    Log.w(LOG_TAG, "Unable to open content: " + mUri, e);
                 } finally {
                     if (stream != null) {
                         try {
                             stream.close();
                         } catch (IOException e) {
-                            Log.w("ImageView", "Unable to close content: " + mUri, e);
+                            Log.w(LOG_TAG, "Unable to close content: " + mUri, e);
                         }
                     }
                 }
-        } else {
+            } else {
                 d = Drawable.createFromPath(mUri.toString());
             }
-    
+
             if (d == null) {
-                System.out.println("resolveUri failed on bad bitmap uri: " + mUri);
+                Log.w(LOG_TAG, "resolveUri failed on bad bitmap uri: " + mUri);
                 // Don't try again.
                 mUri = null;
             }
@@ -890,7 +888,7 @@
     }
 
     private void resizeFromDrawable() {
-        Drawable d = mDrawable;
+        final Drawable d = mDrawable;
         if (d != null) {
             int w = d.getIntrinsicWidth();
             if (w < 0) w = mDrawableWidth;
@@ -923,23 +921,23 @@
     private static Matrix.ScaleToFit scaleTypeToScaleToFit(ScaleType st)  {
         // ScaleToFit enum to their corresponding Matrix.ScaleToFit values
         return sS2FArray[st.nativeInt - 1];
-    }    
+    }
 
     @Override
     protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
         resolveUri();
         int w;
         int h;
-        
+
         // Desired aspect ratio of the view's contents (not including padding)
         float desiredAspect = 0.0f;
-        
+
         // We are allowed to change the view's width
         boolean resizeWidth = false;
-        
+
         // We are allowed to change the view's height
         boolean resizeHeight = false;
-        
+
         final int widthSpecMode = MeasureSpec.getMode(widthMeasureSpec);
         final int heightSpecMode = MeasureSpec.getMode(heightMeasureSpec);
 
@@ -959,15 +957,15 @@
             if (mAdjustViewBounds) {
                 resizeWidth = widthSpecMode != MeasureSpec.EXACTLY;
                 resizeHeight = heightSpecMode != MeasureSpec.EXACTLY;
-                
+
                 desiredAspect = (float) w / (float) h;
             }
         }
-        
-        int pleft = mPaddingLeft;
-        int pright = mPaddingRight;
-        int ptop = mPaddingTop;
-        int pbottom = mPaddingBottom;
+
+        final int pleft = mPaddingLeft;
+        final int pright = mPaddingRight;
+        final int ptop = mPaddingTop;
+        final int pbottom = mPaddingBottom;
 
         int widthSize;
         int heightSize;
@@ -975,7 +973,7 @@
         if (resizeWidth || resizeHeight) {
             /* If we get here, it means we want to resize to match the
                 drawables aspect ratio, and we have the freedom to change at
-                least one dimension. 
+                least one dimension.
             */
 
             // Get the max possible width given our constraints
@@ -986,13 +984,13 @@
 
             if (desiredAspect != 0.0f) {
                 // See what our actual aspect ratio is
-                float actualAspect = (float)(widthSize - pleft - pright) /
+                final float actualAspect = (float)(widthSize - pleft - pright) /
                                         (heightSize - ptop - pbottom);
-                
+
                 if (Math.abs(actualAspect - desiredAspect) > 0.0000001) {
-                    
+
                     boolean done = false;
-                    
+
                     // Try adjusting width to be proportional to height
                     if (resizeWidth) {
                         int newWidth = (int)(desiredAspect * (heightSize - ptop - pbottom)) +
@@ -1006,9 +1004,9 @@
                         if (newWidth <= widthSize) {
                             widthSize = newWidth;
                             done = true;
-                        } 
+                        }
                     }
-                    
+
                     // Try adjusting height to be proportional to width
                     if (!done && resizeHeight) {
                         int newHeight = (int)((widthSize - pleft - pright) / desiredAspect) +
@@ -1033,7 +1031,7 @@
             */
             w += pleft + pright;
             h += ptop + pbottom;
-                
+
             w = Math.max(w, getSuggestedMinimumWidth());
             h = Math.max(h, getSuggestedMinimumHeight());
 
@@ -1047,8 +1045,8 @@
     private int resolveAdjustedSize(int desiredSize, int maxSize,
                                    int measureSpec) {
         int result = desiredSize;
-        int specMode = MeasureSpec.getMode(measureSpec);
-        int specSize =  MeasureSpec.getSize(measureSpec);
+        final int specMode = MeasureSpec.getMode(measureSpec);
+        final int specSize =  MeasureSpec.getSize(measureSpec);
         switch (specMode) {
             case MeasureSpec.UNSPECIFIED:
                 /* Parent says we can be as big as we want. Just don't be larger
@@ -1057,8 +1055,8 @@
                 result = Math.min(desiredSize, maxSize);
                 break;
             case MeasureSpec.AT_MOST:
-                // Parent says we can be as big as we want, up to specSize. 
-                // Don't be larger than specSize, and don't be larger than 
+                // Parent says we can be as big as we want, up to specSize.
+                // Don't be larger than specSize, and don't be larger than
                 // the max size imposed on ourselves.
                 result = Math.min(Math.min(desiredSize, specSize), maxSize);
                 break;
@@ -1072,7 +1070,7 @@
 
     @Override
     protected boolean setFrame(int l, int t, int r, int b) {
-        boolean changed = super.setFrame(l, t, r, b);
+        final boolean changed = super.setFrame(l, t, r, b);
         mHaveFrame = true;
         configureBounds();
         return changed;
@@ -1083,14 +1081,14 @@
             return;
         }
 
-        int dwidth = mDrawableWidth;
-        int dheight = mDrawableHeight;
+        final int dwidth = mDrawableWidth;
+        final int dheight = mDrawableHeight;
 
-        int vwidth = getWidth() - mPaddingLeft - mPaddingRight;
-        int vheight = getHeight() - mPaddingTop - mPaddingBottom;
+        final int vwidth = getWidth() - mPaddingLeft - mPaddingRight;
+        final int vheight = getHeight() - mPaddingTop - mPaddingBottom;
 
-        boolean fits = (dwidth < 0 || vwidth == dwidth) &&
-                       (dheight < 0 || vheight == dheight);
+        final boolean fits = (dwidth < 0 || vwidth == dwidth)
+                && (dheight < 0 || vheight == dheight);
 
         if (dwidth <= 0 || dheight <= 0 || ScaleType.FIT_XY == mScaleType) {
             /* If the drawable has no intrinsic size, or we're told to
@@ -1125,7 +1123,7 @@
                 float dx = 0, dy = 0;
 
                 if (dwidth * vheight > vwidth * dheight) {
-                    scale = (float) vheight / (float) dheight; 
+                    scale = (float) vheight / (float) dheight;
                     dx = (vwidth - dwidth * scale) * 0.5f;
                 } else {
                     scale = (float) vwidth / (float) dwidth;
@@ -1139,14 +1137,14 @@
                 float scale;
                 float dx;
                 float dy;
-                
+
                 if (dwidth <= vwidth && dheight <= vheight) {
                     scale = 1.0f;
                 } else {
                     scale = Math.min((float) vwidth / (float) dwidth,
                             (float) vheight / (float) dheight);
                 }
-                
+
                 dx = Math.round((vwidth - dwidth * scale) * 0.5f);
                 dy = Math.round((vheight - dheight * scale) * 0.5f);
 
@@ -1156,7 +1154,7 @@
                 // Generate the required transform.
                 mTempSrc.set(0, 0, dwidth, dheight);
                 mTempDst.set(0, 0, vwidth, vheight);
-                
+
                 mDrawMatrix = mMatrix;
                 mDrawMatrix.setRectToRect(mTempSrc, mTempDst, scaleTypeToScaleToFit(mScaleType));
             }
@@ -1166,7 +1164,8 @@
     @Override
     protected void drawableStateChanged() {
         super.drawableStateChanged();
-        Drawable d = mDrawable;
+
+        final Drawable d = mDrawable;
         if (d != null && d.isStateful()) {
             d.setState(getDrawableState());
         }
@@ -1213,9 +1212,9 @@
         if (mDrawMatrix == null && mPaddingTop == 0 && mPaddingLeft == 0) {
             mDrawable.draw(canvas);
         } else {
-            int saveCount = canvas.getSaveCount();
+            final int saveCount = canvas.getSaveCount();
             canvas.save();
-            
+
             if (mCropToPadding) {
                 final int scrollX = mScrollX;
                 final int scrollY = mScrollY;
@@ -1223,7 +1222,7 @@
                         scrollX + mRight - mLeft - mPaddingRight,
                         scrollY + mBottom - mTop - mPaddingBottom);
             }
-            
+
             canvas.translate(mPaddingLeft, mPaddingTop);
 
             if (mDrawMatrix != null) {
@@ -1258,7 +1257,7 @@
      *
      * @param baseline The baseline to use, or -1 if none is to be provided.
      *
-     * @see #setBaseline(int) 
+     * @see #setBaseline(int)
      * @attr ref android.R.styleable#ImageView_baseline
      */
     public void setBaseline(int baseline) {
@@ -1295,11 +1294,11 @@
 
     /**
      * Set a tinting option for the image.
-     * 
+     *
      * @param color Color tint to apply.
      * @param mode How to apply the color.  The standard mode is
      * {@link PorterDuff.Mode#SRC_ATOP}
-     * 
+     *
      * @attr ref android.R.styleable#ImageView_tint
      */
     public final void setColorFilter(int color, PorterDuff.Mode mode) {
diff --git a/core/java/android/widget/LinearLayout.java b/core/java/android/widget/LinearLayout.java
index b5e08ca..ad939be 100644
--- a/core/java/android/widget/LinearLayout.java
+++ b/core/java/android/widget/LinearLayout.java
@@ -25,6 +25,7 @@
 import android.content.res.TypedArray;
 import android.graphics.Canvas;
 import android.graphics.drawable.Drawable;
+import android.os.Build;
 import android.util.AttributeSet;
 import android.view.Gravity;
 import android.view.View;
@@ -99,6 +100,13 @@
     public static final int SHOW_DIVIDER_END = 4;
 
     /**
+     * Compatibility check. Old versions of the platform would give different
+     * results from measurement passes using EXACTLY and non-EXACTLY modes,
+     * even when the resulting size was the same.
+     */
+    private final boolean mAllowInconsistentMeasurement;
+
+    /**
      * Whether the children of this layout are baseline aligned.  Only applicable
      * if {@link #mOrientation} is horizontal.
      */
@@ -231,6 +239,9 @@
         mShowDividers = a.getInt(R.styleable.LinearLayout_showDividers, SHOW_DIVIDER_NONE);
         mDividerPadding = a.getDimensionPixelSize(R.styleable.LinearLayout_dividerPadding, 0);
 
+        final int version = context.getApplicationInfo().targetSdkVersion;
+        mAllowInconsistentMeasurement = version <= Build.VERSION_CODES.M;
+
         a.recycle();
     }
 
@@ -699,6 +710,7 @@
         final boolean useLargestChild = mUseLargestChild;
 
         int largestChildHeight = Integer.MIN_VALUE;
+        int consumedExcessSpace = 0;
 
         // See how tall everyone is. Also remember max width.
         for (int i = 0; i < count; ++i) {
@@ -718,26 +730,25 @@
                 mTotalLength += mDividerHeight;
             }
 
-            LinearLayout.LayoutParams lp = (LinearLayout.LayoutParams) child.getLayoutParams();
+            final LayoutParams lp = (LayoutParams) child.getLayoutParams();
 
             totalWeight += lp.weight;
-            
-            if (heightMode == MeasureSpec.EXACTLY && lp.height == 0 && lp.weight > 0) {
-                // Optimization: don't bother measuring children who are going to use
-                // leftover space. These views will get measured again down below if
-                // there is any leftover space.
+
+            final boolean useExcessSpace = lp.height == 0 && lp.weight > 0;
+            if (heightMode == MeasureSpec.EXACTLY && useExcessSpace) {
+                // Optimization: don't bother measuring children who are only
+                // laid out using excess space. These views will get measured
+                // later if we have space to distribute.
                 final int totalLength = mTotalLength;
                 mTotalLength = Math.max(totalLength, totalLength + lp.topMargin + lp.bottomMargin);
                 skippedMeasure = true;
             } else {
-                int oldHeight = Integer.MIN_VALUE;
-
-                if (lp.height == 0 && lp.weight > 0) {
-                    // heightMode is either UNSPECIFIED or AT_MOST, and this
-                    // child wanted to stretch to fill available space.
-                    // Translate that to WRAP_CONTENT so that it does not end up
-                    // with a height of 0
-                    oldHeight = 0;
+                if (useExcessSpace) {
+                    // The heightMode is either UNSPECIFIED or AT_MOST, and
+                    // this child is only laid out using excess space. Measure
+                    // using WRAP_CONTENT so that we can find out the view's
+                    // optimal height. We'll restore the original height of 0
+                    // after measurement.
                     lp.height = LayoutParams.WRAP_CONTENT;
                 }
 
@@ -745,15 +756,19 @@
                 // previous children have given a weight, then we allow it to
                 // use all available space (and we will shrink things later
                 // if needed).
-                measureChildBeforeLayout(
-                       child, i, widthMeasureSpec, 0, heightMeasureSpec,
-                       totalWeight == 0 ? mTotalLength : 0);
-
-                if (oldHeight != Integer.MIN_VALUE) {
-                   lp.height = oldHeight;
-                }
+                final int usedHeight = totalWeight == 0 ? mTotalLength : 0;
+                measureChildBeforeLayout(child, i, widthMeasureSpec, 0,
+                        heightMeasureSpec, usedHeight);
 
                 final int childHeight = child.getMeasuredHeight();
+                if (useExcessSpace) {
+                    // Restore the original height and record how much space
+                    // we've allocated to excess-only children so that we can
+                    // match the behavior of EXACTLY measurement.
+                    lp.height = 0;
+                    consumedExcessSpace += childHeight;
+                }
+
                 final int totalLength = mTotalLength;
                 mTotalLength = Math.max(totalLength, totalLength + childHeight + lp.topMargin +
                        lp.bottomMargin + getNextLocationOffset(child));
@@ -857,52 +872,42 @@
         // Either expand children with weight to take up available space or
         // shrink them if they extend beyond our current bounds. If we skipped
         // measurement on any children, we need to measure them now.
-        int delta = heightSize - mTotalLength;
+        final int delta = heightSize - mTotalLength
+                + (mAllowInconsistentMeasurement ? 0 : consumedExcessSpace);
         if (skippedMeasure || delta != 0 && totalWeight > 0.0f) {
-            float weightSum = mWeightSum > 0.0f ? mWeightSum : totalWeight;
+            final float weightSum = mWeightSum > 0.0f ? mWeightSum : totalWeight;
 
             mTotalLength = 0;
 
             for (int i = 0; i < count; ++i) {
                 final View child = getVirtualChildAt(i);
-                
-                if (child.getVisibility() == View.GONE) {
+                if (child == null || child.getVisibility() == View.GONE) {
                     continue;
                 }
-                
-                LinearLayout.LayoutParams lp = (LinearLayout.LayoutParams) child.getLayoutParams();
-                
-                float childExtra = lp.weight;
+
+                final LayoutParams lp = (LayoutParams) child.getLayoutParams();
+                final float childExtra = lp.weight;
                 if (childExtra > 0) {
-                    // Child said it could absorb extra space -- give him his share
-                    int share = (int) (childExtra * delta / weightSum);
-                    weightSum -= childExtra;
-                    delta -= share;
-
-                    final int childWidthMeasureSpec = getChildMeasureSpec(widthMeasureSpec,
-                            mPaddingLeft + mPaddingRight +
-                                    lp.leftMargin + lp.rightMargin, lp.width);
-
-                    // TODO: Use a field like lp.isMeasured to figure out if this
-                    // child has been previously measured
-                    if ((lp.height != 0) || (heightMode != MeasureSpec.EXACTLY)) {
-                        // child was measured once already above...
-                        // base new measurement on stored values
-                        int childHeight = child.getMeasuredHeight() + share;
-                        if (childHeight < 0) {
-                            childHeight = 0;
-                        }
-                        
-                        child.measure(childWidthMeasureSpec,
-                                MeasureSpec.makeMeasureSpec(childHeight, MeasureSpec.EXACTLY));
+                    final int share = (int) (childExtra * delta / weightSum);
+                    final int childHeight;
+                    if (lp.height == 0 && (!mAllowInconsistentMeasurement
+                            || heightMode == MeasureSpec.EXACTLY)) {
+                        // This child needs to be laid out from scratch using
+                        // only its share of excess space.
+                        childHeight = share;
                     } else {
-                        // child was skipped in the loop above.
-                        // Measure for this first time here      
-                        child.measure(childWidthMeasureSpec,
-                                MeasureSpec.makeMeasureSpec(share > 0 ? share : 0,
-                                        MeasureSpec.EXACTLY));
+                        // This child had some intrinsic height to which we
+                        // need to add its share of excess space.
+                        childHeight = child.getMeasuredHeight() + share;
                     }
 
+                    final int childHeightMeasureSpec = MeasureSpec.makeMeasureSpec(
+                            Math.max(0, childHeight), MeasureSpec.EXACTLY);
+                    final int childWidthMeasureSpec = getChildMeasureSpec(widthMeasureSpec,
+                            mPaddingLeft + mPaddingRight + lp.leftMargin + lp.rightMargin,
+                            lp.width);
+                    child.measure(childWidthMeasureSpec, childHeightMeasureSpec);
+
                     // Child may now not fit in vertical dimension.
                     childState = combineMeasuredStates(childState, child.getMeasuredState()
                             & (MEASURED_STATE_MASK>>MEASURED_HEIGHT_STATE_SHIFT));
@@ -1043,6 +1048,7 @@
         final boolean isExactly = widthMode == MeasureSpec.EXACTLY;
 
         int largestChildWidth = Integer.MIN_VALUE;
+        int usedExcessSpace = 0;
 
         // See how wide everyone is. Also remember max height.
         for (int i = 0; i < count; ++i) {
@@ -1062,15 +1068,15 @@
                 mTotalLength += mDividerWidth;
             }
 
-            final LinearLayout.LayoutParams lp = (LinearLayout.LayoutParams)
-                    child.getLayoutParams();
+            final LayoutParams lp = (LayoutParams) child.getLayoutParams();
 
             totalWeight += lp.weight;
-            
-            if (widthMode == MeasureSpec.EXACTLY && lp.width == 0 && lp.weight > 0) {
-                // Optimization: don't bother measuring children who are going to use
-                // leftover space. These views will get measured again down below if
-                // there is any leftover space.
+
+            final boolean useExcessSpace = lp.width == 0 && lp.weight > 0;
+            if (widthMode == MeasureSpec.EXACTLY && useExcessSpace) {
+                // Optimization: don't bother measuring children who are only
+                // laid out using excess space. These views will get measured
+                // later if we have space to distribute.
                 if (isExactly) {
                     mTotalLength += lp.leftMargin + lp.rightMargin;
                 } else {
@@ -1094,14 +1100,12 @@
                     skippedMeasure = true;
                 }
             } else {
-                int oldWidth = Integer.MIN_VALUE;
-
-                if (lp.width == 0 && lp.weight > 0) {
-                    // widthMode is either UNSPECIFIED or AT_MOST, and this
-                    // child
-                    // wanted to stretch to fill available space. Translate that to
-                    // WRAP_CONTENT so that it does not end up with a width of 0
-                    oldWidth = 0;
+                if (useExcessSpace) {
+                    // The widthMode is either UNSPECIFIED or AT_MOST, and
+                    // this child is only laid out using excess space. Measure
+                    // using WRAP_CONTENT so that we can find out the view's
+                    // optimal width. We'll restore the original width of 0
+                    // after measurement.
                     lp.width = LayoutParams.WRAP_CONTENT;
                 }
 
@@ -1109,22 +1113,26 @@
                 // previous children have given a weight, then we allow it to
                 // use all available space (and we will shrink things later
                 // if needed).
-                measureChildBeforeLayout(child, i, widthMeasureSpec,
-                        totalWeight == 0 ? mTotalLength : 0,
+                final int usedWidth = totalWeight == 0 ? mTotalLength : 0;
+                measureChildBeforeLayout(child, i, widthMeasureSpec, usedWidth,
                         heightMeasureSpec, 0);
 
-                if (oldWidth != Integer.MIN_VALUE) {
-                    lp.width = oldWidth;
+                final int childWidth = child.getMeasuredWidth();
+                if (useExcessSpace) {
+                    // Restore the original width and record how much space
+                    // we've allocated to excess-only children so that we can
+                    // match the behavior of EXACTLY measurement.
+                    lp.width = 0;
+                    usedExcessSpace += childWidth;
                 }
 
-                final int childWidth = child.getMeasuredWidth();
                 if (isExactly) {
-                    mTotalLength += childWidth + lp.leftMargin + lp.rightMargin +
-                            getNextLocationOffset(child);
+                    mTotalLength += childWidth + lp.leftMargin + lp.rightMargin
+                            + getNextLocationOffset(child);
                 } else {
                     final int totalLength = mTotalLength;
-                    mTotalLength = Math.max(totalLength, totalLength + childWidth + lp.leftMargin +
-                           lp.rightMargin + getNextLocationOffset(child));
+                    mTotalLength = Math.max(totalLength, totalLength + childWidth + lp.leftMargin
+                            + lp.rightMargin + getNextLocationOffset(child));
                 }
 
                 if (useLargestChild) {
@@ -1242,9 +1250,10 @@
         // Either expand children with weight to take up available space or
         // shrink them if they extend beyond our current bounds. If we skipped
         // measurement on any children, we need to measure them now.
-        int delta = widthSize - mTotalLength;
+        final int delta = widthSize - mTotalLength
+                + (mAllowInconsistentMeasurement ? 0 : usedExcessSpace);
         if (skippedMeasure || delta != 0 && totalWeight > 0.0f) {
-            float weightSum = mWeightSum > 0.0f ? mWeightSum : totalWeight;
+            final float weightSum = mWeightSum > 0.0f ? mWeightSum : totalWeight;
 
             maxAscent[0] = maxAscent[1] = maxAscent[2] = maxAscent[3] = -1;
             maxDescent[0] = maxDescent[1] = maxDescent[2] = maxDescent[3] = -1;
@@ -1254,45 +1263,32 @@
 
             for (int i = 0; i < count; ++i) {
                 final View child = getVirtualChildAt(i);
-
                 if (child == null || child.getVisibility() == View.GONE) {
                     continue;
                 }
-                
-                final LinearLayout.LayoutParams lp =
-                        (LinearLayout.LayoutParams) child.getLayoutParams();
 
-                float childExtra = lp.weight;
+                final LayoutParams lp = (LayoutParams) child.getLayoutParams();
+                final float childExtra = lp.weight;
                 if (childExtra > 0) {
-                    // Child said it could absorb extra space -- give him his share
-                    int share = (int) (childExtra * delta / weightSum);
-                    weightSum -= childExtra;
-                    delta -= share;
+                    final int share = (int) (childExtra * delta / weightSum);
+                    final int childWidth;
+                    if (lp.width == 0 && (!mAllowInconsistentMeasurement
+                            || widthMode == MeasureSpec.EXACTLY)) {
+                        // This child needs to be laid out from scratch using
+                        // only its share of excess space.
+                        childWidth = share;
+                    } else {
+                        // This child had some intrinsic width to which we
+                        // need to add its share of excess space.
+                        childWidth = child.getMeasuredWidth() + share;
+                    }
 
-                    final int childHeightMeasureSpec = getChildMeasureSpec(
-                            heightMeasureSpec,
+                    final int childWidthMeasureSpec = MeasureSpec.makeMeasureSpec(
+                            Math.max(0, childWidth), MeasureSpec.EXACTLY);
+                    final int childHeightMeasureSpec = getChildMeasureSpec(heightMeasureSpec,
                             mPaddingTop + mPaddingBottom + lp.topMargin + lp.bottomMargin,
                             lp.height);
-
-                    // TODO: Use a field like lp.isMeasured to figure out if this
-                    // child has been previously measured
-                    if ((lp.width != 0) || (widthMode != MeasureSpec.EXACTLY)) {
-                        // child was measured once already above ... base new measurement
-                        // on stored values
-                        int childWidth = child.getMeasuredWidth() + share;
-                        if (childWidth < 0) {
-                            childWidth = 0;
-                        }
-
-                        child.measure(
-                            MeasureSpec.makeMeasureSpec(childWidth, MeasureSpec.EXACTLY),
-                            childHeightMeasureSpec);
-                    } else {
-                        // child was skipped in the loop above. Measure for this first time here
-                        child.measure(MeasureSpec.makeMeasureSpec(
-                                share > 0 ? share : 0, MeasureSpec.EXACTLY),
-                                childHeightMeasureSpec);
-                    }
+                    child.measure(childWidthMeasureSpec, childHeightMeasureSpec);
 
                     // Child may now not fit in horizontal dimension.
                     childState = combineMeasuredStates(childState,
diff --git a/core/java/android/widget/SearchView.java b/core/java/android/widget/SearchView.java
index 088adbb..ad2b4a7 100644
--- a/core/java/android/widget/SearchView.java
+++ b/core/java/android/widget/SearchView.java
@@ -816,7 +816,15 @@
         mSearchButton.setVisibility(visCollapsed);
         updateSubmitButton(hasText);
         mSearchEditFrame.setVisibility(collapsed ? GONE : VISIBLE);
-        mCollapsedIcon.setVisibility(mIconifiedByDefault ? GONE : VISIBLE);
+
+        final int iconVisibility;
+        if (mCollapsedIcon.getDrawable() == null || mIconifiedByDefault) {
+            iconVisibility = GONE;
+        } else {
+            iconVisibility = VISIBLE;
+        }
+        mCollapsedIcon.setVisibility(iconVisibility);
+
         updateCloseButton();
         updateVoiceButton(!hasText);
         updateSubmitArea();
diff --git a/core/java/android/widget/TextView.java b/core/java/android/widget/TextView.java
index ce66eeb..7a64377 100644
--- a/core/java/android/widget/TextView.java
+++ b/core/java/android/widget/TextView.java
@@ -139,6 +139,7 @@
 import android.view.textservice.TextServicesManager;
 import android.widget.RemoteViews.RemoteView;
 
+import com.android.internal.annotations.VisibleForTesting;
 import com.android.internal.util.FastMath;
 import com.android.internal.widget.EditableInputConnection;
 
@@ -1695,6 +1696,15 @@
         throw new UnsupportedOperationException("not implemented");
     }
 
+
+    /**
+     * @hide
+     */
+    @VisibleForTesting
+    public final Editor getEditorForTesting() {
+        return mEditor;
+    }
+
     /**
      * Associate an {@link android.content.UndoManager} with this TextView.  Once
      * done, all edit operations on the TextView will result in appropriate
@@ -8755,12 +8765,9 @@
     public void onPopulateAccessibilityEventInternal(AccessibilityEvent event) {
         super.onPopulateAccessibilityEventInternal(event);
 
-        final boolean isPassword = hasPasswordTransformationMethod();
-        if (!isPassword || shouldSpeakPasswordsForAccessibility()) {
-            final CharSequence text = getTextForAccessibility();
-            if (!TextUtils.isEmpty(text)) {
-                event.getText().add(text);
-            }
+        final CharSequence text = getTextForAccessibility();
+        if (!TextUtils.isEmpty(text)) {
+            event.getText().add(text);
         }
     }
 
@@ -8911,10 +8918,7 @@
 
         final boolean isPassword = hasPasswordTransformationMethod();
         info.setPassword(isPassword);
-
-        if (!isPassword || shouldSpeakPasswordsForAccessibility()) {
-            info.setText(getTextForAccessibility());
-        }
+        info.setText(getTextForAccessibility());
 
         if (mBufferType == BufferType.EDITABLE) {
             info.setEditable(true);
@@ -9146,18 +9150,30 @@
     }
 
     /**
-     * Gets the text reported for accessibility purposes.
+     * Returns the text that should be exposed to accessibility services.
+     * <p>
+     * This approximates what is displayed visually. If the user has specified
+     * that accessibility services should speak passwords, this method will
+     * bypass any password transformation method and return unobscured text.
      *
-     * @return The accessibility text.
-     *
-     * @hide
+     * @return the text that should be exposed to accessibility services, may
+     *         be {@code null} if no text is set
      */
-    public CharSequence getTextForAccessibility() {
-        CharSequence text = getText();
-        if (TextUtils.isEmpty(text)) {
-            text = getHint();
+    @Nullable
+    private CharSequence getTextForAccessibility() {
+        // If the text is empty, we must be showing the hint text.
+        if (TextUtils.isEmpty(mText)) {
+            return mHint;
         }
-        return text;
+
+        // Check whether we need to bypass the transformation
+        // method and expose unobscured text.
+        if (hasPasswordTransformationMethod() && shouldSpeakPasswordsForAccessibility()) {
+            return mText;
+        }
+
+        // Otherwise, speak whatever text is being displayed.
+        return mTransformed;
     }
 
     void sendAccessibilityEventTypeViewTextChanged(CharSequence beforeText,
diff --git a/core/java/com/android/internal/app/ToolbarActionBar.java b/core/java/com/android/internal/app/ToolbarActionBar.java
index c1b184e..9d12803 100644
--- a/core/java/com/android/internal/app/ToolbarActionBar.java
+++ b/core/java/com/android/internal/app/ToolbarActionBar.java
@@ -23,6 +23,7 @@
 import android.content.res.Configuration;
 import android.graphics.drawable.Drawable;
 import android.view.ActionMode;
+import android.view.KeyCharacterMap;
 import android.view.KeyEvent;
 import android.view.LayoutInflater;
 import android.view.Menu;
@@ -467,6 +468,9 @@
     public boolean onKeyShortcut(int keyCode, KeyEvent event) {
         Menu menu = mDecorToolbar.getMenu();
         if (menu != null) {
+            final KeyCharacterMap kmap = KeyCharacterMap.load(
+                    event != null ? event.getDeviceId() : KeyCharacterMap.VIRTUAL_KEYBOARD);
+            menu.setQwertyMode(kmap.getKeyboardType() != KeyCharacterMap.NUMERIC);
             menu.performShortcut(keyCode, event, 0);
         }
         // This action bar always returns true for handling keyboard shortcuts.
diff --git a/core/java/com/android/internal/statusbar/IStatusBar.aidl b/core/java/com/android/internal/statusbar/IStatusBar.aidl
index 1e41e63..ab3ec98 100644
--- a/core/java/com/android/internal/statusbar/IStatusBar.aidl
+++ b/core/java/com/android/internal/statusbar/IStatusBar.aidl
@@ -71,5 +71,10 @@
 
     void showAssistDisclosure();
     void startAssist(in Bundle args);
+
+    /**
+     * Notifies the status bar that a camera launch gesture has been detected.
+     */
+    void onCameraLaunchGestureDetected();
 }
 
diff --git a/core/java/com/android/internal/util/StateMachine.java b/core/java/com/android/internal/util/StateMachine.java
index 229407e..6816646 100644
--- a/core/java/com/android/internal/util/StateMachine.java
+++ b/core/java/com/android/internal/util/StateMachine.java
@@ -29,6 +29,7 @@
 import java.util.ArrayList;
 import java.util.Calendar;
 import java.util.Collection;
+import java.util.Iterator;
 import java.util.HashMap;
 import java.util.Vector;
 
@@ -1864,6 +1865,20 @@
     }
 
     /**
+     * Removes a message from the deferred messages queue.
+     */
+    protected final void removeDeferredMessages(int what) {
+        SmHandler smh = mSmHandler;
+        if (smh == null) return;
+
+        Iterator<Message> iterator = smh.mDeferredMessages.iterator();
+        while (iterator.hasNext()) {
+            Message msg = iterator.next();
+            if (msg.what == what) iterator.remove();
+        }
+    }
+
+    /**
      * Validate that the message was sent by
      * {@link StateMachine#quit} or {@link StateMachine#quitNow}.
      * */
diff --git a/core/java/com/android/internal/widget/LockPatternUtils.java b/core/java/com/android/internal/widget/LockPatternUtils.java
index 1995694..0579ce7d 100644
--- a/core/java/com/android/internal/widget/LockPatternUtils.java
+++ b/core/java/com/android/internal/widget/LockPatternUtils.java
@@ -1284,6 +1284,12 @@
          */
         public static final int SOME_AUTH_REQUIRED_AFTER_USER_REQUEST = 0x4;
 
+        /**
+         * Strong authentication is required because the user has been locked out after too many
+         * attempts.
+         */
+        public static final int STRONG_AUTH_REQUIRED_AFTER_LOCKOUT = 0x8;
+
         public static final int DEFAULT = STRONG_AUTH_REQUIRED_AFTER_BOOT;
         private static final int ALLOWING_FINGERPRINT = SOME_AUTH_REQUIRED_AFTER_USER_REQUEST;
 
diff --git a/core/java/com/android/internal/widget/NonClientDecorView.java b/core/java/com/android/internal/widget/NonClientDecorView.java
index 92812f8..372d934 100644
--- a/core/java/com/android/internal/widget/NonClientDecorView.java
+++ b/core/java/com/android/internal/widget/NonClientDecorView.java
@@ -124,6 +124,10 @@
         // input device we are listening to.
         switch (e.getActionMasked()) {
             case MotionEvent.ACTION_DOWN:
+                if (!mShowDecor) {
+                    // When there is no decor we should not react to anything.
+                    return false;
+                }
                 // A drag action is started if we aren't dragging already and the starting event is
                 // either a left mouse button or any other input device.
                 if (!mDragging &&
diff --git a/core/jni/android/graphics/HarfBuzzNGFaceSkia.cpp b/core/jni/android/graphics/HarfBuzzNGFaceSkia.cpp
index e537942..ae99f0b 100644
--- a/core/jni/android/graphics/HarfBuzzNGFaceSkia.cpp
+++ b/core/jni/android/graphics/HarfBuzzNGFaceSkia.cpp
@@ -32,6 +32,7 @@
 
 #include "HarfBuzzNGFaceSkia.h"
 
+#include <stdlib.h>
 #include <cutils/log.h>
 #include <SkPaint.h>
 #include <SkPath.h>
diff --git a/core/jni/android_view_GraphicBuffer.cpp b/core/jni/android_view_GraphicBuffer.cpp
index aa79d70..17d2a5e 100644
--- a/core/jni/android_view_GraphicBuffer.cpp
+++ b/core/jni/android_view_GraphicBuffer.cpp
@@ -158,7 +158,7 @@
 
     sp<GraphicBuffer> buffer(wrapper->buffer);
 
-    Rect rect;
+    Rect rect(Rect::EMPTY_RECT);
     if (dirtyRect) {
         rect.left = GET_INT(dirtyRect, gRectClassInfo.left);
         rect.top = GET_INT(dirtyRect, gRectClassInfo.top);
diff --git a/core/jni/android_view_Surface.cpp b/core/jni/android_view_Surface.cpp
index abd2409..4a311d31 100644
--- a/core/jni/android_view_Surface.cpp
+++ b/core/jni/android_view_Surface.cpp
@@ -292,7 +292,7 @@
         return 0;
     }
 
-    Rect dirtyRect;
+    Rect dirtyRect(Rect::EMPTY_RECT);
     Rect* dirtyRectPtr = NULL;
 
     if (dirtyRectObj) {
diff --git a/core/jni/android_view_TextureView.cpp b/core/jni/android_view_TextureView.cpp
index 7e05793..beb83b1 100644
--- a/core/jni/android_view_TextureView.cpp
+++ b/core/jni/android_view_TextureView.cpp
@@ -142,7 +142,7 @@
 
     ANativeWindow_Buffer buffer;
 
-    Rect rect;
+    Rect rect(Rect::EMPTY_RECT);
     if (dirtyRect) {
         rect.left = GET_INT(dirtyRect, gRectClassInfo.left);
         rect.top = GET_INT(dirtyRect, gRectClassInfo.top);
diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml
index fefd5a7..b0621e9 100644
--- a/core/res/AndroidManifest.xml
+++ b/core/res/AndroidManifest.xml
@@ -2567,10 +2567,11 @@
     <permission android:name="android.permission.BIND_CHOOSER_TARGET_SERVICE"
         android:protectionLevel="signature" />
 
-    <!-- @SystemApi Must be required by a {@link
+    <!-- Must be required by a {@link
          android.service.notification.ConditionProviderService},
          to ensure that only the system can bind to it.
-         @hide -->
+         <p>Protection level: signature
+         -->
     <permission android:name="android.permission.BIND_CONDITION_PROVIDER_SERVICE"
         android:protectionLevel="signature" />
 
@@ -2804,7 +2805,7 @@
         </activity>
 
         <receiver android:name="com.android.server.BootReceiver"
-                android:primaryUserOnly="true">
+                android:systemUserOnly="true">
             <intent-filter android:priority="1000">
                 <action android:name="android.intent.action.BOOT_COMPLETED" />
             </intent-filter>
diff --git a/core/res/res/drawable-hdpi/sim_dark_blue.9.png b/core/res/res/drawable-hdpi/sim_dark_blue.9.png
old mode 100755
new mode 100644
Binary files differ
diff --git a/core/res/res/drawable-hdpi/sim_dark_green.9.png b/core/res/res/drawable-hdpi/sim_dark_green.9.png
old mode 100755
new mode 100644
Binary files differ
diff --git a/core/res/res/drawable-hdpi/sim_dark_orange.9.png b/core/res/res/drawable-hdpi/sim_dark_orange.9.png
old mode 100755
new mode 100644
Binary files differ
diff --git a/core/res/res/drawable-hdpi/sim_dark_purple.9.png b/core/res/res/drawable-hdpi/sim_dark_purple.9.png
old mode 100755
new mode 100644
Binary files differ
diff --git a/core/res/res/drawable-hdpi/sim_light_blue.9.png b/core/res/res/drawable-hdpi/sim_light_blue.9.png
old mode 100755
new mode 100644
Binary files differ
diff --git a/core/res/res/drawable-hdpi/sim_light_green.9.png b/core/res/res/drawable-hdpi/sim_light_green.9.png
old mode 100755
new mode 100644
Binary files differ
diff --git a/core/res/res/drawable-hdpi/sim_light_orange.9.png b/core/res/res/drawable-hdpi/sim_light_orange.9.png
old mode 100755
new mode 100644
Binary files differ
diff --git a/core/res/res/drawable-hdpi/sim_light_purple.9.png b/core/res/res/drawable-hdpi/sim_light_purple.9.png
old mode 100755
new mode 100644
Binary files differ
diff --git a/core/res/res/drawable-mdpi/sim_dark_blue.9.png b/core/res/res/drawable-mdpi/sim_dark_blue.9.png
old mode 100755
new mode 100644
Binary files differ
diff --git a/core/res/res/drawable-mdpi/sim_dark_green.9.png b/core/res/res/drawable-mdpi/sim_dark_green.9.png
old mode 100755
new mode 100644
Binary files differ
diff --git a/core/res/res/drawable-mdpi/sim_dark_orange.9.png b/core/res/res/drawable-mdpi/sim_dark_orange.9.png
old mode 100755
new mode 100644
Binary files differ
diff --git a/core/res/res/drawable-mdpi/sim_dark_purple.9.png b/core/res/res/drawable-mdpi/sim_dark_purple.9.png
old mode 100755
new mode 100644
Binary files differ
diff --git a/core/res/res/drawable-mdpi/sim_light_blue.9.png b/core/res/res/drawable-mdpi/sim_light_blue.9.png
old mode 100755
new mode 100644
Binary files differ
diff --git a/core/res/res/drawable-mdpi/sim_light_green.9.png b/core/res/res/drawable-mdpi/sim_light_green.9.png
old mode 100755
new mode 100644
Binary files differ
diff --git a/core/res/res/drawable-mdpi/sim_light_orange.9.png b/core/res/res/drawable-mdpi/sim_light_orange.9.png
old mode 100755
new mode 100644
Binary files differ
diff --git a/core/res/res/drawable-mdpi/sim_light_purple.9.png b/core/res/res/drawable-mdpi/sim_light_purple.9.png
old mode 100755
new mode 100644
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/ic_audio_notification_am_alpha.png b/core/res/res/drawable-xxhdpi/ic_audio_notification_am_alpha.png
old mode 100755
new mode 100644
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/stat_notify_car_mode.png b/core/res/res/drawable-xxhdpi/stat_notify_car_mode.png
old mode 100755
new mode 100644
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/stat_notify_disk_full.png b/core/res/res/drawable-xxhdpi/stat_notify_disk_full.png
old mode 100755
new mode 100644
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/stat_notify_email_generic.png b/core/res/res/drawable-xxhdpi/stat_notify_email_generic.png
old mode 100755
new mode 100644
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/stat_notify_gmail.png b/core/res/res/drawable-xxhdpi/stat_notify_gmail.png
old mode 100755
new mode 100644
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/stat_notify_more.png b/core/res/res/drawable-xxhdpi/stat_notify_more.png
old mode 100755
new mode 100644
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/stat_notify_sdcard.png b/core/res/res/drawable-xxhdpi/stat_notify_sdcard.png
old mode 100755
new mode 100644
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/stat_notify_sdcard_prepare.png b/core/res/res/drawable-xxhdpi/stat_notify_sdcard_prepare.png
old mode 100755
new mode 100644
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/stat_notify_sdcard_usb.png b/core/res/res/drawable-xxhdpi/stat_notify_sdcard_usb.png
old mode 100755
new mode 100644
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/stat_notify_sim_toolkit.png b/core/res/res/drawable-xxhdpi/stat_notify_sim_toolkit.png
old mode 100755
new mode 100644
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/stat_notify_sync.png b/core/res/res/drawable-xxhdpi/stat_notify_sync.png
old mode 100755
new mode 100644
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/stat_notify_sync_anim0.png b/core/res/res/drawable-xxhdpi/stat_notify_sync_anim0.png
old mode 100755
new mode 100644
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/stat_notify_sync_error.png b/core/res/res/drawable-xxhdpi/stat_notify_sync_error.png
old mode 100755
new mode 100644
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/stat_notify_voicemail.png b/core/res/res/drawable-xxhdpi/stat_notify_voicemail.png
old mode 100755
new mode 100644
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/stat_sys_data_bluetooth.png b/core/res/res/drawable-xxhdpi/stat_sys_data_bluetooth.png
old mode 100755
new mode 100644
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/stat_sys_data_usb.png b/core/res/res/drawable-xxhdpi/stat_sys_data_usb.png
old mode 100755
new mode 100644
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/stat_sys_download_anim0.png b/core/res/res/drawable-xxhdpi/stat_sys_download_anim0.png
old mode 100755
new mode 100644
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/stat_sys_download_anim1.png b/core/res/res/drawable-xxhdpi/stat_sys_download_anim1.png
old mode 100755
new mode 100644
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/stat_sys_download_anim2.png b/core/res/res/drawable-xxhdpi/stat_sys_download_anim2.png
old mode 100755
new mode 100644
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/stat_sys_download_anim3.png b/core/res/res/drawable-xxhdpi/stat_sys_download_anim3.png
old mode 100755
new mode 100644
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/stat_sys_download_anim4.png b/core/res/res/drawable-xxhdpi/stat_sys_download_anim4.png
old mode 100755
new mode 100644
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/stat_sys_download_anim5.png b/core/res/res/drawable-xxhdpi/stat_sys_download_anim5.png
old mode 100755
new mode 100644
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/stat_sys_gps_on.png b/core/res/res/drawable-xxhdpi/stat_sys_gps_on.png
old mode 100755
new mode 100644
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/stat_sys_throttled.png b/core/res/res/drawable-xxhdpi/stat_sys_throttled.png
old mode 100755
new mode 100644
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/stat_sys_upload_anim0.png b/core/res/res/drawable-xxhdpi/stat_sys_upload_anim0.png
old mode 100755
new mode 100644
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/stat_sys_upload_anim1.png b/core/res/res/drawable-xxhdpi/stat_sys_upload_anim1.png
old mode 100755
new mode 100644
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/stat_sys_upload_anim2.png b/core/res/res/drawable-xxhdpi/stat_sys_upload_anim2.png
old mode 100755
new mode 100644
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/stat_sys_upload_anim3.png b/core/res/res/drawable-xxhdpi/stat_sys_upload_anim3.png
old mode 100755
new mode 100644
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/stat_sys_upload_anim4.png b/core/res/res/drawable-xxhdpi/stat_sys_upload_anim4.png
old mode 100755
new mode 100644
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/stat_sys_upload_anim5.png b/core/res/res/drawable-xxhdpi/stat_sys_upload_anim5.png
old mode 100755
new mode 100644
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/stat_sys_warning.png b/core/res/res/drawable-xxhdpi/stat_sys_warning.png
old mode 100755
new mode 100644
Binary files differ
diff --git a/core/res/res/drawable/edit_text_material.xml b/core/res/res/drawable/edit_text_material.xml
index 38ac567..901b3dc 100644
--- a/core/res/res/drawable/edit_text_material.xml
+++ b/core/res/res/drawable/edit_text_material.xml
@@ -22,8 +22,7 @@
     <selector>
         <item android:state_enabled="false">
             <nine-patch android:src="@drawable/textfield_default_mtrl_alpha"
-                android:tint="?attr/colorControlNormal"
-                android:alpha="?attr/disabledAlpha" />
+                android:tint="?attr/colorControlNormal" />
         </item>
         <item android:state_pressed="false" android:state_focused="false">
             <nine-patch android:src="@drawable/textfield_default_mtrl_alpha"
diff --git a/core/res/res/layout/non_client_decor_dark.xml b/core/res/res/layout/non_client_decor_dark.xml
index d1e2974..112f4b7 100644
--- a/core/res/res/layout/non_client_decor_dark.xml
+++ b/core/res/res/layout/non_client_decor_dark.xml
@@ -26,7 +26,9 @@
         android:layout_width="match_parent"
         android:layout_gravity="end"
         android:layout_height="wrap_content"
-        android:background="@drawable/non_client_decor_title" >
+        android:background="@drawable/non_client_decor_title"
+        android:focusable="false"
+        android:descendantFocusability="blocksDescendants" >
         <TextView
             android:layout_width="0dp"
             android:layout_height="match_parent"
@@ -40,7 +42,7 @@
             android:layout_gravity="center_vertical|end"
             android:contentDescription="@string/maximize_button_text"
             android:background="@drawable/decor_maximize_button_dark" />
-         <Button
+        <Button
             android:id="@+id/close_window"
             android:layout_width="32dp"
             android:layout_height="32dp"
diff --git a/core/res/res/layout/non_client_decor_light.xml b/core/res/res/layout/non_client_decor_light.xml
index f7c3fcd..5dd79c7 100644
--- a/core/res/res/layout/non_client_decor_light.xml
+++ b/core/res/res/layout/non_client_decor_light.xml
@@ -26,7 +26,9 @@
         android:layout_width="match_parent"
         android:layout_gravity="end"
         android:layout_height="wrap_content"
-        android:background="@drawable/non_client_decor_title" >
+        android:background="@drawable/non_client_decor_title"
+        android:focusable="false"
+        android:descendantFocusability="blocksDescendants" >
         <TextView
             android:layout_width="0dp"
             android:layout_height="match_parent"
@@ -40,7 +42,7 @@
             android:layout_gravity="center_vertical|end"
             android:contentDescription="@string/maximize_button_text"
             android:background="@drawable/decor_maximize_button_light" />
-         <Button
+        <Button
             android:id="@+id/close_window"
             android:layout_width="32dp"
             android:layout_height="32dp"
diff --git a/core/res/res/values-af-watch/strings.xml b/core/res/res/values-af-watch/strings.xml
index c81848a..9dc98a1 100644
--- a/core/res/res/values-af-watch/strings.xml
+++ b/core/res/res/values-af-watch/strings.xml
@@ -21,4 +21,48 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="android_upgrading_apk" msgid="1090732262010398759">"Program <xliff:g id="NUMBER_0">%1$d</xliff:g> van <xliff:g id="NUMBER_1">%2$d</xliff:g>."</string>
+    <!-- no translation found for permgrouplab_sensors (202675452368612754) -->
+    <skip />
+    <!-- no translation found for permgrouplab_contactswear (2340286500790908344) -->
+    <skip />
+    <!-- no translation found for permgrouplab_locationwear (6275317222482780209) -->
+    <skip />
+    <!-- no translation found for permgrouplab_calendarwear (441900844045065081) -->
+    <skip />
+    <!-- no translation found for permgrouplab_smswear (6849506550342974220) -->
+    <skip />
+    <!-- no translation found for permgrouplab_storagewear (1003807594193602313) -->
+    <skip />
+    <!-- no translation found for permgrouplab_microphonewear (1047561180980891136) -->
+    <skip />
+    <!-- no translation found for permgrouplab_camerawear (4543951283103407017) -->
+    <skip />
+    <!-- no translation found for permgrouplab_phonewear (134365036753766126) -->
+    <skip />
+    <!-- no translation found for permgrouplab_sensorswear (1429324744329327663) -->
+    <skip />
+    <!-- no translation found for permlab_statusBarServicewear (2469402818964691034) -->
+    <skip />
+    <!-- no translation found for permlab_bodySensorswear (7857941041202791873) -->
+    <skip />
+    <!-- no translation found for permlab_accessFineLocationwear (5584423486924377563) -->
+    <skip />
+    <!-- no translation found for permlab_accessCoarseLocationwear (5880746016230166090) -->
+    <skip />
+    <!-- no translation found for permlab_sim_communicationwear (1899198085342781874) -->
+    <skip />
+    <!-- no translation found for permlab_createNetworkSocketswear (6467042386273822913) -->
+    <skip />
+    <!-- no translation found for permlab_manageProfileAndDeviceOwnerswear (7313340516937821847) -->
+    <skip />
+    <!-- no translation found for permlab_changeWimaxStatewear (3828470843939853744) -->
+    <skip />
+    <!-- no translation found for permlab_handoverStatuswear (4835786819716499249) -->
+    <skip />
+    <!-- no translation found for permlab_route_media_outputwear (8737024341474587192) -->
+    <skip />
+    <!-- no translation found for permlab_readInstallSessionswear (9059478058685861989) -->
+    <skip />
+    <!-- no translation found for permlab_requestInstallPackageswear (4982025836783539503) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-am-watch/strings.xml b/core/res/res/values-am-watch/strings.xml
index 95188b6..ebe6ae0 100644
--- a/core/res/res/values-am-watch/strings.xml
+++ b/core/res/res/values-am-watch/strings.xml
@@ -21,4 +21,48 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="android_upgrading_apk" msgid="1090732262010398759">"<xliff:g id="NUMBER_0">%1$d</xliff:g> መተግበሪያ ከ<xliff:g id="NUMBER_1">%2$d</xliff:g>።"</string>
+    <!-- no translation found for permgrouplab_sensors (202675452368612754) -->
+    <skip />
+    <!-- no translation found for permgrouplab_contactswear (2340286500790908344) -->
+    <skip />
+    <!-- no translation found for permgrouplab_locationwear (6275317222482780209) -->
+    <skip />
+    <!-- no translation found for permgrouplab_calendarwear (441900844045065081) -->
+    <skip />
+    <!-- no translation found for permgrouplab_smswear (6849506550342974220) -->
+    <skip />
+    <!-- no translation found for permgrouplab_storagewear (1003807594193602313) -->
+    <skip />
+    <!-- no translation found for permgrouplab_microphonewear (1047561180980891136) -->
+    <skip />
+    <!-- no translation found for permgrouplab_camerawear (4543951283103407017) -->
+    <skip />
+    <!-- no translation found for permgrouplab_phonewear (134365036753766126) -->
+    <skip />
+    <!-- no translation found for permgrouplab_sensorswear (1429324744329327663) -->
+    <skip />
+    <!-- no translation found for permlab_statusBarServicewear (2469402818964691034) -->
+    <skip />
+    <!-- no translation found for permlab_bodySensorswear (7857941041202791873) -->
+    <skip />
+    <!-- no translation found for permlab_accessFineLocationwear (5584423486924377563) -->
+    <skip />
+    <!-- no translation found for permlab_accessCoarseLocationwear (5880746016230166090) -->
+    <skip />
+    <!-- no translation found for permlab_sim_communicationwear (1899198085342781874) -->
+    <skip />
+    <!-- no translation found for permlab_createNetworkSocketswear (6467042386273822913) -->
+    <skip />
+    <!-- no translation found for permlab_manageProfileAndDeviceOwnerswear (7313340516937821847) -->
+    <skip />
+    <!-- no translation found for permlab_changeWimaxStatewear (3828470843939853744) -->
+    <skip />
+    <!-- no translation found for permlab_handoverStatuswear (4835786819716499249) -->
+    <skip />
+    <!-- no translation found for permlab_route_media_outputwear (8737024341474587192) -->
+    <skip />
+    <!-- no translation found for permlab_readInstallSessionswear (9059478058685861989) -->
+    <skip />
+    <!-- no translation found for permlab_requestInstallPackageswear (4982025836783539503) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-ar-watch/strings.xml b/core/res/res/values-ar-watch/strings.xml
index 8cbb0a5..374b665 100644
--- a/core/res/res/values-ar-watch/strings.xml
+++ b/core/res/res/values-ar-watch/strings.xml
@@ -21,4 +21,48 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="android_upgrading_apk" msgid="1090732262010398759">"التطبيق <xliff:g id="NUMBER_0">%1$d</xliff:g> من <xliff:g id="NUMBER_1">%2$d</xliff:g>."</string>
+    <!-- no translation found for permgrouplab_sensors (202675452368612754) -->
+    <skip />
+    <!-- no translation found for permgrouplab_contactswear (2340286500790908344) -->
+    <skip />
+    <!-- no translation found for permgrouplab_locationwear (6275317222482780209) -->
+    <skip />
+    <!-- no translation found for permgrouplab_calendarwear (441900844045065081) -->
+    <skip />
+    <!-- no translation found for permgrouplab_smswear (6849506550342974220) -->
+    <skip />
+    <!-- no translation found for permgrouplab_storagewear (1003807594193602313) -->
+    <skip />
+    <!-- no translation found for permgrouplab_microphonewear (1047561180980891136) -->
+    <skip />
+    <!-- no translation found for permgrouplab_camerawear (4543951283103407017) -->
+    <skip />
+    <!-- no translation found for permgrouplab_phonewear (134365036753766126) -->
+    <skip />
+    <!-- no translation found for permgrouplab_sensorswear (1429324744329327663) -->
+    <skip />
+    <!-- no translation found for permlab_statusBarServicewear (2469402818964691034) -->
+    <skip />
+    <!-- no translation found for permlab_bodySensorswear (7857941041202791873) -->
+    <skip />
+    <!-- no translation found for permlab_accessFineLocationwear (5584423486924377563) -->
+    <skip />
+    <!-- no translation found for permlab_accessCoarseLocationwear (5880746016230166090) -->
+    <skip />
+    <!-- no translation found for permlab_sim_communicationwear (1899198085342781874) -->
+    <skip />
+    <!-- no translation found for permlab_createNetworkSocketswear (6467042386273822913) -->
+    <skip />
+    <!-- no translation found for permlab_manageProfileAndDeviceOwnerswear (7313340516937821847) -->
+    <skip />
+    <!-- no translation found for permlab_changeWimaxStatewear (3828470843939853744) -->
+    <skip />
+    <!-- no translation found for permlab_handoverStatuswear (4835786819716499249) -->
+    <skip />
+    <!-- no translation found for permlab_route_media_outputwear (8737024341474587192) -->
+    <skip />
+    <!-- no translation found for permlab_readInstallSessionswear (9059478058685861989) -->
+    <skip />
+    <!-- no translation found for permlab_requestInstallPackageswear (4982025836783539503) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-az-rAZ-watch/strings.xml b/core/res/res/values-az-rAZ-watch/strings.xml
index 7e4a762..cdc6a3d 100644
--- a/core/res/res/values-az-rAZ-watch/strings.xml
+++ b/core/res/res/values-az-rAZ-watch/strings.xml
@@ -21,4 +21,48 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="android_upgrading_apk" msgid="1090732262010398759">"Tətbiq <xliff:g id="NUMBER_0">%1$d</xliff:g>/<xliff:g id="NUMBER_1">%2$d</xliff:g>."</string>
+    <!-- no translation found for permgrouplab_sensors (202675452368612754) -->
+    <skip />
+    <!-- no translation found for permgrouplab_contactswear (2340286500790908344) -->
+    <skip />
+    <!-- no translation found for permgrouplab_locationwear (6275317222482780209) -->
+    <skip />
+    <!-- no translation found for permgrouplab_calendarwear (441900844045065081) -->
+    <skip />
+    <!-- no translation found for permgrouplab_smswear (6849506550342974220) -->
+    <skip />
+    <!-- no translation found for permgrouplab_storagewear (1003807594193602313) -->
+    <skip />
+    <!-- no translation found for permgrouplab_microphonewear (1047561180980891136) -->
+    <skip />
+    <!-- no translation found for permgrouplab_camerawear (4543951283103407017) -->
+    <skip />
+    <!-- no translation found for permgrouplab_phonewear (134365036753766126) -->
+    <skip />
+    <!-- no translation found for permgrouplab_sensorswear (1429324744329327663) -->
+    <skip />
+    <!-- no translation found for permlab_statusBarServicewear (2469402818964691034) -->
+    <skip />
+    <!-- no translation found for permlab_bodySensorswear (7857941041202791873) -->
+    <skip />
+    <!-- no translation found for permlab_accessFineLocationwear (5584423486924377563) -->
+    <skip />
+    <!-- no translation found for permlab_accessCoarseLocationwear (5880746016230166090) -->
+    <skip />
+    <!-- no translation found for permlab_sim_communicationwear (1899198085342781874) -->
+    <skip />
+    <!-- no translation found for permlab_createNetworkSocketswear (6467042386273822913) -->
+    <skip />
+    <!-- no translation found for permlab_manageProfileAndDeviceOwnerswear (7313340516937821847) -->
+    <skip />
+    <!-- no translation found for permlab_changeWimaxStatewear (3828470843939853744) -->
+    <skip />
+    <!-- no translation found for permlab_handoverStatuswear (4835786819716499249) -->
+    <skip />
+    <!-- no translation found for permlab_route_media_outputwear (8737024341474587192) -->
+    <skip />
+    <!-- no translation found for permlab_readInstallSessionswear (9059478058685861989) -->
+    <skip />
+    <!-- no translation found for permlab_requestInstallPackageswear (4982025836783539503) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-bg-watch/strings.xml b/core/res/res/values-bg-watch/strings.xml
index 1f1d921..a31f8d8 100644
--- a/core/res/res/values-bg-watch/strings.xml
+++ b/core/res/res/values-bg-watch/strings.xml
@@ -21,4 +21,48 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="android_upgrading_apk" msgid="1090732262010398759">"Прилож. <xliff:g id="NUMBER_0">%1$d</xliff:g> от <xliff:g id="NUMBER_1">%2$d</xliff:g>."</string>
+    <!-- no translation found for permgrouplab_sensors (202675452368612754) -->
+    <skip />
+    <!-- no translation found for permgrouplab_contactswear (2340286500790908344) -->
+    <skip />
+    <!-- no translation found for permgrouplab_locationwear (6275317222482780209) -->
+    <skip />
+    <!-- no translation found for permgrouplab_calendarwear (441900844045065081) -->
+    <skip />
+    <!-- no translation found for permgrouplab_smswear (6849506550342974220) -->
+    <skip />
+    <!-- no translation found for permgrouplab_storagewear (1003807594193602313) -->
+    <skip />
+    <!-- no translation found for permgrouplab_microphonewear (1047561180980891136) -->
+    <skip />
+    <!-- no translation found for permgrouplab_camerawear (4543951283103407017) -->
+    <skip />
+    <!-- no translation found for permgrouplab_phonewear (134365036753766126) -->
+    <skip />
+    <!-- no translation found for permgrouplab_sensorswear (1429324744329327663) -->
+    <skip />
+    <!-- no translation found for permlab_statusBarServicewear (2469402818964691034) -->
+    <skip />
+    <!-- no translation found for permlab_bodySensorswear (7857941041202791873) -->
+    <skip />
+    <!-- no translation found for permlab_accessFineLocationwear (5584423486924377563) -->
+    <skip />
+    <!-- no translation found for permlab_accessCoarseLocationwear (5880746016230166090) -->
+    <skip />
+    <!-- no translation found for permlab_sim_communicationwear (1899198085342781874) -->
+    <skip />
+    <!-- no translation found for permlab_createNetworkSocketswear (6467042386273822913) -->
+    <skip />
+    <!-- no translation found for permlab_manageProfileAndDeviceOwnerswear (7313340516937821847) -->
+    <skip />
+    <!-- no translation found for permlab_changeWimaxStatewear (3828470843939853744) -->
+    <skip />
+    <!-- no translation found for permlab_handoverStatuswear (4835786819716499249) -->
+    <skip />
+    <!-- no translation found for permlab_route_media_outputwear (8737024341474587192) -->
+    <skip />
+    <!-- no translation found for permlab_readInstallSessionswear (9059478058685861989) -->
+    <skip />
+    <!-- no translation found for permlab_requestInstallPackageswear (4982025836783539503) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-bn-rBD-watch/strings.xml b/core/res/res/values-bn-rBD-watch/strings.xml
index b934841..4ce6091 100644
--- a/core/res/res/values-bn-rBD-watch/strings.xml
+++ b/core/res/res/values-bn-rBD-watch/strings.xml
@@ -21,4 +21,48 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="android_upgrading_apk" msgid="1090732262010398759">"<xliff:g id="NUMBER_1">%2$d</xliff:g>টির মধ্যে <xliff:g id="NUMBER_0">%1$d</xliff:g>টি অ্যাপ্লিকেশান"</string>
+    <!-- no translation found for permgrouplab_sensors (202675452368612754) -->
+    <skip />
+    <!-- no translation found for permgrouplab_contactswear (2340286500790908344) -->
+    <skip />
+    <!-- no translation found for permgrouplab_locationwear (6275317222482780209) -->
+    <skip />
+    <!-- no translation found for permgrouplab_calendarwear (441900844045065081) -->
+    <skip />
+    <!-- no translation found for permgrouplab_smswear (6849506550342974220) -->
+    <skip />
+    <!-- no translation found for permgrouplab_storagewear (1003807594193602313) -->
+    <skip />
+    <!-- no translation found for permgrouplab_microphonewear (1047561180980891136) -->
+    <skip />
+    <!-- no translation found for permgrouplab_camerawear (4543951283103407017) -->
+    <skip />
+    <!-- no translation found for permgrouplab_phonewear (134365036753766126) -->
+    <skip />
+    <!-- no translation found for permgrouplab_sensorswear (1429324744329327663) -->
+    <skip />
+    <!-- no translation found for permlab_statusBarServicewear (2469402818964691034) -->
+    <skip />
+    <!-- no translation found for permlab_bodySensorswear (7857941041202791873) -->
+    <skip />
+    <!-- no translation found for permlab_accessFineLocationwear (5584423486924377563) -->
+    <skip />
+    <!-- no translation found for permlab_accessCoarseLocationwear (5880746016230166090) -->
+    <skip />
+    <!-- no translation found for permlab_sim_communicationwear (1899198085342781874) -->
+    <skip />
+    <!-- no translation found for permlab_createNetworkSocketswear (6467042386273822913) -->
+    <skip />
+    <!-- no translation found for permlab_manageProfileAndDeviceOwnerswear (7313340516937821847) -->
+    <skip />
+    <!-- no translation found for permlab_changeWimaxStatewear (3828470843939853744) -->
+    <skip />
+    <!-- no translation found for permlab_handoverStatuswear (4835786819716499249) -->
+    <skip />
+    <!-- no translation found for permlab_route_media_outputwear (8737024341474587192) -->
+    <skip />
+    <!-- no translation found for permlab_readInstallSessionswear (9059478058685861989) -->
+    <skip />
+    <!-- no translation found for permlab_requestInstallPackageswear (4982025836783539503) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-ca-watch/strings.xml b/core/res/res/values-ca-watch/strings.xml
index b44703e..8f626e5 100644
--- a/core/res/res/values-ca-watch/strings.xml
+++ b/core/res/res/values-ca-watch/strings.xml
@@ -21,4 +21,48 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="android_upgrading_apk" msgid="1090732262010398759">"Aplicació <xliff:g id="NUMBER_0">%1$d</xliff:g> de <xliff:g id="NUMBER_1">%2$d</xliff:g>."</string>
+    <!-- no translation found for permgrouplab_sensors (202675452368612754) -->
+    <skip />
+    <!-- no translation found for permgrouplab_contactswear (2340286500790908344) -->
+    <skip />
+    <!-- no translation found for permgrouplab_locationwear (6275317222482780209) -->
+    <skip />
+    <!-- no translation found for permgrouplab_calendarwear (441900844045065081) -->
+    <skip />
+    <!-- no translation found for permgrouplab_smswear (6849506550342974220) -->
+    <skip />
+    <!-- no translation found for permgrouplab_storagewear (1003807594193602313) -->
+    <skip />
+    <!-- no translation found for permgrouplab_microphonewear (1047561180980891136) -->
+    <skip />
+    <!-- no translation found for permgrouplab_camerawear (4543951283103407017) -->
+    <skip />
+    <!-- no translation found for permgrouplab_phonewear (134365036753766126) -->
+    <skip />
+    <!-- no translation found for permgrouplab_sensorswear (1429324744329327663) -->
+    <skip />
+    <!-- no translation found for permlab_statusBarServicewear (2469402818964691034) -->
+    <skip />
+    <!-- no translation found for permlab_bodySensorswear (7857941041202791873) -->
+    <skip />
+    <!-- no translation found for permlab_accessFineLocationwear (5584423486924377563) -->
+    <skip />
+    <!-- no translation found for permlab_accessCoarseLocationwear (5880746016230166090) -->
+    <skip />
+    <!-- no translation found for permlab_sim_communicationwear (1899198085342781874) -->
+    <skip />
+    <!-- no translation found for permlab_createNetworkSocketswear (6467042386273822913) -->
+    <skip />
+    <!-- no translation found for permlab_manageProfileAndDeviceOwnerswear (7313340516937821847) -->
+    <skip />
+    <!-- no translation found for permlab_changeWimaxStatewear (3828470843939853744) -->
+    <skip />
+    <!-- no translation found for permlab_handoverStatuswear (4835786819716499249) -->
+    <skip />
+    <!-- no translation found for permlab_route_media_outputwear (8737024341474587192) -->
+    <skip />
+    <!-- no translation found for permlab_readInstallSessionswear (9059478058685861989) -->
+    <skip />
+    <!-- no translation found for permlab_requestInstallPackageswear (4982025836783539503) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-cs-watch/strings.xml b/core/res/res/values-cs-watch/strings.xml
index 89c9dee..34f8864 100644
--- a/core/res/res/values-cs-watch/strings.xml
+++ b/core/res/res/values-cs-watch/strings.xml
@@ -21,4 +21,48 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="android_upgrading_apk" msgid="1090732262010398759">"Aplikace <xliff:g id="NUMBER_0">%1$d</xliff:g> z <xliff:g id="NUMBER_1">%2$d</xliff:g>."</string>
+    <!-- no translation found for permgrouplab_sensors (202675452368612754) -->
+    <skip />
+    <!-- no translation found for permgrouplab_contactswear (2340286500790908344) -->
+    <skip />
+    <!-- no translation found for permgrouplab_locationwear (6275317222482780209) -->
+    <skip />
+    <!-- no translation found for permgrouplab_calendarwear (441900844045065081) -->
+    <skip />
+    <!-- no translation found for permgrouplab_smswear (6849506550342974220) -->
+    <skip />
+    <!-- no translation found for permgrouplab_storagewear (1003807594193602313) -->
+    <skip />
+    <!-- no translation found for permgrouplab_microphonewear (1047561180980891136) -->
+    <skip />
+    <!-- no translation found for permgrouplab_camerawear (4543951283103407017) -->
+    <skip />
+    <!-- no translation found for permgrouplab_phonewear (134365036753766126) -->
+    <skip />
+    <!-- no translation found for permgrouplab_sensorswear (1429324744329327663) -->
+    <skip />
+    <!-- no translation found for permlab_statusBarServicewear (2469402818964691034) -->
+    <skip />
+    <!-- no translation found for permlab_bodySensorswear (7857941041202791873) -->
+    <skip />
+    <!-- no translation found for permlab_accessFineLocationwear (5584423486924377563) -->
+    <skip />
+    <!-- no translation found for permlab_accessCoarseLocationwear (5880746016230166090) -->
+    <skip />
+    <!-- no translation found for permlab_sim_communicationwear (1899198085342781874) -->
+    <skip />
+    <!-- no translation found for permlab_createNetworkSocketswear (6467042386273822913) -->
+    <skip />
+    <!-- no translation found for permlab_manageProfileAndDeviceOwnerswear (7313340516937821847) -->
+    <skip />
+    <!-- no translation found for permlab_changeWimaxStatewear (3828470843939853744) -->
+    <skip />
+    <!-- no translation found for permlab_handoverStatuswear (4835786819716499249) -->
+    <skip />
+    <!-- no translation found for permlab_route_media_outputwear (8737024341474587192) -->
+    <skip />
+    <!-- no translation found for permlab_readInstallSessionswear (9059478058685861989) -->
+    <skip />
+    <!-- no translation found for permlab_requestInstallPackageswear (4982025836783539503) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-da-watch/strings.xml b/core/res/res/values-da-watch/strings.xml
index f1daf30..efc4cf2 100644
--- a/core/res/res/values-da-watch/strings.xml
+++ b/core/res/res/values-da-watch/strings.xml
@@ -21,4 +21,48 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="android_upgrading_apk" msgid="1090732262010398759">"App <xliff:g id="NUMBER_0">%1$d</xliff:g> af <xliff:g id="NUMBER_1">%2$d</xliff:g>."</string>
+    <!-- no translation found for permgrouplab_sensors (202675452368612754) -->
+    <skip />
+    <!-- no translation found for permgrouplab_contactswear (2340286500790908344) -->
+    <skip />
+    <!-- no translation found for permgrouplab_locationwear (6275317222482780209) -->
+    <skip />
+    <!-- no translation found for permgrouplab_calendarwear (441900844045065081) -->
+    <skip />
+    <!-- no translation found for permgrouplab_smswear (6849506550342974220) -->
+    <skip />
+    <!-- no translation found for permgrouplab_storagewear (1003807594193602313) -->
+    <skip />
+    <!-- no translation found for permgrouplab_microphonewear (1047561180980891136) -->
+    <skip />
+    <!-- no translation found for permgrouplab_camerawear (4543951283103407017) -->
+    <skip />
+    <!-- no translation found for permgrouplab_phonewear (134365036753766126) -->
+    <skip />
+    <!-- no translation found for permgrouplab_sensorswear (1429324744329327663) -->
+    <skip />
+    <!-- no translation found for permlab_statusBarServicewear (2469402818964691034) -->
+    <skip />
+    <!-- no translation found for permlab_bodySensorswear (7857941041202791873) -->
+    <skip />
+    <!-- no translation found for permlab_accessFineLocationwear (5584423486924377563) -->
+    <skip />
+    <!-- no translation found for permlab_accessCoarseLocationwear (5880746016230166090) -->
+    <skip />
+    <!-- no translation found for permlab_sim_communicationwear (1899198085342781874) -->
+    <skip />
+    <!-- no translation found for permlab_createNetworkSocketswear (6467042386273822913) -->
+    <skip />
+    <!-- no translation found for permlab_manageProfileAndDeviceOwnerswear (7313340516937821847) -->
+    <skip />
+    <!-- no translation found for permlab_changeWimaxStatewear (3828470843939853744) -->
+    <skip />
+    <!-- no translation found for permlab_handoverStatuswear (4835786819716499249) -->
+    <skip />
+    <!-- no translation found for permlab_route_media_outputwear (8737024341474587192) -->
+    <skip />
+    <!-- no translation found for permlab_readInstallSessionswear (9059478058685861989) -->
+    <skip />
+    <!-- no translation found for permlab_requestInstallPackageswear (4982025836783539503) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-de-watch/strings.xml b/core/res/res/values-de-watch/strings.xml
index 52a21ba..99b3336 100644
--- a/core/res/res/values-de-watch/strings.xml
+++ b/core/res/res/values-de-watch/strings.xml
@@ -21,4 +21,48 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="android_upgrading_apk" msgid="1090732262010398759">"App <xliff:g id="NUMBER_0">%1$d</xliff:g> von <xliff:g id="NUMBER_1">%2$d</xliff:g>"</string>
+    <!-- no translation found for permgrouplab_sensors (202675452368612754) -->
+    <skip />
+    <!-- no translation found for permgrouplab_contactswear (2340286500790908344) -->
+    <skip />
+    <!-- no translation found for permgrouplab_locationwear (6275317222482780209) -->
+    <skip />
+    <!-- no translation found for permgrouplab_calendarwear (441900844045065081) -->
+    <skip />
+    <!-- no translation found for permgrouplab_smswear (6849506550342974220) -->
+    <skip />
+    <!-- no translation found for permgrouplab_storagewear (1003807594193602313) -->
+    <skip />
+    <!-- no translation found for permgrouplab_microphonewear (1047561180980891136) -->
+    <skip />
+    <!-- no translation found for permgrouplab_camerawear (4543951283103407017) -->
+    <skip />
+    <!-- no translation found for permgrouplab_phonewear (134365036753766126) -->
+    <skip />
+    <!-- no translation found for permgrouplab_sensorswear (1429324744329327663) -->
+    <skip />
+    <!-- no translation found for permlab_statusBarServicewear (2469402818964691034) -->
+    <skip />
+    <!-- no translation found for permlab_bodySensorswear (7857941041202791873) -->
+    <skip />
+    <!-- no translation found for permlab_accessFineLocationwear (5584423486924377563) -->
+    <skip />
+    <!-- no translation found for permlab_accessCoarseLocationwear (5880746016230166090) -->
+    <skip />
+    <!-- no translation found for permlab_sim_communicationwear (1899198085342781874) -->
+    <skip />
+    <!-- no translation found for permlab_createNetworkSocketswear (6467042386273822913) -->
+    <skip />
+    <!-- no translation found for permlab_manageProfileAndDeviceOwnerswear (7313340516937821847) -->
+    <skip />
+    <!-- no translation found for permlab_changeWimaxStatewear (3828470843939853744) -->
+    <skip />
+    <!-- no translation found for permlab_handoverStatuswear (4835786819716499249) -->
+    <skip />
+    <!-- no translation found for permlab_route_media_outputwear (8737024341474587192) -->
+    <skip />
+    <!-- no translation found for permlab_readInstallSessionswear (9059478058685861989) -->
+    <skip />
+    <!-- no translation found for permlab_requestInstallPackageswear (4982025836783539503) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-el-watch/strings.xml b/core/res/res/values-el-watch/strings.xml
index 81a7451..c159d6f 100644
--- a/core/res/res/values-el-watch/strings.xml
+++ b/core/res/res/values-el-watch/strings.xml
@@ -21,4 +21,48 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="android_upgrading_apk" msgid="1090732262010398759">"Εφαρμογή <xliff:g id="NUMBER_0">%1$d</xliff:g> από <xliff:g id="NUMBER_1">%2$d</xliff:g>."</string>
+    <!-- no translation found for permgrouplab_sensors (202675452368612754) -->
+    <skip />
+    <!-- no translation found for permgrouplab_contactswear (2340286500790908344) -->
+    <skip />
+    <!-- no translation found for permgrouplab_locationwear (6275317222482780209) -->
+    <skip />
+    <!-- no translation found for permgrouplab_calendarwear (441900844045065081) -->
+    <skip />
+    <!-- no translation found for permgrouplab_smswear (6849506550342974220) -->
+    <skip />
+    <!-- no translation found for permgrouplab_storagewear (1003807594193602313) -->
+    <skip />
+    <!-- no translation found for permgrouplab_microphonewear (1047561180980891136) -->
+    <skip />
+    <!-- no translation found for permgrouplab_camerawear (4543951283103407017) -->
+    <skip />
+    <!-- no translation found for permgrouplab_phonewear (134365036753766126) -->
+    <skip />
+    <!-- no translation found for permgrouplab_sensorswear (1429324744329327663) -->
+    <skip />
+    <!-- no translation found for permlab_statusBarServicewear (2469402818964691034) -->
+    <skip />
+    <!-- no translation found for permlab_bodySensorswear (7857941041202791873) -->
+    <skip />
+    <!-- no translation found for permlab_accessFineLocationwear (5584423486924377563) -->
+    <skip />
+    <!-- no translation found for permlab_accessCoarseLocationwear (5880746016230166090) -->
+    <skip />
+    <!-- no translation found for permlab_sim_communicationwear (1899198085342781874) -->
+    <skip />
+    <!-- no translation found for permlab_createNetworkSocketswear (6467042386273822913) -->
+    <skip />
+    <!-- no translation found for permlab_manageProfileAndDeviceOwnerswear (7313340516937821847) -->
+    <skip />
+    <!-- no translation found for permlab_changeWimaxStatewear (3828470843939853744) -->
+    <skip />
+    <!-- no translation found for permlab_handoverStatuswear (4835786819716499249) -->
+    <skip />
+    <!-- no translation found for permlab_route_media_outputwear (8737024341474587192) -->
+    <skip />
+    <!-- no translation found for permlab_readInstallSessionswear (9059478058685861989) -->
+    <skip />
+    <!-- no translation found for permlab_requestInstallPackageswear (4982025836783539503) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-en-rAU-watch/strings.xml b/core/res/res/values-en-rAU-watch/strings.xml
index 6734cd3..6102d4e4 100644
--- a/core/res/res/values-en-rAU-watch/strings.xml
+++ b/core/res/res/values-en-rAU-watch/strings.xml
@@ -21,4 +21,48 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="android_upgrading_apk" msgid="1090732262010398759">"App <xliff:g id="NUMBER_0">%1$d</xliff:g> of <xliff:g id="NUMBER_1">%2$d</xliff:g>."</string>
+    <!-- no translation found for permgrouplab_sensors (202675452368612754) -->
+    <skip />
+    <!-- no translation found for permgrouplab_contactswear (2340286500790908344) -->
+    <skip />
+    <!-- no translation found for permgrouplab_locationwear (6275317222482780209) -->
+    <skip />
+    <!-- no translation found for permgrouplab_calendarwear (441900844045065081) -->
+    <skip />
+    <!-- no translation found for permgrouplab_smswear (6849506550342974220) -->
+    <skip />
+    <!-- no translation found for permgrouplab_storagewear (1003807594193602313) -->
+    <skip />
+    <!-- no translation found for permgrouplab_microphonewear (1047561180980891136) -->
+    <skip />
+    <!-- no translation found for permgrouplab_camerawear (4543951283103407017) -->
+    <skip />
+    <!-- no translation found for permgrouplab_phonewear (134365036753766126) -->
+    <skip />
+    <!-- no translation found for permgrouplab_sensorswear (1429324744329327663) -->
+    <skip />
+    <!-- no translation found for permlab_statusBarServicewear (2469402818964691034) -->
+    <skip />
+    <!-- no translation found for permlab_bodySensorswear (7857941041202791873) -->
+    <skip />
+    <!-- no translation found for permlab_accessFineLocationwear (5584423486924377563) -->
+    <skip />
+    <!-- no translation found for permlab_accessCoarseLocationwear (5880746016230166090) -->
+    <skip />
+    <!-- no translation found for permlab_sim_communicationwear (1899198085342781874) -->
+    <skip />
+    <!-- no translation found for permlab_createNetworkSocketswear (6467042386273822913) -->
+    <skip />
+    <!-- no translation found for permlab_manageProfileAndDeviceOwnerswear (7313340516937821847) -->
+    <skip />
+    <!-- no translation found for permlab_changeWimaxStatewear (3828470843939853744) -->
+    <skip />
+    <!-- no translation found for permlab_handoverStatuswear (4835786819716499249) -->
+    <skip />
+    <!-- no translation found for permlab_route_media_outputwear (8737024341474587192) -->
+    <skip />
+    <!-- no translation found for permlab_readInstallSessionswear (9059478058685861989) -->
+    <skip />
+    <!-- no translation found for permlab_requestInstallPackageswear (4982025836783539503) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-en-rGB-watch/strings.xml b/core/res/res/values-en-rGB-watch/strings.xml
index 6734cd3..6102d4e4 100644
--- a/core/res/res/values-en-rGB-watch/strings.xml
+++ b/core/res/res/values-en-rGB-watch/strings.xml
@@ -21,4 +21,48 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="android_upgrading_apk" msgid="1090732262010398759">"App <xliff:g id="NUMBER_0">%1$d</xliff:g> of <xliff:g id="NUMBER_1">%2$d</xliff:g>."</string>
+    <!-- no translation found for permgrouplab_sensors (202675452368612754) -->
+    <skip />
+    <!-- no translation found for permgrouplab_contactswear (2340286500790908344) -->
+    <skip />
+    <!-- no translation found for permgrouplab_locationwear (6275317222482780209) -->
+    <skip />
+    <!-- no translation found for permgrouplab_calendarwear (441900844045065081) -->
+    <skip />
+    <!-- no translation found for permgrouplab_smswear (6849506550342974220) -->
+    <skip />
+    <!-- no translation found for permgrouplab_storagewear (1003807594193602313) -->
+    <skip />
+    <!-- no translation found for permgrouplab_microphonewear (1047561180980891136) -->
+    <skip />
+    <!-- no translation found for permgrouplab_camerawear (4543951283103407017) -->
+    <skip />
+    <!-- no translation found for permgrouplab_phonewear (134365036753766126) -->
+    <skip />
+    <!-- no translation found for permgrouplab_sensorswear (1429324744329327663) -->
+    <skip />
+    <!-- no translation found for permlab_statusBarServicewear (2469402818964691034) -->
+    <skip />
+    <!-- no translation found for permlab_bodySensorswear (7857941041202791873) -->
+    <skip />
+    <!-- no translation found for permlab_accessFineLocationwear (5584423486924377563) -->
+    <skip />
+    <!-- no translation found for permlab_accessCoarseLocationwear (5880746016230166090) -->
+    <skip />
+    <!-- no translation found for permlab_sim_communicationwear (1899198085342781874) -->
+    <skip />
+    <!-- no translation found for permlab_createNetworkSocketswear (6467042386273822913) -->
+    <skip />
+    <!-- no translation found for permlab_manageProfileAndDeviceOwnerswear (7313340516937821847) -->
+    <skip />
+    <!-- no translation found for permlab_changeWimaxStatewear (3828470843939853744) -->
+    <skip />
+    <!-- no translation found for permlab_handoverStatuswear (4835786819716499249) -->
+    <skip />
+    <!-- no translation found for permlab_route_media_outputwear (8737024341474587192) -->
+    <skip />
+    <!-- no translation found for permlab_readInstallSessionswear (9059478058685861989) -->
+    <skip />
+    <!-- no translation found for permlab_requestInstallPackageswear (4982025836783539503) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-en-rIN-watch/strings.xml b/core/res/res/values-en-rIN-watch/strings.xml
index 6734cd3..6102d4e4 100644
--- a/core/res/res/values-en-rIN-watch/strings.xml
+++ b/core/res/res/values-en-rIN-watch/strings.xml
@@ -21,4 +21,48 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="android_upgrading_apk" msgid="1090732262010398759">"App <xliff:g id="NUMBER_0">%1$d</xliff:g> of <xliff:g id="NUMBER_1">%2$d</xliff:g>."</string>
+    <!-- no translation found for permgrouplab_sensors (202675452368612754) -->
+    <skip />
+    <!-- no translation found for permgrouplab_contactswear (2340286500790908344) -->
+    <skip />
+    <!-- no translation found for permgrouplab_locationwear (6275317222482780209) -->
+    <skip />
+    <!-- no translation found for permgrouplab_calendarwear (441900844045065081) -->
+    <skip />
+    <!-- no translation found for permgrouplab_smswear (6849506550342974220) -->
+    <skip />
+    <!-- no translation found for permgrouplab_storagewear (1003807594193602313) -->
+    <skip />
+    <!-- no translation found for permgrouplab_microphonewear (1047561180980891136) -->
+    <skip />
+    <!-- no translation found for permgrouplab_camerawear (4543951283103407017) -->
+    <skip />
+    <!-- no translation found for permgrouplab_phonewear (134365036753766126) -->
+    <skip />
+    <!-- no translation found for permgrouplab_sensorswear (1429324744329327663) -->
+    <skip />
+    <!-- no translation found for permlab_statusBarServicewear (2469402818964691034) -->
+    <skip />
+    <!-- no translation found for permlab_bodySensorswear (7857941041202791873) -->
+    <skip />
+    <!-- no translation found for permlab_accessFineLocationwear (5584423486924377563) -->
+    <skip />
+    <!-- no translation found for permlab_accessCoarseLocationwear (5880746016230166090) -->
+    <skip />
+    <!-- no translation found for permlab_sim_communicationwear (1899198085342781874) -->
+    <skip />
+    <!-- no translation found for permlab_createNetworkSocketswear (6467042386273822913) -->
+    <skip />
+    <!-- no translation found for permlab_manageProfileAndDeviceOwnerswear (7313340516937821847) -->
+    <skip />
+    <!-- no translation found for permlab_changeWimaxStatewear (3828470843939853744) -->
+    <skip />
+    <!-- no translation found for permlab_handoverStatuswear (4835786819716499249) -->
+    <skip />
+    <!-- no translation found for permlab_route_media_outputwear (8737024341474587192) -->
+    <skip />
+    <!-- no translation found for permlab_readInstallSessionswear (9059478058685861989) -->
+    <skip />
+    <!-- no translation found for permlab_requestInstallPackageswear (4982025836783539503) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-es-rUS-watch/strings.xml b/core/res/res/values-es-rUS-watch/strings.xml
index 763b24d..76664ef 100644
--- a/core/res/res/values-es-rUS-watch/strings.xml
+++ b/core/res/res/values-es-rUS-watch/strings.xml
@@ -21,4 +21,48 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="android_upgrading_apk" msgid="1090732262010398759">"Aplicación <xliff:g id="NUMBER_0">%1$d</xliff:g> de <xliff:g id="NUMBER_1">%2$d</xliff:g>"</string>
+    <!-- no translation found for permgrouplab_sensors (202675452368612754) -->
+    <skip />
+    <!-- no translation found for permgrouplab_contactswear (2340286500790908344) -->
+    <skip />
+    <!-- no translation found for permgrouplab_locationwear (6275317222482780209) -->
+    <skip />
+    <!-- no translation found for permgrouplab_calendarwear (441900844045065081) -->
+    <skip />
+    <!-- no translation found for permgrouplab_smswear (6849506550342974220) -->
+    <skip />
+    <!-- no translation found for permgrouplab_storagewear (1003807594193602313) -->
+    <skip />
+    <!-- no translation found for permgrouplab_microphonewear (1047561180980891136) -->
+    <skip />
+    <!-- no translation found for permgrouplab_camerawear (4543951283103407017) -->
+    <skip />
+    <!-- no translation found for permgrouplab_phonewear (134365036753766126) -->
+    <skip />
+    <!-- no translation found for permgrouplab_sensorswear (1429324744329327663) -->
+    <skip />
+    <!-- no translation found for permlab_statusBarServicewear (2469402818964691034) -->
+    <skip />
+    <!-- no translation found for permlab_bodySensorswear (7857941041202791873) -->
+    <skip />
+    <!-- no translation found for permlab_accessFineLocationwear (5584423486924377563) -->
+    <skip />
+    <!-- no translation found for permlab_accessCoarseLocationwear (5880746016230166090) -->
+    <skip />
+    <!-- no translation found for permlab_sim_communicationwear (1899198085342781874) -->
+    <skip />
+    <!-- no translation found for permlab_createNetworkSocketswear (6467042386273822913) -->
+    <skip />
+    <!-- no translation found for permlab_manageProfileAndDeviceOwnerswear (7313340516937821847) -->
+    <skip />
+    <!-- no translation found for permlab_changeWimaxStatewear (3828470843939853744) -->
+    <skip />
+    <!-- no translation found for permlab_handoverStatuswear (4835786819716499249) -->
+    <skip />
+    <!-- no translation found for permlab_route_media_outputwear (8737024341474587192) -->
+    <skip />
+    <!-- no translation found for permlab_readInstallSessionswear (9059478058685861989) -->
+    <skip />
+    <!-- no translation found for permlab_requestInstallPackageswear (4982025836783539503) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-es-watch/strings.xml b/core/res/res/values-es-watch/strings.xml
index d9ea0fe..002bfce 100644
--- a/core/res/res/values-es-watch/strings.xml
+++ b/core/res/res/values-es-watch/strings.xml
@@ -21,4 +21,48 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="android_upgrading_apk" msgid="1090732262010398759">"Aplicación <xliff:g id="NUMBER_0">%1$d</xliff:g> de <xliff:g id="NUMBER_1">%2$d</xliff:g>."</string>
+    <!-- no translation found for permgrouplab_sensors (202675452368612754) -->
+    <skip />
+    <!-- no translation found for permgrouplab_contactswear (2340286500790908344) -->
+    <skip />
+    <!-- no translation found for permgrouplab_locationwear (6275317222482780209) -->
+    <skip />
+    <!-- no translation found for permgrouplab_calendarwear (441900844045065081) -->
+    <skip />
+    <!-- no translation found for permgrouplab_smswear (6849506550342974220) -->
+    <skip />
+    <!-- no translation found for permgrouplab_storagewear (1003807594193602313) -->
+    <skip />
+    <!-- no translation found for permgrouplab_microphonewear (1047561180980891136) -->
+    <skip />
+    <!-- no translation found for permgrouplab_camerawear (4543951283103407017) -->
+    <skip />
+    <!-- no translation found for permgrouplab_phonewear (134365036753766126) -->
+    <skip />
+    <!-- no translation found for permgrouplab_sensorswear (1429324744329327663) -->
+    <skip />
+    <!-- no translation found for permlab_statusBarServicewear (2469402818964691034) -->
+    <skip />
+    <!-- no translation found for permlab_bodySensorswear (7857941041202791873) -->
+    <skip />
+    <!-- no translation found for permlab_accessFineLocationwear (5584423486924377563) -->
+    <skip />
+    <!-- no translation found for permlab_accessCoarseLocationwear (5880746016230166090) -->
+    <skip />
+    <!-- no translation found for permlab_sim_communicationwear (1899198085342781874) -->
+    <skip />
+    <!-- no translation found for permlab_createNetworkSocketswear (6467042386273822913) -->
+    <skip />
+    <!-- no translation found for permlab_manageProfileAndDeviceOwnerswear (7313340516937821847) -->
+    <skip />
+    <!-- no translation found for permlab_changeWimaxStatewear (3828470843939853744) -->
+    <skip />
+    <!-- no translation found for permlab_handoverStatuswear (4835786819716499249) -->
+    <skip />
+    <!-- no translation found for permlab_route_media_outputwear (8737024341474587192) -->
+    <skip />
+    <!-- no translation found for permlab_readInstallSessionswear (9059478058685861989) -->
+    <skip />
+    <!-- no translation found for permlab_requestInstallPackageswear (4982025836783539503) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-et-rEE-watch/strings.xml b/core/res/res/values-et-rEE-watch/strings.xml
index 0adb487..a1d29a8 100644
--- a/core/res/res/values-et-rEE-watch/strings.xml
+++ b/core/res/res/values-et-rEE-watch/strings.xml
@@ -21,4 +21,48 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="android_upgrading_apk" msgid="1090732262010398759">"Rakendus <xliff:g id="NUMBER_0">%1$d</xliff:g>/<xliff:g id="NUMBER_1">%2$d</xliff:g>."</string>
+    <!-- no translation found for permgrouplab_sensors (202675452368612754) -->
+    <skip />
+    <!-- no translation found for permgrouplab_contactswear (2340286500790908344) -->
+    <skip />
+    <!-- no translation found for permgrouplab_locationwear (6275317222482780209) -->
+    <skip />
+    <!-- no translation found for permgrouplab_calendarwear (441900844045065081) -->
+    <skip />
+    <!-- no translation found for permgrouplab_smswear (6849506550342974220) -->
+    <skip />
+    <!-- no translation found for permgrouplab_storagewear (1003807594193602313) -->
+    <skip />
+    <!-- no translation found for permgrouplab_microphonewear (1047561180980891136) -->
+    <skip />
+    <!-- no translation found for permgrouplab_camerawear (4543951283103407017) -->
+    <skip />
+    <!-- no translation found for permgrouplab_phonewear (134365036753766126) -->
+    <skip />
+    <!-- no translation found for permgrouplab_sensorswear (1429324744329327663) -->
+    <skip />
+    <!-- no translation found for permlab_statusBarServicewear (2469402818964691034) -->
+    <skip />
+    <!-- no translation found for permlab_bodySensorswear (7857941041202791873) -->
+    <skip />
+    <!-- no translation found for permlab_accessFineLocationwear (5584423486924377563) -->
+    <skip />
+    <!-- no translation found for permlab_accessCoarseLocationwear (5880746016230166090) -->
+    <skip />
+    <!-- no translation found for permlab_sim_communicationwear (1899198085342781874) -->
+    <skip />
+    <!-- no translation found for permlab_createNetworkSocketswear (6467042386273822913) -->
+    <skip />
+    <!-- no translation found for permlab_manageProfileAndDeviceOwnerswear (7313340516937821847) -->
+    <skip />
+    <!-- no translation found for permlab_changeWimaxStatewear (3828470843939853744) -->
+    <skip />
+    <!-- no translation found for permlab_handoverStatuswear (4835786819716499249) -->
+    <skip />
+    <!-- no translation found for permlab_route_media_outputwear (8737024341474587192) -->
+    <skip />
+    <!-- no translation found for permlab_readInstallSessionswear (9059478058685861989) -->
+    <skip />
+    <!-- no translation found for permlab_requestInstallPackageswear (4982025836783539503) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-eu-rES-watch/strings.xml b/core/res/res/values-eu-rES-watch/strings.xml
index 9c13ef9..aa67602 100644
--- a/core/res/res/values-eu-rES-watch/strings.xml
+++ b/core/res/res/values-eu-rES-watch/strings.xml
@@ -21,4 +21,48 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="android_upgrading_apk" msgid="1090732262010398759">"<xliff:g id="NUMBER_0">%1$d</xliff:g>/<xliff:g id="NUMBER_1">%2$d</xliff:g> aplikaz."</string>
+    <!-- no translation found for permgrouplab_sensors (202675452368612754) -->
+    <skip />
+    <!-- no translation found for permgrouplab_contactswear (2340286500790908344) -->
+    <skip />
+    <!-- no translation found for permgrouplab_locationwear (6275317222482780209) -->
+    <skip />
+    <!-- no translation found for permgrouplab_calendarwear (441900844045065081) -->
+    <skip />
+    <!-- no translation found for permgrouplab_smswear (6849506550342974220) -->
+    <skip />
+    <!-- no translation found for permgrouplab_storagewear (1003807594193602313) -->
+    <skip />
+    <!-- no translation found for permgrouplab_microphonewear (1047561180980891136) -->
+    <skip />
+    <!-- no translation found for permgrouplab_camerawear (4543951283103407017) -->
+    <skip />
+    <!-- no translation found for permgrouplab_phonewear (134365036753766126) -->
+    <skip />
+    <!-- no translation found for permgrouplab_sensorswear (1429324744329327663) -->
+    <skip />
+    <!-- no translation found for permlab_statusBarServicewear (2469402818964691034) -->
+    <skip />
+    <!-- no translation found for permlab_bodySensorswear (7857941041202791873) -->
+    <skip />
+    <!-- no translation found for permlab_accessFineLocationwear (5584423486924377563) -->
+    <skip />
+    <!-- no translation found for permlab_accessCoarseLocationwear (5880746016230166090) -->
+    <skip />
+    <!-- no translation found for permlab_sim_communicationwear (1899198085342781874) -->
+    <skip />
+    <!-- no translation found for permlab_createNetworkSocketswear (6467042386273822913) -->
+    <skip />
+    <!-- no translation found for permlab_manageProfileAndDeviceOwnerswear (7313340516937821847) -->
+    <skip />
+    <!-- no translation found for permlab_changeWimaxStatewear (3828470843939853744) -->
+    <skip />
+    <!-- no translation found for permlab_handoverStatuswear (4835786819716499249) -->
+    <skip />
+    <!-- no translation found for permlab_route_media_outputwear (8737024341474587192) -->
+    <skip />
+    <!-- no translation found for permlab_readInstallSessionswear (9059478058685861989) -->
+    <skip />
+    <!-- no translation found for permlab_requestInstallPackageswear (4982025836783539503) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-fa-watch/strings.xml b/core/res/res/values-fa-watch/strings.xml
index a33d7ec..243ccad 100644
--- a/core/res/res/values-fa-watch/strings.xml
+++ b/core/res/res/values-fa-watch/strings.xml
@@ -21,4 +21,48 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="android_upgrading_apk" msgid="1090732262010398759">"برنامه <xliff:g id="NUMBER_0">%1$d</xliff:g> از <xliff:g id="NUMBER_1">%2$d</xliff:g>."</string>
+    <!-- no translation found for permgrouplab_sensors (202675452368612754) -->
+    <skip />
+    <!-- no translation found for permgrouplab_contactswear (2340286500790908344) -->
+    <skip />
+    <!-- no translation found for permgrouplab_locationwear (6275317222482780209) -->
+    <skip />
+    <!-- no translation found for permgrouplab_calendarwear (441900844045065081) -->
+    <skip />
+    <!-- no translation found for permgrouplab_smswear (6849506550342974220) -->
+    <skip />
+    <!-- no translation found for permgrouplab_storagewear (1003807594193602313) -->
+    <skip />
+    <!-- no translation found for permgrouplab_microphonewear (1047561180980891136) -->
+    <skip />
+    <!-- no translation found for permgrouplab_camerawear (4543951283103407017) -->
+    <skip />
+    <!-- no translation found for permgrouplab_phonewear (134365036753766126) -->
+    <skip />
+    <!-- no translation found for permgrouplab_sensorswear (1429324744329327663) -->
+    <skip />
+    <!-- no translation found for permlab_statusBarServicewear (2469402818964691034) -->
+    <skip />
+    <!-- no translation found for permlab_bodySensorswear (7857941041202791873) -->
+    <skip />
+    <!-- no translation found for permlab_accessFineLocationwear (5584423486924377563) -->
+    <skip />
+    <!-- no translation found for permlab_accessCoarseLocationwear (5880746016230166090) -->
+    <skip />
+    <!-- no translation found for permlab_sim_communicationwear (1899198085342781874) -->
+    <skip />
+    <!-- no translation found for permlab_createNetworkSocketswear (6467042386273822913) -->
+    <skip />
+    <!-- no translation found for permlab_manageProfileAndDeviceOwnerswear (7313340516937821847) -->
+    <skip />
+    <!-- no translation found for permlab_changeWimaxStatewear (3828470843939853744) -->
+    <skip />
+    <!-- no translation found for permlab_handoverStatuswear (4835786819716499249) -->
+    <skip />
+    <!-- no translation found for permlab_route_media_outputwear (8737024341474587192) -->
+    <skip />
+    <!-- no translation found for permlab_readInstallSessionswear (9059478058685861989) -->
+    <skip />
+    <!-- no translation found for permlab_requestInstallPackageswear (4982025836783539503) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-fi-watch/strings.xml b/core/res/res/values-fi-watch/strings.xml
index 89782a5..abe5ebb 100644
--- a/core/res/res/values-fi-watch/strings.xml
+++ b/core/res/res/values-fi-watch/strings.xml
@@ -21,4 +21,48 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="android_upgrading_apk" msgid="1090732262010398759">"Sovellus <xliff:g id="NUMBER_0">%1$d</xliff:g>/<xliff:g id="NUMBER_1">%2$d</xliff:g>."</string>
+    <!-- no translation found for permgrouplab_sensors (202675452368612754) -->
+    <skip />
+    <!-- no translation found for permgrouplab_contactswear (2340286500790908344) -->
+    <skip />
+    <!-- no translation found for permgrouplab_locationwear (6275317222482780209) -->
+    <skip />
+    <!-- no translation found for permgrouplab_calendarwear (441900844045065081) -->
+    <skip />
+    <!-- no translation found for permgrouplab_smswear (6849506550342974220) -->
+    <skip />
+    <!-- no translation found for permgrouplab_storagewear (1003807594193602313) -->
+    <skip />
+    <!-- no translation found for permgrouplab_microphonewear (1047561180980891136) -->
+    <skip />
+    <!-- no translation found for permgrouplab_camerawear (4543951283103407017) -->
+    <skip />
+    <!-- no translation found for permgrouplab_phonewear (134365036753766126) -->
+    <skip />
+    <!-- no translation found for permgrouplab_sensorswear (1429324744329327663) -->
+    <skip />
+    <!-- no translation found for permlab_statusBarServicewear (2469402818964691034) -->
+    <skip />
+    <!-- no translation found for permlab_bodySensorswear (7857941041202791873) -->
+    <skip />
+    <!-- no translation found for permlab_accessFineLocationwear (5584423486924377563) -->
+    <skip />
+    <!-- no translation found for permlab_accessCoarseLocationwear (5880746016230166090) -->
+    <skip />
+    <!-- no translation found for permlab_sim_communicationwear (1899198085342781874) -->
+    <skip />
+    <!-- no translation found for permlab_createNetworkSocketswear (6467042386273822913) -->
+    <skip />
+    <!-- no translation found for permlab_manageProfileAndDeviceOwnerswear (7313340516937821847) -->
+    <skip />
+    <!-- no translation found for permlab_changeWimaxStatewear (3828470843939853744) -->
+    <skip />
+    <!-- no translation found for permlab_handoverStatuswear (4835786819716499249) -->
+    <skip />
+    <!-- no translation found for permlab_route_media_outputwear (8737024341474587192) -->
+    <skip />
+    <!-- no translation found for permlab_readInstallSessionswear (9059478058685861989) -->
+    <skip />
+    <!-- no translation found for permlab_requestInstallPackageswear (4982025836783539503) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-fr-rCA-watch/strings.xml b/core/res/res/values-fr-rCA-watch/strings.xml
index ea9c1c2..197b18a 100644
--- a/core/res/res/values-fr-rCA-watch/strings.xml
+++ b/core/res/res/values-fr-rCA-watch/strings.xml
@@ -21,4 +21,48 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="android_upgrading_apk" msgid="1090732262010398759">"Appli <xliff:g id="NUMBER_0">%1$d</xliff:g> de <xliff:g id="NUMBER_1">%2$d</xliff:g>."</string>
+    <!-- no translation found for permgrouplab_sensors (202675452368612754) -->
+    <skip />
+    <!-- no translation found for permgrouplab_contactswear (2340286500790908344) -->
+    <skip />
+    <!-- no translation found for permgrouplab_locationwear (6275317222482780209) -->
+    <skip />
+    <!-- no translation found for permgrouplab_calendarwear (441900844045065081) -->
+    <skip />
+    <!-- no translation found for permgrouplab_smswear (6849506550342974220) -->
+    <skip />
+    <!-- no translation found for permgrouplab_storagewear (1003807594193602313) -->
+    <skip />
+    <!-- no translation found for permgrouplab_microphonewear (1047561180980891136) -->
+    <skip />
+    <!-- no translation found for permgrouplab_camerawear (4543951283103407017) -->
+    <skip />
+    <!-- no translation found for permgrouplab_phonewear (134365036753766126) -->
+    <skip />
+    <!-- no translation found for permgrouplab_sensorswear (1429324744329327663) -->
+    <skip />
+    <!-- no translation found for permlab_statusBarServicewear (2469402818964691034) -->
+    <skip />
+    <!-- no translation found for permlab_bodySensorswear (7857941041202791873) -->
+    <skip />
+    <!-- no translation found for permlab_accessFineLocationwear (5584423486924377563) -->
+    <skip />
+    <!-- no translation found for permlab_accessCoarseLocationwear (5880746016230166090) -->
+    <skip />
+    <!-- no translation found for permlab_sim_communicationwear (1899198085342781874) -->
+    <skip />
+    <!-- no translation found for permlab_createNetworkSocketswear (6467042386273822913) -->
+    <skip />
+    <!-- no translation found for permlab_manageProfileAndDeviceOwnerswear (7313340516937821847) -->
+    <skip />
+    <!-- no translation found for permlab_changeWimaxStatewear (3828470843939853744) -->
+    <skip />
+    <!-- no translation found for permlab_handoverStatuswear (4835786819716499249) -->
+    <skip />
+    <!-- no translation found for permlab_route_media_outputwear (8737024341474587192) -->
+    <skip />
+    <!-- no translation found for permlab_readInstallSessionswear (9059478058685861989) -->
+    <skip />
+    <!-- no translation found for permlab_requestInstallPackageswear (4982025836783539503) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-fr-watch/strings.xml b/core/res/res/values-fr-watch/strings.xml
index 7e616cd..b853188 100644
--- a/core/res/res/values-fr-watch/strings.xml
+++ b/core/res/res/values-fr-watch/strings.xml
@@ -21,4 +21,48 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="android_upgrading_apk" msgid="1090732262010398759">"Appli <xliff:g id="NUMBER_0">%1$d</xliff:g> sur <xliff:g id="NUMBER_1">%2$d</xliff:g>"</string>
+    <!-- no translation found for permgrouplab_sensors (202675452368612754) -->
+    <skip />
+    <!-- no translation found for permgrouplab_contactswear (2340286500790908344) -->
+    <skip />
+    <!-- no translation found for permgrouplab_locationwear (6275317222482780209) -->
+    <skip />
+    <!-- no translation found for permgrouplab_calendarwear (441900844045065081) -->
+    <skip />
+    <!-- no translation found for permgrouplab_smswear (6849506550342974220) -->
+    <skip />
+    <!-- no translation found for permgrouplab_storagewear (1003807594193602313) -->
+    <skip />
+    <!-- no translation found for permgrouplab_microphonewear (1047561180980891136) -->
+    <skip />
+    <!-- no translation found for permgrouplab_camerawear (4543951283103407017) -->
+    <skip />
+    <!-- no translation found for permgrouplab_phonewear (134365036753766126) -->
+    <skip />
+    <!-- no translation found for permgrouplab_sensorswear (1429324744329327663) -->
+    <skip />
+    <!-- no translation found for permlab_statusBarServicewear (2469402818964691034) -->
+    <skip />
+    <!-- no translation found for permlab_bodySensorswear (7857941041202791873) -->
+    <skip />
+    <!-- no translation found for permlab_accessFineLocationwear (5584423486924377563) -->
+    <skip />
+    <!-- no translation found for permlab_accessCoarseLocationwear (5880746016230166090) -->
+    <skip />
+    <!-- no translation found for permlab_sim_communicationwear (1899198085342781874) -->
+    <skip />
+    <!-- no translation found for permlab_createNetworkSocketswear (6467042386273822913) -->
+    <skip />
+    <!-- no translation found for permlab_manageProfileAndDeviceOwnerswear (7313340516937821847) -->
+    <skip />
+    <!-- no translation found for permlab_changeWimaxStatewear (3828470843939853744) -->
+    <skip />
+    <!-- no translation found for permlab_handoverStatuswear (4835786819716499249) -->
+    <skip />
+    <!-- no translation found for permlab_route_media_outputwear (8737024341474587192) -->
+    <skip />
+    <!-- no translation found for permlab_readInstallSessionswear (9059478058685861989) -->
+    <skip />
+    <!-- no translation found for permlab_requestInstallPackageswear (4982025836783539503) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-gl-rES-watch/strings.xml b/core/res/res/values-gl-rES-watch/strings.xml
index d9ea0fe..002bfce 100644
--- a/core/res/res/values-gl-rES-watch/strings.xml
+++ b/core/res/res/values-gl-rES-watch/strings.xml
@@ -21,4 +21,48 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="android_upgrading_apk" msgid="1090732262010398759">"Aplicación <xliff:g id="NUMBER_0">%1$d</xliff:g> de <xliff:g id="NUMBER_1">%2$d</xliff:g>."</string>
+    <!-- no translation found for permgrouplab_sensors (202675452368612754) -->
+    <skip />
+    <!-- no translation found for permgrouplab_contactswear (2340286500790908344) -->
+    <skip />
+    <!-- no translation found for permgrouplab_locationwear (6275317222482780209) -->
+    <skip />
+    <!-- no translation found for permgrouplab_calendarwear (441900844045065081) -->
+    <skip />
+    <!-- no translation found for permgrouplab_smswear (6849506550342974220) -->
+    <skip />
+    <!-- no translation found for permgrouplab_storagewear (1003807594193602313) -->
+    <skip />
+    <!-- no translation found for permgrouplab_microphonewear (1047561180980891136) -->
+    <skip />
+    <!-- no translation found for permgrouplab_camerawear (4543951283103407017) -->
+    <skip />
+    <!-- no translation found for permgrouplab_phonewear (134365036753766126) -->
+    <skip />
+    <!-- no translation found for permgrouplab_sensorswear (1429324744329327663) -->
+    <skip />
+    <!-- no translation found for permlab_statusBarServicewear (2469402818964691034) -->
+    <skip />
+    <!-- no translation found for permlab_bodySensorswear (7857941041202791873) -->
+    <skip />
+    <!-- no translation found for permlab_accessFineLocationwear (5584423486924377563) -->
+    <skip />
+    <!-- no translation found for permlab_accessCoarseLocationwear (5880746016230166090) -->
+    <skip />
+    <!-- no translation found for permlab_sim_communicationwear (1899198085342781874) -->
+    <skip />
+    <!-- no translation found for permlab_createNetworkSocketswear (6467042386273822913) -->
+    <skip />
+    <!-- no translation found for permlab_manageProfileAndDeviceOwnerswear (7313340516937821847) -->
+    <skip />
+    <!-- no translation found for permlab_changeWimaxStatewear (3828470843939853744) -->
+    <skip />
+    <!-- no translation found for permlab_handoverStatuswear (4835786819716499249) -->
+    <skip />
+    <!-- no translation found for permlab_route_media_outputwear (8737024341474587192) -->
+    <skip />
+    <!-- no translation found for permlab_readInstallSessionswear (9059478058685861989) -->
+    <skip />
+    <!-- no translation found for permlab_requestInstallPackageswear (4982025836783539503) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-gu-rIN-watch/strings.xml b/core/res/res/values-gu-rIN-watch/strings.xml
index 3e50335..f607966 100644
--- a/core/res/res/values-gu-rIN-watch/strings.xml
+++ b/core/res/res/values-gu-rIN-watch/strings.xml
@@ -21,4 +21,48 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="android_upgrading_apk" msgid="1090732262010398759">"<xliff:g id="NUMBER_1">%2$d</xliff:g> માંથી <xliff:g id="NUMBER_0">%1$d</xliff:g> એપ્લિકેશન."</string>
+    <!-- no translation found for permgrouplab_sensors (202675452368612754) -->
+    <skip />
+    <!-- no translation found for permgrouplab_contactswear (2340286500790908344) -->
+    <skip />
+    <!-- no translation found for permgrouplab_locationwear (6275317222482780209) -->
+    <skip />
+    <!-- no translation found for permgrouplab_calendarwear (441900844045065081) -->
+    <skip />
+    <!-- no translation found for permgrouplab_smswear (6849506550342974220) -->
+    <skip />
+    <!-- no translation found for permgrouplab_storagewear (1003807594193602313) -->
+    <skip />
+    <!-- no translation found for permgrouplab_microphonewear (1047561180980891136) -->
+    <skip />
+    <!-- no translation found for permgrouplab_camerawear (4543951283103407017) -->
+    <skip />
+    <!-- no translation found for permgrouplab_phonewear (134365036753766126) -->
+    <skip />
+    <!-- no translation found for permgrouplab_sensorswear (1429324744329327663) -->
+    <skip />
+    <!-- no translation found for permlab_statusBarServicewear (2469402818964691034) -->
+    <skip />
+    <!-- no translation found for permlab_bodySensorswear (7857941041202791873) -->
+    <skip />
+    <!-- no translation found for permlab_accessFineLocationwear (5584423486924377563) -->
+    <skip />
+    <!-- no translation found for permlab_accessCoarseLocationwear (5880746016230166090) -->
+    <skip />
+    <!-- no translation found for permlab_sim_communicationwear (1899198085342781874) -->
+    <skip />
+    <!-- no translation found for permlab_createNetworkSocketswear (6467042386273822913) -->
+    <skip />
+    <!-- no translation found for permlab_manageProfileAndDeviceOwnerswear (7313340516937821847) -->
+    <skip />
+    <!-- no translation found for permlab_changeWimaxStatewear (3828470843939853744) -->
+    <skip />
+    <!-- no translation found for permlab_handoverStatuswear (4835786819716499249) -->
+    <skip />
+    <!-- no translation found for permlab_route_media_outputwear (8737024341474587192) -->
+    <skip />
+    <!-- no translation found for permlab_readInstallSessionswear (9059478058685861989) -->
+    <skip />
+    <!-- no translation found for permlab_requestInstallPackageswear (4982025836783539503) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-hi-watch/strings.xml b/core/res/res/values-hi-watch/strings.xml
index 148dab4..ead4d60 100644
--- a/core/res/res/values-hi-watch/strings.xml
+++ b/core/res/res/values-hi-watch/strings.xml
@@ -21,4 +21,48 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="android_upgrading_apk" msgid="1090732262010398759">"<xliff:g id="NUMBER_1">%2$d</xliff:g> में से <xliff:g id="NUMBER_0">%1$d</xliff:g> ऐप."</string>
+    <!-- no translation found for permgrouplab_sensors (202675452368612754) -->
+    <skip />
+    <!-- no translation found for permgrouplab_contactswear (2340286500790908344) -->
+    <skip />
+    <!-- no translation found for permgrouplab_locationwear (6275317222482780209) -->
+    <skip />
+    <!-- no translation found for permgrouplab_calendarwear (441900844045065081) -->
+    <skip />
+    <!-- no translation found for permgrouplab_smswear (6849506550342974220) -->
+    <skip />
+    <!-- no translation found for permgrouplab_storagewear (1003807594193602313) -->
+    <skip />
+    <!-- no translation found for permgrouplab_microphonewear (1047561180980891136) -->
+    <skip />
+    <!-- no translation found for permgrouplab_camerawear (4543951283103407017) -->
+    <skip />
+    <!-- no translation found for permgrouplab_phonewear (134365036753766126) -->
+    <skip />
+    <!-- no translation found for permgrouplab_sensorswear (1429324744329327663) -->
+    <skip />
+    <!-- no translation found for permlab_statusBarServicewear (2469402818964691034) -->
+    <skip />
+    <!-- no translation found for permlab_bodySensorswear (7857941041202791873) -->
+    <skip />
+    <!-- no translation found for permlab_accessFineLocationwear (5584423486924377563) -->
+    <skip />
+    <!-- no translation found for permlab_accessCoarseLocationwear (5880746016230166090) -->
+    <skip />
+    <!-- no translation found for permlab_sim_communicationwear (1899198085342781874) -->
+    <skip />
+    <!-- no translation found for permlab_createNetworkSocketswear (6467042386273822913) -->
+    <skip />
+    <!-- no translation found for permlab_manageProfileAndDeviceOwnerswear (7313340516937821847) -->
+    <skip />
+    <!-- no translation found for permlab_changeWimaxStatewear (3828470843939853744) -->
+    <skip />
+    <!-- no translation found for permlab_handoverStatuswear (4835786819716499249) -->
+    <skip />
+    <!-- no translation found for permlab_route_media_outputwear (8737024341474587192) -->
+    <skip />
+    <!-- no translation found for permlab_readInstallSessionswear (9059478058685861989) -->
+    <skip />
+    <!-- no translation found for permlab_requestInstallPackageswear (4982025836783539503) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-hr-watch/strings.xml b/core/res/res/values-hr-watch/strings.xml
index 4b88ac7..7e65f07 100644
--- a/core/res/res/values-hr-watch/strings.xml
+++ b/core/res/res/values-hr-watch/strings.xml
@@ -21,4 +21,48 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="android_upgrading_apk" msgid="1090732262010398759">"Aplikacija <xliff:g id="NUMBER_0">%1$d</xliff:g> od <xliff:g id="NUMBER_1">%2$d</xliff:g>."</string>
+    <!-- no translation found for permgrouplab_sensors (202675452368612754) -->
+    <skip />
+    <!-- no translation found for permgrouplab_contactswear (2340286500790908344) -->
+    <skip />
+    <!-- no translation found for permgrouplab_locationwear (6275317222482780209) -->
+    <skip />
+    <!-- no translation found for permgrouplab_calendarwear (441900844045065081) -->
+    <skip />
+    <!-- no translation found for permgrouplab_smswear (6849506550342974220) -->
+    <skip />
+    <!-- no translation found for permgrouplab_storagewear (1003807594193602313) -->
+    <skip />
+    <!-- no translation found for permgrouplab_microphonewear (1047561180980891136) -->
+    <skip />
+    <!-- no translation found for permgrouplab_camerawear (4543951283103407017) -->
+    <skip />
+    <!-- no translation found for permgrouplab_phonewear (134365036753766126) -->
+    <skip />
+    <!-- no translation found for permgrouplab_sensorswear (1429324744329327663) -->
+    <skip />
+    <!-- no translation found for permlab_statusBarServicewear (2469402818964691034) -->
+    <skip />
+    <!-- no translation found for permlab_bodySensorswear (7857941041202791873) -->
+    <skip />
+    <!-- no translation found for permlab_accessFineLocationwear (5584423486924377563) -->
+    <skip />
+    <!-- no translation found for permlab_accessCoarseLocationwear (5880746016230166090) -->
+    <skip />
+    <!-- no translation found for permlab_sim_communicationwear (1899198085342781874) -->
+    <skip />
+    <!-- no translation found for permlab_createNetworkSocketswear (6467042386273822913) -->
+    <skip />
+    <!-- no translation found for permlab_manageProfileAndDeviceOwnerswear (7313340516937821847) -->
+    <skip />
+    <!-- no translation found for permlab_changeWimaxStatewear (3828470843939853744) -->
+    <skip />
+    <!-- no translation found for permlab_handoverStatuswear (4835786819716499249) -->
+    <skip />
+    <!-- no translation found for permlab_route_media_outputwear (8737024341474587192) -->
+    <skip />
+    <!-- no translation found for permlab_readInstallSessionswear (9059478058685861989) -->
+    <skip />
+    <!-- no translation found for permlab_requestInstallPackageswear (4982025836783539503) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-hu-watch/strings.xml b/core/res/res/values-hu-watch/strings.xml
index 9f2e97f..aa72468 100644
--- a/core/res/res/values-hu-watch/strings.xml
+++ b/core/res/res/values-hu-watch/strings.xml
@@ -21,4 +21,48 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="android_upgrading_apk" msgid="1090732262010398759">"<xliff:g id="NUMBER_0">%1$d</xliff:g>/<xliff:g id="NUMBER_1">%2$d</xliff:g>. alkalmazás"</string>
+    <!-- no translation found for permgrouplab_sensors (202675452368612754) -->
+    <skip />
+    <!-- no translation found for permgrouplab_contactswear (2340286500790908344) -->
+    <skip />
+    <!-- no translation found for permgrouplab_locationwear (6275317222482780209) -->
+    <skip />
+    <!-- no translation found for permgrouplab_calendarwear (441900844045065081) -->
+    <skip />
+    <!-- no translation found for permgrouplab_smswear (6849506550342974220) -->
+    <skip />
+    <!-- no translation found for permgrouplab_storagewear (1003807594193602313) -->
+    <skip />
+    <!-- no translation found for permgrouplab_microphonewear (1047561180980891136) -->
+    <skip />
+    <!-- no translation found for permgrouplab_camerawear (4543951283103407017) -->
+    <skip />
+    <!-- no translation found for permgrouplab_phonewear (134365036753766126) -->
+    <skip />
+    <!-- no translation found for permgrouplab_sensorswear (1429324744329327663) -->
+    <skip />
+    <!-- no translation found for permlab_statusBarServicewear (2469402818964691034) -->
+    <skip />
+    <!-- no translation found for permlab_bodySensorswear (7857941041202791873) -->
+    <skip />
+    <!-- no translation found for permlab_accessFineLocationwear (5584423486924377563) -->
+    <skip />
+    <!-- no translation found for permlab_accessCoarseLocationwear (5880746016230166090) -->
+    <skip />
+    <!-- no translation found for permlab_sim_communicationwear (1899198085342781874) -->
+    <skip />
+    <!-- no translation found for permlab_createNetworkSocketswear (6467042386273822913) -->
+    <skip />
+    <!-- no translation found for permlab_manageProfileAndDeviceOwnerswear (7313340516937821847) -->
+    <skip />
+    <!-- no translation found for permlab_changeWimaxStatewear (3828470843939853744) -->
+    <skip />
+    <!-- no translation found for permlab_handoverStatuswear (4835786819716499249) -->
+    <skip />
+    <!-- no translation found for permlab_route_media_outputwear (8737024341474587192) -->
+    <skip />
+    <!-- no translation found for permlab_readInstallSessionswear (9059478058685861989) -->
+    <skip />
+    <!-- no translation found for permlab_requestInstallPackageswear (4982025836783539503) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-hy-rAM-watch/strings.xml b/core/res/res/values-hy-rAM-watch/strings.xml
index 265268e..28617cb 100644
--- a/core/res/res/values-hy-rAM-watch/strings.xml
+++ b/core/res/res/values-hy-rAM-watch/strings.xml
@@ -21,4 +21,48 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="android_upgrading_apk" msgid="1090732262010398759">"Հավելված <xliff:g id="NUMBER_0">%1$d</xliff:g>՝ <xliff:g id="NUMBER_1">%2$d</xliff:g>-ից:"</string>
+    <!-- no translation found for permgrouplab_sensors (202675452368612754) -->
+    <skip />
+    <!-- no translation found for permgrouplab_contactswear (2340286500790908344) -->
+    <skip />
+    <!-- no translation found for permgrouplab_locationwear (6275317222482780209) -->
+    <skip />
+    <!-- no translation found for permgrouplab_calendarwear (441900844045065081) -->
+    <skip />
+    <!-- no translation found for permgrouplab_smswear (6849506550342974220) -->
+    <skip />
+    <!-- no translation found for permgrouplab_storagewear (1003807594193602313) -->
+    <skip />
+    <!-- no translation found for permgrouplab_microphonewear (1047561180980891136) -->
+    <skip />
+    <!-- no translation found for permgrouplab_camerawear (4543951283103407017) -->
+    <skip />
+    <!-- no translation found for permgrouplab_phonewear (134365036753766126) -->
+    <skip />
+    <!-- no translation found for permgrouplab_sensorswear (1429324744329327663) -->
+    <skip />
+    <!-- no translation found for permlab_statusBarServicewear (2469402818964691034) -->
+    <skip />
+    <!-- no translation found for permlab_bodySensorswear (7857941041202791873) -->
+    <skip />
+    <!-- no translation found for permlab_accessFineLocationwear (5584423486924377563) -->
+    <skip />
+    <!-- no translation found for permlab_accessCoarseLocationwear (5880746016230166090) -->
+    <skip />
+    <!-- no translation found for permlab_sim_communicationwear (1899198085342781874) -->
+    <skip />
+    <!-- no translation found for permlab_createNetworkSocketswear (6467042386273822913) -->
+    <skip />
+    <!-- no translation found for permlab_manageProfileAndDeviceOwnerswear (7313340516937821847) -->
+    <skip />
+    <!-- no translation found for permlab_changeWimaxStatewear (3828470843939853744) -->
+    <skip />
+    <!-- no translation found for permlab_handoverStatuswear (4835786819716499249) -->
+    <skip />
+    <!-- no translation found for permlab_route_media_outputwear (8737024341474587192) -->
+    <skip />
+    <!-- no translation found for permlab_readInstallSessionswear (9059478058685861989) -->
+    <skip />
+    <!-- no translation found for permlab_requestInstallPackageswear (4982025836783539503) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-in-watch/strings.xml b/core/res/res/values-in-watch/strings.xml
index 947a7f1..b0b22e7 100644
--- a/core/res/res/values-in-watch/strings.xml
+++ b/core/res/res/values-in-watch/strings.xml
@@ -21,4 +21,48 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="android_upgrading_apk" msgid="1090732262010398759">"Aplikasi <xliff:g id="NUMBER_0">%1$d</xliff:g> dari <xliff:g id="NUMBER_1">%2$d</xliff:g>."</string>
+    <!-- no translation found for permgrouplab_sensors (202675452368612754) -->
+    <skip />
+    <!-- no translation found for permgrouplab_contactswear (2340286500790908344) -->
+    <skip />
+    <!-- no translation found for permgrouplab_locationwear (6275317222482780209) -->
+    <skip />
+    <!-- no translation found for permgrouplab_calendarwear (441900844045065081) -->
+    <skip />
+    <!-- no translation found for permgrouplab_smswear (6849506550342974220) -->
+    <skip />
+    <!-- no translation found for permgrouplab_storagewear (1003807594193602313) -->
+    <skip />
+    <!-- no translation found for permgrouplab_microphonewear (1047561180980891136) -->
+    <skip />
+    <!-- no translation found for permgrouplab_camerawear (4543951283103407017) -->
+    <skip />
+    <!-- no translation found for permgrouplab_phonewear (134365036753766126) -->
+    <skip />
+    <!-- no translation found for permgrouplab_sensorswear (1429324744329327663) -->
+    <skip />
+    <!-- no translation found for permlab_statusBarServicewear (2469402818964691034) -->
+    <skip />
+    <!-- no translation found for permlab_bodySensorswear (7857941041202791873) -->
+    <skip />
+    <!-- no translation found for permlab_accessFineLocationwear (5584423486924377563) -->
+    <skip />
+    <!-- no translation found for permlab_accessCoarseLocationwear (5880746016230166090) -->
+    <skip />
+    <!-- no translation found for permlab_sim_communicationwear (1899198085342781874) -->
+    <skip />
+    <!-- no translation found for permlab_createNetworkSocketswear (6467042386273822913) -->
+    <skip />
+    <!-- no translation found for permlab_manageProfileAndDeviceOwnerswear (7313340516937821847) -->
+    <skip />
+    <!-- no translation found for permlab_changeWimaxStatewear (3828470843939853744) -->
+    <skip />
+    <!-- no translation found for permlab_handoverStatuswear (4835786819716499249) -->
+    <skip />
+    <!-- no translation found for permlab_route_media_outputwear (8737024341474587192) -->
+    <skip />
+    <!-- no translation found for permlab_readInstallSessionswear (9059478058685861989) -->
+    <skip />
+    <!-- no translation found for permlab_requestInstallPackageswear (4982025836783539503) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-is-rIS-watch/strings.xml b/core/res/res/values-is-rIS-watch/strings.xml
index cb6da5c..ab82c1c 100644
--- a/core/res/res/values-is-rIS-watch/strings.xml
+++ b/core/res/res/values-is-rIS-watch/strings.xml
@@ -21,4 +21,48 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="android_upgrading_apk" msgid="1090732262010398759">"Forrit <xliff:g id="NUMBER_0">%1$d</xliff:g> af <xliff:g id="NUMBER_1">%2$d</xliff:g>."</string>
+    <!-- no translation found for permgrouplab_sensors (202675452368612754) -->
+    <skip />
+    <!-- no translation found for permgrouplab_contactswear (2340286500790908344) -->
+    <skip />
+    <!-- no translation found for permgrouplab_locationwear (6275317222482780209) -->
+    <skip />
+    <!-- no translation found for permgrouplab_calendarwear (441900844045065081) -->
+    <skip />
+    <!-- no translation found for permgrouplab_smswear (6849506550342974220) -->
+    <skip />
+    <!-- no translation found for permgrouplab_storagewear (1003807594193602313) -->
+    <skip />
+    <!-- no translation found for permgrouplab_microphonewear (1047561180980891136) -->
+    <skip />
+    <!-- no translation found for permgrouplab_camerawear (4543951283103407017) -->
+    <skip />
+    <!-- no translation found for permgrouplab_phonewear (134365036753766126) -->
+    <skip />
+    <!-- no translation found for permgrouplab_sensorswear (1429324744329327663) -->
+    <skip />
+    <!-- no translation found for permlab_statusBarServicewear (2469402818964691034) -->
+    <skip />
+    <!-- no translation found for permlab_bodySensorswear (7857941041202791873) -->
+    <skip />
+    <!-- no translation found for permlab_accessFineLocationwear (5584423486924377563) -->
+    <skip />
+    <!-- no translation found for permlab_accessCoarseLocationwear (5880746016230166090) -->
+    <skip />
+    <!-- no translation found for permlab_sim_communicationwear (1899198085342781874) -->
+    <skip />
+    <!-- no translation found for permlab_createNetworkSocketswear (6467042386273822913) -->
+    <skip />
+    <!-- no translation found for permlab_manageProfileAndDeviceOwnerswear (7313340516937821847) -->
+    <skip />
+    <!-- no translation found for permlab_changeWimaxStatewear (3828470843939853744) -->
+    <skip />
+    <!-- no translation found for permlab_handoverStatuswear (4835786819716499249) -->
+    <skip />
+    <!-- no translation found for permlab_route_media_outputwear (8737024341474587192) -->
+    <skip />
+    <!-- no translation found for permlab_readInstallSessionswear (9059478058685861989) -->
+    <skip />
+    <!-- no translation found for permlab_requestInstallPackageswear (4982025836783539503) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-it-watch/strings.xml b/core/res/res/values-it-watch/strings.xml
index a042221..111c2a2 100644
--- a/core/res/res/values-it-watch/strings.xml
+++ b/core/res/res/values-it-watch/strings.xml
@@ -21,4 +21,48 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="android_upgrading_apk" msgid="1090732262010398759">"App <xliff:g id="NUMBER_0">%1$d</xliff:g> di <xliff:g id="NUMBER_1">%2$d</xliff:g>."</string>
+    <!-- no translation found for permgrouplab_sensors (202675452368612754) -->
+    <skip />
+    <!-- no translation found for permgrouplab_contactswear (2340286500790908344) -->
+    <skip />
+    <!-- no translation found for permgrouplab_locationwear (6275317222482780209) -->
+    <skip />
+    <!-- no translation found for permgrouplab_calendarwear (441900844045065081) -->
+    <skip />
+    <!-- no translation found for permgrouplab_smswear (6849506550342974220) -->
+    <skip />
+    <!-- no translation found for permgrouplab_storagewear (1003807594193602313) -->
+    <skip />
+    <!-- no translation found for permgrouplab_microphonewear (1047561180980891136) -->
+    <skip />
+    <!-- no translation found for permgrouplab_camerawear (4543951283103407017) -->
+    <skip />
+    <!-- no translation found for permgrouplab_phonewear (134365036753766126) -->
+    <skip />
+    <!-- no translation found for permgrouplab_sensorswear (1429324744329327663) -->
+    <skip />
+    <!-- no translation found for permlab_statusBarServicewear (2469402818964691034) -->
+    <skip />
+    <!-- no translation found for permlab_bodySensorswear (7857941041202791873) -->
+    <skip />
+    <!-- no translation found for permlab_accessFineLocationwear (5584423486924377563) -->
+    <skip />
+    <!-- no translation found for permlab_accessCoarseLocationwear (5880746016230166090) -->
+    <skip />
+    <!-- no translation found for permlab_sim_communicationwear (1899198085342781874) -->
+    <skip />
+    <!-- no translation found for permlab_createNetworkSocketswear (6467042386273822913) -->
+    <skip />
+    <!-- no translation found for permlab_manageProfileAndDeviceOwnerswear (7313340516937821847) -->
+    <skip />
+    <!-- no translation found for permlab_changeWimaxStatewear (3828470843939853744) -->
+    <skip />
+    <!-- no translation found for permlab_handoverStatuswear (4835786819716499249) -->
+    <skip />
+    <!-- no translation found for permlab_route_media_outputwear (8737024341474587192) -->
+    <skip />
+    <!-- no translation found for permlab_readInstallSessionswear (9059478058685861989) -->
+    <skip />
+    <!-- no translation found for permlab_requestInstallPackageswear (4982025836783539503) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-iw-watch/strings.xml b/core/res/res/values-iw-watch/strings.xml
index 64b194d..d0b4943 100644
--- a/core/res/res/values-iw-watch/strings.xml
+++ b/core/res/res/values-iw-watch/strings.xml
@@ -21,4 +21,48 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="android_upgrading_apk" msgid="1090732262010398759">"אפליקציה <xliff:g id="NUMBER_0">%1$d</xliff:g> מתוך <xliff:g id="NUMBER_1">%2$d</xliff:g>."</string>
+    <!-- no translation found for permgrouplab_sensors (202675452368612754) -->
+    <skip />
+    <!-- no translation found for permgrouplab_contactswear (2340286500790908344) -->
+    <skip />
+    <!-- no translation found for permgrouplab_locationwear (6275317222482780209) -->
+    <skip />
+    <!-- no translation found for permgrouplab_calendarwear (441900844045065081) -->
+    <skip />
+    <!-- no translation found for permgrouplab_smswear (6849506550342974220) -->
+    <skip />
+    <!-- no translation found for permgrouplab_storagewear (1003807594193602313) -->
+    <skip />
+    <!-- no translation found for permgrouplab_microphonewear (1047561180980891136) -->
+    <skip />
+    <!-- no translation found for permgrouplab_camerawear (4543951283103407017) -->
+    <skip />
+    <!-- no translation found for permgrouplab_phonewear (134365036753766126) -->
+    <skip />
+    <!-- no translation found for permgrouplab_sensorswear (1429324744329327663) -->
+    <skip />
+    <!-- no translation found for permlab_statusBarServicewear (2469402818964691034) -->
+    <skip />
+    <!-- no translation found for permlab_bodySensorswear (7857941041202791873) -->
+    <skip />
+    <!-- no translation found for permlab_accessFineLocationwear (5584423486924377563) -->
+    <skip />
+    <!-- no translation found for permlab_accessCoarseLocationwear (5880746016230166090) -->
+    <skip />
+    <!-- no translation found for permlab_sim_communicationwear (1899198085342781874) -->
+    <skip />
+    <!-- no translation found for permlab_createNetworkSocketswear (6467042386273822913) -->
+    <skip />
+    <!-- no translation found for permlab_manageProfileAndDeviceOwnerswear (7313340516937821847) -->
+    <skip />
+    <!-- no translation found for permlab_changeWimaxStatewear (3828470843939853744) -->
+    <skip />
+    <!-- no translation found for permlab_handoverStatuswear (4835786819716499249) -->
+    <skip />
+    <!-- no translation found for permlab_route_media_outputwear (8737024341474587192) -->
+    <skip />
+    <!-- no translation found for permlab_readInstallSessionswear (9059478058685861989) -->
+    <skip />
+    <!-- no translation found for permlab_requestInstallPackageswear (4982025836783539503) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-ja-watch/strings.xml b/core/res/res/values-ja-watch/strings.xml
index b3c6d97..ec1257ef 100644
--- a/core/res/res/values-ja-watch/strings.xml
+++ b/core/res/res/values-ja-watch/strings.xml
@@ -21,4 +21,48 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="android_upgrading_apk" msgid="1090732262010398759">"アプリ<xliff:g id="NUMBER_0">%1$d</xliff:g>/<xliff:g id="NUMBER_1">%2$d</xliff:g>"</string>
+    <!-- no translation found for permgrouplab_sensors (202675452368612754) -->
+    <skip />
+    <!-- no translation found for permgrouplab_contactswear (2340286500790908344) -->
+    <skip />
+    <!-- no translation found for permgrouplab_locationwear (6275317222482780209) -->
+    <skip />
+    <!-- no translation found for permgrouplab_calendarwear (441900844045065081) -->
+    <skip />
+    <!-- no translation found for permgrouplab_smswear (6849506550342974220) -->
+    <skip />
+    <!-- no translation found for permgrouplab_storagewear (1003807594193602313) -->
+    <skip />
+    <!-- no translation found for permgrouplab_microphonewear (1047561180980891136) -->
+    <skip />
+    <!-- no translation found for permgrouplab_camerawear (4543951283103407017) -->
+    <skip />
+    <!-- no translation found for permgrouplab_phonewear (134365036753766126) -->
+    <skip />
+    <!-- no translation found for permgrouplab_sensorswear (1429324744329327663) -->
+    <skip />
+    <!-- no translation found for permlab_statusBarServicewear (2469402818964691034) -->
+    <skip />
+    <!-- no translation found for permlab_bodySensorswear (7857941041202791873) -->
+    <skip />
+    <!-- no translation found for permlab_accessFineLocationwear (5584423486924377563) -->
+    <skip />
+    <!-- no translation found for permlab_accessCoarseLocationwear (5880746016230166090) -->
+    <skip />
+    <!-- no translation found for permlab_sim_communicationwear (1899198085342781874) -->
+    <skip />
+    <!-- no translation found for permlab_createNetworkSocketswear (6467042386273822913) -->
+    <skip />
+    <!-- no translation found for permlab_manageProfileAndDeviceOwnerswear (7313340516937821847) -->
+    <skip />
+    <!-- no translation found for permlab_changeWimaxStatewear (3828470843939853744) -->
+    <skip />
+    <!-- no translation found for permlab_handoverStatuswear (4835786819716499249) -->
+    <skip />
+    <!-- no translation found for permlab_route_media_outputwear (8737024341474587192) -->
+    <skip />
+    <!-- no translation found for permlab_readInstallSessionswear (9059478058685861989) -->
+    <skip />
+    <!-- no translation found for permlab_requestInstallPackageswear (4982025836783539503) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-ja/strings.xml b/core/res/res/values-ja/strings.xml
index e43a19c..545b963 100644
--- a/core/res/res/values-ja/strings.xml
+++ b/core/res/res/values-ja/strings.xml
@@ -1024,7 +1024,7 @@
     <string name="usb_ptp_notification_title" msgid="1347328437083192112">"USBを写真転送に使用"</string>
     <string name="usb_midi_notification_title" msgid="4850904915889144654">"USBをMIDIに使用"</string>
     <string name="usb_accessory_notification_title" msgid="7848236974087653666">"USBアクセサリを接続しました"</string>
-    <string name="usb_notification_message" msgid="7347368030849048437">"タップするとその他のオプションが表示されます。"</string>
+    <string name="usb_notification_message" msgid="7347368030849048437">"タップしてその他のオプションを表示"</string>
     <string name="adb_active_notification_title" msgid="6729044778949189918">"USBデバッグが接続されました"</string>
     <string name="adb_active_notification_message" msgid="1016654627626476142">"タップしてUSBデバッグを無効化"</string>
     <string name="select_input_method" msgid="8547250819326693584">"キーボードの変更"</string>
diff --git a/core/res/res/values-ka-rGE-watch/strings.xml b/core/res/res/values-ka-rGE-watch/strings.xml
index 4fe6d11..5aa9aaf 100644
--- a/core/res/res/values-ka-rGE-watch/strings.xml
+++ b/core/res/res/values-ka-rGE-watch/strings.xml
@@ -21,4 +21,48 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="android_upgrading_apk" msgid="1090732262010398759">"აპი <xliff:g id="NUMBER_0">%1$d</xliff:g>, სულ <xliff:g id="NUMBER_1">%2$d</xliff:g>-დან."</string>
+    <!-- no translation found for permgrouplab_sensors (202675452368612754) -->
+    <skip />
+    <!-- no translation found for permgrouplab_contactswear (2340286500790908344) -->
+    <skip />
+    <!-- no translation found for permgrouplab_locationwear (6275317222482780209) -->
+    <skip />
+    <!-- no translation found for permgrouplab_calendarwear (441900844045065081) -->
+    <skip />
+    <!-- no translation found for permgrouplab_smswear (6849506550342974220) -->
+    <skip />
+    <!-- no translation found for permgrouplab_storagewear (1003807594193602313) -->
+    <skip />
+    <!-- no translation found for permgrouplab_microphonewear (1047561180980891136) -->
+    <skip />
+    <!-- no translation found for permgrouplab_camerawear (4543951283103407017) -->
+    <skip />
+    <!-- no translation found for permgrouplab_phonewear (134365036753766126) -->
+    <skip />
+    <!-- no translation found for permgrouplab_sensorswear (1429324744329327663) -->
+    <skip />
+    <!-- no translation found for permlab_statusBarServicewear (2469402818964691034) -->
+    <skip />
+    <!-- no translation found for permlab_bodySensorswear (7857941041202791873) -->
+    <skip />
+    <!-- no translation found for permlab_accessFineLocationwear (5584423486924377563) -->
+    <skip />
+    <!-- no translation found for permlab_accessCoarseLocationwear (5880746016230166090) -->
+    <skip />
+    <!-- no translation found for permlab_sim_communicationwear (1899198085342781874) -->
+    <skip />
+    <!-- no translation found for permlab_createNetworkSocketswear (6467042386273822913) -->
+    <skip />
+    <!-- no translation found for permlab_manageProfileAndDeviceOwnerswear (7313340516937821847) -->
+    <skip />
+    <!-- no translation found for permlab_changeWimaxStatewear (3828470843939853744) -->
+    <skip />
+    <!-- no translation found for permlab_handoverStatuswear (4835786819716499249) -->
+    <skip />
+    <!-- no translation found for permlab_route_media_outputwear (8737024341474587192) -->
+    <skip />
+    <!-- no translation found for permlab_readInstallSessionswear (9059478058685861989) -->
+    <skip />
+    <!-- no translation found for permlab_requestInstallPackageswear (4982025836783539503) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-kk-rKZ-watch/strings.xml b/core/res/res/values-kk-rKZ-watch/strings.xml
index 583eb19..e913230 100644
--- a/core/res/res/values-kk-rKZ-watch/strings.xml
+++ b/core/res/res/values-kk-rKZ-watch/strings.xml
@@ -21,4 +21,48 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="android_upgrading_apk" msgid="1090732262010398759">"<xliff:g id="NUMBER_0">%1$d</xliff:g>/<xliff:g id="NUMBER_1">%2$d</xliff:g> бағдарлама."</string>
+    <!-- no translation found for permgrouplab_sensors (202675452368612754) -->
+    <skip />
+    <!-- no translation found for permgrouplab_contactswear (2340286500790908344) -->
+    <skip />
+    <!-- no translation found for permgrouplab_locationwear (6275317222482780209) -->
+    <skip />
+    <!-- no translation found for permgrouplab_calendarwear (441900844045065081) -->
+    <skip />
+    <!-- no translation found for permgrouplab_smswear (6849506550342974220) -->
+    <skip />
+    <!-- no translation found for permgrouplab_storagewear (1003807594193602313) -->
+    <skip />
+    <!-- no translation found for permgrouplab_microphonewear (1047561180980891136) -->
+    <skip />
+    <!-- no translation found for permgrouplab_camerawear (4543951283103407017) -->
+    <skip />
+    <!-- no translation found for permgrouplab_phonewear (134365036753766126) -->
+    <skip />
+    <!-- no translation found for permgrouplab_sensorswear (1429324744329327663) -->
+    <skip />
+    <!-- no translation found for permlab_statusBarServicewear (2469402818964691034) -->
+    <skip />
+    <!-- no translation found for permlab_bodySensorswear (7857941041202791873) -->
+    <skip />
+    <!-- no translation found for permlab_accessFineLocationwear (5584423486924377563) -->
+    <skip />
+    <!-- no translation found for permlab_accessCoarseLocationwear (5880746016230166090) -->
+    <skip />
+    <!-- no translation found for permlab_sim_communicationwear (1899198085342781874) -->
+    <skip />
+    <!-- no translation found for permlab_createNetworkSocketswear (6467042386273822913) -->
+    <skip />
+    <!-- no translation found for permlab_manageProfileAndDeviceOwnerswear (7313340516937821847) -->
+    <skip />
+    <!-- no translation found for permlab_changeWimaxStatewear (3828470843939853744) -->
+    <skip />
+    <!-- no translation found for permlab_handoverStatuswear (4835786819716499249) -->
+    <skip />
+    <!-- no translation found for permlab_route_media_outputwear (8737024341474587192) -->
+    <skip />
+    <!-- no translation found for permlab_readInstallSessionswear (9059478058685861989) -->
+    <skip />
+    <!-- no translation found for permlab_requestInstallPackageswear (4982025836783539503) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-km-rKH-watch/strings.xml b/core/res/res/values-km-rKH-watch/strings.xml
index 2b7e12f..01731f3 100644
--- a/core/res/res/values-km-rKH-watch/strings.xml
+++ b/core/res/res/values-km-rKH-watch/strings.xml
@@ -21,4 +21,48 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="android_upgrading_apk" msgid="1090732262010398759">"កម្មវិធី <xliff:g id="NUMBER_0">%1$d</xliff:g> នៃ <xliff:g id="NUMBER_1">%2$d</xliff:g>។"</string>
+    <!-- no translation found for permgrouplab_sensors (202675452368612754) -->
+    <skip />
+    <!-- no translation found for permgrouplab_contactswear (2340286500790908344) -->
+    <skip />
+    <!-- no translation found for permgrouplab_locationwear (6275317222482780209) -->
+    <skip />
+    <!-- no translation found for permgrouplab_calendarwear (441900844045065081) -->
+    <skip />
+    <!-- no translation found for permgrouplab_smswear (6849506550342974220) -->
+    <skip />
+    <!-- no translation found for permgrouplab_storagewear (1003807594193602313) -->
+    <skip />
+    <!-- no translation found for permgrouplab_microphonewear (1047561180980891136) -->
+    <skip />
+    <!-- no translation found for permgrouplab_camerawear (4543951283103407017) -->
+    <skip />
+    <!-- no translation found for permgrouplab_phonewear (134365036753766126) -->
+    <skip />
+    <!-- no translation found for permgrouplab_sensorswear (1429324744329327663) -->
+    <skip />
+    <!-- no translation found for permlab_statusBarServicewear (2469402818964691034) -->
+    <skip />
+    <!-- no translation found for permlab_bodySensorswear (7857941041202791873) -->
+    <skip />
+    <!-- no translation found for permlab_accessFineLocationwear (5584423486924377563) -->
+    <skip />
+    <!-- no translation found for permlab_accessCoarseLocationwear (5880746016230166090) -->
+    <skip />
+    <!-- no translation found for permlab_sim_communicationwear (1899198085342781874) -->
+    <skip />
+    <!-- no translation found for permlab_createNetworkSocketswear (6467042386273822913) -->
+    <skip />
+    <!-- no translation found for permlab_manageProfileAndDeviceOwnerswear (7313340516937821847) -->
+    <skip />
+    <!-- no translation found for permlab_changeWimaxStatewear (3828470843939853744) -->
+    <skip />
+    <!-- no translation found for permlab_handoverStatuswear (4835786819716499249) -->
+    <skip />
+    <!-- no translation found for permlab_route_media_outputwear (8737024341474587192) -->
+    <skip />
+    <!-- no translation found for permlab_readInstallSessionswear (9059478058685861989) -->
+    <skip />
+    <!-- no translation found for permlab_requestInstallPackageswear (4982025836783539503) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-kn-rIN-watch/strings.xml b/core/res/res/values-kn-rIN-watch/strings.xml
index e01cee1..ea010b3 100644
--- a/core/res/res/values-kn-rIN-watch/strings.xml
+++ b/core/res/res/values-kn-rIN-watch/strings.xml
@@ -21,4 +21,48 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="android_upgrading_apk" msgid="1090732262010398759">"<xliff:g id="NUMBER_1">%2$d</xliff:g> ರಲ್ಲಿ <xliff:g id="NUMBER_0">%1$d</xliff:g> ಅಪ್ಲಿಕೇಶನ್."</string>
+    <!-- no translation found for permgrouplab_sensors (202675452368612754) -->
+    <skip />
+    <!-- no translation found for permgrouplab_contactswear (2340286500790908344) -->
+    <skip />
+    <!-- no translation found for permgrouplab_locationwear (6275317222482780209) -->
+    <skip />
+    <!-- no translation found for permgrouplab_calendarwear (441900844045065081) -->
+    <skip />
+    <!-- no translation found for permgrouplab_smswear (6849506550342974220) -->
+    <skip />
+    <!-- no translation found for permgrouplab_storagewear (1003807594193602313) -->
+    <skip />
+    <!-- no translation found for permgrouplab_microphonewear (1047561180980891136) -->
+    <skip />
+    <!-- no translation found for permgrouplab_camerawear (4543951283103407017) -->
+    <skip />
+    <!-- no translation found for permgrouplab_phonewear (134365036753766126) -->
+    <skip />
+    <!-- no translation found for permgrouplab_sensorswear (1429324744329327663) -->
+    <skip />
+    <!-- no translation found for permlab_statusBarServicewear (2469402818964691034) -->
+    <skip />
+    <!-- no translation found for permlab_bodySensorswear (7857941041202791873) -->
+    <skip />
+    <!-- no translation found for permlab_accessFineLocationwear (5584423486924377563) -->
+    <skip />
+    <!-- no translation found for permlab_accessCoarseLocationwear (5880746016230166090) -->
+    <skip />
+    <!-- no translation found for permlab_sim_communicationwear (1899198085342781874) -->
+    <skip />
+    <!-- no translation found for permlab_createNetworkSocketswear (6467042386273822913) -->
+    <skip />
+    <!-- no translation found for permlab_manageProfileAndDeviceOwnerswear (7313340516937821847) -->
+    <skip />
+    <!-- no translation found for permlab_changeWimaxStatewear (3828470843939853744) -->
+    <skip />
+    <!-- no translation found for permlab_handoverStatuswear (4835786819716499249) -->
+    <skip />
+    <!-- no translation found for permlab_route_media_outputwear (8737024341474587192) -->
+    <skip />
+    <!-- no translation found for permlab_readInstallSessionswear (9059478058685861989) -->
+    <skip />
+    <!-- no translation found for permlab_requestInstallPackageswear (4982025836783539503) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-ko-watch/strings.xml b/core/res/res/values-ko-watch/strings.xml
index df3288b..985f401 100644
--- a/core/res/res/values-ko-watch/strings.xml
+++ b/core/res/res/values-ko-watch/strings.xml
@@ -21,4 +21,48 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="android_upgrading_apk" msgid="1090732262010398759">"앱 <xliff:g id="NUMBER_1">%2$d</xliff:g>개 중 <xliff:g id="NUMBER_0">%1$d</xliff:g>개"</string>
+    <!-- no translation found for permgrouplab_sensors (202675452368612754) -->
+    <skip />
+    <!-- no translation found for permgrouplab_contactswear (2340286500790908344) -->
+    <skip />
+    <!-- no translation found for permgrouplab_locationwear (6275317222482780209) -->
+    <skip />
+    <!-- no translation found for permgrouplab_calendarwear (441900844045065081) -->
+    <skip />
+    <!-- no translation found for permgrouplab_smswear (6849506550342974220) -->
+    <skip />
+    <!-- no translation found for permgrouplab_storagewear (1003807594193602313) -->
+    <skip />
+    <!-- no translation found for permgrouplab_microphonewear (1047561180980891136) -->
+    <skip />
+    <!-- no translation found for permgrouplab_camerawear (4543951283103407017) -->
+    <skip />
+    <!-- no translation found for permgrouplab_phonewear (134365036753766126) -->
+    <skip />
+    <!-- no translation found for permgrouplab_sensorswear (1429324744329327663) -->
+    <skip />
+    <!-- no translation found for permlab_statusBarServicewear (2469402818964691034) -->
+    <skip />
+    <!-- no translation found for permlab_bodySensorswear (7857941041202791873) -->
+    <skip />
+    <!-- no translation found for permlab_accessFineLocationwear (5584423486924377563) -->
+    <skip />
+    <!-- no translation found for permlab_accessCoarseLocationwear (5880746016230166090) -->
+    <skip />
+    <!-- no translation found for permlab_sim_communicationwear (1899198085342781874) -->
+    <skip />
+    <!-- no translation found for permlab_createNetworkSocketswear (6467042386273822913) -->
+    <skip />
+    <!-- no translation found for permlab_manageProfileAndDeviceOwnerswear (7313340516937821847) -->
+    <skip />
+    <!-- no translation found for permlab_changeWimaxStatewear (3828470843939853744) -->
+    <skip />
+    <!-- no translation found for permlab_handoverStatuswear (4835786819716499249) -->
+    <skip />
+    <!-- no translation found for permlab_route_media_outputwear (8737024341474587192) -->
+    <skip />
+    <!-- no translation found for permlab_readInstallSessionswear (9059478058685861989) -->
+    <skip />
+    <!-- no translation found for permlab_requestInstallPackageswear (4982025836783539503) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-ky-rKG-watch/strings.xml b/core/res/res/values-ky-rKG-watch/strings.xml
index 3f167ac..3c708961 100644
--- a/core/res/res/values-ky-rKG-watch/strings.xml
+++ b/core/res/res/values-ky-rKG-watch/strings.xml
@@ -21,4 +21,48 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="android_upgrading_apk" msgid="1090732262010398759">"<xliff:g id="NUMBER_1">%2$d</xliff:g> ичинен <xliff:g id="NUMBER_0">%1$d</xliff:g> колднм."</string>
+    <!-- no translation found for permgrouplab_sensors (202675452368612754) -->
+    <skip />
+    <!-- no translation found for permgrouplab_contactswear (2340286500790908344) -->
+    <skip />
+    <!-- no translation found for permgrouplab_locationwear (6275317222482780209) -->
+    <skip />
+    <!-- no translation found for permgrouplab_calendarwear (441900844045065081) -->
+    <skip />
+    <!-- no translation found for permgrouplab_smswear (6849506550342974220) -->
+    <skip />
+    <!-- no translation found for permgrouplab_storagewear (1003807594193602313) -->
+    <skip />
+    <!-- no translation found for permgrouplab_microphonewear (1047561180980891136) -->
+    <skip />
+    <!-- no translation found for permgrouplab_camerawear (4543951283103407017) -->
+    <skip />
+    <!-- no translation found for permgrouplab_phonewear (134365036753766126) -->
+    <skip />
+    <!-- no translation found for permgrouplab_sensorswear (1429324744329327663) -->
+    <skip />
+    <!-- no translation found for permlab_statusBarServicewear (2469402818964691034) -->
+    <skip />
+    <!-- no translation found for permlab_bodySensorswear (7857941041202791873) -->
+    <skip />
+    <!-- no translation found for permlab_accessFineLocationwear (5584423486924377563) -->
+    <skip />
+    <!-- no translation found for permlab_accessCoarseLocationwear (5880746016230166090) -->
+    <skip />
+    <!-- no translation found for permlab_sim_communicationwear (1899198085342781874) -->
+    <skip />
+    <!-- no translation found for permlab_createNetworkSocketswear (6467042386273822913) -->
+    <skip />
+    <!-- no translation found for permlab_manageProfileAndDeviceOwnerswear (7313340516937821847) -->
+    <skip />
+    <!-- no translation found for permlab_changeWimaxStatewear (3828470843939853744) -->
+    <skip />
+    <!-- no translation found for permlab_handoverStatuswear (4835786819716499249) -->
+    <skip />
+    <!-- no translation found for permlab_route_media_outputwear (8737024341474587192) -->
+    <skip />
+    <!-- no translation found for permlab_readInstallSessionswear (9059478058685861989) -->
+    <skip />
+    <!-- no translation found for permlab_requestInstallPackageswear (4982025836783539503) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-lo-rLA-watch/strings.xml b/core/res/res/values-lo-rLA-watch/strings.xml
index a8c9cd2..d7e97fb 100644
--- a/core/res/res/values-lo-rLA-watch/strings.xml
+++ b/core/res/res/values-lo-rLA-watch/strings.xml
@@ -21,4 +21,48 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="android_upgrading_apk" msgid="1090732262010398759">"ແອັບ <xliff:g id="NUMBER_0">%1$d</xliff:g> ໃນ <xliff:g id="NUMBER_1">%2$d</xliff:g>."</string>
+    <!-- no translation found for permgrouplab_sensors (202675452368612754) -->
+    <skip />
+    <!-- no translation found for permgrouplab_contactswear (2340286500790908344) -->
+    <skip />
+    <!-- no translation found for permgrouplab_locationwear (6275317222482780209) -->
+    <skip />
+    <!-- no translation found for permgrouplab_calendarwear (441900844045065081) -->
+    <skip />
+    <!-- no translation found for permgrouplab_smswear (6849506550342974220) -->
+    <skip />
+    <!-- no translation found for permgrouplab_storagewear (1003807594193602313) -->
+    <skip />
+    <!-- no translation found for permgrouplab_microphonewear (1047561180980891136) -->
+    <skip />
+    <!-- no translation found for permgrouplab_camerawear (4543951283103407017) -->
+    <skip />
+    <!-- no translation found for permgrouplab_phonewear (134365036753766126) -->
+    <skip />
+    <!-- no translation found for permgrouplab_sensorswear (1429324744329327663) -->
+    <skip />
+    <!-- no translation found for permlab_statusBarServicewear (2469402818964691034) -->
+    <skip />
+    <!-- no translation found for permlab_bodySensorswear (7857941041202791873) -->
+    <skip />
+    <!-- no translation found for permlab_accessFineLocationwear (5584423486924377563) -->
+    <skip />
+    <!-- no translation found for permlab_accessCoarseLocationwear (5880746016230166090) -->
+    <skip />
+    <!-- no translation found for permlab_sim_communicationwear (1899198085342781874) -->
+    <skip />
+    <!-- no translation found for permlab_createNetworkSocketswear (6467042386273822913) -->
+    <skip />
+    <!-- no translation found for permlab_manageProfileAndDeviceOwnerswear (7313340516937821847) -->
+    <skip />
+    <!-- no translation found for permlab_changeWimaxStatewear (3828470843939853744) -->
+    <skip />
+    <!-- no translation found for permlab_handoverStatuswear (4835786819716499249) -->
+    <skip />
+    <!-- no translation found for permlab_route_media_outputwear (8737024341474587192) -->
+    <skip />
+    <!-- no translation found for permlab_readInstallSessionswear (9059478058685861989) -->
+    <skip />
+    <!-- no translation found for permlab_requestInstallPackageswear (4982025836783539503) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-lt-watch/strings.xml b/core/res/res/values-lt-watch/strings.xml
index ed8ccdb..bf32040 100644
--- a/core/res/res/values-lt-watch/strings.xml
+++ b/core/res/res/values-lt-watch/strings.xml
@@ -21,4 +21,48 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="android_upgrading_apk" msgid="1090732262010398759">"<xliff:g id="NUMBER_0">%1$d</xliff:g> programa iš <xliff:g id="NUMBER_1">%2$d</xliff:g>."</string>
+    <!-- no translation found for permgrouplab_sensors (202675452368612754) -->
+    <skip />
+    <!-- no translation found for permgrouplab_contactswear (2340286500790908344) -->
+    <skip />
+    <!-- no translation found for permgrouplab_locationwear (6275317222482780209) -->
+    <skip />
+    <!-- no translation found for permgrouplab_calendarwear (441900844045065081) -->
+    <skip />
+    <!-- no translation found for permgrouplab_smswear (6849506550342974220) -->
+    <skip />
+    <!-- no translation found for permgrouplab_storagewear (1003807594193602313) -->
+    <skip />
+    <!-- no translation found for permgrouplab_microphonewear (1047561180980891136) -->
+    <skip />
+    <!-- no translation found for permgrouplab_camerawear (4543951283103407017) -->
+    <skip />
+    <!-- no translation found for permgrouplab_phonewear (134365036753766126) -->
+    <skip />
+    <!-- no translation found for permgrouplab_sensorswear (1429324744329327663) -->
+    <skip />
+    <!-- no translation found for permlab_statusBarServicewear (2469402818964691034) -->
+    <skip />
+    <!-- no translation found for permlab_bodySensorswear (7857941041202791873) -->
+    <skip />
+    <!-- no translation found for permlab_accessFineLocationwear (5584423486924377563) -->
+    <skip />
+    <!-- no translation found for permlab_accessCoarseLocationwear (5880746016230166090) -->
+    <skip />
+    <!-- no translation found for permlab_sim_communicationwear (1899198085342781874) -->
+    <skip />
+    <!-- no translation found for permlab_createNetworkSocketswear (6467042386273822913) -->
+    <skip />
+    <!-- no translation found for permlab_manageProfileAndDeviceOwnerswear (7313340516937821847) -->
+    <skip />
+    <!-- no translation found for permlab_changeWimaxStatewear (3828470843939853744) -->
+    <skip />
+    <!-- no translation found for permlab_handoverStatuswear (4835786819716499249) -->
+    <skip />
+    <!-- no translation found for permlab_route_media_outputwear (8737024341474587192) -->
+    <skip />
+    <!-- no translation found for permlab_readInstallSessionswear (9059478058685861989) -->
+    <skip />
+    <!-- no translation found for permlab_requestInstallPackageswear (4982025836783539503) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-lv-watch/strings.xml b/core/res/res/values-lv-watch/strings.xml
index a0d051e..3a7fd95 100644
--- a/core/res/res/values-lv-watch/strings.xml
+++ b/core/res/res/values-lv-watch/strings.xml
@@ -21,4 +21,48 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="android_upgrading_apk" msgid="1090732262010398759">"<xliff:g id="NUMBER_0">%1$d</xliff:g>. lietotne no <xliff:g id="NUMBER_1">%2$d</xliff:g>."</string>
+    <!-- no translation found for permgrouplab_sensors (202675452368612754) -->
+    <skip />
+    <!-- no translation found for permgrouplab_contactswear (2340286500790908344) -->
+    <skip />
+    <!-- no translation found for permgrouplab_locationwear (6275317222482780209) -->
+    <skip />
+    <!-- no translation found for permgrouplab_calendarwear (441900844045065081) -->
+    <skip />
+    <!-- no translation found for permgrouplab_smswear (6849506550342974220) -->
+    <skip />
+    <!-- no translation found for permgrouplab_storagewear (1003807594193602313) -->
+    <skip />
+    <!-- no translation found for permgrouplab_microphonewear (1047561180980891136) -->
+    <skip />
+    <!-- no translation found for permgrouplab_camerawear (4543951283103407017) -->
+    <skip />
+    <!-- no translation found for permgrouplab_phonewear (134365036753766126) -->
+    <skip />
+    <!-- no translation found for permgrouplab_sensorswear (1429324744329327663) -->
+    <skip />
+    <!-- no translation found for permlab_statusBarServicewear (2469402818964691034) -->
+    <skip />
+    <!-- no translation found for permlab_bodySensorswear (7857941041202791873) -->
+    <skip />
+    <!-- no translation found for permlab_accessFineLocationwear (5584423486924377563) -->
+    <skip />
+    <!-- no translation found for permlab_accessCoarseLocationwear (5880746016230166090) -->
+    <skip />
+    <!-- no translation found for permlab_sim_communicationwear (1899198085342781874) -->
+    <skip />
+    <!-- no translation found for permlab_createNetworkSocketswear (6467042386273822913) -->
+    <skip />
+    <!-- no translation found for permlab_manageProfileAndDeviceOwnerswear (7313340516937821847) -->
+    <skip />
+    <!-- no translation found for permlab_changeWimaxStatewear (3828470843939853744) -->
+    <skip />
+    <!-- no translation found for permlab_handoverStatuswear (4835786819716499249) -->
+    <skip />
+    <!-- no translation found for permlab_route_media_outputwear (8737024341474587192) -->
+    <skip />
+    <!-- no translation found for permlab_readInstallSessionswear (9059478058685861989) -->
+    <skip />
+    <!-- no translation found for permlab_requestInstallPackageswear (4982025836783539503) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-mk-rMK-watch/strings.xml b/core/res/res/values-mk-rMK-watch/strings.xml
index b4eb51a..5e67a61 100644
--- a/core/res/res/values-mk-rMK-watch/strings.xml
+++ b/core/res/res/values-mk-rMK-watch/strings.xml
@@ -21,4 +21,48 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="android_upgrading_apk" msgid="1090732262010398759">"Апликац. <xliff:g id="NUMBER_0">%1$d</xliff:g> од <xliff:g id="NUMBER_1">%2$d</xliff:g>."</string>
+    <!-- no translation found for permgrouplab_sensors (202675452368612754) -->
+    <skip />
+    <!-- no translation found for permgrouplab_contactswear (2340286500790908344) -->
+    <skip />
+    <!-- no translation found for permgrouplab_locationwear (6275317222482780209) -->
+    <skip />
+    <!-- no translation found for permgrouplab_calendarwear (441900844045065081) -->
+    <skip />
+    <!-- no translation found for permgrouplab_smswear (6849506550342974220) -->
+    <skip />
+    <!-- no translation found for permgrouplab_storagewear (1003807594193602313) -->
+    <skip />
+    <!-- no translation found for permgrouplab_microphonewear (1047561180980891136) -->
+    <skip />
+    <!-- no translation found for permgrouplab_camerawear (4543951283103407017) -->
+    <skip />
+    <!-- no translation found for permgrouplab_phonewear (134365036753766126) -->
+    <skip />
+    <!-- no translation found for permgrouplab_sensorswear (1429324744329327663) -->
+    <skip />
+    <!-- no translation found for permlab_statusBarServicewear (2469402818964691034) -->
+    <skip />
+    <!-- no translation found for permlab_bodySensorswear (7857941041202791873) -->
+    <skip />
+    <!-- no translation found for permlab_accessFineLocationwear (5584423486924377563) -->
+    <skip />
+    <!-- no translation found for permlab_accessCoarseLocationwear (5880746016230166090) -->
+    <skip />
+    <!-- no translation found for permlab_sim_communicationwear (1899198085342781874) -->
+    <skip />
+    <!-- no translation found for permlab_createNetworkSocketswear (6467042386273822913) -->
+    <skip />
+    <!-- no translation found for permlab_manageProfileAndDeviceOwnerswear (7313340516937821847) -->
+    <skip />
+    <!-- no translation found for permlab_changeWimaxStatewear (3828470843939853744) -->
+    <skip />
+    <!-- no translation found for permlab_handoverStatuswear (4835786819716499249) -->
+    <skip />
+    <!-- no translation found for permlab_route_media_outputwear (8737024341474587192) -->
+    <skip />
+    <!-- no translation found for permlab_readInstallSessionswear (9059478058685861989) -->
+    <skip />
+    <!-- no translation found for permlab_requestInstallPackageswear (4982025836783539503) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-ml-rIN-watch/strings.xml b/core/res/res/values-ml-rIN-watch/strings.xml
index 079c42f..c10769e 100644
--- a/core/res/res/values-ml-rIN-watch/strings.xml
+++ b/core/res/res/values-ml-rIN-watch/strings.xml
@@ -21,4 +21,48 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="android_upgrading_apk" msgid="1090732262010398759">"<xliff:g id="NUMBER_0">%1$d</xliff:g> / <xliff:g id="NUMBER_1">%2$d</xliff:g> അപ്ലിക്കേഷൻ."</string>
+    <!-- no translation found for permgrouplab_sensors (202675452368612754) -->
+    <skip />
+    <!-- no translation found for permgrouplab_contactswear (2340286500790908344) -->
+    <skip />
+    <!-- no translation found for permgrouplab_locationwear (6275317222482780209) -->
+    <skip />
+    <!-- no translation found for permgrouplab_calendarwear (441900844045065081) -->
+    <skip />
+    <!-- no translation found for permgrouplab_smswear (6849506550342974220) -->
+    <skip />
+    <!-- no translation found for permgrouplab_storagewear (1003807594193602313) -->
+    <skip />
+    <!-- no translation found for permgrouplab_microphonewear (1047561180980891136) -->
+    <skip />
+    <!-- no translation found for permgrouplab_camerawear (4543951283103407017) -->
+    <skip />
+    <!-- no translation found for permgrouplab_phonewear (134365036753766126) -->
+    <skip />
+    <!-- no translation found for permgrouplab_sensorswear (1429324744329327663) -->
+    <skip />
+    <!-- no translation found for permlab_statusBarServicewear (2469402818964691034) -->
+    <skip />
+    <!-- no translation found for permlab_bodySensorswear (7857941041202791873) -->
+    <skip />
+    <!-- no translation found for permlab_accessFineLocationwear (5584423486924377563) -->
+    <skip />
+    <!-- no translation found for permlab_accessCoarseLocationwear (5880746016230166090) -->
+    <skip />
+    <!-- no translation found for permlab_sim_communicationwear (1899198085342781874) -->
+    <skip />
+    <!-- no translation found for permlab_createNetworkSocketswear (6467042386273822913) -->
+    <skip />
+    <!-- no translation found for permlab_manageProfileAndDeviceOwnerswear (7313340516937821847) -->
+    <skip />
+    <!-- no translation found for permlab_changeWimaxStatewear (3828470843939853744) -->
+    <skip />
+    <!-- no translation found for permlab_handoverStatuswear (4835786819716499249) -->
+    <skip />
+    <!-- no translation found for permlab_route_media_outputwear (8737024341474587192) -->
+    <skip />
+    <!-- no translation found for permlab_readInstallSessionswear (9059478058685861989) -->
+    <skip />
+    <!-- no translation found for permlab_requestInstallPackageswear (4982025836783539503) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-mn-rMN-watch/strings.xml b/core/res/res/values-mn-rMN-watch/strings.xml
index 49f829b..7b2e21b 100644
--- a/core/res/res/values-mn-rMN-watch/strings.xml
+++ b/core/res/res/values-mn-rMN-watch/strings.xml
@@ -21,4 +21,48 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="android_upgrading_apk" msgid="1090732262010398759">"<xliff:g id="NUMBER_0">%1$d</xliff:g>-ны <xliff:g id="NUMBER_1">%2$d</xliff:g> апп."</string>
+    <!-- no translation found for permgrouplab_sensors (202675452368612754) -->
+    <skip />
+    <!-- no translation found for permgrouplab_contactswear (2340286500790908344) -->
+    <skip />
+    <!-- no translation found for permgrouplab_locationwear (6275317222482780209) -->
+    <skip />
+    <!-- no translation found for permgrouplab_calendarwear (441900844045065081) -->
+    <skip />
+    <!-- no translation found for permgrouplab_smswear (6849506550342974220) -->
+    <skip />
+    <!-- no translation found for permgrouplab_storagewear (1003807594193602313) -->
+    <skip />
+    <!-- no translation found for permgrouplab_microphonewear (1047561180980891136) -->
+    <skip />
+    <!-- no translation found for permgrouplab_camerawear (4543951283103407017) -->
+    <skip />
+    <!-- no translation found for permgrouplab_phonewear (134365036753766126) -->
+    <skip />
+    <!-- no translation found for permgrouplab_sensorswear (1429324744329327663) -->
+    <skip />
+    <!-- no translation found for permlab_statusBarServicewear (2469402818964691034) -->
+    <skip />
+    <!-- no translation found for permlab_bodySensorswear (7857941041202791873) -->
+    <skip />
+    <!-- no translation found for permlab_accessFineLocationwear (5584423486924377563) -->
+    <skip />
+    <!-- no translation found for permlab_accessCoarseLocationwear (5880746016230166090) -->
+    <skip />
+    <!-- no translation found for permlab_sim_communicationwear (1899198085342781874) -->
+    <skip />
+    <!-- no translation found for permlab_createNetworkSocketswear (6467042386273822913) -->
+    <skip />
+    <!-- no translation found for permlab_manageProfileAndDeviceOwnerswear (7313340516937821847) -->
+    <skip />
+    <!-- no translation found for permlab_changeWimaxStatewear (3828470843939853744) -->
+    <skip />
+    <!-- no translation found for permlab_handoverStatuswear (4835786819716499249) -->
+    <skip />
+    <!-- no translation found for permlab_route_media_outputwear (8737024341474587192) -->
+    <skip />
+    <!-- no translation found for permlab_readInstallSessionswear (9059478058685861989) -->
+    <skip />
+    <!-- no translation found for permlab_requestInstallPackageswear (4982025836783539503) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-mr-rIN-watch/strings.xml b/core/res/res/values-mr-rIN-watch/strings.xml
index 49fa7d9..11af412 100644
--- a/core/res/res/values-mr-rIN-watch/strings.xml
+++ b/core/res/res/values-mr-rIN-watch/strings.xml
@@ -21,4 +21,48 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="android_upgrading_apk" msgid="1090732262010398759">"<xliff:g id="NUMBER_1">%2$d</xliff:g> पैकी <xliff:g id="NUMBER_0">%1$d</xliff:g> अॅप"</string>
+    <!-- no translation found for permgrouplab_sensors (202675452368612754) -->
+    <skip />
+    <!-- no translation found for permgrouplab_contactswear (2340286500790908344) -->
+    <skip />
+    <!-- no translation found for permgrouplab_locationwear (6275317222482780209) -->
+    <skip />
+    <!-- no translation found for permgrouplab_calendarwear (441900844045065081) -->
+    <skip />
+    <!-- no translation found for permgrouplab_smswear (6849506550342974220) -->
+    <skip />
+    <!-- no translation found for permgrouplab_storagewear (1003807594193602313) -->
+    <skip />
+    <!-- no translation found for permgrouplab_microphonewear (1047561180980891136) -->
+    <skip />
+    <!-- no translation found for permgrouplab_camerawear (4543951283103407017) -->
+    <skip />
+    <!-- no translation found for permgrouplab_phonewear (134365036753766126) -->
+    <skip />
+    <!-- no translation found for permgrouplab_sensorswear (1429324744329327663) -->
+    <skip />
+    <!-- no translation found for permlab_statusBarServicewear (2469402818964691034) -->
+    <skip />
+    <!-- no translation found for permlab_bodySensorswear (7857941041202791873) -->
+    <skip />
+    <!-- no translation found for permlab_accessFineLocationwear (5584423486924377563) -->
+    <skip />
+    <!-- no translation found for permlab_accessCoarseLocationwear (5880746016230166090) -->
+    <skip />
+    <!-- no translation found for permlab_sim_communicationwear (1899198085342781874) -->
+    <skip />
+    <!-- no translation found for permlab_createNetworkSocketswear (6467042386273822913) -->
+    <skip />
+    <!-- no translation found for permlab_manageProfileAndDeviceOwnerswear (7313340516937821847) -->
+    <skip />
+    <!-- no translation found for permlab_changeWimaxStatewear (3828470843939853744) -->
+    <skip />
+    <!-- no translation found for permlab_handoverStatuswear (4835786819716499249) -->
+    <skip />
+    <!-- no translation found for permlab_route_media_outputwear (8737024341474587192) -->
+    <skip />
+    <!-- no translation found for permlab_readInstallSessionswear (9059478058685861989) -->
+    <skip />
+    <!-- no translation found for permlab_requestInstallPackageswear (4982025836783539503) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-ms-rMY-watch/strings.xml b/core/res/res/values-ms-rMY-watch/strings.xml
index 148f518..d8245ed 100644
--- a/core/res/res/values-ms-rMY-watch/strings.xml
+++ b/core/res/res/values-ms-rMY-watch/strings.xml
@@ -21,4 +21,48 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="android_upgrading_apk" msgid="1090732262010398759">"Apl <xliff:g id="NUMBER_0">%1$d</xliff:g> daripada <xliff:g id="NUMBER_1">%2$d</xliff:g>."</string>
+    <!-- no translation found for permgrouplab_sensors (202675452368612754) -->
+    <skip />
+    <!-- no translation found for permgrouplab_contactswear (2340286500790908344) -->
+    <skip />
+    <!-- no translation found for permgrouplab_locationwear (6275317222482780209) -->
+    <skip />
+    <!-- no translation found for permgrouplab_calendarwear (441900844045065081) -->
+    <skip />
+    <!-- no translation found for permgrouplab_smswear (6849506550342974220) -->
+    <skip />
+    <!-- no translation found for permgrouplab_storagewear (1003807594193602313) -->
+    <skip />
+    <!-- no translation found for permgrouplab_microphonewear (1047561180980891136) -->
+    <skip />
+    <!-- no translation found for permgrouplab_camerawear (4543951283103407017) -->
+    <skip />
+    <!-- no translation found for permgrouplab_phonewear (134365036753766126) -->
+    <skip />
+    <!-- no translation found for permgrouplab_sensorswear (1429324744329327663) -->
+    <skip />
+    <!-- no translation found for permlab_statusBarServicewear (2469402818964691034) -->
+    <skip />
+    <!-- no translation found for permlab_bodySensorswear (7857941041202791873) -->
+    <skip />
+    <!-- no translation found for permlab_accessFineLocationwear (5584423486924377563) -->
+    <skip />
+    <!-- no translation found for permlab_accessCoarseLocationwear (5880746016230166090) -->
+    <skip />
+    <!-- no translation found for permlab_sim_communicationwear (1899198085342781874) -->
+    <skip />
+    <!-- no translation found for permlab_createNetworkSocketswear (6467042386273822913) -->
+    <skip />
+    <!-- no translation found for permlab_manageProfileAndDeviceOwnerswear (7313340516937821847) -->
+    <skip />
+    <!-- no translation found for permlab_changeWimaxStatewear (3828470843939853744) -->
+    <skip />
+    <!-- no translation found for permlab_handoverStatuswear (4835786819716499249) -->
+    <skip />
+    <!-- no translation found for permlab_route_media_outputwear (8737024341474587192) -->
+    <skip />
+    <!-- no translation found for permlab_readInstallSessionswear (9059478058685861989) -->
+    <skip />
+    <!-- no translation found for permlab_requestInstallPackageswear (4982025836783539503) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-my-rMM-watch/strings.xml b/core/res/res/values-my-rMM-watch/strings.xml
index ec89e53..34bd033 100644
--- a/core/res/res/values-my-rMM-watch/strings.xml
+++ b/core/res/res/values-my-rMM-watch/strings.xml
@@ -21,4 +21,48 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="android_upgrading_apk" msgid="1090732262010398759">"<xliff:g id="NUMBER_1">%2$d</xliff:g>၏  <xliff:g id="NUMBER_0">%1$d</xliff:g> ‌အသေးစားဆော့ဝဲ"</string>
+    <!-- no translation found for permgrouplab_sensors (202675452368612754) -->
+    <skip />
+    <!-- no translation found for permgrouplab_contactswear (2340286500790908344) -->
+    <skip />
+    <!-- no translation found for permgrouplab_locationwear (6275317222482780209) -->
+    <skip />
+    <!-- no translation found for permgrouplab_calendarwear (441900844045065081) -->
+    <skip />
+    <!-- no translation found for permgrouplab_smswear (6849506550342974220) -->
+    <skip />
+    <!-- no translation found for permgrouplab_storagewear (1003807594193602313) -->
+    <skip />
+    <!-- no translation found for permgrouplab_microphonewear (1047561180980891136) -->
+    <skip />
+    <!-- no translation found for permgrouplab_camerawear (4543951283103407017) -->
+    <skip />
+    <!-- no translation found for permgrouplab_phonewear (134365036753766126) -->
+    <skip />
+    <!-- no translation found for permgrouplab_sensorswear (1429324744329327663) -->
+    <skip />
+    <!-- no translation found for permlab_statusBarServicewear (2469402818964691034) -->
+    <skip />
+    <!-- no translation found for permlab_bodySensorswear (7857941041202791873) -->
+    <skip />
+    <!-- no translation found for permlab_accessFineLocationwear (5584423486924377563) -->
+    <skip />
+    <!-- no translation found for permlab_accessCoarseLocationwear (5880746016230166090) -->
+    <skip />
+    <!-- no translation found for permlab_sim_communicationwear (1899198085342781874) -->
+    <skip />
+    <!-- no translation found for permlab_createNetworkSocketswear (6467042386273822913) -->
+    <skip />
+    <!-- no translation found for permlab_manageProfileAndDeviceOwnerswear (7313340516937821847) -->
+    <skip />
+    <!-- no translation found for permlab_changeWimaxStatewear (3828470843939853744) -->
+    <skip />
+    <!-- no translation found for permlab_handoverStatuswear (4835786819716499249) -->
+    <skip />
+    <!-- no translation found for permlab_route_media_outputwear (8737024341474587192) -->
+    <skip />
+    <!-- no translation found for permlab_readInstallSessionswear (9059478058685861989) -->
+    <skip />
+    <!-- no translation found for permlab_requestInstallPackageswear (4982025836783539503) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-nb-watch/strings.xml b/core/res/res/values-nb-watch/strings.xml
index 3bd7fa5..aba8abb 100644
--- a/core/res/res/values-nb-watch/strings.xml
+++ b/core/res/res/values-nb-watch/strings.xml
@@ -21,4 +21,48 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="android_upgrading_apk" msgid="1090732262010398759">"App <xliff:g id="NUMBER_0">%1$d</xliff:g> av <xliff:g id="NUMBER_1">%2$d</xliff:g>."</string>
+    <!-- no translation found for permgrouplab_sensors (202675452368612754) -->
+    <skip />
+    <!-- no translation found for permgrouplab_contactswear (2340286500790908344) -->
+    <skip />
+    <!-- no translation found for permgrouplab_locationwear (6275317222482780209) -->
+    <skip />
+    <!-- no translation found for permgrouplab_calendarwear (441900844045065081) -->
+    <skip />
+    <!-- no translation found for permgrouplab_smswear (6849506550342974220) -->
+    <skip />
+    <!-- no translation found for permgrouplab_storagewear (1003807594193602313) -->
+    <skip />
+    <!-- no translation found for permgrouplab_microphonewear (1047561180980891136) -->
+    <skip />
+    <!-- no translation found for permgrouplab_camerawear (4543951283103407017) -->
+    <skip />
+    <!-- no translation found for permgrouplab_phonewear (134365036753766126) -->
+    <skip />
+    <!-- no translation found for permgrouplab_sensorswear (1429324744329327663) -->
+    <skip />
+    <!-- no translation found for permlab_statusBarServicewear (2469402818964691034) -->
+    <skip />
+    <!-- no translation found for permlab_bodySensorswear (7857941041202791873) -->
+    <skip />
+    <!-- no translation found for permlab_accessFineLocationwear (5584423486924377563) -->
+    <skip />
+    <!-- no translation found for permlab_accessCoarseLocationwear (5880746016230166090) -->
+    <skip />
+    <!-- no translation found for permlab_sim_communicationwear (1899198085342781874) -->
+    <skip />
+    <!-- no translation found for permlab_createNetworkSocketswear (6467042386273822913) -->
+    <skip />
+    <!-- no translation found for permlab_manageProfileAndDeviceOwnerswear (7313340516937821847) -->
+    <skip />
+    <!-- no translation found for permlab_changeWimaxStatewear (3828470843939853744) -->
+    <skip />
+    <!-- no translation found for permlab_handoverStatuswear (4835786819716499249) -->
+    <skip />
+    <!-- no translation found for permlab_route_media_outputwear (8737024341474587192) -->
+    <skip />
+    <!-- no translation found for permlab_readInstallSessionswear (9059478058685861989) -->
+    <skip />
+    <!-- no translation found for permlab_requestInstallPackageswear (4982025836783539503) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-ne-rNP-watch/strings.xml b/core/res/res/values-ne-rNP-watch/strings.xml
index e2453c89..fe331bd 100644
--- a/core/res/res/values-ne-rNP-watch/strings.xml
+++ b/core/res/res/values-ne-rNP-watch/strings.xml
@@ -21,4 +21,48 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="android_upgrading_apk" msgid="1090732262010398759">"<xliff:g id="NUMBER_1">%2$d</xliff:g> को <xliff:g id="NUMBER_0">%1$d</xliff:g> अनुप्रयोग।"</string>
+    <!-- no translation found for permgrouplab_sensors (202675452368612754) -->
+    <skip />
+    <!-- no translation found for permgrouplab_contactswear (2340286500790908344) -->
+    <skip />
+    <!-- no translation found for permgrouplab_locationwear (6275317222482780209) -->
+    <skip />
+    <!-- no translation found for permgrouplab_calendarwear (441900844045065081) -->
+    <skip />
+    <!-- no translation found for permgrouplab_smswear (6849506550342974220) -->
+    <skip />
+    <!-- no translation found for permgrouplab_storagewear (1003807594193602313) -->
+    <skip />
+    <!-- no translation found for permgrouplab_microphonewear (1047561180980891136) -->
+    <skip />
+    <!-- no translation found for permgrouplab_camerawear (4543951283103407017) -->
+    <skip />
+    <!-- no translation found for permgrouplab_phonewear (134365036753766126) -->
+    <skip />
+    <!-- no translation found for permgrouplab_sensorswear (1429324744329327663) -->
+    <skip />
+    <!-- no translation found for permlab_statusBarServicewear (2469402818964691034) -->
+    <skip />
+    <!-- no translation found for permlab_bodySensorswear (7857941041202791873) -->
+    <skip />
+    <!-- no translation found for permlab_accessFineLocationwear (5584423486924377563) -->
+    <skip />
+    <!-- no translation found for permlab_accessCoarseLocationwear (5880746016230166090) -->
+    <skip />
+    <!-- no translation found for permlab_sim_communicationwear (1899198085342781874) -->
+    <skip />
+    <!-- no translation found for permlab_createNetworkSocketswear (6467042386273822913) -->
+    <skip />
+    <!-- no translation found for permlab_manageProfileAndDeviceOwnerswear (7313340516937821847) -->
+    <skip />
+    <!-- no translation found for permlab_changeWimaxStatewear (3828470843939853744) -->
+    <skip />
+    <!-- no translation found for permlab_handoverStatuswear (4835786819716499249) -->
+    <skip />
+    <!-- no translation found for permlab_route_media_outputwear (8737024341474587192) -->
+    <skip />
+    <!-- no translation found for permlab_readInstallSessionswear (9059478058685861989) -->
+    <skip />
+    <!-- no translation found for permlab_requestInstallPackageswear (4982025836783539503) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-nl-watch/strings.xml b/core/res/res/values-nl-watch/strings.xml
index 989fa27..bed8a11 100644
--- a/core/res/res/values-nl-watch/strings.xml
+++ b/core/res/res/values-nl-watch/strings.xml
@@ -21,4 +21,48 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="android_upgrading_apk" msgid="1090732262010398759">"App <xliff:g id="NUMBER_0">%1$d</xliff:g> van <xliff:g id="NUMBER_1">%2$d</xliff:g>."</string>
+    <!-- no translation found for permgrouplab_sensors (202675452368612754) -->
+    <skip />
+    <!-- no translation found for permgrouplab_contactswear (2340286500790908344) -->
+    <skip />
+    <!-- no translation found for permgrouplab_locationwear (6275317222482780209) -->
+    <skip />
+    <!-- no translation found for permgrouplab_calendarwear (441900844045065081) -->
+    <skip />
+    <!-- no translation found for permgrouplab_smswear (6849506550342974220) -->
+    <skip />
+    <!-- no translation found for permgrouplab_storagewear (1003807594193602313) -->
+    <skip />
+    <!-- no translation found for permgrouplab_microphonewear (1047561180980891136) -->
+    <skip />
+    <!-- no translation found for permgrouplab_camerawear (4543951283103407017) -->
+    <skip />
+    <!-- no translation found for permgrouplab_phonewear (134365036753766126) -->
+    <skip />
+    <!-- no translation found for permgrouplab_sensorswear (1429324744329327663) -->
+    <skip />
+    <!-- no translation found for permlab_statusBarServicewear (2469402818964691034) -->
+    <skip />
+    <!-- no translation found for permlab_bodySensorswear (7857941041202791873) -->
+    <skip />
+    <!-- no translation found for permlab_accessFineLocationwear (5584423486924377563) -->
+    <skip />
+    <!-- no translation found for permlab_accessCoarseLocationwear (5880746016230166090) -->
+    <skip />
+    <!-- no translation found for permlab_sim_communicationwear (1899198085342781874) -->
+    <skip />
+    <!-- no translation found for permlab_createNetworkSocketswear (6467042386273822913) -->
+    <skip />
+    <!-- no translation found for permlab_manageProfileAndDeviceOwnerswear (7313340516937821847) -->
+    <skip />
+    <!-- no translation found for permlab_changeWimaxStatewear (3828470843939853744) -->
+    <skip />
+    <!-- no translation found for permlab_handoverStatuswear (4835786819716499249) -->
+    <skip />
+    <!-- no translation found for permlab_route_media_outputwear (8737024341474587192) -->
+    <skip />
+    <!-- no translation found for permlab_readInstallSessionswear (9059478058685861989) -->
+    <skip />
+    <!-- no translation found for permlab_requestInstallPackageswear (4982025836783539503) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-pa-rIN-watch/strings.xml b/core/res/res/values-pa-rIN-watch/strings.xml
index b30daa4..addaa6b 100644
--- a/core/res/res/values-pa-rIN-watch/strings.xml
+++ b/core/res/res/values-pa-rIN-watch/strings.xml
@@ -21,4 +21,48 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="android_upgrading_apk" msgid="1090732262010398759">"ਐਪ <xliff:g id="NUMBER_1">%2$d</xliff:g> ਦਾ <xliff:g id="NUMBER_0">%1$d</xliff:g>"</string>
+    <!-- no translation found for permgrouplab_sensors (202675452368612754) -->
+    <skip />
+    <!-- no translation found for permgrouplab_contactswear (2340286500790908344) -->
+    <skip />
+    <!-- no translation found for permgrouplab_locationwear (6275317222482780209) -->
+    <skip />
+    <!-- no translation found for permgrouplab_calendarwear (441900844045065081) -->
+    <skip />
+    <!-- no translation found for permgrouplab_smswear (6849506550342974220) -->
+    <skip />
+    <!-- no translation found for permgrouplab_storagewear (1003807594193602313) -->
+    <skip />
+    <!-- no translation found for permgrouplab_microphonewear (1047561180980891136) -->
+    <skip />
+    <!-- no translation found for permgrouplab_camerawear (4543951283103407017) -->
+    <skip />
+    <!-- no translation found for permgrouplab_phonewear (134365036753766126) -->
+    <skip />
+    <!-- no translation found for permgrouplab_sensorswear (1429324744329327663) -->
+    <skip />
+    <!-- no translation found for permlab_statusBarServicewear (2469402818964691034) -->
+    <skip />
+    <!-- no translation found for permlab_bodySensorswear (7857941041202791873) -->
+    <skip />
+    <!-- no translation found for permlab_accessFineLocationwear (5584423486924377563) -->
+    <skip />
+    <!-- no translation found for permlab_accessCoarseLocationwear (5880746016230166090) -->
+    <skip />
+    <!-- no translation found for permlab_sim_communicationwear (1899198085342781874) -->
+    <skip />
+    <!-- no translation found for permlab_createNetworkSocketswear (6467042386273822913) -->
+    <skip />
+    <!-- no translation found for permlab_manageProfileAndDeviceOwnerswear (7313340516937821847) -->
+    <skip />
+    <!-- no translation found for permlab_changeWimaxStatewear (3828470843939853744) -->
+    <skip />
+    <!-- no translation found for permlab_handoverStatuswear (4835786819716499249) -->
+    <skip />
+    <!-- no translation found for permlab_route_media_outputwear (8737024341474587192) -->
+    <skip />
+    <!-- no translation found for permlab_readInstallSessionswear (9059478058685861989) -->
+    <skip />
+    <!-- no translation found for permlab_requestInstallPackageswear (4982025836783539503) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-pl-watch/strings.xml b/core/res/res/values-pl-watch/strings.xml
index d9608f3..f266d0a 100644
--- a/core/res/res/values-pl-watch/strings.xml
+++ b/core/res/res/values-pl-watch/strings.xml
@@ -21,4 +21,48 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="android_upgrading_apk" msgid="1090732262010398759">"Aplikacja <xliff:g id="NUMBER_0">%1$d</xliff:g> z <xliff:g id="NUMBER_1">%2$d</xliff:g>."</string>
+    <!-- no translation found for permgrouplab_sensors (202675452368612754) -->
+    <skip />
+    <!-- no translation found for permgrouplab_contactswear (2340286500790908344) -->
+    <skip />
+    <!-- no translation found for permgrouplab_locationwear (6275317222482780209) -->
+    <skip />
+    <!-- no translation found for permgrouplab_calendarwear (441900844045065081) -->
+    <skip />
+    <!-- no translation found for permgrouplab_smswear (6849506550342974220) -->
+    <skip />
+    <!-- no translation found for permgrouplab_storagewear (1003807594193602313) -->
+    <skip />
+    <!-- no translation found for permgrouplab_microphonewear (1047561180980891136) -->
+    <skip />
+    <!-- no translation found for permgrouplab_camerawear (4543951283103407017) -->
+    <skip />
+    <!-- no translation found for permgrouplab_phonewear (134365036753766126) -->
+    <skip />
+    <!-- no translation found for permgrouplab_sensorswear (1429324744329327663) -->
+    <skip />
+    <!-- no translation found for permlab_statusBarServicewear (2469402818964691034) -->
+    <skip />
+    <!-- no translation found for permlab_bodySensorswear (7857941041202791873) -->
+    <skip />
+    <!-- no translation found for permlab_accessFineLocationwear (5584423486924377563) -->
+    <skip />
+    <!-- no translation found for permlab_accessCoarseLocationwear (5880746016230166090) -->
+    <skip />
+    <!-- no translation found for permlab_sim_communicationwear (1899198085342781874) -->
+    <skip />
+    <!-- no translation found for permlab_createNetworkSocketswear (6467042386273822913) -->
+    <skip />
+    <!-- no translation found for permlab_manageProfileAndDeviceOwnerswear (7313340516937821847) -->
+    <skip />
+    <!-- no translation found for permlab_changeWimaxStatewear (3828470843939853744) -->
+    <skip />
+    <!-- no translation found for permlab_handoverStatuswear (4835786819716499249) -->
+    <skip />
+    <!-- no translation found for permlab_route_media_outputwear (8737024341474587192) -->
+    <skip />
+    <!-- no translation found for permlab_readInstallSessionswear (9059478058685861989) -->
+    <skip />
+    <!-- no translation found for permlab_requestInstallPackageswear (4982025836783539503) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-pt-rBR-watch/strings.xml b/core/res/res/values-pt-rBR-watch/strings.xml
index 120e4a5..0eb0da3 100644
--- a/core/res/res/values-pt-rBR-watch/strings.xml
+++ b/core/res/res/values-pt-rBR-watch/strings.xml
@@ -21,4 +21,48 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="android_upgrading_apk" msgid="1090732262010398759">"App <xliff:g id="NUMBER_0">%1$d</xliff:g> de <xliff:g id="NUMBER_1">%2$d</xliff:g>."</string>
+    <!-- no translation found for permgrouplab_sensors (202675452368612754) -->
+    <skip />
+    <!-- no translation found for permgrouplab_contactswear (2340286500790908344) -->
+    <skip />
+    <!-- no translation found for permgrouplab_locationwear (6275317222482780209) -->
+    <skip />
+    <!-- no translation found for permgrouplab_calendarwear (441900844045065081) -->
+    <skip />
+    <!-- no translation found for permgrouplab_smswear (6849506550342974220) -->
+    <skip />
+    <!-- no translation found for permgrouplab_storagewear (1003807594193602313) -->
+    <skip />
+    <!-- no translation found for permgrouplab_microphonewear (1047561180980891136) -->
+    <skip />
+    <!-- no translation found for permgrouplab_camerawear (4543951283103407017) -->
+    <skip />
+    <!-- no translation found for permgrouplab_phonewear (134365036753766126) -->
+    <skip />
+    <!-- no translation found for permgrouplab_sensorswear (1429324744329327663) -->
+    <skip />
+    <!-- no translation found for permlab_statusBarServicewear (2469402818964691034) -->
+    <skip />
+    <!-- no translation found for permlab_bodySensorswear (7857941041202791873) -->
+    <skip />
+    <!-- no translation found for permlab_accessFineLocationwear (5584423486924377563) -->
+    <skip />
+    <!-- no translation found for permlab_accessCoarseLocationwear (5880746016230166090) -->
+    <skip />
+    <!-- no translation found for permlab_sim_communicationwear (1899198085342781874) -->
+    <skip />
+    <!-- no translation found for permlab_createNetworkSocketswear (6467042386273822913) -->
+    <skip />
+    <!-- no translation found for permlab_manageProfileAndDeviceOwnerswear (7313340516937821847) -->
+    <skip />
+    <!-- no translation found for permlab_changeWimaxStatewear (3828470843939853744) -->
+    <skip />
+    <!-- no translation found for permlab_handoverStatuswear (4835786819716499249) -->
+    <skip />
+    <!-- no translation found for permlab_route_media_outputwear (8737024341474587192) -->
+    <skip />
+    <!-- no translation found for permlab_readInstallSessionswear (9059478058685861989) -->
+    <skip />
+    <!-- no translation found for permlab_requestInstallPackageswear (4982025836783539503) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-pt-rPT-watch/strings.xml b/core/res/res/values-pt-rPT-watch/strings.xml
index 69d2c0a..1654fc3 100644
--- a/core/res/res/values-pt-rPT-watch/strings.xml
+++ b/core/res/res/values-pt-rPT-watch/strings.xml
@@ -21,4 +21,48 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="android_upgrading_apk" msgid="1090732262010398759">"Aplicação <xliff:g id="NUMBER_0">%1$d</xliff:g> de <xliff:g id="NUMBER_1">%2$d</xliff:g>."</string>
+    <!-- no translation found for permgrouplab_sensors (202675452368612754) -->
+    <skip />
+    <!-- no translation found for permgrouplab_contactswear (2340286500790908344) -->
+    <skip />
+    <!-- no translation found for permgrouplab_locationwear (6275317222482780209) -->
+    <skip />
+    <!-- no translation found for permgrouplab_calendarwear (441900844045065081) -->
+    <skip />
+    <!-- no translation found for permgrouplab_smswear (6849506550342974220) -->
+    <skip />
+    <!-- no translation found for permgrouplab_storagewear (1003807594193602313) -->
+    <skip />
+    <!-- no translation found for permgrouplab_microphonewear (1047561180980891136) -->
+    <skip />
+    <!-- no translation found for permgrouplab_camerawear (4543951283103407017) -->
+    <skip />
+    <!-- no translation found for permgrouplab_phonewear (134365036753766126) -->
+    <skip />
+    <!-- no translation found for permgrouplab_sensorswear (1429324744329327663) -->
+    <skip />
+    <!-- no translation found for permlab_statusBarServicewear (2469402818964691034) -->
+    <skip />
+    <!-- no translation found for permlab_bodySensorswear (7857941041202791873) -->
+    <skip />
+    <!-- no translation found for permlab_accessFineLocationwear (5584423486924377563) -->
+    <skip />
+    <!-- no translation found for permlab_accessCoarseLocationwear (5880746016230166090) -->
+    <skip />
+    <!-- no translation found for permlab_sim_communicationwear (1899198085342781874) -->
+    <skip />
+    <!-- no translation found for permlab_createNetworkSocketswear (6467042386273822913) -->
+    <skip />
+    <!-- no translation found for permlab_manageProfileAndDeviceOwnerswear (7313340516937821847) -->
+    <skip />
+    <!-- no translation found for permlab_changeWimaxStatewear (3828470843939853744) -->
+    <skip />
+    <!-- no translation found for permlab_handoverStatuswear (4835786819716499249) -->
+    <skip />
+    <!-- no translation found for permlab_route_media_outputwear (8737024341474587192) -->
+    <skip />
+    <!-- no translation found for permlab_readInstallSessionswear (9059478058685861989) -->
+    <skip />
+    <!-- no translation found for permlab_requestInstallPackageswear (4982025836783539503) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-pt-watch/strings.xml b/core/res/res/values-pt-watch/strings.xml
index 120e4a5..0eb0da3 100644
--- a/core/res/res/values-pt-watch/strings.xml
+++ b/core/res/res/values-pt-watch/strings.xml
@@ -21,4 +21,48 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="android_upgrading_apk" msgid="1090732262010398759">"App <xliff:g id="NUMBER_0">%1$d</xliff:g> de <xliff:g id="NUMBER_1">%2$d</xliff:g>."</string>
+    <!-- no translation found for permgrouplab_sensors (202675452368612754) -->
+    <skip />
+    <!-- no translation found for permgrouplab_contactswear (2340286500790908344) -->
+    <skip />
+    <!-- no translation found for permgrouplab_locationwear (6275317222482780209) -->
+    <skip />
+    <!-- no translation found for permgrouplab_calendarwear (441900844045065081) -->
+    <skip />
+    <!-- no translation found for permgrouplab_smswear (6849506550342974220) -->
+    <skip />
+    <!-- no translation found for permgrouplab_storagewear (1003807594193602313) -->
+    <skip />
+    <!-- no translation found for permgrouplab_microphonewear (1047561180980891136) -->
+    <skip />
+    <!-- no translation found for permgrouplab_camerawear (4543951283103407017) -->
+    <skip />
+    <!-- no translation found for permgrouplab_phonewear (134365036753766126) -->
+    <skip />
+    <!-- no translation found for permgrouplab_sensorswear (1429324744329327663) -->
+    <skip />
+    <!-- no translation found for permlab_statusBarServicewear (2469402818964691034) -->
+    <skip />
+    <!-- no translation found for permlab_bodySensorswear (7857941041202791873) -->
+    <skip />
+    <!-- no translation found for permlab_accessFineLocationwear (5584423486924377563) -->
+    <skip />
+    <!-- no translation found for permlab_accessCoarseLocationwear (5880746016230166090) -->
+    <skip />
+    <!-- no translation found for permlab_sim_communicationwear (1899198085342781874) -->
+    <skip />
+    <!-- no translation found for permlab_createNetworkSocketswear (6467042386273822913) -->
+    <skip />
+    <!-- no translation found for permlab_manageProfileAndDeviceOwnerswear (7313340516937821847) -->
+    <skip />
+    <!-- no translation found for permlab_changeWimaxStatewear (3828470843939853744) -->
+    <skip />
+    <!-- no translation found for permlab_handoverStatuswear (4835786819716499249) -->
+    <skip />
+    <!-- no translation found for permlab_route_media_outputwear (8737024341474587192) -->
+    <skip />
+    <!-- no translation found for permlab_readInstallSessionswear (9059478058685861989) -->
+    <skip />
+    <!-- no translation found for permlab_requestInstallPackageswear (4982025836783539503) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-ro-watch/strings.xml b/core/res/res/values-ro-watch/strings.xml
index 95c8ec3..dc3c9065 100644
--- a/core/res/res/values-ro-watch/strings.xml
+++ b/core/res/res/values-ro-watch/strings.xml
@@ -21,4 +21,48 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="android_upgrading_apk" msgid="1090732262010398759">"Aplic. <xliff:g id="NUMBER_0">%1$d</xliff:g> din <xliff:g id="NUMBER_1">%2$d</xliff:g>."</string>
+    <!-- no translation found for permgrouplab_sensors (202675452368612754) -->
+    <skip />
+    <!-- no translation found for permgrouplab_contactswear (2340286500790908344) -->
+    <skip />
+    <!-- no translation found for permgrouplab_locationwear (6275317222482780209) -->
+    <skip />
+    <!-- no translation found for permgrouplab_calendarwear (441900844045065081) -->
+    <skip />
+    <!-- no translation found for permgrouplab_smswear (6849506550342974220) -->
+    <skip />
+    <!-- no translation found for permgrouplab_storagewear (1003807594193602313) -->
+    <skip />
+    <!-- no translation found for permgrouplab_microphonewear (1047561180980891136) -->
+    <skip />
+    <!-- no translation found for permgrouplab_camerawear (4543951283103407017) -->
+    <skip />
+    <!-- no translation found for permgrouplab_phonewear (134365036753766126) -->
+    <skip />
+    <!-- no translation found for permgrouplab_sensorswear (1429324744329327663) -->
+    <skip />
+    <!-- no translation found for permlab_statusBarServicewear (2469402818964691034) -->
+    <skip />
+    <!-- no translation found for permlab_bodySensorswear (7857941041202791873) -->
+    <skip />
+    <!-- no translation found for permlab_accessFineLocationwear (5584423486924377563) -->
+    <skip />
+    <!-- no translation found for permlab_accessCoarseLocationwear (5880746016230166090) -->
+    <skip />
+    <!-- no translation found for permlab_sim_communicationwear (1899198085342781874) -->
+    <skip />
+    <!-- no translation found for permlab_createNetworkSocketswear (6467042386273822913) -->
+    <skip />
+    <!-- no translation found for permlab_manageProfileAndDeviceOwnerswear (7313340516937821847) -->
+    <skip />
+    <!-- no translation found for permlab_changeWimaxStatewear (3828470843939853744) -->
+    <skip />
+    <!-- no translation found for permlab_handoverStatuswear (4835786819716499249) -->
+    <skip />
+    <!-- no translation found for permlab_route_media_outputwear (8737024341474587192) -->
+    <skip />
+    <!-- no translation found for permlab_readInstallSessionswear (9059478058685861989) -->
+    <skip />
+    <!-- no translation found for permlab_requestInstallPackageswear (4982025836783539503) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-ru-watch/strings.xml b/core/res/res/values-ru-watch/strings.xml
index f32f63b..cd536c5 100644
--- a/core/res/res/values-ru-watch/strings.xml
+++ b/core/res/res/values-ru-watch/strings.xml
@@ -21,4 +21,48 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="android_upgrading_apk" msgid="1090732262010398759">"Приложение <xliff:g id="NUMBER_0">%1$d</xliff:g> из <xliff:g id="NUMBER_1">%2$d</xliff:g>"</string>
+    <!-- no translation found for permgrouplab_sensors (202675452368612754) -->
+    <skip />
+    <!-- no translation found for permgrouplab_contactswear (2340286500790908344) -->
+    <skip />
+    <!-- no translation found for permgrouplab_locationwear (6275317222482780209) -->
+    <skip />
+    <!-- no translation found for permgrouplab_calendarwear (441900844045065081) -->
+    <skip />
+    <!-- no translation found for permgrouplab_smswear (6849506550342974220) -->
+    <skip />
+    <!-- no translation found for permgrouplab_storagewear (1003807594193602313) -->
+    <skip />
+    <!-- no translation found for permgrouplab_microphonewear (1047561180980891136) -->
+    <skip />
+    <!-- no translation found for permgrouplab_camerawear (4543951283103407017) -->
+    <skip />
+    <!-- no translation found for permgrouplab_phonewear (134365036753766126) -->
+    <skip />
+    <!-- no translation found for permgrouplab_sensorswear (1429324744329327663) -->
+    <skip />
+    <!-- no translation found for permlab_statusBarServicewear (2469402818964691034) -->
+    <skip />
+    <!-- no translation found for permlab_bodySensorswear (7857941041202791873) -->
+    <skip />
+    <!-- no translation found for permlab_accessFineLocationwear (5584423486924377563) -->
+    <skip />
+    <!-- no translation found for permlab_accessCoarseLocationwear (5880746016230166090) -->
+    <skip />
+    <!-- no translation found for permlab_sim_communicationwear (1899198085342781874) -->
+    <skip />
+    <!-- no translation found for permlab_createNetworkSocketswear (6467042386273822913) -->
+    <skip />
+    <!-- no translation found for permlab_manageProfileAndDeviceOwnerswear (7313340516937821847) -->
+    <skip />
+    <!-- no translation found for permlab_changeWimaxStatewear (3828470843939853744) -->
+    <skip />
+    <!-- no translation found for permlab_handoverStatuswear (4835786819716499249) -->
+    <skip />
+    <!-- no translation found for permlab_route_media_outputwear (8737024341474587192) -->
+    <skip />
+    <!-- no translation found for permlab_readInstallSessionswear (9059478058685861989) -->
+    <skip />
+    <!-- no translation found for permlab_requestInstallPackageswear (4982025836783539503) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-si-rLK-watch/strings.xml b/core/res/res/values-si-rLK-watch/strings.xml
index b55687f..4adfbb5 100644
--- a/core/res/res/values-si-rLK-watch/strings.xml
+++ b/core/res/res/values-si-rLK-watch/strings.xml
@@ -21,4 +21,48 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="android_upgrading_apk" msgid="1090732262010398759">"<xliff:g id="NUMBER_0">%1$d</xliff:g> හි <xliff:g id="NUMBER_1">%2$d</xliff:g> යෙදුම."</string>
+    <!-- no translation found for permgrouplab_sensors (202675452368612754) -->
+    <skip />
+    <!-- no translation found for permgrouplab_contactswear (2340286500790908344) -->
+    <skip />
+    <!-- no translation found for permgrouplab_locationwear (6275317222482780209) -->
+    <skip />
+    <!-- no translation found for permgrouplab_calendarwear (441900844045065081) -->
+    <skip />
+    <!-- no translation found for permgrouplab_smswear (6849506550342974220) -->
+    <skip />
+    <!-- no translation found for permgrouplab_storagewear (1003807594193602313) -->
+    <skip />
+    <!-- no translation found for permgrouplab_microphonewear (1047561180980891136) -->
+    <skip />
+    <!-- no translation found for permgrouplab_camerawear (4543951283103407017) -->
+    <skip />
+    <!-- no translation found for permgrouplab_phonewear (134365036753766126) -->
+    <skip />
+    <!-- no translation found for permgrouplab_sensorswear (1429324744329327663) -->
+    <skip />
+    <!-- no translation found for permlab_statusBarServicewear (2469402818964691034) -->
+    <skip />
+    <!-- no translation found for permlab_bodySensorswear (7857941041202791873) -->
+    <skip />
+    <!-- no translation found for permlab_accessFineLocationwear (5584423486924377563) -->
+    <skip />
+    <!-- no translation found for permlab_accessCoarseLocationwear (5880746016230166090) -->
+    <skip />
+    <!-- no translation found for permlab_sim_communicationwear (1899198085342781874) -->
+    <skip />
+    <!-- no translation found for permlab_createNetworkSocketswear (6467042386273822913) -->
+    <skip />
+    <!-- no translation found for permlab_manageProfileAndDeviceOwnerswear (7313340516937821847) -->
+    <skip />
+    <!-- no translation found for permlab_changeWimaxStatewear (3828470843939853744) -->
+    <skip />
+    <!-- no translation found for permlab_handoverStatuswear (4835786819716499249) -->
+    <skip />
+    <!-- no translation found for permlab_route_media_outputwear (8737024341474587192) -->
+    <skip />
+    <!-- no translation found for permlab_readInstallSessionswear (9059478058685861989) -->
+    <skip />
+    <!-- no translation found for permlab_requestInstallPackageswear (4982025836783539503) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-sk-watch/strings.xml b/core/res/res/values-sk-watch/strings.xml
index 601c016..24bed89 100644
--- a/core/res/res/values-sk-watch/strings.xml
+++ b/core/res/res/values-sk-watch/strings.xml
@@ -21,4 +21,48 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="android_upgrading_apk" msgid="1090732262010398759">"Aplikácia <xliff:g id="NUMBER_0">%1$d</xliff:g> z <xliff:g id="NUMBER_1">%2$d</xliff:g>."</string>
+    <!-- no translation found for permgrouplab_sensors (202675452368612754) -->
+    <skip />
+    <!-- no translation found for permgrouplab_contactswear (2340286500790908344) -->
+    <skip />
+    <!-- no translation found for permgrouplab_locationwear (6275317222482780209) -->
+    <skip />
+    <!-- no translation found for permgrouplab_calendarwear (441900844045065081) -->
+    <skip />
+    <!-- no translation found for permgrouplab_smswear (6849506550342974220) -->
+    <skip />
+    <!-- no translation found for permgrouplab_storagewear (1003807594193602313) -->
+    <skip />
+    <!-- no translation found for permgrouplab_microphonewear (1047561180980891136) -->
+    <skip />
+    <!-- no translation found for permgrouplab_camerawear (4543951283103407017) -->
+    <skip />
+    <!-- no translation found for permgrouplab_phonewear (134365036753766126) -->
+    <skip />
+    <!-- no translation found for permgrouplab_sensorswear (1429324744329327663) -->
+    <skip />
+    <!-- no translation found for permlab_statusBarServicewear (2469402818964691034) -->
+    <skip />
+    <!-- no translation found for permlab_bodySensorswear (7857941041202791873) -->
+    <skip />
+    <!-- no translation found for permlab_accessFineLocationwear (5584423486924377563) -->
+    <skip />
+    <!-- no translation found for permlab_accessCoarseLocationwear (5880746016230166090) -->
+    <skip />
+    <!-- no translation found for permlab_sim_communicationwear (1899198085342781874) -->
+    <skip />
+    <!-- no translation found for permlab_createNetworkSocketswear (6467042386273822913) -->
+    <skip />
+    <!-- no translation found for permlab_manageProfileAndDeviceOwnerswear (7313340516937821847) -->
+    <skip />
+    <!-- no translation found for permlab_changeWimaxStatewear (3828470843939853744) -->
+    <skip />
+    <!-- no translation found for permlab_handoverStatuswear (4835786819716499249) -->
+    <skip />
+    <!-- no translation found for permlab_route_media_outputwear (8737024341474587192) -->
+    <skip />
+    <!-- no translation found for permlab_readInstallSessionswear (9059478058685861989) -->
+    <skip />
+    <!-- no translation found for permlab_requestInstallPackageswear (4982025836783539503) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-sl-watch/strings.xml b/core/res/res/values-sl-watch/strings.xml
index bf1190f..5bc0ea5 100644
--- a/core/res/res/values-sl-watch/strings.xml
+++ b/core/res/res/values-sl-watch/strings.xml
@@ -21,4 +21,48 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="android_upgrading_apk" msgid="1090732262010398759">"<xliff:g id="NUMBER_0">%1$d</xliff:g>. aplikac. od <xliff:g id="NUMBER_1">%2$d</xliff:g>."</string>
+    <!-- no translation found for permgrouplab_sensors (202675452368612754) -->
+    <skip />
+    <!-- no translation found for permgrouplab_contactswear (2340286500790908344) -->
+    <skip />
+    <!-- no translation found for permgrouplab_locationwear (6275317222482780209) -->
+    <skip />
+    <!-- no translation found for permgrouplab_calendarwear (441900844045065081) -->
+    <skip />
+    <!-- no translation found for permgrouplab_smswear (6849506550342974220) -->
+    <skip />
+    <!-- no translation found for permgrouplab_storagewear (1003807594193602313) -->
+    <skip />
+    <!-- no translation found for permgrouplab_microphonewear (1047561180980891136) -->
+    <skip />
+    <!-- no translation found for permgrouplab_camerawear (4543951283103407017) -->
+    <skip />
+    <!-- no translation found for permgrouplab_phonewear (134365036753766126) -->
+    <skip />
+    <!-- no translation found for permgrouplab_sensorswear (1429324744329327663) -->
+    <skip />
+    <!-- no translation found for permlab_statusBarServicewear (2469402818964691034) -->
+    <skip />
+    <!-- no translation found for permlab_bodySensorswear (7857941041202791873) -->
+    <skip />
+    <!-- no translation found for permlab_accessFineLocationwear (5584423486924377563) -->
+    <skip />
+    <!-- no translation found for permlab_accessCoarseLocationwear (5880746016230166090) -->
+    <skip />
+    <!-- no translation found for permlab_sim_communicationwear (1899198085342781874) -->
+    <skip />
+    <!-- no translation found for permlab_createNetworkSocketswear (6467042386273822913) -->
+    <skip />
+    <!-- no translation found for permlab_manageProfileAndDeviceOwnerswear (7313340516937821847) -->
+    <skip />
+    <!-- no translation found for permlab_changeWimaxStatewear (3828470843939853744) -->
+    <skip />
+    <!-- no translation found for permlab_handoverStatuswear (4835786819716499249) -->
+    <skip />
+    <!-- no translation found for permlab_route_media_outputwear (8737024341474587192) -->
+    <skip />
+    <!-- no translation found for permlab_readInstallSessionswear (9059478058685861989) -->
+    <skip />
+    <!-- no translation found for permlab_requestInstallPackageswear (4982025836783539503) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-sq-rAL-watch/strings.xml b/core/res/res/values-sq-rAL-watch/strings.xml
index d1637ba..1b0bdaf 100644
--- a/core/res/res/values-sq-rAL-watch/strings.xml
+++ b/core/res/res/values-sq-rAL-watch/strings.xml
@@ -21,4 +21,48 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="android_upgrading_apk" msgid="1090732262010398759">"Aplikacioni <xliff:g id="NUMBER_0">%1$d</xliff:g> nga <xliff:g id="NUMBER_1">%2$d</xliff:g>."</string>
+    <!-- no translation found for permgrouplab_sensors (202675452368612754) -->
+    <skip />
+    <!-- no translation found for permgrouplab_contactswear (2340286500790908344) -->
+    <skip />
+    <!-- no translation found for permgrouplab_locationwear (6275317222482780209) -->
+    <skip />
+    <!-- no translation found for permgrouplab_calendarwear (441900844045065081) -->
+    <skip />
+    <!-- no translation found for permgrouplab_smswear (6849506550342974220) -->
+    <skip />
+    <!-- no translation found for permgrouplab_storagewear (1003807594193602313) -->
+    <skip />
+    <!-- no translation found for permgrouplab_microphonewear (1047561180980891136) -->
+    <skip />
+    <!-- no translation found for permgrouplab_camerawear (4543951283103407017) -->
+    <skip />
+    <!-- no translation found for permgrouplab_phonewear (134365036753766126) -->
+    <skip />
+    <!-- no translation found for permgrouplab_sensorswear (1429324744329327663) -->
+    <skip />
+    <!-- no translation found for permlab_statusBarServicewear (2469402818964691034) -->
+    <skip />
+    <!-- no translation found for permlab_bodySensorswear (7857941041202791873) -->
+    <skip />
+    <!-- no translation found for permlab_accessFineLocationwear (5584423486924377563) -->
+    <skip />
+    <!-- no translation found for permlab_accessCoarseLocationwear (5880746016230166090) -->
+    <skip />
+    <!-- no translation found for permlab_sim_communicationwear (1899198085342781874) -->
+    <skip />
+    <!-- no translation found for permlab_createNetworkSocketswear (6467042386273822913) -->
+    <skip />
+    <!-- no translation found for permlab_manageProfileAndDeviceOwnerswear (7313340516937821847) -->
+    <skip />
+    <!-- no translation found for permlab_changeWimaxStatewear (3828470843939853744) -->
+    <skip />
+    <!-- no translation found for permlab_handoverStatuswear (4835786819716499249) -->
+    <skip />
+    <!-- no translation found for permlab_route_media_outputwear (8737024341474587192) -->
+    <skip />
+    <!-- no translation found for permlab_readInstallSessionswear (9059478058685861989) -->
+    <skip />
+    <!-- no translation found for permlab_requestInstallPackageswear (4982025836783539503) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-sr-watch/strings.xml b/core/res/res/values-sr-watch/strings.xml
index 484977e..ae70ab1 100644
--- a/core/res/res/values-sr-watch/strings.xml
+++ b/core/res/res/values-sr-watch/strings.xml
@@ -21,4 +21,48 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="android_upgrading_apk" msgid="1090732262010398759">"Апликација <xliff:g id="NUMBER_0">%1$d</xliff:g> од <xliff:g id="NUMBER_1">%2$d</xliff:g>."</string>
+    <!-- no translation found for permgrouplab_sensors (202675452368612754) -->
+    <skip />
+    <!-- no translation found for permgrouplab_contactswear (2340286500790908344) -->
+    <skip />
+    <!-- no translation found for permgrouplab_locationwear (6275317222482780209) -->
+    <skip />
+    <!-- no translation found for permgrouplab_calendarwear (441900844045065081) -->
+    <skip />
+    <!-- no translation found for permgrouplab_smswear (6849506550342974220) -->
+    <skip />
+    <!-- no translation found for permgrouplab_storagewear (1003807594193602313) -->
+    <skip />
+    <!-- no translation found for permgrouplab_microphonewear (1047561180980891136) -->
+    <skip />
+    <!-- no translation found for permgrouplab_camerawear (4543951283103407017) -->
+    <skip />
+    <!-- no translation found for permgrouplab_phonewear (134365036753766126) -->
+    <skip />
+    <!-- no translation found for permgrouplab_sensorswear (1429324744329327663) -->
+    <skip />
+    <!-- no translation found for permlab_statusBarServicewear (2469402818964691034) -->
+    <skip />
+    <!-- no translation found for permlab_bodySensorswear (7857941041202791873) -->
+    <skip />
+    <!-- no translation found for permlab_accessFineLocationwear (5584423486924377563) -->
+    <skip />
+    <!-- no translation found for permlab_accessCoarseLocationwear (5880746016230166090) -->
+    <skip />
+    <!-- no translation found for permlab_sim_communicationwear (1899198085342781874) -->
+    <skip />
+    <!-- no translation found for permlab_createNetworkSocketswear (6467042386273822913) -->
+    <skip />
+    <!-- no translation found for permlab_manageProfileAndDeviceOwnerswear (7313340516937821847) -->
+    <skip />
+    <!-- no translation found for permlab_changeWimaxStatewear (3828470843939853744) -->
+    <skip />
+    <!-- no translation found for permlab_handoverStatuswear (4835786819716499249) -->
+    <skip />
+    <!-- no translation found for permlab_route_media_outputwear (8737024341474587192) -->
+    <skip />
+    <!-- no translation found for permlab_readInstallSessionswear (9059478058685861989) -->
+    <skip />
+    <!-- no translation found for permlab_requestInstallPackageswear (4982025836783539503) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-sv-watch/strings.xml b/core/res/res/values-sv-watch/strings.xml
index 3bd7fa5..aba8abb 100644
--- a/core/res/res/values-sv-watch/strings.xml
+++ b/core/res/res/values-sv-watch/strings.xml
@@ -21,4 +21,48 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="android_upgrading_apk" msgid="1090732262010398759">"App <xliff:g id="NUMBER_0">%1$d</xliff:g> av <xliff:g id="NUMBER_1">%2$d</xliff:g>."</string>
+    <!-- no translation found for permgrouplab_sensors (202675452368612754) -->
+    <skip />
+    <!-- no translation found for permgrouplab_contactswear (2340286500790908344) -->
+    <skip />
+    <!-- no translation found for permgrouplab_locationwear (6275317222482780209) -->
+    <skip />
+    <!-- no translation found for permgrouplab_calendarwear (441900844045065081) -->
+    <skip />
+    <!-- no translation found for permgrouplab_smswear (6849506550342974220) -->
+    <skip />
+    <!-- no translation found for permgrouplab_storagewear (1003807594193602313) -->
+    <skip />
+    <!-- no translation found for permgrouplab_microphonewear (1047561180980891136) -->
+    <skip />
+    <!-- no translation found for permgrouplab_camerawear (4543951283103407017) -->
+    <skip />
+    <!-- no translation found for permgrouplab_phonewear (134365036753766126) -->
+    <skip />
+    <!-- no translation found for permgrouplab_sensorswear (1429324744329327663) -->
+    <skip />
+    <!-- no translation found for permlab_statusBarServicewear (2469402818964691034) -->
+    <skip />
+    <!-- no translation found for permlab_bodySensorswear (7857941041202791873) -->
+    <skip />
+    <!-- no translation found for permlab_accessFineLocationwear (5584423486924377563) -->
+    <skip />
+    <!-- no translation found for permlab_accessCoarseLocationwear (5880746016230166090) -->
+    <skip />
+    <!-- no translation found for permlab_sim_communicationwear (1899198085342781874) -->
+    <skip />
+    <!-- no translation found for permlab_createNetworkSocketswear (6467042386273822913) -->
+    <skip />
+    <!-- no translation found for permlab_manageProfileAndDeviceOwnerswear (7313340516937821847) -->
+    <skip />
+    <!-- no translation found for permlab_changeWimaxStatewear (3828470843939853744) -->
+    <skip />
+    <!-- no translation found for permlab_handoverStatuswear (4835786819716499249) -->
+    <skip />
+    <!-- no translation found for permlab_route_media_outputwear (8737024341474587192) -->
+    <skip />
+    <!-- no translation found for permlab_readInstallSessionswear (9059478058685861989) -->
+    <skip />
+    <!-- no translation found for permlab_requestInstallPackageswear (4982025836783539503) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-sw-watch/strings.xml b/core/res/res/values-sw-watch/strings.xml
index 5a8c72e..929022f 100644
--- a/core/res/res/values-sw-watch/strings.xml
+++ b/core/res/res/values-sw-watch/strings.xml
@@ -21,4 +21,48 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="android_upgrading_apk" msgid="1090732262010398759">"Programu ya <xliff:g id="NUMBER_0">%1$d</xliff:g> kati ya <xliff:g id="NUMBER_1">%2$d</xliff:g>."</string>
+    <!-- no translation found for permgrouplab_sensors (202675452368612754) -->
+    <skip />
+    <!-- no translation found for permgrouplab_contactswear (2340286500790908344) -->
+    <skip />
+    <!-- no translation found for permgrouplab_locationwear (6275317222482780209) -->
+    <skip />
+    <!-- no translation found for permgrouplab_calendarwear (441900844045065081) -->
+    <skip />
+    <!-- no translation found for permgrouplab_smswear (6849506550342974220) -->
+    <skip />
+    <!-- no translation found for permgrouplab_storagewear (1003807594193602313) -->
+    <skip />
+    <!-- no translation found for permgrouplab_microphonewear (1047561180980891136) -->
+    <skip />
+    <!-- no translation found for permgrouplab_camerawear (4543951283103407017) -->
+    <skip />
+    <!-- no translation found for permgrouplab_phonewear (134365036753766126) -->
+    <skip />
+    <!-- no translation found for permgrouplab_sensorswear (1429324744329327663) -->
+    <skip />
+    <!-- no translation found for permlab_statusBarServicewear (2469402818964691034) -->
+    <skip />
+    <!-- no translation found for permlab_bodySensorswear (7857941041202791873) -->
+    <skip />
+    <!-- no translation found for permlab_accessFineLocationwear (5584423486924377563) -->
+    <skip />
+    <!-- no translation found for permlab_accessCoarseLocationwear (5880746016230166090) -->
+    <skip />
+    <!-- no translation found for permlab_sim_communicationwear (1899198085342781874) -->
+    <skip />
+    <!-- no translation found for permlab_createNetworkSocketswear (6467042386273822913) -->
+    <skip />
+    <!-- no translation found for permlab_manageProfileAndDeviceOwnerswear (7313340516937821847) -->
+    <skip />
+    <!-- no translation found for permlab_changeWimaxStatewear (3828470843939853744) -->
+    <skip />
+    <!-- no translation found for permlab_handoverStatuswear (4835786819716499249) -->
+    <skip />
+    <!-- no translation found for permlab_route_media_outputwear (8737024341474587192) -->
+    <skip />
+    <!-- no translation found for permlab_readInstallSessionswear (9059478058685861989) -->
+    <skip />
+    <!-- no translation found for permlab_requestInstallPackageswear (4982025836783539503) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-ta-rIN-watch/strings.xml b/core/res/res/values-ta-rIN-watch/strings.xml
index 4c05cab..23accbc 100644
--- a/core/res/res/values-ta-rIN-watch/strings.xml
+++ b/core/res/res/values-ta-rIN-watch/strings.xml
@@ -21,4 +21,48 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="android_upgrading_apk" msgid="1090732262010398759">"பயன்பாடு: <xliff:g id="NUMBER_0">%1$d</xliff:g> / <xliff:g id="NUMBER_1">%2$d</xliff:g>."</string>
+    <!-- no translation found for permgrouplab_sensors (202675452368612754) -->
+    <skip />
+    <!-- no translation found for permgrouplab_contactswear (2340286500790908344) -->
+    <skip />
+    <!-- no translation found for permgrouplab_locationwear (6275317222482780209) -->
+    <skip />
+    <!-- no translation found for permgrouplab_calendarwear (441900844045065081) -->
+    <skip />
+    <!-- no translation found for permgrouplab_smswear (6849506550342974220) -->
+    <skip />
+    <!-- no translation found for permgrouplab_storagewear (1003807594193602313) -->
+    <skip />
+    <!-- no translation found for permgrouplab_microphonewear (1047561180980891136) -->
+    <skip />
+    <!-- no translation found for permgrouplab_camerawear (4543951283103407017) -->
+    <skip />
+    <!-- no translation found for permgrouplab_phonewear (134365036753766126) -->
+    <skip />
+    <!-- no translation found for permgrouplab_sensorswear (1429324744329327663) -->
+    <skip />
+    <!-- no translation found for permlab_statusBarServicewear (2469402818964691034) -->
+    <skip />
+    <!-- no translation found for permlab_bodySensorswear (7857941041202791873) -->
+    <skip />
+    <!-- no translation found for permlab_accessFineLocationwear (5584423486924377563) -->
+    <skip />
+    <!-- no translation found for permlab_accessCoarseLocationwear (5880746016230166090) -->
+    <skip />
+    <!-- no translation found for permlab_sim_communicationwear (1899198085342781874) -->
+    <skip />
+    <!-- no translation found for permlab_createNetworkSocketswear (6467042386273822913) -->
+    <skip />
+    <!-- no translation found for permlab_manageProfileAndDeviceOwnerswear (7313340516937821847) -->
+    <skip />
+    <!-- no translation found for permlab_changeWimaxStatewear (3828470843939853744) -->
+    <skip />
+    <!-- no translation found for permlab_handoverStatuswear (4835786819716499249) -->
+    <skip />
+    <!-- no translation found for permlab_route_media_outputwear (8737024341474587192) -->
+    <skip />
+    <!-- no translation found for permlab_readInstallSessionswear (9059478058685861989) -->
+    <skip />
+    <!-- no translation found for permlab_requestInstallPackageswear (4982025836783539503) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-te-rIN-watch/strings.xml b/core/res/res/values-te-rIN-watch/strings.xml
index 6b4b900..0843471 100644
--- a/core/res/res/values-te-rIN-watch/strings.xml
+++ b/core/res/res/values-te-rIN-watch/strings.xml
@@ -21,4 +21,48 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="android_upgrading_apk" msgid="1090732262010398759">"<xliff:g id="NUMBER_1">%2$d</xliff:g>లో <xliff:g id="NUMBER_0">%1$d</xliff:g>వ అనువర్తనం."</string>
+    <!-- no translation found for permgrouplab_sensors (202675452368612754) -->
+    <skip />
+    <!-- no translation found for permgrouplab_contactswear (2340286500790908344) -->
+    <skip />
+    <!-- no translation found for permgrouplab_locationwear (6275317222482780209) -->
+    <skip />
+    <!-- no translation found for permgrouplab_calendarwear (441900844045065081) -->
+    <skip />
+    <!-- no translation found for permgrouplab_smswear (6849506550342974220) -->
+    <skip />
+    <!-- no translation found for permgrouplab_storagewear (1003807594193602313) -->
+    <skip />
+    <!-- no translation found for permgrouplab_microphonewear (1047561180980891136) -->
+    <skip />
+    <!-- no translation found for permgrouplab_camerawear (4543951283103407017) -->
+    <skip />
+    <!-- no translation found for permgrouplab_phonewear (134365036753766126) -->
+    <skip />
+    <!-- no translation found for permgrouplab_sensorswear (1429324744329327663) -->
+    <skip />
+    <!-- no translation found for permlab_statusBarServicewear (2469402818964691034) -->
+    <skip />
+    <!-- no translation found for permlab_bodySensorswear (7857941041202791873) -->
+    <skip />
+    <!-- no translation found for permlab_accessFineLocationwear (5584423486924377563) -->
+    <skip />
+    <!-- no translation found for permlab_accessCoarseLocationwear (5880746016230166090) -->
+    <skip />
+    <!-- no translation found for permlab_sim_communicationwear (1899198085342781874) -->
+    <skip />
+    <!-- no translation found for permlab_createNetworkSocketswear (6467042386273822913) -->
+    <skip />
+    <!-- no translation found for permlab_manageProfileAndDeviceOwnerswear (7313340516937821847) -->
+    <skip />
+    <!-- no translation found for permlab_changeWimaxStatewear (3828470843939853744) -->
+    <skip />
+    <!-- no translation found for permlab_handoverStatuswear (4835786819716499249) -->
+    <skip />
+    <!-- no translation found for permlab_route_media_outputwear (8737024341474587192) -->
+    <skip />
+    <!-- no translation found for permlab_readInstallSessionswear (9059478058685861989) -->
+    <skip />
+    <!-- no translation found for permlab_requestInstallPackageswear (4982025836783539503) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-th-watch/strings.xml b/core/res/res/values-th-watch/strings.xml
index 568b083..9cc21b0 100644
--- a/core/res/res/values-th-watch/strings.xml
+++ b/core/res/res/values-th-watch/strings.xml
@@ -21,4 +21,48 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="android_upgrading_apk" msgid="1090732262010398759">"แอป <xliff:g id="NUMBER_0">%1$d</xliff:g> จาก <xliff:g id="NUMBER_1">%2$d</xliff:g> แอป"</string>
+    <!-- no translation found for permgrouplab_sensors (202675452368612754) -->
+    <skip />
+    <!-- no translation found for permgrouplab_contactswear (2340286500790908344) -->
+    <skip />
+    <!-- no translation found for permgrouplab_locationwear (6275317222482780209) -->
+    <skip />
+    <!-- no translation found for permgrouplab_calendarwear (441900844045065081) -->
+    <skip />
+    <!-- no translation found for permgrouplab_smswear (6849506550342974220) -->
+    <skip />
+    <!-- no translation found for permgrouplab_storagewear (1003807594193602313) -->
+    <skip />
+    <!-- no translation found for permgrouplab_microphonewear (1047561180980891136) -->
+    <skip />
+    <!-- no translation found for permgrouplab_camerawear (4543951283103407017) -->
+    <skip />
+    <!-- no translation found for permgrouplab_phonewear (134365036753766126) -->
+    <skip />
+    <!-- no translation found for permgrouplab_sensorswear (1429324744329327663) -->
+    <skip />
+    <!-- no translation found for permlab_statusBarServicewear (2469402818964691034) -->
+    <skip />
+    <!-- no translation found for permlab_bodySensorswear (7857941041202791873) -->
+    <skip />
+    <!-- no translation found for permlab_accessFineLocationwear (5584423486924377563) -->
+    <skip />
+    <!-- no translation found for permlab_accessCoarseLocationwear (5880746016230166090) -->
+    <skip />
+    <!-- no translation found for permlab_sim_communicationwear (1899198085342781874) -->
+    <skip />
+    <!-- no translation found for permlab_createNetworkSocketswear (6467042386273822913) -->
+    <skip />
+    <!-- no translation found for permlab_manageProfileAndDeviceOwnerswear (7313340516937821847) -->
+    <skip />
+    <!-- no translation found for permlab_changeWimaxStatewear (3828470843939853744) -->
+    <skip />
+    <!-- no translation found for permlab_handoverStatuswear (4835786819716499249) -->
+    <skip />
+    <!-- no translation found for permlab_route_media_outputwear (8737024341474587192) -->
+    <skip />
+    <!-- no translation found for permlab_readInstallSessionswear (9059478058685861989) -->
+    <skip />
+    <!-- no translation found for permlab_requestInstallPackageswear (4982025836783539503) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-tl-watch/strings.xml b/core/res/res/values-tl-watch/strings.xml
index bb0dc4b..3fba2dc 100644
--- a/core/res/res/values-tl-watch/strings.xml
+++ b/core/res/res/values-tl-watch/strings.xml
@@ -21,4 +21,48 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="android_upgrading_apk" msgid="1090732262010398759">"App <xliff:g id="NUMBER_0">%1$d</xliff:g> ng <xliff:g id="NUMBER_1">%2$d</xliff:g>."</string>
+    <!-- no translation found for permgrouplab_sensors (202675452368612754) -->
+    <skip />
+    <!-- no translation found for permgrouplab_contactswear (2340286500790908344) -->
+    <skip />
+    <!-- no translation found for permgrouplab_locationwear (6275317222482780209) -->
+    <skip />
+    <!-- no translation found for permgrouplab_calendarwear (441900844045065081) -->
+    <skip />
+    <!-- no translation found for permgrouplab_smswear (6849506550342974220) -->
+    <skip />
+    <!-- no translation found for permgrouplab_storagewear (1003807594193602313) -->
+    <skip />
+    <!-- no translation found for permgrouplab_microphonewear (1047561180980891136) -->
+    <skip />
+    <!-- no translation found for permgrouplab_camerawear (4543951283103407017) -->
+    <skip />
+    <!-- no translation found for permgrouplab_phonewear (134365036753766126) -->
+    <skip />
+    <!-- no translation found for permgrouplab_sensorswear (1429324744329327663) -->
+    <skip />
+    <!-- no translation found for permlab_statusBarServicewear (2469402818964691034) -->
+    <skip />
+    <!-- no translation found for permlab_bodySensorswear (7857941041202791873) -->
+    <skip />
+    <!-- no translation found for permlab_accessFineLocationwear (5584423486924377563) -->
+    <skip />
+    <!-- no translation found for permlab_accessCoarseLocationwear (5880746016230166090) -->
+    <skip />
+    <!-- no translation found for permlab_sim_communicationwear (1899198085342781874) -->
+    <skip />
+    <!-- no translation found for permlab_createNetworkSocketswear (6467042386273822913) -->
+    <skip />
+    <!-- no translation found for permlab_manageProfileAndDeviceOwnerswear (7313340516937821847) -->
+    <skip />
+    <!-- no translation found for permlab_changeWimaxStatewear (3828470843939853744) -->
+    <skip />
+    <!-- no translation found for permlab_handoverStatuswear (4835786819716499249) -->
+    <skip />
+    <!-- no translation found for permlab_route_media_outputwear (8737024341474587192) -->
+    <skip />
+    <!-- no translation found for permlab_readInstallSessionswear (9059478058685861989) -->
+    <skip />
+    <!-- no translation found for permlab_requestInstallPackageswear (4982025836783539503) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-tr-watch/strings.xml b/core/res/res/values-tr-watch/strings.xml
index d9c3923..b34ad74 100644
--- a/core/res/res/values-tr-watch/strings.xml
+++ b/core/res/res/values-tr-watch/strings.xml
@@ -21,4 +21,48 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="android_upgrading_apk" msgid="1090732262010398759">"Uygulama <xliff:g id="NUMBER_0">%1$d</xliff:g> / <xliff:g id="NUMBER_1">%2$d</xliff:g>."</string>
+    <!-- no translation found for permgrouplab_sensors (202675452368612754) -->
+    <skip />
+    <!-- no translation found for permgrouplab_contactswear (2340286500790908344) -->
+    <skip />
+    <!-- no translation found for permgrouplab_locationwear (6275317222482780209) -->
+    <skip />
+    <!-- no translation found for permgrouplab_calendarwear (441900844045065081) -->
+    <skip />
+    <!-- no translation found for permgrouplab_smswear (6849506550342974220) -->
+    <skip />
+    <!-- no translation found for permgrouplab_storagewear (1003807594193602313) -->
+    <skip />
+    <!-- no translation found for permgrouplab_microphonewear (1047561180980891136) -->
+    <skip />
+    <!-- no translation found for permgrouplab_camerawear (4543951283103407017) -->
+    <skip />
+    <!-- no translation found for permgrouplab_phonewear (134365036753766126) -->
+    <skip />
+    <!-- no translation found for permgrouplab_sensorswear (1429324744329327663) -->
+    <skip />
+    <!-- no translation found for permlab_statusBarServicewear (2469402818964691034) -->
+    <skip />
+    <!-- no translation found for permlab_bodySensorswear (7857941041202791873) -->
+    <skip />
+    <!-- no translation found for permlab_accessFineLocationwear (5584423486924377563) -->
+    <skip />
+    <!-- no translation found for permlab_accessCoarseLocationwear (5880746016230166090) -->
+    <skip />
+    <!-- no translation found for permlab_sim_communicationwear (1899198085342781874) -->
+    <skip />
+    <!-- no translation found for permlab_createNetworkSocketswear (6467042386273822913) -->
+    <skip />
+    <!-- no translation found for permlab_manageProfileAndDeviceOwnerswear (7313340516937821847) -->
+    <skip />
+    <!-- no translation found for permlab_changeWimaxStatewear (3828470843939853744) -->
+    <skip />
+    <!-- no translation found for permlab_handoverStatuswear (4835786819716499249) -->
+    <skip />
+    <!-- no translation found for permlab_route_media_outputwear (8737024341474587192) -->
+    <skip />
+    <!-- no translation found for permlab_readInstallSessionswear (9059478058685861989) -->
+    <skip />
+    <!-- no translation found for permlab_requestInstallPackageswear (4982025836783539503) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-uk-watch/strings.xml b/core/res/res/values-uk-watch/strings.xml
index 02e6466..4141b08 100644
--- a/core/res/res/values-uk-watch/strings.xml
+++ b/core/res/res/values-uk-watch/strings.xml
@@ -21,4 +21,48 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="android_upgrading_apk" msgid="1090732262010398759">"Додаток <xliff:g id="NUMBER_0">%1$d</xliff:g> з <xliff:g id="NUMBER_1">%2$d</xliff:g>."</string>
+    <!-- no translation found for permgrouplab_sensors (202675452368612754) -->
+    <skip />
+    <!-- no translation found for permgrouplab_contactswear (2340286500790908344) -->
+    <skip />
+    <!-- no translation found for permgrouplab_locationwear (6275317222482780209) -->
+    <skip />
+    <!-- no translation found for permgrouplab_calendarwear (441900844045065081) -->
+    <skip />
+    <!-- no translation found for permgrouplab_smswear (6849506550342974220) -->
+    <skip />
+    <!-- no translation found for permgrouplab_storagewear (1003807594193602313) -->
+    <skip />
+    <!-- no translation found for permgrouplab_microphonewear (1047561180980891136) -->
+    <skip />
+    <!-- no translation found for permgrouplab_camerawear (4543951283103407017) -->
+    <skip />
+    <!-- no translation found for permgrouplab_phonewear (134365036753766126) -->
+    <skip />
+    <!-- no translation found for permgrouplab_sensorswear (1429324744329327663) -->
+    <skip />
+    <!-- no translation found for permlab_statusBarServicewear (2469402818964691034) -->
+    <skip />
+    <!-- no translation found for permlab_bodySensorswear (7857941041202791873) -->
+    <skip />
+    <!-- no translation found for permlab_accessFineLocationwear (5584423486924377563) -->
+    <skip />
+    <!-- no translation found for permlab_accessCoarseLocationwear (5880746016230166090) -->
+    <skip />
+    <!-- no translation found for permlab_sim_communicationwear (1899198085342781874) -->
+    <skip />
+    <!-- no translation found for permlab_createNetworkSocketswear (6467042386273822913) -->
+    <skip />
+    <!-- no translation found for permlab_manageProfileAndDeviceOwnerswear (7313340516937821847) -->
+    <skip />
+    <!-- no translation found for permlab_changeWimaxStatewear (3828470843939853744) -->
+    <skip />
+    <!-- no translation found for permlab_handoverStatuswear (4835786819716499249) -->
+    <skip />
+    <!-- no translation found for permlab_route_media_outputwear (8737024341474587192) -->
+    <skip />
+    <!-- no translation found for permlab_readInstallSessionswear (9059478058685861989) -->
+    <skip />
+    <!-- no translation found for permlab_requestInstallPackageswear (4982025836783539503) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-ur-rPK-watch/strings.xml b/core/res/res/values-ur-rPK-watch/strings.xml
index 0fd24c9..f90af0b 100644
--- a/core/res/res/values-ur-rPK-watch/strings.xml
+++ b/core/res/res/values-ur-rPK-watch/strings.xml
@@ -21,4 +21,48 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="android_upgrading_apk" msgid="1090732262010398759">"ایپ <xliff:g id="NUMBER_0">%1$d</xliff:g> از <xliff:g id="NUMBER_1">%2$d</xliff:g>۔"</string>
+    <!-- no translation found for permgrouplab_sensors (202675452368612754) -->
+    <skip />
+    <!-- no translation found for permgrouplab_contactswear (2340286500790908344) -->
+    <skip />
+    <!-- no translation found for permgrouplab_locationwear (6275317222482780209) -->
+    <skip />
+    <!-- no translation found for permgrouplab_calendarwear (441900844045065081) -->
+    <skip />
+    <!-- no translation found for permgrouplab_smswear (6849506550342974220) -->
+    <skip />
+    <!-- no translation found for permgrouplab_storagewear (1003807594193602313) -->
+    <skip />
+    <!-- no translation found for permgrouplab_microphonewear (1047561180980891136) -->
+    <skip />
+    <!-- no translation found for permgrouplab_camerawear (4543951283103407017) -->
+    <skip />
+    <!-- no translation found for permgrouplab_phonewear (134365036753766126) -->
+    <skip />
+    <!-- no translation found for permgrouplab_sensorswear (1429324744329327663) -->
+    <skip />
+    <!-- no translation found for permlab_statusBarServicewear (2469402818964691034) -->
+    <skip />
+    <!-- no translation found for permlab_bodySensorswear (7857941041202791873) -->
+    <skip />
+    <!-- no translation found for permlab_accessFineLocationwear (5584423486924377563) -->
+    <skip />
+    <!-- no translation found for permlab_accessCoarseLocationwear (5880746016230166090) -->
+    <skip />
+    <!-- no translation found for permlab_sim_communicationwear (1899198085342781874) -->
+    <skip />
+    <!-- no translation found for permlab_createNetworkSocketswear (6467042386273822913) -->
+    <skip />
+    <!-- no translation found for permlab_manageProfileAndDeviceOwnerswear (7313340516937821847) -->
+    <skip />
+    <!-- no translation found for permlab_changeWimaxStatewear (3828470843939853744) -->
+    <skip />
+    <!-- no translation found for permlab_handoverStatuswear (4835786819716499249) -->
+    <skip />
+    <!-- no translation found for permlab_route_media_outputwear (8737024341474587192) -->
+    <skip />
+    <!-- no translation found for permlab_readInstallSessionswear (9059478058685861989) -->
+    <skip />
+    <!-- no translation found for permlab_requestInstallPackageswear (4982025836783539503) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-uz-rUZ-watch/strings.xml b/core/res/res/values-uz-rUZ-watch/strings.xml
index 7abd603..42fe54a 100644
--- a/core/res/res/values-uz-rUZ-watch/strings.xml
+++ b/core/res/res/values-uz-rUZ-watch/strings.xml
@@ -21,4 +21,48 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="android_upgrading_apk" msgid="1090732262010398759">"<xliff:g id="NUMBER_1">%2$d</xliff:g>dan <xliff:g id="NUMBER_0">%1$d</xliff:g> ilova."</string>
+    <!-- no translation found for permgrouplab_sensors (202675452368612754) -->
+    <skip />
+    <!-- no translation found for permgrouplab_contactswear (2340286500790908344) -->
+    <skip />
+    <!-- no translation found for permgrouplab_locationwear (6275317222482780209) -->
+    <skip />
+    <!-- no translation found for permgrouplab_calendarwear (441900844045065081) -->
+    <skip />
+    <!-- no translation found for permgrouplab_smswear (6849506550342974220) -->
+    <skip />
+    <!-- no translation found for permgrouplab_storagewear (1003807594193602313) -->
+    <skip />
+    <!-- no translation found for permgrouplab_microphonewear (1047561180980891136) -->
+    <skip />
+    <!-- no translation found for permgrouplab_camerawear (4543951283103407017) -->
+    <skip />
+    <!-- no translation found for permgrouplab_phonewear (134365036753766126) -->
+    <skip />
+    <!-- no translation found for permgrouplab_sensorswear (1429324744329327663) -->
+    <skip />
+    <!-- no translation found for permlab_statusBarServicewear (2469402818964691034) -->
+    <skip />
+    <!-- no translation found for permlab_bodySensorswear (7857941041202791873) -->
+    <skip />
+    <!-- no translation found for permlab_accessFineLocationwear (5584423486924377563) -->
+    <skip />
+    <!-- no translation found for permlab_accessCoarseLocationwear (5880746016230166090) -->
+    <skip />
+    <!-- no translation found for permlab_sim_communicationwear (1899198085342781874) -->
+    <skip />
+    <!-- no translation found for permlab_createNetworkSocketswear (6467042386273822913) -->
+    <skip />
+    <!-- no translation found for permlab_manageProfileAndDeviceOwnerswear (7313340516937821847) -->
+    <skip />
+    <!-- no translation found for permlab_changeWimaxStatewear (3828470843939853744) -->
+    <skip />
+    <!-- no translation found for permlab_handoverStatuswear (4835786819716499249) -->
+    <skip />
+    <!-- no translation found for permlab_route_media_outputwear (8737024341474587192) -->
+    <skip />
+    <!-- no translation found for permlab_readInstallSessionswear (9059478058685861989) -->
+    <skip />
+    <!-- no translation found for permlab_requestInstallPackageswear (4982025836783539503) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-vi-watch/strings.xml b/core/res/res/values-vi-watch/strings.xml
index f419bdf..634d890 100644
--- a/core/res/res/values-vi-watch/strings.xml
+++ b/core/res/res/values-vi-watch/strings.xml
@@ -21,4 +21,48 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="android_upgrading_apk" msgid="1090732262010398759">"Ứng dụng <xliff:g id="NUMBER_0">%1$d</xliff:g> / <xliff:g id="NUMBER_1">%2$d</xliff:g>."</string>
+    <!-- no translation found for permgrouplab_sensors (202675452368612754) -->
+    <skip />
+    <!-- no translation found for permgrouplab_contactswear (2340286500790908344) -->
+    <skip />
+    <!-- no translation found for permgrouplab_locationwear (6275317222482780209) -->
+    <skip />
+    <!-- no translation found for permgrouplab_calendarwear (441900844045065081) -->
+    <skip />
+    <!-- no translation found for permgrouplab_smswear (6849506550342974220) -->
+    <skip />
+    <!-- no translation found for permgrouplab_storagewear (1003807594193602313) -->
+    <skip />
+    <!-- no translation found for permgrouplab_microphonewear (1047561180980891136) -->
+    <skip />
+    <!-- no translation found for permgrouplab_camerawear (4543951283103407017) -->
+    <skip />
+    <!-- no translation found for permgrouplab_phonewear (134365036753766126) -->
+    <skip />
+    <!-- no translation found for permgrouplab_sensorswear (1429324744329327663) -->
+    <skip />
+    <!-- no translation found for permlab_statusBarServicewear (2469402818964691034) -->
+    <skip />
+    <!-- no translation found for permlab_bodySensorswear (7857941041202791873) -->
+    <skip />
+    <!-- no translation found for permlab_accessFineLocationwear (5584423486924377563) -->
+    <skip />
+    <!-- no translation found for permlab_accessCoarseLocationwear (5880746016230166090) -->
+    <skip />
+    <!-- no translation found for permlab_sim_communicationwear (1899198085342781874) -->
+    <skip />
+    <!-- no translation found for permlab_createNetworkSocketswear (6467042386273822913) -->
+    <skip />
+    <!-- no translation found for permlab_manageProfileAndDeviceOwnerswear (7313340516937821847) -->
+    <skip />
+    <!-- no translation found for permlab_changeWimaxStatewear (3828470843939853744) -->
+    <skip />
+    <!-- no translation found for permlab_handoverStatuswear (4835786819716499249) -->
+    <skip />
+    <!-- no translation found for permlab_route_media_outputwear (8737024341474587192) -->
+    <skip />
+    <!-- no translation found for permlab_readInstallSessionswear (9059478058685861989) -->
+    <skip />
+    <!-- no translation found for permlab_requestInstallPackageswear (4982025836783539503) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-zh-rCN-watch/strings.xml b/core/res/res/values-zh-rCN-watch/strings.xml
index 9c9e49d..8864701 100644
--- a/core/res/res/values-zh-rCN-watch/strings.xml
+++ b/core/res/res/values-zh-rCN-watch/strings.xml
@@ -21,4 +21,48 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="android_upgrading_apk" msgid="1090732262010398759">"应用:<xliff:g id="NUMBER_0">%1$d</xliff:g> / <xliff:g id="NUMBER_1">%2$d</xliff:g>。"</string>
+    <!-- no translation found for permgrouplab_sensors (202675452368612754) -->
+    <skip />
+    <!-- no translation found for permgrouplab_contactswear (2340286500790908344) -->
+    <skip />
+    <!-- no translation found for permgrouplab_locationwear (6275317222482780209) -->
+    <skip />
+    <!-- no translation found for permgrouplab_calendarwear (441900844045065081) -->
+    <skip />
+    <!-- no translation found for permgrouplab_smswear (6849506550342974220) -->
+    <skip />
+    <!-- no translation found for permgrouplab_storagewear (1003807594193602313) -->
+    <skip />
+    <!-- no translation found for permgrouplab_microphonewear (1047561180980891136) -->
+    <skip />
+    <!-- no translation found for permgrouplab_camerawear (4543951283103407017) -->
+    <skip />
+    <!-- no translation found for permgrouplab_phonewear (134365036753766126) -->
+    <skip />
+    <!-- no translation found for permgrouplab_sensorswear (1429324744329327663) -->
+    <skip />
+    <!-- no translation found for permlab_statusBarServicewear (2469402818964691034) -->
+    <skip />
+    <!-- no translation found for permlab_bodySensorswear (7857941041202791873) -->
+    <skip />
+    <!-- no translation found for permlab_accessFineLocationwear (5584423486924377563) -->
+    <skip />
+    <!-- no translation found for permlab_accessCoarseLocationwear (5880746016230166090) -->
+    <skip />
+    <!-- no translation found for permlab_sim_communicationwear (1899198085342781874) -->
+    <skip />
+    <!-- no translation found for permlab_createNetworkSocketswear (6467042386273822913) -->
+    <skip />
+    <!-- no translation found for permlab_manageProfileAndDeviceOwnerswear (7313340516937821847) -->
+    <skip />
+    <!-- no translation found for permlab_changeWimaxStatewear (3828470843939853744) -->
+    <skip />
+    <!-- no translation found for permlab_handoverStatuswear (4835786819716499249) -->
+    <skip />
+    <!-- no translation found for permlab_route_media_outputwear (8737024341474587192) -->
+    <skip />
+    <!-- no translation found for permlab_readInstallSessionswear (9059478058685861989) -->
+    <skip />
+    <!-- no translation found for permlab_requestInstallPackageswear (4982025836783539503) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-zh-rHK-watch/strings.xml b/core/res/res/values-zh-rHK-watch/strings.xml
index 3b5fb8e..356e853 100644
--- a/core/res/res/values-zh-rHK-watch/strings.xml
+++ b/core/res/res/values-zh-rHK-watch/strings.xml
@@ -21,4 +21,48 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="android_upgrading_apk" msgid="1090732262010398759">"應用程式 (<xliff:g id="NUMBER_0">%1$d</xliff:g>/<xliff:g id="NUMBER_1">%2$d</xliff:g>)"</string>
+    <!-- no translation found for permgrouplab_sensors (202675452368612754) -->
+    <skip />
+    <!-- no translation found for permgrouplab_contactswear (2340286500790908344) -->
+    <skip />
+    <!-- no translation found for permgrouplab_locationwear (6275317222482780209) -->
+    <skip />
+    <!-- no translation found for permgrouplab_calendarwear (441900844045065081) -->
+    <skip />
+    <!-- no translation found for permgrouplab_smswear (6849506550342974220) -->
+    <skip />
+    <!-- no translation found for permgrouplab_storagewear (1003807594193602313) -->
+    <skip />
+    <!-- no translation found for permgrouplab_microphonewear (1047561180980891136) -->
+    <skip />
+    <!-- no translation found for permgrouplab_camerawear (4543951283103407017) -->
+    <skip />
+    <!-- no translation found for permgrouplab_phonewear (134365036753766126) -->
+    <skip />
+    <!-- no translation found for permgrouplab_sensorswear (1429324744329327663) -->
+    <skip />
+    <!-- no translation found for permlab_statusBarServicewear (2469402818964691034) -->
+    <skip />
+    <!-- no translation found for permlab_bodySensorswear (7857941041202791873) -->
+    <skip />
+    <!-- no translation found for permlab_accessFineLocationwear (5584423486924377563) -->
+    <skip />
+    <!-- no translation found for permlab_accessCoarseLocationwear (5880746016230166090) -->
+    <skip />
+    <!-- no translation found for permlab_sim_communicationwear (1899198085342781874) -->
+    <skip />
+    <!-- no translation found for permlab_createNetworkSocketswear (6467042386273822913) -->
+    <skip />
+    <!-- no translation found for permlab_manageProfileAndDeviceOwnerswear (7313340516937821847) -->
+    <skip />
+    <!-- no translation found for permlab_changeWimaxStatewear (3828470843939853744) -->
+    <skip />
+    <!-- no translation found for permlab_handoverStatuswear (4835786819716499249) -->
+    <skip />
+    <!-- no translation found for permlab_route_media_outputwear (8737024341474587192) -->
+    <skip />
+    <!-- no translation found for permlab_readInstallSessionswear (9059478058685861989) -->
+    <skip />
+    <!-- no translation found for permlab_requestInstallPackageswear (4982025836783539503) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-zh-rTW-watch/strings.xml b/core/res/res/values-zh-rTW-watch/strings.xml
index 87f3abb..20ef6ba 100644
--- a/core/res/res/values-zh-rTW-watch/strings.xml
+++ b/core/res/res/values-zh-rTW-watch/strings.xml
@@ -21,4 +21,48 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="android_upgrading_apk" msgid="1090732262010398759">"應用程式 <xliff:g id="NUMBER_0">%1$d</xliff:g>/<xliff:g id="NUMBER_1">%2$d</xliff:g>。"</string>
+    <!-- no translation found for permgrouplab_sensors (202675452368612754) -->
+    <skip />
+    <!-- no translation found for permgrouplab_contactswear (2340286500790908344) -->
+    <skip />
+    <!-- no translation found for permgrouplab_locationwear (6275317222482780209) -->
+    <skip />
+    <!-- no translation found for permgrouplab_calendarwear (441900844045065081) -->
+    <skip />
+    <!-- no translation found for permgrouplab_smswear (6849506550342974220) -->
+    <skip />
+    <!-- no translation found for permgrouplab_storagewear (1003807594193602313) -->
+    <skip />
+    <!-- no translation found for permgrouplab_microphonewear (1047561180980891136) -->
+    <skip />
+    <!-- no translation found for permgrouplab_camerawear (4543951283103407017) -->
+    <skip />
+    <!-- no translation found for permgrouplab_phonewear (134365036753766126) -->
+    <skip />
+    <!-- no translation found for permgrouplab_sensorswear (1429324744329327663) -->
+    <skip />
+    <!-- no translation found for permlab_statusBarServicewear (2469402818964691034) -->
+    <skip />
+    <!-- no translation found for permlab_bodySensorswear (7857941041202791873) -->
+    <skip />
+    <!-- no translation found for permlab_accessFineLocationwear (5584423486924377563) -->
+    <skip />
+    <!-- no translation found for permlab_accessCoarseLocationwear (5880746016230166090) -->
+    <skip />
+    <!-- no translation found for permlab_sim_communicationwear (1899198085342781874) -->
+    <skip />
+    <!-- no translation found for permlab_createNetworkSocketswear (6467042386273822913) -->
+    <skip />
+    <!-- no translation found for permlab_manageProfileAndDeviceOwnerswear (7313340516937821847) -->
+    <skip />
+    <!-- no translation found for permlab_changeWimaxStatewear (3828470843939853744) -->
+    <skip />
+    <!-- no translation found for permlab_handoverStatuswear (4835786819716499249) -->
+    <skip />
+    <!-- no translation found for permlab_route_media_outputwear (8737024341474587192) -->
+    <skip />
+    <!-- no translation found for permlab_readInstallSessionswear (9059478058685861989) -->
+    <skip />
+    <!-- no translation found for permlab_requestInstallPackageswear (4982025836783539503) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-zu-watch/strings.xml b/core/res/res/values-zu-watch/strings.xml
index acd153b..22b8af7 100644
--- a/core/res/res/values-zu-watch/strings.xml
+++ b/core/res/res/values-zu-watch/strings.xml
@@ -21,4 +21,48 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="android_upgrading_apk" msgid="1090732262010398759">"Uhlelo lokusebenza olungu-<xliff:g id="NUMBER_0">%1$d</xliff:g> kokungu-<xliff:g id="NUMBER_1">%2$d</xliff:g>."</string>
+    <!-- no translation found for permgrouplab_sensors (202675452368612754) -->
+    <skip />
+    <!-- no translation found for permgrouplab_contactswear (2340286500790908344) -->
+    <skip />
+    <!-- no translation found for permgrouplab_locationwear (6275317222482780209) -->
+    <skip />
+    <!-- no translation found for permgrouplab_calendarwear (441900844045065081) -->
+    <skip />
+    <!-- no translation found for permgrouplab_smswear (6849506550342974220) -->
+    <skip />
+    <!-- no translation found for permgrouplab_storagewear (1003807594193602313) -->
+    <skip />
+    <!-- no translation found for permgrouplab_microphonewear (1047561180980891136) -->
+    <skip />
+    <!-- no translation found for permgrouplab_camerawear (4543951283103407017) -->
+    <skip />
+    <!-- no translation found for permgrouplab_phonewear (134365036753766126) -->
+    <skip />
+    <!-- no translation found for permgrouplab_sensorswear (1429324744329327663) -->
+    <skip />
+    <!-- no translation found for permlab_statusBarServicewear (2469402818964691034) -->
+    <skip />
+    <!-- no translation found for permlab_bodySensorswear (7857941041202791873) -->
+    <skip />
+    <!-- no translation found for permlab_accessFineLocationwear (5584423486924377563) -->
+    <skip />
+    <!-- no translation found for permlab_accessCoarseLocationwear (5880746016230166090) -->
+    <skip />
+    <!-- no translation found for permlab_sim_communicationwear (1899198085342781874) -->
+    <skip />
+    <!-- no translation found for permlab_createNetworkSocketswear (6467042386273822913) -->
+    <skip />
+    <!-- no translation found for permlab_manageProfileAndDeviceOwnerswear (7313340516937821847) -->
+    <skip />
+    <!-- no translation found for permlab_changeWimaxStatewear (3828470843939853744) -->
+    <skip />
+    <!-- no translation found for permlab_handoverStatuswear (4835786819716499249) -->
+    <skip />
+    <!-- no translation found for permlab_route_media_outputwear (8737024341474587192) -->
+    <skip />
+    <!-- no translation found for permlab_readInstallSessionswear (9059478058685861989) -->
+    <skip />
+    <!-- no translation found for permlab_requestInstallPackageswear (4982025836783539503) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values/attrs_manifest.xml b/core/res/res/values/attrs_manifest.xml
index 1a2600d..4531f75 100644
--- a/core/res/res/values/attrs_manifest.xml
+++ b/core/res/res/values/attrs_manifest.xml
@@ -1816,9 +1816,9 @@
         <attr name="uiOptions" />
         <attr name="parentActivityName" />
         <attr name="singleUser" />
-        <!-- @hide This broacast receiver will only receive broadcasts for the
-             primary user.  Can only be used with receivers. -->
-        <attr name="primaryUserOnly" format="boolean" />
+        <!-- @hide This broadcast receiver or activity will only receive broadcasts for the
+             system user-->
+        <attr name="systemUserOnly" format="boolean" />
         <attr name="persistableMode" />
         <attr name="allowEmbedded" />
         <attr name="documentLaunchMode" />
diff --git a/core/res/res/values/config.xml b/core/res/res/values/config.xml
index 2c940ae..ef4e261 100755
--- a/core/res/res/values/config.xml
+++ b/core/res/res/values/config.xml
@@ -2029,10 +2029,6 @@
         IMS service implementation will do both.i.e.hold followed by merge. -->
     <bool name="skipHoldBeforeMerge">true</bool>
 
-    <!-- Flag indicating emergency calls will always use IMS irrespective of the state of
-    the IMS connection -->
-    <bool name="useImsAlwaysForEmergencyCall">true</bool>
-
     <!-- Flag indicating whether the IMS service can be turned off. If false then
         the service will not be turned-off completely (the ImsManager.turnOffIms() will
         be disabled) but individual Features can be disabled using ImsConfig.setFeatureValue() -->
diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml
index a55258c..e04c743 100755
--- a/core/res/res/values/symbols.xml
+++ b/core/res/res/values/symbols.xml
@@ -2138,7 +2138,6 @@
   <java-symbol type="bool" name="config_carrier_vt_available" />
   <java-symbol type="bool" name="config_device_wfc_ims_available" />
   <java-symbol type="bool" name="config_carrier_wfc_ims_available" />
-  <java-symbol type="bool" name="useImsAlwaysForEmergencyCall" />
   <java-symbol type="attr" name="touchscreenBlocksFocus" />
   <java-symbol type="layout" name="resolver_list_with_default" />
   <java-symbol type="string" name="whichApplicationNamed" />
diff --git a/core/tests/coretests/src/android/animation/ValueAnimatorTests.java b/core/tests/coretests/src/android/animation/ValueAnimatorTests.java
index 03ae9dc..d99ee80 100644
--- a/core/tests/coretests/src/android/animation/ValueAnimatorTests.java
+++ b/core/tests/coretests/src/android/animation/ValueAnimatorTests.java
@@ -387,6 +387,63 @@
     }
 
     @SmallTest
+    public void testEnd() throws Throwable {
+        final MyListener l1 = new MyListener();
+        final MyListener l2 = new MyListener();
+        a1.addListener(l1);
+        a2.addListener(l2);
+        a1.addListener(new MyListener() {
+            @Override
+            public void onAnimationEnd(Animator anim) {
+                anim.cancel();
+            }
+        });
+        a2.addListener(new MyListener() {
+            @Override
+            public void onAnimationCancel(Animator anim) {
+                anim.end();
+            }
+        });
+
+        runTestOnUiThread(new Runnable() {
+            @Override
+            public void run() {
+                assertFalse(l1.cancelCalled);
+                assertFalse(l1.endCalled);
+                assertFalse(l2.cancelCalled);
+                assertFalse(l2.endCalled);
+                a1.start();
+                a2.start();
+            }
+        });
+        Thread.sleep(POLL_INTERVAL);
+        runTestOnUiThread(new Runnable() {
+            @Override
+            public void run() {
+                a1.end();
+                a2.cancel();
+            }
+        });
+        Thread.sleep(POLL_INTERVAL);
+        runTestOnUiThread(new Runnable() {
+            @Override
+            public void run() {
+                // Calling cancel from onAnimationEnd will be ignored.
+                assertFalse(l1.cancelCalled);
+                assertTrue(l1.endCalled);
+                assertTrue(l2.cancelCalled);
+                assertTrue(l2.endCalled);
+
+                float value1 = (Float) a1.getAnimatedValue();
+                int value2 = (Integer) a2.getAnimatedValue();
+                assertEquals(A1_END_VALUE, value1);
+                assertEquals(A2_END_VALUE, value2);
+            }
+        });
+
+    }
+
+    @SmallTest
     public void testEndValue() throws Throwable {
         final MyListener l1 = new MyListener();
         a1.addListener(l1);
diff --git a/core/tests/coretests/src/android/app/backup/FullBackupTest.java b/core/tests/coretests/src/android/app/backup/FullBackupTest.java
index 8c9c63c..c3afbf6 100644
--- a/core/tests/coretests/src/android/app/backup/FullBackupTest.java
+++ b/core/tests/coretests/src/android/app/backup/FullBackupTest.java
@@ -114,12 +114,14 @@
     public void testparseBackupSchemeFromXml_lotsOfIncludesAndExcludes() throws Exception {
         mXpp.setInput(new StringReader(
                 "<full-backup-content>" +
-                        "<exclude path=\"exclude1.txt\" domain=\"file\"/>" +
+                         "<exclude path=\"exclude1.txt\" domain=\"file\"/>" +
                         "<include path=\"include1.txt\" domain=\"file\"/>" +
                          "<exclude path=\"exclude2.txt\" domain=\"database\"/>" +
                         "<include path=\"include2.txt\" domain=\"database\"/>" +
-                         "<exclude path=\"exclude3.txt\" domain=\"sharedpref\"/>" +
-                        "<include path=\"include3.txt\" domain=\"sharedpref\"/>" +
+                         "<exclude path=\"exclude3\" domain=\"sharedpref\"/>" +
+                        "<include path=\"include3\" domain=\"sharedpref\"/>" +
+                         "<exclude path=\"exclude4.xml\" domain=\"sharedpref\"/>" +
+                        "<include path=\"include4.xml\" domain=\"sharedpref\"/>" +
                 "</full-backup-content>"));
 
 
@@ -146,16 +148,27 @@
                                 "include2.txt-journal")
                                 .getCanonicalPath()));
 
-        Set<String> sharedPrefDomainIncludes = includeMap.get(FullBackup.SHAREDPREFS_TREE_TOKEN);
+        List<String> sharedPrefDomainIncludes = new ArrayList<String>(
+                includeMap.get(FullBackup.SHAREDPREFS_TREE_TOKEN));
+        Collections.sort(sharedPrefDomainIncludes);
+
         assertEquals("Didn't find expected sharedpref domain include.",
-                1, sharedPrefDomainIncludes.size());
+                3, sharedPrefDomainIncludes.size());
         assertEquals("Invalid path parsed for <include/>",
-                new File(mContext.getSharedPrefsFile("foo").getParentFile(), "include3.txt")
+                new File(mContext.getSharedPrefsFile("foo").getParentFile(), "include3")
                         .getCanonicalPath(),
-                sharedPrefDomainIncludes.iterator().next());
+                sharedPrefDomainIncludes.get(0));
+        assertEquals("Invalid path parsed for <include/>",
+                new File(mContext.getSharedPrefsFile("foo").getParentFile(), "include3.xml")
+                        .getCanonicalPath(),
+                sharedPrefDomainIncludes.get(1));
+        assertEquals("Invalid path parsed for <include/>",
+                new File(mContext.getSharedPrefsFile("foo").getParentFile(), "include4.xml")
+                        .getCanonicalPath(),
+                sharedPrefDomainIncludes.get(2));
 
 
-        assertEquals("Unexpected number of <exclude/>s", 4, excludesSet.size());
+        assertEquals("Unexpected number of <exclude/>s", 6, excludesSet.size());
         // Sets are annoying to iterate over b/c order isn't enforced - convert to an array and
         // sort lexicographically.
         List<String> arrayedSet = new ArrayList<String>(excludesSet);
@@ -173,9 +186,17 @@
                 new File(mContext.getFilesDir(), "exclude1.txt").getCanonicalPath(),
                 arrayedSet.get(2));
         assertEquals("Invalid path parsed for <exclude/>",
-                new File(mContext.getSharedPrefsFile("foo").getParentFile(), "exclude3.txt")
+                new File(mContext.getSharedPrefsFile("foo").getParentFile(), "exclude3")
                         .getCanonicalPath(),
                 arrayedSet.get(3));
+        assertEquals("Invalid path parsed for <exclude/>",
+                new File(mContext.getSharedPrefsFile("foo").getParentFile(), "exclude3.xml")
+                        .getCanonicalPath(),
+                arrayedSet.get(4));
+        assertEquals("Invalid path parsed for <exclude/>",
+                new File(mContext.getSharedPrefsFile("foo").getParentFile(), "exclude4.xml")
+                        .getCanonicalPath(),
+                arrayedSet.get(5));
     }
 
     public void testParseBackupSchemeFromXml_invalidXmlFails() throws Exception {
diff --git a/core/tests/coretests/src/android/content/pm/AppsQueryHelperTests.java b/core/tests/coretests/src/android/content/pm/AppsQueryHelperTests.java
new file mode 100644
index 0000000..80181cf
--- /dev/null
+++ b/core/tests/coretests/src/android/content/pm/AppsQueryHelperTests.java
@@ -0,0 +1,131 @@
+/*
+ * Copyright (C) 2015 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.content.pm;
+
+import android.content.Context;
+import android.content.Intent;
+import android.os.UserHandle;
+import android.test.AndroidTestCase;
+
+import java.util.Arrays;
+import java.util.HashSet;
+import java.util.List;
+
+public class AppsQueryHelperTests extends AndroidTestCase {
+
+    private AppsQueryHelper mAppsQueryHelper;
+
+    @Override
+    public void setUp() throws Exception {
+        super.setUp();
+        mAppsQueryHelper = new AppsQueryHelperTestable(getContext());
+    }
+
+    public void testQueryAppsSystemAppsOnly() {
+        List<String> apps = mAppsQueryHelper.queryApps(0, true, UserHandle.SYSTEM);
+        assertEqualsIgnoreOrder(Arrays.asList("sys_app1", "sys_app2", "sys_app3"), apps);
+
+        apps = mAppsQueryHelper.queryApps(0, false, UserHandle.SYSTEM);
+        assertEqualsIgnoreOrder(Arrays.asList("sys_app1", "sys_app2", "sys_app3", "app4"), apps);
+    }
+
+    public void testQueryAppsNonLaunchable() {
+        List<String> apps = mAppsQueryHelper.queryApps(AppsQueryHelper.GET_NON_LAUNCHABLE_APPS,
+                true, UserHandle.SYSTEM);
+        assertEqualsIgnoreOrder(Arrays.asList("sys_app1", "sys_app3"), apps);
+
+        apps = mAppsQueryHelper.queryApps(AppsQueryHelper.GET_NON_LAUNCHABLE_APPS,
+                false, UserHandle.SYSTEM);
+        assertEqualsIgnoreOrder(Arrays.asList("sys_app1", "sys_app3"), apps);
+    }
+
+    public void testQueryAppsInteractAcrossUser() {
+        List<String> apps = mAppsQueryHelper.queryApps(
+                AppsQueryHelper.GET_APPS_WITH_INTERACT_ACROSS_USERS_PERM, true, UserHandle.SYSTEM);
+        assertEqualsIgnoreOrder(Arrays.asList("sys_app1"), apps);
+
+        apps = mAppsQueryHelper.queryApps(
+                AppsQueryHelper.GET_APPS_WITH_INTERACT_ACROSS_USERS_PERM, false, UserHandle.SYSTEM);
+        assertEqualsIgnoreOrder(Arrays.asList("sys_app1"), apps);
+    }
+
+    public void testQueryApps() {
+        List<String> apps = mAppsQueryHelper.queryApps(
+                AppsQueryHelper.GET_NON_LAUNCHABLE_APPS
+                        |AppsQueryHelper.GET_APPS_WITH_INTERACT_ACROSS_USERS_PERM,
+                true, UserHandle.SYSTEM);
+        assertEqualsIgnoreOrder(Arrays.asList("sys_app1", "sys_app3"), apps);
+
+        apps = mAppsQueryHelper.queryApps(
+                AppsQueryHelper.GET_NON_LAUNCHABLE_APPS
+                        |AppsQueryHelper.GET_APPS_WITH_INTERACT_ACROSS_USERS_PERM,
+                false, UserHandle.SYSTEM);
+        assertEqualsIgnoreOrder(Arrays.asList("sys_app1", "sys_app3"), apps);
+    }
+
+    private class AppsQueryHelperTestable extends AppsQueryHelper {
+
+        public AppsQueryHelperTestable(Context context) {
+            super(context);
+        }
+
+        @Override
+        protected List<ApplicationInfo> getAllApps(int userId) {
+            final ApplicationInfo ai1 = new ApplicationInfo();
+            ai1.flags |= ApplicationInfo.FLAG_SYSTEM;
+            ai1.packageName = "sys_app1";
+            final ApplicationInfo ai2 = new ApplicationInfo();
+            ai2.flags |= ApplicationInfo.FLAG_SYSTEM;
+            ai2.packageName = "sys_app2";
+            ai2.flags |= ApplicationInfo.FLAG_SYSTEM;
+            final ApplicationInfo ai3 = new ApplicationInfo();
+            ai3.packageName = "sys_app3";
+            ai3.flags |= ApplicationInfo.FLAG_SYSTEM;
+            final ApplicationInfo ai4 = new ApplicationInfo();
+            ai4.packageName = "app4";
+            return Arrays.asList(ai1, ai2, ai3, ai4);
+        }
+
+        @Override
+        protected List<ResolveInfo> queryIntentActivitiesAsUser(Intent intent, int userId) {
+            assertEquals(Intent.CATEGORY_LAUNCHER, intent.getCategories().iterator().next());
+            final ResolveInfo r2 = new ResolveInfo();
+            r2.activityInfo = new ActivityInfo();
+            r2.activityInfo.packageName = "sys_app2";
+            r2.activityInfo.flags |= ApplicationInfo.FLAG_SYSTEM;
+            final ResolveInfo r4 = new ResolveInfo();
+            r4.activityInfo = new ActivityInfo();
+            r4.activityInfo.packageName = "app4";
+            return Arrays.asList(r2, r4);
+        }
+
+        @Override
+        protected List<PackageInfo> getPackagesHoldingPermission(String perm, int userId) {
+            final PackageInfo p1 = new PackageInfo();
+            p1.packageName = "sys_app1";
+            p1.applicationInfo = new ApplicationInfo();
+            p1.applicationInfo.flags |= ApplicationInfo.FLAG_SYSTEM;
+            return Arrays.asList(p1);
+        }
+    }
+
+    private static void assertEqualsIgnoreOrder(List<String> expected, List<String> actual) {
+        assertTrue("Lists not equal. Expected " + expected + " but was " + actual,
+                (expected.size() == actual.size())
+                        && (new HashSet<>(expected).equals(new HashSet<>(actual))));
+    }
+}
diff --git a/core/tests/coretests/src/android/widget/SuggestionsPopupWindowTest.java b/core/tests/coretests/src/android/widget/SuggestionsPopupWindowTest.java
new file mode 100644
index 0000000..e5d5542
--- /dev/null
+++ b/core/tests/coretests/src/android/widget/SuggestionsPopupWindowTest.java
@@ -0,0 +1,117 @@
+/*
+ * Copyright (C) 2015 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.widget;
+
+import android.app.Activity;
+import android.test.ActivityInstrumentationTestCase2;
+import android.test.suitebuilder.annotation.SmallTest;
+import android.text.Selection;
+import android.text.SpannableStringBuilder;
+import android.text.Spanned;
+import android.text.TextPaint;
+import android.text.style.SuggestionSpan;
+import android.text.style.TextAppearanceSpan;
+
+import com.android.frameworks.coretests.R;
+
+/**
+ * SuggestionsPopupWindowTest tests.
+ */
+public class SuggestionsPopupWindowTest extends ActivityInstrumentationTestCase2<TextViewActivity> {
+
+    public SuggestionsPopupWindowTest() {
+        super(TextViewActivity.class);
+    }
+
+    @SmallTest
+    public void testTextAndAppearanceInSuggestionsPopup() {
+        final Activity activity = getActivity();
+
+        final String sampleText = "abc def ghi";
+        final String[] candidate = {"DEF", "Def"};
+        final SuggestionSpan suggestionSpan = new SuggestionSpan(activity, candidate,
+                SuggestionSpan.FLAG_AUTO_CORRECTION);
+        final int spanStart = 4;
+        final int spanEnd = 7;
+        TextAppearanceSpan expectedSpan = new TextAppearanceSpan(activity,
+                android.R.style.TextAppearance_SuggestionHighlight);
+        TextPaint tmpTp = new TextPaint();
+        expectedSpan.updateDrawState(tmpTp);
+        final int expectedHighlightTextColor = tmpTp.getColor();
+        final float expectedHighlightTextSize = tmpTp.getTextSize();
+
+        // Create and wait until SuggestionsPopupWindow is shown.
+        final EditText editText = (EditText) activity.findViewById(R.id.textview);
+        final Editor editor = editText.getEditorForTesting();
+        assertNotNull(editor);
+        activity.runOnUiThread(new Runnable() {
+            public void run() {
+                SpannableStringBuilder ssb = new SpannableStringBuilder();
+                ssb.append(sampleText);
+                ssb.setSpan(suggestionSpan, spanStart, spanEnd, Spanned.SPAN_INCLUSIVE_INCLUSIVE);
+                editText.setText(ssb);
+
+                Selection.setSelection(editText.getText(), spanStart, spanEnd);
+                editText.onTextContextMenuItem(TextView.ID_REPLACE);
+            }
+        });
+        getInstrumentation().waitForIdleSync();
+
+        // In this test, the SuggestionsPopupWindow looks like
+        // abc def ghi
+        //   ----------
+        //   | *DEF*  |
+        //   | *Def*  |
+        //   | DELETE |
+        //   ----------
+        // *XX* means that XX is highlighted.
+        activity.runOnUiThread(new Runnable() {
+            public void run() {
+                Editor.SuggestionsPopupWindow popupWindow =
+                        editor.getSuggestionsPopupWindowForTesting();
+                assertNotNull(popupWindow);
+
+                ListView listView = (ListView) popupWindow.getContentViewForTesting();
+                assertNotNull(listView);
+
+                int childNum = listView.getChildCount();
+                // +1 for "DELETE" command.
+                assertEquals(candidate.length + 1, childNum);
+
+                for (int i = 0; i < candidate.length; ++i) {
+                    TextView textView = (TextView) listView.getChildAt(i);
+                    assertNotNull(textView);
+
+                    Spanned spanned = (Spanned) textView.getText();
+                    assertNotNull(spanned);
+
+                    // Check that the suggestion item order is kept.
+                    assertEquals(candidate[i], spanned.toString());
+
+                    // Check that the text is highlighted with correct color and text size.
+                    TextAppearanceSpan[] taSpan = spanned.getSpans(0, candidate[i].length(),
+                            TextAppearanceSpan.class);
+                    assertEquals(1, taSpan.length);
+                    TextPaint tp = new TextPaint();
+                    taSpan[0].updateDrawState(tp);
+                    assertEquals(expectedHighlightTextColor, tp.getColor());
+                    assertEquals(expectedHighlightTextSize, tp.getTextSize());
+                }
+            }
+        });
+    }
+}
diff --git a/data/etc/platform.xml b/data/etc/platform.xml
index 350310c..27c6620 100644
--- a/data/etc/platform.xml
+++ b/data/etc/platform.xml
@@ -143,4 +143,7 @@
          access while in power save mode, even if they aren't in the foreground. -->
     <allow-in-power-save-except-idle package="com.android.providers.downloads" />
 
+    <!-- These are the packages that shouldn't run as system user -->
+    <system-user-blacklisted-app package="com.android.wallpaper.livepicker" />
+    <system-user-blacklisted-app package="com.android.settings" />
 </permissions>
diff --git a/docs/html/images/training/auto-desktop-head-unit-context-menu-enabled.png b/docs/html/images/training/auto-desktop-head-unit-context-menu-enabled.png
new file mode 100644
index 0000000..99e60e9
--- /dev/null
+++ b/docs/html/images/training/auto-desktop-head-unit-context-menu-enabled.png
Binary files differ
diff --git a/docs/html/images/training/auto-desktop-head-unit-launch.png b/docs/html/images/training/auto-desktop-head-unit-launch.png
new file mode 100644
index 0000000..012857a4
--- /dev/null
+++ b/docs/html/images/training/auto-desktop-head-unit-launch.png
Binary files differ
diff --git a/docs/html/images/training/auto-desktop-head-unit-server-running.png b/docs/html/images/training/auto-desktop-head-unit-server-running.png
new file mode 100644
index 0000000..5aa3b83
--- /dev/null
+++ b/docs/html/images/training/auto-desktop-head-unit-server-running.png
Binary files differ
diff --git a/docs/html/images/training/auto-desktop-head-unit-wkst-launch.png b/docs/html/images/training/auto-desktop-head-unit-wkst-launch.png
new file mode 100644
index 0000000..4d48ac4
--- /dev/null
+++ b/docs/html/images/training/auto-desktop-head-unit-wkst-launch.png
Binary files differ
diff --git a/docs/html/tools/help/desktop-head-unit.jd b/docs/html/tools/help/desktop-head-unit.jd
new file mode 100644
index 0000000..981979c
--- /dev/null
+++ b/docs/html/tools/help/desktop-head-unit.jd
@@ -0,0 +1,439 @@
+page.title=Desktop Head Unit
+page.tags="auto", "car", "testing","dhu"
+@jd:body
+
+
+<div id="qv-wrapper">
+<div id="qv">
+
+    <h2>In this document</h2>
+    <ol>
+      <li><a href="#launching-dhu">Launching the DHU</a></li>
+      <li><a href="#dhu-commands">Issuing DHU Commands</a></li>
+    </ol>
+
+  <h2>See also</h2>
+  <ol>
+    <li><a href="{@docRoot}training/auto/start/index.html#test-it-dhu">Run and Test Auto Apps</a></li>
+  </ol>
+
+</div>
+</div>
+
+
+<p>The Desktop Head Unit (DHU) enables your development machine to emulate an Android Auto
+head unit, so you can easily run and test Android Auto apps. The DHU runs on
+Windows, Mac, and Linux hosts and replaces previous Android Auto simulators,
+such as the Android Media Browser and Messaging
+simulators.</p>
+
+<p class="note"><strong>Note:</strong> For other information about testing Auto apps, see the
+training lesson
+<a href="{@docRoot}training/auto/start/index.html#test-it-dhu">Run and Test Auto Apps</a>.  </p>
+
+
+<h2 id="launching-dhu">Launching the DHU</h2>
+
+<p>
+  To launch the DHU, run the <code>desktop-head-unit.exe</code> (on Windows)
+  or <code>desktop-head-unit</code> (on Mac or Linux) command, as described in
+  <a href="{@docRoot}training/auto/start/index.html#connecting-dhu">Connecting
+  the DHU to your mobile device</a>.
+</p>
+
+<p>
+  By default, the DHU emulates the most common form of Android Auto-compatible
+  head unit, which uses a touch screen user interface. You can simulate user
+  touches by clicking the DHU with a mouse. To emulate head units which use
+  a rotary controller for input, you can use the <code>-i controller</code> flag,
+  as in this example:
+</p>
+
+<pre class="no-pretty-print">$ ./desktop-head-unit -i controller</pre>
+
+<p>
+  When the DHU is in rotary-controller mode you can simulate controller
+  operations by using keyboard shortcuts, as described in <a href=
+  "#cmd-bindings">DHU commands and key bindings</a>. If the DHU is in rotary
+  controller mode, it ignores mouse clicks; you must operate Android Auto with
+  the simulated rotary controller operations.
+</p>
+
+<h2 id="dhu-commands">Issuing DHU Commands</h2>
+
+<p>
+  DHU commands allow you to test your app with Android Auto features, such as
+  playing voice input or switching between night and day display mode. You can issue commands to
+  the DHU by running commands from the terminal window where you launched DHU.
+  You can also issue commands by selecting the DHU window and
+  using keyboard shortcuts. The DHU commands
+  and key bindings for all controls are listed in <a href="#cmd-bindings">DHU
+  commands and key bindings</a>.
+</p>
+
+
+<h3 id="day-night">Switching between day and night mode</h3>
+
+<p>
+  Android Auto supports different color schemes for day and night. You should test your app in both
+  day and night mode. You can switch between night and day mode in either of the
+  following ways:
+</p>
+
+<ul>
+  <li>Run the command <code>daynight</code> in the terminal where you launched the DHU.
+  </li>
+
+  <li>Select the DHU window and press the <strong>N</strong> key.
+  </li>
+</ul>
+
+<h3>Microphone testing</h3>
+
+<p>The DHU supports using a microphone for voice input. You can also instruct the DHU to treat
+a pre-recorded voice track as input, as if the DHU had heard the track through the microphone.</p>
+
+<p>To use a pre-recorded sound file as input, enter this command: </p>
+<pre class="no-pretty-print">
+$ mic play &lt;sound_file_path&gt;/&lt;sound_file&gt;.wav
+</pre>
+
+<p>For your convenience, we have provided the following sound files for common
+voice commands. These sound files are installed in the
+<code>&lt;sdk&gt;/extras/google/auto/voice/</code> directory.</p>
+
+<dl>
+  <dt>
+    <code>exitnav.wav</code>
+  </dt>
+
+  <dd>
+    "Exit navigation."
+  </dd>
+
+  <dt>
+    <code>navgoogle.wav</code>
+  </dt>
+
+  <dd>
+    "Navigate to 1600 Amphitheatre Parkway, Mountain View."
+  </dd>
+
+  <dt>
+    <code>navsoh.wav</code>
+  </dt>
+
+  <dd>
+    "Navigate to Sydney Opera House."
+  </dd>
+
+  <dt>
+    <code>nextturn.wav</code>
+  </dt>
+
+  <dd>
+    "When is my next turn?"
+  </dd>
+
+  <dt>
+    <code>showalternateroute.wav</code>
+  </dt>
+
+  <dd>
+    "Show alternate routes.""
+  </dd>
+
+  <dt>
+    <code>howlong.wav</code>
+  </dt>
+
+  <dd>
+    "How long until I get there?"
+  </dd>
+
+  <dt>
+    <code>navhome.wav</code>
+  </dt>
+
+  <dd>
+    "Navigate to home."
+  </dd>
+
+  <dt>
+    <code>navwork.wav</code>
+  </dt>
+
+  <dd>
+    "Navigate to work.""
+  </dd>
+
+  <dt>
+    <code>pause.wav</code>
+  </dt>
+
+  <dd>
+    "Pause music."
+  </dd>
+
+  <dt>
+    <code>showtraffic.wav</code>
+  </dt>
+
+  <dd>
+    "Show traffic."
+  </dd>
+</dl>
+<h3 id="cmd-bindings">DHU commands and key bindings</h3>
+
+<p>The DHU supports the following commands.</p>
+
+<p class="table-caption" id="table-commands"><strong>Table 1.</strong> Commands and key bindings</p>
+<table>
+<tr>
+  <th>Category</th>
+  <th>Command</th>
+  <th>Subcommand</th>
+  <th>Argument(s)</th>
+  <th>Keyboard Shortcut(s)</th>
+  <th>Description</th>
+</tr>
+
+<!--system-->
+
+<tr>
+<td rowspan="4">System</td>
+<td>help</td>
+<td></td>
+<td>[command]</td>
+<td></td>
+<td>Shows the full command set. Specifying a command name (for example, <code>help day</code>)
+  causes the system to show help for that command.</td>
+</tr>
+
+<tr>
+
+<td>quit</td>
+<td></td>
+<td></td>
+<td>Alt+q</td>
+<td>Quits the head unit.</td>
+</tr>
+
+<tr>
+
+<td>sleep</td>
+<td></td>
+<td>[seconds]</td>
+<td></td>
+<td>Sleeps for one second. Specifying an argument (for example, <code>sleep 30</code>) causes the
+system to sleep the specified number of seconds. This command
+is useful if you are writing scripts for the DHU. (You can run a script by using I/O redirection
+from the command line: <code>./desktop-head-unit &lt; script.txt</code> loads commands from the
+file <code>script.txt</code>.)</td>
+</tr>
+
+<tr>
+
+<td>screenshot</td>
+<td></td>
+<td>filename.png</td>
+<td></td>
+<td>Saves a screenshot to <code>filename.png</code>.</td>
+</tr>
+
+
+<!--microphone-->
+
+<tr>
+<td rowspan="3">Microphone</td>
+<td rowspan="3">mic</td>
+<td>begin</td>
+<td></td>
+<td>m </td>
+<td>Activates the microphone (equivalent to clicking the steering wheel's microphone button) and
+waits for input from the computer microphone.</td>
+</tr>
+
+<tr>
+
+
+<td>play</td>
+<td>filename.wav</td>
+<td></td>
+<td>Causes the DHU to treat <code>filename.wav</code> as voice input, as if it had heard that sound
+  through the microphone. You do not hear the sound file being played, but you do hear
+  the response from Android Auto.</td>
+</tr>
+
+<tr>
+
+
+<td>repeat</td>
+<td></td>
+<td></td>
+<td>Repeats the last <code>mic play</code> command, as if you had called <code>mic play</code>
+  again with the same sound file parameter.</td>
+</tr>
+
+<!--Input-->
+
+<tr>
+<td rowspan="7">Input</td>
+<td rowspan="6">dpad</td>
+<td>up <br> down <br> left <br> right</td>
+<td></td>
+<td>Arrow keys</td>
+<td>Simulates moving the rotary controller.</td>
+</tr>
+
+<tr>
+
+
+<td>soft left <br> soft right</td>
+<td></td>
+<td>Shift+Arrow keys</td>
+<td>Simulates pressing the side buttons available on some rotary controllers.</td>
+</tr>
+
+<tr>
+
+
+<td>click</td>
+<td></td>
+<td>Return</td>
+<td>Simulates pressing the rotary controller.</td>
+</tr>
+
+<tr>
+
+
+<td>back</td>
+<td></td>
+<td>Backspace</td>
+<td>Simulates pressing the <strong>back</strong> button available below some rotary
+  controllers.</td>
+</tr>
+
+<tr>
+
+
+<td>rotate left <br> rotate right</td>
+<td></td>
+<td>1 <br> 2</td>
+<td>Simulates rotating the rotary controller left (counter-clockwise) or right (clockwise).</td>
+</tr>
+
+<tr>
+
+
+<td>flick left <br> flick right</td>
+<td></td>
+<td>Shift+1 <br> Shift+2</td>
+<td>Simulates a fast spin of the rotary controller to the left (counter-clockwise) or right
+  (clockwise).</td>
+</tr>
+
+<tr>
+
+<td>tap</td>
+<td></td>
+<td>x y</td>
+<td></td>
+<td>Simulates a touch event at the specified coordinates. For example, <code>tap 50 100</code></td>
+</tr>
+
+
+<!--Day/Night-->
+
+<tr>
+<td rowspan="3">Day/Night</td>
+<td>day</td>
+<td></td>
+<td></td>
+<td>Shift+n</td>
+<td>Activates day mode (high brightness, full color).</td>
+</tr>
+
+<tr>
+
+<td>night</td>
+<td></td>
+<td> </td>
+<td>Ctrl+n </td>
+<td>Activates night mode (low brightness, high contrast).</td>
+</tr>
+
+<tr>
+
+<td>daynight</td>
+<td></td>
+<td></td>
+<td>n </td>
+<td>Toggles current day/night mode.</td>
+</tr>
+
+</table>
+
+
+
+
+<h2 id="auto-simulators">Media Browser and Messaging Simulators</h2>
+
+<p class="caution"><strong>Important:</strong> Use of the Android Media Browser and Messaging
+Simulators for testing Android Auto apps is deprecated. Instead, we recommend using the
+Desktop Head Unit, which enables your development machine to act as if it were an Android Auto head
+unit.</p>
+
+<p>To get the simulators, open the
+<a href="{@docRoot}tools/help/sdk-manager.html">SDK Manager</a> and download
+them from <strong>Extras &gt; Android Auto API Simulators</strong>.</p>
+
+<p>Before you begin testing, compile your app in your development environment.
+Install your app and the Android simulator for the features you want to test
+(that is, audio or messaging) on a physical or virtual device running Android
+5.0 (API level 21) or higher. To check the version of Android on the device, go
+to <strong>Settings &gt; About phone</strong> (or <strong>About tablet</strong>)
+<strong>&gt; Android Version</strong>.</p>
+
+<h3 id="testing-audio-apps">Testing audio apps</h3>
+<p>To run and test audio apps:</p>
+
+<ol>
+<li>Install the Android Media Browser simulator
+({@code &lt;sdk&gt;/extras/google/simulators/media-browser-simulator.apk}) on
+the test device. You can do this using
+the <a href="{@docRoot}tools/help/adb.html#move">adb</a> command line tool.</li>
+<li>Enable <a href="{@docRoot}tools/device.html#developer-device-options">
+developer options</a> on the test device.</li>
+<li>Install your app on the test device.</li>
+<li>Launch the Android Media Browser simulator to see how your audio app
+appears in Auto. If your app does not appear, stop the simulator from
+<strong>Settings &gt; Apps</strong> and restart it.</li>
+</ol>
+
+
+<h3 id="testing-messaging-apps">Testing messaging apps</h3>
+<p>To run and test messaging apps:</p>
+
+<ol>
+<li>Install the Android Messaging simulator
+  ({@code &lt;sdk&gt;/extras/google/simulators/messaging-simulator.apk})
+on the test device. You can do this using the
+<a href="{@docRoot}tools/help/adb.html#move">adb</a> command line tool.</li>
+<li>Enable the simulator to read notifications posted on the system:
+<ol type="a">
+	<li>Enable <a href="{@docRoot}tools/device.html#developer-device-options">
+developer options</a> on the test device.</li>
+  <li>Click <strong>Settings &gt; Sounds &amp; Notifications &gt; Notification
+    Access</strong> and check the box labeled
+    <strong>Messaging Simulator</strong>.</li>
+</ol>
+<li>Install your app on the test device.</li>
+<li>Launch the Android Messaging Simulator to see how your messaging app appears
+in Auto. If your app does not appear, stop the simulator from
+<strong>Settings &gt; Apps</strong> and restart it.</li>
+</ol>
+
+
+
+
diff --git a/docs/html/tools/help/monkey.jd b/docs/html/tools/help/monkey.jd
index 941f5d9..7c64830 100644
--- a/docs/html/tools/help/monkey.jd
+++ b/docs/html/tools/help/monkey.jd
@@ -130,7 +130,7 @@
 <td><code>--pct-majornav &lt;percent&gt;</code></td>
 <td>Adjust percentage of "major" navigation events.
 (These are navigation events that will typically cause actions within your UI, such as
-the center button in a 5-way pad, the back key, or the menu key.)</td>
+the center button in a 5-way pad or the menu key.)</td>
 </tr>
 
 <tr>
diff --git a/docs/html/tools/tools_toc.cs b/docs/html/tools/tools_toc.cs
index db19d4f..72f9f21 100644
--- a/docs/html/tools/tools_toc.cs
+++ b/docs/html/tools/tools_toc.cs
@@ -160,6 +160,7 @@
       <li><a href="<?cs var:toroot ?>tools/help/avd-manager.html">AVD Manager</a></li>
       <li><a href="<?cs var:toroot ?>tools/help/bmgr.html">bmgr</a>
       <li><a href="<?cs var:toroot ?>tools/help/monitor.html">Device Monitor</a></li>
+      <li><a href="<?cs var:toroot ?>tools/help/desktop-head-unit.html">Desktop Head Unit</a></li>
       <li><a href="<?cs var:toroot ?>tools/help/dmtracedump.html">dmtracedump</a></li>
       <li><a href="<?cs var:toroot ?>tools/help/draw9patch.html">Draw 9-Patch</a></li>
       <li><a href="<?cs var:toroot ?>tools/help/emulator.html">Emulator</a></li>
diff --git a/docs/html/training/auto/start/index.jd b/docs/html/training/auto/start/index.jd
index 22e7521..f6cdbd1 100644
--- a/docs/html/training/auto/start/index.jd
+++ b/docs/html/training/auto/start/index.jd
@@ -16,7 +16,7 @@
   <ol>
     <li><a href="#dev-project">Set Up an Auto Project</a></li>
     <li><a href="#build-it">Build Auto Apps</a></li>
-    <li><a href="#test-it">Run and Test Auto Apps</a></li>
+    <li><a href="#test-it-dhu">Run and Test Auto Apps </a></li>
   </ol>
 
  <h2>You should also read</h2>
@@ -149,57 +149,124 @@
 more information, see
 <a href="{@docRoot}distribute/essentials/quality/auto.html">Auto App Quality</a>.</p>
 
-<h2 id="test-it">Run and Test Auto Apps</h2>
 
-<p>As you prepare to publish your app, make sure that your app looks correct
-when projected on the Auto user interface. Use the Android Media Browser
-simulator and Android Messaging simulators to view and test your audio or
-messaging apps in a screen that looks similar to what is projected on Auto.</p>
 
-<p>To get the simulators, open the
-<a href="{@docRoot}tools/help/sdk-manager.html">SDK Manager</a> and download
-them from <strong>Extras &gt; Android Auto API Simulators</strong>.</p>
+<h2 id="test-it-dhu">Run and Test Auto Apps </h2>
 
-<p>Before you begin testing, compile your app in your development environment.
-Install your app and the Android simulator for the features you want to test
-(that is, audio or messaging) on a physical or virtual device running Android
-5.0 (API level 21) or higher. To check the version of Android on the device, go
-to <strong>Settings &gt; About &gt; Android Version</strong>.</p>
+<p>
+  As you develop, you can run and test your app on your development machine
+  using the <em>Desktop Head Unit</em> (DHU). The DHU replaces the existing
+  simulators and enables your development machine to simulate a vehicle
+  dashboard system running Android Auto.
+</p>
 
-<h3 id="testing-audio-apps">Testing audio apps</h3>
-<p>To run and test audio apps:</p>
+<h3 id="installing-dhu">Installing the DHU</h3>
 
 <ol>
-<li>Install the Android Media Browser simulator
-({@code &lt;sdk&gt;/extras/google/simulators/media-browser-simulator.apk}) on
-the test device. You can do this using
-the <a href="{@docRoot}tools/help/adb.html#move">adb</a> command line tool.</li>
-<li>Enable <a href="{@docRoot}tools/device.html#device-developer-options">
-developer options</a> on the test device.</li>
-<li>Install your app on the test device.</li>
-<li>Launch the Android Media Browser simulator to see how your audio app
-appears in Auto. If your app does not appear, stop the simulator from
-<strong>Settings &gt; Apps</strong> then restart it.</li>
+  <li>Enable developer mode on your mobile device, as described in
+    <a href="{@docRoot}tools/device.html#developer-device-options">Enabling On-device
+    Developer Options</a>. </li>
+  <li>Compile your app in your development environment and install your app on
+    a physical mobile device running Android 5.0 (API level 21) or higher. To check the
+    version of Android on a Nexus device, go to
+    <strong>Settings &gt; About phone</strong> (or <strong>About tablet</strong>) <strong>&gt;
+    Android version</strong>.</li>
+
+  <li>Install the
+     <a class="external-link"
+     href="https://play.google.com/store/apps/details?id=com.google.android.projection.gearhead&hl=en"
+     >Android Auto app</a> on the mobile device.</li>
+  <li>Open the <a href="{@docRoot}tools/help/sdk-manager.html">SDK Manager</a> and
+    download the DHU package <strong>Android Auto Desktop Head Unit</strong> from the
+    <em>SDK Tools</em> tab. The DHU installs in the <code>&lt;sdk&gt;/extras/google/auto/</code>
+    directory.</li>
+  <li>If you are running the DHU on Linux, you must also install
+    the portaudio, libpng, sdl2, and sdl2_ttf libraries.
+    The procedure to do this varies depending on your Linux distribution. For example, on
+    Debian-derived Linux distributions, you can install the libraries with this command:
+
+<pre class="no-pretty-print">
+$ sudo apt-get install libsdl2-2.0-0 libsdl2-ttf-2.0-0 libportaudio2 libpng12-0
+</pre>
+
+  </li>
 </ol>
 
-<h3 id="testing-messaging-apps">Testing messaging apps</h3>
-<p>To run and test messaging apps:</p>
+<div class="figure" style="width:330px">
+  <img src="{@docRoot}images/training/auto-desktop-head-unit-server-running.png"
+      alt="" >
+  <p class="img-caption">
+    <strong>Figure 2.</strong> Notification that the head unit server is running.
+  </p>
+</div>
+<img src="{@docRoot}images/training/auto-desktop-head-unit-context-menu-enabled.png"
+    alt="" >
+<p class="img-caption">
+  <strong>Figure 1.</strong> Context menu with developer options.
+</p>
+
+<h3 id="connecting-dhu">Connecting the DHU to your mobile device</h3>
+
+<p>Run the DHU by connecting your mobile device to a development machine and setting up a connection to
+  the head unit server over <a href="{@docRoot}tools/help/adb.html">Android Debug Bridge
+  (ADB)</a>. Follow these steps to set up tunneling and start the DHU:</p>
 
 <ol>
-<li>Install the Android Messaging simulator
-  ({@code &lt;sdk&gt;/extras/google/simulators/messaging-simulator.apk})
-on the test device. You can do this using the
-<a href="{@docRoot}tools/help/adb.html#move">adb</a> command line tool.</li>
-<li>Enable the simulator to read notifications posted on the system:
-<ol type="a">
-	<li>Enable <a href="{@docRoot}tools/device.html#device-developer-options">
-developer options</a> on the test device.</li>
-	<li>Click <strong>Settings &gt; Sounds &amp; Notifications &gt; Notification
-	Access</strong> and check the box labeled
-	<strong>Messaging Simulator</strong>.</li>
+  <li>On the mobile device, enable Android Auto developer mode by starting the Android Auto
+    companion app, and then tapping the header image 10 times.
+    This step is only required the first time you run the companion app.
+  </li>
+  <li>If the server is not already running, select <strong>Start head unit server</strong>
+     from the Android Auto menu.
+    <p>On the device, a foreground service appears in the notification area. </p>
+  </li>
+
+  <li>Connect the mobile device to the development machine via USB. Your device must be unlocked to
+    launch the DHU.
+  </li>
+  <li>On the development machine, run the following {@code adb} command to
+    forward socket connections from the
+    development machine's port 5277 to the same port number on the Android device.
+    This configuration allows the DHU to connect to the head unit server running on your phone over
+    a TCP socket.
+    <pre class="no-pretty-print">$ adb forward tcp:5277 tcp:5277</pre>
+  </li>
+
+  <li>Start the DHU by running the command <code>desktop-head-unit.exe</code> (on Windows)
+    or <code>./desktop-head-unit</code> (on Mac or Linux) from the
+    <code>&lt;sdk&gt;/extras/google/auto/</code> directory.
+
+<pre class="no-pretty-print">$ cd &lt;sdk&gt;/extras/google/auto
+$ ./desktop-head-unit</pre>
+
+    <p>
+      By default, the head unit server connects over port 5277. To override the host or port
+      (for example, to forward over SSH), use the <code>--adb</code> flag.
+    </p>
+
+  </li>
 </ol>
-<li>Install your app on the test device.</li>
-<li>Launch the Android Messaging Simulator to see how your messaging app appears
-in Auto. If your app does not appear, stop the simulator from
-<strong>Settings &gt; Apps</strong> then restart it.</li>
-</ol>
+
+<div class="figure" style="width:432px">
+
+    <img src="{@docRoot}images/training/auto-desktop-head-unit-wkst-launch.png"
+        alt="" >
+    <p class="img-caption">
+      <strong>Figure 4.</strong> DHU launches on the development machine.
+    </p>
+</div>
+
+    <img src="{@docRoot}images/training/auto-desktop-head-unit-launch.png"
+        alt="" >
+    <p class="img-caption">
+      <strong>Figure 3.</strong> Android Auto launches on the mobile device.
+    </p>
+
+<p>
+  After you set up and start the DHU, you can run DHU commands from the command line to run and
+  test your app from the terminal. You can also run these commands by using keyboard shortcuts. For
+  more information about DHU configuration and commands, see <a href=
+  "{@docRoot}tools/help/desktop-head-unit.html">Desktop Head Unit</a>.
+</p>
+
+
diff --git a/graphics/java/android/graphics/drawable/Drawable.java b/graphics/java/android/graphics/drawable/Drawable.java
index 32af59a..b95c183 100644
--- a/graphics/java/android/graphics/drawable/Drawable.java
+++ b/graphics/java/android/graphics/drawable/Drawable.java
@@ -1146,77 +1146,11 @@
      * document, tries to create a Drawable from that tag. Returns {@code null}
      * if the tag is not a valid drawable.
      */
-    @SuppressWarnings("deprecation")
     public static Drawable createFromXmlInner(Resources r, XmlPullParser parser, AttributeSet attrs,
             Theme theme) throws XmlPullParserException, IOException {
-        final Drawable drawable;
-
-        final String name = parser.getName();
-        switch (name) {
-            case "selector":
-                drawable = new StateListDrawable();
-                break;
-            case "animated-selector":
-                drawable = new AnimatedStateListDrawable();
-                break;
-            case "level-list":
-                drawable = new LevelListDrawable();
-                break;
-            case "layer-list":
-                drawable = new LayerDrawable();
-                break;
-            case "transition":
-                drawable = new TransitionDrawable();
-                break;
-            case "ripple":
-                drawable = new RippleDrawable();
-                break;
-            case "color":
-                drawable = new ColorDrawable();
-                break;
-            case "shape":
-                drawable = new GradientDrawable();
-                break;
-            case "vector":
-                drawable = new VectorDrawable();
-                break;
-            case "animated-vector":
-                drawable = new AnimatedVectorDrawable();
-                break;
-            case "scale":
-                drawable = new ScaleDrawable();
-                break;
-            case "clip":
-                drawable = new ClipDrawable();
-                break;
-            case "rotate":
-                drawable = new RotateDrawable();
-                break;
-            case "animated-rotate":
-                drawable = new AnimatedRotateDrawable();
-                break;
-            case "animation-list":
-                drawable = new AnimationDrawable();
-                break;
-            case "inset":
-                drawable = new InsetDrawable();
-                break;
-            case "bitmap":
-                drawable = new BitmapDrawable();
-                break;
-            case "nine-patch":
-                drawable = new NinePatchDrawable();
-                break;
-            default:
-                throw new XmlPullParserException(parser.getPositionDescription() +
-                        ": invalid drawable tag " + name);
-
-        }
-        drawable.inflate(r, parser, attrs, theme);
-        return drawable;
+        return r.getDrawableInflater().inflateFromXml(parser.getName(), parser, attrs, theme);
     }
 
-
     /**
      * Create a drawable from file path name.
      */
diff --git a/graphics/java/android/graphics/drawable/DrawableInflater.java b/graphics/java/android/graphics/drawable/DrawableInflater.java
new file mode 100644
index 0000000..20d54ca
--- /dev/null
+++ b/graphics/java/android/graphics/drawable/DrawableInflater.java
@@ -0,0 +1,203 @@
+/*
+ * Copyright (C) 2015 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.graphics.drawable;
+
+import org.xmlpull.v1.XmlPullParser;
+import org.xmlpull.v1.XmlPullParserException;
+
+import android.annotation.DrawableRes;
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.content.Context;
+import android.content.res.Resources;
+import android.content.res.Resources.Theme;
+import android.util.AttributeSet;
+import android.view.InflateException;
+
+import java.io.IOException;
+import java.lang.reflect.Constructor;
+import java.util.HashMap;
+
+/**
+ * Instantiates a drawable XML file into its corresponding
+ * {@link android.graphics.drawable.Drawable} objects.
+ * <p>
+ * For performance reasons, inflation relies heavily on pre-processing of
+ * XML files that is done at build time. Therefore, it is not currently possible
+ * to use this inflater with an XmlPullParser over a plain XML file at runtime;
+ * it only works with an XmlPullParser returned from a compiled resource (R.
+ * <em>something</em> file.)
+ *
+ * @hide Pending API finalization.
+ */
+public final class DrawableInflater {
+    private static final HashMap<String, Constructor<? extends Drawable>> CONSTRUCTOR_MAP =
+            new HashMap<>();
+
+    private final Resources mRes;
+    private final ClassLoader mClassLoader;
+
+    /**
+     * Loads the drawable resource with the specified identifier.
+     *
+     * @param context the context in which the drawable should be loaded
+     * @param id the identifier of the drawable resource
+     * @return a drawable, or {@code null} if the drawable failed to load
+     */
+    @Nullable
+    public static Drawable loadDrawable(@NonNull Context context, @DrawableRes int id) {
+        return loadDrawable(context.getResources(), context.getTheme(), id);
+    }
+
+    /**
+     * Loads the drawable resource with the specified identifier.
+     *
+     * @param resources the resources from which the drawable should be loaded
+     * @param theme the theme against which the drawable should be inflated
+     * @param id the identifier of the drawable resource
+     * @return a drawable, or {@code null} if the drawable failed to load
+     */
+    @Nullable
+    public static Drawable loadDrawable(
+            @NonNull Resources resources, @Nullable Theme theme, @DrawableRes int id) {
+        return resources.getDrawable(id, theme);
+    }
+
+    /**
+     * Constructs a new drawable inflater using the specified resources and
+     * class loader.
+     *
+     * @param res the resources used to resolve resource identifiers
+     * @param classLoader the class loader used to load custom drawables
+     * @hide
+     */
+    public DrawableInflater(@NonNull Resources res, @NonNull ClassLoader classLoader) {
+        mRes = res;
+        mClassLoader = classLoader;
+    }
+
+    /**
+     * Inflates a drawable from inside an XML document using an optional
+     * {@link Theme}.
+     * <p>
+     * This method should be called on a parser positioned at a tag in an XML
+     * document defining a drawable resource. It will attempt to create a
+     * Drawable from the tag at the current position.
+     *
+     * @param name the name of the tag at the current position
+     * @param parser an XML parser positioned at the drawable tag
+     * @param attrs an attribute set that wraps the parser
+     * @param theme the theme against which the drawable should be inflated, or
+     *              {@code null} to not inflate against a theme
+     * @return a drawable
+     *
+     * @throws XmlPullParserException
+     * @throws IOException
+     */
+    @NonNull
+    public Drawable inflateFromXml(@NonNull String name, @NonNull XmlPullParser parser,
+            @NonNull AttributeSet attrs, @Nullable Theme theme)
+            throws XmlPullParserException, IOException {
+        Drawable drawable = inflateFromTag(name);
+        if (drawable == null) {
+            drawable = inflateFromClass(name);
+        }
+        drawable.inflate(mRes, parser, attrs, theme);
+        return drawable;
+    }
+
+    @NonNull
+    @SuppressWarnings("deprecation")
+    private Drawable inflateFromTag(@NonNull String name) {
+        switch (name) {
+            case "selector":
+                return new StateListDrawable();
+            case "animated-selector":
+                return new AnimatedStateListDrawable();
+            case "level-list":
+                return new LevelListDrawable();
+            case "layer-list":
+                return new LayerDrawable();
+            case "transition":
+                return new TransitionDrawable();
+            case "ripple":
+                return new RippleDrawable();
+            case "color":
+                return new ColorDrawable();
+            case "shape":
+                return new GradientDrawable();
+            case "vector":
+                return new VectorDrawable();
+            case "animated-vector":
+                return new AnimatedVectorDrawable();
+            case "scale":
+                return new ScaleDrawable();
+            case "clip":
+                return new ClipDrawable();
+            case "rotate":
+                return new RotateDrawable();
+            case "animated-rotate":
+                return new AnimatedRotateDrawable();
+            case "animation-list":
+                return new AnimationDrawable();
+            case "inset":
+                return new InsetDrawable();
+            case "bitmap":
+                return new BitmapDrawable();
+            case "nine-patch":
+                return new NinePatchDrawable();
+            default:
+                return null;
+        }
+    }
+
+    @NonNull
+    private Drawable inflateFromClass(@NonNull String className) {
+        try {
+            Constructor<? extends Drawable> constructor;
+            synchronized (CONSTRUCTOR_MAP) {
+                constructor = CONSTRUCTOR_MAP.get(className);
+                if (constructor == null) {
+                    final Class<? extends Drawable> clazz =
+                            mClassLoader.loadClass(className).asSubclass(Drawable.class);
+                    constructor = clazz.getConstructor();
+                    CONSTRUCTOR_MAP.put(className, constructor);
+                }
+            }
+            return constructor.newInstance();
+        } catch (NoSuchMethodException e) {
+            final InflateException ie = new InflateException(
+                    "Error inflating class " + className);
+            ie.initCause(e);
+            throw ie;
+        } catch (ClassCastException e) {
+            // If loaded class is not a Drawable subclass.
+            final InflateException ie = new InflateException(
+                    "Class is not a Drawable " + className);
+            ie.initCause(e);
+            throw ie;
+        } catch (ClassNotFoundException e) {
+            // If loadClass fails, we should propagate the exception.
+            throw new InflateException("Class not found " + className);
+        } catch (Exception e) {
+            final InflateException ie = new InflateException(
+                    "Error inflating class " + className);
+            ie.initCause(e);
+            throw ie;
+        }
+    }
+}
diff --git a/graphics/java/android/graphics/drawable/RippleBackground.java b/graphics/java/android/graphics/drawable/RippleBackground.java
index d960c8f..f9474ef 100644
--- a/graphics/java/android/graphics/drawable/RippleBackground.java
+++ b/graphics/java/android/graphics/drawable/RippleBackground.java
@@ -48,8 +48,8 @@
     // Software rendering properties.
     private float mOpacity = 0;
 
-    public RippleBackground(RippleDrawable owner, Rect bounds) {
-        super(owner, bounds);
+    public RippleBackground(RippleDrawable owner, Rect bounds, boolean forceSoftware) {
+        super(owner, bounds, forceSoftware);
     }
 
     public boolean isVisible() {
diff --git a/graphics/java/android/graphics/drawable/RippleComponent.java b/graphics/java/android/graphics/drawable/RippleComponent.java
index 23a3ee3..2d378c6 100644
--- a/graphics/java/android/graphics/drawable/RippleComponent.java
+++ b/graphics/java/android/graphics/drawable/RippleComponent.java
@@ -52,9 +52,16 @@
     /** Screen density used to adjust pixel-based constants. */
     protected float mDensity;
 
-    public RippleComponent(RippleDrawable owner, Rect bounds) {
+    /**
+     * If set, force all ripple animations to not run on RenderThread, even if it would be
+     * available.
+     */
+    private final boolean mForceSoftware;
+
+    public RippleComponent(RippleDrawable owner, Rect bounds, boolean forceSoftware) {
         mOwner = owner;
         mBounds = bounds;
+        mForceSoftware = forceSoftware;
     }
 
     public void onBoundsChange() {
@@ -143,7 +150,7 @@
      * @return {@code true} if something was drawn, {@code false} otherwise
      */
     public boolean draw(Canvas c, Paint p) {
-        final boolean hasDisplayListCanvas = c.isHardwareAccelerated()
+        final boolean hasDisplayListCanvas = !mForceSoftware && c.isHardwareAccelerated()
                 && c instanceof DisplayListCanvas;
         if (mHasDisplayListCanvas != hasDisplayListCanvas) {
             mHasDisplayListCanvas = hasDisplayListCanvas;
diff --git a/graphics/java/android/graphics/drawable/RippleDrawable.java b/graphics/java/android/graphics/drawable/RippleDrawable.java
index 464f3de..2690223 100644
--- a/graphics/java/android/graphics/drawable/RippleDrawable.java
+++ b/graphics/java/android/graphics/drawable/RippleDrawable.java
@@ -166,6 +166,12 @@
     private boolean mOverrideBounds;
 
     /**
+     * If set, force all ripple animations to not run on RenderThread, even if it would be
+     * available.
+     */
+    private boolean mForceSoftware;
+
+    /**
      * Constructor used for drawable inflation.
      */
     RippleDrawable() {
@@ -546,7 +552,7 @@
      */
     private void tryBackgroundEnter(boolean focused) {
         if (mBackground == null) {
-            mBackground = new RippleBackground(this, mHotspotBounds);
+            mBackground = new RippleBackground(this, mHotspotBounds, mForceSoftware);
         }
 
         mBackground.setup(mState.mMaxRadius, mDensity);
@@ -584,7 +590,7 @@
             }
 
             final boolean isBounded = isBounded();
-            mRipple = new RippleForeground(this, mHotspotBounds, x, y, isBounded);
+            mRipple = new RippleForeground(this, mHotspotBounds, x, y, isBounded, mForceSoftware);
         }
 
         mRipple.setup(mState.mMaxRadius, mDensity);
@@ -949,6 +955,16 @@
         }
     }
 
+    /**
+     * Sets whether to disable RenderThread animations for this ripple.
+     *
+     * @param forceSoftware true if RenderThread animations should be disabled, false otherwise
+     * @hide
+     */
+    public void setForceSoftware(boolean forceSoftware) {
+        mForceSoftware = forceSoftware;
+    }
+
     @Override
     public ConstantState getConstantState() {
         return mState;
diff --git a/graphics/java/android/graphics/drawable/RippleForeground.java b/graphics/java/android/graphics/drawable/RippleForeground.java
index 4853b04..c660846 100644
--- a/graphics/java/android/graphics/drawable/RippleForeground.java
+++ b/graphics/java/android/graphics/drawable/RippleForeground.java
@@ -87,8 +87,8 @@
     private boolean mHasFinishedExit;
 
     public RippleForeground(RippleDrawable owner, Rect bounds, float startingX, float startingY,
-            boolean isBounded) {
-        super(owner, bounds);
+            boolean isBounded, boolean forceSoftware) {
+        super(owner, bounds, forceSoftware);
 
         mIsBounded = isBounded;
         mStartingX = startingX;
diff --git a/location/lib/java/com/android/location/provider/ActivityRecognitionProvider.java b/location/lib/java/com/android/location/provider/ActivityRecognitionProvider.java
index f4943d5..bc2dae1 100644
--- a/location/lib/java/com/android/location/provider/ActivityRecognitionProvider.java
+++ b/location/lib/java/com/android/location/provider/ActivityRecognitionProvider.java
@@ -42,6 +42,8 @@
     public static final String ACTIVITY_STILL = "android.activity_recognition.still";
     public static final String ACTIVITY_TILTING = "android.activity_recognition.tilting";
 
+    // NOTE: when adding an additional EVENT_TYPE_, EVENT_TYPE_COUNT needs to be updated in
+    // android.hardware.location.ActivityRecognitionHardware
     public static final int EVENT_TYPE_FLUSH_COMPLETE = 0;
     public static final int EVENT_TYPE_ENTER = 1;
     public static final int EVENT_TYPE_EXIT = 2;
diff --git a/media/java/android/media/AudioAttributes.java b/media/java/android/media/AudioAttributes.java
index 0f1be6b..e92f294 100644
--- a/media/java/android/media/AudioAttributes.java
+++ b/media/java/android/media/AudioAttributes.java
@@ -671,15 +671,15 @@
             case USAGE_VOICE_COMMUNICATION:
                 return new String("USAGE_VOICE_COMMUNICATION");
             case USAGE_VOICE_COMMUNICATION_SIGNALLING:
-                return new String("USAGE_VOICE_COMMUNICATION");
+                return new String("USAGE_VOICE_COMMUNICATION_SIGNALLING");
             case USAGE_ALARM:
                 return new String("USAGE_ALARM");
             case USAGE_NOTIFICATION:
                 return new String("USAGE_NOTIFICATION");
             case USAGE_NOTIFICATION_RINGTONE:
-                return new String("USAGE_NOTIFICATION");
+                return new String("USAGE_NOTIFICATION_RINGTONE");
             case USAGE_NOTIFICATION_COMMUNICATION_REQUEST:
-                return new String("USAGE_NOTIFICATION");
+                return new String("USAGE_NOTIFICATION_COMMUNICATION_REQUEST");
             case USAGE_NOTIFICATION_COMMUNICATION_INSTANT:
                 return new String("USAGE_NOTIFICATION_COMMUNICATION_INSTANT");
             case USAGE_NOTIFICATION_COMMUNICATION_DELAYED:
diff --git a/media/java/android/media/midi/MidiManager.java b/media/java/android/media/midi/MidiManager.java
index 7197dc0..e72bdb4 100644
--- a/media/java/android/media/midi/MidiManager.java
+++ b/media/java/android/media/midi/MidiManager.java
@@ -288,7 +288,6 @@
                         // fetch MidiDeviceInfo from the server
                         MidiDeviceInfo deviceInfo = server.getDeviceInfo();
                         device = new MidiDevice(deviceInfo, server, mService, mToken, deviceToken);
-                        sendOpenDeviceResponse(device, listenerF, handlerF);
                     } catch (RemoteException e) {
                         Log.e(TAG, "remote exception in getDeviceInfo()");
                     }
diff --git a/media/java/android/mtp/MtpDevice.java b/media/java/android/mtp/MtpDevice.java
index fbe047d..3cd157e 100644
--- a/media/java/android/mtp/MtpDevice.java
+++ b/media/java/android/mtp/MtpDevice.java
@@ -257,11 +257,12 @@
      * on completion, and must be done by the caller.
      *
      * @param objectHandle handle of the target file
+     * @param size size of the file in bytes
      * @param descriptor file descriptor to read the data from.
      * @return true if the file transfer succeeds
      */
-    public boolean sendObject(int objectHandle, ParcelFileDescriptor descriptor) {
-        return native_send_object(objectHandle, descriptor.getFd());
+    public boolean sendObject(int objectHandle, int size, ParcelFileDescriptor descriptor) {
+        return native_send_object(objectHandle, size, descriptor.getFd());
     }
 
     /**
@@ -294,6 +295,6 @@
     private native long native_get_storage_id(int objectHandle);
     private native boolean native_import_file(int objectHandle, String destPath);
     private native boolean native_import_file(int objectHandle, int fd);
-    private native boolean native_send_object(int objectHandle, int fd);
+    private native boolean native_send_object(int objectHandle, int size, int fd);
     private native MtpObjectInfo native_send_object_info(MtpObjectInfo info);
 }
diff --git a/media/java/android/mtp/MtpObjectInfo.java b/media/java/android/mtp/MtpObjectInfo.java
index f79d52e..a080c73 100644
--- a/media/java/android/mtp/MtpObjectInfo.java
+++ b/media/java/android/mtp/MtpObjectInfo.java
@@ -273,25 +273,25 @@
         public Builder(MtpObjectInfo objectInfo) {
             mObjectInfo = new MtpObjectInfo();
             mObjectInfo.mHandle = -1;
-            mObjectInfo.mAssociationDesc = mObjectInfo.mAssociationDesc;
-            mObjectInfo.mAssociationType = mObjectInfo.mAssociationType;
-            mObjectInfo.mCompressedSize = mObjectInfo.mCompressedSize;
-            mObjectInfo.mDateCreated = mObjectInfo.mDateCreated;
-            mObjectInfo.mDateModified = mObjectInfo.mDateModified;
-            mObjectInfo.mFormat = mObjectInfo.mFormat;
-            mObjectInfo.mImagePixDepth = mObjectInfo.mImagePixDepth;
-            mObjectInfo.mImagePixHeight = mObjectInfo.mImagePixHeight;
-            mObjectInfo.mImagePixWidth = mObjectInfo.mImagePixWidth;
-            mObjectInfo.mKeywords = mObjectInfo.mKeywords;
-            mObjectInfo.mName = mObjectInfo.mName;
-            mObjectInfo.mParent = mObjectInfo.mParent;
-            mObjectInfo.mProtectionStatus = mObjectInfo.mProtectionStatus;
-            mObjectInfo.mSequenceNumber = mObjectInfo.mSequenceNumber;
-            mObjectInfo.mStorageId = mObjectInfo.mStorageId;
-            mObjectInfo.mThumbCompressedSize = mObjectInfo.mThumbCompressedSize;
-            mObjectInfo.mThumbFormat = mObjectInfo.mThumbFormat;
-            mObjectInfo.mThumbPixHeight = mObjectInfo.mThumbPixHeight;
-            mObjectInfo.mThumbPixWidth = mObjectInfo.mThumbPixWidth;
+            mObjectInfo.mAssociationDesc = objectInfo.mAssociationDesc;
+            mObjectInfo.mAssociationType = objectInfo.mAssociationType;
+            mObjectInfo.mCompressedSize = objectInfo.mCompressedSize;
+            mObjectInfo.mDateCreated = objectInfo.mDateCreated;
+            mObjectInfo.mDateModified = objectInfo.mDateModified;
+            mObjectInfo.mFormat = objectInfo.mFormat;
+            mObjectInfo.mImagePixDepth = objectInfo.mImagePixDepth;
+            mObjectInfo.mImagePixHeight = objectInfo.mImagePixHeight;
+            mObjectInfo.mImagePixWidth = objectInfo.mImagePixWidth;
+            mObjectInfo.mKeywords = objectInfo.mKeywords;
+            mObjectInfo.mName = objectInfo.mName;
+            mObjectInfo.mParent = objectInfo.mParent;
+            mObjectInfo.mProtectionStatus = objectInfo.mProtectionStatus;
+            mObjectInfo.mSequenceNumber = objectInfo.mSequenceNumber;
+            mObjectInfo.mStorageId = objectInfo.mStorageId;
+            mObjectInfo.mThumbCompressedSize = objectInfo.mThumbCompressedSize;
+            mObjectInfo.mThumbFormat = objectInfo.mThumbFormat;
+            mObjectInfo.mThumbPixHeight = objectInfo.mThumbPixHeight;
+            mObjectInfo.mThumbPixWidth = objectInfo.mThumbPixWidth;
         }
 
         public Builder setAssociationDesc(int value) {
diff --git a/media/jni/android_mtp_MtpDevice.cpp b/media/jni/android_mtp_MtpDevice.cpp
index 9dd3861..2a46ee7 100644
--- a/media/jni/android_mtp_MtpDevice.cpp
+++ b/media/jni/android_mtp_MtpDevice.cpp
@@ -412,18 +412,13 @@
 }
 
 static jboolean
-android_mtp_MtpDevice_send_object(JNIEnv *env, jobject thiz, jint object_id, jint fd)
+android_mtp_MtpDevice_send_object(JNIEnv *env, jobject thiz, jint object_id, jint size, jint fd)
 {
     MtpDevice* device = get_device_from_object(env, thiz);
     if (!device)
         return JNI_FALSE;
-    MtpObjectInfo* object_info = device->getObjectInfo(object_id);
-    if (!object_info)
-        return JNI_FALSE;
 
-    bool result = device->sendObject(object_info, fd);
-    delete object_info;
-    return result;
+    return device->sendObject(object_id, size, fd);
 }
 
 static jobject
@@ -516,7 +511,7 @@
     {"native_import_file",      "(ILjava/lang/String;)Z",
                                         (void *)android_mtp_MtpDevice_import_file},
     {"native_import_file",      "(II)Z",(void *)android_mtp_MtpDevice_import_file_to_fd},
-    {"native_send_object",      "(II)Z",(void *)android_mtp_MtpDevice_send_object},
+    {"native_send_object",      "(III)Z",(void *)android_mtp_MtpDevice_send_object},
     {"native_send_object_info", "(Landroid/mtp/MtpObjectInfo;)Landroid/mtp/MtpObjectInfo;",
                                         (void *)android_mtp_MtpDevice_send_object_info}
 };
diff --git a/media/packages/BluetoothMidiService/src/com/android/bluetoothmidiservice/BluetoothMidiService.java b/media/packages/BluetoothMidiService/src/com/android/bluetoothmidiservice/BluetoothMidiService.java
index fbde2b4..1f81a05 100644
--- a/media/packages/BluetoothMidiService/src/com/android/bluetoothmidiservice/BluetoothMidiService.java
+++ b/media/packages/BluetoothMidiService/src/com/android/bluetoothmidiservice/BluetoothMidiService.java
@@ -46,6 +46,7 @@
                 device = mDeviceServerMap.get(bluetoothDevice);
                 if (device == null) {
                     device = new BluetoothMidiDevice(this, bluetoothDevice, this);
+                    mDeviceServerMap.put(bluetoothDevice, device);
                 }
             }
             return device.getBinder();
diff --git a/packages/DocumentsUI/src/com/android/documentsui/BandSelectManager.java b/packages/DocumentsUI/src/com/android/documentsui/BandSelectManager.java
deleted file mode 100644
index 74170f5..0000000
--- a/packages/DocumentsUI/src/com/android/documentsui/BandSelectManager.java
+++ /dev/null
@@ -1,335 +0,0 @@
-/*
- * Copyright (C) 2015 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.documentsui;
-
-import static com.android.documentsui.Events.isMouseEvent;
-import static com.android.internal.util.Preconditions.checkState;
-
-import android.graphics.Point;
-import android.graphics.Rect;
-import android.graphics.drawable.Drawable;
-import android.support.v7.widget.RecyclerView;
-import android.support.v7.widget.RecyclerView.ViewHolder;
-import android.util.Log;
-import android.util.SparseBooleanArray;
-import android.view.MotionEvent;
-import android.view.View;
-
-/**
- * Provides mouse driven band-select support when used in conjuction with {@link RecyclerView} and
- * {@link MultiSelectManager}. This class is responsible for rendering the band select overlay and
- * selecting overlaid items via MultiSelectManager.
- */
-public class BandSelectManager extends RecyclerView.SimpleOnItemTouchListener {
-
-    private static final int NOT_SELECTED = -1;
-    private static final int NOT_SET = -1;
-
-    // For debugging purposes.
-    private static final String TAG = "BandSelectManager";
-    private static final boolean DEBUG = false;
-
-    private final RecyclerView mRecyclerView;
-    private final MultiSelectManager mSelectManager;
-    private final Drawable mRegionSelectorDrawable;
-    private final SparseBooleanArray mSelectedByBand = new SparseBooleanArray();
-
-    private boolean mIsBandSelectActive = false;
-    private Point mOrigin;
-    private Point mPointer;
-    private Rect mBounds;
-
-    // Maintain the last selection made by band, so if bounds shrink back, we can deselect
-    // the respective items.
-    private int mCursorDeltaY = 0;
-    private int mFirstSelected = NOT_SELECTED;
-
-    // The time at which the current band selection-induced scroll began. If no scroll is in
-    // progress, the value is NOT_SET.
-    private long mScrollStartTime = NOT_SET;
-    private final Runnable mScrollRunnable = new Runnable() {
-        /**
-         * The number of milliseconds of scrolling at which scroll speed continues to increase. At
-         * first, the scroll starts slowly; then, the rate of scrolling increases until it reaches
-         * its maximum value at after this many milliseconds.
-         */
-        private static final long SCROLL_ACCELERATION_LIMIT_TIME_MS = 2000;
-
-        @Override
-        public void run() {
-            // Compute the number of pixels the pointer's y-coordinate is past the view. Negative
-            // values mean the pointer is at or before the top of the view, and positive values mean
-            // that the pointer is at or after the bottom of the view. Note that one additional
-            // pixel is added here so that the view still scrolls when the pointer is exactly at the
-            // top or bottom.
-            int pixelsPastView = 0;
-            if (mPointer.y <= 0) {
-                pixelsPastView = mPointer.y - 1;
-            } else if (mPointer.y >= mRecyclerView.getHeight() - 1) {
-                pixelsPastView = mPointer.y - mRecyclerView.getHeight() + 1;
-            }
-
-            if (!mIsBandSelectActive || pixelsPastView == 0) {
-                // If band selection is inactive, or if it is active but not at the edge of the
-                // view, no scrolling is necessary.
-                mScrollStartTime = NOT_SET;
-                return;
-            }
-
-            if (mScrollStartTime == NOT_SET) {
-                // If the pointer was previously not at the edge of the view but now is, set the
-                // start time for the scroll.
-                mScrollStartTime = System.currentTimeMillis();
-            }
-
-            // Compute the number of pixels to scroll, and scroll that many pixels.
-            final int numPixels = computeNumPixelsToScroll(
-                    pixelsPastView, System.currentTimeMillis() - mScrollStartTime);
-            mRecyclerView.scrollBy(0, numPixels);
-
-            // Adjust the y-coordinate of the origin the opposite number of pixels so that the
-            // origin remains in the same place relative to the view's items.
-            mOrigin.y -= numPixels;
-            resizeBandSelectRectangle();
-
-            mRecyclerView.removeCallbacks(mScrollRunnable);
-            mRecyclerView.postOnAnimation(this);
-        }
-
-        /**
-         * Computes the number of pixels to scroll based on how far the pointer is past the end of
-         * the view and how long it has been there. Roughly based on ItemTouchHelper's algorithm for
-         * computing the number of pixels to scroll when an item is dragged to the end of a
-         * {@link RecyclerView}.
-         * @param pixelsPastView
-         * @param scrollDuration
-         * @return
-         */
-        private int computeNumPixelsToScroll(int pixelsPastView, long scrollDuration) {
-            final int maxScrollStep = computeMaxScrollStep(mRecyclerView);
-            final int direction = (int) Math.signum(pixelsPastView);
-            final int absPastView = Math.abs(pixelsPastView);
-
-            // Calculate the ratio of how far out of the view the pointer currently resides to the
-            // entire height of the view.
-            final float outOfBoundsRatio = Math.min(
-                    1.0f, (float) absPastView / mRecyclerView.getHeight());
-            // Interpolate this ratio and use it to compute the maximum scroll that should be
-            // possible for this step.
-            final float cappedScrollStep =
-                    direction * maxScrollStep * smoothOutOfBoundsRatio(outOfBoundsRatio);
-
-            // Likewise, calculate the ratio of the time spent in the scroll to the limit.
-            final float timeRatio = Math.min(
-                    1.0f, (float) scrollDuration / SCROLL_ACCELERATION_LIMIT_TIME_MS);
-            // Interpolate this ratio and use it to compute the final number of pixels to scroll.
-            final int numPixels = (int) (cappedScrollStep * smoothTimeRatio(timeRatio));
-
-            // If the final number of pixels to scroll ends up being 0, the view should still scroll
-            // at least one pixel.
-            return numPixels != 0 ? numPixels : direction;
-        }
-
-        /**
-         * Computes the maximum scroll allowed for a given animation frame. Currently, this
-         * defaults to the height of the view, but this could be tweaked if this results in scrolls
-         * that are too fast or too slow.
-         * @param rv
-         * @return
-         */
-        private int computeMaxScrollStep(RecyclerView rv) {
-            return rv.getHeight();
-        }
-
-        /**
-         * Interpolates the given out of bounds ratio on a curve which starts at (0,0) and ends at
-         * (1,1) and quickly approaches 1 near the start of that interval. This ensures that drags
-         * that are at the edge or barely past the edge of the view still cause sufficient
-         * scrolling. The equation y=(x-1)^5+1 is used, but this could also be tweaked if needed.
-         * @param ratio A ratio which is in the range [0, 1].
-         * @return A "smoothed" value, also in the range [0, 1].
-         */
-        private float smoothOutOfBoundsRatio(float ratio) {
-            return (float) Math.pow(ratio - 1.0f, 5) + 1.0f;
-        }
-
-        /**
-         * Interpolates the given time ratio on a curve which starts at (0,0) and ends at (1,1) and
-         * stays close to 0 for most input values except those very close to 1. This ensures that
-         * scrolls start out very slowly but speed up drastically after the scroll has been in
-         * progress close to SCROLL_ACCELERATION_LIMIT_TIME_MS. The equation y=x^5 is used, but this
-         * could also be tweaked if needed.
-         * @param ratio A ratio which is in the range [0, 1].
-         * @return A "smoothed" value, also in the range [0, 1].
-         */
-        private float smoothTimeRatio(float ratio) {
-            return (float) Math.pow(ratio, 5);
-        }
-    };
-
-    /**
-     * @param recyclerView
-     * @param multiSelectManager
-     */
-    public BandSelectManager(RecyclerView recyclerView, MultiSelectManager multiSelectManager) {
-        mRecyclerView = recyclerView;
-        mSelectManager = multiSelectManager;
-        mRegionSelectorDrawable =
-            mRecyclerView.getContext().getTheme().getDrawable(R.drawable.band_select_overlay);
-
-        mRecyclerView.addOnItemTouchListener(this);
-    }
-
-    @Override
-    public boolean onInterceptTouchEvent(RecyclerView rv, MotionEvent e) {
-        // Only intercept the event if it was triggered by a mouse. If band select is inactive,
-        // do not intercept ACTION_UP events as they will not be processed.
-        return isMouseEvent(e) &&
-                (mIsBandSelectActive || e.getActionMasked() != MotionEvent.ACTION_UP);
-    }
-
-    @Override
-    public void onTouchEvent(RecyclerView rv, MotionEvent e) {
-        checkState(isMouseEvent(e));
-        processMotionEvent(e);
-    }
-
-    /**
-     * Processes a MotionEvent by starting, ending, or resizing the band select overlay.
-     * @param e
-     */
-    private void processMotionEvent(MotionEvent e) {
-        if (mIsBandSelectActive && e.getActionMasked() == MotionEvent.ACTION_UP) {
-            endBandSelect();
-            return;
-        }
-
-        mPointer = new Point((int) e.getX(), (int) e.getY());
-        if (!mIsBandSelectActive) {
-            startBandSelect();
-        }
-
-        scrollViewIfNecessary();
-        resizeBandSelectRectangle();
-        selectChildrenCoveredBySelection();
-    }
-
-    /**
-     * Starts band select by adding the drawable to the RecyclerView's overlay.
-     */
-    private void startBandSelect() {
-        if (DEBUG) Log.d(TAG, "Starting band select from (" + mPointer.x + "," + mPointer.y + ").");
-        mIsBandSelectActive = true;
-        mOrigin = mPointer;
-        mRecyclerView.getOverlay().add(mRegionSelectorDrawable);
-    }
-
-    /**
-     * Scrolls the view if necessary.
-     */
-    private void scrollViewIfNecessary() {
-        mRecyclerView.removeCallbacks(mScrollRunnable);
-        mScrollRunnable.run();
-        mRecyclerView.invalidate();
-    }
-
-    /**
-     * Resizes the band select rectangle by using the origin and the current pointer positoin as
-     * two opposite corners of the selection.
-     */
-    private void resizeBandSelectRectangle() {
-        if (mBounds != null) {
-            mCursorDeltaY = mPointer.y - mBounds.bottom;
-        }
-
-        mBounds = new Rect(Math.min(mOrigin.x, mPointer.x),
-                Math.min(mOrigin.y, mPointer.y),
-                Math.max(mOrigin.x, mPointer.x),
-                Math.max(mOrigin.y, mPointer.y));
-
-        mRegionSelectorDrawable.setBounds(mBounds);
-    }
-
-    /**
-     * Selects the children covered by the band select overlay by delegating to MultiSelectManager.
-     * TODO: Provide a finished implementation. This is down and dirty, proof of concept code.
-     * Final optimized implementation, with support for managing offscreen selection to come.
-     */
-    private void selectChildrenCoveredBySelection() {
-
-        // track top and bottom selections. Details on why this is useful below.
-        int first = NOT_SELECTED;
-        int last = NOT_SELECTED;
-
-        for (int i = 0; i < mRecyclerView.getChildCount(); i++) {
-
-            View child = mRecyclerView.getChildAt(i);
-            ViewHolder holder = mRecyclerView.getChildViewHolder(child);
-            Rect childRect = new Rect();
-            child.getHitRect(childRect);
-
-            boolean shouldSelect = Rect.intersects(childRect, mBounds);
-            int position = holder.getAdapterPosition();
-
-            // This also allows us to clear the selection of elements
-            // that only temporarily entered the bounds of the band.
-            if (mSelectedByBand.get(position) && !shouldSelect) {
-                mSelectManager.setItemSelected(position, false);
-                mSelectedByBand.delete(position);
-            }
-
-            // We need to keep track of the first and last items selected.
-            // We'll use this information along with cursor direction
-            // to determine the starting point of the selection.
-            // We provide this information to selection manager
-            // to enable more natural user interaction when working
-            // with Shift+Click and multiple contiguous selection ranges.
-            if (shouldSelect) {
-                if (first == NOT_SELECTED) {
-                    first = position;
-                } else {
-                    last = position;
-                }
-                mSelectManager.setItemSelected(position, true);
-                mSelectedByBand.put(position, true);
-            }
-        }
-
-        // Remember which is the last selected item, so we can
-        // share that with selection manager when band select ends.
-        // It'll use that as it's begin selection point when
-        // user SHIFT+Clicks.
-        if (mCursorDeltaY < 0 && last != NOT_SELECTED) {
-            mFirstSelected = last;
-        } else if (mCursorDeltaY > 0 && first != NOT_SELECTED) {
-            mFirstSelected = first;
-        }
-    }
-
-    /**
-     * Ends band select by removing the overlay.
-     */
-    private void endBandSelect() {
-        if (DEBUG) Log.d(TAG, "Ending band select.");
-        mIsBandSelectActive = false;
-        mSelectedByBand.clear();
-        mRecyclerView.getOverlay().remove(mRegionSelectorDrawable);
-        if (mFirstSelected != NOT_SELECTED) {
-            mSelectManager.setSelectionFocusBegin(mFirstSelected);
-        }
-    }
-}
diff --git a/packages/DocumentsUI/src/com/android/documentsui/BandSelectMatrix.java b/packages/DocumentsUI/src/com/android/documentsui/BandSelectMatrix.java
deleted file mode 100644
index f259059..0000000
--- a/packages/DocumentsUI/src/com/android/documentsui/BandSelectMatrix.java
+++ /dev/null
@@ -1,645 +0,0 @@
-/*
- * 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.documentsui;
-
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-
-import com.google.common.base.Preconditions;
-
-import android.graphics.Point;
-import android.graphics.Rect;
-import android.support.annotation.Nullable;
-import android.support.v7.widget.GridLayoutManager;
-import android.support.v7.widget.RecyclerView;
-import android.support.v7.widget.RecyclerView.LayoutManager;
-import android.support.v7.widget.RecyclerView.OnScrollListener;
-import android.util.SparseBooleanArray;
-import android.view.View;
-
-/**
- * Provides a band selection item model for views within a RecyclerView. This class queries the
- * RecyclerView to determine where its items are placed; then, once band selection is underway, it
- * alerts listeners of which items are covered by the selections.
- */
-public final class BandSelectMatrix extends RecyclerView.OnScrollListener {
-
-    private final RecyclerViewHelper mHelper;
-    private final List<OnSelectionChangedListener> mOnSelectionChangedListeners = new ArrayList<>();
-
-    // Map from the x-value of the left side of an item to an ordered list of metadata of all items
-    // whose x-values are the same. The list is ordered by the y-values of the items in the column.
-    // For example, if the first column of the view starts at an x-value of 5, mColumns.get(5) would
-    // return a list of all items in that column, with the top-most item first in the list and the
-    // bottom-most item last in the list.
-    private final Map<Integer, List<ItemData>> mColumns = new HashMap<>();
-
-    // List of limits along the x-axis. For example, if the view has two columns, this list will
-    // have two elements, each of which lists the lower- and upper-limits of the x-values of the
-    // view items. This list is sorted from furthest left to furthest right.
-    private final List<Limits> mXLimitsList = new ArrayList<>();
-
-    // Like mXLimitsList, but for y-coordinates. Note that this list only contains items which have
-    // been in the viewport. Thus, limits which exist in an area of the view to which the view has
-    // not scrolled are not present in the list.
-    private final List<Limits> mYLimitsList = new ArrayList<>();
-
-    // The adapter positions which have been recorded so far.
-    private final SparseBooleanArray mRecordedPositions = new SparseBooleanArray();
-
-    // Array passed to registered OnSelectionChangedListeners. One array is created and reused
-    // throughout the lifetime of the object.
-    private final SparseBooleanArray mSelectionForListeners = new SparseBooleanArray();
-
-    // The current pointer (in absolute positioning from the top of the view).
-    private Point mPointer = null;
-
-    // The bounds of the band selection.
-    private RelativePoint mRelativeOrigin;
-    private RelativePoint mRelativePointer;
-
-    BandSelectMatrix(RecyclerViewHelper helper) {
-        mHelper = helper;
-        mHelper.addOnScrollListener(this);
-    }
-
-    BandSelectMatrix(RecyclerView rv) {
-        this(new RuntimeRecyclerViewHelper(rv));
-    }
-
-    /**
-     * Stops listening to the view's scrolls. Call this function before discarding a
-     * BandSelecMatrix object to prevent memory leaks.
-     */
-    void stopListening() {
-        mHelper.removeOnScrollListener(this);
-    }
-
-    /**
-     * Start a band select operation at the given point.
-     * @param relativeOrigin The origin of the band select operation, relative to the viewport.
-     *     For example, if the view is scrolled to the bottom, the top-left of the viewport would
-     *     have a relative origin of (0, 0), even though its absolute point has a higher y-value.
-     */
-    void startSelection(Point relativeOrigin) {
-        Point absoluteOrigin = mHelper.createAbsolutePoint(relativeOrigin);
-        mPointer = new Point(absoluteOrigin.x, absoluteOrigin.y);
-
-        processVisibleChildren();
-        mRelativeOrigin = new RelativePoint(absoluteOrigin);
-        mRelativePointer = new RelativePoint(mPointer);
-        computeCurrentSelection();
-        notifyListeners();
-    }
-
-    /**
-     * Resizes the selection by adjusting the pointer (i.e., the corner of the selection opposite
-     * the origin.
-     * @param relativePointer The pointer (opposite of the origin) of the band select operation,
-     *     relative to the viewport. For example, if the view is scrolled to the bottom, the
-     *     top-left of the viewport would have a relative origin of (0, 0), even though its absolute
-     *     point has a higher y-value.
-     */
-    void resizeSelection(Point relativePointer) {
-        mPointer = mHelper.createAbsolutePoint(relativePointer);
-        handlePointerMoved();
-    }
-
-    @Override
-    public void onScrolled(RecyclerView recyclerView, int dx, int dy) {
-        if (mPointer == null) {
-            return;
-        }
-
-        mPointer.x += dx;
-        mPointer.y += dy;
-        processVisibleChildren();
-        handlePointerMoved();
-    }
-
-    /**
-     * Queries the view for all children and records their location metadata.
-     */
-    private void processVisibleChildren() {
-        for (int i = 0; i < mHelper.getVisibleChildCount(); i++) {
-            int adapterPosition = mHelper.getAdapterPositionAt(i);
-            if (!mRecordedPositions.get(adapterPosition)) {
-                mRecordedPositions.put(adapterPosition, true);
-                captureItemLayoutData(mHelper.getAbsoluteRectForChildViewAt(i), adapterPosition);
-            }
-        }
-    }
-
-    /**
-     * Updates the limits lists and column map with the given item metadata.
-     * @param absoluteChildRect The absolute rectangle for the child view being processed.
-     * @param adapterPosition The position of the child view being processed.
-     */
-    private void captureItemLayoutData(Rect absoluteChildRect, int adapterPosition) {
-        if (mXLimitsList.size() != mHelper.getNumColumns()) {
-            // If not all x-limits have been recorded, record this one.
-            recordLimits(
-                    mXLimitsList, new Limits(absoluteChildRect.left, absoluteChildRect.right));
-        }
-
-        if (mYLimitsList.size() != mHelper.getNumRows()) {
-            // If not all y-limits have been recorded, record this one.
-            recordLimits(
-                    mYLimitsList, new Limits(absoluteChildRect.top, absoluteChildRect.bottom));
-        }
-
-        List<ItemData> columnList = mColumns.get(absoluteChildRect.left);
-        if (columnList == null) {
-            columnList = new ArrayList<ItemData>();
-            mColumns.put(absoluteChildRect.left, columnList);
-        }
-        recordItemData(
-                columnList, new ItemData(adapterPosition, absoluteChildRect.top));
-    }
-
-    /**
-     * Ensures limits exists within the sorted list limitsList, and adds it to the list if it does
-     * not exist.
-     */
-    private static void recordLimits(List<Limits> limitsList, Limits limits) {
-        int index = Collections.binarySearch(limitsList, limits);
-        if (index < 0) {
-            limitsList.add(~index, limits);
-        }
-    }
-
-    /**
-     * Ensures itemData exists within the sorted list itemDataList, and adds it to the list if it
-     * does not exist.
-     */
-    private static void recordItemData(List<ItemData> itemDataList, ItemData itemData) {
-        int index = Collections.binarySearch(itemDataList, itemData);
-        if (index < 0) {
-            itemDataList.add(~index, itemData);
-        }
-    }
-
-    /**
-     * Handles a moved pointer; this function determines whether the pointer movement resulted in a
-     * selection change and, if it has, notifies listeners of this change.
-     */
-    private void handlePointerMoved() {
-        RelativePoint old = mRelativePointer;
-        mRelativePointer = new RelativePoint(mPointer);
-        if (old != null && mRelativePointer.equals(old)) {
-            return;
-        }
-
-        computeCurrentSelection();
-        notifyListeners();
-    }
-
-    /**
-     * Computes the currently-selected items.
-     */
-    private void computeCurrentSelection() {
-        Rect selectionRect = mRelativePointer.computeBounds(mRelativeOrigin);
-        computePositionsCoveredByRect(selectionRect);
-    }
-
-    /**
-     * Notifies all listeners of a selection change. Note that this function simply passes
-     * mSelectionForListeners, so computeCurrentSelection() should be called before this function.
-     */
-    private void notifyListeners() {
-        for (OnSelectionChangedListener listener : mOnSelectionChangedListeners) {
-            listener.onSelectionChanged(mSelectionForListeners);
-        }
-    }
-
-    /**
-     * @param rect Rectangle including all covered items.
-     */
-    private void computePositionsCoveredByRect(@Nullable Rect rect) {
-        mSelectionForListeners.clear();
-        if (rect == null) {
-            // If there is no bounding rectangle, there are no items selected, so just return early.
-            return;
-        }
-
-        int columnIndex = Collections.binarySearch(mXLimitsList, new Limits(rect.left, rect.left));
-        Preconditions.checkState(columnIndex >= 0);
-
-        for (; columnIndex < mXLimitsList.size() &&
-                mXLimitsList.get(columnIndex).lowerLimit <= rect.right; columnIndex++) {
-            List<ItemData> positions =
-                    mColumns.get(mXLimitsList.get(columnIndex).lowerLimit);
-            int rowIndex = Collections.binarySearch(positions, new ItemData(0, rect.top));
-            if (rowIndex < 0) {
-                // If band select occurs after the last item in a row with fewer items than columns,
-                // go to the next column. This situation occurs in the last row of the grid when the
-                // total number of items is not a multiple of the number of columns (e.g., when 10
-                // items exist in a grid with 4 columns).
-                continue;
-            }
-
-            for (; rowIndex < positions.size() &&
-                    positions.get(rowIndex).offset <= rect.bottom; rowIndex++) {
-                mSelectionForListeners.append(positions.get(rowIndex).position, true);
-            }
-        }
-    }
-
-    /**
-     * Provides functionality for interfacing with the view. In practice, RecyclerViewMatrixHelper
-     * should be used; this interface exists solely for the purpose of decoupling the view from
-     * this class so that the view can be mocked out for tests.
-     */
-    interface RecyclerViewHelper {
-        public void addOnScrollListener(RecyclerView.OnScrollListener listener);
-        public void removeOnScrollListener(RecyclerView.OnScrollListener listener);
-        public Point createAbsolutePoint(Point relativePoint);
-        public int getVisibleChildCount();
-        public int getTotalChildCount();
-        public int getNumColumns();
-        public int getNumRows();
-        public int getAdapterPositionAt(int index);
-        public Rect getAbsoluteRectForChildViewAt(int index);
-    }
-
-    /**
-     * Concrete MatrixHelper implementation for use within the Files app.
-     */
-    static class RuntimeRecyclerViewHelper implements RecyclerViewHelper {
-        private final RecyclerView mRecyclerView;
-
-        RuntimeRecyclerViewHelper(RecyclerView rv) {
-            mRecyclerView = rv;
-        }
-
-        @Override
-        public int getAdapterPositionAt(int index) {
-            View child = mRecyclerView.getChildAt(index);
-            return mRecyclerView.getChildViewHolder(child).getAdapterPosition();
-        }
-
-        @Override
-        public void addOnScrollListener(OnScrollListener listener) {
-            mRecyclerView.addOnScrollListener(listener);
-        }
-
-        @Override
-        public void removeOnScrollListener(OnScrollListener listener) {
-            mRecyclerView.removeOnScrollListener(listener);
-        }
-
-        @Override
-        public Point createAbsolutePoint(Point relativePoint) {
-            return new Point(relativePoint.x + mRecyclerView.computeHorizontalScrollOffset(),
-                    relativePoint.y + mRecyclerView.computeVerticalScrollOffset());
-        }
-
-        @Override
-        public Rect getAbsoluteRectForChildViewAt(int index) {
-            final View child = mRecyclerView.getChildAt(index);
-            final Rect childRect = new Rect();
-            child.getHitRect(childRect);
-            childRect.left += mRecyclerView.computeHorizontalScrollOffset();
-            childRect.right += mRecyclerView.computeHorizontalScrollOffset();
-            childRect.top += mRecyclerView.computeVerticalScrollOffset();
-            childRect.bottom += mRecyclerView.computeVerticalScrollOffset();
-            return childRect;
-        }
-
-        @Override
-        public int getVisibleChildCount() {
-            return mRecyclerView.getChildCount();
-        }
-
-        @Override
-        public int getTotalChildCount() {
-            return mRecyclerView.getAdapter().getItemCount();
-        }
-
-        @Override
-        public int getNumColumns() {
-            LayoutManager layoutManager = mRecyclerView.getLayoutManager();
-            if (layoutManager instanceof GridLayoutManager) {
-                return ((GridLayoutManager) layoutManager).getSpanCount();
-            }
-
-            // Otherwise, it is a list with 1 column.
-            return 1;
-        }
-
-        @Override
-        public int getNumRows() {
-            int numFullColumns = getTotalChildCount() / getNumColumns();
-            boolean hasPartiallyFullColumn = getTotalChildCount() % getNumColumns() != 0;
-            return numFullColumns + (hasPartiallyFullColumn ? 1 : 0);
-        }
-    }
-
-    /**
-     * Listener for changes in which items have been band selected.
-     */
-    interface OnSelectionChangedListener {
-        public void onSelectionChanged(SparseBooleanArray updatedSelection);
-    }
-
-    void addOnSelectionChangedListener(OnSelectionChangedListener listener) {
-        mOnSelectionChangedListeners.add(listener);
-    }
-
-    void removeOnSelectionChangedListener(OnSelectionChangedListener listener) {
-        mOnSelectionChangedListeners.remove(listener);
-    }
-
-    /**
-     * Metadata for an item in the view, consisting of the adapter position and the offset from the
-     * top of the view (in pixels). Stored in the mColumns map to model the item grid.
-     */
-    private static class ItemData implements Comparable<ItemData> {
-        int position;
-        int offset;
-
-        ItemData(int position, int offset) {
-            this.position = position;
-            this.offset = offset;
-        }
-
-        @Override
-        public int compareTo(ItemData other) {
-            // The list of columns is sorted via the offset from the top, so PositionMetadata
-            // objects with lower y-values are befor those with higher y-values.
-            return offset - other.offset;
-        }
-    }
-
-    /**
-     * Limits of a view item. For example, if an item's left side is at x-value 5 and its right side
-     * is at x-value 10, the limits would be from 5 to 10. Used to record the left- and right sides
-     * of item columns and the top- and bottom sides of item rows so that it can be determined
-     * whether the pointer is located within the bounds of an item.
-     */
-    private static class Limits implements Comparable<Limits> {
-        int lowerLimit;
-        int upperLimit;
-
-        Limits(int lowerLimit, int upperLimit) {
-            this.lowerLimit = lowerLimit;
-            this.upperLimit = upperLimit;
-        }
-
-        @Override
-        public int compareTo(Limits other) {
-            return lowerLimit - other.lowerLimit;
-        }
-
-        @Override
-        public boolean equals(Object other) {
-            if (!(other instanceof Limits)) {
-                return false;
-            }
-
-            return ((Limits) other).lowerLimit == lowerLimit &&
-                    ((Limits) other).upperLimit == upperLimit;
-        }
-    }
-
-    /**
-     * The location of a coordinate relative to items. This class represents a general area of the
-     * view as it relates to band selection rather than an explicit point. For example, two
-     * different points within an item are considered to have the same "location" because band
-     * selection originating within the item would select the same items no matter which point
-     * was used. Same goes for points between items as well as those at the very beginning or end
-     * of the view.
-     *
-     * Tracking a coordinate (e.g., an x-value) as a CoordinateLocation instead of as an int has the
-     * advantage of tying the value to the Limits of items along that axis. This allows easy
-     * selection of items within those Limits as opposed to a search through every item to see if a
-     * given coordinate value falls within those Limits.
-     */
-    private static class RelativeCoordinate
-            implements Comparable<RelativeCoordinate> {
-        /**
-         * Location describing points after the last known item.
-         */
-        static final int AFTER_LAST_ITEM = 0;
-
-        /**
-         * Location describing points before the first known item.
-         */
-        static final int BEFORE_FIRST_ITEM = 1;
-
-        /**
-         * Location describing points between two items.
-         */
-        static final int BETWEEN_TWO_ITEMS = 2;
-
-        /**
-         * Location describing points within the limits of one item.
-         */
-        static final int WITHIN_LIMITS = 3;
-
-        /**
-         * The type of this coordinate, which is one of AFTER_LAST_ITEM, BEFORE_FIRST_ITEM,
-         * BETWEEN_TWO_ITEMS, or WITHIN_LIMITS.
-         */
-        final int type;
-
-        /**
-         * The limits before the coordinate; only populated when type == WITHIN_LIMITS or type ==
-         * BETWEEN_TWO_ITEMS.
-         */
-        Limits limitsBeforeCoordinate;
-
-        /**
-         * The limits after the coordinate; only populated when type == BETWEEN_TWO_ITEMS.
-         */
-        Limits limitsAfterCoordinate;
-
-        // Limits of the first known item; only populated when type == BEFORE_FIRST_ITEM.
-        Limits mFirstKnownItem;
-        // Limits of the last known item; only populated when type == AFTER_LAST_ITEM.
-        Limits mLastKnownItem;
-
-        /**
-         * @param limitsList The sorted limits list for the coordinate type. If this
-         *     CoordinateLocation is an x-value, mXLimitsList should be passed; otherwise,
-         *     mYLimitsList should be pased.
-         * @param value The coordinate value.
-         */
-        RelativeCoordinate(List<Limits> limitsList, int value) {
-            Limits dummyLimits = new Limits(value, value);
-            int index = Collections.binarySearch(limitsList, dummyLimits);
-
-            if (index >= 0) {
-                this.type = WITHIN_LIMITS;
-                this.limitsBeforeCoordinate = limitsList.get(index);
-            } else if (~index == 0) {
-                this.type = BEFORE_FIRST_ITEM;
-                this.mFirstKnownItem = limitsList.get(0);
-            } else if (~index == limitsList.size()) {
-                Limits lastLimits = limitsList.get(limitsList.size() - 1);
-                if (lastLimits.lowerLimit <= value && value <= lastLimits.upperLimit) {
-                    this.type = WITHIN_LIMITS;
-                    this.limitsBeforeCoordinate = lastLimits;
-                } else {
-                    this.type = AFTER_LAST_ITEM;
-                    this.mLastKnownItem = lastLimits;
-                }
-            } else {
-                Limits limitsBeforeIndex = limitsList.get(~index - 1);
-                if (limitsBeforeIndex.lowerLimit <= value && value <= limitsBeforeIndex.upperLimit) {
-                    this.type = WITHIN_LIMITS;
-                    this.limitsBeforeCoordinate = limitsList.get(~index - 1);
-                } else {
-                    this.type = BETWEEN_TWO_ITEMS;
-                    this.limitsBeforeCoordinate = limitsList.get(~index - 1);
-                    this.limitsAfterCoordinate = limitsList.get(~index);
-                }
-            }
-        }
-
-        int toComparisonValue() {
-            if (type == BEFORE_FIRST_ITEM) {
-                return mFirstKnownItem.lowerLimit - 1;
-            } else if (type == AFTER_LAST_ITEM) {
-                return mLastKnownItem.upperLimit + 1;
-            } else if (type == BETWEEN_TWO_ITEMS) {
-                return limitsBeforeCoordinate.upperLimit + 1;
-            } else {
-                return limitsBeforeCoordinate.lowerLimit;
-            }
-        }
-
-        @Override
-        public boolean equals(Object other) {
-            if (!(other instanceof RelativeCoordinate)) {
-                return false;
-            }
-
-            RelativeCoordinate otherCoordinate = (RelativeCoordinate) other;
-            return toComparisonValue() == otherCoordinate.toComparisonValue();
-        }
-
-        @Override
-        public int compareTo(RelativeCoordinate other) {
-            return toComparisonValue() - other.toComparisonValue();
-        }
-    }
-
-    /**
-     * The location of a point relative to the Limits of nearby items; consists of both an x- and
-     * y-RelativeCoordinateLocation.
-     */
-    private class RelativePoint {
-        final RelativeCoordinate xLocation;
-        final RelativeCoordinate yLocation;
-
-        RelativePoint(Point point) {
-            this.xLocation = new RelativeCoordinate(mXLimitsList, point.x);
-            this.yLocation = new RelativeCoordinate(mYLimitsList, point.y);
-        }
-
-        @Override
-        public boolean equals(Object other) {
-            if (!(other instanceof RelativePoint)) {
-                return false;
-            }
-
-            RelativePoint otherPoint = (RelativePoint) other;
-            return xLocation.equals(otherPoint.xLocation) && yLocation.equals(otherPoint.yLocation);
-        }
-
-        /**
-         * Generates a rectangle which contains the items selected by the two points.
-         * @param other The other PointLocation. A rectangle will be formed between "this" and
-         *     "other".
-         * @return The rectangle, or null if no items were selected.
-         */
-        Rect computeBounds(RelativePoint other) {
-            if (!areItemsCoveredBySelection(mRelativePointer, mRelativeOrigin)) {
-                return null;
-            }
-
-            RelativeCoordinate minXLocation =
-                    xLocation.compareTo(other.xLocation) < 0 ? xLocation : other.xLocation;
-            RelativeCoordinate maxXLocation =
-                    minXLocation == xLocation ? other.xLocation : xLocation;
-            RelativeCoordinate minYLocation =
-                    yLocation.compareTo(other.yLocation) < 0 ? yLocation : other.yLocation;
-            RelativeCoordinate maxYLocation =
-                    minYLocation == yLocation ? other.yLocation : yLocation;
-
-            Rect rect = new Rect();
-            rect.left = getCoordinateValue(minXLocation, mXLimitsList, true);
-            rect.right = getCoordinateValue(maxXLocation, mXLimitsList, false);
-            rect.top = getCoordinateValue(minYLocation, mYLimitsList, true);
-            rect.bottom = getCoordinateValue(maxYLocation, mYLimitsList, false);
-            return rect;
-        }
-
-        int getCoordinateValue(RelativeCoordinate coordinate,
-                List<Limits> limitsList, boolean isStartOfRange) {
-            switch (coordinate.type) {
-                case RelativeCoordinate.BEFORE_FIRST_ITEM:
-                    return limitsList.get(0).lowerLimit;
-                case RelativeCoordinate.AFTER_LAST_ITEM:
-                    return limitsList.get(limitsList.size() - 1).upperLimit;
-                case RelativeCoordinate.BETWEEN_TWO_ITEMS:
-                    if (isStartOfRange) {
-                        return coordinate.limitsAfterCoordinate.lowerLimit;
-                    } else {
-                        return coordinate.limitsBeforeCoordinate.upperLimit;
-                    }
-                case RelativeCoordinate.WITHIN_LIMITS:
-                    return coordinate.limitsBeforeCoordinate.lowerLimit;
-            }
-
-            throw new RuntimeException("Invalid coordinate value.");
-        }
-    }
-
-    private static boolean areItemsCoveredBySelection(
-            RelativePoint first, RelativePoint second) {
-        return doesCoordinateLocationCoverItems(first.xLocation, second.xLocation) &&
-                doesCoordinateLocationCoverItems(first.yLocation, second.yLocation);
-    }
-
-    private static boolean doesCoordinateLocationCoverItems(
-            RelativeCoordinate pointerCoordinate,
-            RelativeCoordinate originCoordinate) {
-        if (pointerCoordinate.type == RelativeCoordinate.BEFORE_FIRST_ITEM &&
-                originCoordinate.type == RelativeCoordinate.BEFORE_FIRST_ITEM) {
-            return false;
-        }
-
-        if (pointerCoordinate.type == RelativeCoordinate.AFTER_LAST_ITEM &&
-                originCoordinate.type == RelativeCoordinate.AFTER_LAST_ITEM) {
-            return false;
-        }
-
-        if (pointerCoordinate.type == RelativeCoordinate.BETWEEN_TWO_ITEMS &&
-                originCoordinate.type == RelativeCoordinate.BETWEEN_TWO_ITEMS &&
-                pointerCoordinate.limitsBeforeCoordinate.equals(originCoordinate) &&
-                pointerCoordinate.limitsAfterCoordinate.equals(originCoordinate)) {
-            return false;
-        }
-
-        return true;
-    }
-}
diff --git a/packages/DocumentsUI/src/com/android/documentsui/DirectoryFragment.java b/packages/DocumentsUI/src/com/android/documentsui/DirectoryFragment.java
index 240cdda..c28806b 100644
--- a/packages/DocumentsUI/src/com/android/documentsui/DirectoryFragment.java
+++ b/packages/DocumentsUI/src/com/android/documentsui/DirectoryFragment.java
@@ -1773,8 +1773,6 @@
         }
 
         @Override
-        public void afterActivityCreated(DirectoryFragment fragment) {
-            new BandSelectManager(fragment.mRecView, fragment.mSelectionManager);
-        }
+        public void afterActivityCreated(DirectoryFragment fragment) {}
     }
 }
diff --git a/packages/DocumentsUI/src/com/android/documentsui/MultiSelectManager.java b/packages/DocumentsUI/src/com/android/documentsui/MultiSelectManager.java
index f87fe4c..e972566 100644
--- a/packages/DocumentsUI/src/com/android/documentsui/MultiSelectManager.java
+++ b/packages/DocumentsUI/src/com/android/documentsui/MultiSelectManager.java
@@ -16,24 +16,33 @@
 
 package com.android.documentsui;
 
+import static com.android.documentsui.Events.isMouseEvent;
 import static com.android.internal.util.Preconditions.checkArgument;
 import static com.android.internal.util.Preconditions.checkNotNull;
 import static com.android.internal.util.Preconditions.checkState;
 
+import android.support.v7.widget.GridLayoutManager;
 import android.support.v7.widget.RecyclerView;
 import android.support.v7.widget.RecyclerView.Adapter;
 import android.support.v7.widget.RecyclerView.AdapterDataObserver;
+import android.support.v7.widget.RecyclerView.LayoutManager;
+import android.support.v7.widget.RecyclerView.OnScrollListener;
 import android.util.Log;
+import android.util.SparseArray;
 import android.util.SparseBooleanArray;
+import android.util.SparseIntArray;
 import android.view.GestureDetector;
 import android.view.GestureDetector.OnDoubleTapListener;
 import android.view.GestureDetector.OnGestureListener;
 import android.view.MotionEvent;
 import android.view.View;
-
+import android.graphics.Point;
+import android.graphics.Rect;
+import android.graphics.drawable.Drawable;
 import android.support.annotation.VisibleForTesting;
 
 import java.util.ArrayList;
+import java.util.Collections;
 import java.util.List;
 
 /**
@@ -61,12 +70,13 @@
     private final List<MultiSelectManager.Callback> mCallbacks = new ArrayList<>(1);
 
     private Adapter<?> mAdapter;
-    private RecyclerViewHelper mHelper;
+    private MultiSelectHelper mHelper;
     private boolean mSingleSelect;
+    private BandSelectManager mBandSelectManager;
 
     /**
      * @param recyclerView
-     * @param gestureDelegate Option delage gesture listener.
+     * @param gestureDelegate Option delegate gesture listener.
      * @param mode Selection mode
      * @template A gestureDelegate that implements both {@link OnGestureListener}
      *     and {@link OnDoubleTapListener}
@@ -76,17 +86,11 @@
 
         this(
                 recyclerView.getAdapter(),
-                new RecyclerViewHelper() {
-                    @Override
-                    public int findEventPosition(MotionEvent e) {
-                        View view = recyclerView.findChildViewUnder(e.getX(), e.getY());
-                        return view != null
-                                ? recyclerView.getChildAdapterPosition(view)
-                                : RecyclerView.NO_POSITION;
-                    }
-                },
+                new RuntimeRecyclerViewHelper(recyclerView),
                 mode);
 
+        mBandSelectManager = new BandSelectManager((RuntimeRecyclerViewHelper) mHelper);
+
         GestureDetector.SimpleOnGestureListener listener =
                 new GestureDetector.SimpleOnGestureListener() {
                     @Override
@@ -101,11 +105,8 @@
 
         CompositeOnGestureListener<? extends Object> compositeListener =
                 new CompositeOnGestureListener<>(listener, gestureDelegate);
-        final GestureDetector detector = new GestureDetector(
-                recyclerView.getContext(),
-                gestureDelegate == null
-                        ? listener
-                        : compositeListener);
+        final GestureDetector detector =
+                new GestureDetector(recyclerView.getContext(), compositeListener);
 
         detector.setOnDoubleTapListener(compositeListener);
 
@@ -113,9 +114,15 @@
                 new RecyclerView.OnItemTouchListener() {
                     public boolean onInterceptTouchEvent(RecyclerView rv, MotionEvent e) {
                         detector.onTouchEvent(e);
-                        return false;
+
+                        // Only intercept the event if it was a mouse-based band selection.
+                        return isMouseEvent(e) && (mBandSelectManager.mIsActive ||
+                                e.getActionMasked() != MotionEvent.ACTION_UP);
                     }
-                    public void onTouchEvent(RecyclerView rv, MotionEvent e) {}
+                    public void onTouchEvent(RecyclerView rv, MotionEvent e) {
+                        checkState(isMouseEvent(e));
+                        mBandSelectManager.processMotionEvent(e);
+                    }
                     public void onRequestDisallowInterceptTouchEvent(boolean disallowIntercept) {}
                 });
     }
@@ -125,7 +132,7 @@
      * @hide
      */
     @VisibleForTesting
-    MultiSelectManager(Adapter<?> adapter, RecyclerViewHelper helper, int mode) {
+    MultiSelectManager(Adapter<?> adapter, MultiSelectHelper helper, int mode) {
         checkNotNull(adapter, "'adapter' cannot be null.");
         checkNotNull(helper, "'helper' cannot be null.");
 
@@ -207,6 +214,7 @@
      * @param selected
      * @return True if the selection state of the item changed.
      */
+    @VisibleForTesting
     public boolean setItemSelected(int position, boolean selected) {
         if (mSingleSelect && !mSelection.isEmpty()) {
             clearSelectionQuietly();
@@ -271,7 +279,7 @@
             if (DEBUG) Log.i(TAG, "View is null. Cannot handle tap event.");
         }
 
-        onLongPress(position);
+        onLongPress(position, e.getMetaState());
     }
 
     /**
@@ -279,17 +287,16 @@
      * can be mocked.
      *
      * @param position
+     * @param metaState as returned from {@link MotionEvent#getMetaState()}.
      * @hide
      */
     @VisibleForTesting
-    void onLongPress(int position) {
+    void onLongPress(int position, int metaState) {
         if (position == RecyclerView.NO_POSITION) {
             if (DEBUG) Log.i(TAG, "View is null. Cannot handle tap event.");
         }
 
-        if (toggleSelection(position)) {
-            notifySelectionChanged();
-        }
+        handlePositionChanged(position, metaState);
     }
 
     /**
@@ -327,17 +334,26 @@
             return false;
         }
 
+        handlePositionChanged(position, metaState);
+        return false;
+    }
+
+    /**
+     * Handles a change caused by a click on the item with the given position. If the Shift key is
+     * held down, this performs a range select; otherwise, it simply toggles the item's selection
+     * state.
+     */
+    private void handlePositionChanged(int position, int metaState) {
         if (Events.hasShiftBit(metaState) && mRanger != null) {
             mRanger.snapSelection(position);
-        } else {
-            toggleSelection(position);
-        }
 
-        // We're being lazy here notifying even when something might not have changed.
-        // To make this more correct, we'd need to update the Ranger class to return
-        // information about what has changed.
-        notifySelectionChanged();
-        return false;
+            // We're being lazy here notifying even when something might not have changed.
+            // To make this more correct, we'd need to update the Ranger class to return
+            // information about what has changed.
+            notifySelectionChanged();
+        } else if (toggleSelection(position)) {
+            notifySelectionChanged();
+        }
     }
 
     /**
@@ -588,10 +604,23 @@
      */
     public static final class Selection {
 
-        private SparseBooleanArray mSelection;
+        // This class tracks selected positions by managing two arrays: the saved selection, and
+        // the total selection. Saved selections are those which have been completed by tapping an
+        // item or by completing a band select operation. Provisional selections are selections
+        // which have been temporarily created by an in-progress band select operation (once the
+        // user releases the mouse button during a band select operation, the selected items
+        // become saved). The total selection is the combination of both the saved selection and
+        // the provisional selection. Tracking both separately is necessary to ensure that saved
+        // selections do not become deselected when they are removed from the provisional selection;
+        // for example, if item A is tapped (and selected), then an in-progress band select covers A
+        // then uncovers A, A should still be selected as it has been saved. To ensure this
+        // behavior, the saved selection must be tracked separately.
+        private SparseBooleanArray mSavedSelection;
+        private SparseBooleanArray mTotalSelection;
 
         public Selection() {
-            mSelection = new SparseBooleanArray();
+            mSavedSelection = new SparseBooleanArray();
+            mTotalSelection = new SparseBooleanArray();
         }
 
         /**
@@ -599,7 +628,7 @@
          * @return true if the position is currently selected.
          */
         public boolean contains(int position) {
-            return mSelection.get(position);
+            return mTotalSelection.get(position);
         }
 
         /**
@@ -613,21 +642,85 @@
          * @return the position value stored at specified index.
          */
         public int get(int index) {
-            return mSelection.keyAt(index);
+            return mTotalSelection.keyAt(index);
         }
 
         /**
          * @return size of the selection.
          */
         public int size() {
-            return mSelection.size();
+            return mTotalSelection.size();
         }
 
         /**
          * @return true if the selection is empty.
          */
         public boolean isEmpty() {
-            return mSelection.size() == 0;
+            return mTotalSelection.size() == 0;
+        }
+
+        /**
+         * Sets the provisional selection, which is a temporary selection that can be saved,
+         * canceled, or adjusted at a later time. When a new provision selection is applied, the old
+         * one (if it exists) is abandoned.
+         * @return Array with entry for each position added or removed. Entries which were added
+         *     contain a value of true, and entries which were removed contain a value of false.
+         */
+        @VisibleForTesting
+        protected SparseBooleanArray setProvisionalSelection(
+                SparseBooleanArray provisionalSelection) {
+            SparseBooleanArray delta = new SparseBooleanArray();
+
+            for (int i = 0; i < mTotalSelection.size(); i++) {
+                int position = mTotalSelection.keyAt(i);
+                if (!provisionalSelection.get(position) && !mSavedSelection.get(position)) {
+                    // Remove each item that used to be in the selection but is unsaved and not in
+                    // the new provisional selection.
+                    delta.put(position, false);
+                }
+            }
+
+            for (int i = 0; i < provisionalSelection.size(); i++) {
+                int position = provisionalSelection.keyAt(i);
+                if (!mTotalSelection.get(position)) {
+                    // Add each item that was not previously in the selection but is in the
+                    // new provisional selection.
+                    delta.put(position, true);
+                }
+            }
+
+            // Now, iterate through the changes and actually add/remove them to/from
+            // mCurrentSelection. This could not be done in the previous loops because changing the
+            // size of the selection mid-iteration changes iteration order erroneously.
+            for (int i = 0; i < delta.size(); i++) {
+                int position = delta.keyAt(i);
+                if (delta.get(position)) {
+                    mTotalSelection.put(position, true);
+                } else {
+                    mTotalSelection.delete(position);
+                }
+            }
+
+            return delta;
+        }
+
+        /**
+         * Saves the existing provisional selection. Once the provisional selection is saved,
+         * subsequent provisional selections which are different from this existing one cannot
+         * cause items in this existing provisional selection to become deselected.
+         */
+        @VisibleForTesting
+        protected void applyProvisionalSelection() {
+            mSavedSelection = mTotalSelection.clone();
+        }
+
+        /**
+         * Abandons the existing provisional selection so that all items provisionally selected are
+         * now deselected.
+         */
+        @VisibleForTesting
+        protected void cancelProvisionalSelection() {
+            mTotalSelection = mSavedSelection.clone();
         }
 
         private boolean flip(int position) {
@@ -643,8 +736,9 @@
         /** @hide */
         @VisibleForTesting
         boolean add(int position) {
-            if (!mSelection.get(position)) {
-                mSelection.put(position, true);
+            if (!mTotalSelection.get(position)) {
+                mTotalSelection.put(position, true);
+                mSavedSelection.put(position, true);
                 return true;
             }
             return false;
@@ -653,8 +747,9 @@
         /** @hide */
         @VisibleForTesting
         boolean remove(int position) {
-            if (mSelection.get(position)) {
-                mSelection.delete(position);
+            if (mTotalSelection.get(position)) {
+                mTotalSelection.delete(position);
+                mSavedSelection.delete(position);
                 return true;
             }
             return false;
@@ -663,7 +758,8 @@
         /**
          * Adjusts the selection range to reflect the existence of newly inserted values at
          * the specified positions. This has the effect of adjusting all existing selected
-         * positions within the specified range accordingly.
+         * positions within the specified range accordingly. Note that this function discards any
+         * provisional selections which may have been applied.
          *
          * @param startPosition
          * @param count
@@ -673,11 +769,13 @@
         void expand(int startPosition, int count) {
             checkState(startPosition >= 0);
             checkState(count > 0);
+            cancelProvisionalSelection();
 
-            for (int i = 0; i < mSelection.size(); i++) {
-                int itemPosition = mSelection.keyAt(i);
+            for (int i = 0; i < mTotalSelection.size(); i++) {
+                int itemPosition = mTotalSelection.keyAt(i);
                 if (itemPosition >= startPosition) {
-                    mSelection.setKeyAt(i, itemPosition + count);
+                    mTotalSelection.setKeyAt(i, itemPosition + count);
+                    mSavedSelection.setKeyAt(i, itemPosition + count);
                 }
             }
         }
@@ -685,7 +783,8 @@
         /**
          * Adjusts the selection range to reflect the removal specified positions. This has
          * the effect of adjusting all existing selected positions within the specified range
-         * accordingly.
+         * accordingly. Note that this function discards any provisional selections which may have
+         * been applied.
          *
          * @param startPosition
          * @param count The length of the range to collapse. Must be greater than 0.
@@ -699,27 +798,30 @@
             int endPosition = startPosition + count - 1;
 
             SparseBooleanArray newSelection = new SparseBooleanArray();
-            for (int i = 0; i < mSelection.size(); i++) {
-                int itemPosition = mSelection.keyAt(i);
+            for (int i = 0; i < mSavedSelection.size(); i++) {
+                int itemPosition = mSavedSelection.keyAt(i);
                 if (itemPosition < startPosition) {
                     newSelection.append(itemPosition, true);
                 } else if (itemPosition > endPosition) {
                     newSelection.append(itemPosition - count, true);
                 }
             }
-            mSelection = newSelection;
+            mSavedSelection = newSelection;
+            cancelProvisionalSelection();
         }
 
         /** @hide */
         @VisibleForTesting
         void clear() {
-            mSelection.clear();
+            mSavedSelection.clear();
+            mTotalSelection.clear();
         }
 
         /** @hide */
         @VisibleForTesting
         void copyFrom(Selection source) {
-            mSelection = source.mSelection.clone();
+            mSavedSelection = source.mSavedSelection.clone();
+            mTotalSelection = source.mTotalSelection.clone();
         }
 
         @Override
@@ -728,16 +830,16 @@
                 return "size=0, items=[]";
             }
 
-            StringBuilder buffer = new StringBuilder(mSelection.size() * 28);
+            StringBuilder buffer = new StringBuilder(mTotalSelection.size() * 28);
             buffer.append("{size=")
-                    .append(mSelection.size())
+                    .append(mTotalSelection.size())
                     .append(", ")
                     .append("items=[");
-            for (int i=0; i < mSelection.size(); i++) {
+            for (int i=0; i < mTotalSelection.size(); i++) {
                 if (i > 0) {
                     buffer.append(", ");
                 }
-                buffer.append(mSelection.keyAt(i));
+                buffer.append(mTotalSelection.keyAt(i));
             }
             buffer.append("]}");
             return buffer.toString();
@@ -745,7 +847,7 @@
 
         @Override
         public int hashCode() {
-            return mSelection.hashCode();
+            return mSavedSelection.hashCode() ^ mTotalSelection.hashCode();
         }
 
         @Override
@@ -758,14 +860,178 @@
               return false;
           }
 
-          return mSelection.equals(((Selection) that).mSelection);
+          return mSavedSelection.equals(((Selection) that).mSavedSelection) &&
+                  mTotalSelection.equals(((Selection) that).mTotalSelection);
         }
     }
 
-    interface RecyclerViewHelper {
+    /**
+     * Provides functionality for MultiSelectManager. In practice, use RuntimeRecyclerViewHelper;
+     * this interface exists only for mocking in tests.
+     */
+    interface MultiSelectHelper {
         int findEventPosition(MotionEvent e);
     }
 
+    /**
+     * Provides functionality for BandSelectManager. In practice, use RuntimeRecyclerViewHelper;
+     * this interface exists only for mocking in tests.
+     */
+    interface BandManagerHelper {
+        void drawBand(Rect rect);
+        void addOnScrollListener(RecyclerView.OnScrollListener listener);
+        int findEventPosition(MotionEvent e);
+        int getHeight();
+        void hideBand();
+        void invalidateView();
+        void postRunnable(Runnable r);
+        void removeCallback(Runnable r);
+        void scrollBy(int dy);
+    }
+
+    /**
+     * Provides functionality for BandSelectModel. In practice, use RuntimeRecyclerViewHelper;
+     * this interface exists only for mocking in tests.
+     */
+    interface BandModelHelper {
+        void addOnScrollListener(RecyclerView.OnScrollListener listener);
+        Point createAbsolutePoint(Point relativePoint);
+        Rect getAbsoluteRectForChildViewAt(int index);
+        int getAdapterPositionAt(int index);
+        int getNumColumns();
+        int getNumRows();
+        int getTotalChildCount();
+        int getVisibleChildCount();
+        void removeOnScrollListener(RecyclerView.OnScrollListener listener);
+    }
+
+    /**
+     * Concrete RecyclerViewHelper implementation for use within the Files app.
+     */
+    private static final class RuntimeRecyclerViewHelper implements MultiSelectHelper,
+            BandManagerHelper, BandModelHelper {
+
+        private final RecyclerView mRecyclerView;
+        private final Drawable mBandSelectRect;
+
+        private boolean mIsOverlayShown = false;
+
+        RuntimeRecyclerViewHelper(RecyclerView rv) {
+            mRecyclerView = rv;
+            mBandSelectRect = mRecyclerView.getContext().getTheme().getDrawable(
+                    R.drawable.band_select_overlay);
+        }
+
+        @Override
+        public int getAdapterPositionAt(int index) {
+            View child = mRecyclerView.getChildAt(index);
+            return mRecyclerView.getChildViewHolder(child).getAdapterPosition();
+        }
+
+        @Override
+        public void addOnScrollListener(OnScrollListener listener) {
+            mRecyclerView.addOnScrollListener(listener);
+        }
+
+        @Override
+        public void removeOnScrollListener(OnScrollListener listener) {
+            mRecyclerView.removeOnScrollListener(listener);
+        }
+
+        @Override
+        public Point createAbsolutePoint(Point relativePoint) {
+            return new Point(relativePoint.x + mRecyclerView.computeHorizontalScrollOffset(),
+                    relativePoint.y + mRecyclerView.computeVerticalScrollOffset());
+        }
+
+        @Override
+        public Rect getAbsoluteRectForChildViewAt(int index) {
+            final View child = mRecyclerView.getChildAt(index);
+            final Rect childRect = new Rect();
+            child.getHitRect(childRect);
+            childRect.left += mRecyclerView.computeHorizontalScrollOffset();
+            childRect.right += mRecyclerView.computeHorizontalScrollOffset();
+            childRect.top += mRecyclerView.computeVerticalScrollOffset();
+            childRect.bottom += mRecyclerView.computeVerticalScrollOffset();
+            return childRect;
+        }
+
+        @Override
+        public int getVisibleChildCount() {
+            return mRecyclerView.getChildCount();
+        }
+
+        @Override
+        public int getTotalChildCount() {
+            return mRecyclerView.getAdapter().getItemCount();
+        }
+
+        @Override
+        public int getNumColumns() {
+            LayoutManager layoutManager = mRecyclerView.getLayoutManager();
+            if (layoutManager instanceof GridLayoutManager) {
+                return ((GridLayoutManager) layoutManager).getSpanCount();
+            }
+
+            // Otherwise, it is a list with 1 column.
+            return 1;
+        }
+
+        @Override
+        public int getNumRows() {
+            int numFullColumns = getTotalChildCount() / getNumColumns();
+            boolean hasPartiallyFullColumn = getTotalChildCount() % getNumColumns() != 0;
+            return numFullColumns + (hasPartiallyFullColumn ? 1 : 0);
+        }
+
+        @Override
+        public int findEventPosition(MotionEvent e) {
+            View view = mRecyclerView.findChildViewUnder(e.getX(), e.getY());
+            return view != null
+                    ? mRecyclerView.getChildAdapterPosition(view)
+                    : RecyclerView.NO_POSITION;
+        }
+
+        @Override
+        public int getHeight() {
+            return mRecyclerView.getHeight();
+        }
+
+        @Override
+        public void invalidateView() {
+            mRecyclerView.invalidate();
+        }
+
+        @Override
+        public void postRunnable(Runnable r) {
+            mRecyclerView.postOnAnimation(r);
+        }
+
+        @Override
+        public void removeCallback(Runnable r) {
+            mRecyclerView.removeCallbacks(r);
+        }
+
+        @Override
+        public void scrollBy(int dy) {
+            mRecyclerView.scrollBy(0, dy);
+        }
+
+        @Override
+        public void drawBand(Rect rect) {
+            mBandSelectRect.setBounds(rect);
+
+            if (!mIsOverlayShown) {
+                mRecyclerView.getOverlay().add(mBandSelectRect);
+            }
+        }
+
+        @Override
+        public void hideBand() {
+            mRecyclerView.getOverlay().remove(mBandSelectRect);
+        }
+    }
+
     public interface Callback {
         /**
          * Called when an item is selected or unselected while in selection mode.
@@ -893,4 +1159,846 @@
             return false;
         }
     }
+
+    /**
+     * Provides mouse driven band-select support when used in conjunction with {@link RecyclerView}
+     * and {@link MultiSelectManager}. This class is responsible for rendering the band select
+     * overlay and selecting overlaid items via MultiSelectManager.
+     */
+    public class BandSelectManager extends RecyclerView.OnScrollListener
+            implements BandSelectModel.OnSelectionChangedListener {
+
+        private static final int NOT_SET = -1;
+
+        private final BandManagerHelper mHelper;
+
+        private boolean mIsActive;
+        private Point mOrigin;
+        private Point mPointer;
+        private Rect mBounds;
+        private BandSelectModel mModel;
+
+        // The time at which the current band selection-induced scroll began. If no scroll is in
+        // progress, the value is NOT_SET.
+        private long mScrollStartTime = NOT_SET;
+        private final Runnable mViewScroller = new ViewScroller();
+
+        public <T extends BandManagerHelper & BandModelHelper>
+                BandSelectManager(T helper) {
+            mHelper = helper;
+            mHelper.addOnScrollListener(this);
+            mModel = new BandSelectModel(helper);
+            mModel.addOnSelectionChangedListener(this);
+        }
+
+        /**
+         * Processes a MotionEvent by starting, ending, or resizing the band select overlay.
+         * @param e
+         */
+        private void processMotionEvent(MotionEvent e) {
+            if (!isMouseEvent(e)) {
+                return;
+            }
+
+            if (mIsActive && e.getActionMasked() == MotionEvent.ACTION_UP) {
+                endBandSelect();
+                return;
+            }
+
+            mPointer = new Point((int) e.getX(), (int) e.getY());
+            if (!mIsActive) {
+                // Only start a band select if the pointer is in margins between items, not
+                // actually within an item's bounds.
+                if (mHelper.findEventPosition(e) != RecyclerView.NO_POSITION) {
+                    return;
+                }
+                startBandSelect();
+            } else {
+                mModel.resizeSelection(mPointer);
+            }
+
+            scrollViewIfNecessary();
+            resizeBandSelectRectangle();
+        }
+
+        /**
+         * Starts band select by adding the drawable to the RecyclerView's overlay.
+         */
+        private void startBandSelect() {
+            if (DEBUG) {
+                Log.d(TAG, "Starting band select from (" + mPointer.x + "," + mPointer.y + ").");
+            }
+            mIsActive = true;
+            mOrigin = new Point(mPointer.x, mPointer.y);
+            mModel.startSelection(mOrigin);
+        }
+
+        /**
+         * Scrolls the view if necessary.
+         */
+        private void scrollViewIfNecessary() {
+            mHelper.removeCallback(mViewScroller);
+            mViewScroller.run();
+            mHelper.invalidateView();
+        }
+
+        /**
+         * Resizes the band select rectangle by using the origin and the current pointer position as
+         * two opposite corners of the selection.
+         */
+        private void resizeBandSelectRectangle() {
+            mBounds = new Rect(Math.min(mOrigin.x, mPointer.x),
+                    Math.min(mOrigin.y, mPointer.y),
+                    Math.max(mOrigin.x, mPointer.x),
+                    Math.max(mOrigin.y, mPointer.y));
+            mHelper.drawBand(mBounds);
+        }
+
+        /**
+         * Ends band select by removing the overlay.
+         */
+        private void endBandSelect() {
+            if (DEBUG) Log.d(TAG, "Ending band select.");
+            mIsActive = false;
+            mHelper.hideBand();
+            mSelection.applyProvisionalSelection();
+            mModel.endSelection();
+            int firstSelected = mModel.getPositionNearestOrigin();
+            if (firstSelected != BandSelectModel.NOT_SET) {
+                setSelectionFocusBegin(firstSelected);
+            }
+        }
+
+        @Override
+        public void onSelectionChanged(SparseBooleanArray updatedSelection) {
+            SparseBooleanArray delta = mSelection.setProvisionalSelection(updatedSelection);
+            for (int i = 0; i < delta.size(); i++) {
+                int position = delta.keyAt(i);
+                notifyItemStateChanged(position, delta.get(position));
+            }
+            notifySelectionChanged();
+        }
+
+        private class ViewScroller implements Runnable {
+            /**
+             * The number of milliseconds of scrolling at which scroll speed continues to increase.
+             * At first, the scroll starts slowly; then, the rate of scrolling increases until it
+             * reaches its maximum value at after this many milliseconds.
+             */
+            private static final long SCROLL_ACCELERATION_LIMIT_TIME_MS = 2000;
+
+            @Override
+            public void run() {
+                // Compute the number of pixels the pointer's y-coordinate is past the view.
+                // Negative values mean the pointer is at or before the top of the view, and
+                // positive values mean that the pointer is at or after the bottom of the view. Note
+                // that one additional pixel is added here so that the view still scrolls when the
+                // pointer is exactly at the top or bottom.
+                int pixelsPastView = 0;
+                if (mPointer.y <= 0) {
+                    pixelsPastView = mPointer.y - 1;
+                } else if (mPointer.y >= mHelper.getHeight() - 1) {
+                    pixelsPastView = mPointer.y - mHelper.getHeight() + 1;
+                }
+
+                if (!mIsActive || pixelsPastView == 0) {
+                    // If band selection is inactive, or if it is active but not at the edge of the
+                    // view, no scrolling is necessary.
+                    mScrollStartTime = NOT_SET;
+                    return;
+                }
+
+                if (mScrollStartTime == NOT_SET) {
+                    // If the pointer was previously not at the edge of the view but now is, set the
+                    // start time for the scroll.
+                    mScrollStartTime = System.currentTimeMillis();
+                }
+
+                // Compute the number of pixels to scroll, and scroll that many pixels.
+                final int numPixels = computeScrollDistance(
+                        pixelsPastView, System.currentTimeMillis() - mScrollStartTime);
+                mHelper.scrollBy(numPixels);
+
+                mHelper.removeCallback(mViewScroller);
+                mHelper.postRunnable(this);
+            }
+
+            /**
+             * Computes the number of pixels to scroll based on how far the pointer is past the end
+             * of the view and how long it has been there. Roughly based on ItemTouchHelper's
+             * algorithm for computing the number of pixels to scroll when an item is dragged to the
+             * end of a {@link RecyclerView}.
+             * @param pixelsPastView
+             * @param scrollDuration
+             * @return
+             */
+            private int computeScrollDistance(int pixelsPastView, long scrollDuration) {
+                final int maxScrollStep = mHelper.getHeight();
+                final int direction = (int) Math.signum(pixelsPastView);
+                final int absPastView = Math.abs(pixelsPastView);
+
+                // Calculate the ratio of how far out of the view the pointer currently resides to
+                // the entire height of the view.
+                final float outOfBoundsRatio = Math.min(
+                        1.0f, (float) absPastView / mHelper.getHeight());
+                // Interpolate this ratio and use it to compute the maximum scroll that should be
+                // possible for this step.
+                final float cappedScrollStep =
+                        direction * maxScrollStep * smoothOutOfBoundsRatio(outOfBoundsRatio);
+
+                // Likewise, calculate the ratio of the time spent in the scroll to the limit.
+                final float timeRatio = Math.min(
+                        1.0f, (float) scrollDuration / SCROLL_ACCELERATION_LIMIT_TIME_MS);
+                // Interpolate this ratio and use it to compute the final number of pixels to
+                // scroll.
+                final int numPixels = (int) (cappedScrollStep * smoothTimeRatio(timeRatio));
+
+                // If the final number of pixels to scroll ends up being 0, the view should still
+                // scroll at least one pixel.
+                return numPixels != 0 ? numPixels : direction;
+            }
+
+            /**
+             * Interpolates the given out of bounds ratio on a curve which starts at (0,0) and ends
+             * at (1,1) and quickly approaches 1 near the start of that interval. This ensures that
+             * drags that are at the edge or barely past the edge of the view still cause sufficient
+             * scrolling. The equation y=(x-1)^5+1 is used, but this could also be tweaked if
+             * needed.
+             * @param ratio A ratio which is in the range [0, 1].
+             * @return A "smoothed" value, also in the range [0, 1].
+             */
+            private float smoothOutOfBoundsRatio(float ratio) {
+                return (float) Math.pow(ratio - 1.0f, 5) + 1.0f;
+            }
+
+            /**
+             * Interpolates the given time ratio on a curve which starts at (0,0) and ends at (1,1)
+             * and stays close to 0 for most input values except those very close to 1. This ensures
+             * that scrolls start out very slowly but speed up drastically after the scroll has been
+             * in progress close to SCROLL_ACCELERATION_LIMIT_TIME_MS. The equation y=x^5 is used,
+             * but this could also be tweaked if needed.
+             * @param ratio A ratio which is in the range [0, 1].
+             * @return A "smoothed" value, also in the range [0, 1].
+             */
+            private float smoothTimeRatio(float ratio) {
+                return (float) Math.pow(ratio, 5);
+            }
+        };
+
+        @Override
+        public void onScrolled(RecyclerView recyclerView, int dx, int dy) {
+            if (!mIsActive) {
+                return;
+            }
+
+            // Adjust the y-coordinate of the origin the opposite number of pixels so that the
+            // origin remains in the same place relative to the view's items.
+            mOrigin.y -= dy;
+            resizeBandSelectRectangle();
+        }
+    }
+
+    /**
+     * Provides a band selection item model for views within a RecyclerView. This class queries the
+     * RecyclerView to determine where its items are placed; then, once band selection is underway,
+     * it alerts listeners of which items are covered by the selections.
+     */
+    public static final class BandSelectModel extends RecyclerView.OnScrollListener {
+
+        public static final int NOT_SET = -1;
+
+        // Enum values used to determine the corner at which the origin is located within the
+        private static final int UPPER = 0x00;
+        private static final int LOWER = 0x01;
+        private static final int LEFT = 0x00;
+        private static final int RIGHT = 0x02;
+        private static final int UPPER_LEFT = UPPER | LEFT;
+        private static final int UPPER_RIGHT = UPPER | RIGHT;
+        private static final int LOWER_LEFT = LOWER | LEFT;
+        private static final int LOWER_RIGHT = LOWER | RIGHT;
+
+        private final BandModelHelper mHelper;
+        private final List<OnSelectionChangedListener> mOnSelectionChangedListeners = new ArrayList<>();
+
+        // Map from the x-value of the left side of a SparseBooleanArray of adapter positions, keyed
+        // by their y-offset. For example, if the first column of the view starts at an x-value of 5,
+        // mColumns.get(5) would return an array of positions in that column. Within that array, the
+        // value for key y is the adapter position for the item whose y-offset is y.
+        private final SparseArray<SparseIntArray> mColumns = new SparseArray<>();
+
+        // List of limits along the x-axis. For example, if the view has two columns, this list will
+        // have two elements, each of which lists the lower- and upper-limits of the x-values of the
+        // view items. This list is sorted from furthest left to furthest right.
+        private final List<Limits> mXLimitsList = new ArrayList<>();
+
+        // Like mXLimitsList, but for y-coordinates. Note that this list only contains items which
+        // have been in the viewport. Thus, limits which exist in an area of the view to which the
+        // view has not scrolled are not present in the list.
+        private final List<Limits> mYLimitsList = new ArrayList<>();
+
+        // The adapter positions which have been recorded so far.
+        private final SparseBooleanArray mKnownPositions = new SparseBooleanArray();
+
+        // Array passed to registered OnSelectionChangedListeners. One array is created and reused
+        // throughout the lifetime of the object.
+        private final SparseBooleanArray mSelection = new SparseBooleanArray();
+
+        // The current pointer (in absolute positioning from the top of the view).
+        private Point mPointer = null;
+
+        // The bounds of the band selection.
+        private RelativePoint mRelativeOrigin;
+        private RelativePoint mRelativePointer;
+
+        private boolean mIsActive;
+
+        // Tracks where the band select originated from. This is used to determine where selections
+        // should expand from when Shift+click is used.
+        private int mPositionNearestOrigin = NOT_SET;
+
+        BandSelectModel(BandModelHelper helper) {
+            mHelper = helper;
+            mHelper.addOnScrollListener(this);
+        }
+
+        /**
+         * Stops listening to the view's scrolls. Call this function before discarding a
+         * BandSelecModel object to prevent memory leaks.
+         */
+        void stopListening() {
+            mHelper.removeOnScrollListener(this);
+        }
+
+        /**
+         * Start a band select operation at the given point.
+         * @param relativeOrigin The origin of the band select operation, relative to the viewport.
+         *     For example, if the view is scrolled to the bottom, the top-left of the viewport
+         *     would have a relative origin of (0, 0), even though its absolute point has a higher
+         *     y-value.
+         */
+        void startSelection(Point relativeOrigin) {
+            mIsActive = true;
+            mPointer = mHelper.createAbsolutePoint(relativeOrigin);
+
+            recordVisibleChildren();
+            mRelativeOrigin = new RelativePoint(mPointer);
+            mRelativePointer = new RelativePoint(mPointer);
+            computeCurrentSelection();
+            notifyListeners();
+        }
+
+        /**
+         * Resizes the selection by adjusting the pointer (i.e., the corner of the selection
+         * opposite the origin.
+         * @param relativePointer The pointer (opposite of the origin) of the band select operation,
+         *     relative to the viewport. For example, if the view is scrolled to the bottom, the
+         *     top-left of the viewport would have a relative origin of (0, 0), even though its
+         *     absolute point has a higher y-value.
+         */
+        void resizeSelection(Point relativePointer) {
+            mPointer = mHelper.createAbsolutePoint(relativePointer);
+            updateModel();
+        }
+
+        /**
+         * Ends the band selection.
+         */
+        void endSelection() {
+            mIsActive = false;
+        }
+
+        /**
+         * @return The adapter position for the item nearest the origin corresponding to the latest
+         *         band select operation, or NOT_SET if the selection did not cover any items.
+         */
+        int getPositionNearestOrigin() {
+            return mPositionNearestOrigin;
+        }
+
+        @Override
+        public void onScrolled(RecyclerView recyclerView, int dx, int dy) {
+            if (!mIsActive) {
+                return;
+            }
+
+            mPointer.x += dx;
+            mPointer.y += dy;
+            recordVisibleChildren();
+            updateModel();
+        }
+
+        /**
+         * Queries the view for all children and records their location metadata.
+         */
+        private void recordVisibleChildren() {
+            for (int i = 0; i < mHelper.getVisibleChildCount(); i++) {
+                int adapterPosition = mHelper.getAdapterPositionAt(i);
+                if (!mKnownPositions.get(adapterPosition)) {
+                    mKnownPositions.put(adapterPosition, true);
+                    recordItemData(
+                            mHelper.getAbsoluteRectForChildViewAt(i), adapterPosition);
+                }
+            }
+        }
+
+        /**
+         * Updates the limits lists and column map with the given item metadata.
+         * @param absoluteChildRect The absolute rectangle for the child view being processed.
+         * @param adapterPosition The position of the child view being processed.
+         */
+        private void recordItemData(Rect absoluteChildRect, int adapterPosition) {
+            if (mXLimitsList.size() != mHelper.getNumColumns()) {
+                // If not all x-limits have been recorded, record this one.
+                recordLimits(
+                        mXLimitsList, new Limits(absoluteChildRect.left, absoluteChildRect.right));
+            }
+
+            if (mYLimitsList.size() != mHelper.getNumRows()) {
+                // If not all y-limits have been recorded, record this one.
+                recordLimits(
+                        mYLimitsList, new Limits(absoluteChildRect.top, absoluteChildRect.bottom));
+            }
+
+            SparseIntArray columnList = mColumns.get(absoluteChildRect.left);
+            if (columnList == null) {
+                columnList = new SparseIntArray();
+                mColumns.put(absoluteChildRect.left, columnList);
+            }
+            columnList.put(absoluteChildRect.top, adapterPosition);
+        }
+
+        /**
+         * Ensures limits exists within the sorted list limitsList, and adds it to the list if it
+         * does not exist.
+         */
+        private void recordLimits(List<Limits> limitsList, Limits limits) {
+            int index = Collections.binarySearch(limitsList, limits);
+            if (index < 0) {
+                limitsList.add(~index, limits);
+            }
+        }
+
+        /**
+         * Handles a moved pointer; this function determines whether the pointer movement resulted
+         * in a selection change and, if it has, notifies listeners of this change.
+         */
+        private void updateModel() {
+            RelativePoint old = mRelativePointer;
+            mRelativePointer = new RelativePoint(mPointer);
+            if (old != null && mRelativePointer.equals(old)) {
+                return;
+            }
+
+            computeCurrentSelection();
+            notifyListeners();
+        }
+
+        /**
+         * Computes the currently-selected items.
+         */
+        private void computeCurrentSelection() {
+            if (areItemsCoveredBySelection(mRelativePointer, mRelativeOrigin)) {
+                updateSelection(computeBounds());
+            } else {
+                mSelection.clear();
+                mPositionNearestOrigin = NOT_SET;
+            }
+        }
+
+        /**
+         * Notifies all listeners of a selection change. Note that this function simply passes
+         * mSelection, so computeCurrentSelection() should be called before this
+         * function.
+         */
+        private void notifyListeners() {
+            for (OnSelectionChangedListener listener : mOnSelectionChangedListeners) {
+                listener.onSelectionChanged(mSelection);
+            }
+        }
+
+        /**
+         * @param rect Rectangle including all covered items.
+         */
+        private void updateSelection(Rect rect) {
+            int columnStartIndex =
+                    Collections.binarySearch(mXLimitsList, new Limits(rect.left, rect.left));
+            checkState(columnStartIndex >= 0);
+            int columnEndIndex = columnStartIndex;
+
+            for (int i = columnStartIndex;
+                    i < mXLimitsList.size() && mXLimitsList.get(i).lowerLimit <= rect.right; i++) {
+                columnEndIndex = i;
+            }
+
+            SparseIntArray firstColumn =
+                    mColumns.get(mXLimitsList.get(columnStartIndex).lowerLimit);
+            int rowStartIndex = firstColumn.indexOfKey(rect.top);
+            if (rowStartIndex < 0) {
+                mPositionNearestOrigin = NOT_SET;
+                return;
+            }
+
+            int rowEndIndex = rowStartIndex;
+            for (int i = rowStartIndex;
+                    i < firstColumn.size() && firstColumn.keyAt(i) <= rect.bottom; i++) {
+                rowEndIndex = i;
+            }
+
+            updateSelection(columnStartIndex, columnEndIndex, rowStartIndex, rowEndIndex);
+        }
+
+        /**
+         * Computes the selection given the previously-computed start- and end-indices for each
+         * row and column.
+         */
+        private void updateSelection(
+                int columnStartIndex, int columnEndIndex, int rowStartIndex, int rowEndIndex) {
+            mSelection.clear();
+            for (int column = columnStartIndex; column <= columnEndIndex; column++) {
+                SparseIntArray items = mColumns.get(mXLimitsList.get(column).lowerLimit);
+                for (int row = rowStartIndex; row <= rowEndIndex; row++) {
+                    int position = items.get(items.keyAt(row));
+                    mSelection.append(position, true);
+                    if (isPossiblePositionNearestOrigin(column, columnStartIndex, columnEndIndex,
+                            row, rowStartIndex, rowEndIndex)) {
+                        // If this is the position nearest the origin, record it now so that it
+                        // can be returned by endSelection() later.
+                        mPositionNearestOrigin = position;
+                    }
+                }
+            }
+        }
+
+        /**
+         * @return Returns true if the position is the nearest to the origin, or, in the case of the
+         *     lower-right corner, whether it is possible that the position is the nearest to the
+         *     origin. See comment below for reasoning for this special case.
+         */
+        private boolean isPossiblePositionNearestOrigin(int columnIndex, int columnStartIndex,
+                int columnEndIndex, int rowIndex, int rowStartIndex, int rowEndIndex) {
+            int corner = computeCornerNearestOrigin();
+            switch (corner) {
+                case UPPER_LEFT:
+                    return columnIndex == columnStartIndex && rowIndex == rowStartIndex;
+                case UPPER_RIGHT:
+                    return columnIndex == columnEndIndex && rowIndex == rowStartIndex;
+                case LOWER_LEFT:
+                    return columnIndex == columnStartIndex && rowIndex == rowEndIndex;
+                case LOWER_RIGHT:
+                    // Note that in some cases, the last row will not have as many items as there
+                    // are columns (e.g., if there are 4 items and 3 columns, the second row will
+                    // only have one item in the first column). This function is invoked for each
+                    // position from left to right, so return true for any position in the bottom
+                    // row and only the right-most position in the bottom row will be recorded.
+                    return rowIndex == rowEndIndex;
+                default:
+                    throw new RuntimeException("Invalid corner type.");
+            }
+        }
+
+        /**
+         * Listener for changes in which items have been band selected.
+         */
+        static interface OnSelectionChangedListener {
+            public void onSelectionChanged(SparseBooleanArray updatedSelection);
+        }
+
+        void addOnSelectionChangedListener(OnSelectionChangedListener listener) {
+            mOnSelectionChangedListeners.add(listener);
+        }
+
+        void removeOnSelectionChangedListener(OnSelectionChangedListener listener) {
+            mOnSelectionChangedListeners.remove(listener);
+        }
+
+        /**
+         * Limits of a view item. For example, if an item's left side is at x-value 5 and its right side
+         * is at x-value 10, the limits would be from 5 to 10. Used to record the left- and right sides
+         * of item columns and the top- and bottom sides of item rows so that it can be determined
+         * whether the pointer is located within the bounds of an item.
+         */
+        private class Limits implements Comparable<Limits> {
+            int lowerLimit;
+            int upperLimit;
+
+            Limits(int lowerLimit, int upperLimit) {
+                this.lowerLimit = lowerLimit;
+                this.upperLimit = upperLimit;
+            }
+
+            @Override
+            public int compareTo(Limits other) {
+                return lowerLimit - other.lowerLimit;
+            }
+
+            @Override
+            public boolean equals(Object other) {
+                if (!(other instanceof Limits)) {
+                    return false;
+                }
+
+                return ((Limits) other).lowerLimit == lowerLimit &&
+                        ((Limits) other).upperLimit == upperLimit;
+            }
+        }
+
+        /**
+         * The location of a coordinate relative to items. This class represents a general area of the
+         * view as it relates to band selection rather than an explicit point. For example, two
+         * different points within an item are considered to have the same "location" because band
+         * selection originating within the item would select the same items no matter which point
+         * was used. Same goes for points between items as well as those at the very beginning or end
+         * of the view.
+         *
+         * Tracking a coordinate (e.g., an x-value) as a CoordinateLocation instead of as an int has the
+         * advantage of tying the value to the Limits of items along that axis. This allows easy
+         * selection of items within those Limits as opposed to a search through every item to see if a
+         * given coordinate value falls within those Limits.
+         */
+        private class RelativeCoordinate
+                implements Comparable<RelativeCoordinate> {
+            /**
+             * Location describing points after the last known item.
+             */
+            static final int AFTER_LAST_ITEM = 0;
+
+            /**
+             * Location describing points before the first known item.
+             */
+            static final int BEFORE_FIRST_ITEM = 1;
+
+            /**
+             * Location describing points between two items.
+             */
+            static final int BETWEEN_TWO_ITEMS = 2;
+
+            /**
+             * Location describing points within the limits of one item.
+             */
+            static final int WITHIN_LIMITS = 3;
+
+            /**
+             * The type of this coordinate, which is one of AFTER_LAST_ITEM, BEFORE_FIRST_ITEM,
+             * BETWEEN_TWO_ITEMS, or WITHIN_LIMITS.
+             */
+            final int type;
+
+            /**
+             * The limits before the coordinate; only populated when type == WITHIN_LIMITS or type ==
+             * BETWEEN_TWO_ITEMS.
+             */
+            Limits limitsBeforeCoordinate;
+
+            /**
+             * The limits after the coordinate; only populated when type == BETWEEN_TWO_ITEMS.
+             */
+            Limits limitsAfterCoordinate;
+
+            // Limits of the first known item; only populated when type == BEFORE_FIRST_ITEM.
+            Limits mFirstKnownItem;
+            // Limits of the last known item; only populated when type == AFTER_LAST_ITEM.
+            Limits mLastKnownItem;
+
+            /**
+             * @param limitsList The sorted limits list for the coordinate type. If this
+             *     CoordinateLocation is an x-value, mXLimitsList should be passed; otherwise,
+             *     mYLimitsList should be pased.
+             * @param value The coordinate value.
+             */
+            RelativeCoordinate(List<Limits> limitsList, int value) {
+                Limits dummyLimits = new Limits(value, value);
+                int index = Collections.binarySearch(limitsList, dummyLimits);
+
+                if (index >= 0) {
+                    this.type = WITHIN_LIMITS;
+                    this.limitsBeforeCoordinate = limitsList.get(index);
+                } else if (~index == 0) {
+                    this.type = BEFORE_FIRST_ITEM;
+                    this.mFirstKnownItem = limitsList.get(0);
+                } else if (~index == limitsList.size()) {
+                    Limits lastLimits = limitsList.get(limitsList.size() - 1);
+                    if (lastLimits.lowerLimit <= value && value <= lastLimits.upperLimit) {
+                        this.type = WITHIN_LIMITS;
+                        this.limitsBeforeCoordinate = lastLimits;
+                    } else {
+                        this.type = AFTER_LAST_ITEM;
+                        this.mLastKnownItem = lastLimits;
+                    }
+                } else {
+                    Limits limitsBeforeIndex = limitsList.get(~index - 1);
+                    if (limitsBeforeIndex.lowerLimit <= value && value <= limitsBeforeIndex.upperLimit) {
+                        this.type = WITHIN_LIMITS;
+                        this.limitsBeforeCoordinate = limitsList.get(~index - 1);
+                    } else {
+                        this.type = BETWEEN_TWO_ITEMS;
+                        this.limitsBeforeCoordinate = limitsList.get(~index - 1);
+                        this.limitsAfterCoordinate = limitsList.get(~index);
+                    }
+                }
+            }
+
+            int toComparisonValue() {
+                if (type == BEFORE_FIRST_ITEM) {
+                    return mFirstKnownItem.lowerLimit - 1;
+                } else if (type == AFTER_LAST_ITEM) {
+                    return mLastKnownItem.upperLimit + 1;
+                } else if (type == BETWEEN_TWO_ITEMS) {
+                    return limitsBeforeCoordinate.upperLimit + 1;
+                } else {
+                    return limitsBeforeCoordinate.lowerLimit;
+                }
+            }
+
+            @Override
+            public boolean equals(Object other) {
+                if (!(other instanceof RelativeCoordinate)) {
+                    return false;
+                }
+
+                RelativeCoordinate otherCoordinate = (RelativeCoordinate) other;
+                return toComparisonValue() == otherCoordinate.toComparisonValue();
+            }
+
+            @Override
+            public int compareTo(RelativeCoordinate other) {
+                return toComparisonValue() - other.toComparisonValue();
+            }
+        }
+
+        /**
+         * The location of a point relative to the Limits of nearby items; consists of both an x- and
+         * y-RelativeCoordinateLocation.
+         */
+        private class RelativePoint {
+            final RelativeCoordinate xLocation;
+            final RelativeCoordinate yLocation;
+
+            RelativePoint(Point point) {
+                this.xLocation = new RelativeCoordinate(mXLimitsList, point.x);
+                this.yLocation = new RelativeCoordinate(mYLimitsList, point.y);
+            }
+
+            @Override
+            public boolean equals(Object other) {
+                if (!(other instanceof RelativePoint)) {
+                    return false;
+                }
+
+                RelativePoint otherPoint = (RelativePoint) other;
+                return xLocation.equals(otherPoint.xLocation) && yLocation.equals(otherPoint.yLocation);
+            }
+        }
+
+        /**
+         * Generates a rectangle which contains the items selected by the pointer and origin.
+         * @return The rectangle, or null if no items were selected.
+         */
+        private Rect computeBounds() {
+            Rect rect = new Rect();
+            rect.left = getCoordinateValue(
+                    min(mRelativeOrigin.xLocation, mRelativePointer.xLocation),
+                    mXLimitsList,
+                    true);
+            rect.right = getCoordinateValue(
+                    max(mRelativeOrigin.xLocation, mRelativePointer.xLocation),
+                    mXLimitsList,
+                    false);
+            rect.top = getCoordinateValue(
+                    min(mRelativeOrigin.yLocation, mRelativePointer.yLocation),
+                    mYLimitsList,
+                    true);
+            rect.bottom = getCoordinateValue(
+                    max(mRelativeOrigin.yLocation, mRelativePointer.yLocation),
+                    mYLimitsList,
+                    false);
+            return rect;
+        }
+
+        /**
+         * Computes the corner of the selection nearest the origin.
+         * @return
+         */
+        private int computeCornerNearestOrigin() {
+            int cornerValue = 0;
+
+            if (mRelativeOrigin.yLocation ==
+                    min(mRelativeOrigin.yLocation, mRelativePointer.yLocation)) {
+                cornerValue |= UPPER;
+            } else {
+                cornerValue |= LOWER;
+            }
+
+            if (mRelativeOrigin.xLocation ==
+                    min(mRelativeOrigin.xLocation, mRelativePointer.xLocation)) {
+                cornerValue |= LEFT;
+            } else {
+                cornerValue |= RIGHT;
+            }
+
+            return cornerValue;
+        }
+
+        private RelativeCoordinate min(RelativeCoordinate first, RelativeCoordinate second) {
+            return first.compareTo(second) < 0 ? first : second;
+        }
+
+        private RelativeCoordinate max(RelativeCoordinate first, RelativeCoordinate second) {
+            return first.compareTo(second) > 0 ? first : second;
+        }
+
+        /**
+         * @return The absolute coordinate (i.e., the x- or y-value) of the given relative
+         *     coordinate.
+         */
+        private int getCoordinateValue(RelativeCoordinate coordinate,
+                List<Limits> limitsList, boolean isStartOfRange) {
+            switch (coordinate.type) {
+                case RelativeCoordinate.BEFORE_FIRST_ITEM:
+                    return limitsList.get(0).lowerLimit;
+                case RelativeCoordinate.AFTER_LAST_ITEM:
+                    return limitsList.get(limitsList.size() - 1).upperLimit;
+                case RelativeCoordinate.BETWEEN_TWO_ITEMS:
+                    if (isStartOfRange) {
+                        return coordinate.limitsAfterCoordinate.lowerLimit;
+                    } else {
+                        return coordinate.limitsBeforeCoordinate.upperLimit;
+                    }
+                case RelativeCoordinate.WITHIN_LIMITS:
+                    return coordinate.limitsBeforeCoordinate.lowerLimit;
+            }
+
+            throw new RuntimeException("Invalid coordinate value.");
+        }
+
+        private boolean areItemsCoveredBySelection(
+                RelativePoint first, RelativePoint second) {
+            return doesCoordinateLocationCoverItems(first.xLocation, second.xLocation) &&
+                    doesCoordinateLocationCoverItems(first.yLocation, second.yLocation);
+        }
+
+        private boolean doesCoordinateLocationCoverItems(
+                RelativeCoordinate pointerCoordinate,
+                RelativeCoordinate originCoordinate) {
+            if (pointerCoordinate.type == RelativeCoordinate.BEFORE_FIRST_ITEM &&
+                    originCoordinate.type == RelativeCoordinate.BEFORE_FIRST_ITEM) {
+                return false;
+            }
+
+            if (pointerCoordinate.type == RelativeCoordinate.AFTER_LAST_ITEM &&
+                    originCoordinate.type == RelativeCoordinate.AFTER_LAST_ITEM) {
+                return false;
+            }
+
+            if (pointerCoordinate.type == RelativeCoordinate.BETWEEN_TWO_ITEMS &&
+                    originCoordinate.type == RelativeCoordinate.BETWEEN_TWO_ITEMS &&
+                    pointerCoordinate.limitsBeforeCoordinate.equals(
+                            originCoordinate.limitsBeforeCoordinate) &&
+                    pointerCoordinate.limitsAfterCoordinate.equals(
+                            originCoordinate.limitsAfterCoordinate)) {
+                return false;
+            }
+
+            return true;
+        }
+    }
 }
diff --git a/packages/DocumentsUI/tests/src/com/android/documentsui/BandSelectMatrixTest.java b/packages/DocumentsUI/tests/src/com/android/documentsui/BandSelectModelTest.java
similarity index 71%
rename from packages/DocumentsUI/tests/src/com/android/documentsui/BandSelectMatrixTest.java
rename to packages/DocumentsUI/tests/src/com/android/documentsui/BandSelectModelTest.java
index f15a643..20c4548 100644
--- a/packages/DocumentsUI/tests/src/com/android/documentsui/BandSelectMatrixTest.java
+++ b/packages/DocumentsUI/tests/src/com/android/documentsui/BandSelectModelTest.java
@@ -18,7 +18,7 @@
 
 import static org.junit.Assert.*;
 
-import com.android.documentsui.BandSelectMatrix;
+import com.android.documentsui.MultiSelectManager.BandSelectModel;
 
 import android.graphics.Point;
 import android.graphics.Rect;
@@ -28,13 +28,13 @@
 import org.junit.After;
 import org.junit.Test;
 
-public class BandSelectMatrixTest {
+public class BandSelectModelTest {
 
     private static final int VIEW_PADDING_PX = 5;
     private static final int CHILD_VIEW_EDGE_PX = 100;
     private static final int VIEWPORT_HEIGHT = 500;
 
-    private static BandSelectMatrix matrix;
+    private static BandSelectModel model;
     private static TestHelper helper;
     private static SparseBooleanArray lastSelection;
     private static int viewWidth;
@@ -42,8 +42,8 @@
     private static void setUp(int numChildren, int numColumns) {
         helper = new TestHelper(numChildren, numColumns);
         viewWidth = VIEW_PADDING_PX + numColumns * (VIEW_PADDING_PX + CHILD_VIEW_EDGE_PX);
-        matrix = new BandSelectMatrix(helper);
-        matrix.addOnSelectionChangedListener(new BandSelectMatrix.OnSelectionChangedListener() {
+        model = new BandSelectModel(helper);
+        model.addOnSelectionChangedListener(new BandSelectModel.OnSelectionChangedListener() {
 
             @Override
             public void onSelectionChanged(SparseBooleanArray updatedSelection) {
@@ -54,7 +54,7 @@
 
     @After
     public void tearDown() {
-        matrix = null;
+        model = null;
         helper = null;
         lastSelection = null;
     }
@@ -62,111 +62,120 @@
     @Test
     public void testSelectionLeftOfItems() {
         setUp(20, 5);
-        matrix.startSelection(new Point(0, 10));
-        matrix.resizeSelection(new Point(1, 11));
+        model.startSelection(new Point(0, 10));
+        model.resizeSelection(new Point(1, 11));
         assertSelected(new int[0]);
+        assertEquals(BandSelectModel.NOT_SET, model.getPositionNearestOrigin());
     }
 
     @Test
     public void testSelectionRightOfItems() {
         setUp(20, 4);
-        matrix.startSelection(new Point(viewWidth - 1, 10));
-        matrix.resizeSelection(new Point(viewWidth - 2, 11));
+        model.startSelection(new Point(viewWidth - 1, 10));
+        model.resizeSelection(new Point(viewWidth - 2, 11));
         assertSelected(new int[0]);
+        assertEquals(BandSelectModel.NOT_SET, model.getPositionNearestOrigin());
     }
 
     @Test
     public void testSelectionAboveItems() {
         setUp(20, 4);
-        matrix.startSelection(new Point(10, 0));
-        matrix.resizeSelection(new Point(11, 1));
+        model.startSelection(new Point(10, 0));
+        model.resizeSelection(new Point(11, 1));
         assertSelected(new int[0]);
+        assertEquals(BandSelectModel.NOT_SET, model.getPositionNearestOrigin());
     }
 
     @Test
     public void testSelectionBelowItems() {
         setUp(5, 4);
-        matrix.startSelection(new Point(10, VIEWPORT_HEIGHT - 1));
-        matrix.resizeSelection(new Point(11, VIEWPORT_HEIGHT - 2));
+        model.startSelection(new Point(10, VIEWPORT_HEIGHT - 1));
+        model.resizeSelection(new Point(11, VIEWPORT_HEIGHT - 2));
         assertSelected(new int[0]);
+        assertEquals(BandSelectModel.NOT_SET, model.getPositionNearestOrigin());
     }
 
     @Test
     public void testVerticalSelectionBetweenItems() {
         setUp(20, 4);
-        matrix.startSelection(new Point(106, 0));
-        matrix.resizeSelection(new Point(107, 200));
+        model.startSelection(new Point(106, 0));
+        model.resizeSelection(new Point(107, 200));
         assertSelected(new int[0]);
+        assertEquals(BandSelectModel.NOT_SET, model.getPositionNearestOrigin());
     }
 
     @Test
     public void testHorizontalSelectionBetweenItems() {
         setUp(20, 4);
-        matrix.startSelection(new Point(0, 105));
-        matrix.resizeSelection(new Point(200, 106));
+        model.startSelection(new Point(0, 105));
+        model.resizeSelection(new Point(200, 106));
         assertSelected(new int[0]);
+        assertEquals(BandSelectModel.NOT_SET, model.getPositionNearestOrigin());
     }
 
     @Test
     public void testGrowingAndShrinkingSelection() {
         setUp(20, 4);
-        matrix.startSelection(new Point(0, 0));
-        matrix.resizeSelection(new Point(5, 5));
+        model.startSelection(new Point(0, 0));
+        model.resizeSelection(new Point(5, 5));
         assertSelected(new int[] {0});
-        matrix.resizeSelection(new Point(109, 109));
+        model.resizeSelection(new Point(109, 109));
         assertSelected(new int[] {0});
-        matrix.resizeSelection(new Point(110, 109));
+        model.resizeSelection(new Point(110, 109));
         assertSelected(new int[] {0, 1});
-        matrix.resizeSelection(new Point(110, 110));
+        model.resizeSelection(new Point(110, 110));
         assertSelected(new int[] {0, 1, 4, 5});
-        matrix.resizeSelection(new Point(214, 214));
+        model.resizeSelection(new Point(214, 214));
         assertSelected(new int[] {0, 1, 4, 5});
-        matrix.resizeSelection(new Point(215, 214));
+        model.resizeSelection(new Point(215, 214));
         assertSelected(new int[] {0, 1, 2, 4, 5, 6});
-        matrix.resizeSelection(new Point(214, 214));
+        model.resizeSelection(new Point(214, 214));
         assertSelected(new int[] {0, 1, 4, 5});
-        matrix.resizeSelection(new Point(110, 110));
+        model.resizeSelection(new Point(110, 110));
         assertSelected(new int[] {0, 1, 4, 5});
-        matrix.resizeSelection(new Point(110, 109));
+        model.resizeSelection(new Point(110, 109));
         assertSelected(new int[] {0, 1});
-        matrix.resizeSelection(new Point(109, 109));
+        model.resizeSelection(new Point(109, 109));
         assertSelected(new int[] {0});
-        matrix.resizeSelection(new Point(5, 5));
+        model.resizeSelection(new Point(5, 5));
         assertSelected(new int[] {0});
-        matrix.resizeSelection(new Point(0, 0));
+        model.resizeSelection(new Point(0, 0));
         assertSelected(new int[0]);
+        assertEquals(BandSelectModel.NOT_SET, model.getPositionNearestOrigin());
     }
 
     @Test
     public void testSelectionMovingAroundOrigin() {
         setUp(16, 4);
-        matrix.startSelection(new Point(210, 210));
-        matrix.resizeSelection(new Point(viewWidth - 1, 0));
+        model.startSelection(new Point(210, 210));
+        model.resizeSelection(new Point(viewWidth - 1, 0));
         assertSelected(new int[] {2, 3, 6, 7});
-        matrix.resizeSelection(new Point(0, 0));
+        model.resizeSelection(new Point(0, 0));
         assertSelected(new int[] {0, 1, 4, 5});
-        matrix.resizeSelection(new Point(0, 420));
+        model.resizeSelection(new Point(0, 420));
         assertSelected(new int[] {8, 9, 12, 13});
-        matrix.resizeSelection(new Point(viewWidth - 1, 420));
+        model.resizeSelection(new Point(viewWidth - 1, 420));
         assertSelected(new int[] {10, 11, 14, 15});
+        assertEquals(10, model.getPositionNearestOrigin());
     }
 
     @Test
     public void testScrollingBandSelect() {
         setUp(40, 4);
-        matrix.startSelection(new Point(0, 0));
-        matrix.resizeSelection(new Point(100, VIEWPORT_HEIGHT - 1));
+        model.startSelection(new Point(0, 0));
+        model.resizeSelection(new Point(100, VIEWPORT_HEIGHT - 1));
         assertSelected(new int[] {0, 4, 8, 12, 16});
         scroll(CHILD_VIEW_EDGE_PX);
         assertSelected(new int[] {0, 4, 8, 12, 16, 20});
-        matrix.resizeSelection(new Point(200, VIEWPORT_HEIGHT - 1));
+        model.resizeSelection(new Point(200, VIEWPORT_HEIGHT - 1));
         assertSelected(new int[] {0, 1, 4, 5, 8, 9, 12, 13, 16, 17, 20, 21});
         scroll(CHILD_VIEW_EDGE_PX);
         assertSelected(new int[] {0, 1, 4, 5, 8, 9, 12, 13, 16, 17, 20, 21, 24, 25});
         scroll(-2 * CHILD_VIEW_EDGE_PX);
         assertSelected(new int[] {0, 1, 4, 5, 8, 9, 12, 13, 16, 17});
-        matrix.resizeSelection(new Point(100, VIEWPORT_HEIGHT - 1));
+        model.resizeSelection(new Point(100, VIEWPORT_HEIGHT - 1));
         assertSelected(new int[] {0, 4, 8, 12, 16});
+        assertEquals(0, model.getPositionNearestOrigin());
     }
 
     private static void assertSelected(int[] selectedPositions) {
@@ -179,10 +188,10 @@
     private static void scroll(int dy) {
         assertTrue(helper.verticalOffset + VIEWPORT_HEIGHT + dy <= helper.getTotalHeight());
         helper.verticalOffset += dy;
-        matrix.onScrolled(null, 0, dy);
+        model.onScrolled(null, 0, dy);
     }
 
-    private static final class TestHelper implements BandSelectMatrix.RecyclerViewHelper {
+    private static final class TestHelper implements MultiSelectManager.BandModelHelper {
 
         public int horizontalOffset = 0;
         public int verticalOffset = 0;
diff --git a/packages/DocumentsUI/tests/src/com/android/documentsui/MultiSelectManagerTest.java b/packages/DocumentsUI/tests/src/com/android/documentsui/MultiSelectManagerTest.java
index 03ad3d4..b82251c 100644
--- a/packages/DocumentsUI/tests/src/com/android/documentsui/MultiSelectManagerTest.java
+++ b/packages/DocumentsUI/tests/src/com/android/documentsui/MultiSelectManagerTest.java
@@ -19,12 +19,12 @@
 import static org.junit.Assert.*;
 
 import android.support.v7.widget.RecyclerView;
+import android.util.SparseBooleanArray;
 import android.view.KeyEvent;
 import android.view.MotionEvent;
 import android.view.View;
 import android.view.ViewGroup;
 
-import com.android.documentsui.MultiSelectManager.RecyclerViewHelper;
 import com.android.documentsui.MultiSelectManager.Selection;
 
 import org.junit.Before;
@@ -79,7 +79,7 @@
 
     @Test
     public void mouseClick_NoPosition_ClearsSelection() {
-        mManager.onLongPress(7);
+        mManager.onLongPress(7, 0);
         click(11);
         click(RecyclerView.NO_POSITION);
         assertSelection();
@@ -95,27 +95,27 @@
 
     @Test
     public void longPress_StartsSelectionMode() {
-        mManager.onLongPress(7);
+        mManager.onLongPress(7, 0);
         assertSelection(7);
     }
 
     @Test
     public void longPress_SecondPressExtendsSelection() {
-        mManager.onLongPress(7);
-        mManager.onLongPress(99);
+        mManager.onLongPress(7, 0);
+        mManager.onLongPress(99, 0);
         assertSelection(7, 99);
     }
 
     @Test
     public void singleTapUp_UnselectsSelectedItem() {
-        mManager.onLongPress(7);
+        mManager.onLongPress(7, 0);
         tap(7);
         assertSelection();
     }
 
     @Test
     public void singleTapUp_NoPosition_ClearsSelection() {
-        mManager.onLongPress(7);
+        mManager.onLongPress(7, 0);
         tap(11);
         tap(RecyclerView.NO_POSITION);
         assertSelection();
@@ -123,7 +123,7 @@
 
     @Test
     public void singleTapUp_ExtendsSelection() {
-        mManager.onLongPress(99);
+        mManager.onLongPress(99, 0);
         tap(7);
         tap(13);
         tap(129899);
@@ -132,21 +132,21 @@
 
     @Test
     public void singleTapUp_ShiftCreatesRangeSelection() {
-        mManager.onLongPress(7);
+        mManager.onLongPress(7, 0);
         shiftTap(17);
         assertRangeSelection(7, 17);
     }
 
     @Test
     public void singleTapUp_ShiftCreatesRangeSeletion_Backwards() {
-        mManager.onLongPress(17);
+        mManager.onLongPress(17, 0);
         shiftTap(7);
         assertRangeSelection(7, 17);
     }
 
     @Test
     public void singleTapUp_SecondShiftClickExtendsSelection() {
-        mManager.onLongPress(7);
+        mManager.onLongPress(7, 0);
         shiftTap(11);
         shiftTap(17);
         assertRangeSelection(7, 17);
@@ -154,7 +154,7 @@
 
     @Test
     public void singleTapUp_MultipleContiguousRangesSelected() {
-        mManager.onLongPress(7);
+        mManager.onLongPress(7, 0);
         shiftTap(11);
         tap(20);
         shiftTap(25);
@@ -165,7 +165,7 @@
 
     @Test
     public void singleTapUp_ShiftReducesSelectionRange_FromPreviousShiftClick() {
-        mManager.onLongPress(7);
+        mManager.onLongPress(7, 0);
         shiftTap(17);
         shiftTap(10);
         assertRangeSelection(7, 10);
@@ -173,7 +173,7 @@
 
     @Test
     public void singleTapUp_ShiftReducesSelectionRange_FromPreviousShiftClick_Backwards() {
-        mManager.onLongPress(17);
+        mManager.onLongPress(17, 0);
         shiftTap(7);
         shiftTap(14);
         assertRangeSelection(14, 17);
@@ -182,7 +182,7 @@
 
     @Test
     public void singleTapUp_ShiftReversesSelectionDirection() {
-        mManager.onLongPress(7);
+        mManager.onLongPress(7, 0);
         shiftTap(17);
         shiftTap(0);
         assertRangeSelection(0, 7);
@@ -206,6 +206,36 @@
         assertSelection(20);
     }
 
+    @Test
+    public void provisionaSelection() {
+        Selection s = mManager.getSelection();
+        assertSelection();
+
+        SparseBooleanArray provisional = new SparseBooleanArray();
+        provisional.append(1, true);
+        provisional.append(2, true);
+        s.setProvisionalSelection(provisional);
+        assertSelection(1, 2);
+
+        provisional.delete(1);
+        provisional.append(3, true);
+        s.setProvisionalSelection(provisional);
+        assertSelection(2, 3);
+
+        s.applyProvisionalSelection();
+        assertSelection(2, 3);
+
+        provisional.clear();
+        provisional.append(3, true);
+        provisional.append(4, true);
+        s.setProvisionalSelection(provisional);
+        assertSelection(2, 3, 4);
+
+        provisional.delete(3);
+        s.setProvisionalSelection(provisional);
+        assertSelection(2, 3, 4);
+    }
+
     private void tap(int position) {
         mManager.onSingleTapUp(position, 0, MotionEvent.TOOL_TYPE_MOUSE);
     }
@@ -252,7 +282,8 @@
         assertEquals(selection.toString(), expected, selection.size());
     }
 
-    private static final class EventHelper implements RecyclerViewHelper {
+    private static final class EventHelper implements MultiSelectManager.MultiSelectHelper {
+
         @Override
         public int findEventPosition(MotionEvent e) {
             throw new UnsupportedOperationException();
diff --git a/packages/DocumentsUI/tests/src/com/android/documentsui/UnitTests.java b/packages/DocumentsUI/tests/src/com/android/documentsui/UnitTests.java
index 0553270..d90130f 100644
--- a/packages/DocumentsUI/tests/src/com/android/documentsui/UnitTests.java
+++ b/packages/DocumentsUI/tests/src/com/android/documentsui/UnitTests.java
@@ -22,7 +22,7 @@
 
 @RunWith(Suite.class)
 @SuiteClasses({
-        BandSelectMatrixTest.class,
+        BandSelectModelTest.class,
         MultiSelectManager_SelectionTest.class,
         MultiSelectManagerTest.class
 })
diff --git a/packages/Keyguard/src/com/android/keyguard/KeyguardAbsKeyInputView.java b/packages/Keyguard/src/com/android/keyguard/KeyguardAbsKeyInputView.java
index dfc31ab..b03871a 100644
--- a/packages/Keyguard/src/com/android/keyguard/KeyguardAbsKeyInputView.java
+++ b/packages/Keyguard/src/com/android/keyguard/KeyguardAbsKeyInputView.java
@@ -40,6 +40,7 @@
     protected SecurityMessageDisplay mSecurityMessageDisplay;
     protected View mEcaView;
     protected boolean mEnableHaptics;
+    private boolean mDismissing;
 
     // To avoid accidental lockout due to events while the device in in the pocket, ignore
     // any passwords with length less than or equal to this length.
@@ -67,6 +68,7 @@
     @Override
     public void reset() {
         // start fresh
+        mDismissing = false;
         resetPasswordText(false /* animate */);
         // if the user is currently locked out, enforce it.
         long deadline = mLockPatternUtils.getLockoutAttemptDeadline(
@@ -113,6 +115,8 @@
     }
 
     protected void verifyPasswordAndUnlock() {
+        if (mDismissing) return; // already verified but haven't been dismissed; don't do it again.
+
         final String entry = getPasswordText();
         setPasswordEntryInputEnabled(false);
         if (mPendingLockCheck != null) {
@@ -143,6 +147,7 @@
 
     private void onPasswordChecked(boolean matched, int timeoutMs, boolean isValidPassword) {
         if (matched) {
+            mDismissing = true;
             mCallback.reportUnlockAttempt(true, 0);
             mCallback.dismiss(true);
         } else {
diff --git a/packages/Keyguard/src/com/android/keyguard/KeyguardPinBasedInputView.java b/packages/Keyguard/src/com/android/keyguard/KeyguardPinBasedInputView.java
index 4cd4845..ce2d11a 100644
--- a/packages/Keyguard/src/com/android/keyguard/KeyguardPinBasedInputView.java
+++ b/packages/Keyguard/src/com/android/keyguard/KeyguardPinBasedInputView.java
@@ -62,6 +62,7 @@
         return mPasswordEntry.requestFocus(direction, previouslyFocusedRect);
     }
 
+    @Override
     protected void resetState() {
         mPasswordEntry.setEnabled(true);
     }
@@ -69,11 +70,13 @@
     @Override
     protected void setPasswordEntryEnabled(boolean enabled) {
         mPasswordEntry.setEnabled(enabled);
+        mOkButton.setEnabled(enabled);
     }
 
     @Override
     protected void setPasswordEntryInputEnabled(boolean enabled) {
         mPasswordEntry.setEnabled(enabled);
+        mOkButton.setEnabled(enabled);
     }
 
     @Override
@@ -186,6 +189,7 @@
         mDeleteButton = findViewById(R.id.delete_button);
         mDeleteButton.setVisibility(View.VISIBLE);
         mDeleteButton.setOnClickListener(new OnClickListener() {
+            @Override
             public void onClick(View v) {
                 // check for time-based lockouts
                 if (mPasswordEntry.isEnabled()) {
@@ -195,6 +199,7 @@
             }
         });
         mDeleteButton.setOnLongClickListener(new View.OnLongClickListener() {
+            @Override
             public boolean onLongClick(View v) {
                 // check for time-based lockouts
                 if (mPasswordEntry.isEnabled()) {
diff --git a/packages/Keyguard/src/com/android/keyguard/KeyguardSecurityContainer.java b/packages/Keyguard/src/com/android/keyguard/KeyguardSecurityContainer.java
index 77215a7..f45b9bd 100644
--- a/packages/Keyguard/src/com/android/keyguard/KeyguardSecurityContainer.java
+++ b/packages/Keyguard/src/com/android/keyguard/KeyguardSecurityContainer.java
@@ -255,7 +255,6 @@
 
         if (DEBUG) Log.d(TAG, "reportFailedPatternAttempt: #" + failedAttempts);
 
-        SecurityMode mode = mSecurityModel.getSecurityMode();
         final int currentUser = KeyguardUpdateMonitor.getCurrentUser();
         final DevicePolicyManager dpm = mLockPatternUtils.getDevicePolicyManager();
         final int failedAttemptsBeforeWipe =
@@ -264,7 +263,6 @@
         final int remainingBeforeWipe = failedAttemptsBeforeWipe > 0 ?
                 (failedAttemptsBeforeWipe - failedAttempts)
                 : Integer.MAX_VALUE; // because DPM returns 0 if no restriction
-        boolean showTimeout = false;
         if (remainingBeforeWipe < LockPatternUtils.FAILED_ATTEMPTS_BEFORE_WIPE_GRACE) {
             // The user has installed a DevicePolicyManager that requests a user/profile to be wiped
             // N attempts. Once we get below the grace period, we post this dialog every time as a
@@ -273,7 +271,8 @@
             final int expiringUser = dpm.getProfileWithMinimumFailedPasswordsForWipe(currentUser);
             int userType = USER_TYPE_PRIMARY;
             if (expiringUser == currentUser) {
-                if (expiringUser != UserHandle.USER_OWNER) {
+                // TODO: http://b/23522538
+                if (expiringUser != UserHandle.USER_SYSTEM) {
                     userType = USER_TYPE_SECONDARY_USER;
                 }
             } else if (expiringUser != UserHandle.USER_NULL) {
diff --git a/packages/Keyguard/src/com/android/keyguard/KeyguardUpdateMonitor.java b/packages/Keyguard/src/com/android/keyguard/KeyguardUpdateMonitor.java
index ead0307..fc6117f 100644
--- a/packages/Keyguard/src/com/android/keyguard/KeyguardUpdateMonitor.java
+++ b/packages/Keyguard/src/com/android/keyguard/KeyguardUpdateMonitor.java
@@ -523,7 +523,8 @@
         final DevicePolicyManager dpm =
                 (DevicePolicyManager) mContext.getSystemService(Context.DEVICE_POLICY_SERVICE);
         return dpm != null && (dpm.getKeyguardDisabledFeatures(null, userId)
-                    & DevicePolicyManager.KEYGUARD_DISABLE_FINGERPRINT) != 0;
+                    & DevicePolicyManager.KEYGUARD_DISABLE_FINGERPRINT) != 0
+                || isSimPinSecure();
     }
 
     public boolean getUserCanSkipBouncer(int userId) {
@@ -1016,7 +1017,7 @@
 
     private boolean shouldListenForFingerprint() {
         return (mKeyguardIsVisible || !mDeviceInteractive) && !mSwitchingUser
-                && !mFingerprintAlreadyAuthenticated;
+                && !mFingerprintAlreadyAuthenticated && !isFingerprintDisabled(getCurrentUser());
     }
 
     private void startListeningForFingerprint() {
@@ -1090,6 +1091,7 @@
      * Handle {@link #MSG_DPM_STATE_CHANGED}
      */
     protected void handleDevicePolicyManagerStateChanged() {
+        updateFingerprintListeningState();
         for (int i = mCallbacks.size() - 1; i >= 0; i--) {
             KeyguardUpdateMonitorCallback cb = mCallbacks.get(i).get();
             if (cb != null) {
diff --git a/packages/MtpDocumentsProvider/src/com/android/mtp/MtpDocument.java b/packages/MtpDocumentsProvider/src/com/android/mtp/MtpDocument.java
index 7126694..c1d9609 100644
--- a/packages/MtpDocumentsProvider/src/com/android/mtp/MtpDocument.java
+++ b/packages/MtpDocumentsProvider/src/com/android/mtp/MtpDocument.java
@@ -76,18 +76,25 @@
     void addToCursor(Identifier rootIdentifier, MatrixCursor.RowBuilder builder) {
         final Identifier identifier = new Identifier(
                 rootIdentifier.mDeviceId, rootIdentifier.mStorageId, mObjectHandle);
+        final String mimeType = formatTypeToMimeType(mFormat);
 
         int flag = 0;
         if (mObjectHandle != DUMMY_HANDLE_FOR_ROOT) {
-            flag |= DocumentsContract.Document.FLAG_SUPPORTS_DELETE;
             if (mThumbSize > 0) {
                 flag |= DocumentsContract.Document.FLAG_SUPPORTS_THUMBNAIL;
             }
+            if (!mReadOnly) {
+                flag |= DocumentsContract.Document.FLAG_SUPPORTS_DELETE |
+                        DocumentsContract.Document.FLAG_SUPPORTS_WRITE;
+            }
+        }
+        if (mimeType == DocumentsContract.Document.MIME_TYPE_DIR && !mReadOnly) {
+            flag |= DocumentsContract.Document.FLAG_DIR_SUPPORTS_CREATE;
         }
 
         builder.add(Document.COLUMN_DOCUMENT_ID, identifier.toDocumentId());
         builder.add(Document.COLUMN_DISPLAY_NAME, mName);
-        builder.add(Document.COLUMN_MIME_TYPE, formatTypeToMimeType(mFormat));
+        builder.add(Document.COLUMN_MIME_TYPE, mimeType); 
         builder.add(
                 Document.COLUMN_LAST_MODIFIED,
                 mDateModified != null ? mDateModified.getTime() : null);
diff --git a/packages/MtpDocumentsProvider/src/com/android/mtp/MtpDocumentsProvider.java b/packages/MtpDocumentsProvider/src/com/android/mtp/MtpDocumentsProvider.java
index 031cc07..a3cf3e2 100644
--- a/packages/MtpDocumentsProvider/src/com/android/mtp/MtpDocumentsProvider.java
+++ b/packages/MtpDocumentsProvider/src/com/android/mtp/MtpDocumentsProvider.java
@@ -167,13 +167,18 @@
     public ParcelFileDescriptor openDocument(
             String documentId, String mode, CancellationSignal signal)
                     throws FileNotFoundException {
-        if (!"r".equals(mode) && !"w".equals(mode)) {
-            // TODO: Support seekable file.
-            throw new UnsupportedOperationException("The provider does not support seekable file.");
-        }
         final Identifier identifier = Identifier.createFromDocumentId(documentId);
         try {
-            return mPipeManager.readDocument(mMtpManager, identifier);
+            switch (mode) {
+                case "r":
+                    return mPipeManager.readDocument(mMtpManager, identifier);
+                case "w":
+                    return mPipeManager.writeDocument(getContext(), mMtpManager, identifier);
+                default:
+                    // TODO: Add support for seekable files.
+                    throw new UnsupportedOperationException(
+                            "The provider does not support seekable file.");
+            }
         } catch (IOException error) {
             throw new FileNotFoundException(error.getMessage());
         }
diff --git a/packages/MtpDocumentsProvider/src/com/android/mtp/MtpManager.java b/packages/MtpDocumentsProvider/src/com/android/mtp/MtpManager.java
index 27ba794..6647009 100644
--- a/packages/MtpDocumentsProvider/src/com/android/mtp/MtpManager.java
+++ b/packages/MtpDocumentsProvider/src/com/android/mtp/MtpManager.java
@@ -108,6 +108,11 @@
         return results;
     }
 
+    synchronized MtpObjectInfo getObjectInfo(int deviceId, int objectHandle) throws IOException {
+        final MtpDevice device = getDevice(deviceId);
+        return device.getObjectInfo(objectHandle);
+    }
+
     synchronized MtpDocument getDocument(int deviceId, int objectHandle) throws IOException {
         final MtpDevice device = getDevice(deviceId);
         return new MtpDocument(device.getObjectInfo(objectHandle));
@@ -137,15 +142,20 @@
         }
     }
 
+    // TODO: Remove this method.
     synchronized int createDocument(int deviceId, int storageId, int parentObjectHandle,
             String mimeType, String name) throws IOException {
-        final MtpDevice device = getDevice(deviceId);
         final MtpObjectInfo objectInfo = new MtpObjectInfo.Builder()
                 .setName(name)
                 .setStorageId(storageId)
                 .setParent(parentObjectHandle)
                 .setFormat(MtpDocument.mimeTypeToFormatType(mimeType))
                 .build();
+        return createDocument(deviceId, objectInfo);
+    }
+
+    synchronized int createDocument(int deviceId, MtpObjectInfo objectInfo) throws IOException {
+        final MtpDevice device = getDevice(deviceId);
         final MtpObjectInfo result = device.sendObjectInfo(objectInfo);
         if (result == null) {
             throw new IOException("Failed to create a document");
@@ -168,6 +178,13 @@
         device.importFile(objectHandle, target);
     }
 
+    synchronized void sendObject(int deviceId, int objectHandle, int size,
+            ParcelFileDescriptor source) throws IOException {
+        final MtpDevice device = getDevice(deviceId);
+        if (!device.sendObject(objectHandle, size, source))
+            throw new IOException("Failed to send a document");
+    }
+
     private MtpDevice getDevice(int deviceId) throws IOException {
         final MtpDevice device = mDevices.get(deviceId);
         if (device == null) {
diff --git a/packages/MtpDocumentsProvider/src/com/android/mtp/PipeManager.java b/packages/MtpDocumentsProvider/src/com/android/mtp/PipeManager.java
index ba13b31..53f1b65 100644
--- a/packages/MtpDocumentsProvider/src/com/android/mtp/PipeManager.java
+++ b/packages/MtpDocumentsProvider/src/com/android/mtp/PipeManager.java
@@ -16,10 +16,16 @@
 
 package com.android.mtp;
 
+import android.content.Context;
+import android.mtp.MtpObjectInfo;
 import android.os.ParcelFileDescriptor;
 import android.util.Log;
 
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
 import java.io.IOException;
+import java.io.OutputStream;
 import java.util.concurrent.ExecutorService;
 import java.util.concurrent.Executors;
 
@@ -40,6 +46,13 @@
         return task.getReadingFileDescriptor();
     }
 
+    ParcelFileDescriptor writeDocument(Context context, MtpManager model, Identifier identifier)
+            throws IOException {
+        final Task task = new WriteDocumentTask(context, model, identifier);
+        mExecutor.execute(task);
+        return task.getWritingFileDescriptor();
+    }
+
     ParcelFileDescriptor readThumbnail(MtpManager model, Identifier identifier) throws IOException {
         final Task task = new GetThumbnailTask(model, identifier);
         mExecutor.execute(task);
@@ -60,6 +73,10 @@
         ParcelFileDescriptor getReadingFileDescriptor() {
             return mDescriptors[0];
         }
+
+        ParcelFileDescriptor getWritingFileDescriptor() {
+            return mDescriptors[1];
+        }
     }
 
     private static class ImportFileTask extends Task {
@@ -83,6 +100,70 @@
         }
     }
 
+    private static class WriteDocumentTask extends Task {
+        private final Context mContext;
+
+        WriteDocumentTask(Context context, MtpManager model, Identifier identifier)
+                throws IOException {
+            super(model, identifier);
+            mContext = context;
+        }
+
+        @Override
+        public void run() {
+            File tempFile = null;
+            try {
+                // Obtain a temporary file and copy the data to it.
+                tempFile = mContext.getCacheDir().createTempFile("mtp", "tmp");
+                try (
+                    final FileOutputStream tempOutputStream =
+                            new ParcelFileDescriptor.AutoCloseOutputStream(
+                                    ParcelFileDescriptor.open(
+                                            tempFile, ParcelFileDescriptor.MODE_WRITE_ONLY));
+                    final ParcelFileDescriptor.AutoCloseInputStream inputStream =
+                            new ParcelFileDescriptor.AutoCloseInputStream(mDescriptors[0])
+                ) {
+                    final byte[] buffer = new byte[32 * 1024];
+                    int bytes;
+                    while ((bytes = inputStream.read(buffer)) != -1) {
+                        mDescriptors[0].checkError();
+                        tempOutputStream.write(buffer, 0, bytes);
+                    }
+                    tempOutputStream.flush();
+                }
+
+                // Get the placeholder object info.
+                final MtpObjectInfo placeholderObjectInfo =
+                        mManager.getObjectInfo(mIdentifier.mDeviceId, mIdentifier.mObjectHandle);
+
+                // Delete the target object info if it already exists (as a placeholder).
+                mManager.deleteDocument(mIdentifier.mDeviceId, mIdentifier.mObjectHandle);
+
+                // Create the target object info with a correct file size.
+                final int targetObjectHandle =
+                        mManager.createDocument(
+                                mIdentifier.mDeviceId,
+                                new MtpObjectInfo.Builder(placeholderObjectInfo)
+                                        .setCompressedSize((int) tempFile.length())
+                                        .build());
+
+                // Upload the object.
+                final ParcelFileDescriptor tempInputDescriptor = ParcelFileDescriptor.open(
+                        tempFile, ParcelFileDescriptor.MODE_READ_ONLY);
+                mManager.sendObject(mIdentifier.mDeviceId,
+                        targetObjectHandle, (int) tempFile.length(), tempInputDescriptor);
+
+            } catch (IOException error) {
+                Log.w(MtpDocumentsProvider.TAG,
+                        "Failed to send a file because of: " + error.getMessage());
+            } finally {
+                if (tempFile != null) {
+                    tempFile.delete();
+                }
+            }
+        }
+    }
+
     private static class GetThumbnailTask extends Task {
         GetThumbnailTask(MtpManager model, Identifier identifier) throws IOException {
             super(model, identifier);
diff --git a/packages/MtpDocumentsProvider/tests/src/com/android/mtp/MtpDocumentsProviderTest.java b/packages/MtpDocumentsProvider/tests/src/com/android/mtp/MtpDocumentsProviderTest.java
index f06e2ff..1826bd0 100644
--- a/packages/MtpDocumentsProvider/tests/src/com/android/mtp/MtpDocumentsProviderTest.java
+++ b/packages/MtpDocumentsProvider/tests/src/com/android/mtp/MtpDocumentsProviderTest.java
@@ -140,7 +140,7 @@
             assertEquals(1, cursor.getCount());
             cursor.moveToNext();
             assertEquals("0_1", cursor.getString(0));
-            assertEquals(Root.FLAG_SUPPORTS_IS_CHILD, cursor.getInt(1));
+            assertEquals(Root.FLAG_SUPPORTS_IS_CHILD | Root.FLAG_SUPPORTS_CREATE, cursor.getInt(1));
             // TODO: Add storage icon for MTP devices.
             assertTrue(cursor.isNull(2) /* icon */);
             assertEquals("Storage A", cursor.getString(3));
@@ -156,7 +156,7 @@
             cursor.moveToNext();
             cursor.moveToNext();
             assertEquals("1_1", cursor.getString(0));
-            assertEquals(Root.FLAG_SUPPORTS_IS_CHILD, cursor.getInt(1));
+            assertEquals(Root.FLAG_SUPPORTS_IS_CHILD | Root.FLAG_SUPPORTS_CREATE, cursor.getInt(1));
             // TODO: Add storage icon for MTP devices.
             assertTrue(cursor.isNull(2) /* icon */);
             assertEquals("Storage B", cursor.getString(3));
@@ -194,7 +194,7 @@
             assertEquals(1, cursor.getCount());
             cursor.moveToNext();
             assertEquals("1_1", cursor.getString(0));
-            assertEquals(Root.FLAG_SUPPORTS_IS_CHILD, cursor.getInt(1));
+            assertEquals(Root.FLAG_SUPPORTS_IS_CHILD | Root.FLAG_SUPPORTS_CREATE, cursor.getInt(1));
             // TODO: Add storage icon for MTP devices.
             assertTrue(cursor.isNull(2) /* icon */);
             assertEquals("Storage B", cursor.getString(3));
@@ -211,7 +211,7 @@
                 new Date(1422716400000L) /* modified date */,
                 1024 * 1024 * 5 /* file size */,
                 1024 * 50 /* thumbnail size */,
-                true /* read only */));
+                false /* read only */));
         final Cursor cursor = mProvider.queryDocument("0_1_2", null);
         assertEquals(1, cursor.getCount());
 
@@ -222,11 +222,37 @@
         assertEquals(1422716400000L, cursor.getLong(3));
         assertEquals(
                 DocumentsContract.Document.FLAG_SUPPORTS_DELETE |
+                DocumentsContract.Document.FLAG_SUPPORTS_WRITE |
                 DocumentsContract.Document.FLAG_SUPPORTS_THUMBNAIL,
                 cursor.getInt(4));
         assertEquals(1024 * 1024 * 5, cursor.getInt(5));
     }
 
+    public void testQueryDocument_directory() throws IOException {
+        mMtpManager.setDocument(0, 2, new MtpDocument(
+                2 /* object handle */,
+                0x3001 /* directory */,
+                "directory" /* display name */,
+                new Date(1422716400000L) /* modified date */,
+                0 /* file size */,
+                0 /* thumbnail size */,
+                false /* read only */));
+        final Cursor cursor = mProvider.queryDocument("0_1_2", null);
+        assertEquals(1, cursor.getCount());
+
+        cursor.moveToNext();
+        assertEquals("0_1_2", cursor.getString(0));
+        assertEquals(DocumentsContract.Document.MIME_TYPE_DIR, cursor.getString(1));
+        assertEquals("directory", cursor.getString(2));
+        assertEquals(1422716400000L, cursor.getLong(3));
+        assertEquals(
+                DocumentsContract.Document.FLAG_SUPPORTS_DELETE |
+                DocumentsContract.Document.FLAG_SUPPORTS_WRITE |
+                DocumentsContract.Document.FLAG_DIR_SUPPORTS_CREATE,
+                cursor.getInt(4));
+        assertEquals(0, cursor.getInt(5));
+    }
+
     public void testQueryDocument_forRoot() throws IOException {
         mMtpManager.setRoots(0, new MtpRoot[] {
                 new MtpRoot(
@@ -269,10 +295,7 @@
         assertEquals("image/jpeg", cursor.getString(1));
         assertEquals("image.jpg", cursor.getString(2));
         assertEquals(0, cursor.getLong(3));
-        assertEquals(
-                DocumentsContract.Document.FLAG_SUPPORTS_DELETE |
-                DocumentsContract.Document.FLAG_SUPPORTS_THUMBNAIL,
-                cursor.getInt(4));
+        assertEquals(DocumentsContract.Document.FLAG_SUPPORTS_THUMBNAIL, cursor.getInt(4));
         assertEquals(1024 * 1024 * 5, cursor.getInt(5));
 
         assertFalse(cursor.moveToNext());
diff --git a/packages/MtpDocumentsProvider/tests/src/com/android/mtp/PipeManagerTest.java b/packages/MtpDocumentsProvider/tests/src/com/android/mtp/PipeManagerTest.java
index 35918e1..e2cc3ed 100644
--- a/packages/MtpDocumentsProvider/tests/src/com/android/mtp/PipeManagerTest.java
+++ b/packages/MtpDocumentsProvider/tests/src/com/android/mtp/PipeManagerTest.java
@@ -21,6 +21,7 @@
 import android.test.suitebuilder.annotation.SmallTest;
 
 import java.io.IOException;
+import java.util.Date;
 import java.util.concurrent.ExecutorService;
 import java.util.concurrent.Executors;
 import java.util.concurrent.TimeUnit;
@@ -53,6 +54,41 @@
         assertDescriptorError(descriptor);
     }
 
+    public void testWriteDocument_basic() throws Exception {
+        // Create a placeholder file which should be replaced by a real file later.
+        mtpManager.setDocument(0, 1, new MtpDocument(1, 0, "", new Date(), 0, 0, false));
+
+        // Upload testing bytes.
+        final ParcelFileDescriptor descriptor = pipeManager.writeDocument(
+                getContext(), mtpManager, new Identifier(0, 0, 1));
+        final ParcelFileDescriptor.AutoCloseOutputStream outputStream =
+                new ParcelFileDescriptor.AutoCloseOutputStream(descriptor);
+        outputStream.write(HELLO_BYTES, 0, HELLO_BYTES.length);
+        outputStream.close();
+        executor.awaitTermination(1000, TimeUnit.MILLISECONDS);
+
+        // Check if the placeholder file is removed.
+        try {
+            final MtpDocument placeholderDocument = mtpManager.getDocument(0, 1);
+            fail();  // The placeholder file has not been deleted.
+        } catch (IOException e) {
+            // Expected error, as the file is gone.
+        }
+
+        // Confirm that the target file is created.
+        final MtpDocument targetDocument = mtpManager.getDocument(
+                0, TestMtpManager.CREATED_DOCUMENT_HANDLE);
+        assertTrue(targetDocument != null);
+
+        // Verify uploaded bytes.
+        final byte[] uploadedBytes = mtpManager.getImportFileBytes(
+                0, TestMtpManager.CREATED_DOCUMENT_HANDLE);
+        assertEquals(HELLO_BYTES.length, uploadedBytes.length);
+        for (int i = 0; i < HELLO_BYTES.length; i++) {
+            assertEquals(HELLO_BYTES[i], uploadedBytes[i]);
+        }
+    }
+
     public void testReadThumbnail_basic() throws Exception {
         mtpManager.setThumbnail(0, 1, HELLO_BYTES);
         final ParcelFileDescriptor descriptor = pipeManager.readThumbnail(
diff --git a/packages/MtpDocumentsProvider/tests/src/com/android/mtp/TestMtpManager.java b/packages/MtpDocumentsProvider/tests/src/com/android/mtp/TestMtpManager.java
index 40de7b4..94b5ba0 100644
--- a/packages/MtpDocumentsProvider/tests/src/com/android/mtp/TestMtpManager.java
+++ b/packages/MtpDocumentsProvider/tests/src/com/android/mtp/TestMtpManager.java
@@ -17,10 +17,13 @@
 package com.android.mtp;
 
 import android.content.Context;
+import android.mtp.MtpObjectInfo;
+import android.mtp.MtpObjectInfo.Builder;
 import android.os.ParcelFileDescriptor;
 
 import java.io.IOException;
 import java.util.Arrays;
+import java.util.Date;
 import java.util.HashMap;
 import java.util.HashSet;
 import java.util.Map;
@@ -28,6 +31,8 @@
 import java.util.TreeSet;
 
 public class TestMtpManager extends MtpManager {
+    public static final int CREATED_DOCUMENT_HANDLE = 1000;
+
     protected static String pack(int... args) {
         return Arrays.toString(args);
     }
@@ -65,6 +70,10 @@
         mImportFileBytes.put(pack(deviceId, objectHandle), bytes);
     }
 
+    byte[] getImportFileBytes(int deviceId, int objectHandle) {
+        return mImportFileBytes.get(pack(deviceId, objectHandle));
+    }
+
     void setThumbnail(int deviceId, int objectHandle, byte[] bytes) {
         mThumbnailBytes.put(pack(deviceId, objectHandle), bytes);
     }
@@ -109,6 +118,15 @@
     }
 
     @Override
+    MtpObjectInfo getObjectInfo(int deviceId, int objectHandle) throws IOException {
+        final MtpDocument document = getDocument(deviceId, objectHandle);
+        // It's impossible to set an object id of MtpObjectInfo at this stage. Also,
+        // it's hard to get any information from MtpDocument, as it's designed to return them
+        // only via cursors. Rework these.
+        return new MtpObjectInfo.Builder().build();
+    }
+
+    @Override
     int[] getObjectHandles(int deviceId, int storageId, int parentObjectHandle) throws IOException {
         final String key = pack(deviceId, storageId, parentObjectHandle);
         if (mObjectHandles.containsKey(key)) {
@@ -119,8 +137,9 @@
     }
 
     @Override
-    void importFile(int deviceId, int storageId, ParcelFileDescriptor target) throws IOException {
-        final String key = pack(deviceId, storageId);
+    void importFile(int deviceId, int objectHandle, ParcelFileDescriptor target)
+            throws IOException {
+        final String key = pack(deviceId, objectHandle);
         if (mImportFileBytes.containsKey(key)) {
             try (final ParcelFileDescriptor.AutoCloseOutputStream outputStream =
                     new ParcelFileDescriptor.AutoCloseOutputStream(target)) {
@@ -132,6 +151,44 @@
     }
 
     @Override
+    int createDocument(int deviceId, MtpObjectInfo objectInfo) throws IOException {
+        // For simplicity, it allows to create only one document, and it always has the hardcoded
+        // CREATED_DOCUMENT_HANDLE document handle.
+        final String key = pack(deviceId, CREATED_DOCUMENT_HANDLE);
+        if (!mDocuments.containsKey(key)) {
+            mDocuments.put(key, new MtpDocument(
+                  CREATED_DOCUMENT_HANDLE,
+                  objectInfo.getFormat(),
+                  objectInfo.getName(),
+                  new Date(objectInfo.getDateModified()),
+                  objectInfo.getCompressedSize(),
+                  objectInfo.getThumbCompressedSize(),
+                  false /* Always writable for testing. */));
+        } else {
+            throw new IOException();
+        }
+        return CREATED_DOCUMENT_HANDLE;
+    }
+
+    @Override
+    void sendObject(int deviceId, int objectHandle, int size, ParcelFileDescriptor source)
+            throws IOException {
+        final String key = pack(deviceId, objectHandle);
+        if (!mDocuments.containsKey(key)) {
+            throw new IOException();
+        }
+
+        ParcelFileDescriptor.AutoCloseInputStream inputStream =
+                new ParcelFileDescriptor.AutoCloseInputStream(source);
+        byte[] buffer = new byte[size];
+        if (inputStream.read(buffer, 0, size) != size) {
+            throw new IOException();
+        }
+
+        mImportFileBytes.put(pack(deviceId, objectHandle), buffer);
+    }
+
+    @Override
     byte[] getThumbnail(int deviceId, int objectHandle) throws IOException {
         final String key = pack(deviceId, objectHandle);
         if (mThumbnailBytes.containsKey(key)) {
diff --git a/packages/SettingsLib/res/values/dimens.xml b/packages/SettingsLib/res/values/dimens.xml
index 1c4b05f..3ad8f21 100644
--- a/packages/SettingsLib/res/values/dimens.xml
+++ b/packages/SettingsLib/res/values/dimens.xml
@@ -21,4 +21,6 @@
 
     <!-- The translation for disappearing security views after having solved them. -->
     <dimen name="disappear_y_translation">-32dp</dimen>
-</resources>
\ No newline at end of file
+
+    <dimen name="circle_avatar_size">40dp</dimen>
+</resources>
diff --git a/packages/SettingsLib/res/values/strings.xml b/packages/SettingsLib/res/values/strings.xml
index b03f100..9b1f103 100644
--- a/packages/SettingsLib/res/values/strings.xml
+++ b/packages/SettingsLib/res/values/strings.xml
@@ -195,4 +195,34 @@
     <!-- Content description of the WIFI signal when it is full for accessibility (not shown on the screen). [CHAR LIMIT=NONE] -->
     <string name="accessibility_wifi_signal_full">Wifi signal full.</string>
 
+    <!-- Label for kernel threads in battery usage -->
+    <string name="process_kernel_label">Android OS</string>
+    <!-- Title of data usage item that represents all uninstalled applications. [CHAR LIMIT=48] -->
+    <string name="data_usage_uninstalled_apps">Removed apps</string>
+    <!-- Title of data usage item that represents all uninstalled applications or removed users. [CHAR LIMIT=48] -->
+    <string name="data_usage_uninstalled_apps_users">Removed apps and users</string>
+
+    <!-- Tethering controls, item title to go into the tethering settings -->
+    <!-- Tethering controls, item title to go into the tethering settings when only USB tethering is available [CHAR LIMIT=25]-->
+    <string name="tether_settings_title_usb">USB tethering</string>
+    <!-- Tethering controls, item title to go into the tethering settings when only Wifi tethering is available [CHAR LIMIT=25]-->
+    <string name="tether_settings_title_wifi">Portable hotspot</string>
+    <!-- Tethering controls, item title to go into the tethering settings when only Bluetooth tethering is available [CHAR LIMIT=25]-->
+    <string name="tether_settings_title_bluetooth">Bluetooth tethering</string>
+    <!-- Tethering controls, item title to go into the tethering settings when USB and Bluetooth tethering are available [CHAR LIMIT=25]-->
+    <string name="tether_settings_title_usb_bluetooth">Tethering</string>
+    <!-- Tethering controls, item title to go into the tethering settings when USB, Bluetooth and Wifi tethering are available [CHAR LIMIT=25]-->
+    <string name="tether_settings_title_all">Tethering &amp; portable hotspot</string>
+
+    <!-- Title for a work profile. [CHAR LIMIT=25] -->
+    <string name="managed_user_title">Work profile</string>
+
+    <!-- Title for Guest user [CHAR LIMIT=35] -->
+    <string name="user_guest">Guest</string>
+
+    <!-- Manage apps, individual app screen, substituted for the application's label when the app's label CAN NOT be determined.-->
+    <string name="unknown">Unknown</string>
+
+    <!-- [CHAR LIMIT=NONE] Label of a running process that represents another user -->
+    <string name="running_process_item_user_label">User: <xliff:g id="user_name">%1$s</xliff:g></string>
 </resources>
diff --git a/packages/SettingsLib/src/com/android/settingslib/Utils.java b/packages/SettingsLib/src/com/android/settingslib/Utils.java
new file mode 100644
index 0000000..621a09cd
--- /dev/null
+++ b/packages/SettingsLib/src/com/android/settingslib/Utils.java
@@ -0,0 +1,84 @@
+package com.android.settingslib;
+
+import android.content.Context;
+import android.content.pm.UserInfo;
+import android.graphics.Bitmap;
+import android.graphics.BitmapFactory;
+import android.graphics.drawable.Drawable;
+import android.net.ConnectivityManager;
+import android.os.UserManager;
+
+import com.android.internal.util.UserIcons;
+import com.android.settingslib.drawable.CircleFramedDrawable;
+
+public final class Utils {
+
+    /**
+     * Return string resource that best describes combination of tethering
+     * options available on this device.
+     */
+    public static int getTetheringLabel(ConnectivityManager cm) {
+        String[] usbRegexs = cm.getTetherableUsbRegexs();
+        String[] wifiRegexs = cm.getTetherableWifiRegexs();
+        String[] bluetoothRegexs = cm.getTetherableBluetoothRegexs();
+
+        boolean usbAvailable = usbRegexs.length != 0;
+        boolean wifiAvailable = wifiRegexs.length != 0;
+        boolean bluetoothAvailable = bluetoothRegexs.length != 0;
+
+        if (wifiAvailable && usbAvailable && bluetoothAvailable) {
+            return R.string.tether_settings_title_all;
+        } else if (wifiAvailable && usbAvailable) {
+            return R.string.tether_settings_title_all;
+        } else if (wifiAvailable && bluetoothAvailable) {
+            return R.string.tether_settings_title_all;
+        } else if (wifiAvailable) {
+            return R.string.tether_settings_title_wifi;
+        } else if (usbAvailable && bluetoothAvailable) {
+            return R.string.tether_settings_title_usb_bluetooth;
+        } else if (usbAvailable) {
+            return R.string.tether_settings_title_usb;
+        } else {
+            return R.string.tether_settings_title_bluetooth;
+        }
+    }
+
+    /**
+     * Returns a label for the user, in the form of "User: user name" or "Work profile".
+     */
+    public static String getUserLabel(Context context, UserInfo info) {
+        String name = info != null ? info.name : null;
+        if (info.isManagedProfile()) {
+            // We use predefined values for managed profiles
+            return context.getString(R.string.managed_user_title);
+        } else if (info.isGuest()) {
+            name = context.getString(R.string.user_guest);
+        }
+        if (name == null && info != null) {
+            name = Integer.toString(info.id);
+        } else if (info == null) {
+            name = context.getString(R.string.unknown);
+        }
+        return context.getResources().getString(R.string.running_process_item_user_label, name);
+    }
+
+    /**
+     * Returns a circular icon for a user.
+     */
+    public static Drawable getUserIcon(Context context, UserManager um, UserInfo user) {
+        if (user.isManagedProfile()) {
+            // We use predefined values for managed profiles
+            Bitmap b = BitmapFactory.decodeResource(context.getResources(),
+                    com.android.internal.R.drawable.ic_corp_icon);
+            return CircleFramedDrawable.getInstance(context, b);
+        }
+        if (user.iconPath != null) {
+            Bitmap icon = um.getUserIcon(user.id);
+            if (icon != null) {
+                return CircleFramedDrawable.getInstance(context, icon);
+            }
+        }
+        return CircleFramedDrawable.getInstance(context, UserIcons.convertToBitmap(
+                UserIcons.getDefaultUserIcon(user.id, /* light= */ false)));
+    }
+}
diff --git a/packages/SettingsLib/src/com/android/settingslib/drawable/CircleFramedDrawable.java b/packages/SettingsLib/src/com/android/settingslib/drawable/CircleFramedDrawable.java
new file mode 100644
index 0000000..278b57d
--- /dev/null
+++ b/packages/SettingsLib/src/com/android/settingslib/drawable/CircleFramedDrawable.java
@@ -0,0 +1,136 @@
+/*
+ * 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.settingslib.drawable;
+
+import android.content.Context;
+import android.content.res.Resources;
+import android.graphics.Bitmap;
+import android.graphics.Canvas;
+import android.graphics.Color;
+import android.graphics.ColorFilter;
+import android.graphics.Paint;
+import android.graphics.Path;
+import android.graphics.PixelFormat;
+import android.graphics.PorterDuff;
+import android.graphics.PorterDuffXfermode;
+import android.graphics.Rect;
+import android.graphics.RectF;
+import android.graphics.drawable.Drawable;
+
+import com.android.settingslib.R;
+
+/**
+ * Converts the user avatar icon to a circularly clipped one.
+ * TODO: Move this to an internal framework class and share with the one in Keyguard.
+ */
+public class CircleFramedDrawable extends Drawable {
+
+    private final Bitmap mBitmap;
+    private final int mSize;
+    private final Paint mPaint;
+
+    private float mScale;
+    private Rect mSrcRect;
+    private RectF mDstRect;
+
+    public static CircleFramedDrawable getInstance(Context context, Bitmap icon) {
+        Resources res = context.getResources();
+        float iconSize = res.getDimension(R.dimen.circle_avatar_size);
+
+        CircleFramedDrawable instance = new CircleFramedDrawable(icon, (int) iconSize);
+        return instance;
+    }
+
+    public CircleFramedDrawable(Bitmap icon, int size) {
+        super();
+        mSize = size;
+
+        mBitmap = Bitmap.createBitmap(mSize, mSize, Bitmap.Config.ARGB_8888);
+        final Canvas canvas = new Canvas(mBitmap);
+
+        final int width = icon.getWidth();
+        final int height = icon.getHeight();
+        final int square = Math.min(width, height);
+
+        final Rect cropRect = new Rect((width - square) / 2, (height - square) / 2, square, square);
+        final RectF circleRect = new RectF(0f, 0f, mSize, mSize);
+
+        final Path fillPath = new Path();
+        fillPath.addArc(circleRect, 0f, 360f);
+
+        canvas.drawColor(0, PorterDuff.Mode.CLEAR);
+
+        // opaque circle matte
+        mPaint = new Paint();
+        mPaint.setAntiAlias(true);
+        mPaint.setColor(Color.BLACK);
+        mPaint.setStyle(Paint.Style.FILL);
+        canvas.drawPath(fillPath, mPaint);
+
+        // mask in the icon where the bitmap is opaque
+        mPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC_IN));
+        canvas.drawBitmap(icon, cropRect, circleRect, mPaint);
+
+        // prepare paint for frame drawing
+        mPaint.setXfermode(null);
+
+        mScale = 1f;
+
+        mSrcRect = new Rect(0, 0, mSize, mSize);
+        mDstRect = new RectF(0, 0, mSize, mSize);
+    }
+
+    @Override
+    public void draw(Canvas canvas) {
+        final float inside = mScale * mSize;
+        final float pad = (mSize - inside) / 2f;
+
+        mDstRect.set(pad, pad, mSize - pad, mSize - pad);
+        canvas.drawBitmap(mBitmap, mSrcRect, mDstRect, null);
+    }
+
+    public void setScale(float scale) {
+        mScale = scale;
+    }
+
+    public float getScale() {
+        return mScale;
+    }
+
+    @Override
+    public int getOpacity() {
+        return PixelFormat.TRANSLUCENT;
+    }
+
+    @Override
+    public void setAlpha(int alpha) {
+    }
+
+    @Override
+    public void setColorFilter(ColorFilter cf) {
+    }
+    
+    @Override
+    public int getIntrinsicWidth() {
+        return mSize;
+    }
+
+    @Override
+    public int getIntrinsicHeight() {
+        return mSize;
+    }
+}
diff --git a/packages/SettingsLib/src/com/android/settingslib/net/SummaryForAllUidLoader.java b/packages/SettingsLib/src/com/android/settingslib/net/SummaryForAllUidLoader.java
new file mode 100644
index 0000000..572bae1
--- /dev/null
+++ b/packages/SettingsLib/src/com/android/settingslib/net/SummaryForAllUidLoader.java
@@ -0,0 +1,79 @@
+/*
+ * Copyright (C) 2011 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.settingslib.net;
+
+import android.content.AsyncTaskLoader;
+import android.content.Context;
+import android.net.INetworkStatsSession;
+import android.net.NetworkStats;
+import android.net.NetworkTemplate;
+import android.os.Bundle;
+import android.os.RemoteException;
+
+public class SummaryForAllUidLoader extends AsyncTaskLoader<NetworkStats> {
+    private static final String KEY_TEMPLATE = "template";
+    private static final String KEY_START = "start";
+    private static final String KEY_END = "end";
+
+    private final INetworkStatsSession mSession;
+    private final Bundle mArgs;
+
+    public static Bundle buildArgs(NetworkTemplate template, long start, long end) {
+        final Bundle args = new Bundle();
+        args.putParcelable(KEY_TEMPLATE, template);
+        args.putLong(KEY_START, start);
+        args.putLong(KEY_END, end);
+        return args;
+    }
+
+    public SummaryForAllUidLoader(Context context, INetworkStatsSession session, Bundle args) {
+        super(context);
+        mSession = session;
+        mArgs = args;
+    }
+
+    @Override
+    protected void onStartLoading() {
+        super.onStartLoading();
+        forceLoad();
+    }
+
+    @Override
+    public NetworkStats loadInBackground() {
+        final NetworkTemplate template = mArgs.getParcelable(KEY_TEMPLATE);
+        final long start = mArgs.getLong(KEY_START);
+        final long end = mArgs.getLong(KEY_END);
+
+        try {
+            return mSession.getSummaryForAllUid(template, start, end, false);
+        } catch (RemoteException e) {
+            return null;
+        }
+    }
+
+    @Override
+    protected void onStopLoading() {
+        super.onStopLoading();
+        cancelLoad();
+    }
+
+    @Override
+    protected void onReset() {
+        super.onReset();
+        cancelLoad();
+    }
+}
diff --git a/packages/SettingsLib/src/com/android/settingslib/net/UidDetail.java b/packages/SettingsLib/src/com/android/settingslib/net/UidDetail.java
new file mode 100644
index 0000000..5e42281
--- /dev/null
+++ b/packages/SettingsLib/src/com/android/settingslib/net/UidDetail.java
@@ -0,0 +1,27 @@
+/*
+ * Copyright (C) 2011 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.settingslib.net;
+
+import android.graphics.drawable.Drawable;
+
+public class UidDetail {
+    public CharSequence label;
+    public CharSequence contentDescription;
+    public CharSequence[] detailLabels;
+    public CharSequence[] detailContentDescriptions;
+    public Drawable icon;
+}
diff --git a/packages/SettingsLib/src/com/android/settingslib/net/UidDetailProvider.java b/packages/SettingsLib/src/com/android/settingslib/net/UidDetailProvider.java
new file mode 100644
index 0000000..224b967
--- /dev/null
+++ b/packages/SettingsLib/src/com/android/settingslib/net/UidDetailProvider.java
@@ -0,0 +1,194 @@
+/*
+ * Copyright (C) 2011 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.settingslib.net;
+
+import android.app.AppGlobals;
+import android.content.Context;
+import android.content.pm.ApplicationInfo;
+import android.content.pm.IPackageManager;
+import android.content.pm.PackageInfo;
+import android.content.pm.PackageManager;
+import android.content.pm.PackageManager.NameNotFoundException;
+import android.content.pm.UserInfo;
+import android.content.res.Resources;
+import android.graphics.drawable.Drawable;
+import android.net.ConnectivityManager;
+import android.net.TrafficStats;
+import android.os.UserManager;
+import android.os.UserHandle;
+import android.os.RemoteException;
+import android.text.TextUtils;
+import android.util.Log;
+import android.util.SparseArray;
+
+import com.android.settingslib.R;
+import com.android.settingslib.Utils;
+
+/**
+ * Return details about a specific UID, handling special cases like
+ * {@link TrafficStats#UID_TETHERING} and {@link UserInfo}.
+ */
+public class UidDetailProvider {
+    private static final String TAG = "DataUsage";
+    private final Context mContext;
+    private final SparseArray<UidDetail> mUidDetailCache;
+
+    public static final int OTHER_USER_RANGE_START = -2000;
+
+    public static int buildKeyForUser(int userHandle) {
+        return OTHER_USER_RANGE_START - userHandle;
+    }
+
+    public static boolean isKeyForUser(int key) {
+        return key <= OTHER_USER_RANGE_START;
+    }
+
+    public static int getUserIdForKey(int key) {
+        return OTHER_USER_RANGE_START - key;
+    }
+
+    public UidDetailProvider(Context context) {
+        mContext = context.getApplicationContext();
+        mUidDetailCache = new SparseArray<UidDetail>();
+    }
+
+    public void clearCache() {
+        synchronized (mUidDetailCache) {
+            mUidDetailCache.clear();
+        }
+    }
+
+    /**
+     * Resolve best descriptive label for the given UID.
+     */
+    public UidDetail getUidDetail(int uid, boolean blocking) {
+        UidDetail detail;
+
+        synchronized (mUidDetailCache) {
+            detail = mUidDetailCache.get(uid);
+        }
+
+        if (detail != null) {
+            return detail;
+        } else if (!blocking) {
+            return null;
+        }
+
+        detail = buildUidDetail(uid);
+
+        synchronized (mUidDetailCache) {
+            mUidDetailCache.put(uid, detail);
+        }
+
+        return detail;
+    }
+
+    /**
+     * Build {@link UidDetail} object, blocking until all {@link Drawable}
+     * lookup is finished.
+     */
+    private UidDetail buildUidDetail(int uid) {
+        final Resources res = mContext.getResources();
+        final PackageManager pm = mContext.getPackageManager();
+
+        final UidDetail detail = new UidDetail();
+        detail.label = pm.getNameForUid(uid);
+        detail.icon = pm.getDefaultActivityIcon();
+
+        // handle special case labels
+        switch (uid) {
+            case android.os.Process.SYSTEM_UID:
+                detail.label = res.getString(R.string.process_kernel_label);
+                detail.icon = pm.getDefaultActivityIcon();
+                return detail;
+            case TrafficStats.UID_REMOVED:
+                detail.label = res.getString(UserManager.supportsMultipleUsers()
+                        ? R.string.data_usage_uninstalled_apps_users
+                        : R.string.data_usage_uninstalled_apps);
+                detail.icon = pm.getDefaultActivityIcon();
+                return detail;
+            case TrafficStats.UID_TETHERING:
+                final ConnectivityManager cm = (ConnectivityManager) mContext.getSystemService(
+                        Context.CONNECTIVITY_SERVICE);
+                detail.label = res.getString(Utils.getTetheringLabel(cm));
+                detail.icon = pm.getDefaultActivityIcon();
+                return detail;
+        }
+
+        final UserManager um = (UserManager) mContext.getSystemService(Context.USER_SERVICE);
+
+        // Handle keys that are actually user handles
+        if (isKeyForUser(uid)) {
+            final int userHandle = getUserIdForKey(uid);
+            final UserInfo info = um.getUserInfo(userHandle);
+            if (info != null) {
+                detail.label = Utils.getUserLabel(mContext, info);
+                detail.icon = Utils.getUserIcon(mContext, um, info);
+                return detail;
+            }
+        }
+
+        // otherwise fall back to using packagemanager labels
+        final String[] packageNames = pm.getPackagesForUid(uid);
+        final int length = packageNames != null ? packageNames.length : 0;
+        try {
+            final int userId = UserHandle.getUserId(uid);
+            UserHandle userHandle = new UserHandle(userId);
+            IPackageManager ipm = AppGlobals.getPackageManager();
+            if (length == 1) {
+                final ApplicationInfo info = ipm.getApplicationInfo(packageNames[0],
+                        0 /* no flags */, userId);
+                if (info != null) {
+                    detail.label = info.loadLabel(pm).toString();
+                    detail.icon = um.getBadgedIconForUser(info.loadIcon(pm),
+                            new UserHandle(userId));
+                }
+            } else if (length > 1) {
+                detail.detailLabels = new CharSequence[length];
+                detail.detailContentDescriptions = new CharSequence[length];
+                for (int i = 0; i < length; i++) {
+                    final String packageName = packageNames[i];
+                    final PackageInfo packageInfo = pm.getPackageInfo(packageName, 0);
+                    final ApplicationInfo appInfo = ipm.getApplicationInfo(packageName,
+                            0 /* no flags */, userId);
+
+                    if (appInfo != null) {
+                        detail.detailLabels[i] = appInfo.loadLabel(pm).toString();
+                        detail.detailContentDescriptions[i] = um.getBadgedLabelForUser(
+                                detail.detailLabels[i], userHandle);
+                        if (packageInfo.sharedUserLabel != 0) {
+                            detail.label = pm.getText(packageName, packageInfo.sharedUserLabel,
+                                    packageInfo.applicationInfo).toString();
+                            detail.icon = um.getBadgedIconForUser(appInfo.loadIcon(pm), userHandle);
+                        }
+                    }
+                }
+            }
+            detail.contentDescription = um.getBadgedLabelForUser(detail.label, userHandle);
+        } catch (NameNotFoundException e) {
+            Log.w(TAG, "Error while building UI detail for uid "+uid, e);
+        } catch (RemoteException e) {
+            Log.w(TAG, "Error while building UI detail for uid "+uid, e);
+        }
+
+        if (TextUtils.isEmpty(detail.label)) {
+            detail.label = Integer.toString(uid);
+        }
+
+        return detail;
+    }
+}
diff --git a/packages/Shell/AndroidManifest.xml b/packages/Shell/AndroidManifest.xml
index 345f682..efacd2c 100644
--- a/packages/Shell/AndroidManifest.xml
+++ b/packages/Shell/AndroidManifest.xml
@@ -104,6 +104,7 @@
     <uses-permission android:name="android.permission.REGISTER_CALL_PROVIDER" />
     <uses-permission android:name="android.permission.REGISTER_CONNECTION_MANAGER" />
     <uses-permission android:name="android.permission.REGISTER_SIM_SUBSCRIPTION" />
+    <uses-permission android:name="android.permission.GET_APP_OPS_STATS" />
 
     <application android:label="@string/app_label">
         <provider
diff --git a/packages/SystemUI/AndroidManifest.xml b/packages/SystemUI/AndroidManifest.xml
index 8ab53b8..e4fc075 100644
--- a/packages/SystemUI/AndroidManifest.xml
+++ b/packages/SystemUI/AndroidManifest.xml
@@ -168,14 +168,14 @@
                 android:permission="android.permission.BIND_WALLPAPER"
                 android:exported="true" />
 
-        <receiver android:name=".BootReceiver" androidprv:primaryUserOnly="true">
+        <receiver android:name=".BootReceiver" androidprv:systemUserOnly="true">
             <intent-filter android:priority="1000">
                 <action android:name="android.intent.action.BOOT_COMPLETED" />
             </intent-filter>
         </receiver>
 
         <receiver android:name=".qs.tiles.HotspotTile$APChangedReceiver"
-                androidprv:primaryUserOnly="true">
+                androidprv:systemUserOnly="true">
             <intent-filter>
                 <action android:name="android.net.wifi.WIFI_AP_STATE_CHANGED" />
             </intent-filter>
diff --git a/packages/SystemUI/res/values-fr-rCA/strings.xml b/packages/SystemUI/res/values-fr-rCA/strings.xml
index 4e57f2b5..f99447c 100644
--- a/packages/SystemUI/res/values-fr-rCA/strings.xml
+++ b/packages/SystemUI/res/values-fr-rCA/strings.xml
@@ -435,6 +435,6 @@
     <string name="remove_from_settings" msgid="8389591916603406378">"Supprimer des paramètres"</string>
     <string name="remove_from_settings_prompt" msgid="6069085993355887748">"Supprimer « System UI Tuner » des paramètres et arrêter d\'utiliser toutes ses fonctionnalités?"</string>
     <string name="activity_not_found" msgid="348423244327799974">"L\'application n\'est pas installée sur votre appareil"</string>
-    <string name="clock_seconds" msgid="7689554147579179507">"Afficher les secondes de l\'horloge"</string>
-    <string name="clock_seconds_desc" msgid="6282693067130470675">"Afficher les secondes de l\'horloge dans la barre d\'état. Cela peut influer sur l\'autonomie de la pile."</string>
+    <string name="clock_seconds" msgid="7689554147579179507">"Afficher les secondes sur l\'horloge"</string>
+    <string name="clock_seconds_desc" msgid="6282693067130470675">"Afficher les secondes sur l\'horloge dans la barre d\'état. Cela peut réduire l\'autonomie de la pile."</string>
 </resources>
diff --git a/packages/SystemUI/res/values-ja/strings.xml b/packages/SystemUI/res/values-ja/strings.xml
index b9bfba9..9cb2fc8 100644
--- a/packages/SystemUI/res/values-ja/strings.xml
+++ b/packages/SystemUI/res/values-ja/strings.xml
@@ -88,7 +88,7 @@
     <string name="accessibility_voice_assist_button" msgid="487611083884852965">"音声アシスト"</string>
     <string name="accessibility_unlock_button" msgid="128158454631118828">"ロック解除"</string>
     <string name="accessibility_unlock_button_fingerprint" msgid="8214125623493923751">"ロック解除ボタン、指紋を待っています"</string>
-    <string name="accessibility_unlock_without_fingerprint" msgid="7541705575183694446">"指紋を使用せずにロック解除"</string>
+    <string name="accessibility_unlock_without_fingerprint" msgid="7541705575183694446">"指紋認証を使用せずにロック解除"</string>
     <string name="unlock_label" msgid="8779712358041029439">"ロック解除"</string>
     <string name="phone_label" msgid="2320074140205331708">"電話を起動"</string>
     <string name="voice_assist_label" msgid="3956854378310019854">"音声アシストを開く"</string>
diff --git a/packages/SystemUI/src/com/android/systemui/media/MediaProjectionPermissionActivity.java b/packages/SystemUI/src/com/android/systemui/media/MediaProjectionPermissionActivity.java
index 2a84362..adc9b36 100644
--- a/packages/SystemUI/src/com/android/systemui/media/MediaProjectionPermissionActivity.java
+++ b/packages/SystemUI/src/com/android/systemui/media/MediaProjectionPermissionActivity.java
@@ -22,6 +22,7 @@
 import android.content.Intent;
 import android.content.pm.ApplicationInfo;
 import android.content.pm.PackageManager;
+import android.graphics.Typeface;
 import android.media.projection.MediaProjectionManager;
 import android.media.projection.IMediaProjectionManager;
 import android.media.projection.IMediaProjection;
@@ -29,7 +30,14 @@
 import android.os.IBinder;
 import android.os.RemoteException;
 import android.os.ServiceManager;
+import android.text.BidiFormatter;
+import android.text.Spannable;
+import android.text.SpannableString;
+import android.text.TextPaint;
+import android.text.TextUtils;
+import android.text.style.StyleSpan;
 import android.util.Log;
+import android.util.TypedValue;
 import android.view.WindowManager;
 import android.widget.CheckBox;
 import android.widget.CompoundButton;
@@ -39,6 +47,8 @@
         implements DialogInterface.OnClickListener, CheckBox.OnCheckedChangeListener,
         DialogInterface.OnCancelListener {
     private static final String TAG = "MediaProjectionPermissionActivity";
+    private static final float MAX_APP_NAME_SIZE_PX = 500f;
+    private static final String ELLIPSIS = "\u2026";
 
     private boolean mPermanentGrant;
     private String mPackageName;
@@ -84,11 +94,49 @@
             return;
         }
 
-        String appName = aInfo.loadLabel(packageManager).toString();
+        TextPaint paint = new TextPaint();
+        paint.setTextSize(42);
+
+        String label = aInfo.loadLabel(packageManager).toString();
+
+        // If the label contains new line characters it may push the security
+        // message below the fold of the dialog. Labels shouldn't have new line
+        // characters anyways, so just truncate the message the first time one
+        // is seen.
+        final int labelLength = label.length();
+        int offset = 0;
+        while (offset < labelLength) {
+            final int codePoint = label.codePointAt(offset);
+            final int type = Character.getType(codePoint);
+            if (type == Character.LINE_SEPARATOR
+                    || type == Character.CONTROL
+                    || type == Character.PARAGRAPH_SEPARATOR) {
+                label = label.substring(0, offset) + ELLIPSIS;
+                break;
+            }
+            offset += Character.charCount(codePoint);
+        }
+
+        if (label.isEmpty()) {
+            label = mPackageName;
+        }
+
+        String unsanitizedAppName = TextUtils.ellipsize(label,
+                paint, MAX_APP_NAME_SIZE_PX, TextUtils.TruncateAt.END).toString();
+        String appName = BidiFormatter.getInstance().unicodeWrap(unsanitizedAppName);
+
+        String actionText = getString(R.string.media_projection_dialog_text, appName);
+        SpannableString message = new SpannableString(actionText);
+
+        int appNameIndex = actionText.indexOf(appName);
+        if (appNameIndex >= 0) {
+            message.setSpan(new StyleSpan(Typeface.BOLD),
+                    appNameIndex, appNameIndex + appName.length(), 0);
+        }
 
         mDialog = new AlertDialog.Builder(this)
                 .setIcon(aInfo.loadIcon(packageManager))
-                .setMessage(getString(R.string.media_projection_dialog_text, appName))
+                .setMessage(message)
                 .setPositiveButton(R.string.media_projection_action_text, this)
                 .setNegativeButton(android.R.string.cancel, this)
                 .setView(R.layout.remember_permission_checkbox)
diff --git a/packages/SystemUI/src/com/android/systemui/media/NotificationPlayer.java b/packages/SystemUI/src/com/android/systemui/media/NotificationPlayer.java
index 803a014..728d558 100644
--- a/packages/SystemUI/src/com/android/systemui/media/NotificationPlayer.java
+++ b/packages/SystemUI/src/com/android/systemui/media/NotificationPlayer.java
@@ -21,6 +21,7 @@
 import android.media.AudioManager;
 import android.media.MediaPlayer;
 import android.media.MediaPlayer.OnCompletionListener;
+import android.media.MediaPlayer.OnErrorListener;
 import android.net.Uri;
 import android.os.Looper;
 import android.os.PowerManager;
@@ -36,7 +37,7 @@
  * - whenever audio is played, audio focus is requested,
  * - whenever audio playback is stopped or the playback completed, audio focus is abandoned.
  */
-public class NotificationPlayer implements OnCompletionListener {
+public class NotificationPlayer implements OnCompletionListener, OnErrorListener {
     private static final int PLAY = 1;
     private static final int STOP = 2;
     private static final boolean mDebug = false;
@@ -112,6 +113,7 @@
                     //  done playing. This class should be modified to use a single thread, on which
                     //  command are issued, and on which it receives the completion callbacks.
                     player.setOnCompletionListener(NotificationPlayer.this);
+                    player.setOnErrorListener(NotificationPlayer.this);
                     player.start();
                     if (mPlayer != null) {
                         mPlayer.release();
@@ -245,6 +247,13 @@
         }
     }
 
+    public boolean onError(MediaPlayer mp, int what, int extra) {
+        Log.e(mTag, "error " + what + " (extra=" + extra + ") playing notification");
+        // error happened, handle it just like a completion
+        onCompletion(mp);
+        return true;
+    }
+
     private String mTag;
     private CmdThread mThread;
     private CreationAndCompletionThread mCompletionThread;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/CommandQueue.java b/packages/SystemUI/src/com/android/systemui/statusbar/CommandQueue.java
index d0cd6cb..b01a2a8 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/CommandQueue.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/CommandQueue.java
@@ -64,7 +64,8 @@
     private static final int MSG_APP_TRANSITION_STARTING    = 21 << MSG_SHIFT;
     private static final int MSG_ASSIST_DISCLOSURE          = 22 << MSG_SHIFT;
     private static final int MSG_START_ASSIST               = 23 << MSG_SHIFT;
-    private static final int MSG_SHOW_KEYBOARD_SHORTCUTS    = 24 << MSG_SHIFT;
+    private static final int MSG_CAMERA_LAUNCH_GESTURE      = 24 << MSG_SHIFT;
+    private static final int MSG_SHOW_KEYBOARD_SHORTCUTS    = 25 << MSG_SHIFT;
 
     public static final int FLAG_EXCLUDE_NONE = 0;
     public static final int FLAG_EXCLUDE_SEARCH_PANEL = 1 << 0;
@@ -111,6 +112,7 @@
         public void appTransitionStarting(long startTime, long duration);
         public void showAssistDisclosure();
         public void startAssist(Bundle args);
+        public void onCameraLaunchGestureDetected();
     }
 
     public CommandQueue(Callbacks callbacks, StatusBarIconList list) {
@@ -303,6 +305,14 @@
         }
     }
 
+    @Override
+    public void onCameraLaunchGestureDetected() {
+        synchronized (mList) {
+            mHandler.removeMessages(MSG_CAMERA_LAUNCH_GESTURE);
+            mHandler.obtainMessage(MSG_CAMERA_LAUNCH_GESTURE).sendToTarget();
+        }
+    }
+
     private final class H extends Handler {
         public void handleMessage(Message msg) {
             final int what = msg.what & MSG_MASK;
@@ -404,6 +414,9 @@
                 case MSG_START_ASSIST:
                     mCallbacks.startAssist((Bundle) msg.obj);
                     break;
+                case MSG_CAMERA_LAUNCH_GESTURE:
+                    mCallbacks.onCameraLaunchGestureDetected();
+                    break;
             }
         }
     }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableNotificationRow.java b/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableNotificationRow.java
index 2f6aec7..564a60a 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableNotificationRow.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableNotificationRow.java
@@ -24,6 +24,7 @@
 import android.graphics.drawable.AnimationDrawable;
 import android.graphics.drawable.ColorDrawable;
 import android.graphics.drawable.Drawable;
+import android.graphics.drawable.RippleDrawable;
 import android.service.notification.StatusBarNotification;
 import android.util.AttributeSet;
 import android.view.MotionEvent;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/KeyguardAffordanceView.java b/packages/SystemUI/src/com/android/systemui/statusbar/KeyguardAffordanceView.java
index 164c496..8058933 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/KeyguardAffordanceView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/KeyguardAffordanceView.java
@@ -36,6 +36,7 @@
 import android.view.animation.AnimationUtils;
 import android.view.animation.Interpolator;
 import android.widget.ImageView;
+
 import com.android.systemui.R;
 import com.android.systemui.statusbar.phone.KeyguardAffordanceHelper;
 import com.android.systemui.statusbar.phone.PhoneStatusBar;
@@ -79,6 +80,7 @@
     private float mRestingAlpha = KeyguardAffordanceHelper.SWIPE_RESTING_ALPHA_AMOUNT;
     private boolean mSupportHardware;
     private boolean mFinishing;
+    private boolean mLaunchingAffordance;
 
     private CanvasProperty<Float> mHwCircleRadius;
     private CanvasProperty<Float> mHwCenterX;
@@ -152,7 +154,7 @@
 
     @Override
     protected void onDraw(Canvas canvas) {
-        mSupportHardware = canvas.isHardwareAccelerated();
+        mSupportHardware = false;//canvas.isHardwareAccelerated();
         drawBackgroundCircle(canvas);
         canvas.save();
         canvas.scale(mImageScale, mImageScale, getWidth() / 2, getHeight() / 2);
@@ -161,9 +163,11 @@
     }
 
     public void setPreviewView(View v) {
+        View oldPreviewView = mPreviewView;
         mPreviewView = v;
         if (mPreviewView != null) {
-            mPreviewView.setVisibility(INVISIBLE);
+            mPreviewView.setVisibility(mLaunchingAffordance
+                    ? oldPreviewView.getVisibility() : INVISIBLE);
         }
     }
 
@@ -176,7 +180,7 @@
     }
 
     private void drawBackgroundCircle(Canvas canvas) {
-        if (mCircleRadius > 0) {
+        if (mCircleRadius > 0 || mFinishing) {
             if (mFinishing && mSupportHardware) {
                 DisplayListCanvas displayListCanvas = (DisplayListCanvas) canvas;
                 displayListCanvas.drawCircle(mHwCenterX, mHwCenterY, mHwCircleRadius,
@@ -207,11 +211,12 @@
         cancelAnimator(mPreviewClipper);
         mFinishing = true;
         mCircleStartRadius = mCircleRadius;
-        float maxCircleSize = getMaxCircleSize();
+        final float maxCircleSize = getMaxCircleSize();
         Animator animatorToRadius;
         if (mSupportHardware) {
             initHwProperties();
             animatorToRadius = getRtAnimatorToRadius(maxCircleSize);
+            startRtAlphaFadeIn();
         } else {
             animatorToRadius = getAnimatorToRadius(maxCircleSize);
         }
@@ -222,6 +227,8 @@
             public void onAnimationEnd(Animator animation) {
                 mAnimationEndRunnable.run();
                 mFinishing = false;
+                mCircleRadius = maxCircleSize;
+                invalidate();
             }
         });
         animatorToRadius.start();
@@ -241,6 +248,36 @@
         }
     }
 
+    /**
+     * Fades in the Circle on the RenderThread. It's used when finishing the circle when it had
+     * alpha 0 in the beginning.
+     */
+    private void startRtAlphaFadeIn() {
+        if (mCircleRadius == 0 && mPreviewView == null) {
+            Paint modifiedPaint = new Paint(mCirclePaint);
+            modifiedPaint.setColor(mCircleColor);
+            modifiedPaint.setAlpha(0);
+            mHwCirclePaint = CanvasProperty.createPaint(modifiedPaint);
+            RenderNodeAnimator animator = new RenderNodeAnimator(mHwCirclePaint,
+                    RenderNodeAnimator.PAINT_ALPHA, 255);
+            animator.setTarget(this);
+            animator.setInterpolator(PhoneStatusBar.ALPHA_IN);
+            animator.setDuration(250);
+            animator.start();
+        }
+    }
+
+    public void instantFinishAnimation() {
+        cancelAnimator(mPreviewClipper);
+        if (mPreviewView != null) {
+            mPreviewView.setClipBounds(null);
+            mPreviewView.setVisibility(View.VISIBLE);
+        }
+        mCircleRadius = getMaxCircleSize();
+        setImageAlpha(0, false);
+        invalidate();
+    }
+
     private void startRtCircleFadeOut(long duration) {
         RenderNodeAnimator animator = new RenderNodeAnimator(mHwCirclePaint,
                 RenderNodeAnimator.PAINT_ALPHA, 0);
@@ -443,6 +480,7 @@
     public void setImageAlpha(float alpha, boolean animate, long duration,
             Interpolator interpolator, Runnable runnable) {
         cancelAnimator(mAlphaAnimator);
+        alpha = mLaunchingAffordance ? 0 : alpha;
         int endAlpha = (int) (alpha * 255);
         final Drawable background = getBackground();
         if (!animate) {
@@ -509,4 +547,8 @@
             return false;
         }
     }
+
+    public void setLaunchingAffordance(boolean launchingAffordance) {
+        mLaunchingAffordance = launchingAffordance;
+    }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationBackgroundView.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationBackgroundView.java
index 01aa8d1..8688c28 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationBackgroundView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationBackgroundView.java
@@ -86,6 +86,9 @@
         if (mBackground != null) {
             mBackground.setCallback(this);
         }
+        if (mBackground instanceof RippleDrawable) {
+            ((RippleDrawable) mBackground).setForceSoftware(true);
+        }
         invalidate();
     }
 
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/AppInfo.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/AppInfo.java
index 5ec5147..e34c821 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/AppInfo.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/AppInfo.java
@@ -17,24 +17,26 @@
 package com.android.systemui.statusbar.phone;
 
 import android.content.ComponentName;
+import android.os.UserHandle;
 
 /**
  * Navigation bar app information.
  */
 class AppInfo {
     private final ComponentName mComponentName;
-    private final long mUserSerialNumber;
+    private final UserHandle mUser;
 
-    public AppInfo(ComponentName componentName, long userSerialNumber) {
+    public AppInfo(ComponentName componentName, UserHandle user) {
+        if (componentName == null || user == null) throw new IllegalArgumentException();
         mComponentName = componentName;
-        mUserSerialNumber = userSerialNumber;
+        mUser = user;
     }
 
     public ComponentName getComponentName() {
         return mComponentName;
     }
 
-    public long getUserSerialNumber() {
-        return mUserSerialNumber;
+    public UserHandle getUser() {
+        return mUser;
     }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/GetActivityIconTask.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/GetActivityIconTask.java
index 076378e..f46d1a6 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/GetActivityIconTask.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/GetActivityIconTask.java
@@ -16,20 +16,21 @@
 
 package com.android.systemui.statusbar.phone;
 
-import android.content.ComponentName;
+import android.app.AppGlobals;
+import android.content.pm.ActivityInfo;
+import android.content.pm.IPackageManager;
 import android.content.pm.PackageManager;
-import android.content.pm.PackageManager.NameNotFoundException;
 import android.graphics.drawable.Drawable;
 import android.os.AsyncTask;
+import android.os.RemoteException;
 import android.util.Slog;
-import android.view.View;
 import android.widget.ImageView;
 
 /**
  * Retrieves the icon for an activity and sets it as the Drawable on an ImageView. The ImageView
  * is hidden if the activity isn't recognized or if there is no icon.
  */
-class GetActivityIconTask extends AsyncTask<ComponentName, Void, Drawable> {
+class GetActivityIconTask extends AsyncTask<AppInfo, Void, Drawable> {
     private final static String TAG = "GetActivityIconTask";
 
     private final PackageManager mPackageManager;
@@ -43,15 +44,27 @@
     }
 
     @Override
-    protected Drawable doInBackground(ComponentName... params) {
+    protected Drawable doInBackground(AppInfo... params) {
         if (params.length != 1) {
             throw new IllegalArgumentException("Expected one parameter");
         }
-        ComponentName activityName = params[0];
+        AppInfo appInfo = params[0];
         try {
-            return mPackageManager.getActivityIcon(activityName);
-        } catch (NameNotFoundException e) {
-            Slog.w(TAG, "Icon not found for " + activityName);
+            IPackageManager mPM = AppGlobals.getPackageManager();
+            ActivityInfo ai = mPM.getActivityInfo(
+                    appInfo.getComponentName(),
+                    0,
+                    appInfo.getUser().getIdentifier());
+
+            if (ai == null) {
+                Slog.w(TAG, "Icon not found for " + appInfo);
+                return null;
+            }
+
+            Drawable unbadgedIcon = ai.loadIcon(mPackageManager);
+            return mPackageManager.getUserBadgedIcon(unbadgedIcon, appInfo.getUser());
+        } catch (RemoteException e) {
+            Slog.w(TAG, "Icon not found for " + appInfo, e);
             return null;
         }
     }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardAffordanceHelper.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardAffordanceHelper.java
index 10019f9..60ebfdf 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardAffordanceHelper.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardAffordanceHelper.java
@@ -86,9 +86,9 @@
         mContext = context;
         mCallback = callback;
         initIcons();
-        updateIcon(mLeftIcon, 0.0f, mLeftIcon.getRestingAlpha(), false, false, true);
-        updateIcon(mCenterIcon, 0.0f, mCenterIcon.getRestingAlpha(), false, false, true);
-        updateIcon(mRightIcon, 0.0f, mRightIcon.getRestingAlpha(), false, false, true);
+        updateIcon(mLeftIcon, 0.0f, mLeftIcon.getRestingAlpha(), false, false, true, false);
+        updateIcon(mCenterIcon, 0.0f, mCenterIcon.getRestingAlpha(), false, false, true, false);
+        updateIcon(mRightIcon, 0.0f, mRightIcon.getRestingAlpha(), false, false, true, false);
         initDimens();
     }
 
@@ -144,9 +144,7 @@
                 } else {
                     mTouchSlopExeeded = false;
                 }
-                mCallback.onSwipingStarted(targetView == mRightIcon);
-                mSwipingInProgress = true;
-                mTargetedView = targetView;
+                startSwiping(targetView);
                 mInitialTouchX = x;
                 mInitialTouchY = y;
                 mTranslationOnDown = mTranslation;
@@ -192,6 +190,12 @@
         return true;
     }
 
+    private void startSwiping(View targetView) {
+        mCallback.onSwipingStarted(targetView == mRightIcon);
+        mSwipingInProgress = true;
+        mTargetedView = targetView;
+    }
+
     private View getIconAtPosition(float x, float y) {
         if (leftSwipePossible() && isOnIcon(mLeftIcon, x, y)) {
             return mLeftIcon;
@@ -324,7 +328,7 @@
         boolean velIsInWrongDirection = vel * mTranslation < 0;
         snapBack |= Math.abs(vel) > mMinFlingVelocity && velIsInWrongDirection;
         vel = snapBack ^ velIsInWrongDirection ? 0 : vel;
-        fling(vel, snapBack || forceSnapBack);
+        fling(vel, snapBack || forceSnapBack, mTranslation < 0);
     }
 
     private boolean isBelowFalsingThreshold() {
@@ -336,9 +340,8 @@
         return (int) (mMinTranslationAmount * factor);
     }
 
-    private void fling(float vel, final boolean snapBack) {
-        float target = mTranslation < 0
-                ? -mCallback.getMaxTranslationDistance()
+    private void fling(float vel, final boolean snapBack, boolean right) {
+        float target = right ? -mCallback.getMaxTranslationDistance()
                 : mCallback.getMaxTranslationDistance();
         target = snapBack ? 0 : target;
 
@@ -352,8 +355,8 @@
         });
         animator.addListener(mFlingEndListener);
         if (!snapBack) {
-            startFinishingCircleAnimation(vel * 0.375f, mAnimationEndRunnable);
-            mCallback.onAnimationToSideStarted(mTranslation < 0, mTranslation, vel);
+            startFinishingCircleAnimation(vel * 0.375f, mAnimationEndRunnable, right);
+            mCallback.onAnimationToSideStarted(right, mTranslation, vel);
         } else {
             reset(true);
         }
@@ -364,8 +367,9 @@
         }
     }
 
-    private void startFinishingCircleAnimation(float velocity, Runnable mAnimationEndRunnable) {
-        KeyguardAffordanceView targetView = mTranslation > 0 ? mLeftIcon : mRightIcon;
+    private void startFinishingCircleAnimation(float velocity, Runnable mAnimationEndRunnable,
+            boolean right) {
+        KeyguardAffordanceView targetView = right ? mRightIcon : mLeftIcon;
         targetView.finishAnimation(velocity, mAnimationEndRunnable);
     }
 
@@ -383,19 +387,20 @@
             fadeOutAlpha = Math.max(fadeOutAlpha, 0.0f);
 
             boolean animateIcons = isReset && animateReset;
+            boolean forceNoCircleAnimation = isReset && !animateReset;
             float radius = getRadiusFromTranslation(absTranslation);
             boolean slowAnimation = isReset && isBelowFalsingThreshold();
             if (!isReset) {
                 updateIcon(targetView, radius, alpha + fadeOutAlpha * targetView.getRestingAlpha(),
-                        false, false, false);
+                        false, false, false, false);
             } else {
                 updateIcon(targetView, 0.0f, fadeOutAlpha * targetView.getRestingAlpha(),
-                        animateIcons, slowAnimation, false);
+                        animateIcons, slowAnimation, false, forceNoCircleAnimation);
             }
             updateIcon(otherView, 0.0f, fadeOutAlpha * otherView.getRestingAlpha(),
-                    animateIcons, slowAnimation, false);
+                    animateIcons, slowAnimation, false, forceNoCircleAnimation);
             updateIcon(mCenterIcon, 0.0f, fadeOutAlpha * mCenterIcon.getRestingAlpha(),
-                    animateIcons, slowAnimation, false);
+                    animateIcons, slowAnimation, false, forceNoCircleAnimation);
 
             mTranslation = translation;
         }
@@ -431,16 +436,21 @@
 
     public void animateHideLeftRightIcon() {
         cancelAnimation();
-        updateIcon(mRightIcon, 0f, 0f, true, false, false);
-        updateIcon(mLeftIcon, 0f, 0f, true, false, false);
+        updateIcon(mRightIcon, 0f, 0f, true, false, false, false);
+        updateIcon(mLeftIcon, 0f, 0f, true, false, false, false);
     }
 
     private void updateIcon(KeyguardAffordanceView view, float circleRadius, float alpha,
-            boolean animate, boolean slowRadiusAnimation, boolean force) {
+                            boolean animate, boolean slowRadiusAnimation, boolean force,
+                            boolean forceNoCircleAnimation) {
         if (view.getVisibility() != View.VISIBLE && !force) {
             return;
         }
-        view.setCircleRadius(circleRadius, slowRadiusAnimation);
+        if (forceNoCircleAnimation) {
+            view.setCircleRadiusWithoutAnimation(circleRadius);
+        } else {
+            view.setCircleRadius(circleRadius, slowRadiusAnimation);
+        }
         updateIconAlpha(view, alpha, animate);
     }
 
@@ -503,8 +513,36 @@
         mMotionCancelled = true;
         if (mSwipingInProgress) {
             mCallback.onSwipingAborted();
+            mSwipingInProgress = false;
         }
-        mSwipingInProgress = false;
+    }
+
+    public boolean isSwipingInProgress() {
+        return mSwipingInProgress;
+    }
+
+    public void launchAffordance(boolean animate, boolean left) {
+        if (mSwipingInProgress) {
+            // We don't want to mess with the state if the user is actually swiping already.
+            return;
+        }
+        KeyguardAffordanceView targetView = left ? mLeftIcon : mRightIcon;
+        KeyguardAffordanceView otherView = left ? mRightIcon : mLeftIcon;
+        startSwiping(targetView);
+        if (animate) {
+            fling(0, false, !left);
+            updateIcon(otherView, 0.0f, 0, true, false, true, false);
+            updateIcon(mCenterIcon, 0.0f, 0, true, false, true, false);
+        } else {
+            mCallback.onAnimationToSideStarted(!left, mTranslation, 0);
+            mTranslation = left ? mCallback.getMaxTranslationDistance()
+                    : mCallback.getMaxTranslationDistance();
+            updateIcon(mCenterIcon, 0.0f, 0.0f, false, false, true, false);
+            updateIcon(otherView, 0.0f, 0.0f, false, false, true, false);
+            targetView.instantFinishAnimation();
+            mFlingEndListener.onAnimationEnd(null);
+            mAnimationEndRunnable.run();
+        }
     }
 
     public interface Callback {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBottomAreaView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBottomAreaView.java
index 579889d..d30411a 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBottomAreaView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBottomAreaView.java
@@ -80,7 +80,7 @@
     private static final Intent SECURE_CAMERA_INTENT =
             new Intent(MediaStore.INTENT_ACTION_STILL_IMAGE_CAMERA_SECURE)
                     .addFlags(Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS);
-    private static final Intent INSECURE_CAMERA_INTENT =
+    public static final Intent INSECURE_CAMERA_INTENT =
             new Intent(MediaStore.INTENT_ACTION_STILL_IMAGE_CAMERA);
     private static final Intent PHONE_INTENT = new Intent(Intent.ACTION_DIAL);
     private static final int DOZE_ANIMATION_STAGGER_DELAY = 48;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarApps.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarApps.java
index cb5c125..adcec98 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarApps.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarApps.java
@@ -28,14 +28,12 @@
 import android.content.Intent;
 import android.content.IntentFilter;
 import android.content.pm.ApplicationInfo;
-import android.content.pm.IPackageManager;
 import android.content.pm.PackageManager;
 import android.graphics.Rect;
 import android.os.Bundle;
 import android.os.UserHandle;
 import android.os.UserManager;
 import android.util.AttributeSet;
-import android.util.Log;
 import android.util.Slog;
 import android.view.DragEvent;
 import android.view.LayoutInflater;
@@ -48,8 +46,6 @@
 import com.android.internal.content.PackageMonitor;
 import com.android.systemui.R;
 
-import java.util.List;
-
 /**
  * Container for application icons that appear in the navigation bar. Their appearance is similar
  * to the launcher hotseat. Clicking an icon launches the associated activity. A long click will
@@ -84,8 +80,6 @@
     // When the user is not dragging this member is null.
     private View mDragView;
 
-    private long mCurrentUserSerialNumber = -1;
-
     private final BroadcastReceiver mBroadcastReceiver = new BroadcastReceiver() {
         @Override
         public void onReceive(Context context, Intent intent) {
@@ -93,6 +87,9 @@
             if (Intent.ACTION_USER_SWITCHED.equals(action)) {
                 int currentUserId = intent.getIntExtra(Intent.EXTRA_USER_HANDLE, -1);
                 onUserSwitched(currentUserId);
+            } else if (Intent.ACTION_MANAGED_PROFILE_REMOVED.equals(action)) {
+                UserHandle removedProfile = intent.getParcelableExtra(Intent.EXTRA_USER);
+                onManagedProfileRemoved(removedProfile);
             }
         }
     };
@@ -173,17 +170,17 @@
     }
 
     private void removeIfUnlauncheable(String packageName, UserHandle user) {
-        long appUserSerialNumber = mUserManager.getSerialNumberForUser(user);
-
         // Remove icons for all apps that match a package that perhaps became unlauncheable.
         for(int i = sAppsModel.getAppCount() - 1; i >= 0; --i) {
             AppInfo appInfo = sAppsModel.getApp(i);
-            if (appInfo.getUserSerialNumber() != appUserSerialNumber) continue;
+            if (!appInfo.getUser().equals(user)) continue;
 
             ComponentName appComponentName = appInfo.getComponentName();
             if (!appComponentName.getPackageName().equals(packageName)) continue;
 
-            if (sAppsModel.buildAppLaunchIntent(appComponentName, user) != null) continue;
+            if (sAppsModel.buildAppLaunchIntent(appInfo) != null) {
+                continue;
+            }
 
             removeViewAt(i);
             sAppsModel.removeApp(i);
@@ -206,14 +203,12 @@
         transition.enableTransitionType(LayoutTransition.CHANGING);
         parent.setLayoutTransition(transition);
 
-        int currentUserId = ActivityManager.getCurrentUser();
-        mCurrentUserSerialNumber = mUserManager.getSerialNumberForUser(
-                new UserHandle(currentUserId));
-        sAppsModel.setCurrentUser(currentUserId);
+        sAppsModel.setCurrentUser(ActivityManager.getCurrentUser());
         recreateAppButtons();
 
         IntentFilter filter = new IntentFilter();
         filter.addAction(Intent.ACTION_USER_SWITCHED);
+        filter.addAction(Intent.ACTION_MANAGED_PROFILE_REMOVED);
         mContext.registerReceiver(mBroadcastReceiver, filter);
 
         mAppPackageMonitor.register(mContext, null, UserHandle.ALL, true);
@@ -244,7 +239,7 @@
             button.setContentDescription(appLabel);
 
             // Load the icon asynchronously.
-            new GetActivityIconTask(mPackageManager, button).execute(app.getComponentName());
+            new GetActivityIconTask(mPackageManager, button).execute(app);
         }
     }
 
@@ -280,7 +275,7 @@
      */
     @Nullable
     static CharSequence getAppLabel(PackageManager packageManager,
-            ComponentName activityName) {
+                                    ComponentName activityName) {
         String packageName = activityName.getPackageName();
         ApplicationInfo info;
         try {
@@ -296,7 +291,10 @@
     static void startAppDrag(ImageView icon, AppInfo appInfo) {
         // The drag data is an Intent to launch the activity.
         Intent mainIntent = Intent.makeMainActivity(appInfo.getComponentName());
-        mainIntent.putExtra(EXTRA_PROFILE, appInfo.getUserSerialNumber());
+        UserManager userManager =
+                (UserManager) icon.getContext().getSystemService(Context.USER_SERVICE);
+        long userSerialNumber = userManager.getSerialNumberForUser(appInfo.getUser());
+        mainIntent.putExtra(EXTRA_PROFILE, userSerialNumber);
         ClipData dragData = ClipData.newIntent("", mainIntent);
         // Use the ImageView to create the shadow.
         View.DragShadowBuilder shadow = new AppIconDragShadowBuilder(icon);
@@ -462,27 +460,38 @@
         if (data.getItemCount() != 1) {
             return null;
         }
-        Intent intent = data.getItemAt(0).getIntent();
+        ClipData.Item item = data.getItemAt(0);
+        if (item == null) {
+            return null;
+        }
+        Intent intent = item.getIntent();
         if (intent == null) {
             return null;
         }
-
         long userSerialNumber = intent.getLongExtra(EXTRA_PROFILE, -1);
-
-        // Validate the received user serial number.
+        if (userSerialNumber == -1) {
+            return null;
+        }
         UserHandle appUser = mUserManager.getUserForSerialNumber(userSerialNumber);
         if (appUser == null) {
-            userSerialNumber = mCurrentUserSerialNumber;
+            return null;
         }
-
-        return new AppInfo(intent.getComponent(), userSerialNumber);
+        ComponentName componentName = intent.getComponent();
+        if (componentName == null) {
+            return null;
+        }
+        AppInfo appInfo = new AppInfo(componentName, appUser);
+        if (sAppsModel.buildAppLaunchIntent(appInfo) == null) {
+            return null;
+        }
+        return appInfo;
     }
 
     /** Updates the app at a given view index. */
     private void updateAppAt(int index, AppInfo appInfo) {
         sAppsModel.setApp(index, appInfo);
         ImageView button = (ImageView) getChildAt(index);
-        new GetActivityIconTask(mPackageManager, button).execute(appInfo.getComponentName());
+        new GetActivityIconTask(mPackageManager, button).execute(appInfo);
     }
 
     /** Removes the empty placeholder view and cleans up the data model. */
@@ -540,20 +549,10 @@
         @Override
         public void onClick(View v) {
             AppInfo appInfo = sAppsModel.getApp(indexOfChild(v));
-            ComponentName component = appInfo.getComponentName();
-
-            long appUserSerialNumber = appInfo.getUserSerialNumber();
-            UserHandle appUser = mUserManager.getUserForSerialNumber(appUserSerialNumber);
-            if (appUser == null) {
-                Toast.makeText(getContext(), R.string.activity_not_found, Toast.LENGTH_SHORT).show();
-                Log.e(TAG, "Can't start activity " + component +
-                        " because its user doesn't exist.");
-                return;
-            }
-
-            Intent launchIntent = sAppsModel.buildAppLaunchIntent(component, appUser);
+            Intent launchIntent = sAppsModel.buildAppLaunchIntent(appInfo);
             if (launchIntent == null) {
-                Toast.makeText(getContext(), R.string.activity_not_found, Toast.LENGTH_SHORT).show();
+                Toast.makeText(
+                        getContext(), R.string.activity_not_found, Toast.LENGTH_SHORT).show();
                 return;
             }
 
@@ -568,18 +567,25 @@
             Bundle optsBundle = opts.toBundle();
             launchIntent.setSourceBounds(sourceBounds);
 
-            mContext.startActivityAsUser(launchIntent, optsBundle, appUser);
+            mContext.startActivityAsUser(launchIntent, optsBundle, appInfo.getUser());
         }
     }
 
     private void onUserSwitched(int currentUserId) {
-        final long newUserSerialNumber =
-                mUserManager.getSerialNumberForUser(new UserHandle(currentUserId));
+        sAppsModel.setCurrentUser(currentUserId);
+        recreateAppButtons();
+    }
 
-        if (newUserSerialNumber != mCurrentUserSerialNumber) {
-            mCurrentUserSerialNumber = newUserSerialNumber;
-            sAppsModel.setCurrentUser(currentUserId);
-            recreateAppButtons();
+    private void onManagedProfileRemoved(UserHandle removedProfile) {
+        boolean removedApps = false;
+        for(int i = sAppsModel.getAppCount() - 1; i >= 0; --i) {
+            AppInfo appInfo = sAppsModel.getApp(i);
+            if (!appInfo.getUser().equals(removedProfile)) continue;
+
+            removeViewAt(i);
+            sAppsModel.removeApp(i);
+            removedApps = true;
         }
+        if (removedApps) sAppsModel.savePrefs();
     }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarAppsModel.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarAppsModel.java
index c4c31fd..c7b9e1c 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarAppsModel.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarAppsModel.java
@@ -106,9 +106,24 @@
         return AppGlobals.getPackageManager();
     }
 
-    // Returns a launch intent for a given component, or null if the component is unlauncheable.
-    public Intent buildAppLaunchIntent(ComponentName component, UserHandle appUser) {
-        int appUserId = appUser.getIdentifier();
+    // Returns a launch intent for a given app info, or null if the app info is unlauncheable.
+    public Intent buildAppLaunchIntent(AppInfo appInfo) {
+        ComponentName component = appInfo.getComponentName();
+        int appUserId = appInfo.getUser().getIdentifier();
+
+        if (mCurrentUserId != appUserId) {
+            // Check if app user is a profile of current user and the app user is enabled.
+            UserInfo appUserInfo = mUserManager.getUserInfo(appUserId);
+            UserInfo currentUserInfo = mUserManager.getUserInfo(mCurrentUserId);
+            if (appUserInfo == null || currentUserInfo == null
+                    || appUserInfo.profileGroupId == UserInfo.NO_PROFILE_GROUP_ID
+                    || appUserInfo.profileGroupId != currentUserInfo.profileGroupId
+                    || !appUserInfo.isEnabled()) {
+                Log.e(TAG, "User " + appUserId +
+                        " is is not a profile of the current user, or is disabled.");
+                return null;
+            }
+        }
 
         // This code is based on LauncherAppsService.startActivityAsUser code.
         Intent launchIntent = new Intent(Intent.ACTION_MAIN);
@@ -164,7 +179,7 @@
 
         int appCount = mPrefs.getInt(userPrefixed(APP_COUNT_PREF), -1);
         if (appCount >= 0) {
-            loadAppsFromPrefs();
+            loadAppsFromPrefs(appCount);
         } else {
             // We switched to this user for the first time ever. This is a good opportunity to clean
             // prefs for users deleted in the past.
@@ -250,42 +265,52 @@
             final AppInfo appInfo = mApps.get(i);
             String componentNameString = appInfo.getComponentName().flattenToString();
             edit.putString(prefNameForApp(i), componentNameString);
-            edit.putLong(prefUserForApp(i), appInfo.getUserSerialNumber());
+            long userSerialNumber = mUserManager.getSerialNumberForUser(appInfo.getUser());
+            edit.putLong(prefUserForApp(i), userSerialNumber);
         }
         // Start an asynchronous disk write.
         edit.apply();
     }
 
+    /** Loads AppInfo from prefs. Returns null if something is wrong. */
+    private AppInfo loadAppFromPrefs(int index) {
+        String prefValue = mPrefs.getString(prefNameForApp(index), null);
+        if (prefValue == null) {
+            Slog.w(TAG, "Couldn't find pref " + prefNameForApp(index));
+            return null;
+        }
+        ComponentName componentName = ComponentName.unflattenFromString(prefValue);
+        if (componentName == null) {
+            Slog.w(TAG, "Invalid component name " + prefValue);
+            return null;
+        }
+        long userSerialNumber = mPrefs.getLong(prefUserForApp(index), -1);
+        if (userSerialNumber == -1) {
+            Slog.w(TAG, "Couldn't find pref " + prefUserForApp(index));
+            return null;
+        }
+        UserHandle appUser = mUserManager.getUserForSerialNumber(userSerialNumber);
+        if (appUser == null) {
+            Slog.w(TAG, "No user for serial " + userSerialNumber);
+            return null;
+        }
+        AppInfo appInfo = new AppInfo(componentName, appUser);
+        if (buildAppLaunchIntent(appInfo) == null) {
+            return null;
+        }
+        return appInfo;
+    }
+
     /** Loads the list of apps from SharedPreferences. */
-    private void loadAppsFromPrefs() {
-        UserManager mUserManager = (UserManager) mContext.getSystemService(Context.USER_SERVICE);
-
-        boolean hadUnlauncheableApps = false;
-
-        int appCount = mPrefs.getInt(userPrefixed(APP_COUNT_PREF), -1);
+    private void loadAppsFromPrefs(int appCount) {
         for (int i = 0; i < appCount; i++) {
-            String prefValue = mPrefs.getString(prefNameForApp(i), null);
-            if (prefValue == null) {
-                Slog.w(TAG, "Couldn't find pref " + prefNameForApp(i));
-                // Couldn't find the saved state. Just skip this item.
-                continue;
-            }
-            ComponentName componentName = ComponentName.unflattenFromString(prefValue);
-            long userSerialNumber = mPrefs.getLong(prefUserForApp(i), -1);
-            if (userSerialNumber == -1) {
-                Slog.w(TAG, "Couldn't find pref " + prefUserForApp(i));
-                // Couldn't find the saved state. Just skip this item.
-                continue;
-            }
-            UserHandle appUser = mUserManager.getUserForSerialNumber(userSerialNumber);
-            if (appUser != null && buildAppLaunchIntent(componentName, appUser) != null) {
-                mApps.add(new AppInfo(componentName, userSerialNumber));
-            } else {
-                hadUnlauncheableApps = true;
+            AppInfo appInfo = loadAppFromPrefs(i);
+            if (appInfo != null) {
+                mApps.add(appInfo);
             }
         }
 
-        if (hadUnlauncheableApps) savePrefs();
+        if (appCount != mApps.size()) savePrefs();
     }
 
     /** Adds the first few apps from the owner profile. Used for demo purposes. */
@@ -301,7 +326,7 @@
             ResolveInfo ri = apps.get(i);
             ComponentName componentName = new ComponentName(
                     ri.activityInfo.packageName, ri.activityInfo.name);
-            mApps.add(new AppInfo(componentName, mCurrentUserSerialNumber));
+            mApps.add(new AppInfo(componentName, new UserHandle(mCurrentUserId)));
         }
 
         savePrefs();
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarRecents.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarRecents.java
index b024ec4..1f71bc0 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarRecents.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarRecents.java
@@ -25,11 +25,12 @@
 import android.content.Context;
 import android.content.Intent;
 import android.content.pm.PackageManager;
+import android.content.pm.ResolveInfo;
 import android.os.Handler;
 import android.os.RemoteException;
 import android.os.UserHandle;
-import android.os.UserManager;
 import android.util.AttributeSet;
+import android.util.Log;
 import android.util.Slog;
 import android.util.SparseBooleanArray;
 import android.view.LayoutInflater;
@@ -160,7 +161,8 @@
 
         button.setVisibility(View.VISIBLE);
         // Load the activity icon on a background thread.
-        new GetActivityIconTask(mPackageManager, button).execute(getRealActivityForTask(task));
+        AppInfo app = new AppInfo(activityName, new UserHandle(task.userId));
+        new GetActivityIconTask(mPackageManager, button).execute(app);
 
         final int taskPersistentId = task.persistentId;
         button.setOnClickListener(new View.OnClickListener() {
@@ -171,7 +173,9 @@
                 try {
                     manager.startActivityFromRecents(taskPersistentId, null /* options */);
                 } catch (RemoteException e) {
-                    e.printStackTrace();
+                    Log.e(TAG, "Exception when activating a recent task", e);
+                } catch (IllegalArgumentException e) {
+                    Log.e(TAG, "Exception when activating a recent task", e);
                 }
             }
         });
@@ -218,6 +222,35 @@
             mContext = context;
         }
 
+        private ComponentName getLaunchComponentForPackage(String packageName, int userId) {
+            // This code is based on ApplicationPackageManager.getLaunchIntentForPackage.
+            PackageManager packageManager = mContext.getPackageManager();
+
+            // First see if the package has an INFO activity; the existence of
+            // such an activity is implied to be the desired front-door for the
+            // overall package (such as if it has multiple launcher entries).
+            Intent intentToResolve = new Intent(Intent.ACTION_MAIN);
+            intentToResolve.addCategory(Intent.CATEGORY_INFO);
+            intentToResolve.setPackage(packageName);
+            List<ResolveInfo> ris = packageManager.queryIntentActivitiesAsUser(
+                    intentToResolve, 0, userId);
+
+            // Otherwise, try to find a main launcher activity.
+            if (ris == null || ris.size() <= 0) {
+                // reuse the intent instance
+                intentToResolve.removeCategory(Intent.CATEGORY_INFO);
+                intentToResolve.addCategory(Intent.CATEGORY_LAUNCHER);
+                intentToResolve.setPackage(packageName);
+                ris = packageManager.queryIntentActivitiesAsUser(intentToResolve, 0, userId);
+            }
+            if (ris == null || ris.size() <= 0) {
+                Log.e(TAG, "Failed to build intent for " + packageName);
+                return null;
+            }
+            return new ComponentName(ris.get(0).activityInfo.packageName,
+                    ris.get(0).activityInfo.name);
+        }
+
         @Override
         public boolean onLongClick(View v) {
             ImageView icon = (ImageView) v;
@@ -226,17 +259,15 @@
             // for the task's package.
             RecentTaskInfo task = (RecentTaskInfo) v.getTag();
             String packageName = getRealActivityForTask(task).getPackageName();
-            Intent intent = mContext.getPackageManager().getLaunchIntentForPackage(packageName);
-            if (intent == null) {
+            ComponentName component = getLaunchComponentForPackage(packageName, task.userId);
+            if (component == null) {
                 return false;
             }
 
-            if (DEBUG) Slog.d(TAG, "Start drag with " + intent);
+            if (DEBUG) Slog.d(TAG, "Start drag with " + component);
 
-            UserManager userManager = (UserManager) mContext.getSystemService(Context.USER_SERVICE);
-            long userSerialNumber = userManager.getSerialNumberForUser(new UserHandle(task.userId));
             NavigationBarApps.startAppDrag(
-                    icon, new AppInfo(intent.getComponent(), userSerialNumber));
+                    icon, new AppInfo(component, new UserHandle(task.userId)));
             return true;
         }
     }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java
index 24ae47d..3ad7246 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java
@@ -204,6 +204,7 @@
     private int mLastOrientation = -1;
     private boolean mClosingWithAlphaFadeOut;
     private boolean mHeadsUpAnimatingAway;
+    private boolean mLaunchingAffordance;
     private LockedPhoneAnalytics mLockedPhoneAnalytics;
 
     private Runnable mHeadsUpExistenceChangedRunnable = new Runnable() {
@@ -491,7 +492,9 @@
         mIsLaunchTransitionFinished = false;
         mBlockTouches = false;
         mUnlockIconActive = false;
-        mAfforanceHelper.reset(true);
+        if (!mLaunchingAffordance) {
+            mAfforanceHelper.reset(false);
+        }
         closeQs();
         mStatusBar.dismissPopups();
         mNotificationStackScroller.setOverScrollAmount(0f, true /* onTop */, false /* animate */,
@@ -2430,4 +2433,36 @@
     public boolean hasOverlappingRendering() {
         return !mDozing;
     }
+
+    public void launchCamera(boolean animate) {
+        // If we are launching it when we are occluded already we don't want it to animate,
+        // nor setting these flags, since the occluded state doesn't change anymore, hence it's
+        // never reset.
+        if (!isFullyCollapsed()) {
+            mLaunchingAffordance = true;
+            setLaunchingAffordance(true);
+        } else {
+            animate = false;
+        }
+        mAfforanceHelper.launchAffordance(animate, getLayoutDirection() == LAYOUT_DIRECTION_RTL);
+    }
+
+    public void onAffordanceLaunchEnded() {
+        mLaunchingAffordance = false;
+        setLaunchingAffordance(false);
+    }
+
+    /**
+     * Set whether we are currently launching an affordance. This is currently only set when
+     * launched via a camera gesture.
+     */
+    private void setLaunchingAffordance(boolean launchingAffordance) {
+        getLeftIcon().setLaunchingAffordance(launchingAffordance);
+        getRightIcon().setLaunchingAffordance(launchingAffordance);
+        getCenterIcon().setLaunchingAffordance(launchingAffordance);
+    }
+
+    public boolean canCameraGestureBeLaunched() {
+        return !mAfforanceHelper.isSwipingInProgress();
+    }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java
index 278a7e7..7b04da0 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java
@@ -66,6 +66,7 @@
 import android.os.SystemClock;
 import android.os.UserHandle;
 import android.os.UserManager;
+import android.os.Vibrator;
 import android.provider.Settings;
 import android.service.notification.NotificationListenerService;
 import android.service.notification.NotificationListenerService.RankingMap;
@@ -485,6 +486,9 @@
     private Runnable mLaunchTransitionEndRunnable;
     private boolean mLaunchTransitionFadingAway;
     private ExpandableNotificationRow mDraggedDownRow;
+    private boolean mLaunchCameraOnScreenTurningOn;
+    private PowerManager.WakeLock mGestureWakeLock;
+    private Vibrator mVibrator;
 
     // Fingerprint (as computed by getLoggingFingerprint() of the last logged state.
     private int mLastLoggedStateFingerprint;
@@ -919,7 +923,9 @@
         PowerManager pm = (PowerManager) mContext.getSystemService(Context.POWER_SERVICE);
         mBroadcastReceiver.onReceive(mContext,
                 new Intent(pm.isScreenOn() ? Intent.ACTION_SCREEN_ON : Intent.ACTION_SCREEN_OFF));
-
+        mGestureWakeLock = pm.newWakeLock(PowerManager.SCREEN_BRIGHT_WAKE_LOCK,
+                "GestureWakeLock");
+        mVibrator = mContext.getSystemService(Vibrator.class);
 
         // receive broadcasts
         IntentFilter filter = new IntentFilter();
@@ -3425,6 +3431,8 @@
 
     private void onLaunchTransitionFadingEnded() {
         mNotificationPanel.setAlpha(1.0f);
+        mNotificationPanel.onAffordanceLaunchEnded();
+        releaseGestureWakeLock();
         runLaunchTransitionEndRunnable();
         mLaunchTransitionFadingAway = false;
         mScrimController.forceHideScrims(false /* hide */);
@@ -3512,6 +3520,8 @@
 
     private void onLaunchTransitionTimeout() {
         Log.w(TAG, "Launch transition: Timeout!");
+        mNotificationPanel.onAffordanceLaunchEnded();
+        releaseGestureWakeLock();
         mNotificationPanel.resetViews();
     }
 
@@ -3563,10 +3573,18 @@
             mQSPanel.refreshAllTiles();
         }
         mHandler.removeMessages(MSG_LAUNCH_TRANSITION_TIMEOUT);
+        releaseGestureWakeLock();
+        mNotificationPanel.onAffordanceLaunchEnded();
         mNotificationPanel.setAlpha(1f);
         return staying;
     }
 
+    private void releaseGestureWakeLock() {
+        if (mGestureWakeLock.isHeld()) {
+            mGestureWakeLock.release();
+        }
+    }
+
     public long calculateGoingToFullShadeDelay() {
         return mKeyguardFadingAwayDelay + mKeyguardFadingAwayDuration;
     }
@@ -3704,6 +3722,11 @@
         return mState == StatusBarState.KEYGUARD && mStatusBarKeyguardViewManager.onMenuPressed();
     }
 
+    public void endAffordanceLaunch() {
+        releaseGestureWakeLock();
+        mNotificationPanel.onAffordanceLaunchEnded();
+    }
+
     public boolean onBackPressed() {
         if (mStatusBarKeyguardViewManager.onBackPressed()) {
             return true;
@@ -3939,6 +3962,9 @@
     }
 
     public void onFinishedGoingToSleep() {
+        mNotificationPanel.onAffordanceLaunchEnded();
+        releaseGestureWakeLock();
+        mLaunchCameraOnScreenTurningOn = false;
         mDeviceInteractive = false;
         mWakeUpComingFromTouch = false;
         mWakeUpTouchLocation = null;
@@ -3957,6 +3983,14 @@
 
     public void onScreenTurningOn() {
         mNotificationPanel.onScreenTurningOn();
+        if (mLaunchCameraOnScreenTurningOn) {
+            mNotificationPanel.launchCamera(false);
+            mLaunchCameraOnScreenTurningOn = false;
+        }
+    }
+
+    private void vibrateForCameraGesture() {
+        mVibrator.vibrate(1000L);
     }
 
     public void onScreenTurnedOn() {
@@ -4114,6 +4148,39 @@
         }
     }
 
+    @Override
+    public void onCameraLaunchGestureDetected() {
+        if (!mNotificationPanel.canCameraGestureBeLaunched()) {
+            return;
+        }
+        if (!mDeviceInteractive) {
+            PowerManager pm = mContext.getSystemService(PowerManager.class);
+            pm.wakeUp(SystemClock.uptimeMillis(), "com.android.systemui:CAMERA_GESTURE");
+            mStatusBarKeyguardViewManager.notifyDeviceWakeUpRequested();
+        }
+        vibrateForCameraGesture();
+        if (!mStatusBarKeyguardViewManager.isShowing()) {
+            startActivity(KeyguardBottomAreaView.INSECURE_CAMERA_INTENT,
+                    true /* dismissShade */);
+        } else {
+            if (!mDeviceInteractive) {
+                // Avoid flickering of the scrim when we instant launch the camera and the bouncer
+                // comes on.
+                mScrimController.dontAnimateBouncerChangesUntilNextFrame();
+                mGestureWakeLock.acquire(LAUNCH_TRANSITION_TIMEOUT_MS + 1000L);
+            }
+            if (mStatusBarKeyguardViewManager.isScreenTurnedOn()) {
+                mNotificationPanel.launchCamera(mDeviceInteractive /* animate */);
+            } else {
+                // We need to defer the camera launch until the screen comes on, since otherwise
+                // we will dismiss us too early since we are waiting on an activity to be drawn and
+                // incorrectly get notified because of the screen on event (which resumes and pauses
+                // some activities)
+                mLaunchCameraOnScreenTurningOn = true;
+            }
+        }
+    }
+
     public void notifyFpAuthModeChanged() {
         updateDozing();
     }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimController.java
index cc6f396..b9e9292 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimController.java
@@ -87,6 +87,7 @@
     private View mDraggedHeadsUpView;
     private boolean mForceHideScrims;
     private boolean mSkipFirstFrame;
+    private boolean mDontAnimateBouncerChanges;
 
     public ScrimController(ScrimView scrimBehind, ScrimView scrimInFront, View headsUpScrim,
             boolean scrimSrcEnabled) {
@@ -125,7 +126,7 @@
 
     public void setBouncerShowing(boolean showing) {
         mBouncerShowing = showing;
-        mAnimateChange = !mExpanding;
+        mAnimateChange = !mExpanding && !mDontAnimateBouncerChanges;
         scheduleUpdate();
     }
 
@@ -360,6 +361,9 @@
     public boolean onPreDraw() {
         mScrimBehind.getViewTreeObserver().removeOnPreDrawListener(this);
         mUpdatePending = false;
+        if (mDontAnimateBouncerChanges) {
+            mDontAnimateBouncerChanges = false;
+        }
         updateScrims();
         mDurationOverride = -1;
         mAnimationDelay = 0;
@@ -496,4 +500,8 @@
         mAnimateChange = false;
         scheduleUpdate();
     }
+
+    public void dontAnimateBouncerChangesUntilNextFrame() {
+        mDontAnimateBouncerChanges = true;
+    }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/SettingsButton.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/SettingsButton.java
index a1e9ece..18db5b8 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/SettingsButton.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/SettingsButton.java
@@ -19,6 +19,7 @@
 import android.animation.Animator.AnimatorListener;
 import android.animation.ObjectAnimator;
 import android.content.Context;
+import android.graphics.drawable.RippleDrawable;
 import android.os.Handler;
 import android.os.Message;
 import android.util.AttributeSet;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarHeaderView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarHeaderView.java
index 7ee47df..e9c4e49 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarHeaderView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarHeaderView.java
@@ -26,6 +26,7 @@
 import android.graphics.Rect;
 import android.graphics.drawable.Animatable;
 import android.graphics.drawable.Drawable;
+import android.graphics.drawable.RippleDrawable;
 import android.util.AttributeSet;
 import android.util.MathUtils;
 import android.util.TypedValue;
@@ -184,6 +185,12 @@
             }
         });
         requestCaptureValues();
+
+        // RenderThread is doing more harm than good when touching the header (to expand quick
+        // settings), so disable it for this view
+        ((RippleDrawable) getBackground()).setForceSoftware(true);
+        ((RippleDrawable) mSettingsButton.getBackground()).setForceSoftware(true);
+        ((RippleDrawable) mSystemIconsSuperContainer.getBackground()).setForceSoftware(true);
     }
 
     @Override
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java
index 59ee5c5..d0604c5 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java
@@ -179,6 +179,10 @@
         mPhoneStatusBar.onScreenTurningOn();
     }
 
+    public boolean isScreenTurnedOn() {
+        return mScreenTurnedOn;
+    }
+
     public void onScreenTurnedOn() {
         mScreenTurnedOn = true;
         if (mDeferScrimFadeOut) {
@@ -385,6 +389,7 @@
      */
     public boolean onBackPressed() {
         if (mBouncer.isShowing()) {
+            mPhoneStatusBar.endAffordanceLaunch();
             reset();
             return true;
         }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/tv/TvStatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/tv/TvStatusBar.java
index 920b682..2587b9f 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/tv/TvStatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/tv/TvStatusBar.java
@@ -171,6 +171,10 @@
     }
 
     @Override
+    public void onCameraLaunchGestureDetected() {
+    }
+
+    @Override
     protected void updateHeadsUp(String key, NotificationData.Entry entry, boolean shouldInterrupt,
             boolean alertAgain) {
     }
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NavigationBarAppsModelTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NavigationBarAppsModelTest.java
index 4d0e28b..fce6b29 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NavigationBarAppsModelTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NavigationBarAppsModelTest.java
@@ -72,7 +72,7 @@
         mMockEdit = mock(SharedPreferences.Editor.class);
         mMockUserManager = mock(UserManager.class);
 
-        when (context.getSharedPreferences(
+        when(context.getSharedPreferences(
                 "com.android.systemui.navbarapps", Context.MODE_PRIVATE)).thenReturn(mMockPrefs);
         when(context.getSystemService(Context.USER_SERVICE)).thenReturn(mMockUserManager);
         when(context.getPackageManager()).thenReturn(mMockPackageManager);
@@ -84,9 +84,22 @@
         when(mMockPrefs.getInt("version", -1)).thenReturn(3);
         when(mMockPrefs.edit()).thenReturn(mMockEdit);
 
-        when(mMockUserManager.getSerialNumberForUser(new UserHandle(2))).thenReturn(22L);
-        when(mMockUserManager.getUserForSerialNumber(45L)).thenReturn(new UserHandle(4));
-        when(mMockUserManager.getUserForSerialNumber(239L)).thenReturn(new UserHandle(5));
+        when(mMockUserManager.getSerialNumberForUser(new UserHandle(2))).thenReturn(222L);
+        when(mMockUserManager.getSerialNumberForUser(new UserHandle(4))).thenReturn(444L);
+        when(mMockUserManager.getSerialNumberForUser(new UserHandle(5))).thenReturn(555L);
+        when(mMockUserManager.getUserForSerialNumber(222L)).thenReturn(new UserHandle(2));
+        when(mMockUserManager.getUserForSerialNumber(444L)).thenReturn(new UserHandle(4));
+        when(mMockUserManager.getUserForSerialNumber(555L)).thenReturn(new UserHandle(5));
+
+        UserInfo ui2 = new UserInfo();
+        ui2.profileGroupId = 999;
+        UserInfo ui4 = new UserInfo();
+        ui4.profileGroupId = 999;
+        UserInfo ui5 = new UserInfo();
+        ui5.profileGroupId = 999;
+        when(mMockUserManager.getUserInfo(2)).thenReturn(ui2);
+        when(mMockUserManager.getUserInfo(4)).thenReturn(ui4);
+        when(mMockUserManager.getUserInfo(5)).thenReturn(ui5);
 
         mModel = new NavigationBarAppsModel(context) {
             @Override
@@ -134,19 +147,24 @@
                 .queryIntentActivitiesAsUser(any(Intent.class), eq(0), any(int.class)))
                 .thenReturn(Arrays.asList(ri0, ri1));
 
+        mModel.setCurrentUser(3);
         // Unlauncheable (for various reasons) apps.
         assertEquals(null, mModel.buildAppLaunchIntent(
-                new ComponentName("package0", "class0"), new UserHandle(3)));
+                new AppInfo(new ComponentName("package0", "class0"), new UserHandle(3))));
+        mModel.setCurrentUser(4);
         assertEquals(null, mModel.buildAppLaunchIntent(
-                new ComponentName("package1", "class1"), new UserHandle(4)));
+                new AppInfo(new ComponentName("package1", "class1"), new UserHandle(4))));
+        mModel.setCurrentUser(5);
         assertEquals(null, mModel.buildAppLaunchIntent(
-                new ComponentName("package2", "class2"), new UserHandle(5)));
+                new AppInfo(new ComponentName("package2", "class2"), new UserHandle(5))));
+        mModel.setCurrentUser(6);
         assertEquals(null, mModel.buildAppLaunchIntent(
-                new ComponentName("package3", "class3"), new UserHandle(6)));
+                new AppInfo(new ComponentName("package3", "class3"), new UserHandle(6))));
 
         // A launcheable app.
+        mModel.setCurrentUser(7);
         Intent intent = mModel.buildAppLaunchIntent(
-                new ComponentName("package4", "class4"), new UserHandle(7));
+                new AppInfo(new ComponentName("package4", "class4"), new UserHandle(7)));
         assertNotNull(intent);
         assertEquals(new ComponentName("package4", "class4"), intent.getComponent());
         assertEquals("package4", intent.getPackage());
@@ -155,13 +173,11 @@
     /** Initializes the model from SharedPreferences for a few app activites. */
     private void initializeModelFromPrefs() {
         // Assume several apps are stored.
-        when(mMockPrefs.getInt("22|app_count", -1)).thenReturn(3);
-        when(mMockPrefs.getString("22|app_0", null)).thenReturn("package0/class0");
-        when(mMockPrefs.getLong("22|app_user_0", -1)).thenReturn(-1L);
-        when(mMockPrefs.getString("22|app_1", null)).thenReturn("package1/class1");
-        when(mMockPrefs.getLong("22|app_user_1", -1)).thenReturn(45L);
-        when(mMockPrefs.getString("22|app_2", null)).thenReturn("package2/class2");
-        when(mMockPrefs.getLong("22|app_user_2", -1)).thenReturn(239L);
+        when(mMockPrefs.getInt("222|app_count", -1)).thenReturn(2);
+        when(mMockPrefs.getString("222|app_0", null)).thenReturn("package1/class1");
+        when(mMockPrefs.getLong("222|app_user_0", -1)).thenReturn(444L);
+        when(mMockPrefs.getString("222|app_1", null)).thenReturn("package2/class2");
+        when(mMockPrefs.getLong("222|app_user_1", -1)).thenReturn(555L);
 
         ActivityInfo mockActivityInfo = new ActivityInfo();
         mockActivityInfo.exported = true;
@@ -204,15 +220,15 @@
         initializeModelFromPrefs();
         assertEquals(2, mModel.getAppCount());
         assertEquals("package1/class1", mModel.getApp(0).getComponentName().flattenToString());
-        assertEquals(45L, mModel.getApp(0).getUserSerialNumber());
+        assertEquals(new UserHandle(4), mModel.getApp(0).getUser());
         assertEquals("package2/class2", mModel.getApp(1).getComponentName().flattenToString());
-        assertEquals(239L, mModel.getApp(1).getUserSerialNumber());
+        assertEquals(new UserHandle(5), mModel.getApp(1).getUser());
     }
 
     /** Tests initializing the model when the SharedPreferences aren't available. */
     public void testInitializeDefaultApps() {
         // Assume the user's app count pref isn't available.
-        when(mMockPrefs.getInt("22|app_count", -1)).thenReturn(-1);
+        when(mMockPrefs.getInt("222|app_count", -1)).thenReturn(-1);
 
         // Assume some installed activities.
         ActivityInfo ai1 = new ActivityInfo();
@@ -233,16 +249,16 @@
         mModel.setCurrentUser(2);
         assertEquals(2, mModel.getAppCount());
         assertEquals("package1/class1", mModel.getApp(0).getComponentName().flattenToString());
-        assertEquals(22L, mModel.getApp(0).getUserSerialNumber());
+        assertEquals(new UserHandle(2), mModel.getApp(0).getUser());
         assertEquals("package2/class2", mModel.getApp(1).getComponentName().flattenToString());
-        assertEquals(22L, mModel.getApp(1).getUserSerialNumber());
+        assertEquals(new UserHandle(2), mModel.getApp(1).getUser());
         InOrder order = inOrder(mMockEdit);
         order.verify(mMockEdit).apply();
-        order.verify(mMockEdit).putInt("22|app_count", 2);
-        order.verify(mMockEdit).putString("22|app_0", "package1/class1");
-        order.verify(mMockEdit).putLong("22|app_user_0", 22L);
-        order.verify(mMockEdit).putString("22|app_1", "package2/class2");
-        order.verify(mMockEdit).putLong("22|app_user_1", 22L);
+        order.verify(mMockEdit).putInt("222|app_count", 2);
+        order.verify(mMockEdit).putString("222|app_0", "package1/class1");
+        order.verify(mMockEdit).putLong("222|app_user_0", 222L);
+        order.verify(mMockEdit).putString("222|app_1", "package2/class2");
+        order.verify(mMockEdit).putLong("222|app_user_1", 222L);
         order.verify(mMockEdit).apply();
         verifyNoMoreInteractions(mMockEdit);
     }
@@ -250,12 +266,12 @@
     /** Tests initializing the model if one of the prefs is missing. */
     public void testInitializeWithMissingPref() {
         // Assume two apps are nominally stored.
-        when(mMockPrefs.getInt("22|app_count", -1)).thenReturn(2);
-        when(mMockPrefs.getString("22|app_0", null)).thenReturn("package0/class0");
-        when(mMockPrefs.getLong("22|app_user_0", -1)).thenReturn(239L);
+        when(mMockPrefs.getInt("222|app_count", -1)).thenReturn(2);
+        when(mMockPrefs.getString("222|app_0", null)).thenReturn("package0/class0");
+        when(mMockPrefs.getLong("222|app_user_0", -1)).thenReturn(555L);
 
         // But assume one pref is missing.
-        when(mMockPrefs.getString("22|app_1", null)).thenReturn(null);
+        when(mMockPrefs.getString("222|app_1", null)).thenReturn(null);
 
         ActivityInfo mockActivityInfo = new ActivityInfo();
         mockActivityInfo.exported = true;
@@ -279,18 +295,23 @@
         mModel.setCurrentUser(2);
         assertEquals(1, mModel.getAppCount());
         assertEquals("package0/class0", mModel.getApp(0).getComponentName().flattenToString());
-        assertEquals(239L, mModel.getApp(0).getUserSerialNumber());
+        assertEquals(new UserHandle(5), mModel.getApp(0).getUser());
+        InOrder order = inOrder(mMockEdit);
+        order.verify(mMockEdit).putInt("222|app_count", 1);
+        order.verify(mMockEdit).putString("222|app_0", "package0/class0");
+        order.verify(mMockEdit).putLong("222|app_user_0", 555L);
+        order.verify(mMockEdit).apply();
         verifyNoMoreInteractions(mMockEdit);
     }
 
     /** Tests initializing the model if one of the apps is unlauncheable. */
     public void testInitializeWithUnlauncheableApp() {
         // Assume two apps are nominally stored.
-        when(mMockPrefs.getInt("22|app_count", -1)).thenReturn(2);
-        when(mMockPrefs.getString("22|app_0", null)).thenReturn("package0/class0");
-        when(mMockPrefs.getLong("22|app_user_0", -1)).thenReturn(239L);
-        when(mMockPrefs.getString("22|app_1", null)).thenReturn("package1/class1");
-        when(mMockPrefs.getLong("22|app_user_1", -1)).thenReturn(45L);
+        when(mMockPrefs.getInt("222|app_count", -1)).thenReturn(2);
+        when(mMockPrefs.getString("222|app_0", null)).thenReturn("package0/class0");
+        when(mMockPrefs.getLong("222|app_user_0", -1)).thenReturn(555L);
+        when(mMockPrefs.getString("222|app_1", null)).thenReturn("package1/class1");
+        when(mMockPrefs.getLong("222|app_user_1", -1)).thenReturn(444L);
 
         ActivityInfo mockActivityInfo = new ActivityInfo();
         mockActivityInfo.exported = true;
@@ -314,13 +335,13 @@
         mModel.setCurrentUser(2);
         assertEquals(1, mModel.getAppCount());
         assertEquals("package0/class0", mModel.getApp(0).getComponentName().flattenToString());
-        assertEquals(239L, mModel.getApp(0).getUserSerialNumber());
+        assertEquals(new UserHandle(5), mModel.getApp(0).getUser());
 
         // Once an unlauncheable app is detected, the model should save all apps excluding the
         // unlauncheable one.
-        verify(mMockEdit).putInt("22|app_count", 1);
-        verify(mMockEdit).putString("22|app_0", "package0/class0");
-        verify(mMockEdit).putLong("22|app_user_0", 239L);
+        verify(mMockEdit).putInt("222|app_count", 1);
+        verify(mMockEdit).putString("222|app_0", "package0/class0");
+        verify(mMockEdit).putLong("222|app_user_0", 555L);
         verify(mMockEdit).apply();
         verifyNoMoreInteractions(mMockEdit);
     }
@@ -330,11 +351,11 @@
         initializeModelFromPrefs();
 
         mModel.savePrefs();
-        verify(mMockEdit).putInt("22|app_count", 2);
-        verify(mMockEdit).putString("22|app_0", "package1/class1");
-        verify(mMockEdit).putLong("22|app_user_0", 45L);
-        verify(mMockEdit).putString("22|app_1", "package2/class2");
-        verify(mMockEdit).putLong("22|app_user_1", 239L);
+        verify(mMockEdit).putInt("222|app_count", 2);
+        verify(mMockEdit).putString("222|app_0", "package1/class1");
+        verify(mMockEdit).putLong("222|app_user_0", 444L);
+        verify(mMockEdit).putString("222|app_1", "package2/class2");
+        verify(mMockEdit).putLong("222|app_user_1", 555L);
         verify(mMockEdit).apply();
         verifyNoMoreInteractions(mMockEdit);
     }
@@ -367,7 +388,7 @@
 
         // Assume the user's app count pref isn't available. This will trigger clearing deleted
         // users' prefs.
-        when(mMockPrefs.getInt("22|app_count", -1)).thenReturn(-1);
+        when(mMockPrefs.getInt("222|app_count", -1)).thenReturn(-1);
 
         final Map allPrefs = new HashMap<String, Object>();
         allPrefs.put("version", null);
diff --git a/packages/WallpaperCropper/AndroidManifest.xml b/packages/WallpaperCropper/AndroidManifest.xml
index 81d1085..e558d7e 100644
--- a/packages/WallpaperCropper/AndroidManifest.xml
+++ b/packages/WallpaperCropper/AndroidManifest.xml
@@ -21,7 +21,10 @@
         <uses-permission android:name="android.permission.SET_WALLPAPER" />
         <uses-permission android:name="android.permission.SET_WALLPAPER_HINTS" />
 
-        <application android:requiredForAllUsers="true">
+        <application
+            android:requiredForAllUsers="true"
+            android:largeHeap="true">
+
         <activity
             android:name="WallpaperCropActivity"
             android:theme="@style/Theme.WallpaperCropper"
diff --git a/services/core/java/com/android/server/AppOpsService.java b/services/core/java/com/android/server/AppOpsService.java
index 56ebed6..c373fb8 100644
--- a/services/core/java/com/android/server/AppOpsService.java
+++ b/services/core/java/com/android/server/AppOpsService.java
@@ -1569,6 +1569,8 @@
                 if ("-h".equals(arg)) {
                     dumpHelp(pw);
                     return;
+                } else if ("-a".equals(arg)) {
+                    // dump all data
                 } else if ("write-settings".equals(arg)) {
                     long token = Binder.clearCallingIdentity();
                     try {
diff --git a/services/core/java/com/android/server/EventLogTags.logtags b/services/core/java/com/android/server/EventLogTags.logtags
index 13b3f8d..b826cfd 100644
--- a/services/core/java/com/android/server/EventLogTags.logtags
+++ b/services/core/java/com/android/server/EventLogTags.logtags
@@ -246,3 +246,8 @@
 # ---------------------------
 40000 volume_changed (stream|1), (prev_level|1), (level|1), (max_level|1), (caller|3)
 40001 stream_devices_changed (stream|1), (prev_devices|1), (devices|1)
+
+# ---------------------------
+# GestureLauncherService.java
+# ---------------------------
+40100 camera_gesture_triggered (gesture_on_time|2|3), (sensor1_on_time|2|3), (sensor2_on_time|2|3), (event_extra|1|1)
diff --git a/services/core/java/com/android/server/GestureLauncherService.java b/services/core/java/com/android/server/GestureLauncherService.java
index 55af9f0..342a3ef 100644
--- a/services/core/java/com/android/server/GestureLauncherService.java
+++ b/services/core/java/com/android/server/GestureLauncherService.java
@@ -19,12 +19,9 @@
 import android.app.ActivityManager;
 import android.app.KeyguardManager;
 import android.content.BroadcastReceiver;
-import android.content.ComponentName;
 import android.content.Context;
 import android.content.Intent;
 import android.content.IntentFilter;
-import android.content.pm.PackageManager;
-import android.content.pm.ResolveInfo;
 import android.content.res.Resources;
 import android.database.ContentObserver;
 import android.hardware.Sensor;
@@ -34,13 +31,14 @@
 import android.os.Handler;
 import android.os.PowerManager;
 import android.os.PowerManager.WakeLock;
+import android.os.SystemClock;
 import android.os.SystemProperties;
-import android.os.UserHandle;
 import android.os.Vibrator;
-import android.provider.MediaStore;
 import android.provider.Settings;
 import android.util.Slog;
 
+import com.android.server.statusbar.StatusBarManagerInternal;
+
 /**
  * The service that listens for gestures detected in sensor firmware and starts the intent
  * accordingly.
@@ -56,8 +54,6 @@
     private final GestureEventListener mGestureListener = new GestureEventListener();
 
     private Sensor mCameraLaunchSensor;
-    private Vibrator mVibrator;
-    private KeyguardManager mKeyGuard;
     private Context mContext;
 
     /** The wake lock held when a gesture is detected. */
@@ -65,6 +61,36 @@
     private boolean mRegistered;
     private int mUserId;
 
+    // Below are fields used for event logging only.
+    /** Elapsed real time when the camera gesture is turned on. */
+    private long mCameraGestureOnTimeMs = 0L;
+
+    /** Elapsed real time when the last camera gesture was detected. */
+    private long mCameraGestureLastEventTime = 0L;
+
+    /**
+     * How long the sensor 1 has been turned on since camera launch sensor was
+     * subscribed to and when the last camera launch gesture was detected.
+     * <p>Sensor 1 is the main sensor used to detect camera launch gesture.</p>
+     */
+    private long mCameraGestureSensor1LastOnTimeMs = 0L;
+
+    /**
+     * If applicable, how long the sensor 2 has been turned on since camera
+     * launch sensor was subscribed to and when the last camera launch
+     * gesture was detected.
+     * <p>Sensor 2 is the secondary sensor used to detect camera launch gesture.
+     * This is optional and if only sensor 1 is used for detect camera launch
+     * gesture, this value would always be 0.</p>
+     */
+    private long mCameraGestureSensor2LastOnTimeMs = 0L;
+
+    /**
+     * Extra information about the event when the last camera launch gesture
+     * was detected.
+     */
+    private int mCameraLaunchLastEventExtra = 0;
+
     public GestureLauncherService(Context context) {
         super(context);
         mContext = context;
@@ -82,12 +108,9 @@
                 return;
             }
 
-            mVibrator = (Vibrator) mContext.getSystemService(Context.VIBRATOR_SERVICE);
-            mKeyGuard = (KeyguardManager) mContext.getSystemService(Context.KEYGUARD_SERVICE);
             PowerManager powerManager = (PowerManager) mContext.getSystemService(
                     Context.POWER_SERVICE);
-            mWakeLock = powerManager.newWakeLock(
-                    PowerManager.SCREEN_BRIGHT_WAKE_LOCK | PowerManager.ACQUIRE_CAUSES_WAKEUP,
+            mWakeLock = powerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK,
                     "GestureLauncherService");
             updateCameraRegistered();
 
@@ -115,6 +138,12 @@
     private void unregisterCameraLaunchGesture() {
         if (mRegistered) {
             mRegistered = false;
+            mCameraGestureOnTimeMs = 0L;
+            mCameraGestureLastEventTime = 0L;
+            mCameraGestureSensor1LastOnTimeMs = 0;
+            mCameraGestureSensor2LastOnTimeMs = 0;
+            mCameraLaunchLastEventExtra = 0;
+
             SensorManager sensorManager = (SensorManager) mContext.getSystemService(
                     Context.SENSOR_SERVICE);
             sensorManager.unregisterListener(mGestureListener);
@@ -128,6 +157,8 @@
         if (mRegistered) {
             return;
         }
+        mCameraGestureOnTimeMs = SystemClock.elapsedRealtime();
+        mCameraGestureLastEventTime = mCameraGestureOnTimeMs;
         SensorManager sensorManager = (SensorManager) mContext.getSystemService(
                 Context.SENSOR_SERVICE);
         int cameraLaunchGestureId = resources.getInteger(
@@ -208,14 +239,22 @@
     private final class GestureEventListener implements SensorEventListener {
         @Override
         public void onSensorChanged(SensorEvent event) {
+            if (!mRegistered) {
+              if (DBG) Slog.d(TAG, "Ignoring gesture event because it's unregistered.");
+              return;
+            }
             if (event.sensor == mCameraLaunchSensor) {
-                handleCameraLaunchGesture();
+                handleCameraLaunchGesture(event);
                 return;
             }
         }
 
-        private void handleCameraLaunchGesture() {
-            if (DBG) Slog.d(TAG, "Received a camera launch event.");
+        private void handleCameraLaunchGesture(SensorEvent event) {
+            if (DBG) {
+                float[] values = event.values;
+                Slog.d(TAG, String.format("Received a camera launch event: " +
+                      "values=[%.4f, %.4f, %.4f].", values[0], values[1], values[2]));
+            }
             boolean userSetupComplete = Settings.Secure.getInt(mContext.getContentResolver(),
                     Settings.Secure.USER_SETUP_COMPLETE, 0) != 0;
             if (!userSetupComplete) {
@@ -227,28 +266,13 @@
             if (DBG) Slog.d(TAG, String.format(
                     "userSetupComplete = %s, performing camera launch gesture.",
                     userSetupComplete));
-            boolean locked = mKeyGuard != null && mKeyGuard.inKeyguardRestrictedInputMode();
-            String action = locked
-                    ? MediaStore.INTENT_ACTION_STILL_IMAGE_CAMERA_SECURE
-                    : MediaStore.INTENT_ACTION_STILL_IMAGE_CAMERA;
-            Intent intent = new Intent(action);
-            PackageManager pm = mContext.getPackageManager();
-            ResolveInfo componentInfo = pm.resolveActivity(intent,
-                PackageManager.MATCH_DEFAULT_ONLY);
-            if (componentInfo == null) {
-                if (DBG) Slog.d(TAG, "Couldn't find an app to process the camera intent.");
-                return;
-            }
 
-            if (mVibrator != null && mVibrator.hasVibrator()) {
-                mVibrator.vibrate(1000L);
-            }
-            // Turn on the screen before the camera launches.
+            // Make sure we don't sleep too early
             mWakeLock.acquire(500L);
-            intent.setComponent(new ComponentName(componentInfo.activityInfo.packageName,
-                    componentInfo.activityInfo.name));
-            intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
-            mContext.startActivityAsUser(intent, UserHandle.CURRENT);
+            StatusBarManagerInternal service = LocalServices.getService(
+                    StatusBarManagerInternal.class);
+            service.onCameraLaunchGestureDetected();
+            trackCameraLaunchEvent(event);
             mWakeLock.release();
         }
 
@@ -256,5 +280,50 @@
         public void onAccuracyChanged(Sensor sensor, int accuracy) {
             // Ignored.
         }
+
+        private void trackCameraLaunchEvent(SensorEvent event) {
+            long now = SystemClock.elapsedRealtime();
+            long totalDuration = now - mCameraGestureOnTimeMs;
+            // values[0]: ratio between total time duration when accel is turned on and time
+            //            duration since camera launch gesture is subscribed.
+            // values[1]: ratio between total time duration when gyro is turned on and time duration
+            //            since camera launch gesture is subscribed.
+            // values[2]: extra information
+            float[] values = event.values;
+
+            long sensor1OnTime = (long) (totalDuration * (double) values[0]);
+            long sensor2OnTime = (long) (totalDuration * (double) values[1]);
+            int extra = (int) values[2];
+
+            // We only log the difference in the event log to make aggregation easier.
+            long gestureOnTimeDiff = now - mCameraGestureLastEventTime;
+            long sensor1OnTimeDiff = sensor1OnTime - mCameraGestureSensor1LastOnTimeMs;
+            long sensor2OnTimeDiff = sensor2OnTime - mCameraGestureSensor2LastOnTimeMs;
+            int extraDiff = extra - mCameraLaunchLastEventExtra;
+
+            // Gating against negative time difference. This doesn't usually happen, but it may
+            // happen because of numeric errors.
+            if (gestureOnTimeDiff < 0 || sensor1OnTimeDiff < 0 || sensor2OnTimeDiff < 0) {
+                if (DBG) Slog.d(TAG, "Skipped event logging because negative numbers.");
+                return;
+            }
+
+            if (DBG) Slog.d(TAG, String.format("totalDuration: %d, sensor1OnTime: %s, " +
+                    "sensor2OnTime: %d, extra: %d",
+                    gestureOnTimeDiff,
+                    sensor1OnTimeDiff,
+                    sensor2OnTimeDiff,
+                    extraDiff));
+            EventLogTags.writeCameraGestureTriggered(
+                    gestureOnTimeDiff,
+                    sensor1OnTimeDiff,
+                    sensor2OnTimeDiff,
+                    extraDiff);
+
+            mCameraGestureLastEventTime = now;
+            mCameraGestureSensor1LastOnTimeMs = sensor1OnTime;
+            mCameraGestureSensor2LastOnTimeMs = sensor2OnTime;
+            mCameraLaunchLastEventExtra = extra;
+        }
     }
 }
diff --git a/services/core/java/com/android/server/InputMethodManagerService.java b/services/core/java/com/android/server/InputMethodManagerService.java
index 0a0ee3f..b418aba 100644
--- a/services/core/java/com/android/server/InputMethodManagerService.java
+++ b/services/core/java/com/android/server/InputMethodManagerService.java
@@ -15,8 +15,6 @@
 
 package com.android.server;
 
-import android.annotation.NonNull;
-import android.content.pm.PackageManagerInternal;
 import com.android.internal.content.PackageMonitor;
 import com.android.internal.inputmethod.InputMethodSubtypeSwitchingController;
 import com.android.internal.inputmethod.InputMethodSubtypeSwitchingController.ImeSubtypeListItem;
@@ -27,21 +25,21 @@
 import com.android.internal.util.FastXmlSerializer;
 import com.android.internal.view.IInputContext;
 import com.android.internal.view.IInputMethod;
-import com.android.internal.view.IInputSessionCallback;
 import com.android.internal.view.IInputMethodClient;
 import com.android.internal.view.IInputMethodManager;
 import com.android.internal.view.IInputMethodSession;
+import com.android.internal.view.IInputSessionCallback;
 import com.android.internal.view.InputBindResult;
 import com.android.server.statusbar.StatusBarManagerService;
-import com.android.server.wm.WindowManagerService;
 
 import org.xmlpull.v1.XmlPullParser;
 import org.xmlpull.v1.XmlPullParserException;
 import org.xmlpull.v1.XmlSerializer;
 
+import android.annotation.NonNull;
 import android.app.ActivityManagerNative;
-import android.app.AppGlobals;
 import android.app.AlertDialog;
+import android.app.AppGlobals;
 import android.app.AppOpsManager;
 import android.app.IUserSwitchObserver;
 import android.app.KeyguardManager;
@@ -61,6 +59,7 @@
 import android.content.pm.ApplicationInfo;
 import android.content.pm.IPackageManager;
 import android.content.pm.PackageManager;
+import android.content.pm.PackageManagerInternal;
 import android.content.pm.ResolveInfo;
 import android.content.pm.ServiceInfo;
 import android.content.pm.UserInfo;
@@ -80,8 +79,8 @@
 import android.os.IInterface;
 import android.os.IRemoteCallback;
 import android.os.Message;
-import android.os.Process;
 import android.os.Parcel;
+import android.os.Process;
 import android.os.RemoteException;
 import android.os.ResultReceiver;
 import android.os.ServiceManager;
@@ -90,7 +89,6 @@
 import android.os.UserManager;
 import android.provider.Settings;
 import android.text.TextUtils;
-import android.text.TextUtils.SimpleStringSplitter;
 import android.text.style.SuggestionSpan;
 import android.util.ArrayMap;
 import android.util.ArraySet;
@@ -109,6 +107,7 @@
 import android.view.View;
 import android.view.ViewGroup;
 import android.view.WindowManager;
+import android.view.WindowManagerInternal;
 import android.view.inputmethod.EditorInfo;
 import android.view.inputmethod.InputBinding;
 import android.view.inputmethod.InputMethod;
@@ -182,11 +181,11 @@
     final InputMethodSettings mSettings;
     final SettingsObserver mSettingsObserver;
     final IWindowManager mIWindowManager;
+    final WindowManagerInternal mWindowManagerInternal;
     final HandlerCaller mCaller;
     final boolean mHasFeature;
     private InputMethodFileManager mFileManager;
     private final HardKeyboardListener mHardKeyboardListener;
-    private final WindowManagerService mWindowManagerService;
     private final AppOpsManager mAppOpsManager;
 
     final InputBindResult mNoBinding = new InputBindResult(null, null, null, -1, -1);
@@ -710,7 +709,7 @@
     }
 
     private class HardKeyboardListener
-            implements WindowManagerService.OnHardKeyboardStatusChangeListener {
+            implements WindowManagerInternal.OnHardKeyboardStatusChangeListener {
         @Override
         public void onHardKeyboardStatusChange(boolean available) {
             mHandler.sendMessage(mHandler.obtainMessage(MSG_HARD_KEYBOARD_SWITCH_CHANGED,
@@ -732,7 +731,7 @@
         }
     }
 
-    public InputMethodManagerService(Context context, WindowManagerService windowManager) {
+    public InputMethodManagerService(Context context) {
         mIPackageManager = AppGlobals.getPackageManager();
         mContext = context;
         mRes = context.getResources();
@@ -741,13 +740,13 @@
         mSettingsObserver = new SettingsObserver(mHandler);
         mIWindowManager = IWindowManager.Stub.asInterface(
                 ServiceManager.getService(Context.WINDOW_SERVICE));
+        mWindowManagerInternal = LocalServices.getService(WindowManagerInternal.class);
         mCaller = new HandlerCaller(context, null, new HandlerCaller.Callback() {
             @Override
             public void executeMessage(Message msg) {
                 handleMessage(msg);
             }
         }, true /*asyncHandler*/);
-        mWindowManagerService = windowManager;
         mAppOpsManager = (AppOpsManager) mContext.getSystemService(Context.APP_OPS_SERVICE);
         mHardKeyboardListener = new HardKeyboardListener();
         mHasFeature = context.getPackageManager().hasSystemFeature(
@@ -1045,7 +1044,7 @@
                 mShowOngoingImeSwitcherForPhones = mRes.getBoolean(
                         com.android.internal.R.bool.show_ongoing_ime_switcher);
                 if (mShowOngoingImeSwitcherForPhones) {
-                    mWindowManagerService.setOnHardKeyboardStatusChangeListener(
+                    mWindowManagerInternal.setOnHardKeyboardStatusChangeListener(
                             mHardKeyboardListener);
                 }
                 buildInputMethodListLocked(mMethodList, mMethodMap,
@@ -1507,7 +1506,7 @@
                 if (DEBUG) Slog.v(TAG, "Removing window token: " + mCurToken);
                 if ((mImeWindowVis & InputMethodService.IME_ACTIVE) != 0 && savePosition) {
                     // The current IME is shown. Hence an IME switch (transition) is happening.
-                    mWindowManagerService.saveLastInputMethodWindowForTransition();
+                    mWindowManagerInternal.saveLastInputMethodWindowForTransition();
                 }
                 mIWindowManager.removeWindowToken(mCurToken);
             } catch (RemoteException e) {
@@ -1641,7 +1640,7 @@
         if (mSwitchingDialog != null) return false;
         if (isScreenLocked()) return false;
         if ((visibility & InputMethodService.IME_ACTIVE) == 0) return false;
-        if (mWindowManagerService.isHardKeyboardAvailable()) {
+        if (mWindowManagerInternal.isHardKeyboardAvailable()) {
             // When physical keyboard is attached, we show the ime switcher (or notification if
             // NavBar is not available) because SHOW_IME_WITH_HARD_KEYBOARD settings currently
             // exists in the IME switcher dialog.  Might be OK to remove this condition once
@@ -1753,15 +1752,18 @@
                 mImeSwitcherNotification.setContentTitle(title)
                         .setContentText(summary)
                         .setContentIntent(mImeSwitchPendingIntent);
-                if ((mNotificationManager != null)
-                        && !mWindowManagerService.hasNavigationBar()) {
-                    if (DEBUG) {
-                        Slog.d(TAG, "--- show notification: label =  " + summary);
+                try {
+                    if ((mNotificationManager != null)
+                            && !mIWindowManager.hasNavigationBar()) {
+                        if (DEBUG) {
+                            Slog.d(TAG, "--- show notification: label =  " + summary);
+                        }
+                        mNotificationManager.notifyAsUser(null,
+                                com.android.internal.R.string.select_input_method,
+                                mImeSwitcherNotification.build(), UserHandle.ALL);
+                        mNotificationShown = true;
                     }
-                    mNotificationManager.notifyAsUser(null,
-                            com.android.internal.R.string.select_input_method,
-                            mImeSwitcherNotification.build(), UserHandle.ALL);
-                    mNotificationShown = true;
+                } catch (RemoteException e) {
                 }
             } else {
                 if (mNotificationShown && mNotificationManager != null) {
@@ -2527,7 +2529,7 @@
 
     @Override
     public int getInputMethodWindowVisibleHeight() {
-        return mWindowManagerService.getInputMethodWindowVisibleHeight();
+        return mWindowManagerInternal.getInputMethodWindowVisibleHeight();
     }
 
     @Override
@@ -3041,7 +3043,7 @@
             mSwitchingDialogTitleView = tv;
             mSwitchingDialogTitleView
                     .findViewById(com.android.internal.R.id.hard_keyboard_section)
-                    .setVisibility(mWindowManagerService.isHardKeyboardAvailable()
+                    .setVisibility(mWindowManagerInternal.isHardKeyboardAvailable()
                             ? View.VISIBLE : View.GONE);
             final Switch hardKeySwitch = (Switch) mSwitchingDialogTitleView.findViewById(
                     com.android.internal.R.id.hard_keyboard_switch);
diff --git a/services/core/java/com/android/server/LockSettingsService.java b/services/core/java/com/android/server/LockSettingsService.java
index 7e4bcdc..c7e0c98 100644
--- a/services/core/java/com/android/server/LockSettingsService.java
+++ b/services/core/java/com/android/server/LockSettingsService.java
@@ -29,6 +29,8 @@
 import static android.Manifest.permission.ACCESS_KEYGUARD_SECURE_STORAGE;
 import static android.content.Context.USER_SERVICE;
 import static android.Manifest.permission.READ_CONTACTS;
+import static com.android.internal.widget.LockPatternUtils.StrongAuthTracker.STRONG_AUTH_REQUIRED_AFTER_LOCKOUT;
+
 import android.database.sqlite.SQLiteDatabase;
 import android.os.Binder;
 import android.os.IBinder;
@@ -664,6 +666,10 @@
             if (shouldReEnroll) {
                 credentialUtil.setCredential(credential, credential, userId);
             }
+        } else if (response.getResponseCode() == VerifyCredentialResponse.RESPONSE_RETRY) {
+            if (response.getTimeout() > 0) {
+                requireStrongAuth(STRONG_AUTH_REQUIRED_AFTER_LOCKOUT, userId);
+            }
         }
 
         return response;
diff --git a/services/core/java/com/android/server/SystemConfig.java b/services/core/java/com/android/server/SystemConfig.java
index cd61347..86183af 100644
--- a/services/core/java/com/android/server/SystemConfig.java
+++ b/services/core/java/com/android/server/SystemConfig.java
@@ -99,6 +99,12 @@
     // URL-handling state upon factory reset.
     final ArraySet<String> mLinkedApps = new ArraySet<>();
 
+    // These are the packages that are whitelisted to be able to run as system user
+    final ArraySet<String> mSystemUserWhitelistedApps = new ArraySet<>();
+
+    // These are the packages that should not run under system user
+    final ArraySet<String> mSystemUserBlacklistedApps = new ArraySet<>();
+
     public static SystemConfig getInstance() {
         synchronized (SystemConfig.class) {
             if (sInstance == null) {
@@ -144,6 +150,14 @@
         return mLinkedApps;
     }
 
+    public ArraySet<String> getSystemUserWhitelistedApps() {
+        return mSystemUserWhitelistedApps;
+    }
+
+    public ArraySet<String> getSystemUserBlacklistedApps() {
+        return mSystemUserBlacklistedApps;
+    }
+
     SystemConfig() {
         // Read configuration from system
         readPermissions(Environment.buildPath(
@@ -380,7 +394,24 @@
                         mLinkedApps.add(pkgname);
                     }
                     XmlUtils.skipCurrentTag(parser);
-
+                } else if ("system-user-whitelisted-app".equals(name)) {
+                    String pkgname = parser.getAttributeValue(null, "package");
+                    if (pkgname == null) {
+                        Slog.w(TAG, "<system-user-whitelisted-app> without package in " + permFile
+                                + " at " + parser.getPositionDescription());
+                    } else {
+                        mSystemUserWhitelistedApps.add(pkgname);
+                    }
+                    XmlUtils.skipCurrentTag(parser);
+                } else if ("system-user-blacklisted-app".equals(name)) {
+                    String pkgname = parser.getAttributeValue(null, "package");
+                    if (pkgname == null) {
+                        Slog.w(TAG, "<system-user-blacklisted-app without package in " + permFile
+                                + " at " + parser.getPositionDescription());
+                    } else {
+                        mSystemUserBlacklistedApps.add(pkgname);
+                    }
+                    XmlUtils.skipCurrentTag(parser);
                 } else {
                     XmlUtils.skipCurrentTag(parser);
                     continue;
diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java
index 007b14b..8e24127 100644
--- a/services/core/java/com/android/server/am/ActivityManagerService.java
+++ b/services/core/java/com/android/server/am/ActivityManagerService.java
@@ -54,6 +54,7 @@
 import android.app.usage.UsageEvents;
 import android.app.usage.UsageStatsManagerInternal;
 import android.appwidget.AppWidgetManager;
+import android.content.pm.AppsQueryHelper;
 import android.content.pm.PermissionInfo;
 import android.content.res.Resources;
 import android.graphics.Bitmap;
@@ -101,6 +102,7 @@
 import com.android.server.IntentResolver;
 import com.android.server.LocalServices;
 import com.android.server.ServiceThread;
+import com.android.server.SystemConfig;
 import com.android.server.SystemService;
 import com.android.server.SystemServiceManager;
 import com.android.server.Watchdog;
@@ -208,7 +210,6 @@
 import android.os.Process;
 import android.os.RemoteCallbackList;
 import android.os.RemoteException;
-import android.os.SELinux;
 import android.os.ServiceManager;
 import android.os.StrictMode;
 import android.os.SystemClock;
@@ -11983,6 +11984,8 @@
                 }
             }
 
+            enableSystemUserApps();
+
             // Start up initial activity.
             mBooting = true;
             startHomeActivityLocked(mCurrentUserId, "systemReady");
@@ -12033,6 +12036,42 @@
         }
     }
 
+    private void enableSystemUserApps() {
+        // For system user, enable apps based on the following conditions:
+        // - app is whitelisted; or has no launcher icons; or has INTERACT_ACROSS_USERS permission
+        // - app is not in the blacklist
+        if (UserManager.isSplitSystemUser()) {
+            AppsQueryHelper queryHelper = new AppsQueryHelper(mContext);
+            Set<String> enableApps = new HashSet<>();
+            enableApps.addAll(queryHelper.queryApps(AppsQueryHelper.GET_NON_LAUNCHABLE_APPS
+                            | AppsQueryHelper.GET_APPS_WITH_INTERACT_ACROSS_USERS_PERM,
+                            /* systemAppsOnly */ true, UserHandle.SYSTEM));
+            ArraySet<String> wlApps = SystemConfig.getInstance().getSystemUserWhitelistedApps();
+            enableApps.addAll(wlApps);
+            ArraySet<String> blApps = SystemConfig.getInstance().getSystemUserBlacklistedApps();
+            enableApps.removeAll(blApps);
+
+            List<String> systemApps = queryHelper.queryApps(0, /* systemAppsOnly */ true,
+                    UserHandle.SYSTEM);
+            final int systemAppsSize = systemApps.size();
+            for (int i = 0; i < systemAppsSize; i++) {
+                String pName = systemApps.get(i);
+                boolean enable = enableApps.contains(pName);
+                try {
+                    if (enable) {
+                        AppGlobals.getPackageManager().installExistingPackageAsUser(pName,
+                                UserHandle.USER_SYSTEM);
+                    } else {
+                        AppGlobals.getPackageManager().deletePackageAsUser(pName, null,
+                                UserHandle.USER_SYSTEM, PackageManager.DELETE_SYSTEM_APP);
+                    }
+                } catch (RemoteException e) {
+                    Slog.e(TAG, "Error occured when processing package " + pName, e);
+                }
+            }
+        }
+    }
+
     private boolean makeAppCrashingLocked(ProcessRecord app,
             String shortMsg, String longMsg, String stackTrace) {
         app.crashing = true;
@@ -16541,12 +16580,12 @@
                 }
                 List<ResolveInfo> newReceivers = AppGlobals.getPackageManager()
                         .queryIntentReceivers(intent, resolvedType, STOCK_PM_FLAGS, user);
-                if (user != UserHandle.USER_OWNER && newReceivers != null) {
-                    // If this is not the primary user, we need to check for
+                if (user != UserHandle.USER_SYSTEM && newReceivers != null) {
+                    // If this is not the system user, we need to check for
                     // any receivers that should be filtered out.
                     for (int i=0; i<newReceivers.size(); i++) {
                         ResolveInfo ri = newReceivers.get(i);
-                        if ((ri.activityInfo.flags&ActivityInfo.FLAG_PRIMARY_USER_ONLY) != 0) {
+                        if ((ri.activityInfo.flags&ActivityInfo.FLAG_SYSTEM_USER_ONLY) != 0) {
                             newReceivers.remove(i);
                             i--;
                         }
diff --git a/services/core/java/com/android/server/am/ActivityStack.java b/services/core/java/com/android/server/am/ActivityStack.java
index 965f5b6..f50df3a 100644
--- a/services/core/java/com/android/server/am/ActivityStack.java
+++ b/services/core/java/com/android/server/am/ActivityStack.java
@@ -902,7 +902,14 @@
         prev.task.touchActiveTime();
         clearLaunchTime(prev);
         final ActivityRecord next = mStackSupervisor.topRunningActivityLocked();
-        if (mService.mHasRecents && (next == null || next.noDisplay || next.task != prev.task || uiSleeping)) {
+        // In freeform mode we only update the thumbnail when there is no thumbnail yet since every
+        // focus change will request a thumbnail to be taken.
+        // Note furthermore that since windows can change their content in freeform mode all the
+        // time a thumbnail is possibly constantly outdated.
+        if (mService.mHasRecents &&
+                (next == null || next.noDisplay || next.task != prev.task || uiSleeping) &&
+                (!prev.task.hasThumbnail() ||
+                        prev.task.stack.mStackId != FREEFORM_WORKSPACE_STACK_ID)) {
             prev.updateThumbnailLocked(screenshotActivities(prev), null);
         }
         stopFullyDrawnTraceIfNeeded();
diff --git a/services/core/java/com/android/server/am/BatteryStatsService.java b/services/core/java/com/android/server/am/BatteryStatsService.java
index 9bf4f5f..335288d 100644
--- a/services/core/java/com/android/server/am/BatteryStatsService.java
+++ b/services/core/java/com/android/server/am/BatteryStatsService.java
@@ -1263,8 +1263,8 @@
                     Slog.v(TAG, "WiFi energy data was reset, new WiFi energy data is " + result);
                 }
 
-                // There is some accuracy error in reports so allow 30 milliseconds of error.
-                final long SAMPLE_ERROR_MILLIS = 30;
+                // There is some accuracy error in reports so allow some slop in the results.
+                final long SAMPLE_ERROR_MILLIS = 750;
                 final long totalTimeMs = result.mControllerIdleTimeMs + result.mControllerRxTimeMs +
                         result.mControllerTxTimeMs;
                 if (totalTimeMs > timePeriodMs + SAMPLE_ERROR_MILLIS) {
diff --git a/services/core/java/com/android/server/am/TaskRecord.java b/services/core/java/com/android/server/am/TaskRecord.java
index 712b8cc..9cbaec5 100644
--- a/services/core/java/com/android/server/am/TaskRecord.java
+++ b/services/core/java/com/android/server/am/TaskRecord.java
@@ -478,6 +478,14 @@
     }
 
     /**
+     * Returns true when we have a thumbnail.
+     * @return Returns true if there is a thumbnail.
+     */
+    boolean hasThumbnail() {
+        return mLastThumbnail != null;
+    }
+
+    /**
      * Sets the last thumbnail.
      * @return whether the thumbnail was set
      */
diff --git a/services/core/java/com/android/server/fingerprint/FingerprintService.java b/services/core/java/com/android/server/fingerprint/FingerprintService.java
index 932662f..470bd5a 100644
--- a/services/core/java/com/android/server/fingerprint/FingerprintService.java
+++ b/services/core/java/com/android/server/fingerprint/FingerprintService.java
@@ -298,6 +298,7 @@
             final int result = daemon.enroll(cryptoToken, groupId, timeout);
             if (result != 0) {
                 Slog.w(TAG, "startEnroll failed, result=" + result);
+                dispatchError(mHalDeviceId, FingerprintManager.FINGERPRINT_ERROR_HW_UNAVAILABLE);
             }
         } catch (RemoteException e) {
             Slog.e(TAG, "startEnroll failed", e);
@@ -391,6 +392,7 @@
             final int result = daemon.authenticate(opId, groupId);
             if (result != 0) {
                 Slog.w(TAG, "startAuthentication failed, result=" + result);
+                dispatchError(mHalDeviceId, FingerprintManager.FINGERPRINT_ERROR_HW_UNAVAILABLE);
             }
         } catch (RemoteException e) {
             Slog.e(TAG, "startAuthentication failed", e);
@@ -433,12 +435,14 @@
             return;
         }
 
+        stopPendingOperations(true);
         mRemoveClient = new ClientMonitor(token, receiver, userId, restricted);
         // The fingerprint template ids will be removed when we get confirmation from the HAL
         try {
             final int result = daemon.remove(fingerId, userId);
             if (result != 0) {
                 Slog.w(TAG, "startRemove with id = " + fingerId + " failed, result=" + result);
+                dispatchError(mHalDeviceId, FingerprintManager.FINGERPRINT_ERROR_HW_UNAVAILABLE);
             }
         } catch (RemoteException e) {
             Slog.e(TAG, "startRemove failed", e);
diff --git a/services/core/java/com/android/server/notification/ZenModeHelper.java b/services/core/java/com/android/server/notification/ZenModeHelper.java
index edd274b..0a12d5a 100644
--- a/services/core/java/com/android/server/notification/ZenModeHelper.java
+++ b/services/core/java/com/android/server/notification/ZenModeHelper.java
@@ -413,8 +413,7 @@
         applyRestrictions(muteNotifications, USAGE_NOTIFICATION);
 
         // call restrictions
-        final boolean muteCalls = zen && !mConfig.allowCalls && !mConfig.allowRepeatCallers
-                || mEffectsSuppressed;
+        final boolean muteCalls = zen && !mConfig.allowCalls && !mConfig.allowRepeatCallers;
         applyRestrictions(muteCalls, USAGE_NOTIFICATION_RINGTONE);
 
         // alarm restrictions
diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java
index a559116..9e878e7 100644
--- a/services/core/java/com/android/server/pm/PackageManagerService.java
+++ b/services/core/java/com/android/server/pm/PackageManagerService.java
@@ -4554,7 +4554,7 @@
                 if (xpResolveInfo != null && isUserEnabled(xpResolveInfo.targetUserId)) {
                     List<ResolveInfo> result = new ArrayList<ResolveInfo>(1);
                     result.add(xpResolveInfo);
-                    return filterIfNotPrimaryUser(result, userId);
+                    return filterIfNotSystemUser(result, userId);
                 }
 
                 // Check for results in the current profile.
@@ -4568,7 +4568,7 @@
                     result.add(xpResolveInfo);
                     Collections.sort(result, mResolvePrioritySorter);
                 }
-                result = filterIfNotPrimaryUser(result, userId);
+                result = filterIfNotSystemUser(result, userId);
                 if (hasWebURI(intent)) {
                     CrossProfileDomainInfo xpDomainInfo = null;
                     final UserInfo parent = getProfileParent(userId);
@@ -4597,7 +4597,7 @@
             }
             final PackageParser.Package pkg = mPackages.get(pkgName);
             if (pkg != null) {
-                return filterIfNotPrimaryUser(
+                return filterIfNotSystemUser(
                         mActivities.queryIntentForPackage(
                                 intent, resolvedType, flags, pkg.activities, userId),
                         userId);
@@ -4644,7 +4644,7 @@
             if (result == null) {
                 result = new CrossProfileDomainInfo();
                 result.resolveInfo =
-                        createForwardingResolveInfo(null, sourceUserId, parentUserId);
+                        createForwardingResolveInfo(new IntentFilter(), sourceUserId, parentUserId);
                 result.bestDomainVerificationStatus = status;
             } else {
                 result.bestDomainVerificationStatus = bestDomainVerificationStatus(status,
@@ -4684,17 +4684,17 @@
     }
 
     /**
-     * Filter out activities with primaryUserOnly flag set, when current user is not the owner.
+     * Filter out activities with systemUserOnly flag set, when current user is not System.
      *
      * @return filtered list
      */
-    private List<ResolveInfo> filterIfNotPrimaryUser(List<ResolveInfo> resolveInfos, int userId) {
-        if (userId == UserHandle.USER_OWNER) {
+    private List<ResolveInfo> filterIfNotSystemUser(List<ResolveInfo> resolveInfos, int userId) {
+        if (userId == UserHandle.USER_SYSTEM) {
             return resolveInfos;
         }
         for (int i = resolveInfos.size() - 1; i >= 0; i--) {
             ResolveInfo info = resolveInfos.get(i);
-            if ((info.activityInfo.flags & ActivityInfo.FLAG_PRIMARY_USER_ONLY) != 0) {
+            if ((info.activityInfo.flags & ActivityInfo.FLAG_SYSTEM_USER_ONLY) != 0) {
                 resolveInfos.remove(i);
             }
         }
diff --git a/services/core/java/com/android/server/pm/Settings.java b/services/core/java/com/android/server/pm/Settings.java
index 715dd2c..61d2676 100644
--- a/services/core/java/com/android/server/pm/Settings.java
+++ b/services/core/java/com/android/server/pm/Settings.java
@@ -23,7 +23,6 @@
 import static android.content.pm.PackageManager.COMPONENT_ENABLED_STATE_ENABLED;
 import static android.Manifest.permission.READ_EXTERNAL_STORAGE;
 import static android.content.pm.PackageManager.INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_ALWAYS;
-import static android.content.pm.PackageManager.INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_NEVER;
 import static android.content.pm.PackageManager.INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_UNDEFINED;
 import static android.os.Process.SYSTEM_UID;
 import static android.os.Process.PACKAGE_INFO_GID;
@@ -39,13 +38,10 @@
 import android.os.Build;
 import android.os.Environment;
 import android.os.FileUtils;
-import android.os.IBinder;
 import android.os.Handler;
 import android.os.Message;
 import android.os.PatternMatcher;
 import android.os.Process;
-import android.os.RemoteException;
-import android.os.ServiceManager;
 import android.os.SystemClock;
 import android.os.UserHandle;
 import android.os.UserManager;
diff --git a/services/core/java/com/android/server/policy/PhoneWindowManager.java b/services/core/java/com/android/server/policy/PhoneWindowManager.java
index e0da33f..4aaba14 100644
--- a/services/core/java/com/android/server/policy/PhoneWindowManager.java
+++ b/services/core/java/com/android/server/policy/PhoneWindowManager.java
@@ -4455,7 +4455,7 @@
                     if (mAppsToBeHidden.isEmpty()) {
                         if (dismissKeyguard && !mKeyguardSecure) {
                             mAppsThatDismissKeyguard.add(appToken);
-                        } else {
+                        } else if (win.isDrawnLw()) {
                             mWinShowWhenLocked = win;
                             mHideLockScreen = true;
                             mForceStatusBarFromKeyguard = false;
@@ -4489,7 +4489,7 @@
                         mWinDismissingKeyguard = win;
                         mSecureDismissingKeyguard = mKeyguardSecure;
                         mForceStatusBarFromKeyguard = mShowingLockscreen && mKeyguardSecure;
-                    } else if (mAppsToBeHidden.isEmpty() && showWhenLocked) {
+                    } else if (mAppsToBeHidden.isEmpty() && showWhenLocked && win.isDrawnLw()) {
                         if (DEBUG_LAYOUT) Slog.v(TAG,
                                 "Setting mHideLockScreen to true by win " + win);
                         mHideLockScreen = true;
diff --git a/services/core/java/com/android/server/policy/WindowOrientationListener.java b/services/core/java/com/android/server/policy/WindowOrientationListener.java
index 8b3c036..9916223 100644
--- a/services/core/java/com/android/server/policy/WindowOrientationListener.java
+++ b/services/core/java/com/android/server/policy/WindowOrientationListener.java
@@ -217,6 +217,8 @@
      * It is called each time the orientation determination transitions from being
      * uncertain to being certain again, even if it is the same orientation as before.
      *
+     * This should only be called on the Handler thread.
+     *
      * @param rotation The new orientation of the device, one of the Surface.ROTATION_* constants.
      * @see android.view.Surface
      */
@@ -995,9 +997,13 @@
 
         @Override
         public void onSensorChanged(SensorEvent event) {
+            int newRotation;
             synchronized (mLock) {
                 mDesiredRotation = (int) event.values[0];
-                evaluateRotationChangeLocked();
+                newRotation = evaluateRotationChangeLocked();
+            }
+            if (newRotation >=0) {
+                onProposedRotationChanged(newRotation);
             }
         }
 
@@ -1023,18 +1029,19 @@
             unscheduleRotationEvaluationLocked();
         }
 
-        public void evaluateRotationChangeLocked() {
+        public int evaluateRotationChangeLocked() {
             unscheduleRotationEvaluationLocked();
             if (mDesiredRotation == mProposedRotation) {
-                return;
+                return -1;
             }
             final long now = SystemClock.elapsedRealtimeNanos();
             if (isDesiredRotationAcceptableLocked(now)) {
                 mProposedRotation = mDesiredRotation;
-                onProposedRotationChanged(mProposedRotation);
+                return mProposedRotation;
             } else {
                 scheduleRotationEvaluationIfNecessaryLocked(now);
             }
+            return -1;
         }
 
         private boolean isDesiredRotationAcceptableLocked(long now) {
@@ -1090,9 +1097,13 @@
         private Runnable mRotationEvaluator = new Runnable() {
             @Override
             public void run() {
+                int newRotation;
                 synchronized (mLock) {
                     mRotationEvaluationScheduled = false;
-                    evaluateRotationChangeLocked();
+                    newRotation = evaluateRotationChangeLocked();
+                }
+                if (newRotation >= 0) {
+                    onProposedRotationChanged(newRotation);
                 }
             }
         };
diff --git a/services/core/java/com/android/server/statusbar/StatusBarManagerInternal.java b/services/core/java/com/android/server/statusbar/StatusBarManagerInternal.java
index 130815e..5d01931 100644
--- a/services/core/java/com/android/server/statusbar/StatusBarManagerInternal.java
+++ b/services/core/java/com/android/server/statusbar/StatusBarManagerInternal.java
@@ -28,4 +28,5 @@
     void showScreenPinningRequest();
     void showAssistDisclosure();
     void startAssist(Bundle args);
+    void onCameraLaunchGestureDetected();
 }
diff --git a/services/core/java/com/android/server/statusbar/StatusBarManagerService.java b/services/core/java/com/android/server/statusbar/StatusBarManagerService.java
index 8663254..87dc6c4 100644
--- a/services/core/java/com/android/server/statusbar/StatusBarManagerService.java
+++ b/services/core/java/com/android/server/statusbar/StatusBarManagerService.java
@@ -176,6 +176,16 @@
                 }
             }
         }
+
+        @Override
+        public void onCameraLaunchGestureDetected() {
+            if (mBar != null) {
+                try {
+                    mBar.onCameraLaunchGestureDetected();
+                } catch (RemoteException e) {
+                }
+            }
+        }
     };
 
     // ================================================================================
diff --git a/services/core/java/com/android/server/wm/AppTransition.java b/services/core/java/com/android/server/wm/AppTransition.java
index d1145d0..de7c07e 100644
--- a/services/core/java/com/android/server/wm/AppTransition.java
+++ b/services/core/java/com/android/server/wm/AppTransition.java
@@ -870,10 +870,10 @@
     }
 
     private Animation createAspectScaledThumbnailEnterNonFullscreenAnimationLocked(
-            Rect containingFrame, @Nullable Rect surfaceInsets, int taskId) {
+            Rect frame, @Nullable Rect surfaceInsets, int taskId) {
         getNextAppTransitionStartRect(taskId, mTmpStartRect);
-        float width = containingFrame.width();
-        float height = containingFrame.height();
+        float width = frame.width();
+        float height = frame.height();
         float scaleWidth = mTmpStartRect.width() / width;
         float scaleHeight = mTmpStartRect.height() / height;
         AnimationSet set = new AnimationSet(true);
@@ -886,9 +886,9 @@
         ScaleAnimation scale = new ScaleAnimation(scaleWidth, 1, scaleHeight, 1,
                 (width + surfaceInsetsHorizontal) / 2, (height + surfaceInsetsVertical) / 2);
         int fromX = mTmpStartRect.left + mTmpStartRect.width() / 2
-                - (containingFrame.left + containingFrame.width() / 2);
+                - (frame.left + frame.width() / 2);
         int fromY = mTmpStartRect.top + mTmpStartRect.height() / 2
-                - (containingFrame.top + containingFrame.height() / 2);
+                - (frame.top + frame.height() / 2);
         TranslateAnimation translation = new TranslateAnimation(fromX, 0, fromY, 0);
         set.addAnimation(scale);
         set.addAnimation(translation);
diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java
index 7b4c2a0..cf690a5 100644
--- a/services/core/java/com/android/server/wm/WindowManagerService.java
+++ b/services/core/java/com/android/server/wm/WindowManagerService.java
@@ -552,7 +552,7 @@
 
     boolean mHardKeyboardAvailable;
     boolean mShowImeWithHardKeyboard;
-    OnHardKeyboardStatusChangeListener mHardKeyboardStatusChangeListener;
+    WindowManagerInternal.OnHardKeyboardStatusChangeListener mHardKeyboardStatusChangeListener;
     SettingsObserver mSettingsObserver;
 
     private final class SettingsObserver extends ContentObserver {
@@ -2806,12 +2806,17 @@
             Rect appFrame = new Rect(0, 0, width, height);
             Rect surfaceInsets = null;
             final boolean fullscreen = win != null && win.isFullscreen(width, height);
-            // Dialog activities have windows with containing frame being very large, but not
-            // exactly fullscreen and much smaller mFrame. We use this distinction to identify
-            // dialog activities.
-            final boolean dialogWindow = win != null && !win.mContainingFrame.equals(win.mFrame);
+            final boolean freeform = win != null && win.inFreeformWorkspace();
             if (win != null) {
-                containingFrame.set(win.mContainingFrame);
+                // Containing frame will usually cover the whole screen, including dialog windows.
+                // For freeform workspace windows it will not cover the whole screen and it also
+                // won't exactly match the final freeform window frame (e.g. when overlapping with
+                // the status bar). In that case we need to use the final frame.
+                if (freeform) {
+                    containingFrame.set(win.mFrame);
+                } else {
+                    containingFrame.set(win.mContainingFrame);
+                }
                 surfaceInsets = win.getAttrs().surfaceInsets;
                 if (fullscreen) {
                     // For fullscreen windows use the window frames and insets to set the thumbnail
@@ -2830,11 +2835,9 @@
                 // screen gets the enter animation. Both appear in the mOpeningApps set.
                 enter = false;
             }
-            final boolean resizedWindow = !fullscreen && !dialogWindow;
             Animation a = mAppTransition.loadAnimation(lp, transit, enter, containingWidth,
                     containingHeight, mCurConfiguration.orientation, containingFrame, contentInsets,
-                    surfaceInsets, appFrame, isVoiceInteraction, resizedWindow,
-                    atoken.mTask.mTaskId);
+                    surfaceInsets, appFrame, isVoiceInteraction, freeform, atoken.mTask.mTaskId);
             if (a != null) {
                 if (DEBUG_ANIM) {
                     RuntimeException e = null;
@@ -6808,12 +6811,6 @@
         mPolicy.adjustConfigurationLw(config, keyboardPresence, navigationPresence);
     }
 
-    public boolean isHardKeyboardAvailable() {
-        synchronized (mWindowMap) {
-            return mHardKeyboardAvailable;
-        }
-    }
-
     public void updateShowImeWithHardKeyboard() {
         synchronized (mWindowMap) {
             final boolean showImeWithHardKeyboard = Settings.Secure.getIntForUser(
@@ -6826,16 +6823,9 @@
         }
     }
 
-    public void setOnHardKeyboardStatusChangeListener(
-            OnHardKeyboardStatusChangeListener listener) {
-        synchronized (mWindowMap) {
-            mHardKeyboardStatusChangeListener = listener;
-        }
-    }
-
     void notifyHardKeyboardStatusChange() {
         final boolean available;
-        final OnHardKeyboardStatusChangeListener listener;
+        final WindowManagerInternal.OnHardKeyboardStatusChangeListener listener;
         synchronized (mWindowMap) {
             listener = mHardKeyboardStatusChangeListener;
             available = mHardKeyboardAvailable;
@@ -10431,23 +10421,6 @@
         }
     }
 
-    // It is assumed that this method is called only by InputMethodManagerService.
-    public void saveLastInputMethodWindowForTransition() {
-        synchronized (mWindowMap) {
-            // TODO(multidisplay): Pass in the displayID.
-            DisplayContent displayContent = getDefaultDisplayContentLocked();
-            if (mInputMethodWindow != null) {
-                mPolicy.setLastInputMethodWindowLw(mInputMethodWindow, mInputMethodTarget);
-            }
-        }
-    }
-
-    public int getInputMethodWindowVisibleHeight() {
-        synchronized (mWindowMap) {
-            return mPolicy.getInputMethodWindowVisibleHeightLw();
-        }
-    }
-
     @Override
     public boolean hasNavigationBar() {
         return mPolicy.hasNavigationBar();
@@ -11037,10 +11010,6 @@
         synchronized (mWindowMap) { }
     }
 
-    public interface OnHardKeyboardStatusChangeListener {
-        public void onHardKeyboardStatusChange(boolean available);
-    }
-
     void debugLayoutRepeats(final String msg, int pendingLayoutChanges) {
         if (mLayoutRepeatCount >= LAYOUT_REPEAT_THRESHOLD) {
             Slog.v(TAG, "Layouts looping: " + msg + ", mPendingLayoutChanges = 0x" +
@@ -11348,5 +11317,39 @@
                 mAppTransition.registerListenerLocked(listener);
             }
         }
+
+        @Override
+        public int getInputMethodWindowVisibleHeight() {
+            synchronized (mWindowMap) {
+                return mPolicy.getInputMethodWindowVisibleHeightLw();
+            }
+        }
+
+        @Override
+        public void saveLastInputMethodWindowForTransition() {
+            synchronized (mWindowMap) {
+                // TODO(multidisplay): Pass in the displayID.
+                DisplayContent displayContent = getDefaultDisplayContentLocked();
+                if (mInputMethodWindow != null) {
+                    mPolicy.setLastInputMethodWindowLw(mInputMethodWindow, mInputMethodTarget);
+                }
+            }
+        }
+
+        @Override
+        public boolean isHardKeyboardAvailable() {
+            synchronized (mWindowMap) {
+                return mHardKeyboardAvailable;
+            }
+        }
+
+        @Override
+        public void setOnHardKeyboardStatusChangeListener(
+                OnHardKeyboardStatusChangeListener listener) {
+            synchronized (mWindowMap) {
+                mHardKeyboardStatusChangeListener = listener;
+            }
+        }
+
     }
 }
diff --git a/services/core/java/com/android/server/wm/WindowState.java b/services/core/java/com/android/server/wm/WindowState.java
index 092a6d1..761e5eb 100644
--- a/services/core/java/com/android/server/wm/WindowState.java
+++ b/services/core/java/com/android/server/wm/WindowState.java
@@ -1629,7 +1629,7 @@
         }
     }
 
-    private boolean inFreeformWorkspace() {
+    boolean inFreeformWorkspace() {
         final Task task = getTask();
         return task != null && task.mStack != null &&
                 task.mStack.mStackId == FREEFORM_WORKSPACE_STACK_ID;
diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
index 0f60cc8..8788908 100644
--- a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
+++ b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
@@ -4236,6 +4236,17 @@
                 mDeviceOwner.clearDeviceOwner();
                 mDeviceOwner.writeOwnerFile();
                 updateDeviceOwnerLocked();
+                // Reactivate backup service.
+                long ident = Binder.clearCallingIdentity();
+                try {
+                    IBackupManager ibm = IBackupManager.Stub.asInterface(
+                            ServiceManager.getService(Context.BACKUP_SERVICE));
+                    ibm.setBackupServiceActive(UserHandle.USER_OWNER, true);
+                } catch (RemoteException e) {
+                    throw new IllegalStateException("Failed reactivating backup service.", e);
+                } finally {
+                    Binder.restoreCallingIdentity(ident);
+                }
             }
         }
     }
diff --git a/services/java/com/android/server/SystemServer.java b/services/java/com/android/server/SystemServer.java
index ed32c76..21dd647b 100644
--- a/services/java/com/android/server/SystemServer.java
+++ b/services/java/com/android/server/SystemServer.java
@@ -546,7 +546,7 @@
         if (mFactoryTestMode != FactoryTest.FACTORY_TEST_LOW_LEVEL) {
             try {
                 Slog.i(TAG, "Input Method Service");
-                imm = new InputMethodManagerService(context, wm);
+                imm = new InputMethodManagerService(context);
                 ServiceManager.addService(Context.INPUT_METHOD_SERVICE, imm);
             } catch (Throwable e) {
                 reportWtf("starting Input Manager Service", e);
diff --git a/services/usb/java/com/android/server/usb/UsbDeviceManager.java b/services/usb/java/com/android/server/usb/UsbDeviceManager.java
index fb9a3a3..b021e80 100644
--- a/services/usb/java/com/android/server/usb/UsbDeviceManager.java
+++ b/services/usb/java/com/android/server/usb/UsbDeviceManager.java
@@ -61,6 +61,7 @@
 import java.util.Locale;
 import java.util.Map;
 import java.util.Scanner;
+import java.util.Set;
 
 /**
  * UsbDeviceManager manages USB state in device mode.
@@ -148,6 +149,7 @@
     private String[] mAccessoryStrings;
     private UsbDebuggingManager mDebuggingManager;
     private final UsbAlsaManager mUsbAlsaManager;
+    private Intent mBroadcastedIntent;
 
     private class AdbSettingsObserver extends ContentObserver {
         public AdbSettingsObserver() {
@@ -427,7 +429,7 @@
             if (DEBUG) Slog.d(TAG, "setUsbDataUnlocked: " + enable);
             mUsbDataUnlocked = enable;
             updateUsbNotification();
-            updateUsbStateBroadcast();
+            updateUsbStateBroadcastIfNeeded();
             setEnabledFunctions(mCurrentFunctions, true);
         }
 
@@ -574,7 +576,33 @@
             }
         }
 
-        private void updateUsbStateBroadcast() {
+        private boolean isUsbStateChanged(Intent intent) {
+            final Set<String> keySet = intent.getExtras().keySet();
+            if (mBroadcastedIntent == null) {
+                for (String key : keySet) {
+                    if (intent.getBooleanExtra(key, false)) {
+                        // MTP function is enabled by default.
+                        if (UsbManager.USB_FUNCTION_MTP.equals(key)) {
+                            continue;
+                        }
+                        return true;
+                    }
+                }
+            } else {
+                if (!keySet.equals(mBroadcastedIntent.getExtras().keySet())) {
+                    return true;
+                }
+                for (String key : keySet) {
+                    if (intent.getBooleanExtra(key, false) !=
+                        mBroadcastedIntent.getBooleanExtra(key, false)) {
+                        return true;
+                    }
+                }
+            }
+            return false;
+        }
+
+        private void updateUsbStateBroadcastIfNeeded() {
             // send a sticky broadcast containing current USB state
             Intent intent = new Intent(UsbManager.ACTION_USB_STATE);
             intent.addFlags(Intent.FLAG_RECEIVER_REPLACE_PENDING
@@ -586,13 +614,25 @@
             if (mCurrentFunctions != null) {
                 String[] functions = mCurrentFunctions.split(",");
                 for (int i = 0; i < functions.length; i++) {
-                    intent.putExtra(functions[i], true);
+                    final String function = functions[i];
+                    if (UsbManager.USB_FUNCTION_NONE.equals(function)) {
+                        continue;
+                    }
+                    intent.putExtra(function, true);
                 }
             }
 
-            if (DEBUG) Slog.d(TAG, "broadcasting " + intent + " connected: " + mConnected
-                                    + " configured: " + mConfigured);
+            // send broadcast intent only if the USB state has changed
+            if (!isUsbStateChanged(intent)) {
+                if (DEBUG) {
+                    Slog.d(TAG, "skip broadcasting " + intent + " extras: " + intent.getExtras());
+                }
+                return;
+            }
+
+            if (DEBUG) Slog.d(TAG, "broadcasting " + intent + " extras: " + intent.getExtras());
             mContext.sendStickyBroadcastAsUser(intent, UserHandle.ALL);
+            mBroadcastedIntent = intent;
         }
 
         private void updateUsbFunctions() {
@@ -670,7 +710,7 @@
                         setEnabledFunctions(null, false);
                     }
                     if (mBootCompleted) {
-                        updateUsbStateBroadcast();
+                        updateUsbStateBroadcastIfNeeded();
                         updateUsbFunctions();
                     }
                     break;
@@ -694,7 +734,7 @@
                 case MSG_SYSTEM_READY:
                     updateUsbNotification();
                     updateAdbNotification();
-                    updateUsbStateBroadcast();
+                    updateUsbStateBroadcastIfNeeded();
                     updateUsbFunctions();
                     break;
                 case MSG_BOOT_COMPLETED:
diff --git a/telephony/java/android/telephony/CarrierConfigManager.java b/telephony/java/android/telephony/CarrierConfigManager.java
index 31f1d7f..e3f3c75 100644
--- a/telephony/java/android/telephony/CarrierConfigManager.java
+++ b/telephony/java/android/telephony/CarrierConfigManager.java
@@ -266,6 +266,13 @@
     public static final String KEY_CARRIER_INSTANT_LETTERING_AVAILABLE_BOOL =
             "carrier_instant_lettering_available_bool";
 
+    /*
+     * Flag specifying whether IMS should be the first phone attempted for E911 even if the
+     * phone is not in service.
+     */
+    public static final String KEY_CARRIER_USE_IMS_FIRST_FOR_EMERGENCY_BOOL
+            = "carrier_use_ims_first_for_emergency_bool";
+
     /**
      * If Voice Radio Technology is RIL_RADIO_TECHNOLOGY_LTE:14 or RIL_RADIO_TECHNOLOGY_UNKNOWN:0
      * this is the value that should be used instead. A configuration value of
@@ -425,6 +432,7 @@
         sDefaults.putBoolean(KEY_CARRIER_VOLTE_TTY_SUPPORTED_BOOL, true);
         sDefaults.putBoolean(KEY_CARRIER_ALLOW_TURNOFF_IMS_BOOL, true);
         sDefaults.putBoolean(KEY_CARRIER_INSTANT_LETTERING_AVAILABLE_BOOL, false);
+        sDefaults.putBoolean(KEY_CARRIER_USE_IMS_FIRST_FOR_EMERGENCY_BOOL, true);
         sDefaults.putBoolean(KEY_DISABLE_CDMA_ACTIVATION_CODE_BOOL, false);
         sDefaults.putBoolean(KEY_DTMF_TYPE_ENABLED_BOOL, false);
         sDefaults.putBoolean(KEY_ENABLE_DIALER_KEY_VIBRATION_BOOL, true);
diff --git a/telephony/java/android/telephony/PhoneNumberUtils.java b/telephony/java/android/telephony/PhoneNumberUtils.java
index 79146f3..273cc93 100644
--- a/telephony/java/android/telephony/PhoneNumberUtils.java
+++ b/telephony/java/android/telephony/PhoneNumberUtils.java
@@ -1135,6 +1135,8 @@
         "VI", // U.S. Virgin Islands
     };
 
+    private static final String KOREA_ISO_COUNTRY_CODE = "KR";
+
     /**
      * Breaks the given number down and formats it according to the rules
      * for the country the number is from.
@@ -1455,7 +1457,14 @@
         String result = null;
         try {
             PhoneNumber pn = util.parseAndKeepRawInput(phoneNumber, defaultCountryIso);
-            result = util.formatInOriginalFormat(pn, defaultCountryIso);
+            if (KOREA_ISO_COUNTRY_CODE.equals(defaultCountryIso) &&
+                    (pn.getCountryCode() == util.getCountryCodeForRegion(KOREA_ISO_COUNTRY_CODE))) {
+                // Format local Korean phone numbers with country code to corresponding national
+                // format which would replace the leading +82 with 0.
+                result = util.format(pn, PhoneNumberUtil.PhoneNumberFormat.NATIONAL);
+            } else {
+                result = util.formatInOriginalFormat(pn, defaultCountryIso);
+            }
         } catch (NumberParseException e) {
         }
         return result;
diff --git a/tests/UiBench/.gitignore b/tests/UiBench/.gitignore
new file mode 100644
index 0000000..c39eac2
--- /dev/null
+++ b/tests/UiBench/.gitignore
@@ -0,0 +1,5 @@
+.gradle
+.idea
+*.iml
+build
+local.properties
diff --git a/tests/UiBench/Android.mk b/tests/UiBench/Android.mk
new file mode 100644
index 0000000..ce9db3d
--- /dev/null
+++ b/tests/UiBench/Android.mk
@@ -0,0 +1,23 @@
+LOCAL_PATH:= $(call my-dir)
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_TAGS := tests
+
+# omit gradle 'build' dir
+LOCAL_SRC_FILES := $(call all-java-files-under,src)
+
+# use appcompat/support lib from the tree, so improvements/
+# regressions are reflected in test data
+LOCAL_RESOURCE_DIR := \
+    frameworks/support/v7/appcompat/res
+
+LOCAL_AAPT_FLAGS := \
+    --extra-packages android.support.v7.appcompat
+
+LOCAL_STATIC_JAVA_LIBRARIES := \
+    android-support-v4 \
+    android-support-v7-appcompat
+
+LOCAL_PACKAGE_NAME := UiBench
+
+include $(BUILD_PACKAGE)
diff --git a/tests/UiBench/AndroidManifest.xml b/tests/UiBench/AndroidManifest.xml
new file mode 100644
index 0000000..b19e109
--- /dev/null
+++ b/tests/UiBench/AndroidManifest.xml
@@ -0,0 +1,45 @@
+<!--
+  ~ Copyright (C) 2015 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
+  -->
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+        package="com.android.test.uibench">
+
+    <application
+        android:allowBackup="false"
+        android:theme="@style/Theme.AppCompat.Light.DarkActionBar">
+        <uses-library android:name="android.test.runner" />
+
+        <!-- Root navigation activity -->
+        <activity
+            android:name=".MainActivity"
+            android:label="UiBench">
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN" />
+                <category android:name="android.intent.category.DEFAULT" />
+                <category android:name="android.intent.category.LAUNCHER" />
+            </intent-filter>
+        </activity>
+
+        <!-- Tests -->
+        <activity
+            android:name=".TrivialListActivity"
+            android:label="Microbenchmarks/Trivial ListActivity" >
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN" />
+                <category android:name="com.android.test.uibench.TEST" />
+            </intent-filter>
+        </activity>
+    </application>
+</manifest>
diff --git a/tests/UiBench/build.gradle b/tests/UiBench/build.gradle
new file mode 100644
index 0000000..bf0ed11
--- /dev/null
+++ b/tests/UiBench/build.gradle
@@ -0,0 +1,37 @@
+buildscript {
+    repositories {
+        jcenter()
+    }
+    dependencies {
+        classpath 'com.android.tools.build:gradle:1.3.0'
+
+    }
+}
+
+apply plugin: 'com.android.application'
+
+android {
+    compileSdkVersion 23
+    buildToolsVersion "22.0.0"
+
+    defaultConfig {
+        minSdkVersion 14
+        targetSdkVersion 23
+        versionCode 1
+        versionName "1.0"
+    }
+
+    sourceSets {
+        main {
+            manifest.srcFile 'AndroidManifest.xml'
+            java.srcDirs = ['src']
+            res.srcDirs = ['res']
+        }
+    }
+}
+
+dependencies {
+    // Dependencies enumerated specifically for platform-independent / reproducible builds.
+    compile 'com.android.support:support-v4:23.0.0'
+    compile 'com.android.support:appcompat-v7:23.0.0'
+}
diff --git a/tests/UiBench/gradle/wrapper/gradle-wrapper.jar b/tests/UiBench/gradle/wrapper/gradle-wrapper.jar
new file mode 100644
index 0000000..8c0fb64
--- /dev/null
+++ b/tests/UiBench/gradle/wrapper/gradle-wrapper.jar
Binary files differ
diff --git a/tests/UiBench/gradle/wrapper/gradle-wrapper.properties b/tests/UiBench/gradle/wrapper/gradle-wrapper.properties
new file mode 100644
index 0000000..12582f8
--- /dev/null
+++ b/tests/UiBench/gradle/wrapper/gradle-wrapper.properties
@@ -0,0 +1,6 @@
+#Wed Aug 26 10:51:13 PDT 2015
+distributionBase=GRADLE_USER_HOME
+distributionPath=wrapper/dists
+zipStoreBase=GRADLE_USER_HOME
+zipStorePath=wrapper/dists
+distributionUrl=https\://services.gradle.org/distributions/gradle-2.4-all.zip
diff --git a/tests/UiBench/src/com/android/test/uibench/MainActivity.java b/tests/UiBench/src/com/android/test/uibench/MainActivity.java
new file mode 100644
index 0000000..7c3391d
--- /dev/null
+++ b/tests/UiBench/src/com/android/test/uibench/MainActivity.java
@@ -0,0 +1,166 @@
+/*
+ * Copyright (C) 2015 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.test.uibench;
+
+import android.content.Intent;
+import android.content.pm.PackageManager;
+import android.content.pm.ResolveInfo;
+import android.os.Bundle;
+import android.support.v4.app.FragmentManager;
+import android.support.v4.app.ListFragment;
+import android.support.v7.app.AppCompatActivity;
+import android.view.View;
+import android.widget.ListView;
+import android.widget.SimpleAdapter;
+
+import java.text.Collator;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+public class MainActivity extends AppCompatActivity {
+    private static final String EXTRA_PATH = "activity_path";
+    private static final String CATEGORY_HWUI_TEST = "com.android.test.uibench.TEST";
+
+    @Override
+    public void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+
+        Intent intent = getIntent();
+        String path = intent.getStringExtra(EXTRA_PATH);
+
+        if (path == null) {
+            path = "";
+        } else {
+            // not root level, display where we are in the hierarchy
+            setTitle(path);
+        }
+
+        FragmentManager fm = getSupportFragmentManager();
+        if (fm.findFragmentById(android.R.id.content) == null) {
+            ListFragment listFragment = new ListFragment() {
+                @Override
+                @SuppressWarnings({ "unchecked" })
+                public void onListItemClick(ListView l, View v, int position, long id) {
+                    Map<String, Object> map = (Map<String, Object>)l.getItemAtPosition(position);
+
+                    Intent intent = (Intent) map.get("intent");
+                    startActivity(intent);
+                }
+
+                @Override
+                public void onViewCreated(View view, Bundle savedInstanceState) {
+                    super.onViewCreated(view, savedInstanceState);
+                    getListView().setTextFilterEnabled(true);
+                }
+            };
+            listFragment.setListAdapter(new SimpleAdapter(this, getData(path),
+                    android.R.layout.simple_list_item_1, new String[] { "title" },
+                    new int[] { android.R.id.text1 }));
+            fm.beginTransaction().add(android.R.id.content, listFragment).commit();
+        }
+    }
+
+    protected List<Map<String, Object>> getData(String prefix) {
+        List<Map<String, Object>> myData = new ArrayList<>();
+
+        Intent mainIntent = new Intent(Intent.ACTION_MAIN, null);
+        mainIntent.addCategory(CATEGORY_HWUI_TEST);
+
+        PackageManager pm = getPackageManager();
+        List<ResolveInfo> list = pm.queryIntentActivities(mainIntent, 0);
+
+        if (null == list)
+            return myData;
+
+        String[] prefixPath;
+        String prefixWithSlash = prefix;
+
+        if (prefix.equals("")) {
+            prefixPath = null;
+        } else {
+            prefixPath = prefix.split("/");
+            prefixWithSlash = prefix + "/";
+        }
+
+        int len = list.size();
+
+        Map<String, Boolean> entries = new HashMap<>();
+
+        for (int i = 0; i < len; i++) {
+            ResolveInfo info = list.get(i);
+            CharSequence labelSeq = info.loadLabel(pm);
+            String label = labelSeq != null
+                    ? labelSeq.toString()
+                    : info.activityInfo.name;
+
+            if (prefixWithSlash.length() == 0 || label.startsWith(prefixWithSlash)) {
+
+                String[] labelPath = label.split("/");
+
+                String nextLabel = prefixPath == null ? labelPath[0] : labelPath[prefixPath.length];
+
+                if ((prefixPath != null ? prefixPath.length : 0) == labelPath.length - 1) {
+                    addItem(myData, nextLabel, activityIntent(
+                            info.activityInfo.applicationInfo.packageName,
+                            info.activityInfo.name));
+                } else {
+                    if (entries.get(nextLabel) == null) {
+                        addItem(myData, nextLabel, browseIntent(prefix.equals("") ?
+                                nextLabel : prefix + "/" + nextLabel));
+                        entries.put(nextLabel, true);
+                    }
+                }
+            }
+        }
+
+        Collections.sort(myData, sDisplayNameComparator);
+
+        return myData;
+    }
+
+    private final static Comparator<Map<String, Object>> sDisplayNameComparator =
+            new Comparator<Map<String, Object>>() {
+                private final Collator collator = Collator.getInstance();
+
+                public int compare(Map<String, Object> map1, Map<String, Object> map2) {
+                    return collator.compare(map1.get("title"), map2.get("title"));
+                }
+            };
+
+    protected Intent activityIntent(String pkg, String componentName) {
+        Intent result = new Intent();
+        result.setClassName(pkg, componentName);
+        return result;
+    }
+
+    protected Intent browseIntent(String path) {
+        Intent result = new Intent();
+        result.setClass(this, MainActivity.class);
+        result.putExtra(EXTRA_PATH, path);
+        return result;
+    }
+
+    protected void addItem(List<Map<String, Object>> data, String name, Intent intent) {
+        Map<String, Object> temp = new HashMap<>();
+        temp.put("title", name);
+        temp.put("intent", intent);
+        data.add(temp);
+    }
+}
diff --git a/tests/UiBench/src/com/android/test/uibench/TrivialListActivity.java b/tests/UiBench/src/com/android/test/uibench/TrivialListActivity.java
new file mode 100644
index 0000000..0af3471
--- /dev/null
+++ b/tests/UiBench/src/com/android/test/uibench/TrivialListActivity.java
@@ -0,0 +1,55 @@
+/*
+ * Copyright (C) 2015 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.test.uibench;
+
+import android.os.Bundle;
+import android.support.v4.app.FragmentManager;
+import android.support.v4.app.ListFragment;
+import android.support.v7.app.AppCompatActivity;
+import android.widget.ArrayAdapter;
+
+import java.util.Random;
+
+public class TrivialListActivity extends AppCompatActivity {
+    static final int STRING_LENGTH = 10;
+
+    static String[] buildStringList() {
+        String[] strings = new String[200];
+        Random random = new Random(0);
+        for (int i = 0; i < strings.length; i++) {
+            String result = "";
+            for (int j = 0; j < STRING_LENGTH; j++) {
+                // add random letter
+                result += (char)(random.nextInt(26) + 65);
+            }
+            strings[i] = result;
+        }
+        return strings;
+    }
+
+    @Override
+    protected void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+
+        FragmentManager fm = getSupportFragmentManager();
+        if (fm.findFragmentById(android.R.id.content) == null) {
+            ListFragment listFragment = new ListFragment();
+            listFragment.setListAdapter(new ArrayAdapter<>(TrivialListActivity.this,
+                    android.R.layout.simple_list_item_1, buildStringList()));
+            fm.beginTransaction().add(android.R.id.content, listFragment).commit();
+        }
+    }
+}
diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/bars/CustomBar.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/bars/CustomBar.java
index b76ec17..567002e 100644
--- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/bars/CustomBar.java
+++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/bars/CustomBar.java
@@ -33,6 +33,7 @@
 import org.xmlpull.v1.XmlPullParserException;
 
 import android.annotation.NonNull;
+import android.annotation.Nullable;
 import android.content.res.ColorStateList;
 import android.graphics.Bitmap;
 import android.graphics.Bitmap_Delegate;
@@ -227,16 +228,18 @@
      * Find the background color for this bar from the theme attributes. Only relevant to StatusBar
      * and NavigationBar.
      * <p/>
-     * Returns 0 if not found.
+     * Returns null if not found.
      *
      * @param colorAttrName the attribute name for the background color
      * @param translucentAttrName the attribute name for the translucency property of the bar.
      *
      * @throws NumberFormatException if color resolved to an invalid string.
      */
-    protected int getBarColor(@NonNull String colorAttrName, @NonNull String translucentAttrName) {
+    @Nullable
+    protected Integer getBarColor(@NonNull String colorAttrName,
+            @NonNull String translucentAttrName) {
         if (!Config.isGreaterOrEqual(mSimulatedPlatformVersion, LOLLIPOP)) {
-            return 0;
+            return null;
         }
         RenderResources renderResources = getContext().getRenderResources();
         // First check if the bar is translucent.
@@ -251,10 +254,11 @@
         if (transparent) {
             return getColor(renderResources, colorAttrName);
         }
-        return 0;
+        return null;
     }
 
-    private static int getColor(RenderResources renderResources, String attr) {
+    @Nullable
+    private static Integer getColor(RenderResources renderResources, String attr) {
         // From ?attr/foo to @color/bar. This is most likely an ItemResourceValue.
         ResourceValue resource = renderResources.findItemInTheme(attr, true);
         // Form @color/bar to the #AARRGGBB
@@ -275,7 +279,7 @@
                 }
             }
         }
-        return 0;
+        return null;
     }
 
     private ResourceValue getResourceValue(String reference) {
diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/bars/NavigationBar.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/bars/NavigationBar.java
index 9c89bfe2..d50ce23 100644
--- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/bars/NavigationBar.java
+++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/bars/NavigationBar.java
@@ -65,8 +65,8 @@
         super(context, orientation, getShortestWidth(context)>= 600 ? LAYOUT_600DP_XML : LAYOUT_XML,
                 "navigation_bar.xml", simulatedPlatformVersion);
 
-        int color = getBarColor(ATTR_COLOR, ATTR_TRANSLUCENT);
-        setBackgroundColor(color == 0 ? 0xFF000000 : color);
+        Integer color = getBarColor(ATTR_COLOR, ATTR_TRANSLUCENT);
+        setBackgroundColor(color == null ? 0xFF000000 : color);
 
         // Cannot access the inside items through id because no R.id values have been
         // created for them.
diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/bars/StatusBar.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/bars/StatusBar.java
index 2dc7c65..95a5a58 100644
--- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/bars/StatusBar.java
+++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/bars/StatusBar.java
@@ -71,8 +71,9 @@
         // FIXME: use FILL_H?
         setGravity(Gravity.START | Gravity.TOP | Gravity.RIGHT);
 
-        int color = getBarColor(ATTR_COLOR, ATTR_TRANSLUCENT);
-        setBackgroundColor(color == 0 ? Config.getStatusBarColor(simulatedPlatformVersion) : color);
+        Integer color = getBarColor(ATTR_COLOR, ATTR_TRANSLUCENT);
+        setBackgroundColor(
+                color == null ? Config.getStatusBarColor(simulatedPlatformVersion) : color);
 
         // Cannot access the inside items through id because no R.id values have been
         // created for them.
diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/RenderSessionImpl.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/RenderSessionImpl.java
index ac7c409..24e1ce7 100644
--- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/RenderSessionImpl.java
+++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/RenderSessionImpl.java
@@ -421,8 +421,7 @@
                     gc.setComposite(AlphaComposite.Src);
 
                     gc.setColor(new Color(0x00000000, true));
-                    gc.fillRect(0, 0,
-                            mMeasuredScreenWidth, mMeasuredScreenHeight);
+                    gc.fillRect(0, 0, mMeasuredScreenWidth, mMeasuredScreenHeight);
 
                     // done
                     gc.dispose();