Merge "TIF: set audio gain properly" into lmp-mr1-dev
diff --git a/api/current.txt b/api/current.txt
index c480a1b..c9d7579 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -1056,6 +1056,7 @@
     field public static final int scrollbars = 16842974; // 0x10100de
     field public static final int scrollingCache = 16843006; // 0x10100fe
     field public static final deprecated int searchButtonText = 16843269; // 0x1010205
+    field public static final int searchHintIcon = 16844038; // 0x1010506
     field public static final int searchIcon = 16843907; // 0x1010483
     field public static final int searchMode = 16843221; // 0x10101d5
     field public static final int searchSettingsDescription = 16843402; // 0x101028a
@@ -3111,6 +3112,7 @@
     method public void removeAllUpdateListeners();
     method public void removeUpdateListener(android.animation.ValueAnimator.AnimatorUpdateListener);
     method public void reverse();
+    method public void setCurrentFraction(float);
     method public void setCurrentPlayTime(long);
     method public android.animation.ValueAnimator setDuration(long);
     method public void setEvaluator(android.animation.TypeEvaluator);
@@ -5402,8 +5404,8 @@
     field public static final java.lang.String EXTRA_PROVISIONING_DEVICE_ADMIN_PACKAGE_DOWNLOAD_COOKIE_HEADER = "android.app.extra.PROVISIONING_DEVICE_ADMIN_PACKAGE_DOWNLOAD_COOKIE_HEADER";
     field public static final java.lang.String EXTRA_PROVISIONING_DEVICE_ADMIN_PACKAGE_DOWNLOAD_LOCATION = "android.app.extra.PROVISIONING_DEVICE_ADMIN_PACKAGE_DOWNLOAD_LOCATION";
     field public static final java.lang.String EXTRA_PROVISIONING_DEVICE_ADMIN_PACKAGE_NAME = "android.app.extra.PROVISIONING_DEVICE_ADMIN_PACKAGE_NAME";
-    field public static final java.lang.String EXTRA_PROVISIONING_DONT_DISABLE_SYSTEM_APPS = "android.app.extra.PROVISIONING_DONT_DISABLE_SYSTEM_APPS";
     field public static final java.lang.String EXTRA_PROVISIONING_EMAIL_ADDRESS = "android.app.extra.PROVISIONING_EMAIL_ADDRESS";
+    field public static final java.lang.String EXTRA_PROVISIONING_LEAVE_ALL_SYSTEM_APPS_ENABLED = "android.app.extra.PROVISIONING_LEAVE_ALL_SYSTEM_APPS_ENABLED";
     field public static final java.lang.String EXTRA_PROVISIONING_LOCALE = "android.app.extra.PROVISIONING_LOCALE";
     field public static final java.lang.String EXTRA_PROVISIONING_LOCAL_TIME = "android.app.extra.PROVISIONING_LOCAL_TIME";
     field public static final java.lang.String EXTRA_PROVISIONING_TIME_ZONE = "android.app.extra.PROVISIONING_TIME_ZONE";
@@ -28512,8 +28514,8 @@
     method public android.os.Bundle getCarrierConfigValues();
     method public static android.telephony.SmsManager getDefault();
     method public static int getDefaultSmsSubscriptionId();
-    method public static android.telephony.SmsManager getSmsManagerForSubscriber(int);
-    method public int getSubId();
+    method public static android.telephony.SmsManager getSmsManagerForSubscriptionId(int);
+    method public int getSubscriptionId();
     method public void injectSmsPdu(byte[], java.lang.String, android.app.PendingIntent);
     method public void sendDataMessage(java.lang.String, java.lang.String, short, byte[], android.app.PendingIntent, android.app.PendingIntent);
     method public void sendMultimediaMessage(android.content.Context, android.net.Uri, java.lang.String, android.os.Bundle, android.app.PendingIntent);
@@ -28545,6 +28547,7 @@
     field public static final java.lang.String MMS_CONFIG_NOTIFY_WAP_MMSC_ENABLED = "enabledNotifyWapMMSC";
     field public static final java.lang.String MMS_CONFIG_RECIPIENT_LIMIT = "recipientLimit";
     field public static final java.lang.String MMS_CONFIG_SEND_MULTIPART_SMS_AS_SEPARATE_MESSAGES = "sendMultipartSmsAsSeparateMessages";
+    field public static final java.lang.String MMS_CONFIG_SHOW_CELL_BROADCAST_APP_LINKS = "config_cellBroadcastAppLinks";
     field public static final java.lang.String MMS_CONFIG_SMS_DELIVERY_REPORT_ENABLED = "enableSMSDeliveryReports";
     field public static final java.lang.String MMS_CONFIG_SMS_TO_MMS_TEXT_LENGTH_THRESHOLD = "smsToMmsTextLengthThreshold";
     field public static final java.lang.String MMS_CONFIG_SMS_TO_MMS_TEXT_THRESHOLD = "smsToMmsTextThreshold";
@@ -28560,7 +28563,6 @@
     field public static final int MMS_ERROR_RETRY = 6; // 0x6
     field public static final int MMS_ERROR_UNABLE_CONNECT_MMS = 3; // 0x3
     field public static final int MMS_ERROR_UNSPECIFIED = 1; // 0x1
-    field public static final java.lang.String MMS_SHOW_CELL_BROADCAST_APP_LINKS = "config_cellBroadcastAppLinks";
     field public static final int RESULT_ERROR_GENERIC_FAILURE = 1; // 0x1
     field public static final int RESULT_ERROR_NO_SERVICE = 4; // 0x4
     field public static final int RESULT_ERROR_NULL_PDU = 3; // 0x3
diff --git a/core/java/android/animation/TimeAnimator.java b/core/java/android/animation/TimeAnimator.java
index f9aa00e..1738ade 100644
--- a/core/java/android/animation/TimeAnimator.java
+++ b/core/java/android/animation/TimeAnimator.java
@@ -1,5 +1,23 @@
+/*
+ * Copyright (C) 2010 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.view.animation.AnimationUtils;
+
 /**
  * This class provides a simple callback mechanism to listeners that is synchronized with all
  * other animators in the system. There is no duration, interpolation, or object value-setting
@@ -29,6 +47,13 @@
         return false;
     }
 
+    @Override
+    public void setCurrentPlayTime(long playTime) {
+        long currentTime = AnimationUtils.currentAnimationTimeMillis();
+        mStartTime = Math.max(mStartTime, currentTime - playTime);
+        animationFrame(currentTime);
+    }
+
     /**
      * Sets a listener that is sent update events throughout the life of
      * an animation.
diff --git a/core/java/android/animation/ValueAnimator.java b/core/java/android/animation/ValueAnimator.java
index 07f79b8..d65b490 100644
--- a/core/java/android/animation/ValueAnimator.java
+++ b/core/java/android/animation/ValueAnimator.java
@@ -79,7 +79,7 @@
      * Set when setCurrentPlayTime() is called. If negative, animation is not currently seeked
      * to a value.
      */
-    long mSeekTime = -1;
+    float mSeekFraction = -1;
 
     /**
      * Set on the next frame after pause() is called, used to calculate a new startTime
@@ -537,14 +537,31 @@
      * @param playTime The time, in milliseconds, to which the animation is advanced or rewound.
      */
     public void setCurrentPlayTime(long playTime) {
+        float fraction = mUnscaledDuration > 0 ? (float) playTime / mUnscaledDuration :
+                playTime == 0 ? 0 : 1;
+        setCurrentFraction(fraction);
+    }
+
+    /**
+     * Sets the position of the animation to the specified fraction. This fraction should
+     * be between 0 and the total fraction of the animation, including any repetition. That is,
+     * a fraction of 0 will position the animation at the beginning, a value of 1 at the end,
+     * and a value of 2 at the beginning of a reversing animator that repeats once. If
+     * the animation has not yet been started, then it will not advance forward after it is
+     * set to this fraction; it will simply set the fraction to this value and perform any
+     * appropriate actions based on that fraction. If the animation is already running, then
+     * setCurrentFraction() will set the current fraction to this value and continue
+     * playing from that point.
+     *
+     * @param fraction The fraction to which the animation is advanced or rewound.
+     */
+    public void setCurrentFraction(float fraction) {
         initAnimation();
-        long currentTime = AnimationUtils.currentAnimationTimeMillis();
         if (mPlayingState != RUNNING) {
-            mSeekTime = playTime;
+            mSeekFraction = fraction;
             mPlayingState = SEEKED;
         }
-        mStartTime = currentTime - playTime;
-        doAnimationFrame(currentTime);
+        animateValue(fraction);
     }
 
     /**
@@ -948,6 +965,7 @@
         }
         mPlayingBackwards = playBackwards;
         mCurrentIteration = 0;
+        int prevPlayingState = mPlayingState;
         mPlayingState = STOPPED;
         mStarted = true;
         mStartedDelay = false;
@@ -957,7 +975,9 @@
         animationHandler.mPendingAnimations.add(this);
         if (mStartDelay == 0) {
             // This sets the initial value of the animation, prior to actually starting it running
-            setCurrentPlayTime(0);
+            if (prevPlayingState != SEEKED) {
+                setCurrentPlayTime(0);
+            }
             mPlayingState = STOPPED;
             mRunning = true;
             notifyStartListeners();
@@ -1221,12 +1241,12 @@
     final boolean doAnimationFrame(long frameTime) {
         if (mPlayingState == STOPPED) {
             mPlayingState = RUNNING;
-            if (mSeekTime < 0) {
+            if (mSeekFraction < 0) {
                 mStartTime = frameTime;
             } else {
-                mStartTime = frameTime - mSeekTime;
-                // Now that we're playing, reset the seek time
-                mSeekTime = -1;
+                long seekTime = (long) (mDuration * mSeekFraction);
+                mStartTime = frameTime - seekTime;
+                mSeekFraction = -1;
             }
         }
         if (mPaused) {
@@ -1292,7 +1312,7 @@
         if (mUpdateListeners != null) {
             anim.mUpdateListeners = new ArrayList<AnimatorUpdateListener>(mUpdateListeners);
         }
-        anim.mSeekTime = -1;
+        anim.mSeekFraction = -1;
         anim.mPlayingBackwards = false;
         anim.mCurrentIteration = 0;
         anim.mInitialized = false;
diff --git a/core/java/android/app/ActivityThread.java b/core/java/android/app/ActivityThread.java
index e3de44e..98a096c 100644
--- a/core/java/android/app/ActivityThread.java
+++ b/core/java/android/app/ActivityThread.java
@@ -84,6 +84,8 @@
 import android.util.SuperNotCalledException;
 import android.view.Display;
 import android.view.HardwareRenderer;
+import android.view.IWindowManager;
+import android.view.IWindowSessionCallback;
 import android.view.View;
 import android.view.ViewDebug;
 import android.view.ViewManager;
@@ -2366,6 +2368,9 @@
         if (localLOGV) Slog.v(
             TAG, "Handling launch of " + r);
 
+        // Initialize before creating the activity
+        WindowManagerGlobal.initialize();
+
         Activity a = performLaunchActivity(r, customIntent);
 
         if (a != null) {
diff --git a/core/java/android/app/admin/DevicePolicyManager.java b/core/java/android/app/admin/DevicePolicyManager.java
index ad1cf44..57d53aa 100644
--- a/core/java/android/app/admin/DevicePolicyManager.java
+++ b/core/java/android/app/admin/DevicePolicyManager.java
@@ -182,8 +182,8 @@
      * <p>Use in an NFC record with {@link #MIME_TYPE_PROVISIONING_NFC} that starts device owner
      * provisioning via an NFC bump.
      */
-    public static final String EXTRA_PROVISIONING_DONT_DISABLE_SYSTEM_APPS =
-            "android.app.extra.PROVISIONING_DONT_DISABLE_SYSTEM_APPS";
+    public static final String EXTRA_PROVISIONING_LEAVE_ALL_SYSTEM_APPS_ENABLED =
+            "android.app.extra.PROVISIONING_LEAVE_ALL_SYSTEM_APPS_ENABLED";
 
     /**
      * A String extra holding the time zone {@link android.app.AlarmManager} that the device
@@ -3421,12 +3421,13 @@
     }
 
     /**
-     * Called by profile or device owners to check whether a user has been blocked from
-     * uninstalling a package.
+     * Check whether the current user has been blocked by device policy from uninstalling a package.
+     * Requires the caller to be the profile owner if checking a specific admin's policy.
      *
-     * @param admin Which {@link DeviceAdminReceiver} this request is associated with.
+     * @param admin The name of the admin component whose blocking policy will be checked, or null
+     *        to check if any admin has blocked the uninstallation.
      * @param packageName package to check.
-     * @return true if the user shouldn't be able to uninstall the package.
+     * @return true if uninstallation is blocked.
      */
     public boolean isUninstallBlocked(ComponentName admin, String packageName) {
         if (mService != null) {
diff --git a/core/java/android/content/Intent.java b/core/java/android/content/Intent.java
index 57f6028..a13a2ea 100644
--- a/core/java/android/content/Intent.java
+++ b/core/java/android/content/Intent.java
@@ -3763,7 +3763,7 @@
      * This flag is used to open a document into a new task rooted at the activity launched
      * by this Intent. Through the use of this flag, or its equivalent attribute,
      * {@link android.R.attr#documentLaunchMode} multiple instances of the same activity
-     * containing different douments will appear in the recent tasks list.
+     * containing different documents will appear in the recent tasks list.
      *
      * <p>The use of the activity attribute form of this,
      * {@link android.R.attr#documentLaunchMode}, is
diff --git a/core/java/android/os/BatteryStats.java b/core/java/android/os/BatteryStats.java
index 461469c..4709443 100644
--- a/core/java/android/os/BatteryStats.java
+++ b/core/java/android/os/BatteryStats.java
@@ -3669,6 +3669,45 @@
         pw.print(suffix);
     }
 
+    private static boolean dumpTimeEstimate(PrintWriter pw, String label, long[] steps,
+            int count, long modesOfInterest, long modeValues) {
+        if (count <= 0) {
+            return false;
+        }
+        long total = 0;
+        int numOfInterest = 0;
+        for (int i=0; i<count; i++) {
+            long initMode = (steps[i] & STEP_LEVEL_INITIAL_MODE_MASK)
+                    >> STEP_LEVEL_INITIAL_MODE_SHIFT;
+            long modMode = (steps[i] & STEP_LEVEL_MODIFIED_MODE_MASK)
+                    >> STEP_LEVEL_MODIFIED_MODE_SHIFT;
+            // If the modes of interest didn't change during this step period...
+            if ((modMode&modesOfInterest) == 0) {
+                // And the mode values during this period match those we are measuring...
+                if ((initMode&modesOfInterest) == modeValues) {
+                    // Then this can be used to estimate the total time!
+                    numOfInterest++;
+                    total += steps[i] & STEP_LEVEL_TIME_MASK;
+                }
+            }
+        }
+        if (numOfInterest <= 0) {
+            return false;
+        }
+
+        // The estimated time is the average time we spend in each level, multipled
+        // by 100 -- the total number of battery levels
+        long estimatedTime = (total / numOfInterest) * 100;
+
+        pw.print(label);
+        StringBuilder sb = new StringBuilder(64);
+        formatTimeMs(sb, estimatedTime);
+        pw.print(sb);
+        pw.println();
+
+        return true;
+    }
+
     private static boolean dumpDurationSteps(PrintWriter pw, String header, long[] steps,
             int count, boolean checkin) {
         if (count <= 0) {
@@ -3923,6 +3962,38 @@
                     TimeUtils.formatDuration(timeRemaining / 1000, pw);
                     pw.println();
                 }
+                dumpTimeEstimate(pw, "  Estimated screen off time: ",
+                        getDischargeStepDurationsArray(), getNumDischargeStepDurations(),
+                        STEP_LEVEL_MODE_SCREEN_STATE|STEP_LEVEL_MODE_POWER_SAVE,
+                        (Display.STATE_OFF-1));
+                dumpTimeEstimate(pw, "  Estimated screen off power save time: ",
+                        getDischargeStepDurationsArray(), getNumDischargeStepDurations(),
+                        STEP_LEVEL_MODE_SCREEN_STATE|STEP_LEVEL_MODE_POWER_SAVE,
+                        (Display.STATE_OFF-1)|STEP_LEVEL_MODE_POWER_SAVE);
+                dumpTimeEstimate(pw, "  Estimated screen on time: ",
+                        getDischargeStepDurationsArray(), getNumDischargeStepDurations(),
+                        STEP_LEVEL_MODE_SCREEN_STATE|STEP_LEVEL_MODE_POWER_SAVE,
+                        (Display.STATE_ON-1));
+                dumpTimeEstimate(pw, "  Estimated screen on power save time: ",
+                        getDischargeStepDurationsArray(), getNumDischargeStepDurations(),
+                        STEP_LEVEL_MODE_SCREEN_STATE|STEP_LEVEL_MODE_POWER_SAVE,
+                        (Display.STATE_ON-1)|STEP_LEVEL_MODE_POWER_SAVE);
+                dumpTimeEstimate(pw, "  Estimated screen doze time: ",
+                        getDischargeStepDurationsArray(), getNumDischargeStepDurations(),
+                        STEP_LEVEL_MODE_SCREEN_STATE|STEP_LEVEL_MODE_POWER_SAVE,
+                        (Display.STATE_DOZE-1));
+                dumpTimeEstimate(pw, "  Estimated screen doze power save time: ",
+                        getDischargeStepDurationsArray(), getNumDischargeStepDurations(),
+                        STEP_LEVEL_MODE_SCREEN_STATE|STEP_LEVEL_MODE_POWER_SAVE,
+                        (Display.STATE_DOZE-1)|STEP_LEVEL_MODE_POWER_SAVE);
+                dumpTimeEstimate(pw, "  Estimated screen doze suspend time: ",
+                        getDischargeStepDurationsArray(), getNumDischargeStepDurations(),
+                        STEP_LEVEL_MODE_SCREEN_STATE|STEP_LEVEL_MODE_POWER_SAVE,
+                        (Display.STATE_DOZE_SUSPEND-1));
+                dumpTimeEstimate(pw, "  Estimated screen doze suspend power save time: ",
+                        getDischargeStepDurationsArray(), getNumDischargeStepDurations(),
+                        STEP_LEVEL_MODE_SCREEN_STATE|STEP_LEVEL_MODE_POWER_SAVE,
+                        (Display.STATE_DOZE_SUSPEND-1)|STEP_LEVEL_MODE_POWER_SAVE);
                 pw.println();
             }
             if (dumpDurationSteps(pw, "Charge step durations:", getChargeStepDurationsArray(),
diff --git a/core/java/android/os/UserManager.java b/core/java/android/os/UserManager.java
index bd6eeea..ffbed94 100644
--- a/core/java/android/os/UserManager.java
+++ b/core/java/android/os/UserManager.java
@@ -383,8 +383,8 @@
      *
      * <p/>Key for application restrictions.
      * <p/>Type: Boolean
-     * @see android.app.admin.DevicePolicyManager#addApplicationRestriction()
-     * @see android.app.admin.DevicePolicyManager#getApplicationRestriction()
+     * @see android.app.admin.DevicePolicyManager#setApplicationRestrictions()
+     * @see android.app.admin.DevicePolicyManager#getApplicationRestrictions()
      */
     public static final String KEY_RESTRICTIONS_PENDING = "restrictions_pending";
 
diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java
index 1f45f0a..3c12e06 100644
--- a/core/java/android/provider/Settings.java
+++ b/core/java/android/provider/Settings.java
@@ -984,8 +984,8 @@
      * InputDeviceIdentifier. This field is used by some activities to jump straight into the
      * settings for the given device.
      * <p>
-     * Example: The {@link #INPUT_METHOD_SETTINGS} intent opens the keyboard layout dialog for the
-     * given device.
+     * Example: The {@link #ACTION_INPUT_METHOD_SETTINGS} intent opens the keyboard layout
+     * dialog for the given device.
      * @hide
      */
     public static final String EXTRA_INPUT_DEVICE_IDENTIFIER = "input_device_identifier";
@@ -4816,7 +4816,7 @@
          * The timeout in milliseconds before the device fully goes to sleep after
          * a period of inactivity.  This value sets an upper bound on how long the device
          * will stay awake or dreaming without user activity.  It should generally
-         * be longer than {@link #SCREEN_OFF_TIMEOUT} as otherwise the device
+         * be longer than {@link Settings.System#SCREEN_OFF_TIMEOUT} as otherwise the device
          * will sleep before it ever has a chance to dream.
          * <p>
          * Use -1 to disable this timeout.
@@ -6601,6 +6601,15 @@
         public static final String ENHANCED_4G_MODE_ENABLED = "volte_vt_enabled";
 
         /**
+         * Whether user can enable/disable LTE as a preferred network. A carrier might control
+         * this via gservices, OMA-DM, carrier app, etc.
+         * <p>
+         * Type: int (0 for false, 1 for true)
+         * @hide
+         */
+        public static final String LTE_SERVICE_FORCED = "lte_service_forced";
+
+        /**
          * Settings to backup. This is here so that it's in the same place as the settings
          * keys and easy to update.
          *
diff --git a/core/java/android/service/carriermessaging/CarrierMessagingService.java b/core/java/android/service/carriermessaging/CarrierMessagingService.java
index 101f69b..7aea590 100644
--- a/core/java/android/service/carriermessaging/CarrierMessagingService.java
+++ b/core/java/android/service/carriermessaging/CarrierMessagingService.java
@@ -16,6 +16,7 @@
 
 package android.service.carriermessaging;
 
+import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.annotation.SdkConstant;
 import android.app.Service;
@@ -93,7 +94,7 @@
      * @return True to keep an inbound SMS message and delivered to SMS apps. False to
      * drop the message.
      */
-    public boolean onFilterSms(MessagePdu pdu, String format, int destPort) {
+    public boolean onFilterSms(@NonNull MessagePdu pdu, @NonNull String format, int destPort) {
         // optional
         return true;
     }
@@ -105,9 +106,11 @@
      * @param format the format of the response PDU, typically "3gpp" or "3gpp2"
      * @param destAddress phone number of the recipient of the message
      *
-     * @return a {@link SendSmsResponse}.
+     * @return a possibly {code null} {@link SendSmsResponse}. Upon returning {@code null}, the SMS
+     *         is sent using the carrier network.
      */
-    public SendSmsResponse onSendTextSms(String text, String format, String destAddress) {
+    public @Nullable SendSmsResponse onSendTextSms(
+            @NonNull String text, @NonNull String format, @NonNull String destAddress) {
         // optional
         return null;
     }
@@ -120,10 +123,11 @@
      * @param destAddress phone number of the recipient of the message
      * @param destPort the destination port
      *
-     * @return a {@link SendSmsResponse}
+     * @return a possibly {code null} {@link SendSmsResponse}. Upon returning {@code null}, the SMS
+     *         is sent using the carrier network.
      */
-    public SendSmsResponse onSendDataSms(byte[] data, String format, String destAddress,
-            int destPort) {
+    public @Nullable SendSmsResponse onSendDataSms(@NonNull byte[] data, @NonNull String format,
+            @NonNull String destAddress, int destPort) {
         // optional
         return null;
     }
@@ -135,10 +139,11 @@
      * @param format format the format of the response PDU, typically "3gpp" or "3gpp2"
      * @param destAddress phone number of the recipient of the message
      *
-     * @return a {@link List} of {@link SendSmsResponse}, one for each message part.
+     * @return a possibly {code null} {@link List} of {@link SendSmsResponse}, one for each message
+     *         part. Upon returning {@code null}, the SMS is sent using the carrier network.
      */
-    public List<SendSmsResponse> onSendMultipartTextSms(List<String> parts, String format,
-            String destAddress) {
+    public @Nullable List<SendSmsResponse> onSendMultipartTextSms(@NonNull List<String> parts,
+            @NonNull String format, @NonNull String destAddress) {
         // optional
         return null;
     }
@@ -150,9 +155,10 @@
      * @param locationUrl the optional URL to send this MMS PDU. If this is not specified,
      *                    the PDU should be sent to the default MMSC URL.
      *
-     * @return a {@link SendMmsResult}.
+     * @return a possibly {@code null} {@link SendMmsResult}. Upon returning {@code null}, the
+     *         MMS is sent using the carrier network.
      */
-    public SendMmsResult onSendMms(Uri pduUri, @Nullable String locationUrl) {
+    public @Nullable SendMmsResult onSendMms(@NonNull Uri pduUri, @Nullable String locationUrl) {
         // optional
         return null;
     }
@@ -165,13 +171,13 @@
      *
      * @return a {@link SendMmsResult}.
      */
-    public int onDownloadMms(Uri contentUri, String locationUrl) {
+    public int onDownloadMms(@NonNull Uri contentUri, @NonNull String locationUrl) {
         // optional
         return DOWNLOAD_STATUS_RETRY_ON_CARRIER_NETWORK;
     }
 
     @Override
-    public IBinder onBind(Intent intent) {
+    public @Nullable IBinder onBind(@NonNull Intent intent) {
         if (!SERVICE_INTERFACE.equals(intent.getAction())) {
             return null;
         }
@@ -185,12 +191,24 @@
         private int mResult;
         private byte[] mSendConfPdu;
 
-        public SendMmsResult(int result, byte[] sendConfPdu) {
+        /**
+         * Constructs a SendMmsResult with the MMS send result, and the SenConf PDU.
+         *
+         * @param result the result which is one of {@link #SEND_STATUS_OK},
+         *               {@link #SEND_STATUS_RETRY_ON_CARRIER_NETWORK}, and
+         *               {@link #SEND_STATUS_ERROR}
+         * @param sendConfPdu a possibly {code null} SendConf PDU, which confirms that the message
+         *        was sent. sendConfPdu is ignored if the {@code result} is not
+         *        {@link #SEND_STATUS_OK}
+         */
+        public SendMmsResult(int result, @Nullable byte[] sendConfPdu) {
             mResult = result;
             mSendConfPdu = sendConfPdu;
         }
 
         /**
+         * Returns the result of sending the MMS.
+         *
          * @return the result which is one of {@link #SEND_STATUS_OK},
          *         {@link #SEND_STATUS_RETRY_ON_CARRIER_NETWORK}, and {@link #SEND_STATUS_ERROR}
          */
@@ -199,9 +217,11 @@
         }
 
         /**
-         * @return the SendConf PDU, which confirms that the message was sent.
+         * Returns the SendConf PDU, which confirms that the message was sent.
+         *
+         * @return the SendConf PDU
          */
-        public byte[] getSendConfPdu() {
+        public @Nullable byte[] getSendConfPdu() {
             return mSendConfPdu;
         }
     }
@@ -219,12 +239,15 @@
         private int mErrorCode;
 
         /**
+         * Constructs a SendSmsResponse for the message reference, the ack PDU, and error code for
+         * the just-sent SMS.
+         *
          * @param messageRef message reference of the just-sent SMS
          * @param ackPdu ackPdu for the just-sent SMS
          * @param errorCode error code. See 3GPP 27.005, 3.2.5 for GSM/UMTS,
          *     3GPP2 N.S0005 (IS-41C) Table 171 for CDMA, -1 if unknown or not applicable.
          */
-        public SendSmsResponse(int messageRef, byte[] ackPdu, int errorCode) {
+        public SendSmsResponse(int messageRef, @NonNull byte[] ackPdu, int errorCode) {
             mMessageRef = messageRef;
             mAckPdu = ackPdu;
             mErrorCode = errorCode;
@@ -244,7 +267,7 @@
          *
          * @return the ackPdu
          */
-        public byte[] getAckPdu() {
+        public @NonNull byte[] getAckPdu() {
             return mAckPdu;
         }
 
diff --git a/core/java/android/service/carriermessaging/MessagePdu.java b/core/java/android/service/carriermessaging/MessagePdu.java
index b81719f..3c78568 100644
--- a/core/java/android/service/carriermessaging/MessagePdu.java
+++ b/core/java/android/service/carriermessaging/MessagePdu.java
@@ -16,6 +16,7 @@
 
 package android.service.carriermessaging;
 
+import android.annotation.NonNull;
 import android.os.Parcel;
 import android.os.Parcelable;
 
@@ -31,9 +32,14 @@
     private final List<byte[]> mPduList;
 
     /**
+     * Constructs a MessagePdu with the list of message PDUs.
+     *
      * @param pduList the list of message PDUs
      */
-    public MessagePdu(List<byte[]> pduList) {
+    public MessagePdu(@NonNull List<byte[]> pduList) {
+        if (pduList == null || pduList.contains(null)) {
+            throw new IllegalArgumentException("pduList must not be null or contain nulls");
+        }
         mPduList = pduList;
     }
 
@@ -42,7 +48,7 @@
      *
      * @return the list of PDUs
      */
-    public List<byte[]> getPdus() {
+    public @NonNull List<byte[]> getPdus() {
         return mPduList;
     }
 
@@ -51,9 +57,6 @@
         return 0;
     }
 
-    /**
-     * Writes the PDU into a {@link Parcel}.
-     */
     @Override
     public void writeToParcel(Parcel dest, int flags) {
         if (mPduList == null) {
diff --git a/core/java/android/text/StaticLayout.java b/core/java/android/text/StaticLayout.java
index e82057c..02297e3 100644
--- a/core/java/android/text/StaticLayout.java
+++ b/core/java/android/text/StaticLayout.java
@@ -383,7 +383,6 @@
                                 okBottom = fitBottom;
                         }
                     } else {
-                        final boolean moreChars;
                         int endPos;
                         int above, below, top, bottom;
                         float currentTextWidth;
@@ -395,7 +394,6 @@
                             top = okTop;
                             bottom = okBottom;
                             currentTextWidth = okWidth;
-                            moreChars = (j + 1 < spanEnd);
                         } else if (fit != here) {
                             endPos = fit;
                             above = fitAscent;
@@ -403,7 +401,6 @@
                             top = fitTop;
                             bottom = fitBottom;
                             currentTextWidth = fitWidth;
-                            moreChars = (j + 1 < spanEnd);
                         } else {
                             // must make progress, so take next character
                             endPos = here + 1;
@@ -417,7 +414,6 @@
                             top = fmTop;
                             bottom = fmBottom;
                             currentTextWidth = widths[here - paraStart];
-                            moreChars = (endPos < spanEnd);
                         }
 
                         v = out(source, here, endPos,
@@ -425,7 +421,7 @@
                                 v, spacingmult, spacingadd, chooseHt,chooseHtv, fm, hasTabOrEmoji,
                                 needMultiply, chdirs, dir, easy, bufEnd, includepad, trackpad,
                                 chs, widths, paraStart, ellipsize, ellipsizedWidth,
-                                currentTextWidth, paint, moreChars);
+                                currentTextWidth, paint, true);
 
                         here = endPos;
                         j = here - 1; // restart j-span loop from here, compensating for the j++
diff --git a/core/java/android/transition/Visibility.java b/core/java/android/transition/Visibility.java
index 36bac31..8779229 100644
--- a/core/java/android/transition/Visibility.java
+++ b/core/java/android/transition/Visibility.java
@@ -63,6 +63,7 @@
 
     private static final String[] sTransitionProperties = {
             PROPNAME_VISIBILITY,
+            PROPNAME_PARENT,
     };
 
     private static class VisibilityInfo {
diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java
index 77c1d7b..1d19c9b 100644
--- a/core/java/android/view/View.java
+++ b/core/java/android/view/View.java
@@ -2400,12 +2400,6 @@
      */
     static final int PFLAG3_NESTED_SCROLLING_ENABLED = 0x80;
 
-    /**
-     * Flag indicating that outline was invalidated and should be rebuilt the next time
-     * the DisplayList is updated.
-     */
-    static final int PFLAG3_OUTLINE_INVALID = 0x100;
-
     /* End of masks for mPrivateFlags3 */
 
     static final int DRAG_MASK = PFLAG2_DRAG_CAN_ACCEPT | PFLAG2_DRAG_HOVERED;
@@ -11277,7 +11271,7 @@
      * @see #setOutlineProvider(ViewOutlineProvider)
      */
     public void invalidateOutline() {
-        mPrivateFlags3 |= PFLAG3_OUTLINE_INVALID;
+        rebuildOutline();
 
         notifySubtreeAccessibilityStateChangedIfNeeded();
         invalidateViewProperty(false, false);
@@ -14774,27 +14768,21 @@
      * this view, to which future drawing operations will be clipped.
      */
     public void setClipBounds(Rect clipBounds) {
+        if (clipBounds == mClipBounds
+                || (clipBounds != null && clipBounds.equals(mClipBounds))) {
+            return;
+        }
         if (clipBounds != null) {
-            if (clipBounds.equals(mClipBounds)) {
-                return;
-            }
             if (mClipBounds == null) {
-                invalidate();
                 mClipBounds = new Rect(clipBounds);
             } else {
-                invalidate(Math.min(mClipBounds.left, clipBounds.left),
-                        Math.min(mClipBounds.top, clipBounds.top),
-                        Math.max(mClipBounds.right, clipBounds.right),
-                        Math.max(mClipBounds.bottom, clipBounds.bottom));
                 mClipBounds.set(clipBounds);
             }
         } else {
-            if (mClipBounds != null) {
-                invalidate();
-                mClipBounds = null;
-            }
+            mClipBounds = null;
         }
         mRenderNode.setClipBounds(mClipBounds);
+        invalidateViewProperty(false, false);
     }
 
     /**
@@ -14873,10 +14861,6 @@
      */
     void setDisplayListProperties(RenderNode renderNode) {
         if (renderNode != null) {
-            if ((mPrivateFlags3 & PFLAG3_OUTLINE_INVALID) != 0) {
-                rebuildOutline();
-                mPrivateFlags3 &= ~PFLAG3_OUTLINE_INVALID;
-            }
             renderNode.setHasOverlappingRendering(hasOverlappingRendering());
             if (mParent instanceof ViewGroup) {
                 renderNode.setClipToBounds(
@@ -15478,7 +15462,7 @@
         if (mBackgroundSizeChanged) {
             background.setBounds(0, 0,  mRight - mLeft, mBottom - mTop);
             mBackgroundSizeChanged = false;
-            mPrivateFlags3 |= PFLAG3_OUTLINE_INVALID;
+            rebuildOutline();
         }
 
         // Attempt to use a display list if requested.
@@ -15861,7 +15845,7 @@
             mOverlay.getOverlayView().setRight(newWidth);
             mOverlay.getOverlayView().setBottom(newHeight);
         }
-        mPrivateFlags3 |= PFLAG3_OUTLINE_INVALID;
+        rebuildOutline();
     }
 
     /**
@@ -15897,8 +15881,7 @@
 
             invalidate(dirty.left + scrollX, dirty.top + scrollY,
                     dirty.right + scrollX, dirty.bottom + scrollY);
-
-            mPrivateFlags3 |= PFLAG3_OUTLINE_INVALID;
+            rebuildOutline();
         }
     }
 
diff --git a/core/java/android/view/ViewGroup.java b/core/java/android/view/ViewGroup.java
index bae0b12..1a5ff26 100644
--- a/core/java/android/view/ViewGroup.java
+++ b/core/java/android/view/ViewGroup.java
@@ -3534,8 +3534,11 @@
     }
 
     /**
-     * By default, children are clipped to the padding of the ViewGroup. This
-     * allows view groups to override this behavior
+     * Sets whether this ViewGroup will clip its children to its padding, if
+     * padding is present.
+     * <p>
+     * By default, children are clipped to the padding of their parent
+     * Viewgroup. This clipping behavior is only enabled if padding is non-zero.
      *
      * @param clipToPadding true to clip children to the padding of the
      *        group, false otherwise
@@ -3549,7 +3552,11 @@
     }
 
     /**
-     * Check if this ViewGroup is configured to clip child views to its padding.
+     * Returns whether this ViewGroup will clip its children to its padding, if
+     * padding is present.
+     * <p>
+     * By default, children are clipped to the padding of their parent
+     * Viewgroup. This clipping behavior is only enabled if padding is non-zero.
      *
      * @return true if this ViewGroup clips children to its padding, false otherwise
      *
diff --git a/core/java/android/view/WindowManagerGlobal.java b/core/java/android/view/WindowManagerGlobal.java
index 82b1073..8e27834 100644
--- a/core/java/android/view/WindowManagerGlobal.java
+++ b/core/java/android/view/WindowManagerGlobal.java
@@ -124,6 +124,10 @@
     private WindowManagerGlobal() {
     }
 
+    public static void initialize() {
+        getWindowManagerService();
+    }
+
     public static WindowManagerGlobal getInstance() {
         synchronized (WindowManagerGlobal.class) {
             if (sDefaultWindowManager == null) {
@@ -138,6 +142,12 @@
             if (sWindowManagerService == null) {
                 sWindowManagerService = IWindowManager.Stub.asInterface(
                         ServiceManager.getService("window"));
+                try {
+                    sWindowManagerService = getWindowManagerService();
+                    ValueAnimator.setDurationScale(sWindowManagerService.getCurrentAnimatorScale());
+                } catch (RemoteException e) {
+                    Log.e(TAG, "Failed to get WindowManagerService, cannot set animator scale", e);
+                }
             }
             return sWindowManagerService;
         }
@@ -157,7 +167,6 @@
                                 }
                             },
                             imm.getClient(), imm.getInputContext());
-                    ValueAnimator.setDurationScale(windowManager.getCurrentAnimatorScale());
                 } catch (RemoteException e) {
                     Log.e(TAG, "Failed to open window session", e);
                 }
diff --git a/core/java/android/widget/CalendarView.java b/core/java/android/widget/CalendarView.java
index f380d68..ed59ea6 100644
--- a/core/java/android/widget/CalendarView.java
+++ b/core/java/android/widget/CalendarView.java
@@ -17,42 +17,24 @@
 package android.widget;
 
 import android.annotation.Widget;
-import android.app.Service;
 import android.content.Context;
 import android.content.res.Configuration;
 import android.content.res.TypedArray;
-import android.database.DataSetObserver;
-import android.graphics.Canvas;
-import android.graphics.Paint;
-import android.graphics.Paint.Align;
-import android.graphics.Paint.Style;
-import android.graphics.Rect;
 import android.graphics.drawable.Drawable;
-import android.text.TextUtils;
-import android.text.format.DateUtils;
 import android.util.AttributeSet;
-import android.util.DisplayMetrics;
 import android.util.Log;
-import android.util.TypedValue;
-import android.view.GestureDetector;
-import android.view.LayoutInflater;
-import android.view.MotionEvent;
-import android.view.View;
-import android.view.ViewGroup;
 import android.view.accessibility.AccessibilityEvent;
 import android.view.accessibility.AccessibilityNodeInfo;
-import android.widget.AbsListView.OnScrollListener;
 
 import com.android.internal.R;
 
+import java.text.DateFormat;
 import java.text.ParseException;
 import java.text.SimpleDateFormat;
 import java.util.Calendar;
 import java.util.Locale;
 import java.util.TimeZone;
 
-import libcore.icu.LocaleData;
-
 /**
  * This class is a calendar widget for displaying and selecting dates. The range
  * of dates supported by this calendar is configurable. A user can select a date
@@ -74,13 +56,12 @@
  */
 @Widget
 public class CalendarView extends FrameLayout {
+    private static final String LOG_TAG = "CalendarView";
 
-    /**
-     * Tag for logging.
-     */
-    private static final String LOG_TAG = CalendarView.class.getSimpleName();
+    private static final int MODE_HOLO = 0;
+    private static final int MODE_MATERIAL = 1;
 
-    private CalendarViewDelegate mDelegate;
+    private final CalendarViewDelegate mDelegate;
 
     /**
      * The callback used to indicate the user changes the date.
@@ -113,7 +94,23 @@
     public CalendarView(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
         super(context, attrs, defStyleAttr, defStyleRes);
 
-        mDelegate = new LegacyCalendarViewDelegate(this, context, attrs, defStyleAttr, defStyleRes);
+        final TypedArray a = context.obtainStyledAttributes(
+                attrs, R.styleable.CalendarView, defStyleAttr, defStyleRes);
+        final int mode = a.getInt(R.styleable.CalendarView_calendarViewMode, MODE_HOLO);
+        a.recycle();
+
+        switch (mode) {
+            case MODE_HOLO:
+                mDelegate = new CalendarViewLegacyDelegate(
+                        this, context, attrs, defStyleAttr, defStyleRes);
+                break;
+            case MODE_MATERIAL:
+                mDelegate = new CalendarViewMaterialDelegate(
+                        this, context, attrs, defStyleAttr, defStyleRes);
+                break;
+            default:
+                throw new IllegalArgumentException("invalid calendarViewMode attribute");
+        }
     }
 
     /**
@@ -326,16 +323,6 @@
         return mDelegate.getDateTextAppearance();
     }
 
-    @Override
-    public void setEnabled(boolean enabled) {
-        mDelegate.setEnabled(enabled);
-    }
-
-    @Override
-    public boolean isEnabled() {
-        return mDelegate.isEnabled();
-    }
-
     /**
      * Gets the minimal date supported by this {@link CalendarView} in milliseconds
      * since January 1, 1970 00:00:00 in {@link TimeZone#getDefault()} time
@@ -516,14 +503,12 @@
 
     @Override
     public void onInitializeAccessibilityEvent(AccessibilityEvent event) {
-        super.onInitializeAccessibilityEvent(event);
-        mDelegate.onInitializeAccessibilityEvent(event);
+        event.setClassName(CalendarView.class.getName());
     }
 
     @Override
     public void onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo info) {
-        super.onInitializeAccessibilityNodeInfo(info);
-        mDelegate.onInitializeAccessibilityNodeInfo(info);
+        info.setClassName(CalendarView.class.getName());
     }
 
     /**
@@ -560,9 +545,6 @@
         void setDateTextAppearance(int resourceId);
         int getDateTextAppearance();
 
-        void setEnabled(boolean enabled);
-        boolean isEnabled();
-
         void setMinDate(long minDate);
         long getMinDate();
 
@@ -582,21 +564,26 @@
         void setOnDateChangeListener(OnDateChangeListener listener);
 
         void onConfigurationChanged(Configuration newConfig);
-        void onInitializeAccessibilityEvent(AccessibilityEvent event);
-        void onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo info);
     }
 
     /**
      * An abstract class which can be used as a start for CalendarView implementations
      */
     abstract static class AbstractCalendarViewDelegate implements CalendarViewDelegate {
-        // The delegator
+        /** String for parsing dates. */
+        private static final String DATE_FORMAT = "MM/dd/yyyy";
+
+        /** The default minimal date. */
+        protected static final String DEFAULT_MIN_DATE = "01/01/1900";
+
+        /** The default maximal date. */
+        protected static final String DEFAULT_MAX_DATE = "01/01/2100";
+
+        /** Date format for parsing dates. */
+        protected static final DateFormat DATE_FORMATTER = new SimpleDateFormat(DATE_FORMAT);
+
         protected CalendarView mDelegator;
-
-        // The context
         protected Context mContext;
-
-        // The current locale
         protected Locale mCurrentLocale;
 
         AbstractCalendarViewDelegate(CalendarView delegator, Context context) {
@@ -613,830 +600,6 @@
             }
             mCurrentLocale = locale;
         }
-    }
-
-    /**
-     * A delegate implementing the legacy CalendarView
-     */
-    private static class LegacyCalendarViewDelegate extends AbstractCalendarViewDelegate {
-
-        /**
-         * Default value whether to show week number.
-         */
-        private static final boolean DEFAULT_SHOW_WEEK_NUMBER = true;
-
-        /**
-         * The number of milliseconds in a day.e
-         */
-        private static final long MILLIS_IN_DAY = 86400000L;
-
-        /**
-         * The number of day in a week.
-         */
-        private static final int DAYS_PER_WEEK = 7;
-
-        /**
-         * The number of milliseconds in a week.
-         */
-        private static final long MILLIS_IN_WEEK = DAYS_PER_WEEK * MILLIS_IN_DAY;
-
-        /**
-         * Affects when the month selection will change while scrolling upe
-         */
-        private static final int SCROLL_HYST_WEEKS = 2;
-
-        /**
-         * How long the GoTo fling animation should last.
-         */
-        private static final int GOTO_SCROLL_DURATION = 1000;
-
-        /**
-         * The duration of the adjustment upon a user scroll in milliseconds.
-         */
-        private static final int ADJUSTMENT_SCROLL_DURATION = 500;
-
-        /**
-         * How long to wait after receiving an onScrollStateChanged notification
-         * before acting on it.
-         */
-        private static final int SCROLL_CHANGE_DELAY = 40;
-
-        /**
-         * String for parsing dates.
-         */
-        private static final String DATE_FORMAT = "MM/dd/yyyy";
-
-        /**
-         * The default minimal date.
-         */
-        private static final String DEFAULT_MIN_DATE = "01/01/1900";
-
-        /**
-         * The default maximal date.
-         */
-        private static final String DEFAULT_MAX_DATE = "01/01/2100";
-
-        private static final int DEFAULT_SHOWN_WEEK_COUNT = 6;
-
-        private static final int DEFAULT_DATE_TEXT_SIZE = 14;
-
-        private static final int UNSCALED_SELECTED_DATE_VERTICAL_BAR_WIDTH = 6;
-
-        private static final int UNSCALED_WEEK_MIN_VISIBLE_HEIGHT = 12;
-
-        private static final int UNSCALED_LIST_SCROLL_TOP_OFFSET = 2;
-
-        private static final int UNSCALED_BOTTOM_BUFFER = 20;
-
-        private static final int UNSCALED_WEEK_SEPARATOR_LINE_WIDTH = 1;
-
-        private static final int DEFAULT_WEEK_DAY_TEXT_APPEARANCE_RES_ID = -1;
-
-        private final int mWeekSeperatorLineWidth;
-
-        private int mDateTextSize;
-
-        private Drawable mSelectedDateVerticalBar;
-
-        private final int mSelectedDateVerticalBarWidth;
-
-        private int mSelectedWeekBackgroundColor;
-
-        private int mFocusedMonthDateColor;
-
-        private int mUnfocusedMonthDateColor;
-
-        private int mWeekSeparatorLineColor;
-
-        private int mWeekNumberColor;
-
-        private int mWeekDayTextAppearanceResId;
-
-        private int mDateTextAppearanceResId;
-
-        /**
-         * The top offset of the weeks list.
-         */
-        private int mListScrollTopOffset = 2;
-
-        /**
-         * The visible height of a week view.
-         */
-        private int mWeekMinVisibleHeight = 12;
-
-        /**
-         * The visible height of a week view.
-         */
-        private int mBottomBuffer = 20;
-
-        /**
-         * The number of shown weeks.
-         */
-        private int mShownWeekCount;
-
-        /**
-         * Flag whether to show the week number.
-         */
-        private boolean mShowWeekNumber;
-
-        /**
-         * The number of day per week to be shown.
-         */
-        private int mDaysPerWeek = 7;
-
-        /**
-         * The friction of the week list while flinging.
-         */
-        private float mFriction = .05f;
-
-        /**
-         * Scale for adjusting velocity of the week list while flinging.
-         */
-        private float mVelocityScale = 0.333f;
-
-        /**
-         * The adapter for the weeks list.
-         */
-        private WeeksAdapter mAdapter;
-
-        /**
-         * The weeks list.
-         */
-        private ListView mListView;
-
-        /**
-         * The name of the month to display.
-         */
-        private TextView mMonthName;
-
-        /**
-         * The header with week day names.
-         */
-        private ViewGroup mDayNamesHeader;
-
-        /**
-         * Cached abbreviations for day of week names.
-         */
-        private String[] mDayNamesShort;
-
-        /**
-         * Cached full-length day of week names.
-         */
-        private String[] mDayNamesLong;
-
-        /**
-         * The first day of the week.
-         */
-        private int mFirstDayOfWeek;
-
-        /**
-         * Which month should be displayed/highlighted [0-11].
-         */
-        private int mCurrentMonthDisplayed = -1;
-
-        /**
-         * Used for tracking during a scroll.
-         */
-        private long mPreviousScrollPosition;
-
-        /**
-         * Used for tracking which direction the view is scrolling.
-         */
-        private boolean mIsScrollingUp = false;
-
-        /**
-         * The previous scroll state of the weeks ListView.
-         */
-        private int mPreviousScrollState = OnScrollListener.SCROLL_STATE_IDLE;
-
-        /**
-         * The current scroll state of the weeks ListView.
-         */
-        private int mCurrentScrollState = OnScrollListener.SCROLL_STATE_IDLE;
-
-        /**
-         * Listener for changes in the selected day.
-         */
-        private OnDateChangeListener mOnDateChangeListener;
-
-        /**
-         * Command for adjusting the position after a scroll/fling.
-         */
-        private ScrollStateRunnable mScrollStateChangedRunnable = new ScrollStateRunnable();
-
-        /**
-         * Temporary instance to avoid multiple instantiations.
-         */
-        private Calendar mTempDate;
-
-        /**
-         * The first day of the focused month.
-         */
-        private Calendar mFirstDayOfMonth;
-
-        /**
-         * The start date of the range supported by this picker.
-         */
-        private Calendar mMinDate;
-
-        /**
-         * The end date of the range supported by this picker.
-         */
-        private Calendar mMaxDate;
-
-        /**
-         * Date format for parsing dates.
-         */
-        private final java.text.DateFormat mDateFormat = new SimpleDateFormat(DATE_FORMAT);
-
-        LegacyCalendarViewDelegate(CalendarView delegator, Context context, AttributeSet attrs,
-                                   int defStyleAttr, int defStyleRes) {
-            super(delegator, context);
-
-            // initialization based on locale
-            setCurrentLocale(Locale.getDefault());
-
-            TypedArray attributesArray = context.obtainStyledAttributes(attrs,
-                    R.styleable.CalendarView, defStyleAttr, defStyleRes);
-            mShowWeekNumber = attributesArray.getBoolean(R.styleable.CalendarView_showWeekNumber,
-                    DEFAULT_SHOW_WEEK_NUMBER);
-            mFirstDayOfWeek = attributesArray.getInt(R.styleable.CalendarView_firstDayOfWeek,
-                    LocaleData.get(Locale.getDefault()).firstDayOfWeek);
-            String minDate = attributesArray.getString(R.styleable.CalendarView_minDate);
-            if (TextUtils.isEmpty(minDate) || !parseDate(minDate, mMinDate)) {
-                parseDate(DEFAULT_MIN_DATE, mMinDate);
-            }
-            String maxDate = attributesArray.getString(R.styleable.CalendarView_maxDate);
-            if (TextUtils.isEmpty(maxDate) || !parseDate(maxDate, mMaxDate)) {
-                parseDate(DEFAULT_MAX_DATE, mMaxDate);
-            }
-            if (mMaxDate.before(mMinDate)) {
-                throw new IllegalArgumentException("Max date cannot be before min date.");
-            }
-            mShownWeekCount = attributesArray.getInt(R.styleable.CalendarView_shownWeekCount,
-                    DEFAULT_SHOWN_WEEK_COUNT);
-            mSelectedWeekBackgroundColor = attributesArray.getColor(
-                    R.styleable.CalendarView_selectedWeekBackgroundColor, 0);
-            mFocusedMonthDateColor = attributesArray.getColor(
-                    R.styleable.CalendarView_focusedMonthDateColor, 0);
-            mUnfocusedMonthDateColor = attributesArray.getColor(
-                    R.styleable.CalendarView_unfocusedMonthDateColor, 0);
-            mWeekSeparatorLineColor = attributesArray.getColor(
-                    R.styleable.CalendarView_weekSeparatorLineColor, 0);
-            mWeekNumberColor = attributesArray.getColor(R.styleable.CalendarView_weekNumberColor, 0);
-            mSelectedDateVerticalBar = attributesArray.getDrawable(
-                    R.styleable.CalendarView_selectedDateVerticalBar);
-
-            mDateTextAppearanceResId = attributesArray.getResourceId(
-                    R.styleable.CalendarView_dateTextAppearance, R.style.TextAppearance_Small);
-            updateDateTextSize();
-
-            mWeekDayTextAppearanceResId = attributesArray.getResourceId(
-                    R.styleable.CalendarView_weekDayTextAppearance,
-                    DEFAULT_WEEK_DAY_TEXT_APPEARANCE_RES_ID);
-            attributesArray.recycle();
-
-            DisplayMetrics displayMetrics = mDelegator.getResources().getDisplayMetrics();
-            mWeekMinVisibleHeight = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP,
-                    UNSCALED_WEEK_MIN_VISIBLE_HEIGHT, displayMetrics);
-            mListScrollTopOffset = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP,
-                    UNSCALED_LIST_SCROLL_TOP_OFFSET, displayMetrics);
-            mBottomBuffer = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP,
-                    UNSCALED_BOTTOM_BUFFER, displayMetrics);
-            mSelectedDateVerticalBarWidth = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP,
-                    UNSCALED_SELECTED_DATE_VERTICAL_BAR_WIDTH, displayMetrics);
-            mWeekSeperatorLineWidth = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP,
-                    UNSCALED_WEEK_SEPARATOR_LINE_WIDTH, displayMetrics);
-
-            LayoutInflater layoutInflater = (LayoutInflater) mContext
-                    .getSystemService(Service.LAYOUT_INFLATER_SERVICE);
-            View content = layoutInflater.inflate(R.layout.calendar_view, null, false);
-            mDelegator.addView(content);
-
-            mListView = (ListView) mDelegator.findViewById(R.id.list);
-            mDayNamesHeader = (ViewGroup) content.findViewById(com.android.internal.R.id.day_names);
-            mMonthName = (TextView) content.findViewById(com.android.internal.R.id.month_name);
-
-            setUpHeader();
-            setUpListView();
-            setUpAdapter();
-
-            // go to today or whichever is close to today min or max date
-            mTempDate.setTimeInMillis(System.currentTimeMillis());
-            if (mTempDate.before(mMinDate)) {
-                goTo(mMinDate, false, true, true);
-            } else if (mMaxDate.before(mTempDate)) {
-                goTo(mMaxDate, false, true, true);
-            } else {
-                goTo(mTempDate, false, true, true);
-            }
-
-            mDelegator.invalidate();
-        }
-
-        @Override
-        public void setShownWeekCount(int count) {
-            if (mShownWeekCount != count) {
-                mShownWeekCount = count;
-                mDelegator.invalidate();
-            }
-        }
-
-        @Override
-        public int getShownWeekCount() {
-            return mShownWeekCount;
-        }
-
-        @Override
-        public void setSelectedWeekBackgroundColor(int color) {
-            if (mSelectedWeekBackgroundColor != color) {
-                mSelectedWeekBackgroundColor = color;
-                final int childCount = mListView.getChildCount();
-                for (int i = 0; i < childCount; i++) {
-                    WeekView weekView = (WeekView) mListView.getChildAt(i);
-                    if (weekView.mHasSelectedDay) {
-                        weekView.invalidate();
-                    }
-                }
-            }
-        }
-
-        @Override
-        public int getSelectedWeekBackgroundColor() {
-            return mSelectedWeekBackgroundColor;
-        }
-
-        @Override
-        public void setFocusedMonthDateColor(int color) {
-            if (mFocusedMonthDateColor != color) {
-                mFocusedMonthDateColor = color;
-                final int childCount = mListView.getChildCount();
-                for (int i = 0; i < childCount; i++) {
-                    WeekView weekView = (WeekView) mListView.getChildAt(i);
-                    if (weekView.mHasFocusedDay) {
-                        weekView.invalidate();
-                    }
-                }
-            }
-        }
-
-        @Override
-        public int getFocusedMonthDateColor() {
-            return mFocusedMonthDateColor;
-        }
-
-        @Override
-        public void setUnfocusedMonthDateColor(int color) {
-            if (mUnfocusedMonthDateColor != color) {
-                mUnfocusedMonthDateColor = color;
-                final int childCount = mListView.getChildCount();
-                for (int i = 0; i < childCount; i++) {
-                    WeekView weekView = (WeekView) mListView.getChildAt(i);
-                    if (weekView.mHasUnfocusedDay) {
-                        weekView.invalidate();
-                    }
-                }
-            }
-        }
-
-        @Override
-        public int getUnfocusedMonthDateColor() {
-            return mFocusedMonthDateColor;
-        }
-
-        @Override
-        public void setWeekNumberColor(int color) {
-            if (mWeekNumberColor != color) {
-                mWeekNumberColor = color;
-                if (mShowWeekNumber) {
-                    invalidateAllWeekViews();
-                }
-            }
-        }
-
-        @Override
-        public int getWeekNumberColor() {
-            return mWeekNumberColor;
-        }
-
-        @Override
-        public void setWeekSeparatorLineColor(int color) {
-            if (mWeekSeparatorLineColor != color) {
-                mWeekSeparatorLineColor = color;
-                invalidateAllWeekViews();
-            }
-        }
-
-        @Override
-        public int getWeekSeparatorLineColor() {
-            return mWeekSeparatorLineColor;
-        }
-
-        @Override
-        public void setSelectedDateVerticalBar(int resourceId) {
-            Drawable drawable = mDelegator.getContext().getDrawable(resourceId);
-            setSelectedDateVerticalBar(drawable);
-        }
-
-        @Override
-        public void setSelectedDateVerticalBar(Drawable drawable) {
-            if (mSelectedDateVerticalBar != drawable) {
-                mSelectedDateVerticalBar = drawable;
-                final int childCount = mListView.getChildCount();
-                for (int i = 0; i < childCount; i++) {
-                    WeekView weekView = (WeekView) mListView.getChildAt(i);
-                    if (weekView.mHasSelectedDay) {
-                        weekView.invalidate();
-                    }
-                }
-            }
-        }
-
-        @Override
-        public Drawable getSelectedDateVerticalBar() {
-            return mSelectedDateVerticalBar;
-        }
-
-        @Override
-        public void setWeekDayTextAppearance(int resourceId) {
-            if (mWeekDayTextAppearanceResId != resourceId) {
-                mWeekDayTextAppearanceResId = resourceId;
-                setUpHeader();
-            }
-        }
-
-        @Override
-        public int getWeekDayTextAppearance() {
-            return mWeekDayTextAppearanceResId;
-        }
-
-        @Override
-        public void setDateTextAppearance(int resourceId) {
-            if (mDateTextAppearanceResId != resourceId) {
-                mDateTextAppearanceResId = resourceId;
-                updateDateTextSize();
-                invalidateAllWeekViews();
-            }
-        }
-
-        @Override
-        public int getDateTextAppearance() {
-            return mDateTextAppearanceResId;
-        }
-
-        @Override
-        public void setEnabled(boolean enabled) {
-            mListView.setEnabled(enabled);
-        }
-
-        @Override
-        public boolean isEnabled() {
-            return mListView.isEnabled();
-        }
-
-        @Override
-        public void setMinDate(long minDate) {
-            mTempDate.setTimeInMillis(minDate);
-            if (isSameDate(mTempDate, mMinDate)) {
-                return;
-            }
-            mMinDate.setTimeInMillis(minDate);
-            // make sure the current date is not earlier than
-            // the new min date since the latter is used for
-            // calculating the indices in the adapter thus
-            // avoiding out of bounds error
-            Calendar date = mAdapter.mSelectedDate;
-            if (date.before(mMinDate)) {
-                mAdapter.setSelectedDay(mMinDate);
-            }
-            // reinitialize the adapter since its range depends on min date
-            mAdapter.init();
-            if (date.before(mMinDate)) {
-                setDate(mTempDate.getTimeInMillis());
-            } else {
-                // we go to the current date to force the ListView to query its
-                // adapter for the shown views since we have changed the adapter
-                // range and the base from which the later calculates item indices
-                // note that calling setDate will not work since the date is the same
-                goTo(date, false, true, false);
-            }
-        }
-
-        @Override
-        public long getMinDate() {
-            return mMinDate.getTimeInMillis();
-        }
-
-        @Override
-        public void setMaxDate(long maxDate) {
-            mTempDate.setTimeInMillis(maxDate);
-            if (isSameDate(mTempDate, mMaxDate)) {
-                return;
-            }
-            mMaxDate.setTimeInMillis(maxDate);
-            // reinitialize the adapter since its range depends on max date
-            mAdapter.init();
-            Calendar date = mAdapter.mSelectedDate;
-            if (date.after(mMaxDate)) {
-                setDate(mMaxDate.getTimeInMillis());
-            } else {
-                // we go to the current date to force the ListView to query its
-                // adapter for the shown views since we have changed the adapter
-                // range and the base from which the later calculates item indices
-                // note that calling setDate will not work since the date is the same
-                goTo(date, false, true, false);
-            }
-        }
-
-        @Override
-        public long getMaxDate() {
-            return mMaxDate.getTimeInMillis();
-        }
-
-        @Override
-        public void setShowWeekNumber(boolean showWeekNumber) {
-            if (mShowWeekNumber == showWeekNumber) {
-                return;
-            }
-            mShowWeekNumber = showWeekNumber;
-            mAdapter.notifyDataSetChanged();
-            setUpHeader();
-        }
-
-        @Override
-        public boolean getShowWeekNumber() {
-            return mShowWeekNumber;
-        }
-
-        @Override
-        public void setFirstDayOfWeek(int firstDayOfWeek) {
-            if (mFirstDayOfWeek == firstDayOfWeek) {
-                return;
-            }
-            mFirstDayOfWeek = firstDayOfWeek;
-            mAdapter.init();
-            mAdapter.notifyDataSetChanged();
-            setUpHeader();
-        }
-
-        @Override
-        public int getFirstDayOfWeek() {
-            return mFirstDayOfWeek;
-        }
-
-        @Override
-        public void setDate(long date) {
-            setDate(date, false, false);
-        }
-
-        @Override
-        public void setDate(long date, boolean animate, boolean center) {
-            mTempDate.setTimeInMillis(date);
-            if (isSameDate(mTempDate, mAdapter.mSelectedDate)) {
-                return;
-            }
-            goTo(mTempDate, animate, true, center);
-        }
-
-        @Override
-        public long getDate() {
-            return mAdapter.mSelectedDate.getTimeInMillis();
-        }
-
-        @Override
-        public void setOnDateChangeListener(OnDateChangeListener listener) {
-            mOnDateChangeListener = listener;
-        }
-
-        @Override
-        public void onConfigurationChanged(Configuration newConfig) {
-            setCurrentLocale(newConfig.locale);
-        }
-
-        @Override
-        public void onInitializeAccessibilityEvent(AccessibilityEvent event) {
-            event.setClassName(CalendarView.class.getName());
-        }
-
-        @Override
-        public void onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo info) {
-            info.setClassName(CalendarView.class.getName());
-        }
-
-        /**
-         * Sets the current locale.
-         *
-         * @param locale The current locale.
-         */
-        @Override
-        protected void setCurrentLocale(Locale locale) {
-            super.setCurrentLocale(locale);
-
-            mTempDate = getCalendarForLocale(mTempDate, locale);
-            mFirstDayOfMonth = getCalendarForLocale(mFirstDayOfMonth, locale);
-            mMinDate = getCalendarForLocale(mMinDate, locale);
-            mMaxDate = getCalendarForLocale(mMaxDate, locale);
-        }
-        private void updateDateTextSize() {
-            TypedArray dateTextAppearance = mDelegator.getContext().obtainStyledAttributes(
-                    mDateTextAppearanceResId, R.styleable.TextAppearance);
-            mDateTextSize = dateTextAppearance.getDimensionPixelSize(
-                    R.styleable.TextAppearance_textSize, DEFAULT_DATE_TEXT_SIZE);
-            dateTextAppearance.recycle();
-        }
-
-        /**
-         * Invalidates all week views.
-         */
-        private void invalidateAllWeekViews() {
-            final int childCount = mListView.getChildCount();
-            for (int i = 0; i < childCount; i++) {
-                View view = mListView.getChildAt(i);
-                view.invalidate();
-            }
-        }
-
-        /**
-         * Gets a calendar for locale bootstrapped with the value of a given calendar.
-         *
-         * @param oldCalendar The old calendar.
-         * @param locale The locale.
-         */
-        private static Calendar getCalendarForLocale(Calendar oldCalendar, Locale locale) {
-            if (oldCalendar == null) {
-                return Calendar.getInstance(locale);
-            } else {
-                final long currentTimeMillis = oldCalendar.getTimeInMillis();
-                Calendar newCalendar = Calendar.getInstance(locale);
-                newCalendar.setTimeInMillis(currentTimeMillis);
-                return newCalendar;
-            }
-        }
-
-        /**
-         * @return True if the <code>firstDate</code> is the same as the <code>
-         * secondDate</code>.
-         */
-        private static boolean isSameDate(Calendar firstDate, Calendar secondDate) {
-            return (firstDate.get(Calendar.DAY_OF_YEAR) == secondDate.get(Calendar.DAY_OF_YEAR)
-                    && firstDate.get(Calendar.YEAR) == secondDate.get(Calendar.YEAR));
-        }
-
-        /**
-         * Creates a new adapter if necessary and sets up its parameters.
-         */
-        private void setUpAdapter() {
-            if (mAdapter == null) {
-                mAdapter = new WeeksAdapter(mContext);
-                mAdapter.registerDataSetObserver(new DataSetObserver() {
-                    @Override
-                    public void onChanged() {
-                        if (mOnDateChangeListener != null) {
-                            Calendar selectedDay = mAdapter.getSelectedDay();
-                            mOnDateChangeListener.onSelectedDayChange(mDelegator,
-                                    selectedDay.get(Calendar.YEAR),
-                                    selectedDay.get(Calendar.MONTH),
-                                    selectedDay.get(Calendar.DAY_OF_MONTH));
-                        }
-                    }
-                });
-                mListView.setAdapter(mAdapter);
-            }
-
-            // refresh the view with the new parameters
-            mAdapter.notifyDataSetChanged();
-        }
-
-        /**
-         * Sets up the strings to be used by the header.
-         */
-        private void setUpHeader() {
-            mDayNamesShort = new String[mDaysPerWeek];
-            mDayNamesLong = new String[mDaysPerWeek];
-            for (int i = mFirstDayOfWeek, count = mFirstDayOfWeek + mDaysPerWeek; i < count; i++) {
-                int calendarDay = (i > Calendar.SATURDAY) ? i - Calendar.SATURDAY : i;
-                mDayNamesShort[i - mFirstDayOfWeek] = DateUtils.getDayOfWeekString(calendarDay,
-                        DateUtils.LENGTH_SHORTEST);
-                mDayNamesLong[i - mFirstDayOfWeek] = DateUtils.getDayOfWeekString(calendarDay,
-                        DateUtils.LENGTH_LONG);
-            }
-
-            TextView label = (TextView) mDayNamesHeader.getChildAt(0);
-            if (mShowWeekNumber) {
-                label.setVisibility(View.VISIBLE);
-            } else {
-                label.setVisibility(View.GONE);
-            }
-            for (int i = 1, count = mDayNamesHeader.getChildCount(); i < count; i++) {
-                label = (TextView) mDayNamesHeader.getChildAt(i);
-                if (mWeekDayTextAppearanceResId > -1) {
-                    label.setTextAppearance(mContext, mWeekDayTextAppearanceResId);
-                }
-                if (i < mDaysPerWeek + 1) {
-                    label.setText(mDayNamesShort[i - 1]);
-                    label.setContentDescription(mDayNamesLong[i - 1]);
-                    label.setVisibility(View.VISIBLE);
-                } else {
-                    label.setVisibility(View.GONE);
-                }
-            }
-            mDayNamesHeader.invalidate();
-        }
-
-        /**
-         * Sets all the required fields for the list view.
-         */
-        private void setUpListView() {
-            // Configure the listview
-            mListView.setDivider(null);
-            mListView.setItemsCanFocus(true);
-            mListView.setVerticalScrollBarEnabled(false);
-            mListView.setOnScrollListener(new OnScrollListener() {
-                public void onScrollStateChanged(AbsListView view, int scrollState) {
-                    LegacyCalendarViewDelegate.this.onScrollStateChanged(view, scrollState);
-                }
-
-                public void onScroll(
-                        AbsListView view, int firstVisibleItem, int visibleItemCount,
-                        int totalItemCount) {
-                    LegacyCalendarViewDelegate.this.onScroll(view, firstVisibleItem,
-                            visibleItemCount, totalItemCount);
-                }
-            });
-            // Make the scrolling behavior nicer
-            mListView.setFriction(mFriction);
-            mListView.setVelocityScale(mVelocityScale);
-        }
-
-        /**
-         * This moves to the specified time in the view. If the time is not already
-         * in range it will move the list so that the first of the month containing
-         * the time is at the top of the view. If the new time is already in view
-         * the list will not be scrolled unless forceScroll is true. This time may
-         * optionally be highlighted as selected as well.
-         *
-         * @param date The time to move to.
-         * @param animate Whether to scroll to the given time or just redraw at the
-         *            new location.
-         * @param setSelected Whether to set the given time as selected.
-         * @param forceScroll Whether to recenter even if the time is already
-         *            visible.
-         *
-         * @throws IllegalArgumentException of the provided date is before the
-         *        range start of after the range end.
-         */
-        private void goTo(Calendar date, boolean animate, boolean setSelected,
-                boolean forceScroll) {
-            if (date.before(mMinDate) || date.after(mMaxDate)) {
-                throw new IllegalArgumentException("Time not between " + mMinDate.getTime()
-                        + " and " + mMaxDate.getTime());
-            }
-            // Find the first and last entirely visible weeks
-            int firstFullyVisiblePosition = mListView.getFirstVisiblePosition();
-            View firstChild = mListView.getChildAt(0);
-            if (firstChild != null && firstChild.getTop() < 0) {
-                firstFullyVisiblePosition++;
-            }
-            int lastFullyVisiblePosition = firstFullyVisiblePosition + mShownWeekCount - 1;
-            if (firstChild != null && firstChild.getTop() > mBottomBuffer) {
-                lastFullyVisiblePosition--;
-            }
-            if (setSelected) {
-                mAdapter.setSelectedDay(date);
-            }
-            // Get the week we're going to
-            int position = getWeeksSinceMinDate(date);
-
-            // Check if the selected day is now outside of our visible range
-            // and if so scroll to the month that contains it
-            if (position < firstFullyVisiblePosition || position > lastFullyVisiblePosition
-                    || forceScroll) {
-                mFirstDayOfMonth.setTimeInMillis(date.getTimeInMillis());
-                mFirstDayOfMonth.set(Calendar.DAY_OF_MONTH, 1);
-
-                setMonthDisplayed(mFirstDayOfMonth);
-
-                // the earliest time we can scroll to is the min date
-                if (mFirstDayOfMonth.before(mMinDate)) {
-                    position = 0;
-                } else {
-                    position = getWeeksSinceMinDate(mFirstDayOfMonth);
-                }
-
-                mPreviousScrollState = OnScrollListener.SCROLL_STATE_FLING;
-                if (animate) {
-                    mListView.smoothScrollToPositionFromTop(position, mListScrollTopOffset,
-                            GOTO_SCROLL_DURATION);
-                } else {
-                    mListView.setSelectionFromTop(position, mListScrollTopOffset);
-                    // Perform any after scroll operations that are needed
-                    onScrollStateChanged(mListView, OnScrollListener.SCROLL_STATE_IDLE);
-                }
-            } else if (setSelected) {
-                // Otherwise just set the selection
-                setMonthDisplayed(date);
-            }
-        }
 
         /**
          * Parses the given <code>date</code> and in case of success sets
@@ -1444,718 +607,15 @@
          *
          * @return True if the date was parsed.
          */
-        private boolean parseDate(String date, Calendar outDate) {
+        protected boolean parseDate(String date, Calendar outDate) {
             try {
-                outDate.setTime(mDateFormat.parse(date));
+                outDate.setTime(DATE_FORMATTER.parse(date));
                 return true;
             } catch (ParseException e) {
                 Log.w(LOG_TAG, "Date: " + date + " not in format: " + DATE_FORMAT);
                 return false;
             }
         }
-
-        /**
-         * Called when a <code>view</code> transitions to a new <code>scrollState
-         * </code>.
-         */
-        private void onScrollStateChanged(AbsListView view, int scrollState) {
-            mScrollStateChangedRunnable.doScrollStateChange(view, scrollState);
-        }
-
-        /**
-         * Updates the title and selected month if the <code>view</code> has moved to a new
-         * month.
-         */
-        private void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount,
-                              int totalItemCount) {
-            WeekView child = (WeekView) view.getChildAt(0);
-            if (child == null) {
-                return;
-            }
-
-            // Figure out where we are
-            long currScroll =
-                    view.getFirstVisiblePosition() * child.getHeight() - child.getBottom();
-
-            // If we have moved since our last call update the direction
-            if (currScroll < mPreviousScrollPosition) {
-                mIsScrollingUp = true;
-            } else if (currScroll > mPreviousScrollPosition) {
-                mIsScrollingUp = false;
-            } else {
-                return;
-            }
-
-            // Use some hysteresis for checking which month to highlight. This
-            // causes the month to transition when two full weeks of a month are
-            // visible when scrolling up, and when the first day in a month reaches
-            // the top of the screen when scrolling down.
-            int offset = child.getBottom() < mWeekMinVisibleHeight ? 1 : 0;
-            if (mIsScrollingUp) {
-                child = (WeekView) view.getChildAt(SCROLL_HYST_WEEKS + offset);
-            } else if (offset != 0) {
-                child = (WeekView) view.getChildAt(offset);
-            }
-
-            if (child != null) {
-                // Find out which month we're moving into
-                int month;
-                if (mIsScrollingUp) {
-                    month = child.getMonthOfFirstWeekDay();
-                } else {
-                    month = child.getMonthOfLastWeekDay();
-                }
-
-                // And how it relates to our current highlighted month
-                int monthDiff;
-                if (mCurrentMonthDisplayed == 11 && month == 0) {
-                    monthDiff = 1;
-                } else if (mCurrentMonthDisplayed == 0 && month == 11) {
-                    monthDiff = -1;
-                } else {
-                    monthDiff = month - mCurrentMonthDisplayed;
-                }
-
-                // Only switch months if we're scrolling away from the currently
-                // selected month
-                if ((!mIsScrollingUp && monthDiff > 0) || (mIsScrollingUp && monthDiff < 0)) {
-                    Calendar firstDay = child.getFirstDay();
-                    if (mIsScrollingUp) {
-                        firstDay.add(Calendar.DAY_OF_MONTH, -DAYS_PER_WEEK);
-                    } else {
-                        firstDay.add(Calendar.DAY_OF_MONTH, DAYS_PER_WEEK);
-                    }
-                    setMonthDisplayed(firstDay);
-                }
-            }
-            mPreviousScrollPosition = currScroll;
-            mPreviousScrollState = mCurrentScrollState;
-        }
-
-        /**
-         * Sets the month displayed at the top of this view based on time. Override
-         * to add custom events when the title is changed.
-         *
-         * @param calendar A day in the new focus month.
-         */
-        private void setMonthDisplayed(Calendar calendar) {
-            mCurrentMonthDisplayed = calendar.get(Calendar.MONTH);
-            mAdapter.setFocusMonth(mCurrentMonthDisplayed);
-            final int flags = DateUtils.FORMAT_SHOW_DATE | DateUtils.FORMAT_NO_MONTH_DAY
-                    | DateUtils.FORMAT_SHOW_YEAR;
-            final long millis = calendar.getTimeInMillis();
-            String newMonthName = DateUtils.formatDateRange(mContext, millis, millis, flags);
-            mMonthName.setText(newMonthName);
-            mMonthName.invalidate();
-        }
-
-        /**
-         * @return Returns the number of weeks between the current <code>date</code>
-         *         and the <code>mMinDate</code>.
-         */
-        private int getWeeksSinceMinDate(Calendar date) {
-            if (date.before(mMinDate)) {
-                throw new IllegalArgumentException("fromDate: " + mMinDate.getTime()
-                        + " does not precede toDate: " + date.getTime());
-            }
-            long endTimeMillis = date.getTimeInMillis()
-                    + date.getTimeZone().getOffset(date.getTimeInMillis());
-            long startTimeMillis = mMinDate.getTimeInMillis()
-                    + mMinDate.getTimeZone().getOffset(mMinDate.getTimeInMillis());
-            long dayOffsetMillis = (mMinDate.get(Calendar.DAY_OF_WEEK) - mFirstDayOfWeek)
-                    * MILLIS_IN_DAY;
-            return (int) ((endTimeMillis - startTimeMillis + dayOffsetMillis) / MILLIS_IN_WEEK);
-        }
-
-        /**
-         * Command responsible for acting upon scroll state changes.
-         */
-        private class ScrollStateRunnable implements Runnable {
-            private AbsListView mView;
-
-            private int mNewState;
-
-            /**
-             * Sets up the runnable with a short delay in case the scroll state
-             * immediately changes again.
-             *
-             * @param view The list view that changed state
-             * @param scrollState The new state it changed to
-             */
-            public void doScrollStateChange(AbsListView view, int scrollState) {
-                mView = view;
-                mNewState = scrollState;
-                mDelegator.removeCallbacks(this);
-                mDelegator.postDelayed(this, SCROLL_CHANGE_DELAY);
-            }
-
-            public void run() {
-                mCurrentScrollState = mNewState;
-                // Fix the position after a scroll or a fling ends
-                if (mNewState == OnScrollListener.SCROLL_STATE_IDLE
-                        && mPreviousScrollState != OnScrollListener.SCROLL_STATE_IDLE) {
-                    View child = mView.getChildAt(0);
-                    if (child == null) {
-                        // The view is no longer visible, just return
-                        return;
-                    }
-                    int dist = child.getBottom() - mListScrollTopOffset;
-                    if (dist > mListScrollTopOffset) {
-                        if (mIsScrollingUp) {
-                            mView.smoothScrollBy(dist - child.getHeight(),
-                                    ADJUSTMENT_SCROLL_DURATION);
-                        } else {
-                            mView.smoothScrollBy(dist, ADJUSTMENT_SCROLL_DURATION);
-                        }
-                    }
-                }
-                mPreviousScrollState = mNewState;
-            }
-        }
-
-        /**
-         * <p>
-         * This is a specialized adapter for creating a list of weeks with
-         * selectable days. It can be configured to display the week number, start
-         * the week on a given day, show a reduced number of days, or display an
-         * arbitrary number of weeks at a time.
-         * </p>
-         */
-        private class WeeksAdapter extends BaseAdapter implements OnTouchListener {
-
-            private int mSelectedWeek;
-
-            private GestureDetector mGestureDetector;
-
-            private int mFocusedMonth;
-
-            private final Calendar mSelectedDate = Calendar.getInstance();
-
-            private int mTotalWeekCount;
-
-            public WeeksAdapter(Context context) {
-                mContext = context;
-                mGestureDetector = new GestureDetector(mContext, new CalendarGestureListener());
-                init();
-            }
-
-            /**
-             * Set up the gesture detector and selected time
-             */
-            private void init() {
-                mSelectedWeek = getWeeksSinceMinDate(mSelectedDate);
-                mTotalWeekCount = getWeeksSinceMinDate(mMaxDate);
-                if (mMinDate.get(Calendar.DAY_OF_WEEK) != mFirstDayOfWeek
-                        || mMaxDate.get(Calendar.DAY_OF_WEEK) != mFirstDayOfWeek) {
-                    mTotalWeekCount++;
-                }
-                notifyDataSetChanged();
-            }
-
-            /**
-             * Updates the selected day and related parameters.
-             *
-             * @param selectedDay The time to highlight
-             */
-            public void setSelectedDay(Calendar selectedDay) {
-                if (selectedDay.get(Calendar.DAY_OF_YEAR) == mSelectedDate.get(Calendar.DAY_OF_YEAR)
-                        && selectedDay.get(Calendar.YEAR) == mSelectedDate.get(Calendar.YEAR)) {
-                    return;
-                }
-                mSelectedDate.setTimeInMillis(selectedDay.getTimeInMillis());
-                mSelectedWeek = getWeeksSinceMinDate(mSelectedDate);
-                mFocusedMonth = mSelectedDate.get(Calendar.MONTH);
-                notifyDataSetChanged();
-            }
-
-            /**
-             * @return The selected day of month.
-             */
-            public Calendar getSelectedDay() {
-                return mSelectedDate;
-            }
-
-            @Override
-            public int getCount() {
-                return mTotalWeekCount;
-            }
-
-            @Override
-            public Object getItem(int position) {
-                return null;
-            }
-
-            @Override
-            public long getItemId(int position) {
-                return position;
-            }
-
-            @Override
-            public View getView(int position, View convertView, ViewGroup parent) {
-                WeekView weekView = null;
-                if (convertView != null) {
-                    weekView = (WeekView) convertView;
-                } else {
-                    weekView = new WeekView(mContext);
-                    android.widget.AbsListView.LayoutParams params =
-                            new android.widget.AbsListView.LayoutParams(LayoutParams.WRAP_CONTENT,
-                                    LayoutParams.WRAP_CONTENT);
-                    weekView.setLayoutParams(params);
-                    weekView.setClickable(true);
-                    weekView.setOnTouchListener(this);
-                }
-
-                int selectedWeekDay = (mSelectedWeek == position) ? mSelectedDate.get(
-                        Calendar.DAY_OF_WEEK) : -1;
-                weekView.init(position, selectedWeekDay, mFocusedMonth);
-
-                return weekView;
-            }
-
-            /**
-             * Changes which month is in focus and updates the view.
-             *
-             * @param month The month to show as in focus [0-11]
-             */
-            public void setFocusMonth(int month) {
-                if (mFocusedMonth == month) {
-                    return;
-                }
-                mFocusedMonth = month;
-                notifyDataSetChanged();
-            }
-
-            @Override
-            public boolean onTouch(View v, MotionEvent event) {
-                if (mListView.isEnabled() && mGestureDetector.onTouchEvent(event)) {
-                    WeekView weekView = (WeekView) v;
-                    // if we cannot find a day for the given location we are done
-                    if (!weekView.getDayFromLocation(event.getX(), mTempDate)) {
-                        return true;
-                    }
-                    // it is possible that the touched day is outside the valid range
-                    // we draw whole weeks but range end can fall not on the week end
-                    if (mTempDate.before(mMinDate) || mTempDate.after(mMaxDate)) {
-                        return true;
-                    }
-                    onDateTapped(mTempDate);
-                    return true;
-                }
-                return false;
-            }
-
-            /**
-             * Maintains the same hour/min/sec but moves the day to the tapped day.
-             *
-             * @param day The day that was tapped
-             */
-            private void onDateTapped(Calendar day) {
-                setSelectedDay(day);
-                setMonthDisplayed(day);
-            }
-
-            /**
-             * This is here so we can identify single tap events and set the
-             * selected day correctly
-             */
-            class CalendarGestureListener extends GestureDetector.SimpleOnGestureListener {
-                @Override
-                public boolean onSingleTapUp(MotionEvent e) {
-                    return true;
-                }
-            }
-        }
-
-        /**
-         * <p>
-         * This is a dynamic view for drawing a single week. It can be configured to
-         * display the week number, start the week on a given day, or show a reduced
-         * number of days. It is intended for use as a single view within a
-         * ListView. See {@link WeeksAdapter} for usage.
-         * </p>
-         */
-        private class WeekView extends View {
-
-            private final Rect mTempRect = new Rect();
-
-            private final Paint mDrawPaint = new Paint();
-
-            private final Paint mMonthNumDrawPaint = new Paint();
-
-            // Cache the number strings so we don't have to recompute them each time
-            private String[] mDayNumbers;
-
-            // Quick lookup for checking which days are in the focus month
-            private boolean[] mFocusDay;
-
-            // Whether this view has a focused day.
-            private boolean mHasFocusedDay;
-
-            // Whether this view has only focused days.
-            private boolean mHasUnfocusedDay;
-
-            // The first day displayed by this item
-            private Calendar mFirstDay;
-
-            // The month of the first day in this week
-            private int mMonthOfFirstWeekDay = -1;
-
-            // The month of the last day in this week
-            private int mLastWeekDayMonth = -1;
-
-            // The position of this week, equivalent to weeks since the week of Jan
-            // 1st, 1900
-            private int mWeek = -1;
-
-            // Quick reference to the width of this view, matches parent
-            private int mWidth;
-
-            // The height this view should draw at in pixels, set by height param
-            private int mHeight;
-
-            // If this view contains the selected day
-            private boolean mHasSelectedDay = false;
-
-            // Which day is selected [0-6] or -1 if no day is selected
-            private int mSelectedDay = -1;
-
-            // The number of days + a spot for week number if it is displayed
-            private int mNumCells;
-
-            // The left edge of the selected day
-            private int mSelectedLeft = -1;
-
-            // The right edge of the selected day
-            private int mSelectedRight = -1;
-
-            public WeekView(Context context) {
-                super(context);
-
-                // Sets up any standard paints that will be used
-                initilaizePaints();
-            }
-
-            /**
-             * Initializes this week view.
-             *
-             * @param weekNumber The number of the week this view represents. The
-             *            week number is a zero based index of the weeks since
-             *            {@link CalendarView#getMinDate()}.
-             * @param selectedWeekDay The selected day of the week from 0 to 6, -1 if no
-             *            selected day.
-             * @param focusedMonth The month that is currently in focus i.e.
-             *            highlighted.
-             */
-            public void init(int weekNumber, int selectedWeekDay, int focusedMonth) {
-                mSelectedDay = selectedWeekDay;
-                mHasSelectedDay = mSelectedDay != -1;
-                mNumCells = mShowWeekNumber ? mDaysPerWeek + 1 : mDaysPerWeek;
-                mWeek = weekNumber;
-                mTempDate.setTimeInMillis(mMinDate.getTimeInMillis());
-
-                mTempDate.add(Calendar.WEEK_OF_YEAR, mWeek);
-                mTempDate.setFirstDayOfWeek(mFirstDayOfWeek);
-
-                // Allocate space for caching the day numbers and focus values
-                mDayNumbers = new String[mNumCells];
-                mFocusDay = new boolean[mNumCells];
-
-                // If we're showing the week number calculate it based on Monday
-                int i = 0;
-                if (mShowWeekNumber) {
-                    mDayNumbers[0] = String.format(Locale.getDefault(), "%d",
-                            mTempDate.get(Calendar.WEEK_OF_YEAR));
-                    i++;
-                }
-
-                // Now adjust our starting day based on the start day of the week
-                int diff = mFirstDayOfWeek - mTempDate.get(Calendar.DAY_OF_WEEK);
-                mTempDate.add(Calendar.DAY_OF_MONTH, diff);
-
-                mFirstDay = (Calendar) mTempDate.clone();
-                mMonthOfFirstWeekDay = mTempDate.get(Calendar.MONTH);
-
-                mHasUnfocusedDay = true;
-                for (; i < mNumCells; i++) {
-                    final boolean isFocusedDay = (mTempDate.get(Calendar.MONTH) == focusedMonth);
-                    mFocusDay[i] = isFocusedDay;
-                    mHasFocusedDay |= isFocusedDay;
-                    mHasUnfocusedDay &= !isFocusedDay;
-                    // do not draw dates outside the valid range to avoid user confusion
-                    if (mTempDate.before(mMinDate) || mTempDate.after(mMaxDate)) {
-                        mDayNumbers[i] = "";
-                    } else {
-                        mDayNumbers[i] = String.format(Locale.getDefault(), "%d",
-                                mTempDate.get(Calendar.DAY_OF_MONTH));
-                    }
-                    mTempDate.add(Calendar.DAY_OF_MONTH, 1);
-                }
-                // We do one extra add at the end of the loop, if that pushed us to
-                // new month undo it
-                if (mTempDate.get(Calendar.DAY_OF_MONTH) == 1) {
-                    mTempDate.add(Calendar.DAY_OF_MONTH, -1);
-                }
-                mLastWeekDayMonth = mTempDate.get(Calendar.MONTH);
-
-                updateSelectionPositions();
-            }
-
-            /**
-             * Initialize the paint instances.
-             */
-            private void initilaizePaints() {
-                mDrawPaint.setFakeBoldText(false);
-                mDrawPaint.setAntiAlias(true);
-                mDrawPaint.setStyle(Style.FILL);
-
-                mMonthNumDrawPaint.setFakeBoldText(true);
-                mMonthNumDrawPaint.setAntiAlias(true);
-                mMonthNumDrawPaint.setStyle(Style.FILL);
-                mMonthNumDrawPaint.setTextAlign(Align.CENTER);
-                mMonthNumDrawPaint.setTextSize(mDateTextSize);
-            }
-
-            /**
-             * Returns the month of the first day in this week.
-             *
-             * @return The month the first day of this view is in.
-             */
-            public int getMonthOfFirstWeekDay() {
-                return mMonthOfFirstWeekDay;
-            }
-
-            /**
-             * Returns the month of the last day in this week
-             *
-             * @return The month the last day of this view is in
-             */
-            public int getMonthOfLastWeekDay() {
-                return mLastWeekDayMonth;
-            }
-
-            /**
-             * Returns the first day in this view.
-             *
-             * @return The first day in the view.
-             */
-            public Calendar getFirstDay() {
-                return mFirstDay;
-            }
-
-            /**
-             * Calculates the day that the given x position is in, accounting for
-             * week number.
-             *
-             * @param x The x position of the touch event.
-             * @return True if a day was found for the given location.
-             */
-            public boolean getDayFromLocation(float x, Calendar outCalendar) {
-                final boolean isLayoutRtl = isLayoutRtl();
-
-                int start;
-                int end;
-
-                if (isLayoutRtl) {
-                    start = 0;
-                    end = mShowWeekNumber ? mWidth - mWidth / mNumCells : mWidth;
-                } else {
-                    start = mShowWeekNumber ? mWidth / mNumCells : 0;
-                    end = mWidth;
-                }
-
-                if (x < start || x > end) {
-                    outCalendar.clear();
-                    return false;
-                }
-
-                // Selection is (x - start) / (pixels/day) which is (x - start) * day / pixels
-                int dayPosition = (int) ((x - start) * mDaysPerWeek / (end - start));
-
-                if (isLayoutRtl) {
-                    dayPosition = mDaysPerWeek - 1 - dayPosition;
-                }
-
-                outCalendar.setTimeInMillis(mFirstDay.getTimeInMillis());
-                outCalendar.add(Calendar.DAY_OF_MONTH, dayPosition);
-
-                return true;
-            }
-
-            @Override
-            protected void onDraw(Canvas canvas) {
-                drawBackground(canvas);
-                drawWeekNumbersAndDates(canvas);
-                drawWeekSeparators(canvas);
-                drawSelectedDateVerticalBars(canvas);
-            }
-
-            /**
-             * This draws the selection highlight if a day is selected in this week.
-             *
-             * @param canvas The canvas to draw on
-             */
-            private void drawBackground(Canvas canvas) {
-                if (!mHasSelectedDay) {
-                    return;
-                }
-                mDrawPaint.setColor(mSelectedWeekBackgroundColor);
-
-                mTempRect.top = mWeekSeperatorLineWidth;
-                mTempRect.bottom = mHeight;
-
-                final boolean isLayoutRtl = isLayoutRtl();
-
-                if (isLayoutRtl) {
-                    mTempRect.left = 0;
-                    mTempRect.right = mSelectedLeft - 2;
-                } else {
-                    mTempRect.left = mShowWeekNumber ? mWidth / mNumCells : 0;
-                    mTempRect.right = mSelectedLeft - 2;
-                }
-                canvas.drawRect(mTempRect, mDrawPaint);
-
-                if (isLayoutRtl) {
-                    mTempRect.left = mSelectedRight + 3;
-                    mTempRect.right = mShowWeekNumber ? mWidth - mWidth / mNumCells : mWidth;
-                } else {
-                    mTempRect.left = mSelectedRight + 3;
-                    mTempRect.right = mWidth;
-                }
-                canvas.drawRect(mTempRect, mDrawPaint);
-            }
-
-            /**
-             * Draws the week and month day numbers for this week.
-             *
-             * @param canvas The canvas to draw on
-             */
-            private void drawWeekNumbersAndDates(Canvas canvas) {
-                final float textHeight = mDrawPaint.getTextSize();
-                final int y = (int) ((mHeight + textHeight) / 2) - mWeekSeperatorLineWidth;
-                final int nDays = mNumCells;
-                final int divisor = 2 * nDays;
-
-                mDrawPaint.setTextAlign(Align.CENTER);
-                mDrawPaint.setTextSize(mDateTextSize);
-
-                int i = 0;
-
-                if (isLayoutRtl()) {
-                    for (; i < nDays - 1; i++) {
-                        mMonthNumDrawPaint.setColor(mFocusDay[i] ? mFocusedMonthDateColor
-                                : mUnfocusedMonthDateColor);
-                        int x = (2 * i + 1) * mWidth / divisor;
-                        canvas.drawText(mDayNumbers[nDays - 1 - i], x, y, mMonthNumDrawPaint);
-                    }
-                    if (mShowWeekNumber) {
-                        mDrawPaint.setColor(mWeekNumberColor);
-                        int x = mWidth - mWidth / divisor;
-                        canvas.drawText(mDayNumbers[0], x, y, mDrawPaint);
-                    }
-                } else {
-                    if (mShowWeekNumber) {
-                        mDrawPaint.setColor(mWeekNumberColor);
-                        int x = mWidth / divisor;
-                        canvas.drawText(mDayNumbers[0], x, y, mDrawPaint);
-                        i++;
-                    }
-                    for (; i < nDays; i++) {
-                        mMonthNumDrawPaint.setColor(mFocusDay[i] ? mFocusedMonthDateColor
-                                : mUnfocusedMonthDateColor);
-                        int x = (2 * i + 1) * mWidth / divisor;
-                        canvas.drawText(mDayNumbers[i], x, y, mMonthNumDrawPaint);
-                    }
-                }
-            }
-
-            /**
-             * Draws a horizontal line for separating the weeks.
-             *
-             * @param canvas The canvas to draw on.
-             */
-            private void drawWeekSeparators(Canvas canvas) {
-                // If it is the topmost fully visible child do not draw separator line
-                int firstFullyVisiblePosition = mListView.getFirstVisiblePosition();
-                if (mListView.getChildAt(0).getTop() < 0) {
-                    firstFullyVisiblePosition++;
-                }
-                if (firstFullyVisiblePosition == mWeek) {
-                    return;
-                }
-                mDrawPaint.setColor(mWeekSeparatorLineColor);
-                mDrawPaint.setStrokeWidth(mWeekSeperatorLineWidth);
-                float startX;
-                float stopX;
-                if (isLayoutRtl()) {
-                    startX = 0;
-                    stopX = mShowWeekNumber ? mWidth - mWidth / mNumCells : mWidth;
-                } else {
-                    startX = mShowWeekNumber ? mWidth / mNumCells : 0;
-                    stopX = mWidth;
-                }
-                canvas.drawLine(startX, 0, stopX, 0, mDrawPaint);
-            }
-
-            /**
-             * Draws the selected date bars if this week has a selected day.
-             *
-             * @param canvas The canvas to draw on
-             */
-            private void drawSelectedDateVerticalBars(Canvas canvas) {
-                if (!mHasSelectedDay) {
-                    return;
-                }
-                mSelectedDateVerticalBar.setBounds(
-                        mSelectedLeft - mSelectedDateVerticalBarWidth / 2,
-                        mWeekSeperatorLineWidth,
-                        mSelectedLeft + mSelectedDateVerticalBarWidth / 2,
-                        mHeight);
-                mSelectedDateVerticalBar.draw(canvas);
-                mSelectedDateVerticalBar.setBounds(
-                        mSelectedRight - mSelectedDateVerticalBarWidth / 2,
-                        mWeekSeperatorLineWidth,
-                        mSelectedRight + mSelectedDateVerticalBarWidth / 2,
-                        mHeight);
-                mSelectedDateVerticalBar.draw(canvas);
-            }
-
-            @Override
-            protected void onSizeChanged(int w, int h, int oldw, int oldh) {
-                mWidth = w;
-                updateSelectionPositions();
-            }
-
-            /**
-             * This calculates the positions for the selected day lines.
-             */
-            private void updateSelectionPositions() {
-                if (mHasSelectedDay) {
-                    final boolean isLayoutRtl = isLayoutRtl();
-                    int selectedPosition = mSelectedDay - mFirstDayOfWeek;
-                    if (selectedPosition < 0) {
-                        selectedPosition += 7;
-                    }
-                    if (mShowWeekNumber && !isLayoutRtl) {
-                        selectedPosition++;
-                    }
-                    if (isLayoutRtl) {
-                        mSelectedLeft = (mDaysPerWeek - 1 - selectedPosition) * mWidth / mNumCells;
-
-                    } else {
-                        mSelectedLeft = selectedPosition * mWidth / mNumCells;
-                    }
-                    mSelectedRight = mSelectedLeft + mWidth / mNumCells;
-                }
-            }
-
-            @Override
-            protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
-                mHeight = (mListView.getHeight() - mListView.getPaddingTop() - mListView
-                        .getPaddingBottom()) / mShownWeekCount;
-                setMeasuredDimension(MeasureSpec.getSize(widthMeasureSpec), mHeight);
-            }
-        }
-
     }
 
 }
diff --git a/core/java/android/widget/CalendarViewLegacyDelegate.java b/core/java/android/widget/CalendarViewLegacyDelegate.java
new file mode 100644
index 0000000..2ab3548
--- /dev/null
+++ b/core/java/android/widget/CalendarViewLegacyDelegate.java
@@ -0,0 +1,1527 @@
+/*
+ * Copyright (C) 2014 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 com.android.internal.R;
+
+import android.app.Service;
+import android.content.Context;
+import android.content.res.Configuration;
+import android.content.res.TypedArray;
+import android.database.DataSetObserver;
+import android.graphics.Canvas;
+import android.graphics.Paint;
+import android.graphics.Rect;
+import android.graphics.drawable.Drawable;
+import android.text.TextUtils;
+import android.text.format.DateUtils;
+import android.util.AttributeSet;
+import android.util.DisplayMetrics;
+import android.util.TypedValue;
+import android.view.GestureDetector;
+import android.view.LayoutInflater;
+import android.view.MotionEvent;
+import android.view.View;
+import android.view.ViewGroup;
+
+import java.util.Calendar;
+import java.util.Locale;
+
+import libcore.icu.LocaleData;
+
+/**
+ * A delegate implementing the legacy CalendarView
+ */
+class CalendarViewLegacyDelegate extends CalendarView.AbstractCalendarViewDelegate {
+    /**
+     * Default value whether to show week number.
+     */
+    private static final boolean DEFAULT_SHOW_WEEK_NUMBER = true;
+
+    /**
+     * The number of milliseconds in a day.e
+     */
+    private static final long MILLIS_IN_DAY = 86400000L;
+
+    /**
+     * The number of day in a week.
+     */
+    private static final int DAYS_PER_WEEK = 7;
+
+    /**
+     * The number of milliseconds in a week.
+     */
+    private static final long MILLIS_IN_WEEK = DAYS_PER_WEEK * MILLIS_IN_DAY;
+
+    /**
+     * Affects when the month selection will change while scrolling upe
+     */
+    private static final int SCROLL_HYST_WEEKS = 2;
+
+    /**
+     * How long the GoTo fling animation should last.
+     */
+    private static final int GOTO_SCROLL_DURATION = 1000;
+
+    /**
+     * The duration of the adjustment upon a user scroll in milliseconds.
+     */
+    private static final int ADJUSTMENT_SCROLL_DURATION = 500;
+
+    /**
+     * How long to wait after receiving an onScrollStateChanged notification
+     * before acting on it.
+     */
+    private static final int SCROLL_CHANGE_DELAY = 40;
+
+    private static final int DEFAULT_SHOWN_WEEK_COUNT = 6;
+
+    private static final int DEFAULT_DATE_TEXT_SIZE = 14;
+
+    private static final int UNSCALED_SELECTED_DATE_VERTICAL_BAR_WIDTH = 6;
+
+    private static final int UNSCALED_WEEK_MIN_VISIBLE_HEIGHT = 12;
+
+    private static final int UNSCALED_LIST_SCROLL_TOP_OFFSET = 2;
+
+    private static final int UNSCALED_BOTTOM_BUFFER = 20;
+
+    private static final int UNSCALED_WEEK_SEPARATOR_LINE_WIDTH = 1;
+
+    private static final int DEFAULT_WEEK_DAY_TEXT_APPEARANCE_RES_ID = -1;
+
+    private final int mWeekSeperatorLineWidth;
+
+    private int mDateTextSize;
+
+    private Drawable mSelectedDateVerticalBar;
+
+    private final int mSelectedDateVerticalBarWidth;
+
+    private int mSelectedWeekBackgroundColor;
+
+    private int mFocusedMonthDateColor;
+
+    private int mUnfocusedMonthDateColor;
+
+    private int mWeekSeparatorLineColor;
+
+    private int mWeekNumberColor;
+
+    private int mWeekDayTextAppearanceResId;
+
+    private int mDateTextAppearanceResId;
+
+    /**
+     * The top offset of the weeks list.
+     */
+    private int mListScrollTopOffset = 2;
+
+    /**
+     * The visible height of a week view.
+     */
+    private int mWeekMinVisibleHeight = 12;
+
+    /**
+     * The visible height of a week view.
+     */
+    private int mBottomBuffer = 20;
+
+    /**
+     * The number of shown weeks.
+     */
+    private int mShownWeekCount;
+
+    /**
+     * Flag whether to show the week number.
+     */
+    private boolean mShowWeekNumber;
+
+    /**
+     * The number of day per week to be shown.
+     */
+    private int mDaysPerWeek = 7;
+
+    /**
+     * The friction of the week list while flinging.
+     */
+    private float mFriction = .05f;
+
+    /**
+     * Scale for adjusting velocity of the week list while flinging.
+     */
+    private float mVelocityScale = 0.333f;
+
+    /**
+     * The adapter for the weeks list.
+     */
+    private WeeksAdapter mAdapter;
+
+    /**
+     * The weeks list.
+     */
+    private ListView mListView;
+
+    /**
+     * The name of the month to display.
+     */
+    private TextView mMonthName;
+
+    /**
+     * The header with week day names.
+     */
+    private ViewGroup mDayNamesHeader;
+
+    /**
+     * Cached abbreviations for day of week names.
+     */
+    private String[] mDayNamesShort;
+
+    /**
+     * Cached full-length day of week names.
+     */
+    private String[] mDayNamesLong;
+
+    /**
+     * The first day of the week.
+     */
+    private int mFirstDayOfWeek;
+
+    /**
+     * Which month should be displayed/highlighted [0-11].
+     */
+    private int mCurrentMonthDisplayed = -1;
+
+    /**
+     * Used for tracking during a scroll.
+     */
+    private long mPreviousScrollPosition;
+
+    /**
+     * Used for tracking which direction the view is scrolling.
+     */
+    private boolean mIsScrollingUp = false;
+
+    /**
+     * The previous scroll state of the weeks ListView.
+     */
+    private int mPreviousScrollState = AbsListView.OnScrollListener.SCROLL_STATE_IDLE;
+
+    /**
+     * The current scroll state of the weeks ListView.
+     */
+    private int mCurrentScrollState = AbsListView.OnScrollListener.SCROLL_STATE_IDLE;
+
+    /**
+     * Listener for changes in the selected day.
+     */
+    private CalendarView.OnDateChangeListener mOnDateChangeListener;
+
+    /**
+     * Command for adjusting the position after a scroll/fling.
+     */
+    private ScrollStateRunnable mScrollStateChangedRunnable = new ScrollStateRunnable();
+
+    /**
+     * Temporary instance to avoid multiple instantiations.
+     */
+    private Calendar mTempDate;
+
+    /**
+     * The first day of the focused month.
+     */
+    private Calendar mFirstDayOfMonth;
+
+    /**
+     * The start date of the range supported by this picker.
+     */
+    private Calendar mMinDate;
+
+    /**
+     * The end date of the range supported by this picker.
+     */
+    private Calendar mMaxDate;
+
+    CalendarViewLegacyDelegate(CalendarView delegator, Context context, AttributeSet attrs,
+            int defStyleAttr, int defStyleRes) {
+        super(delegator, context);
+
+        final TypedArray a = context.obtainStyledAttributes(attrs,
+                R.styleable.CalendarView, defStyleAttr, defStyleRes);
+        mShowWeekNumber = a.getBoolean(R.styleable.CalendarView_showWeekNumber,
+                DEFAULT_SHOW_WEEK_NUMBER);
+        mFirstDayOfWeek = a.getInt(R.styleable.CalendarView_firstDayOfWeek,
+                LocaleData.get(Locale.getDefault()).firstDayOfWeek);
+        final String minDate = a.getString(R.styleable.CalendarView_minDate);
+        if (TextUtils.isEmpty(minDate) || !parseDate(minDate, mMinDate)) {
+            parseDate(DEFAULT_MIN_DATE, mMinDate);
+        }
+        final String maxDate = a.getString(R.styleable.CalendarView_maxDate);
+        if (TextUtils.isEmpty(maxDate) || !parseDate(maxDate, mMaxDate)) {
+            parseDate(DEFAULT_MAX_DATE, mMaxDate);
+        }
+        if (mMaxDate.before(mMinDate)) {
+            throw new IllegalArgumentException("Max date cannot be before min date.");
+        }
+        mShownWeekCount = a.getInt(R.styleable.CalendarView_shownWeekCount,
+                DEFAULT_SHOWN_WEEK_COUNT);
+        mSelectedWeekBackgroundColor = a.getColor(
+                R.styleable.CalendarView_selectedWeekBackgroundColor, 0);
+        mFocusedMonthDateColor = a.getColor(
+                R.styleable.CalendarView_focusedMonthDateColor, 0);
+        mUnfocusedMonthDateColor = a.getColor(
+                R.styleable.CalendarView_unfocusedMonthDateColor, 0);
+        mWeekSeparatorLineColor = a.getColor(
+                R.styleable.CalendarView_weekSeparatorLineColor, 0);
+        mWeekNumberColor = a.getColor(R.styleable.CalendarView_weekNumberColor, 0);
+        mSelectedDateVerticalBar = a.getDrawable(
+                R.styleable.CalendarView_selectedDateVerticalBar);
+
+        mDateTextAppearanceResId = a.getResourceId(
+                R.styleable.CalendarView_dateTextAppearance, R.style.TextAppearance_Small);
+        updateDateTextSize();
+
+        mWeekDayTextAppearanceResId = a.getResourceId(
+                R.styleable.CalendarView_weekDayTextAppearance,
+                DEFAULT_WEEK_DAY_TEXT_APPEARANCE_RES_ID);
+        a.recycle();
+
+        DisplayMetrics displayMetrics = mDelegator.getResources().getDisplayMetrics();
+        mWeekMinVisibleHeight = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP,
+                UNSCALED_WEEK_MIN_VISIBLE_HEIGHT, displayMetrics);
+        mListScrollTopOffset = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP,
+                UNSCALED_LIST_SCROLL_TOP_OFFSET, displayMetrics);
+        mBottomBuffer = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP,
+                UNSCALED_BOTTOM_BUFFER, displayMetrics);
+        mSelectedDateVerticalBarWidth = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP,
+                UNSCALED_SELECTED_DATE_VERTICAL_BAR_WIDTH, displayMetrics);
+        mWeekSeperatorLineWidth = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP,
+                UNSCALED_WEEK_SEPARATOR_LINE_WIDTH, displayMetrics);
+
+        LayoutInflater layoutInflater = (LayoutInflater) mContext
+                .getSystemService(Service.LAYOUT_INFLATER_SERVICE);
+        View content = layoutInflater.inflate(R.layout.calendar_view, null, false);
+        mDelegator.addView(content);
+
+        mListView = (ListView) mDelegator.findViewById(R.id.list);
+        mDayNamesHeader = (ViewGroup) content.findViewById(R.id.day_names);
+        mMonthName = (TextView) content.findViewById(R.id.month_name);
+
+        setUpHeader();
+        setUpListView();
+        setUpAdapter();
+
+        // go to today or whichever is close to today min or max date
+        mTempDate.setTimeInMillis(System.currentTimeMillis());
+        if (mTempDate.before(mMinDate)) {
+            goTo(mMinDate, false, true, true);
+        } else if (mMaxDate.before(mTempDate)) {
+            goTo(mMaxDate, false, true, true);
+        } else {
+            goTo(mTempDate, false, true, true);
+        }
+
+        mDelegator.invalidate();
+    }
+
+    @Override
+    public void setShownWeekCount(int count) {
+        if (mShownWeekCount != count) {
+            mShownWeekCount = count;
+            mDelegator.invalidate();
+        }
+    }
+
+    @Override
+    public int getShownWeekCount() {
+        return mShownWeekCount;
+    }
+
+    @Override
+    public void setSelectedWeekBackgroundColor(int color) {
+        if (mSelectedWeekBackgroundColor != color) {
+            mSelectedWeekBackgroundColor = color;
+            final int childCount = mListView.getChildCount();
+            for (int i = 0; i < childCount; i++) {
+                WeekView weekView = (WeekView) mListView.getChildAt(i);
+                if (weekView.mHasSelectedDay) {
+                    weekView.invalidate();
+                }
+            }
+        }
+    }
+
+    @Override
+    public int getSelectedWeekBackgroundColor() {
+        return mSelectedWeekBackgroundColor;
+    }
+
+    @Override
+    public void setFocusedMonthDateColor(int color) {
+        if (mFocusedMonthDateColor != color) {
+            mFocusedMonthDateColor = color;
+            final int childCount = mListView.getChildCount();
+            for (int i = 0; i < childCount; i++) {
+                WeekView weekView = (WeekView) mListView.getChildAt(i);
+                if (weekView.mHasFocusedDay) {
+                    weekView.invalidate();
+                }
+            }
+        }
+    }
+
+    @Override
+    public int getFocusedMonthDateColor() {
+        return mFocusedMonthDateColor;
+    }
+
+    @Override
+    public void setUnfocusedMonthDateColor(int color) {
+        if (mUnfocusedMonthDateColor != color) {
+            mUnfocusedMonthDateColor = color;
+            final int childCount = mListView.getChildCount();
+            for (int i = 0; i < childCount; i++) {
+                WeekView weekView = (WeekView) mListView.getChildAt(i);
+                if (weekView.mHasUnfocusedDay) {
+                    weekView.invalidate();
+                }
+            }
+        }
+    }
+
+    @Override
+    public int getUnfocusedMonthDateColor() {
+        return mFocusedMonthDateColor;
+    }
+
+    @Override
+    public void setWeekNumberColor(int color) {
+        if (mWeekNumberColor != color) {
+            mWeekNumberColor = color;
+            if (mShowWeekNumber) {
+                invalidateAllWeekViews();
+            }
+        }
+    }
+
+    @Override
+    public int getWeekNumberColor() {
+        return mWeekNumberColor;
+    }
+
+    @Override
+    public void setWeekSeparatorLineColor(int color) {
+        if (mWeekSeparatorLineColor != color) {
+            mWeekSeparatorLineColor = color;
+            invalidateAllWeekViews();
+        }
+    }
+
+    @Override
+    public int getWeekSeparatorLineColor() {
+        return mWeekSeparatorLineColor;
+    }
+
+    @Override
+    public void setSelectedDateVerticalBar(int resourceId) {
+        Drawable drawable = mDelegator.getContext().getDrawable(resourceId);
+        setSelectedDateVerticalBar(drawable);
+    }
+
+    @Override
+    public void setSelectedDateVerticalBar(Drawable drawable) {
+        if (mSelectedDateVerticalBar != drawable) {
+            mSelectedDateVerticalBar = drawable;
+            final int childCount = mListView.getChildCount();
+            for (int i = 0; i < childCount; i++) {
+                WeekView weekView = (WeekView) mListView.getChildAt(i);
+                if (weekView.mHasSelectedDay) {
+                    weekView.invalidate();
+                }
+            }
+        }
+    }
+
+    @Override
+    public Drawable getSelectedDateVerticalBar() {
+        return mSelectedDateVerticalBar;
+    }
+
+    @Override
+    public void setWeekDayTextAppearance(int resourceId) {
+        if (mWeekDayTextAppearanceResId != resourceId) {
+            mWeekDayTextAppearanceResId = resourceId;
+            setUpHeader();
+        }
+    }
+
+    @Override
+    public int getWeekDayTextAppearance() {
+        return mWeekDayTextAppearanceResId;
+    }
+
+    @Override
+    public void setDateTextAppearance(int resourceId) {
+        if (mDateTextAppearanceResId != resourceId) {
+            mDateTextAppearanceResId = resourceId;
+            updateDateTextSize();
+            invalidateAllWeekViews();
+        }
+    }
+
+    @Override
+    public int getDateTextAppearance() {
+        return mDateTextAppearanceResId;
+    }
+
+    @Override
+    public void setMinDate(long minDate) {
+        mTempDate.setTimeInMillis(minDate);
+        if (isSameDate(mTempDate, mMinDate)) {
+            return;
+        }
+        mMinDate.setTimeInMillis(minDate);
+        // make sure the current date is not earlier than
+        // the new min date since the latter is used for
+        // calculating the indices in the adapter thus
+        // avoiding out of bounds error
+        Calendar date = mAdapter.mSelectedDate;
+        if (date.before(mMinDate)) {
+            mAdapter.setSelectedDay(mMinDate);
+        }
+        // reinitialize the adapter since its range depends on min date
+        mAdapter.init();
+        if (date.before(mMinDate)) {
+            setDate(mTempDate.getTimeInMillis());
+        } else {
+            // we go to the current date to force the ListView to query its
+            // adapter for the shown views since we have changed the adapter
+            // range and the base from which the later calculates item indices
+            // note that calling setDate will not work since the date is the same
+            goTo(date, false, true, false);
+        }
+    }
+
+    @Override
+    public long getMinDate() {
+        return mMinDate.getTimeInMillis();
+    }
+
+    @Override
+    public void setMaxDate(long maxDate) {
+        mTempDate.setTimeInMillis(maxDate);
+        if (isSameDate(mTempDate, mMaxDate)) {
+            return;
+        }
+        mMaxDate.setTimeInMillis(maxDate);
+        // reinitialize the adapter since its range depends on max date
+        mAdapter.init();
+        Calendar date = mAdapter.mSelectedDate;
+        if (date.after(mMaxDate)) {
+            setDate(mMaxDate.getTimeInMillis());
+        } else {
+            // we go to the current date to force the ListView to query its
+            // adapter for the shown views since we have changed the adapter
+            // range and the base from which the later calculates item indices
+            // note that calling setDate will not work since the date is the same
+            goTo(date, false, true, false);
+        }
+    }
+
+    @Override
+    public long getMaxDate() {
+        return mMaxDate.getTimeInMillis();
+    }
+
+    @Override
+    public void setShowWeekNumber(boolean showWeekNumber) {
+        if (mShowWeekNumber == showWeekNumber) {
+            return;
+        }
+        mShowWeekNumber = showWeekNumber;
+        mAdapter.notifyDataSetChanged();
+        setUpHeader();
+    }
+
+    @Override
+    public boolean getShowWeekNumber() {
+        return mShowWeekNumber;
+    }
+
+    @Override
+    public void setFirstDayOfWeek(int firstDayOfWeek) {
+        if (mFirstDayOfWeek == firstDayOfWeek) {
+            return;
+        }
+        mFirstDayOfWeek = firstDayOfWeek;
+        mAdapter.init();
+        mAdapter.notifyDataSetChanged();
+        setUpHeader();
+    }
+
+    @Override
+    public int getFirstDayOfWeek() {
+        return mFirstDayOfWeek;
+    }
+
+    @Override
+    public void setDate(long date) {
+        setDate(date, false, false);
+    }
+
+    @Override
+    public void setDate(long date, boolean animate, boolean center) {
+        mTempDate.setTimeInMillis(date);
+        if (isSameDate(mTempDate, mAdapter.mSelectedDate)) {
+            return;
+        }
+        goTo(mTempDate, animate, true, center);
+    }
+
+    @Override
+    public long getDate() {
+        return mAdapter.mSelectedDate.getTimeInMillis();
+    }
+
+    @Override
+    public void setOnDateChangeListener(CalendarView.OnDateChangeListener listener) {
+        mOnDateChangeListener = listener;
+    }
+
+    @Override
+    public void onConfigurationChanged(Configuration newConfig) {
+        setCurrentLocale(newConfig.locale);
+    }
+
+    /**
+     * Sets the current locale.
+     *
+     * @param locale The current locale.
+     */
+    @Override
+    protected void setCurrentLocale(Locale locale) {
+        super.setCurrentLocale(locale);
+
+        mTempDate = getCalendarForLocale(mTempDate, locale);
+        mFirstDayOfMonth = getCalendarForLocale(mFirstDayOfMonth, locale);
+        mMinDate = getCalendarForLocale(mMinDate, locale);
+        mMaxDate = getCalendarForLocale(mMaxDate, locale);
+    }
+    private void updateDateTextSize() {
+        TypedArray dateTextAppearance = mDelegator.getContext().obtainStyledAttributes(
+                mDateTextAppearanceResId, R.styleable.TextAppearance);
+        mDateTextSize = dateTextAppearance.getDimensionPixelSize(
+                R.styleable.TextAppearance_textSize, DEFAULT_DATE_TEXT_SIZE);
+        dateTextAppearance.recycle();
+    }
+
+    /**
+     * Invalidates all week views.
+     */
+    private void invalidateAllWeekViews() {
+        final int childCount = mListView.getChildCount();
+        for (int i = 0; i < childCount; i++) {
+            View view = mListView.getChildAt(i);
+            view.invalidate();
+        }
+    }
+
+    /**
+     * Gets a calendar for locale bootstrapped with the value of a given calendar.
+     *
+     * @param oldCalendar The old calendar.
+     * @param locale The locale.
+     */
+    private static Calendar getCalendarForLocale(Calendar oldCalendar, Locale locale) {
+        if (oldCalendar == null) {
+            return Calendar.getInstance(locale);
+        } else {
+            final long currentTimeMillis = oldCalendar.getTimeInMillis();
+            Calendar newCalendar = Calendar.getInstance(locale);
+            newCalendar.setTimeInMillis(currentTimeMillis);
+            return newCalendar;
+        }
+    }
+
+    /**
+     * @return True if the <code>firstDate</code> is the same as the <code>
+     * secondDate</code>.
+     */
+    private static boolean isSameDate(Calendar firstDate, Calendar secondDate) {
+        return (firstDate.get(Calendar.DAY_OF_YEAR) == secondDate.get(Calendar.DAY_OF_YEAR)
+                && firstDate.get(Calendar.YEAR) == secondDate.get(Calendar.YEAR));
+    }
+
+    /**
+     * Creates a new adapter if necessary and sets up its parameters.
+     */
+    private void setUpAdapter() {
+        if (mAdapter == null) {
+            mAdapter = new WeeksAdapter(mContext);
+            mAdapter.registerDataSetObserver(new DataSetObserver() {
+                @Override
+                public void onChanged() {
+                    if (mOnDateChangeListener != null) {
+                        Calendar selectedDay = mAdapter.getSelectedDay();
+                        mOnDateChangeListener.onSelectedDayChange(mDelegator,
+                                selectedDay.get(Calendar.YEAR),
+                                selectedDay.get(Calendar.MONTH),
+                                selectedDay.get(Calendar.DAY_OF_MONTH));
+                    }
+                }
+            });
+            mListView.setAdapter(mAdapter);
+        }
+
+        // refresh the view with the new parameters
+        mAdapter.notifyDataSetChanged();
+    }
+
+    /**
+     * Sets up the strings to be used by the header.
+     */
+    private void setUpHeader() {
+        mDayNamesShort = new String[mDaysPerWeek];
+        mDayNamesLong = new String[mDaysPerWeek];
+        for (int i = mFirstDayOfWeek, count = mFirstDayOfWeek + mDaysPerWeek; i < count; i++) {
+            int calendarDay = (i > Calendar.SATURDAY) ? i - Calendar.SATURDAY : i;
+            mDayNamesShort[i - mFirstDayOfWeek] = DateUtils.getDayOfWeekString(calendarDay,
+                    DateUtils.LENGTH_SHORTEST);
+            mDayNamesLong[i - mFirstDayOfWeek] = DateUtils.getDayOfWeekString(calendarDay,
+                    DateUtils.LENGTH_LONG);
+        }
+
+        TextView label = (TextView) mDayNamesHeader.getChildAt(0);
+        if (mShowWeekNumber) {
+            label.setVisibility(View.VISIBLE);
+        } else {
+            label.setVisibility(View.GONE);
+        }
+        for (int i = 1, count = mDayNamesHeader.getChildCount(); i < count; i++) {
+            label = (TextView) mDayNamesHeader.getChildAt(i);
+            if (mWeekDayTextAppearanceResId > -1) {
+                label.setTextAppearance(mContext, mWeekDayTextAppearanceResId);
+            }
+            if (i < mDaysPerWeek + 1) {
+                label.setText(mDayNamesShort[i - 1]);
+                label.setContentDescription(mDayNamesLong[i - 1]);
+                label.setVisibility(View.VISIBLE);
+            } else {
+                label.setVisibility(View.GONE);
+            }
+        }
+        mDayNamesHeader.invalidate();
+    }
+
+    /**
+     * Sets all the required fields for the list view.
+     */
+    private void setUpListView() {
+        // Configure the listview
+        mListView.setDivider(null);
+        mListView.setItemsCanFocus(true);
+        mListView.setVerticalScrollBarEnabled(false);
+        mListView.setOnScrollListener(new AbsListView.OnScrollListener() {
+            public void onScrollStateChanged(AbsListView view, int scrollState) {
+                CalendarViewLegacyDelegate.this.onScrollStateChanged(view, scrollState);
+            }
+
+            public void onScroll(
+                    AbsListView view, int firstVisibleItem, int visibleItemCount,
+                    int totalItemCount) {
+                CalendarViewLegacyDelegate.this.onScroll(view, firstVisibleItem,
+                        visibleItemCount, totalItemCount);
+            }
+        });
+        // Make the scrolling behavior nicer
+        mListView.setFriction(mFriction);
+        mListView.setVelocityScale(mVelocityScale);
+    }
+
+    /**
+     * This moves to the specified time in the view. If the time is not already
+     * in range it will move the list so that the first of the month containing
+     * the time is at the top of the view. If the new time is already in view
+     * the list will not be scrolled unless forceScroll is true. This time may
+     * optionally be highlighted as selected as well.
+     *
+     * @param date The time to move to.
+     * @param animate Whether to scroll to the given time or just redraw at the
+     *            new location.
+     * @param setSelected Whether to set the given time as selected.
+     * @param forceScroll Whether to recenter even if the time is already
+     *            visible.
+     *
+     * @throws IllegalArgumentException of the provided date is before the
+     *        range start of after the range end.
+     */
+    private void goTo(Calendar date, boolean animate, boolean setSelected,
+            boolean forceScroll) {
+        if (date.before(mMinDate) || date.after(mMaxDate)) {
+            throw new IllegalArgumentException("Time not between " + mMinDate.getTime()
+                    + " and " + mMaxDate.getTime());
+        }
+        // Find the first and last entirely visible weeks
+        int firstFullyVisiblePosition = mListView.getFirstVisiblePosition();
+        View firstChild = mListView.getChildAt(0);
+        if (firstChild != null && firstChild.getTop() < 0) {
+            firstFullyVisiblePosition++;
+        }
+        int lastFullyVisiblePosition = firstFullyVisiblePosition + mShownWeekCount - 1;
+        if (firstChild != null && firstChild.getTop() > mBottomBuffer) {
+            lastFullyVisiblePosition--;
+        }
+        if (setSelected) {
+            mAdapter.setSelectedDay(date);
+        }
+        // Get the week we're going to
+        int position = getWeeksSinceMinDate(date);
+
+        // Check if the selected day is now outside of our visible range
+        // and if so scroll to the month that contains it
+        if (position < firstFullyVisiblePosition || position > lastFullyVisiblePosition
+                || forceScroll) {
+            mFirstDayOfMonth.setTimeInMillis(date.getTimeInMillis());
+            mFirstDayOfMonth.set(Calendar.DAY_OF_MONTH, 1);
+
+            setMonthDisplayed(mFirstDayOfMonth);
+
+            // the earliest time we can scroll to is the min date
+            if (mFirstDayOfMonth.before(mMinDate)) {
+                position = 0;
+            } else {
+                position = getWeeksSinceMinDate(mFirstDayOfMonth);
+            }
+
+            mPreviousScrollState = AbsListView.OnScrollListener.SCROLL_STATE_FLING;
+            if (animate) {
+                mListView.smoothScrollToPositionFromTop(position, mListScrollTopOffset,
+                        GOTO_SCROLL_DURATION);
+            } else {
+                mListView.setSelectionFromTop(position, mListScrollTopOffset);
+                // Perform any after scroll operations that are needed
+                onScrollStateChanged(mListView, AbsListView.OnScrollListener.SCROLL_STATE_IDLE);
+            }
+        } else if (setSelected) {
+            // Otherwise just set the selection
+            setMonthDisplayed(date);
+        }
+    }
+
+    /**
+     * Called when a <code>view</code> transitions to a new <code>scrollState
+     * </code>.
+     */
+    private void onScrollStateChanged(AbsListView view, int scrollState) {
+        mScrollStateChangedRunnable.doScrollStateChange(view, scrollState);
+    }
+
+    /**
+     * Updates the title and selected month if the <code>view</code> has moved to a new
+     * month.
+     */
+    private void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount,
+                          int totalItemCount) {
+        WeekView child = (WeekView) view.getChildAt(0);
+        if (child == null) {
+            return;
+        }
+
+        // Figure out where we are
+        long currScroll =
+                view.getFirstVisiblePosition() * child.getHeight() - child.getBottom();
+
+        // If we have moved since our last call update the direction
+        if (currScroll < mPreviousScrollPosition) {
+            mIsScrollingUp = true;
+        } else if (currScroll > mPreviousScrollPosition) {
+            mIsScrollingUp = false;
+        } else {
+            return;
+        }
+
+        // Use some hysteresis for checking which month to highlight. This
+        // causes the month to transition when two full weeks of a month are
+        // visible when scrolling up, and when the first day in a month reaches
+        // the top of the screen when scrolling down.
+        int offset = child.getBottom() < mWeekMinVisibleHeight ? 1 : 0;
+        if (mIsScrollingUp) {
+            child = (WeekView) view.getChildAt(SCROLL_HYST_WEEKS + offset);
+        } else if (offset != 0) {
+            child = (WeekView) view.getChildAt(offset);
+        }
+
+        if (child != null) {
+            // Find out which month we're moving into
+            int month;
+            if (mIsScrollingUp) {
+                month = child.getMonthOfFirstWeekDay();
+            } else {
+                month = child.getMonthOfLastWeekDay();
+            }
+
+            // And how it relates to our current highlighted month
+            int monthDiff;
+            if (mCurrentMonthDisplayed == 11 && month == 0) {
+                monthDiff = 1;
+            } else if (mCurrentMonthDisplayed == 0 && month == 11) {
+                monthDiff = -1;
+            } else {
+                monthDiff = month - mCurrentMonthDisplayed;
+            }
+
+            // Only switch months if we're scrolling away from the currently
+            // selected month
+            if ((!mIsScrollingUp && monthDiff > 0) || (mIsScrollingUp && monthDiff < 0)) {
+                Calendar firstDay = child.getFirstDay();
+                if (mIsScrollingUp) {
+                    firstDay.add(Calendar.DAY_OF_MONTH, -DAYS_PER_WEEK);
+                } else {
+                    firstDay.add(Calendar.DAY_OF_MONTH, DAYS_PER_WEEK);
+                }
+                setMonthDisplayed(firstDay);
+            }
+        }
+        mPreviousScrollPosition = currScroll;
+        mPreviousScrollState = mCurrentScrollState;
+    }
+
+    /**
+     * Sets the month displayed at the top of this view based on time. Override
+     * to add custom events when the title is changed.
+     *
+     * @param calendar A day in the new focus month.
+     */
+    private void setMonthDisplayed(Calendar calendar) {
+        mCurrentMonthDisplayed = calendar.get(Calendar.MONTH);
+        mAdapter.setFocusMonth(mCurrentMonthDisplayed);
+        final int flags = DateUtils.FORMAT_SHOW_DATE | DateUtils.FORMAT_NO_MONTH_DAY
+                | DateUtils.FORMAT_SHOW_YEAR;
+        final long millis = calendar.getTimeInMillis();
+        String newMonthName = DateUtils.formatDateRange(mContext, millis, millis, flags);
+        mMonthName.setText(newMonthName);
+        mMonthName.invalidate();
+    }
+
+    /**
+     * @return Returns the number of weeks between the current <code>date</code>
+     *         and the <code>mMinDate</code>.
+     */
+    private int getWeeksSinceMinDate(Calendar date) {
+        if (date.before(mMinDate)) {
+            throw new IllegalArgumentException("fromDate: " + mMinDate.getTime()
+                    + " does not precede toDate: " + date.getTime());
+        }
+        long endTimeMillis = date.getTimeInMillis()
+                + date.getTimeZone().getOffset(date.getTimeInMillis());
+        long startTimeMillis = mMinDate.getTimeInMillis()
+                + mMinDate.getTimeZone().getOffset(mMinDate.getTimeInMillis());
+        long dayOffsetMillis = (mMinDate.get(Calendar.DAY_OF_WEEK) - mFirstDayOfWeek)
+                * MILLIS_IN_DAY;
+        return (int) ((endTimeMillis - startTimeMillis + dayOffsetMillis) / MILLIS_IN_WEEK);
+    }
+
+    /**
+     * Command responsible for acting upon scroll state changes.
+     */
+    private class ScrollStateRunnable implements Runnable {
+        private AbsListView mView;
+
+        private int mNewState;
+
+        /**
+         * Sets up the runnable with a short delay in case the scroll state
+         * immediately changes again.
+         *
+         * @param view The list view that changed state
+         * @param scrollState The new state it changed to
+         */
+        public void doScrollStateChange(AbsListView view, int scrollState) {
+            mView = view;
+            mNewState = scrollState;
+            mDelegator.removeCallbacks(this);
+            mDelegator.postDelayed(this, SCROLL_CHANGE_DELAY);
+        }
+
+        public void run() {
+            mCurrentScrollState = mNewState;
+            // Fix the position after a scroll or a fling ends
+            if (mNewState == AbsListView.OnScrollListener.SCROLL_STATE_IDLE
+                    && mPreviousScrollState != AbsListView.OnScrollListener.SCROLL_STATE_IDLE) {
+                View child = mView.getChildAt(0);
+                if (child == null) {
+                    // The view is no longer visible, just return
+                    return;
+                }
+                int dist = child.getBottom() - mListScrollTopOffset;
+                if (dist > mListScrollTopOffset) {
+                    if (mIsScrollingUp) {
+                        mView.smoothScrollBy(dist - child.getHeight(),
+                                ADJUSTMENT_SCROLL_DURATION);
+                    } else {
+                        mView.smoothScrollBy(dist, ADJUSTMENT_SCROLL_DURATION);
+                    }
+                }
+            }
+            mPreviousScrollState = mNewState;
+        }
+    }
+
+    /**
+     * <p>
+     * This is a specialized adapter for creating a list of weeks with
+     * selectable days. It can be configured to display the week number, start
+     * the week on a given day, show a reduced number of days, or display an
+     * arbitrary number of weeks at a time.
+     * </p>
+     */
+    private class WeeksAdapter extends BaseAdapter implements View.OnTouchListener {
+
+        private int mSelectedWeek;
+
+        private GestureDetector mGestureDetector;
+
+        private int mFocusedMonth;
+
+        private final Calendar mSelectedDate = Calendar.getInstance();
+
+        private int mTotalWeekCount;
+
+        public WeeksAdapter(Context context) {
+            mContext = context;
+            mGestureDetector = new GestureDetector(mContext, new WeeksAdapter.CalendarGestureListener());
+            init();
+        }
+
+        /**
+         * Set up the gesture detector and selected time
+         */
+        private void init() {
+            mSelectedWeek = getWeeksSinceMinDate(mSelectedDate);
+            mTotalWeekCount = getWeeksSinceMinDate(mMaxDate);
+            if (mMinDate.get(Calendar.DAY_OF_WEEK) != mFirstDayOfWeek
+                    || mMaxDate.get(Calendar.DAY_OF_WEEK) != mFirstDayOfWeek) {
+                mTotalWeekCount++;
+            }
+            notifyDataSetChanged();
+        }
+
+        /**
+         * Updates the selected day and related parameters.
+         *
+         * @param selectedDay The time to highlight
+         */
+        public void setSelectedDay(Calendar selectedDay) {
+            if (selectedDay.get(Calendar.DAY_OF_YEAR) == mSelectedDate.get(Calendar.DAY_OF_YEAR)
+                    && selectedDay.get(Calendar.YEAR) == mSelectedDate.get(Calendar.YEAR)) {
+                return;
+            }
+            mSelectedDate.setTimeInMillis(selectedDay.getTimeInMillis());
+            mSelectedWeek = getWeeksSinceMinDate(mSelectedDate);
+            mFocusedMonth = mSelectedDate.get(Calendar.MONTH);
+            notifyDataSetChanged();
+        }
+
+        /**
+         * @return The selected day of month.
+         */
+        public Calendar getSelectedDay() {
+            return mSelectedDate;
+        }
+
+        @Override
+        public int getCount() {
+            return mTotalWeekCount;
+        }
+
+        @Override
+        public Object getItem(int position) {
+            return null;
+        }
+
+        @Override
+        public long getItemId(int position) {
+            return position;
+        }
+
+        @Override
+        public View getView(int position, View convertView, ViewGroup parent) {
+            WeekView weekView = null;
+            if (convertView != null) {
+                weekView = (WeekView) convertView;
+            } else {
+                weekView = new WeekView(mContext);
+                AbsListView.LayoutParams params =
+                        new AbsListView.LayoutParams(FrameLayout.LayoutParams.WRAP_CONTENT,
+                                FrameLayout.LayoutParams.WRAP_CONTENT);
+                weekView.setLayoutParams(params);
+                weekView.setClickable(true);
+                weekView.setOnTouchListener(this);
+            }
+
+            int selectedWeekDay = (mSelectedWeek == position) ? mSelectedDate.get(
+                    Calendar.DAY_OF_WEEK) : -1;
+            weekView.init(position, selectedWeekDay, mFocusedMonth);
+
+            return weekView;
+        }
+
+        /**
+         * Changes which month is in focus and updates the view.
+         *
+         * @param month The month to show as in focus [0-11]
+         */
+        public void setFocusMonth(int month) {
+            if (mFocusedMonth == month) {
+                return;
+            }
+            mFocusedMonth = month;
+            notifyDataSetChanged();
+        }
+
+        @Override
+        public boolean onTouch(View v, MotionEvent event) {
+            if (mListView.isEnabled() && mGestureDetector.onTouchEvent(event)) {
+                WeekView weekView = (WeekView) v;
+                // if we cannot find a day for the given location we are done
+                if (!weekView.getDayFromLocation(event.getX(), mTempDate)) {
+                    return true;
+                }
+                // it is possible that the touched day is outside the valid range
+                // we draw whole weeks but range end can fall not on the week end
+                if (mTempDate.before(mMinDate) || mTempDate.after(mMaxDate)) {
+                    return true;
+                }
+                onDateTapped(mTempDate);
+                return true;
+            }
+            return false;
+        }
+
+        /**
+         * Maintains the same hour/min/sec but moves the day to the tapped day.
+         *
+         * @param day The day that was tapped
+         */
+        private void onDateTapped(Calendar day) {
+            setSelectedDay(day);
+            setMonthDisplayed(day);
+        }
+
+        /**
+         * This is here so we can identify single tap events and set the
+         * selected day correctly
+         */
+        class CalendarGestureListener extends GestureDetector.SimpleOnGestureListener {
+            @Override
+            public boolean onSingleTapUp(MotionEvent e) {
+                return true;
+            }
+        }
+    }
+
+    /**
+     * <p>
+     * This is a dynamic view for drawing a single week. It can be configured to
+     * display the week number, start the week on a given day, or show a reduced
+     * number of days. It is intended for use as a single view within a
+     * ListView. See {@link WeeksAdapter} for usage.
+     * </p>
+     */
+    private class WeekView extends View {
+
+        private final Rect mTempRect = new Rect();
+
+        private final Paint mDrawPaint = new Paint();
+
+        private final Paint mMonthNumDrawPaint = new Paint();
+
+        // Cache the number strings so we don't have to recompute them each time
+        private String[] mDayNumbers;
+
+        // Quick lookup for checking which days are in the focus month
+        private boolean[] mFocusDay;
+
+        // Whether this view has a focused day.
+        private boolean mHasFocusedDay;
+
+        // Whether this view has only focused days.
+        private boolean mHasUnfocusedDay;
+
+        // The first day displayed by this item
+        private Calendar mFirstDay;
+
+        // The month of the first day in this week
+        private int mMonthOfFirstWeekDay = -1;
+
+        // The month of the last day in this week
+        private int mLastWeekDayMonth = -1;
+
+        // The position of this week, equivalent to weeks since the week of Jan
+        // 1st, 1900
+        private int mWeek = -1;
+
+        // Quick reference to the width of this view, matches parent
+        private int mWidth;
+
+        // The height this view should draw at in pixels, set by height param
+        private int mHeight;
+
+        // If this view contains the selected day
+        private boolean mHasSelectedDay = false;
+
+        // Which day is selected [0-6] or -1 if no day is selected
+        private int mSelectedDay = -1;
+
+        // The number of days + a spot for week number if it is displayed
+        private int mNumCells;
+
+        // The left edge of the selected day
+        private int mSelectedLeft = -1;
+
+        // The right edge of the selected day
+        private int mSelectedRight = -1;
+
+        public WeekView(Context context) {
+            super(context);
+
+            // Sets up any standard paints that will be used
+            initilaizePaints();
+        }
+
+        /**
+         * Initializes this week view.
+         *
+         * @param weekNumber The number of the week this view represents. The
+         *            week number is a zero based index of the weeks since
+         *            {@link android.widget.CalendarView#getMinDate()}.
+         * @param selectedWeekDay The selected day of the week from 0 to 6, -1 if no
+         *            selected day.
+         * @param focusedMonth The month that is currently in focus i.e.
+         *            highlighted.
+         */
+        public void init(int weekNumber, int selectedWeekDay, int focusedMonth) {
+            mSelectedDay = selectedWeekDay;
+            mHasSelectedDay = mSelectedDay != -1;
+            mNumCells = mShowWeekNumber ? mDaysPerWeek + 1 : mDaysPerWeek;
+            mWeek = weekNumber;
+            mTempDate.setTimeInMillis(mMinDate.getTimeInMillis());
+
+            mTempDate.add(Calendar.WEEK_OF_YEAR, mWeek);
+            mTempDate.setFirstDayOfWeek(mFirstDayOfWeek);
+
+            // Allocate space for caching the day numbers and focus values
+            mDayNumbers = new String[mNumCells];
+            mFocusDay = new boolean[mNumCells];
+
+            // If we're showing the week number calculate it based on Monday
+            int i = 0;
+            if (mShowWeekNumber) {
+                mDayNumbers[0] = String.format(Locale.getDefault(), "%d",
+                        mTempDate.get(Calendar.WEEK_OF_YEAR));
+                i++;
+            }
+
+            // Now adjust our starting day based on the start day of the week
+            int diff = mFirstDayOfWeek - mTempDate.get(Calendar.DAY_OF_WEEK);
+            mTempDate.add(Calendar.DAY_OF_MONTH, diff);
+
+            mFirstDay = (Calendar) mTempDate.clone();
+            mMonthOfFirstWeekDay = mTempDate.get(Calendar.MONTH);
+
+            mHasUnfocusedDay = true;
+            for (; i < mNumCells; i++) {
+                final boolean isFocusedDay = (mTempDate.get(Calendar.MONTH) == focusedMonth);
+                mFocusDay[i] = isFocusedDay;
+                mHasFocusedDay |= isFocusedDay;
+                mHasUnfocusedDay &= !isFocusedDay;
+                // do not draw dates outside the valid range to avoid user confusion
+                if (mTempDate.before(mMinDate) || mTempDate.after(mMaxDate)) {
+                    mDayNumbers[i] = "";
+                } else {
+                    mDayNumbers[i] = String.format(Locale.getDefault(), "%d",
+                            mTempDate.get(Calendar.DAY_OF_MONTH));
+                }
+                mTempDate.add(Calendar.DAY_OF_MONTH, 1);
+            }
+            // We do one extra add at the end of the loop, if that pushed us to
+            // new month undo it
+            if (mTempDate.get(Calendar.DAY_OF_MONTH) == 1) {
+                mTempDate.add(Calendar.DAY_OF_MONTH, -1);
+            }
+            mLastWeekDayMonth = mTempDate.get(Calendar.MONTH);
+
+            updateSelectionPositions();
+        }
+
+        /**
+         * Initialize the paint instances.
+         */
+        private void initilaizePaints() {
+            mDrawPaint.setFakeBoldText(false);
+            mDrawPaint.setAntiAlias(true);
+            mDrawPaint.setStyle(Paint.Style.FILL);
+
+            mMonthNumDrawPaint.setFakeBoldText(true);
+            mMonthNumDrawPaint.setAntiAlias(true);
+            mMonthNumDrawPaint.setStyle(Paint.Style.FILL);
+            mMonthNumDrawPaint.setTextAlign(Paint.Align.CENTER);
+            mMonthNumDrawPaint.setTextSize(mDateTextSize);
+        }
+
+        /**
+         * Returns the month of the first day in this week.
+         *
+         * @return The month the first day of this view is in.
+         */
+        public int getMonthOfFirstWeekDay() {
+            return mMonthOfFirstWeekDay;
+        }
+
+        /**
+         * Returns the month of the last day in this week
+         *
+         * @return The month the last day of this view is in
+         */
+        public int getMonthOfLastWeekDay() {
+            return mLastWeekDayMonth;
+        }
+
+        /**
+         * Returns the first day in this view.
+         *
+         * @return The first day in the view.
+         */
+        public Calendar getFirstDay() {
+            return mFirstDay;
+        }
+
+        /**
+         * Calculates the day that the given x position is in, accounting for
+         * week number.
+         *
+         * @param x The x position of the touch event.
+         * @return True if a day was found for the given location.
+         */
+        public boolean getDayFromLocation(float x, Calendar outCalendar) {
+            final boolean isLayoutRtl = isLayoutRtl();
+
+            int start;
+            int end;
+
+            if (isLayoutRtl) {
+                start = 0;
+                end = mShowWeekNumber ? mWidth - mWidth / mNumCells : mWidth;
+            } else {
+                start = mShowWeekNumber ? mWidth / mNumCells : 0;
+                end = mWidth;
+            }
+
+            if (x < start || x > end) {
+                outCalendar.clear();
+                return false;
+            }
+
+            // Selection is (x - start) / (pixels/day) which is (x - start) * day / pixels
+            int dayPosition = (int) ((x - start) * mDaysPerWeek / (end - start));
+
+            if (isLayoutRtl) {
+                dayPosition = mDaysPerWeek - 1 - dayPosition;
+            }
+
+            outCalendar.setTimeInMillis(mFirstDay.getTimeInMillis());
+            outCalendar.add(Calendar.DAY_OF_MONTH, dayPosition);
+
+            return true;
+        }
+
+        @Override
+        protected void onDraw(Canvas canvas) {
+            drawBackground(canvas);
+            drawWeekNumbersAndDates(canvas);
+            drawWeekSeparators(canvas);
+            drawSelectedDateVerticalBars(canvas);
+        }
+
+        /**
+         * This draws the selection highlight if a day is selected in this week.
+         *
+         * @param canvas The canvas to draw on
+         */
+        private void drawBackground(Canvas canvas) {
+            if (!mHasSelectedDay) {
+                return;
+            }
+            mDrawPaint.setColor(mSelectedWeekBackgroundColor);
+
+            mTempRect.top = mWeekSeperatorLineWidth;
+            mTempRect.bottom = mHeight;
+
+            final boolean isLayoutRtl = isLayoutRtl();
+
+            if (isLayoutRtl) {
+                mTempRect.left = 0;
+                mTempRect.right = mSelectedLeft - 2;
+            } else {
+                mTempRect.left = mShowWeekNumber ? mWidth / mNumCells : 0;
+                mTempRect.right = mSelectedLeft - 2;
+            }
+            canvas.drawRect(mTempRect, mDrawPaint);
+
+            if (isLayoutRtl) {
+                mTempRect.left = mSelectedRight + 3;
+                mTempRect.right = mShowWeekNumber ? mWidth - mWidth / mNumCells : mWidth;
+            } else {
+                mTempRect.left = mSelectedRight + 3;
+                mTempRect.right = mWidth;
+            }
+            canvas.drawRect(mTempRect, mDrawPaint);
+        }
+
+        /**
+         * Draws the week and month day numbers for this week.
+         *
+         * @param canvas The canvas to draw on
+         */
+        private void drawWeekNumbersAndDates(Canvas canvas) {
+            final float textHeight = mDrawPaint.getTextSize();
+            final int y = (int) ((mHeight + textHeight) / 2) - mWeekSeperatorLineWidth;
+            final int nDays = mNumCells;
+            final int divisor = 2 * nDays;
+
+            mDrawPaint.setTextAlign(Paint.Align.CENTER);
+            mDrawPaint.setTextSize(mDateTextSize);
+
+            int i = 0;
+
+            if (isLayoutRtl()) {
+                for (; i < nDays - 1; i++) {
+                    mMonthNumDrawPaint.setColor(mFocusDay[i] ? mFocusedMonthDateColor
+                            : mUnfocusedMonthDateColor);
+                    int x = (2 * i + 1) * mWidth / divisor;
+                    canvas.drawText(mDayNumbers[nDays - 1 - i], x, y, mMonthNumDrawPaint);
+                }
+                if (mShowWeekNumber) {
+                    mDrawPaint.setColor(mWeekNumberColor);
+                    int x = mWidth - mWidth / divisor;
+                    canvas.drawText(mDayNumbers[0], x, y, mDrawPaint);
+                }
+            } else {
+                if (mShowWeekNumber) {
+                    mDrawPaint.setColor(mWeekNumberColor);
+                    int x = mWidth / divisor;
+                    canvas.drawText(mDayNumbers[0], x, y, mDrawPaint);
+                    i++;
+                }
+                for (; i < nDays; i++) {
+                    mMonthNumDrawPaint.setColor(mFocusDay[i] ? mFocusedMonthDateColor
+                            : mUnfocusedMonthDateColor);
+                    int x = (2 * i + 1) * mWidth / divisor;
+                    canvas.drawText(mDayNumbers[i], x, y, mMonthNumDrawPaint);
+                }
+            }
+        }
+
+        /**
+         * Draws a horizontal line for separating the weeks.
+         *
+         * @param canvas The canvas to draw on.
+         */
+        private void drawWeekSeparators(Canvas canvas) {
+            // If it is the topmost fully visible child do not draw separator line
+            int firstFullyVisiblePosition = mListView.getFirstVisiblePosition();
+            if (mListView.getChildAt(0).getTop() < 0) {
+                firstFullyVisiblePosition++;
+            }
+            if (firstFullyVisiblePosition == mWeek) {
+                return;
+            }
+            mDrawPaint.setColor(mWeekSeparatorLineColor);
+            mDrawPaint.setStrokeWidth(mWeekSeperatorLineWidth);
+            float startX;
+            float stopX;
+            if (isLayoutRtl()) {
+                startX = 0;
+                stopX = mShowWeekNumber ? mWidth - mWidth / mNumCells : mWidth;
+            } else {
+                startX = mShowWeekNumber ? mWidth / mNumCells : 0;
+                stopX = mWidth;
+            }
+            canvas.drawLine(startX, 0, stopX, 0, mDrawPaint);
+        }
+
+        /**
+         * Draws the selected date bars if this week has a selected day.
+         *
+         * @param canvas The canvas to draw on
+         */
+        private void drawSelectedDateVerticalBars(Canvas canvas) {
+            if (!mHasSelectedDay) {
+                return;
+            }
+            mSelectedDateVerticalBar.setBounds(
+                    mSelectedLeft - mSelectedDateVerticalBarWidth / 2,
+                    mWeekSeperatorLineWidth,
+                    mSelectedLeft + mSelectedDateVerticalBarWidth / 2,
+                    mHeight);
+            mSelectedDateVerticalBar.draw(canvas);
+            mSelectedDateVerticalBar.setBounds(
+                    mSelectedRight - mSelectedDateVerticalBarWidth / 2,
+                    mWeekSeperatorLineWidth,
+                    mSelectedRight + mSelectedDateVerticalBarWidth / 2,
+                    mHeight);
+            mSelectedDateVerticalBar.draw(canvas);
+        }
+
+        @Override
+        protected void onSizeChanged(int w, int h, int oldw, int oldh) {
+            mWidth = w;
+            updateSelectionPositions();
+        }
+
+        /**
+         * This calculates the positions for the selected day lines.
+         */
+        private void updateSelectionPositions() {
+            if (mHasSelectedDay) {
+                final boolean isLayoutRtl = isLayoutRtl();
+                int selectedPosition = mSelectedDay - mFirstDayOfWeek;
+                if (selectedPosition < 0) {
+                    selectedPosition += 7;
+                }
+                if (mShowWeekNumber && !isLayoutRtl) {
+                    selectedPosition++;
+                }
+                if (isLayoutRtl) {
+                    mSelectedLeft = (mDaysPerWeek - 1 - selectedPosition) * mWidth / mNumCells;
+
+                } else {
+                    mSelectedLeft = selectedPosition * mWidth / mNumCells;
+                }
+                mSelectedRight = mSelectedLeft + mWidth / mNumCells;
+            }
+        }
+
+        @Override
+        protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
+            mHeight = (mListView.getHeight() - mListView.getPaddingTop() - mListView
+                    .getPaddingBottom()) / mShownWeekCount;
+            setMeasuredDimension(MeasureSpec.getSize(widthMeasureSpec), mHeight);
+        }
+    }
+
+}
diff --git a/core/java/android/widget/CalendarViewMaterialDelegate.java b/core/java/android/widget/CalendarViewMaterialDelegate.java
new file mode 100644
index 0000000..b0f3740
--- /dev/null
+++ b/core/java/android/widget/CalendarViewMaterialDelegate.java
@@ -0,0 +1,260 @@
+/*
+ * Copyright (C) 2014 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 com.android.internal.R;
+
+import android.content.Context;
+import android.content.res.Configuration;
+import android.content.res.TypedArray;
+import android.graphics.drawable.Drawable;
+import android.text.TextUtils;
+import android.util.AttributeSet;
+import android.util.MathUtils;
+
+import java.util.Calendar;
+import java.util.Locale;
+
+import libcore.icu.LocaleData;
+
+class CalendarViewMaterialDelegate extends CalendarView.AbstractCalendarViewDelegate {
+    private final DayPickerView mDayPickerView;
+
+    private CalendarView.OnDateChangeListener mOnDateChangeListener;
+
+    public CalendarViewMaterialDelegate(CalendarView delegator, Context context, AttributeSet attrs,
+            int defStyleAttr, int defStyleRes) {
+        super(delegator, context);
+
+        final TypedArray a = context.obtainStyledAttributes(attrs,
+                R.styleable.CalendarView, defStyleAttr, defStyleRes);
+        final int firstDayOfWeek = a.getInt(R.styleable.CalendarView_firstDayOfWeek,
+                LocaleData.get(Locale.getDefault()).firstDayOfWeek);
+
+        final long minDate = parseDateToMillis(a.getString(
+                R.styleable.CalendarView_minDate), DEFAULT_MIN_DATE);
+        final long maxDate = parseDateToMillis(a.getString(
+                R.styleable.CalendarView_maxDate), DEFAULT_MAX_DATE);
+        if (maxDate < minDate) {
+            throw new IllegalArgumentException("max date cannot be before min date");
+        }
+
+        final long setDate = MathUtils.constrain(System.currentTimeMillis(), minDate, maxDate);
+        final int dateTextAppearanceResId = a.getResourceId(
+                R.styleable.CalendarView_dateTextAppearance,
+                R.style.TextAppearance_DeviceDefault_Small);
+
+        a.recycle();
+
+        mDayPickerView = new DayPickerView(context);
+        mDayPickerView.setFirstDayOfWeek(firstDayOfWeek);
+        mDayPickerView.setCalendarTextAppearance(dateTextAppearanceResId);
+        mDayPickerView.setMinDate(minDate);
+        mDayPickerView.setMaxDate(maxDate);
+        mDayPickerView.setDate(setDate, false, true);
+        mDayPickerView.setOnDaySelectedListener(mOnDaySelectedListener);
+
+        delegator.addView(mDayPickerView);
+    }
+
+    private long parseDateToMillis(String dateStr, String defaultDateStr) {
+        final Calendar tempCalendar = Calendar.getInstance();
+        if (TextUtils.isEmpty(dateStr) || !parseDate(dateStr, tempCalendar)) {
+            parseDate(defaultDateStr, tempCalendar);
+        }
+        return tempCalendar.getTimeInMillis();
+    }
+
+    @Override
+    public void setShownWeekCount(int count) {
+        // Deprecated.
+    }
+
+    @Override
+    public int getShownWeekCount() {
+        // Deprecated.
+        return 0;
+    }
+
+    @Override
+    public void setSelectedWeekBackgroundColor(int color) {
+        // TODO: Should use a ColorStateList. Deprecate?
+    }
+
+    @Override
+    public int getSelectedWeekBackgroundColor() {
+        return 0;
+    }
+
+    @Override
+    public void setFocusedMonthDateColor(int color) {
+        // TODO: Should use a ColorStateList. Deprecate?
+    }
+
+    @Override
+    public int getFocusedMonthDateColor() {
+        return 0;
+    }
+
+    @Override
+    public void setUnfocusedMonthDateColor(int color) {
+        // TODO: Should use a ColorStateList. Deprecate?
+    }
+
+    @Override
+    public int getUnfocusedMonthDateColor() {
+        return 0;
+    }
+
+    @Override
+    public void setWeekDayTextAppearance(int resourceId) {
+
+    }
+
+    @Override
+    public int getWeekDayTextAppearance() {
+        return 0;
+    }
+
+    @Override
+    public void setDateTextAppearance(int resourceId) {
+
+    }
+
+    @Override
+    public int getDateTextAppearance() {
+        return 0;
+    }
+
+    @Override
+    public void setWeekNumberColor(int color) {
+        // Deprecated.
+    }
+
+    @Override
+    public int getWeekNumberColor() {
+        // Deprecated.
+        return 0;
+    }
+
+    @Override
+    public void setWeekSeparatorLineColor(int color) {
+        // Deprecated.
+    }
+
+    @Override
+    public int getWeekSeparatorLineColor() {
+        // Deprecated.
+        return 0;
+    }
+
+    @Override
+    public void setSelectedDateVerticalBar(int resourceId) {
+        // Deprecated.
+    }
+
+    @Override
+    public void setSelectedDateVerticalBar(Drawable drawable) {
+        // Deprecated.
+    }
+
+    @Override
+    public Drawable getSelectedDateVerticalBar() {
+        // Deprecated.
+        return null;
+    }
+
+    @Override
+    public void setMinDate(long minDate) {
+        mDayPickerView.setMinDate(minDate);
+    }
+
+    @Override
+    public long getMinDate() {
+        return mDayPickerView.getMinDate();
+    }
+
+    @Override
+    public void setMaxDate(long maxDate) {
+        mDayPickerView.setMaxDate(maxDate);
+    }
+
+    @Override
+    public long getMaxDate() {
+        return mDayPickerView.getMaxDate();
+    }
+
+    @Override
+    public void setShowWeekNumber(boolean showWeekNumber) {
+        // Deprecated.
+    }
+
+    @Override
+    public boolean getShowWeekNumber() {
+        // Deprecated.
+        return false;
+    }
+
+    @Override
+    public void setFirstDayOfWeek(int firstDayOfWeek) {
+        mDayPickerView.setFirstDayOfWeek(firstDayOfWeek);
+    }
+
+    @Override
+    public int getFirstDayOfWeek() {
+        return mDayPickerView.getFirstDayOfWeek();
+    }
+
+    @Override
+    public void setDate(long date) {
+        mDayPickerView.setDate(date, true, false);
+    }
+
+    @Override
+    public void setDate(long date, boolean animate, boolean center) {
+        mDayPickerView.setDate(date, animate, center);
+    }
+
+    @Override
+    public long getDate() {
+        return mDayPickerView.getDate();
+    }
+
+    @Override
+    public void setOnDateChangeListener(CalendarView.OnDateChangeListener listener) {
+        mOnDateChangeListener = listener;
+    }
+
+    @Override
+    public void onConfigurationChanged(Configuration newConfig) {
+        // Nothing to do here, configuration changes are already propagated
+        // by ViewGroup.
+    }
+
+    private final DayPickerView.OnDaySelectedListener mOnDaySelectedListener =
+            new DayPickerView.OnDaySelectedListener() {
+        @Override
+        public void onDaySelected(DayPickerView view, Calendar day) {
+            if (mOnDateChangeListener != null) {
+                final int year = day.get(Calendar.YEAR);
+                final int month = day.get(Calendar.MONTH);
+                final int dayOfMonth = day.get(Calendar.DAY_OF_MONTH);
+                mOnDateChangeListener.onSelectedDayChange(mDelegator, year, month, dayOfMonth);
+            }
+        }
+    };
+}
diff --git a/core/java/android/widget/DatePickerCalendarDelegate.java b/core/java/android/widget/DatePickerCalendarDelegate.java
index cf3dbab..820bf78 100644
--- a/core/java/android/widget/DatePickerCalendarDelegate.java
+++ b/core/java/android/widget/DatePickerCalendarDelegate.java
@@ -185,8 +185,9 @@
 
         mDayPickerView = new DayPickerView(mContext);
         mDayPickerView.setFirstDayOfWeek(mFirstDayOfWeek);
-        mDayPickerView.setRange(mMinDate, mMaxDate);
-        mDayPickerView.setDay(mCurrentDate);
+        mDayPickerView.setMinDate(mMinDate.getTimeInMillis());
+        mDayPickerView.setMaxDate(mMaxDate.getTimeInMillis());
+        mDayPickerView.setDate(mCurrentDate.getTimeInMillis());
         mDayPickerView.setOnDaySelectedListener(mOnDaySelectedListener);
 
         mYearPickerView = new YearPickerView(mContext);
@@ -336,7 +337,7 @@
 
         switch (viewIndex) {
             case MONTH_AND_DAY_VIEW:
-                mDayPickerView.setDay(getSelectedDay());
+                mDayPickerView.setDate(getSelectedDay().getTimeInMillis());
                 if (mCurrentView != viewIndex) {
                     mMonthAndDayLayout.setSelected(true);
                     mHeaderYearTextView.setSelected(false);
@@ -414,7 +415,7 @@
             updateDisplay(false);
         }
         mMinDate.setTimeInMillis(minDate);
-        mDayPickerView.setRange(mMinDate, mMaxDate);
+        mDayPickerView.setMinDate(minDate);
         mYearPickerView.setRange(mMinDate, mMaxDate);
     }
 
@@ -436,7 +437,7 @@
             updateDisplay(false);
         }
         mMaxDate.setTimeInMillis(maxDate);
-        mDayPickerView.setRange(mMinDate, mMaxDate);
+        mDayPickerView.setMaxDate(maxDate);
         mYearPickerView.setRange(mMinDate, mMaxDate);
     }
 
@@ -616,7 +617,7 @@
             listener.onDateChanged();
         }
 
-        mDayPickerView.setDay(getSelectedDay());
+        mDayPickerView.setDate(getSelectedDay().getTimeInMillis());
     }
 
     @Override
diff --git a/core/java/android/widget/DayPickerView.java b/core/java/android/widget/DayPickerView.java
index 6cb1c9d..7db3fb9 100644
--- a/core/java/android/widget/DayPickerView.java
+++ b/core/java/android/widget/DayPickerView.java
@@ -58,6 +58,8 @@
     private Calendar mMinDate = Calendar.getInstance();
     private Calendar mMaxDate = Calendar.getInstance();
 
+    private Calendar mTempCalendar;
+
     private OnDaySelectedListener mOnDaySelectedListener;
 
     // which month should be displayed/highlighted [0-11]
@@ -77,28 +79,65 @@
         setDrawSelectorOnTop(false);
         setUpListView();
 
-        goTo(mSelectedDay, false, true, true);
+        goTo(mSelectedDay.getTimeInMillis(), false, false, true);
 
         mAdapter.setOnDaySelectedListener(mProxyOnDaySelectedListener);
     }
 
-    public void setDay(Calendar day) {
-        goTo(day, false, true, true);
+    /**
+     * Sets the currently selected date to the specified timestamp. Jumps
+     * immediately to the new date. To animate to the new date, use
+     * {@link #setDate(long, boolean, boolean)}.
+     *
+     * @param timeInMillis
+     */
+    public void setDate(long timeInMillis) {
+        setDate(timeInMillis, false, true);
+    }
+
+    public void setDate(long timeInMillis, boolean animate, boolean forceScroll) {
+        goTo(timeInMillis, animate, true, forceScroll);
+    }
+
+    public long getDate() {
+        return mSelectedDay.getTimeInMillis();
     }
 
     public void setFirstDayOfWeek(int firstDayOfWeek) {
         mAdapter.setFirstDayOfWeek(firstDayOfWeek);
     }
 
-    public void setRange(Calendar minDate, Calendar maxDate) {
-        mMinDate.setTimeInMillis(minDate.getTimeInMillis());
-        mMaxDate.setTimeInMillis(maxDate.getTimeInMillis());
+    public int getFirstDayOfWeek() {
+        return mAdapter.getFirstDayOfWeek();
+    }
 
+    public void setMinDate(long timeInMillis) {
+        mMinDate.setTimeInMillis(timeInMillis);
+        onRangeChanged();
+    }
+
+    public long getMinDate() {
+        return mMinDate.getTimeInMillis();
+    }
+
+    public void setMaxDate(long timeInMillis) {
+        mMaxDate.setTimeInMillis(timeInMillis);
+        onRangeChanged();
+    }
+
+    public long getMaxDate() {
+        return mMaxDate.getTimeInMillis();
+    }
+
+    /**
+     * Handles changes to date range.
+     */
+    public void onRangeChanged() {
         mAdapter.setRange(mMinDate, mMaxDate);
 
         // Changing the min/max date changes the selection position since we
-        // don't really have stable IDs.
-        goTo(mSelectedDay, false, true, true);
+        // don't really have stable IDs. Jumps immediately to the new position.
+        goTo(mSelectedDay.getTimeInMillis(), false, false, true);
     }
 
     /**
@@ -136,12 +175,20 @@
         return diffMonths;
     }
 
-    private int getPositionFromDay(Calendar day) {
+    private int getPositionFromDay(long timeInMillis) {
         final int diffMonthMax = getDiffMonths(mMinDate, mMaxDate);
-        final int diffMonth = getDiffMonths(mMinDate, day);
+        final int diffMonth = getDiffMonths(mMinDate, getTempCalendarForTime(timeInMillis));
         return MathUtils.constrain(diffMonth, 0, diffMonthMax);
     }
 
+    private Calendar getTempCalendarForTime(long timeInMillis) {
+        if (mTempCalendar == null) {
+            mTempCalendar = Calendar.getInstance();
+        }
+        mTempCalendar.setTimeInMillis(timeInMillis);
+        return mTempCalendar;
+    }
+
     /**
      * This moves to the specified time in the view. If the time is not already
      * in range it will move the list so that the first of the month containing
@@ -157,14 +204,14 @@
      *            visible
      * @return Whether or not the view animated to the new location
      */
-    private boolean goTo(Calendar day, boolean animate, boolean setSelected, boolean forceScroll) {
+    private boolean goTo(long day, boolean animate, boolean setSelected, boolean forceScroll) {
 
         // Set the selected day
         if (setSelected) {
-            mSelectedDay.setTimeInMillis(day.getTimeInMillis());
+            mSelectedDay.setTimeInMillis(day);
         }
 
-        mTempDay.setTimeInMillis(day.getTimeInMillis());
+        mTempDay.setTimeInMillis(day);
         final int position = getPositionFromDay(day);
 
         View child;
@@ -258,6 +305,10 @@
         mAdapter.setCalendarTextColor(colors);
     }
 
+    void setCalendarTextAppearance(int resId) {
+        mAdapter.setCalendarTextAppearance(resId);
+    }
+
     protected class ScrollStateRunnable implements Runnable {
         private int mNewState;
         private View mParent;
@@ -415,7 +466,7 @@
     }
 
     private String getMonthAndYearString(Calendar day) {
-        StringBuffer sbuf = new StringBuffer();
+        final StringBuilder sbuf = new StringBuilder();
         sbuf.append(day.getDisplayName(Calendar.MONTH, Calendar.LONG, Locale.getDefault()));
         sbuf.append(" ");
         sbuf.append(mYearFormat.format(day.getTime()));
@@ -429,8 +480,8 @@
     @Override
     public void onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo info) {
         super.onInitializeAccessibilityNodeInfo(info);
-        info.addAction(AccessibilityNodeInfo.ACTION_SCROLL_FORWARD);
-        info.addAction(AccessibilityNodeInfo.ACTION_SCROLL_BACKWARD);
+        info.addAction(AccessibilityNodeInfo.AccessibilityAction.ACTION_SCROLL_FORWARD);
+        info.addAction(AccessibilityNodeInfo.AccessibilityAction.ACTION_SCROLL_BACKWARD);
     }
 
     /**
@@ -474,7 +525,7 @@
 
         // Go to that month.
         announceForAccessibility(getMonthAndYearString(day));
-        goTo(day, true, false, true);
+        goTo(day.getTimeInMillis(), true, false, true);
         mPerformingScroll = true;
         return true;
     }
diff --git a/core/java/android/widget/FastScroller.java b/core/java/android/widget/FastScroller.java
index 0687905..06bb32c 100644
--- a/core/java/android/widget/FastScroller.java
+++ b/core/java/android/widget/FastScroller.java
@@ -1194,17 +1194,37 @@
         return MathUtils.constrain((y - offset) / range, 0f, 1f);
     }
 
+    /**
+     * Calculates the thumb position based on the visible items.
+     *
+     * @param firstVisibleItem First visible item, >= 0.
+     * @param visibleItemCount Number of visible items, >= 0.
+     * @param totalItemCount Total number of items, >= 0.
+     * @return
+     */
     private float getPosFromItemCount(
             int firstVisibleItem, int visibleItemCount, int totalItemCount) {
-        if (mSectionIndexer == null || mListAdapter == null) {
+        final SectionIndexer sectionIndexer = mSectionIndexer;
+        if (sectionIndexer == null || mListAdapter == null) {
             getSectionsFromIndexer();
         }
 
-        final boolean hasSections = mSectionIndexer != null && mSections != null
+        if (visibleItemCount == 0 || totalItemCount == 0) {
+            // No items are visible.
+            return 0;
+        }
+
+        final boolean hasSections = sectionIndexer != null && mSections != null
                 && mSections.length > 0;
         if (!hasSections || !mMatchDragPosition) {
-            return (float) firstVisibleItem / (totalItemCount - visibleItemCount);
+            if (visibleItemCount == totalItemCount) {
+                // All items are visible.
+                return 0;
+            } else {
+                return (float) firstVisibleItem / (totalItemCount - visibleItemCount);
+            }
         }
+
         // Ignore headers.
         firstVisibleItem -= mHeaderCount;
         if (firstVisibleItem < 0) {
@@ -1222,14 +1242,14 @@
         }
 
         // Number of rows in this section.
-        final int section = mSectionIndexer.getSectionForPosition(firstVisibleItem);
-        final int sectionPos = mSectionIndexer.getPositionForSection(section);
+        final int section = sectionIndexer.getSectionForPosition(firstVisibleItem);
+        final int sectionPos = sectionIndexer.getPositionForSection(section);
         final int sectionCount = mSections.length;
         final int positionsInSection;
         if (section < sectionCount - 1) {
             final int nextSectionPos;
             if (section + 1 < sectionCount) {
-                nextSectionPos = mSectionIndexer.getPositionForSection(section + 1);
+                nextSectionPos = sectionIndexer.getPositionForSection(section + 1);
             } else {
                 nextSectionPos = totalItemCount - 1;
             }
diff --git a/core/java/android/widget/RadialTimePickerView.java b/core/java/android/widget/RadialTimePickerView.java
index 24fc2bb..8b01dde 100644
--- a/core/java/android/widget/RadialTimePickerView.java
+++ b/core/java/android/widget/RadialTimePickerView.java
@@ -452,7 +452,10 @@
     }
 
     public void initialize(int hour, int minute, boolean is24HourMode) {
-        mIs24HourMode = is24HourMode;
+        if (mIs24HourMode != is24HourMode) {
+            mIs24HourMode = is24HourMode;
+            initData();
+        }
 
         setCurrentHourInternal(hour, false, false);
         setCurrentMinuteInternal(minute, false);
diff --git a/core/java/android/widget/SearchView.java b/core/java/android/widget/SearchView.java
index dfdf606..4ee6418 100644
--- a/core/java/android/widget/SearchView.java
+++ b/core/java/android/widget/SearchView.java
@@ -45,7 +45,6 @@
 import android.text.style.ImageSpan;
 import android.util.AttributeSet;
 import android.util.Log;
-import android.util.TypedValue;
 import android.view.CollapsibleActionView;
 import android.view.KeyEvent;
 import android.view.LayoutInflater;
@@ -99,17 +98,21 @@
      */
     private static final String IME_OPTION_NO_MICROPHONE = "nm";
 
-    private final SearchAutoComplete mQueryTextView;
+    private final SearchAutoComplete mSearchSrcTextView;
     private final View mSearchEditFrame;
     private final View mSearchPlate;
     private final View mSubmitArea;
     private final ImageView mSearchButton;
-    private final ImageView mSubmitButton;
+    private final ImageView mGoButton;
     private final ImageView mCloseButton;
     private final ImageView mVoiceButton;
-    private final ImageView mSearchHintIcon;
     private final View mDropDownAnchor;
-    private final int mSearchIconResId;
+
+    /** Icon optionally displayed when the SearchView is collapsed. */
+    private final ImageView mCollapsedIcon;
+
+    /** Drawable used as an EditText hint. */
+    private final Drawable mSearchHintIcon;
 
     // Resources used by SuggestionsAdapter to display suggestions.
     private final int mSuggestionRowLayout;
@@ -262,30 +265,38 @@
                 attrs, R.styleable.SearchView, defStyleAttr, defStyleRes);
         final LayoutInflater inflater = (LayoutInflater) context.getSystemService(
                 Context.LAYOUT_INFLATER_SERVICE);
-        final int layoutResId = a.getResourceId(R.styleable.SearchView_layout, R.layout.search_view);
+        final int layoutResId = a.getResourceId(
+                R.styleable.SearchView_layout, R.layout.search_view);
         inflater.inflate(layoutResId, this, true);
 
-        mQueryTextView = (SearchAutoComplete) findViewById(R.id.search_src_text);
-        mQueryTextView.setSearchView(this);
+        mSearchSrcTextView = (SearchAutoComplete) findViewById(R.id.search_src_text);
+        mSearchSrcTextView.setSearchView(this);
 
         mSearchEditFrame = findViewById(R.id.search_edit_frame);
         mSearchPlate = findViewById(R.id.search_plate);
         mSubmitArea = findViewById(R.id.submit_area);
         mSearchButton = (ImageView) findViewById(R.id.search_button);
-        mSubmitButton = (ImageView) findViewById(R.id.search_go_btn);
+        mGoButton = (ImageView) findViewById(R.id.search_go_btn);
         mCloseButton = (ImageView) findViewById(R.id.search_close_btn);
         mVoiceButton = (ImageView) findViewById(R.id.search_voice_btn);
-        mSearchHintIcon = (ImageView) findViewById(R.id.search_mag_icon);
+        mCollapsedIcon = (ImageView) findViewById(R.id.search_mag_icon);
 
         // Set up icons and backgrounds.
         mSearchPlate.setBackground(a.getDrawable(R.styleable.SearchView_queryBackground));
         mSubmitArea.setBackground(a.getDrawable(R.styleable.SearchView_submitBackground));
-        mSearchIconResId = a.getResourceId(R.styleable.SearchView_searchIcon, 0);
-        mSearchButton.setImageResource(mSearchIconResId);
-        mSubmitButton.setImageDrawable(a.getDrawable(R.styleable.SearchView_goIcon));
+        mSearchButton.setImageDrawable(a.getDrawable(R.styleable.SearchView_searchIcon));
+        mGoButton.setImageDrawable(a.getDrawable(R.styleable.SearchView_goIcon));
         mCloseButton.setImageDrawable(a.getDrawable(R.styleable.SearchView_closeIcon));
         mVoiceButton.setImageDrawable(a.getDrawable(R.styleable.SearchView_voiceIcon));
-        mSearchHintIcon.setImageDrawable(a.getDrawable(R.styleable.SearchView_searchIcon));
+        mCollapsedIcon.setImageDrawable(a.getDrawable(R.styleable.SearchView_searchIcon));
+
+        // Prior to L MR1, the search hint icon defaulted to searchIcon. If the
+        // style does not have an explicit value set, fall back to that.
+        if (a.hasValueOrEmpty(R.styleable.SearchView_searchHintIcon)) {
+            mSearchHintIcon = a.getDrawable(R.styleable.SearchView_searchHintIcon);
+        } else {
+            mSearchHintIcon = a.getDrawable(R.styleable.SearchView_searchIcon);
+        }
 
         // Extract dropdown layout resource IDs for later use.
         mSuggestionRowLayout = a.getResourceId(R.styleable.SearchView_suggestionRowLayout,
@@ -294,18 +305,18 @@
 
         mSearchButton.setOnClickListener(mOnClickListener);
         mCloseButton.setOnClickListener(mOnClickListener);
-        mSubmitButton.setOnClickListener(mOnClickListener);
+        mGoButton.setOnClickListener(mOnClickListener);
         mVoiceButton.setOnClickListener(mOnClickListener);
-        mQueryTextView.setOnClickListener(mOnClickListener);
+        mSearchSrcTextView.setOnClickListener(mOnClickListener);
 
-        mQueryTextView.addTextChangedListener(mTextWatcher);
-        mQueryTextView.setOnEditorActionListener(mOnEditorActionListener);
-        mQueryTextView.setOnItemClickListener(mOnItemClickListener);
-        mQueryTextView.setOnItemSelectedListener(mOnItemSelectedListener);
-        mQueryTextView.setOnKeyListener(mTextKeyListener);
+        mSearchSrcTextView.addTextChangedListener(mTextWatcher);
+        mSearchSrcTextView.setOnEditorActionListener(mOnEditorActionListener);
+        mSearchSrcTextView.setOnItemClickListener(mOnItemClickListener);
+        mSearchSrcTextView.setOnItemSelectedListener(mOnItemSelectedListener);
+        mSearchSrcTextView.setOnKeyListener(mTextKeyListener);
 
         // Inform any listener of focus changes
-        mQueryTextView.setOnFocusChangeListener(new OnFocusChangeListener() {
+        mSearchSrcTextView.setOnFocusChangeListener(new OnFocusChangeListener() {
 
             public void onFocusChange(View v, boolean hasFocus) {
                 if (mOnQueryTextFocusChangeListener != null) {
@@ -350,7 +361,7 @@
         mVoiceAppSearchIntent = new Intent(RecognizerIntent.ACTION_RECOGNIZE_SPEECH);
         mVoiceAppSearchIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
 
-        mDropDownAnchor = findViewById(mQueryTextView.getDropDownAnchor());
+        mDropDownAnchor = findViewById(mSearchSrcTextView.getDropDownAnchor());
         if (mDropDownAnchor != null) {
             mDropDownAnchor.addOnLayoutChangeListener(new OnLayoutChangeListener() {
                 @Override
@@ -393,7 +404,7 @@
         if (mVoiceButtonEnabled) {
             // Disable the microphone on the keyboard, as a mic is displayed near the text box
             // TODO: use imeOptions to disable voice input when the new API will be available
-            mQueryTextView.setPrivateImeOptions(IME_OPTION_NO_MICROPHONE);
+            mSearchSrcTextView.setPrivateImeOptions(IME_OPTION_NO_MICROPHONE);
         }
         updateViewsVisibility(isIconified());
     }
@@ -416,7 +427,7 @@
      * @attr ref android.R.styleable#SearchView_imeOptions
      */
     public void setImeOptions(int imeOptions) {
-        mQueryTextView.setImeOptions(imeOptions);
+        mSearchSrcTextView.setImeOptions(imeOptions);
     }
 
     /**
@@ -427,7 +438,7 @@
      * @attr ref android.R.styleable#SearchView_imeOptions
      */
     public int getImeOptions() {
-        return mQueryTextView.getImeOptions();
+        return mSearchSrcTextView.getImeOptions();
     }
 
     /**
@@ -439,7 +450,7 @@
      * @attr ref android.R.styleable#SearchView_inputType
      */
     public void setInputType(int inputType) {
-        mQueryTextView.setInputType(inputType);
+        mSearchSrcTextView.setInputType(inputType);
     }
 
     /**
@@ -449,7 +460,7 @@
      * @attr ref android.R.styleable#SearchView_inputType
      */
     public int getInputType() {
-        return mQueryTextView.getInputType();
+        return mSearchSrcTextView.getInputType();
     }
 
     /** @hide */
@@ -461,7 +472,7 @@
         if (!isFocusable()) return false;
         // If it is not iconified, then give the focus to the text field
         if (!isIconified()) {
-            boolean result = mQueryTextView.requestFocus(direction, previouslyFocusedRect);
+            boolean result = mSearchSrcTextView.requestFocus(direction, previouslyFocusedRect);
             if (result) {
                 updateViewsVisibility(false);
             }
@@ -477,7 +488,7 @@
         mClearingFocus = true;
         setImeVisibility(false);
         super.clearFocus();
-        mQueryTextView.clearFocus();
+        mSearchSrcTextView.clearFocus();
         mClearingFocus = false;
     }
 
@@ -536,7 +547,7 @@
      * @return the query string
      */
     public CharSequence getQuery() {
-        return mQueryTextView.getText();
+        return mSearchSrcTextView.getText();
     }
 
     /**
@@ -548,9 +559,9 @@
      * text field.
      */
     public void setQuery(CharSequence query, boolean submit) {
-        mQueryTextView.setText(query);
+        mSearchSrcTextView.setText(query);
         if (query != null) {
-            mQueryTextView.setSelection(mQueryTextView.length());
+            mSearchSrcTextView.setSelection(mSearchSrcTextView.length());
             mUserQuery = query;
         }
 
@@ -711,7 +722,7 @@
     public void setSuggestionsAdapter(CursorAdapter adapter) {
         mSuggestionsAdapter = adapter;
 
-        mQueryTextView.setAdapter(mSuggestionsAdapter);
+        mSearchSrcTextView.setAdapter(mSuggestionsAdapter);
     }
 
     /**
@@ -789,12 +800,12 @@
         // Visibility of views that are visible when collapsed
         final int visCollapsed = collapsed ? VISIBLE : GONE;
         // Is there text in the query
-        final boolean hasText = !TextUtils.isEmpty(mQueryTextView.getText());
+        final boolean hasText = !TextUtils.isEmpty(mSearchSrcTextView.getText());
 
         mSearchButton.setVisibility(visCollapsed);
         updateSubmitButton(hasText);
         mSearchEditFrame.setVisibility(collapsed ? GONE : VISIBLE);
-        mSearchHintIcon.setVisibility(mIconifiedByDefault ? GONE : VISIBLE);
+        mCollapsedIcon.setVisibility(mIconifiedByDefault ? GONE : VISIBLE);
         updateCloseButton();
         updateVoiceButton(!hasText);
         updateSubmitArea();
@@ -827,13 +838,13 @@
                 && (hasText || !mVoiceButtonEnabled)) {
             visibility = VISIBLE;
         }
-        mSubmitButton.setVisibility(visibility);
+        mGoButton.setVisibility(visibility);
     }
 
     private void updateSubmitArea() {
         int visibility = GONE;
         if (isSubmitAreaEnabled()
-                && (mSubmitButton.getVisibility() == VISIBLE
+                && (mGoButton.getVisibility() == VISIBLE
                         || mVoiceButton.getVisibility() == VISIBLE)) {
             visibility = VISIBLE;
         }
@@ -841,12 +852,15 @@
     }
 
     private void updateCloseButton() {
-        final boolean hasText = !TextUtils.isEmpty(mQueryTextView.getText());
+        final boolean hasText = !TextUtils.isEmpty(mSearchSrcTextView.getText());
         // Should we show the close button? It is not shown if there's no focus,
         // field is not iconified by default and there is no text in it.
         final boolean showClose = hasText || (mIconifiedByDefault && !mExpandedInActionView);
         mCloseButton.setVisibility(showClose ? VISIBLE : GONE);
-        mCloseButton.getDrawable().setState(hasText ? ENABLED_STATE_SET : EMPTY_STATE_SET);
+        final Drawable closeButtonImg = mCloseButton.getDrawable();
+        if (closeButtonImg != null){
+            closeButtonImg.setState(hasText ? ENABLED_STATE_SET : EMPTY_STATE_SET);
+        }
     }
 
     private void postUpdateFocusedState() {
@@ -854,9 +868,16 @@
     }
 
     private void updateFocusedState() {
-        boolean focused = mQueryTextView.hasFocus();
-        mSearchPlate.getBackground().setState(focused ? FOCUSED_STATE_SET : EMPTY_STATE_SET);
-        mSubmitArea.getBackground().setState(focused ? FOCUSED_STATE_SET : EMPTY_STATE_SET);
+        final boolean focused = mSearchSrcTextView.hasFocus();
+        final int[] stateSet = focused ? FOCUSED_STATE_SET : EMPTY_STATE_SET;
+        final Drawable searchPlateBg = mSearchPlate.getBackground();
+        if (searchPlateBg != null) {
+            searchPlateBg.setState(stateSet);
+        }
+        final Drawable submitAreaBg = mSubmitArea.getBackground();
+        if (submitAreaBg != null) {
+            submitAreaBg.setState(stateSet);
+        }
         invalidate();
     }
 
@@ -896,11 +917,11 @@
                 onSearchClicked();
             } else if (v == mCloseButton) {
                 onCloseClicked();
-            } else if (v == mSubmitButton) {
+            } else if (v == mGoButton) {
                 onSubmitQuery();
             } else if (v == mVoiceButton) {
                 onVoiceClicked();
-            } else if (v == mQueryTextView) {
+            } else if (v == mSearchSrcTextView) {
                 forceSuggestionQuery();
             }
         }
@@ -925,7 +946,7 @@
         // entered query with the action key
         SearchableInfo.ActionKeyInfo actionKey = mSearchable.findActionKey(keyCode);
         if ((actionKey != null) && (actionKey.getQueryActionMsg() != null)) {
-            launchQuerySearch(keyCode, actionKey.getQueryActionMsg(), mQueryTextView.getText()
+            launchQuerySearch(keyCode, actionKey.getQueryActionMsg(), mSearchSrcTextView.getText()
                     .toString());
             return true;
         }
@@ -947,25 +968,25 @@
 
             if (DBG) {
                 Log.d(LOG_TAG, "mTextListener.onKey(" + keyCode + "," + event + "), selection: "
-                        + mQueryTextView.getListSelection());
+                        + mSearchSrcTextView.getListSelection());
             }
 
             // If a suggestion is selected, handle enter, search key, and action keys
             // as presses on the selected suggestion
-            if (mQueryTextView.isPopupShowing()
-                    && mQueryTextView.getListSelection() != ListView.INVALID_POSITION) {
+            if (mSearchSrcTextView.isPopupShowing()
+                    && mSearchSrcTextView.getListSelection() != ListView.INVALID_POSITION) {
                 return onSuggestionsKey(v, keyCode, event);
             }
 
             // If there is text in the query box, handle enter, and action keys
             // The search key is handled by the dialog's onKeyDown().
-            if (!mQueryTextView.isEmpty() && event.hasNoModifiers()) {
+            if (!mSearchSrcTextView.isEmpty() && event.hasNoModifiers()) {
                 if (event.getAction() == KeyEvent.ACTION_UP) {
                     if (keyCode == KeyEvent.KEYCODE_ENTER) {
                         v.cancelLongPress();
 
                         // Launch as a regular search.
-                        launchQuerySearch(KeyEvent.KEYCODE_UNKNOWN, null, mQueryTextView.getText()
+                        launchQuerySearch(KeyEvent.KEYCODE_UNKNOWN, null, mSearchSrcTextView.getText()
                                 .toString());
                         return true;
                     }
@@ -973,7 +994,7 @@
                 if (event.getAction() == KeyEvent.ACTION_DOWN) {
                     SearchableInfo.ActionKeyInfo actionKey = mSearchable.findActionKey(keyCode);
                     if ((actionKey != null) && (actionKey.getQueryActionMsg() != null)) {
-                        launchQuerySearch(keyCode, actionKey.getQueryActionMsg(), mQueryTextView
+                        launchQuerySearch(keyCode, actionKey.getQueryActionMsg(), mSearchSrcTextView
                                 .getText().toString());
                         return true;
                     }
@@ -1001,7 +1022,7 @@
             // "click")
             if (keyCode == KeyEvent.KEYCODE_ENTER || keyCode == KeyEvent.KEYCODE_SEARCH
                     || keyCode == KeyEvent.KEYCODE_TAB) {
-                int position = mQueryTextView.getListSelection();
+                int position = mSearchSrcTextView.getListSelection();
                 return onItemClicked(position, KeyEvent.KEYCODE_UNKNOWN, null);
             }
 
@@ -1012,18 +1033,18 @@
                 // left key, at end if right key
                 // TODO: Reverse left/right for right-to-left languages, e.g.
                 // Arabic
-                int selPoint = (keyCode == KeyEvent.KEYCODE_DPAD_LEFT) ? 0 : mQueryTextView
+                int selPoint = (keyCode == KeyEvent.KEYCODE_DPAD_LEFT) ? 0 : mSearchSrcTextView
                         .length();
-                mQueryTextView.setSelection(selPoint);
-                mQueryTextView.setListSelection(0);
-                mQueryTextView.clearListSelection();
-                mQueryTextView.ensureImeVisible(true);
+                mSearchSrcTextView.setSelection(selPoint);
+                mSearchSrcTextView.setListSelection(0);
+                mSearchSrcTextView.clearListSelection();
+                mSearchSrcTextView.ensureImeVisible(true);
 
                 return true;
             }
 
             // Next, check for an "up and out" move
-            if (keyCode == KeyEvent.KEYCODE_DPAD_UP && 0 == mQueryTextView.getListSelection()) {
+            if (keyCode == KeyEvent.KEYCODE_DPAD_UP && 0 == mSearchSrcTextView.getListSelection()) {
                 // TODO: restoreUserQuery();
                 // let ACTV complete the move
                 return false;
@@ -1035,7 +1056,7 @@
                     && ((actionKey.getSuggestActionMsg() != null) || (actionKey
                             .getSuggestActionMsgColumn() != null))) {
                 // launch suggestion using action key column
-                int position = mQueryTextView.getListSelection();
+                int position = mSearchSrcTextView.getListSelection();
                 if (position != ListView.INVALID_POSITION) {
                     Cursor c = mSuggestionsAdapter.getCursor();
                     if (c.moveToPosition(position)) {
@@ -1078,24 +1099,24 @@
     }
 
     private CharSequence getDecoratedHint(CharSequence hintText) {
-        // If the field is always expanded, then don't add the search icon to the hint
-        if (!mIconifiedByDefault) {
+        // If the field is always expanded or we don't have a search hint icon,
+        // then don't add the search icon to the hint.
+        if (!mIconifiedByDefault || mSearchHintIcon == null) {
             return hintText;
         }
 
-        final Drawable searchIcon = getContext().getDrawable(mSearchIconResId);
-        final int textSize = (int) (mQueryTextView.getTextSize() * 1.25);
-        searchIcon.setBounds(0, 0, textSize, textSize);
+        final int textSize = (int) (mSearchSrcTextView.getTextSize() * 1.25);
+        mSearchHintIcon.setBounds(0, 0, textSize, textSize);
 
-        final SpannableStringBuilder ssb = new SpannableStringBuilder("   "); // for the icon
+        final SpannableStringBuilder ssb = new SpannableStringBuilder("   ");
+        ssb.setSpan(new ImageSpan(mSearchHintIcon), 1, 2, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
         ssb.append(hintText);
-        ssb.setSpan(new ImageSpan(searchIcon), 1, 2, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
         return ssb;
     }
 
     private void updateQueryHint() {
         if (mQueryHint != null) {
-            mQueryTextView.setHint(getDecoratedHint(mQueryHint));
+            mSearchSrcTextView.setHint(getDecoratedHint(mQueryHint));
         } else if (mSearchable != null) {
             CharSequence hint = null;
             int hintId = mSearchable.getHintId();
@@ -1103,10 +1124,10 @@
                 hint = getContext().getString(hintId);
             }
             if (hint != null) {
-                mQueryTextView.setHint(getDecoratedHint(hint));
+                mSearchSrcTextView.setHint(getDecoratedHint(hint));
             }
         } else {
-            mQueryTextView.setHint(getDecoratedHint(""));
+            mSearchSrcTextView.setHint(getDecoratedHint(""));
         }
     }
 
@@ -1114,9 +1135,9 @@
      * Updates the auto-complete text view.
      */
     private void updateSearchAutoComplete() {
-        mQueryTextView.setDropDownAnimationStyle(0); // no animation
-        mQueryTextView.setThreshold(mSearchable.getSuggestThreshold());
-        mQueryTextView.setImeOptions(mSearchable.getImeOptions());
+        mSearchSrcTextView.setDropDownAnimationStyle(0); // no animation
+        mSearchSrcTextView.setThreshold(mSearchable.getSuggestThreshold());
+        mSearchSrcTextView.setImeOptions(mSearchable.getImeOptions());
         int inputType = mSearchable.getInputType();
         // We only touch this if the input type is set up for text (which it almost certainly
         // should be, in the case of search!)
@@ -1135,7 +1156,7 @@
                 inputType |= InputType.TYPE_TEXT_FLAG_NO_SUGGESTIONS;
             }
         }
-        mQueryTextView.setInputType(inputType);
+        mSearchSrcTextView.setInputType(inputType);
         if (mSuggestionsAdapter != null) {
             mSuggestionsAdapter.changeCursor(null);
         }
@@ -1144,7 +1165,7 @@
         if (mSearchable.getSuggestAuthority() != null) {
             mSuggestionsAdapter = new SuggestionsAdapter(getContext(),
                     this, mSearchable, mOutsideDrawablesCache);
-            mQueryTextView.setAdapter(mSuggestionsAdapter);
+            mSearchSrcTextView.setAdapter(mSuggestionsAdapter);
             ((SuggestionsAdapter) mSuggestionsAdapter).setQueryRefinement(
                     mQueryRefinement ? SuggestionsAdapter.REFINE_ALL
                     : SuggestionsAdapter.REFINE_BY_ENTRY);
@@ -1161,7 +1182,7 @@
         int visibility = GONE;
         if (mVoiceButtonEnabled && !isIconified() && empty) {
             visibility = VISIBLE;
-            mSubmitButton.setVisibility(GONE);
+            mGoButton.setVisibility(GONE);
         }
         mVoiceButton.setVisibility(visibility);
     }
@@ -1178,7 +1199,7 @@
     };
 
     private void onTextChanged(CharSequence newText) {
-        CharSequence text = mQueryTextView.getText();
+        CharSequence text = mSearchSrcTextView.getText();
         mUserQuery = text;
         boolean hasText = !TextUtils.isEmpty(text);
         updateSubmitButton(hasText);
@@ -1192,7 +1213,7 @@
     }
 
     private void onSubmitQuery() {
-        CharSequence query = mQueryTextView.getText();
+        CharSequence query = mSearchSrcTextView.getText();
         if (query != null && TextUtils.getTrimmedLength(query) > 0) {
             if (mOnQueryChangeListener == null
                     || !mOnQueryChangeListener.onQueryTextSubmit(query.toString())) {
@@ -1206,11 +1227,11 @@
     }
 
     private void dismissSuggestions() {
-        mQueryTextView.dismissDropDown();
+        mSearchSrcTextView.dismissDropDown();
     }
 
     private void onCloseClicked() {
-        CharSequence text = mQueryTextView.getText();
+        CharSequence text = mSearchSrcTextView.getText();
         if (TextUtils.isEmpty(text)) {
             if (mIconifiedByDefault) {
                 // If the app doesn't override the close behavior
@@ -1222,8 +1243,8 @@
                 }
             }
         } else {
-            mQueryTextView.setText("");
-            mQueryTextView.requestFocus();
+            mSearchSrcTextView.setText("");
+            mSearchSrcTextView.requestFocus();
             setImeVisibility(true);
         }
 
@@ -1231,7 +1252,7 @@
 
     private void onSearchClicked() {
         updateViewsVisibility(false);
-        mQueryTextView.requestFocus();
+        mSearchSrcTextView.requestFocus();
         setImeVisibility(true);
         if (mOnSearchClickListener != null) {
             mOnSearchClickListener.onClick(this);
@@ -1266,7 +1287,7 @@
         // Delayed update to make sure that the focus has settled down and window focus changes
         // don't affect it. A synchronous update was not working.
         postUpdateFocusedState();
-        if (mQueryTextView.hasFocus()) {
+        if (mSearchSrcTextView.hasFocus()) {
             forceSuggestionQuery();
         }
     }
@@ -1286,7 +1307,7 @@
         setQuery("", false);
         clearFocus();
         updateViewsVisibility(true);
-        mQueryTextView.setImeOptions(mCollapsedImeOptions);
+        mSearchSrcTextView.setImeOptions(mCollapsedImeOptions);
         mExpandedInActionView = false;
     }
 
@@ -1298,9 +1319,9 @@
         if (mExpandedInActionView) return;
 
         mExpandedInActionView = true;
-        mCollapsedImeOptions = mQueryTextView.getImeOptions();
-        mQueryTextView.setImeOptions(mCollapsedImeOptions | EditorInfo.IME_FLAG_NO_FULLSCREEN);
-        mQueryTextView.setText("");
+        mCollapsedImeOptions = mSearchSrcTextView.getImeOptions();
+        mSearchSrcTextView.setImeOptions(mCollapsedImeOptions | EditorInfo.IME_FLAG_NO_FULLSCREEN);
+        mSearchSrcTextView.setText("");
         setIconified(false);
     }
 
@@ -1326,17 +1347,17 @@
                     ? res.getDimensionPixelSize(R.dimen.dropdownitem_icon_width)
                     + res.getDimensionPixelSize(R.dimen.dropdownitem_text_padding_left)
                     : 0;
-            mQueryTextView.getDropDownBackground().getPadding(dropDownPadding);
+            mSearchSrcTextView.getDropDownBackground().getPadding(dropDownPadding);
             int offset;
             if (isLayoutRtl) {
                 offset = - dropDownPadding.left;
             } else {
                 offset = anchorPadding - (dropDownPadding.left + iconOffset);
             }
-            mQueryTextView.setDropDownHorizontalOffset(offset);
+            mSearchSrcTextView.setDropDownHorizontalOffset(offset);
             final int width = mDropDownAnchor.getWidth() + dropDownPadding.left
                     + dropDownPadding.right + iconOffset - anchorPadding;
-            mQueryTextView.setDropDownWidth(width);
+            mSearchSrcTextView.setDropDownWidth(width);
         }
     }
 
@@ -1394,7 +1415,7 @@
      * Query rewriting.
      */
     private void rewriteQueryFromSuggestion(int position) {
-        CharSequence oldQuery = mQueryTextView.getText();
+        CharSequence oldQuery = mSearchSrcTextView.getText();
         Cursor c = mSuggestionsAdapter.getCursor();
         if (c == null) {
             return;
@@ -1460,9 +1481,9 @@
      * Sets the text in the query box, without updating the suggestions.
      */
     private void setQuery(CharSequence query) {
-        mQueryTextView.setText(query, true);
+        mSearchSrcTextView.setText(query, true);
         // Move the cursor to the end
-        mQueryTextView.setSelection(TextUtils.isEmpty(query) ? 0 : query.length());
+        mSearchSrcTextView.setSelection(TextUtils.isEmpty(query) ? 0 : query.length());
     }
 
     private void launchQuerySearch(int actionKey, String actionMsg, String query) {
@@ -1648,8 +1669,8 @@
     }
 
     private void forceSuggestionQuery() {
-        mQueryTextView.doBeforeTextChanged();
-        mQueryTextView.doAfterTextChanged();
+        mSearchSrcTextView.doBeforeTextChanged();
+        mSearchSrcTextView.doAfterTextChanged();
     }
 
     static boolean isLandscapeMode(Context context) {
diff --git a/core/java/android/widget/SimpleMonthAdapter.java b/core/java/android/widget/SimpleMonthAdapter.java
index ecd2912..24ebb2c 100644
--- a/core/java/android/widget/SimpleMonthAdapter.java
+++ b/core/java/android/widget/SimpleMonthAdapter.java
@@ -16,8 +16,12 @@
 
 package android.widget;
 
+import com.android.internal.R;
+
 import android.content.Context;
 import android.content.res.ColorStateList;
+import android.content.res.TypedArray;
+import android.graphics.Color;
 import android.view.View;
 import android.view.ViewGroup;
 import android.widget.SimpleMonthView.OnDayClickListener;
@@ -33,15 +37,14 @@
 
     private final Context mContext;
 
-    private Calendar mSelectedDay;
-    private ColorStateList mCalendarTextColors;
+    private Calendar mSelectedDay = Calendar.getInstance();
+    private ColorStateList mCalendarTextColors = ColorStateList.valueOf(Color.BLACK);
     private OnDaySelectedListener mOnDaySelectedListener;
 
     private int mFirstDayOfWeek;
 
     public SimpleMonthAdapter(Context context) {
         mContext = context;
-        mSelectedDay = Calendar.getInstance();
     }
 
     public void setRange(Calendar min, Calendar max) {
@@ -57,6 +60,10 @@
         notifyDataSetInvalidated();
     }
 
+    public int getFirstDayOfWeek() {
+        return mFirstDayOfWeek;
+    }
+
     /**
      * Updates the selected day and related parameters.
      *
@@ -81,6 +88,24 @@
         mCalendarTextColors = colors;
     }
 
+    /**
+     * Sets the text color, size, style, hint color, and highlight color from
+     * the specified TextAppearance resource. This is mostly copied from
+     * {@link TextView#setTextAppearance(Context, int)}.
+     */
+    void setCalendarTextAppearance(int resId) {
+        final TypedArray a = mContext.obtainStyledAttributes(resId, R.styleable.TextAppearance);
+
+        final ColorStateList textColor = a.getColorStateList(R.styleable.TextAppearance_textColor);
+        if (textColor != null) {
+            mCalendarTextColors = textColor;
+        }
+
+        // TODO: Support font size, etc.
+
+        a.recycle();
+    }
+
     @Override
     public int getCount() {
         final int diffYear = mMaxDate.get(Calendar.YEAR) - mMinDate.get(Calendar.YEAR);
diff --git a/core/jni/AndroidRuntime.cpp b/core/jni/AndroidRuntime.cpp
index c5f1d88..1fbd4a1 100644
--- a/core/jni/AndroidRuntime.cpp
+++ b/core/jni/AndroidRuntime.cpp
@@ -787,6 +787,12 @@
         addOption("-Ximage-compiler-option");
         addOption("--image-classes=/system/etc/preloaded-classes");
 
+        // If there is a compiled-classes file, push it.
+        if (hasFile("/system/etc/compiled-classes")) {
+            addOption("-Ximage-compiler-option");
+            addOption("--compiled-classes=/system/etc/compiled-classes");
+        }
+
         property_get("dalvik.vm.image-dex2oat-flags", dex2oatImageFlagsBuf, "");
         parseExtraOpts(dex2oatImageFlagsBuf, "-Ximage-compiler-option");
 
diff --git a/core/jni/android_media_AudioSystem.cpp b/core/jni/android_media_AudioSystem.cpp
index 4b4b367..cabe200 100644
--- a/core/jni/android_media_AudioSystem.cpp
+++ b/core/jni/android_media_AudioSystem.cpp
@@ -484,7 +484,8 @@
 
 static jint convertAudioPortConfigToNative(JNIEnv *env,
                                                struct audio_port_config *nAudioPortConfig,
-                                               const jobject jAudioPortConfig)
+                                               const jobject jAudioPortConfig,
+                                               bool useConfigMask)
 {
     jobject jAudioPort = env->GetObjectField(jAudioPortConfig, gAudioPortConfigFields.mPort);
     jobject jHandle = env->GetObjectField(jAudioPort, gAudioPortFields.mHandle);
@@ -503,8 +504,13 @@
     ALOGV("convertAudioPortConfigToNative handle %d role %d type %d",
           nAudioPortConfig->id, nAudioPortConfig->role, nAudioPortConfig->type);
 
+    unsigned int configMask = 0;
+
     nAudioPortConfig->sample_rate = env->GetIntField(jAudioPortConfig,
                                                      gAudioPortConfigFields.mSamplingRate);
+    if (nAudioPortConfig->sample_rate != 0) {
+        configMask |= AUDIO_PORT_CONFIG_SAMPLE_RATE;
+    }
 
     bool useInMask = useInChannelMask(nAudioPortConfig->type, nAudioPortConfig->role);
     audio_channel_mask_t nMask;
@@ -518,22 +524,34 @@
         ALOGV("convertAudioPortConfigToNative OUT mask java %x native %x", jMask, nMask);
     }
     nAudioPortConfig->channel_mask = nMask;
+    if (nAudioPortConfig->channel_mask != AUDIO_CHANNEL_NONE) {
+        configMask |= AUDIO_PORT_CONFIG_CHANNEL_MASK;
+    }
 
     jint jFormat = env->GetIntField(jAudioPortConfig, gAudioPortConfigFields.mFormat);
     audio_format_t nFormat = audioFormatToNative(jFormat);
     ALOGV("convertAudioPortConfigToNative format %d native %d", jFormat, nFormat);
     nAudioPortConfig->format = nFormat;
+    if (nAudioPortConfig->format != AUDIO_FORMAT_DEFAULT &&
+            nAudioPortConfig->format != AUDIO_FORMAT_INVALID) {
+        configMask |= AUDIO_PORT_CONFIG_FORMAT;
+    }
+
     jobject jGain = env->GetObjectField(jAudioPortConfig, gAudioPortConfigFields.mGain);
     if (jGain != NULL) {
         convertAudioGainConfigToNative(env, &nAudioPortConfig->gain, jGain, useInMask);
         env->DeleteLocalRef(jGain);
+        configMask |= AUDIO_PORT_CONFIG_GAIN;
     } else {
         ALOGV("convertAudioPortConfigToNative no gain");
         nAudioPortConfig->gain.index = -1;
     }
-    nAudioPortConfig->config_mask = env->GetIntField(jAudioPortConfig,
-                                                     gAudioPortConfigFields.mConfigMask);
-
+    if (useConfigMask) {
+        nAudioPortConfig->config_mask = env->GetIntField(jAudioPortConfig,
+                                                         gAudioPortConfigFields.mConfigMask);
+    } else {
+        nAudioPortConfig->config_mask = configMask;
+    }
     env->DeleteLocalRef(jAudioPort);
     env->DeleteLocalRef(jHandle);
     return (jint)AUDIO_JAVA_SUCCESS;
@@ -998,7 +1016,7 @@
             jStatus = (jint)AUDIO_JAVA_BAD_VALUE;
             goto exit;
         }
-        jStatus = convertAudioPortConfigToNative(env, &nPatch.sources[i], jSource);
+        jStatus = convertAudioPortConfigToNative(env, &nPatch.sources[i], jSource, false);
         env->DeleteLocalRef(jSource);
         jSource = NULL;
         if (jStatus != AUDIO_JAVA_SUCCESS) {
@@ -1013,7 +1031,7 @@
             jStatus = (jint)AUDIO_JAVA_BAD_VALUE;
             goto exit;
         }
-        jStatus = convertAudioPortConfigToNative(env, &nPatch.sinks[i], jSink);
+        jStatus = convertAudioPortConfigToNative(env, &nPatch.sinks[i], jSink, false);
         env->DeleteLocalRef(jSink);
         jSink = NULL;
         if (jStatus != AUDIO_JAVA_SUCCESS) {
@@ -1268,7 +1286,7 @@
         return AUDIO_JAVA_BAD_VALUE;
     }
     struct audio_port_config nAudioPortConfig;
-    jint jStatus = convertAudioPortConfigToNative(env, &nAudioPortConfig, jAudioPortConfig);
+    jint jStatus = convertAudioPortConfigToNative(env, &nAudioPortConfig, jAudioPortConfig, true);
     if (jStatus != AUDIO_JAVA_SUCCESS) {
         return jStatus;
     }
diff --git a/core/jni/android_os_Debug.cpp b/core/jni/android_os_Debug.cpp
index 178bab6..e572d22 100644
--- a/core/jni/android_os_Debug.cpp
+++ b/core/jni/android_os_Debug.cpp
@@ -275,6 +275,7 @@
                         subHeap = HEAP_DALVIK_LINEARALLOC;
                     } else if ((strstr(name, "/dev/ashmem/dalvik-alloc space") == name) ||
                                (strstr(name, "/dev/ashmem/dalvik-main space") == name) ||
+                               (strstr(name, "/dev/ashmem/dalvik-zygote space") == name) ||
                                (strstr(name, "/dev/ashmem/dalvik-non moving space") == name)) {
                         // This is the regular Dalvik heap.
                         whichHeap = HEAP_DALVIK;
diff --git a/core/res/res/anim/dock_bottom_enter.xml b/core/res/res/anim/dock_bottom_enter.xml
index 4f2f753..bfb97b6 100644
--- a/core/res/res/anim/dock_bottom_enter.xml
+++ b/core/res/res/anim/dock_bottom_enter.xml
@@ -20,5 +20,5 @@
 <set xmlns:android="http://schemas.android.com/apk/res/android"
         android:interpolator="@android:interpolator/decelerate_cubic">
     <translate android:fromYDelta="100%" android:toYDelta="0"
-        android:duration="250"/>
+        android:duration="@integer/dock_enter_exit_duration"/>
 </set>
diff --git a/core/res/res/anim/dock_bottom_exit.xml b/core/res/res/anim/dock_bottom_exit.xml
index afbe24b..4e15448 100644
--- a/core/res/res/anim/dock_bottom_exit.xml
+++ b/core/res/res/anim/dock_bottom_exit.xml
@@ -20,5 +20,5 @@
 <set xmlns:android="http://schemas.android.com/apk/res/android"
         android:interpolator="@android:interpolator/accelerate_cubic">
     <translate android:fromYDelta="0" android:toYDelta="100%"
-        android:startOffset="100" android:duration="250"/>
+        android:startOffset="100" android:duration="@integer/dock_enter_exit_duration"/>
 </set>
diff --git a/core/res/res/anim/dock_top_enter.xml b/core/res/res/anim/dock_top_enter.xml
index 1f74e48..f763fb5 100644
--- a/core/res/res/anim/dock_top_enter.xml
+++ b/core/res/res/anim/dock_top_enter.xml
@@ -20,5 +20,5 @@
 <set xmlns:android="http://schemas.android.com/apk/res/android"
         android:interpolator="@android:interpolator/decelerate_cubic">
     <translate android:fromYDelta="-100%" android:toYDelta="0"
-        android:duration="250"/>
+        android:duration="@integer/dock_enter_exit_duration"/>
 </set>
diff --git a/core/res/res/anim/dock_top_exit.xml b/core/res/res/anim/dock_top_exit.xml
index 4d2fea94..995b7d0 100644
--- a/core/res/res/anim/dock_top_exit.xml
+++ b/core/res/res/anim/dock_top_exit.xml
@@ -20,5 +20,5 @@
 <set xmlns:android="http://schemas.android.com/apk/res/android"
         android:interpolator="@android:interpolator/accelerate_cubic">
     <translate android:fromYDelta="0" android:toYDelta="-100%"
-        android:startOffset="100" android:duration="250"/>
+        android:startOffset="100" android:duration="@integer/dock_enter_exit_duration"/>
 </set>
diff --git a/core/res/res/drawable-hdpi/switch_track_mtrl_alpha.9.png b/core/res/res/drawable-hdpi/switch_track_mtrl_alpha.9.png
index 0ebe65e..9415bc0 100644
--- a/core/res/res/drawable-hdpi/switch_track_mtrl_alpha.9.png
+++ b/core/res/res/drawable-hdpi/switch_track_mtrl_alpha.9.png
Binary files differ
diff --git a/core/res/res/drawable-ldpi/switch_track_mtrl_alpha.9.png b/core/res/res/drawable-ldpi/switch_track_mtrl_alpha.9.png
deleted file mode 100644
index a58128f..0000000
--- a/core/res/res/drawable-ldpi/switch_track_mtrl_alpha.9.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable/edit_text_material.xml b/core/res/res/drawable/edit_text_material.xml
index bbc7301..38ac567 100644
--- a/core/res/res/drawable/edit_text_material.xml
+++ b/core/res/res/drawable/edit_text_material.xml
@@ -15,21 +15,23 @@
 -->
 
 <inset xmlns:android="http://schemas.android.com/apk/res/android"
-        android:inset="@dimen/control_inset_material">
-    <ripple android:color="?attr/colorControlActivated">
-        <item>
-            <selector>
-                <item android:state_enabled="false">
-                    <nine-patch android:src="@drawable/textfield_default_mtrl_alpha"
-                        android:tint="?attr/colorControlNormal"
-                        android:alpha="?attr/disabledAlpha" />
-                </item>
-                <item>
-                    <nine-patch android:src="@drawable/textfield_default_mtrl_alpha"
-                        android:tint="?attr/colorControlNormal" />
-                </item>
-            </selector>
+       android:insetLeft="@dimen/edit_text_inset_horizontal_material"
+       android:insetRight="@dimen/edit_text_inset_horizontal_material"
+       android:insetTop="@dimen/edit_text_inset_top_material"
+       android:insetBottom="@dimen/edit_text_inset_bottom_material">
+    <selector>
+        <item android:state_enabled="false">
+            <nine-patch android:src="@drawable/textfield_default_mtrl_alpha"
+                android:tint="?attr/colorControlNormal"
+                android:alpha="?attr/disabledAlpha" />
         </item>
-        <item android:id="@+id/mask" android:drawable="@drawable/textfield_activated_mtrl_alpha" />
-    </ripple>
+        <item android:state_pressed="false" android:state_focused="false">
+            <nine-patch android:src="@drawable/textfield_default_mtrl_alpha"
+                android:tint="?attr/colorControlNormal" />
+        </item>
+        <item>
+            <nine-patch android:src="@drawable/textfield_activated_mtrl_alpha"
+                android:tint="?attr/colorControlActivated" />
+        </item>
+    </selector>
 </inset>
diff --git a/core/res/res/values-af/strings.xml b/core/res/res/values-af/strings.xml
index f0a05ea..522af95 100644
--- a/core/res/res/values-af/strings.xml
+++ b/core/res/res/values-af/strings.xml
@@ -564,6 +564,8 @@
     <string name="permdesc_configureWifiDisplay" msgid="7916815158690218065">"Laat die program toe om Wi-Fi-skerms op te stel en daaraan te koppel."</string>
     <string name="permlab_controlWifiDisplay" msgid="393641276723695496">"beheer Wi-Fi-skerms"</string>
     <string name="permdesc_controlWifiDisplay" msgid="4543912292681826986">"Laat die program toe om laevlak-kenmerke van Wi-Fi-skerms te beheer."</string>
+    <string name="permlab_controlVpn" msgid="2618442789397588200">"beheer virtuele private netwerke"</string>
+    <string name="permdesc_controlVpn" msgid="762852603315861214">"Laat die program toe om laevlak-kenmerke van virtuele private netwerke te beheer."</string>
     <string name="permlab_captureAudioOutput" msgid="6857134498402346708">"vang oudio-uitset vas"</string>
     <string name="permdesc_captureAudioOutput" msgid="6210597754212208853">"Laat die program oudio-uitset vasvang en herlei."</string>
     <string name="permlab_captureAudioHotword" msgid="1890553935650349808">"Aktiveerwoord-opsporing"</string>
@@ -1902,4 +1904,18 @@
     <string name="zen_mode_next_alarm_summary" msgid="5915140424683747372">"Tot die volgende wekker om <xliff:g id="FORMATTEDTIME">%1$s</xliff:g>"</string>
     <string name="zen_mode_next_alarm_line_one" msgid="5537042951553420916">"Tot die volgende wekker"</string>
     <string name="muted_by" msgid="6147073845094180001">"Gedemp deur <xliff:g id="THIRD_PARTY">%1$s</xliff:g>"</string>
+    <string name="system_error_wipe_data" msgid="6608165524785354962">"Daar is \'n interne probleem met jou toestel en dit sal dalk onstabiel wees totdat jy \'n fabriekterugstelling doen."</string>
+    <string name="system_error_manufacturer" msgid="8086872414744210668">"Daar is \'n interne probleem met jou toestel. Kontak jou vervaardiger vir besonderhede."</string>
+    <!-- no translation found for stk_cc_ussd_to_dial (5202342984749947872) -->
+    <skip />
+    <!-- no translation found for stk_cc_ussd_to_ss (2345360594181405482) -->
+    <skip />
+    <!-- no translation found for stk_cc_ussd_to_ussd (7466087659967191653) -->
+    <skip />
+    <!-- no translation found for stk_cc_ss_to_dial (2151304435775557162) -->
+    <skip />
+    <!-- no translation found for stk_cc_ss_to_ussd (3951862188105305589) -->
+    <skip />
+    <!-- no translation found for stk_cc_ss_to_ss (5470768854991452695) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-am/strings.xml b/core/res/res/values-am/strings.xml
index 7c90290..4efa564 100644
--- a/core/res/res/values-am/strings.xml
+++ b/core/res/res/values-am/strings.xml
@@ -564,6 +564,8 @@
     <string name="permdesc_configureWifiDisplay" msgid="7916815158690218065">"መተግበሪያው የWifi ማሳያዎችን እንዲያዋቅርና ከእነሱ ጋር እንዲገናኝ ይፈቅድለታል።"</string>
     <string name="permlab_controlWifiDisplay" msgid="393641276723695496">"የWifi ማሳያዎችን ተቆጣጠር"</string>
     <string name="permdesc_controlWifiDisplay" msgid="4543912292681826986">"መተግበሪያው በዝቅተኛ ደረጃ ላይ ያሉ የWifi ማሳያዎችን እንዲቆጣጠር ይፈቅድለታል።"</string>
+    <string name="permlab_controlVpn" msgid="2618442789397588200">"ምናባዊ የግል አውታረ መረቦችን ይቆጣጠሩ"</string>
+    <string name="permdesc_controlVpn" msgid="762852603315861214">"መተግበሪያው የምናባዊ ግል አውታረ መረቦች ዝቅተኛ ደረጃ ባህሪያትን እንዲቆጣጠር ያስችለዋል።"</string>
     <string name="permlab_captureAudioOutput" msgid="6857134498402346708">"የድምጽ ውጽዓት ይቅረጹ"</string>
     <string name="permdesc_captureAudioOutput" msgid="6210597754212208853">"መተግበሪያው የድምጽ ውጽዓት እንዲቀርጽ እና አቅጣጫውን እንዲያዞር ያስችለዋል።"</string>
     <string name="permlab_captureAudioHotword" msgid="1890553935650349808">"ትኩስ ቃል ማወቅ"</string>
@@ -1902,4 +1904,18 @@
     <string name="zen_mode_next_alarm_summary" msgid="5915140424683747372">"በ<xliff:g id="FORMATTEDTIME">%1$s</xliff:g> ላይ እስከሚቀጥለው ማንቂያ ድረስ"</string>
     <string name="zen_mode_next_alarm_line_one" msgid="5537042951553420916">"እስከሚቀጥለው ማንቂያ ድረስ"</string>
     <string name="muted_by" msgid="6147073845094180001">"ድምጽ በ<xliff:g id="THIRD_PARTY">%1$s</xliff:g> ተዘግቷል"</string>
+    <string name="system_error_wipe_data" msgid="6608165524785354962">"መሣሪያዎ ላይ የውስጣዊ ችግር አለ፣ የፋብሪካ ውሂብ ዳግም እስኪያስጀምሩት ድረስ ላይረጋጋ ይችላል።"</string>
+    <string name="system_error_manufacturer" msgid="8086872414744210668">"መሣሪያዎ ላይ የውስጣዊ ችግር አለ። ዝርዝሮችን ለማግኘት አምራችዎን ያነጋግሩ።"</string>
+    <!-- no translation found for stk_cc_ussd_to_dial (5202342984749947872) -->
+    <skip />
+    <!-- no translation found for stk_cc_ussd_to_ss (2345360594181405482) -->
+    <skip />
+    <!-- no translation found for stk_cc_ussd_to_ussd (7466087659967191653) -->
+    <skip />
+    <!-- no translation found for stk_cc_ss_to_dial (2151304435775557162) -->
+    <skip />
+    <!-- no translation found for stk_cc_ss_to_ussd (3951862188105305589) -->
+    <skip />
+    <!-- no translation found for stk_cc_ss_to_ss (5470768854991452695) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-ar/strings.xml b/core/res/res/values-ar/strings.xml
index f696947..98821ca 100644
--- a/core/res/res/values-ar/strings.xml
+++ b/core/res/res/values-ar/strings.xml
@@ -564,6 +564,8 @@
     <string name="permdesc_configureWifiDisplay" msgid="7916815158690218065">"‏للسماح للتطبيق بتهيئة شاشات Wi-Fi والاتصال بها."</string>
     <string name="permlab_controlWifiDisplay" msgid="393641276723695496">"‏التحكم في شاشات Wi-Fi"</string>
     <string name="permdesc_controlWifiDisplay" msgid="4543912292681826986">"‏للسماح للتطبيق بالتحكم في الميزات ذات المستوى المنخفض في شاشات Wi-Fi."</string>
+    <string name="permlab_controlVpn" msgid="2618442789397588200">"التحكم في الشبكات الظاهرية الخاصة"</string>
+    <string name="permdesc_controlVpn" msgid="762852603315861214">"للسماح للتطبيق بالتحكم في ميزات المستوى المنخفض للشبكات الظاهرية الخاصة."</string>
     <string name="permlab_captureAudioOutput" msgid="6857134498402346708">"التقاط إخراج الصوت"</string>
     <string name="permdesc_captureAudioOutput" msgid="6210597754212208853">"السماح للتطبيق بالتقاط إخراج الصوت وإعادة توجيهه."</string>
     <string name="permlab_captureAudioHotword" msgid="1890553935650349808">"اكتشاف الكلمة المهمة"</string>
@@ -1902,4 +1904,18 @@
     <string name="zen_mode_next_alarm_summary" msgid="5915140424683747372">"حتى التنبيه التالي في <xliff:g id="FORMATTEDTIME">%1$s</xliff:g>"</string>
     <string name="zen_mode_next_alarm_line_one" msgid="5537042951553420916">"حتى التنبيه التالي"</string>
     <string name="muted_by" msgid="6147073845094180001">"تم كتم الصوت بواسطة <xliff:g id="THIRD_PARTY">%1$s</xliff:g>"</string>
+    <string name="system_error_wipe_data" msgid="6608165524785354962">"حدثت مشكلة داخلية في جهازك، وقد لا يستقر وضعه حتى إجراء إعادة الضبط بحسب بيانات المصنع."</string>
+    <string name="system_error_manufacturer" msgid="8086872414744210668">"حدثت مشكلة داخلية في جهازك. يمكنك الاتصال بالمصنِّع للحصول على تفاصيل."</string>
+    <!-- no translation found for stk_cc_ussd_to_dial (5202342984749947872) -->
+    <skip />
+    <!-- no translation found for stk_cc_ussd_to_ss (2345360594181405482) -->
+    <skip />
+    <!-- no translation found for stk_cc_ussd_to_ussd (7466087659967191653) -->
+    <skip />
+    <!-- no translation found for stk_cc_ss_to_dial (2151304435775557162) -->
+    <skip />
+    <!-- no translation found for stk_cc_ss_to_ussd (3951862188105305589) -->
+    <skip />
+    <!-- no translation found for stk_cc_ss_to_ss (5470768854991452695) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-bg/strings.xml b/core/res/res/values-bg/strings.xml
index 00640bb..97b8fc5 100644
--- a/core/res/res/values-bg/strings.xml
+++ b/core/res/res/values-bg/strings.xml
@@ -564,6 +564,8 @@
     <string name="permdesc_configureWifiDisplay" msgid="7916815158690218065">"Разрешава на приложението да конфигурира и да се свързва с дисплеите през WiFi."</string>
     <string name="permlab_controlWifiDisplay" msgid="393641276723695496">"контролиране на дисплеите през WiFi"</string>
     <string name="permdesc_controlWifiDisplay" msgid="4543912292681826986">"Разрешава на приложението да контролира функциите от ниско ниво на дисплеите през WiFi."</string>
+    <string name="permlab_controlVpn" msgid="2618442789397588200">"управление на виртуалните частни мрежи"</string>
+    <string name="permdesc_controlVpn" msgid="762852603315861214">"Разрешава на приложението да управлява функциите от ниско ниво на виртуалните частни мрежи."</string>
     <string name="permlab_captureAudioOutput" msgid="6857134498402346708">"записване на възпроизвеждания звук"</string>
     <string name="permdesc_captureAudioOutput" msgid="6210597754212208853">"Разрешава на приложението да записва и пренасочва възпроизвеждания звук."</string>
     <string name="permlab_captureAudioHotword" msgid="1890553935650349808">"Откриване на активиращи думи"</string>
@@ -1902,4 +1904,18 @@
     <string name="zen_mode_next_alarm_summary" msgid="5915140424683747372">"До следващия будилник в <xliff:g id="FORMATTEDTIME">%1$s</xliff:g>"</string>
     <string name="zen_mode_next_alarm_line_one" msgid="5537042951553420916">"До следващия будилник"</string>
     <string name="muted_by" msgid="6147073845094180001">"Заглушено от <xliff:g id="THIRD_PARTY">%1$s</xliff:g>"</string>
+    <string name="system_error_wipe_data" msgid="6608165524785354962">"Възникна вътрешен проблем с устройството ви. То може да е нестабилно, докато не възстановите фабричните настройки."</string>
+    <string name="system_error_manufacturer" msgid="8086872414744210668">"Възникна вътрешен проблем с устройството ви. За подробности се свържете с производителя."</string>
+    <!-- no translation found for stk_cc_ussd_to_dial (5202342984749947872) -->
+    <skip />
+    <!-- no translation found for stk_cc_ussd_to_ss (2345360594181405482) -->
+    <skip />
+    <!-- no translation found for stk_cc_ussd_to_ussd (7466087659967191653) -->
+    <skip />
+    <!-- no translation found for stk_cc_ss_to_dial (2151304435775557162) -->
+    <skip />
+    <!-- no translation found for stk_cc_ss_to_ussd (3951862188105305589) -->
+    <skip />
+    <!-- no translation found for stk_cc_ss_to_ss (5470768854991452695) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-bn-rBD/strings.xml b/core/res/res/values-bn-rBD/strings.xml
index b865a18..cb55c95 100644
--- a/core/res/res/values-bn-rBD/strings.xml
+++ b/core/res/res/values-bn-rBD/strings.xml
@@ -564,6 +564,8 @@
     <string name="permdesc_configureWifiDisplay" msgid="7916815158690218065">"Wifi প্রদর্শনগুলি অনুযায়ী কনফিগার করে নিতে এবং সংযোগ স্থাপন করতে অ্যাপ্লিকেশানটিকে মঞ্জুর করে৷"</string>
     <string name="permlab_controlWifiDisplay" msgid="393641276723695496">"Wifi প্রদর্শনগুলিকে নিয়ন্ত্রণ করুন"</string>
     <string name="permdesc_controlWifiDisplay" msgid="4543912292681826986">"Wifi প্রদর্শনের নিম্ন মানের বৈশিষ্ট্যগুলিকে নিয়ন্ত্রণ করতে অ্যাপ্লিকেশানটিকে মঞ্জুর করে৷"</string>
+    <string name="permlab_controlVpn" msgid="2618442789397588200">"ভার্চুয়াল প্রাইভেট নেটওয়ার্ক নিয়ন্ত্রণ করুন"</string>
+    <string name="permdesc_controlVpn" msgid="762852603315861214">"অ্যাপ্লিকেশানটিকে ভার্চুয়াল প্রাইভেট নেটওয়ার্কের নিম্নস্তরের বৈশিষ্ট্য নিয়ন্ত্রণ করতে দেয়৷"</string>
     <string name="permlab_captureAudioOutput" msgid="6857134498402346708">"অডিও আউটপুট গ্রহণ করে"</string>
     <string name="permdesc_captureAudioOutput" msgid="6210597754212208853">"অ্যাপ্লিকেশানটিকে অডিও আউটপুট গ্রহণ এবং পুনর্নির্দেশ করতে দেয়৷"</string>
     <string name="permlab_captureAudioHotword" msgid="1890553935650349808">"হটওয়ার্ড সনাক্তকরণ"</string>
@@ -1902,4 +1904,18 @@
     <string name="zen_mode_next_alarm_summary" msgid="5915140424683747372">"<xliff:g id="FORMATTEDTIME">%1$s</xliff:g> এ পরবর্তী অ্যালার্ম পর্যন্ত"</string>
     <string name="zen_mode_next_alarm_line_one" msgid="5537042951553420916">"পরবর্তী অ্যালার্ম পর্যন্ত"</string>
     <string name="muted_by" msgid="6147073845094180001">"<xliff:g id="THIRD_PARTY">%1$s</xliff:g> দ্বারা নিঃশব্দ করা হয়েছে"</string>
+    <string name="system_error_wipe_data" msgid="6608165524785354962">"আপনার ডিভাইসে একটি অভ্যন্তরীন সমস্যা হয়েছে, এবং আপনি যতক্ষণ না পর্যন্ত এটিকে ফ্যাক্টরি ডেটা রিসেট করছেন ততক্ষণ এটি ঠিকভাবে কাজ নাও করতে পারে৷"</string>
+    <string name="system_error_manufacturer" msgid="8086872414744210668">"আপনার ডিভাইসে একটি অভ্যন্তরীন সমস্যা হয়েছে৷ বিস্তারিত জানার জন্য প্রস্তুতকারকের সাথে যোগাযোগ করুন৷"</string>
+    <!-- no translation found for stk_cc_ussd_to_dial (5202342984749947872) -->
+    <skip />
+    <!-- no translation found for stk_cc_ussd_to_ss (2345360594181405482) -->
+    <skip />
+    <!-- no translation found for stk_cc_ussd_to_ussd (7466087659967191653) -->
+    <skip />
+    <!-- no translation found for stk_cc_ss_to_dial (2151304435775557162) -->
+    <skip />
+    <!-- no translation found for stk_cc_ss_to_ussd (3951862188105305589) -->
+    <skip />
+    <!-- no translation found for stk_cc_ss_to_ss (5470768854991452695) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-ca/strings.xml b/core/res/res/values-ca/strings.xml
index 72179d8..3ac2fd80 100644
--- a/core/res/res/values-ca/strings.xml
+++ b/core/res/res/values-ca/strings.xml
@@ -564,6 +564,8 @@
     <string name="permdesc_configureWifiDisplay" msgid="7916815158690218065">"Permet a l\'aplicació configurar-se i connectar-se a les pantalles Wi-Fi."</string>
     <string name="permlab_controlWifiDisplay" msgid="393641276723695496">"control de les pantalles Wi-Fi"</string>
     <string name="permdesc_controlWifiDisplay" msgid="4543912292681826986">"Permet a l\'aplicació controlar les funcions de baix nivell de les pantalles Wi-Fi."</string>
+    <string name="permlab_controlVpn" msgid="2618442789397588200">"controlar xarxes privades virtuals"</string>
+    <string name="permdesc_controlVpn" msgid="762852603315861214">"Permet que l\'aplicació controli funcions de nivell baix de xarxes privades virtuals."</string>
     <string name="permlab_captureAudioOutput" msgid="6857134498402346708">"captura la sortida d\'àudio"</string>
     <string name="permdesc_captureAudioOutput" msgid="6210597754212208853">"Permet que l\'aplicació capturi i redirigeixi la sortida d\'àudio."</string>
     <string name="permlab_captureAudioHotword" msgid="1890553935650349808">"Detecció de paraules actives"</string>
@@ -833,8 +835,8 @@
     <string name="permdesc_handoverStatus" msgid="4788144087245714948">"Permet que aquesta aplicació rebi informació sobre les transferències d\'Android Beam actuals."</string>
     <string name="permlab_removeDrmCertificates" msgid="7044888287209892751">"suprimir els certificats DRM"</string>
     <string name="permdesc_removeDrmCertificates" msgid="7272999075113400993">"Permet que una aplicació suprimeixi els certificats DRM. No ha de ser mai necessari per a aplicacions normals."</string>
-    <string name="permlab_bindCarrierMessagingService" msgid="1490229371796969158">"vincular-la a un servei de missatgeria"</string>
-    <string name="permdesc_bindCarrierMessagingService" msgid="2762882888502113944">"Permet que el propietari la pugui vincular a la interfície principal d\'un servei de missatgeria. És possible que no s\'hagi d\'utilitzar mai amb aplicacions normals."</string>
+    <string name="permlab_bindCarrierMessagingService" msgid="1490229371796969158">"vincular-la al servei de missatgeria d\'un operador"</string>
+    <string name="permdesc_bindCarrierMessagingService" msgid="2762882888502113944">"Permet que el propietari la pugui vincular a la interfície principal del servei de missatgeria d\'un operador. No s\'hauria de necessitar mai per a les aplicacions normals."</string>
     <string name="policylab_limitPassword" msgid="4497420728857585791">"Definir les normes de contrasenya"</string>
     <string name="policydesc_limitPassword" msgid="3252114203919510394">"Controla la longitud i els caràcters permesos a les contrasenyes de desbloqueig de pantalla."</string>
     <string name="policylab_watchLogin" msgid="914130646942199503">"Controlar els intents de desbloqueig de pantalla"</string>
@@ -1902,4 +1904,18 @@
     <string name="zen_mode_next_alarm_summary" msgid="5915140424683747372">"Fins que soni l\'alarma següent a les <xliff:g id="FORMATTEDTIME">%1$s</xliff:g>"</string>
     <string name="zen_mode_next_alarm_line_one" msgid="5537042951553420916">"Fins que soni l\'alarma següent"</string>
     <string name="muted_by" msgid="6147073845094180001">"Silenciat per <xliff:g id="THIRD_PARTY">%1$s</xliff:g>"</string>
+    <string name="system_error_wipe_data" msgid="6608165524785354962">"S\'ha produït un error intern al dispositiu i és possible que funcioni de manera inestable fins que restableixis les dades de fàbrica."</string>
+    <string name="system_error_manufacturer" msgid="8086872414744210668">"S\'ha produït un error intern al dispositiu. Contacta amb el fabricant del dispositiu per obtenir més informació."</string>
+    <!-- no translation found for stk_cc_ussd_to_dial (5202342984749947872) -->
+    <skip />
+    <!-- no translation found for stk_cc_ussd_to_ss (2345360594181405482) -->
+    <skip />
+    <!-- no translation found for stk_cc_ussd_to_ussd (7466087659967191653) -->
+    <skip />
+    <!-- no translation found for stk_cc_ss_to_dial (2151304435775557162) -->
+    <skip />
+    <!-- no translation found for stk_cc_ss_to_ussd (3951862188105305589) -->
+    <skip />
+    <!-- no translation found for stk_cc_ss_to_ss (5470768854991452695) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-cs/strings.xml b/core/res/res/values-cs/strings.xml
index a91c3ba..81d2e50 100644
--- a/core/res/res/values-cs/strings.xml
+++ b/core/res/res/values-cs/strings.xml
@@ -564,6 +564,8 @@
     <string name="permdesc_configureWifiDisplay" msgid="7916815158690218065">"Povoluje aplikaci připojit a konfigurovat displeje přes Wi-Fi."</string>
     <string name="permlab_controlWifiDisplay" msgid="393641276723695496">"ovládat displeje přes Wi-Fi"</string>
     <string name="permdesc_controlWifiDisplay" msgid="4543912292681826986">"Povoluje aplikaci ovládat základní funkce displejů přes Wi-Fi."</string>
+    <string name="permlab_controlVpn" msgid="2618442789397588200">"ovládat virtuální privátní sítě"</string>
+    <string name="permdesc_controlVpn" msgid="762852603315861214">"Umožňuje aplikaci ovládat nízkoúrovňové funkce virtuálních privátních síti."</string>
     <string name="permlab_captureAudioOutput" msgid="6857134498402346708">"zachytit výstup zvuku"</string>
     <string name="permdesc_captureAudioOutput" msgid="6210597754212208853">"Umožní aplikaci zachytit a přesměrovat výstup zvuku."</string>
     <string name="permlab_captureAudioHotword" msgid="1890553935650349808">"Detekce klíčových slov"</string>
@@ -1902,4 +1904,18 @@
     <string name="zen_mode_next_alarm_summary" msgid="5915140424683747372">"Do dalšího budíku v <xliff:g id="FORMATTEDTIME">%1$s</xliff:g>"</string>
     <string name="zen_mode_next_alarm_line_one" msgid="5537042951553420916">"Do příštího budíku"</string>
     <string name="muted_by" msgid="6147073845094180001">"Ignorováno stranou <xliff:g id="THIRD_PARTY">%1$s</xliff:g>"</string>
+    <string name="system_error_wipe_data" msgid="6608165524785354962">"V zařízení došlo k internímu problému. Dokud neprovedete obnovení továrních dat, může být nestabilní."</string>
+    <string name="system_error_manufacturer" msgid="8086872414744210668">"V zařízení došlo k internímu problému. Další informace vám sdělí výrobce."</string>
+    <!-- no translation found for stk_cc_ussd_to_dial (5202342984749947872) -->
+    <skip />
+    <!-- no translation found for stk_cc_ussd_to_ss (2345360594181405482) -->
+    <skip />
+    <!-- no translation found for stk_cc_ussd_to_ussd (7466087659967191653) -->
+    <skip />
+    <!-- no translation found for stk_cc_ss_to_dial (2151304435775557162) -->
+    <skip />
+    <!-- no translation found for stk_cc_ss_to_ussd (3951862188105305589) -->
+    <skip />
+    <!-- no translation found for stk_cc_ss_to_ss (5470768854991452695) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-da/strings.xml b/core/res/res/values-da/strings.xml
index 2088ac4..22c9506 100644
--- a/core/res/res/values-da/strings.xml
+++ b/core/res/res/values-da/strings.xml
@@ -564,6 +564,8 @@
     <string name="permdesc_configureWifiDisplay" msgid="7916815158690218065">"Tillader, at appen konfigurerer og opretter forbindelse til Wi-Fi-skærme."</string>
     <string name="permlab_controlWifiDisplay" msgid="393641276723695496">"kontrollér Wi-Fi-skærme"</string>
     <string name="permdesc_controlWifiDisplay" msgid="4543912292681826986">"Tillader, at appen kontrollerer Wi-Fi-skærmfunktioner på lavt niveau."</string>
+    <string name="permlab_controlVpn" msgid="2618442789397588200">"styre virtuelle private netværk"</string>
+    <string name="permdesc_controlVpn" msgid="762852603315861214">"Tillader, at appen styrer basale funktioner i virtuelle private netværk."</string>
     <string name="permlab_captureAudioOutput" msgid="6857134498402346708">"opfang et lydoutput"</string>
     <string name="permdesc_captureAudioOutput" msgid="6210597754212208853">"Tillader, at appen opfanger og omdirigerer et lydoutput."</string>
     <string name="permlab_captureAudioHotword" msgid="1890553935650349808">"Registrering af kommandoord"</string>
@@ -1902,4 +1904,18 @@
     <string name="zen_mode_next_alarm_summary" msgid="5915140424683747372">"Indtil næste alarm kl. <xliff:g id="FORMATTEDTIME">%1$s</xliff:g>"</string>
     <string name="zen_mode_next_alarm_line_one" msgid="5537042951553420916">"Indtil næste alarm"</string>
     <string name="muted_by" msgid="6147073845094180001">"Lyden blev afbrudt af <xliff:g id="THIRD_PARTY">%1$s</xliff:g>"</string>
+    <string name="system_error_wipe_data" msgid="6608165524785354962">"Der er et internt problem med enheden, og den vil muligvis være ustabil, indtil du gendanner fabriksdataene."</string>
+    <string name="system_error_manufacturer" msgid="8086872414744210668">"Der er et internt problem med enheden. Kontakt producenten for at få yderligere oplysninger."</string>
+    <!-- no translation found for stk_cc_ussd_to_dial (5202342984749947872) -->
+    <skip />
+    <!-- no translation found for stk_cc_ussd_to_ss (2345360594181405482) -->
+    <skip />
+    <!-- no translation found for stk_cc_ussd_to_ussd (7466087659967191653) -->
+    <skip />
+    <!-- no translation found for stk_cc_ss_to_dial (2151304435775557162) -->
+    <skip />
+    <!-- no translation found for stk_cc_ss_to_ussd (3951862188105305589) -->
+    <skip />
+    <!-- no translation found for stk_cc_ss_to_ss (5470768854991452695) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-de/strings.xml b/core/res/res/values-de/strings.xml
index bd38d66..cdbe08d 100644
--- a/core/res/res/values-de/strings.xml
+++ b/core/res/res/values-de/strings.xml
@@ -564,6 +564,8 @@
     <string name="permdesc_configureWifiDisplay" msgid="7916815158690218065">"Erlaubt der App, WLAN-Anzeigen zu konfigurieren und eine Verbindung zu diesen herzustellen"</string>
     <string name="permlab_controlWifiDisplay" msgid="393641276723695496">"WLAN-Anzeigen steuern"</string>
     <string name="permdesc_controlWifiDisplay" msgid="4543912292681826986">"Erlaubt der App, untergeordnete Funktionen von WLAN-Anzeigen zu steuern"</string>
+    <string name="permlab_controlVpn" msgid="2618442789397588200">"Virtuelle private Netzwerke steuern"</string>
+    <string name="permdesc_controlVpn" msgid="762852603315861214">"Ermöglicht der App die Steuerung von Basisfunktionen von virtuellen privaten Netzwerken"</string>
     <string name="permlab_captureAudioOutput" msgid="6857134498402346708">"Audioausgabe erfassen"</string>
     <string name="permdesc_captureAudioOutput" msgid="6210597754212208853">"Ermöglicht der App die Erfassung und Weiterleitung von Audioausgaben"</string>
     <string name="permlab_captureAudioHotword" msgid="1890553935650349808">"Hotword-Erkennung"</string>
@@ -1902,4 +1904,18 @@
     <string name="zen_mode_next_alarm_summary" msgid="5915140424683747372">"Bis zum nächsten Weckruf um <xliff:g id="FORMATTEDTIME">%1$s</xliff:g>"</string>
     <string name="zen_mode_next_alarm_line_one" msgid="5537042951553420916">"Bis zum nächsten Weckruf"</string>
     <string name="muted_by" msgid="6147073845094180001">"Stummgeschaltet durch <xliff:g id="THIRD_PARTY">%1$s</xliff:g>"</string>
+    <string name="system_error_wipe_data" msgid="6608165524785354962">"Es liegt ein internes Problem mit Ihrem Gerät vor. Möglicherweise verhält es sich instabil, bis Sie es auf die Werkseinstellungen zurücksetzen."</string>
+    <string name="system_error_manufacturer" msgid="8086872414744210668">"Es liegt ein internes Problem mit Ihrem Gerät vor. Bitte wenden Sie sich diesbezüglich an den Hersteller."</string>
+    <!-- no translation found for stk_cc_ussd_to_dial (5202342984749947872) -->
+    <skip />
+    <!-- no translation found for stk_cc_ussd_to_ss (2345360594181405482) -->
+    <skip />
+    <!-- no translation found for stk_cc_ussd_to_ussd (7466087659967191653) -->
+    <skip />
+    <!-- no translation found for stk_cc_ss_to_dial (2151304435775557162) -->
+    <skip />
+    <!-- no translation found for stk_cc_ss_to_ussd (3951862188105305589) -->
+    <skip />
+    <!-- no translation found for stk_cc_ss_to_ss (5470768854991452695) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-el/strings.xml b/core/res/res/values-el/strings.xml
index fcd4a9d..c062e42 100644
--- a/core/res/res/values-el/strings.xml
+++ b/core/res/res/values-el/strings.xml
@@ -564,6 +564,8 @@
     <string name="permdesc_configureWifiDisplay" msgid="7916815158690218065">"Επιτρέπει τη διαμόρφωση της εφαρμογής και τη σύνδεσης σε οθόνες Wifi."</string>
     <string name="permlab_controlWifiDisplay" msgid="393641276723695496">"έλεγχος οθονών Wifi"</string>
     <string name="permdesc_controlWifiDisplay" msgid="4543912292681826986">"Επιτρέπει στην εφαρμογή τον έλεγχο των λειτουργιών χαμηλού επιπέδου των οθονών Wifi."</string>
+    <string name="permlab_controlVpn" msgid="2618442789397588200">"έλεγχος εικονικών ιδιωτικών δικτύων"</string>
+    <string name="permdesc_controlVpn" msgid="762852603315861214">"Επιτρέπει στην εφαρμογή να ελέγχει τις λειτουργίες χαμηλού επιπέδου των εικονικών ιδιωτικών δικτύων."</string>
     <string name="permlab_captureAudioOutput" msgid="6857134498402346708">"έγγραφή εξόδου ήχου"</string>
     <string name="permdesc_captureAudioOutput" msgid="6210597754212208853">"Δίνει στην εφαρμογή τη δυνατότητα εγγραφής και ανακατεύθυνσης εξόδου ήχου."</string>
     <string name="permlab_captureAudioHotword" msgid="1890553935650349808">"Ανίχνευση ενεργών λέξεων"</string>
@@ -1902,4 +1904,18 @@
     <string name="zen_mode_next_alarm_summary" msgid="5915140424683747372">"Έως την επόμενη ειδοποίηση στις <xliff:g id="FORMATTEDTIME">%1$s</xliff:g>"</string>
     <string name="zen_mode_next_alarm_line_one" msgid="5537042951553420916">"Έως την επόμενη ειδοποίηση"</string>
     <string name="muted_by" msgid="6147073845094180001">"Σίγαση από <xliff:g id="THIRD_PARTY">%1$s</xliff:g>"</string>
+    <string name="system_error_wipe_data" msgid="6608165524785354962">"Υπάρχει ένα εσωτερικό πρόβλημα με τη συσκευή σας και ενδέχεται να είναι ασταθής μέχρι την επαναφορά των εργοστασιακών ρυθμίσεων."</string>
+    <string name="system_error_manufacturer" msgid="8086872414744210668">"Υπάρχει ένα εσωτερικό πρόβλημα με τη συσκευή σας. Επικοινωνήστε με τον κατασκευαστή σας για λεπτομέρειες."</string>
+    <!-- no translation found for stk_cc_ussd_to_dial (5202342984749947872) -->
+    <skip />
+    <!-- no translation found for stk_cc_ussd_to_ss (2345360594181405482) -->
+    <skip />
+    <!-- no translation found for stk_cc_ussd_to_ussd (7466087659967191653) -->
+    <skip />
+    <!-- no translation found for stk_cc_ss_to_dial (2151304435775557162) -->
+    <skip />
+    <!-- no translation found for stk_cc_ss_to_ussd (3951862188105305589) -->
+    <skip />
+    <!-- no translation found for stk_cc_ss_to_ss (5470768854991452695) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-en-rGB/strings.xml b/core/res/res/values-en-rGB/strings.xml
index 678f2e6..98dc0f5 100644
--- a/core/res/res/values-en-rGB/strings.xml
+++ b/core/res/res/values-en-rGB/strings.xml
@@ -564,6 +564,8 @@
     <string name="permdesc_configureWifiDisplay" msgid="7916815158690218065">"Allows the app to configure and connect to Wi-Fi displays."</string>
     <string name="permlab_controlWifiDisplay" msgid="393641276723695496">"control Wi-Fi displays"</string>
     <string name="permdesc_controlWifiDisplay" msgid="4543912292681826986">"Allows the app to control low-level features of Wi-Fi displays."</string>
+    <string name="permlab_controlVpn" msgid="2618442789397588200">"control Virtual Private Networks"</string>
+    <string name="permdesc_controlVpn" msgid="762852603315861214">"Allows the app to control low-level features of Virtual Private Networks."</string>
     <string name="permlab_captureAudioOutput" msgid="6857134498402346708">"capture audio output"</string>
     <string name="permdesc_captureAudioOutput" msgid="6210597754212208853">"Allows the app to capture and redirect audio output."</string>
     <string name="permlab_captureAudioHotword" msgid="1890553935650349808">"Hotword detection"</string>
@@ -1902,4 +1904,12 @@
     <string name="zen_mode_next_alarm_summary" msgid="5915140424683747372">"Until next alarm at <xliff:g id="FORMATTEDTIME">%1$s</xliff:g>"</string>
     <string name="zen_mode_next_alarm_line_one" msgid="5537042951553420916">"Until next alarm"</string>
     <string name="muted_by" msgid="6147073845094180001">"Muted by <xliff:g id="THIRD_PARTY">%1$s</xliff:g>"</string>
+    <string name="system_error_wipe_data" msgid="6608165524785354962">"There\'s an internal problem with your device, and it may be unstable until you factory data reset."</string>
+    <string name="system_error_manufacturer" msgid="8086872414744210668">"There\'s an internal problem with your device. Contact your manufacturer for details."</string>
+    <string name="stk_cc_ussd_to_dial" msgid="5202342984749947872">"USSD request is modified to DIAL request."</string>
+    <string name="stk_cc_ussd_to_ss" msgid="2345360594181405482">"USSD request is modified to SS request."</string>
+    <string name="stk_cc_ussd_to_ussd" msgid="7466087659967191653">"USSD request is modified to new USSD request."</string>
+    <string name="stk_cc_ss_to_dial" msgid="2151304435775557162">"SS request is modified to DIAL request."</string>
+    <string name="stk_cc_ss_to_ussd" msgid="3951862188105305589">"SS request is modified to USSD request."</string>
+    <string name="stk_cc_ss_to_ss" msgid="5470768854991452695">"SS request is modified to new SS request."</string>
 </resources>
diff --git a/core/res/res/values-en-rIN/strings.xml b/core/res/res/values-en-rIN/strings.xml
index 678f2e6..98dc0f5 100644
--- a/core/res/res/values-en-rIN/strings.xml
+++ b/core/res/res/values-en-rIN/strings.xml
@@ -564,6 +564,8 @@
     <string name="permdesc_configureWifiDisplay" msgid="7916815158690218065">"Allows the app to configure and connect to Wi-Fi displays."</string>
     <string name="permlab_controlWifiDisplay" msgid="393641276723695496">"control Wi-Fi displays"</string>
     <string name="permdesc_controlWifiDisplay" msgid="4543912292681826986">"Allows the app to control low-level features of Wi-Fi displays."</string>
+    <string name="permlab_controlVpn" msgid="2618442789397588200">"control Virtual Private Networks"</string>
+    <string name="permdesc_controlVpn" msgid="762852603315861214">"Allows the app to control low-level features of Virtual Private Networks."</string>
     <string name="permlab_captureAudioOutput" msgid="6857134498402346708">"capture audio output"</string>
     <string name="permdesc_captureAudioOutput" msgid="6210597754212208853">"Allows the app to capture and redirect audio output."</string>
     <string name="permlab_captureAudioHotword" msgid="1890553935650349808">"Hotword detection"</string>
@@ -1902,4 +1904,12 @@
     <string name="zen_mode_next_alarm_summary" msgid="5915140424683747372">"Until next alarm at <xliff:g id="FORMATTEDTIME">%1$s</xliff:g>"</string>
     <string name="zen_mode_next_alarm_line_one" msgid="5537042951553420916">"Until next alarm"</string>
     <string name="muted_by" msgid="6147073845094180001">"Muted by <xliff:g id="THIRD_PARTY">%1$s</xliff:g>"</string>
+    <string name="system_error_wipe_data" msgid="6608165524785354962">"There\'s an internal problem with your device, and it may be unstable until you factory data reset."</string>
+    <string name="system_error_manufacturer" msgid="8086872414744210668">"There\'s an internal problem with your device. Contact your manufacturer for details."</string>
+    <string name="stk_cc_ussd_to_dial" msgid="5202342984749947872">"USSD request is modified to DIAL request."</string>
+    <string name="stk_cc_ussd_to_ss" msgid="2345360594181405482">"USSD request is modified to SS request."</string>
+    <string name="stk_cc_ussd_to_ussd" msgid="7466087659967191653">"USSD request is modified to new USSD request."</string>
+    <string name="stk_cc_ss_to_dial" msgid="2151304435775557162">"SS request is modified to DIAL request."</string>
+    <string name="stk_cc_ss_to_ussd" msgid="3951862188105305589">"SS request is modified to USSD request."</string>
+    <string name="stk_cc_ss_to_ss" msgid="5470768854991452695">"SS request is modified to new SS request."</string>
 </resources>
diff --git a/core/res/res/values-es-rUS/strings.xml b/core/res/res/values-es-rUS/strings.xml
index 18424ab..e9fd79d 100644
--- a/core/res/res/values-es-rUS/strings.xml
+++ b/core/res/res/values-es-rUS/strings.xml
@@ -564,6 +564,8 @@
     <string name="permdesc_configureWifiDisplay" msgid="7916815158690218065">"Permite que la aplicación configure y se conecte a pantallas Wi-Fi."</string>
     <string name="permlab_controlWifiDisplay" msgid="393641276723695496">"controlar pantallas Wi-Fi"</string>
     <string name="permdesc_controlWifiDisplay" msgid="4543912292681826986">"Permite que la aplicación controle funciones de bajo nivel de las pantallas Wi-Fi."</string>
+    <string name="permlab_controlVpn" msgid="2618442789397588200">"controlar redes privadas virtuales"</string>
+    <string name="permdesc_controlVpn" msgid="762852603315861214">"Permite que la aplicación controle las funciones de bajo nivel de las redes privadas virtuales."</string>
     <string name="permlab_captureAudioOutput" msgid="6857134498402346708">"Capturar salida de audio"</string>
     <string name="permdesc_captureAudioOutput" msgid="6210597754212208853">"Permite que la aplicación capture y redirija la salida de audio."</string>
     <string name="permlab_captureAudioHotword" msgid="1890553935650349808">"Detectar palabras activas"</string>
@@ -1902,4 +1904,18 @@
     <string name="zen_mode_next_alarm_summary" msgid="5915140424683747372">"Hasta la próxima alarma a la(s) <xliff:g id="FORMATTEDTIME">%1$s</xliff:g>"</string>
     <string name="zen_mode_next_alarm_line_one" msgid="5537042951553420916">"Hasta la próxima alarma"</string>
     <string name="muted_by" msgid="6147073845094180001">"Silenciados por <xliff:g id="THIRD_PARTY">%1$s</xliff:g>"</string>
+    <string name="system_error_wipe_data" msgid="6608165524785354962">"Existe un problema interno con el dispositivo, de modo que el dispositivo puede estar inestable hasta que restablezcas la configuración de fábrica."</string>
+    <string name="system_error_manufacturer" msgid="8086872414744210668">"Existe un problema interno con el dispositivo. Comunícate con el fabricante para obtener más información."</string>
+    <!-- no translation found for stk_cc_ussd_to_dial (5202342984749947872) -->
+    <skip />
+    <!-- no translation found for stk_cc_ussd_to_ss (2345360594181405482) -->
+    <skip />
+    <!-- no translation found for stk_cc_ussd_to_ussd (7466087659967191653) -->
+    <skip />
+    <!-- no translation found for stk_cc_ss_to_dial (2151304435775557162) -->
+    <skip />
+    <!-- no translation found for stk_cc_ss_to_ussd (3951862188105305589) -->
+    <skip />
+    <!-- no translation found for stk_cc_ss_to_ss (5470768854991452695) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-es/strings.xml b/core/res/res/values-es/strings.xml
index a90ef65..a8bdbbd 100644
--- a/core/res/res/values-es/strings.xml
+++ b/core/res/res/values-es/strings.xml
@@ -564,6 +564,8 @@
     <string name="permdesc_configureWifiDisplay" msgid="7916815158690218065">"Permite que la aplicación configure pantallas Wi-Fi y se conecte a ellas."</string>
     <string name="permlab_controlWifiDisplay" msgid="393641276723695496">"controlar pantallas Wi-Fi"</string>
     <string name="permdesc_controlWifiDisplay" msgid="4543912292681826986">"Permite que la aplicación controle funciones de bajo nivel de pantallas Wi-Fi."</string>
+    <string name="permlab_controlVpn" msgid="2618442789397588200">"controlar redes privadas virtuales"</string>
+    <string name="permdesc_controlVpn" msgid="762852603315861214">"Permite que la aplicación controle funciones de bajo nivel de redes privadas virtuales."</string>
     <string name="permlab_captureAudioOutput" msgid="6857134498402346708">"capturar salida de audio"</string>
     <string name="permdesc_captureAudioOutput" msgid="6210597754212208853">"Permite que la aplicación capture y redirija la salida de audio."</string>
     <string name="permlab_captureAudioHotword" msgid="1890553935650349808">"Detectar palabras activas"</string>
@@ -1902,4 +1904,18 @@
     <string name="zen_mode_next_alarm_summary" msgid="5915140424683747372">"Hasta la próxima alarma a las <xliff:g id="FORMATTEDTIME">%1$s</xliff:g>"</string>
     <string name="zen_mode_next_alarm_line_one" msgid="5537042951553420916">"Hasta la próxima alarma"</string>
     <string name="muted_by" msgid="6147073845094180001">"Silenciado por <xliff:g id="THIRD_PARTY">%1$s</xliff:g>"</string>
+    <string name="system_error_wipe_data" msgid="6608165524785354962">"Se ha producido un problema interno en el dispositivo y es posible que este no sea estable hasta que restablezcas los datos de fábrica."</string>
+    <string name="system_error_manufacturer" msgid="8086872414744210668">"Se ha producido un problema interno en el dispositivo. Ponte en contacto con el fabricante para obtener más información."</string>
+    <!-- no translation found for stk_cc_ussd_to_dial (5202342984749947872) -->
+    <skip />
+    <!-- no translation found for stk_cc_ussd_to_ss (2345360594181405482) -->
+    <skip />
+    <!-- no translation found for stk_cc_ussd_to_ussd (7466087659967191653) -->
+    <skip />
+    <!-- no translation found for stk_cc_ss_to_dial (2151304435775557162) -->
+    <skip />
+    <!-- no translation found for stk_cc_ss_to_ussd (3951862188105305589) -->
+    <skip />
+    <!-- no translation found for stk_cc_ss_to_ss (5470768854991452695) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-et-rEE/strings.xml b/core/res/res/values-et-rEE/strings.xml
index 08b82a7..d6627da 100644
--- a/core/res/res/values-et-rEE/strings.xml
+++ b/core/res/res/values-et-rEE/strings.xml
@@ -564,6 +564,8 @@
     <string name="permdesc_configureWifiDisplay" msgid="7916815158690218065">"Lubab rakendusel seadistada WiFi-ekraane ja nendega ühendus luua."</string>
     <string name="permlab_controlWifiDisplay" msgid="393641276723695496">"WiFi-ekraanide juhtimine"</string>
     <string name="permdesc_controlWifiDisplay" msgid="4543912292681826986">"Lubab rakendusel juhtida WiFi-ekraanide madala taseme funktsioone."</string>
+    <string name="permlab_controlVpn" msgid="2618442789397588200">"virtuaalsete privaatvõrkudega juhtimine"</string>
+    <string name="permdesc_controlVpn" msgid="762852603315861214">"Lubab rakendusel juhtida virtuaalsete privaatvõrkude alamtaseme funktsioone."</string>
     <string name="permlab_captureAudioOutput" msgid="6857134498402346708">"heliväljundi jäädvustamine"</string>
     <string name="permdesc_captureAudioOutput" msgid="6210597754212208853">"Lubab rakendusel jäädvustada ja ümber suunata heliväljundit."</string>
     <string name="permlab_captureAudioHotword" msgid="1890553935650349808">"Otsetee sõna tuvastamine"</string>
@@ -1902,4 +1904,18 @@
     <string name="zen_mode_next_alarm_summary" msgid="5915140424683747372">"Kuni järgmise alarmini <xliff:g id="FORMATTEDTIME">%1$s</xliff:g>"</string>
     <string name="zen_mode_next_alarm_line_one" msgid="5537042951553420916">"Kuni järgmise alarmini"</string>
     <string name="muted_by" msgid="6147073845094180001">"<xliff:g id="THIRD_PARTY">%1$s</xliff:g> vaigistas"</string>
+    <string name="system_error_wipe_data" msgid="6608165524785354962">"Seadmes ilmnes sisemine probleem ja seade võib olla ebastabiilne seni, kuni lähtestate seadme tehase andmetele."</string>
+    <string name="system_error_manufacturer" msgid="8086872414744210668">"Seadmes ilmnes sisemine probleem. Üksikasjaliku teabe saamiseks võtke ühendust tootjaga."</string>
+    <!-- no translation found for stk_cc_ussd_to_dial (5202342984749947872) -->
+    <skip />
+    <!-- no translation found for stk_cc_ussd_to_ss (2345360594181405482) -->
+    <skip />
+    <!-- no translation found for stk_cc_ussd_to_ussd (7466087659967191653) -->
+    <skip />
+    <!-- no translation found for stk_cc_ss_to_dial (2151304435775557162) -->
+    <skip />
+    <!-- no translation found for stk_cc_ss_to_ussd (3951862188105305589) -->
+    <skip />
+    <!-- no translation found for stk_cc_ss_to_ss (5470768854991452695) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-eu-rES/strings.xml b/core/res/res/values-eu-rES/strings.xml
index bc4912c..aa7d6c4 100644
--- a/core/res/res/values-eu-rES/strings.xml
+++ b/core/res/res/values-eu-rES/strings.xml
@@ -564,6 +564,8 @@
     <string name="permdesc_configureWifiDisplay" msgid="7916815158690218065">"Wi-Fi pantailak konfiguratzeko eta haietara konektatzeko baimena ematen die aplikazioei."</string>
     <string name="permlab_controlWifiDisplay" msgid="393641276723695496">"Wi-Fi pantailak kontrolatzea"</string>
     <string name="permdesc_controlWifiDisplay" msgid="4543912292681826986">"Wi-Fi pantailetako behe-mailako eginbideak kontrolatzeko baimena ematen die aplikazioei."</string>
+    <string name="permlab_controlVpn" msgid="2618442789397588200">"Kontrolatu sare pribatu birtualak"</string>
+    <string name="permdesc_controlVpn" msgid="762852603315861214">"Sare pribatu birtualen behe-mailako eginbideak kontrolatzea baimentzen die aplikazioei."</string>
     <string name="permlab_captureAudioOutput" msgid="6857134498402346708">"Grabatu audio-irteera"</string>
     <string name="permdesc_captureAudioOutput" msgid="6210597754212208853">"Audio-irteera grabatzeko eta birbideratzeko aukera ematen die aplikazioei."</string>
     <string name="permlab_captureAudioHotword" msgid="1890553935650349808">"Hauteman Hotword"</string>
@@ -1902,4 +1904,18 @@
     <string name="zen_mode_next_alarm_summary" msgid="5915140424683747372">"Hurrengo alarmara arte (<xliff:g id="FORMATTEDTIME">%1$s</xliff:g>)"</string>
     <string name="zen_mode_next_alarm_line_one" msgid="5537042951553420916">"Hurrengo alarmara arte"</string>
     <string name="muted_by" msgid="6147073845094180001">"Audioa desaktibatu da (<xliff:g id="THIRD_PARTY">%1$s</xliff:g>)"</string>
+    <string name="system_error_wipe_data" msgid="6608165524785354962">"Barneko arazo bat dago zure gailuan eta agian ezegonkor egongo da jatorrizko datuak berrezartzen dituzun arte."</string>
+    <string name="system_error_manufacturer" msgid="8086872414744210668">"Barneko arazo bat dago zure gailuan. Xehetasunak jakiteko, jarri fabrikatzailearekin harremanetan."</string>
+    <!-- no translation found for stk_cc_ussd_to_dial (5202342984749947872) -->
+    <skip />
+    <!-- no translation found for stk_cc_ussd_to_ss (2345360594181405482) -->
+    <skip />
+    <!-- no translation found for stk_cc_ussd_to_ussd (7466087659967191653) -->
+    <skip />
+    <!-- no translation found for stk_cc_ss_to_dial (2151304435775557162) -->
+    <skip />
+    <!-- no translation found for stk_cc_ss_to_ussd (3951862188105305589) -->
+    <skip />
+    <!-- no translation found for stk_cc_ss_to_ss (5470768854991452695) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-fa/strings.xml b/core/res/res/values-fa/strings.xml
index 0ddb458..51ba165 100644
--- a/core/res/res/values-fa/strings.xml
+++ b/core/res/res/values-fa/strings.xml
@@ -564,6 +564,8 @@
     <string name="permdesc_configureWifiDisplay" msgid="7916815158690218065">"‏به برنامه اجازه می‌دهد تا اتصال به صفحات نمایش Wi‑Fi را پیکربندی کند."</string>
     <string name="permlab_controlWifiDisplay" msgid="393641276723695496">"‏کنترل صفحه نمایش‌های Wi‑Fi"</string>
     <string name="permdesc_controlWifiDisplay" msgid="4543912292681826986">"‏به برنامه اجازه می‌دهد که ویژگی‌های سطح پایین صفحه‌های نمایش Wi‑Fi را کنترل کند."</string>
+    <string name="permlab_controlVpn" msgid="2618442789397588200">"کنترل شبکه‌های خصوصی مجازی"</string>
+    <string name="permdesc_controlVpn" msgid="762852603315861214">"به برنامه امکان کنترل ویژگی‌های سطح پایین شبکه‌های خصوصی مجازی را می‌دهد."</string>
     <string name="permlab_captureAudioOutput" msgid="6857134498402346708">"ضبط خروجی صدا"</string>
     <string name="permdesc_captureAudioOutput" msgid="6210597754212208853">"به برنامه امکان می‌دهد خروجی صدا را ضبط و هدایت کند."</string>
     <string name="permlab_captureAudioHotword" msgid="1890553935650349808">"تشخیص کلیدگفته"</string>
@@ -1902,4 +1904,18 @@
     <string name="zen_mode_next_alarm_summary" msgid="5915140424683747372">"تا هشدار بعدی در <xliff:g id="FORMATTEDTIME">%1$s</xliff:g>"</string>
     <string name="zen_mode_next_alarm_line_one" msgid="5537042951553420916">"تا هشدار بعدی"</string>
     <string name="muted_by" msgid="6147073845094180001">"<xliff:g id="THIRD_PARTY">%1$s</xliff:g> آن را بی‌صدا کرد"</string>
+    <string name="system_error_wipe_data" msgid="6608165524785354962">"دستگاهتان یک مشکل داخلی دارد، و ممکن است تا زمانی که بازنشانی به داده کارخانه انجام نگیرد، بی‌ثبات بماند."</string>
+    <string name="system_error_manufacturer" msgid="8086872414744210668">"دستگاهتان یک مشکل داخلی دارد. برای جزئیات آن با سازنده‌تان تماس بگیرید."</string>
+    <!-- no translation found for stk_cc_ussd_to_dial (5202342984749947872) -->
+    <skip />
+    <!-- no translation found for stk_cc_ussd_to_ss (2345360594181405482) -->
+    <skip />
+    <!-- no translation found for stk_cc_ussd_to_ussd (7466087659967191653) -->
+    <skip />
+    <!-- no translation found for stk_cc_ss_to_dial (2151304435775557162) -->
+    <skip />
+    <!-- no translation found for stk_cc_ss_to_ussd (3951862188105305589) -->
+    <skip />
+    <!-- no translation found for stk_cc_ss_to_ss (5470768854991452695) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-fi/strings.xml b/core/res/res/values-fi/strings.xml
index a484cf7..f39abf1 100644
--- a/core/res/res/values-fi/strings.xml
+++ b/core/res/res/values-fi/strings.xml
@@ -564,6 +564,8 @@
     <string name="permdesc_configureWifiDisplay" msgid="7916815158690218065">"Antaa sovelluksen määrittää wifi-näyttöjä ja muodostaa yhteyden niihin."</string>
     <string name="permlab_controlWifiDisplay" msgid="393641276723695496">"hallitse wifi-näyttöjä"</string>
     <string name="permdesc_controlWifiDisplay" msgid="4543912292681826986">"Antaa sovelluksen hallita wifi-näyttöjen matalan tason ominaisuuksia."</string>
+    <string name="permlab_controlVpn" msgid="2618442789397588200">"Hallita virtuaalisia yksityisverkkoja."</string>
+    <string name="permdesc_controlVpn" msgid="762852603315861214">"Sallii sovelluksen hallita virtuaalisten yksityisverkkojen alempien tasojen ominaisuuksia."</string>
     <string name="permlab_captureAudioOutput" msgid="6857134498402346708">"äänentoiston kaappaus"</string>
     <string name="permdesc_captureAudioOutput" msgid="6210597754212208853">"Antaa sovellukselle luvan äänentoiston kaappaamiseen ja uudelleenohjaamiseen."</string>
     <string name="permlab_captureAudioHotword" msgid="1890553935650349808">"Toimintosanan tunnistus"</string>
@@ -1902,4 +1904,18 @@
     <string name="zen_mode_next_alarm_summary" msgid="5915140424683747372">"Seuraavaan herätykseen saakka (<xliff:g id="FORMATTEDTIME">%1$s</xliff:g>)"</string>
     <string name="zen_mode_next_alarm_line_one" msgid="5537042951553420916">"Seuraavaan herätykseen saakka"</string>
     <string name="muted_by" msgid="6147073845094180001">"Mykistänyt <xliff:g id="THIRD_PARTY">%1$s</xliff:g>"</string>
+    <string name="system_error_wipe_data" msgid="6608165524785354962">"Laitteellasi on sisäinen ongelma, joka aiheuttaa epävakautta. Voit korjata tilanteen palauttamalla tehdasasetukset."</string>
+    <string name="system_error_manufacturer" msgid="8086872414744210668">"Laitteesi yhdistäminen ei onnistu sisäisen virheen takia. Saat lisätietoja valmistajalta."</string>
+    <!-- no translation found for stk_cc_ussd_to_dial (5202342984749947872) -->
+    <skip />
+    <!-- no translation found for stk_cc_ussd_to_ss (2345360594181405482) -->
+    <skip />
+    <!-- no translation found for stk_cc_ussd_to_ussd (7466087659967191653) -->
+    <skip />
+    <!-- no translation found for stk_cc_ss_to_dial (2151304435775557162) -->
+    <skip />
+    <!-- no translation found for stk_cc_ss_to_ussd (3951862188105305589) -->
+    <skip />
+    <!-- no translation found for stk_cc_ss_to_ss (5470768854991452695) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-fr-rCA/strings.xml b/core/res/res/values-fr-rCA/strings.xml
index 8f08926..6925454 100644
--- a/core/res/res/values-fr-rCA/strings.xml
+++ b/core/res/res/values-fr-rCA/strings.xml
@@ -564,6 +564,8 @@
     <string name="permdesc_configureWifiDisplay" msgid="7916815158690218065">"Permet à l\'application de configurer des écrans Wi-Fi et de s\'y connecter."</string>
     <string name="permlab_controlWifiDisplay" msgid="393641276723695496">"contrôler les écrans Wi-Fi"</string>
     <string name="permdesc_controlWifiDisplay" msgid="4543912292681826986">"Permet à l\'application de contrôler les fonctionnalités de base des écrans Wi-Fi."</string>
+    <string name="permlab_controlVpn" msgid="2618442789397588200">"commander les réseaux privés virtuels"</string>
+    <string name="permdesc_controlVpn" msgid="762852603315861214">"Permet à l\'application de commander les fonctions de bas niveau des réseaux privés virtuels."</string>
     <string name="permlab_captureAudioOutput" msgid="6857134498402346708">"capturer la sortie audio"</string>
     <string name="permdesc_captureAudioOutput" msgid="6210597754212208853">"Autoriser l\'application à capturer et à rediriger la sortie audio."</string>
     <string name="permlab_captureAudioHotword" msgid="1890553935650349808">"Détection de mots clés"</string>
@@ -1902,4 +1904,18 @@
     <string name="zen_mode_next_alarm_summary" msgid="5915140424683747372">"Jusqu\'à la prochaine alarme, à <xliff:g id="FORMATTEDTIME">%1$s</xliff:g>"</string>
     <string name="zen_mode_next_alarm_line_one" msgid="5537042951553420916">"Jusqu\'à la prochaine alarme"</string>
     <string name="muted_by" msgid="6147073845094180001">"Mis en sourdine par <xliff:g id="THIRD_PARTY">%1$s</xliff:g>"</string>
+    <string name="system_error_wipe_data" msgid="6608165524785354962">"Un problème interne est survenu avec votre appareil. Il se peut qu\'il soit instable jusqu\'à ce que vous le réinitialisiez à sa configuration d\'usine."</string>
+    <string name="system_error_manufacturer" msgid="8086872414744210668">"Un problème interne est survenu avec votre appareil. Communiquez avec le fabricant pour obtenir plus de détails."</string>
+    <!-- no translation found for stk_cc_ussd_to_dial (5202342984749947872) -->
+    <skip />
+    <!-- no translation found for stk_cc_ussd_to_ss (2345360594181405482) -->
+    <skip />
+    <!-- no translation found for stk_cc_ussd_to_ussd (7466087659967191653) -->
+    <skip />
+    <!-- no translation found for stk_cc_ss_to_dial (2151304435775557162) -->
+    <skip />
+    <!-- no translation found for stk_cc_ss_to_ussd (3951862188105305589) -->
+    <skip />
+    <!-- no translation found for stk_cc_ss_to_ss (5470768854991452695) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-fr/strings.xml b/core/res/res/values-fr/strings.xml
index 95d58ad..def3d35c 100644
--- a/core/res/res/values-fr/strings.xml
+++ b/core/res/res/values-fr/strings.xml
@@ -564,6 +564,8 @@
     <string name="permdesc_configureWifiDisplay" msgid="7916815158690218065">"Permet à l\'application de configurer des écrans Wi-Fi et de s\'y connecter."</string>
     <string name="permlab_controlWifiDisplay" msgid="393641276723695496">"contrôler les écrans Wi-Fi"</string>
     <string name="permdesc_controlWifiDisplay" msgid="4543912292681826986">"Permet à l\'application de contrôler les fonctionnalités de base des écrans Wi-Fi."</string>
+    <string name="permlab_controlVpn" msgid="2618442789397588200">"contrôler les réseaux privés virtuels"</string>
+    <string name="permdesc_controlVpn" msgid="762852603315861214">"Permettre à l\'application de contrôler les fonctionnalités de base des réseaux privés virtuels"</string>
     <string name="permlab_captureAudioOutput" msgid="6857134498402346708">"enregistrer les sorties audio"</string>
     <string name="permdesc_captureAudioOutput" msgid="6210597754212208853">"Autoriser l\'application à enregistrer et à rediriger les sorties audio"</string>
     <string name="permlab_captureAudioHotword" msgid="1890553935650349808">"Détection de mot clé"</string>
@@ -1902,4 +1904,18 @@
     <string name="zen_mode_next_alarm_summary" msgid="5915140424683747372">"Jusqu\'à la prochaine alarme à <xliff:g id="FORMATTEDTIME">%1$s</xliff:g>"</string>
     <string name="zen_mode_next_alarm_line_one" msgid="5537042951553420916">"Jusqu\'à la prochaine alarme"</string>
     <string name="muted_by" msgid="6147073845094180001">"Son coupé par : <xliff:g id="THIRD_PARTY">%1$s</xliff:g>"</string>
+    <string name="system_error_wipe_data" msgid="6608165524785354962">"Un problème interne lié à votre appareil est survenu. Ce dernier risque d\'être instable jusqu\'à ce que vous rétablissiez la configuration d\'usine."</string>
+    <string name="system_error_manufacturer" msgid="8086872414744210668">"Un problème interne lié à votre appareil est survenu. Veuillez contacter le fabricant pour en savoir plus."</string>
+    <!-- no translation found for stk_cc_ussd_to_dial (5202342984749947872) -->
+    <skip />
+    <!-- no translation found for stk_cc_ussd_to_ss (2345360594181405482) -->
+    <skip />
+    <!-- no translation found for stk_cc_ussd_to_ussd (7466087659967191653) -->
+    <skip />
+    <!-- no translation found for stk_cc_ss_to_dial (2151304435775557162) -->
+    <skip />
+    <!-- no translation found for stk_cc_ss_to_ussd (3951862188105305589) -->
+    <skip />
+    <!-- no translation found for stk_cc_ss_to_ss (5470768854991452695) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-gl-rES/strings.xml b/core/res/res/values-gl-rES/strings.xml
index c6264b9..0380519 100644
--- a/core/res/res/values-gl-rES/strings.xml
+++ b/core/res/res/values-gl-rES/strings.xml
@@ -564,6 +564,8 @@
     <string name="permdesc_configureWifiDisplay" msgid="7916815158690218065">"Permite á aplicación configurar e conectarse a pantallas wifi."</string>
     <string name="permlab_controlWifiDisplay" msgid="393641276723695496">"controlar pantallas wifi"</string>
     <string name="permdesc_controlWifiDisplay" msgid="4543912292681826986">"Permite á aplicación controlar funcións de baixo nivel de pantallas wifi."</string>
+    <string name="permlab_controlVpn" msgid="2618442789397588200">"controlar redes virtuais privadas"</string>
+    <string name="permdesc_controlVpn" msgid="762852603315861214">"Permite que a aplicación controle as funcións de nivel básico das redes virtuais privadas."</string>
     <string name="permlab_captureAudioOutput" msgid="6857134498402346708">"capturar saída de audio"</string>
     <string name="permdesc_captureAudioOutput" msgid="6210597754212208853">"Permite á aplicación capturar e redireccionar a saída de audio."</string>
     <string name="permlab_captureAudioHotword" msgid="1890553935650349808">"Detección de palabras activas"</string>
@@ -833,8 +835,8 @@
     <string name="permdesc_handoverStatus" msgid="4788144087245714948">"Permite a esta aplicación recibir información acerca das transferencias actuais de Android Beam"</string>
     <string name="permlab_removeDrmCertificates" msgid="7044888287209892751">"eliminar certificados DRM"</string>
     <string name="permdesc_removeDrmCertificates" msgid="7272999075113400993">"Permite a unha aplicación eliminar os certificados DRM. As aplicacións normais non o deberían precisar nunca."</string>
-    <string name="permlab_bindCarrierMessagingService" msgid="1490229371796969158">"vincular a un servizo de mensaxería do operador"</string>
-    <string name="permdesc_bindCarrierMessagingService" msgid="2762882888502113944">"Permite ao propietario vincularse á interface de nivel superior dun servizo de mensaxería do operador. As aplicacións normais non deberían necesitar este permiso."</string>
+    <string name="permlab_bindCarrierMessagingService" msgid="1490229371796969158">"vincular a un servizo de mensaxería"</string>
+    <string name="permdesc_bindCarrierMessagingService" msgid="2762882888502113944">"Permite ao propietario vincularse á interface de nivel superior dun servizo de mensaxería. As aplicacións normais non deberían necesitar este permiso."</string>
     <string name="policylab_limitPassword" msgid="4497420728857585791">"Establecer as normas de contrasinal"</string>
     <string name="policydesc_limitPassword" msgid="3252114203919510394">"Controlar a lonxitude e os caracteres permitidos nos contrasinais de desbloqueo da pantalla."</string>
     <string name="policylab_watchLogin" msgid="914130646942199503">"Supervisar os intentos de desbloqueo da pantalla"</string>
@@ -1902,4 +1904,18 @@
     <string name="zen_mode_next_alarm_summary" msgid="5915140424683747372">"Ata que soe a seguinte alarma ás <xliff:g id="FORMATTEDTIME">%1$s</xliff:g>"</string>
     <string name="zen_mode_next_alarm_line_one" msgid="5537042951553420916">"Ata que soe a seguinte alarma"</string>
     <string name="muted_by" msgid="6147073845094180001">"Silenciado por <xliff:g id="THIRD_PARTY">%1$s</xliff:g>"</string>
+    <string name="system_error_wipe_data" msgid="6608165524785354962">"Produciuse un problema interno co teu dispositivo e quizais estea inestable ata o restablecemento dos datos de fábrica."</string>
+    <string name="system_error_manufacturer" msgid="8086872414744210668">"Produciuse un problema interno co teu dispositivo. Contacta co teu fabricante para obter máis detalles."</string>
+    <!-- no translation found for stk_cc_ussd_to_dial (5202342984749947872) -->
+    <skip />
+    <!-- no translation found for stk_cc_ussd_to_ss (2345360594181405482) -->
+    <skip />
+    <!-- no translation found for stk_cc_ussd_to_ussd (7466087659967191653) -->
+    <skip />
+    <!-- no translation found for stk_cc_ss_to_dial (2151304435775557162) -->
+    <skip />
+    <!-- no translation found for stk_cc_ss_to_ussd (3951862188105305589) -->
+    <skip />
+    <!-- no translation found for stk_cc_ss_to_ss (5470768854991452695) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-hi/strings.xml b/core/res/res/values-hi/strings.xml
index cdff615..ab2edfc 100644
--- a/core/res/res/values-hi/strings.xml
+++ b/core/res/res/values-hi/strings.xml
@@ -564,6 +564,8 @@
     <string name="permdesc_configureWifiDisplay" msgid="7916815158690218065">"ऐप्स  को कॉन्फ़िगर करने देता है और Wifi डिस्प्ले से कनेक्ट करता है."</string>
     <string name="permlab_controlWifiDisplay" msgid="393641276723695496">"Wifi डिस्प्ले को नियंत्रित करें"</string>
     <string name="permdesc_controlWifiDisplay" msgid="4543912292681826986">"ऐप्स  को Wifi डिस्प्ले की निम्न-स्तर की सुविधाएं नियंत्रित करने देता है."</string>
+    <string name="permlab_controlVpn" msgid="2618442789397588200">"आभासी निजी नेटवर्क को नियंत्रित करें"</string>
+    <string name="permdesc_controlVpn" msgid="762852603315861214">"ऐप्‍स को आभासी निजी नेटवर्क की निम्‍न-स्‍तर की सुविधाओं को नियंत्रित करने देती है."</string>
     <string name="permlab_captureAudioOutput" msgid="6857134498402346708">"ऑडियो आउटपुट को कैप्‍चर करें"</string>
     <string name="permdesc_captureAudioOutput" msgid="6210597754212208853">"ऐप्स को ऑडियो आउटपुट को कैप्‍चर और रीडायरेक्‍ट करने देता है."</string>
     <string name="permlab_captureAudioHotword" msgid="1890553935650349808">"हॉटवर्ड पहचान"</string>
@@ -1902,4 +1904,18 @@
     <string name="zen_mode_next_alarm_summary" msgid="5915140424683747372">"<xliff:g id="FORMATTEDTIME">%1$s</xliff:g> पर अगले अलार्म तक"</string>
     <string name="zen_mode_next_alarm_line_one" msgid="5537042951553420916">"अगले अलार्म तक"</string>
     <string name="muted_by" msgid="6147073845094180001">"<xliff:g id="THIRD_PARTY">%1$s</xliff:g> द्वारा म्यूट किया गया"</string>
+    <string name="system_error_wipe_data" msgid="6608165524785354962">"आपके डिवाइस के साथ कोई आंतरिक त्रुटि हुई और यह तब तक अस्‍थिर रह सकता है, जब तक आप फ़ैक्‍टरी डेटा रीसेट नहीं करते."</string>
+    <string name="system_error_manufacturer" msgid="8086872414744210668">"आपके डिवाइस के साथ कोई आंतरिक त्रुटि हुई. विवरणों के लिए अपने निर्माता से संपर्क करें."</string>
+    <!-- no translation found for stk_cc_ussd_to_dial (5202342984749947872) -->
+    <skip />
+    <!-- no translation found for stk_cc_ussd_to_ss (2345360594181405482) -->
+    <skip />
+    <!-- no translation found for stk_cc_ussd_to_ussd (7466087659967191653) -->
+    <skip />
+    <!-- no translation found for stk_cc_ss_to_dial (2151304435775557162) -->
+    <skip />
+    <!-- no translation found for stk_cc_ss_to_ussd (3951862188105305589) -->
+    <skip />
+    <!-- no translation found for stk_cc_ss_to_ss (5470768854991452695) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-hr/strings.xml b/core/res/res/values-hr/strings.xml
index 6c82b25..2315075 100644
--- a/core/res/res/values-hr/strings.xml
+++ b/core/res/res/values-hr/strings.xml
@@ -564,6 +564,8 @@
     <string name="permdesc_configureWifiDisplay" msgid="7916815158690218065">"Omogućuje aplikaciji konfiguriranje i povezivanje s Wi-Fi zaslonima."</string>
     <string name="permlab_controlWifiDisplay" msgid="393641276723695496">"upravljaj Wifi zaslonima"</string>
     <string name="permdesc_controlWifiDisplay" msgid="4543912292681826986">"Omogućuje aplikaciji upravljanje značajkama Wi-Fi zaslona niske razine."</string>
+    <string name="permlab_controlVpn" msgid="2618442789397588200">"upravljanje virtualnim privatnim mrežama"</string>
+    <string name="permdesc_controlVpn" msgid="762852603315861214">"Aplikaciji omogućuje upravljanje značajkama niske razine na virtualnim privatnim mrežama."</string>
     <string name="permlab_captureAudioOutput" msgid="6857134498402346708">"primanje audioizlaza"</string>
     <string name="permdesc_captureAudioOutput" msgid="6210597754212208853">"Omogućuje aplikaciji primanje i preusmjeravanje audioizlaza."</string>
     <string name="permlab_captureAudioHotword" msgid="1890553935650349808">"Otkrivanje pokretača značajke"</string>
@@ -1902,4 +1904,18 @@
     <string name="zen_mode_next_alarm_summary" msgid="5915140424683747372">"Do sljedećeg alarma u <xliff:g id="FORMATTEDTIME">%1$s</xliff:g>"</string>
     <string name="zen_mode_next_alarm_line_one" msgid="5537042951553420916">"Do sljedećeg alarma"</string>
     <string name="muted_by" msgid="6147073845094180001">"Zvuk je isklj. treća strana <xliff:g id="THIRD_PARTY">%1$s</xliff:g>"</string>
+    <string name="system_error_wipe_data" msgid="6608165524785354962">"Na vašem uređaju postoji interni problem i možda neće biti stabilan dok ga ne vratite na tvorničko stanje."</string>
+    <string name="system_error_manufacturer" msgid="8086872414744210668">"Na vašem uređaju postoji interni problem. Obratite se proizvođaču za više pojedinosti."</string>
+    <!-- no translation found for stk_cc_ussd_to_dial (5202342984749947872) -->
+    <skip />
+    <!-- no translation found for stk_cc_ussd_to_ss (2345360594181405482) -->
+    <skip />
+    <!-- no translation found for stk_cc_ussd_to_ussd (7466087659967191653) -->
+    <skip />
+    <!-- no translation found for stk_cc_ss_to_dial (2151304435775557162) -->
+    <skip />
+    <!-- no translation found for stk_cc_ss_to_ussd (3951862188105305589) -->
+    <skip />
+    <!-- no translation found for stk_cc_ss_to_ss (5470768854991452695) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-hu/strings.xml b/core/res/res/values-hu/strings.xml
index 79f36c0..1e56caf 100644
--- a/core/res/res/values-hu/strings.xml
+++ b/core/res/res/values-hu/strings.xml
@@ -564,6 +564,8 @@
     <string name="permdesc_configureWifiDisplay" msgid="7916815158690218065">"Lehetővé teszi, hogy az alkalmazás Wi-Fi kijelzőket konfiguráljon, és csatlakozzon hozzájuk."</string>
     <string name="permlab_controlWifiDisplay" msgid="393641276723695496">"Wi-Fi kijelzők irányítása"</string>
     <string name="permdesc_controlWifiDisplay" msgid="4543912292681826986">"Lehetővé teszi, hogy az alkalmazás irányítsa a Wi-Fi kijelzők alacsonyabb szintű funkcióit."</string>
+    <string name="permlab_controlVpn" msgid="2618442789397588200">"virtuális magánhálózatok kezelése"</string>
+    <string name="permdesc_controlVpn" msgid="762852603315861214">"Lehetővé teszi, hogy az alkalmazás kezelje a virtuális magánhálózatok alacsony szintű funkcióit."</string>
     <string name="permlab_captureAudioOutput" msgid="6857134498402346708">"audiokimenet rögzítése"</string>
     <string name="permdesc_captureAudioOutput" msgid="6210597754212208853">"Engedélyezi az alkalmazásnak a hangkimenet rögzítését és átirányítását."</string>
     <string name="permlab_captureAudioHotword" msgid="1890553935650349808">"Hotwordérzékelés"</string>
@@ -1902,4 +1904,18 @@
     <string name="zen_mode_next_alarm_summary" msgid="5915140424683747372">"A következő ébresztésig ekkor: <xliff:g id="FORMATTEDTIME">%1$s</xliff:g>"</string>
     <string name="zen_mode_next_alarm_line_one" msgid="5537042951553420916">"A következő ébresztésig"</string>
     <string name="muted_by" msgid="6147073845094180001">"A(z) <xliff:g id="THIRD_PARTY">%1$s</xliff:g> elnémította"</string>
+    <string name="system_error_wipe_data" msgid="6608165524785354962">"Belső probléma van az eszközzel, és instabil lehet, amíg vissza nem állítja a gyári adatokat."</string>
+    <string name="system_error_manufacturer" msgid="8086872414744210668">"Belső probléma van az eszközzel. A részletekért vegye fel a kapcsolatot a gyártóval."</string>
+    <!-- no translation found for stk_cc_ussd_to_dial (5202342984749947872) -->
+    <skip />
+    <!-- no translation found for stk_cc_ussd_to_ss (2345360594181405482) -->
+    <skip />
+    <!-- no translation found for stk_cc_ussd_to_ussd (7466087659967191653) -->
+    <skip />
+    <!-- no translation found for stk_cc_ss_to_dial (2151304435775557162) -->
+    <skip />
+    <!-- no translation found for stk_cc_ss_to_ussd (3951862188105305589) -->
+    <skip />
+    <!-- no translation found for stk_cc_ss_to_ss (5470768854991452695) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-hy-rAM/strings.xml b/core/res/res/values-hy-rAM/strings.xml
index ec4e551..018dbb3 100644
--- a/core/res/res/values-hy-rAM/strings.xml
+++ b/core/res/res/values-hy-rAM/strings.xml
@@ -564,6 +564,8 @@
     <string name="permdesc_configureWifiDisplay" msgid="7916815158690218065">"Թույլ է տալիս հավելվածին կարգավորել և միանալ WiFi ցուցադրիչներին:"</string>
     <string name="permlab_controlWifiDisplay" msgid="393641276723695496">"կառավարել Wifi-ի ցուցադրումը"</string>
     <string name="permdesc_controlWifiDisplay" msgid="4543912292681826986">"Թույլ է տալիս հավելվածին կառավարել WiFi ցուցադրիչների ցածր մակարդակի գործառույթները:"</string>
+    <string name="permlab_controlVpn" msgid="2618442789397588200">"վերահսկել Վիրտուալ մասնավոր ցանցերը"</string>
+    <string name="permdesc_controlVpn" msgid="762852603315861214">"Թույլ է տալիս հավելվածին վերահսկել Վիրտուալ մասնավոր ցանցերի ցածր մակարդակի գործառույթները:"</string>
     <string name="permlab_captureAudioOutput" msgid="6857134498402346708">"պահել աուդիո արտածումը"</string>
     <string name="permdesc_captureAudioOutput" msgid="6210597754212208853">"Թույլ է տալիս ծրագրին պահել և վերահղել աուդիո արտածումը:"</string>
     <string name="permlab_captureAudioHotword" msgid="1890553935650349808">"Թեժ բառի հայտնաբերում"</string>
@@ -1902,4 +1904,18 @@
     <string name="zen_mode_next_alarm_summary" msgid="5915140424683747372">"Մինչև հաջորդ զարթուցիչը՝ <xliff:g id="FORMATTEDTIME">%1$s</xliff:g>"</string>
     <string name="zen_mode_next_alarm_line_one" msgid="5537042951553420916">"Մինչև հաջորդ զարթուցիչը"</string>
     <string name="muted_by" msgid="6147073845094180001">"Համրեցվել է <xliff:g id="THIRD_PARTY">%1$s</xliff:g>-ի կողմից"</string>
+    <string name="system_error_wipe_data" msgid="6608165524785354962">"Սարքում ներքին խնդիր է առաջացել և այն կարող է կրկնվել, եթե գործարանային տվյալների վերականգնում չկատարեք:"</string>
+    <string name="system_error_manufacturer" msgid="8086872414744210668">"Սարքում ներքին խնդիր է առաջացել: Մանրամասների համար կապվեք արտադրողի հետ:"</string>
+    <!-- no translation found for stk_cc_ussd_to_dial (5202342984749947872) -->
+    <skip />
+    <!-- no translation found for stk_cc_ussd_to_ss (2345360594181405482) -->
+    <skip />
+    <!-- no translation found for stk_cc_ussd_to_ussd (7466087659967191653) -->
+    <skip />
+    <!-- no translation found for stk_cc_ss_to_dial (2151304435775557162) -->
+    <skip />
+    <!-- no translation found for stk_cc_ss_to_ussd (3951862188105305589) -->
+    <skip />
+    <!-- no translation found for stk_cc_ss_to_ss (5470768854991452695) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-in/strings.xml b/core/res/res/values-in/strings.xml
index c5748e6..98556a2 100644
--- a/core/res/res/values-in/strings.xml
+++ b/core/res/res/values-in/strings.xml
@@ -34,7 +34,7 @@
     <string name="durationHourMinutes" msgid="9029176248692041549">"<xliff:g id="HOURS">%1$d</xliff:g> jam <xliff:g id="MINUTES">%2$d</xliff:g> mnt"</string>
     <string name="durationHourMinute" msgid="2741677355177402539">"<xliff:g id="HOURS">%1$d</xliff:g> jam <xliff:g id="MINUTES">%2$d</xliff:g> mnt"</string>
     <string name="durationMinutes" msgid="3134226679883579347">"<xliff:g id="MINUTES">%1$d</xliff:g> mnt"</string>
-    <string name="durationMinute" msgid="7155301744174623818">"<xliff:g id="MINUTES">%1$d</xliff:g> mnt"</string>
+    <string name="durationMinute" msgid="7155301744174623818">"<xliff:g id="MINUTES">%1$d</xliff:g> menit"</string>
     <string name="durationMinuteSeconds" msgid="1424656185379003751">"<xliff:g id="MINUTES">%1$d</xliff:g> mnt <xliff:g id="SECONDS">%2$d</xliff:g> dtk"</string>
     <string name="durationMinuteSecond" msgid="3989228718067466680">"<xliff:g id="MINUTES">%1$d</xliff:g> mnt <xliff:g id="SECONDS">%2$d</xliff:g> dtk"</string>
     <string name="durationSeconds" msgid="8050088505238241405">"<xliff:g id="SECONDS">%1$d</xliff:g> dtk"</string>
@@ -564,6 +564,8 @@
     <string name="permdesc_configureWifiDisplay" msgid="7916815158690218065">"Izinkan aplikasi mengonfigurasi dan terhubung ke tampilan Wi-Fi."</string>
     <string name="permlab_controlWifiDisplay" msgid="393641276723695496">"mengontrol tampilan Wi-Fi"</string>
     <string name="permdesc_controlWifiDisplay" msgid="4543912292681826986">"Izinkan aplikasi mengontrol fitur tingkat rendah dari tampilan Wi-Fi."</string>
+    <string name="permlab_controlVpn" msgid="2618442789397588200">"kontrol Jaringan Pribadi Maya"</string>
+    <string name="permdesc_controlVpn" msgid="762852603315861214">"Mengizinkan aplikasi untuk mengontrol fitur tingkat rendah dari Jaringan Pribadi Maya."</string>
     <string name="permlab_captureAudioOutput" msgid="6857134498402346708">"tangkap keluaran audio"</string>
     <string name="permdesc_captureAudioOutput" msgid="6210597754212208853">"Memungkinkan aplikasi menangkap dan mengalihkan keluaran audio."</string>
     <string name="permlab_captureAudioHotword" msgid="1890553935650349808">"Deteksi kata cepat"</string>
@@ -1902,4 +1904,18 @@
     <string name="zen_mode_next_alarm_summary" msgid="5915140424683747372">"Sampai alarm berikutnya pukul <xliff:g id="FORMATTEDTIME">%1$s</xliff:g>"</string>
     <string name="zen_mode_next_alarm_line_one" msgid="5537042951553420916">"Sampai alarm berikutnya"</string>
     <string name="muted_by" msgid="6147073845094180001">"Dinonaktifkan oleh <xliff:g id="THIRD_PARTY">%1$s</xliff:g>"</string>
+    <string name="system_error_wipe_data" msgid="6608165524785354962">"Ada masalah internal dengan perangkat, dan mungkin tidak stabil sampai dikembalikan ke setelan pabrik."</string>
+    <string name="system_error_manufacturer" msgid="8086872414744210668">"Ada masalah internal dengan perangkat. Hubungi pembuat perangkat untuk detail lengkap."</string>
+    <!-- no translation found for stk_cc_ussd_to_dial (5202342984749947872) -->
+    <skip />
+    <!-- no translation found for stk_cc_ussd_to_ss (2345360594181405482) -->
+    <skip />
+    <!-- no translation found for stk_cc_ussd_to_ussd (7466087659967191653) -->
+    <skip />
+    <!-- no translation found for stk_cc_ss_to_dial (2151304435775557162) -->
+    <skip />
+    <!-- no translation found for stk_cc_ss_to_ussd (3951862188105305589) -->
+    <skip />
+    <!-- no translation found for stk_cc_ss_to_ss (5470768854991452695) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-is-rIS/strings.xml b/core/res/res/values-is-rIS/strings.xml
index 5c9def4..a852cda 100644
--- a/core/res/res/values-is-rIS/strings.xml
+++ b/core/res/res/values-is-rIS/strings.xml
@@ -564,6 +564,8 @@
     <string name="permdesc_configureWifiDisplay" msgid="7916815158690218065">"Leyfir forriti að grunnstilla og tengjast þráðlausum skjáum."</string>
     <string name="permlab_controlWifiDisplay" msgid="393641276723695496">"stjórna þráðlausum skjáum"</string>
     <string name="permdesc_controlWifiDisplay" msgid="4543912292681826986">"Leyfir forriti að stjórna grunnvirkni þráðlausra skjáa."</string>
+    <string name="permlab_controlVpn" msgid="2618442789397588200">"stjórna VPN-sýndarnetum"</string>
+    <string name="permdesc_controlVpn" msgid="762852603315861214">"Leyfir forritinu að stjórna grunneiginleikum VPN-sýndarneta."</string>
     <string name="permlab_captureAudioOutput" msgid="6857134498402346708">"fanga hljóðúttak"</string>
     <string name="permdesc_captureAudioOutput" msgid="6210597754212208853">"Leyfir forriti að fanga og endurbeina hljóðúttaki."</string>
     <string name="permlab_captureAudioHotword" msgid="1890553935650349808">"Greining skipana"</string>
@@ -1902,4 +1904,18 @@
     <string name="zen_mode_next_alarm_summary" msgid="5915140424683747372">"Fram að næsta vekjara kl. <xliff:g id="FORMATTEDTIME">%1$s</xliff:g>"</string>
     <string name="zen_mode_next_alarm_line_one" msgid="5537042951553420916">"Fram að næsta vekjara"</string>
     <string name="muted_by" msgid="6147073845094180001">"<xliff:g id="THIRD_PARTY">%1$s</xliff:g> tók hljóðið af"</string>
+    <string name="system_error_wipe_data" msgid="6608165524785354962">"Innra vandamál kom upp í tækinu og það kann að vera óstöðugt þangað til þú núllstillir það."</string>
+    <string name="system_error_manufacturer" msgid="8086872414744210668">"Innra vandamál kom upp í tækinu. Hafðu samband við framleiðanda til að fá nánari upplýsingar."</string>
+    <!-- no translation found for stk_cc_ussd_to_dial (5202342984749947872) -->
+    <skip />
+    <!-- no translation found for stk_cc_ussd_to_ss (2345360594181405482) -->
+    <skip />
+    <!-- no translation found for stk_cc_ussd_to_ussd (7466087659967191653) -->
+    <skip />
+    <!-- no translation found for stk_cc_ss_to_dial (2151304435775557162) -->
+    <skip />
+    <!-- no translation found for stk_cc_ss_to_ussd (3951862188105305589) -->
+    <skip />
+    <!-- no translation found for stk_cc_ss_to_ss (5470768854991452695) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-it/strings.xml b/core/res/res/values-it/strings.xml
index e08b34f..8fc5786 100644
--- a/core/res/res/values-it/strings.xml
+++ b/core/res/res/values-it/strings.xml
@@ -564,6 +564,8 @@
     <string name="permdesc_configureWifiDisplay" msgid="7916815158690218065">"Consente all\'applicazione di configurare schermi Wi-Fi e di collegarsi a essi."</string>
     <string name="permlab_controlWifiDisplay" msgid="393641276723695496">"controllo di schermi Wi-Fi"</string>
     <string name="permdesc_controlWifiDisplay" msgid="4543912292681826986">"Consente all\'applicazione di controllare le funzioni di basso livello di schermi Wi-Fi."</string>
+    <string name="permlab_controlVpn" msgid="2618442789397588200">"controllo di reti private virtuali"</string>
+    <string name="permdesc_controlVpn" msgid="762852603315861214">"Consente all\'app di controllare le funzioni di basso livello di reti private virtuali."</string>
     <string name="permlab_captureAudioOutput" msgid="6857134498402346708">"acquisizione dell\'uscita audio"</string>
     <string name="permdesc_captureAudioOutput" msgid="6210597754212208853">"Consente all\'app di acquisire e reindirizzare l\'uscita audio."</string>
     <string name="permlab_captureAudioHotword" msgid="1890553935650349808">"Rilevamento hotword"</string>
@@ -1902,4 +1904,18 @@
     <string name="zen_mode_next_alarm_summary" msgid="5915140424683747372">"Fino alla prossima sveglia alle ore <xliff:g id="FORMATTEDTIME">%1$s</xliff:g>"</string>
     <string name="zen_mode_next_alarm_line_one" msgid="5537042951553420916">"Fino alla prossima sveglia"</string>
     <string name="muted_by" msgid="6147073845094180001">"Audio disattivato da <xliff:g id="THIRD_PARTY">%1$s</xliff:g>"</string>
+    <string name="system_error_wipe_data" msgid="6608165524785354962">"Si è verificato un problema interno con il dispositivo, che potrebbe essere instabile fino al ripristino dei dati di fabbrica."</string>
+    <string name="system_error_manufacturer" msgid="8086872414744210668">"Si è verificato un problema interno con il dispositivo. Per informazioni dettagliate, contatta il produttore."</string>
+    <!-- no translation found for stk_cc_ussd_to_dial (5202342984749947872) -->
+    <skip />
+    <!-- no translation found for stk_cc_ussd_to_ss (2345360594181405482) -->
+    <skip />
+    <!-- no translation found for stk_cc_ussd_to_ussd (7466087659967191653) -->
+    <skip />
+    <!-- no translation found for stk_cc_ss_to_dial (2151304435775557162) -->
+    <skip />
+    <!-- no translation found for stk_cc_ss_to_ussd (3951862188105305589) -->
+    <skip />
+    <!-- no translation found for stk_cc_ss_to_ss (5470768854991452695) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-iw/strings.xml b/core/res/res/values-iw/strings.xml
index a7f8870..d469ca8 100644
--- a/core/res/res/values-iw/strings.xml
+++ b/core/res/res/values-iw/strings.xml
@@ -564,6 +564,8 @@
     <string name="permdesc_configureWifiDisplay" msgid="7916815158690218065">"‏מאפשר לאפליקציה להגדיר ולהתחבר לתצוגות Wi-Fi."</string>
     <string name="permlab_controlWifiDisplay" msgid="393641276723695496">"‏שלוט בתצוגות Wi-Fi"</string>
     <string name="permdesc_controlWifiDisplay" msgid="4543912292681826986">"‏מאפשר לאפליקציה לשלוט בתכונות ברמה נמוכה של תצוגות Wi-Fi."</string>
+    <string name="permlab_controlVpn" msgid="2618442789397588200">"שליטה על רשתות וירטואליות פרטיות"</string>
+    <string name="permdesc_controlVpn" msgid="762852603315861214">"מאפשר לאפליקציה לקבוע תכונות ברמה נמוכה של רשתות וירטואליות פרטיות."</string>
     <string name="permlab_captureAudioOutput" msgid="6857134498402346708">"קליטת פלט אודיו"</string>
     <string name="permdesc_captureAudioOutput" msgid="6210597754212208853">"מאפשרת לאפליקציה לקלוט ולהפנות מחדש פלט אודיו."</string>
     <string name="permlab_captureAudioHotword" msgid="1890553935650349808">"זיהוי של מילת הפעלה"</string>
@@ -1902,4 +1904,12 @@
     <string name="zen_mode_next_alarm_summary" msgid="5915140424683747372">"עד ההתראה הבאה ב-<xliff:g id="FORMATTEDTIME">%1$s</xliff:g>"</string>
     <string name="zen_mode_next_alarm_line_one" msgid="5537042951553420916">"עד ההתראה הבאה"</string>
     <string name="muted_by" msgid="6147073845094180001">"הושתק על ידי <xliff:g id="THIRD_PARTY">%1$s</xliff:g>"</string>
+    <string name="system_error_wipe_data" msgid="6608165524785354962">"קיימת בעיה פנימית במכשיר שלך, וייתכן שהתפקוד שלו לא יהיה יציב עד שתבצע איפוס לנתוני היצרן."</string>
+    <string name="system_error_manufacturer" msgid="8086872414744210668">"קיימת בעיה פנימית במכשיר שלך. לקבלת פרטים, צור קשר עם היצרן."</string>
+    <string name="stk_cc_ussd_to_dial" msgid="5202342984749947872">"‏בקשת USSD שונתה לבקשת DIAL."</string>
+    <string name="stk_cc_ussd_to_ss" msgid="2345360594181405482">"‏בקשת USSD שונתה לבקשת SS."</string>
+    <string name="stk_cc_ussd_to_ussd" msgid="7466087659967191653">"‏בקשת USSD שונתה לבקשת USSD חדשה."</string>
+    <string name="stk_cc_ss_to_dial" msgid="2151304435775557162">"‏בקשת SS שונתה לבקשת DIAL."</string>
+    <string name="stk_cc_ss_to_ussd" msgid="3951862188105305589">"‏בקשת SS שונתה לבקשת USSD."</string>
+    <string name="stk_cc_ss_to_ss" msgid="5470768854991452695">"‏בקשת SS שונתה לבקשת SS חדשה."</string>
 </resources>
diff --git a/core/res/res/values-ja/strings.xml b/core/res/res/values-ja/strings.xml
index f44681d..93f6f79 100644
--- a/core/res/res/values-ja/strings.xml
+++ b/core/res/res/values-ja/strings.xml
@@ -564,6 +564,8 @@
     <string name="permdesc_configureWifiDisplay" msgid="7916815158690218065">"Wi-Fiディスプレイを設定して接続することをアプリに許可します。"</string>
     <string name="permlab_controlWifiDisplay" msgid="393641276723695496">"Wi-Fiディスプレイの制御"</string>
     <string name="permdesc_controlWifiDisplay" msgid="4543912292681826986">"Wi-Fiディスプレイの低レベル機能を制御することをアプリに許可します。"</string>
+    <string name="permlab_controlVpn" msgid="2618442789397588200">"仮想プライベートネットワークの制御"</string>
+    <string name="permdesc_controlVpn" msgid="762852603315861214">"仮想プライベートネットワークの低レベル機能を制御することをアプリに許可します。"</string>
     <string name="permlab_captureAudioOutput" msgid="6857134498402346708">"音声出力のキャプチャ"</string>
     <string name="permdesc_captureAudioOutput" msgid="6210597754212208853">"音声出力のキャプチャとリダイレクトをアプリに許可します。"</string>
     <string name="permlab_captureAudioHotword" msgid="1890553935650349808">"注目ワード検出"</string>
@@ -1902,4 +1904,18 @@
     <string name="zen_mode_next_alarm_summary" msgid="5915140424683747372">"次のアラーム(<xliff:g id="FORMATTEDTIME">%1$s</xliff:g>)まで"</string>
     <string name="zen_mode_next_alarm_line_one" msgid="5537042951553420916">"次のアラームまで"</string>
     <string name="muted_by" msgid="6147073845094180001">"<xliff:g id="THIRD_PARTY">%1$s</xliff:g>によりミュートになっています"</string>
+    <string name="system_error_wipe_data" msgid="6608165524785354962">"端末で内部的な問題が発生しました。データが初期化されるまで不安定になる可能性があります。"</string>
+    <string name="system_error_manufacturer" msgid="8086872414744210668">"端末で内部的な問題が発生しました。詳しくはメーカーにお問い合わせください。"</string>
+    <!-- no translation found for stk_cc_ussd_to_dial (5202342984749947872) -->
+    <skip />
+    <!-- no translation found for stk_cc_ussd_to_ss (2345360594181405482) -->
+    <skip />
+    <!-- no translation found for stk_cc_ussd_to_ussd (7466087659967191653) -->
+    <skip />
+    <!-- no translation found for stk_cc_ss_to_dial (2151304435775557162) -->
+    <skip />
+    <!-- no translation found for stk_cc_ss_to_ussd (3951862188105305589) -->
+    <skip />
+    <!-- no translation found for stk_cc_ss_to_ss (5470768854991452695) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-ka-rGE/strings.xml b/core/res/res/values-ka-rGE/strings.xml
index d6f48fd..eebaabf 100644
--- a/core/res/res/values-ka-rGE/strings.xml
+++ b/core/res/res/values-ka-rGE/strings.xml
@@ -564,6 +564,8 @@
     <string name="permdesc_configureWifiDisplay" msgid="7916815158690218065">"აპს შეეძლება Wifi ეკრანებთან დაკავშირება და დაკონფიგურირება."</string>
     <string name="permlab_controlWifiDisplay" msgid="393641276723695496">"Wifi ეკრანების მართვა"</string>
     <string name="permdesc_controlWifiDisplay" msgid="4543912292681826986">"აპს შეეძლება აკონტროლოს Wifi ეკრანების დაბალი დონის ფუნქციები."</string>
+    <string name="permlab_controlVpn" msgid="2618442789397588200">"ვირტუალური კერძო ქსელების კონტროლი"</string>
+    <string name="permdesc_controlVpn" msgid="762852603315861214">"საშუალებას აძლევს აპლიკაციას აკონტროლოს ვირტუალური პირადი ქსელების დაბალი დონის ფუნქციები."</string>
     <string name="permlab_captureAudioOutput" msgid="6857134498402346708">"გამომავალი აუდიოს დაჭერა"</string>
     <string name="permdesc_captureAudioOutput" msgid="6210597754212208853">"საშუალებას აძლევს აპს დაიჭიროს და გადაამისამართოს გამომავალი აუდიო."</string>
     <string name="permlab_captureAudioHotword" msgid="1890553935650349808">"ჯადოსნური სიტყვის პოვნა"</string>
@@ -1902,4 +1904,18 @@
     <string name="zen_mode_next_alarm_summary" msgid="5915140424683747372">"შემდეგ მაღვიძარამდე <xliff:g id="FORMATTEDTIME">%1$s</xliff:g>-ში"</string>
     <string name="zen_mode_next_alarm_line_one" msgid="5537042951553420916">"შემდეგ მაღვიძარამდე"</string>
     <string name="muted_by" msgid="6147073845094180001">"დადუმებულია <xliff:g id="THIRD_PARTY">%1$s</xliff:g>-ის მიერ"</string>
+    <string name="system_error_wipe_data" msgid="6608165524785354962">"ფიქსირდება თქვენი მ ოწყობილობის შიდა პრობლემა და შეიძლება არასტაბილური იყოს, სანამ ქარხნულ მონაცემების არ განაახლებთ."</string>
+    <string name="system_error_manufacturer" msgid="8086872414744210668">"ფიქსირდება თქვენი მოწყობილობის შიდა პრობლემა. დეტალებისათვის, მიმართეთ თქვენს მწარმოებელს."</string>
+    <!-- no translation found for stk_cc_ussd_to_dial (5202342984749947872) -->
+    <skip />
+    <!-- no translation found for stk_cc_ussd_to_ss (2345360594181405482) -->
+    <skip />
+    <!-- no translation found for stk_cc_ussd_to_ussd (7466087659967191653) -->
+    <skip />
+    <!-- no translation found for stk_cc_ss_to_dial (2151304435775557162) -->
+    <skip />
+    <!-- no translation found for stk_cc_ss_to_ussd (3951862188105305589) -->
+    <skip />
+    <!-- no translation found for stk_cc_ss_to_ss (5470768854991452695) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-kk-rKZ/strings.xml b/core/res/res/values-kk-rKZ/strings.xml
index a15ac78..97b435a 100644
--- a/core/res/res/values-kk-rKZ/strings.xml
+++ b/core/res/res/values-kk-rKZ/strings.xml
@@ -564,6 +564,8 @@
     <string name="permdesc_configureWifiDisplay" msgid="7916815158690218065">"Қолданбаларға Wifi дисплейлерін конфигурациялау және қосылу мүмкіндігін береді."</string>
     <string name="permlab_controlWifiDisplay" msgid="393641276723695496">"Wifi дисплейлерін басқару"</string>
     <string name="permdesc_controlWifiDisplay" msgid="4543912292681826986">"Қолданбаларға Wifi дисплейлерінің төмен деңгейлі функцияларын басқару мүмкіндігін береді."</string>
+    <string name="permlab_controlVpn" msgid="2618442789397588200">"control Virtual Private Networks"</string>
+    <string name="permdesc_controlVpn" msgid="762852603315861214">"Allows the app to control low-level features of Virtual Private Networks."</string>
     <string name="permlab_captureAudioOutput" msgid="6857134498402346708">"аудио шығысын жазып алу"</string>
     <string name="permdesc_captureAudioOutput" msgid="6210597754212208853">"Қолданбаға аудио сигналды қабылдап, басқа бағытта жөнелту мүмкіндігін ұсынады."</string>
     <string name="permlab_captureAudioHotword" msgid="1890553935650349808">"Байланыс сөзін анықтау"</string>
@@ -1902,4 +1904,18 @@
     <string name="zen_mode_next_alarm_summary" msgid="5915140424683747372">"<xliff:g id="FORMATTEDTIME">%1$s</xliff:g> уақытындағы келесі дабылға дейін"</string>
     <string name="zen_mode_next_alarm_line_one" msgid="5537042951553420916">"Келесі дабылға дейін"</string>
     <string name="muted_by" msgid="6147073845094180001">"<xliff:g id="THIRD_PARTY">%1$s</xliff:g> үнін өшірген"</string>
+    <string name="system_error_wipe_data" msgid="6608165524785354962">"There\'s an internal problem with your device, and it may be unstable until you factory data reset."</string>
+    <string name="system_error_manufacturer" msgid="8086872414744210668">"There\'s an internal problem with your device. Contact your manufacturer for details."</string>
+    <!-- no translation found for stk_cc_ussd_to_dial (5202342984749947872) -->
+    <skip />
+    <!-- no translation found for stk_cc_ussd_to_ss (2345360594181405482) -->
+    <skip />
+    <!-- no translation found for stk_cc_ussd_to_ussd (7466087659967191653) -->
+    <skip />
+    <!-- no translation found for stk_cc_ss_to_dial (2151304435775557162) -->
+    <skip />
+    <!-- no translation found for stk_cc_ss_to_ussd (3951862188105305589) -->
+    <skip />
+    <!-- no translation found for stk_cc_ss_to_ss (5470768854991452695) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-km-rKH/strings.xml b/core/res/res/values-km-rKH/strings.xml
index 5be27a8..9b13133 100644
--- a/core/res/res/values-km-rKH/strings.xml
+++ b/core/res/res/values-km-rKH/strings.xml
@@ -564,6 +564,8 @@
     <string name="permdesc_configureWifiDisplay" msgid="7916815158690218065">"ឲ្យ​កម្មវិធី​កំណត់​រចនាសម្ព័ន្ធ​ និង​ភ្ជាប់​ទៅ​ការ​បង្ហាញ​វ៉ាយហ្វាយ។"</string>
     <string name="permlab_controlWifiDisplay" msgid="393641276723695496">"ពិនិត្យ​ការ​បង្ហាញ​វ៉ាយហ្វាយ"</string>
     <string name="permdesc_controlWifiDisplay" msgid="4543912292681826986">"ឲ្យ​កម្មវិធី​ពិនិត្យ​លក្ខណៈ​កម្រិត​ទាប​​នៃ​ការ​បង្ហាញ​វ៉ាយហ្វាយ។"</string>
+    <string name="permlab_controlVpn" msgid="2618442789397588200">"គ្រប់គ្រង បណ្តាញឯកជននិមិត្ម"</string>
+    <string name="permdesc_controlVpn" msgid="762852603315861214">"អនុញ្ញាតឲ្យកម្មវិធីគ្រប់គ្រងលក្ខណៈពិសេសកម្រិតទាបនៃបណ្តាញឯកជននិមិត្ម Virtual Private Networks។"</string>
     <string name="permlab_captureAudioOutput" msgid="6857134498402346708">"ចាប់​យក​លទ្ធផល​អូឌីយ៉ូ"</string>
     <string name="permdesc_captureAudioOutput" msgid="6210597754212208853">"​ឱ្យ​កម្មវិធី​ដើម្បី​ចាប់​យក​ និង​​ប្ដូរ​​ទិស​លទ្ធផល​អូឌីយ៉ូ​។"</string>
     <string name="permlab_captureAudioHotword" msgid="1890553935650349808">"ការ​រក​ឃើញ​ពាក្យ"</string>
@@ -1904,4 +1906,18 @@
     <string name="zen_mode_next_alarm_summary" msgid="5915140424683747372">"រហូត​ដល់​ការ​ជូន​ដំណឹង​បន្ទាប់​នៅ <xliff:g id="FORMATTEDTIME">%1$s</xliff:g>"</string>
     <string name="zen_mode_next_alarm_line_one" msgid="5537042951553420916">"រហូត​ការ​ជូន​ដំណឹង​បន្ទាប់"</string>
     <string name="muted_by" msgid="6147073845094180001">"បាន​បិទ​សំឡេង​ដោយ <xliff:g id="THIRD_PARTY">%1$s</xliff:g>"</string>
+    <string name="system_error_wipe_data" msgid="6608165524785354962">"មានបញ្ហាខាងក្នុងឧបករណ៍របស់អ្នក ហើយវាអ្នកមិនមានស្ថេរភាព រហូតទាល់តែអ្នកកំណត់ដូចដើមវិញទាំងស្រុង។"</string>
+    <string name="system_error_manufacturer" msgid="8086872414744210668">"មានបញ្ហាខាងក្នុងឧបករណ៍របស់អ្នក ទំនាក់ទំនងក្រុមហ៊ុនផលិតឧបករណ៍របស់អ្នកសម្រាប់ព័ត៌មានបន្ថែម។"</string>
+    <!-- no translation found for stk_cc_ussd_to_dial (5202342984749947872) -->
+    <skip />
+    <!-- no translation found for stk_cc_ussd_to_ss (2345360594181405482) -->
+    <skip />
+    <!-- no translation found for stk_cc_ussd_to_ussd (7466087659967191653) -->
+    <skip />
+    <!-- no translation found for stk_cc_ss_to_dial (2151304435775557162) -->
+    <skip />
+    <!-- no translation found for stk_cc_ss_to_ussd (3951862188105305589) -->
+    <skip />
+    <!-- no translation found for stk_cc_ss_to_ss (5470768854991452695) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-kn-rIN/strings.xml b/core/res/res/values-kn-rIN/strings.xml
index f932c1d..e53fb1e 100644
--- a/core/res/res/values-kn-rIN/strings.xml
+++ b/core/res/res/values-kn-rIN/strings.xml
@@ -564,6 +564,8 @@
     <string name="permdesc_configureWifiDisplay" msgid="7916815158690218065">"ವೈಫೈ ಪ್ರದರ್ಶನಗಳಿಗೆ ಕಾನ್ಫಿಗರ್ ಮಾಡಲು ಮತ್ತು ಸಂಪರ್ಕಪಡಿಸಲು ಅಪ್ಲಿಕೇಶನ್‍‍ಗೆ ಅವಕಾಶ ನೀಡುತ್ತದೆ."</string>
     <string name="permlab_controlWifiDisplay" msgid="393641276723695496">"ವೈಫೈ ಪ್ರದರ್ಶನಗಳನ್ನು ನಿಯಂತ್ರಿಸಿ"</string>
     <string name="permdesc_controlWifiDisplay" msgid="4543912292681826986">"ವೈಫೈ ಪ್ರದರ್ಶನಗಳ ಕೆಳ-ಮಟ್ಟದ ವೈಶಿಷ್ಟ್ಯಗಳನ್ನು ನಿಯಂತ್ರಿಸಲು ಅಪ್ಲಿಕೇಶನ್‍‍ಗೆ ಅವಕಾಶ ಕಲ್ಪಿಸುತ್ತದೆ."</string>
+    <string name="permlab_controlVpn" msgid="2618442789397588200">"ವರ್ಚುವಲ್ ಖಾಸಗಿ ನೆಟ್‌ವರ್ಕ್‌ಗಳನ್ನು ನಿಯಂತ್ರಿಸಿ"</string>
+    <string name="permdesc_controlVpn" msgid="762852603315861214">"ವರ್ಚುವಲ್ ಖಾಸಗಿ ನೆಟ್‌ವರ್ಕ್‌ಗಳ ಕೆಳ ಮಟ್ಟದ ವೈಶಿಷ್ಟ್ಯಗಳನ್ನು ನಿಯಂತ್ರಿಸಲು ಅಪ್ಲಿಕೇಶನ್‌ಗೆ ಅನುಮತಿಸುತ್ತದೆ."</string>
     <string name="permlab_captureAudioOutput" msgid="6857134498402346708">"ಆಡಿಯೊ ಔಟ್‌ಪುಟ್ ಸೆರೆಹಿಡಿಯಿರಿ"</string>
     <string name="permdesc_captureAudioOutput" msgid="6210597754212208853">"ಆಡಿಯೊ ಔಟ್‌ಪುಟ್ ಸೆರೆಹಿಡಿಯಲು ಮತ್ತು ಮರುನಿರ್ದೇಶಿಸಲು ಅಪ್ಲಿಕೇಶನ್‌ಗೆ ಅವಕಾಶ ಮಾಡಿಕೊಡುತ್ತದೆ."</string>
     <string name="permlab_captureAudioHotword" msgid="1890553935650349808">"ಹಾಟ್‌ವರ್ಡ್ ಪತ್ತೆಹಚ್ಚುವಿಕೆ"</string>
@@ -1902,4 +1904,18 @@
     <string name="zen_mode_next_alarm_summary" msgid="5915140424683747372">"ಮುಂದಿನ ಅಲಾರಮ್ <xliff:g id="FORMATTEDTIME">%1$s</xliff:g> ವರೆಗೆ"</string>
     <string name="zen_mode_next_alarm_line_one" msgid="5537042951553420916">"ಮುಂದಿನ ಅಲಾರಮ್‌ವರೆಗೆ"</string>
     <string name="muted_by" msgid="6147073845094180001">"<xliff:g id="THIRD_PARTY">%1$s</xliff:g> ಅವರಿಂದ ಮ್ಯೂಟ್‌ ಮಾಡಲಾಗಿದೆ"</string>
+    <string name="system_error_wipe_data" msgid="6608165524785354962">"ನಿಮ್ಮ ಸಾಧನದಲ್ಲಿ ಆಂತರಿಕ ಸಮಸ್ಯೆಯಿದೆ ಹಾಗೂ ನೀವು ಫ್ಯಾಕ್ಟರಿ ಡೇಟಾವನ್ನು ಮರುಹೊಂದಿಸುವರೆಗೂ ಅದು ಅಸ್ಥಿರವಾಗಬಹುದು."</string>
+    <string name="system_error_manufacturer" msgid="8086872414744210668">"ನಿಮ್ಮ ಸಾಧನದಲ್ಲಿ ಆಂತರಿಕ ಸಮಸ್ಯೆಯಿದೆ. ವಿವರಗಳಿಗಾಗಿ ನಿಮ್ಮ ತಯಾರಕರನ್ನು ಸಂಪರ್ಕಿಸಿ."</string>
+    <!-- no translation found for stk_cc_ussd_to_dial (5202342984749947872) -->
+    <skip />
+    <!-- no translation found for stk_cc_ussd_to_ss (2345360594181405482) -->
+    <skip />
+    <!-- no translation found for stk_cc_ussd_to_ussd (7466087659967191653) -->
+    <skip />
+    <!-- no translation found for stk_cc_ss_to_dial (2151304435775557162) -->
+    <skip />
+    <!-- no translation found for stk_cc_ss_to_ussd (3951862188105305589) -->
+    <skip />
+    <!-- no translation found for stk_cc_ss_to_ss (5470768854991452695) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-ko/strings.xml b/core/res/res/values-ko/strings.xml
index d279b73..f7b8052 100644
--- a/core/res/res/values-ko/strings.xml
+++ b/core/res/res/values-ko/strings.xml
@@ -564,6 +564,8 @@
     <string name="permdesc_configureWifiDisplay" msgid="7916815158690218065">"앱이 Wi-Fi 디스플레이를 설정하고 연결하도록 허용합니다."</string>
     <string name="permlab_controlWifiDisplay" msgid="393641276723695496">"Wi-Fi 디스플레이 제어"</string>
     <string name="permdesc_controlWifiDisplay" msgid="4543912292681826986">"앱이 Wi-Fi 디스플레이의 하위 수준 기능을 제어하도록 허용합니다."</string>
+    <string name="permlab_controlVpn" msgid="2618442789397588200">"가상 사설망(VPN) 관리"</string>
+    <string name="permdesc_controlVpn" msgid="762852603315861214">"앱에서 가상 사설망(VPN)의 하위 수준 기능을 관리하도록 허용하세요."</string>
     <string name="permlab_captureAudioOutput" msgid="6857134498402346708">"오디오 출력 캡처"</string>
     <string name="permdesc_captureAudioOutput" msgid="6210597754212208853">"앱이 오디오 출력을 캡처하고 리디렉션하도록 허용합니다."</string>
     <string name="permlab_captureAudioHotword" msgid="1890553935650349808">"핫워드 감지"</string>
@@ -1902,4 +1904,18 @@
     <string name="zen_mode_next_alarm_summary" msgid="5915140424683747372">"다음 <xliff:g id="FORMATTEDTIME">%1$s</xliff:g> 알람까지"</string>
     <string name="zen_mode_next_alarm_line_one" msgid="5537042951553420916">"다음 알람까지"</string>
     <string name="muted_by" msgid="6147073845094180001">"<xliff:g id="THIRD_PARTY">%1$s</xliff:g>에서 알림음 음소거"</string>
+    <string name="system_error_wipe_data" msgid="6608165524785354962">"사용 중인 기기 내부에 문제가 발생했습니다. 초기화할 때까지 불안정할 수 있습니다."</string>
+    <string name="system_error_manufacturer" msgid="8086872414744210668">"사용 중인 기기 내부에 문제가 발생했습니다. 자세한 내용은 제조업체에 문의하세요."</string>
+    <!-- no translation found for stk_cc_ussd_to_dial (5202342984749947872) -->
+    <skip />
+    <!-- no translation found for stk_cc_ussd_to_ss (2345360594181405482) -->
+    <skip />
+    <!-- no translation found for stk_cc_ussd_to_ussd (7466087659967191653) -->
+    <skip />
+    <!-- no translation found for stk_cc_ss_to_dial (2151304435775557162) -->
+    <skip />
+    <!-- no translation found for stk_cc_ss_to_ussd (3951862188105305589) -->
+    <skip />
+    <!-- no translation found for stk_cc_ss_to_ss (5470768854991452695) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-ky-rKG/strings.xml b/core/res/res/values-ky-rKG/strings.xml
index 392f790..be5b499 100644
--- a/core/res/res/values-ky-rKG/strings.xml
+++ b/core/res/res/values-ky-rKG/strings.xml
@@ -728,6 +728,8 @@
     <string name="permdesc_configureWifiDisplay" msgid="7916815158690218065">"Колдонмого тууралоолорду жүргүзүп, Wifi-дисплейлерге туташуу уруксатын берет."</string>
     <string name="permlab_controlWifiDisplay" msgid="393641276723695496">"Wifi дисплейлерин башкаруу"</string>
     <string name="permdesc_controlWifiDisplay" msgid="4543912292681826986">"Колдонмого Wifi-дисплейлердин төмөнкү деңгээл мүмкүнчүлүктөрүн башкаруу уруксатын берет."</string>
+    <string name="permlab_controlVpn" msgid="2618442789397588200">"Виртуалдык жеке тармактарды көзөмөлдөө"</string>
+    <string name="permdesc_controlVpn" msgid="762852603315861214">"Колдонмо Виртуалдык жеке тармактардын төмөнкү деңгээлдеги мүмкүнчүлүктөрүн көзөмөлдөй алат."</string>
     <string name="permlab_captureAudioOutput" msgid="6857134498402346708">"аудио чыгарылышты жаздыруу"</string>
     <string name="permdesc_captureAudioOutput" msgid="6210597754212208853">"Колдонмого аудио чыгарылышты жаздырып, аны кайра багыттоо мүмкүнчүлүгүн берет."</string>
     <string name="permlab_captureAudioHotword" msgid="1890553935650349808">"Ачкыч сөз таануу"</string>
@@ -2382,4 +2384,18 @@
     <string name="zen_mode_next_alarm_summary" msgid="5915140424683747372">"Саат <xliff:g id="FORMATTEDTIME">%1$s</xliff:g> боло турган кийинки айгайга чейин"</string>
     <string name="zen_mode_next_alarm_line_one" msgid="5537042951553420916">"Кийинки айгайга чейин"</string>
     <string name="muted_by" msgid="6147073845094180001">"<xliff:g id="THIRD_PARTY">%1$s</xliff:g> тарабынан үнсүздөлдү"</string>
+    <string name="system_error_wipe_data" msgid="6608165524785354962">"Түзмөгүңүздө ички көйгөй бар жана ал баштапкы абалга кайтарылмайынча туруктуу иштебей коюшу мүмкүн."</string>
+    <string name="system_error_manufacturer" msgid="8086872414744210668">"Түзмөгүңүздө ички көйгөй бар. Анын чоо-жайын билүү үчүн өндүрүүчүңүзгө кайрылыңыз."</string>
+    <!-- no translation found for stk_cc_ussd_to_dial (5202342984749947872) -->
+    <skip />
+    <!-- no translation found for stk_cc_ussd_to_ss (2345360594181405482) -->
+    <skip />
+    <!-- no translation found for stk_cc_ussd_to_ussd (7466087659967191653) -->
+    <skip />
+    <!-- no translation found for stk_cc_ss_to_dial (2151304435775557162) -->
+    <skip />
+    <!-- no translation found for stk_cc_ss_to_ussd (3951862188105305589) -->
+    <skip />
+    <!-- no translation found for stk_cc_ss_to_ss (5470768854991452695) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-lo-rLA/strings.xml b/core/res/res/values-lo-rLA/strings.xml
index 94ad1ec..fbb8857 100644
--- a/core/res/res/values-lo-rLA/strings.xml
+++ b/core/res/res/values-lo-rLA/strings.xml
@@ -564,6 +564,8 @@
     <string name="permdesc_configureWifiDisplay" msgid="7916815158690218065">"ອະນຸຍາດໃຫ້ແອັບຯຕັ້ງຄ່າ ແລະເຊື່ອມຕໍ່ຈໍສະແດງຜົນ WiFi."</string>
     <string name="permlab_controlWifiDisplay" msgid="393641276723695496">"ຄວບຄຸມການສະແດງ WiFi"</string>
     <string name="permdesc_controlWifiDisplay" msgid="4543912292681826986">"ອະນຸຍາດໃຫ້ແອັບຯ ຄວບຄຸມຄວາມສາມາດລະດັບຕໍ່າຂອງການສະແດງຜົນ Wifi."</string>
+    <string name="permlab_controlVpn" msgid="2618442789397588200">"ຄວບ​ຄຸມ​ເຄືອ​ຂ່າຍ​ສ່ວນ​ຕົວ​ສະ​ເໝືອນ"</string>
+    <string name="permdesc_controlVpn" msgid="762852603315861214">"ອະ​ນຸ​ຍາດ​ໃຫ້​ແອັບ​ຄວບ​ຄຸມ​ຄຸນ​ສົມ​ບັດ​ເຄືອ​ຂ່າຍ​ສ່ວນ​ຕົວ​​ສະ​ເໝືອນລະ​ດັບ​ຕ່ຳ."</string>
     <string name="permlab_captureAudioOutput" msgid="6857134498402346708">"ບັນທຶກສຽງອອກ"</string>
     <string name="permdesc_captureAudioOutput" msgid="6210597754212208853">"ອະນຸຍາດໃຫ້ແອັບຯບັນທຶກ ແລະປ່ຽນເສັ້ນທາງການປ້ອນຂໍ້ມູນອອກຂອງສຽງ."</string>
     <string name="permlab_captureAudioHotword" msgid="1890553935650349808">"ການກວດຫາ Hotword"</string>
@@ -1902,4 +1904,18 @@
     <string name="zen_mode_next_alarm_summary" msgid="5915140424683747372">"​ຈົນ​ກວ່າ​ໂມງ​ປຸກ​ຄັ້ງ​ຕໍ່​ໄປ​ໃນ​ເວ​ລາ <xliff:g id="FORMATTEDTIME">%1$s</xliff:g>"</string>
     <string name="zen_mode_next_alarm_line_one" msgid="5537042951553420916">"​ຈົນ​ກວ່າ​ໂມງ​ປຸກ​ຄັ້ງຕໍ່​ໄປ"</string>
     <string name="muted_by" msgid="6147073845094180001">"ຖືກ​ປິດ​ສຽງ​ໂດຍ <xliff:g id="THIRD_PARTY">%1$s</xliff:g>"</string>
+    <string name="system_error_wipe_data" msgid="6608165524785354962">"ມີ​ບັນ​ຫາ​ພາຍ​ໃນ​ກັບ​ອຸ​ປະ​ກອນ​ຂອງ​ທ່ານ, ແລະ​ມັນ​ອາດ​ຈະ​ບໍ່​ສະ​ຖຽນ​ຈົນ​ກວ່າ​ທ່ານ​ຕັ້ງ​ເປັນ​ຂໍ້​ມູນ​ໂຮງ​ງານ​ຄືນ​ແລ້ວ."</string>
+    <string name="system_error_manufacturer" msgid="8086872414744210668">"ມີ​ບັນ​ຫາ​ພາຍ​ໃນ​ກັບ​ອຸ​ປະ​ກອນ​ຂອງ​ທ່ານ. ຕິດ​ຕໍ່ຜູ້​ຜະ​ລິດ​ຂອງ​ທ່ານ​ສຳ​ລັບ​ລາຍ​ລະ​ອຽດ​ຕ່າງໆ."</string>
+    <!-- no translation found for stk_cc_ussd_to_dial (5202342984749947872) -->
+    <skip />
+    <!-- no translation found for stk_cc_ussd_to_ss (2345360594181405482) -->
+    <skip />
+    <!-- no translation found for stk_cc_ussd_to_ussd (7466087659967191653) -->
+    <skip />
+    <!-- no translation found for stk_cc_ss_to_dial (2151304435775557162) -->
+    <skip />
+    <!-- no translation found for stk_cc_ss_to_ussd (3951862188105305589) -->
+    <skip />
+    <!-- no translation found for stk_cc_ss_to_ss (5470768854991452695) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-lt/strings.xml b/core/res/res/values-lt/strings.xml
index 24b5e01..273ff62 100644
--- a/core/res/res/values-lt/strings.xml
+++ b/core/res/res/values-lt/strings.xml
@@ -564,6 +564,8 @@
     <string name="permdesc_configureWifiDisplay" msgid="7916815158690218065">"Leidžiama programai konfigūruoti ir prisijungti prie „Wi-Fi“ pateikčių."</string>
     <string name="permlab_controlWifiDisplay" msgid="393641276723695496">"valdyti „Wi-Fi“ pateiktis"</string>
     <string name="permdesc_controlWifiDisplay" msgid="4543912292681826986">"Leidžiama programai valdyti „Wi-Fi“ pateikčių žemo lygio funkcijas."</string>
+    <string name="permlab_controlVpn" msgid="2618442789397588200">"valdyti virtualiuosius privačiuosius tinklus"</string>
+    <string name="permdesc_controlVpn" msgid="762852603315861214">"Programai leidžiama valdyti pagrindines virtualiųjų privačiųjų tinklų funkcijas."</string>
     <string name="permlab_captureAudioOutput" msgid="6857134498402346708">"fiksuoti garso išvestį"</string>
     <string name="permdesc_captureAudioOutput" msgid="6210597754212208853">"Programai leidžiama fiksuoti ir peradresuoti garso išvestį."</string>
     <string name="permlab_captureAudioHotword" msgid="1890553935650349808">"Aktyvinamųjų žodžių aptikimas"</string>
@@ -1902,4 +1904,18 @@
     <string name="zen_mode_next_alarm_summary" msgid="5915140424683747372">"Iki kito įspėjimo <xliff:g id="FORMATTEDTIME">%1$s</xliff:g>"</string>
     <string name="zen_mode_next_alarm_line_one" msgid="5537042951553420916">"Iki kito įspėjimo"</string>
     <string name="muted_by" msgid="6147073845094180001">"Nutildė <xliff:g id="THIRD_PARTY">%1$s</xliff:g>"</string>
+    <string name="system_error_wipe_data" msgid="6608165524785354962">"Iškilo vidinė su jūsų įrenginiu susijusi problema, todėl įrenginys gali veikti nestabiliai, kol neatkursite gamyklinių duomenų."</string>
+    <string name="system_error_manufacturer" msgid="8086872414744210668">"Iškilo vidinė su jūsų įrenginiu susijusi problema. Jei reikia išsamios informacijos, susisiekite su gamintoju."</string>
+    <!-- no translation found for stk_cc_ussd_to_dial (5202342984749947872) -->
+    <skip />
+    <!-- no translation found for stk_cc_ussd_to_ss (2345360594181405482) -->
+    <skip />
+    <!-- no translation found for stk_cc_ussd_to_ussd (7466087659967191653) -->
+    <skip />
+    <!-- no translation found for stk_cc_ss_to_dial (2151304435775557162) -->
+    <skip />
+    <!-- no translation found for stk_cc_ss_to_ussd (3951862188105305589) -->
+    <skip />
+    <!-- no translation found for stk_cc_ss_to_ss (5470768854991452695) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-lv/strings.xml b/core/res/res/values-lv/strings.xml
index ce85173..4c96dd9 100644
--- a/core/res/res/values-lv/strings.xml
+++ b/core/res/res/values-lv/strings.xml
@@ -564,6 +564,8 @@
     <string name="permdesc_configureWifiDisplay" msgid="7916815158690218065">"Ļauj lietotnei konfigurēt Wi-Fi displejus un veidot savienojumu ar tiem."</string>
     <string name="permlab_controlWifiDisplay" msgid="393641276723695496">"Wi-Fi displeju vadība"</string>
     <string name="permdesc_controlWifiDisplay" msgid="4543912292681826986">"Ļauj lietotnei kontrolēt zema līmeņa funkcijas Wi-Fi displejos."</string>
+    <string name="permlab_controlVpn" msgid="2618442789397588200">"Virtuālo privāto tīklu kontrolēšana"</string>
+    <string name="permdesc_controlVpn" msgid="762852603315861214">"Ļauj lietotnei kontrolēt virtuālo privāto tīklu zema līmeņa funkcijas."</string>
     <string name="permlab_captureAudioOutput" msgid="6857134498402346708">"tvert audio izvadi"</string>
     <string name="permdesc_captureAudioOutput" msgid="6210597754212208853">"Ļauj lietotnei tvert un novirzīt audio izvadi."</string>
     <string name="permlab_captureAudioHotword" msgid="1890553935650349808">"Īsinājumvārda noteikšana"</string>
@@ -1902,4 +1904,18 @@
     <string name="zen_mode_next_alarm_summary" msgid="5915140424683747372">"Līdz nākamajam signālam: <xliff:g id="FORMATTEDTIME">%1$s</xliff:g>"</string>
     <string name="zen_mode_next_alarm_line_one" msgid="5537042951553420916">"Līdz nākamajam signālam"</string>
     <string name="muted_by" msgid="6147073845094180001">"Skaņu izslēdza <xliff:g id="THIRD_PARTY">%1$s</xliff:g>"</string>
+    <string name="system_error_wipe_data" msgid="6608165524785354962">"Jūsu ierīcē ir radusies iekšēja problēma, un ierīce var darboties nestabili. Lai to labotu, veiciet rūpnīcas datu atiestatīšanu."</string>
+    <string name="system_error_manufacturer" msgid="8086872414744210668">"Jūsu ierīcē ir radusies iekšēja problēma. Lai iegūtu plašāku informāciju, lūdzu, sazinieties ar ražotāju."</string>
+    <!-- no translation found for stk_cc_ussd_to_dial (5202342984749947872) -->
+    <skip />
+    <!-- no translation found for stk_cc_ussd_to_ss (2345360594181405482) -->
+    <skip />
+    <!-- no translation found for stk_cc_ussd_to_ussd (7466087659967191653) -->
+    <skip />
+    <!-- no translation found for stk_cc_ss_to_dial (2151304435775557162) -->
+    <skip />
+    <!-- no translation found for stk_cc_ss_to_ussd (3951862188105305589) -->
+    <skip />
+    <!-- no translation found for stk_cc_ss_to_ss (5470768854991452695) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-mk-rMK/strings.xml b/core/res/res/values-mk-rMK/strings.xml
index 78ff999..531b6c1 100644
--- a/core/res/res/values-mk-rMK/strings.xml
+++ b/core/res/res/values-mk-rMK/strings.xml
@@ -564,6 +564,8 @@
     <string name="permdesc_configureWifiDisplay" msgid="7916815158690218065">"Овозможува апликацијата да конфигурира и да се поврзува со Wi-Fi прикази."</string>
     <string name="permlab_controlWifiDisplay" msgid="393641276723695496">"контролирај прикази на Wi-Fi"</string>
     <string name="permdesc_controlWifiDisplay" msgid="4543912292681826986">"Овозможува апликацијата да контролира карактеристики на ниско ниво на Wi-fi прикази."</string>
+    <string name="permlab_controlVpn" msgid="2618442789397588200">"Контролирајте виртуелни приватни мрежи"</string>
+    <string name="permdesc_controlVpn" msgid="762852603315861214">"Дозволува апликацијата да ги контролира функциите на ниско ниво на виртуелните приватни мрежи."</string>
     <string name="permlab_captureAudioOutput" msgid="6857134498402346708">"сними аудио излез"</string>
     <string name="permdesc_captureAudioOutput" msgid="6210597754212208853">"Овозможува апликацијата да снима и пренасочува аудио излез."</string>
     <string name="permlab_captureAudioHotword" msgid="1890553935650349808">"Откривање клучни зборови"</string>
@@ -1904,4 +1906,18 @@
     <string name="zen_mode_next_alarm_summary" msgid="5915140424683747372">"До следниот аларм во <xliff:g id="FORMATTEDTIME">%1$s</xliff:g>"</string>
     <string name="zen_mode_next_alarm_line_one" msgid="5537042951553420916">"До следниот аларм"</string>
     <string name="muted_by" msgid="6147073845094180001">"Звукот го исклучи <xliff:g id="THIRD_PARTY">%1$s</xliff:g>"</string>
+    <string name="system_error_wipe_data" msgid="6608165524785354962">"Настана внатрешен проблем со уредот и може да биде нестабилен сè додека не ресетирате на фабричките податоци."</string>
+    <string name="system_error_manufacturer" msgid="8086872414744210668">"Настана внатрешен проблем со уредот. Контактирајте го производителот за детали."</string>
+    <!-- no translation found for stk_cc_ussd_to_dial (5202342984749947872) -->
+    <skip />
+    <!-- no translation found for stk_cc_ussd_to_ss (2345360594181405482) -->
+    <skip />
+    <!-- no translation found for stk_cc_ussd_to_ussd (7466087659967191653) -->
+    <skip />
+    <!-- no translation found for stk_cc_ss_to_dial (2151304435775557162) -->
+    <skip />
+    <!-- no translation found for stk_cc_ss_to_ussd (3951862188105305589) -->
+    <skip />
+    <!-- no translation found for stk_cc_ss_to_ss (5470768854991452695) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-ml-rIN/strings.xml b/core/res/res/values-ml-rIN/strings.xml
index 2ab0fa8..0c32045 100644
--- a/core/res/res/values-ml-rIN/strings.xml
+++ b/core/res/res/values-ml-rIN/strings.xml
@@ -564,6 +564,8 @@
     <string name="permdesc_configureWifiDisplay" msgid="7916815158690218065">"വൈഫൈ ഡിസ്പ്ലേകൾ കോൺഫിഗർ ചെയ്യാനും അതിലേക്ക് കണക്റ്റുചെയ്യാനും അപ്ലിക്കേഷനെ അനുവദിക്കുന്നു."</string>
     <string name="permlab_controlWifiDisplay" msgid="393641276723695496">"വൈഫൈ ഡിസ്‌പ്ലേകൾ നിയന്ത്രിക്കുക"</string>
     <string name="permdesc_controlWifiDisplay" msgid="4543912292681826986">"വൈഫൈ ഡിസ്‌പ്ലേകളുടെ കുറഞ്ഞ നിലയിലുള്ള സവിശേഷതകൾ നിയന്ത്രിക്കാൻ അപ്ലിക്കേഷനെ അനുവദിക്കുന്നു."</string>
+    <string name="permlab_controlVpn" msgid="2618442789397588200">"വെർച്വൽ സ്വകാര്യ നെറ്റ്‌വർക്കുകൾ നിയന്ത്രിക്കുക"</string>
+    <string name="permdesc_controlVpn" msgid="762852603315861214">"വെർച്വൽ സ്വകാര്യ നെറ്റ്‌വർക്കുകളുടെ താഴ്‌ന്ന നിലയിലുള്ള ഫീച്ചറുകൾ നിയന്ത്രിക്കാൻ അപ്ലിക്കേഷനെ അനുവദിക്കുന്നു."</string>
     <string name="permlab_captureAudioOutput" msgid="6857134498402346708">"ഓഡിയോ ഔട്ട്പുട്ട് ക്യാപ്‌ചർ ചെയ്യുക"</string>
     <string name="permdesc_captureAudioOutput" msgid="6210597754212208853">"ഓഡിയോ ഔട്ട്‌പുട്ട് ക്യാപ്‌ചർ ചെയ്‌ത് റീഡയറക്‌ടുചെയ്യാൻ അപ്ലിക്കേഷനെ അനുവദിക്കുന്നു."</string>
     <string name="permlab_captureAudioHotword" msgid="1890553935650349808">"ഹോട്ട്‌വേഡ് തിരിച്ചറിയൽ"</string>
@@ -1900,4 +1902,18 @@
     <string name="zen_mode_next_alarm_summary" msgid="5915140424683747372">"<xliff:g id="FORMATTEDTIME">%1$s</xliff:g>-നുള്ള അടുത്ത അലാറം വരെ"</string>
     <string name="zen_mode_next_alarm_line_one" msgid="5537042951553420916">"അടുത്ത അലാറം വരെ"</string>
     <string name="muted_by" msgid="6147073845094180001">"<xliff:g id="THIRD_PARTY">%1$s</xliff:g>, മ്യൂട്ടുചെയ്‌തു"</string>
+    <string name="system_error_wipe_data" msgid="6608165524785354962">"നിങ്ങളുടെ ഉപകരണത്തിൽ ഒരു ആന്തരിക പ്രശ്‌നമുണ്ട്, ഫാക്‌ടറി വിവര പുനഃസജ്ജീകരണം ചെയ്യുന്നതുവരെ ഇതു അസ്ഥിരമായിരിക്കാനിടയുണ്ട്."</string>
+    <string name="system_error_manufacturer" msgid="8086872414744210668">"നിങ്ങളുടെ ഉപകരണത്തിൽ ഒരു ആന്തരിക പ്രശ്‌നമുണ്ട്. വിശദാംശങ്ങൾക്കായി നിർമ്മാതാവിനെ ബന്ധപ്പെടുക."</string>
+    <!-- no translation found for stk_cc_ussd_to_dial (5202342984749947872) -->
+    <skip />
+    <!-- no translation found for stk_cc_ussd_to_ss (2345360594181405482) -->
+    <skip />
+    <!-- no translation found for stk_cc_ussd_to_ussd (7466087659967191653) -->
+    <skip />
+    <!-- no translation found for stk_cc_ss_to_dial (2151304435775557162) -->
+    <skip />
+    <!-- no translation found for stk_cc_ss_to_ussd (3951862188105305589) -->
+    <skip />
+    <!-- no translation found for stk_cc_ss_to_ss (5470768854991452695) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-mn-rMN/strings.xml b/core/res/res/values-mn-rMN/strings.xml
index 47fb415..8074a99 100644
--- a/core/res/res/values-mn-rMN/strings.xml
+++ b/core/res/res/values-mn-rMN/strings.xml
@@ -564,6 +564,8 @@
     <string name="permdesc_configureWifiDisplay" msgid="7916815158690218065">"Апп нь Wifi дэлгэцийг тохируулах болон холбогдох боломжтой."</string>
     <string name="permlab_controlWifiDisplay" msgid="393641276723695496">"Wifi дэлгэцийг удирдах"</string>
     <string name="permdesc_controlWifiDisplay" msgid="4543912292681826986">"Апп нь Wifi дэлгэцний доод-төвшиний функцийг удирдах боломжтой."</string>
+    <string name="permlab_controlVpn" msgid="2618442789397588200">"Виртуал Хувийн Сүлжээнүүдийг удирдах"</string>
+    <string name="permdesc_controlVpn" msgid="762852603315861214">"Виртуал Хувийн Сүлжээнүүдийн доод түвшний функцүүдийг тус апликейшнээр удирдахыг зөвшөөрдөг."</string>
     <string name="permlab_captureAudioOutput" msgid="6857134498402346708">"аудио гаралтыг барих"</string>
     <string name="permdesc_captureAudioOutput" msgid="6210597754212208853">"Апп-т аудио гаралтыг барих, дахин чиглүүлэхийг зөвшөөрнө."</string>
     <string name="permlab_captureAudioHotword" msgid="1890553935650349808">"Хотворд таних"</string>
@@ -1902,4 +1904,18 @@
     <string name="zen_mode_next_alarm_summary" msgid="5915140424683747372">"<xliff:g id="FORMATTEDTIME">%1$s</xliff:g> дахь дараагийн анхааруулга хүртэл"</string>
     <string name="zen_mode_next_alarm_line_one" msgid="5537042951553420916">"Дараагийн анхааруулга хүртэл"</string>
     <string name="muted_by" msgid="6147073845094180001">"<xliff:g id="THIRD_PARTY">%1$s</xliff:g>-с хаасан"</string>
+    <string name="system_error_wipe_data" msgid="6608165524785354962">"Таны төхөөрөмжид дотоод алдаа байна.Та төхөөрөмжөө үйлдвэрээс гарсан төлөвт шилжүүлэх хүртэл таны төхөөрөмж чинь тогтворгүй байж болох юм."</string>
+    <string name="system_error_manufacturer" msgid="8086872414744210668">"Таны төхөөрөмжид дотоод алдаа байна. Дэлгэрэнгүй мэдээлэл авахыг хүсвэл үйлдвэрлэгчтэйгээ холбоо барина уу."</string>
+    <!-- no translation found for stk_cc_ussd_to_dial (5202342984749947872) -->
+    <skip />
+    <!-- no translation found for stk_cc_ussd_to_ss (2345360594181405482) -->
+    <skip />
+    <!-- no translation found for stk_cc_ussd_to_ussd (7466087659967191653) -->
+    <skip />
+    <!-- no translation found for stk_cc_ss_to_dial (2151304435775557162) -->
+    <skip />
+    <!-- no translation found for stk_cc_ss_to_ussd (3951862188105305589) -->
+    <skip />
+    <!-- no translation found for stk_cc_ss_to_ss (5470768854991452695) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-mr-rIN/strings.xml b/core/res/res/values-mr-rIN/strings.xml
index f0391dd..1f51ecb 100644
--- a/core/res/res/values-mr-rIN/strings.xml
+++ b/core/res/res/values-mr-rIN/strings.xml
@@ -564,6 +564,8 @@
     <string name="permdesc_configureWifiDisplay" msgid="7916815158690218065">"वायफाय प्रदर्शने कॉन्फिगर करण्यासाठी आणि त्यावर कनेक्ट करण्यासाठी अॅप ला अनुमती देते."</string>
     <string name="permlab_controlWifiDisplay" msgid="393641276723695496">"वायफाय प्रदर्शने नियंत्रित करा"</string>
     <string name="permdesc_controlWifiDisplay" msgid="4543912292681826986">"वायफाय प्रदर्शनांची निम्न-स्तर वैशिष्ट्ये नियंत्रित करण्यासाठी अॅप ला अनुमती देते."</string>
+    <string name="permlab_controlVpn" msgid="2618442789397588200">"व्हर्च्युअल प्रायव्हेट नेटवर्क नियंत्रित करा"</string>
+    <string name="permdesc_controlVpn" msgid="762852603315861214">"अ‍ॅपला व्हर्च्युअल प्रायव्हेट नेटवर्कच्या निम्न-दर्जाच्या वैशिष्‍ट्यांना नियंत्रित करण्‍याची अनुमती देते."</string>
     <string name="permlab_captureAudioOutput" msgid="6857134498402346708">"ऑडिओ आउटपुट कॅप्‍चर करा"</string>
     <string name="permdesc_captureAudioOutput" msgid="6210597754212208853">"अ‍ॅपला ऑडिओ आउटपुट कॅप्‍चर करण्‍याची आणि पुनर्निर्देशित करण्‍याची अनुमती देते."</string>
     <string name="permlab_captureAudioHotword" msgid="1890553935650349808">"Hotword शोध"</string>
@@ -833,7 +835,7 @@
     <string name="permdesc_handoverStatus" msgid="4788144087245714948">"वर्तमान Android बीम स्थानांतरणांविषयी माहिती प्राप्त करण्यासाठी या अनुप्रयोगास अनुमती देते"</string>
     <string name="permlab_removeDrmCertificates" msgid="7044888287209892751">"DRM प्रमाणपत्रे काढा"</string>
     <string name="permdesc_removeDrmCertificates" msgid="7272999075113400993">"DRM प्रमाणपत्रे काढण्यासाठी अनुप्रयोगास अनुमती देते. सामान्य अॅप्स साठी कधीही आवश्यकता नसते."</string>
-    <string name="permlab_bindCarrierMessagingService" msgid="1490229371796969158">"एका वाहक संदेशन सेवेवर प्रतिबद्ध करा"</string>
+    <string name="permlab_bindCarrierMessagingService" msgid="1490229371796969158">"एका वाहक संदेशन सेवेसाठी प्रतिबद्ध"</string>
     <string name="permdesc_bindCarrierMessagingService" msgid="2762882888502113944">"वाहक संदेशन सेवेचा शीर्ष-स्तर इंटरफेस प्रतिबद्ध करण्यासाठी होल्डरला अनुमती देते. सामान्‍य अ‍ॅप्‍सकरिता कधीही आवश्‍यक नसते."</string>
     <string name="policylab_limitPassword" msgid="4497420728857585791">"संकेतशब्द नियम सेट करा"</string>
     <string name="policydesc_limitPassword" msgid="3252114203919510394">"स्क्रीन-अनलॉक संकेतशब्दांमध्ये अनुमती दिलेली लांबी आणि वर्ण नियंत्रित करा."</string>
@@ -1902,4 +1904,18 @@
     <string name="zen_mode_next_alarm_summary" msgid="5915140424683747372">"<xliff:g id="FORMATTEDTIME">%1$s</xliff:g> वाजता पुढील अलार्मपर्यंत"</string>
     <string name="zen_mode_next_alarm_line_one" msgid="5537042951553420916">"पुढील अलार्मपर्यंत"</string>
     <string name="muted_by" msgid="6147073845094180001">"<xliff:g id="THIRD_PARTY">%1$s</xliff:g> द्वारे नि:शब्द केले"</string>
+    <string name="system_error_wipe_data" msgid="6608165524785354962">"आपल्‍या डिव्‍हाइसमध्‍ये अंतर्गत समस्‍या आहे आणि आपला फॅक्‍टरी डेटा रीसेट होईपर्यंत ती अस्‍थिर असू शकते."</string>
+    <string name="system_error_manufacturer" msgid="8086872414744210668">"आपल्‍या डिव्‍हाइसमध्‍ये अंतर्गत समस्‍या आहे. तपशीलांसाठी आपल्‍या निर्मात्याशी संपर्क साधा."</string>
+    <!-- no translation found for stk_cc_ussd_to_dial (5202342984749947872) -->
+    <skip />
+    <!-- no translation found for stk_cc_ussd_to_ss (2345360594181405482) -->
+    <skip />
+    <!-- no translation found for stk_cc_ussd_to_ussd (7466087659967191653) -->
+    <skip />
+    <!-- no translation found for stk_cc_ss_to_dial (2151304435775557162) -->
+    <skip />
+    <!-- no translation found for stk_cc_ss_to_ussd (3951862188105305589) -->
+    <skip />
+    <!-- no translation found for stk_cc_ss_to_ss (5470768854991452695) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-ms-rMY/strings.xml b/core/res/res/values-ms-rMY/strings.xml
index 1a295d2..01d1bbb 100644
--- a/core/res/res/values-ms-rMY/strings.xml
+++ b/core/res/res/values-ms-rMY/strings.xml
@@ -564,6 +564,8 @@
     <string name="permdesc_configureWifiDisplay" msgid="7916815158690218065">"Membenarkan apl mengkonfigurasi dan menyambung ke paparan Wifi."</string>
     <string name="permlab_controlWifiDisplay" msgid="393641276723695496">"kawal paparan Wifi"</string>
     <string name="permdesc_controlWifiDisplay" msgid="4543912292681826986">"Membenarkan apl mengawal ciri tahap rendah paparan Wifi."</string>
+    <string name="permlab_controlVpn" msgid="2618442789397588200">"kawal Rangkaian Peribadi Maya"</string>
+    <string name="permdesc_controlVpn" msgid="762852603315861214">"Membenarkan apl mengawal ciri tahap rendah Rangkaian Peribadi Maya."</string>
     <string name="permlab_captureAudioOutput" msgid="6857134498402346708">"tangkap output audio"</string>
     <string name="permdesc_captureAudioOutput" msgid="6210597754212208853">"Membenarkan apl menangkap dan mengubah hala output audio."</string>
     <string name="permlab_captureAudioHotword" msgid="1890553935650349808">"Pengesanan sebutan laluan"</string>
@@ -834,7 +836,7 @@
     <string name="permlab_removeDrmCertificates" msgid="7044888287209892751">"alih keluar sijil DRM"</string>
     <string name="permdesc_removeDrmCertificates" msgid="7272999075113400993">"Membenarkan aplikasi mengalih keluar sijil DRM. Tidak sekali-kali diperlukan untuk apl biasa."</string>
     <string name="permlab_bindCarrierMessagingService" msgid="1490229371796969158">"terikat kepada perkhidmatan pemesejan pembawa"</string>
-    <string name="permdesc_bindCarrierMessagingService" msgid="2762882888502113944">"Membenarkan pemegang terikat dengan antara muka peringkat tertinggi bagi perkhidmatan pemesejan pembawa. Tidak sekali-kali diperlukan untuk apl biasa."</string>
+    <string name="permdesc_bindCarrierMessagingService" msgid="2762882888502113944">"Membenarkan pemegang terikat dengan antara muka peringkat tertinggi perkhidmatan pemesejan pembawa. Tidak sekali-kali diperlukan untuk apl biasa."</string>
     <string name="policylab_limitPassword" msgid="4497420728857585791">"Tetapkan peraturan kata laluan"</string>
     <string name="policydesc_limitPassword" msgid="3252114203919510394">"Mengawal panjang dan aksara yang dibenarkan dalam kata laluan buka kunci skrin."</string>
     <string name="policylab_watchLogin" msgid="914130646942199503">"Memantau percubaan buka kunci skrin"</string>
@@ -1902,4 +1904,18 @@
     <string name="zen_mode_next_alarm_summary" msgid="5915140424683747372">"Sehingga penggera seterusnya pada <xliff:g id="FORMATTEDTIME">%1$s</xliff:g>"</string>
     <string name="zen_mode_next_alarm_line_one" msgid="5537042951553420916">"Sehingga penggera seterusnya"</string>
     <string name="muted_by" msgid="6147073845094180001">"Diredam oleh <xliff:g id="THIRD_PARTY">%1$s</xliff:g>"</string>
+    <string name="system_error_wipe_data" msgid="6608165524785354962">"Terdapat masalah dalaman dengan peranti anda. Peranti mungkin tidak stabil sehingga anda membuat tetapan semula data kilang."</string>
+    <string name="system_error_manufacturer" msgid="8086872414744210668">"Terdapat masalah dalaman dengan peranti anda. Hubungi pengilang untuk mengetahui butirannya."</string>
+    <!-- no translation found for stk_cc_ussd_to_dial (5202342984749947872) -->
+    <skip />
+    <!-- no translation found for stk_cc_ussd_to_ss (2345360594181405482) -->
+    <skip />
+    <!-- no translation found for stk_cc_ussd_to_ussd (7466087659967191653) -->
+    <skip />
+    <!-- no translation found for stk_cc_ss_to_dial (2151304435775557162) -->
+    <skip />
+    <!-- no translation found for stk_cc_ss_to_ussd (3951862188105305589) -->
+    <skip />
+    <!-- no translation found for stk_cc_ss_to_ss (5470768854991452695) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-my-rMM/strings.xml b/core/res/res/values-my-rMM/strings.xml
index 2beba37..c2ea4bd 100644
--- a/core/res/res/values-my-rMM/strings.xml
+++ b/core/res/res/values-my-rMM/strings.xml
@@ -564,6 +564,8 @@
     <string name="permdesc_configureWifiDisplay" msgid="7916815158690218065">"အပလီကေးရှင်းအား ဝိုင်ဖိုင်မှ တဆင့် ပြသမှုအား ပြင်ဆင်ခြင်း၊ ဆက်သွယ်ခြင်း ခွင့်ပြုပါ"</string>
     <string name="permlab_controlWifiDisplay" msgid="393641276723695496">"ဝိုင်ဖိုင်ဖြင့် ပြသမှု အား ထိန်းချုပ်ရန်"</string>
     <string name="permdesc_controlWifiDisplay" msgid="4543912292681826986">"အပလီကေးရှင်းအား စက်ရဲ့ အနိမ့်ပိုင်းမှာ ရှိသော ဝိုင်ဖိုင် ပြသမှုအား ထိန်းချုပ်ခွင့်ပြုပါ"</string>
+    <string name="permlab_controlVpn" msgid="2618442789397588200">"ကိုယ်ပိုင်ကွန်ယက်အတုကို ထိန်းချုပ်ရန်"</string>
+    <string name="permdesc_controlVpn" msgid="762852603315861214">"ကိုယ်ပိုင်ကွန်ယက်အတု၏ အရည်အသွေးနိမ့်လုပ်ဆောင်ချက်များကို ထိန်းချုပ်ရန် app အား ခွင့်ပြုပါ။"</string>
     <string name="permlab_captureAudioOutput" msgid="6857134498402346708">"အသံထွက်မှု အား ဖမ်းယူခြင်း"</string>
     <string name="permdesc_captureAudioOutput" msgid="6210597754212208853">"အပလီကေးရှင်းကို အသံဖမ်းခွင့် လမ်းကြောင်းလွှဲခွင့်များ ခွင့်ပြုခြင်း"</string>
     <string name="permlab_captureAudioHotword" msgid="1890553935650349808">"အသံဖြင့်ညွှန်ကြားရန်အတိုကောက်များအား ဖမ်းယူ သိနိုင်မှု"</string>
@@ -1900,4 +1902,18 @@
     <string name="zen_mode_next_alarm_summary" msgid="5915140424683747372">"နောက်ထပ် <xliff:g id="FORMATTEDTIME">%1$s</xliff:g> ၌နိုးစက်အထိ"</string>
     <string name="zen_mode_next_alarm_line_one" msgid="5537042951553420916">"နောက်ထပ်နိုးစက်အထိ"</string>
     <string name="muted_by" msgid="6147073845094180001">"<xliff:g id="THIRD_PARTY">%1$s</xliff:g> အသံပိတ်သည်"</string>
+    <string name="system_error_wipe_data" msgid="6608165524785354962">"သင့်ကိရိယာအတွင်းပိုင်းတွင် ပြဿနာရှိနေပြီး၊ မူလစက်ရုံထုတ်အခြေအနေအဖြစ် ပြန်လည်ရယူနိုင်သည်အထိ အခြေအနေမတည်ငြိမ်နိုင်ပါ။"</string>
+    <string name="system_error_manufacturer" msgid="8086872414744210668">"သင့်ကိရိယာအတွင်းပိုင်းတွင် ပြဿနာရှိနေ၏။ အသေးစိတ်သိရန်အတွက် ပစ္စည်းထုတ်လုပ်သူအား ဆက်သွယ်ပါ။"</string>
+    <!-- no translation found for stk_cc_ussd_to_dial (5202342984749947872) -->
+    <skip />
+    <!-- no translation found for stk_cc_ussd_to_ss (2345360594181405482) -->
+    <skip />
+    <!-- no translation found for stk_cc_ussd_to_ussd (7466087659967191653) -->
+    <skip />
+    <!-- no translation found for stk_cc_ss_to_dial (2151304435775557162) -->
+    <skip />
+    <!-- no translation found for stk_cc_ss_to_ussd (3951862188105305589) -->
+    <skip />
+    <!-- no translation found for stk_cc_ss_to_ss (5470768854991452695) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-nb/strings.xml b/core/res/res/values-nb/strings.xml
index e2c8f05..101f201 100644
--- a/core/res/res/values-nb/strings.xml
+++ b/core/res/res/values-nb/strings.xml
@@ -564,6 +564,8 @@
     <string name="permdesc_configureWifiDisplay" msgid="7916815158690218065">"Tillater appen å konfigurere og koble til Wi-Fi-skjermer."</string>
     <string name="permlab_controlWifiDisplay" msgid="393641276723695496">"kontrollere Wi-Fi-skjermer"</string>
     <string name="permdesc_controlWifiDisplay" msgid="4543912292681826986">"Tillater appen å kontrollere lavnivåfunksjoner i Wi-Fi-skjermer."</string>
+    <string name="permlab_controlVpn" msgid="2618442789397588200">"kontrollér virtuelle private nettverk"</string>
+    <string name="permdesc_controlVpn" msgid="762852603315861214">"Lar appen kontrollere de grunnleggende funksjonene for virtuelle private nettverk."</string>
     <string name="permlab_captureAudioOutput" msgid="6857134498402346708">"ta opp fra lydutdata"</string>
     <string name="permdesc_captureAudioOutput" msgid="6210597754212208853">"Lar appen ta opp og omdirigere lydutdata."</string>
     <string name="permlab_captureAudioHotword" msgid="1890553935650349808">"Gjenkjennelse av kommandoord"</string>
@@ -1902,4 +1904,18 @@
     <string name="zen_mode_next_alarm_summary" msgid="5915140424683747372">"Inntil neste alarm kl. <xliff:g id="FORMATTEDTIME">%1$s</xliff:g>"</string>
     <string name="zen_mode_next_alarm_line_one" msgid="5537042951553420916">"Inntil neste alarm"</string>
     <string name="muted_by" msgid="6147073845094180001">"<xliff:g id="THIRD_PARTY">%1$s</xliff:g> har kuttet lyden"</string>
+    <string name="system_error_wipe_data" msgid="6608165524785354962">"Det har oppstått et internt problem på enheten din, og den kan være ustabil til du tilbakestiller den til fabrikkdata."</string>
+    <string name="system_error_manufacturer" msgid="8086872414744210668">"Det har oppstått et internt problem på enheten din. Ta kontakt med produsenten for mer informasjon."</string>
+    <!-- no translation found for stk_cc_ussd_to_dial (5202342984749947872) -->
+    <skip />
+    <!-- no translation found for stk_cc_ussd_to_ss (2345360594181405482) -->
+    <skip />
+    <!-- no translation found for stk_cc_ussd_to_ussd (7466087659967191653) -->
+    <skip />
+    <!-- no translation found for stk_cc_ss_to_dial (2151304435775557162) -->
+    <skip />
+    <!-- no translation found for stk_cc_ss_to_ussd (3951862188105305589) -->
+    <skip />
+    <!-- no translation found for stk_cc_ss_to_ss (5470768854991452695) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-ne-rNP/strings.xml b/core/res/res/values-ne-rNP/strings.xml
index 168e5f2..c8193c2 100644
--- a/core/res/res/values-ne-rNP/strings.xml
+++ b/core/res/res/values-ne-rNP/strings.xml
@@ -564,6 +564,8 @@
     <string name="permdesc_configureWifiDisplay" msgid="7916815158690218065">"अनुप्रयोगलाई कन्फिगर गर्न र वाइफाइ प्रदर्शनहरूसँग जोड्न अनुमति दिन्छ।"</string>
     <string name="permlab_controlWifiDisplay" msgid="393641276723695496">"वाइफाइ प्रदर्शनहरू नियन्त्रण गर्नुहोस्"</string>
     <string name="permdesc_controlWifiDisplay" msgid="4543912292681826986">"वाइफाइ प्रदर्शनीका तल्लो तह विषेशताहरू नियन्त्रण गर्न अनुप्रयोगलाई अनुमति दिन्छ।"</string>
+    <string name="permlab_controlVpn" msgid="2618442789397588200">"भर्चुअल निजी नेटवर्कलाई नियन्त्रण गर्छ"</string>
+    <string name="permdesc_controlVpn" msgid="762852603315861214">"भर्चुअल निजी नेटवर्कहरूको कम-स्तर सुविधाहरू नियन्त्रण गर्न एपलाई अनुमति दिन्छ।"</string>
     <string name="permlab_captureAudioOutput" msgid="6857134498402346708">"अडियो आउटपुट कैद गर्नुहोस्"</string>
     <string name="permdesc_captureAudioOutput" msgid="6210597754212208853">"अनुप्रयोगलाई अडियो आउटपुट कैद गर्न र रिडाइरेक्ट गर्न अनुमति दिन्छ।"</string>
     <string name="permlab_captureAudioHotword" msgid="1890553935650349808">"Hotword पत्ता लगाउने कार्य"</string>
@@ -1910,4 +1912,18 @@
     <string name="zen_mode_next_alarm_summary" msgid="5915140424683747372">"<xliff:g id="FORMATTEDTIME">%1$s</xliff:g> मा अर्को अलार्म सम्म"</string>
     <string name="zen_mode_next_alarm_line_one" msgid="5537042951553420916">"अर्को अलार्म सम्म"</string>
     <string name="muted_by" msgid="6147073845094180001">"<xliff:g id="THIRD_PARTY">%1$s</xliff:g> द्वारा मौन गरिएको"</string>
+    <string name="system_error_wipe_data" msgid="6608165524785354962">"तपाईंको यन्त्रसँग आन्तरिक समस्या छ, र तपाईंले फ्याक्ट्री डाटा रिसेट नगर्दासम्म यो अस्थिर रहन्छ।"</string>
+    <string name="system_error_manufacturer" msgid="8086872414744210668">"तपाईंको यन्त्रसँग आन्तरिक समस्या छ। विवरणहरूको लागि आफ्नो निर्मातासँग सम्पर्क गर्नुहोस्।"</string>
+    <!-- no translation found for stk_cc_ussd_to_dial (5202342984749947872) -->
+    <skip />
+    <!-- no translation found for stk_cc_ussd_to_ss (2345360594181405482) -->
+    <skip />
+    <!-- no translation found for stk_cc_ussd_to_ussd (7466087659967191653) -->
+    <skip />
+    <!-- no translation found for stk_cc_ss_to_dial (2151304435775557162) -->
+    <skip />
+    <!-- no translation found for stk_cc_ss_to_ussd (3951862188105305589) -->
+    <skip />
+    <!-- no translation found for stk_cc_ss_to_ss (5470768854991452695) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-nl/strings.xml b/core/res/res/values-nl/strings.xml
index c5e70bd..668d7b0 100644
--- a/core/res/res/values-nl/strings.xml
+++ b/core/res/res/values-nl/strings.xml
@@ -564,6 +564,8 @@
     <string name="permdesc_configureWifiDisplay" msgid="7916815158690218065">"De app toestaan wifi-displays te configureren en hiermee verbinding te maken."</string>
     <string name="permlab_controlWifiDisplay" msgid="393641276723695496">"wifi-displays beheren"</string>
     <string name="permdesc_controlWifiDisplay" msgid="4543912292681826986">"De app toestaan minder belangrijke functies van wifi-displays te beheren."</string>
+    <string name="permlab_controlVpn" msgid="2618442789397588200">"VPN\'s (Virtual Private Networks) beheren"</string>
+    <string name="permdesc_controlVpn" msgid="762852603315861214">"Hiermee kan de app VPN-functies (Virtual Private Networks) op laag niveau beheren."</string>
     <string name="permlab_captureAudioOutput" msgid="6857134498402346708">"audio-uitvoer vastleggen"</string>
     <string name="permdesc_captureAudioOutput" msgid="6210597754212208853">"Hiermee kan de app audio-uitvoer vastleggen en verwerken."</string>
     <string name="permlab_captureAudioHotword" msgid="1890553935650349808">"Detectie van hotwords"</string>
@@ -1902,4 +1904,18 @@
     <string name="zen_mode_next_alarm_summary" msgid="5915140424683747372">"Tot het volgende alarm om <xliff:g id="FORMATTEDTIME">%1$s</xliff:g>"</string>
     <string name="zen_mode_next_alarm_line_one" msgid="5537042951553420916">"Tot het volgende alarm"</string>
     <string name="muted_by" msgid="6147073845094180001">"Gedempt door <xliff:g id="THIRD_PARTY">%1$s</xliff:g>"</string>
+    <string name="system_error_wipe_data" msgid="6608165524785354962">"Er is een intern probleem met uw apparaat. Het apparaat kan instabiel zijn totdat u het apparaat terugzet naar de fabrieksinstellingen."</string>
+    <string name="system_error_manufacturer" msgid="8086872414744210668">"Er is een intern probleem met uw apparaat. Neem contact op met de fabrikant voor meer informatie."</string>
+    <!-- no translation found for stk_cc_ussd_to_dial (5202342984749947872) -->
+    <skip />
+    <!-- no translation found for stk_cc_ussd_to_ss (2345360594181405482) -->
+    <skip />
+    <!-- no translation found for stk_cc_ussd_to_ussd (7466087659967191653) -->
+    <skip />
+    <!-- no translation found for stk_cc_ss_to_dial (2151304435775557162) -->
+    <skip />
+    <!-- no translation found for stk_cc_ss_to_ussd (3951862188105305589) -->
+    <skip />
+    <!-- no translation found for stk_cc_ss_to_ss (5470768854991452695) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-pl/strings.xml b/core/res/res/values-pl/strings.xml
index f50ab9bc..83303b7 100644
--- a/core/res/res/values-pl/strings.xml
+++ b/core/res/res/values-pl/strings.xml
@@ -564,6 +564,8 @@
     <string name="permdesc_configureWifiDisplay" msgid="7916815158690218065">"Zezwala aplikacji na konfigurację wyświetlaczy Wi-Fi i łączenie z nimi."</string>
     <string name="permlab_controlWifiDisplay" msgid="393641276723695496">"zarządzanie wyświetlaczami Wi-Fi"</string>
     <string name="permdesc_controlWifiDisplay" msgid="4543912292681826986">"Zezwala aplikacji na zarządzanie niskopoziomowymi funkcjami wyświetlaczy Wi-Fi."</string>
+    <string name="permlab_controlVpn" msgid="2618442789397588200">"kontrola nad wirtualnymi sieciami prywatnymi (VPN)"</string>
+    <string name="permdesc_controlVpn" msgid="762852603315861214">"Zezwala aplikacji na kontrolę nad niskopoziomowymi funkcjami wirtualnych sieci prywatnych (VPN)."</string>
     <string name="permlab_captureAudioOutput" msgid="6857134498402346708">"przechwyć wyjście audio"</string>
     <string name="permdesc_captureAudioOutput" msgid="6210597754212208853">"Zezwala aplikacji na przechwytywanie i przekierowywanie wyjścia audio."</string>
     <string name="permlab_captureAudioHotword" msgid="1890553935650349808">"Wykrywanie słów-kluczy"</string>
@@ -1902,4 +1904,18 @@
     <string name="zen_mode_next_alarm_summary" msgid="5915140424683747372">"Do następnego alarmu o <xliff:g id="FORMATTEDTIME">%1$s</xliff:g>"</string>
     <string name="zen_mode_next_alarm_line_one" msgid="5537042951553420916">"Do następnego alarmu"</string>
     <string name="muted_by" msgid="6147073845094180001">"Ściszone przez: <xliff:g id="THIRD_PARTY">%1$s</xliff:g>"</string>
+    <string name="system_error_wipe_data" msgid="6608165524785354962">"W Twoim urządzeniu wystąpił problem wewnętrzny. Może być ono niestabilne, dopóki nie przywrócisz danych fabrycznych."</string>
+    <string name="system_error_manufacturer" msgid="8086872414744210668">"W Twoim urządzeniu wystąpił problem wewnętrzny. Skontaktuj się z jego producentem, by otrzymać szczegółowe informacje."</string>
+    <!-- no translation found for stk_cc_ussd_to_dial (5202342984749947872) -->
+    <skip />
+    <!-- no translation found for stk_cc_ussd_to_ss (2345360594181405482) -->
+    <skip />
+    <!-- no translation found for stk_cc_ussd_to_ussd (7466087659967191653) -->
+    <skip />
+    <!-- no translation found for stk_cc_ss_to_dial (2151304435775557162) -->
+    <skip />
+    <!-- no translation found for stk_cc_ss_to_ussd (3951862188105305589) -->
+    <skip />
+    <!-- no translation found for stk_cc_ss_to_ss (5470768854991452695) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-pt-rPT/strings.xml b/core/res/res/values-pt-rPT/strings.xml
index 16385b4..b1ebcc9 100644
--- a/core/res/res/values-pt-rPT/strings.xml
+++ b/core/res/res/values-pt-rPT/strings.xml
@@ -564,6 +564,8 @@
     <string name="permdesc_configureWifiDisplay" msgid="7916815158690218065">"Permite que a aplicação se configure e se ligue a visores Wi-Fi."</string>
     <string name="permlab_controlWifiDisplay" msgid="393641276723695496">"controlar visores Wi-Fi"</string>
     <string name="permdesc_controlWifiDisplay" msgid="4543912292681826986">"Permite que a aplicação controle funcionalidades de baixo nível em visores Wi-Fi."</string>
+    <string name="permlab_controlVpn" msgid="2618442789397588200">"controlar Redes privadas virtuais"</string>
+    <string name="permdesc_controlVpn" msgid="762852603315861214">"Permite que a aplicação controle funcionalidades de baixo nível de Redes privadas virtuais"</string>
     <string name="permlab_captureAudioOutput" msgid="6857134498402346708">"capturar saída de áudio"</string>
     <string name="permdesc_captureAudioOutput" msgid="6210597754212208853">"Permite à aplicação capturar e redirecionar a saída de áudio."</string>
     <string name="permlab_captureAudioHotword" msgid="1890553935650349808">"Deteção de palavra de ativação"</string>
@@ -1902,4 +1904,18 @@
     <string name="zen_mode_next_alarm_summary" msgid="5915140424683747372">"Até ao próximo alarme, às <xliff:g id="FORMATTEDTIME">%1$s</xliff:g>"</string>
     <string name="zen_mode_next_alarm_line_one" msgid="5537042951553420916">"Até ao próximo alarme"</string>
     <string name="muted_by" msgid="6147073845094180001">"Som desativado por <xliff:g id="THIRD_PARTY">%1$s</xliff:g>"</string>
+    <string name="system_error_wipe_data" msgid="6608165524785354962">"Existe um problema interno no seu dispositivo e pode ficar instável até efetuar uma reposição de dados de fábrica."</string>
+    <string name="system_error_manufacturer" msgid="8086872414744210668">"Existe um problema interno no seu dispositivo. Contacte o fabricante para obter mais informações."</string>
+    <!-- no translation found for stk_cc_ussd_to_dial (5202342984749947872) -->
+    <skip />
+    <!-- no translation found for stk_cc_ussd_to_ss (2345360594181405482) -->
+    <skip />
+    <!-- no translation found for stk_cc_ussd_to_ussd (7466087659967191653) -->
+    <skip />
+    <!-- no translation found for stk_cc_ss_to_dial (2151304435775557162) -->
+    <skip />
+    <!-- no translation found for stk_cc_ss_to_ussd (3951862188105305589) -->
+    <skip />
+    <!-- no translation found for stk_cc_ss_to_ss (5470768854991452695) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-pt/strings.xml b/core/res/res/values-pt/strings.xml
index 92143b9..00b82be 100644
--- a/core/res/res/values-pt/strings.xml
+++ b/core/res/res/values-pt/strings.xml
@@ -564,6 +564,8 @@
     <string name="permdesc_configureWifiDisplay" msgid="7916815158690218065">"Permite que o app configure e conecte a monitores Wi-Fi."</string>
     <string name="permlab_controlWifiDisplay" msgid="393641276723695496">"controlar monitores Wi-Fi"</string>
     <string name="permdesc_controlWifiDisplay" msgid="4543912292681826986">"Permite que o app controle recursos de baixo nível de monitores Wi-Fi."</string>
+    <string name="permlab_controlVpn" msgid="2618442789397588200">"controlar Redes Privadas Virtuais"</string>
+    <string name="permdesc_controlVpn" msgid="762852603315861214">"Permite que o app controle os recursos de nível inferior das Redes Privadas Virtuais."</string>
     <string name="permlab_captureAudioOutput" msgid="6857134498402346708">"capturar saída de áudio"</string>
     <string name="permdesc_captureAudioOutput" msgid="6210597754212208853">"Permite que o app capture e redirecione a saída de áudio."</string>
     <string name="permlab_captureAudioHotword" msgid="1890553935650349808">"Detecção de hotwords"</string>
@@ -795,14 +797,10 @@
     <string name="permdesc_cache_filesystem" msgid="5578967642265550955">"Permite que o app leia e grave o sistema de arquivos cache."</string>
     <string name="permlab_use_sip" msgid="2052499390128979920">"fazer/receber chamadas SIP"</string>
     <string name="permdesc_use_sip" msgid="2297804849860225257">"Permite que o app faça e receba chamadas SIP."</string>
-    <!-- no translation found for permlab_register_sim_subscription (3166535485877549177) -->
-    <skip />
-    <!-- no translation found for permdesc_register_sim_subscription (2138909035926222911) -->
-    <skip />
-    <!-- no translation found for permlab_register_call_provider (108102120289029841) -->
-    <skip />
-    <!-- no translation found for permdesc_register_call_provider (7034310263521081388) -->
-    <skip />
+    <string name="permlab_register_sim_subscription" msgid="3166535485877549177">"registrar novas conexões SIM de telecomunicações"</string>
+    <string name="permdesc_register_sim_subscription" msgid="2138909035926222911">"Permite que o app registre novas conexões SIM de telecomunicações."</string>
+    <string name="permlab_register_call_provider" msgid="108102120289029841">"registrar novas conexões de telecomunicações"</string>
+    <string name="permdesc_register_call_provider" msgid="7034310263521081388">"Permite que o app registre novas conexões de telecomunicações."</string>
     <string name="permlab_connection_manager" msgid="1116193254522105375">"gerenciar conexões de telecomunicações"</string>
     <string name="permdesc_connection_manager" msgid="5925480810356483565">"Permite que o app gerencie conexões de telecomunicações."</string>
     <string name="permlab_bind_incall_service" msgid="6773648341975287125">"interagir com chamada na tela"</string>
@@ -1906,4 +1904,18 @@
     <string name="zen_mode_next_alarm_summary" msgid="5915140424683747372">"Até o próximo alarme em <xliff:g id="FORMATTEDTIME">%1$s</xliff:g>"</string>
     <string name="zen_mode_next_alarm_line_one" msgid="5537042951553420916">"Até o próximo alarme"</string>
     <string name="muted_by" msgid="6147073845094180001">"Som desativado por <xliff:g id="THIRD_PARTY">%1$s</xliff:g>"</string>
+    <string name="system_error_wipe_data" msgid="6608165524785354962">"Há um problema interno com seu dispositivo. Ele pode ficar instável até que você faça a redefinição para configuração original."</string>
+    <string name="system_error_manufacturer" msgid="8086872414744210668">"Há um problema interno com seu dispositivo. Entre em contato com o fabricante para saber mais detalhes."</string>
+    <!-- no translation found for stk_cc_ussd_to_dial (5202342984749947872) -->
+    <skip />
+    <!-- no translation found for stk_cc_ussd_to_ss (2345360594181405482) -->
+    <skip />
+    <!-- no translation found for stk_cc_ussd_to_ussd (7466087659967191653) -->
+    <skip />
+    <!-- no translation found for stk_cc_ss_to_dial (2151304435775557162) -->
+    <skip />
+    <!-- no translation found for stk_cc_ss_to_ussd (3951862188105305589) -->
+    <skip />
+    <!-- no translation found for stk_cc_ss_to_ss (5470768854991452695) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-ro/strings.xml b/core/res/res/values-ro/strings.xml
index 70f3b49..57e72a8 100644
--- a/core/res/res/values-ro/strings.xml
+++ b/core/res/res/values-ro/strings.xml
@@ -564,6 +564,8 @@
     <string name="permdesc_configureWifiDisplay" msgid="7916815158690218065">"Permite aplicaţiei să configureze şi să se conecteze la afişaje Wi-Fi."</string>
     <string name="permlab_controlWifiDisplay" msgid="393641276723695496">"controlează afişaje Wi-Fi"</string>
     <string name="permdesc_controlWifiDisplay" msgid="4543912292681826986">"Permite aplicaţiei să controleze funcţiile de nivel redus ale afişajelor Wi-Fi."</string>
+    <string name="permlab_controlVpn" msgid="2618442789397588200">"controlează rețelele private virtuale"</string>
+    <string name="permdesc_controlVpn" msgid="762852603315861214">"Permite aplicației să controleze funcțiile de nivel inferior ale rețelelor private virtuale."</string>
     <string name="permlab_captureAudioOutput" msgid="6857134498402346708">"să intercepteze ieșirea audio"</string>
     <string name="permdesc_captureAudioOutput" msgid="6210597754212208853">"Permite aplicației să intercepteze și să redirecționeze ieșirea audio."</string>
     <string name="permlab_captureAudioHotword" msgid="1890553935650349808">"detectarea expresiei de activare"</string>
@@ -834,7 +836,7 @@
     <string name="permlab_removeDrmCertificates" msgid="7044888287209892751">"eliminarea certificatelor DRM"</string>
     <string name="permdesc_removeDrmCertificates" msgid="7272999075113400993">"Permite unei aplicații să elimine certificatele DRM. Nu ar trebui să fie necesară pentru aplicațiile obișnuite."</string>
     <string name="permlab_bindCarrierMessagingService" msgid="1490229371796969158">"se conectează la un serviciu de mesagerie oferit de operator"</string>
-    <string name="permdesc_bindCarrierMessagingService" msgid="2762882888502113944">"Permite proprietarului să se conecteze la interfața de nivel superior a unui serviciu de mesagerie oferit de operator. Nu ar trebui să fie niciodată necesară pentru aplicațiile obișnuite."</string>
+    <string name="permdesc_bindCarrierMessagingService" msgid="2762882888502113944">"Permite aplicației să se conecteze la interfața de nivel superior a unui serviciu de mesagerie oferit de operator. Nu ar trebui să fie niciodată necesară pentru aplicațiile obișnuite."</string>
     <string name="policylab_limitPassword" msgid="4497420728857585791">"Setaţi reguli pentru parolă"</string>
     <string name="policydesc_limitPassword" msgid="3252114203919510394">"Stabiliţi lungimea şi tipul de caractere permise în parolele pentru deblocarea ecranului."</string>
     <string name="policylab_watchLogin" msgid="914130646942199503">"Monitorizaţi încercările de deblocare a ecranului"</string>
@@ -1902,4 +1904,18 @@
     <string name="zen_mode_next_alarm_summary" msgid="5915140424683747372">"Până la alarma următoare, la <xliff:g id="FORMATTEDTIME">%1$s</xliff:g>"</string>
     <string name="zen_mode_next_alarm_line_one" msgid="5537042951553420916">"Până la alarma următoare"</string>
     <string name="muted_by" msgid="6147073845094180001">"Dezactivate de <xliff:g id="THIRD_PARTY">%1$s</xliff:g>"</string>
+    <string name="system_error_wipe_data" msgid="6608165524785354962">"A apărut o problemă internă pe dispozitiv, iar acesta poate fi instabil până la revenirea la setările din fabrică."</string>
+    <string name="system_error_manufacturer" msgid="8086872414744210668">"A apărut o problemă internă pe dispozitiv. Pentru detalii, contactați producătorul."</string>
+    <!-- no translation found for stk_cc_ussd_to_dial (5202342984749947872) -->
+    <skip />
+    <!-- no translation found for stk_cc_ussd_to_ss (2345360594181405482) -->
+    <skip />
+    <!-- no translation found for stk_cc_ussd_to_ussd (7466087659967191653) -->
+    <skip />
+    <!-- no translation found for stk_cc_ss_to_dial (2151304435775557162) -->
+    <skip />
+    <!-- no translation found for stk_cc_ss_to_ussd (3951862188105305589) -->
+    <skip />
+    <!-- no translation found for stk_cc_ss_to_ss (5470768854991452695) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-ru/strings.xml b/core/res/res/values-ru/strings.xml
index 18fc49f..768b071 100644
--- a/core/res/res/values-ru/strings.xml
+++ b/core/res/res/values-ru/strings.xml
@@ -564,6 +564,8 @@
     <string name="permdesc_configureWifiDisplay" msgid="7916815158690218065">"Приложение сможет подключаться к экранам с помощью Wi-Fi и настраивать их."</string>
     <string name="permlab_controlWifiDisplay" msgid="393641276723695496">"Управление мониторами, подключенными через Wi-Fi"</string>
     <string name="permdesc_controlWifiDisplay" msgid="4543912292681826986">"Приложение сможет управлять низкоуровневыми функциями экранов, подключенных через Wi-Fi."</string>
+    <string name="permlab_controlVpn" msgid="2618442789397588200">"управление виртуальными частными сетями"</string>
+    <string name="permdesc_controlVpn" msgid="762852603315861214">"Управление низкоуровневыми функциями виртуальных частных сетей."</string>
     <string name="permlab_captureAudioOutput" msgid="6857134498402346708">"захват аудиосигнала"</string>
     <string name="permdesc_captureAudioOutput" msgid="6210597754212208853">"Приложение сможет захватывать и перенаправлять аудиосигнал."</string>
     <string name="permlab_captureAudioHotword" msgid="1890553935650349808">"распознавать голосовые команды"</string>
@@ -1902,4 +1904,18 @@
     <string name="zen_mode_next_alarm_summary" msgid="5915140424683747372">"До следующего будильника в <xliff:g id="FORMATTEDTIME">%1$s</xliff:g>"</string>
     <string name="zen_mode_next_alarm_line_one" msgid="5537042951553420916">"До следующего будильника"</string>
     <string name="muted_by" msgid="6147073845094180001">"Звук отключен приложением \"<xliff:g id="THIRD_PARTY">%1$s</xliff:g>\""</string>
+    <string name="system_error_wipe_data" msgid="6608165524785354962">"Произошла внутренняя ошибка, и устройство может работать нестабильно, пока вы не выполните сброс настроек."</string>
+    <string name="system_error_manufacturer" msgid="8086872414744210668">"Произошла внутренняя ошибка. Обратитесь к производителю устройства за подробными сведениями."</string>
+    <!-- no translation found for stk_cc_ussd_to_dial (5202342984749947872) -->
+    <skip />
+    <!-- no translation found for stk_cc_ussd_to_ss (2345360594181405482) -->
+    <skip />
+    <!-- no translation found for stk_cc_ussd_to_ussd (7466087659967191653) -->
+    <skip />
+    <!-- no translation found for stk_cc_ss_to_dial (2151304435775557162) -->
+    <skip />
+    <!-- no translation found for stk_cc_ss_to_ussd (3951862188105305589) -->
+    <skip />
+    <!-- no translation found for stk_cc_ss_to_ss (5470768854991452695) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-si-rLK/strings.xml b/core/res/res/values-si-rLK/strings.xml
index af76b0f..3460606 100644
--- a/core/res/res/values-si-rLK/strings.xml
+++ b/core/res/res/values-si-rLK/strings.xml
@@ -564,6 +564,8 @@
     <string name="permdesc_configureWifiDisplay" msgid="7916815158690218065">"වින්‍යාස කිරීමට සහ Wifi සංදර්ශක වෙත සම්බන්ධ වීමට යෙදුමට අවසර දෙන්න."</string>
     <string name="permlab_controlWifiDisplay" msgid="393641276723695496">"Wifi සංදර්ශක පාලනය"</string>
     <string name="permdesc_controlWifiDisplay" msgid="4543912292681826986">"Wifi සංදර්ශකයේ පහළ මට්ටමේ විශේෂාංග පාලනයට යෙදුමට අවසර දෙන්න."</string>
+    <string name="permlab_controlVpn" msgid="2618442789397588200">"අතථ්‍ය පුද්ගලික ජාල පාලනය කරන්න"</string>
+    <string name="permdesc_controlVpn" msgid="762852603315861214">"යෙදුමට අතථ්‍ය පුද්ගලික ජාලවල පහළ-මට්ටම් විශේෂාංග පාලනය කිරීමට ඉඩ දෙයි."</string>
     <string name="permlab_captureAudioOutput" msgid="6857134498402346708">"ශබ්ද ප්‍රතිදානය ග්‍රහණය"</string>
     <string name="permdesc_captureAudioOutput" msgid="6210597754212208853">"යෙදුමට ශබ්ද ප්‍රතිදානය ග්‍රහණය කර හරවා යැවීමට ඉඩ දේ."</string>
     <string name="permlab_captureAudioHotword" msgid="1890553935650349808">"Hotword හදුනා ගැනීම"</string>
@@ -1904,4 +1906,18 @@
     <string name="zen_mode_next_alarm_summary" msgid="5915140424683747372">"<xliff:g id="FORMATTEDTIME">%1$s</xliff:g> හි ඊළඟ සීනුව තෙක්"</string>
     <string name="zen_mode_next_alarm_line_one" msgid="5537042951553420916">"ඊළඟ සීනුව තෙක්"</string>
     <string name="muted_by" msgid="6147073845094180001">"<xliff:g id="THIRD_PARTY">%1$s</xliff:g> විසින් නිශ්ශබ්ද කරන ලදි"</string>
+    <string name="system_error_wipe_data" msgid="6608165524785354962">"ඔබේ උපාංගය සමගින් ගැටලුවක් ඇති අතර, ඔබේ කර්මාන්තශාලා දත්ත යළි සකසන තෙක් එය අස්ථායි විය හැකිය."</string>
+    <string name="system_error_manufacturer" msgid="8086872414744210668">"ඔබේ උපාංගය සමගින් අභ්‍යන්තර ගැටලුවක් ඇත. විස්තර සඳහා ඔබේ නිෂ්පාදක අමතන්න."</string>
+    <!-- no translation found for stk_cc_ussd_to_dial (5202342984749947872) -->
+    <skip />
+    <!-- no translation found for stk_cc_ussd_to_ss (2345360594181405482) -->
+    <skip />
+    <!-- no translation found for stk_cc_ussd_to_ussd (7466087659967191653) -->
+    <skip />
+    <!-- no translation found for stk_cc_ss_to_dial (2151304435775557162) -->
+    <skip />
+    <!-- no translation found for stk_cc_ss_to_ussd (3951862188105305589) -->
+    <skip />
+    <!-- no translation found for stk_cc_ss_to_ss (5470768854991452695) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-sk/strings.xml b/core/res/res/values-sk/strings.xml
index f42a7dc..d29ef6b 100644
--- a/core/res/res/values-sk/strings.xml
+++ b/core/res/res/values-sk/strings.xml
@@ -564,6 +564,8 @@
     <string name="permdesc_configureWifiDisplay" msgid="7916815158690218065">"Umožňuje aplikácii konfigurovať displeje a pripojiť sa k nim cez siete Wi-Fi."</string>
     <string name="permlab_controlWifiDisplay" msgid="393641276723695496">"ovládať displeje cez sieť Wi-Fi"</string>
     <string name="permdesc_controlWifiDisplay" msgid="4543912292681826986">"Umožňuje aplikácii ovládať základné funkcie displejov cez siete Wi-Fi."</string>
+    <string name="permlab_controlVpn" msgid="2618442789397588200">"ovládanie virtuálnych súkromných sietí"</string>
+    <string name="permdesc_controlVpn" msgid="762852603315861214">"Umožňuje aplikáciám ovládať funkcie nízkej úrovne virtuálnych súkromných sietí."</string>
     <string name="permlab_captureAudioOutput" msgid="6857134498402346708">"zachytiť výstup zvuku"</string>
     <string name="permdesc_captureAudioOutput" msgid="6210597754212208853">"Umožňuje aplikácii zachytiť a presmerovať výstup zvuku."</string>
     <string name="permlab_captureAudioHotword" msgid="1890553935650349808">"Rozpoznanie kľúčových slov"</string>
@@ -1902,4 +1904,18 @@
     <string name="zen_mode_next_alarm_summary" msgid="5915140424683747372">"Do ďalšieho budíka o <xliff:g id="FORMATTEDTIME">%1$s</xliff:g>"</string>
     <string name="zen_mode_next_alarm_line_one" msgid="5537042951553420916">"Do ďalšieho budíka"</string>
     <string name="muted_by" msgid="6147073845094180001">"Stlmené aplikáciou <xliff:g id="THIRD_PARTY">%1$s</xliff:g>"</string>
+    <string name="system_error_wipe_data" msgid="6608165524785354962">"Vo vašom zariadení došlo k internému problému. Môže byť nestabilné, kým neobnovíte jeho továrenské nastavenia."</string>
+    <string name="system_error_manufacturer" msgid="8086872414744210668">"Vo vašom zariadení došlo k internému problému. Ak chcete získať podrobné informácie, obráťte sa na jeho výrobcu."</string>
+    <!-- no translation found for stk_cc_ussd_to_dial (5202342984749947872) -->
+    <skip />
+    <!-- no translation found for stk_cc_ussd_to_ss (2345360594181405482) -->
+    <skip />
+    <!-- no translation found for stk_cc_ussd_to_ussd (7466087659967191653) -->
+    <skip />
+    <!-- no translation found for stk_cc_ss_to_dial (2151304435775557162) -->
+    <skip />
+    <!-- no translation found for stk_cc_ss_to_ussd (3951862188105305589) -->
+    <skip />
+    <!-- no translation found for stk_cc_ss_to_ss (5470768854991452695) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-sl/strings.xml b/core/res/res/values-sl/strings.xml
index ba85bde..8880265 100644
--- a/core/res/res/values-sl/strings.xml
+++ b/core/res/res/values-sl/strings.xml
@@ -564,6 +564,8 @@
     <string name="permdesc_configureWifiDisplay" msgid="7916815158690218065">"Omogoča aplikaciji konfiguriranje zaslonov Wi-Fi in povezovanje z njimi."</string>
     <string name="permlab_controlWifiDisplay" msgid="393641276723695496">"nadzor zaslonov Wi-Fi"</string>
     <string name="permdesc_controlWifiDisplay" msgid="4543912292681826986">"Omogoča aplikaciji nadzor osnovnih funkcij zaslonov Wi-Fi."</string>
+    <string name="permlab_controlVpn" msgid="2618442789397588200">"upravljanje navideznih zasebnih omrežij"</string>
+    <string name="permdesc_controlVpn" msgid="762852603315861214">"Aplikaciji omogoča upravljanje funkcij nizke ravni navideznih zasebnih omrežij."</string>
     <string name="permlab_captureAudioOutput" msgid="6857134498402346708">"zajem avdioizhoda"</string>
     <string name="permdesc_captureAudioOutput" msgid="6210597754212208853">"Omogoči aplikaciji, da zajame in preusmeri avdioizhod."</string>
     <string name="permlab_captureAudioHotword" msgid="1890553935650349808">"Zaznavanje sprožilnih besed"</string>
@@ -1902,4 +1904,18 @@
     <string name="zen_mode_next_alarm_summary" msgid="5915140424683747372">"Do naslednjega alarma ob <xliff:g id="FORMATTEDTIME">%1$s</xliff:g>"</string>
     <string name="zen_mode_next_alarm_line_one" msgid="5537042951553420916">"Do naslednjega alarma"</string>
     <string name="muted_by" msgid="6147073845094180001">"Izklop zvoka: <xliff:g id="THIRD_PARTY">%1$s</xliff:g>"</string>
+    <string name="system_error_wipe_data" msgid="6608165524785354962">"Vaša naprava ima notranjo napako in bo morda nestabilna, dokler je ne ponastavite na tovarniške nastavitve."</string>
+    <string name="system_error_manufacturer" msgid="8086872414744210668">"Vaša naprava ima notranjo napako. Če želite več informacij, se obrnite na proizvajalca."</string>
+    <!-- no translation found for stk_cc_ussd_to_dial (5202342984749947872) -->
+    <skip />
+    <!-- no translation found for stk_cc_ussd_to_ss (2345360594181405482) -->
+    <skip />
+    <!-- no translation found for stk_cc_ussd_to_ussd (7466087659967191653) -->
+    <skip />
+    <!-- no translation found for stk_cc_ss_to_dial (2151304435775557162) -->
+    <skip />
+    <!-- no translation found for stk_cc_ss_to_ussd (3951862188105305589) -->
+    <skip />
+    <!-- no translation found for stk_cc_ss_to_ss (5470768854991452695) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-sr/strings.xml b/core/res/res/values-sr/strings.xml
index 108b99d..e91a58b 100644
--- a/core/res/res/values-sr/strings.xml
+++ b/core/res/res/values-sr/strings.xml
@@ -564,6 +564,8 @@
     <string name="permdesc_configureWifiDisplay" msgid="7916815158690218065">"Дозвољава апликацији да конфигурише Wi-Fi екране и повезује се са њима."</string>
     <string name="permlab_controlWifiDisplay" msgid="393641276723695496">"контрола Wi-Fi екрана"</string>
     <string name="permdesc_controlWifiDisplay" msgid="4543912292681826986">"Дозвољава апликацији да контролише функције Wi-Fi екрана ниског нивоа."</string>
+    <string name="permlab_controlVpn" msgid="2618442789397588200">"контролиши виртуелне приватне мреже"</string>
+    <string name="permdesc_controlVpn" msgid="762852603315861214">"Дозвољава апликацији да контролише функције ниског нивоа виртуелних приватних мрежа."</string>
     <string name="permlab_captureAudioOutput" msgid="6857134498402346708">"снимање аудио садржаја"</string>
     <string name="permdesc_captureAudioOutput" msgid="6210597754212208853">"Дозвољава апликацији да снима и преусмерава аудио садржај."</string>
     <string name="permlab_captureAudioHotword" msgid="1890553935650349808">"Откривање актуелних речи"</string>
@@ -987,10 +989,10 @@
     <string name="emergency_call_dialog_number_for_display" msgid="696192103195090970">"Број за хитне случајеве"</string>
     <string name="lockscreen_carrier_default" msgid="8963839242565653192">"Нема услуге."</string>
     <string name="lockscreen_screen_locked" msgid="7288443074806832904">"Екран је закључан."</string>
-    <string name="lockscreen_instructions_when_pattern_enabled" msgid="46154051614126049">"Притисните „Мени“ да бисте откључали телефон или упутите хитни позив."</string>
+    <string name="lockscreen_instructions_when_pattern_enabled" msgid="46154051614126049">"Притисните „Мени“ да бисте откључали телефон или упутите хитан позив."</string>
     <string name="lockscreen_instructions_when_pattern_disabled" msgid="686260028797158364">"Притисните „Мени“ за откључавање."</string>
     <string name="lockscreen_pattern_instructions" msgid="7478703254964810302">"Унесите шаблон за откључавање"</string>
-    <string name="lockscreen_emergency_call" msgid="5347633784401285225">"Хитни позив"</string>
+    <string name="lockscreen_emergency_call" msgid="5347633784401285225">"Хитан позив"</string>
     <string name="lockscreen_return_to_call" msgid="5244259785500040021">"Назад на позив"</string>
     <string name="lockscreen_pattern_correct" msgid="9039008650362261237">"Тачно!"</string>
     <string name="lockscreen_pattern_wrong" msgid="4317955014948108794">"Покушајте поново"</string>
@@ -1640,7 +1642,7 @@
     <string name="data_usage_4g_limit_title" msgid="4609566827219442376">"Нема више 4G података"</string>
     <string name="data_usage_mobile_limit_title" msgid="557158376602636112">"Нема више подат. за мобил. уређ."</string>
     <string name="data_usage_wifi_limit_title" msgid="5803363779034792676">"Нема више Wi-Fi података"</string>
-    <string name="data_usage_limit_body" msgid="291731708279614081">"Нема података до краја циклуса"</string>
+    <string name="data_usage_limit_body" msgid="291731708279614081">"Потрошили сте податке за овај месец"</string>
     <string name="data_usage_3g_limit_snoozed_title" msgid="7026739121138005231">"Прекорачен пренос 2G-3G података"</string>
     <string name="data_usage_4g_limit_snoozed_title" msgid="1106562779311209039">"Прекорачење преноса 4G података"</string>
     <string name="data_usage_mobile_limit_snoozed_title" msgid="4941346653729943789">"Ограничење мобилних података је прекорачено"</string>
@@ -1698,7 +1700,7 @@
     <string name="display_manager_overlay_display_name" msgid="5142365982271620716">"Постављени елемент бр. <xliff:g id="ID">%1$d</xliff:g>"</string>
     <string name="display_manager_overlay_display_title" msgid="652124517672257172">"<xliff:g id="NAME">%1$s</xliff:g>: <xliff:g id="WIDTH">%2$d</xliff:g>×<xliff:g id="HEIGHT">%3$d</xliff:g>, <xliff:g id="DPI">%4$d</xliff:g> dpi"</string>
     <string name="display_manager_overlay_display_secure_suffix" msgid="6022119702628572080">", безбедно"</string>
-    <string name="kg_emergency_call_label" msgid="684946192523830531">"Хитни позив"</string>
+    <string name="kg_emergency_call_label" msgid="684946192523830531">"Хитан позив"</string>
     <string name="kg_forgot_pattern_button_text" msgid="8852021467868220608">"Заборављени шаблон"</string>
     <string name="kg_wrong_pattern" msgid="1850806070801358830">"Погрешан шаблон"</string>
     <string name="kg_wrong_password" msgid="2333281762128113157">"Погрешна лозинка"</string>
@@ -1902,4 +1904,18 @@
     <string name="zen_mode_next_alarm_summary" msgid="5915140424683747372">"До следећег аларма у <xliff:g id="FORMATTEDTIME">%1$s</xliff:g>"</string>
     <string name="zen_mode_next_alarm_line_one" msgid="5537042951553420916">"До следећег аларма"</string>
     <string name="muted_by" msgid="6147073845094180001">"Звук је искључио/ла <xliff:g id="THIRD_PARTY">%1$s</xliff:g>"</string>
+    <string name="system_error_wipe_data" msgid="6608165524785354962">"Дошло је до интерног проблема у вези са уређајем и можда ће бити нестабилан док не обавите ресетовање на фабричка подешавања."</string>
+    <string name="system_error_manufacturer" msgid="8086872414744210668">"Дошло је до интерног проблема у вези са уређајем. Потражите детаље од произвођача."</string>
+    <!-- no translation found for stk_cc_ussd_to_dial (5202342984749947872) -->
+    <skip />
+    <!-- no translation found for stk_cc_ussd_to_ss (2345360594181405482) -->
+    <skip />
+    <!-- no translation found for stk_cc_ussd_to_ussd (7466087659967191653) -->
+    <skip />
+    <!-- no translation found for stk_cc_ss_to_dial (2151304435775557162) -->
+    <skip />
+    <!-- no translation found for stk_cc_ss_to_ussd (3951862188105305589) -->
+    <skip />
+    <!-- no translation found for stk_cc_ss_to_ss (5470768854991452695) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-sv/strings.xml b/core/res/res/values-sv/strings.xml
index abbf28a..2023f5a 100644
--- a/core/res/res/values-sv/strings.xml
+++ b/core/res/res/values-sv/strings.xml
@@ -564,6 +564,8 @@
     <string name="permdesc_configureWifiDisplay" msgid="7916815158690218065">"Tillåter att appen konfigurerar och ansluter till Wi-Fi-skärmar."</string>
     <string name="permlab_controlWifiDisplay" msgid="393641276723695496">"kontrollerar Wi-Fi-skärmar"</string>
     <string name="permdesc_controlWifiDisplay" msgid="4543912292681826986">"Tillåter att appen kontrollerar grundläggande funktioner för Wi-Fi-skärmar."</string>
+    <string name="permlab_controlVpn" msgid="2618442789397588200">"styra virtuella privata nätverk"</string>
+    <string name="permdesc_controlVpn" msgid="762852603315861214">"Tillåter att appen styr grundläggande funktioner i virtuella privata nätverk."</string>
     <string name="permlab_captureAudioOutput" msgid="6857134498402346708">"fånga upp ljudutgång"</string>
     <string name="permdesc_captureAudioOutput" msgid="6210597754212208853">"Tillåt att appen fångar upp och omdirigerar ljudutgången."</string>
     <string name="permlab_captureAudioHotword" msgid="1890553935650349808">"Kommandoordsidentifiering"</string>
@@ -1902,4 +1904,18 @@
     <string name="zen_mode_next_alarm_summary" msgid="5915140424683747372">"Till nästa alarm kl. <xliff:g id="FORMATTEDTIME">%1$s</xliff:g>"</string>
     <string name="zen_mode_next_alarm_line_one" msgid="5537042951553420916">"Till nästa alarm"</string>
     <string name="muted_by" msgid="6147073845094180001">"<xliff:g id="THIRD_PARTY">%1$s</xliff:g> har stängt av ljudet"</string>
+    <string name="system_error_wipe_data" msgid="6608165524785354962">"Ett internt problem har uppstått i enheten, och det kan hända att problemet kvarstår tills du återställer standardinställningarna."</string>
+    <string name="system_error_manufacturer" msgid="8086872414744210668">"Ett internt problem har uppstått i enheten. Kontakta tillverkaren om du vill veta mer."</string>
+    <!-- no translation found for stk_cc_ussd_to_dial (5202342984749947872) -->
+    <skip />
+    <!-- no translation found for stk_cc_ussd_to_ss (2345360594181405482) -->
+    <skip />
+    <!-- no translation found for stk_cc_ussd_to_ussd (7466087659967191653) -->
+    <skip />
+    <!-- no translation found for stk_cc_ss_to_dial (2151304435775557162) -->
+    <skip />
+    <!-- no translation found for stk_cc_ss_to_ussd (3951862188105305589) -->
+    <skip />
+    <!-- no translation found for stk_cc_ss_to_ss (5470768854991452695) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-sw/strings.xml b/core/res/res/values-sw/strings.xml
index 2e265c9..b9237ce 100644
--- a/core/res/res/values-sw/strings.xml
+++ b/core/res/res/values-sw/strings.xml
@@ -564,6 +564,8 @@
     <string name="permdesc_configureWifiDisplay" msgid="7916815158690218065">"Inaruhusu programu kusanidi na kuunganika kwenye maonyesho ya Wifi."</string>
     <string name="permlab_controlWifiDisplay" msgid="393641276723695496">"dhibiti maonyesho ya Wifi"</string>
     <string name="permdesc_controlWifiDisplay" msgid="4543912292681826986">"Inaruhusu programu kudhibiti vipengele vya kiwango cha chini vya maonyesho ya Wifi."</string>
+    <string name="permlab_controlVpn" msgid="2618442789397588200">"dhibiti Virtual Private Networks"</string>
+    <string name="permdesc_controlVpn" msgid="762852603315861214">"Huruhusu programu kudhibiti vipengele vya viwango vya chini vya Virtual Private Networks."</string>
     <string name="permlab_captureAudioOutput" msgid="6857134498402346708">"nasa sauti"</string>
     <string name="permdesc_captureAudioOutput" msgid="6210597754212208853">"Inaruhusu programu kunasa na kuelekeza sauti kwingine."</string>
     <string name="permlab_captureAudioHotword" msgid="1890553935650349808">"Kutambua neno tekelezi"</string>
@@ -1700,7 +1702,7 @@
     <string name="display_manager_overlay_display_secure_suffix" msgid="6022119702628572080">", salama"</string>
     <string name="kg_emergency_call_label" msgid="684946192523830531">"Simu ya dharura"</string>
     <string name="kg_forgot_pattern_button_text" msgid="8852021467868220608">"Umesahau Ruwaza"</string>
-    <string name="kg_wrong_pattern" msgid="1850806070801358830">"Mchoro Usio sahihi"</string>
+    <string name="kg_wrong_pattern" msgid="1850806070801358830">"Mchoro huo si sahihi"</string>
     <string name="kg_wrong_password" msgid="2333281762128113157">"Nenosiri Lisilo sahihi"</string>
     <string name="kg_wrong_pin" msgid="1131306510833563801">"Nambari ya PIN si sahihi"</string>
     <string name="kg_too_many_failed_attempts_countdown" msgid="6358110221603297548">"Jaribu tena baada ya sekunde <xliff:g id="NUMBER">%1$d</xliff:g>."</string>
@@ -1902,4 +1904,18 @@
     <string name="zen_mode_next_alarm_summary" msgid="5915140424683747372">"Hadi kengele inayofuata saa <xliff:g id="FORMATTEDTIME">%1$s</xliff:g>"</string>
     <string name="zen_mode_next_alarm_line_one" msgid="5537042951553420916">"Hadi kengele inayofuata"</string>
     <string name="muted_by" msgid="6147073845094180001">"Sauti imezimwa na <xliff:g id="THIRD_PARTY">%1$s</xliff:g>"</string>
+    <string name="system_error_wipe_data" msgid="6608165524785354962">"Kuna hitilafu ya ndani ya kifaa chako, na huenda kisiwe thabiti mpaka urejeshe mipangilio ya kiwandani."</string>
+    <string name="system_error_manufacturer" msgid="8086872414744210668">"Kuna hitilafu ya ndani ya kifaa chako. Wasiliana na mtengenezaji wa kifaa chako kwa maelezo."</string>
+    <!-- no translation found for stk_cc_ussd_to_dial (5202342984749947872) -->
+    <skip />
+    <!-- no translation found for stk_cc_ussd_to_ss (2345360594181405482) -->
+    <skip />
+    <!-- no translation found for stk_cc_ussd_to_ussd (7466087659967191653) -->
+    <skip />
+    <!-- no translation found for stk_cc_ss_to_dial (2151304435775557162) -->
+    <skip />
+    <!-- no translation found for stk_cc_ss_to_ussd (3951862188105305589) -->
+    <skip />
+    <!-- no translation found for stk_cc_ss_to_ss (5470768854991452695) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-ta-rIN/strings.xml b/core/res/res/values-ta-rIN/strings.xml
index 4c8c97a..809d354 100644
--- a/core/res/res/values-ta-rIN/strings.xml
+++ b/core/res/res/values-ta-rIN/strings.xml
@@ -564,6 +564,8 @@
     <string name="permdesc_configureWifiDisplay" msgid="7916815158690218065">"Wifi காட்சிகளை உள்ளமைத்து அவற்றுடன் இணையப் பயன்பாட்டை அனுமதிக்கிறது."</string>
     <string name="permlab_controlWifiDisplay" msgid="393641276723695496">"Wifi காட்சிகளைக் கட்டுப்படுத்துதல்"</string>
     <string name="permdesc_controlWifiDisplay" msgid="4543912292681826986">"Wifi காட்சிகளில் கீழ்-நிலை அம்சங்களைக் கட்டுப்படுத்தப் பயன்பாட்டை அனுமதிக்கிறது."</string>
+    <string name="permlab_controlVpn" msgid="2618442789397588200">"மெய்நிகர் தனியார் பிணையங்களைக் கட்டுப்படுத்துதல்"</string>
+    <string name="permdesc_controlVpn" msgid="762852603315861214">"மெய்நிகர் தனியார் பிணையங்களின் குறை-நிலை அம்சங்களைக் கட்டுப்படுத்த பயன்பாட்டை அனுமதிக்கும்."</string>
     <string name="permlab_captureAudioOutput" msgid="6857134498402346708">"ஆடியோ வெளியீட்டைப் பதிவுசெய்தல்"</string>
     <string name="permdesc_captureAudioOutput" msgid="6210597754212208853">"ஆடியோ வெளியீட்டைப் பதிவுசெய்ய மற்றும் திசைதிருப்ப பயன்பாட்டை அனுமதிக்கிறது."</string>
     <string name="permlab_captureAudioHotword" msgid="1890553935650349808">"குறிப்பிட்ட சொல்லைக் கண்டறிதல்"</string>
@@ -1902,4 +1904,18 @@
     <string name="zen_mode_next_alarm_summary" msgid="5915140424683747372">"<xliff:g id="FORMATTEDTIME">%1$s</xliff:g>க்கு ஒலிக்கும் அடுத்த அலாரம் வரை"</string>
     <string name="zen_mode_next_alarm_line_one" msgid="5537042951553420916">"அடுத்த அலாரம் வரை"</string>
     <string name="muted_by" msgid="6147073845094180001">"<xliff:g id="THIRD_PARTY">%1$s</xliff:g> ஒலியடக்கினார்"</string>
+    <string name="system_error_wipe_data" msgid="6608165524785354962">"சாதனத்தில் அகச் சிக்கல் இருக்கிறது, அதனை ஆரம்பநிலைக்கு மீட்டமைக்கும் வரை நிலையற்று இயங்கலாம்."</string>
+    <string name="system_error_manufacturer" msgid="8086872414744210668">"சாதனத்தில் அகச் சிக்கல் இருக்கிறது. விவரங்களுக்கு சாதன தயாரிப்பாளரைத் தொடர்புகொள்ளவும்."</string>
+    <!-- no translation found for stk_cc_ussd_to_dial (5202342984749947872) -->
+    <skip />
+    <!-- no translation found for stk_cc_ussd_to_ss (2345360594181405482) -->
+    <skip />
+    <!-- no translation found for stk_cc_ussd_to_ussd (7466087659967191653) -->
+    <skip />
+    <!-- no translation found for stk_cc_ss_to_dial (2151304435775557162) -->
+    <skip />
+    <!-- no translation found for stk_cc_ss_to_ussd (3951862188105305589) -->
+    <skip />
+    <!-- no translation found for stk_cc_ss_to_ss (5470768854991452695) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-te-rIN/strings.xml b/core/res/res/values-te-rIN/strings.xml
index 104c052..a1b28e3 100644
--- a/core/res/res/values-te-rIN/strings.xml
+++ b/core/res/res/values-te-rIN/strings.xml
@@ -564,6 +564,8 @@
     <string name="permdesc_configureWifiDisplay" msgid="7916815158690218065">"వైఫై డిస్‌ప్లేలను కాన్ఫిగర్ చేయడానికి మరియు వాటికి కనెక్ట్ చేయడానికి అనువర్తనాన్ని అనుమతిస్తుంది."</string>
     <string name="permlab_controlWifiDisplay" msgid="393641276723695496">"వైఫై డిస్‌ప్లేలను నియంత్రించడం"</string>
     <string name="permdesc_controlWifiDisplay" msgid="4543912292681826986">"వైఫై డిస్‌ప్లేల యొక్క తక్కువ-స్థాయి లక్షణాలను నియంత్రించడానికి అనువర్తనాన్ని అనుమతిస్తుంది."</string>
+    <string name="permlab_controlVpn" msgid="2618442789397588200">"వర్చువల్ ప్రైవేట్ నెట్‌వర్క్‌లను నియంత్రించడం"</string>
+    <string name="permdesc_controlVpn" msgid="762852603315861214">"వర్చువల్ ప్రైవేట్ నెట్‌వర్క్‌ల తక్కువ-స్థాయి లక్షణాలను నియంత్రించడానికి అనువర్తనాన్ని అనుమతిస్తుంది."</string>
     <string name="permlab_captureAudioOutput" msgid="6857134498402346708">"ఆడియో అవుట్‌పుట్‌ను క్యాప్చర్ చేయడం"</string>
     <string name="permdesc_captureAudioOutput" msgid="6210597754212208853">"ఆడియో అవుట్‌పుట్‌ను క్యాప్చర్ చేసి, దారి మళ్లించడానికి అనువర్తనాన్ని అనుమతిస్తుంది."</string>
     <string name="permlab_captureAudioHotword" msgid="1890553935650349808">"హాట్‌వర్డ్ గుర్తింపు"</string>
@@ -1902,4 +1904,18 @@
     <string name="zen_mode_next_alarm_summary" msgid="5915140424683747372">"<xliff:g id="FORMATTEDTIME">%1$s</xliff:g>కి సెట్ చేసిన తదుపరి అలారం వరకు"</string>
     <string name="zen_mode_next_alarm_line_one" msgid="5537042951553420916">"తదుపరి అలారం వరకు"</string>
     <string name="muted_by" msgid="6147073845094180001">"<xliff:g id="THIRD_PARTY">%1$s</xliff:g> ద్వారా మ్యూట్ చేయబడింది"</string>
+    <string name="system_error_wipe_data" msgid="6608165524785354962">"మీ పరికరంతో అంతర్గత సమస్య ఏర్పడింది మరియు మీరు ఫ్యాక్టరీ డేటా రీసెట్ చేసే వరకు అస్థిరంగా ఉంటుంది."</string>
+    <string name="system_error_manufacturer" msgid="8086872414744210668">"మీ పరికరంతో అంతర్గత సమస్య ఏర్పడింది. వివరాల కోసం మీ తయారీదారుని సంప్రదించండి."</string>
+    <!-- no translation found for stk_cc_ussd_to_dial (5202342984749947872) -->
+    <skip />
+    <!-- no translation found for stk_cc_ussd_to_ss (2345360594181405482) -->
+    <skip />
+    <!-- no translation found for stk_cc_ussd_to_ussd (7466087659967191653) -->
+    <skip />
+    <!-- no translation found for stk_cc_ss_to_dial (2151304435775557162) -->
+    <skip />
+    <!-- no translation found for stk_cc_ss_to_ussd (3951862188105305589) -->
+    <skip />
+    <!-- no translation found for stk_cc_ss_to_ss (5470768854991452695) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-th/strings.xml b/core/res/res/values-th/strings.xml
index 7455f84..852054f 100644
--- a/core/res/res/values-th/strings.xml
+++ b/core/res/res/values-th/strings.xml
@@ -564,6 +564,8 @@
     <string name="permdesc_configureWifiDisplay" msgid="7916815158690218065">"อนุญาตให้แอปกำหนดค่าและเชื่อมต่อกับจอแสดงผล WiFi ได้"</string>
     <string name="permlab_controlWifiDisplay" msgid="393641276723695496">"ควบคุมการแสดงผลด้วย WiFi"</string>
     <string name="permdesc_controlWifiDisplay" msgid="4543912292681826986">"อนุญาตให้แอปควบคุมคุณลักษณะต่างๆ ในระดับล่างของการแสดงผลด้วย WiFi"</string>
+    <string name="permlab_controlVpn" msgid="2618442789397588200">"ควบคุมเครือข่ายส่วนตัวเสมือน"</string>
+    <string name="permdesc_controlVpn" msgid="762852603315861214">"อนุญาตให้แอปควบคุมคุณลักษณะระดับต่ำของเครือข่ายส่วนตัวเสมือน"</string>
     <string name="permlab_captureAudioOutput" msgid="6857134498402346708">"บันทึกเอาต์พุตเสียง"</string>
     <string name="permdesc_captureAudioOutput" msgid="6210597754212208853">"อนุญาตให้แอปบันทึกและเปลี่ยนเส้นทางเอาต์พุตเสียง"</string>
     <string name="permlab_captureAudioHotword" msgid="1890553935650349808">"การตรวจหาคำที่นิยม"</string>
@@ -1902,4 +1904,18 @@
     <string name="zen_mode_next_alarm_summary" msgid="5915140424683747372">"จนถึงการตั้งปลุกครั้งถัดไปในเวลา <xliff:g id="FORMATTEDTIME">%1$s</xliff:g>"</string>
     <string name="zen_mode_next_alarm_line_one" msgid="5537042951553420916">"จนถึงการตั้งปลุกครั้งถัดไป"</string>
     <string name="muted_by" msgid="6147073845094180001">"ปิดเสียงโดย <xliff:g id="THIRD_PARTY">%1$s</xliff:g>"</string>
+    <string name="system_error_wipe_data" msgid="6608165524785354962">"เกิดปัญหาภายในกับอุปกรณ์ของคุณ อุปกรณ์อาจทำงานไม่เสถียรจนกว่าคุณจะรีเซ็ตข้อมูลเป็นค่าเริ่มต้น"</string>
+    <string name="system_error_manufacturer" msgid="8086872414744210668">"เกิดปัญหาภายในกับอุปกรณ์ของคุณ โปรดติดต่อผู้ผลิตสำหรับรายละเอียดเพิ่มเติม"</string>
+    <!-- no translation found for stk_cc_ussd_to_dial (5202342984749947872) -->
+    <skip />
+    <!-- no translation found for stk_cc_ussd_to_ss (2345360594181405482) -->
+    <skip />
+    <!-- no translation found for stk_cc_ussd_to_ussd (7466087659967191653) -->
+    <skip />
+    <!-- no translation found for stk_cc_ss_to_dial (2151304435775557162) -->
+    <skip />
+    <!-- no translation found for stk_cc_ss_to_ussd (3951862188105305589) -->
+    <skip />
+    <!-- no translation found for stk_cc_ss_to_ss (5470768854991452695) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-tl/strings.xml b/core/res/res/values-tl/strings.xml
index a2f793a..5a4063f 100644
--- a/core/res/res/values-tl/strings.xml
+++ b/core/res/res/values-tl/strings.xml
@@ -564,6 +564,8 @@
     <string name="permdesc_configureWifiDisplay" msgid="7916815158690218065">"Pinapayagan ang app na mag-configure at kumonekta sa mga Wifi display."</string>
     <string name="permlab_controlWifiDisplay" msgid="393641276723695496">"magkontrol ng mga Wifi display"</string>
     <string name="permdesc_controlWifiDisplay" msgid="4543912292681826986">"Pinapayagan ang app na magkontrol ng mga tampok sa mababang antas ng mga dispay ng Wifi."</string>
+    <string name="permlab_controlVpn" msgid="2618442789397588200">"kontrolin ang mga Virtual Private Network"</string>
+    <string name="permdesc_controlVpn" msgid="762852603315861214">"Nagbibigay-daan sa app na kontrolin ang mga nasa mababang antas na feature ng mga Virtual Private Network."</string>
     <string name="permlab_captureAudioOutput" msgid="6857134498402346708">"kumuha ng audio output"</string>
     <string name="permdesc_captureAudioOutput" msgid="6210597754212208853">"Pinapayagan ang app na kumuha at mag-redirect ng audio output."</string>
     <string name="permlab_captureAudioHotword" msgid="1890553935650349808">"Paghahanap ng hotword"</string>
@@ -1902,4 +1904,18 @@
     <string name="zen_mode_next_alarm_summary" msgid="5915140424683747372">"Hanggang sa susunod na alarma sa <xliff:g id="FORMATTEDTIME">%1$s</xliff:g>"</string>
     <string name="zen_mode_next_alarm_line_one" msgid="5537042951553420916">"Hanggang sa susunod na alarma"</string>
     <string name="muted_by" msgid="6147073845094180001">"Na-mute ng <xliff:g id="THIRD_PARTY">%1$s</xliff:g>"</string>
+    <string name="system_error_wipe_data" msgid="6608165524785354962">"May internal na problema sa iyong device, at maaaring hindi ito maging stable hanggang sa i-reset mo ang factory data."</string>
+    <string name="system_error_manufacturer" msgid="8086872414744210668">"May internal na problema sa iyong device. Makipag-ugnayan sa iyong manufacturer upang malaman ang mga detalye."</string>
+    <!-- no translation found for stk_cc_ussd_to_dial (5202342984749947872) -->
+    <skip />
+    <!-- no translation found for stk_cc_ussd_to_ss (2345360594181405482) -->
+    <skip />
+    <!-- no translation found for stk_cc_ussd_to_ussd (7466087659967191653) -->
+    <skip />
+    <!-- no translation found for stk_cc_ss_to_dial (2151304435775557162) -->
+    <skip />
+    <!-- no translation found for stk_cc_ss_to_ussd (3951862188105305589) -->
+    <skip />
+    <!-- no translation found for stk_cc_ss_to_ss (5470768854991452695) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-tr/strings.xml b/core/res/res/values-tr/strings.xml
index dd95ce9..45cac47 100644
--- a/core/res/res/values-tr/strings.xml
+++ b/core/res/res/values-tr/strings.xml
@@ -564,6 +564,8 @@
     <string name="permdesc_configureWifiDisplay" msgid="7916815158690218065">"Uygulamaya kablosuz ekranları yapılandırma ve bunlara bağlanma izni verir."</string>
     <string name="permlab_controlWifiDisplay" msgid="393641276723695496">"Kablosuz ekranları denetle"</string>
     <string name="permdesc_controlWifiDisplay" msgid="4543912292681826986">"Uygulamaya kablosuz ekranların alt düzey özelliklerini kontrol etme izni verir."</string>
+    <string name="permlab_controlVpn" msgid="2618442789397588200">"Sanal Özel Ağları denetle"</string>
+    <string name="permdesc_controlVpn" msgid="762852603315861214">"Uygulamaya, Sanal Özel Ağların düşük seviye özelliklerini denetleme izni verir."</string>
     <string name="permlab_captureAudioOutput" msgid="6857134498402346708">"ses çıkışını yakala"</string>
     <string name="permdesc_captureAudioOutput" msgid="6210597754212208853">"Uygulamaya, ses çıkışını yakalayıp yönlendirme izni verir."</string>
     <string name="permlab_captureAudioHotword" msgid="1890553935650349808">"Özel kelime algılama"</string>
@@ -1902,4 +1904,18 @@
     <string name="zen_mode_next_alarm_summary" msgid="5915140424683747372">"<xliff:g id="FORMATTEDTIME">%1$s</xliff:g> saatindeki bir sonraki alarma kadar"</string>
     <string name="zen_mode_next_alarm_line_one" msgid="5537042951553420916">"Bir sonraki alarma kadar"</string>
     <string name="muted_by" msgid="6147073845094180001">"<xliff:g id="THIRD_PARTY">%1$s</xliff:g> tarafından kapatıldı"</string>
+    <string name="system_error_wipe_data" msgid="6608165524785354962">"Cihazınızla ilgili dahili bir sorun oluştu ve fabrika verilerine sıfırlama işlemi gerçekleştirilene kadar kararsız çalışabilir."</string>
+    <string name="system_error_manufacturer" msgid="8086872414744210668">"Cihazınızla ilgili dahili bir sorun oluştu. Ayrıntılı bilgi için üreticinizle iletişim kurun."</string>
+    <!-- no translation found for stk_cc_ussd_to_dial (5202342984749947872) -->
+    <skip />
+    <!-- no translation found for stk_cc_ussd_to_ss (2345360594181405482) -->
+    <skip />
+    <!-- no translation found for stk_cc_ussd_to_ussd (7466087659967191653) -->
+    <skip />
+    <!-- no translation found for stk_cc_ss_to_dial (2151304435775557162) -->
+    <skip />
+    <!-- no translation found for stk_cc_ss_to_ussd (3951862188105305589) -->
+    <skip />
+    <!-- no translation found for stk_cc_ss_to_ss (5470768854991452695) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-uk/strings.xml b/core/res/res/values-uk/strings.xml
index e3b34b1..591bc2a 100644
--- a/core/res/res/values-uk/strings.xml
+++ b/core/res/res/values-uk/strings.xml
@@ -564,6 +564,8 @@
     <string name="permdesc_configureWifiDisplay" msgid="7916815158690218065">"Дозволяє програмі налаштовувати екрани Wi-Fi і під’єднуватися до них."</string>
     <string name="permlab_controlWifiDisplay" msgid="393641276723695496">"керувати екранами Wi-Fi"</string>
     <string name="permdesc_controlWifiDisplay" msgid="4543912292681826986">"Дозволяє програмі керувати низькорівневими функціями екранів Wi-Fi."</string>
+    <string name="permlab_controlVpn" msgid="2618442789397588200">"керування віртуальними приватними мережами"</string>
+    <string name="permdesc_controlVpn" msgid="762852603315861214">"Додаток може керувати низькорівневими функціями віртуальних приватних мереж."</string>
     <string name="permlab_captureAudioOutput" msgid="6857134498402346708">"отримувати доступ до аудіовиходу"</string>
     <string name="permdesc_captureAudioOutput" msgid="6210597754212208853">"Дозволяє програмі отримувати доступ до аудіовиходу й переспрямовувати його."</string>
     <string name="permlab_captureAudioHotword" msgid="1890553935650349808">"виявляти команди швидкого запуску"</string>
@@ -1902,4 +1904,18 @@
     <string name="zen_mode_next_alarm_summary" msgid="5915140424683747372">"До наступного сигналу о <xliff:g id="FORMATTEDTIME">%1$s</xliff:g>"</string>
     <string name="zen_mode_next_alarm_line_one" msgid="5537042951553420916">"До наступного сигналу"</string>
     <string name="muted_by" msgid="6147073845094180001">"<xliff:g id="THIRD_PARTY">%1$s</xliff:g> вимикає звук"</string>
+    <string name="system_error_wipe_data" msgid="6608165524785354962">"Через внутрішню помилку ваш пристрій може працювати нестабільно. Відновіть заводські налаштування."</string>
+    <string name="system_error_manufacturer" msgid="8086872414744210668">"На пристрої сталася внутрішня помилка. Зв’яжіться з виробником пристрою, щоб дізнатися більше."</string>
+    <!-- no translation found for stk_cc_ussd_to_dial (5202342984749947872) -->
+    <skip />
+    <!-- no translation found for stk_cc_ussd_to_ss (2345360594181405482) -->
+    <skip />
+    <!-- no translation found for stk_cc_ussd_to_ussd (7466087659967191653) -->
+    <skip />
+    <!-- no translation found for stk_cc_ss_to_dial (2151304435775557162) -->
+    <skip />
+    <!-- no translation found for stk_cc_ss_to_ussd (3951862188105305589) -->
+    <skip />
+    <!-- no translation found for stk_cc_ss_to_ss (5470768854991452695) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-ur-rPK/strings.xml b/core/res/res/values-ur-rPK/strings.xml
index 39657de..bf8c64f 100644
--- a/core/res/res/values-ur-rPK/strings.xml
+++ b/core/res/res/values-ur-rPK/strings.xml
@@ -564,6 +564,8 @@
     <string name="permdesc_configureWifiDisplay" msgid="7916815158690218065">"‏ایپ کو Wifi ڈسپلیز کے ساتھ ترتیب دینے اور مربوط کرنے کی اجازت دیتا ہے۔"</string>
     <string name="permlab_controlWifiDisplay" msgid="393641276723695496">"‏Wifi ڈسپلیز کنٹرول کریں"</string>
     <string name="permdesc_controlWifiDisplay" msgid="4543912292681826986">"‏ایپ کو Wifi ڈسپلیز کی کم سطح والی خصوصیات کو کنٹرول کرنے کی اجازت دیتا ہے۔"</string>
+    <string name="permlab_controlVpn" msgid="2618442789397588200">"ورچوئل نجی نیٹ ورکس کو کنٹرول کریں"</string>
+    <string name="permdesc_controlVpn" msgid="762852603315861214">"ایپ کو ورچوئل نجی نیٹ ورکس کی کم سطحی خصوصیات کو کنٹرول کرنے کی اجازت دیتی ہے۔"</string>
     <string name="permlab_captureAudioOutput" msgid="6857134498402346708">"آڈیو آؤٹ پٹ کیپچر کریں"</string>
     <string name="permdesc_captureAudioOutput" msgid="6210597754212208853">"ایپ کو آڈیو آؤٹ پٹ کو کیپچر کرنے اور ری ڈائریکٹ کرنے کی اجازت دیتا ہے۔"</string>
     <string name="permlab_captureAudioHotword" msgid="1890553935650349808">"ہاٹ ورڈ کا پتہ لگانا"</string>
@@ -1902,4 +1904,18 @@
     <string name="zen_mode_next_alarm_summary" msgid="5915140424683747372">"اگلے الارم تک بوقت <xliff:g id="FORMATTEDTIME">%1$s</xliff:g>"</string>
     <string name="zen_mode_next_alarm_line_one" msgid="5537042951553420916">"اگلے الارم تک"</string>
     <string name="muted_by" msgid="6147073845094180001">"<xliff:g id="THIRD_PARTY">%1$s</xliff:g> کے ذریعے خاموش کردہ"</string>
+    <string name="system_error_wipe_data" msgid="6608165524785354962">"آپ کے آلہ میں ایک داخلی مسئلہ ہے اور جب تک آپ فیکٹری ڈیٹا کو دوبارہ ترتیب نہیں دے دیتے ہیں، ہوسکتا ہے کہ یہ غیر مستحکم رہے۔"</string>
+    <string name="system_error_manufacturer" msgid="8086872414744210668">"آپ کے آلہ میں ایک داخلی مسئلہ ہے۔ تفصیلات کیلئے اپنے مینوفیکچرر سے رابطہ کریں۔"</string>
+    <!-- no translation found for stk_cc_ussd_to_dial (5202342984749947872) -->
+    <skip />
+    <!-- no translation found for stk_cc_ussd_to_ss (2345360594181405482) -->
+    <skip />
+    <!-- no translation found for stk_cc_ussd_to_ussd (7466087659967191653) -->
+    <skip />
+    <!-- no translation found for stk_cc_ss_to_dial (2151304435775557162) -->
+    <skip />
+    <!-- no translation found for stk_cc_ss_to_ussd (3951862188105305589) -->
+    <skip />
+    <!-- no translation found for stk_cc_ss_to_ss (5470768854991452695) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-uz-rUZ/strings.xml b/core/res/res/values-uz-rUZ/strings.xml
index 0c5c83f..c6f44e8 100644
--- a/core/res/res/values-uz-rUZ/strings.xml
+++ b/core/res/res/values-uz-rUZ/strings.xml
@@ -564,6 +564,8 @@
     <string name="permdesc_configureWifiDisplay" msgid="7916815158690218065">"Ilovaga Wifi ekranlarini sozlashga va ularga ulanishga ruxsat beradi."</string>
     <string name="permlab_controlWifiDisplay" msgid="393641276723695496">"Wifi ekranlarini boshqarish"</string>
     <string name="permdesc_controlWifiDisplay" msgid="4543912292681826986">"Ilovaga Wifi ekranlarining past darajali xususiyatlarini boshqarishga ruxsat beradi."</string>
+    <string name="permlab_controlVpn" msgid="2618442789397588200">"virtual xususiy tarmoqlarni (VPN) boshqarish"</string>
+    <string name="permdesc_controlVpn" msgid="762852603315861214">"Ilovaga virtual xususiy tarmoqlarning (VPN) quyi darajali funksiyalarini boshqarish uchun ruxsat beradi."</string>
     <string name="permlab_captureAudioOutput" msgid="6857134498402346708">"audio chiqishni yozib olish"</string>
     <string name="permdesc_captureAudioOutput" msgid="6210597754212208853">"Dasturga ovoz lavhasini yozib olib, qayta yo‘llashga ruxsat beradi."</string>
     <string name="permlab_captureAudioHotword" msgid="1890553935650349808">"Hotword aniqlash"</string>
@@ -1902,4 +1904,18 @@
     <string name="zen_mode_next_alarm_summary" msgid="5915140424683747372">"Keyingi uyg‘otkich vaqtigacha (<xliff:g id="FORMATTEDTIME">%1$s</xliff:g>)"</string>
     <string name="zen_mode_next_alarm_line_one" msgid="5537042951553420916">"Keyingi uyg‘otkich vaqtigacha"</string>
     <string name="muted_by" msgid="6147073845094180001">"“<xliff:g id="THIRD_PARTY">%1$s</xliff:g>” tomonidan ovozsiz qilingan"</string>
+    <string name="system_error_wipe_data" msgid="6608165524785354962">"Qurilmangiz bilan bog‘liq ichki muammo mavjud. U zavod sozlamalari tiklanmaguncha barqaror ishlamasligi mumkin."</string>
+    <string name="system_error_manufacturer" msgid="8086872414744210668">"Qurilmangiz bilan bog‘liq ichki muammo mavjud. Tafsilotlar uchun qurilmangiz ishlab chiqaruvchisiga murojaat qiling."</string>
+    <!-- no translation found for stk_cc_ussd_to_dial (5202342984749947872) -->
+    <skip />
+    <!-- no translation found for stk_cc_ussd_to_ss (2345360594181405482) -->
+    <skip />
+    <!-- no translation found for stk_cc_ussd_to_ussd (7466087659967191653) -->
+    <skip />
+    <!-- no translation found for stk_cc_ss_to_dial (2151304435775557162) -->
+    <skip />
+    <!-- no translation found for stk_cc_ss_to_ussd (3951862188105305589) -->
+    <skip />
+    <!-- no translation found for stk_cc_ss_to_ss (5470768854991452695) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-vi/strings.xml b/core/res/res/values-vi/strings.xml
index c088e68..c9ded6d 100644
--- a/core/res/res/values-vi/strings.xml
+++ b/core/res/res/values-vi/strings.xml
@@ -564,6 +564,8 @@
     <string name="permdesc_configureWifiDisplay" msgid="7916815158690218065">"Cho phép ứng dụng định cấu hình và kết nối với màn hình Wi-Fi."</string>
     <string name="permlab_controlWifiDisplay" msgid="393641276723695496">"kiểm soát màn hình Wi-Fi"</string>
     <string name="permdesc_controlWifiDisplay" msgid="4543912292681826986">"Cho phép ứng dụng kiểm soát các tính năng cấp thấp của màn hình Wi-Fi."</string>
+    <string name="permlab_controlVpn" msgid="2618442789397588200">"kiểm soát Mạng riêng ảo"</string>
+    <string name="permdesc_controlVpn" msgid="762852603315861214">"Cho phép ứng dụng kiểm soát các tính năng cấp thấp của Mạng riêng ảo."</string>
     <string name="permlab_captureAudioOutput" msgid="6857134498402346708">"thu thập dữ liệu đầu ra âm thanh"</string>
     <string name="permdesc_captureAudioOutput" msgid="6210597754212208853">"Cho phép ứng dụng thu thập và chuyển hướng dữ liệu đầu ra âm thanh."</string>
     <string name="permlab_captureAudioHotword" msgid="1890553935650349808">"Phát hiện từ nóng"</string>
@@ -1902,4 +1904,18 @@
     <string name="zen_mode_next_alarm_summary" msgid="5915140424683747372">"Cho đến lần báo thức tiếp theo vào <xliff:g id="FORMATTEDTIME">%1$s</xliff:g>"</string>
     <string name="zen_mode_next_alarm_line_one" msgid="5537042951553420916">"Cho đến lần báo thức tiếp theo"</string>
     <string name="muted_by" msgid="6147073845094180001">"Do <xliff:g id="THIRD_PARTY">%1$s</xliff:g> tắt tiếng"</string>
+    <string name="system_error_wipe_data" msgid="6608165524785354962">"Đã xảy ra sự cố nội bộ với thiết bị của bạn và thiết bị có thể sẽ không ổn định cho tới khi bạn thiết lập lại dữ liệu ban đầu."</string>
+    <string name="system_error_manufacturer" msgid="8086872414744210668">"Đã xảy ra sự cố nội bộ với thiết bị. Hãy liên hệ với nhà sản xuất của bạn để biết chi tiết."</string>
+    <!-- no translation found for stk_cc_ussd_to_dial (5202342984749947872) -->
+    <skip />
+    <!-- no translation found for stk_cc_ussd_to_ss (2345360594181405482) -->
+    <skip />
+    <!-- no translation found for stk_cc_ussd_to_ussd (7466087659967191653) -->
+    <skip />
+    <!-- no translation found for stk_cc_ss_to_dial (2151304435775557162) -->
+    <skip />
+    <!-- no translation found for stk_cc_ss_to_ussd (3951862188105305589) -->
+    <skip />
+    <!-- no translation found for stk_cc_ss_to_ss (5470768854991452695) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-zh-rCN/strings.xml b/core/res/res/values-zh-rCN/strings.xml
index 1b4aad1..54040d6 100644
--- a/core/res/res/values-zh-rCN/strings.xml
+++ b/core/res/res/values-zh-rCN/strings.xml
@@ -564,6 +564,10 @@
     <string name="permdesc_configureWifiDisplay" msgid="7916815158690218065">"允许应用配置并连接到WLAN显示设备。"</string>
     <string name="permlab_controlWifiDisplay" msgid="393641276723695496">"控制WLAN显示设备"</string>
     <string name="permdesc_controlWifiDisplay" msgid="4543912292681826986">"允许应用控制WLAN显示设备的基础功能。"</string>
+    <!-- no translation found for permlab_controlVpn (2618442789397588200) -->
+    <skip />
+    <!-- no translation found for permdesc_controlVpn (762852603315861214) -->
+    <skip />
     <string name="permlab_captureAudioOutput" msgid="6857134498402346708">"捕获音频输出"</string>
     <string name="permdesc_captureAudioOutput" msgid="6210597754212208853">"允许该应用捕获和重定向音频输出。"</string>
     <string name="permlab_captureAudioHotword" msgid="1890553935650349808">"启动指令检测"</string>
@@ -833,10 +837,8 @@
     <string name="permdesc_handoverStatus" msgid="4788144087245714948">"允许此应用接收Android Beam当前传输内容的相关信息"</string>
     <string name="permlab_removeDrmCertificates" msgid="7044888287209892751">"移除DRM证书"</string>
     <string name="permdesc_removeDrmCertificates" msgid="7272999075113400993">"允许应用移除DRM证书。普通应用绝不需要此权限。"</string>
-    <!-- no translation found for permlab_bindCarrierMessagingService (1490229371796969158) -->
-    <skip />
-    <!-- no translation found for permdesc_bindCarrierMessagingService (2762882888502113944) -->
-    <skip />
+    <string name="permlab_bindCarrierMessagingService" msgid="1490229371796969158">"绑定到运营商消息传递服务"</string>
+    <string name="permdesc_bindCarrierMessagingService" msgid="2762882888502113944">"允许应用绑定到运营商消息传递服务的顶级接口。普通应用绝不需要此权限。"</string>
     <string name="policylab_limitPassword" msgid="4497420728857585791">"设置密码规则"</string>
     <string name="policydesc_limitPassword" msgid="3252114203919510394">"控制屏幕解锁密码所允许的长度和字符。"</string>
     <string name="policylab_watchLogin" msgid="914130646942199503">"监视屏幕解锁尝试次数"</string>
@@ -1904,4 +1906,20 @@
     <string name="zen_mode_next_alarm_summary" msgid="5915140424683747372">"到下次闹钟时间(<xliff:g id="FORMATTEDTIME">%1$s</xliff:g>)"</string>
     <string name="zen_mode_next_alarm_line_one" msgid="5537042951553420916">"到下次闹钟时间"</string>
     <string name="muted_by" msgid="6147073845094180001">"已被<xliff:g id="THIRD_PARTY">%1$s</xliff:g>设为静音"</string>
+    <!-- no translation found for system_error_wipe_data (6608165524785354962) -->
+    <skip />
+    <!-- no translation found for system_error_manufacturer (8086872414744210668) -->
+    <skip />
+    <!-- no translation found for stk_cc_ussd_to_dial (5202342984749947872) -->
+    <skip />
+    <!-- no translation found for stk_cc_ussd_to_ss (2345360594181405482) -->
+    <skip />
+    <!-- no translation found for stk_cc_ussd_to_ussd (7466087659967191653) -->
+    <skip />
+    <!-- no translation found for stk_cc_ss_to_dial (2151304435775557162) -->
+    <skip />
+    <!-- no translation found for stk_cc_ss_to_ussd (3951862188105305589) -->
+    <skip />
+    <!-- no translation found for stk_cc_ss_to_ss (5470768854991452695) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-zh-rHK/strings.xml b/core/res/res/values-zh-rHK/strings.xml
index 1759445..8e888da 100644
--- a/core/res/res/values-zh-rHK/strings.xml
+++ b/core/res/res/values-zh-rHK/strings.xml
@@ -564,6 +564,8 @@
     <string name="permdesc_configureWifiDisplay" msgid="7916815158690218065">"允許應用程式設定及連接 WiFi Display。"</string>
     <string name="permlab_controlWifiDisplay" msgid="393641276723695496">"控制 WiFi Display"</string>
     <string name="permdesc_controlWifiDisplay" msgid="4543912292681826986">"允許應用程式控制 WiFi Display 的低階功能。"</string>
+    <string name="permlab_controlVpn" msgid="2618442789397588200">"控制虛擬私人網絡"</string>
+    <string name="permdesc_controlVpn" msgid="762852603315861214">"允許應用程式控制虛擬私人網絡的低層級功能。"</string>
     <string name="permlab_captureAudioOutput" msgid="6857134498402346708">"擷取音頻輸出"</string>
     <string name="permdesc_captureAudioOutput" msgid="6210597754212208853">"允許應用程式擷取及重新導向音頻輸出。"</string>
     <string name="permlab_captureAudioHotword" msgid="1890553935650349808">"啟動字詞偵測"</string>
@@ -833,8 +835,8 @@
     <string name="permdesc_handoverStatus" msgid="4788144087245714948">"允許應用程式接收 Android Beam 目前傳送的資料"</string>
     <string name="permlab_removeDrmCertificates" msgid="7044888287209892751">"移除 DRM 憑證"</string>
     <string name="permdesc_removeDrmCertificates" msgid="7272999075113400993">"允許應用程式移除 DRM 憑證 (一般應用程式並不需要)。"</string>
-    <string name="permlab_bindCarrierMessagingService" msgid="1490229371796969158">"綁定到流動網絡供應商短訊服務"</string>
-    <string name="permdesc_bindCarrierMessagingService" msgid="2762882888502113944">"允許持有人綁定到流動網絡供應商短訊服務頂層介面 (一般應用程式不需要)。"</string>
+    <string name="permlab_bindCarrierMessagingService" msgid="1490229371796969158">"繫結至流動網絡供應商短訊服務"</string>
+    <string name="permdesc_bindCarrierMessagingService" msgid="2762882888502113944">"允許應用程式繫結至流動網絡供應商短訊服務的頂層介面 (不建議一般應用程式使用)。"</string>
     <string name="policylab_limitPassword" msgid="4497420728857585791">"設定密碼規則"</string>
     <string name="policydesc_limitPassword" msgid="3252114203919510394">"控制螢幕解鎖密碼所允許的長度和字元。"</string>
     <string name="policylab_watchLogin" msgid="914130646942199503">"監控螢幕解鎖嘗試次數"</string>
@@ -1902,4 +1904,18 @@
     <string name="zen_mode_next_alarm_summary" msgid="5915140424683747372">"直到下一個在 <xliff:g id="FORMATTEDTIME">%1$s</xliff:g> 的鬧鐘"</string>
     <string name="zen_mode_next_alarm_line_one" msgid="5537042951553420916">"直到下一個鬧鐘"</string>
     <string name="muted_by" msgid="6147073845094180001">"靜音設定者:<xliff:g id="THIRD_PARTY">%1$s</xliff:g>"</string>
+    <string name="system_error_wipe_data" msgid="6608165524785354962">"您裝置的系統發生問題,回復原廠設定後即可解決該問題。"</string>
+    <string name="system_error_manufacturer" msgid="8086872414744210668">"您裝置的系統發生問題,請聯絡您的製造商瞭解詳情。"</string>
+    <!-- no translation found for stk_cc_ussd_to_dial (5202342984749947872) -->
+    <skip />
+    <!-- no translation found for stk_cc_ussd_to_ss (2345360594181405482) -->
+    <skip />
+    <!-- no translation found for stk_cc_ussd_to_ussd (7466087659967191653) -->
+    <skip />
+    <!-- no translation found for stk_cc_ss_to_dial (2151304435775557162) -->
+    <skip />
+    <!-- no translation found for stk_cc_ss_to_ussd (3951862188105305589) -->
+    <skip />
+    <!-- no translation found for stk_cc_ss_to_ss (5470768854991452695) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-zh-rTW/strings.xml b/core/res/res/values-zh-rTW/strings.xml
index cde2929..bccdd483 100644
--- a/core/res/res/values-zh-rTW/strings.xml
+++ b/core/res/res/values-zh-rTW/strings.xml
@@ -564,6 +564,8 @@
     <string name="permdesc_configureWifiDisplay" msgid="7916815158690218065">"允許應用程式設定及連接 Wi-Fi 顯示裝置。"</string>
     <string name="permlab_controlWifiDisplay" msgid="393641276723695496">"控制 Wi-Fi 顯示裝置"</string>
     <string name="permdesc_controlWifiDisplay" msgid="4543912292681826986">"允許應用程式控制 Wi-Fi 顯示裝置的低階功能。"</string>
+    <string name="permlab_controlVpn" msgid="2618442789397588200">"控制虛擬私人網路"</string>
+    <string name="permdesc_controlVpn" msgid="762852603315861214">"允許應用程式控制虛擬私人網路的低階功能。"</string>
     <string name="permlab_captureAudioOutput" msgid="6857134498402346708">"擷取音訊輸出"</string>
     <string name="permdesc_captureAudioOutput" msgid="6210597754212208853">"允許應用程式擷取及重新導向音訊輸出。"</string>
     <string name="permlab_captureAudioHotword" msgid="1890553935650349808">"啟動字詞偵測"</string>
@@ -833,8 +835,8 @@
     <string name="permdesc_handoverStatus" msgid="4788144087245714948">"允許應用程式接收 Android Beam 目前傳輸的資訊"</string>
     <string name="permlab_removeDrmCertificates" msgid="7044888287209892751">"移除 DRM 憑證"</string>
     <string name="permdesc_removeDrmCertificates" msgid="7272999075113400993">"允許應用程式移除 DRM 憑證 (一般應用程式並不需要)。"</string>
-    <string name="permlab_bindCarrierMessagingService" msgid="1490229371796969158">"繫結至行動通訊業者簡訊服務"</string>
-    <string name="permdesc_bindCarrierMessagingService" msgid="2762882888502113944">"允許應用程式繫結至行動通訊業者簡訊服務的頂層介面 (一般應用程式並不需要)。"</string>
+    <string name="permlab_bindCarrierMessagingService" msgid="1490229371796969158">"與行動通訊業者簡訊服務繫結"</string>
+    <string name="permdesc_bindCarrierMessagingService" msgid="2762882888502113944">"允許應用程式與行動通訊業者簡訊服務的頂層介面繫結 (一般應用程式並不需要)。"</string>
     <string name="policylab_limitPassword" msgid="4497420728857585791">"設定密碼規則"</string>
     <string name="policydesc_limitPassword" msgid="3252114203919510394">"控制螢幕解鎖密碼所允許的長度和字元。"</string>
     <string name="policylab_watchLogin" msgid="914130646942199503">"監視螢幕解鎖嘗試次數"</string>
@@ -1902,4 +1904,18 @@
     <string name="zen_mode_next_alarm_summary" msgid="5915140424683747372">"直到下次鬧鐘鈴響:<xliff:g id="FORMATTEDTIME">%1$s</xliff:g>"</string>
     <string name="zen_mode_next_alarm_line_one" msgid="5537042951553420916">"直到下次鬧鐘鈴響"</string>
     <string name="muted_by" msgid="6147073845094180001">"由 <xliff:g id="THIRD_PARTY">%1$s</xliff:g> 設為靜音"</string>
+    <string name="system_error_wipe_data" msgid="6608165524785354962">"您的裝置內部發生問題,必須讓裝置恢復原廠設定才能解除不穩定的狀態。"</string>
+    <string name="system_error_manufacturer" msgid="8086872414744210668">"您的裝置內部發生問題,詳情請洽詢裝置製造商。"</string>
+    <!-- no translation found for stk_cc_ussd_to_dial (5202342984749947872) -->
+    <skip />
+    <!-- no translation found for stk_cc_ussd_to_ss (2345360594181405482) -->
+    <skip />
+    <!-- no translation found for stk_cc_ussd_to_ussd (7466087659967191653) -->
+    <skip />
+    <!-- no translation found for stk_cc_ss_to_dial (2151304435775557162) -->
+    <skip />
+    <!-- no translation found for stk_cc_ss_to_ussd (3951862188105305589) -->
+    <skip />
+    <!-- no translation found for stk_cc_ss_to_ss (5470768854991452695) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-zu/strings.xml b/core/res/res/values-zu/strings.xml
index 50a3008..116b2a6 100644
--- a/core/res/res/values-zu/strings.xml
+++ b/core/res/res/values-zu/strings.xml
@@ -564,6 +564,8 @@
     <string name="permdesc_configureWifiDisplay" msgid="7916815158690218065">"Ivumela uhlelo lokusebenza ukulungisa nokuxhuma ekubukisweni kwe-Wi-Fi."</string>
     <string name="permlab_controlWifiDisplay" msgid="393641276723695496">"lawula ukubukwa kwe-Wi-Fi"</string>
     <string name="permdesc_controlWifiDisplay" msgid="4543912292681826986">"Uvumela uhlelo lokusebenza ukulawula izici zeleveli ephansi zokuboniswa kwe-Wi-Fi."</string>
+    <string name="permlab_controlVpn" msgid="2618442789397588200">"lawula Amanethiwekhi Wemfihlo Abonakalayo"</string>
+    <string name="permdesc_controlVpn" msgid="762852603315861214">"Ivumela uhlelo lokusebenza ukulawula izici zeleveli ephansi Zamanethiwekhi Wemfihlo Abonakalayo."</string>
     <string name="permlab_captureAudioOutput" msgid="6857134498402346708">"shutha okukhipha umsindo"</string>
     <string name="permdesc_captureAudioOutput" msgid="6210597754212208853">"Kuvumela uhlelo lokusebenza ukuba lushuthe futhi luqondise kabusha okukhipha umsindo."</string>
     <string name="permlab_captureAudioHotword" msgid="1890553935650349808">"Ukutholwa kwe-Hotword"</string>
@@ -1902,4 +1904,18 @@
     <string name="zen_mode_next_alarm_summary" msgid="5915140424683747372">"Kuze kube yi-alamu elandelayo ngo-<xliff:g id="FORMATTEDTIME">%1$s</xliff:g>"</string>
     <string name="zen_mode_next_alarm_line_one" msgid="5537042951553420916">"Kuze kube yi-alamu elandelayo"</string>
     <string name="muted_by" msgid="6147073845094180001">"Ithuliswe ngu-<xliff:g id="THIRD_PARTY">%1$s</xliff:g>"</string>
+    <string name="system_error_wipe_data" msgid="6608165524785354962">"Kukhona inkinga yangaphakathi ngedivayisi yakho, futhi ingase ibe engazinzile kuze kube yilapho usetha kabusha yonke idatha."</string>
+    <string name="system_error_manufacturer" msgid="8086872414744210668">"Kukhona inkinga yangaphakathi ngedivayisi yakho. Xhumana nomkhiqizi wakho ukuze uthole imininingwane."</string>
+    <!-- no translation found for stk_cc_ussd_to_dial (5202342984749947872) -->
+    <skip />
+    <!-- no translation found for stk_cc_ussd_to_ss (2345360594181405482) -->
+    <skip />
+    <!-- no translation found for stk_cc_ussd_to_ussd (7466087659967191653) -->
+    <skip />
+    <!-- no translation found for stk_cc_ss_to_dial (2151304435775557162) -->
+    <skip />
+    <!-- no translation found for stk_cc_ss_to_ussd (3951862188105305589) -->
+    <skip />
+    <!-- no translation found for stk_cc_ss_to_ss (5470768854991452695) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values/attrs.xml b/core/res/res/values/attrs.xml
index 4f8acdb..403fd99 100644
--- a/core/res/res/values/attrs.xml
+++ b/core/res/res/values/attrs.xml
@@ -2639,8 +2639,8 @@
              to allow the children to draw outside of their bounds. The default value of
              this property is true. -->
         <attr name="clipChildren" format="boolean" />
-        <!-- Defines whether the ViewGroup will clip its drawing surface so as to exclude
-             the padding area. This property is set to true by default. -->
+        <!-- Defines whether the ViewGroup will clip its children to its padding, if
+             padding is not zero. This property is set to true by default. -->
         <attr name="clipToPadding" format="boolean" />
         <!-- Defines the layout animation to use the first time the ViewGroup is laid out.
              Layout animations can also be started manually after the first layout. -->
@@ -4662,6 +4662,11 @@
         <attr name="weekDayTextAppearance" format="reference" />
         <!-- The text appearance for the calendar dates. -->
         <attr name="dateTextAppearance" format="reference" />
+        <!-- The number of weeks to be shown. -->
+        <attr name="calendarViewMode">
+            <enum name="holo" value="0" />
+            <enum name="material" value="1" />
+        </attr>
     </declare-styleable>
 
     <declare-styleable name="NumberPicker">
@@ -7215,6 +7220,8 @@
         <attr name="goIcon" format="reference" />
         <!-- Search icon -->
         <attr name="searchIcon" format="reference" />
+        <!-- Search icon displayed as a text field hint -->
+        <attr name="searchHintIcon" format="reference" />
         <!-- Voice button icon -->
         <attr name="voiceIcon" format="reference" />
         <!-- Commit icon shown in the query suggestion row -->
diff --git a/core/res/res/values/colors_material.xml b/core/res/res/values/colors_material.xml
index 46ec838..a8fd8d4 100644
--- a/core/res/res/values/colors_material.xml
+++ b/core/res/res/values/colors_material.xml
@@ -22,7 +22,7 @@
     <color name="background_floating_material_light">#ffeeeeee</color>
 
     <color name="primary_material_dark">#ff212121</color>
-    <color name="primary_material_light">#ffe0e0e0</color>
+    <color name="primary_material_light">#ffefefef</color>
     <color name="primary_dark_material_dark">#ff000000</color>
     <color name="primary_dark_material_light">#ff757575</color>
 
diff --git a/core/res/res/values/dimens_material.xml b/core/res/res/values/dimens_material.xml
index 4a2119b..e3672c8 100644
--- a/core/res/res/values/dimens_material.xml
+++ b/core/res/res/values/dimens_material.xml
@@ -91,6 +91,10 @@
     <!-- Default rounded corner for controls -->
     <dimen name="control_corner_material">2dp</dimen>
 
+    <dimen name="edit_text_inset_horizontal_material">4dp</dimen>
+    <dimen name="edit_text_inset_top_material">4dp</dimen>
+    <dimen name="edit_text_inset_bottom_material">8dp</dimen>
+
     <dimen name="dialog_padding_material">24dp</dimen>
     <dimen name="dialog_padding_top_material">18dp</dimen>
 </resources>
diff --git a/core/res/res/values/integers.xml b/core/res/res/values/integers.xml
index 0343cfa..8e27226 100644
--- a/core/res/res/values/integers.xml
+++ b/core/res/res/values/integers.xml
@@ -22,4 +22,5 @@
     <integer name="button_pressed_animation_duration">100</integer>
     <integer name="button_pressed_animation_delay">100</integer>
     <integer name="disabled_alpha_animation_duration">100</integer>
+    <integer name="dock_enter_exit_duration">250</integer>
 </resources>
diff --git a/core/res/res/values/public.xml b/core/res/res/values/public.xml
index c661c33..c01d406 100644
--- a/core/res/res/values/public.xml
+++ b/core/res/res/values/public.xml
@@ -2600,5 +2600,6 @@
     <public type="attr" name="accessibilityTraversalBefore" />
     <public type="attr" name="accessibilityTraversalAfter" />
     <public type="attr" name="dialogPreferredPadding" />
+    <public type="attr" name="searchHintIcon" />
 
 </resources>
diff --git a/core/res/res/values/strings.xml b/core/res/res/values/strings.xml
index b97be6e..7bc24c3 100644
--- a/core/res/res/values/strings.xml
+++ b/core/res/res/values/strings.xml
@@ -212,6 +212,12 @@
     <!-- Displayed to tell the user that all service is blocked by access control. -->
     <string name="RestrictedOnAll">All voice/data/SMS services are blocked.</string>
 
+    <!-- Displayed to tell the user that peer changed TTY mode -->
+    <string name="peerTtyModeFull">Peer requested TTY Mode FULL</string>
+    <string name="peerTtyModeHco">Peer requested TTY Mode HCO</string>
+    <string name="peerTtyModeVco">Peer requested TTY Mode VCO</string>
+    <string name="peerTtyModeOff">Peer requested TTY Mode OFF</string>
+
     <!-- Mappings between TS 27.007 +CFCC/+CLCK "service classes" and human-readable strings--> <skip />
     <!-- Example: Service was enabled for: Voice, Data -->
     <string name="serviceClassVoice">Voice</string>
@@ -3306,6 +3312,8 @@
     <!-- This is the default button label in the system-wide search UI.
          It is also used by the home screen's search "widget". It should be short -->
     <string name="search_go">Search</string>
+    <!-- Default hint text for the system-wide search UI's text field. [CHAR LIMIT=30] -->
+    <string name="search_hint">Search…</string>
     <!-- SearchView accessibility description for search button [CHAR LIMIT=NONE] -->
     <string name="searchview_description_search">Search</string>
     <!-- SearchView accessibility description for search text field [CHAR LIMIT=NONE] -->
@@ -5077,7 +5085,7 @@
     <string name="lock_to_app_unlock_password">Ask for password before unpinning</string>
 
     <!-- [CHAR_LIMIT=NONE] Battery saver: Feature description -->
-    <string name="battery_saver_description">To help improve battery life, battery saver reduces your device’s performance and limits vibration and most background data. Email, messaging, and other apps that rely on syncing may not update unless you open them.\n\nBattery saver turns off automatically when your device is charging.</string>
+    <string name="battery_saver_description">To help improve battery life, battery saver reduces your device’s performance and limits vibration, location services, and most background data. Email, messaging, and other apps that rely on syncing may not update unless you open them.\n\nBattery saver turns off automatically when your device is charging.</string>
 
     <!-- [CHAR_LIMIT=NONE] Zen mode: Condition summary for built-in downtime condition, if active -->
     <string name="downtime_condition_summary">Until your downtime ends at <xliff:g id="formattedTime" example="10:00 PM">%1$s</xliff:g></string>
@@ -5132,4 +5140,13 @@
     <!-- Error message shown when there is a system error which can be solved by the manufacturer. [CHAR LIMIT=NONE] -->
     <string name="system_error_manufacturer">There\'s an internal problem with your device. Contact your manufacturer for details.</string>
 
+    <!-- Displayed when the USSD/SS request is modified by STK CC to a
+    different request. This will be displayed in a toast. -->
+    <string name="stk_cc_ussd_to_dial">USSD request is modified to DIAL request.</string>
+    <string name="stk_cc_ussd_to_ss">USSD request is modified to SS request.</string>
+    <string name="stk_cc_ussd_to_ussd">USSD request is modified to new USSD request.</string>
+    <string name="stk_cc_ss_to_dial">SS request is modified to DIAL request.</string>
+    <string name="stk_cc_ss_to_ussd">SS request is modified to USSD request.</string>
+    <string name="stk_cc_ss_to_ss">SS request is modified to new SS request.</string>
+
 </resources>
diff --git a/core/res/res/values/styles.xml b/core/res/res/values/styles.xml
index 5a59afe..c520a46 100644
--- a/core/res/res/values/styles.xml
+++ b/core/res/res/values/styles.xml
@@ -565,6 +565,7 @@
         <item name="selectedDateVerticalBar">@drawable/day_picker_week_view_dayline_holo</item>
         <item name="weekDayTextAppearance">@style/TextAppearance.Small.CalendarViewWeekDayView</item>
         <item name="dateTextAppearance">?attr/textAppearanceSmall</item>
+        <item name="calendarViewMode">holo</item>
     </style>
 
     <style name="Widget.NumberPicker">
diff --git a/core/res/res/values/styles_holo.xml b/core/res/res/values/styles_holo.xml
index c7d2db1..41b8b25 100644
--- a/core/res/res/values/styles_holo.xml
+++ b/core/res/res/values/styles_holo.xml
@@ -358,6 +358,7 @@
         <item name="submitBackground">@drawable/textfield_searchview_right_holo_dark</item>
         <item name="closeIcon">@drawable/ic_clear_holo_dark</item>
         <item name="searchIcon">@drawable/ic_search_api_holo_dark</item>
+        <item name="searchHintIcon">@drawable/ic_search_api_holo_dark</item>
         <item name="goIcon">@drawable/ic_go_search_api_holo_dark</item>
         <item name="voiceIcon">@drawable/ic_voice_search_api_holo_dark</item>
         <item name="commitIcon">@drawable/ic_commit_search_api_holo_dark</item>
@@ -444,6 +445,7 @@
         <item name="weekSeparatorLineColor">#19FFFFFF</item>
         <item name="selectedDateVerticalBar">@drawable/day_picker_week_view_dayline_holo</item>
         <item name="weekDayTextAppearance">@style/TextAppearance.Holo.CalendarViewWeekDayView</item>
+        <item name="calendarViewMode">holo</item>
     </style>
 
     <style name="Widget.Holo.ImageButton" parent="Widget.ImageButton">
@@ -881,6 +883,7 @@
         <item name="weekNumberColor">#7F080021</item>
         <item name="weekSeparatorLineColor">#7F08002A</item>
         <item name="weekDayTextAppearance">@style/TextAppearance.Holo.Light.CalendarViewWeekDayView</item>
+        <item name="calendarViewMode">holo</item>
     </style>
 
     <style name="Widget.Holo.Light.NumberPicker" parent="Widget.Holo.NumberPicker" />
diff --git a/core/res/res/values/styles_material.xml b/core/res/res/values/styles_material.xml
index e04d901..6749441 100644
--- a/core/res/res/values/styles_material.xml
+++ b/core/res/res/values/styles_material.xml
@@ -517,12 +517,20 @@
         <item name="submitBackground">@drawable/textfield_search_material</item>
         <item name="closeIcon">@drawable/ic_clear_material</item>
         <item name="searchIcon">@drawable/ic_search_api_material</item>
+        <item name="searchHintIcon">@drawable/ic_search_api_material</item>
         <item name="goIcon">@drawable/ic_go_search_api_material</item>
         <item name="voiceIcon">@drawable/ic_voice_search_api_material</item>
         <item name="commitIcon">@drawable/ic_commit_search_api_material</item>
         <item name="suggestionRowLayout">@layout/search_dropdown_item_icons_2line</item>
     </style>
 
+    <style name="Widget.Material.SearchView.ActionBar">
+        <item name="queryBackground">@empty</item>
+        <item name="submitBackground">@empty</item>
+        <item name="searchHintIcon">@empty</item>
+        <item name="queryHint">@string/search_hint</item>
+    </style>
+
     <style name="Widget.Material.SegmentedButton" parent="SegmentedButton">
         <item name="background">@drawable/btn_group_holo_dark</item>
     </style>
@@ -612,6 +620,7 @@
         <item name="weekSeparatorLineColor">#19FFFFFF</item>
         <item name="selectedDateVerticalBar">@drawable/day_picker_week_view_dayline_holo</item>
         <item name="weekDayTextAppearance">@style/TextAppearance.Material.CalendarViewWeekDayView</item>
+        <item name="calendarViewMode">material</item>
     </style>
 
     <style name="Widget.Material.ImageButton" parent="Widget.ImageButton">
@@ -961,6 +970,7 @@
     <style name="Widget.Material.Light.ButtonBar" parent="Widget.Material.ButtonBar"/>
     <style name="Widget.Material.Light.ButtonBar.AlertDialog" parent="Widget.Material.ButtonBar.AlertDialog"/>
     <style name="Widget.Material.Light.SearchView" parent="Widget.Material.SearchView"/>
+    <style name="Widget.Material.Light.SearchView.ActionBar" parent="Widget.Material.SearchView.ActionBar"/>
 
     <style name="Widget.Material.Light.SegmentedButton" parent="Widget.Material.SegmentedButton">
         <item name="background">@drawable/btn_group_holo_light</item>
@@ -999,6 +1009,7 @@
         <item name="weekNumberColor">#7F080021</item>
         <item name="weekSeparatorLineColor">#7F08002A</item>
         <item name="weekDayTextAppearance">@style/TextAppearance.Material.CalendarViewWeekDayView</item>
+        <item name="calendarViewMode">material</item>
     </style>
 
     <style name="Widget.Material.Light.NumberPicker" parent="Widget.Material.NumberPicker"/>
diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml
index 702d5ed..6135466 100644
--- a/core/res/res/values/symbols.xml
+++ b/core/res/res/values/symbols.xml
@@ -715,6 +715,10 @@
   <java-symbol type="string" name="perms_description_app" />
   <java-symbol type="string" name="perms_new_perm_prefix" />
   <java-symbol type="string" name="petabyteShort" />
+  <java-symbol type="string" name="peerTtyModeFull" />
+  <java-symbol type="string" name="peerTtyModeHco" />
+  <java-symbol type="string" name="peerTtyModeVco" />
+  <java-symbol type="string" name="peerTtyModeOff" />
   <java-symbol type="string" name="phoneTypeAssistant" />
   <java-symbol type="string" name="phoneTypeCallback" />
   <java-symbol type="string" name="phoneTypeCar" />
@@ -918,6 +922,12 @@
   <java-symbol type="string" name="default_audio_route_name_dock_speakers" />
   <java-symbol type="string" name="default_media_route_name_hdmi" />
   <java-symbol type="string" name="default_audio_route_category_name" />
+  <java-symbol type="string" name="stk_cc_ss_to_dial" />
+  <java-symbol type="string" name="stk_cc_ss_to_ss" />
+  <java-symbol type="string" name="stk_cc_ss_to_ussd" />
+  <java-symbol type="string" name="stk_cc_ussd_to_dial" />
+  <java-symbol type="string" name="stk_cc_ussd_to_ss" />
+  <java-symbol type="string" name="stk_cc_ussd_to_ussd" />
   <java-symbol type="string" name="safe_media_volume_warning" />
   <java-symbol type="string" name="media_route_status_scanning" />
   <java-symbol type="string" name="media_route_status_connecting" />
@@ -1848,6 +1858,7 @@
   <java-symbol type="string" name="usb_storage_stop_title" />
   <java-symbol type="string" name="usb_storage_title" />
   <java-symbol type="style" name="Animation.RecentApplications" />
+  <java-symbol type="integer" name="dock_enter_exit_duration" />
 
   <!-- ImfTest -->
   <java-symbol type="layout" name="auto_complete_list" />
diff --git a/core/res/res/values/themes_material.xml b/core/res/res/values/themes_material.xml
index b320ae5..3f2062dc 100644
--- a/core/res/res/values/themes_material.xml
+++ b/core/res/res/values/themes_material.xml
@@ -828,6 +828,7 @@
          secondary text color, with the primary text color. -->
     <style name="ThemeOverlay.Material.ActionBar">
         <item name="colorControlNormal">?attr/textColorPrimary</item>
+        <item name="searchViewStyle">@style/Widget.Material.Light.SearchView.ActionBar</item>
     </style>
 
     <!-- Theme overlay that replaces colors with their dark versions and replaces the normal
@@ -835,6 +836,7 @@
          text color. -->
     <style name="ThemeOverlay.Material.Dark.ActionBar">
         <item name="colorControlNormal">?attr/textColorPrimary</item>
+        <item name="searchViewStyle">@style/Widget.Material.SearchView.ActionBar</item>
     </style>
 
     <!-- Variant of the material (dark) theme with no action bar. -->
diff --git a/docs/html/auto/images/assets/icons/auto_app_in_simulator.png b/docs/html/auto/images/assets/icons/auto_app_in_simulator.png
new file mode 100644
index 0000000..085b82b
--- /dev/null
+++ b/docs/html/auto/images/assets/icons/auto_app_in_simulator.png
Binary files differ
diff --git a/docs/html/auto/images/assets/icons/gp-auto-quality.png.png b/docs/html/auto/images/assets/icons/gp-auto-quality.png.png
new file mode 100644
index 0000000..483f418
--- /dev/null
+++ b/docs/html/auto/images/assets/icons/gp-auto-quality.png.png
Binary files differ
diff --git a/docs/html/auto/images/assets/icons/media_app_playback.png b/docs/html/auto/images/assets/icons/media_app_playback.png
new file mode 100644
index 0000000..3de04bf
--- /dev/null
+++ b/docs/html/auto/images/assets/icons/media_app_playback.png
Binary files differ
diff --git a/docs/html/auto/images/assets/icons/messaging_app_notifications.png b/docs/html/auto/images/assets/icons/messaging_app_notifications.png
new file mode 100644
index 0000000..3236fdf
--- /dev/null
+++ b/docs/html/auto/images/assets/icons/messaging_app_notifications.png
Binary files differ
diff --git a/docs/html/auto/images/assets/landing/01.gif b/docs/html/auto/images/assets/landing/01.gif
new file mode 100644
index 0000000..34c9fa8
--- /dev/null
+++ b/docs/html/auto/images/assets/landing/01.gif
Binary files differ
diff --git a/docs/html/auto/images/assets/landing/02.gif b/docs/html/auto/images/assets/landing/02.gif
new file mode 100644
index 0000000..d50e06b
--- /dev/null
+++ b/docs/html/auto/images/assets/landing/02.gif
Binary files differ
diff --git a/docs/html/auto/images/assets/landing/03.gif b/docs/html/auto/images/assets/landing/03.gif
new file mode 100644
index 0000000..7992021
--- /dev/null
+++ b/docs/html/auto/images/assets/landing/03.gif
Binary files differ
diff --git a/docs/html/auto/images/assets/landing/04.png b/docs/html/auto/images/assets/landing/04.png
new file mode 100644
index 0000000..a0e75f3
--- /dev/null
+++ b/docs/html/auto/images/assets/landing/04.png
Binary files differ
diff --git a/docs/html/auto/images/assets/landing/05.png b/docs/html/auto/images/assets/landing/05.png
new file mode 100644
index 0000000..f3d2ab8
--- /dev/null
+++ b/docs/html/auto/images/assets/landing/05.png
Binary files differ
diff --git a/docs/html/auto/images/assets/landing/06.png b/docs/html/auto/images/assets/landing/06.png
new file mode 100644
index 0000000..b19a6bb
--- /dev/null
+++ b/docs/html/auto/images/assets/landing/06.png
Binary files differ
diff --git a/docs/html/auto/images/assets/landing/07.png b/docs/html/auto/images/assets/landing/07.png
new file mode 100644
index 0000000..380e8da
--- /dev/null
+++ b/docs/html/auto/images/assets/landing/07.png
Binary files differ
diff --git a/docs/html/auto/images/assets/landing/08.png b/docs/html/auto/images/assets/landing/08.png
new file mode 100644
index 0000000..9889b39
--- /dev/null
+++ b/docs/html/auto/images/assets/landing/08.png
Binary files differ
diff --git a/docs/html/auto/images/assets/landing/FrameA.png b/docs/html/auto/images/assets/landing/FrameA.png
new file mode 100644
index 0000000..2a78380
--- /dev/null
+++ b/docs/html/auto/images/assets/landing/FrameA.png
Binary files differ
diff --git a/docs/html/auto/images/assets/landing/FrameB.png b/docs/html/auto/images/assets/landing/FrameB.png
new file mode 100644
index 0000000..cb7a3c4
--- /dev/null
+++ b/docs/html/auto/images/assets/landing/FrameB.png
Binary files differ
diff --git a/docs/html/auto/images/logos/apps/TextMe.png b/docs/html/auto/images/logos/apps/TextMe.png
new file mode 100644
index 0000000..b96f81a
--- /dev/null
+++ b/docs/html/auto/images/logos/apps/TextMe.png
Binary files differ
diff --git a/docs/html/auto/images/logos/apps/kik.png b/docs/html/auto/images/logos/apps/kik.png
new file mode 100644
index 0000000..056ef7e
--- /dev/null
+++ b/docs/html/auto/images/logos/apps/kik.png
Binary files differ
diff --git a/docs/html/auto/images/logos/apps/npr.png b/docs/html/auto/images/logos/apps/npr.png
new file mode 100644
index 0000000..5234201
--- /dev/null
+++ b/docs/html/auto/images/logos/apps/npr.png
Binary files differ
diff --git a/docs/html/auto/images/logos/apps/soundcloud.png b/docs/html/auto/images/logos/apps/soundcloud.png
new file mode 100644
index 0000000..a5bdbe3
--- /dev/null
+++ b/docs/html/auto/images/logos/apps/soundcloud.png
Binary files differ
diff --git a/docs/html/auto/images/logos/apps/textplus.png b/docs/html/auto/images/logos/apps/textplus.png
new file mode 100644
index 0000000..2a640c4
--- /dev/null
+++ b/docs/html/auto/images/logos/apps/textplus.png
Binary files differ
diff --git a/docs/html/auto/images/logos/apps/whatsapp.png b/docs/html/auto/images/logos/apps/whatsapp.png
new file mode 100644
index 0000000..fb5866e
--- /dev/null
+++ b/docs/html/auto/images/logos/apps/whatsapp.png
Binary files differ
diff --git a/docs/html/auto/images/ui/gearhead_custom_UI.png b/docs/html/auto/images/ui/gearhead_custom_UI.png
new file mode 100644
index 0000000..345db12
--- /dev/null
+++ b/docs/html/auto/images/ui/gearhead_custom_UI.png
Binary files differ
diff --git a/docs/html/auto/images/ui/gearhead_custom_user_actions.png b/docs/html/auto/images/ui/gearhead_custom_user_actions.png
new file mode 100644
index 0000000..6cc0dcb
--- /dev/null
+++ b/docs/html/auto/images/ui/gearhead_custom_user_actions.png
Binary files differ
diff --git a/docs/html/auto/images/ui/gearhead_day.png b/docs/html/auto/images/ui/gearhead_day.png
new file mode 100644
index 0000000..81ead75
--- /dev/null
+++ b/docs/html/auto/images/ui/gearhead_day.png
Binary files differ
diff --git a/docs/html/auto/images/ui/gearhead_drawer_generic.png b/docs/html/auto/images/ui/gearhead_drawer_generic.png
new file mode 100644
index 0000000..d203aed
--- /dev/null
+++ b/docs/html/auto/images/ui/gearhead_drawer_generic.png
Binary files differ
diff --git a/docs/html/auto/images/ui/gearhead_drawers_customized.png b/docs/html/auto/images/ui/gearhead_drawers_customized.png
new file mode 100644
index 0000000..44915b5
--- /dev/null
+++ b/docs/html/auto/images/ui/gearhead_drawers_customized.png
Binary files differ
diff --git a/docs/html/auto/images/ui/gearhead_generic_UI.png b/docs/html/auto/images/ui/gearhead_generic_UI.png
new file mode 100644
index 0000000..beb0701
--- /dev/null
+++ b/docs/html/auto/images/ui/gearhead_generic_UI.png
Binary files differ
diff --git a/docs/html/auto/images/ui/gearhead_lens_switching.png b/docs/html/auto/images/ui/gearhead_lens_switching.png
new file mode 100644
index 0000000..9dbfe6c
--- /dev/null
+++ b/docs/html/auto/images/ui/gearhead_lens_switching.png
Binary files differ
diff --git a/docs/html/auto/images/ui/gearhead_night.png b/docs/html/auto/images/ui/gearhead_night.png
new file mode 100644
index 0000000..3f8c593
--- /dev/null
+++ b/docs/html/auto/images/ui/gearhead_night.png
Binary files differ
diff --git a/docs/html/auto/images/ui/gearhead_overview.png b/docs/html/auto/images/ui/gearhead_overview.png
new file mode 100644
index 0000000..4332ddf3
--- /dev/null
+++ b/docs/html/auto/images/ui/gearhead_overview.png
Binary files differ
diff --git a/docs/html/auto/index.jd b/docs/html/auto/index.jd
index 63ac287..129478a 100644
--- a/docs/html/auto/index.jd
+++ b/docs/html/auto/index.jd
@@ -77,17 +77,20 @@
             <div class="col-10">
               <div class="landing-section-header">
                 <div class="landing-h1 hero">Android Auto</div>
-                <div class="landing-subhead hero">Entertainment and services on your dashboard</div>
+                <div class="landing-subhead hero">Audio entertainment and
+                  messaging services in the car</div>
                 <div class="landing-hero-description">
-                  <p style="width:450px">Display and control your Android app in vehicles.
-                   Integrate your content with easy-to-use APIs and let Android Auto take
-                   care of the rest.</p>
+                  <p style="width:450px">Let drivers listen to and control
+                    content in your music and other audio apps. Allow drivers to
+                    hear and respond to your messaging service via the
+                    car's controls and screen.</p>
                 </div>
 
               <div class="landing-body">
-                <a href="{@docRoot}auto/overview.html" class="landing-button landing-primary"
+                <a href="{@docRoot}training/auto/index.html"
+                   class="landing-button landing-primary"
                    style="margin-top:40px;">
-                  Developer Overview
+                  Get Started
                 </a>
               </div>
             </div>
@@ -103,149 +106,114 @@
     </div> <!-- end .landing-section .landing-hero -->
   </div> <!-- end .landing-hero-container -->
 
-    <div class="landing-rest-of-page">
+  <div class="landing-rest-of-page">
 
-      <div class="landing-section landing-gray-background" id="android-in-car">
-        <div class="wrap">
-          <div class="landing-section-h1">
-            <div class="landing-h1">Extending Android to Cars</div>
-          </div>
-          <div class="landing-body">
-            <div class="landing-subhead">Android Auto brings the Android experience to
-            cars with apps like Google Now and Maps.</div>
-            <div class="cols">
-              <div class="col-8">
-                <div class="auto-img-container-cols">
-                  <img class="auto-img-frame-cols" src="{@docRoot}auto/images/assets/00_frame.png" />
-                  <img class="auto-img-shot-cols" src="{@docRoot}auto/images/assets/01_b_now.png" />
-                </div>
-              </div>
-              <div class="col-8">
-                <div class="auto-img-container-cols">
-                  <img class="auto-img-frame-cols" src="{@docRoot}auto/images/assets/00_frame.png" />
-                  <img class="auto-img-shot-cols" src="{@docRoot}auto/images/assets/01_a_maps.png" />
-                </div>
+    <div class="landing-section landing-gray-background" id="android-in-car">
+      <div class="wrap">
+        <div class="landing-section-h1">
+          <div class="landing-h1">Extending Android to Cars</div>
+          <div class="landing-subhead">Android Auto brings the Android
+              platform into the car with a user interface that's optimized for driving.</div>
+        </div>
+
+        <div class="landing-body">
+          <div class="cols">
+            <div class="col-8">
+              <div class="auto-img-container-cols">
+                <img class="auto-img-frame-cols" src="/auto/images/assets/landing/FrameA.png" />
+                <img class="auto-img-shot-cols" src="/auto/images/assets/landing/01.gif" />
               </div>
             </div>
-
-            <p>When users connect their Android phones to compatible vehicles, Android Auto
-             shows a standard interface that lets them start enabled apps and services.
-             Android Auto locks the handheld device when connected, so drivers
-            interact with Auto by using the vehicle's input controls, touch display, and voice.</p>
-            </p>
+            <div class="col-8">
+              <div class="auto-img-container-cols">
+                <img class="auto-img-frame-cols" src="/auto/images/assets/landing/FrameA.png" />
+                <img class="auto-img-shot-cols" src="/auto/images/assets/landing/02.gif" />
+              </div>
+            </div>
           </div>
-        </div> <!-- end .wrap -->
-      </div> <!-- end .landing-section -->
+          <p>Before you start building, check out the
+              <a href="http://youtu.be/ctiaVxgclsg" class="external-link">Introduction to Android Auto</a> video to understand how
+              users see and interact with your app in Android Auto.
+          </p>
+        </div>
+      </div> <!-- end .wrap -->
+    </div> <!-- end .landing-section -->
 
-
-      <div class="landing-section">
+    <div class="landing-section">
         <div class="wrap">
           <div class="landing-section-header">
             <div class="landing-h1">Build for One Platform</div>
-            <div class="landing-subhead">Create apps with the Android APIs you're familiar with
-            and extend them to cars with the Auto SDK.
+            <div class="landing-subhead">Create apps with the Android APIs
+              you’re familiar with and extend them to cars.
             </div>
           </div>
 
           <div class="landing-body">
-
-            <div class="cols">
-              <div class="col-8">
-                <div class="auto-img-container-cols">
-                  <img class="auto-img-frame-cols" src="{@docRoot}auto/images/assets/00_frame.png" />
-                  <img class="auto-img-shot-cols" src="{@docRoot}auto/images/assets/02_b_switcher.gif" />
-                </div>
-              </div>
-              <div class="col-8">
-                <div class="auto-img-container-cols">
-                  <img class="auto-img-frame-cols" src="{@docRoot}auto/images/assets/00_frame.png" />
-                  <img class="auto-img-shot-cols" src="{@docRoot}auto/images/assets/02_a_notif.gif" />
-                </div>
-              </div>
-            </div>
-            <p>Write your apps without having
-            to worry about vehicle-specific hardware differences like screen resolution, software
-            interfaces, knobs, and touch controls. Your users get the same experience on any compatible
-            vehicle such as a consistent app launcher and system events such as notifications.</p>
-          </div>
-        </div> <!-- end .wrap -->
-      </div> <!-- end .landing-section -->
-
-
-      <div class="landing-section landing-gray-background">
-        <div class="wrap">
-          <div class="landing-section-header">
-            <div class="landing-h1">Minimize Distraction</div>
-            <div class="landing-subhead">
-             Android Auto displays different UIs for several app categories that let users focus on the road.
-            </div>
-          </div>
-          <div class="landing-body">
             <div class="cols">
               <div class="col-8">
                 <div class="auto-img-container-cols">
-                  <img class="auto-img-frame-cols" src="{@docRoot}auto/images/assets/00_frame.png" />
-                  <img class="auto-img-shot-cols" src="{@docRoot}auto/images/assets/03_b_voice.gif" />
+                  <img class="auto-img-frame-cols" src="/auto/images/assets/landing/FrameA.png" />
+                  <img class="auto-img-shot-cols" src="/auto/images/assets/landing/05.png" />
                 </div>
               </div>
               <div class="col-8">
                 <div class="auto-img-container-cols">
-                  <img class="auto-img-frame-cols" src="{@docRoot}auto/images/assets/00_frame.png" />
-                  <img class="auto-img-shot-cols" src="{@docRoot}auto/images/assets/03_a_musict.png" />
+                  <img class="auto-img-frame-cols" src="/auto/images/assets/landing/FrameA.png" />
+                  <img class="auto-img-shot-cols" src="/auto/images/assets/landing/06.png" />
                 </div>
               </div>
             </div>
-            <p>Android Auto defines the user interaction model for all
-             apps and let you hook into a standard UI with touch and voice controls. The interface
-             is designed to reduce driver distraction while still letting you customize and brand them to properly deliver your content.
-             </p>
+            <p>Write your apps without having to worry about vehicle-specific
+            hardware differences like screen resolution, software interfaces,
+            knobs, and touch controls. Your users get the same experience on any
+            compatible vehicle such as a consistent app launcher and system
+            events such as notifications.</p>
           </div>
         </div> <!-- end .wrap -->
       </div> <!-- end .landing-section -->
 
-      <div class="landing-section" style="background-color:#f5f5f5">
+    <div class="landing-section" style="background-color:#f5f5f5" id="developing-for-auto">
         <div class="wrap">
           <div class="landing-section-header">
-            <div class="landing-pre-h1">Coming soon</div>
-            <div class="landing-h1">Android Auto SDK</div>
+            <div class="landing-pre-h1">Now Available</div>
+            <div class="landing-h1">Developing for Android Auto</div>
+            <div class="landing-subhead">The APIs for building Auto-enabled apps
+              are available now! When connected to compatible vehicles, apps on
+              handheld devices running Android 5.0 or higher can communicate
+              with Android Auto.</div>
           </div>
 
           <div class="landing-body">
-            <p>In the coming months, we’ll be releasing the Android Auto SDK, which includes APIs
-              and tools to make your existing apps compatible with Android Auto. The first version
-              of the SDK will provide APIs for music, podcast, live radio, and audio
-              news apps, as well as limited voice actions.</p>
-
-            <div class="cols" style="margin-top:40px">
-              <div class="col-3-wide">
-                <p class="sdk-link-title">Updates</p>
-                <p class="sdk-link-desc">
-                  Register to receive more information and be notified when the SDK is available.
+            <div class="cols">
+              <div class="col-8">
+                <div class="auto-img-container-cols">
+                  <img class="auto-img-frame-cols" src="/auto/images/assets/landing/FrameA.png" />
+                  <img class="auto-img-shot-cols" src="/auto/images/assets/landing/03.gif" />
+                </div>
+                <div class="landing-h3">Play Music on the Road from Your App</div>
+                <p class="landing-small" style="padding-left:0px; padding-top:15px;">
+                  Extend audio apps such as music, radio, and audiobook players
+                  into the car. Build apps that let users browse and play their
+                  music in the car.<br><a href="{@docRoot}training/auto/audio/index.html">Learn how to build audio apps</a>
                 </p>
-                <a class="sdk-link" href="https://docs.google.com/a/google.com/forms/d/1ANgYOoYLkfyZ2JRPSU34Nep5yNaU-Ha2syXJ9b4xLrA/viewform">Sign up for updates</a>
               </div>
-              <div class="col-3-wide">
-                <p class="sdk-link-title">Google+ Community</p>
-                <p class="sdk-link-desc">
-                  Stay involved, get updates, and exchange experiences with other developers.
+              <div class="col-8">
+                <div class="auto-img-container-cols">
+                  <img class="auto-img-frame-cols" src="/auto/images/assets/landing/FrameA.png" />
+                  <img class="auto-img-shot-cols" src="/auto/images/assets/landing/04.png" />
+                </div>
+                <div class="landing-h3">Keep Users Connected with In-Vehicle Messaging</div>
+                <p class="landing-small" style="padding-left:0px; padding-top:15px;">
+                  Create messaging apps that receive incoming notifications,
+                  read messages via text-to-speech, and let users reply by voice
+                  input in the car.<br><a href="{@docRoot}training/auto/messaging/index.html">Learn how to build messaging apps</a>
                 </p>
-                <a class="sdk-link" href="http://g.co/androidautodev">Discuss on Google+</a>
-              </div>
-              <div class="col-3-wide">
-                <p class="sdk-link-title">Developer Overview</p>
-                <p class="sdk-link-desc">
-                  Learn more about developing apps for Android Auto when the SDK is available.
-                </p>
-                <a class="sdk-link" href="{@docRoot}auto/overview.html">Learn about the platform</a>
               </div>
             </div>
           </div>
-
         </div> <!-- end .wrap -->
       </div> <!-- end .landing-section -->
 
-
-
       <div class="landing-section landing-gray-background" >
         <div class="wrap">
           <div class="landing-section-header">
@@ -255,15 +223,25 @@
           </div>
           <div class="landing-body">
           <div class="cols">
-
+            <div class="col-4">
+              <img src="{@docRoot}auto/images/logos/apps/iheartradio.png"
+                   width="160" height="160" class="img-logo" />
+            </div>
             <div class="col-4">
               <img src="{@docRoot}auto/images/logos/apps/joyride.png"
                    width="160" height="160" class="img-logo" />
             </div>
             <div class="col-4">
+              <img src="{@docRoot}auto/images/logos/apps/kik.png"
+                   width="120" height="120" class="img-logo" style="margin-top:30px" />
+            </div>
+            <div class="col-4">
               <img src="{@docRoot}auto/images/logos/apps/mlb.png"
                    width="160" height="160" class="img-logo" />
             </div>
+          </div>
+
+          <div class="cols">
             <div class="col-4">
               <img src="{@docRoot}auto/images/logos/apps/pandora.png"
                    width="160" height="160" class="img-logo" />
@@ -272,43 +250,75 @@
               <img src="{@docRoot}auto/images/logos/apps/pocketcasts.png"
                    width="160" height="160" class="img-logo" />
             </div>
-          </div>
-          <div class="cols">
             <div class="col-4">
               <img src="{@docRoot}auto/images/logos/apps/songza.png"
                    width="160" height="160" class="img-logo" />
             </div>
             <div class="col-4">
+              <img src="/auto/images/logos/apps/soundcloud.png"
+                   width="100" height="100" class="img-logo"
+                   style="margin-top:30px" />
+            </div>
+          </div>
+
+          <div class="cols">
+            <div class="col-4">
+              <img src="/auto/images/logos/apps/spotify.png"
+                   width="160" height="160" class="img-logo" />
+            </div>
+            <div class="col-4">
               <img src="{@docRoot}auto/images/logos/apps/stitcher.png"
                    width="160" height="160" class="img-logo" />
             </div>
             <div class="col-4">
+              <img src="/auto/images/logos/apps/TextMe.png"
+                   width="100" height="100" class="img-logo" style="margin-top:30px" />
+            </div>
+            <div class="col-4">
+              <img src="/auto/images/logos/apps/textplus.png"
+                   width="120" height="24" class="img-logo" style="margin-top:70px" />
+            </div>
+          </div>
+
+          <div class="cols">
+            <div class="col-4">
               <img src="{@docRoot}auto/images/logos/apps/tunein.png"
-                   width="160" height="160" class="img-logo" />
+                   width="160" height="160" class="img-logo" style="margin-left:160px" />
             </div>
             <div class="col-4">
               <img src="{@docRoot}auto/images/logos/apps/umano.png"
-                   width="160" height="160" class="img-logo" />
+                   width="160" height="160" class="img-logo" style="margin-left:370px" />
             </div>
           </div>
+
           <div class="cols" style="margin-top:40px">
               <div class="col-4">
-                <img src="{@docRoot}auto/images/logos/apps/iheartradio.png"
-                     width="160" height="160" class="img-logo" />
+                <img src="/auto/images/logos/apps/whatsapp.png"
+                     width="120" height="120" class="img-logo" />
               </div>
-              <div class="col-12">
+              <div class="col-8">
                 <p><em>
-                "The Android Auto APIs provide an easy way to integrate the most important features and functionality of iHeartRadio’s robust music service into a safety-minded automotive infotainment solution. The process was seamless, utilizing a flexible construct that allowed us to quickly adapt our existing product without losing any of the core experience our listeners know and love."</em></p>
+                "We were able to get messaging functionality for text
+                implemented easily on Android Auto, with minimal development
+                effort. We're excited to participate in Android Auto which
+                provides a notification interface for the car that is both
+                user-friendly and highly safety-minded."</em></p>
               </div>
           </div>
+
           <div class="cols" style="margin-top:60px">
 
               <div class="col-4">
-                <img src="{@docRoot}auto/images/logos/apps/spotify.png"
-                     width="160" height="160" class="img-logo" />
+                <img src="/auto/images/logos/apps/npr.png"
+                     width="100" height="128" class="img-logo" />
               </div>
-              <div class="col-12"><p style="margin-top:20px"><em>
-              "Android Auto offers Spotify the exciting opportunity to easily enable safe access to millions of songs while driving. We were able to quickly develop for the platform using the new Android voice and media API extensions. As a result, Android users will soon be able to continue the Spotify experience in their cars, including being able to play any song, artist, album or playlist by voice.</em></p>
+              <div class="col-8"><p style="margin-top:0px"><em>
+              "Android Auto connects NPR One listeners to a personalized stream
+              of public radio news and stories to catch up on in the car. It's
+              an engaging and driver-safe user experience that was developed
+              using the media APIs provided in Android 5.0. The available
+              development tools made the integration and testing process simple
+              for launching in a short period of time."</em></p>
               </div>
               </div>
           </div>
@@ -316,8 +326,6 @@
       </div> <!-- end .landing-section -->
 
 
-
-
       <div class="landing-section landing-white-background">
         <div class="wrap">
           <div class="landing-section-header">
@@ -456,24 +464,47 @@
           </div>
         </div>
       </div>
-    </div> <!-- end .landing-rest-of-page -->
-    <div class="content-footer wrap" itemscope="" itemtype="http://schema.org/SiteNavigationElement"
-    style="border-top: none;">
-      <div class="layout-content-col col-16" style="padding-top:4px">
-        <style>#___plusone_0 {float:right !important;}</style>
-        <div class="g-plusone" data-size="medium"></div>
+
+      <div class="landing-section landing-red-background">
+        <div class="wrap">
+          <div class="landing-section-header">
+            <div class="landing-h1 landing-align-left">Get Started with Android Auto</div>
+
+            <div class="landing-subhead landing-subhead-red">
+              <p>
+                Set up your development environment and start working with the APIs.
+                We’re excited about the experiences you'll create and can't
+                wait to see what you do next.</p>
+            </div>
+          </div>
+          <div class="landing-body">
+            <a href="{@docRoot}training/auto/index.html"
+            class="landing-button landing-primary" style="margin-top: 20px;">
+              Get Started
+            </a>
+          </div>
+        </div>
       </div>
+  </div>
+  <div class="content-footer wrap" itemscope="" itemtype="http://schema.org/SiteNavigationElement"
+    style="border-top: none;">
+
+    <div class="layout-content-col col-16" style="padding-top:4px">
+      <style>#___plusone_0 {float:right !important;}</style>
+      <div class="g-plusone" data-size="medium"></div>
     </div>
-    <div id="footer" class="wrap" style="width:940px;position:relative;top:-35px;z-index:-1">
-      <div id="copyright">
+  </div>
+
+  <div id="footer" class="wrap" style="width:940px;position:relative;top:-35px;z-index:-1">
+    <div id="copyright">
         Except as noted, this content is
         licensed under <a href="http://creativecommons.org/licenses/by/2.5/">
         Creative Commons Attribution 2.5</a>. For details and
         restrictions, see the <a href="{@docRoot}license.html">Content
         License</a>.
-      </div>
     </div>
-  </div> <!-- end .landing-hero-container -->
+  </div>
+</div> <!-- end .landing-hero-container -->
 
   <script>
   $("a.landing-down-arrow").on("click", function(e) {
diff --git a/docs/html/auto/overview.jd b/docs/html/auto/overview.jd
deleted file mode 100644
index ae1efec..0000000
--- a/docs/html/auto/overview.jd
+++ /dev/null
@@ -1,411 +0,0 @@
-fullpage=true
-page.viewport_width=970
-no_footer_links=true
-excludeFromSuggestions=true
-page.metaDescription=Android Auto
-
-@jd:body
-
-<style>
-.jd-descr {
-    height:auto;
-}
-#copyright {
-    margin-top:-35px;
-}
-.auto-img-container {
-  position:relative;
-}
-.auto-img-frame {
-  z-index:2;
-  position:relative;
-}
-.auto-img-shot {
-  position:absolute;
-  top:9px;
-  left:8px;
-  z-index:1;
-}
-.auto-img-container-cols {
-  position:relative;
-  margin-top:10px;
-}
-.auto-img-frame-cols {
-  width:380px;
-  z-index:2;
-  position:relative;
-}
-.auto-img-shot-cols {
-  width:369px;
-  position:absolute;
-  top:7px;
-  left:6px;
-  z-index:1;
-}
-.auto-col-2 {
-  width:380px;
-  display: inline;
-  float: left;
-  margin-left: 10px;
-  margin-right: 10px;
-}
-.auto-img-container-single {
-  width:380px;
-  margin:0 auto;
-  margin-top:20px;
-}
-</style>
-
-<div style="width:780px; margin:0 auto;">
-
-<div id="qv-wrapper">
-<div id="qv">
-<h2>In this document</h2>
-<ol>
-  <li><a href="#design">Design</a>
-    <ol>
-      <li><a href="#designprinciples">Design Principles</a></li>
-      <li><a href="#uioverview">UI Overview</a></li>
-    </ol>
-  </li>
-  <li><a href="#architecture">Architecture</a></li>
-  <li><a href="#ui">User Interface</a>
-    <ol>
-      <li><a href="#launchapp">Launch App</a></li>
-      <li><a href="#useractions">User Actions</a></li>
-      <li><a href="#drawertransitions">Drawer Transitions</a></li>
-      <li><a href="#daynighttransitions">Day and Night Transitions</a></li>
-      <li><a href="#customizeui">Customizing the UI</a></li>
-    </ol>
-  </li>
-  <li><a href="#devprocess">Development Process</a></li>
-  <li><a href="#emulator">Testing Your App</a></li>
-  <li><a href="#running">Running Your App</a></li>
-</ol>
-</div>
-</div>
-
-<h1>Android Auto Developer Overview</h1>
-
-<p>Android Auto extends the Android platform into the car. When users connect
-their Android handheld device to a compatible vehicle, Android Auto provides a car-optimized
-Android experience on the vehicle's screen. Users interact with compatible apps and services
-through voice actions and the vehicle's input controls.</p>
-
-<p>The Android Auto SDK lets you easily extend your existing apps to work in the car, without
-having to worry about vehicle-specific hardware differences. You can use many Android APIs and
-services you are already familiar with. Android Auto provides an easy to use UI model and
-supports notifications and voice actions:</p>
-
-<dl>
-<dt style="margin-bottom:10px"><strong>Media UI</strong></dt>
-<dd style="margin-bottom:20px">
-Android Auto defines interaction models and car-specific UI patterns for apps. The
-first version of Android Auto supports media apps, such as music, podcast, live radio, and
-audio news apps.
-</dd>
-<dt style="margin-bottom:10px"><strong>Notifications</strong></dt>
-<dd style="margin-bottom:20px">
-The platform will integrate with existing Android APIs for notifications. Users will get
-car appropiate notifications from Android apps on the vehicle's screen.</dd>
-
-<dt style="margin-bottom:10px"><strong>Voice Actions</strong></dt>
-<dd style="margin-bottom:20px">
-Android Auto supports a set of voice actions to interact with compatible apps and services.
-Apps can respond to the voice actions they're interested in, such as playing a particular song
-or taking a note.</dd>
-
-<dt style="margin-bottom:10px"><strong>Easy Development Workflow</strong></dt>
-<dd style="margin-bottom:20px">
-To extend an existing Android app for Android Auto, you implement a set of interfaces and
-services defined in the platform. You can reuse existing functionality and many Android APIs
-you already know.</dd>
-</dl>
-
-<p>We’ll release the Android Auto SDK in the coming months, which will let you test your
-Android Auto experience on a regular Android device.</p>
-
-
-<h2 id="design">Design</h2>
-
-<p>Android Auto extends users' digital ecosystem into their cars, allowing drivers to stay
-connected to their virtual worlds while staying focused on the road ahead.</p>
-
-<p>Because driving is the primary activity in the car, any digital experiences should be designed
-to complement and augment that activity. They should never demand the user's attention.</p>
-
-<p>Designing for cars is fundamentally different than designing for phones or tablets, and
-requires rethinking how experiences unfold. Because attention is limited and not all tasks are
-possible in the car, effective apps leverage the entire set of devices that drivers have,
-leveraging the app experience on those devices, outside of the car, to set the stage for simple
-experiences while driving.</p>
-
-<p>Android Auto experiences are:</p>
-
-<p><strong>Glanceable and simple</strong>. Driving requires users' full attention. In-car software
-should not. Android Auto was designed to simplify not only the UI, but to optimize interactions
-and require less thinking, induce lower cognitive load, and ultimately, be safer. Effective apps
-provide just enough information in the minimum amount of time the user needs to glance at it and
-return their attention back to the road. Apps should also reduce the number of features to only
-those that are safe and drive-appropriate.</p>
-
-<p><strong>Predictive, yet predictable</strong>. Android Auto leverages rich, contextual awareness
-to keep the driver informed about important situations during the drive. Rich, timely help is
-combined with predictable functions. Effective apps make use of the patterns for common tasks and
-show timely information only when relevant.</p>
-
-<p><strong>Connected</strong>. By leveraging the user's personal ecosystem of apps and services,
-Android Auto promotes a continuous experience from phone to car to other devices. The user's
-music, destinations, and virtual ecosystem are always available to augment the drive. Experiences
-that leverage personal context and other devices are naturally part of Android Auto.</p>
-
-<p><strong>Naturally integrated</strong>. Android Auto blends the user's apps with the car,
-creating a truly integrated experience that leverages what is unique about each car. By using
-the screens, controls, and capabilities of the vehicle, Android Auto feels like an extension of
-the car.</p>
-
-
-
-
-<h2 id="architecture">Architecture</h2>
-
-<p>The Android Auto app shows your app's customized UI on the vehicle's screen. To communicate
-with the Android Auto app, your media app implements a set of media interfaces.</p>
-
-<div style="width:750px;margin:0 auto">
-<img src="{@docRoot}auto/images/figure01.png" alt="" />
-<p class="img-caption">
-  <strong>Figure 1</strong> - Architecture of Android Auto.
-</p>
-</div>
-
-<p>The architecture consists of the following components:</p>
-
-<p><strong>Media App</strong> - Runs a media service that exposes content through browsing and
-playback APIs. The service provides content to the Android Auto app. This is your Android app.</p>
-
-<p><strong>Android Auto App</strong> - Creates the UI and handles user interactions.
-This app uses a media client to request content from the media service running in the media
-app. The client requests data from the media service and monitors service states.</p>
-
-<p><strong>Vehicle Display</strong> - Shows app content and supports user interaction via
-on-screen soft buttons and other components, such as physical buttons or steering
-wheel controls.</p>
-
-<p>Android media apps must implement binders to these APIs:</p>
-
-<ul>
-<li><strong>Browsing</strong> - Enables a media client to browse a hierarchy of a user’s
-media collection, presented as a virtual file system with containers (similar to directories)
-and items (similar to files).</li>
-<li><strong>Playback</strong> - Enables a media client to control media playback and monitor
-playback state through callbacks.</li>
-</ul>
-
-
-<h2 id="ui">User Interface</h2>
-
-<p>The Android Auto app uses a car-specific UI model to display content and user interaction
-opportunities. Android Auto provides you with a standard UI designed to minimize driver
-distraction. You do not have to test a custom UI for driver distraction, which is a
-lengthy and expensive process involving multiple legislations across the globe and different
-standards for each vehicle OEM.</p>
-
-<p>The UI defines interfaces for browsing, searching, and listening to content from
-media apps. You can customize the UI colors, action icons, background images, and more.</p>
-
-<h3 id="launchapp">Launcher</h3>
-
-<p>The launcher shows all the compatible media apps installed on the user’s
-Android device and lets users select one of them from a scrollable list:</p>
-
-<div class="auto-img-container-single">
-  <div class="auto-img-container">
-    <img class="auto-img-frame-cols" src="/auto/images/assets/00_frame.png" />
-    <img class="auto-img-shot-cols" src="/auto/images/assets/do_01_switcher.png" />
-  </div>
-  <p class="img-caption" style="margin-top:0px">
-    <strong>Figure 2.</strong> The launcher.
-  </p>
-</div>
-
-<h3>Primary App UI</h3>
-
-<p>After the user selects a media app, the display shows the primary app UI.
-You can customize this UI to show your own icons, app name, and
-background images. Figure 3 shows an example of a customized UI:</p>
-
-<div class="cols">
-<div class="auto-col-2">
-  <div class="auto-img-container-cols">
-    <img class="auto-img-frame-cols" src="{@docRoot}auto/images/assets/00_frame.png" />
-    <img class="auto-img-shot-cols" src="{@docRoot}auto/images/assets/do_05_template.png" />
-  </div>
-</div>
-<div class="auto-col-2">
-  <div class="auto-img-container-cols">
-    <img class="auto-img-frame-cols" src="{@docRoot}auto/images/assets/00_frame.png" />
-    <img class="auto-img-shot-cols" src="{@docRoot}auto/images/assets/do_02_music.png" />
-  </div>
-</div>
-</div>
-<p class="img-caption">
-  <strong>Figure 3.</strong> A customized UI.
-</p>
-
-
-
-<h3 id="useractions">User Actions</h3>
-
-<p>The primary app UI supports four main actions on the action bar, four auxiliary actions
-on the overflow bar, and the <em>Return</em> action. You can use standard controls and customize
-the actions and icons, as shown in Figure 4.</p>
-
-<div class="auto-img-container-single">
-  <div class="auto-img-container">
-    <img class="auto-img-frame-cols" src="/auto/images/assets/00_frame.png" />
-    <img class="auto-img-shot-cols" src="/auto/images/assets/do_03_more.png" />
-  </div>
-  <p class="img-caption" style="margin-top:0px">
-    <strong>Figure 4.</strong> Custom extra actions.
-  </p>
-</div>
-
-<h3 id="drawertransitions">Drawer Transitions</h3>
-
-<p>For browse actions, the display shows the drawer transition as shown in Figure 5.</p>
-
-<div class="cols">
-<div class="auto-col-2">
-  <div class="auto-img-container-cols">
-    <img class="auto-img-frame-cols" src="{@docRoot}auto/images/assets/00_frame.png" />
-    <img class="auto-img-shot-cols" src="{@docRoot}auto/images/assets/do_06_gdrawer.png" />
-  </div>
-</div>
-<div class="auto-col-2">
-  <div class="auto-img-container-cols">
-    <img class="auto-img-frame-cols" src="{@docRoot}auto/images/assets/00_frame.png" />
-    <img class="auto-img-shot-cols" src="{@docRoot}auto/images/assets/do_04_mdrawer.png" />
-  </div>
-</div>
-</div>
-<p class="img-caption">
-  <strong>Figure 5.</strong> Generic and customized drawers.
-</p>
-
-<p>After the transition from the primary app UI to the drawer UI, the drawer
-appears on the center. The customized drawer UI shows the media containers and
-media files provided by the media service in your app. You can also customize drawers
-with icons for list items.</p>
-
-
-<h3 id="daynighttransitions">Day and Night Transitions</h3>
-
-<p>All the UIs support different color schemes for day and night.
-The platform provides the state (day or night) and makes adjustments automatically.</p>
-
-<div class="cols">
-<div class="auto-col-2">
-  <div class="auto-img-container-cols">
-    <img class="auto-img-frame-cols" src="{@docRoot}auto/images/assets/00_frame.png" />
-    <img class="auto-img-shot-cols" src="{@docRoot}auto/images/assets/do_02_music.png" />
-  </div>
-</div>
-<div class="auto-col-2">
-  <div class="auto-img-container-cols">
-    <img class="auto-img-frame-cols" src="{@docRoot}auto/images/assets/00_frame.png" />
-    <img class="auto-img-shot-cols" src="{@docRoot}auto/images/assets/do_02_music_night.png" />
-  </div>
-</div>
-</div>
-<p class="img-caption">
-  <strong>Figure 6.</strong> Day and night modes.
-</p>
-
-<h3 id="customizeui">Customizing UIs</h3>
-
-<p>To customize the UI, you provide the following app-specific resources and actions
-to the Android Auto media client:</p>
-
-<ul>
-<li><strong>Resources</strong> - App logo, app name, theme colors, and background images.</li>
-<li><strong>Actions</strong> - Multiple custom actions; for example: <em>Thumbs Up/Down</em>,
-<em>Favorite</em>, and <em>Bookmark</em>. These actions are app-specific.</li>
-</ul>
-
-<p>If provided, the media client automatically uses them in the UI.</p>
-
-
-<h2 id="devprocess">Development Process</h2>
-
-<p class="note"><strong>Note:</strong> When released, the Android Auto SDK will provide
-media service interfaces, an APK for handheld devices that simulates the Android Auto
-app, and other tools for Android Auto development.</p>
-
-<p>To create a media app for Android Auto, you include an Android service in your app
-that implements the media service interfaces provided by the Android Auto SDK. These
-interfaces define functionality for browsing and finding content, playing media,
-customizing the UI, and performing app-specific actions.</p>
-
-<p>The media service interfaces present the content library as a navigable tree and enable
-clients to play media, get album art, obtain theme resources for the UI, and
-invoke app-specific actions.</p>
-
-<p>You don’t have to create a new app for Android Auto: you can extend your existing
-Android app with implementations of the media service interfaces. Your service exposes
-your app’s media content, theme resources, and app-specific actions using the methods and
-data types specified by the media service interfaces. This simplifies the development
-cycle because:</p>
-
-<ul>
-<li>You do not have to maintain a separate project for Android Auto</li>
-<li>You can reuse existing functionality from your Android app</li>
-</ul>
-
-<p>The Android Auto client presents the customized UI to users and invokes the
-functionality from your service as needed. This has two additional advantages:</p>
-
-<ul>
-<li>Your app does not implement a UI for Android Auto</li>
-<li>Your app does not manage user interactions directly</li>
-</ul>
-
-<p>This also means that you do not have to worry about vehicle-specific hardware
-differences such as screen resolutions, software interfaces, knobs and touch
-controls.</p>
-
-
-<h2 id="emulator">Testing Your App on an Android Device</h2>
-
-<p>The Android Auto SDK includes an APK with a media client implementation, which is
-similar to those available in compatible vehicles. To test your app with this
-client:</p>
-
-<ol>
-<li>Get an Android device with a similar form factor to a dashboard screen (like a
-Nexus 7).</li>
-<li>Configure the device for Android development.</li>
-<li>Install the APK for the media client from the Android Auto SDK on the device.</li>
-<li>Install the APK for your app on the device.</li>
-<li>Open the media client app from the Android Auto SDK on the device.</li>
-<li>Select your app from the list of available services.</li>
-</ol>
-
-<p>The customized UI for your app appears on the client. You can navigate the content
-library and play media. If your app provides app-specific actions, these actions appear
-in the UI controls.</p>
-
-
-<h2 id="running">Running Your App on Android Auto</h2>
-
-<p>Media apps are available on the Google Play Store for compatible Android devices.
-When users connect their Android device to a compatible vehicle, the
-Android Auto media client shows a list of all the Android apps installed on the phone
-that implement the media service interfaces.</p>
-
-<p>When users select one of these apps, the Android Auto media client uses the app’s
-service to respond to user input and invoke the methods in the media service interfaces
-to build the UI, navigate the content library, and play media.</p>
-
-<div style="margin-bottom:40px"> </div>
-</div>
diff --git a/docs/html/design/auto/index.jd b/docs/html/design/auto/index.jd
index c970cac..e45bd36 100644
--- a/docs/html/design/auto/index.jd
+++ b/docs/html/design/auto/index.jd
@@ -1,35 +1,177 @@
-page.title=Android Auto
+page.title=Designing for Auto
+page.tags="design","Auto"
 @jd:body
 
-<style>
-.auto-img-container-cols {
-  position:relative;
-  margin-bottom:25px;
-  margin-top:25px;
-}
-.auto-img-frame-cols {
-  z-index:2;
-  position:relative;
-}
-.auto-img-shot-cols {
-  position:absolute;
-  top:5px;
-  left:2px;
-  z-index:1;
-}
-</style>
+<a class="notice-developers" href="{@docRoot}training/auto/index.html">
+  <div>
+    <h3>Developer Docs</h3>
+    <p>Building Apps for Auto</p>
+  </div>
+</a>
 
-<div class="auto-img-container-cols" style="float:right; margin:0 0 40px 40px;width:460px">
-  <img class="auto-img-frame-cols" src="/auto/images/assets/00_frame.png">
-  <img class="auto-img-shot-cols" src="/auto/images/assets/03_a_musict.png">
+<div class="sidebox-wrapper">
+<div class="sidebox">
+  <h2><strong>UI Guidelines</strong></h2>
+  <ul>
+  <li><a href="{@docRoot}shareables/auto/AndroidAuto-media-apps.pdf">
+    <strong>Auto Media Apps (PDF)</strong></a>
+  </li>
+  <li><a href="{@docRoot}shareables/auto/AndroidAuto-messaging-apps.pdf">
+    <strong>Auto Messaging Apps (PDF)</strong></a>
+  </li>
+  <li><a href="{@docRoot}shareables/auto/AndroidAuto-custom-colors.pdf">
+    <strong>Auto Color Customization (PDF)</strong></a>
+  </li>
+ </ul>
+</div>
 </div>
 
-<p>Android Auto is <strong>coming soon</strong> and brings apps to the car,
-integrating with the vehicle's input controls and display.</p>
+<p>Android Auto provide a standardized user interface and user interaction
+model that works across vehicles. As a designer, you do not
+need to worry about vehicle-specific hardware differences. This page
+describes some of the key screens that users will encounter in the
+Auto user interface. To dive deeper into how to design for
+the Auto user interface (UI), see the Auto UI guidelines in the sidebar.</p>
 
-<p>The future design guidelines provide templates that define the user interaction model for all apps and let you hook into a standard UI with touch and voice controls. The templates meet international best practices for reducing driver distraction while still letting you customize and brand them to properly deliver your content.</p>
+<p class="note"><strong>Important:</strong> Google takes driver distraction
+very seriously. There are specific design requirements your app must meet to
+qualify as an Auto app on Google Play. By adhering to these
+requirements, you can reduce the effort for building and testing your app. For
+more information, see <a href="{@docRoot}distribute/essentials/quality/auto.html">Auto App Quality</a>.</p>
 
-<p><a href="{@docRoot}auto/index.html">Learn more about Android Auto</a>.</p>
+<br>
+
+<h2 id="overview-screen">Overview Screen</h2>
+
+<p>When users first connect their Android device to the car, they are presented
+with the Overview screen. This screen displays contextual cards based on the
+user’s location, time of day, and so on. The user can also use this screen to view
+notifications from their messaging apps and select a message to send a response
+by voice input.</p>
+
+<div class="auto-img-container-single">
+  <div class="auto-img-container">
+    <img src="{@docRoot}auto/images/ui/gearhead_overview.png" alt="Overview screen" />
+  </div>
+  <p class="img-caption" style="margin-top:0px">
+    <strong>Figure 1.</strong> The Overview screen may show contextual cards and
+new messages.
+  </p>
+</div>
+
+<h2 id="launchapp">Audio App Launcher</h2>
+
+<p>Tapping on the headphones icon in the Activity Bar lets the
+  user see all audio apps installed on the user’s handheld device and select
+  one of them from a scrollable list.</p>
+
+<div class="auto-img-container-single">
+  <div class="auto-img-container">
+    <img src="{@docRoot}auto/images/ui/gearhead_lens_switching.png" alt="Launcher" />
+  </div>
+  <p class="img-caption" style="margin-top:0px">
+    <strong>Figure 2.</strong> The audio app launcher shows available audio apps.
+  </p>
+</div>
+
+<h2>Primary App UI</h2>
+
+<p>After the user selects an audio app, the display shows the primary app UI.
+Auto presents the app in a standardized UI, but you can customize
+this UI to show your own icons, app name, and background images
+(such as the album art).</p>
+
+<div class="auto-img-container-single">
+  <div class="auto-img-container">
+    <img src="{@docRoot}auto/images/ui/gearhead_generic_UI.png" alt="Generic audio app UI" />
+  </div>
+  <p class="img-caption" style="margin-top:0px">
+    <strong>Figure 3.</strong> Generic audio app UI.
+  </p>
+</div>
+
+<div class="auto-img-container-single">
+  <div class="auto-img-container">
+    <img src="{@docRoot}auto/images/ui/gearhead_custom_UI.png" alt="Customized audio app UI" />
+  </div>
+  <p class="img-caption" style="margin-top:0px">
+    <strong>Figure 4.</strong> Example of the Google Play Music app UI.
+  </p>
+</div>
+
+<h3 id="useractions">User Actions</h3>
+
+<p>The media control card in the primary app UI supports up to four main actions,
+four auxiliary actions on the overflow bar, and the <em>Return</em> action. You can
+use standard controls and customize the actions and icons.</p>
+
+<div class="auto-img-container-single">
+  <div class="auto-img-container">
+    <img src="{@docRoot}auto/images/ui/gearhead_custom_user_actions.png" alt="Customized user actions" />
+  </div>
+  <p class="img-caption" style="margin-top:0px">
+    <strong>Figure 5.</strong> Example of user actions in the Google Play Music app.
+  </p>
+</div>
+
+<h3 id="drawerlist">Drawer List</h3>
+
+<p>For browse actions, the display shows the drawer transition. After the
+transition from the primary app UI to the list UI, the drawer appears in the
+center. The customized list UI shows the media containers and the audio files
+provided by the media service in your app. You can also customize drawers with
+icons for list items.</p>
+
+<div class="auto-img-container-single">
+  <div class="auto-img-container">
+    <img src="{@docRoot}auto/images/ui/gearhead_drawer_generic.png"
+    alt="Generic drawers" style="border:3px solid black" />
+  </div>
+  <p class="img-caption" style="margin-top:0px">
+    <strong>Figure 6.</strong> Example of the drawer layout template with generic list items.
+  </p>
+</div>
+
+<div class="auto-img-container-single">
+  <div class="auto-img-container">
+    <img src="{@docRoot}auto/images/ui/gearhead_drawers_customized.png"
+    alt="Customized drawers" style="border:3px solid black" />
+  </div>
+  <p class="img-caption" style="margin-top:0px">
+    <strong>Figure 7.</strong> Example of the the drawer layout in the Google Play Music app.
+  </p>
+</div>
+
+
+<h2 id="daynighttransitions">Day and Night Transitions</h2>
+
+<p>All the UIs support different color schemes for day and night. The platform
+provides the state (day or night) and makes adjustments automatically.</p>
+
+<div class="auto-img-container-single">
+  <div class="auto-img-container">
+    <img src="{@docRoot}auto/images/ui/gearhead_day.png" alt="Audio app in day mode" />
+  </div>
+  <p class="img-caption" style="margin-top:0px">
+    <strong>Figure 8.</strong> Example of the Google Play Music app in day mode.
+  </p>
+</div>
+
+<div class="auto-img-container-single">
+  <div class="auto-img-container">
+    <img src="{@docRoot}auto/images/ui/gearhead_night.png" alt="Audio app in night mode" />
+  </div>
+  <p class="img-caption" style="margin-top:0px">
+    <strong>Figure 9.</strong> Example of the Google Play Music app in night mode.
+  </p>
+</div>
+
+<h3 class="rel-resources clearfloat">Related resources</h3>
+
+<div class="resource-widget resource-flow-layout col-13" data-query=
+"collection:design/auto/auto_ui_guidelines"
+data-sortorder="-timestamp" data-cardsizes="6x3" data-maxresults="6">
+</div>
 
 
 
diff --git a/docs/html/distribute/essentials/essentials_toc.cs b/docs/html/distribute/essentials/essentials_toc.cs
index a1c9575..985809a 100644
--- a/docs/html/distribute/essentials/essentials_toc.cs
+++ b/docs/html/distribute/essentials/essentials_toc.cs
@@ -22,6 +22,12 @@
           </a>
     </div>
   </li>
+    <li class="nav-section">
+    <div class="nav-section empty" style="font-weight:normal"><a href="<?cs var:toroot?>distribute/essentials/quality/auto.html">
+            <span class="en">Auto App Quality</span>
+          </a>
+    </div>
+  </li>
   <li class="nav-section">
     <div class="nav-section empty" style="font-weight:normal"><a href="<?cs var:toroot?>distribute/essentials/optimizing-your-app.html">
           <span class="en">Optimize Your App</span>
diff --git a/docs/html/distribute/essentials/quality/auto.jd b/docs/html/distribute/essentials/quality/auto.jd
new file mode 100644
index 0000000..757305e
--- /dev/null
+++ b/docs/html/distribute/essentials/quality/auto.jd
@@ -0,0 +1,411 @@
+
+page.title=Auto App Quality
+page.metaDescription=Auto apps integrate with the vehicle's input controls and display and minimize driver distraction to create a great experience.
+page.image=/distribute/images/gp-auto-quality.png
+@jd:body
+
+<div id="qv-wrapper"><div id="qv">
+<h2>Quality Criteria</h2>
+  <ol>
+    <li><a href="#core">Core App Quality</a></li>
+    <li><a href="#ux">Visual Design and Interaction</a></li>
+    <li><a href="#fn">Functionality</a></li>
+    <li><a href="#faq">Frequently Asked Questions</a></li>
+  </ol>
+
+  <h2>You Should Also Read</h2>
+  <ol>
+    <li><a href="{@docRoot}distribute/essentials/quality/core.html">
+      Core App Quality</a></li>
+    <li><a href="{@docRoot}distribute/essentials/optimizing-your-app.html">
+      Optimize Your App</a></li>
+    <li><a href="{@docRoot}shareables/auto/AndroidAuto-media-apps.pdf">Android Auto UX Guidelines
+      for Media Applications</a></li>
+    <li><a href="{@docRoot}shareables/auto/AndroidAuto-messaging-apps.pdf">Android Auto UX Guidelines
+      for Messaging Applications</a></li>
+  </ol>
+</div>
+</div>
+
+
+  <img src="{@docRoot}distribute/images/gp-auto-quality.png" style="width:480px;">
+
+
+<p>When designing support for Android Auto in your app, avoid driver distraction above all else.
+  Apps that work with the Auto user interface should minimize distractions faced by the driver
+  through best practices such as voice commands and very simple visual design.
+</p>
+
+<p>
+  Great auto experiences are predictive and predictable.  Apps that support Android Auto
+  should show timely information to the driver only when it is relevant, and use
+  simple, predictable patterns for common tasks.
+</p>
+
+<p class="caution">
+  <strong>Important:</strong> The criteria listed in this page apply to your app's user interface 
+  and behavior when running on devices connected to an Android Auto screen. Apps must meet these 
+  criteria to qualify as an Android Auto app on Google Play.
+</p>
+
+
+<div class="headerLine">
+  <h2 id="core">
+  Core App Quality
+  </h2>
+
+<p>
+ In addition to the Auto-specific criteria listed below, Auto apps should meet all relevant core app
+ quality criteria for the Android platform, as detailed in the
+  <a href="{@docRoot}distribute/essentials/quality/core.html">Core App Quality</a> criteria. Test
+  your app against those criteria to ensure that they meet Android standards for navigation and
+  design. Then test your app against all Auto-specific criteria, keeping in mind
+  that, when running on a device connected to Android auto, your app must meet the requirements
+  listed in this page.
+
+
+
+<div class="headerLine">
+  <h2 id="ux">
+  Visual Design and User Interaction
+  </h2>
+
+</div>
+
+<p>
+  These criteria ensure that your app follows critical design and interaction patterns
+  to ensure a consistent, intuitive, and enjoyable user experience on Android Auto. Many elements,
+  such as the navigation drawer, card backgrounds, fonts and icon colors, are set and rendered by
+  the system. Your own app-specific design elements must meet the following criteria.
+</p>
+
+<table>
+
+<tr>
+  <th style="width:2px;">
+    Type
+  </th>
+  <th style="width:54px;">
+    Test
+  </th>
+  <th>
+    Description
+  </th>
+</tr>
+
+<tr>
+  <td rowspan="4" id="safety">
+    Driver Attention
+  </td>
+
+  <td id="AU-MV">
+    AU-MV
+  </td>
+  <td>
+    <p style="margin-bottom:.5em;">
+      App does not display on the Auto screen animated elements such as animated graphics, games, video, or
+      progress bars.
+    </p>
+  </td>
+</tr>
+
+<tr>
+  <td id="AU-VA">
+    AU-VA
+  </td>
+  <td>
+    <p style="margin-bottom:.5em;">
+     App does not display any form of visual or text advertising on the Auto screen.  Only audio
+      ads are acceptable.
+    </p>
+  </td>
+</tr>
+
+<tr>
+  <td id="AU-IM">
+    AU-IM
+  </td>
+  <td>
+    <p style="margin-bottom:.5em;">
+    App elements do not display any images on the Auto screen. Exceptions include: app may display 
+    a single static image for
+    content context in the background of the consumption screen, such as album art, and app may 
+    display icons in the content navigation drawer.
+    </p>
+  </td>
+</tr>
+
+<tr>
+  <td id="AU-DS">
+    AU-DS
+  </td>
+  <td>
+    <p style="margin-bottom:.5em;">
+    App does not include any features that distract the driver.
+    </p>
+  </td>
+</tr>
+
+
+
+<tr>
+  <td rowspan="4" id="layout">
+    Layout
+  </td>
+
+<tr>
+  <td id="AU-SC">
+    AU-SC
+  </td>
+  <td>
+    <p style="margin-bottom:.5em;">
+     App does not display automatically scrolling text.
+    </p>
+  </td>
+</tr>
+
+
+<tr>
+  <td id="AU-FT">
+    AU-FT
+  </td>
+  <td>
+    <p style="margin-bottom:.5em;">
+     App displays all strings using the default Roboto fonts in two approved sizes.
+    </p>
+  </td>
+</tr>
+
+<tr>
+  <td id="AU-ST">
+    AU-ST
+  </td>
+  <td>
+    <p style="margin-bottom:.5em;">
+     App does not display any individual string longer than 120 characters.
+    </p>
+  </td>
+</tr>
+
+<tr>
+  <td id="contrast">
+    Visual Contrast
+  </td>
+
+  <td id="AU-NM">
+    AU-NM
+  </td>
+  <td>
+    <p style="margin-bottom:.5em;">
+     App supports night mode, rendering light text and controls on a dark background.
+    </p>
+  </td>
+</tr>
+
+
+<tr>
+  <td rowspan="2" id="interaction">
+    Interaction
+  </td>
+
+  <td id="AU-VC">
+    AU-VC
+  </td>
+  <td>
+    <p style="margin-bottom:.5em;">
+     App must support voice commands.
+    </p>
+  </td>
+</tr>
+
+<tr>
+  <td id="AU-AB">
+    AU-AB
+  </td>
+  <td>
+    <p style="margin-bottom:.5em;">
+      App-specific buttons respond to user actions with no more than a two-second delay.
+    </p>
+  </td>
+</tr>
+
+</table>
+
+
+<h3 class="rel-resources clearfloat">Related resources</h3>
+
+<div class="resource-widget resource-flow-layout col-13" data-query=
+"collection:distribute/essentials/autoqualityguidelines/visualdesign"
+data-sortorder="-timestamp" data-cardsizes="9x3" data-maxresults="6">
+</div>
+
+
+
+<div class="headerLine">
+  <h2 id="fn">
+  Functionality
+  </h2>
+
+
+</div>
+
+<p>
+  These criteria ensure that your app is configured correctly and provides expected
+  functional behavior.
+</p>
+
+
+<table>
+<tr>
+  <th style="width:2px;">
+    Type
+  </th>
+  <th style="width:54px;">
+    Test
+  </th>
+  <th>
+    Description
+  </th>
+</tr>
+
+<tr>
+  <td rowspan="2" id="general">
+   General
+  </td>
+
+  <td id="AU-RL">
+    AU-RL
+  </td>
+  <td>
+    <p style="margin-bottom:.5em;">
+     When the app is relaunched from the home screen, the app restores the app state as closely as
+     possible to the previous state.
+    </p>
+  </td>
+</tr>
+
+
+</tr>
+  <td id="AU-SS">
+    AU-SS
+  </td>
+  <td>
+    <p style="margin-bottom:.5em;">
+     No tasks in the app take more than six steps to complete.
+    </p>
+  </td>
+</tr>
+
+
+<tr>
+  <td rowspan="2" id="media">
+    Media
+  </td>
+
+
+  <td id="AU-PA">
+    AU-PA
+  </td>
+  <td>
+    <p style="margin-bottom:.5em;">
+     App has no more than four primary actions plus one optional action overflow toggle (or five if
+     no action overflow is used). For more information, see details on the media control card in the
+     <a href="{@docRoot}shareables/auto/AndroidAuto-media-apps.pdf">Android Auto UX Guidelines
+      for Media Applications</a>.
+    </p>
+  </td>
+</tr>
+
+<tr>
+  <td id="AU-SA">
+    AU-SA
+  </td>
+  <td>
+    <p style="margin-bottom:.5em;">
+     App has no more than four optional secondary actions plus one action overflow toggle. For more
+     information, see details on the media control card in the
+     <a href="{@docRoot}shareables/auto/AndroidAuto-media-apps.pdf">Android Auto UX Guidelines
+      for Media Applications</a>.
+    </p>
+  </td>
+</tr>
+
+
+<tr>
+  <td rowspan="2" id="notifications">
+    Notifications
+  </td>
+
+  <td id="AU-NA">
+    AU-NA
+  </td>
+  <td>
+    <p style="margin-bottom:.5em;">
+      App does not present advertisements through notifications.
+    </p>
+  </td>
+</tr>
+
+<tr>
+  <td id="AU-NT">
+    AU-NT
+  </td>
+  <td>
+    <p style="margin-bottom:.5em;">
+     App displays notifications only when relevant to the driver’s needs.
+   </p>
+   <p>
+    Examples:<br />
+    Good: Notifying the user that a new message has arrived.<br />
+    Bad: Notifying the user about a new album release.
+    </p>
+  </td>
+</tr>
+
+</table>
+
+<!--
+<h3 class="rel-resources clearfloat">Related resources</h3>
+
+<div class="resource-widget resource-flow-layout col-13" data-query=
+"collection:distribute/essentials/autoqualityguidelines/functionality"
+data-sortorder="-timestamp" data-cardsizes="9x3" data-maxresults="6">
+</div>
+-->
+
+<div class="headerLine">
+  <h2 id="faq">
+  Frequently Asked Questions
+  </h2>
+</div>
+
+<p style="margin-top:30px;">
+  <strong>After I submit my app, how will find out if my app does not meet all
+    the requirements for Android Auto?</strong>
+</p>
+<p>If you are planning to develop apps for Auto, you are encouraged to begin enabling and testing
+  your apps now. However, Auto-enabled apps cannot be published at this time. Join the
+ <a href="http://g.co/AndroidAutoDev" class="external-link">Auto
+ Developers Google+ community</a> for updates on when you will be able to submit
+ your Auto-enabled apps.</p>
+</p>
+
+
+<p style="margin-top:30px;">
+  <strong>My app targets more than just Android Auto. If my app does not meet the Auto
+  requirements, will my new or updated app still appear on Google Play for phones and
+  tablets?</strong>
+</p>
+<p>
+  No. When Google begins the approval process, your auto app will undergo a driver safety
+  review, and will not be
+  available for distribution until the app is approved. Because this is the same APK as
+  for phones and tablets, your Play Store updates for those devices will not be available until the
+  Auto approval process is complete.  
+</p>
+
+<p class="caution">
+  <strong>Important:</strong> Due to this restriction, you should not use your production APK
+  for Auto support prototyping. 
+</p>
+
diff --git a/docs/html/distribute/images/gp-auto-quality.png b/docs/html/distribute/images/gp-auto-quality.png
new file mode 100644
index 0000000..d322849
--- /dev/null
+++ b/docs/html/distribute/images/gp-auto-quality.png
Binary files differ
diff --git a/docs/html/guide/components/intents-common.jd b/docs/html/guide/components/intents-common.jd
index d4b033a..adba1cd 100644
--- a/docs/html/guide/components/intents-common.jd
+++ b/docs/html/guide/components/intents-common.jd
@@ -2282,6 +2282,14 @@
     <li>"search for cat videos on myvideoapp"</li>
   </ul>
 </div>
+<!-- Video box -->
+<a class="notice-developers-video"
+   href="https://www.youtube.com/watch?v=PS1FbB5qWEI">
+<div>
+    <h3>Video</h3>
+    <p>Voice search in your app</p>
+</div>
+</a>
 
 <p>To support search within the context of your app, declare an intent filter in your app with
 the <code>SEARCH_ACTION</code> action, as shown in the example intent filter below.</p>
diff --git a/docs/html/jd_collections.js b/docs/html/jd_collections.js
index a38b80b..a843350 100644
--- a/docs/html/jd_collections.js
+++ b/docs/html/jd_collections.js
@@ -68,8 +68,8 @@
       "distribute/essentials/quality/tablets.html",
       "distribute/essentials/quality/tv.html",
       "distribute/essentials/quality/wear.html",
-      "https://developers.google.com/edu/guidelines",
-      "distribute/essentials/optimizing-your-app.html"
+      "distribute/essentials/quality/auto.html",
+      "https://developers.google.com/edu/guidelines"
     ]
   },
   "distribute/users": {
@@ -348,6 +348,13 @@
       "training/wearables/notifications/voice-input.html"
     ]
   },
+    "distribute/essentials/autoqualityguidelines/visualdesign": {
+    "title": "",
+    "resources": [
+      "training/auto/messaging/index.html",
+      "training/auto/start/index.html"
+    ]
+  },
   "distribute/essentials/core/performance": {
     "title": "",
     "resources": [
@@ -787,6 +794,14 @@
       "shareables/distribute/play_dev_guide_secrets_en.pdf"
     ]
   },
+  "design/auto/auto_ui_guidelines": {
+    "title": "",
+    "resources": [
+      "shareables/auto/AndroidAuto-media-apps.pdf",
+      "shareables/auto/AndroidAuto-messaging-apps.pdf",
+      "shareables/auto/AndroidAuto-custom-colors.pdf"
+    ]
+  },
   "distribute/stories/games": {
     "title": "",
     "resources": [
diff --git a/docs/html/jd_extras.js b/docs/html/jd_extras.js
index 36f26e8..a86ffeb 100644
--- a/docs/html/jd_extras.js
+++ b/docs/html/jd_extras.js
@@ -1407,5 +1407,44 @@
     "keywords": ["distribute"],
     "type": "PDF DOWNLOAD (11MB)",
     "titleFriendly": ""
+  },
+  {
+    "lang": "en",
+    "group": "",
+    "tags": [],
+    "url": "shareables/auto/AndroidAuto-media-apps.pdf",
+    "timestamp": null,
+    "image": "auto/images/assets/icons/media_app_playback.png",
+    "title": "Android Auto Media Apps UI Guidelines",
+    "summary": "Guidelines for designing audio apps that work with Auto. ",
+    "keywords": ["design", "Auto", "Automotive"],
+    "type": "PDF DOWNLOAD (1.1MB)",
+    "titleFriendly": ""
+  },
+  {
+    "lang": "en",
+    "group": "",
+    "tags": [],
+    "url": "shareables/auto/AndroidAuto-messaging-apps.pdf",
+    "timestamp": null,
+    "image": "auto/images/assets/icons/messaging_app_notifications.png",
+    "title": "Android Auto Messaging Apps UI Guidelines",
+    "summary": "Guidelines for designing messaging apps that work with Auto. ",
+    "keywords": ["design", "Auto", "Automotive"],
+    "type": "PDF DOWNLOAD (628KB)",
+    "titleFriendly": ""
+  },
+  {
+    "lang": "en",
+    "group": "",
+    "tags": [],
+    "url": "shareables/auto/AndroidAuto-custom-colors.pdf",
+    "timestamp": null,
+    "image": "auto/images/assets/icons/auto_app_in_simulator.png",
+    "title": "Android Auto Color Customization UI Guidelines",
+    "summary": "Guidelines for color-customizing apps that work with Auto. ",
+    "keywords": ["design", "Auto", "Automotive"],
+    "type": "PDF DOWNLOAD (779KB)",
+    "titleFriendly": ""
   }
-]);
+]);
\ No newline at end of file
diff --git a/docs/html/training/auto/audio/index.jd b/docs/html/training/auto/audio/index.jd
new file mode 100644
index 0000000..aa25769
--- /dev/null
+++ b/docs/html/training/auto/audio/index.jd
@@ -0,0 +1,475 @@
+page.title=Providing Audio Playback for Auto
+page.tags="auto", "car", "automotive", "audio"
+page.article=true
+
+@jd:body
+
+<div id="tb-wrapper">
+<div id="tb">
+  <h2>Dependencies and Prerequisites</h2>
+  <ul>
+    <li>Android 5.0 (API level 21) or higher</li>
+  </ul>
+
+    <h2>This class teaches you how to</h2>
+
+    <ol>
+      <li><a href="#overview">Provide Audio Services</a></li>
+      <li><a href="#config_manifest">Configure Your Manifest</a></li>
+      <li><a href="#implement_browser">Build a Browser Service</a></li>
+      <li><a href="#implement_callback">Implement Play Controls</a></li>
+    </ol>
+
+    <h2>Related Samples</h2>
+
+    <ul>
+      <li><a href="{@docRoot}samples/MediaBrowserService/index.html">
+        MediaBrowserService</a></li>
+    </ul>
+
+    <h2>See Also</h2>
+
+    <ul>
+      <li>
+        <a href="{@docRoot}shareables/auto/AndroidAuto-media-apps.pdf">
+              User Experience Guidelines: Media Apps</a>
+      </li>
+      <li><a href="{@docRoot}training/managing-audio/index.html">Managing Audio
+        Playback</a></li>
+      <li><a href="{@docRoot}guide/topics/media/exoplayer.html">ExoPlayer</a>
+      </li>
+    </ul>
+
+</div>
+</div>
+
+<a class="notice-developers-video wide"
+href="https://www.youtube.com/watch?v=Q96Sw6v4ULg">
+<div>
+    <h3>Video</h3>
+    <p>Devbytes: Android Auto Audio</p>
+</div>
+</a>
+
+<p>
+  Drivers want to access their music and other audio content on the road. Audio books, podcasts,
+  sports commentary, and recorded talks can make a long trip educational, inspirational, and
+  enjoyable. The Android framework allows you to extend your audio app so users can listen to their
+  favorite tunes and audio content using a simpler, safer user interface.
+</p>
+
+<p>
+  Apps running on mobile devices with Android 5.0 or higher can provide audio services for
+  dashboard systems running Android Auto. By configuring your app with a few settings and
+  implementing a service for accessing music tracks, you can enable Auto devices to discover your
+  app and provide a browse and playback interface for your app's audio content.
+</p>
+
+<p>
+  This class assumes that you have built an app that plays audio through an Android device's
+  integrated speakers or connected headphones. It describes how to extend your app to allow Auto
+  devices to browse your content listings and play it through a car stereo system.
+</p>
+
+
+<h2 id="overview">Provide Audio Services</h2>
+
+<p>
+  Audio apps do not directly control a car dashboard device that runs Android Auto. When the user
+  connects an Android mobile device into a dashboard system, Android Auto discovers your app through
+  manifest entries that indicate what audio services your app can provide. The dashboard system
+  displays a launcher icon for your app as a music provider and the user can choose to use your
+  app's services. If the user launches your app, the Auto device queries your app to see what
+  content is available, displays your content items to the user, and sends requests to your app to
+  control playback with actions such as play, pause, or skip track.
+</p>
+
+<p>To enable your app to provide audio content for Auto devices, you need to:
+</p>
+
+<ul>
+  <li>Configure your app manifest to do the following:</li>
+    <ul>
+      <li>Declare that your app can provide audio content for Auto devices.</li>
+      <li>Define a service that provides a browsable list of your audio tracks.</li>
+    </ul>
+  </li>
+  <li>Build a service that provides audio track listing information extending
+    {@link android.service.media.MediaBrowserService}.</li>
+  <li>Register a {@link android.media.session.MediaSession} object and implement the
+    {@link android.media.session.MediaSession.Callback} object to enable playback controls.</li>
+</ul>
+
+
+<h2 id="config_manifest">Configure Your Manifest</h2>
+
+<p>
+  When a user plugs an Android mobile device into a dashboard device running Auto, the system
+  requests a list of installed apps that include <a href=
+  "{@docRoot}guide/topics/manifest/manifest-intro.html">app manifest</a> entries to indicate they
+  support services for Auto devices and how to access them. This section describes how to configure
+  your app manifest to indicate your app supports audio services for Auto devices, and allow
+  dashboard system to connect with your app.
+</p>
+
+
+<h3 id="manifest-car-app">Declare Auto audio support</h3>
+
+<p>
+  You indicate that your app supports cars capabilities using the following manifest entry:
+</p>
+
+<pre>
+&lt;application&gt;
+    ...
+    &lt;meta-data android:name="com.google.android.gms.car.application"
+        android:resource="&#64;xml/automotive_app_desc"/&gt;
+    ...
+&lt;application&gt;
+</pre>
+
+<p>
+  This manifest entry refers to a secondary XML file, where you declare what Auto capabilities your
+  app supports. For an app that supports audio for cars, add an XML file to the {@code res/xml/}
+  resources directory as {@code automotive_app_desc.xml}, with the following content:
+</p>
+
+<pre>
+&lt;automotiveApp&gt;
+    &lt;uses name="media"/&gt;
+&lt;/automotiveApp&gt;
+</pre>
+
+<p>
+  For more information about declaring capabilities for Auto devices, see <a href=
+  "{@docRoot}training/auto/start/index.html#auto-metadata">Getting Started with Auto</a>.
+</p>
+
+
+<h3 id="manifest-service">Declare your media browser service</h3>
+
+<p>
+  Auto devices expect to connect to a service in order to browse audio track
+  listings. You declare this service in your manifest to allow the dashboard system to discover
+  this service and connect to your app.
+</p>
+
+<p>The following code example shows how to declare this listing browser service in your manifest:</p>
+
+<pre>
+&lt;application&gt;
+    ...
+    &lt;service android:name="<em>.MyMediaBrowserService</em>"
+                android:exported="true"&gt;
+        &lt;intent-filter&gt;
+            <strong>&lt;action android:name=</strong>
+                <strong>"android.media.browse.MediaBrowserService"/&gt;</strong>
+        &lt;/intent-filter&gt;
+    &lt;/service&gt;
+    ...
+&lt;application&gt;
+</pre>
+
+<p>
+  The service your app provides for browsing audio tracks must extend the
+  {@link android.service.media.MediaBrowserService}. The implementation of this service is discussed
+  in the <a href="#implement_browser">Build a Browser Service</a> section.
+</p>
+
+<p class="note">
+  <strong>Note:</strong> Other clients can also contact your app's browser service aside from Auto
+  devices. These media clients might be other apps on a user's mobile device, or they might be other
+  remote clients.
+</p>
+
+<h3 id="manifest-icon">Specify a notification icon</h3>
+
+<p>
+  The Auto user interface shows notifications about your audio app to the user during the course
+  of operation. For example, if the user has a navigation app running, and one song finishes
+  and a new song starts, the Auto device shows the user a notification to indicate the change with
+  an icon from your app. You can specify an icon that is used to represent your app for these
+  notifications using the following manifest declaration:
+</p>
+
+<pre>
+&lt;application&gt;
+    ...
+    &lt;meta-data android:name="com.google.android.gms.car.notification.SmallIcon"
+        android:resource="&#64;drawable/ic_notification" /&gt;
+    ...
+&lt;application&gt;
+</pre>
+
+<p class="note"><strong>Note:</strong> The icon you provide should have transparency enabled, so the
+icon's background gets filled in with the app's primary color.</p>
+
+
+<h2 id="implement_browser">Build a Browser Service</h2>
+
+<p>Auto devices interact with your app by contacting its implementation of a
+  {@link android.service.media.MediaBrowserService}, which
+you declare in your app manifest. This service allows Auto devices to find out what content your app
+provides. Connected Auto devices can also query your app's media browser service to contact the
+{@link android.media.session.MediaSession} provided by your app, which handles content playback
+commands.</p>
+
+<p>You create a media browser service by extending the
+{@link android.service.media.MediaBrowserService} class.
+Connected Auto devices can contact your service to do the following:</p>
+
+<ul>
+  <li>Browse your app's content hierarchy, in order to present a menu to the
+    user</li>
+  <li>Get the token for your app's {@link android.media.session.MediaSession}
+    object, in order to control audio playback</li>
+</ul>
+
+
+<h3 id="browser_workflow">Media browser service workflow</h3>
+
+<ol>
+
+<li>When your app's audio services are requested by a user through a connected Auto device, the
+dashboard system contacts your app's media browser service.
+In your implementation of the {@link android.service.media.MediaBrowserService#onCreate()
+onCreate()} method, you must create and register a {@link
+android.media.session.MediaSession} object and its callback object.</li>
+
+<li>The Auto device calls the browser service's {@link
+android.service.media.MediaBrowserService#onGetRoot onGetRoot()} method to get the top node of
+your content hierarchy. The node retrieved by this call is not used as a menu item, it is only used
+to retrieve its child nodes, which are subsequently displayed as the top menu items.
+</li>
+
+<li>Auto invokes the {@link android.service.media.MediaBrowserService#onLoadChildren
+onLoadChildren()} method to get the children of the root node, and uses this information to
+present a menu to the user.</li>
+
+<li>If the user selects a submenu, Auto invokes
+{@link android.service.media.MediaBrowserService#onLoadChildren
+onLoadChildren()} again to retrieve the child nodes of the selected menu item.</li>
+
+<li>If the user begins playback, Auto invokes the appropriate media session
+callback method to perform that action. For more information, see the section about how to
+<a href="#implement_callback">Implement Playback Controls</a>. </li>
+
+</ol>
+
+
+<h3 id="build_hierarchy">Building your content hierarchy</h3>
+
+<p>Auto devices acting as audio clients call your app's {@link
+android.service.media.MediaBrowserService} to find out what content you have
+available. You need to implement two methods in your browser service to support
+this: {@link android.service.media.MediaBrowserService#onGetRoot
+onGetRoot()} and {@link
+android.service.media.MediaBrowserService#onLoadChildren
+onLoadChildren()}.</p>
+
+<p>Each node in your content hierarchy is represented by a  {@link
+android.media.browse.MediaBrowser.MediaItem} object. Each of these objects is
+identified by a unique ID string. The client treats these ID strings as
+opaque tokens. When a client wants to browse to a submenu, or play a content
+item, it passes the ID token. Your app is responsible for associating the ID
+token with the appropriate menu node or content item.</p>
+
+<p class="note"><strong>Note:</strong> You should consider providing different content
+hierarchies depending on what client is making the query. In particular, Auto
+applications have strict limits on how large a menu they can display. This is
+intended to prevent distracting the driver, and to make it easy for the driver
+to operate the app via voice commands. For more information on the Auto user
+experience restrictions, see the <a href="{@docRoot}shareables/auto/AndroidAuto-media-apps.pdf">
+Auto Media Apps</a> guidelines.</p>
+
+<p>Your implementation of {@link android.service.media.MediaBrowserService#onGetRoot
+onGetRoot()} returns information about the root node of the menu
+hierarchy. This root node is the parent of the top items your browse hierarchy.
+The method is passed information about the calling client. You can use this
+information to decide if the client should have access to your content at all.
+For example, if you want to limit your app's content to a list of approved
+clients, you can compare the passed {@code clientPackageName} to your whitelist.
+If the caller isn't an approved package, you can return null to deny access to
+your content.</p>
+
+<p>A typical implementation of {@link
+android.service.media.MediaBrowserService#onGetRoot onGetRoot()} might
+look like this:</p>
+
+<pre>
+&#64;Override
+public BrowserRoot onGetRoot(String clientPackageName, int clientUid,
+    Bundle rootHints) {
+
+    // To ensure you are not allowing any arbitrary app to browse your app's
+    // contents, you need to check the origin:
+    if (!PackageValidator.isCallerAllowed(this, clientPackageName, clientUid)) {
+        // If the request comes from an untrusted package, return null.
+        // No further calls will be made to other media browsing methods.
+        LogHelper.w(TAG, "OnGetRoot: IGNORING request from untrusted package "
+                + clientPackageName);
+        return null;
+    }
+    if (ANDROID_AUTO_PACKAGE_NAME.equals(clientPackageName)) {
+        // Optional: if your app needs to adapt ads, music library or anything
+        // else that needs to run differently when connected to the car, this
+        // is where you should handle it.
+    }
+    return new BrowserRoot(MEDIA_ID_ROOT, null);
+}
+</pre>
+
+<p>
+  The Auto device client builds the top-level menu by calling {@link
+  android.service.media.MediaBrowserService#onLoadChildren onLoadChildren()}
+  with the root node object and getting it's children. The client builds
+  submenus by calling the same method with other child nodes. The following
+  example code shows a simple implementation of {@link
+  android.service.media.MediaBrowserService#onLoadChildren onLoadChildren()} method:
+</p>
+
+<pre>
+&#64;Override
+public void onLoadChildren(final String parentMediaId,
+    final Result&lt;List&lt;MediaItem&gt;&gt; result) {
+
+    // Assume for example that the music catalog is already loaded/cached.
+
+    List&lt;MediaBrowser.MediaItem&gt; mediaItems = new ArrayList&lt;&gt;();
+
+    // Check if this is the root menu:
+    if (MEDIA_BROWSER_ROOT.equals(parentMediaId)) {
+
+        // build the MediaItem objects for the top level,
+        // and put them in the &lt;result&gt; list
+    } else {
+
+        // examine the passed parentMediaId to see which submenu we're at,
+        // and put the children of that menu in the &lt;result&gt; list
+    }
+}
+</pre>
+
+
+<h2 id="implement_callback">Enable Playback Control</h2>
+
+<p>
+  Auto devices use {@link android.media.session.MediaSession} objects to pass playback control
+  commands to an app that is providing audio services. Your audio app must create an instance of
+  this object to pass to the dashboard device and implement callback methods to enable remote
+  control of audio playback.
+</p>
+
+<h3 id="registering_mediasession">Register a media session</h3>
+
+<p>An Auto device using your app as audio service needs to obtain a {@link
+android.media.session.MediaSession} object from your app. The Auto device uses the session object
+to send playback commands requested by the Auto user back to your app.</p>
+
+<p>When you initialize your browser service, you register that session object with your {@link
+android.service.media.MediaBrowserService} by calling the {@link
+android.service.media.MediaBrowserService#setSessionToken setSessionToken()} method. This step
+allows clients such as an Auto device to retrieve that object by calling your browser service's
+{@link android.service.media.MediaBrowserService#getSessionToken getSessionToken()} method.</p>
+
+<p>In your browser service's {@link
+android.service.media.MediaBrowserService#onCreate() onCreate()} method,
+create a {@link android.media.session.MediaSession}. You can then query
+the {@link android.media.session.MediaSession} to get its token, and register
+the token with your browser service:</p>
+
+<pre>
+public void onCreate() {
+        super.onCreate();
+
+    ...
+    // Start a new MediaSession
+    MediaSession mSession = new MediaSession(this, "session tag");
+    setSessionToken(mSession.getSessionToken());
+
+    // Set a callback object to handle play control requests, which
+    // implements MediaSession.Callback
+    mSession.setCallback(new MyMediaSessionCallback());
+
+    ...
+</pre>
+
+<p>
+  When you create the media session object, you set a callback object that is used to handle
+  playback control requests. You create this callback object by providing an implementation of the
+  {@link android.media.session.MediaSession.Callback} class for your app. The next section
+  discusses how to implement this object.
+</p>
+
+
+<h3 id="playback-commands">Implement play commands</h3>
+
+<p>When an Auto device requests playback of an audio track from your app, it uses the
+{@link android.media.session.MediaSession.Callback} class from your app's
+{@link android.media.session.MediaSession} object, which it obtained from your app's
+media browse service. When an Auto user wants to play content or control content playback,
+such as pausing play or skipping to the next track, Auto invokes one
+of the callback object's methods.</p>
+
+<p>To handle content playback, your app must extend the abstract {@link
+android.media.session.MediaSession.Callback} class and implement the methods
+that your app supports. The most important callback methods are as follows:</p>
+
+<dl>
+
+<dt>{@link android.media.session.MediaSession.Callback#onPlay onPlay()}</dt>
+<dd>Invoked if the user chooses play without choosing a specific item. Your
+app should play its default content. If playback was paused with
+{@link android.media.session.MediaSession.Callback#onPause onPause()}, your
+app should resume playback.</dd>
+
+<dt>{@link android.media.session.MediaSession.Callback#onPlayFromMediaId
+onPlayFromMediaId()}</dt>
+<dd>Invoked when the user chooses to play a specific item. The method is passed
+the item's media ID, which you assigned to the item in the content
+hierarchy.</dd>
+
+<dt>{@link android.media.session.MediaSession.Callback#onPlayFromSearch
+onPlayFromSearch()}</dt>
+<dd>Invoked when the user chooses to play from a search query. The app should
+make an appropriate choice based on the passed search string.</dd>
+
+<dt>{@link android.media.session.MediaSession.Callback#onPause onPause()}</dt>
+<dd>Pause playback.</dd>
+
+<dt>{@link android.media.session.MediaSession.Callback#onSkipToNext
+onSkipToNext()}</dt>
+<dd>Skip to the next item.</dd>
+
+<dt>{@link android.media.session.MediaSession.Callback#onSkipToPrevious
+onSkipToPrevious()}</dt>
+<dd>Skip to the previous item.</dd>
+
+<dt>{@link android.media.session.MediaSession.Callback#onStop onStop()}</dt>
+<dd>Stop playback.</dd>
+
+</dl>
+
+<p>Your app should override these methods to provide any desired functionality.
+In some cases you might not implement a method if it is not supported by your app.
+For example, if your app plays a live stream (such as a sports
+broadcast), the skip to next function might not make sense. In that case, you
+could simply use the default implementation of
+{@link android.media.session.MediaSession.Callback#onSkipToNext
+onSkipToNext()}.</p>
+
+<p>When your app receives a request to play content, it should play audio the same way it
+would in a non-Auto situation (as if the user was listening through a device speaker
+or connected headphones). The audio content is automatically sent to the dashboard system
+to be played over the car's speakers.</p>
+
+<p>For more information about playing audio content, see
+<a href="{@docRoot}guide/topics/media/mediaplayer.html">Media Playback</a>,
+<a href="{@docRoot}training/managing-audio/index.html">Managing Audio Playback</a>, and
+<a href="{@docRoot}guide/topics/media/exoplayer.html">ExoPlayer</a>.
+
+
+(for example, by using a {@link
+android.media.MediaPlayer} or <a
+href="{@docRoot}guide/topics/media/exoplayer.html">ExoPlayer</a>). If the phone
+is connected to an Auto device, .</p>
diff --git a/docs/html/training/auto/index.jd b/docs/html/training/auto/index.jd
new file mode 100644
index 0000000..26eee32
--- /dev/null
+++ b/docs/html/training/auto/index.jd
@@ -0,0 +1,9 @@
+page.title=Building Apps for Auto
+page.trainingcourse=true
+page.metaDescription=Starting point for building apps for Auto, with guidelines, information, and examples.
+page.image=design/tv/images/focus.png
+@jd:body
+
+
+
+<p>These classes teach you how to build and extend apps to work with Auto devices.</p>
\ No newline at end of file
diff --git a/docs/html/training/auto/messaging/index.jd b/docs/html/training/auto/messaging/index.jd
new file mode 100644
index 0000000..c51ad7e
--- /dev/null
+++ b/docs/html/training/auto/messaging/index.jd
@@ -0,0 +1,533 @@
+page.title=Providing Messaging for Auto
+page.tags="auto", "car", "automotive", "messaging"
+page.article=true
+
+@jd:body
+
+<div id="tb-wrapper">
+<div id="tb">
+  <h2>Dependencies and Prerequisites</h2>
+  <ul>
+    <li>Android 5.0 (API level 21) or higher</li>
+  </ul>
+
+    <h2>This class teaches you to:</h2>
+
+    <ul>
+      <li><a href="#overview">Provide Messaging Services</a></li>
+      <li><a href="#manifest">Configure Your Manifest</a></li>
+      <li><a href="#support-lib">Import Support Library for Messaging</a></li>
+      <li><a href="#messaging">Notify Users of Messages</a></li>
+      <li><a href="#handle_actions">Handle User Actions</a></li>
+    </ul>
+
+    <h2>Related Samples</h2>
+
+    <ul>
+      <li><a href="{@docRoot}samples/MessagingService/index.html">
+        MessagingService</a></li>
+    </ul>
+
+    <h2>See Also</h2>
+
+    <ul>
+      <li><a href="{@docRoot}shareables/auto/AndroidAuto-messaging-apps.pdf">
+        User Experience Guidelines: Messaging Apps</a></li>
+      <li><a href="{@docRoot}guide/topics/ui/notifiers/notifications.html">
+        Notifications</a></li>
+    </ul>
+</div>
+</div>
+
+<a class="notice-developers-video wide"
+    href="https://www.youtube.com/watch?v=gSVLuaOTIPk">
+<div>
+    <h3>Video</h3>
+    <p>DevBytes: Android Auto Messaging</p>
+</div>
+</a>
+
+<p>
+  Staying connected through text messages is important to many drivers. Chat apps can let users
+  know if a child need to be picked up, or if a dinner location has been changed. Apps that provide
+  sports information might tell the user who just won the big game, and let the user ask questions
+  about other games being played. The Android framework enables messaging apps to extend their
+  services into car dashboards using a standard user interface that lets drivers keep their eyes
+  on the road.
+</p>
+
+<p>
+  Apps that support messaging can be extended to pass messaging notifications to Auto
+  dashboard systems, alerting them to new messages and allowing them to respond. You can configure
+  your messaging app to provide these services when an Android mobile device with your app
+  installed is connected to an Auto dashboard. Once connected, your app can provide text
+  information to users and allow them to respond. The Auto dashboard system handles displaying the
+  notification and the interface for replies.
+</p>
+
+<p>
+  This lesson assumes that you have built an app that displays messages to the user and receive the
+  user's replies, such as a chat app. It shows you how to extend your app to hand those messages
+  off to an Auto device for display and replies.
+</p>
+
+
+<h2 id="overview">Provide Messaging Services</h2>
+
+<p>
+  Messaging apps do not run directly on the Android dashboard hardware. They are installed on
+  separate, Android mobile device. When the mobile device is plugged into a dashboard,
+  the installed messaging apps can offer services for viewing and responding to messages
+  through the Auto user interface.
+</p>
+
+<p>To enable your app to provide messaging services for Auto devices:</p>
+
+<ul>
+  <li>Configure your app manifest to indicate that your app provides messaging services which are
+  compatible with Android Auto dashboard devices.
+  </li>
+  <li>Build and send a specific type of <a href=
+  "{@docRoot}guide/topics/ui/notifiers/notifications.html">notification</a> for display on Auto
+  devices.
+  </li>
+  <li>Configure your app to receive {@link android.content.Intent} objects that indicate a user
+    has read or replied to a message.
+</ul>
+
+
+<h2 id="#manifest">Configure Your Manifest</h2>
+
+<p>
+  You configure your app <a href="{@docRoot}guide/topics/manifest/manifest-intro.html">manifest</a>
+  to indicate that it supports messaging services for Auto devices and handle message actions. This
+  section describes what changes to make to your manifest to support messaging for Auto devices.
+</p>
+
+
+<h3 id="manifest-messaging">Declare Auto messaging support</h3>
+
+<p>
+  When a user connects a Android mobile device to a dashboard running Android, the dashboard
+  device looks for apps that declare support for vehicle services, such as messaging. You indicate
+  that your app supports cars capabilities using the following manifest entry:
+</p>
+
+<pre>
+&lt;application&gt;
+    ...
+    &lt;meta-data android:name="com.google.android.gms.car.application"
+        android:resource="@xml/automotive_app_desc" /&gt;
+    ...
+&lt;application&gt;
+</pre>
+
+<p>
+  This manifest entry refers to a secondary xml file, where you declare what Auto capabilities your
+  app supports. For an app that supports messaging for Auto devices, add an xml file to the {@code
+  res/xml/} your app's development project directory as {@code automotive_app_desc.xml}, with the
+  following content:
+</p>
+
+<pre>
+&lt;automotiveApp&gt;
+    &lt;uses name="notification"/&gt;
+&lt;/automotiveApp&gt;
+</pre>
+
+<p>
+  For more information about declaring capabilities for Auto devices, see <a href=
+  "{@docRoot}training/auto/start/index.html#auto-metadata">Getting Started with Auto</a>.
+</p>
+
+
+<h3 id="manifest-intent">Define read and reply intent filters</h3>
+
+<p>
+  Auto devices use {@link android.content.Intent} objects that indicate a user has read or replied
+  to a message provided by your app. Your app defines intent types for reading and replying to
+  messages and adds this information to messaging notifications for Auto devices, so that the
+  dashboard system can notify your app when a user takes one of these actions.
+</p>
+
+<p>
+  You define the read action and reply action intents types for your app and the {@code
+  android.content.BroadcastReceiver} classes that handle them in the manifest. The following code
+  example demonstrates how to declare these intents and thier associated receivers.
+</p>
+
+<pre>
+&lt;application&gt;
+    ...
+    &lt;receiver android:name="<em>.MyMessageReadReceiver</em>"&gt;
+        &lt;intent-filter&gt;
+          &lt;action android:name="<em>com.myapp.messagingservice.ACTION_MESSAGE_HEARD</em>"/&gt;
+        &lt;/intent-filter&gt;
+    &lt;/receiver&gt;
+
+    &lt;receiver android:name="<em>.MyMessageReplyReceiver</em>"&gt;
+        &lt;intent-filter&gt;
+          &lt;action android:name="<em>com.myapp.messagingservice.ACTION_MESSAGE_REPLY</em>"/&gt;
+        &lt;/intent-filter&gt;
+    &lt;/receiver&gt;
+    ...
+&lt;/application&gt;
+</pre>
+
+<p>
+  The definition of the {@code android.content.BroadcastReceiver} classes shown in this example
+  is discussed in <a href="#handle_actions">Handle User Actions</a>.
+</p>
+
+
+<h2 id="support-lib">Import Support Library for Messaging</h3>
+
+<p>
+  Building notifications for use with Auto devices requires classes from the
+  <a href="{@docRoot}tools/support-library/features.html#v4">v4 support library</a>. Use the
+  <a href="{@docRoot}tools/help/sdk-manager.html">Android SDK Manager</a> to update the
+  <em>Extras > Android Support Repository</em> to version 9 or higher and the
+  <em>Extras > Android Support Library</em> to version 21.1.0 or higher.
+</p>
+
+<p>
+  After you have updated the support libraries, import them into your Android Studio development
+  project by adding this dependency to your
+  <a href="{@docRoot}sdk/installing/studio-build.html#configBuild">build.gradle</a> file:
+</p>
+
+<pre>
+dependencies {
+    ...
+    compile 'com.android.support:support-v4:21.1.+'
+}
+</pre>
+
+<p>
+  For information about importing the support library into development projects for other
+  development environments, see <a href="{@docRoot}tools/support-library/setup.html">Support
+  Library Setup</a>.
+</p>
+
+
+
+<h2 id="messaging">Notify Users of Messages</h2>
+
+<p>
+  A messaging app provides messages to a connected Auto dashboard using the <a href=
+  "{@docRoot}guide/topics/ui/notifiers/notifications.html">notifications</a> framework. When your
+  messaging app has a message for a user, you build a specially configured notification that is
+  received by the dashboard system and presented to the user. The Auto device manages the
+  presentation on the dashboard screen and may play the message via text-to-speech. The dashboard
+  system also handles voice interaction if the user replies to a message using verbal input.
+</p>
+
+<p>
+  The messaging user interface for Auto presents users with two levels of information about
+  messages. The first level of notification tells users what <em>conversations</em> are
+  available, and who they are with, but not the content of the messages. Typically, a
+  conversation is one or more messages from another user to the Auto user.
+</p>
+
+<p>
+  The second level of the notification is the actual content of messages in the conversation. If a
+  user indicates they want to hear the messages in a conversation, the Auto user interface plays
+  the messages using text-to-speech.
+</p>
+
+<p>
+  This section describes how to notify Auto users that conversations are available and
+  provide the content of messages in those conversations.
+</p>
+
+
+<h3 id="build_conversation">Build message conversations</h4>
+
+<p>
+  Messaging notifications for Auto organize messages into conversations using the {@code
+  NotificationCompat.CarExtender.UnreadConversation} class, that represents an unread or new
+  portion of a conversation from a particular sender. It contains a list of messages from the
+  sender.
+</p>
+
+<p>
+  Use the {@code UnreadConversation.Builder} class to create an unread conversation object,
+  as shown in the following example code:
+</p>
+
+<pre>
+// Build a RemoteInput for receiving voice input in a Car Notification
+RemoteInput remoteInput = new RemoteInput.Builder(EXTRA_VOICE_REPLY)
+        .setLabel(getApplicationContext().getString(R.string.notification_reply))
+        .build();
+
+// Create an unread conversation object to organize a group of messages
+// from a particular sender.
+UnreadConversation.Builder unreadConvBuilder =
+    new UnreadConversation.Builder(participantName)
+        .setReadPendingIntent(msgHeardPendingIntent)
+        .setReplyAction(replyPendingIntent, remoteInput);
+</pre>
+
+<p>
+  This conversation object includes a {@link android.app.PendingIntent}, which allows the Auto
+  device to signal your app that the conversation has been read by the Auto user. The construction
+  of this intent is discussed in the <a href="#conversation-intents">Creating conversation read and
+  reply intents</a> section.
+</p>
+
+<p>
+  If your app supports replying to a conversation, you must call the {@code setReplyAction()}
+  method and provide a pending intent to pass that user action back to your app. The {@code
+  UnreadConversation} object you create must also include a {@link
+  android.support.v4.app.RemoteInput} object. This object is required because the Auto user
+  receiving this conversation speaks a reply, a the remote input objects lets your app get a text
+  version of the voice reply.
+</p>
+
+
+<h4 id="conversation-messages">Associate messages with conversations</h4>
+
+<p>
+  Messages provided for Auto must be associated with a conversation using the {@code
+  NotificationCompat.CarExtender.UnreadConversation} class. The following code example shows how
+  to associate individual messages with a conversation object.
+</p>
+
+<pre>
+// Note: Add messages from oldest to newest to the UnreadConversation.Builder
+for (Iterator&lt;String&gt; messages = conversation.getMessages().iterator();
+     messages.hasNext(); ) {
+    String message = messages.next();
+    unreadConvBuilder.addMessage(message);
+}
+</pre>
+
+<p>
+  When a new message arrives in a particular conversation, your app should check if there is
+  already a conversation object for that particular conversation. If there is, associate the new
+  message with the existing conversation instead of building a new one.
+</p>
+
+
+<h4 id="conversation-intents">Create conversation read and reply intents</h4>
+
+<p>
+  Unread conversation objects contain intents for reading and replying to a conversation. You
+  create a {@link android.app.PendingIntent} object for each of these actions, so the Auto device
+  can notify your app of action taken by the Auto user on a particular conversation.
+</p>
+
+<p>
+  The following example code demonstrates how to define a {@link android.app.PendingIntent} to let
+  your app know if a conversation was listened to by the Auto user:
+</p>
+
+<pre>
+Intent msgHeardIntent = new Intent()
+    .addFlags(Intent.FLAG_INCLUDE_STOPPED_PACKAGES)
+    .setAction(<em>com.myapp.messagingservice.ACTION_MESSAGE_HEARD</em>)
+    .putExtra("conversation_id", conversationId);
+
+PendingIntent msgHeardPendingIntent =
+    PendingIntent.getBroadcast(getApplicationContext(),
+        conversationId,
+        msgHeardIntent,
+        PendingIntent.FLAG_UPDATE_CURRENT);
+</pre>
+
+<p>
+  In this example, {@code conversationId} is an integer that identifies the current conversation.
+  The value of {@code setAction()} is an intent filter identifier for heard messages which is
+  defined in your app manifest, as shown in <a href="#manifest-intent">Define read and reply intent
+  filters</a>.
+</p>
+
+<p>
+  If your app supports replying to conversations, you also create a {@link
+  android.app.PendingIntent} for each conversation to notify your app that the user has replied.
+  The following code example shows you how to build this intent for use with a particular
+  conversation:
+</p>
+
+<pre>
+Intent msgReplyIntent = new Intent()
+    .addFlags(Intent.FLAG_INCLUDE_STOPPED_PACKAGES)
+    .setAction(<em>com.myapp.messagingservice.ACTION_MESSAGE_REPLY</em>)
+    .putExtra("conversation_id", <em>conversationId</em>);
+
+PendingIntent msgReplyPendingIntent = PendingIntent.getBroadcast(
+    getApplicationContext(),
+    <em>conversationId</em>,
+    msgReplyIntent,
+    PendingIntent.FLAG_UPDATE_CURRENT);
+</pre>
+
+<p>
+  Once again, {@code conversationId} is an integer that uniquely identifies this conversation. The
+  value of {@code setAction()} is an intent filter identifier for replies which is defined in your
+  app manifest, as shown in <a href="#manifest-intent">Define read and reply intent filters</a>.
+</p>
+
+
+<h3 id="sending_messages">Sending Messages</h4>
+
+<p>
+  When a message arrives for a conversation, you take the following steps to dispatch it as a
+  notification to Auto.
+</p>
+
+<p>First, add the message to the <code>UnreadConversation.Builder</code> for
+this conversation, and update its timestamp:</p>
+
+<pre>
+unreadConvBuilder.addMessage(<em>messageString</em>)
+    .setLatestTimestamp(<em>currentTimestamp</em>);
+</pre>
+
+<p>Then create a {@link android.support.v4.app.NotificationCompat.Builder}
+object that you'll use to build the actual notification. You'll need to use the
+pending intents you created in the previous step.</p>
+
+<pre>
+NotificationCompat.Builder notificationBuilder =
+    new NotificationCompat.Builder(getApplicationContext())
+        .setSmallIcon(R.drawable.<em>notification_icon</em>)
+        .setLargeIcon(<em>icon_bitmap</em>)
+        .setContentText(<em>messageString</em>)
+        .setWhen(<em>currentTimestamp</em>)
+        .setContentTitle(<em>participant_name</em>)
+        .setContentIntent(msgHeardPendingIntent);
+
+</pre>
+
+<p>You'll also need to extend the  {@link
+android.support.v4.app.NotificationCompat.Builder} with the
+<code>CarExtender</code>. This is where you actually create the
+<code>UnreadConversation</code> object using the builder you just
+created, and attach it to the <code>CarExtender</code>:</p>
+
+<pre>
+notificationBuilder.extend(new CarExtender()
+    .setUnreadConversation(unreadConvBuilder.build());
+</pre>
+
+<p>Once you've done all this, you use your app's {@link
+android.support.v4.app.NotificationManagerCompat} to send the notification:</p>
+
+<pre>
+mNotificationManager = NotificationManagerCompat.from(context);
+mNotificationManager.notify(<em>notificationId</em>, notificationBuilder.build());
+</pre>
+
+<p>In this example, <em>msgNotificationManager</em> is a
+{@link android.support.v4.app.NotificationManagerCompat} you created for your app.</p>
+
+
+<h2 id="handle_actions">Handle User Actions</h2>
+
+<p>
+  When your create and dispatch a notification for messaging, you specify intents to be triggered
+  when the Auto user hears the message and when the user dictates a reply. Your app indicates to
+  the Android framework that it handles these intends by registering them through it's manifest, as
+  discussed in <a href="#manifest-intent">Define read and reply intent filters</a>.
+</p>
+
+<p>
+  In addition to registering these intent filters, your app must provide code to handle these
+  actions. Your app can do this by providing a service or {@link android.content.BroadcastReceiver}
+  objects that handle these intents.</p>
+
+<p>
+  For more information about intents, see <a href=
+  "{@docRoot}guide/components/intents-filters.html">Intents and Intent Filters</a>.
+</p>
+
+
+<h3 id="handling_msg_heard">Handling a message heard action</h3>
+
+<p>
+  When a user listens to a messaging conversation through the Auto user interface, the dashboard
+  device sends a read intent based on how your app defined the messaging notification. Your app
+  catches that intent and invokes the broadcast receiver class associated with it, or the service
+  method set up to handle that action.
+</p>
+
+<p>
+  The following code example shows how to define a {@link android.content.BroadcastReceiver} class
+  to handle a received message heard intent:
+</p>
+
+<pre>
+public class MessageHeardReceiver extends BroadcastReceiver {
+
+    &#64;Override
+    public void onReceive(Context context, Intent intent) {
+
+        // If you set up the intent as described in
+        // "Create conversation read and reply intents",
+        // you can get the conversation ID by calling:
+        int conversationId = intent.getIntExtra("conversation_id", -1);
+
+        // Remove the notification to indicate it has been read
+        // and update the list of unread conversations in your app.
+    }
+}
+</pre>
+
+<p>
+  Once a notification is read, your app can remove it by calling
+  {@link android.support.v4.app.NotificationManagerCompat#cancel} with the notification ID.
+  Within your app, you should mark the messages provided in the notification as read.
+</p>
+
+
+<p class="note">
+  <strong>Note:</strong> An alternative to this implementation is to use a service in a
+  {@link android.app.PendingIntent}.
+</p>
+
+
+<h3 id="handling_reply">Handling a reply action</h3>
+
+<p>
+  When a user replies to a messaging conversation through the Auto user interface, the dashboard
+  system sends a reply intent based on how your app defined the messaging notification. Your app
+  catches that intent and invokes the broadcast receiver class associated with it, or the service
+  method set up to handle that action.
+</p>
+
+<p>
+  The following code example shows how to define a {@link android.content.BroadcastReceiver} class
+  to handle a received message reply intent:
+</p>
+
+<pre>
+  public class MessageReplyReceiver extends BroadcastReceiver {
+
+
+    &#64;Override
+    public void onReceive(Context context, Intent intent) {
+        // If you set up the intent as described in
+        // "Create conversation read and reply intents",
+        // you can get the conversation ID by calling:
+        int conversationId = intent.getIntExtra("conversation_id", -1).
+
+    }
+
+    /**
+     * Get the message text from the intent.
+     * Note that you should call
+     * RemoteInput.getResultsFromIntent() to process
+     * the RemoteInput.
+     */
+    private CharSequence getMessageText(Intent intent) {
+        Bundle remoteInput =
+            RemoteInput.getResultsFromIntent(intent);
+        if (remoteInput != null) {
+            return remoteInput.getCharSequence("extra_voice_reply");
+        }
+        return null;
+    }
+
+}</pre>
diff --git a/docs/html/training/auto/start/index.jd b/docs/html/training/auto/start/index.jd
new file mode 100644
index 0000000..b955cef
--- /dev/null
+++ b/docs/html/training/auto/start/index.jd
@@ -0,0 +1,210 @@
+page.title=Getting Started with Auto
+page.tags="auto", "car", "automotive"
+page.article=true
+page.image=auto/images/assets/icons/auto_app_in_simulator.png
+
+@jd:body
+
+<div id="tb-wrapper">
+<div id="tb">
+  <h2>Dependencies and Prerequisites</h2>
+  <ul>
+    <li>Android 5.0 (API level 21) or higher</li>
+  </ul>
+
+  <h2>This class teaches you how to</h2>
+  <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>
+  </ol>
+
+ <h2>You should also read</h2>
+ <ul>
+   <li><a href="{@docRoot}design/auto/index.html">Designing for Auto</a></li>
+   <li><a href="{@docRoot}training/auto/audio/index.html">Providing Audio Playback with Auto</a></li>
+   <li><a href="{@docRoot}training/auto/messaging/index.html">Providing Messaging for Auto</a></li>
+ </ul>
+</div>
+</div>
+
+<p>Android Auto extends the Android platform into the car. When users connect
+their handheld devices running Android 5.0 or higher to a compatible vehicle,
+the Auto user interface provides a car-optimized Android experience on the
+vehicle's screen. Users interact with compatible apps and services through
+voice actions and the vehicle's input controls (like a touchscreen or dashboard
+buttons).</p>
+
+<p>Auto currently supports two types of apps:</p>
+
+<ul>
+<li><em>Audio apps</em> that allow users to browse and play music and spoken
+audio content in the car.</li>
+<li><em>Messaging apps</em> that receive incoming notifications, read messages
+  aloud via text-to-speech, and send replies via voice input in the car.</li>
+</ul>
+
+<p>You can enable your existing audio and messaging apps developed for
+phones and tablets to work in the car, without having to worry about
+vehicle-specific hardware differences. To enable your app for Auto, your
+app must target Android 5.0 (API level 21) or higher. Your app’s manifest must
+also declare the car capabilities that it uses, such as audio playback or
+messaging services. </p>
+
+<p>This lesson describes how to start building apps for Auto, including
+setting up your development environment and meeting the the minimum requirements
+to enable an app to communicate with Auto.</p>
+
+<p class="note"><strong>Important:</strong> If you are planning to develop
+apps for Auto, you are encouraged to begin enabling and testing your
+apps now. However, Auto-enabled apps cannot be published at this time.
+Join the
+<a href="http://g.co/AndroidAutoDev" class="external-link">Auto
+Developers Google+ community</a> for updates on when you will be able to submit
+your Auto-enabled apps.</p>
+
+<h2 id="dev-project">Set Up an Auto Project</h2>
+<p>This section describes how to create a new app or modify an existing app to
+communicate with Auto.</p>
+
+<h3 id="prerequisites">Prerequisites</h3>
+<p>Before you begin building apps for Auto, you must:</p>
+
+<ul>
+<li><strong><a href="{@docRoot}sdk/installing/create-project.html">Create or
+update your app project</a></strong> - Android 5.0 (API level 21) provides new
+APIs for implementing audio playback and messaging that is compatible with Auto.
+To access the new APIs, create a project or modify an existing project to target
+Android 5.0 (API level 21) or higher. This means you must set the manifest
+<a href="{@docRoot}topics/manifest/uses-sdk-element.html">{@code targetSdkVersion}</a>
+to 21 or higher.
+</li>
+<li><strong><a href="{@docRoot}tools/support-library/setup.html">Install the
+support library</a></strong> - If you are building messaging apps for Auto, you
+need the {@code NotificationCompat.CarExtender} class contained in the
+<a href="{@docRoot}tools/support-library/features.html#v4">v4 support library</a>.
+This class allows you to create notifications that are compatible with Auto
+devices.</li>
+</ul>
+
+<h3 id="auto-metadata">Declare Auto capabilities</h3>
+<p>The Auto features that your app can access are controlled
+by the settings in your app manifest and a separate XML configuration file.
+Before adding Auto features to your app, you must first define the Auto
+XML configuration file and add a manifest entry referencing your XML file.</p>
+
+<h4 id="auto_xml">Define the Auto XML configuration file</h4>
+<p>Specify the car capabilities that your app uses in an XML file that you
+place in your project’s resources directory ({@code res/xml/}). For example, to
+extend an audio application for Auto, create a file called
+{@code automotive_app_desc.xml} and store it under your projects’s
+{@code res/xml/} folder. The {@code automotive_app_desc.xml} file contains the
+following metadata:</p>
+<pre>
+&lt;automotiveApp&gt;
+   &lt;uses name="media" /&gt;
+&lt;/automotiveApp&gt;
+</pre>
+<p>The {@code &lt;uses&gt;} element declares the Auto capability your app
+intends to use. Multiple {@code &lt;uses&gt;} tags can be added if your
+application uses multiple car capabilities. The {@code name} attribute indicates
+the specific capability your app uses. The values supported are:</p>
+<ul>
+<li>{@code media} - The app uses the Android framework APIs to play music in
+a vehicle. Set this value if you are enabling an audio app for Auto.</li>
+<li>{@code notification} - The app displays message notifications in the car’s
+Overview screen, allows users select a message to be read aloud, and lets them
+respond through voice input. Set this value if you are enabling a messaging
+app for Auto.
+</ul>
+
+<h4 id="auto_xml">Add a manifest entry</h4>
+<p>In your app’s manifest ({@code AndroidManifest.xml}), provide a reference to
+the Auto XML configuration file you created in the previous section. Add a
+{@code "com.google.android.gms.car.application"} metadata entry under the
+<a href="{@docRoot}guide/topics/manifest/application-element.html">{@code &lt;application&gt;}</a>
+element that references your Auto XML configuration file. Omit the {@code .xml}
+file extension when specifying the configuration filename.</p>
+<p>The following code snippet shows how to include this reference in your
+manifest.</p>
+<pre>
+&lt;application&gt;
+
+    ...
+    &lt;meta-data android:name="com.google.android.gms.car.application"
+     android:resource="@xml/automotive_app_desc"/&gt;
+
+&lt;/application&gt;
+</pre>
+
+<h2 id="build-it">Add Auto Features to Your Apps</h2>
+<p>After you have completed the steps described above, you're ready to add Auto
+features to your apps. See these additional topics to help you build apps for
+Auto:</p>
+
+<ul>
+<li><a href="{@docRoot}training/auto/audio/index.html">Providing Audio Playback for Auto</a>
+- Create apps that let users browse and play music in the car.</li>
+<li><a href="{@docRoot}training/auto/messaging/index.html">Providing Messaging for Auto</a>
+- Enable users to receive and reply to messages in the car.</li>
+</ul>
+
+<p class="caution"><strong>Important:</strong> Google takes driver distraction
+very seriously. There are specific design requirements your app must meet to
+qualify as an Auto app on Google Play. By adhering to these
+requirements, you can reduce the effort for building and testing your app. For
+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>
+
+<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>
+
+<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 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>
+</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 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>
+</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>
diff --git a/docs/html/training/training_toc.cs b/docs/html/training/training_toc.cs
index 9f06666..61a5e3c 100644
--- a/docs/html/training/training_toc.cs
+++ b/docs/html/training/training_toc.cs
@@ -939,6 +939,36 @@
   <!-- End: Building for TV -->
 
 
+  <!-- Start: Building for Auto -->
+  <li class="nav-section">
+    <div class="nav-section-header">
+      <a href="<?cs var:toroot ?>training/auto/index.html">
+      <span class="small">Building Apps for</span><br/>
+              Auto
+      </a>
+    </div>
+    <ul>
+      <li>
+        <a href="<?cs var:toroot ?>training/auto/start/index.html"
+             description="How to start building or extending apps that work
+             with Auto devices.">
+             Getting Started with Auto</a>
+      </li>
+      <li>
+        <a href="<?cs var:toroot ?>training/auto/audio/index.html"
+             description="How to extend audio apps to play content on Auto devices.">
+             Playing Audio for Auto</a>
+      </li>
+      <li>
+        <a href="<?cs var:toroot ?>training/auto/messaging/index.html"
+             description="How to extend text messaging apps to work with Auto devices.">
+             Messaging for Auto</a>
+      </li>
+    </ul>
+  </li>
+  <!-- End: Building for Auto -->
+
+
   <li class="nav-section">
     <div class="nav-section-header">
       <a href="<?cs var:toroot ?>training/best-ux.html">
diff --git a/libs/hwui/AssetAtlas.cpp b/libs/hwui/AssetAtlas.cpp
index fc86e4f..e5a93bd 100644
--- a/libs/hwui/AssetAtlas.cpp
+++ b/libs/hwui/AssetAtlas.cpp
@@ -33,6 +33,8 @@
         return;
     }
 
+    ATRACE_NAME("AssetAtlas::init");
+
     mImage = new Image(buffer);
 
     if (mImage->getTexture()) {
diff --git a/libs/hwui/Caches.cpp b/libs/hwui/Caches.cpp
index 952f739..6453206 100644
--- a/libs/hwui/Caches.cpp
+++ b/libs/hwui/Caches.cpp
@@ -66,6 +66,8 @@
 bool Caches::init() {
     if (mInitialized) return false;
 
+    ATRACE_NAME("Caches::init");
+
     glGenBuffers(1, &meshBuffer);
     glBindBuffer(GL_ARRAY_BUFFER, meshBuffer);
     glBufferData(GL_ARRAY_BUFFER, sizeof(gMeshVertices), gMeshVertices, GL_STATIC_DRAW);
diff --git a/libs/hwui/renderthread/CanvasContext.cpp b/libs/hwui/renderthread/CanvasContext.cpp
index 6c3637d..39528be 100644
--- a/libs/hwui/renderthread/CanvasContext.cpp
+++ b/libs/hwui/renderthread/CanvasContext.cpp
@@ -71,6 +71,8 @@
 }
 
 void CanvasContext::setSurface(ANativeWindow* window) {
+    ATRACE_CALL();
+
     mNativeWindow = window;
 
     if (mEglSurface != EGL_NO_SURFACE) {
diff --git a/libs/hwui/renderthread/EglManager.cpp b/libs/hwui/renderthread/EglManager.cpp
index 9bd6f41..378cf61 100644
--- a/libs/hwui/renderthread/EglManager.cpp
+++ b/libs/hwui/renderthread/EglManager.cpp
@@ -82,6 +82,8 @@
 void EglManager::initialize() {
     if (hasEglContext()) return;
 
+    ATRACE_NAME("Creating EGLContext");
+
     mEglDisplay = eglGetDisplay(EGL_DEFAULT_DISPLAY);
     LOG_ALWAYS_FATAL_IF(mEglDisplay == EGL_NO_DISPLAY,
             "Failed to get EGL_DEFAULT_DISPLAY! err=%s", egl_error_str());
diff --git a/media/java/android/media/AudioService.java b/media/java/android/media/AudioService.java
index a80b356..6e14aba 100644
--- a/media/java/android/media/AudioService.java
+++ b/media/java/android/media/AudioService.java
@@ -1827,8 +1827,8 @@
                 if (!isStreamAffectedByRingerMode(streamType) ||
                     ringerMode == AudioManager.RINGER_MODE_NORMAL) {
                     // ring and notifications volume should never be 0 when not silenced
-                    // on voice capable devices
-                    if (isPlatformVoice() &&
+                    // on voice capable devices or devices that support vibration
+                    if ((isPlatformVoice() || mHasVibrator) &&
                             mStreamVolumeAlias[streamType] == AudioSystem.STREAM_RING) {
                         synchronized (VolumeStreamState.class) {
                             Set set = mStreamStates[streamType].mIndex.entrySet();
diff --git a/media/java/android/media/tv/ITvInputSessionWrapper.java b/media/java/android/media/tv/ITvInputSessionWrapper.java
index 1ac80c1..da6f3fc 100644
--- a/media/java/android/media/tv/ITvInputSessionWrapper.java
+++ b/media/java/android/media/tv/ITvInputSessionWrapper.java
@@ -42,6 +42,7 @@
     private static final String TAG = "TvInputSessionWrapper";
 
     private static final int MESSAGE_HANDLING_DURATION_THRESHOLD_MILLIS = 50;
+    private static final int MESSAGE_TUNE_DURATION_THRESHOLD_MILLIS = 1000;
 
     private static final int DO_RELEASE = 1;
     private static final int DO_SET_MAIN = 2;
@@ -161,6 +162,11 @@
         if (duration > MESSAGE_HANDLING_DURATION_THRESHOLD_MILLIS) {
             Log.w(TAG, "Handling message (" + msg.what + ") took too long time (duration="
                     + duration + "ms)");
+            if (msg.what == DO_TUNE && duration > MESSAGE_TUNE_DURATION_THRESHOLD_MILLIS) {
+                throw new RuntimeException("Too much time to handle tune request. (" + duration
+                        + "ms > " + MESSAGE_TUNE_DURATION_THRESHOLD_MILLIS + "ms) "
+                        + "Consider handling the tune request in a separate thread.");
+            }
         }
     }
 
@@ -193,6 +199,8 @@
 
     @Override
     public void tune(Uri channelUri, Bundle params) {
+        // Clear the pending tune requests.
+        mCaller.removeMessages(DO_TUNE);
         mCaller.executeOrSendMessage(mCaller.obtainMessageOO(DO_TUNE, channelUri, params));
     }
 
diff --git a/packages/SettingsProvider/src/com/android/providers/settings/DatabaseHelper.java b/packages/SettingsProvider/src/com/android/providers/settings/DatabaseHelper.java
index 1771eac..175b424 100644
--- a/packages/SettingsProvider/src/com/android/providers/settings/DatabaseHelper.java
+++ b/packages/SettingsProvider/src/com/android/providers/settings/DatabaseHelper.java
@@ -2620,8 +2620,7 @@
             // Set the preferred network mode to target desired value or Default
             // value defined in RILConstants
             int type;
-            type = SystemProperties.getInt("ro.telephony.default_network",
-                        RILConstants.PREFERRED_NETWORK_MODE);
+            type = RILConstants.PREFERRED_NETWORK_MODE;
             loadSetting(stmt, Settings.Global.PREFERRED_NETWORK_MODE, type);
 
             // Set the preferred cdma subscription source to target desired value or default
diff --git a/packages/SystemUI/res/anim/recents_from_app_enter.xml b/packages/SystemUI/res/anim/recents_from_app_enter.xml
index 6abe8b3..10ddce6 100644
--- a/packages/SystemUI/res/anim/recents_from_app_enter.xml
+++ b/packages/SystemUI/res/anim/recents_from_app_enter.xml
@@ -16,7 +16,7 @@
 ** limitations under the License.
 */
 -->
-
+<!-- Recents Activity -->
 <set xmlns:android="http://schemas.android.com/apk/res/android"
      android:shareInterpolator="false"
      android:zAdjustment="top">
diff --git a/packages/SystemUI/res/anim/recents_from_app_exit.xml b/packages/SystemUI/res/anim/recents_from_app_exit.xml
index 1447a5a..c98ecf4 100644
--- a/packages/SystemUI/res/anim/recents_from_app_exit.xml
+++ b/packages/SystemUI/res/anim/recents_from_app_exit.xml
@@ -16,7 +16,7 @@
 ** limitations under the License.
 */
 -->
-
+<!-- Incoming Activity -->
 <set xmlns:android="http://schemas.android.com/apk/res/android"
      android:shareInterpolator="false"
      android:zAdjustment="normal">
diff --git a/packages/SystemUI/res/anim/recents_from_search_launcher_enter.xml b/packages/SystemUI/res/anim/recents_from_search_launcher_enter.xml
index 20e7764..7de4460 100644
--- a/packages/SystemUI/res/anim/recents_from_search_launcher_enter.xml
+++ b/packages/SystemUI/res/anim/recents_from_search_launcher_enter.xml
@@ -16,13 +16,13 @@
 ** limitations under the License.
 */
 -->
-
+<!-- Recents Activity -->
 <set xmlns:android="http://schemas.android.com/apk/res/android"
      android:shareInterpolator="false"
      android:zAdjustment="normal">
-  <alpha android:fromAlpha="0.0" android:toAlpha="1.0"
+  <alpha android:fromAlpha="1.0" android:toAlpha="1.0"
          android:fillEnabled="true"
          android:fillBefore="true" android:fillAfter="true"
          android:interpolator="@android:interpolator/linear"
-         android:duration="50"/>
+         android:duration="1"/>
 </set>
diff --git a/packages/SystemUI/res/anim/recents_from_search_launcher_exit.xml b/packages/SystemUI/res/anim/recents_from_search_launcher_exit.xml
index 92a8882..e0e2fc8 100644
--- a/packages/SystemUI/res/anim/recents_from_search_launcher_exit.xml
+++ b/packages/SystemUI/res/anim/recents_from_search_launcher_exit.xml
@@ -16,14 +16,13 @@
 ** limitations under the License.
 */
 -->
-
+<!-- Launcher Activity -->
 <set xmlns:android="http://schemas.android.com/apk/res/android"
      android:shareInterpolator="false"
      android:zAdjustment="top">
   <alpha android:fromAlpha="1.0" android:toAlpha="0.0"
-  		 android:startOffset="50"
          android:fillEnabled="true"
          android:fillBefore="true" android:fillAfter="true"
          android:interpolator="@android:interpolator/linear_out_slow_in"
-         android:duration="100"/>
+         android:duration="@integer/recents_enter_from_home_transition_duration"/>
 </set>
diff --git a/packages/SystemUI/res/anim/recents_to_search_launcher_enter.xml b/packages/SystemUI/res/anim/recents_to_search_launcher_enter.xml
index 4e1d66d..ea82835 100644
--- a/packages/SystemUI/res/anim/recents_to_search_launcher_enter.xml
+++ b/packages/SystemUI/res/anim/recents_to_search_launcher_enter.xml
@@ -16,7 +16,7 @@
 ** limitations under the License.
 */
 -->
-
+<!-- Launcher Activity -->
 <set xmlns:android="http://schemas.android.com/apk/res/android"
      android:shareInterpolator="false"
      android:zAdjustment="normal">
diff --git a/packages/SystemUI/res/anim/recents_to_search_launcher_exit.xml b/packages/SystemUI/res/anim/recents_to_search_launcher_exit.xml
index d7a12a4..a8bdc8e 100644
--- a/packages/SystemUI/res/anim/recents_to_search_launcher_exit.xml
+++ b/packages/SystemUI/res/anim/recents_to_search_launcher_exit.xml
@@ -16,14 +16,13 @@
 ** limitations under the License.
 */
 -->
-
+<!-- Recents Activity -->
 <set xmlns:android="http://schemas.android.com/apk/res/android"
      android:shareInterpolator="false"
      android:zAdjustment="top">
-  <alpha android:fromAlpha="1.0" android:toAlpha="0.0"
-  		 android:startOffset="100"
+  <alpha android:fromAlpha="1.0" android:toAlpha="1.0"
          android:fillEnabled="true"
          android:fillBefore="true" android:fillAfter="true"
          android:interpolator="@android:interpolator/linear"
-         android:duration="50"/>
+         android:duration="100"/>
 </set>
diff --git a/packages/SystemUI/res/drawable-hdpi/btn_fab_recents.png b/packages/SystemUI/res/drawable-hdpi/btn_fab_recents.png
deleted file mode 100644
index b95fde5..0000000
--- a/packages/SystemUI/res/drawable-hdpi/btn_fab_recents.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/ic_sysbar_back.png b/packages/SystemUI/res/drawable-hdpi/ic_sysbar_back.png
index 5be74ec..d2760bb 100644
--- a/packages/SystemUI/res/drawable-hdpi/ic_sysbar_back.png
+++ b/packages/SystemUI/res/drawable-hdpi/ic_sysbar_back.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/ic_sysbar_back_ime.png b/packages/SystemUI/res/drawable-hdpi/ic_sysbar_back_ime.png
index 305c9fb..5cbf418 100644
--- a/packages/SystemUI/res/drawable-hdpi/ic_sysbar_back_ime.png
+++ b/packages/SystemUI/res/drawable-hdpi/ic_sysbar_back_ime.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/ic_sysbar_back_land.png b/packages/SystemUI/res/drawable-hdpi/ic_sysbar_back_land.png
index 3e676ab..d6e2065 100644
--- a/packages/SystemUI/res/drawable-hdpi/ic_sysbar_back_land.png
+++ b/packages/SystemUI/res/drawable-hdpi/ic_sysbar_back_land.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/ic_sysbar_home.png b/packages/SystemUI/res/drawable-hdpi/ic_sysbar_home.png
index d3e1f7a..df43e21 100644
--- a/packages/SystemUI/res/drawable-hdpi/ic_sysbar_home.png
+++ b/packages/SystemUI/res/drawable-hdpi/ic_sysbar_home.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/ic_sysbar_home_land.png b/packages/SystemUI/res/drawable-hdpi/ic_sysbar_home_land.png
index d632600..6be4161 100644
--- a/packages/SystemUI/res/drawable-hdpi/ic_sysbar_home_land.png
+++ b/packages/SystemUI/res/drawable-hdpi/ic_sysbar_home_land.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/ic_sysbar_lights_out_dot_large.png b/packages/SystemUI/res/drawable-hdpi/ic_sysbar_lights_out_dot_large.png
index 1233fca..552a3d1 100644
--- a/packages/SystemUI/res/drawable-hdpi/ic_sysbar_lights_out_dot_large.png
+++ b/packages/SystemUI/res/drawable-hdpi/ic_sysbar_lights_out_dot_large.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/ic_sysbar_lights_out_dot_small.png b/packages/SystemUI/res/drawable-hdpi/ic_sysbar_lights_out_dot_small.png
index 6768c1f..6016ac4 100644
--- a/packages/SystemUI/res/drawable-hdpi/ic_sysbar_lights_out_dot_small.png
+++ b/packages/SystemUI/res/drawable-hdpi/ic_sysbar_lights_out_dot_small.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/ic_sysbar_menu.png b/packages/SystemUI/res/drawable-hdpi/ic_sysbar_menu.png
index 8984a49d..72b2b21 100644
--- a/packages/SystemUI/res/drawable-hdpi/ic_sysbar_menu.png
+++ b/packages/SystemUI/res/drawable-hdpi/ic_sysbar_menu.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/ic_sysbar_menu_land.png b/packages/SystemUI/res/drawable-hdpi/ic_sysbar_menu_land.png
index 2e8f8f0..bcb203e 100644
--- a/packages/SystemUI/res/drawable-hdpi/ic_sysbar_menu_land.png
+++ b/packages/SystemUI/res/drawable-hdpi/ic_sysbar_menu_land.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/ic_sysbar_recent.png b/packages/SystemUI/res/drawable-hdpi/ic_sysbar_recent.png
index ec499d4..6fab1d6 100644
--- a/packages/SystemUI/res/drawable-hdpi/ic_sysbar_recent.png
+++ b/packages/SystemUI/res/drawable-hdpi/ic_sysbar_recent.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/ic_sysbar_recent_land.png b/packages/SystemUI/res/drawable-hdpi/ic_sysbar_recent_land.png
index 13e8a4f..b031273 100644
--- a/packages/SystemUI/res/drawable-hdpi/ic_sysbar_recent_land.png
+++ b/packages/SystemUI/res/drawable-hdpi/ic_sysbar_recent_land.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-ldrtl-hdpi/ic_sysbar_back.png b/packages/SystemUI/res/drawable-ldrtl-hdpi/ic_sysbar_back.png
index c697da7..2fcfdde 100644
--- a/packages/SystemUI/res/drawable-ldrtl-hdpi/ic_sysbar_back.png
+++ b/packages/SystemUI/res/drawable-ldrtl-hdpi/ic_sysbar_back.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-ldrtl-hdpi/ic_sysbar_back_land.png b/packages/SystemUI/res/drawable-ldrtl-hdpi/ic_sysbar_back_land.png
index 94404df..2f4dbbe 100644
--- a/packages/SystemUI/res/drawable-ldrtl-hdpi/ic_sysbar_back_land.png
+++ b/packages/SystemUI/res/drawable-ldrtl-hdpi/ic_sysbar_back_land.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-ldrtl-mdpi/ic_sysbar_back.png b/packages/SystemUI/res/drawable-ldrtl-mdpi/ic_sysbar_back.png
index 9d0014d..48708a5 100644
--- a/packages/SystemUI/res/drawable-ldrtl-mdpi/ic_sysbar_back.png
+++ b/packages/SystemUI/res/drawable-ldrtl-mdpi/ic_sysbar_back.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-ldrtl-mdpi/ic_sysbar_back_land.png b/packages/SystemUI/res/drawable-ldrtl-mdpi/ic_sysbar_back_land.png
index 9a8b0e9..d04d84f 100644
--- a/packages/SystemUI/res/drawable-ldrtl-mdpi/ic_sysbar_back_land.png
+++ b/packages/SystemUI/res/drawable-ldrtl-mdpi/ic_sysbar_back_land.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-ldrtl-sw600dp-hdpi/ic_sysbar_back.png b/packages/SystemUI/res/drawable-ldrtl-sw600dp-hdpi/ic_sysbar_back.png
deleted file mode 100644
index 80d60af..0000000
--- a/packages/SystemUI/res/drawable-ldrtl-sw600dp-hdpi/ic_sysbar_back.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-ldrtl-sw600dp-hdpi/ic_sysbar_back_land.png b/packages/SystemUI/res/drawable-ldrtl-sw600dp-hdpi/ic_sysbar_back_land.png
deleted file mode 100644
index 2dfe964..0000000
--- a/packages/SystemUI/res/drawable-ldrtl-sw600dp-hdpi/ic_sysbar_back_land.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-ldrtl-sw600dp-mdpi/ic_sysbar_back.png b/packages/SystemUI/res/drawable-ldrtl-sw600dp-mdpi/ic_sysbar_back.png
deleted file mode 100644
index fd1cc27..0000000
--- a/packages/SystemUI/res/drawable-ldrtl-sw600dp-mdpi/ic_sysbar_back.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-ldrtl-sw600dp-mdpi/ic_sysbar_back_land.png b/packages/SystemUI/res/drawable-ldrtl-sw600dp-mdpi/ic_sysbar_back_land.png
deleted file mode 100644
index 183aa0d..0000000
--- a/packages/SystemUI/res/drawable-ldrtl-sw600dp-mdpi/ic_sysbar_back_land.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-ldrtl-sw600dp-xhdpi/ic_sysbar_back.png b/packages/SystemUI/res/drawable-ldrtl-sw600dp-xhdpi/ic_sysbar_back.png
deleted file mode 100644
index 6f763a4..0000000
--- a/packages/SystemUI/res/drawable-ldrtl-sw600dp-xhdpi/ic_sysbar_back.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-ldrtl-sw600dp-xhdpi/ic_sysbar_back_land.png b/packages/SystemUI/res/drawable-ldrtl-sw600dp-xhdpi/ic_sysbar_back_land.png
deleted file mode 100644
index 3dc75a3..0000000
--- a/packages/SystemUI/res/drawable-ldrtl-sw600dp-xhdpi/ic_sysbar_back_land.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-ldrtl-sw600dp-xxhdpi/ic_sysbar_back.png b/packages/SystemUI/res/drawable-ldrtl-sw600dp-xxhdpi/ic_sysbar_back.png
deleted file mode 100644
index 83040fd..0000000
--- a/packages/SystemUI/res/drawable-ldrtl-sw600dp-xxhdpi/ic_sysbar_back.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-ldrtl-sw600dp-xxhdpi/ic_sysbar_back_land.png b/packages/SystemUI/res/drawable-ldrtl-sw600dp-xxhdpi/ic_sysbar_back_land.png
deleted file mode 100644
index 9917be4..0000000
--- a/packages/SystemUI/res/drawable-ldrtl-sw600dp-xxhdpi/ic_sysbar_back_land.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-ldrtl-xhdpi/ic_sysbar_back.png b/packages/SystemUI/res/drawable-ldrtl-xhdpi/ic_sysbar_back.png
index c116bbe..3d73184 100644
--- a/packages/SystemUI/res/drawable-ldrtl-xhdpi/ic_sysbar_back.png
+++ b/packages/SystemUI/res/drawable-ldrtl-xhdpi/ic_sysbar_back.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-ldrtl-xhdpi/ic_sysbar_back_land.png b/packages/SystemUI/res/drawable-ldrtl-xhdpi/ic_sysbar_back_land.png
index 1446850..1500ae5 100644
--- a/packages/SystemUI/res/drawable-ldrtl-xhdpi/ic_sysbar_back_land.png
+++ b/packages/SystemUI/res/drawable-ldrtl-xhdpi/ic_sysbar_back_land.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-ldrtl-xxhdpi/ic_sysbar_back.png b/packages/SystemUI/res/drawable-ldrtl-xxhdpi/ic_sysbar_back.png
index 83040fd..786935d 100644
--- a/packages/SystemUI/res/drawable-ldrtl-xxhdpi/ic_sysbar_back.png
+++ b/packages/SystemUI/res/drawable-ldrtl-xxhdpi/ic_sysbar_back.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-ldrtl-xxhdpi/ic_sysbar_back_land.png b/packages/SystemUI/res/drawable-ldrtl-xxhdpi/ic_sysbar_back_land.png
index 9917be4..a7fec49 100644
--- a/packages/SystemUI/res/drawable-ldrtl-xxhdpi/ic_sysbar_back_land.png
+++ b/packages/SystemUI/res/drawable-ldrtl-xxhdpi/ic_sysbar_back_land.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/btn_fab_recents.png b/packages/SystemUI/res/drawable-mdpi/btn_fab_recents.png
deleted file mode 100644
index 6bbed06..0000000
--- a/packages/SystemUI/res/drawable-mdpi/btn_fab_recents.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/ic_sysbar_back.png b/packages/SystemUI/res/drawable-mdpi/ic_sysbar_back.png
index 447c655..1d8c3af 100644
--- a/packages/SystemUI/res/drawable-mdpi/ic_sysbar_back.png
+++ b/packages/SystemUI/res/drawable-mdpi/ic_sysbar_back.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/ic_sysbar_back_ime.png b/packages/SystemUI/res/drawable-mdpi/ic_sysbar_back_ime.png
index d5ca622..47c6ebd 100644
--- a/packages/SystemUI/res/drawable-mdpi/ic_sysbar_back_ime.png
+++ b/packages/SystemUI/res/drawable-mdpi/ic_sysbar_back_ime.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/ic_sysbar_back_land.png b/packages/SystemUI/res/drawable-mdpi/ic_sysbar_back_land.png
index 47985de..12ceb90 100644
--- a/packages/SystemUI/res/drawable-mdpi/ic_sysbar_back_land.png
+++ b/packages/SystemUI/res/drawable-mdpi/ic_sysbar_back_land.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/ic_sysbar_home.png b/packages/SystemUI/res/drawable-mdpi/ic_sysbar_home.png
index 7b5fe8b..66de0ec 100644
--- a/packages/SystemUI/res/drawable-mdpi/ic_sysbar_home.png
+++ b/packages/SystemUI/res/drawable-mdpi/ic_sysbar_home.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/ic_sysbar_home_land.png b/packages/SystemUI/res/drawable-mdpi/ic_sysbar_home_land.png
index 9fcb705..dc8809e 100644
--- a/packages/SystemUI/res/drawable-mdpi/ic_sysbar_home_land.png
+++ b/packages/SystemUI/res/drawable-mdpi/ic_sysbar_home_land.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/ic_sysbar_lights_out_dot_large.png b/packages/SystemUI/res/drawable-mdpi/ic_sysbar_lights_out_dot_large.png
index 4d9c21c..48b96d8 100644
--- a/packages/SystemUI/res/drawable-mdpi/ic_sysbar_lights_out_dot_large.png
+++ b/packages/SystemUI/res/drawable-mdpi/ic_sysbar_lights_out_dot_large.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/ic_sysbar_lights_out_dot_small.png b/packages/SystemUI/res/drawable-mdpi/ic_sysbar_lights_out_dot_small.png
index 9f0570a..9bdc305 100644
--- a/packages/SystemUI/res/drawable-mdpi/ic_sysbar_lights_out_dot_small.png
+++ b/packages/SystemUI/res/drawable-mdpi/ic_sysbar_lights_out_dot_small.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/ic_sysbar_menu.png b/packages/SystemUI/res/drawable-mdpi/ic_sysbar_menu.png
index 23c24ba..35e7af4 100644
--- a/packages/SystemUI/res/drawable-mdpi/ic_sysbar_menu.png
+++ b/packages/SystemUI/res/drawable-mdpi/ic_sysbar_menu.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/ic_sysbar_menu_land.png b/packages/SystemUI/res/drawable-mdpi/ic_sysbar_menu_land.png
index 41c1acb..94c9743 100644
--- a/packages/SystemUI/res/drawable-mdpi/ic_sysbar_menu_land.png
+++ b/packages/SystemUI/res/drawable-mdpi/ic_sysbar_menu_land.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/ic_sysbar_recent.png b/packages/SystemUI/res/drawable-mdpi/ic_sysbar_recent.png
index 11a92f0..30c65f5 100644
--- a/packages/SystemUI/res/drawable-mdpi/ic_sysbar_recent.png
+++ b/packages/SystemUI/res/drawable-mdpi/ic_sysbar_recent.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/ic_sysbar_recent_land.png b/packages/SystemUI/res/drawable-mdpi/ic_sysbar_recent_land.png
index 7fb14a8..5178ac5 100644
--- a/packages/SystemUI/res/drawable-mdpi/ic_sysbar_recent_land.png
+++ b/packages/SystemUI/res/drawable-mdpi/ic_sysbar_recent_land.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw600dp-hdpi/ic_sysbar_back.png b/packages/SystemUI/res/drawable-sw600dp-hdpi/ic_sysbar_back.png
deleted file mode 100644
index eaac305..0000000
--- a/packages/SystemUI/res/drawable-sw600dp-hdpi/ic_sysbar_back.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw600dp-hdpi/ic_sysbar_back_ime.png b/packages/SystemUI/res/drawable-sw600dp-hdpi/ic_sysbar_back_ime.png
deleted file mode 100644
index b5d3739..0000000
--- a/packages/SystemUI/res/drawable-sw600dp-hdpi/ic_sysbar_back_ime.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw600dp-hdpi/ic_sysbar_back_land.png b/packages/SystemUI/res/drawable-sw600dp-hdpi/ic_sysbar_back_land.png
deleted file mode 100644
index 9915260..0000000
--- a/packages/SystemUI/res/drawable-sw600dp-hdpi/ic_sysbar_back_land.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw600dp-hdpi/ic_sysbar_home.png b/packages/SystemUI/res/drawable-sw600dp-hdpi/ic_sysbar_home.png
deleted file mode 100644
index 4a349e2..0000000
--- a/packages/SystemUI/res/drawable-sw600dp-hdpi/ic_sysbar_home.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw600dp-hdpi/ic_sysbar_home_land.png b/packages/SystemUI/res/drawable-sw600dp-hdpi/ic_sysbar_home_land.png
deleted file mode 100644
index d14da80..0000000
--- a/packages/SystemUI/res/drawable-sw600dp-hdpi/ic_sysbar_home_land.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw600dp-hdpi/ic_sysbar_lights_out_dot_large.png b/packages/SystemUI/res/drawable-sw600dp-hdpi/ic_sysbar_lights_out_dot_large.png
index 11e3b65..23ec6db 100644
--- a/packages/SystemUI/res/drawable-sw600dp-hdpi/ic_sysbar_lights_out_dot_large.png
+++ b/packages/SystemUI/res/drawable-sw600dp-hdpi/ic_sysbar_lights_out_dot_large.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw600dp-hdpi/ic_sysbar_lights_out_dot_small.png b/packages/SystemUI/res/drawable-sw600dp-hdpi/ic_sysbar_lights_out_dot_small.png
index afcc487..91a4d2d 100644
--- a/packages/SystemUI/res/drawable-sw600dp-hdpi/ic_sysbar_lights_out_dot_small.png
+++ b/packages/SystemUI/res/drawable-sw600dp-hdpi/ic_sysbar_lights_out_dot_small.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw600dp-hdpi/ic_sysbar_menu.png b/packages/SystemUI/res/drawable-sw600dp-hdpi/ic_sysbar_menu.png
deleted file mode 100644
index 4f5e723..0000000
--- a/packages/SystemUI/res/drawable-sw600dp-hdpi/ic_sysbar_menu.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw600dp-hdpi/ic_sysbar_menu_land.png b/packages/SystemUI/res/drawable-sw600dp-hdpi/ic_sysbar_menu_land.png
deleted file mode 100644
index 05b9b44..0000000
--- a/packages/SystemUI/res/drawable-sw600dp-hdpi/ic_sysbar_menu_land.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw600dp-hdpi/ic_sysbar_recent.png b/packages/SystemUI/res/drawable-sw600dp-hdpi/ic_sysbar_recent.png
deleted file mode 100644
index 2035323..0000000
--- a/packages/SystemUI/res/drawable-sw600dp-hdpi/ic_sysbar_recent.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw600dp-hdpi/ic_sysbar_recent_land.png b/packages/SystemUI/res/drawable-sw600dp-hdpi/ic_sysbar_recent_land.png
deleted file mode 100644
index 69b541b..0000000
--- a/packages/SystemUI/res/drawable-sw600dp-hdpi/ic_sysbar_recent_land.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw600dp-mdpi/ic_sysbar_back.png b/packages/SystemUI/res/drawable-sw600dp-mdpi/ic_sysbar_back.png
deleted file mode 100644
index 3f2b8b4..0000000
--- a/packages/SystemUI/res/drawable-sw600dp-mdpi/ic_sysbar_back.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw600dp-mdpi/ic_sysbar_back_ime.png b/packages/SystemUI/res/drawable-sw600dp-mdpi/ic_sysbar_back_ime.png
deleted file mode 100644
index 23e5e8f..0000000
--- a/packages/SystemUI/res/drawable-sw600dp-mdpi/ic_sysbar_back_ime.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw600dp-mdpi/ic_sysbar_back_land.png b/packages/SystemUI/res/drawable-sw600dp-mdpi/ic_sysbar_back_land.png
deleted file mode 100644
index 4b7f3ac..0000000
--- a/packages/SystemUI/res/drawable-sw600dp-mdpi/ic_sysbar_back_land.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw600dp-mdpi/ic_sysbar_home.png b/packages/SystemUI/res/drawable-sw600dp-mdpi/ic_sysbar_home.png
deleted file mode 100644
index 41054f6..0000000
--- a/packages/SystemUI/res/drawable-sw600dp-mdpi/ic_sysbar_home.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw600dp-mdpi/ic_sysbar_home_land.png b/packages/SystemUI/res/drawable-sw600dp-mdpi/ic_sysbar_home_land.png
deleted file mode 100644
index e4a7181..0000000
--- a/packages/SystemUI/res/drawable-sw600dp-mdpi/ic_sysbar_home_land.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw600dp-mdpi/ic_sysbar_lights_out_dot_large.png b/packages/SystemUI/res/drawable-sw600dp-mdpi/ic_sysbar_lights_out_dot_large.png
index 24442343..e450058 100644
--- a/packages/SystemUI/res/drawable-sw600dp-mdpi/ic_sysbar_lights_out_dot_large.png
+++ b/packages/SystemUI/res/drawable-sw600dp-mdpi/ic_sysbar_lights_out_dot_large.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw600dp-mdpi/ic_sysbar_lights_out_dot_small.png b/packages/SystemUI/res/drawable-sw600dp-mdpi/ic_sysbar_lights_out_dot_small.png
index a3e32f4c..edd53aa 100644
--- a/packages/SystemUI/res/drawable-sw600dp-mdpi/ic_sysbar_lights_out_dot_small.png
+++ b/packages/SystemUI/res/drawable-sw600dp-mdpi/ic_sysbar_lights_out_dot_small.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw600dp-mdpi/ic_sysbar_menu.png b/packages/SystemUI/res/drawable-sw600dp-mdpi/ic_sysbar_menu.png
deleted file mode 100644
index be678e0..0000000
--- a/packages/SystemUI/res/drawable-sw600dp-mdpi/ic_sysbar_menu.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw600dp-mdpi/ic_sysbar_menu_land.png b/packages/SystemUI/res/drawable-sw600dp-mdpi/ic_sysbar_menu_land.png
deleted file mode 100644
index 24d37e0..0000000
--- a/packages/SystemUI/res/drawable-sw600dp-mdpi/ic_sysbar_menu_land.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw600dp-mdpi/ic_sysbar_recent.png b/packages/SystemUI/res/drawable-sw600dp-mdpi/ic_sysbar_recent.png
deleted file mode 100644
index 9443656..0000000
--- a/packages/SystemUI/res/drawable-sw600dp-mdpi/ic_sysbar_recent.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw600dp-mdpi/ic_sysbar_recent_land.png b/packages/SystemUI/res/drawable-sw600dp-mdpi/ic_sysbar_recent_land.png
deleted file mode 100644
index c3c64f4..0000000
--- a/packages/SystemUI/res/drawable-sw600dp-mdpi/ic_sysbar_recent_land.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw600dp-xhdpi/ic_sysbar_back.png b/packages/SystemUI/res/drawable-sw600dp-xhdpi/ic_sysbar_back.png
deleted file mode 100644
index 0ab43ce..0000000
--- a/packages/SystemUI/res/drawable-sw600dp-xhdpi/ic_sysbar_back.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw600dp-xhdpi/ic_sysbar_back_ime.png b/packages/SystemUI/res/drawable-sw600dp-xhdpi/ic_sysbar_back_ime.png
deleted file mode 100644
index 3c58211..0000000
--- a/packages/SystemUI/res/drawable-sw600dp-xhdpi/ic_sysbar_back_ime.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw600dp-xhdpi/ic_sysbar_back_land.png b/packages/SystemUI/res/drawable-sw600dp-xhdpi/ic_sysbar_back_land.png
deleted file mode 100644
index 14ff6d3..0000000
--- a/packages/SystemUI/res/drawable-sw600dp-xhdpi/ic_sysbar_back_land.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw600dp-xhdpi/ic_sysbar_home.png b/packages/SystemUI/res/drawable-sw600dp-xhdpi/ic_sysbar_home.png
deleted file mode 100644
index eb74d0d..0000000
--- a/packages/SystemUI/res/drawable-sw600dp-xhdpi/ic_sysbar_home.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw600dp-xhdpi/ic_sysbar_home_land.png b/packages/SystemUI/res/drawable-sw600dp-xhdpi/ic_sysbar_home_land.png
deleted file mode 100644
index e29c9d0..0000000
--- a/packages/SystemUI/res/drawable-sw600dp-xhdpi/ic_sysbar_home_land.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw600dp-xhdpi/ic_sysbar_lights_out_dot_large.png b/packages/SystemUI/res/drawable-sw600dp-xhdpi/ic_sysbar_lights_out_dot_large.png
index 298b62f..d18e419 100644
--- a/packages/SystemUI/res/drawable-sw600dp-xhdpi/ic_sysbar_lights_out_dot_large.png
+++ b/packages/SystemUI/res/drawable-sw600dp-xhdpi/ic_sysbar_lights_out_dot_large.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw600dp-xhdpi/ic_sysbar_lights_out_dot_small.png b/packages/SystemUI/res/drawable-sw600dp-xhdpi/ic_sysbar_lights_out_dot_small.png
index 41f4b42..cb54780 100644
--- a/packages/SystemUI/res/drawable-sw600dp-xhdpi/ic_sysbar_lights_out_dot_small.png
+++ b/packages/SystemUI/res/drawable-sw600dp-xhdpi/ic_sysbar_lights_out_dot_small.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw600dp-xhdpi/ic_sysbar_menu.png b/packages/SystemUI/res/drawable-sw600dp-xhdpi/ic_sysbar_menu.png
deleted file mode 100644
index cfecdcf..0000000
--- a/packages/SystemUI/res/drawable-sw600dp-xhdpi/ic_sysbar_menu.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw600dp-xhdpi/ic_sysbar_menu_land.png b/packages/SystemUI/res/drawable-sw600dp-xhdpi/ic_sysbar_menu_land.png
deleted file mode 100644
index d98208a..0000000
--- a/packages/SystemUI/res/drawable-sw600dp-xhdpi/ic_sysbar_menu_land.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw600dp-xhdpi/ic_sysbar_recent.png b/packages/SystemUI/res/drawable-sw600dp-xhdpi/ic_sysbar_recent.png
deleted file mode 100644
index 71cc61b..0000000
--- a/packages/SystemUI/res/drawable-sw600dp-xhdpi/ic_sysbar_recent.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw600dp-xhdpi/ic_sysbar_recent_land.png b/packages/SystemUI/res/drawable-sw600dp-xhdpi/ic_sysbar_recent_land.png
deleted file mode 100644
index bdecf06..0000000
--- a/packages/SystemUI/res/drawable-sw600dp-xhdpi/ic_sysbar_recent_land.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw600dp-xxhdpi/ic_sysbar_back.png b/packages/SystemUI/res/drawable-sw600dp-xxhdpi/ic_sysbar_back.png
deleted file mode 100644
index 01edd86..0000000
--- a/packages/SystemUI/res/drawable-sw600dp-xxhdpi/ic_sysbar_back.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw600dp-xxhdpi/ic_sysbar_back_ime.png b/packages/SystemUI/res/drawable-sw600dp-xxhdpi/ic_sysbar_back_ime.png
deleted file mode 100644
index 52bd6e8..0000000
--- a/packages/SystemUI/res/drawable-sw600dp-xxhdpi/ic_sysbar_back_ime.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw600dp-xxhdpi/ic_sysbar_back_land.png b/packages/SystemUI/res/drawable-sw600dp-xxhdpi/ic_sysbar_back_land.png
deleted file mode 100644
index b0dd0f0..0000000
--- a/packages/SystemUI/res/drawable-sw600dp-xxhdpi/ic_sysbar_back_land.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw600dp-xxhdpi/ic_sysbar_home.png b/packages/SystemUI/res/drawable-sw600dp-xxhdpi/ic_sysbar_home.png
deleted file mode 100644
index b5c189d..0000000
--- a/packages/SystemUI/res/drawable-sw600dp-xxhdpi/ic_sysbar_home.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw600dp-xxhdpi/ic_sysbar_home_land.png b/packages/SystemUI/res/drawable-sw600dp-xxhdpi/ic_sysbar_home_land.png
deleted file mode 100644
index 42e9e31..0000000
--- a/packages/SystemUI/res/drawable-sw600dp-xxhdpi/ic_sysbar_home_land.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw600dp-xxhdpi/ic_sysbar_lights_out_dot_large.png b/packages/SystemUI/res/drawable-sw600dp-xxhdpi/ic_sysbar_lights_out_dot_large.png
index 5ef7798..00a751c 100644
--- a/packages/SystemUI/res/drawable-sw600dp-xxhdpi/ic_sysbar_lights_out_dot_large.png
+++ b/packages/SystemUI/res/drawable-sw600dp-xxhdpi/ic_sysbar_lights_out_dot_large.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw600dp-xxhdpi/ic_sysbar_lights_out_dot_small.png b/packages/SystemUI/res/drawable-sw600dp-xxhdpi/ic_sysbar_lights_out_dot_small.png
index 4a98e31..dfc8f96 100644
--- a/packages/SystemUI/res/drawable-sw600dp-xxhdpi/ic_sysbar_lights_out_dot_small.png
+++ b/packages/SystemUI/res/drawable-sw600dp-xxhdpi/ic_sysbar_lights_out_dot_small.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw600dp-xxhdpi/ic_sysbar_menu.png b/packages/SystemUI/res/drawable-sw600dp-xxhdpi/ic_sysbar_menu.png
deleted file mode 100644
index 669d8ba..0000000
--- a/packages/SystemUI/res/drawable-sw600dp-xxhdpi/ic_sysbar_menu.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw600dp-xxhdpi/ic_sysbar_menu_land.png b/packages/SystemUI/res/drawable-sw600dp-xxhdpi/ic_sysbar_menu_land.png
deleted file mode 100644
index 0fbf1f6..0000000
--- a/packages/SystemUI/res/drawable-sw600dp-xxhdpi/ic_sysbar_menu_land.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw600dp-xxhdpi/ic_sysbar_recent.png b/packages/SystemUI/res/drawable-sw600dp-xxhdpi/ic_sysbar_recent.png
deleted file mode 100644
index 023b94c..0000000
--- a/packages/SystemUI/res/drawable-sw600dp-xxhdpi/ic_sysbar_recent.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw600dp-xxhdpi/ic_sysbar_recent_land.png b/packages/SystemUI/res/drawable-sw600dp-xxhdpi/ic_sysbar_recent_land.png
deleted file mode 100644
index 5884492..0000000
--- a/packages/SystemUI/res/drawable-sw600dp-xxhdpi/ic_sysbar_recent_land.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/btn_fab_recents.png b/packages/SystemUI/res/drawable-xhdpi/btn_fab_recents.png
deleted file mode 100644
index 4cdd0aa..0000000
--- a/packages/SystemUI/res/drawable-xhdpi/btn_fab_recents.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_back.png b/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_back.png
index 4956aad..a356285 100644
--- a/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_back.png
+++ b/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_back.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_back_ime.png b/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_back_ime.png
index e9a6223..42893ff 100644
--- a/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_back_ime.png
+++ b/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_back_ime.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_back_land.png b/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_back_land.png
index e9767a1..98be526 100644
--- a/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_back_land.png
+++ b/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_back_land.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_home.png b/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_home.png
index acaf32d..ba2d0b2 100644
--- a/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_home.png
+++ b/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_home.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_home_land.png b/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_home_land.png
index 20cb101..eed3f54 100644
--- a/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_home_land.png
+++ b/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_home_land.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_lights_out_dot_large.png b/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_lights_out_dot_large.png
index e62dece..e49db34 100644
--- a/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_lights_out_dot_large.png
+++ b/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_lights_out_dot_large.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_lights_out_dot_small.png b/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_lights_out_dot_small.png
index 958b2fe..0b75558 100644
--- a/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_lights_out_dot_small.png
+++ b/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_lights_out_dot_small.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_menu.png b/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_menu.png
index cc620a2..69a018d 100644
--- a/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_menu.png
+++ b/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_menu.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_menu_land.png b/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_menu_land.png
index aa8a60e..8a7ac4f 100644
--- a/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_menu_land.png
+++ b/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_menu_land.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_recent.png b/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_recent.png
index 88d6a41..94a74b1 100644
--- a/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_recent.png
+++ b/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_recent.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_recent_land.png b/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_recent_land.png
index 8acdd3c..22ae09d 100644
--- a/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_recent_land.png
+++ b/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_recent_land.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xxhdpi/btn_fab_recents.png b/packages/SystemUI/res/drawable-xxhdpi/btn_fab_recents.png
deleted file mode 100644
index 2220d60..0000000
--- a/packages/SystemUI/res/drawable-xxhdpi/btn_fab_recents.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xxhdpi/ic_sysbar_back.png b/packages/SystemUI/res/drawable-xxhdpi/ic_sysbar_back.png
index 01edd86..29da099 100644
--- a/packages/SystemUI/res/drawable-xxhdpi/ic_sysbar_back.png
+++ b/packages/SystemUI/res/drawable-xxhdpi/ic_sysbar_back.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xxhdpi/ic_sysbar_back_ime.png b/packages/SystemUI/res/drawable-xxhdpi/ic_sysbar_back_ime.png
index 52bd6e8..ada2879 100644
--- a/packages/SystemUI/res/drawable-xxhdpi/ic_sysbar_back_ime.png
+++ b/packages/SystemUI/res/drawable-xxhdpi/ic_sysbar_back_ime.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xxhdpi/ic_sysbar_back_land.png b/packages/SystemUI/res/drawable-xxhdpi/ic_sysbar_back_land.png
index b0dd0f0..c819545 100644
--- a/packages/SystemUI/res/drawable-xxhdpi/ic_sysbar_back_land.png
+++ b/packages/SystemUI/res/drawable-xxhdpi/ic_sysbar_back_land.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xxhdpi/ic_sysbar_home.png b/packages/SystemUI/res/drawable-xxhdpi/ic_sysbar_home.png
index b5c189d..59b32f2 100644
--- a/packages/SystemUI/res/drawable-xxhdpi/ic_sysbar_home.png
+++ b/packages/SystemUI/res/drawable-xxhdpi/ic_sysbar_home.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xxhdpi/ic_sysbar_home_land.png b/packages/SystemUI/res/drawable-xxhdpi/ic_sysbar_home_land.png
index 42e9e31..6075caf 100644
--- a/packages/SystemUI/res/drawable-xxhdpi/ic_sysbar_home_land.png
+++ b/packages/SystemUI/res/drawable-xxhdpi/ic_sysbar_home_land.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xxhdpi/ic_sysbar_lights_out_dot_large.png b/packages/SystemUI/res/drawable-xxhdpi/ic_sysbar_lights_out_dot_large.png
index 55a266f..b91704a 100644
--- a/packages/SystemUI/res/drawable-xxhdpi/ic_sysbar_lights_out_dot_large.png
+++ b/packages/SystemUI/res/drawable-xxhdpi/ic_sysbar_lights_out_dot_large.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xxhdpi/ic_sysbar_lights_out_dot_small.png b/packages/SystemUI/res/drawable-xxhdpi/ic_sysbar_lights_out_dot_small.png
index 97d1fbc..d83d285 100644
--- a/packages/SystemUI/res/drawable-xxhdpi/ic_sysbar_lights_out_dot_small.png
+++ b/packages/SystemUI/res/drawable-xxhdpi/ic_sysbar_lights_out_dot_small.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xxhdpi/ic_sysbar_menu.png b/packages/SystemUI/res/drawable-xxhdpi/ic_sysbar_menu.png
index 669d8ba..a37ca5d 100644
--- a/packages/SystemUI/res/drawable-xxhdpi/ic_sysbar_menu.png
+++ b/packages/SystemUI/res/drawable-xxhdpi/ic_sysbar_menu.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xxhdpi/ic_sysbar_menu_land.png b/packages/SystemUI/res/drawable-xxhdpi/ic_sysbar_menu_land.png
index 0fbf1f6..62f44e8 100644
--- a/packages/SystemUI/res/drawable-xxhdpi/ic_sysbar_menu_land.png
+++ b/packages/SystemUI/res/drawable-xxhdpi/ic_sysbar_menu_land.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xxhdpi/ic_sysbar_recent.png b/packages/SystemUI/res/drawable-xxhdpi/ic_sysbar_recent.png
index 023b94c..ba66d27 100644
--- a/packages/SystemUI/res/drawable-xxhdpi/ic_sysbar_recent.png
+++ b/packages/SystemUI/res/drawable-xxhdpi/ic_sysbar_recent.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xxhdpi/ic_sysbar_recent_land.png b/packages/SystemUI/res/drawable-xxhdpi/ic_sysbar_recent_land.png
index 5884492..bccda1b 100644
--- a/packages/SystemUI/res/drawable-xxhdpi/ic_sysbar_recent_land.png
+++ b/packages/SystemUI/res/drawable-xxhdpi/ic_sysbar_recent_land.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable/recents_lock_to_task_button_bg.xml b/packages/SystemUI/res/drawable/recents_lock_to_task_button_bg.xml
index 6424a65..8a8164a 100644
--- a/packages/SystemUI/res/drawable/recents_lock_to_task_button_bg.xml
+++ b/packages/SystemUI/res/drawable/recents_lock_to_task_button_bg.xml
@@ -16,5 +16,11 @@
 
 <ripple xmlns:android="http://schemas.android.com/apk/res/android"
      android:color="#ff9cdfd9">
-    <item android:drawable="@drawable/btn_fab_recents" />
+     <item>
+          <shape android:shape="oval">
+               <solid android:color="#9cc8c4" />
+               <size android:width="@dimen/recents_lock_to_app_size"
+                     android:height="@dimen/recents_lock_to_app_size" />
+          </shape>
+     </item>
 </ripple>
\ No newline at end of file
diff --git a/packages/SystemUI/res/layout-land/status_bar_recent_panel.xml b/packages/SystemUI/res/layout-land/status_bar_recent_panel.xml
index 0c0be29..b5d2f86 100644
--- a/packages/SystemUI/res/layout-land/status_bar_recent_panel.xml
+++ b/packages/SystemUI/res/layout-land/status_bar_recent_panel.xml
@@ -20,7 +20,7 @@
 
 <com.android.systemui.recent.RecentsPanelView
     xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:systemui="http://schemas.android.com/apk/res/com.android.systemui"
+    xmlns:systemui="http://schemas.android.com/apk/res-auto"
     android:id="@+id/recents_root"
     android:layout_height="match_parent"
     android:layout_width="match_parent"
diff --git a/packages/SystemUI/res/layout-sw600dp/navigation_bar.xml b/packages/SystemUI/res/layout-sw600dp/navigation_bar.xml
index c2733fb..5c776e6 100644
--- a/packages/SystemUI/res/layout-sw600dp/navigation_bar.xml
+++ b/packages/SystemUI/res/layout-sw600dp/navigation_bar.xml
@@ -19,7 +19,7 @@
 <!--  navigation bar for sw600dp (small tablets) -->
 <com.android.systemui.statusbar.phone.NavigationBarView
     xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:systemui="http://schemas.android.com/apk/res/com.android.systemui"
+    xmlns:systemui="http://schemas.android.com/apk/res-auto"
     android:layout_height="match_parent"
     android:layout_width="match_parent"
     android:background="@drawable/system_bar_background"
diff --git a/packages/SystemUI/res/layout/navigation_bar.xml b/packages/SystemUI/res/layout/navigation_bar.xml
index 2e38b20..898389d 100644
--- a/packages/SystemUI/res/layout/navigation_bar.xml
+++ b/packages/SystemUI/res/layout/navigation_bar.xml
@@ -20,7 +20,7 @@
 
 <com.android.systemui.statusbar.phone.NavigationBarView
     xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:systemui="http://schemas.android.com/apk/res/com.android.systemui"
+    xmlns:systemui="http://schemas.android.com/apk/res-auto"
     android:layout_height="match_parent"
     android:layout_width="match_parent"
     android:background="@drawable/system_bar_background"
@@ -98,6 +98,7 @@
                     android:contentDescription="@string/accessibility_menu"
                     android:src="@drawable/ic_sysbar_menu"
                     android:visibility="invisible"
+                    android:scaleType="centerInside"
                     android:layout_gravity="end"
                     systemui:keyCode="82" />
 
@@ -210,6 +211,7 @@
                     android:layout_height="40dp"
                     android:contentDescription="@string/accessibility_menu"
                     android:src="@drawable/ic_sysbar_menu_land"
+                    android:scaleType="centerInside"
                     android:layout_gravity="top"
                     android:visibility="invisible"
                     systemui:keyCode="82" />
diff --git a/packages/SystemUI/res/layout/quick_settings_brightness_dialog.xml b/packages/SystemUI/res/layout/quick_settings_brightness_dialog.xml
index f776a87..a996260 100644
--- a/packages/SystemUI/res/layout/quick_settings_brightness_dialog.xml
+++ b/packages/SystemUI/res/layout/quick_settings_brightness_dialog.xml
@@ -14,7 +14,7 @@
      limitations under the License.
 -->
 <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:systemui="http://schemas.android.com/apk/res/com.android.systemui"
+    xmlns:systemui="http://schemas.android.com/apk/res-auto"
     android:paddingLeft="16dp"
     android:paddingRight="16dp"
     style="@style/BrightnessDialogContainer">
diff --git a/packages/SystemUI/res/layout/recents_task_view.xml b/packages/SystemUI/res/layout/recents_task_view.xml
index d1d3828..9c6f67c 100644
--- a/packages/SystemUI/res/layout/recents_task_view.xml
+++ b/packages/SystemUI/res/layout/recents_task_view.xml
@@ -29,8 +29,8 @@
         <include layout="@layout/recents_task_view_header" />
         <FrameLayout
             android:id="@+id/lock_to_app_fab"
-            android:layout_width="48dp"
-            android:layout_height="48dp"
+            android:layout_width="@dimen/recents_lock_to_app_size"
+            android:layout_height="@dimen/recents_lock_to_app_size"
             android:layout_gravity="bottom|right"
             android:layout_marginRight="15dp"
             android:layout_marginBottom="15dp"
@@ -38,8 +38,8 @@
             android:contentDescription="@string/recents_lock_to_app_button_label"
             android:background="@drawable/recents_lock_to_task_button_bg">
             <ImageView
-                android:layout_width="24dp"
-                android:layout_height="24dp"
+                android:layout_width="@dimen/recents_lock_to_app_icon_size"
+                android:layout_height="@dimen/recents_lock_to_app_icon_size"
                 android:layout_gravity="center"
                 android:src="@drawable/recents_lock_to_app_pin" />
         </FrameLayout>
diff --git a/packages/SystemUI/res/layout/status_bar_expanded_header.xml b/packages/SystemUI/res/layout/status_bar_expanded_header.xml
index 9912e89c..2fb7cdbf 100644
--- a/packages/SystemUI/res/layout/status_bar_expanded_header.xml
+++ b/packages/SystemUI/res/layout/status_bar_expanded_header.xml
@@ -18,7 +18,7 @@
 <!-- Extends RelativeLayout -->
 <com.android.systemui.statusbar.phone.StatusBarHeaderView
     xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:systemui="http://schemas.android.com/apk/res/com.android.systemui"
+    xmlns:systemui="http://schemas.android.com/apk/res-auto"
     android:id="@+id/header"
     android:layout_width="@dimen/notification_panel_width"
     android:layout_height="@dimen/status_bar_header_height"
diff --git a/packages/SystemUI/res/layout/status_bar_recent_panel.xml b/packages/SystemUI/res/layout/status_bar_recent_panel.xml
index 2f3968d..588873a 100644
--- a/packages/SystemUI/res/layout/status_bar_recent_panel.xml
+++ b/packages/SystemUI/res/layout/status_bar_recent_panel.xml
@@ -20,7 +20,7 @@
 
 <com.android.systemui.recent.RecentsPanelView
     xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:systemui="http://schemas.android.com/apk/res/com.android.systemui"
+    xmlns:systemui="http://schemas.android.com/apk/res-auto"
     android:id="@+id/recents_root"
     android:layout_height="match_parent"
     android:layout_width="match_parent"
diff --git a/packages/SystemUI/res/values/config.xml b/packages/SystemUI/res/values/config.xml
index 44e0fd1..1152eea 100644
--- a/packages/SystemUI/res/values/config.xml
+++ b/packages/SystemUI/res/values/config.xml
@@ -144,42 +144,61 @@
 
     <!-- The duration in seconds to wait before the dismiss buttons are shown. -->
     <integer name="recents_task_bar_dismiss_delay_seconds">1</integer>
+
     <!-- The min animation duration for animating views that are currently visible. -->
     <integer name="recents_filter_animate_current_views_duration">250</integer>
+
     <!-- The min animation duration for animating views that are newly visible. -->
     <integer name="recents_filter_animate_new_views_duration">250</integer>
-    <!-- The min animation duration for animating the task bar in. -->
-    <integer name="recents_animate_task_bar_enter_duration">225</integer>
-    <!-- The animation delay for animating the first task in. This should roughly be the animation
-     duration of the transition in to recents. -->
-    <integer name="recents_animate_task_bar_enter_delay">275</integer>
-    <!-- The min animation duration for animating the task bar out. -->
-    <integer name="recents_animate_task_exit_to_home_duration">225</integer>
-    <!-- The min animation duration for animating the task bar out. -->
-    <integer name="recents_animate_task_bar_exit_duration">125</integer>
-    <!-- The animation delay for animating the first task in. This should roughly be the animation
-     duration of the transition in to recents from home. -->
-    <integer name="recents_animate_task_enter_from_home_delay">150</integer>
-    <!-- The min animation duration for animating the task in when transitioning from home. -->
-    <integer name="recents_animate_task_enter_from_home_duration">250</integer>
-    <!-- The animation stagger to apply to each task animation when transitioning from home. -->
-    <integer name="recents_animate_task_enter_from_home_stagger_delay">12</integer>
-    <!-- The short duration when animating in/out the lock to app button. -->
-    <integer name="recents_animate_lock_to_app_button_short_duration">150</integer>
-    <!-- The long duration when animating in/out the lock to app button. -->
-    <integer name="recents_animate_lock_to_app_button_long_duration">300</integer>
+
+    <!-- The duration of the window transition when coming to Recents from an app.
+         In order to defer the in-app animations until after the transition is complete,
+         we also need to use this value as the starting delay when animating the first
+         task decorations in. -->
+    <integer name="recents_enter_from_app_transition_duration">325</integer>
+
+    <!-- The duration for animating the task decorations in after transitioning from an app. -->
+    <integer name="recents_task_enter_from_app_duration">200</integer>
+
+    <!-- The duration for animating the task decorations out before transitioning to an app. -->
+    <integer name="recents_task_exit_to_app_duration">125</integer>
+
+    <!-- The duration of the window transition when coming to Recents from the Launcher.
+         In order to defer the in-app animations until after the transition is complete,
+         we also need to use this value as the starting delay when animating the task views
+         in from the bottom of the screen. -->
+    <integer name="recents_enter_from_home_transition_duration">100</integer>
+
+    <!-- The duration for animating the task from the bottom of the screen when transitioning
+     from home. -->
+    <integer name="recents_task_enter_from_home_duration">225</integer>
+
+    <!-- The stagger for each task when animating the task from the bottom of the screen when 
+     transitioning from home. -->
+    <integer name="recents_task_enter_from_home_stagger_delay">12</integer>
+
+    <!-- The duration of the animation of the tasks to the bottom of the screen when leaving
+     Recents to go back to the Launcher. -->
+    <integer name="recents_task_exit_to_home_duration">225</integer>
+
     <!-- The min animation duration for animating the nav bar scrim in. -->
     <integer name="recents_nav_bar_scrim_enter_duration">400</integer>
+
     <!-- The animation duration for animating the removal of a task view. -->
     <integer name="recents_animate_task_view_remove_duration">250</integer>
+
     <!-- The animation duration for scrolling the stack to a particular item. -->
     <integer name="recents_animate_task_stack_scroll_duration">225</integer>
+
     <!-- The minimum alpha for the dim applied to cards that go deeper into the stack. -->
     <integer name="recents_max_task_stack_view_dim">96</integer>
+
     <!-- The delay to enforce between each alt-tab key press. -->
     <integer name="recents_alt_tab_key_delay">200</integer>
+
     <!-- Transposes the search bar layout in landscape. -->
     <bool name="recents_has_transposed_search_bar">true</bool>
+
     <!-- Transposes the nav bar in landscape (only used for purposes of layout). -->
     <bool name="recents_has_transposed_nav_bar">true</bool>
     <!-- Svelte specific logic, see RecentsConfiguration.SVELTE_* constants. -->
diff --git a/packages/SystemUI/res/values/dimens.xml b/packages/SystemUI/res/values/dimens.xml
index 3d9f723..1143553 100644
--- a/packages/SystemUI/res/values/dimens.xml
+++ b/packages/SystemUI/res/values/dimens.xml
@@ -226,9 +226,6 @@
     <!-- The amount of highlight to make on each task view. -->
     <dimen name="recents_task_view_highlight">1.5dp</dimen>
 
-    <!-- The height of the lock-to-app button. -->
-    <dimen name="recents_task_view_lock_to_app_button_height">48dp</dimen>
-
     <!-- The amount to offset when animating into an affiliate group. -->
     <dimen name="recents_task_view_affiliate_group_enter_offset">64dp</dimen>
 
@@ -257,6 +254,12 @@
     <!-- The min alpha to apply to a task affiliation group color. -->
     <item name="recents_task_affiliation_color_min_alpha_percentage" format="float" type="dimen">0.6</item>
 
+    <!-- The size of the lock-to-app button. -->
+    <dimen name="recents_lock_to_app_size">56dp</dimen>
+
+    <!-- The size of the lock-to-app button icon. -->
+    <dimen name="recents_lock_to_app_icon_size">28dp</dimen>
+
     <!-- Space reserved for the cards behind the top card in the top stack -->
     <dimen name="top_stack_peek_amount">12dp</dimen>
 
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/BluetoothTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/BluetoothTile.java
index 4d77348..1bc1d77 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/BluetoothTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/BluetoothTile.java
@@ -77,6 +77,10 @@
 
     @Override
     protected void handleSecondaryClick() {
+        if (!mState.value) {
+            mState.value = true;
+            mController.setBluetoothEnabled(true);
+        }
         showDetail(true);
     }
 
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/CellularTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/CellularTile.java
index 178590b..80ddd4a 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/CellularTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/CellularTile.java
@@ -29,7 +29,8 @@
 import com.android.systemui.qs.QSTileView;
 import com.android.systemui.qs.SignalTileView;
 import com.android.systemui.statusbar.policy.NetworkController;
-import com.android.systemui.statusbar.policy.NetworkController.DataUsageInfo;
+import com.android.systemui.statusbar.policy.NetworkController.MobileDataController;
+import com.android.systemui.statusbar.policy.NetworkController.MobileDataController.DataUsageInfo;
 import com.android.systemui.statusbar.policy.NetworkController.NetworkSignalChangedCallback;
 
 /** Quick settings tile: Cellular **/
@@ -38,11 +39,13 @@
             "com.android.settings", "com.android.settings.Settings$DataUsageSummaryActivity"));
 
     private final NetworkController mController;
+    private final MobileDataController mDataController;
     private final CellularDetailAdapter mDetailAdapter;
 
     public CellularTile(Host host) {
         super(host);
         mController = host.getNetworkController();
+        mDataController = mController.getMobileDataController();
         mDetailAdapter = new CellularDetailAdapter();
     }
 
@@ -72,7 +75,7 @@
 
     @Override
     protected void handleClick() {
-        if (mController.isMobileDataSupported()) {
+        if (mDataController.isMobileDataSupported()) {
             showDetail(true);
         } else {
             mHost.startSettingsActivity(CELLULAR_SETTINGS);
@@ -199,7 +202,8 @@
 
         @Override
         public Boolean getToggleState() {
-            return mController.isMobileDataSupported() ? mController.isMobileDataEnabled() : null;
+            return mDataController.isMobileDataSupported()
+                    ? mDataController.isMobileDataEnabled() : null;
         }
 
         @Override
@@ -209,7 +213,7 @@
 
         @Override
         public void setToggleState(boolean state) {
-            mController.setMobileDataEnabled(state);
+            mDataController.setMobileDataEnabled(state);
         }
 
         @Override
@@ -217,7 +221,7 @@
             final DataUsageDetailView v = (DataUsageDetailView) (convertView != null
                     ? convertView
                     : LayoutInflater.from(mContext).inflate(R.layout.data_usage, parent, false));
-            final DataUsageInfo info = mController.getDataUsageInfo();
+            final DataUsageInfo info = mDataController.getDataUsageInfo();
             if (info == null) return v;
             v.bind(info);
             return v;
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/DataUsageDetailView.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/DataUsageDetailView.java
index 7bdb58f..eb816b7 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/DataUsageDetailView.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/DataUsageDetailView.java
@@ -20,7 +20,6 @@
 import android.content.res.Configuration;
 import android.content.res.Resources;
 import android.util.AttributeSet;
-import android.util.TypedValue;
 import android.view.View;
 import android.widget.LinearLayout;
 import android.widget.TextView;
@@ -61,7 +60,7 @@
                 R.dimen.qs_data_usage_text_size);
     }
 
-    public void bind(NetworkController.DataUsageInfo info) {
+    public void bind(NetworkController.MobileDataController.DataUsageInfo info) {
         final Resources res = mContext.getResources();
         final int titleId;
         final long bytes;
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/WifiTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/WifiTile.java
index 7aa884e..4fb1189 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/WifiTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/WifiTile.java
@@ -31,7 +31,8 @@
 import com.android.systemui.qs.QSTileView;
 import com.android.systemui.qs.SignalTileView;
 import com.android.systemui.statusbar.policy.NetworkController;
-import com.android.systemui.statusbar.policy.NetworkController.AccessPoint;
+import com.android.systemui.statusbar.policy.NetworkController.AccessPointController;
+import com.android.systemui.statusbar.policy.NetworkController.AccessPointController.AccessPoint;
 import com.android.systemui.statusbar.policy.NetworkController.NetworkSignalChangedCallback;
 
 /** Quick settings tile: Wifi **/
@@ -39,12 +40,14 @@
     private static final Intent WIFI_SETTINGS = new Intent(Settings.ACTION_WIFI_SETTINGS);
 
     private final NetworkController mController;
+    private final AccessPointController mWifiController;
     private final WifiDetailAdapter mDetailAdapter;
     private final QSTile.SignalState mStateBeforeClick = newTileState();
 
     public WifiTile(Host host) {
         super(host);
         mController = host.getNetworkController();
+        mWifiController = mController.getAccessPointController();
         mDetailAdapter = new WifiDetailAdapter();
     }
 
@@ -62,10 +65,10 @@
     public void setListening(boolean listening) {
         if (listening) {
             mController.addNetworkSignalChangedCallback(mCallback);
-            mController.addAccessPointCallback(mDetailAdapter);
+            mWifiController.addAccessPointCallback(mDetailAdapter);
         } else {
             mController.removeNetworkSignalChangedCallback(mCallback);
-            mController.removeAccessPointCallback(mDetailAdapter);
+            mWifiController.removeAccessPointCallback(mDetailAdapter);
         }
     }
 
@@ -87,7 +90,7 @@
 
     @Override
     protected void handleSecondaryClick() {
-        if (!mController.canConfigWifi()) {
+        if (!mWifiController.canConfigWifi()) {
             mHost.startSettingsActivity(new Intent(Settings.ACTION_WIFI_SETTINGS));
             return;
         }
@@ -231,7 +234,7 @@
     };
 
     private final class WifiDetailAdapter implements DetailAdapter,
-            NetworkController.AccessPointCallback, QSDetailItems.Callback {
+            NetworkController.AccessPointController.AccessPointCallback, QSDetailItems.Callback {
 
         private QSDetailItems mItems;
         private AccessPoint[] mAccessPoints;
@@ -261,7 +264,7 @@
         public View createDetailView(Context context, View convertView, ViewGroup parent) {
             if (DEBUG) Log.d(TAG, "createDetailView convertView=" + (convertView != null));
             mAccessPoints = null;
-            mController.scanForAccessPoints();
+            mWifiController.scanForAccessPoints();
             fireScanStateChanged(true);
             mItems = QSDetailItems.convertOrInflate(context, convertView, parent);
             mItems.setTagSuffix("Wifi");
@@ -287,7 +290,7 @@
             if (item == null || item.tag == null) return;
             final AccessPoint ap = (AccessPoint) item.tag;
             if (!ap.isConnected) {
-                if (mController.connect(ap)) {
+                if (mWifiController.connect(ap)) {
                     mHost.collapsePanels();
                 }
             }
diff --git a/packages/SystemUI/src/com/android/systemui/recents/RecentsActivity.java b/packages/SystemUI/src/com/android/systemui/recents/RecentsActivity.java
index d1eadd8..676f1ab 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/RecentsActivity.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/RecentsActivity.java
@@ -431,8 +431,6 @@
         // Update if we are getting a configuration change
         if (savedInstanceState != null) {
             // Update RecentsConfiguration
-            mConfig = RecentsConfiguration.reinitialize(this,
-                    RecentsTaskLoader.getInstance().getSystemServicesProxy());
             mConfig.updateOnConfigurationChange();
             // Trigger the enter animation
             onEnterAnimationTriggered();
diff --git a/packages/SystemUI/src/com/android/systemui/recents/RecentsConfiguration.java b/packages/SystemUI/src/com/android/systemui/recents/RecentsConfiguration.java
index 43d9dc1..2b33d14 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/RecentsConfiguration.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/RecentsConfiguration.java
@@ -86,11 +86,15 @@
     public float taskStackWidthPaddingPct;
     public float taskStackOverscrollPct;
 
+    /** Transitions */
+    public int transitionEnterFromAppDelay;
+    public int transitionEnterFromHomeDelay;
+
     /** Task view animation and styles */
-    public int taskViewEnterFromHomeDelay;
+    public int taskViewEnterFromAppDuration;
     public int taskViewEnterFromHomeDuration;
     public int taskViewEnterFromHomeStaggerDelay;
-    public int taskViewEnterFromHomeStaggerDuration;
+    public int taskViewExitToAppDuration;
     public int taskViewExitToHomeDuration;
     public int taskViewRemoveAnimDuration;
     public int taskViewRemoveAnimTranslationXPx;
@@ -110,16 +114,8 @@
 
     /** Task bar size & animations */
     public int taskBarHeight;
-    public int taskBarEnterAnimDuration;
-    public int taskBarEnterAnimDelay;
-    public int taskBarExitAnimDuration;
     public int taskBarDismissDozeDelaySeconds;
 
-    /** Lock to app */
-    public int taskViewLockToAppButtonHeight;
-    public int taskViewLockToAppShortAnimDuration;
-    public int taskViewLockToAppLongAnimDuration;
-
     /** Nav bar scrim */
     public int navBarScrimEnterDuration;
 
@@ -226,15 +222,23 @@
         taskStackMaxDim = res.getInteger(R.integer.recents_max_task_stack_view_dim);
         taskStackTopPaddingPx = res.getDimensionPixelSize(R.dimen.recents_stack_top_padding);
 
+        // Transition
+        transitionEnterFromAppDelay =
+                res.getInteger(R.integer.recents_enter_from_app_transition_duration);
+        transitionEnterFromHomeDelay =
+                res.getInteger(R.integer.recents_enter_from_home_transition_duration);
+
         // Task view animation and styles
-        taskViewEnterFromHomeDelay =
-                res.getInteger(R.integer.recents_animate_task_enter_from_home_delay);
+        taskViewEnterFromAppDuration =
+                res.getInteger(R.integer.recents_task_enter_from_app_duration);
         taskViewEnterFromHomeDuration =
-                res.getInteger(R.integer.recents_animate_task_enter_from_home_duration);
+                res.getInteger(R.integer.recents_task_enter_from_home_duration);
         taskViewEnterFromHomeStaggerDelay =
-                res.getInteger(R.integer.recents_animate_task_enter_from_home_stagger_delay);
+                res.getInteger(R.integer.recents_task_enter_from_home_stagger_delay);
+        taskViewExitToAppDuration =
+                res.getInteger(R.integer.recents_task_exit_to_app_duration);
         taskViewExitToHomeDuration =
-                res.getInteger(R.integer.recents_animate_task_exit_to_home_duration);
+                res.getInteger(R.integer.recents_task_exit_to_home_duration);
         taskViewRemoveAnimDuration =
                 res.getInteger(R.integer.recents_animate_task_view_remove_duration);
         taskViewRemoveAnimTranslationXPx =
@@ -265,23 +269,9 @@
 
         // Task bar size & animations
         taskBarHeight = res.getDimensionPixelSize(R.dimen.recents_task_bar_height);
-        taskBarEnterAnimDuration =
-                res.getInteger(R.integer.recents_animate_task_bar_enter_duration);
-        taskBarEnterAnimDelay =
-                res.getInteger(R.integer.recents_animate_task_bar_enter_delay);
-        taskBarExitAnimDuration =
-                res.getInteger(R.integer.recents_animate_task_bar_exit_duration);
         taskBarDismissDozeDelaySeconds =
                 res.getInteger(R.integer.recents_task_bar_dismiss_delay_seconds);
 
-        // Lock to app
-        taskViewLockToAppButtonHeight =
-                res.getDimensionPixelSize(R.dimen.recents_task_view_lock_to_app_button_height);
-        taskViewLockToAppShortAnimDuration =
-                res.getInteger(R.integer.recents_animate_lock_to_app_button_short_duration);
-        taskViewLockToAppLongAnimDuration =
-                res.getInteger(R.integer.recents_animate_lock_to_app_button_long_duration);
-
         // Nav bar scrim
         navBarScrimEnterDuration =
                 res.getInteger(R.integer.recents_nav_bar_scrim_enter_duration);
diff --git a/packages/SystemUI/src/com/android/systemui/recents/model/RecentsTaskLoader.java b/packages/SystemUI/src/com/android/systemui/recents/model/RecentsTaskLoader.java
index 67a36b9..ba2903a 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/model/RecentsTaskLoader.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/model/RecentsTaskLoader.java
@@ -170,65 +170,65 @@
             } else {
                 RecentsConfiguration config = RecentsConfiguration.getInstance();
                 SystemServicesProxy ssp = mSystemServicesProxy;
-                // If we've stopped the loader, then fall thorugh to the above logic to wait on
+                // If we've stopped the loader, then fall through to the above logic to wait on
                 // the load thread
-                if (ssp == null) continue;
+                if (ssp != null) {
+                    // Load the next item from the queue
+                    final Task t = mLoadQueue.nextTask();
+                    if (t != null) {
+                        Drawable cachedIcon = mApplicationIconCache.get(t.key);
+                        Bitmap cachedThumbnail = mThumbnailCache.get(t.key);
 
-                // Load the next item from the queue
-                final Task t = mLoadQueue.nextTask();
-                if (t != null) {
-                    Drawable cachedIcon = mApplicationIconCache.get(t.key);
-                    Bitmap cachedThumbnail = mThumbnailCache.get(t.key);
-
-                    // Load the application icon if it is stale or we haven't cached one yet
-                    if (cachedIcon == null) {
-                        cachedIcon = getTaskDescriptionIcon(t.key, t.icon, t.iconFilename, ssp,
-                                mContext.getResources());
-
+                        // Load the application icon if it is stale or we haven't cached one yet
                         if (cachedIcon == null) {
-                            ActivityInfo info = ssp.getActivityInfo(t.key.baseIntent.getComponent(),
-                                    t.key.userId);
-                            if (info != null) {
-                                if (DEBUG) Log.d(TAG, "Loading icon: " + t.key);
-                                cachedIcon = ssp.getActivityIcon(info, t.key.userId);
+                            cachedIcon = getTaskDescriptionIcon(t.key, t.icon, t.iconFilename, ssp,
+                                    mContext.getResources());
+
+                            if (cachedIcon == null) {
+                                ActivityInfo info = ssp.getActivityInfo(
+                                        t.key.baseIntent.getComponent(), t.key.userId);
+                                if (info != null) {
+                                    if (DEBUG) Log.d(TAG, "Loading icon: " + t.key);
+                                    cachedIcon = ssp.getActivityIcon(info, t.key.userId);
+                                }
                             }
-                        }
 
-                        if (cachedIcon == null) {
-                            cachedIcon = mDefaultApplicationIcon;
-                        }
+                            if (cachedIcon == null) {
+                                cachedIcon = mDefaultApplicationIcon;
+                            }
 
-                        // At this point, even if we can't load the icon, we will set the default
-                        // icon.
-                        mApplicationIconCache.put(t.key, cachedIcon);
-                    }
-                    // Load the thumbnail if it is stale or we haven't cached one yet
-                    if (cachedThumbnail == null) {
-                        if (config.svelteLevel < RecentsConfiguration.SVELTE_DISABLE_LOADING) {
-                            if (DEBUG) Log.d(TAG, "Loading thumbnail: " + t.key);
-                            cachedThumbnail = ssp.getTaskThumbnail(t.key.id);
+                            // At this point, even if we can't load the icon, we will set the
+                            // default icon.
+                            mApplicationIconCache.put(t.key, cachedIcon);
                         }
+                        // Load the thumbnail if it is stale or we haven't cached one yet
                         if (cachedThumbnail == null) {
-                            cachedThumbnail = mDefaultThumbnail;
-                        }
-                        // When svelte, we trim the memory to just the visible thumbnails when
-                        // leaving, so don't thrash the cache as the user scrolls (just load them
-                        // from scratch each time)
-                        if (config.svelteLevel < RecentsConfiguration.SVELTE_LIMIT_CACHE) {
-                            mThumbnailCache.put(t.key, cachedThumbnail);
-                        }
-                    }
-                    if (!mCancelled) {
-                        // Notify that the task data has changed
-                        final Drawable newIcon = cachedIcon;
-                        final Bitmap newThumbnail = cachedThumbnail == mDefaultThumbnail
-                                ? null : cachedThumbnail;
-                        mMainThreadHandler.post(new Runnable() {
-                            @Override
-                            public void run() {
-                                t.notifyTaskDataLoaded(newThumbnail, newIcon);
+                            if (config.svelteLevel < RecentsConfiguration.SVELTE_DISABLE_LOADING) {
+                                if (DEBUG) Log.d(TAG, "Loading thumbnail: " + t.key);
+                                cachedThumbnail = ssp.getTaskThumbnail(t.key.id);
                             }
-                        });
+                            if (cachedThumbnail == null) {
+                                cachedThumbnail = mDefaultThumbnail;
+                            }
+                            // When svelte, we trim the memory to just the visible thumbnails when
+                            // leaving, so don't thrash the cache as the user scrolls (just load
+                            // them from scratch each time)
+                            if (config.svelteLevel < RecentsConfiguration.SVELTE_LIMIT_CACHE) {
+                                mThumbnailCache.put(t.key, cachedThumbnail);
+                            }
+                        }
+                        if (!mCancelled) {
+                            // Notify that the task data has changed
+                            final Drawable newIcon = cachedIcon;
+                            final Bitmap newThumbnail = cachedThumbnail == mDefaultThumbnail
+                                    ? null : cachedThumbnail;
+                            mMainThreadHandler.post(new Runnable() {
+                                @Override
+                                public void run() {
+                                    t.notifyTaskDataLoaded(newThumbnail, newIcon);
+                                }
+                            });
+                        }
                     }
                 }
 
diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/AnimateableViewBounds.java b/packages/SystemUI/src/com/android/systemui/recents/views/AnimateableViewBounds.java
index 5f8f3f2..fb05c01 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/views/AnimateableViewBounds.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/views/AnimateableViewBounds.java
@@ -16,7 +16,6 @@
 
 package com.android.systemui.recents.views;
 
-import android.animation.ObjectAnimator;
 import android.graphics.Outline;
 import android.graphics.Rect;
 import android.view.View;
@@ -35,8 +34,6 @@
     float mAlpha = 1f;
     final float mMinAlpha = 0.25f;
 
-    ObjectAnimator mClipBottomAnimator;
-
     public AnimateableViewBounds(TaskView source, int cornerRadius) {
         mConfig = RecentsConfiguration.getInstance();
         mSourceView = source;
diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/SystemBarScrimViews.java b/packages/SystemUI/src/com/android/systemui/recents/views/SystemBarScrimViews.java
index 162897e..1086160 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/views/SystemBarScrimViews.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/views/SystemBarScrimViews.java
@@ -64,7 +64,9 @@
             mStatusBarScrimView.setTranslationY(-mStatusBarScrimView.getMeasuredHeight());
             mStatusBarScrimView.animate()
                     .translationY(0)
-                    .setStartDelay(mConfig.taskBarEnterAnimDelay)
+                    .setStartDelay(mConfig.launchedFromHome ?
+                            mConfig.transitionEnterFromHomeDelay :
+                            mConfig.transitionEnterFromAppDelay)
                     .setDuration(mConfig.navBarScrimEnterDuration)
                     .setInterpolator(mConfig.quintOutInterpolator)
                     .withStartAction(new Runnable() {
@@ -79,7 +81,9 @@
             mNavBarScrimView.setTranslationY(mNavBarScrimView.getMeasuredHeight());
             mNavBarScrimView.animate()
                     .translationY(0)
-                    .setStartDelay(mConfig.taskBarEnterAnimDelay)
+                    .setStartDelay(mConfig.launchedFromHome ?
+                            mConfig.transitionEnterFromHomeDelay :
+                            mConfig.transitionEnterFromAppDelay)
                     .setDuration(mConfig.navBarScrimEnterDuration)
                     .setInterpolator(mConfig.quintOutInterpolator)
                     .withStartAction(new Runnable() {
@@ -101,7 +105,7 @@
             mStatusBarScrimView.animate()
                     .translationY(-mStatusBarScrimView.getMeasuredHeight())
                     .setStartDelay(0)
-                    .setDuration(mConfig.taskBarExitAnimDuration)
+                    .setDuration(mConfig.taskViewExitToAppDuration)
                     .setInterpolator(mConfig.fastOutSlowInInterpolator)
                     .start();
         }
@@ -109,7 +113,7 @@
             mNavBarScrimView.animate()
                     .translationY(mNavBarScrimView.getMeasuredHeight())
                     .setStartDelay(0)
-                    .setDuration(mConfig.taskBarExitAnimDuration)
+                    .setDuration(mConfig.taskViewExitToAppDuration)
                     .setInterpolator(mConfig.fastOutSlowInInterpolator)
                     .start();
         }
diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackView.java b/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackView.java
index 1731d38..5732879 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackView.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackView.java
@@ -186,6 +186,7 @@
             mUIDozeTrigger.stopDozing();
             mUIDozeTrigger.resetTrigger();
         }
+        mStackScroller.reset();
     }
 
     /** Requests that the views be synchronized with the model */
@@ -659,9 +660,10 @@
         // If this is the first layout, then scroll to the front of the stack and synchronize the
         // stack views immediately to load all the views
         if (mAwaitingFirstLayout) {
-            mStackScroller.setStackScrollToInitialState();
-            requestSynchronizeStackViewsWithModel();
-            synchronizeStackViewsWithModel();
+            if (mStackScroller.setStackScrollToInitialState()) {
+                requestSynchronizeStackViewsWithModel();
+                synchronizeStackViewsWithModel();
+            }
         }
 
         // Measure each of the TaskViews
@@ -915,7 +917,7 @@
             TaskView frontTv = getChildViewForTask(newFrontMostTask);
             if (frontTv != null) {
                 frontTv.onTaskBound(newFrontMostTask);
-                frontTv.fadeInActionButton(false);
+                frontTv.fadeInActionButton(0, mConfig.taskViewEnterFromAppDuration);
             }
         }
 
diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackViewScroller.java b/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackViewScroller.java
index 04f7c6f..f7067be 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackViewScroller.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackViewScroller.java
@@ -48,6 +48,11 @@
         setStackScroll(getStackScroll());
     }
 
+    /** Resets the task scroller. */
+    void reset() {
+        mStackScrollP = 0f;
+    }
+
     /** Sets the callbacks */
     void setCallbacks(TaskStackViewScrollerCallbacks cb) {
         mCb = cb;
@@ -71,9 +76,14 @@
         mStackScrollP = s;
     }
 
-    /** Sets the current stack scroll to the initial state when you first enter recents */
-    public void setStackScrollToInitialState() {
+    /**
+     * Sets the current stack scroll to the initial state when you first enter recents.
+     * @return whether the stack progress changed.
+     */
+    public boolean setStackScrollToInitialState() {
+        float prevStackScrollP = mStackScrollP;
         setStackScroll(getBoundedStackScroll(mLayoutAlgorithm.mInitialScrollP));
+        return Float.compare(prevStackScrollP, mStackScrollP) != 0;
     }
 
     /** Bounds the current scroll if necessary */
diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/TaskView.java b/packages/SystemUI/src/com/android/systemui/recents/views/TaskView.java
index 27d2fda..d42fa15 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/views/TaskView.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/views/TaskView.java
@@ -24,7 +24,6 @@
 import android.util.AttributeSet;
 import android.view.View;
 import android.view.ViewOutlineProvider;
-import android.view.ViewPropertyAnimator;
 import android.view.animation.AccelerateInterpolator;
 import android.widget.FrameLayout;
 import com.android.systemui.R;
@@ -271,24 +270,25 @@
                 if (Constants.DebugFlags.App.EnableThumbnailAlphaOnFrontmost) {
                     // Animate the thumbnail alpha before the dim animation (to prevent updating the
                     // hardware layer)
-                    mThumbnailView.startEnterRecentsAnimation(mConfig.taskBarEnterAnimDelay,
+                    mThumbnailView.startEnterRecentsAnimation(mConfig.transitionEnterFromAppDelay,
                             new Runnable() {
                                 @Override
                                 public void run() {
-                                    animateDimToProgress(0, mConfig.taskBarEnterAnimDuration,
+                                    animateDimToProgress(0, mConfig.taskViewEnterFromAppDuration,
                                             ctx.postAnimationTrigger.decrementOnAnimationEnd());
                                 }
                             });
                 } else {
                     // Immediately start the dim animation
-                    animateDimToProgress(mConfig.taskBarEnterAnimDelay,
-                            mConfig.taskBarEnterAnimDuration,
+                    animateDimToProgress(mConfig.transitionEnterFromAppDelay,
+                            mConfig.taskViewEnterFromAppDuration,
                             ctx.postAnimationTrigger.decrementOnAnimationEnd());
                 }
                 ctx.postAnimationTrigger.increment();
 
                 // Animate the action button in
-                fadeInActionButton(true);
+                fadeInActionButton(mConfig.transitionEnterFromAppDelay,
+                        mConfig.taskViewEnterFromAppDuration);
             } else {
                 // Animate the task up if it was occluding the launch target
                 if (ctx.currentTaskOccludesLaunchTarget) {
@@ -296,7 +296,7 @@
                     setAlpha(0f);
                     animate().alpha(1f)
                             .translationY(transform.translationY)
-                            .setStartDelay(mConfig.taskBarEnterAnimDelay)
+                            .setStartDelay(mConfig.transitionEnterFromAppDelay)
                             .setUpdateListener(null)
                             .setInterpolator(mConfig.fastOutSlowInInterpolator)
                             .setDuration(mConfig.taskViewEnterFromHomeDuration)
@@ -311,12 +311,12 @@
                     ctx.postAnimationTrigger.increment();
                 }
             }
-            startDelay = mConfig.taskBarEnterAnimDelay;
+            startDelay = mConfig.transitionEnterFromAppDelay;
 
         } else if (mConfig.launchedFromHome) {
             // Animate the tasks up
             int frontIndex = (ctx.currentStackViewCount - ctx.currentStackViewIndex - 1);
-            int delay = mConfig.taskViewEnterFromHomeDelay +
+            int delay = mConfig.transitionEnterFromHomeDelay +
                     frontIndex * mConfig.taskViewEnterFromHomeStaggerDelay;
 
             setScaleX(transform.scale);
@@ -353,19 +353,17 @@
         }, (startDelay / 2));
     }
 
-    public void fadeInActionButton(boolean withDelay) {
+    public void fadeInActionButton(int delay, int duration) {
         // Hide the action button
         mActionButtonView.setAlpha(0f);
 
         // Animate the action button in
-        ViewPropertyAnimator animator = mActionButtonView.animate().alpha(1f)
-                .setDuration(mConfig.taskBarEnterAnimDuration)
+        mActionButtonView.animate().alpha(1f)
+                .setStartDelay(delay)
+                .setDuration(duration)
                 .setInterpolator(PhoneStatusBar.ALPHA_IN)
-                .withLayer();
-        if (withDelay) {
-            animator.setStartDelay(mConfig.taskBarEnterAnimDelay);
-        }
-        animator.start();
+                .withLayer()
+                .start();
     }
 
     /** Animates this task view as it leaves recents by pressing home. */
@@ -391,7 +389,7 @@
             // Animate the dim
             if (mDimAlpha > 0) {
                 ObjectAnimator anim = ObjectAnimator.ofInt(this, "dim", 0);
-                anim.setDuration(mConfig.taskBarExitAnimDuration);
+                anim.setDuration(mConfig.taskViewExitToAppDuration);
                 anim.setInterpolator(mConfig.fastOutLinearInInterpolator);
                 anim.start();
             }
@@ -406,7 +404,7 @@
             mActionButtonView.animate()
                     .alpha(0f)
                     .setStartDelay(0)
-                    .setDuration(mConfig.taskBarExitAnimDuration)
+                    .setDuration(mConfig.taskViewExitToAppDuration)
                     .setInterpolator(mConfig.fastOutLinearInInterpolator)
                     .withLayer()
                     .start();
@@ -421,7 +419,7 @@
                     .setStartDelay(0)
                     .setUpdateListener(null)
                     .setInterpolator(mConfig.fastOutLinearInInterpolator)
-                    .setDuration(mConfig.taskBarExitAnimDuration)
+                    .setDuration(mConfig.taskViewExitToAppDuration)
                     .start();
             }
         }
diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/TaskViewHeader.java b/packages/SystemUI/src/com/android/systemui/recents/views/TaskViewHeader.java
index 5de84bd..1e5d9fc 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/views/TaskViewHeader.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/views/TaskViewHeader.java
@@ -235,7 +235,7 @@
                     .alpha(0f)
                     .setStartDelay(0)
                     .setInterpolator(mConfig.fastOutSlowInInterpolator)
-                    .setDuration(mConfig.taskBarExitAnimDuration)
+                    .setDuration(mConfig.taskViewExitToAppDuration)
                     .withLayer()
                     .start();
         }
@@ -249,7 +249,7 @@
                 .alpha(1f)
                 .setStartDelay(0)
                 .setInterpolator(mConfig.fastOutLinearInInterpolator)
-                .setDuration(mConfig.taskBarEnterAnimDuration)
+                .setDuration(mConfig.taskViewEnterFromAppDuration)
                 .withLayer()
                 .start();
     }
diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/TaskViewThumbnail.java b/packages/SystemUI/src/com/android/systemui/recents/views/TaskViewThumbnail.java
index c83248e..117a7d3 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/views/TaskViewThumbnail.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/views/TaskViewThumbnail.java
@@ -237,12 +237,12 @@
     /** Animates this task thumbnail as it enters Recents. */
     void startEnterRecentsAnimation(int delay, Runnable postAnimRunnable) {
         startFadeAnimation(mConfig.taskViewThumbnailAlpha, delay,
-                mConfig.taskBarEnterAnimDuration, postAnimRunnable);
+                mConfig.taskViewEnterFromAppDuration, postAnimRunnable);
     }
 
     /** Animates this task thumbnail as it exits Recents. */
     void startLaunchTaskAnimation(Runnable postAnimRunnable) {
-        startFadeAnimation(1f, 0, mConfig.taskBarExitAnimDuration, postAnimRunnable);
+        startFadeAnimation(1f, 0, mConfig.taskViewExitToAppDuration, postAnimRunnable);
     }
 
     /** Starts a new thumbnail alpha animation. */
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/SignalClusterView.java b/packages/SystemUI/src/com/android/systemui/statusbar/SignalClusterView.java
index 9154a48..418c57f 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/SignalClusterView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/SignalClusterView.java
@@ -48,6 +48,7 @@
     private int mMobileStrengthId = 0, mMobileTypeId = 0;
     private boolean mIsAirplaneMode = false;
     private int mAirplaneIconId = 0;
+    private int mAirplaneContentDescription;
     private String mWifiDescription, mMobileDescription, mMobileTypeDescription;
     private boolean mIsMobileTypeIconWide;
 
@@ -160,9 +161,10 @@
     }
 
     @Override
-    public void setIsAirplaneMode(boolean is, int airplaneIconId) {
+    public void setIsAirplaneMode(boolean is, int airplaneIconId, int contentDescription) {
         mIsAirplaneMode = is;
         mAirplaneIconId = airplaneIconId;
+        mAirplaneContentDescription = contentDescription;
 
         apply();
     }
@@ -236,6 +238,8 @@
 
         if (mIsAirplaneMode) {
             mAirplane.setImageResource(mAirplaneIconId);
+            mAirplane.setContentDescription(mAirplaneContentDescription != 0 ?
+                    mContext.getString(mAirplaneContentDescription) : "");
             mAirplane.setVisibility(View.VISIBLE);
         } else {
             mAirplane.setVisibility(View.GONE);
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 f5c994a..9a1ac49 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java
@@ -79,6 +79,7 @@
 import android.service.notification.NotificationListenerService;
 import android.service.notification.NotificationListenerService.RankingMap;
 import android.service.notification.StatusBarNotification;
+import android.text.TextUtils;
 import android.util.ArraySet;
 import android.util.DisplayMetrics;
 import android.util.EventLog;
@@ -821,7 +822,12 @@
         signalClusterQs.setNetworkController(mNetworkController);
         final boolean isAPhone = mNetworkController.hasVoiceCallingFeature();
         if (isAPhone) {
-            mNetworkController.addEmergencyLabelView(mHeader);
+            mNetworkController.addEmergencyListener(new NetworkControllerImpl.EmergencyListener() {
+                @Override
+                public void setEmergencyCallsOnly(boolean emergencyOnly) {
+                    mHeader.setShowEmergencyCallsOnly(emergencyOnly);
+                }
+            });
         }
 
         mCarrierLabel = (TextView)mStatusBarWindow.findViewById(R.id.carrier_label);
@@ -830,13 +836,19 @@
         if (mShowCarrierInPanel) {
             mCarrierLabel.setVisibility(mCarrierLabelVisible ? View.VISIBLE : View.INVISIBLE);
 
-            // for mobile devices, we always show mobile connection info here (SPN/PLMN)
-            // for other devices, we show whatever network is connected
-            if (mNetworkController.hasMobileDataFeature()) {
-                mNetworkController.addMobileLabelView(mCarrierLabel);
-            } else {
-                mNetworkController.addCombinedLabelView(mCarrierLabel);
-            }
+            mNetworkController.addCarrierLabel(new NetworkControllerImpl.CarrierLabelListener() {
+                @Override
+                public void setCarrierLabel(String label) {
+                    mCarrierLabel.setText(label);
+                    if (mNetworkController.hasMobileDataFeature()) {
+                        if (TextUtils.isEmpty(label)) {
+                            mCarrierLabel.setVisibility(View.GONE);
+                        } else {
+                            mCarrierLabel.setVisibility(View.VISIBLE);
+                        }
+                    }
+                }
+            });
 
             // set up the dynamic hide/show of the label
             // TODO: uncomment, handle this for the Stack scroller aswell
@@ -2669,6 +2681,7 @@
 
     @Override
     public void setInteracting(int barWindow, boolean interacting) {
+        final boolean changing = ((mInteractingWindows & barWindow) != 0) != interacting;
         mInteractingWindows = interacting
                 ? (mInteractingWindows | barWindow)
                 : (mInteractingWindows & ~barWindow);
@@ -2677,6 +2690,12 @@
         } else {
             resumeSuspendedAutohide();
         }
+        // manually dismiss the volume panel when interacting with the nav bar
+        if (changing && interacting && barWindow == StatusBarManager.WINDOW_NAVIGATION_BAR) {
+            if (mVolumeComponent != null) {
+                mVolumeComponent.dismissNow();
+            }
+        }
         checkBarModes();
     }
 
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/QSTileHost.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/QSTileHost.java
index 45a1386..8ce608c 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/QSTileHost.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/QSTileHost.java
@@ -122,7 +122,7 @@
                     tile.userSwitch(newUserId);
                 }
                 mSecurity.onUserSwitched(newUserId);
-                mNetwork.onUserSwitched(newUserId);
+                mNetwork.getAccessPointController().onUserSwitched(newUserId);
                 mObserver.register();
             }
         };
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/AccessPointController.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/AccessPointControllerImpl.java
similarity index 95%
rename from packages/SystemUI/src/com/android/systemui/statusbar/policy/AccessPointController.java
rename to packages/SystemUI/src/com/android/systemui/statusbar/policy/AccessPointControllerImpl.java
index 0a385d7..6fec97e 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/AccessPointController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/AccessPointControllerImpl.java
@@ -36,15 +36,13 @@
 import android.util.Log;
 
 import com.android.systemui.R;
-import com.android.systemui.statusbar.policy.NetworkController.AccessPoint;
-import com.android.systemui.statusbar.policy.NetworkController.AccessPointCallback;
 
 import java.util.ArrayList;
 import java.util.Collections;
 import java.util.Comparator;
 import java.util.List;
 
-public class AccessPointController {
+public class AccessPointControllerImpl implements NetworkController.AccessPointController {
     private static final String TAG = "AccessPointController";
     private static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG);
 
@@ -69,7 +67,7 @@
     private boolean mScanning;
     private int mCurrentUser;
 
-    public AccessPointController(Context context) {
+    public AccessPointControllerImpl(Context context) {
         mContext = context;
         mWifiManager = (WifiManager) mContext.getSystemService(Context.WIFI_SERVICE);
         mUserManager = (UserManager) mContext.getSystemService(Context.USER_SERVICE);
@@ -81,25 +79,28 @@
                 new UserHandle(mCurrentUser));
     }
 
-    void onUserSwitched(int newUserId) {
+    public void onUserSwitched(int newUserId) {
         mCurrentUser = newUserId;
     }
 
-    public void addCallback(AccessPointCallback callback) {
+    @Override
+    public void addAccessPointCallback(AccessPointCallback callback) {
         if (callback == null || mCallbacks.contains(callback)) return;
         if (DEBUG) Log.d(TAG, "addCallback " + callback);
         mCallbacks.add(callback);
         mReceiver.setListening(!mCallbacks.isEmpty());
     }
 
-    public void removeCallback(AccessPointCallback callback) {
+    @Override
+    public void removeAccessPointCallback(AccessPointCallback callback) {
         if (callback == null) return;
         if (DEBUG) Log.d(TAG, "removeCallback " + callback);
         mCallbacks.remove(callback);
         mReceiver.setListening(!mCallbacks.isEmpty());
     }
 
-    public void scan() {
+    @Override
+    public void scanForAccessPoints() {
         if (mScanning) return;
         if (DEBUG) Log.d(TAG, "scan!");
         mScanning = mWifiManager.startScan();
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/AccessibilityContentDescriptions.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/AccessibilityContentDescriptions.java
index 7ac2a98..b7c74e3 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/AccessibilityContentDescriptions.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/AccessibilityContentDescriptions.java
@@ -33,11 +33,5 @@
         R.string.accessibility_wifi_three_bars,
         R.string.accessibility_wifi_signal_full
     };
-    static final int[] WIMAX_CONNECTION_STRENGTH = {
-        R.string.accessibility_no_wimax,
-        R.string.accessibility_wimax_one_bar,
-        R.string.accessibility_wimax_two_bars,
-        R.string.accessibility_wimax_three_bars,
-        R.string.accessibility_wimax_signal_full
-    };
+    static final int WIFI_NO_CONNECTION = R.string.accessibility_no_wifi;
 }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/MobileDataController.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/MobileDataControllerImpl.java
similarity index 94%
rename from packages/SystemUI/src/com/android/systemui/statusbar/policy/MobileDataController.java
rename to packages/SystemUI/src/com/android/systemui/statusbar/policy/MobileDataControllerImpl.java
index 33d68bf..20f0a83 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/MobileDataController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/MobileDataControllerImpl.java
@@ -38,12 +38,10 @@
 import android.text.format.Time;
 import android.util.Log;
 
-import com.android.systemui.statusbar.policy.NetworkController.DataUsageInfo;
-
 import java.util.Date;
 import java.util.Locale;
 
-public class MobileDataController {
+public class MobileDataControllerImpl implements NetworkController.MobileDataController {
     private static final String TAG = "MobileDataController";
     private static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG);
 
@@ -61,8 +59,9 @@
 
     private INetworkStatsSession mSession;
     private Callback mCallback;
+    private NetworkControllerImpl mNetworkController;
 
-    public MobileDataController(Context context) {
+    public MobileDataControllerImpl(Context context) {
         mContext = context;
         mTelephonyManager = TelephonyManager.from(context);
         mConnectivityManager = ConnectivityManager.from(context);
@@ -71,6 +70,10 @@
         mPolicyManager = NetworkPolicyManager.from(mContext);
     }
 
+    public void setNetworkController(NetworkControllerImpl networkController) {
+        mNetworkController = networkController;
+    }
+
     private INetworkStatsSession getSession() {
         if (mSession == null) {
             try {
@@ -155,6 +158,9 @@
             } else {
                 usage.warningLevel = DEFAULT_WARNING_LEVEL;
             }
+            if (usage != null) {
+                usage.carrier = mNetworkController.getMobileNetworkName();
+            }
             return usage;
         } catch (RemoteException e) {
             return warn("remote call failed");
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkController.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkController.java
index bb29d01..b024f58 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkController.java
@@ -22,6 +22,8 @@
     void addNetworkSignalChangedCallback(NetworkSignalChangedCallback cb);
     void removeNetworkSignalChangedCallback(NetworkSignalChangedCallback cb);
     void setWifiEnabled(boolean enabled);
+    AccessPointController getAccessPointController();
+    MobileDataController getMobileDataController();
 
     public interface NetworkSignalChangedCallback {
         void onWifiSignalChanged(boolean enabled, boolean connected, int wifiSignalIconId,
@@ -36,38 +38,50 @@
         void onMobileDataEnabled(boolean enabled);
     }
 
-    void addAccessPointCallback(AccessPointCallback callback);
-    void removeAccessPointCallback(AccessPointCallback callback);
-    void scanForAccessPoints();
-    boolean connect(AccessPoint ap);
-    boolean isMobileDataSupported();
-    boolean isMobileDataEnabled();
-    void setMobileDataEnabled(boolean enabled);
-    DataUsageInfo getDataUsageInfo();
-    boolean canConfigWifi();
-    void onUserSwitched(int newUserId);
+    /**
+     * Tracks changes in access points.  Allows listening for changes, scanning for new APs,
+     * and connecting to new ones.
+     */
+    public interface AccessPointController {
+        void addAccessPointCallback(AccessPointCallback callback);
+        void removeAccessPointCallback(AccessPointCallback callback);
+        void scanForAccessPoints();
+        boolean connect(AccessPoint ap);
+        boolean canConfigWifi();
+        void onUserSwitched(int newUserId);
 
-    public interface AccessPointCallback {
-        void onAccessPointsChanged(AccessPoint[] accessPoints);
+        public interface AccessPointCallback {
+            void onAccessPointsChanged(AccessPoint[] accessPoints);
+        }
+
+        public static class AccessPoint {
+            public static final int NO_NETWORK = -1;  // see WifiManager
+
+            public int networkId;
+            public int iconId;
+            public String ssid;
+            public boolean isConnected;
+            public boolean isConfigured;
+            public boolean hasSecurity;
+            public int level;  // 0 - 5
+        }
     }
 
-    public static class AccessPoint {
-        public static final int NO_NETWORK = -1;  // see WifiManager
+    /**
+     * Tracks mobile data support and usage.
+     */
+    public interface MobileDataController {
+        boolean isMobileDataSupported();
+        boolean isMobileDataEnabled();
+        void setMobileDataEnabled(boolean enabled);
+        DataUsageInfo getDataUsageInfo();
 
-        public int networkId;
-        public int iconId;
-        public String ssid;
-        public boolean isConnected;
-        public boolean isConfigured;
-        public boolean hasSecurity;
-        public int level;  // 0 - 5
-    }
-
-    public static class DataUsageInfo {
-        public String carrier;
-        public String period;
-        public long limitLevel;
-        public long warningLevel;
-        public long usageLevel;
+        public static class DataUsageInfo {
+            public String carrier;
+            public String period;
+            public long limitLevel;
+            public long warningLevel;
+            public long usageLevel;
+        }
     }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkControllerImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkControllerImpl.java
index 0caded5..5a97c75 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkControllerImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkControllerImpl.java
@@ -26,7 +26,6 @@
 import android.net.wifi.WifiConfiguration;
 import android.net.wifi.WifiInfo;
 import android.net.wifi.WifiManager;
-import android.net.wimax.WimaxManagerConstants;
 import android.os.AsyncTask;
 import android.os.Bundle;
 import android.os.Handler;
@@ -37,9 +36,8 @@
 import android.telephony.ServiceState;
 import android.telephony.SignalStrength;
 import android.telephony.TelephonyManager;
+import android.text.format.DateFormat;
 import android.util.Log;
-import android.view.View;
-import android.widget.TextView;
 
 import com.android.internal.annotations.VisibleForTesting;
 import com.android.internal.telephony.IccCardConstants;
@@ -48,130 +46,66 @@
 import com.android.internal.util.AsyncChannel;
 import com.android.systemui.DemoMode;
 import com.android.systemui.R;
-import com.android.systemui.statusbar.phone.StatusBarHeaderView;
 
 import java.io.FileDescriptor;
 import java.io.PrintWriter;
 import java.util.ArrayList;
+import java.util.HashMap;
 import java.util.List;
 import java.util.Locale;
+import java.util.Map;
+import java.util.Objects;
 
 /** Platform implementation of the network controller. **/
 public class NetworkControllerImpl extends BroadcastReceiver
         implements NetworkController, DemoMode {
     // debug
-    static final String TAG = "StatusBar.NetworkController";
-    static final boolean DEBUG = false;
-    static final boolean CHATTY = false; // additional diagnostics, but not logspew
+    static final String TAG = "NetworkController";
+    static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG);
+    // additional diagnostics, but not logspew
+    static final boolean CHATTY =  Log.isLoggable(TAG + ".Chat", Log.DEBUG);
+    // Save the previous states of all SignalController state info.
+    static final boolean RECORD_HISTORY = true;
+    // How many to save, must be a power of 2.
+    static final int HISTORY_SIZE = 16;
 
-    // telephony
-    boolean mHspaDataDistinguishable;
-    final TelephonyManager mPhone;
-    boolean mDataConnected;
-    IccCardConstants.State mSimState = IccCardConstants.State.READY;
-    int mPhoneState = TelephonyManager.CALL_STATE_IDLE;
-    int mDataNetType = TelephonyManager.NETWORK_TYPE_UNKNOWN;
-    int mDataState = TelephonyManager.DATA_DISCONNECTED;
-    int mDataActivity = TelephonyManager.DATA_ACTIVITY_NONE;
-    ServiceState mServiceState;
-    SignalStrength mSignalStrength;
-    int[] mDataIconList = TelephonyIcons.DATA_G[0];
-    String mNetworkName;
-    String mNetworkNameDefault;
-    String mNetworkNameSeparator;
-    int mPhoneSignalIconId;
-    int mQSPhoneSignalIconId;
-    int mDataDirectionIconId; // data + data direction on phones
-    int mDataSignalIconId;
-    int mDataTypeIconId;
-    int mQSDataTypeIconId;
-    int mAirplaneIconId;
-    boolean mDataActive;
-    boolean mNoSim;
-    int mLastSignalLevel;
-    boolean mShowPhoneRSSIForData = false;
-    boolean mShowAtLeastThreeGees = false;
-    boolean mAlwaysShowCdmaRssi = false;
+    private static final int INET_CONDITION_THRESHOLD = 50;
 
-    String mContentDescriptionPhoneSignal;
-    String mContentDescriptionWifi;
-    String mContentDescriptionWimax;
-    String mContentDescriptionCombinedSignal;
-    String mContentDescriptionDataType;
+    private final Context mContext;
+    private final TelephonyManager mPhone;
+    private final WifiManager mWifiManager;
+    private final ConnectivityManager mConnectivityManager;
+    private final boolean mHasMobileDataFeature;
 
-    // wifi
-    final WifiManager mWifiManager;
-    AsyncChannel mWifiChannel;
-    boolean mWifiEnabled, mWifiConnected;
-    int mWifiRssi, mWifiLevel;
-    String mWifiSsid;
-    int mWifiIconId = 0;
-    int mQSWifiIconId = 0;
-    int mWifiActivity = WifiManager.DATA_ACTIVITY_NONE;
+    // Subcontrollers.
+    @VisibleForTesting
+    final WifiSignalController mWifiSignalController;
+    @VisibleForTesting
+    final MobileSignalController mMobileSignalController;
+    private final AccessPointController mAccessPoints;
+    private final MobileDataControllerImpl mMobileDataController;
 
     // bluetooth
     private boolean mBluetoothTethered = false;
-    private int mBluetoothTetherIconId =
-        com.android.internal.R.drawable.stat_sys_tether_bluetooth;
-
-    //wimax
-    private boolean mWimaxSupported = false;
-    private boolean mIsWimaxEnabled = false;
-    private boolean mWimaxConnected = false;
-    private boolean mWimaxIdle = false;
-    private int mWimaxIconId = 0;
-    private int mWimaxSignal = 0;
-    private int mWimaxState = 0;
-    private int mWimaxExtraState = 0;
 
     // data connectivity (regardless of state, can we access the internet?)
     // state of inet connection - 0 not connected, 100 connected
     private boolean mConnected = false;
     private int mConnectedNetworkType = ConnectivityManager.TYPE_NONE;
     private String mConnectedNetworkTypeName;
-    private int mLastConnectedNetworkType = ConnectivityManager.TYPE_NONE;
+    private boolean mInetCondition; // Used for Logging and demo.
 
-    private int mInetCondition = 0;
-    private int mLastInetCondition = 0;
-    private static final int INET_CONDITION_THRESHOLD = 50;
-
+    // States that don't belong to a subcontroller.
     private boolean mAirplaneMode = false;
-    private boolean mLastAirplaneMode = true;
-
     private Locale mLocale = null;
-    private Locale mLastLocale = null;
 
-    // our ui
-    Context mContext;
-    ArrayList<TextView> mCombinedLabelViews = new ArrayList<TextView>();
-    ArrayList<TextView> mMobileLabelViews = new ArrayList<TextView>();
-    ArrayList<TextView> mWifiLabelViews = new ArrayList<TextView>();
-    ArrayList<StatusBarHeaderView> mEmergencyViews = new ArrayList<>();
-    ArrayList<SignalCluster> mSignalClusters = new ArrayList<SignalCluster>();
-    ArrayList<NetworkSignalChangedCallback> mSignalsChangedCallbacks =
+    // All the callbacks.
+    private ArrayList<EmergencyListener> mEmergencyListeners = new ArrayList<EmergencyListener>();
+    private ArrayList<CarrierLabelListener> mCarrierListeners =
+            new ArrayList<CarrierLabelListener>();
+    private ArrayList<SignalCluster> mSignalClusters = new ArrayList<SignalCluster>();
+    private ArrayList<NetworkSignalChangedCallback> mSignalsChangedCallbacks =
             new ArrayList<NetworkSignalChangedCallback>();
-    int mLastPhoneSignalIconId = -1;
-    int mLastDataDirectionIconId = -1;
-    int mLastWifiIconId = -1;
-    int mLastWimaxIconId = -1;
-    int mLastCombinedSignalIconId = -1;
-    int mLastDataTypeIconId = -1;
-    String mLastCombinedLabel = "";
-
-    private boolean mHasMobileDataFeature;
-
-    boolean mDataAndWifiStacked = false;
-
-    public interface SignalCluster {
-        void setWifiIndicators(boolean visible, int strengthIcon, String contentDescription);
-        void setMobileDataIndicators(boolean visible, int strengthIcon, int typeIcon,
-                String contentDescription, String typeContentDescription, boolean isTypeIconWide);
-        void setIsAirplaneMode(boolean is, int airplaneIcon);
-    }
-
-    private final AccessPointController mAccessPoints;
-    private final MobileDataController mMobileDataController;
-    private final ConnectivityManager mConnectivityManager;
 
     /**
      * Construct this controller object and register for updates.
@@ -179,68 +113,51 @@
     public NetworkControllerImpl(Context context) {
         this(context, (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE),
                 (TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE),
-                (WifiManager) context.getSystemService(Context.WIFI_SERVICE));
+                (WifiManager) context.getSystemService(Context.WIFI_SERVICE),
+                Config.readConfig(context), new AccessPointControllerImpl(context),
+                new MobileDataControllerImpl(context));
         registerListeners();
     }
 
     @VisibleForTesting
     NetworkControllerImpl(Context context, ConnectivityManager connectivityManager,
-            TelephonyManager telephonyManager, WifiManager wifiManager) {
+            TelephonyManager telephonyManager, WifiManager wifiManager, Config config,
+            AccessPointControllerImpl accessPointController,
+            MobileDataControllerImpl mobileDataController) {
         mContext = context;
-        final Resources res = context.getResources();
 
         mConnectivityManager = connectivityManager;
         mHasMobileDataFeature =
                 mConnectivityManager.isNetworkSupported(ConnectivityManager.TYPE_MOBILE);
 
-        mShowPhoneRSSIForData = res.getBoolean(R.bool.config_showPhoneRSSIForData);
-        mShowAtLeastThreeGees = res.getBoolean(R.bool.config_showMin3G);
-        mAlwaysShowCdmaRssi = res.getBoolean(
-                com.android.internal.R.bool.config_alwaysUseCdmaRssi);
-
-        // set up the default wifi icon, used when no radios have ever appeared
-        updateWifiIcons();
-        updateWimaxIcons();
-
         // telephony
         mPhone = (TelephonyManager) mContext.getSystemService(Context.TELEPHONY_SERVICE);
-        mHspaDataDistinguishable = mContext.getResources().getBoolean(
-                R.bool.config_hspa_data_distinguishable);
-        mNetworkNameSeparator = mContext.getString(R.string.status_bar_network_name_separator);
-        mNetworkNameDefault = mContext.getString(
-                com.android.internal.R.string.lockscreen_carrier_default);
-        mNetworkName = mNetworkNameDefault;
 
         // wifi
         mWifiManager = wifiManager;
-        Handler handler = new WifiHandler();
-        mWifiChannel = new AsyncChannel();
-        Messenger wifiMessenger = mWifiManager.getWifiServiceMessenger();
-        if (wifiMessenger != null) {
-            mWifiChannel.connect(mContext, handler, wifiMessenger);
-        }
 
-        // AIRPLANE_MODE_CHANGED is sent at boot; we've probably already missed it
-        updateAirplaneMode();
-
-        mLastLocale = mContext.getResources().getConfiguration().locale;
-        mAccessPoints = new AccessPointController(mContext);
-        mMobileDataController = new MobileDataController(mContext);
-        mMobileDataController.setCallback(new MobileDataController.Callback() {
+        mLocale = mContext.getResources().getConfiguration().locale;
+        mAccessPoints = accessPointController;
+        mMobileDataController = mobileDataController;
+        mMobileDataController.setNetworkController(this);
+        // TODO: Find a way to move this into MobileDataController.
+        mMobileDataController.setCallback(new MobileDataControllerImpl.Callback() {
             @Override
             public void onMobileDataEnabled(boolean enabled) {
                 notifyMobileDataEnabled(enabled);
             }
         });
+        mWifiSignalController = new WifiSignalController(mContext, mHasMobileDataFeature,
+                mSignalsChangedCallbacks, mSignalClusters, this);
+        mMobileSignalController = new MobileSignalController(mContext, config,
+                mHasMobileDataFeature, mPhone, mSignalsChangedCallbacks, mSignalClusters, this);
+
+        // AIRPLANE_MODE_CHANGED is sent at boot; we've probably already missed it
+        updateAirplaneMode(true);
     }
 
     private void registerListeners() {
-        mPhone.listen(mPhoneStateListener,
-                          PhoneStateListener.LISTEN_SERVICE_STATE
-                        | PhoneStateListener.LISTEN_SIGNAL_STRENGTHS
-                        | PhoneStateListener.LISTEN_CALL_STATE
-                        | PhoneStateListener.LISTEN_DATA_CONNECTION_STATE
-                        | PhoneStateListener.LISTEN_DATA_ACTIVITY);
+        mMobileSignalController.registerListener();
 
         // broadcasts
         IntentFilter filter = new IntentFilter();
@@ -253,29 +170,38 @@
         filter.addAction(ConnectivityManager.INET_CONDITION_ACTION);
         filter.addAction(Intent.ACTION_CONFIGURATION_CHANGED);
         filter.addAction(Intent.ACTION_AIRPLANE_MODE_CHANGED);
-        mWimaxSupported = mContext.getResources().getBoolean(
-                com.android.internal.R.bool.config_wimaxEnabled);
-        if(mWimaxSupported) {
-            filter.addAction(WimaxManagerConstants.WIMAX_NETWORK_STATE_CHANGED_ACTION);
-            filter.addAction(WimaxManagerConstants.SIGNAL_LEVEL_CHANGED_ACTION);
-            filter.addAction(WimaxManagerConstants.NET_4G_STATE_CHANGED_ACTION);
-        }
         mContext.registerReceiver(this, filter);
     }
 
-    @Override
-    public boolean canConfigWifi() {
-        return mAccessPoints.canConfigWifi();
+    private void unregisterListeners() {
+        mMobileSignalController.unregisterListener();
+        mContext.unregisterReceiver(this);
     }
 
     @Override
-    public void onUserSwitched(int newUserId) {
-        mAccessPoints.onUserSwitched(newUserId);
+    public AccessPointController getAccessPointController() {
+        return mAccessPoints;
+    }
+
+    @Override
+    public MobileDataController getMobileDataController() {
+        return mMobileDataController;
+    }
+
+    public void addEmergencyListener(EmergencyListener listener) {
+        mEmergencyListeners.add(listener);
+        refreshCarrierLabel();
+    }
+
+    public void addCarrierLabel(CarrierLabelListener listener) {
+        mCarrierListeners.add(listener);
+        refreshCarrierLabel();
     }
 
     private void notifyMobileDataEnabled(boolean enabled) {
-        for (NetworkSignalChangedCallback cb : mSignalsChangedCallbacks) {
-            cb.onMobileDataEnabled(enabled);
+        int length = mSignalsChangedCallbacks.size();
+        for (int i = 0; i < length; i++) {
+            mSignalsChangedCallbacks.get(i).onMobileDataEnabled(enabled);
         }
     }
 
@@ -287,34 +213,40 @@
         return mPhone.getPhoneType() != TelephonyManager.PHONE_TYPE_NONE;
     }
 
+    public String getMobileNetworkName() {
+        return mMobileSignalController.mCurrentState.networkName;
+    }
+
     public boolean isEmergencyOnly() {
-        return (mServiceState != null && mServiceState.isEmergencyOnly());
+        return mMobileSignalController.isEmergencyOnly();
     }
 
-    public void addCombinedLabelView(TextView v) {
-        mCombinedLabelViews.add(v);
-    }
+    /**
+     * Emergency status may have changed (triggered by MobileSignalController),
+     * so we should recheck and send out the state to listeners.
+     */
+    void recalculateEmergency() {
+        final boolean emergencyOnly = isEmergencyOnly();
 
-    public void addMobileLabelView(TextView v) {
-        mMobileLabelViews.add(v);
-    }
-
-    public void addWifiLabelView(TextView v) {
-        mWifiLabelViews.add(v);
-    }
-
-    public void addEmergencyLabelView(StatusBarHeaderView v) {
-        mEmergencyViews.add(v);
+        int length = mEmergencyListeners.size();
+        for (int i = 0; i < length; i++) {
+            mEmergencyListeners.get(i).setEmergencyCallsOnly(emergencyOnly);
+        }
     }
 
     public void addSignalCluster(SignalCluster cluster) {
         mSignalClusters.add(cluster);
-        refreshSignalCluster(cluster);
+        cluster.setIsAirplaneMode(mAirplaneMode, TelephonyIcons.FLIGHT_MODE_ICON,
+                R.string.accessibility_airplane_mode);
+        mWifiSignalController.notifyListeners();
+        mMobileSignalController.notifyListeners();
     }
 
     public void addNetworkSignalChangedCallback(NetworkSignalChangedCallback cb) {
         mSignalsChangedCallbacks.add(cb);
-        notifySignalsChangedCallbacks(cb);
+        cb.onAirplaneModeChanged(mAirplaneMode);
+        mWifiSignalController.notifyListeners();
+        mMobileSignalController.notifyListeners();
     }
 
     public void removeNetworkSignalChangedCallback(NetworkSignalChangedCallback cb) {
@@ -322,26 +254,6 @@
     }
 
     @Override
-    public void addAccessPointCallback(AccessPointCallback callback) {
-        mAccessPoints.addCallback(callback);
-    }
-
-    @Override
-    public void removeAccessPointCallback(AccessPointCallback callback) {
-        mAccessPoints.removeCallback(callback);
-    }
-
-    @Override
-    public void scanForAccessPoints() {
-        mAccessPoints.scan();
-    }
-
-    @Override
-    public boolean connect(AccessPoint ap) {
-        return mAccessPoints.connect(ap);
-    }
-
-    @Override
     public void setWifiEnabled(final boolean enabled) {
         new AsyncTask<Void, Void, Void>() {
             @Override
@@ -349,7 +261,7 @@
                 // Disable tethering if enabling Wifi
                 final int wifiApState = mWifiManager.getWifiApState();
                 if (enabled && ((wifiApState == WifiManager.WIFI_AP_STATE_ENABLING) ||
-                               (wifiApState == WifiManager.WIFI_AP_STATE_ENABLED))) {
+                        (wifiApState == WifiManager.WIFI_AP_STATE_ENABLED))) {
                     mWifiManager.setWifiApEnabled(null, false);
                 }
 
@@ -360,732 +272,79 @@
     }
 
     @Override
-    public DataUsageInfo getDataUsageInfo() {
-        final DataUsageInfo info =  mMobileDataController.getDataUsageInfo();
-        if (info != null) {
-            info.carrier = mNetworkName;
-        }
-        return info;
-    }
-
-    @Override
-    public boolean isMobileDataSupported() {
-        return mMobileDataController.isMobileDataSupported();
-    }
-
-    @Override
-    public boolean isMobileDataEnabled() {
-        return mMobileDataController.isMobileDataEnabled();
-    }
-
-    @Override
-    public void setMobileDataEnabled(boolean enabled) {
-        mMobileDataController.setMobileDataEnabled(enabled);
-    }
-
-    private boolean isTypeIconWide(int iconId) {
-        return TelephonyIcons.ICON_LTE == iconId || TelephonyIcons.ICON_1X == iconId
-                || TelephonyIcons.ICON_3G == iconId || TelephonyIcons.ICON_4G == iconId;
-    }
-
-    private boolean isQsTypeIconWide(int iconId) {
-        return TelephonyIcons.QS_ICON_LTE == iconId || TelephonyIcons.QS_ICON_1X == iconId
-                || TelephonyIcons.QS_ICON_3G == iconId || TelephonyIcons.QS_ICON_4G == iconId;
-    }
-
-    public void refreshSignalCluster(SignalCluster cluster) {
-        if (mDemoMode) return;
-        cluster.setWifiIndicators(
-                // only show wifi in the cluster if connected or if wifi-only
-                mWifiEnabled && (mWifiConnected || !mHasMobileDataFeature),
-                mWifiIconId,
-                mContentDescriptionWifi);
-
-        if (mIsWimaxEnabled && mWimaxConnected) {
-            // wimax is special
-            cluster.setMobileDataIndicators(
-                    true,
-                    mAlwaysShowCdmaRssi ? mPhoneSignalIconId : mWimaxIconId,
-                    mDataTypeIconId,
-                    mContentDescriptionWimax,
-                    mContentDescriptionDataType,
-                    false /* isTypeIconWide */ );
-        } else {
-            // normal mobile data
-            cluster.setMobileDataIndicators(
-                    mHasMobileDataFeature,
-                    mShowPhoneRSSIForData ? mPhoneSignalIconId : mDataSignalIconId,
-                    mDataTypeIconId,
-                    mContentDescriptionPhoneSignal,
-                    mContentDescriptionDataType,
-                    isTypeIconWide(mDataTypeIconId));
-        }
-        cluster.setIsAirplaneMode(mAirplaneMode, mAirplaneIconId);
-    }
-
-    void notifySignalsChangedCallbacks(NetworkSignalChangedCallback cb) {
-        // only show wifi in the cluster if connected or if wifi-only
-        boolean wifiEnabled = mWifiEnabled && (mWifiConnected || !mHasMobileDataFeature);
-        String wifiDesc = wifiEnabled ?
-                mWifiSsid : null;
-        boolean wifiIn = wifiEnabled && mWifiSsid != null
-                && (mWifiActivity == WifiManager.DATA_ACTIVITY_INOUT
-                || mWifiActivity == WifiManager.DATA_ACTIVITY_IN);
-        boolean wifiOut = wifiEnabled && mWifiSsid != null
-                && (mWifiActivity == WifiManager.DATA_ACTIVITY_INOUT
-                || mWifiActivity == WifiManager.DATA_ACTIVITY_OUT);
-        cb.onWifiSignalChanged(mWifiEnabled, mWifiConnected, mQSWifiIconId, wifiIn, wifiOut,
-                mContentDescriptionWifi, wifiDesc);
-
-        boolean mobileIn = mDataConnected && (mDataActivity == TelephonyManager.DATA_ACTIVITY_INOUT
-                || mDataActivity == TelephonyManager.DATA_ACTIVITY_IN);
-        boolean mobileOut = mDataConnected && (mDataActivity == TelephonyManager.DATA_ACTIVITY_INOUT
-                || mDataActivity == TelephonyManager.DATA_ACTIVITY_OUT);
-        if (isEmergencyOnly()) {
-            cb.onMobileDataSignalChanged(false, mQSPhoneSignalIconId,
-                    mContentDescriptionPhoneSignal, mQSDataTypeIconId, mobileIn, mobileOut,
-                    mContentDescriptionDataType, null, mNoSim, isQsTypeIconWide(mQSDataTypeIconId));
-        } else {
-            if (mIsWimaxEnabled && mWimaxConnected) {
-                // Wimax is special
-                cb.onMobileDataSignalChanged(true, mQSPhoneSignalIconId,
-                        mContentDescriptionPhoneSignal, mQSDataTypeIconId, mobileIn, mobileOut,
-                        mContentDescriptionDataType, mNetworkName, mNoSim,
-                        isQsTypeIconWide(mQSDataTypeIconId));
-            } else {
-                // Normal mobile data
-                cb.onMobileDataSignalChanged(mHasMobileDataFeature, mQSPhoneSignalIconId,
-                        mContentDescriptionPhoneSignal, mQSDataTypeIconId, mobileIn, mobileOut,
-                        mContentDescriptionDataType, mNetworkName, mNoSim,
-                        isQsTypeIconWide(mQSDataTypeIconId));
-            }
-        }
-        cb.onAirplaneModeChanged(mAirplaneMode);
-    }
-
-    public void setStackedMode(boolean stacked) {
-        mDataAndWifiStacked = true;
-    }
-
-    @Override
     public void onReceive(Context context, Intent intent) {
+        if (CHATTY) {
+            Log.d(TAG, "onReceive: intent=" + intent);
+        }
         final String action = intent.getAction();
-        if (action.equals(WifiManager.RSSI_CHANGED_ACTION)
-                || action.equals(WifiManager.WIFI_STATE_CHANGED_ACTION)
-                || action.equals(WifiManager.NETWORK_STATE_CHANGED_ACTION)) {
-            updateWifiState(intent);
-            refreshViews();
-        } else if (action.equals(TelephonyIntents.ACTION_SIM_STATE_CHANGED)) {
-            updateSimState(intent);
-            updateDataIcon();
-            refreshViews();
-        } else if (action.equals(TelephonyIntents.SPN_STRINGS_UPDATED_ACTION)) {
-            updateNetworkName(intent.getBooleanExtra(TelephonyIntents.EXTRA_SHOW_SPN, false),
-                        intent.getStringExtra(TelephonyIntents.EXTRA_SPN),
-                        intent.getBooleanExtra(TelephonyIntents.EXTRA_SHOW_PLMN, false),
-                        intent.getStringExtra(TelephonyIntents.EXTRA_PLMN));
-            refreshViews();
-        } else if (action.equals(ConnectivityManager.CONNECTIVITY_ACTION_IMMEDIATE) ||
-                 action.equals(ConnectivityManager.INET_CONDITION_ACTION)) {
+        if (action.equals(ConnectivityManager.CONNECTIVITY_ACTION_IMMEDIATE) ||
+                action.equals(ConnectivityManager.INET_CONDITION_ACTION)) {
             updateConnectivity(intent);
-            refreshViews();
+            refreshCarrierLabel();
         } else if (action.equals(Intent.ACTION_CONFIGURATION_CHANGED)) {
             refreshLocale();
-            refreshViews();
+            refreshCarrierLabel();
         } else if (action.equals(Intent.ACTION_AIRPLANE_MODE_CHANGED)) {
             refreshLocale();
-            updateAirplaneMode();
-            refreshViews();
-        } else if (action.equals(WimaxManagerConstants.NET_4G_STATE_CHANGED_ACTION) ||
-                action.equals(WimaxManagerConstants.SIGNAL_LEVEL_CHANGED_ACTION) ||
-                action.equals(WimaxManagerConstants.WIMAX_NETWORK_STATE_CHANGED_ACTION)) {
-            updateWimaxState(intent);
-            refreshViews();
+            updateAirplaneMode(false);
+            refreshCarrierLabel();
         }
+        mWifiSignalController.handleBroadcast(intent);
+        mMobileSignalController.handleBroadcast(intent);
     }
 
-
-    // ===== Telephony ==============================================================
-
-    PhoneStateListener mPhoneStateListener = new PhoneStateListener() {
-        @Override
-        public void onSignalStrengthsChanged(SignalStrength signalStrength) {
-            if (DEBUG) {
-                Log.d(TAG, "onSignalStrengthsChanged signalStrength=" + signalStrength +
-                    ((signalStrength == null) ? "" : (" level=" + signalStrength.getLevel())));
-            }
-            mSignalStrength = signalStrength;
-            updateTelephonySignalStrength();
-            refreshViews();
+    private void updateAirplaneMode(boolean force) {
+        boolean airplaneMode = (Settings.Global.getInt(mContext.getContentResolver(),
+                Settings.Global.AIRPLANE_MODE_ON, 0) == 1);
+        if (airplaneMode != mAirplaneMode || force) {
+            mAirplaneMode = airplaneMode;
+            mMobileSignalController.setAirplaneMode(mAirplaneMode);
+            notifyAirplaneCallbacks();
+            refreshCarrierLabel();
         }
-
-        @Override
-        public void onServiceStateChanged(ServiceState state) {
-            if (DEBUG) {
-                Log.d(TAG, "onServiceStateChanged voiceState=" + state.getVoiceRegState()
-                        + " dataState=" + state.getDataRegState());
-            }
-            mServiceState = state;
-            updateTelephonySignalStrength();
-            updateDataNetType();
-            updateDataIcon();
-            refreshViews();
-        }
-
-        @Override
-        public void onCallStateChanged(int state, String incomingNumber) {
-            if (DEBUG) {
-                Log.d(TAG, "onCallStateChanged state=" + state);
-            }
-            // In cdma, if a voice call is made, RSSI should switch to 1x.
-            if (isCdma()) {
-                updateTelephonySignalStrength();
-                refreshViews();
-            }
-        }
-
-        @Override
-        public void onDataConnectionStateChanged(int state, int networkType) {
-            if (DEBUG) {
-                Log.d(TAG, "onDataConnectionStateChanged: state=" + state
-                        + " type=" + networkType);
-            }
-            mDataState = state;
-            mDataNetType = networkType;
-            updateDataNetType();
-            updateDataIcon();
-            refreshViews();
-        }
-
-        @Override
-        public void onDataActivity(int direction) {
-            if (DEBUG) {
-                Log.d(TAG, "onDataActivity: direction=" + direction);
-            }
-            mDataActivity = direction;
-            updateDataIcon();
-            refreshViews();
-        }
-    };
-
-    private final void updateSimState(Intent intent) {
-        String stateExtra = intent.getStringExtra(IccCardConstants.INTENT_KEY_ICC_STATE);
-        if (IccCardConstants.INTENT_VALUE_ICC_ABSENT.equals(stateExtra)) {
-            mSimState = IccCardConstants.State.ABSENT;
-        }
-        else if (IccCardConstants.INTENT_VALUE_ICC_READY.equals(stateExtra)) {
-            mSimState = IccCardConstants.State.READY;
-        }
-        else if (IccCardConstants.INTENT_VALUE_ICC_LOCKED.equals(stateExtra)) {
-            final String lockedReason =
-                    intent.getStringExtra(IccCardConstants.INTENT_KEY_LOCKED_REASON);
-            if (IccCardConstants.INTENT_VALUE_LOCKED_ON_PIN.equals(lockedReason)) {
-                mSimState = IccCardConstants.State.PIN_REQUIRED;
-            }
-            else if (IccCardConstants.INTENT_VALUE_LOCKED_ON_PUK.equals(lockedReason)) {
-                mSimState = IccCardConstants.State.PUK_REQUIRED;
-            }
-            else {
-                mSimState = IccCardConstants.State.NETWORK_LOCKED;
-            }
-        } else {
-            mSimState = IccCardConstants.State.UNKNOWN;
-        }
-        if (DEBUG) Log.d(TAG, "updateSimState: mSimState=" + mSimState);
-    }
-
-    private boolean isCdma() {
-        return (mSignalStrength != null) && !mSignalStrength.isGsm();
-    }
-
-    private boolean hasService() {
-        boolean retVal;
-        if (mServiceState != null) {
-            // Consider the device to be in service if either voice or data service is available.
-            // Some SIM cards are marketed as data-only and do not support voice service, and on
-            // these SIM cards, we want to show signal bars for data service as well as the "no
-            // service" or "emergency calls only" text that indicates that voice is not available.
-            switch(mServiceState.getVoiceRegState()) {
-                case ServiceState.STATE_POWER_OFF:
-                    retVal = false;
-                    break;
-                case ServiceState.STATE_OUT_OF_SERVICE:
-                case ServiceState.STATE_EMERGENCY_ONLY:
-                    retVal = mServiceState.getDataRegState() == ServiceState.STATE_IN_SERVICE;
-                    break;
-                default:
-                    retVal = true;
-            }
-        } else {
-            retVal = false;
-        }
-        if (DEBUG) Log.d(TAG, "hasService: mServiceState=" + mServiceState + " retVal=" + retVal);
-        return retVal;
-    }
-
-    private void updateAirplaneMode() {
-        mAirplaneMode = (Settings.Global.getInt(mContext.getContentResolver(),
-            Settings.Global.AIRPLANE_MODE_ON, 0) == 1);
     }
 
     private void refreshLocale() {
-        mLocale = mContext.getResources().getConfiguration().locale;
-    }
-
-    private final void updateTelephonySignalStrength() {
-        if (DEBUG) {
-            Log.d(TAG, "updateTelephonySignalStrength: hasService=" + hasService()
-                    + " ss=" + mSignalStrength);
-        }
-        if (!hasService()) {
-            if (CHATTY) Log.d(TAG, "updateTelephonySignalStrength: !hasService()");
-            mPhoneSignalIconId = R.drawable.stat_sys_signal_null;
-            mQSPhoneSignalIconId = R.drawable.ic_qs_signal_no_signal;
-            mDataSignalIconId = R.drawable.stat_sys_signal_null;
-            mContentDescriptionPhoneSignal = mContext.getString(
-                    AccessibilityContentDescriptions.PHONE_SIGNAL_STRENGTH[0]);
-        } else {
-            if (mSignalStrength == null) {
-                if (CHATTY) Log.d(TAG, "updateTelephonySignalStrength: mSignalStrength == null");
-                mPhoneSignalIconId = R.drawable.stat_sys_signal_null;
-                mQSPhoneSignalIconId = R.drawable.ic_qs_signal_no_signal;
-                mDataSignalIconId = R.drawable.stat_sys_signal_null;
-                mContentDescriptionPhoneSignal = mContext.getString(
-                        AccessibilityContentDescriptions.PHONE_SIGNAL_STRENGTH[0]);
-            } else {
-                int iconLevel;
-                int[] iconList;
-                if (isCdma() && mAlwaysShowCdmaRssi) {
-                    mLastSignalLevel = iconLevel = mSignalStrength.getCdmaLevel();
-                    if (DEBUG) {
-                        Log.d(TAG, "updateTelephonySignalStrength:"
-                            + " mAlwaysShowCdmaRssi=" + mAlwaysShowCdmaRssi
-                            + " set to cdmaLevel=" + mSignalStrength.getCdmaLevel()
-                            + " instead of level=" + mSignalStrength.getLevel());
-                    }
-                } else {
-                    mLastSignalLevel = iconLevel = mSignalStrength.getLevel();
-                }
-
-                if (isRoaming()) {
-                    iconList = TelephonyIcons.TELEPHONY_SIGNAL_STRENGTH_ROAMING[mInetCondition];
-                } else {
-                    iconList = TelephonyIcons.TELEPHONY_SIGNAL_STRENGTH[mInetCondition];
-                }
-                mPhoneSignalIconId = iconList[iconLevel];
-                mQSPhoneSignalIconId =
-                        TelephonyIcons.QS_TELEPHONY_SIGNAL_STRENGTH[mInetCondition][iconLevel];
-                mContentDescriptionPhoneSignal = mContext.getString(
-                        AccessibilityContentDescriptions.PHONE_SIGNAL_STRENGTH[iconLevel]);
-                mDataSignalIconId = TelephonyIcons.DATA_SIGNAL_STRENGTH[mInetCondition][iconLevel];
-                if (DEBUG) Log.d(TAG, "updateTelephonySignalStrength: iconLevel=" + iconLevel);
-            }
+        Locale current = mContext.getResources().getConfiguration().locale;
+        if (current.equals(mLocale)) {
+            mLocale = current;
+            notifyAllListeners();
         }
     }
 
-    private int inetConditionForNetwork(int networkType) {
-        return (mInetCondition == 1 && mConnectedNetworkType == networkType) ? 1 : 0;
+    /**
+     * Turns inet condition into a boolean indexing for a specific network.
+     * returns 0 for bad connectivity on this network.
+     * returns 1 for good connectivity on this network.
+     */
+    private int inetConditionForNetwork(int networkType, boolean inetCondition) {
+        return (inetCondition && mConnectedNetworkType == networkType) ? 1 : 0;
     }
 
-    private final void updateDataNetType() {
-        int inetCondition;
-        mDataTypeIconId = mQSDataTypeIconId = 0;
-        if (mIsWimaxEnabled && mWimaxConnected) {
-            // wimax is a special 4g network not handled by telephony
-            inetCondition = inetConditionForNetwork(ConnectivityManager.TYPE_WIMAX);
-            mDataIconList = TelephonyIcons.DATA_4G[inetCondition];
-            mDataTypeIconId = R.drawable.stat_sys_data_fully_connected_4g;
-            mQSDataTypeIconId = TelephonyIcons.QS_DATA_4G[inetCondition];
-            mContentDescriptionDataType = mContext.getString(
-                    R.string.accessibility_data_connection_4g);
-        } else {
-            inetCondition = inetConditionForNetwork(ConnectivityManager.TYPE_MOBILE);
-            final boolean showDataTypeIcon = (inetCondition > 0);
-            switch (mDataNetType) {
-                case TelephonyManager.NETWORK_TYPE_UNKNOWN:
-                    if (!mShowAtLeastThreeGees) {
-                        mDataIconList = TelephonyIcons.DATA_G[inetCondition];
-                        mContentDescriptionDataType = "";
-                        break;
-                    } else {
-                        // fall through
-                    }
-                case TelephonyManager.NETWORK_TYPE_EDGE:
-                    if (!mShowAtLeastThreeGees) {
-                        mDataIconList = TelephonyIcons.DATA_E[inetCondition];
-                        mDataTypeIconId = showDataTypeIcon ?
-                                R.drawable.stat_sys_data_fully_connected_e : 0;
-                        mQSDataTypeIconId = TelephonyIcons.QS_DATA_E[inetCondition];
-                        mContentDescriptionDataType = mContext.getString(
-                                R.string.accessibility_data_connection_edge);
-                        break;
-                    } else {
-                        // fall through
-                    }
-                case TelephonyManager.NETWORK_TYPE_UMTS:
-                    mDataIconList = TelephonyIcons.DATA_3G[inetCondition];
-                    mDataTypeIconId = showDataTypeIcon ?
-                                R.drawable.stat_sys_data_fully_connected_3g : 0;
-                    mQSDataTypeIconId = TelephonyIcons.QS_DATA_3G[inetCondition];
-                    mContentDescriptionDataType = mContext.getString(
-                            R.string.accessibility_data_connection_3g);
-                    break;
-                case TelephonyManager.NETWORK_TYPE_HSDPA:
-                case TelephonyManager.NETWORK_TYPE_HSUPA:
-                case TelephonyManager.NETWORK_TYPE_HSPA:
-                case TelephonyManager.NETWORK_TYPE_HSPAP:
-                    if (mHspaDataDistinguishable) {
-                        mDataIconList = TelephonyIcons.DATA_H[inetCondition];
-                        mDataTypeIconId = showDataTypeIcon ?
-                                R.drawable.stat_sys_data_fully_connected_h : 0;
-                        mQSDataTypeIconId = TelephonyIcons.QS_DATA_H[inetCondition];
-                        mContentDescriptionDataType = mContext.getString(
-                                R.string.accessibility_data_connection_3_5g);
-                    } else {
-                        mDataIconList = TelephonyIcons.DATA_3G[inetCondition];
-                        mDataTypeIconId = showDataTypeIcon ?
-                                R.drawable.stat_sys_data_fully_connected_3g : 0;
-                        mQSDataTypeIconId = TelephonyIcons.QS_DATA_3G[inetCondition];
-                        mContentDescriptionDataType = mContext.getString(
-                                R.string.accessibility_data_connection_3g);
-                    }
-                    break;
-                case TelephonyManager.NETWORK_TYPE_CDMA:
-                    if (!mShowAtLeastThreeGees) {
-                        // display 1xRTT for IS95A/B
-                        mDataIconList = TelephonyIcons.DATA_1X[inetCondition];
-                        mDataTypeIconId = showDataTypeIcon ?
-                                R.drawable.stat_sys_data_fully_connected_1x : 0;
-                        mQSDataTypeIconId = TelephonyIcons.QS_DATA_1X[inetCondition];
-                        mContentDescriptionDataType = mContext.getString(
-                                R.string.accessibility_data_connection_cdma);
-                        break;
-                    } else {
-                        // fall through
-                    }
-                case TelephonyManager.NETWORK_TYPE_1xRTT:
-                    if (!mShowAtLeastThreeGees) {
-                        mDataIconList = TelephonyIcons.DATA_1X[inetCondition];
-                        mDataTypeIconId = showDataTypeIcon ?
-                                R.drawable.stat_sys_data_fully_connected_1x : 0;
-                        mQSDataTypeIconId = TelephonyIcons.QS_DATA_1X[inetCondition];
-                        mContentDescriptionDataType = mContext.getString(
-                                R.string.accessibility_data_connection_cdma);
-                        break;
-                    } else {
-                        // fall through
-                    }
-                case TelephonyManager.NETWORK_TYPE_EVDO_0: //fall through
-                case TelephonyManager.NETWORK_TYPE_EVDO_A:
-                case TelephonyManager.NETWORK_TYPE_EVDO_B:
-                case TelephonyManager.NETWORK_TYPE_EHRPD:
-                    mDataIconList = TelephonyIcons.DATA_3G[inetCondition];
-                    mDataTypeIconId = showDataTypeIcon ?
-                                R.drawable.stat_sys_data_fully_connected_3g : 0;
-                    mQSDataTypeIconId = TelephonyIcons.QS_DATA_3G[inetCondition];
-                    mContentDescriptionDataType = mContext.getString(
-                            R.string.accessibility_data_connection_3g);
-                    break;
-                case TelephonyManager.NETWORK_TYPE_LTE:
-                    boolean show4GforLTE = mContext.getResources().getBoolean(R.bool.config_show4GForLTE);
-                    if (show4GforLTE) {
-                        mDataIconList = TelephonyIcons.DATA_4G[inetCondition];
-                        mDataTypeIconId = showDataTypeIcon ?
-                                R.drawable.stat_sys_data_fully_connected_4g : 0;
-                        mQSDataTypeIconId = TelephonyIcons.QS_DATA_4G[inetCondition];
-                        mContentDescriptionDataType = mContext.getString(
-                                R.string.accessibility_data_connection_4g);
-                    } else {
-                        mDataIconList = TelephonyIcons.DATA_LTE[inetCondition];
-                        mDataTypeIconId = showDataTypeIcon ? TelephonyIcons.ICON_LTE : 0;
-                        mQSDataTypeIconId = TelephonyIcons.QS_DATA_LTE[inetCondition];
-                        mContentDescriptionDataType = mContext.getString(
-                                R.string.accessibility_data_connection_lte);
-                    }
-                    break;
-                default:
-                    if (!mShowAtLeastThreeGees) {
-                        mDataIconList = TelephonyIcons.DATA_G[inetCondition];
-                        mDataTypeIconId = showDataTypeIcon ?
-                                R.drawable.stat_sys_data_fully_connected_g : 0;
-                        mQSDataTypeIconId = TelephonyIcons.QS_DATA_G[inetCondition];
-                        mContentDescriptionDataType = mContext.getString(
-                                R.string.accessibility_data_connection_gprs);
-                    } else {
-                        mDataIconList = TelephonyIcons.DATA_3G[inetCondition];
-                        mDataTypeIconId = showDataTypeIcon ?
-                                R.drawable.stat_sys_data_fully_connected_3g : 0;
-                        mQSDataTypeIconId = TelephonyIcons.QS_DATA_3G[inetCondition];
-                        mContentDescriptionDataType = mContext.getString(
-                                R.string.accessibility_data_connection_3g);
-                    }
-                    break;
-            }
-        }
+    private void notifyAllListeners() {
+        // Something changed, trigger everything!
+        notifyAirplaneCallbacks();
+        mMobileSignalController.notifyListeners();
+        mWifiSignalController.notifyListeners();
+    }
 
-        if (isRoaming()) {
-            mDataTypeIconId = TelephonyIcons.ROAMING_ICON;
-            mQSDataTypeIconId = TelephonyIcons.QS_DATA_R[mInetCondition];
+    private void notifyAirplaneCallbacks() {
+        int length = mSignalClusters.size();
+        for (int i = 0; i < length; i++) {
+            mSignalClusters.get(i).setIsAirplaneMode(mAirplaneMode, TelephonyIcons.FLIGHT_MODE_ICON,
+                    R.string.accessibility_airplane_mode);
+        }
+        // update QS
+        int signalsChangedLength = mSignalsChangedCallbacks.size();
+        for (int i = 0; i < signalsChangedLength; i++) {
+            mSignalsChangedCallbacks.get(i).onAirplaneModeChanged(mAirplaneMode);
         }
     }
 
-    boolean isCdmaEri() {
-        if (mServiceState != null) {
-            final int iconIndex = mServiceState.getCdmaEriIconIndex();
-            if (iconIndex != EriInfo.ROAMING_INDICATOR_OFF) {
-                final int iconMode = mServiceState.getCdmaEriIconMode();
-                if (iconMode == EriInfo.ROAMING_ICON_MODE_NORMAL
-                        || iconMode == EriInfo.ROAMING_ICON_MODE_FLASH) {
-                    return true;
-                }
-            }
-        }
-        return false;
-    }
-
-    private boolean isRoaming() {
-        if (isCdma()) {
-            return isCdmaEri();
-        } else {
-            return mServiceState != null && mServiceState.getRoaming();
-        }
-    }
-
-    private final void updateDataIcon() {
-        int iconId;
-        boolean visible = true;
-
-        if (!isCdma()) {
-            // GSM case, we have to check also the sim state
-            if (mSimState == IccCardConstants.State.READY ||
-                    mSimState == IccCardConstants.State.UNKNOWN) {
-                mNoSim = false;
-                if (hasService() && mDataState == TelephonyManager.DATA_CONNECTED) {
-                    switch (mDataActivity) {
-                        case TelephonyManager.DATA_ACTIVITY_IN:
-                            iconId = mDataIconList[1];
-                            break;
-                        case TelephonyManager.DATA_ACTIVITY_OUT:
-                            iconId = mDataIconList[2];
-                            break;
-                        case TelephonyManager.DATA_ACTIVITY_INOUT:
-                            iconId = mDataIconList[3];
-                            break;
-                        default:
-                            iconId = mDataIconList[0];
-                            break;
-                    }
-                    mDataDirectionIconId = iconId;
-                } else {
-                    iconId = 0;
-                    visible = false;
-                }
-            } else {
-                iconId = 0;
-                mNoSim = true;
-                visible = false; // no SIM? no data
-            }
-        } else {
-            // CDMA case, mDataActivity can be also DATA_ACTIVITY_DORMANT
-            if (hasService() && mDataState == TelephonyManager.DATA_CONNECTED) {
-                switch (mDataActivity) {
-                    case TelephonyManager.DATA_ACTIVITY_IN:
-                        iconId = mDataIconList[1];
-                        break;
-                    case TelephonyManager.DATA_ACTIVITY_OUT:
-                        iconId = mDataIconList[2];
-                        break;
-                    case TelephonyManager.DATA_ACTIVITY_INOUT:
-                        iconId = mDataIconList[3];
-                        break;
-                    case TelephonyManager.DATA_ACTIVITY_DORMANT:
-                    default:
-                        iconId = mDataIconList[0];
-                        break;
-                }
-            } else {
-                iconId = 0;
-                visible = false;
-            }
-        }
-
-        mDataDirectionIconId = iconId;
-        mDataConnected = visible;
-    }
-
-    void updateNetworkName(boolean showSpn, String spn, boolean showPlmn, String plmn) {
-        if (false) {
-            Log.d("CarrierLabel", "updateNetworkName showSpn=" + showSpn + " spn=" + spn
-                    + " showPlmn=" + showPlmn + " plmn=" + plmn);
-        }
-        StringBuilder str = new StringBuilder();
-        boolean something = false;
-        if (showPlmn && plmn != null) {
-            str.append(plmn);
-            something = true;
-        }
-        if (showSpn && spn != null) {
-            if (something) {
-                str.append(mNetworkNameSeparator);
-            }
-            str.append(spn);
-            something = true;
-        }
-        if (something) {
-            mNetworkName = str.toString();
-        } else {
-            mNetworkName = mNetworkNameDefault;
-        }
-    }
-
-    // ===== Wifi ===================================================================
-
-    class WifiHandler extends Handler {
-        @Override
-        public void handleMessage(Message msg) {
-            switch (msg.what) {
-                case AsyncChannel.CMD_CHANNEL_HALF_CONNECTED:
-                    if (msg.arg1 == AsyncChannel.STATUS_SUCCESSFUL) {
-                        mWifiChannel.sendMessage(Message.obtain(this,
-                                AsyncChannel.CMD_CHANNEL_FULL_CONNECTION));
-                    } else {
-                        Log.e(TAG, "Failed to connect to wifi");
-                    }
-                    break;
-                case WifiManager.DATA_ACTIVITY_NOTIFICATION:
-                    if (msg.arg1 != mWifiActivity) {
-                        mWifiActivity = msg.arg1;
-                        refreshViews();
-                    }
-                    break;
-                default:
-                    //Ignore
-                    break;
-            }
-        }
-    }
-
-    private void updateWifiState(Intent intent) {
-        final String action = intent.getAction();
-        if (action.equals(WifiManager.WIFI_STATE_CHANGED_ACTION)) {
-            mWifiEnabled = intent.getIntExtra(WifiManager.EXTRA_WIFI_STATE,
-                    WifiManager.WIFI_STATE_UNKNOWN) == WifiManager.WIFI_STATE_ENABLED;
-
-        } else if (action.equals(WifiManager.NETWORK_STATE_CHANGED_ACTION)) {
-            final NetworkInfo networkInfo = (NetworkInfo)
-                    intent.getParcelableExtra(WifiManager.EXTRA_NETWORK_INFO);
-            boolean wasConnected = mWifiConnected;
-            mWifiConnected = networkInfo != null && networkInfo.isConnected();
-            // If Connected grab the signal strength and ssid
-            if (mWifiConnected) {
-                // try getting it out of the intent first
-                WifiInfo info = (WifiInfo) intent.getParcelableExtra(WifiManager.EXTRA_WIFI_INFO);
-                if (info == null) {
-                    info = mWifiManager.getConnectionInfo();
-                }
-                if (info != null) {
-                    mWifiSsid = huntForSsid(info);
-                } else {
-                    mWifiSsid = null;
-                }
-            } else if (!mWifiConnected) {
-                mWifiSsid = null;
-            }
-        } else if (action.equals(WifiManager.RSSI_CHANGED_ACTION)) {
-            mWifiRssi = intent.getIntExtra(WifiManager.EXTRA_NEW_RSSI, -200);
-            mWifiLevel = WifiManager.calculateSignalLevel(
-                    mWifiRssi, WifiIcons.WIFI_LEVEL_COUNT);
-        }
-
-        updateWifiIcons();
-    }
-
-    private void updateWifiIcons() {
-        int inetCondition = inetConditionForNetwork(ConnectivityManager.TYPE_WIFI);
-        if (mWifiConnected) {
-            mWifiIconId = WifiIcons.WIFI_SIGNAL_STRENGTH[inetCondition][mWifiLevel];
-            mQSWifiIconId = WifiIcons.QS_WIFI_SIGNAL_STRENGTH[inetCondition][mWifiLevel];
-            mContentDescriptionWifi = mContext.getString(
-                    AccessibilityContentDescriptions.WIFI_CONNECTION_STRENGTH[mWifiLevel]);
-        } else {
-            if (mDataAndWifiStacked) {
-                mWifiIconId = 0;
-                mQSWifiIconId = 0;
-            } else {
-                mWifiIconId = mWifiEnabled ? R.drawable.stat_sys_wifi_signal_null : 0;
-                mQSWifiIconId = mWifiEnabled ? R.drawable.ic_qs_wifi_no_network : 0;
-            }
-            mContentDescriptionWifi = mContext.getString(R.string.accessibility_no_wifi);
-        }
-    }
-
-    private String huntForSsid(WifiInfo info) {
-        String ssid = info.getSSID();
-        if (ssid != null) {
-            return ssid;
-        }
-        // OK, it's not in the connectionInfo; we have to go hunting for it
-        List<WifiConfiguration> networks = mWifiManager.getConfiguredNetworks();
-        for (WifiConfiguration net : networks) {
-            if (net.networkId == info.getNetworkId()) {
-                return net.SSID;
-            }
-        }
-        return null;
-    }
-
-
-    // ===== Wimax ===================================================================
-    private final void updateWimaxState(Intent intent) {
-        final String action = intent.getAction();
-        boolean wasConnected = mWimaxConnected;
-        if (action.equals(WimaxManagerConstants.NET_4G_STATE_CHANGED_ACTION)) {
-            int wimaxStatus = intent.getIntExtra(WimaxManagerConstants.EXTRA_4G_STATE,
-                    WimaxManagerConstants.NET_4G_STATE_UNKNOWN);
-            mIsWimaxEnabled = (wimaxStatus ==
-                    WimaxManagerConstants.NET_4G_STATE_ENABLED);
-        } else if (action.equals(WimaxManagerConstants.SIGNAL_LEVEL_CHANGED_ACTION)) {
-            mWimaxSignal = intent.getIntExtra(WimaxManagerConstants.EXTRA_NEW_SIGNAL_LEVEL, 0);
-        } else if (action.equals(WimaxManagerConstants.WIMAX_NETWORK_STATE_CHANGED_ACTION)) {
-            mWimaxState = intent.getIntExtra(WimaxManagerConstants.EXTRA_WIMAX_STATE,
-                    WimaxManagerConstants.NET_4G_STATE_UNKNOWN);
-            mWimaxExtraState = intent.getIntExtra(
-                    WimaxManagerConstants.EXTRA_WIMAX_STATE_DETAIL,
-                    WimaxManagerConstants.NET_4G_STATE_UNKNOWN);
-            mWimaxConnected = (mWimaxState ==
-                    WimaxManagerConstants.WIMAX_STATE_CONNECTED);
-            mWimaxIdle = (mWimaxExtraState == WimaxManagerConstants.WIMAX_IDLE);
-        }
-        updateDataNetType();
-        updateWimaxIcons();
-    }
-
-    private void updateWimaxIcons() {
-        if (mIsWimaxEnabled) {
-            if (mWimaxConnected) {
-                int inetCondition = inetConditionForNetwork(ConnectivityManager.TYPE_WIMAX);
-                if (mWimaxIdle)
-                    mWimaxIconId = WimaxIcons.WIMAX_IDLE;
-                else
-                    mWimaxIconId = WimaxIcons.WIMAX_SIGNAL_STRENGTH[inetCondition][mWimaxSignal];
-                mContentDescriptionWimax = mContext.getString(
-                        AccessibilityContentDescriptions.WIMAX_CONNECTION_STRENGTH[mWimaxSignal]);
-            } else {
-                mWimaxIconId = WimaxIcons.WIMAX_DISCONNECTED;
-                mContentDescriptionWimax = mContext.getString(R.string.accessibility_no_wimax);
-            }
-        } else {
-            mWimaxIconId = 0;
-        }
-    }
-
-    // ===== Full or limited Internet connectivity ==================================
-
+    /**
+     * Update the Inet conditions and what network we are connected to.
+     */
     private void updateConnectivity(Intent intent) {
-        if (CHATTY) {
-            Log.d(TAG, "updateConnectivity: intent=" + intent);
-        }
-
         final NetworkInfo info = mConnectivityManager.getActiveNetworkInfo();
 
         // Are we connected at all, by any interface?
@@ -1105,7 +364,7 @@
             Log.d(TAG, "updateConnectivity: connectionStatus=" + connectionStatus);
         }
 
-        mInetCondition = (connectionStatus > INET_CONDITION_THRESHOLD ? 1 : 0);
+        mInetCondition = connectionStatus > INET_CONDITION_THRESHOLD;
 
         if (info != null && info.getType() == ConnectivityManager.TYPE_BLUETOOTH) {
             mBluetoothTethered = info.isConnected();
@@ -1114,376 +373,68 @@
         }
 
         // We want to update all the icons, all at once, for any condition change
-        updateDataNetType();
-        updateWimaxIcons();
-        updateDataIcon();
-        updateTelephonySignalStrength();
-        updateWifiIcons();
+        mMobileSignalController.setInetCondition(mInetCondition ? 1 : 0,
+                inetConditionForNetwork(mMobileSignalController.getNetworkType(), mInetCondition));
+        mWifiSignalController.setInetCondition(
+                inetConditionForNetwork(mWifiSignalController.getNetworkType(), mInetCondition));
     }
 
-
-    // ===== Update the views =======================================================
-
-    void refreshViews() {
+    /**
+     * Recalculate and update the carrier label.
+     */
+    void refreshCarrierLabel() {
         Context context = mContext;
 
-        int combinedSignalIconId = 0;
-        String combinedLabel = "";
-        String wifiLabel = "";
-        String mobileLabel = "";
-        int N;
-        final boolean emergencyOnly = isEmergencyOnly();
+        WifiSignalController.WifiState wifiState = mWifiSignalController.getState();
+        MobileSignalController.MobileState mobileState = mMobileSignalController.getState();
+        String label = mMobileSignalController.getLabel("", mConnected, mHasMobileDataFeature);
 
-        if (!mHasMobileDataFeature) {
-            mDataSignalIconId = mPhoneSignalIconId = 0;
-            mQSPhoneSignalIconId = 0;
-            mobileLabel = "";
-        } else {
-            // We want to show the carrier name if in service and either:
-            //   - We are connected to mobile data, or
-            //   - We are not connected to mobile data, as long as the *reason* packets are not
-            //     being routed over that link is that we have better connectivity via wifi.
-            // If data is disconnected for some other reason but wifi (or ethernet/bluetooth)
-            // is connected, we show nothing.
-            // Otherwise (nothing connected) we show "No internet connection".
-
-            if (mDataConnected) {
-                mobileLabel = mNetworkName;
-            } else if (mConnected || emergencyOnly) {
-                if (hasService() || emergencyOnly) {
-                    // The isEmergencyOnly test covers the case of a phone with no SIM
-                    mobileLabel = mNetworkName;
-                } else {
-                    // Tablets, basically
-                    mobileLabel = "";
-                }
-            } else {
-                mobileLabel
-                    = context.getString(R.string.status_bar_settings_signal_meter_disconnected);
-            }
-
-            // Now for things that should only be shown when actually using mobile data.
-            if (mDataConnected) {
-                combinedSignalIconId = mDataSignalIconId;
-
-                combinedLabel = mobileLabel;
-                combinedSignalIconId = mDataSignalIconId; // set by updateDataIcon()
-                mContentDescriptionCombinedSignal = mContentDescriptionDataType;
-            }
+        // TODO Simplify this ugliness, some of the flows below shouldn't be possible anymore
+        // but stay for the sake of history.
+        if (mBluetoothTethered && !mHasMobileDataFeature) {
+            label = mContext.getString(R.string.bluetooth_tethered);
         }
 
-        if (mWifiConnected) {
-            if (mWifiSsid == null) {
-                wifiLabel = context.getString(R.string.status_bar_settings_signal_meter_wifi_nossid);
-            } else {
-                wifiLabel = mWifiSsid;
-                if (DEBUG) {
-                    wifiLabel += "xxxxXXXXxxxxXXXX";
-                }
-            }
-
-            combinedLabel = wifiLabel;
-            combinedSignalIconId = mWifiIconId; // set by updateWifiIcons()
-            mContentDescriptionCombinedSignal = mContentDescriptionWifi;
-        } else {
-            if (mHasMobileDataFeature) {
-                wifiLabel = "";
-            } else {
-                wifiLabel = context.getString(R.string.status_bar_settings_signal_meter_disconnected);
-            }
+        final boolean ethernetConnected =
+                (mConnectedNetworkType == ConnectivityManager.TYPE_ETHERNET);
+        if (ethernetConnected && !mHasMobileDataFeature) {
+            label = context.getString(R.string.ethernet_label);
         }
 
-        if (mBluetoothTethered) {
-            combinedLabel = mContext.getString(R.string.bluetooth_tethered);
-            combinedSignalIconId = mBluetoothTetherIconId;
-            mContentDescriptionCombinedSignal = mContext.getString(
-                    R.string.accessibility_bluetooth_tether);
-        }
-
-        final boolean ethernetConnected = (mConnectedNetworkType == ConnectivityManager.TYPE_ETHERNET);
-        if (ethernetConnected) {
-            combinedLabel = context.getString(R.string.ethernet_label);
-        }
-
-        if (mAirplaneMode &&
-                (mServiceState == null || (!hasService() && !mServiceState.isEmergencyOnly()))) {
-            // Only display the flight-mode icon if not in "emergency calls only" mode.
-
-            // look again; your radios are now airplanes
-            mContentDescriptionPhoneSignal = mContext.getString(
-                    R.string.accessibility_airplane_mode);
-            mAirplaneIconId = TelephonyIcons.FLIGHT_MODE_ICON;
-            mPhoneSignalIconId = mDataSignalIconId = mDataTypeIconId = mQSDataTypeIconId = 0;
-            mQSPhoneSignalIconId = 0;
-
+        if (mAirplaneMode && (!mobileState.connected && !mobileState.isEmergency)) {
             // combined values from connected wifi take precedence over airplane mode
-            if (mWifiConnected) {
+            if (wifiState.connected && mHasMobileDataFeature) {
                 // Suppress "No internet connection." from mobile if wifi connected.
-                mobileLabel = "";
+                label = "";
             } else {
-                if (mHasMobileDataFeature) {
-                    // let the mobile icon show "No internet connection."
-                    wifiLabel = "";
-                } else {
-                    wifiLabel = context.getString(R.string.status_bar_settings_signal_meter_disconnected);
-                    combinedLabel = wifiLabel;
-                }
-                mContentDescriptionCombinedSignal = mContentDescriptionPhoneSignal;
-                combinedSignalIconId = mDataSignalIconId;
+                 if (!mHasMobileDataFeature) {
+                      label = context.getString(
+                              R.string.status_bar_settings_signal_meter_disconnected);
+                 }
             }
-        }
-        else if (!mDataConnected && !mWifiConnected && !mBluetoothTethered && !mWimaxConnected && !ethernetConnected) {
-            // pretty much totally disconnected
-
-            combinedLabel = context.getString(R.string.status_bar_settings_signal_meter_disconnected);
-            // On devices without mobile radios, we want to show the wifi icon
-            combinedSignalIconId =
-                mHasMobileDataFeature ? mDataSignalIconId : mWifiIconId;
-            mContentDescriptionCombinedSignal = mHasMobileDataFeature
-                ? mContentDescriptionDataType : mContentDescriptionWifi;
-
-            int inetCondition = inetConditionForNetwork(ConnectivityManager.TYPE_MOBILE);
-
-            mDataTypeIconId = 0;
-            mQSDataTypeIconId = 0;
-            if (isRoaming()) {
-                mDataTypeIconId = TelephonyIcons.ROAMING_ICON;
-                mQSDataTypeIconId = TelephonyIcons.QS_DATA_R[mInetCondition];
-            }
+        } else if (!mobileState.dataConnected && !wifiState.connected && !mBluetoothTethered &&
+                 !ethernetConnected && !mHasMobileDataFeature) {
+            // Pretty much no connection.
+            label = context.getString(R.string.status_bar_settings_signal_meter_disconnected);
         }
 
-        if (mDemoMode) {
-            mQSWifiIconId = mDemoWifiLevel < 0 ? R.drawable.ic_qs_wifi_no_network
-                    : WifiIcons.QS_WIFI_SIGNAL_STRENGTH[mDemoInetCondition][mDemoWifiLevel];
-            mQSPhoneSignalIconId = mDemoMobileLevel < 0 ? R.drawable.ic_qs_signal_no_signal :
-                    TelephonyIcons.QS_TELEPHONY_SIGNAL_STRENGTH[mDemoInetCondition][mDemoMobileLevel];
-            mQSDataTypeIconId = mDemoQSDataTypeIconId;
-        }
-
-        if (DEBUG) {
-            Log.d(TAG, "refreshViews connected={"
-                    + (mWifiConnected?" wifi":"")
-                    + (mDataConnected?" data":"")
-                    + " } level="
-                    + ((mSignalStrength == null)?"??":Integer.toString(mSignalStrength.getLevel()))
-                    + " combinedSignalIconId=0x"
-                    + Integer.toHexString(combinedSignalIconId)
-                    + "/" + getResourceName(combinedSignalIconId)
-                    + " mobileLabel=" + mobileLabel
-                    + " wifiLabel=" + wifiLabel
-                    + " emergencyOnly=" + emergencyOnly
-                    + " combinedLabel=" + combinedLabel
-                    + " mAirplaneMode=" + mAirplaneMode
-                    + " mDataActivity=" + mDataActivity
-                    + " mPhoneSignalIconId=0x" + Integer.toHexString(mPhoneSignalIconId)
-                    + " mQSPhoneSignalIconId=0x" + Integer.toHexString(mQSPhoneSignalIconId)
-                    + " mDataDirectionIconId=0x" + Integer.toHexString(mDataDirectionIconId)
-                    + " mDataSignalIconId=0x" + Integer.toHexString(mDataSignalIconId)
-                    + " mDataTypeIconId=0x" + Integer.toHexString(mDataTypeIconId)
-                    + " mQSDataTypeIconId=0x" + Integer.toHexString(mQSDataTypeIconId)
-                    + " mWifiIconId=0x" + Integer.toHexString(mWifiIconId)
-                    + " mQSWifiIconId=0x" + Integer.toHexString(mQSWifiIconId)
-                    + " mBluetoothTetherIconId=0x" + Integer.toHexString(mBluetoothTetherIconId));
-        }
-
-        // update QS
-        for (NetworkSignalChangedCallback cb : mSignalsChangedCallbacks) {
-            notifySignalsChangedCallbacks(cb);
-        }
-
-        if (mLastPhoneSignalIconId          != mPhoneSignalIconId
-         || mLastWifiIconId                 != mWifiIconId
-         || mLastInetCondition              != mInetCondition
-         || mLastWimaxIconId                != mWimaxIconId
-         || mLastDataTypeIconId             != mDataTypeIconId
-         || mLastAirplaneMode               != mAirplaneMode
-         || mLastLocale                     != mLocale
-         || mLastConnectedNetworkType       != mConnectedNetworkType)
-        {
-            // NB: the mLast*s will be updated later
-            for (SignalCluster cluster : mSignalClusters) {
-                refreshSignalCluster(cluster);
-            }
-        }
-
-        if (mLastAirplaneMode != mAirplaneMode) {
-            mLastAirplaneMode = mAirplaneMode;
-        }
-
-        if (mLastLocale != mLocale) {
-            mLastLocale = mLocale;
-        }
-
-        // the phone icon on phones
-        if (mLastPhoneSignalIconId != mPhoneSignalIconId) {
-            mLastPhoneSignalIconId = mPhoneSignalIconId;
-        }
-
-        // the data icon on phones
-        if (mLastDataDirectionIconId != mDataDirectionIconId) {
-            mLastDataDirectionIconId = mDataDirectionIconId;
-        }
-
-        // the wifi icon on phones
-        if (mLastWifiIconId != mWifiIconId) {
-            mLastWifiIconId = mWifiIconId;
-        }
-
-        if (mLastInetCondition != mInetCondition) {
-            mLastInetCondition = mInetCondition;
-        }
-
-        if (mLastConnectedNetworkType != mConnectedNetworkType) {
-            mLastConnectedNetworkType = mConnectedNetworkType;
-        }
-
-        // the wimax icon on phones
-        if (mLastWimaxIconId != mWimaxIconId) {
-            mLastWimaxIconId = mWimaxIconId;
-        }
-        // the combined data signal icon
-        if (mLastCombinedSignalIconId != combinedSignalIconId) {
-            mLastCombinedSignalIconId = combinedSignalIconId;
-        }
-
-        // the data network type overlay
-        if (mLastDataTypeIconId != mDataTypeIconId) {
-            mLastDataTypeIconId = mDataTypeIconId;
-        }
-
-        // the combinedLabel in the notification panel
-        if (!mLastCombinedLabel.equals(combinedLabel)) {
-            mLastCombinedLabel = combinedLabel;
-            N = mCombinedLabelViews.size();
-            for (int i=0; i<N; i++) {
-                TextView v = mCombinedLabelViews.get(i);
-                v.setText(combinedLabel);
-            }
-        }
-
-        // wifi label
-        N = mWifiLabelViews.size();
-        for (int i=0; i<N; i++) {
-            TextView v = mWifiLabelViews.get(i);
-            v.setText(wifiLabel);
-            if ("".equals(wifiLabel)) {
-                v.setVisibility(View.GONE);
-            } else {
-                v.setVisibility(View.VISIBLE);
-            }
-        }
-
-        // mobile label
-        N = mMobileLabelViews.size();
-        for (int i=0; i<N; i++) {
-            TextView v = mMobileLabelViews.get(i);
-            v.setText(mobileLabel);
-            if ("".equals(mobileLabel)) {
-                v.setVisibility(View.GONE);
-            } else {
-                v.setVisibility(View.VISIBLE);
-            }
-        }
-
-        // e-call label
-        N = mEmergencyViews.size();
-        for (int i=0; i<N; i++) {
-            StatusBarHeaderView v = mEmergencyViews.get(i);
-            v.setShowEmergencyCallsOnly(emergencyOnly);
+        // for mobile devices, we always show mobile connection info here (SPN/PLMN)
+        // for other devices, we show whatever network is connected
+        // This is determined above by references to mHasMobileDataFeature.
+        int length = mCarrierListeners.size();
+        for (int i = 0; i < length; i++) {
+            mCarrierListeners.get(i).setCarrierLabel(label);
         }
     }
 
     public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
         pw.println("NetworkController state:");
         pw.println(String.format("  %s network type %d (%s)",
-                mConnected?"CONNECTED":"DISCONNECTED",
+                mConnected ? "CONNECTED" : "DISCONNECTED",
                 mConnectedNetworkType, mConnectedNetworkTypeName));
         pw.println("  - telephony ------");
         pw.print("  hasVoiceCallingFeature()=");
         pw.println(hasVoiceCallingFeature());
-        pw.print("  hasService()=");
-        pw.println(hasService());
-        pw.print("  mHspaDataDistinguishable=");
-        pw.println(mHspaDataDistinguishable);
-        pw.print("  mDataConnected=");
-        pw.println(mDataConnected);
-        pw.print("  mSimState=");
-        pw.println(mSimState);
-        pw.print("  mPhoneState=");
-        pw.println(mPhoneState);
-        pw.print("  mDataState=");
-        pw.println(mDataState);
-        pw.print("  mDataActivity=");
-        pw.println(mDataActivity);
-        pw.print("  mDataNetType=");
-        pw.print(mDataNetType);
-        pw.print("/");
-        pw.println(TelephonyManager.getNetworkTypeName(mDataNetType));
-        pw.print("  mServiceState=");
-        pw.println(mServiceState);
-        pw.print("  mSignalStrength=");
-        pw.println(mSignalStrength);
-        pw.print("  mLastSignalLevel=");
-        pw.println(mLastSignalLevel);
-        pw.print("  mNetworkName=");
-        pw.println(mNetworkName);
-        pw.print("  mNetworkNameDefault=");
-        pw.println(mNetworkNameDefault);
-        pw.print("  mNetworkNameSeparator=");
-        pw.println(mNetworkNameSeparator.replace("\n","\\n"));
-        pw.print("  mPhoneSignalIconId=0x");
-        pw.print(Integer.toHexString(mPhoneSignalIconId));
-        pw.print("/");
-        pw.print("  mQSPhoneSignalIconId=0x");
-        pw.print(Integer.toHexString(mQSPhoneSignalIconId));
-        pw.print("/");
-        pw.println(getResourceName(mPhoneSignalIconId));
-        pw.print("  mDataDirectionIconId=");
-        pw.print(Integer.toHexString(mDataDirectionIconId));
-        pw.print("/");
-        pw.println(getResourceName(mDataDirectionIconId));
-        pw.print("  mDataSignalIconId=");
-        pw.print(Integer.toHexString(mDataSignalIconId));
-        pw.print("/");
-        pw.println(getResourceName(mDataSignalIconId));
-        pw.print("  mDataTypeIconId=");
-        pw.print(Integer.toHexString(mDataTypeIconId));
-        pw.print("/");
-        pw.println(getResourceName(mDataTypeIconId));
-        pw.print("  mQSDataTypeIconId=");
-        pw.print(Integer.toHexString(mQSDataTypeIconId));
-        pw.print("/");
-        pw.println(getResourceName(mQSDataTypeIconId));
-
-        pw.println("  - wifi ------");
-        pw.print("  mWifiEnabled=");
-        pw.println(mWifiEnabled);
-        pw.print("  mWifiConnected=");
-        pw.println(mWifiConnected);
-        pw.print("  mWifiRssi=");
-        pw.println(mWifiRssi);
-        pw.print("  mWifiLevel=");
-        pw.println(mWifiLevel);
-        pw.print("  mWifiSsid=");
-        pw.println(mWifiSsid);
-        pw.println(String.format("  mWifiIconId=0x%08x/%s",
-                    mWifiIconId, getResourceName(mWifiIconId)));
-        pw.println(String.format("  mQSWifiIconId=0x%08x/%s",
-                    mQSWifiIconId, getResourceName(mQSWifiIconId)));
-        pw.print("  mWifiActivity=");
-        pw.println(mWifiActivity);
-
-        if (mWimaxSupported) {
-            pw.println("  - wimax ------");
-            pw.print("  mIsWimaxEnabled="); pw.println(mIsWimaxEnabled);
-            pw.print("  mWimaxConnected="); pw.println(mWimaxConnected);
-            pw.print("  mWimaxIdle="); pw.println(mWimaxIdle);
-            pw.println(String.format("  mWimaxIconId=0x%08x/%s",
-                        mWimaxIconId, getResourceName(mWimaxIconId)));
-            pw.println(String.format("  mWimaxSignal=%d", mWimaxSignal));
-            pw.println(String.format("  mWimaxState=%d", mWimaxState));
-            pw.println(String.format("  mWimaxExtraState=%d", mWimaxExtraState));
-        }
 
         pw.println("  - Bluetooth ----");
         pw.print("  mBtReverseTethered=");
@@ -1492,143 +443,1079 @@
         pw.println("  - connectivity ------");
         pw.print("  mInetCondition=");
         pw.println(mInetCondition);
+        pw.print("  mAirplaneMode=");
+        pw.println(mAirplaneMode);
+        pw.print("  mLocale=");
+        pw.println(mLocale);
 
-        pw.println("  - icons ------");
-        pw.print("  mLastPhoneSignalIconId=0x");
-        pw.print(Integer.toHexString(mLastPhoneSignalIconId));
-        pw.print("/");
-        pw.println(getResourceName(mLastPhoneSignalIconId));
-        pw.print("  mLastDataDirectionIconId=0x");
-        pw.print(Integer.toHexString(mLastDataDirectionIconId));
-        pw.print("/");
-        pw.println(getResourceName(mLastDataDirectionIconId));
-        pw.print("  mLastWifiIconId=0x");
-        pw.print(Integer.toHexString(mLastWifiIconId));
-        pw.print("/");
-        pw.println(getResourceName(mLastWifiIconId));
-        pw.print("  mLastCombinedSignalIconId=0x");
-        pw.print(Integer.toHexString(mLastCombinedSignalIconId));
-        pw.print("/");
-        pw.println(getResourceName(mLastCombinedSignalIconId));
-        pw.print("  mLastDataTypeIconId=0x");
-        pw.print(Integer.toHexString(mLastDataTypeIconId));
-        pw.print("/");
-        pw.println(getResourceName(mLastDataTypeIconId));
-        pw.print("  mLastCombinedLabel=");
-        pw.print(mLastCombinedLabel);
-        pw.println("");
-    }
-
-    private String getResourceName(int resId) {
-        if (resId != 0) {
-            final Resources res = mContext.getResources();
-            try {
-                return res.getResourceName(resId);
-            } catch (android.content.res.Resources.NotFoundException ex) {
-                return "(unknown)";
-            }
-        } else {
-            return "(null)";
-        }
+        mMobileSignalController.dump(pw);
+        mWifiSignalController.dump(pw);
     }
 
     private boolean mDemoMode;
     private int mDemoInetCondition;
-    private int mDemoWifiLevel;
-    private int mDemoDataTypeIconId;
-    private int mDemoQSDataTypeIconId;
-    private int mDemoMobileLevel;
+    private WifiSignalController.WifiState mDemoWifiState;
+    private MobileSignalController.MobileState mDemoMobileState;
 
     @Override
     public void dispatchDemoCommand(String command, Bundle args) {
         if (!mDemoMode && command.equals(COMMAND_ENTER)) {
+            if (DEBUG) Log.d(TAG, "Entering demo mode");
+            unregisterListeners();
             mDemoMode = true;
-            mDemoWifiLevel = mWifiLevel;
-            mDemoInetCondition = mInetCondition;
-            mDemoDataTypeIconId = mDataTypeIconId;
-            mDemoQSDataTypeIconId = mQSDataTypeIconId;
-            mDemoMobileLevel = mLastSignalLevel;
+            mDemoInetCondition = mInetCondition ? 1 : 0;
+            mDemoWifiState = mWifiSignalController.getState();
+            mDemoMobileState = mMobileSignalController.getState();
         } else if (mDemoMode && command.equals(COMMAND_EXIT)) {
+            if (DEBUG) Log.d(TAG, "Exiting demo mode");
             mDemoMode = false;
-            for (SignalCluster cluster : mSignalClusters) {
-                refreshSignalCluster(cluster);
-            }
-            refreshViews();
+            mWifiSignalController.resetLastState();
+            mMobileSignalController.resetLastState();
+            registerListeners();
+            notifyAllListeners();
+            refreshCarrierLabel();
         } else if (mDemoMode && command.equals(COMMAND_NETWORK)) {
             String airplane = args.getString("airplane");
             if (airplane != null) {
                 boolean show = airplane.equals("show");
-                for (SignalCluster cluster : mSignalClusters) {
-                    cluster.setIsAirplaneMode(show, TelephonyIcons.FLIGHT_MODE_ICON);
+                int length = mSignalClusters.size();
+                for (int i = 0; i < length; i++) {
+                    mSignalClusters.get(i).setIsAirplaneMode(show, TelephonyIcons.FLIGHT_MODE_ICON,
+                            R.string.accessibility_airplane_mode);
                 }
             }
             String fully = args.getString("fully");
             if (fully != null) {
                 mDemoInetCondition = Boolean.parseBoolean(fully) ? 1 : 0;
+                mWifiSignalController.setInetCondition(mDemoInetCondition);
+                mMobileSignalController.setInetCondition(mDemoInetCondition, mDemoInetCondition);
             }
             String wifi = args.getString("wifi");
             if (wifi != null) {
                 boolean show = wifi.equals("show");
                 String level = args.getString("level");
                 if (level != null) {
-                    mDemoWifiLevel = level.equals("null") ? -1
+                    mDemoWifiState.level = level.equals("null") ? -1
                             : Math.min(Integer.parseInt(level), WifiIcons.WIFI_LEVEL_COUNT - 1);
+                    mDemoWifiState.connected = mDemoWifiState.level >= 0;
                 }
-                int iconId = mDemoWifiLevel < 0 ? R.drawable.stat_sys_wifi_signal_null
-                        : WifiIcons.WIFI_SIGNAL_STRENGTH[mDemoInetCondition][mDemoWifiLevel];
-                for (SignalCluster cluster : mSignalClusters) {
-                    cluster.setWifiIndicators(
-                            show,
-                            iconId,
-                            "Demo");
-                }
-                refreshViews();
+                mDemoWifiState.enabled = show;
+                mWifiSignalController.notifyListeners();
             }
             String mobile = args.getString("mobile");
             if (mobile != null) {
                 boolean show = mobile.equals("show");
                 String datatype = args.getString("datatype");
                 if (datatype != null) {
-                    mDemoDataTypeIconId =
-                            datatype.equals("1x") ? TelephonyIcons.ICON_1X :
-                            datatype.equals("3g") ? TelephonyIcons.ICON_3G :
-                            datatype.equals("4g") ? TelephonyIcons.ICON_4G :
-                            datatype.equals("e") ? R.drawable.stat_sys_data_fully_connected_e :
-                            datatype.equals("g") ? R.drawable.stat_sys_data_fully_connected_g :
-                            datatype.equals("h") ? R.drawable.stat_sys_data_fully_connected_h :
-                            datatype.equals("lte") ? TelephonyIcons.ICON_LTE :
-                            datatype.equals("roam") ? TelephonyIcons.ROAMING_ICON :
-                            0;
-                    mDemoQSDataTypeIconId =
-                            datatype.equals("1x") ? TelephonyIcons.QS_ICON_1X :
-                            datatype.equals("3g") ? TelephonyIcons.QS_ICON_3G :
-                            datatype.equals("4g") ? TelephonyIcons.QS_ICON_4G :
-                            datatype.equals("e") ? R.drawable.ic_qs_signal_e :
-                            datatype.equals("g") ? R.drawable.ic_qs_signal_g :
-                            datatype.equals("h") ? R.drawable.ic_qs_signal_h :
-                            datatype.equals("lte") ? TelephonyIcons.QS_ICON_LTE :
-                            datatype.equals("roam") ? R.drawable.ic_qs_signal_r :
-                            0;
+                    mDemoMobileState.iconGroup =
+                            datatype.equals("1x") ? TelephonyIcons.ONE_X :
+                            datatype.equals("3g") ? TelephonyIcons.THREE_G :
+                            datatype.equals("4g") ? TelephonyIcons.FOUR_G :
+                            datatype.equals("e") ? TelephonyIcons.E :
+                            datatype.equals("g") ? TelephonyIcons.G :
+                            datatype.equals("h") ? TelephonyIcons.H :
+                            datatype.equals("lte") ? TelephonyIcons.LTE :
+                            datatype.equals("roam") ? TelephonyIcons.ROAMING :
+                            TelephonyIcons.UNKNOWN;
                 }
                 int[][] icons = TelephonyIcons.TELEPHONY_SIGNAL_STRENGTH;
                 String level = args.getString("level");
                 if (level != null) {
-                    mDemoMobileLevel = level.equals("null") ? -1
+                    mDemoMobileState.level = level.equals("null") ? -1
                             : Math.min(Integer.parseInt(level), icons[0].length - 1);
+                    mDemoMobileState.connected = mDemoMobileState.level >= 0;
                 }
-                int iconId = mDemoMobileLevel < 0 ? R.drawable.stat_sys_signal_null :
-                        icons[mDemoInetCondition][mDemoMobileLevel];
-                for (SignalCluster cluster : mSignalClusters) {
-                    cluster.setMobileDataIndicators(
-                            show,
-                            iconId,
-                            mDemoDataTypeIconId,
-                            "Demo",
-                            "Demo",
-                            isTypeIconWide(mDemoDataTypeIconId));
-                }
-                refreshViews();
+                mDemoMobileState.enabled = show;
+                mMobileSignalController.notifyListeners();
             }
+            refreshCarrierLabel();
+        }
+    }
+
+    static class WifiSignalController extends
+            SignalController<WifiSignalController.WifiState, SignalController.IconGroup> {
+        private final WifiManager mWifiManager;
+        private final AsyncChannel mWifiChannel;
+        private final boolean mHasMobileData;
+
+        public WifiSignalController(Context context, boolean hasMobileData,
+                List<NetworkSignalChangedCallback> signalCallbacks,
+                List<SignalCluster> signalClusters, NetworkControllerImpl networkController) {
+            super("WifiSignalController", context, ConnectivityManager.TYPE_WIFI, signalCallbacks,
+                    signalClusters, networkController);
+            mWifiManager = (WifiManager) context.getSystemService(Context.WIFI_SERVICE);
+            mHasMobileData = hasMobileData;
+            Handler handler = new WifiHandler();
+            mWifiChannel = new AsyncChannel();
+            Messenger wifiMessenger = mWifiManager.getWifiServiceMessenger();
+            if (wifiMessenger != null) {
+                mWifiChannel.connect(context, handler, wifiMessenger);
+            }
+            // WiFi only has one state.
+            mCurrentState.iconGroup = mLastState.iconGroup = new IconGroup(
+                    "Wi-Fi Icons",
+                    WifiIcons.WIFI_SIGNAL_STRENGTH,
+                    WifiIcons.QS_WIFI_SIGNAL_STRENGTH,
+                    AccessibilityContentDescriptions.WIFI_CONNECTION_STRENGTH,
+                    WifiIcons.WIFI_NO_NETWORK,
+                    WifiIcons.QS_WIFI_NO_NETWORK,
+                    WifiIcons.WIFI_NO_NETWORK,
+                    WifiIcons.QS_WIFI_NO_NETWORK,
+                    AccessibilityContentDescriptions.WIFI_NO_CONNECTION
+                    );
+        }
+
+        @Override
+        public WifiState cleanState() {
+            return new WifiState();
+        }
+
+        /**
+         * {@inheritDoc}
+         */
+        @Override
+        public void notifyListeners() {
+            // only show wifi in the cluster if connected or if wifi-only
+            boolean wifiEnabled = mCurrentState.enabled
+                    && (mCurrentState.connected || !mHasMobileData);
+            String wifiDesc = wifiEnabled ? mCurrentState.ssid : null;
+            boolean ssidPresent = wifiEnabled && mCurrentState.ssid != null;
+            String contentDescription = getStringIfExists(getContentDescription());
+            int length = mSignalsChangedCallbacks.size();
+            for (int i = 0; i < length; i++) {
+                mSignalsChangedCallbacks.get(i).onWifiSignalChanged(mCurrentState.enabled,
+                        mCurrentState.connected, getQsCurrentIconId(),
+                        ssidPresent && mCurrentState.activityIn,
+                        ssidPresent && mCurrentState.activityOut, contentDescription, wifiDesc);
+            }
+
+            int signalClustersLength = mSignalClusters.size();
+            for (int i = 0; i < signalClustersLength; i++) {
+                mSignalClusters.get(i).setWifiIndicators(
+                        // only show wifi in the cluster if connected or if wifi-only
+                        mCurrentState.enabled && (mCurrentState.connected || !mHasMobileData),
+                        getCurrentIconId(), contentDescription);
+            }
+        }
+
+        /**
+         * Extract wifi state directly from broadcasts about changes in wifi state.
+         */
+        public void handleBroadcast(Intent intent) {
+            String action = intent.getAction();
+            if (action.equals(WifiManager.WIFI_STATE_CHANGED_ACTION)) {
+                mCurrentState.enabled = intent.getIntExtra(WifiManager.EXTRA_WIFI_STATE,
+                        WifiManager.WIFI_STATE_UNKNOWN) == WifiManager.WIFI_STATE_ENABLED;
+            } else if (action.equals(WifiManager.NETWORK_STATE_CHANGED_ACTION)) {
+                final NetworkInfo networkInfo = (NetworkInfo)
+                        intent.getParcelableExtra(WifiManager.EXTRA_NETWORK_INFO);
+                mCurrentState.connected = networkInfo != null && networkInfo.isConnected();
+                // If Connected grab the signal strength and ssid.
+                if (mCurrentState.connected) {
+                    // try getting it out of the intent first
+                    WifiInfo info = intent.getParcelableExtra(WifiManager.EXTRA_WIFI_INFO) != null
+                            ? (WifiInfo) intent.getParcelableExtra(WifiManager.EXTRA_WIFI_INFO)
+                            : mWifiManager.getConnectionInfo();
+                    if (info != null) {
+                        mCurrentState.ssid = huntForSsid(info);
+                    } else {
+                        mCurrentState.ssid = null;
+                    }
+                } else if (!mCurrentState.connected) {
+                    mCurrentState.ssid = null;
+                }
+            } else if (action.equals(WifiManager.RSSI_CHANGED_ACTION)) {
+                mCurrentState.rssi = intent.getIntExtra(WifiManager.EXTRA_NEW_RSSI, -200);
+                mCurrentState.level = WifiManager.calculateSignalLevel(
+                        mCurrentState.rssi, WifiIcons.WIFI_LEVEL_COUNT);
+            }
+
+            notifyListenersIfNecessary();
+        }
+
+        private String huntForSsid(WifiInfo info) {
+            String ssid = info.getSSID();
+            if (ssid != null) {
+                return ssid;
+            }
+            // OK, it's not in the connectionInfo; we have to go hunting for it
+            List<WifiConfiguration> networks = mWifiManager.getConfiguredNetworks();
+            int length = networks.size();
+            for (int i = 0; i < length; i++) {
+                if (networks.get(i).networkId == info.getNetworkId()) {
+                    return networks.get(i).SSID;
+                }
+            }
+            return null;
+        }
+
+        @VisibleForTesting
+        void setActivity(int wifiActivity) {
+            mCurrentState.activityIn = wifiActivity == WifiManager.DATA_ACTIVITY_INOUT
+                    || wifiActivity == WifiManager.DATA_ACTIVITY_IN;
+            mCurrentState.activityOut = wifiActivity == WifiManager.DATA_ACTIVITY_INOUT
+                    || wifiActivity == WifiManager.DATA_ACTIVITY_OUT;
+            notifyListenersIfNecessary();
+        }
+
+        /**
+         * Handler to receive the data activity on wifi.
+         */
+        class WifiHandler extends Handler {
+            @Override
+            public void handleMessage(Message msg) {
+                switch (msg.what) {
+                    case AsyncChannel.CMD_CHANNEL_HALF_CONNECTED:
+                        if (msg.arg1 == AsyncChannel.STATUS_SUCCESSFUL) {
+                            mWifiChannel.sendMessage(Message.obtain(this,
+                                    AsyncChannel.CMD_CHANNEL_FULL_CONNECTION));
+                        } else {
+                            Log.e(mTag, "Failed to connect to wifi");
+                        }
+                        break;
+                    case WifiManager.DATA_ACTIVITY_NOTIFICATION:
+                        setActivity(msg.arg1);
+                        break;
+                    default:
+                        // Ignore
+                        break;
+                }
+            }
+        }
+
+        static class WifiState extends SignalController.State {
+            String ssid;
+
+            @Override
+            public void copyFrom(State s) {
+                WifiState state = (WifiState) s;
+                ssid = state.ssid;
+                super.copyFrom(s);
+            }
+
+            @Override
+            protected void toString(StringBuilder builder) {
+                builder.append("ssid=").append(ssid).append(',');
+                super.toString(builder);
+            }
+
+            @Override
+            public boolean equals(Object o) {
+                return super.equals(o)
+                        && Objects.equals(((WifiState) o).ssid, ssid);
+            }
+        }
+    }
+
+    static class MobileSignalController extends SignalController<MobileSignalController.MobileState,
+            MobileSignalController.MobileIconGroup> {
+        private final Config mConfig;
+        private final TelephonyManager mPhone;
+        private final String mNetworkNameDefault;
+        private final String mNetworkNameSeparator;
+
+        // @VisibleForDemoMode
+        Map<Integer, MobileIconGroup> mNetworkToIconLookup;
+
+        // Since some pieces of the phone state are interdependent we store it locally,
+        // this could potentially become part of MobileState for simplification/complication
+        // of code.
+        private IccCardConstants.State mSimState = IccCardConstants.State.READY;
+        private int mDataNetType = TelephonyManager.NETWORK_TYPE_UNKNOWN;
+        private int mDataState = TelephonyManager.DATA_DISCONNECTED;
+        private ServiceState mServiceState;
+        private SignalStrength mSignalStrength;
+        private MobileIconGroup mDefaultIcons;
+
+        // TODO: Reduce number of vars passed in, if we have the NetworkController, probably don't
+        // need listener lists anymore.
+        public MobileSignalController(Context context, Config config, boolean hasMobileData,
+                TelephonyManager phone, List<NetworkSignalChangedCallback> signalCallbacks,
+                List<SignalCluster> signalClusters, NetworkControllerImpl networkController) {
+            super("MobileSignalController", context, ConnectivityManager.TYPE_MOBILE,
+                    signalCallbacks, signalClusters, networkController);
+            mConfig = config;
+            mPhone = phone;
+            mNetworkNameSeparator = getStringIfExists(R.string.status_bar_network_name_separator);
+            mNetworkNameDefault = getStringIfExists(
+                    com.android.internal.R.string.lockscreen_carrier_default);
+
+            mapIconSets();
+
+            mLastState.networkName = mCurrentState.networkName = mNetworkNameDefault;
+            mLastState.enabled = mCurrentState.enabled = hasMobileData;
+            mLastState.iconGroup = mCurrentState.iconGroup = mDefaultIcons;
+        }
+
+        /**
+         * Get (the mobile parts of) the carrier string.
+         *
+         * @param currentLabel can be used for concatenation, currently just empty
+         * @param connected whether the device has connection to the internet at all
+         * @param isMobileLabel whether to always return the network or just when data is connected
+         */
+        public String getLabel(String currentLabel, boolean connected, boolean isMobileLabel) {
+            if (!mCurrentState.enabled) {
+                return "";
+            } else {
+                String mobileLabel = "";
+                // We want to show the carrier name if in service and either:
+                // - We are connected to mobile data, or
+                // - We are not connected to mobile data, as long as the *reason* packets are not
+                //   being routed over that link is that we have better connectivity via wifi.
+                // If data is disconnected for some other reason but wifi (or ethernet/bluetooth)
+                // is connected, we show nothing.
+                // Otherwise (nothing connected) we show "No internet connection".
+                if (mCurrentState.dataConnected) {
+                    mobileLabel = mCurrentState.networkName;
+                } else if (connected || mCurrentState.isEmergency) {
+                    if (mCurrentState.connected || mCurrentState.isEmergency) {
+                        // The isEmergencyOnly test covers the case of a phone with no SIM
+                        mobileLabel = mCurrentState.networkName;
+                    }
+                } else {
+                    mobileLabel = mContext
+                            .getString(R.string.status_bar_settings_signal_meter_disconnected);
+                }
+
+                // Now for things that should only be shown when actually using mobile data.
+                if (isMobileLabel) {
+                    return mobileLabel;
+                } else {
+                    return mCurrentState.dataConnected ? mobileLabel : currentLabel;
+                }
+            }
+        }
+
+        public int getDataContentDescription() {
+            return getIcons().mDataContentDescription;
+        }
+
+        public void setAirplaneMode(boolean airplaneMode) {
+            mCurrentState.airplaneMode = airplaneMode;
+            notifyListenersIfNecessary();
+        }
+
+        public void setInetCondition(int inetCondition, int inetConditionForNetwork) {
+            // For mobile data, use general inet condition for phone signal indexing,
+            // and network specific for data indexing (I think this might be a bug, but
+            // keeping for now).
+            // TODO: Update with explanation of why.
+            mCurrentState.inetForNetwork = inetConditionForNetwork;
+            setInetCondition(inetCondition);
+        }
+
+        /**
+         * Start listening for phone state changes.
+         */
+        public void registerListener() {
+            mPhone.listen(mPhoneStateListener,
+                    PhoneStateListener.LISTEN_SERVICE_STATE
+                            | PhoneStateListener.LISTEN_SIGNAL_STRENGTHS
+                            | PhoneStateListener.LISTEN_CALL_STATE
+                            | PhoneStateListener.LISTEN_DATA_CONNECTION_STATE
+                            | PhoneStateListener.LISTEN_DATA_ACTIVITY);
+        }
+
+        /**
+         * Stop listening for phone state changes.
+         */
+        public void unregisterListener() {
+            mPhone.listen(mPhoneStateListener, 0);
+        }
+
+        /**
+         * Produce a mapping of data network types to icon groups for simple and quick use in
+         * updateTelephony.
+         *
+         * TODO: See if config can change with locale, this may need to be regenerated on Locale
+         * change.
+         */
+        private void mapIconSets() {
+            mNetworkToIconLookup = new HashMap<Integer, MobileIconGroup>();
+
+            mNetworkToIconLookup.put(TelephonyManager.NETWORK_TYPE_EVDO_0, TelephonyIcons.THREE_G);
+            mNetworkToIconLookup.put(TelephonyManager.NETWORK_TYPE_EVDO_A, TelephonyIcons.THREE_G);
+            mNetworkToIconLookup.put(TelephonyManager.NETWORK_TYPE_EVDO_B, TelephonyIcons.THREE_G);
+            mNetworkToIconLookup.put(TelephonyManager.NETWORK_TYPE_EHRPD, TelephonyIcons.THREE_G);
+            mNetworkToIconLookup.put(TelephonyManager.NETWORK_TYPE_UMTS, TelephonyIcons.THREE_G);
+
+            if (!mConfig.showAtLeastThreeGees) {
+                mNetworkToIconLookup.put(TelephonyManager.NETWORK_TYPE_UNKNOWN,
+                        TelephonyIcons.UNKNOWN);
+                mNetworkToIconLookup.put(TelephonyManager.NETWORK_TYPE_EDGE, TelephonyIcons.E);
+                mNetworkToIconLookup.put(TelephonyManager.NETWORK_TYPE_CDMA, TelephonyIcons.ONE_X);
+                mNetworkToIconLookup.put(TelephonyManager.NETWORK_TYPE_1xRTT, TelephonyIcons.ONE_X);
+
+                mDefaultIcons = TelephonyIcons.G;
+            } else {
+                mNetworkToIconLookup.put(TelephonyManager.NETWORK_TYPE_UNKNOWN,
+                        TelephonyIcons.THREE_G);
+                mNetworkToIconLookup.put(TelephonyManager.NETWORK_TYPE_EDGE,
+                        TelephonyIcons.THREE_G);
+                mNetworkToIconLookup.put(TelephonyManager.NETWORK_TYPE_CDMA,
+                        TelephonyIcons.THREE_G);
+                mNetworkToIconLookup.put(TelephonyManager.NETWORK_TYPE_1xRTT,
+                        TelephonyIcons.THREE_G);
+                mDefaultIcons = TelephonyIcons.THREE_G;
+            }
+
+            MobileIconGroup hGroup = TelephonyIcons.THREE_G;
+            if (mConfig.hspaDataDistinguishable) {
+                hGroup = TelephonyIcons.H;
+            }
+            mNetworkToIconLookup.put(TelephonyManager.NETWORK_TYPE_HSDPA, hGroup);
+            mNetworkToIconLookup.put(TelephonyManager.NETWORK_TYPE_HSUPA, hGroup);
+            mNetworkToIconLookup.put(TelephonyManager.NETWORK_TYPE_HSPA, hGroup);
+            mNetworkToIconLookup.put(TelephonyManager.NETWORK_TYPE_HSPAP, hGroup);
+
+            if (mConfig.show4gForLte) {
+                mNetworkToIconLookup.put(TelephonyManager.NETWORK_TYPE_LTE, TelephonyIcons.FOUR_G);
+            } else {
+                mNetworkToIconLookup.put(TelephonyManager.NETWORK_TYPE_LTE, TelephonyIcons.LTE);
+            }
+        }
+
+        /**
+         * {@inheritDoc}
+         */
+        @Override
+        public void notifyListeners() {
+            MobileIconGroup icons = getIcons();
+
+            String contentDescription = getStringIfExists(getContentDescription());
+            String dataContentDescription = getStringIfExists(icons.mDataContentDescription);
+            int qsTypeIcon = icons.mQsDataType[mCurrentState.inetForNetwork];
+            int length = mSignalsChangedCallbacks.size();
+            for (int i = 0; i < length; i++) {
+                mSignalsChangedCallbacks.get(i).onMobileDataSignalChanged(mCurrentState.enabled
+                        && !mCurrentState.isEmergency && !mCurrentState.airplaneMode,
+                        getQsCurrentIconId(), contentDescription,
+                        qsTypeIcon,
+                        mCurrentState.dataConnected && mCurrentState.activityIn,
+                        mCurrentState.dataConnected && mCurrentState.activityOut,
+                        dataContentDescription,
+                        mCurrentState.isEmergency ? null : mCurrentState.networkName,
+                        mCurrentState.noSim,
+                        // Only wide if actually showing something.
+                        icons.mIsWide && qsTypeIcon != 0);
+            }
+            boolean showDataIcon = mCurrentState.inetForNetwork != 0
+                    || mCurrentState.iconGroup == TelephonyIcons.ROAMING;
+            int typeIcon = showDataIcon ? icons.mDataType : 0;
+            int signalClustersLength = mSignalClusters.size();
+            for (int i = 0; i < signalClustersLength; i++) {
+                mSignalClusters.get(i).setMobileDataIndicators(
+                        mCurrentState.enabled && !mCurrentState.airplaneMode,
+                        getCurrentIconId(),
+                        typeIcon,
+                        contentDescription,
+                        dataContentDescription,
+                        // Only wide if actually showing something.
+                        icons.mIsWide && typeIcon != 0);
+            }
+        }
+
+        @Override
+        public MobileState cleanState() {
+            return new MobileState();
+        }
+
+        private boolean hasService() {
+            if (mServiceState != null) {
+                // Consider the device to be in service if either voice or data
+                // service is available. Some SIM cards are marketed as data-only
+                // and do not support voice service, and on these SIM cards, we
+                // want to show signal bars for data service as well as the "no
+                // service" or "emergency calls only" text that indicates that voice
+                // is not available.
+                switch (mServiceState.getVoiceRegState()) {
+                    case ServiceState.STATE_POWER_OFF:
+                        return false;
+                    case ServiceState.STATE_OUT_OF_SERVICE:
+                    case ServiceState.STATE_EMERGENCY_ONLY:
+                        return mServiceState.getDataRegState() == ServiceState.STATE_IN_SERVICE;
+                    default:
+                        return true;
+                }
+            } else {
+                return false;
+            }
+        }
+
+        private boolean isCdma() {
+            return (mSignalStrength != null) && !mSignalStrength.isGsm();
+        }
+
+        public boolean isEmergencyOnly() {
+            return (mServiceState != null && mServiceState.isEmergencyOnly());
+        }
+
+        private boolean isRoaming() {
+            if (isCdma()) {
+                final int iconMode = mServiceState.getCdmaEriIconMode();
+                return mServiceState.getCdmaEriIconIndex() != EriInfo.ROAMING_INDICATOR_OFF
+                        && (iconMode == EriInfo.ROAMING_ICON_MODE_NORMAL
+                            || iconMode == EriInfo.ROAMING_ICON_MODE_FLASH);
+            } else {
+                return mServiceState != null && mServiceState.getRoaming();
+            }
+        }
+
+        public void handleBroadcast(Intent intent) {
+            String action = intent.getAction();
+            if (action.equals(TelephonyIntents.ACTION_SIM_STATE_CHANGED)) {
+                String stateExtra = intent.getStringExtra(IccCardConstants.INTENT_KEY_ICC_STATE);
+                final String lockedReason =
+                        intent.getStringExtra(IccCardConstants.INTENT_KEY_LOCKED_REASON);
+                updateSimState(stateExtra, lockedReason);
+                updateTelephony();
+            } else if (action.equals(TelephonyIntents.SPN_STRINGS_UPDATED_ACTION)) {
+                updateNetworkName(intent.getBooleanExtra(TelephonyIntents.EXTRA_SHOW_SPN, false),
+                        intent.getStringExtra(TelephonyIntents.EXTRA_SPN),
+                        intent.getBooleanExtra(TelephonyIntents.EXTRA_SHOW_PLMN, false),
+                        intent.getStringExtra(TelephonyIntents.EXTRA_PLMN));
+                notifyListenersIfNecessary();
+            }
+        }
+
+        /**
+         * Determines the current sim state, based on a TelephonyIntents.ACTION_SIM_STATE_CHANGED
+         * broadcast.
+         */
+        private final void updateSimState(String stateExtra, String lockedReason) {
+            if (IccCardConstants.INTENT_VALUE_ICC_ABSENT.equals(stateExtra)) {
+                mSimState = IccCardConstants.State.ABSENT;
+            } else if (IccCardConstants.INTENT_VALUE_ICC_READY.equals(stateExtra)) {
+                mSimState = IccCardConstants.State.READY;
+            } else if (IccCardConstants.INTENT_VALUE_ICC_LOCKED.equals(stateExtra)) {
+                if (IccCardConstants.INTENT_VALUE_LOCKED_ON_PIN.equals(lockedReason)) {
+                    mSimState = IccCardConstants.State.PIN_REQUIRED;
+                } else if (IccCardConstants.INTENT_VALUE_LOCKED_ON_PUK.equals(lockedReason)) {
+                    mSimState = IccCardConstants.State.PUK_REQUIRED;
+                } else {
+                    mSimState = IccCardConstants.State.NETWORK_LOCKED;
+                }
+            } else {
+                mSimState = IccCardConstants.State.UNKNOWN;
+            }
+            if (DEBUG) Log.d(TAG, "updateSimState: mSimState=" + mSimState);
+        }
+
+        /**
+         * Updates the network's name based on incoming spn and plmn.
+         */
+        void updateNetworkName(boolean showSpn, String spn, boolean showPlmn, String plmn) {
+            if (CHATTY) {
+                Log.d("CarrierLabel", "updateNetworkName showSpn=" + showSpn + " spn=" + spn
+                        + " showPlmn=" + showPlmn + " plmn=" + plmn);
+            }
+            StringBuilder str = new StringBuilder();
+            if (showPlmn && plmn != null) {
+                str.append(plmn);
+            }
+            if (showSpn && spn != null) {
+                if (str.length() != 0) {
+                    str.append(mNetworkNameSeparator);
+                }
+                str.append(spn);
+            }
+            if (str.length() != 0) {
+                mCurrentState.networkName = str.toString();
+            } else {
+                mCurrentState.networkName = mNetworkNameDefault;
+            }
+        }
+
+        /**
+         * Updates the current state based on mServiceState, mSignalStrength, mDataNetType,
+         * mDataState, and mSimState.  It should be called any time one of these is updated.
+         * This will call listeners if necessary.
+         */
+        private final void updateTelephony() {
+            if (DEBUG) {
+                Log.d(TAG, "updateTelephonySignalStrength: hasService=" + hasService()
+                        + " ss=" + mSignalStrength);
+            }
+            mCurrentState.connected = hasService() && mSignalStrength != null;
+            if (mCurrentState.connected) {
+                if (!mSignalStrength.isGsm() && mConfig.alwaysShowCdmaRssi) {
+                    mCurrentState.level = mSignalStrength.getCdmaLevel();
+                } else {
+                    mCurrentState.level = mSignalStrength.getLevel();
+                }
+            }
+            if (mNetworkToIconLookup.containsKey(mDataNetType)) {
+                mCurrentState.iconGroup = mNetworkToIconLookup.get(mDataNetType);
+            } else {
+                mCurrentState.iconGroup = mDefaultIcons;
+            }
+            mCurrentState.dataConnected = mCurrentState.connected
+                    && mDataState == TelephonyManager.DATA_CONNECTED;
+            if (!isCdma()) {
+                if (mSimState == IccCardConstants.State.READY ||
+                        mSimState == IccCardConstants.State.UNKNOWN) {
+                    mCurrentState.noSim = false;
+                } else {
+                    mCurrentState.noSim = true;
+                    // No sim, no data.
+                    mCurrentState.dataConnected = false;
+                }
+            }
+
+            if (isRoaming()) {
+                mCurrentState.iconGroup = TelephonyIcons.ROAMING;
+            }
+            if (isEmergencyOnly() != mCurrentState.isEmergency) {
+                mCurrentState.isEmergency = isEmergencyOnly();
+                mNetworkController.recalculateEmergency();
+            }
+            notifyListenersIfNecessary();
+        }
+
+        @VisibleForTesting
+        void setActivity(int activity) {
+            mCurrentState.activityIn = activity == TelephonyManager.DATA_ACTIVITY_INOUT
+                    || activity == TelephonyManager.DATA_ACTIVITY_IN;
+            mCurrentState.activityOut = activity == TelephonyManager.DATA_ACTIVITY_INOUT
+                    || activity == TelephonyManager.DATA_ACTIVITY_OUT;
+            notifyListenersIfNecessary();
+        }
+
+        @Override
+        public void dump(PrintWriter pw) {
+            super.dump(pw);
+            pw.println("  mServiceState=" + mServiceState + ",");
+            pw.println("  mSignalStrength=" + mSignalStrength + ",");
+            pw.println("  mDataState=" + mDataState + ",");
+            pw.println("  mDataNetType=" + mDataNetType + ",");
+        }
+
+        PhoneStateListener mPhoneStateListener = new PhoneStateListener() {
+            @Override
+            public void onSignalStrengthsChanged(SignalStrength signalStrength) {
+                if (DEBUG) {
+                    Log.d(TAG, "onSignalStrengthsChanged signalStrength=" + signalStrength +
+                            ((signalStrength == null) ? "" : (" level=" + signalStrength.getLevel())));
+                }
+                mSignalStrength = signalStrength;
+                updateTelephony();
+            }
+
+            @Override
+            public void onServiceStateChanged(ServiceState state) {
+                if (DEBUG) {
+                    Log.d(TAG, "onServiceStateChanged voiceState=" + state.getVoiceRegState()
+                            + " dataState=" + state.getDataRegState());
+                }
+                mServiceState = state;
+                updateTelephony();
+            }
+
+            @Override
+            public void onDataConnectionStateChanged(int state, int networkType) {
+                if (DEBUG) {
+                    Log.d(TAG, "onDataConnectionStateChanged: state=" + state
+                            + " type=" + networkType);
+                }
+                mDataState = state;
+                mDataNetType = networkType;
+                updateTelephony();
+            }
+
+            @Override
+            public void onDataActivity(int direction) {
+                if (DEBUG) {
+                    Log.d(TAG, "onDataActivity: direction=" + direction);
+                }
+                setActivity(direction);
+            }
+        };
+
+        static class MobileIconGroup extends SignalController.IconGroup {
+            final int mDataContentDescription; // mContentDescriptionDataType
+            final int mDataType;
+            final boolean mIsWide;
+            final int[] mQsDataType;
+
+            public MobileIconGroup(String name, int[][] sbIcons, int[][] qsIcons, int[] contentDesc,
+                    int sbNullState, int qsNullState, int sbDiscState, int qsDiscState,
+                    int discContentDesc, int dataContentDesc, int dataType, boolean isWide,
+                    int[] qsDataType) {
+                super(name, sbIcons, qsIcons, contentDesc, sbNullState, qsNullState, sbDiscState,
+                        qsDiscState, discContentDesc);
+                mDataContentDescription = dataContentDesc;
+                mDataType = dataType;
+                mIsWide = isWide;
+                mQsDataType = qsDataType;
+            }
+        }
+
+        static class MobileState extends SignalController.State {
+            String networkName;
+            boolean noSim;
+            boolean dataConnected;
+            boolean isEmergency;
+            boolean airplaneMode;
+            int inetForNetwork;
+
+            @Override
+            public void copyFrom(State s) {
+                MobileState state = (MobileState) s;
+                noSim = state.noSim;
+                networkName = state.networkName;
+                dataConnected = state.dataConnected;
+                inetForNetwork = state.inetForNetwork;
+                isEmergency = state.isEmergency;
+                airplaneMode = state.airplaneMode;
+                super.copyFrom(s);
+            }
+
+            @Override
+            protected void toString(StringBuilder builder) {
+                builder.append("noSim=").append(noSim).append(',');
+                builder.append("networkName=").append(networkName).append(',');
+                builder.append("dataConnected=").append(dataConnected).append(',');
+                builder.append("inetForNetwork=").append(inetForNetwork).append(',');
+                builder.append("isEmergency=").append(isEmergency).append(',');
+                builder.append("airplaneMode=").append(airplaneMode).append(',');
+                super.toString(builder);
+            }
+
+            @Override
+            public boolean equals(Object o) {
+                return super.equals(o)
+                        && Objects.equals(((MobileState) o).networkName, networkName)
+                        && ((MobileState) o).noSim == noSim
+                        && ((MobileState) o).dataConnected == dataConnected
+                        && ((MobileState) o).isEmergency == isEmergency
+                        && ((MobileState) o).airplaneMode == airplaneMode
+                        && ((MobileState) o).inetForNetwork == inetForNetwork;
+            }
+        }
+    }
+
+    /**
+     * Common base class for handling signal for both wifi and mobile data.
+     */
+    static abstract class SignalController<T extends SignalController.State,
+            I extends SignalController.IconGroup> {
+        protected final String mTag;
+        protected final T mCurrentState;
+        protected final T mLastState;
+        protected final int mNetworkType;
+        protected final Context mContext;
+        // The owner of the SignalController (i.e. NetworkController will maintain the following
+        // lists and call notifyListeners whenever the list has changed to ensure everyone
+        // is aware of current state.
+        protected final List<NetworkSignalChangedCallback> mSignalsChangedCallbacks;
+        protected final List<SignalCluster> mSignalClusters;
+        protected final NetworkControllerImpl mNetworkController;
+
+        // Save the previous HISTORY_SIZE states for logging.
+        private final State[] mHistory;
+        // Where to copy the next state into.
+        private int mHistoryIndex;
+
+        public SignalController(String tag, Context context, int type,
+                List<NetworkSignalChangedCallback> signalCallbacks,
+                List<SignalCluster> signalClusters, NetworkControllerImpl networkController) {
+            mTag = TAG + "::" + tag;
+            mNetworkController = networkController;
+            mNetworkType = type;
+            mContext = context;
+            mSignalsChangedCallbacks = signalCallbacks;
+            mSignalClusters = signalClusters;
+            mCurrentState = cleanState();
+            mLastState = cleanState();
+            if (RECORD_HISTORY) {
+                mHistory = new State[HISTORY_SIZE];
+                for (int i = 0; i < HISTORY_SIZE; i++) {
+                    mHistory[i] = cleanState();
+                }
+            }
+        }
+
+        public T getState() {
+            return mCurrentState;
+        }
+
+        public int getNetworkType() {
+            return mNetworkType;
+        }
+
+        public void setInetCondition(int inetCondition) {
+            mCurrentState.inetCondition = inetCondition;
+            notifyListenersIfNecessary();
+        }
+
+        // @VisibleForDemoMode
+        /**
+         * Used at the end of demo mode to clear out any ugly state that it has created.
+         * Since we haven't had any callbacks, then isDirty will not have been triggered,
+         * so we can just take the last good state directly from there.
+         */
+        void resetLastState() {
+            mCurrentState.copyFrom(mLastState);
+        }
+
+        /**
+         * Determines if the state of this signal controller has changed and
+         * needs to trigger callbacks related to it.
+         */
+        public boolean isDirty() {
+            if (!mLastState.equals(mCurrentState)) {
+                if (DEBUG) {
+                    Log.d(mTag, "Change in state from: " + mLastState + "\n"
+                            + "\tto: " + mCurrentState);
+                }
+                return true;
+            }
+            return false;
+        }
+
+        public void saveLastState() {
+            if (RECORD_HISTORY) {
+                recordLast();
+            }
+            // Updates the current time.
+            mCurrentState.time = System.currentTimeMillis();
+            mLastState.copyFrom(mCurrentState);
+        }
+
+        /**
+         * Gets the signal icon for QS based on current state of connected, enabled, and level.
+         */
+        public int getQsCurrentIconId() {
+            if (mCurrentState.connected) {
+                return getIcons().mQsIcons[mCurrentState.inetCondition][mCurrentState.level];
+            } else if (mCurrentState.enabled) {
+                return getIcons().mQsDiscState;
+            } else {
+                return getIcons().mQsNullState;
+            }
+        }
+
+        /**
+         * Gets the signal icon for SB based on current state of connected, enabled, and level.
+         */
+        public int getCurrentIconId() {
+            if (mCurrentState.connected) {
+                return getIcons().mSbIcons[mCurrentState.inetCondition][mCurrentState.level];
+            } else if (mCurrentState.enabled) {
+                return getIcons().mSbDiscState;
+            } else {
+                return getIcons().mSbNullState;
+            }
+        }
+
+        /**
+         * Gets the content description for the signal based on current state of connected and
+         * level.
+         */
+        public int getContentDescription() {
+            if (mCurrentState.connected) {
+                return getIcons().mContentDesc[mCurrentState.level];
+            } else {
+                return getIcons().mDiscContentDesc;
+            }
+        }
+
+        protected void notifyListenersIfNecessary() {
+            if (isDirty()) {
+                saveLastState();
+                notifyListeners();
+                mNetworkController.refreshCarrierLabel();
+            }
+        }
+
+        /**
+         * Returns the resource if resId is not 0, and an empty string otherwise.
+         */
+        protected String getStringIfExists(int resId) {
+            return resId != 0 ? mContext.getString(resId) : "";
+        }
+
+        protected I getIcons() {
+            return (I) mCurrentState.iconGroup;
+        }
+
+        /**
+         * Saves the last state of any changes, so we can log the current
+         * and last value of any state data.
+         */
+        protected void recordLast() {
+            mHistory[mHistoryIndex++ & (HISTORY_SIZE - 1)].copyFrom(mLastState);
+        }
+
+        public void dump(PrintWriter pw) {
+            pw.println("  - " + mTag + " -----");
+            pw.println("  Current State: " + mCurrentState);
+            if (RECORD_HISTORY) {
+                // Count up the states that actually contain time stamps, and only display those.
+                int size = 0;
+                for (int i = 0; i < HISTORY_SIZE; i++) {
+                    if (mHistory[i].time != 0) size++;
+                }
+                // Print out the previous states in ordered number.
+                for (int i = mHistoryIndex + HISTORY_SIZE - 1;
+                        i >= mHistoryIndex + HISTORY_SIZE - size; i--) {
+                    pw.println("  Previous State(" + (mHistoryIndex + HISTORY_SIZE - i) + ": "
+                            + mHistory[i & (HISTORY_SIZE - 1)]);
+                }
+            }
+        }
+
+        /**
+         * Trigger callbacks based on current state.  The callbacks should be completely
+         * based on current state, and only need to be called in the scenario where
+         * mCurrentState != mLastState.
+         */
+        public abstract void notifyListeners();
+
+        /**
+         * Generate a blank T.
+         */
+        public abstract T cleanState();
+
+        /*
+         * Holds icons for a given state. Arrays are generally indexed as inet
+         * state (full connectivity or not) first, and second dimension as
+         * signal strength.
+         */
+        static class IconGroup {
+            final int[][] mSbIcons;
+            final int[][] mQsIcons;
+            final int[] mContentDesc;
+            final int mSbNullState;
+            final int mQsNullState;
+            final int mSbDiscState;
+            final int mQsDiscState;
+            final int mDiscContentDesc;
+            // For logging.
+            final String mName;
+
+            public IconGroup(String name, int[][] sbIcons, int[][] qsIcons, int[] contentDesc,
+                    int sbNullState, int qsNullState, int sbDiscState, int qsDiscState,
+                    int discContentDesc) {
+                mName = name;
+                mSbIcons = sbIcons;
+                mQsIcons = qsIcons;
+                mContentDesc = contentDesc;
+                mSbNullState = sbNullState;
+                mQsNullState = qsNullState;
+                mSbDiscState = sbDiscState;
+                mQsDiscState = qsDiscState;
+                mDiscContentDesc = discContentDesc;
+            }
+
+            @Override
+            public String toString() {
+                return "IconGroup(" + mName + ")";
+            }
+        }
+
+        static class State {
+            boolean connected;
+            boolean enabled;
+            boolean activityIn;
+            boolean activityOut;
+            int level;
+            IconGroup iconGroup;
+            int inetCondition;
+            int rssi; // Only for logging.
+
+            // Not used for comparison, just used for logging.
+            long time;
+
+            public void copyFrom(State state) {
+                connected = state.connected;
+                enabled = state.enabled;
+                level = state.level;
+                iconGroup = state.iconGroup;
+                inetCondition = state.inetCondition;
+                activityIn = state.activityIn;
+                activityOut = state.activityOut;
+                rssi = state.rssi;
+                time = state.time;
+            }
+
+            @Override
+            public String toString() {
+                if (time != 0) {
+                    StringBuilder builder = new StringBuilder();
+                    toString(builder);
+                    return builder.toString();
+                } else {
+                    return "Empty " + getClass().getSimpleName();
+                }
+            }
+
+            protected void toString(StringBuilder builder) {
+                builder.append("connected=").append(connected).append(',')
+                        .append("enabled=").append(enabled).append(',')
+                        .append("level=").append(level).append(',')
+                        .append("inetCondition=").append(inetCondition).append(',')
+                        .append("iconGroup=").append(iconGroup).append(',')
+                        .append("activityIn=").append(activityIn).append(',')
+                        .append("activityOut=").append(activityOut).append(',')
+                        .append("rssi=").append(rssi).append(',')
+                        .append("lastModified=").append(DateFormat.format("MM-dd hh:mm:ss", time));
+            }
+
+            @Override
+            public boolean equals(Object o) {
+                if (!o.getClass().equals(getClass())) {
+                    return false;
+                }
+                State other = (State) o;
+                return other.connected == connected
+                        && other.enabled == enabled
+                        && other.level == level
+                        && other.inetCondition == inetCondition
+                        && other.iconGroup == iconGroup
+                        && other.activityIn == activityIn
+                        && other.activityOut == activityOut
+                        && other.rssi == rssi;
+            }
+        }
+    }
+
+    public interface SignalCluster {
+        void setWifiIndicators(boolean visible, int strengthIcon, String contentDescription);
+
+        void setMobileDataIndicators(boolean visible, int strengthIcon, int typeIcon,
+                String contentDescription, String typeContentDescription, boolean isTypeIconWide);
+
+        void setIsAirplaneMode(boolean is, int airplaneIcon, int contentDescription);
+    }
+
+    public interface EmergencyListener {
+        void setEmergencyCallsOnly(boolean emergencyOnly);
+    }
+
+    public interface CarrierLabelListener {
+        void setCarrierLabel(String label);
+    }
+
+    @VisibleForTesting
+    static class Config {
+        boolean showAtLeastThreeGees = false;
+        boolean alwaysShowCdmaRssi = false;
+        boolean show4gForLte = false;
+        boolean hspaDataDistinguishable;
+
+        static Config readConfig(Context context) {
+            Config config = new Config();
+            Resources res = context.getResources();
+
+            config.showAtLeastThreeGees = res.getBoolean(R.bool.config_showMin3G);
+            config.alwaysShowCdmaRssi =
+                    res.getBoolean(com.android.internal.R.bool.config_alwaysUseCdmaRssi);
+            config.show4gForLte = res.getBoolean(R.bool.config_show4GForLTE);
+            config.hspaDataDistinguishable =
+                    res.getBoolean(R.bool.config_hspa_data_distinguishable);
+            return config;
         }
     }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/TelephonyIcons.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/TelephonyIcons.java
index 1f2b918..4091619 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/TelephonyIcons.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/TelephonyIcons.java
@@ -17,11 +17,16 @@
 package com.android.systemui.statusbar.policy;
 
 import com.android.systemui.R;
+import com.android.systemui.statusbar.policy.NetworkControllerImpl.MobileSignalController.MobileIconGroup;
 
 class TelephonyIcons {
     //***** Signal strength icons
 
+    static final int TELEPHONY_NUM_LEVELS = 5;
+
     //GSM/UMTS
+    static final int TELEPHONY_NO_NETWORK = R.drawable.stat_sys_signal_null;
+
     static final int[][] TELEPHONY_SIGNAL_STRENGTH = {
         { R.drawable.stat_sys_signal_0,
           R.drawable.stat_sys_signal_1,
@@ -35,6 +40,8 @@
           R.drawable.stat_sys_signal_4_fully }
     };
 
+    static final int QS_TELEPHONY_NO_NETWORK = R.drawable.ic_qs_signal_no_signal;
+
     static final int[][] QS_TELEPHONY_SIGNAL_STRENGTH = {
         { R.drawable.ic_qs_signal_0,
           R.drawable.ic_qs_signal_1,
@@ -66,8 +73,6 @@
         R.drawable.ic_qs_signal_r
     };
 
-    static final int[][] DATA_SIGNAL_STRENGTH = TELEPHONY_SIGNAL_STRENGTH;
-
     //***** Data connection icons
 
     //GSM/UMTS
@@ -191,6 +196,9 @@
     static final int FLIGHT_MODE_ICON = R.drawable.stat_sys_airplane_mode;
     static final int ROAMING_ICON = R.drawable.stat_sys_data_fully_connected_roam;
     static final int ICON_LTE = R.drawable.stat_sys_data_fully_connected_lte;
+    static final int ICON_G = R.drawable.stat_sys_data_fully_connected_g;
+    static final int ICON_E = R.drawable.stat_sys_data_fully_connected_e;
+    static final int ICON_H = R.drawable.stat_sys_data_fully_connected_h;
     static final int ICON_3G = R.drawable.stat_sys_data_fully_connected_3g;
     static final int ICON_4G = R.drawable.stat_sys_data_fully_connected_4g;
     static final int ICON_1X = R.drawable.stat_sys_data_fully_connected_1x;
@@ -199,5 +207,137 @@
     static final int QS_ICON_3G = R.drawable.ic_qs_signal_3g;
     static final int QS_ICON_4G = R.drawable.ic_qs_signal_4g;
     static final int QS_ICON_1X = R.drawable.ic_qs_signal_1x;
+
+    static final MobileIconGroup THREE_G = new MobileIconGroup(
+            "3G",
+            TelephonyIcons.TELEPHONY_SIGNAL_STRENGTH,
+            TelephonyIcons.QS_TELEPHONY_SIGNAL_STRENGTH,
+            AccessibilityContentDescriptions.PHONE_SIGNAL_STRENGTH,
+            0, 0,
+            TelephonyIcons.TELEPHONY_NO_NETWORK,
+            TelephonyIcons.QS_TELEPHONY_NO_NETWORK,
+            AccessibilityContentDescriptions.PHONE_SIGNAL_STRENGTH[0],
+            R.string.accessibility_data_connection_3g,
+            TelephonyIcons.ICON_3G,
+            true,
+            TelephonyIcons.QS_DATA_3G
+            );
+
+    static final MobileIconGroup UNKNOWN = new MobileIconGroup(
+            "Unknown",
+            TelephonyIcons.TELEPHONY_SIGNAL_STRENGTH,
+            TelephonyIcons.QS_TELEPHONY_SIGNAL_STRENGTH,
+            AccessibilityContentDescriptions.PHONE_SIGNAL_STRENGTH,
+            0, 0,
+            TelephonyIcons.TELEPHONY_NO_NETWORK,
+            TelephonyIcons.QS_TELEPHONY_NO_NETWORK,
+            AccessibilityContentDescriptions.PHONE_SIGNAL_STRENGTH[0],
+            0, 0, false, new int[2]
+            );
+
+    static final MobileIconGroup E = new MobileIconGroup(
+            "E",
+            TelephonyIcons.TELEPHONY_SIGNAL_STRENGTH,
+            TelephonyIcons.QS_TELEPHONY_SIGNAL_STRENGTH,
+            AccessibilityContentDescriptions.PHONE_SIGNAL_STRENGTH,
+            0, 0,
+            TelephonyIcons.TELEPHONY_NO_NETWORK,
+            TelephonyIcons.QS_TELEPHONY_NO_NETWORK,
+            AccessibilityContentDescriptions.PHONE_SIGNAL_STRENGTH[0],
+            R.string.accessibility_data_connection_edge,
+            TelephonyIcons.ICON_E,
+            false,
+            TelephonyIcons.QS_DATA_E
+            );
+
+    static final MobileIconGroup ONE_X = new MobileIconGroup(
+            "1X",
+            TelephonyIcons.TELEPHONY_SIGNAL_STRENGTH,
+            TelephonyIcons.QS_TELEPHONY_SIGNAL_STRENGTH,
+            AccessibilityContentDescriptions.PHONE_SIGNAL_STRENGTH,
+            0, 0,
+            TelephonyIcons.TELEPHONY_NO_NETWORK,
+            TelephonyIcons.QS_TELEPHONY_NO_NETWORK,
+            AccessibilityContentDescriptions.PHONE_SIGNAL_STRENGTH[0],
+            R.string.accessibility_data_connection_cdma,
+            TelephonyIcons.ICON_1X,
+            true,
+            TelephonyIcons.QS_DATA_1X
+            );
+
+    static final MobileIconGroup G = new MobileIconGroup(
+            "G",
+            TelephonyIcons.TELEPHONY_SIGNAL_STRENGTH,
+            TelephonyIcons.QS_TELEPHONY_SIGNAL_STRENGTH,
+            AccessibilityContentDescriptions.PHONE_SIGNAL_STRENGTH,
+            0, 0,
+            TelephonyIcons.TELEPHONY_NO_NETWORK,
+            TelephonyIcons.QS_TELEPHONY_NO_NETWORK,
+            AccessibilityContentDescriptions.PHONE_SIGNAL_STRENGTH[0],
+            R.string.accessibility_data_connection_gprs,
+            TelephonyIcons.ICON_G,
+            false,
+            TelephonyIcons.QS_DATA_G
+            );
+
+    static final MobileIconGroup H = new MobileIconGroup(
+            "H",
+            TelephonyIcons.TELEPHONY_SIGNAL_STRENGTH,
+            TelephonyIcons.QS_TELEPHONY_SIGNAL_STRENGTH,
+            AccessibilityContentDescriptions.PHONE_SIGNAL_STRENGTH,
+            0, 0,
+            TelephonyIcons.TELEPHONY_NO_NETWORK,
+            TelephonyIcons.QS_TELEPHONY_NO_NETWORK,
+            AccessibilityContentDescriptions.PHONE_SIGNAL_STRENGTH[0],
+            R.string.accessibility_data_connection_3_5g,
+            TelephonyIcons.ICON_H,
+            false,
+            TelephonyIcons.QS_DATA_H
+            );
+
+    static final MobileIconGroup FOUR_G = new MobileIconGroup(
+            "4G",
+            TelephonyIcons.TELEPHONY_SIGNAL_STRENGTH,
+            TelephonyIcons.QS_TELEPHONY_SIGNAL_STRENGTH,
+            AccessibilityContentDescriptions.PHONE_SIGNAL_STRENGTH,
+            0, 0,
+            TelephonyIcons.TELEPHONY_NO_NETWORK,
+            TelephonyIcons.QS_TELEPHONY_NO_NETWORK,
+            AccessibilityContentDescriptions.PHONE_SIGNAL_STRENGTH[0],
+            R.string.accessibility_data_connection_4g,
+            TelephonyIcons.ICON_4G,
+            true,
+            TelephonyIcons.QS_DATA_4G
+            );
+
+    static final MobileIconGroup LTE = new MobileIconGroup(
+            "LTE",
+            TelephonyIcons.TELEPHONY_SIGNAL_STRENGTH,
+            TelephonyIcons.QS_TELEPHONY_SIGNAL_STRENGTH,
+            AccessibilityContentDescriptions.PHONE_SIGNAL_STRENGTH,
+            0, 0,
+            TelephonyIcons.TELEPHONY_NO_NETWORK,
+            TelephonyIcons.QS_TELEPHONY_NO_NETWORK,
+            AccessibilityContentDescriptions.PHONE_SIGNAL_STRENGTH[0],
+            R.string.accessibility_data_connection_lte,
+            TelephonyIcons.ICON_LTE,
+            true,
+            TelephonyIcons.QS_DATA_LTE
+            );
+
+    static final MobileIconGroup ROAMING = new MobileIconGroup(
+            "Roaming",
+            TelephonyIcons.TELEPHONY_SIGNAL_STRENGTH_ROAMING,
+            TelephonyIcons.QS_TELEPHONY_SIGNAL_STRENGTH,
+            AccessibilityContentDescriptions.PHONE_SIGNAL_STRENGTH,
+            0, 0,
+            TelephonyIcons.TELEPHONY_NO_NETWORK,
+            TelephonyIcons.QS_TELEPHONY_NO_NETWORK,
+            AccessibilityContentDescriptions.PHONE_SIGNAL_STRENGTH[0],
+            R.string.accessibility_data_connection_roaming,
+            TelephonyIcons.ROAMING_ICON,
+            false,
+            TelephonyIcons.QS_DATA_R
+            );
 }
 
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/WifiIcons.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/WifiIcons.java
index 49af979..c56646f 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/WifiIcons.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/WifiIcons.java
@@ -45,5 +45,8 @@
               R.drawable.ic_qs_wifi_full_4 }
         };
 
+    static final int QS_WIFI_NO_NETWORK = R.drawable.ic_qs_wifi_no_network;
+    static final int WIFI_NO_NETWORK = R.drawable.stat_sys_wifi_signal_null;
+
     static final int WIFI_LEVEL_COUNT = WIFI_SIGNAL_STRENGTH[0].length;
 }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/WimaxIcons.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/WimaxIcons.java
deleted file mode 100644
index 4877828..0000000
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/WimaxIcons.java
+++ /dev/null
@@ -1,27 +0,0 @@
-/*
- * 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.systemui.statusbar.policy;
-
-import com.android.systemui.statusbar.policy.TelephonyIcons;
-
-class WimaxIcons {
-    static final int[][] WIMAX_SIGNAL_STRENGTH = TelephonyIcons.DATA_SIGNAL_STRENGTH;
-
-    static final int WIMAX_DISCONNECTED = WIMAX_SIGNAL_STRENGTH[0][0];
-
-    static final int WIMAX_IDLE = WIMAX_DISCONNECTED; // XXX: unclear if we need a different icon
-}
diff --git a/packages/SystemUI/src/com/android/systemui/volume/VolumeComponent.java b/packages/SystemUI/src/com/android/systemui/volume/VolumeComponent.java
index 31adc95..e3f8f3d 100644
--- a/packages/SystemUI/src/com/android/systemui/volume/VolumeComponent.java
+++ b/packages/SystemUI/src/com/android/systemui/volume/VolumeComponent.java
@@ -21,4 +21,5 @@
 
 public interface VolumeComponent extends DemoMode {
     ZenModeController getZenController();
+    void dismissNow();
 }
diff --git a/packages/SystemUI/src/com/android/systemui/volume/VolumePanel.java b/packages/SystemUI/src/com/android/systemui/volume/VolumePanel.java
index f12053c..351911c 100644
--- a/packages/SystemUI/src/com/android/systemui/volume/VolumePanel.java
+++ b/packages/SystemUI/src/com/android/systemui/volume/VolumePanel.java
@@ -793,7 +793,7 @@
             sc.icon.setAlpha(mDisabledAlpha);
             sc.icon.setClickable(false);
         } else if (fixedVolume ||
-                (sc.streamType != mAudioManager.getMasterStreamType() && muted) ||
+                (sc.streamType != mAudioManager.getMasterStreamType() && !isRinger && muted) ||
                 (sSafetyWarning != null)) {
             sc.seekbarView.setEnabled(false);
         } else {
diff --git a/packages/SystemUI/src/com/android/systemui/volume/VolumeUI.java b/packages/SystemUI/src/com/android/systemui/volume/VolumeUI.java
index 5232a17..7102c2a 100644
--- a/packages/SystemUI/src/com/android/systemui/volume/VolumeUI.java
+++ b/packages/SystemUI/src/com/android/systemui/volume/VolumeUI.java
@@ -178,7 +178,7 @@
 
         @Override
         public void dismiss() throws RemoteException {
-            mPanel.postDismiss(0);
+            dismissNow();
         }
 
         @Override
@@ -190,6 +190,11 @@
         public void dispatchDemoCommand(String command, Bundle args) {
             mPanel.dispatchDemoCommand(command, args);
         }
+
+        @Override
+        public void dismissNow() {
+            mPanel.postDismiss(0);
+        }
     }
 
     private final class RemoteVolumeController extends IRemoteVolumeController.Stub {
diff --git a/packages/SystemUI/tests/Android.mk b/packages/SystemUI/tests/Android.mk
index 8b87522..5a90324 100644
--- a/packages/SystemUI/tests/Android.mk
+++ b/packages/SystemUI/tests/Android.mk
@@ -17,14 +17,20 @@
 
 LOCAL_MODULE_TAGS := tests
 
-LOCAL_SRC_FILES := $(call all-java-files-under, src)
+LOCAL_AAPT_FLAGS := --auto-add-overlay --extra-packages com.android.systemui:com.android.keyguard
+LOCAL_SRC_FILES := $(call all-java-files-under, src) \
+    $(call all-java-files-under, ../src) \
+    src/com/android/systemui/EventLogTags.logtags
+
+LOCAL_RESOURCE_DIR := $(LOCAL_PATH)/res \
+    frameworks/base/packages/SystemUI/res \
+    frameworks/base/packages/Keyguard/res
 
 LOCAL_JAVA_LIBRARIES := android.test.runner telephony-common
 
 LOCAL_PACKAGE_NAME := SystemUITests
-LOCAL_INSTRUMENTATION_FOR := SystemUI
 
-LOCAL_STATIC_JAVA_LIBRARIES := mockito-target
+LOCAL_STATIC_JAVA_LIBRARIES := mockito-target Keyguard
 
 # sign this with platform cert, so this test is allowed to inject key events into
 # UI it doesn't own. This is necessary to allow screenshots to be taken
diff --git a/packages/SystemUI/tests/AndroidManifest.xml b/packages/SystemUI/tests/AndroidManifest.xml
index 1d319cf..e52806d 100644
--- a/packages/SystemUI/tests/AndroidManifest.xml
+++ b/packages/SystemUI/tests/AndroidManifest.xml
@@ -25,7 +25,7 @@
     </application>
 
     <instrumentation android:name="android.test.InstrumentationTestRunner"
-        android:targetPackage="com.android.systemui"
+        android:targetPackage="com.android.systemui.tests"
         android:label="Tests for SystemUI">
     </instrumentation>
 </manifest>
diff --git a/packages/SystemUI/tests/src/com/android/systemui/EventLogTags.logtags b/packages/SystemUI/tests/src/com/android/systemui/EventLogTags.logtags
new file mode 120000
index 0000000..2f243d7
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/EventLogTags.logtags
@@ -0,0 +1 @@
+../../../../../src/com/android/systemui/EventLogTags.logtags
\ No newline at end of file
diff --git a/packages/SystemUI/tests/src/com/android/systemui/screenshot/ScreenshotStubActivity.java b/packages/SystemUI/tests/src/com/android/systemui/screenshot/ScreenshotStubActivity.java
index 2935373..784d035 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/screenshot/ScreenshotStubActivity.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/screenshot/ScreenshotStubActivity.java
@@ -15,7 +15,7 @@
  */
 package com.android.systemui.screenshot;
 
-import com.android.systemui.tests.R;
+import com.android.systemui.R;
 
 import android.app.Activity;
 import android.os.Bundle;
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/NetworkControllerBaseTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/NetworkControllerBaseTest.java
index 97605ea..49fe1e3 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/NetworkControllerBaseTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/NetworkControllerBaseTest.java
@@ -17,6 +17,7 @@
 
 import com.android.internal.telephony.cdma.EriInfo;
 import com.android.systemui.statusbar.policy.NetworkController.NetworkSignalChangedCallback;
+import com.android.systemui.statusbar.policy.NetworkControllerImpl.Config;
 import com.android.systemui.statusbar.policy.NetworkControllerImpl.SignalCluster;
 
 import org.mockito.ArgumentCaptor;
@@ -44,6 +45,7 @@
     protected ConnectivityManager mMockCm;
     protected WifiManager mMockWm;
     protected TelephonyManager mMockTm;
+    protected Config mConfig;
 
     @Override
     protected void setUp() throws Exception {
@@ -59,15 +61,19 @@
 
         mSignalStrength = mock(SignalStrength.class);
         mServiceState = mock(ServiceState.class);
-        mSignalCluster = mock(SignalCluster.class);
-        mNetworkSignalChangedCallback = mock(NetworkSignalChangedCallback.class);
 
-        mNetworkController = new NetworkControllerImpl(mContext, mMockCm, mMockTm, mMockWm);
+        mConfig = new Config();
+        mConfig.hspaDataDistinguishable = true;
+        mNetworkController = new NetworkControllerImpl(mContext, mMockCm, mMockTm, mMockWm,
+                mConfig, mock(AccessPointControllerImpl.class),
+                mock(MobileDataControllerImpl.class));
         setupNetworkController();
     }
 
     protected void setupNetworkController() {
-        mPhoneStateListener = mNetworkController.mPhoneStateListener;
+        mPhoneStateListener = mNetworkController.mMobileSignalController.mPhoneStateListener;
+        mSignalCluster = mock(SignalCluster.class);
+        mNetworkSignalChangedCallback = mock(NetworkSignalChangedCallback.class);
         mNetworkController.addSignalCluster(mSignalCluster);
         mNetworkController.addNetworkSignalChangedCallback(mNetworkSignalChangedCallback);
     }
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/NetworkControllerSignalTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/NetworkControllerSignalTest.java
index ed76ae5..bb2ff7c 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/NetworkControllerSignalTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/NetworkControllerSignalTest.java
@@ -1,5 +1,7 @@
 package com.android.systemui.statusbar.policy;
 
+import static org.mockito.Mockito.mock;
+
 import android.net.ConnectivityManager;
 import android.telephony.ServiceState;
 import android.telephony.SignalStrength;
@@ -15,7 +17,9 @@
         // Turn off mobile network support.
         Mockito.when(mMockCm.isNetworkSupported(ConnectivityManager.TYPE_MOBILE)).thenReturn(false);
         // Create a new NetworkController as this is currently handled in constructor.
-        mNetworkController = new NetworkControllerImpl(mContext, mMockCm, mMockTm, mMockWm);
+        mNetworkController = new NetworkControllerImpl(mContext, mMockCm, mMockTm, mMockWm,
+                mConfig, mock(AccessPointControllerImpl.class),
+                mock(MobileDataControllerImpl.class));
         setupNetworkController();
 
         verifyLastMobileDataIndicators(false, 0, 0);
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/NetworkControllerWifiTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/NetworkControllerWifiTest.java
index 4ffdff2..7f0a8f4 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/NetworkControllerWifiTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/NetworkControllerWifiTest.java
@@ -6,8 +6,6 @@
 import android.net.wifi.WifiInfo;
 import android.net.wifi.WifiManager;
 
-import com.android.systemui.R;
-
 import org.mockito.ArgumentCaptor;
 import org.mockito.Mockito;
 
@@ -16,14 +14,10 @@
     private static final int MIN_RSSI = -100;
     private static final int MAX_RSSI = -55;
 
-    // TODO: Move this into WifiIcons, remove all R.drawable from NetworkControllerImpl.
-    private static final int NULL_SIGNAL = R.drawable.stat_sys_wifi_signal_null;
-    private static final int QS_NO_NET = R.drawable.ic_qs_wifi_no_network;
-
     public void testWifiIcon() {
         String testSsid = "Test SSID";
         setWifiEnabled(true);
-        verifyLastWifiIcon(false, NULL_SIGNAL);
+        verifyLastWifiIcon(false, WifiIcons.WIFI_NO_NETWORK);
 
         setWifiState(true, testSsid);
         verifyLastWifiIcon(true, WifiIcons.WIFI_SIGNAL_STRENGTH[0][0]);
@@ -42,10 +36,10 @@
         String testSsid = "Test SSID";
 
         setWifiEnabled(false);
-        verifyLastQsWifiIcon(false, false, 0, null);
+        verifyLastQsWifiIcon(false, false, WifiIcons.QS_WIFI_NO_NETWORK, null);
 
         setWifiEnabled(true);
-        verifyLastQsWifiIcon(true, false, QS_NO_NET, null);
+        verifyLastQsWifiIcon(true, false, WifiIcons.QS_WIFI_NO_NETWORK, null);
 
         setWifiState(true, testSsid);
         for (int testLevel = 0; testLevel < WifiIcons.WIFI_LEVEL_COUNT; testLevel++) {
@@ -118,8 +112,7 @@
 
     protected void setWifiActivity(int activity) {
         // TODO: Not this, because this variable probably isn't sticking around.
-        mNetworkController.mWifiActivity = activity;
-        mNetworkController.refreshViews();
+        mNetworkController.mWifiSignalController.setActivity(activity);
     }
 
     protected void setWifiLevel(int level) {
diff --git a/policy/src/com/android/internal/policy/impl/PhoneWindow.java b/policy/src/com/android/internal/policy/impl/PhoneWindow.java
index c34316b..30a271e 100644
--- a/policy/src/com/android/internal/policy/impl/PhoneWindow.java
+++ b/policy/src/com/android/internal/policy/impl/PhoneWindow.java
@@ -101,6 +101,7 @@
 import android.view.accessibility.AccessibilityManager;
 import android.view.animation.Animation;
 import android.view.animation.AnimationUtils;
+import android.view.animation.Interpolator;
 import android.widget.FrameLayout;
 import android.widget.ImageView;
 import android.widget.PopupWindow;
@@ -2153,6 +2154,7 @@
     }
 
     private final class DecorView extends FrameLayout implements RootViewSurfaceTaker {
+
         /* package */int mDefaultOpacity = PixelFormat.OPAQUE;
 
         /** The feature ID of the panel, or -1 if this is the application's DecorView */
@@ -2182,19 +2184,45 @@
         // View added at runtime to draw under the navigation bar area
         private View mNavigationGuard;
 
-        private View mStatusColorView;
-        private View mNavigationColorView;
+        private final ColorViewState mStatusColorViewState = new ColorViewState(
+                SYSTEM_UI_FLAG_FULLSCREEN, FLAG_TRANSLUCENT_STATUS,
+                Gravity.TOP,
+                STATUS_BAR_BACKGROUND_TRANSITION_NAME,
+                com.android.internal.R.id.statusBarBackground,
+                FLAG_FULLSCREEN);
+        private final ColorViewState mNavigationColorViewState = new ColorViewState(
+                SYSTEM_UI_FLAG_HIDE_NAVIGATION, FLAG_TRANSLUCENT_NAVIGATION,
+                Gravity.BOTTOM,
+                NAVIGATION_BAR_BACKGROUND_TRANSITION_NAME,
+                com.android.internal.R.id.navigationBarBackground,
+                0 /* hideWindowFlag */);
+
+        private final Interpolator mShowInterpolator;
+        private final Interpolator mHideInterpolator;
+        private final int mBarEnterExitDuration;
+
         private final BackgroundFallback mBackgroundFallback = new BackgroundFallback();
 
         private int mLastTopInset = 0;
         private int mLastBottomInset = 0;
         private int mLastRightInset = 0;
+        private boolean mLastHasTopStableInset = false;
+        private boolean mLastHasBottomStableInset = false;
+        private int mLastWindowFlags = 0;
 
         private int mRootScrollY = 0;
 
         public DecorView(Context context, int featureId) {
             super(context);
             mFeatureId = featureId;
+
+            mShowInterpolator = AnimationUtils.loadInterpolator(context,
+                    android.R.interpolator.linear_out_slow_in);
+            mHideInterpolator = AnimationUtils.loadInterpolator(context,
+                    android.R.interpolator.fast_out_linear_in);
+
+            mBarEnterExitDuration = context.getResources().getInteger(
+                    R.integer.dock_enter_exit_duration);
         }
 
         public void setBackgroundFallback(int resId) {
@@ -2787,13 +2815,13 @@
 
         @Override
         public void onWindowSystemUiVisibilityChanged(int visible) {
-            updateColorViews(null /* insets */);
+            updateColorViews(null /* insets */, true /* animate */);
         }
 
         @Override
         public WindowInsets onApplyWindowInsets(WindowInsets insets) {
             mFrameOffsets.set(insets.getSystemWindowInsets());
-            insets = updateColorViews(insets);
+            insets = updateColorViews(insets, true /* animate */);
             insets = updateStatusGuard(insets);
             updateNavigationGuard(insets);
             if (getForeground() != null) {
@@ -2807,11 +2835,16 @@
             return false;
         }
 
-        private WindowInsets updateColorViews(WindowInsets insets) {
+        private WindowInsets updateColorViews(WindowInsets insets, boolean animate) {
             WindowManager.LayoutParams attrs = getAttributes();
             int sysUiVisibility = attrs.systemUiVisibility | getWindowSystemUiVisibility();
 
             if (!mIsFloating && ActivityManager.isHighEndGfx()) {
+                boolean disallowAnimate = !isLaidOut();
+                disallowAnimate |= ((mLastWindowFlags ^ attrs.flags)
+                        & FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS) != 0;
+                mLastWindowFlags = attrs.flags;
+
                 if (insets != null) {
                     mLastTopInset = Math.min(insets.getStableInsetTop(),
                             insets.getSystemWindowInsetTop());
@@ -2819,19 +2852,23 @@
                             insets.getSystemWindowInsetBottom());
                     mLastRightInset = Math.min(insets.getStableInsetRight(),
                             insets.getSystemWindowInsetRight());
+
+                    // Don't animate if the presence of stable insets has changed, because that
+                    // indicates that the window was either just added and received them for the
+                    // first time, or the window size or position has changed.
+                    boolean hasTopStableInset = insets.getStableInsetTop() != 0;
+                    disallowAnimate |= hasTopStableInset && !mLastHasTopStableInset;
+                    mLastHasTopStableInset = hasTopStableInset;
+
+                    boolean hasBottomStableInset = insets.getStableInsetBottom() != 0;
+                    disallowAnimate |= hasBottomStableInset && !mLastHasBottomStableInset;
+                    mLastHasBottomStableInset = hasBottomStableInset;
                 }
-                mStatusColorView = updateColorViewInt(mStatusColorView, sysUiVisibility,
-                        SYSTEM_UI_FLAG_FULLSCREEN, FLAG_TRANSLUCENT_STATUS,
-                        mStatusBarColor, mLastTopInset, Gravity.TOP,
-                        STATUS_BAR_BACKGROUND_TRANSITION_NAME,
-                        com.android.internal.R.id.statusBarBackground,
-                        (getAttributes().flags & FLAG_FULLSCREEN) != 0);
-                mNavigationColorView = updateColorViewInt(mNavigationColorView, sysUiVisibility,
-                        SYSTEM_UI_FLAG_HIDE_NAVIGATION, FLAG_TRANSLUCENT_NAVIGATION,
-                        mNavigationBarColor, mLastBottomInset, Gravity.BOTTOM,
-                        NAVIGATION_BAR_BACKGROUND_TRANSITION_NAME,
-                        com.android.internal.R.id.navigationBarBackground,
-                        false /* hiddenByWindowFlag */);
+
+                updateColorViewInt(mStatusColorViewState, sysUiVisibility, mStatusBarColor,
+                        mLastTopInset, animate && !disallowAnimate);
+                updateColorViewInt(mNavigationColorViewState, sysUiVisibility, mNavigationBarColor,
+                        mLastBottomInset, animate && !disallowAnimate);
             }
 
             // When we expand the window with FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS, we still need
@@ -2875,28 +2912,35 @@
             return insets;
         }
 
-        private View updateColorViewInt(View view, int sysUiVis, int systemUiHideFlag,
-                int translucentFlag, int color, int height, int verticalGravity,
-                String transitionName, int id, boolean hiddenByWindowFlag) {
-            boolean show = height > 0 && (sysUiVis & systemUiHideFlag) == 0
-                    && !hiddenByWindowFlag
-                    && (getAttributes().flags & translucentFlag) == 0
+        private void updateColorViewInt(final ColorViewState state, int sysUiVis, int color,
+                int height, boolean animate) {
+            boolean show = height > 0 && (sysUiVis & state.systemUiHideFlag) == 0
+                    && (getAttributes().flags & state.hideWindowFlag) == 0
+                    && (getAttributes().flags & state.translucentFlag) == 0
                     && (color & Color.BLACK) != 0
                     && (getAttributes().flags & FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS) != 0;
 
+            boolean visibilityChanged = false;
+            View view = state.view;
+
             if (view == null) {
                 if (show) {
-                    view = new View(mContext);
+                    state.view = view = new View(mContext);
                     view.setBackgroundColor(color);
-                    view.setTransitionName(transitionName);
-                    view.setId(id);
+                    view.setTransitionName(state.transitionName);
+                    view.setId(state.id);
+                    visibilityChanged = true;
+                    view.setVisibility(INVISIBLE);
+                    state.targetVisibility = VISIBLE;
+
                     addView(view, new LayoutParams(LayoutParams.MATCH_PARENT, height,
-                            Gravity.START | verticalGravity));
+                            Gravity.START | state.verticalGravity));
                     updateColorViewTranslations();
                 }
             } else {
                 int vis = show ? VISIBLE : INVISIBLE;
-                view.setVisibility(vis);
+                visibilityChanged = state.targetVisibility != vis;
+                state.targetVisibility = vis;
                 if (show) {
                     LayoutParams lp = (LayoutParams) view.getLayoutParams();
                     if (lp.height != height) {
@@ -2906,18 +2950,43 @@
                     view.setBackgroundColor(color);
                 }
             }
-            return view;
+            if (visibilityChanged) {
+                view.animate().cancel();
+                if (animate) {
+                    if (show) {
+                        if (view.getVisibility() != VISIBLE) {
+                            view.setVisibility(VISIBLE);
+                            view.setAlpha(0.0f);
+                        }
+                        view.animate().alpha(1.0f).setInterpolator(mShowInterpolator).
+                                setDuration(mBarEnterExitDuration);
+                    } else {
+                        view.animate().alpha(0.0f).setInterpolator(mHideInterpolator)
+                                .setDuration(mBarEnterExitDuration)
+                                .withEndAction(new Runnable() {
+                                    @Override
+                                    public void run() {
+                                        state.view.setAlpha(1.0f);
+                                        state.view.setVisibility(INVISIBLE);
+                                    }
+                                });
+                    }
+                } else {
+                    view.setAlpha(1.0f);
+                    view.setVisibility(show ? VISIBLE : INVISIBLE);
+                }
+            }
         }
 
         private void updateColorViewTranslations() {
             // Put the color views back in place when they get moved off the screen
             // due to the the ViewRootImpl panning.
             int rootScrollY = mRootScrollY;
-            if (mStatusColorView != null) {
-                mStatusColorView.setTranslationY(rootScrollY > 0 ? rootScrollY : 0);
+            if (mStatusColorViewState.view != null) {
+                mStatusColorViewState.view.setTranslationY(rootScrollY > 0 ? rootScrollY : 0);
             }
-            if (mNavigationColorView != null) {
-                mNavigationColorView.setTranslationY(rootScrollY < 0 ? rootScrollY : 0);
+            if (mNavigationColorViewState.view != null) {
+                mNavigationColorViewState.view.setTranslationY(rootScrollY < 0 ? rootScrollY : 0);
             }
         }
 
@@ -2948,7 +3017,7 @@
                                 mStatusGuard = new View(mContext);
                                 mStatusGuard.setBackgroundColor(mContext.getResources()
                                         .getColor(R.color.input_method_navigation_guard));
-                                addView(mStatusGuard, indexOfChild(mStatusColorView),
+                                addView(mStatusGuard, indexOfChild(mStatusColorViewState.view),
                                         new LayoutParams(LayoutParams.MATCH_PARENT,
                                                 mlp.topMargin, Gravity.START | Gravity.TOP));
                             } else {
@@ -3008,9 +3077,10 @@
                     mNavigationGuard = new View(mContext);
                     mNavigationGuard.setBackgroundColor(mContext.getResources()
                             .getColor(R.color.input_method_navigation_guard));
-                    addView(mNavigationGuard, indexOfChild(mNavigationColorView), new LayoutParams(
-                            LayoutParams.MATCH_PARENT, insets.getSystemWindowInsetBottom(),
-                            Gravity.START | Gravity.BOTTOM));
+                    addView(mNavigationGuard, indexOfChild(mNavigationColorViewState.view),
+                            new LayoutParams(LayoutParams.MATCH_PARENT,
+                                    insets.getSystemWindowInsetBottom(),
+                                    Gravity.START | Gravity.BOTTOM));
                 } else {
                     LayoutParams lp = (LayoutParams) mNavigationGuard.getLayoutParams();
                     lp.height = insets.getSystemWindowInsetBottom();
@@ -3912,7 +3982,7 @@
     protected void dispatchWindowAttributesChanged(WindowManager.LayoutParams attrs) {
         super.dispatchWindowAttributesChanged(attrs);
         if (mDecor != null) {
-            mDecor.updateColorViews(null /* insets */);
+            mDecor.updateColorViews(null /* insets */, true /* animate */);
         }
     }
 
@@ -4639,6 +4709,29 @@
         }
     }
 
+    private static class ColorViewState {
+        View view = null;
+        int targetVisibility = View.INVISIBLE;
+
+        final int id;
+        final int systemUiHideFlag;
+        final int translucentFlag;
+        final int verticalGravity;
+        final String transitionName;
+        final int hideWindowFlag;
+
+        ColorViewState(int systemUiHideFlag,
+                int translucentFlag, int verticalGravity,
+                String transitionName, int id, int hideWindowFlag) {
+            this.id = id;
+            this.systemUiHideFlag = systemUiHideFlag;
+            this.translucentFlag = translucentFlag;
+            this.verticalGravity = verticalGravity;
+            this.transitionName = transitionName;
+            this.hideWindowFlag = hideWindowFlag;
+        }
+    }
+
     void sendCloseSystemWindows() {
         PhoneWindowManager.sendCloseSystemWindows(getContext(), null);
     }
@@ -4657,7 +4750,7 @@
         mStatusBarColor = color;
         mForcedStatusBarColor = true;
         if (mDecor != null) {
-            mDecor.updateColorViews(null);
+            mDecor.updateColorViews(null, false /* animate */);
         }
     }
 
@@ -4671,7 +4764,7 @@
         mNavigationBarColor = color;
         mForcedNavigationBarColor = true;
         if (mDecor != null) {
-            mDecor.updateColorViews(null);
+            mDecor.updateColorViews(null, false /* animate */);
         }
     }
 }
diff --git a/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java b/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java
index 1ac956a..dea9932 100644
--- a/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java
+++ b/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java
@@ -319,6 +319,7 @@
     // handler thread.  We'll need to resolve this someday by teaching the input dispatcher
     // to hold wakelocks during dispatch and eliminating the critical path.
     volatile boolean mPowerKeyHandled;
+    volatile boolean mBeganFromNonInteractive;
     volatile int mPowerKeyPressCounter;
     volatile boolean mEndCallKeyHandled;
 
@@ -882,15 +883,13 @@
                             ViewConfiguration.get(mContext).getDeviceGlobalActionKeyTimeout());
                 }
             } else {
-                // When non-interactive, we ordinarily wake up immediately and
-                // consume the key.  However on some devices we need to support multi-press
-                // without waking so we will delay handling for later in that case
-                // (at the cost of increased latency).
+                wakeUpFromPowerKey(event.getDownTime());
                 final int maxCount = getMaxMultiPressPowerCount();
+
                 if (maxCount <= 1) {
-                    // No other actions.  We can wake immediately.
-                    wakeUpFromPowerKey(event.getDownTime());
                     mPowerKeyHandled = true;
+                } else {
+                    mBeganFromNonInteractive = true;
                 }
             }
         }
@@ -927,6 +926,7 @@
     }
 
     private void finishPowerKeyPress() {
+        mBeganFromNonInteractive = false;
         mPowerKeyPressCounter = 0;
         if (mPowerKeyWakeLock.isHeld()) {
             mPowerKeyWakeLock.release();
@@ -951,9 +951,7 @@
             powerMultiPressAction(eventTime, interactive, mDoublePressOnPowerBehavior);
         } else if (count == 3) {
             powerMultiPressAction(eventTime, interactive, mTriplePressOnPowerBehavior);
-        } else if (!interactive) {
-            wakeUpFromPowerKey(eventTime);
-        } else {
+        } else if (interactive && !mBeganFromNonInteractive) {
             switch (mShortPressOnPowerBehavior) {
                 case SHORT_PRESS_POWER_NOTHING:
                     break;
diff --git a/services/core/java/com/android/server/AlarmManagerService.java b/services/core/java/com/android/server/AlarmManagerService.java
index 8b524dd..08c47dc 100644
--- a/services/core/java/com/android/server/AlarmManagerService.java
+++ b/services/core/java/com/android/server/AlarmManagerService.java
@@ -75,6 +75,12 @@
     // warning message.  The time duration is in milliseconds.
     private static final long LATE_ALARM_THRESHOLD = 10 * 1000;
 
+    // Minimum futurity of a new alarm
+    private static final long MIN_FUTURITY = 5 * 1000;  // 5 seconds, in millis
+
+    // Minimum alarm recurrence interval
+    private static final long MIN_INTERVAL = 60 * 1000;  // one minute, in millis
+
     private static final int RTC_WAKEUP_MASK = 1 << RTC_WAKEUP;
     private static final int RTC_MASK = 1 << RTC;
     private static final int ELAPSED_REALTIME_WAKEUP_MASK = 1 << ELAPSED_REALTIME_WAKEUP;
@@ -696,6 +702,15 @@
             windowLength = AlarmManager.INTERVAL_HOUR;
         }
 
+        // Sanity check the recurrence interval.  This will catch people who supply
+        // seconds when the API expects milliseconds.
+        if (interval > 0 && interval < MIN_INTERVAL) {
+            Slog.w(TAG, "Suspiciously short interval " + interval
+                    + " millis; expanding to " + (int)(MIN_INTERVAL/1000)
+                    + " seconds");
+            interval = MIN_INTERVAL;
+        }
+
         if (type < RTC_WAKEUP || type > ELAPSED_REALTIME) {
             throw new IllegalArgumentException("Invalid alarm type " + type);
         }
@@ -709,7 +724,11 @@
         }
 
         final long nowElapsed = SystemClock.elapsedRealtime();
-        final long triggerElapsed = convertToElapsed(triggerAtTime, type);
+        final long nominalTrigger = convertToElapsed(triggerAtTime, type);
+        // Try to prevent spamming by making sure we aren't firing alarms in the immediate future
+        final long minTrigger = nowElapsed + MIN_FUTURITY;
+        final long triggerElapsed = (nominalTrigger > minTrigger) ? nominalTrigger : minTrigger;
+
         final long maxElapsed;
         if (windowLength == AlarmManager.WINDOW_EXACT) {
             maxElapsed = triggerElapsed;
diff --git a/services/core/java/com/android/server/PersistentDataBlockService.java b/services/core/java/com/android/server/PersistentDataBlockService.java
index de90aa2..17edb53 100644
--- a/services/core/java/com/android/server/PersistentDataBlockService.java
+++ b/services/core/java/com/android/server/PersistentDataBlockService.java
@@ -41,6 +41,9 @@
 import java.io.IOException;
 import java.nio.ByteBuffer;
 import java.nio.channels.FileChannel;
+import java.security.MessageDigest;
+import java.security.NoSuchAlgorithmException;
+import java.util.Arrays;
 
 /**
  * Service for reading and writing blocks to a persistent partition.
@@ -63,22 +66,16 @@
     private static final String PERSISTENT_DATA_BLOCK_PROP = "ro.frp.pst";
     private static final int HEADER_SIZE = 8;
     // Magic number to mark block device as adhering to the format consumed by this service
-    private static final int PARTITION_TYPE_MARKER = 0x1990;
+    private static final int PARTITION_TYPE_MARKER = 0x19901873;
     // Limit to 100k as blocks larger than this might cause strain on Binder.
-    // TODO(anmorales): Consider splitting up too-large blocks in PersistentDataBlockManager
     private static final int MAX_DATA_BLOCK_SIZE = 1024 * 100;
+    public static final int DIGEST_SIZE_BYTES = 32;
 
     private final Context mContext;
     private final String mDataBlockFile;
     private final Object mLock = new Object();
 
     private int mAllowedUid = -1;
-    /*
-     * Separate lock for OEM unlock related operations as they can happen in parallel with regular
-     * block operations.
-     */
-    private final Object mOemLock = new Object();
-
     private long mBlockDeviceSize;
 
     public PersistentDataBlockService(Context context) {
@@ -89,7 +86,6 @@
         mAllowedUid = getAllowedUid(UserHandle.USER_OWNER);
     }
 
-
     private int getAllowedUid(int userHandle) {
         String allowedPackage = mContext.getResources()
                 .getString(R.string.config_persistentDataPackageName);
@@ -106,6 +102,7 @@
 
     @Override
     public void onStart() {
+        enforceChecksumValidity();
         publishBinderService(Context.PERSISTENT_DATA_BLOCK_SERVICE, mService);
     }
 
@@ -128,6 +125,9 @@
     }
 
     private int getTotalDataSizeLocked(DataInputStream inputStream) throws IOException {
+        // skip over checksum
+        inputStream.skipBytes(DIGEST_SIZE_BYTES);
+
         int totalDataSize;
         int blockId = inputStream.readInt();
         if (blockId == PARTITION_TYPE_MARKER) {
@@ -148,6 +148,143 @@
         return mBlockDeviceSize;
     }
 
+    private boolean enforceChecksumValidity() {
+        byte[] storedDigest = new byte[DIGEST_SIZE_BYTES];
+
+        synchronized (mLock) {
+            byte[] digest = computeDigestLocked(storedDigest);
+            if (digest == null || !Arrays.equals(storedDigest, digest)) {
+                Slog.i(TAG, "Formatting FRP partition...");
+                formatPartitionLocked();
+                return false;
+            }
+        }
+
+        return true;
+    }
+
+    private boolean computeAndWriteDigestLocked() {
+        byte[] digest = computeDigestLocked(null);
+        if (digest != null) {
+            DataOutputStream outputStream;
+            try {
+                outputStream = new DataOutputStream(
+                        new FileOutputStream(new File(mDataBlockFile)));
+            } catch (FileNotFoundException e) {
+                Slog.e(TAG, "partition not available?", e);
+                return false;
+            }
+
+            try {
+                outputStream.write(digest, 0, DIGEST_SIZE_BYTES);
+                outputStream.flush();
+            } catch (IOException e) {
+                Slog.e(TAG, "failed to write block checksum", e);
+                return false;
+            } finally {
+                IoUtils.closeQuietly(outputStream);
+            }
+            return true;
+        } else {
+            return false;
+        }
+    }
+
+    private byte[] computeDigestLocked(byte[] storedDigest) {
+        DataInputStream inputStream;
+        try {
+            inputStream = new DataInputStream(new FileInputStream(new File(mDataBlockFile)));
+        } catch (FileNotFoundException e) {
+            Slog.e(TAG, "partition not available?", e);
+            return null;
+        }
+
+        MessageDigest md;
+        try {
+            md = MessageDigest.getInstance("SHA-256");
+        } catch (NoSuchAlgorithmException e) {
+            // won't ever happen -- every implementation is required to support SHA-256
+            Slog.e(TAG, "SHA-256 not supported?", e);
+            IoUtils.closeQuietly(inputStream);
+            return null;
+        }
+
+        try {
+            if (storedDigest != null && storedDigest.length == DIGEST_SIZE_BYTES) {
+                inputStream.read(storedDigest);
+            } else {
+                inputStream.skipBytes(DIGEST_SIZE_BYTES);
+            }
+
+            int read;
+            byte[] data = new byte[1024];
+            md.update(data, 0, DIGEST_SIZE_BYTES); // include 0 checksum in digest
+            while ((read = inputStream.read(data)) != -1) {
+                md.update(data, 0, read);
+            }
+        } catch (IOException e) {
+            Slog.e(TAG, "failed to read partition", e);
+            return null;
+        } finally {
+            IoUtils.closeQuietly(inputStream);
+        }
+
+        return md.digest();
+    }
+
+    private void formatPartitionLocked() {
+        DataOutputStream outputStream;
+        try {
+            outputStream = new DataOutputStream(new FileOutputStream(new File(mDataBlockFile)));
+        } catch (FileNotFoundException e) {
+            Slog.e(TAG, "partition not available?", e);
+            return;
+        }
+
+        byte[] data = new byte[DIGEST_SIZE_BYTES];
+        try {
+            outputStream.write(data, 0, DIGEST_SIZE_BYTES);
+            outputStream.writeInt(PARTITION_TYPE_MARKER);
+            outputStream.writeInt(0); // data size
+            outputStream.flush();
+        } catch (IOException e) {
+            Slog.e(TAG, "failed to format block", e);
+            return;
+        } finally {
+            IoUtils.closeQuietly(outputStream);
+        }
+
+        doSetOemUnlockEnabledLocked(false);
+        computeAndWriteDigestLocked();
+    }
+
+    private void doSetOemUnlockEnabledLocked(boolean enabled) {
+        FileOutputStream outputStream;
+        try {
+            outputStream = new FileOutputStream(new File(mDataBlockFile));
+        } catch (FileNotFoundException e) {
+            Slog.e(TAG, "partition not available", e);
+            return;
+        }
+
+        try {
+            FileChannel channel = outputStream.getChannel();
+
+            channel.position(getBlockDeviceSize() - 1);
+
+            ByteBuffer data = ByteBuffer.allocate(1);
+            data.put(enabled ? (byte) 1 : (byte) 0);
+            data.flip();
+            channel.write(data);
+            outputStream.flush();
+        } catch (IOException e) {
+            Slog.e(TAG, "unable to access persistent partition", e);
+            return;
+        } finally {
+            IoUtils.closeQuietly(outputStream);
+        }
+    }
+
     private native long nativeGetBlockDeviceSize(String path);
     private native int nativeWipe(String path);
 
@@ -176,19 +313,23 @@
             headerAndData.putInt(data.length);
             headerAndData.put(data);
 
-            try {
-                synchronized (mLock) {
-                    outputStream.write(headerAndData.array());
-                    return data.length;
-                }
-            } catch (IOException e) {
-                Slog.e(TAG, "failed writing to the persistent data block", e);
-                return -1;
-            } finally {
+            synchronized (mLock) {
                 try {
-                    outputStream.close();
+                    byte[] checksum = new byte[DIGEST_SIZE_BYTES];
+                    outputStream.write(checksum, 0, DIGEST_SIZE_BYTES);
+                    outputStream.write(headerAndData.array());
+                    outputStream.flush();
                 } catch (IOException e) {
-                    Slog.e(TAG, "failed closing output stream", e);
+                    Slog.e(TAG, "failed writing to the persistent data block", e);
+                    return -1;
+                } finally {
+                    IoUtils.closeQuietly(outputStream);
+                }
+
+                if (computeAndWriteDigestLocked()) {
+                    return data.length;
+                } else {
+                    return -1;
                 }
             }
         }
@@ -196,6 +337,9 @@
         @Override
         public byte[] read() {
             enforceUid(Binder.getCallingUid());
+            if (!enforceChecksumValidity()) {
+                return new byte[0];
+            }
 
             DataInputStream inputStream;
             try {
@@ -256,30 +400,10 @@
             }
             enforceOemUnlockPermission();
             enforceIsOwner();
-            FileOutputStream outputStream;
-            try {
-                outputStream = new FileOutputStream(new File(mDataBlockFile));
-            } catch (FileNotFoundException e) {
-                Slog.e(TAG, "parition not available", e);
-                return;
-            }
 
-            try {
-                FileChannel channel = outputStream.getChannel();
-
-                channel.position(getBlockDeviceSize() - 1);
-
-                ByteBuffer data = ByteBuffer.allocate(1);
-                data.put(enabled ? (byte) 1 : (byte) 0);
-                data.flip();
-
-                synchronized (mOemLock) {
-                    channel.write(data);
-                }
-            } catch (IOException e) {
-                Slog.e(TAG, "unable to access persistent partition", e);
-            } finally {
-                IoUtils.closeQuietly(outputStream);
+            synchronized (mLock) {
+                doSetOemUnlockEnabledLocked(enabled);
+                computeAndWriteDigestLocked();
             }
         }
 
@@ -295,8 +419,8 @@
             }
 
             try {
-                inputStream.skip(getBlockDeviceSize() - 1);
-                synchronized (mOemLock) {
+                synchronized (mLock) {
+                    inputStream.skip(getBlockDeviceSize() - 1);
                     return inputStream.readByte() != 0;
                 }
             } catch (IOException e) {
@@ -336,6 +460,5 @@
             long actualSize = getBlockDeviceSize() - HEADER_SIZE - 1;
             return actualSize <= MAX_DATA_BLOCK_SIZE ? actualSize : MAX_DATA_BLOCK_SIZE;
         }
-
     };
 }
diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java
index 772192a..fd54892 100755
--- a/services/core/java/com/android/server/am/ActivityManagerService.java
+++ b/services/core/java/com/android/server/am/ActivityManagerService.java
@@ -795,7 +795,11 @@
 
         @Override
         public int hashCode() {
-            return toString().hashCode();
+            int hashCode = 1;
+            hashCode = 31 * hashCode + sourceUserId;
+            hashCode = 31 * hashCode + uri.hashCode();
+            hashCode = 31 * hashCode + (prefix ? 1231 : 1237);
+            return hashCode;
         }
 
         @Override
@@ -6256,7 +6260,7 @@
             synchronized (this) {
                 ActivityStack stack = ActivityRecord.getStackLocked(token);
                 if (stack != null) {
-                    stack.backgroundResourcesReleased(token);
+                    stack.backgroundResourcesReleased();
                 }
             }
         } finally {
diff --git a/services/core/java/com/android/server/am/ActivityStack.java b/services/core/java/com/android/server/am/ActivityStack.java
index 3a1fafe..c8b7205 100755
--- a/services/core/java/com/android/server/am/ActivityStack.java
+++ b/services/core/java/com/android/server/am/ActivityStack.java
@@ -3317,17 +3317,18 @@
                 mHandler.sendEmptyMessageDelayed(RELEASE_BACKGROUND_RESOURCES_TIMEOUT_MSG, 500);
             } else {
                 Slog.e(TAG, "releaseBackgroundResources: activity " + r + " no longer running");
-                backgroundResourcesReleased(r.appToken);
+                backgroundResourcesReleased();
             }
         }
     }
 
-    final void backgroundResourcesReleased(IBinder token) {
+    final void backgroundResourcesReleased() {
         mHandler.removeMessages(RELEASE_BACKGROUND_RESOURCES_TIMEOUT_MSG);
         final ActivityRecord r = getVisibleBehindActivity();
         if (r != null) {
             mStackSupervisor.mStoppingActivities.add(r);
             setVisibleBehindActivity(null);
+            mStackSupervisor.scheduleIdleTimeoutLocked(null);
         }
         mStackSupervisor.resumeTopActivitiesLocked();
     }
diff --git a/services/core/java/com/android/server/hdmi/HdmiCecLocalDeviceTv.java b/services/core/java/com/android/server/hdmi/HdmiCecLocalDeviceTv.java
index 0cdb4d5..ec38124 100644
--- a/services/core/java/com/android/server/hdmi/HdmiCecLocalDeviceTv.java
+++ b/services/core/java/com/android/server/hdmi/HdmiCecLocalDeviceTv.java
@@ -798,7 +798,7 @@
     }
 
     boolean isSystemAudioActivated() {
-        if (getAvrDeviceInfo() == null) {
+        if (!hasSystemAudioDevice()) {
             return false;
         }
         synchronized (mLock) {
diff --git a/services/core/java/com/android/server/notification/NotificationManagerService.java b/services/core/java/com/android/server/notification/NotificationManagerService.java
index 42a8551..6958ff8 100644
--- a/services/core/java/com/android/server/notification/NotificationManagerService.java
+++ b/services/core/java/com/android/server/notification/NotificationManagerService.java
@@ -1931,12 +1931,7 @@
             if (hasValidSound) {
                 boolean looping =
                         (notification.flags & Notification.FLAG_INSISTENT) != 0;
-                AudioAttributes audioAttributes;
-                if (notification.audioAttributes != null) {
-                    audioAttributes = notification.audioAttributes;
-                } else {
-                    audioAttributes = Notification.AUDIO_ATTRIBUTES_DEFAULT;
-                }
+                AudioAttributes audioAttributes = audioAttributesForNotification(notification);
                 mSoundNotification = record;
                 // do not play notifications if stream volume is 0 (typically because
                 // ringer mode is silent) or if there is a user of exclusive audio focus
@@ -2030,7 +2025,9 @@
     }
 
     private static AudioAttributes audioAttributesForNotification(Notification n) {
-        if (n.audioAttributes != null) {
+        if (n.audioAttributes != null
+                && !Notification.AUDIO_ATTRIBUTES_DEFAULT.equals(n.audioAttributes)) {
+            // the audio attributes are set and different from the default, use them
             return n.audioAttributes;
         } else if (n.audioStreamType >= 0 && n.audioStreamType < AudioSystem.getNumStreamTypes()) {
             // the stream type is valid, use it
diff --git a/services/core/java/com/android/server/tv/TvInputHardwareManager.java b/services/core/java/com/android/server/tv/TvInputHardwareManager.java
index d0c5a88..c3cbbd3 100644
--- a/services/core/java/com/android/server/tv/TvInputHardwareManager.java
+++ b/services/core/java/com/android/server/tv/TvInputHardwareManager.java
@@ -680,28 +680,35 @@
                 if (mReleased) {
                     throw new IllegalStateException("Device already released.");
                 }
-                if (surface != null && config == null) {
-                    return false;
-                }
-                if (surface == null && mActiveConfig == null) {
-                    return false;
-                }
 
                 int result = TvInputHal.ERROR_UNKNOWN;
                 if (surface == null) {
-                    result = mHal.removeStream(mInfo.getDeviceId(), mActiveConfig);
-                    mActiveConfig = null;
+                    // The value of config is ignored when surface == null.
+                    if (mActiveConfig != null) {
+                        result = mHal.removeStream(mInfo.getDeviceId(), mActiveConfig);
+                        mActiveConfig = null;
+                    } else {
+                        // We already have no active stream.
+                        return true;
+                    }
                 } else {
-                    if (!config.equals(mActiveConfig)) {
+                    // It's impossible to set a non-null surface with a null config.
+                    if (config == null) {
+                        return false;
+                    }
+                    // Remove stream only if we have an existing active configuration.
+                    if (mActiveConfig != null && !config.equals(mActiveConfig)) {
                         result = mHal.removeStream(mInfo.getDeviceId(), mActiveConfig);
                         if (result != TvInputHal.SUCCESS) {
                             mActiveConfig = null;
-                            return false;
                         }
                     }
-                    result = mHal.addOrUpdateStream(mInfo.getDeviceId(), surface, config);
+                    // Proceed only if all previous operations succeeded.
                     if (result == TvInputHal.SUCCESS) {
-                        mActiveConfig = config;
+                        result = mHal.addOrUpdateStream(mInfo.getDeviceId(), surface, config);
+                        if (result == TvInputHal.SUCCESS) {
+                            mActiveConfig = config;
+                        }
                     }
                 }
                 updateAudioConfigLocked();
diff --git a/services/core/java/com/android/server/wm/AccessibilityController.java b/services/core/java/com/android/server/wm/AccessibilityController.java
index 7e6da8b5..0cbf03a 100644
--- a/services/core/java/com/android/server/wm/AccessibilityController.java
+++ b/services/core/java/com/android/server/wm/AccessibilityController.java
@@ -992,12 +992,6 @@
                         continue;
                     }
 
-                    // If the window is an accessibility overlay - ignore.
-                    if (windowState.mAttrs.type ==
-                            WindowManager.LayoutParams.TYPE_ACCESSIBILITY_OVERLAY) {
-                        continue;
-                    }
-
                     // Compute the bounds in the screen.
                     final Rect boundsInScreen = mTempRect;
                     computeWindowBoundsInScreen(windowState, boundsInScreen);
@@ -1018,8 +1012,14 @@
                         }
                     }
 
-                    unaccountedSpace.op(boundsInScreen, unaccountedSpace,
-                            Region.Op.REVERSE_DIFFERENCE);
+                    // Account for the space this window takes if the window
+                    // is not an accessibility overlay which does not change
+                    // the reported windows.
+                    if (windowState.mAttrs.type !=
+                            WindowManager.LayoutParams.TYPE_ACCESSIBILITY_OVERLAY) {
+                        unaccountedSpace.op(boundsInScreen, unaccountedSpace,
+                                Region.Op.REVERSE_DIFFERENCE);
+                    }
 
                     // We figured out what is touchable for the entire screen - done.
                     if (unaccountedSpace.isEmpty()) {
diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
index 9e51849..3b0a511 100644
--- a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
+++ b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
@@ -3923,7 +3923,7 @@
         final int n = policy.mAdminList.size();
         for (int i = 0; i < n; i++) {
             ActiveAdmin admin = policy.mAdminList.get(i);
-            if (profileOwner.equals(admin.info)) {
+            if (profileOwner.equals(admin.info.getComponent())) {
                 return admin;
             }
         }
@@ -5040,13 +5040,15 @@
 
     @Override
     public boolean isUninstallBlocked(ComponentName who, String packageName) {
+        // This function should return true if and only if the package is blocked by
+        // setUninstallBlocked(). It should still return false for other cases of blocks, such as
+        // when the package is a system app, or when it is an active device admin.
         final int userId = UserHandle.getCallingUserId();
 
         synchronized (this) {
-            if (who == null) {
-                throw new NullPointerException("ComponentName is null");
+            if (who != null) {
+                getActiveAdminForCallerLocked(who, DeviceAdminInfo.USES_POLICY_PROFILE_OWNER);
             }
-            getActiveAdminForCallerLocked(who, DeviceAdminInfo.USES_POLICY_PROFILE_OWNER);
 
             long id = Binder.clearCallingIdentity();
             try {
diff --git a/telecomm/java/android/telecom/Conference.java b/telecomm/java/android/telecom/Conference.java
index 215c682..6e404de 100644
--- a/telecomm/java/android/telecom/Conference.java
+++ b/telecomm/java/android/telecom/Conference.java
@@ -30,7 +30,7 @@
  * @hide
  */
 @SystemApi
-public abstract class Conference {
+public abstract class Conference implements IConferenceable {
 
     /** @hide */
     public abstract static class Listener {
diff --git a/telecomm/java/android/telecom/Connection.java b/telecomm/java/android/telecom/Connection.java
index 63b44a6..fb63c85 100644
--- a/telecomm/java/android/telecom/Connection.java
+++ b/telecomm/java/android/telecom/Connection.java
@@ -47,7 +47,7 @@
  * @hide
  */
 @SystemApi
-public abstract class Connection {
+public abstract class Connection implements IConferenceable {
 
     public static final int STATE_INITIALIZING = 0;
 
@@ -82,8 +82,8 @@
                 Connection c, VideoProvider videoProvider) {}
         public void onAudioModeIsVoipChanged(Connection c, boolean isVoip) {}
         public void onStatusHintsChanged(Connection c, StatusHints statusHints) {}
-        public void onConferenceableConnectionsChanged(
-                Connection c, List<Connection> conferenceableConnections) {}
+        public void onConferenceablesChanged(
+                Connection c, List<IConferenceable> conferenceables) {}
         public void onConferenceChanged(Connection c, Conference conference) {}
         /** @hide */
         public void onConferenceParticipantsChanged(Connection c,
@@ -449,7 +449,16 @@
     private final Listener mConnectionDeathListener = new Listener() {
         @Override
         public void onDestroyed(Connection c) {
-            if (mConferenceableConnections.remove(c)) {
+            if (mConferenceables.remove(c)) {
+                fireOnConferenceableConnectionsChanged();
+            }
+        }
+    };
+
+    private final Conference.Listener mConferenceDeathListener = new Conference.Listener() {
+        @Override
+        public void onDestroyed(Conference c) {
+            if (mConferenceables.remove(c)) {
                 fireOnConferenceableConnectionsChanged();
             }
         }
@@ -462,9 +471,9 @@
      */
     private final Set<Listener> mListeners = Collections.newSetFromMap(
             new ConcurrentHashMap<Listener, Boolean>(8, 0.9f, 1));
-    private final List<Connection> mConferenceableConnections = new ArrayList<>();
-    private final List<Connection> mUnmodifiableConferenceableConnections =
-            Collections.unmodifiableList(mConferenceableConnections);
+    private final List<IConferenceable> mConferenceables = new ArrayList<>();
+    private final List<IConferenceable> mUnmodifiableConferenceables =
+            Collections.unmodifiableList(mConferenceables);
 
     private int mState = STATE_NEW;
     private AudioState mAudioState;
@@ -864,19 +873,44 @@
         for (Connection c : conferenceableConnections) {
             // If statement checks for duplicates in input. It makes it N^2 but we're dealing with a
             // small amount of items here.
-            if (!mConferenceableConnections.contains(c)) {
+            if (!mConferenceables.contains(c)) {
                 c.addConnectionListener(mConnectionDeathListener);
-                mConferenceableConnections.add(c);
+                mConferenceables.add(c);
             }
         }
         fireOnConferenceableConnectionsChanged();
     }
 
     /**
-     * Returns the connections with which this connection can be conferenced.
+     * Similar to {@link #setConferenceableConnections(java.util.List)}, sets a list of connections
+     * or conferences with which this connection can be conferenced.
+     *
+     * @param conferenceables The conferenceables.
      */
-    public final List<Connection> getConferenceableConnections() {
-        return mUnmodifiableConferenceableConnections;
+    public final void setConferenceables(List<IConferenceable> conferenceables) {
+        clearConferenceableList();
+        for (IConferenceable c : conferenceables) {
+            // If statement checks for duplicates in input. It makes it N^2 but we're dealing with a
+            // small amount of items here.
+            if (!mConferenceables.contains(c)) {
+                if (c instanceof Connection) {
+                    Connection connection = (Connection) c;
+                    connection.addConnectionListener(mConnectionDeathListener);
+                } else if (c instanceof Conference) {
+                    Conference conference = (Conference) c;
+                    conference.addListener(mConferenceDeathListener);
+                }
+                mConferenceables.add(c);
+            }
+        }
+        fireOnConferenceableConnectionsChanged();
+    }
+
+    /**
+     * Returns the connections or conferences with which this connection can be conferenced.
+     */
+    public final List<IConferenceable> getConferenceables() {
+        return mUnmodifiableConferenceables;
     }
 
     /*
@@ -1109,7 +1143,7 @@
 
     private final void  fireOnConferenceableConnectionsChanged() {
         for (Listener l : mListeners) {
-            l.onConferenceableConnectionsChanged(this, getConferenceableConnections());
+            l.onConferenceablesChanged(this, getConferenceables());
         }
     }
 
@@ -1120,10 +1154,16 @@
     }
 
     private final void clearConferenceableList() {
-        for (Connection c : mConferenceableConnections) {
-            c.removeConnectionListener(mConnectionDeathListener);
+        for (IConferenceable c : mConferenceables) {
+            if (c instanceof Connection) {
+                Connection connection = (Connection) c;
+                connection.removeConnectionListener(mConnectionDeathListener);
+            } else if (c instanceof Conference) {
+                Conference conference = (Conference) c;
+                conference.removeListener(mConferenceDeathListener);
+            }
         }
-        mConferenceableConnections.clear();
+        mConferenceables.clear();
     }
 
     /**
diff --git a/telecomm/java/android/telecom/ConnectionService.java b/telecomm/java/android/telecom/ConnectionService.java
index 48e6ff3..08f3853 100644
--- a/telecomm/java/android/telecom/ConnectionService.java
+++ b/telecomm/java/android/telecom/ConnectionService.java
@@ -515,11 +515,11 @@
         }
 
         @Override
-        public void onConferenceableConnectionsChanged(
-                Connection connection, List<Connection> conferenceableConnections) {
+        public void onConferenceablesChanged(
+                Connection connection, List<IConferenceable> conferenceables) {
             mAdapter.setConferenceableConnections(
                     mIdByConnection.get(connection),
-                    createConnectionIdList(conferenceableConnections));
+                    createIdList(conferenceables));
         }
 
         @Override
@@ -602,7 +602,7 @@
                         connection.getAudioModeIsVoip(),
                         connection.getStatusHints(),
                         connection.getDisconnectCause(),
-                        createConnectionIdList(connection.getConferenceableConnections())));
+                        createIdList(connection.getConferenceables())));
     }
 
     private void abort(String callId) {
@@ -682,12 +682,19 @@
     private void conference(String callId1, String callId2) {
         Log.d(this, "conference %s, %s", callId1, callId2);
 
+        // Attempt to get second connection or conference.
         Connection connection2 = findConnectionForAction(callId2, "conference");
+        Conference conference2 = getNullConference();
         if (connection2 == getNullConnection()) {
-            Log.w(this, "Connection2 missing in conference request %s.", callId2);
-            return;
+            conference2 = findConferenceForAction(callId2, "conference");
+            if (conference2 == getNullConference()) {
+                Log.w(this, "Connection2 or Conference2 missing in conference request %s.",
+                        callId2);
+                return;
+            }
         }
 
+        // Attempt to get first connection or conference and perform merge.
         Connection connection1 = findConnectionForAction(callId1, "conference");
         if (connection1 == getNullConnection()) {
             Conference conference1 = findConferenceForAction(callId1, "addConnection");
@@ -696,10 +703,26 @@
                         "Connection1 or Conference1 missing in conference request %s.",
                         callId1);
             } else {
-                conference1.onMerge(connection2);
+                // Call 1 is a conference.
+                if (connection2 != getNullConnection()) {
+                    // Call 2 is a connection so merge via call 1 (conference).
+                    conference1.onMerge(connection2);
+                } else {
+                    // Call 2 is ALSO a conference; this should never happen.
+                    Log.wtf(this, "There can only be one conference and an attempt was made to " +
+                            "merge two conferences.");
+                    return;
+                }
             }
         } else {
-            onConference(connection1, connection2);
+            // Call 1 is a connection.
+            if (conference2 != getNullConference()) {
+                // Call 2 is a conference, so merge via call 2.
+                conference2.onMerge(connection1);
+            } else {
+                // Call 2 is a connection, so merge together.
+                onConference(connection1, connection2);
+            }
         }
     }
 
@@ -1111,6 +1134,33 @@
         return ids;
     }
 
+    /**
+     * Builds a list of {@link Connection} and {@link Conference} IDs based on the list of
+     * {@link IConferenceable}s passed in.
+     *
+     * @param conferenceables The {@link IConferenceable} connections and conferences.
+     * @return List of string conference and call Ids.
+     */
+    private List<String> createIdList(List<IConferenceable> conferenceables) {
+        List<String> ids = new ArrayList<>();
+        for (IConferenceable c : conferenceables) {
+            // Only allow Connection and Conference conferenceables.
+            if (c instanceof Connection) {
+                Connection connection = (Connection) c;
+                if (mIdByConnection.containsKey(connection)) {
+                    ids.add(mIdByConnection.get(connection));
+                }
+            } else if (c instanceof Conference) {
+                Conference conference = (Conference) c;
+                if (mIdByConference.containsKey(conference)) {
+                    ids.add(mIdByConference.get(conference));
+                }
+            }
+        }
+        Collections.sort(ids);
+        return ids;
+    }
+
     private Conference getNullConference() {
         if (sNullConference == null) {
             sNullConference = new Conference(null) {};
diff --git a/telecomm/java/android/telecom/IConferenceable.java b/telecomm/java/android/telecom/IConferenceable.java
new file mode 100644
index 0000000..095d7cb
--- /dev/null
+++ b/telecomm/java/android/telecom/IConferenceable.java
@@ -0,0 +1,31 @@
+/*
+ * Copyright (C) 2014 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.telecom;
+
+import android.annotation.SystemApi;
+
+/**
+ * Interface used to identify entities with which another entity can participate in a conference
+ * call with.  The {@link ConnectionService} implementation will only recognize
+ * {@link IConferenceable}s which are {@link Connection}s or {@link Conference}s.
+ *
+ * @hide
+ */
+@SystemApi
+public interface IConferenceable {
+
+}
diff --git a/telecomm/java/android/telecom/PhoneCapabilities.java b/telecomm/java/android/telecom/PhoneCapabilities.java
index feb7a95..c21a6d1 100644
--- a/telecomm/java/android/telecom/PhoneCapabilities.java
+++ b/telecomm/java/android/telecom/PhoneCapabilities.java
@@ -101,6 +101,16 @@
      */
     public static final int DISCONNECT_FROM_CONFERENCE = 0x00002000;
 
+    /**
+     * Whether the call is a generic conference, where we do not know the precise state of
+     * participants in the conference (eg. on CDMA).
+     *
+     * TODO: Move to CallProperties.
+     *
+     * @hide
+     */
+    public static final int GENERIC_CONFERENCE = 0x00004000;
+
     public static final int ALL = HOLD | SUPPORT_HOLD | MERGE_CONFERENCE | SWAP_CONFERENCE
             | RESPOND_VIA_TEXT | MUTE | MANAGE_CONFERENCE | SEPARATE_FROM_CONFERENCE
             | DISCONNECT_FROM_CONFERENCE;
@@ -163,6 +173,10 @@
         if (can(capabilities, VoWIFI)) {
             builder.append(" VoWIFI");
         }
+        if (can(capabilities, GENERIC_CONFERENCE)) {
+            builder.append(" GENERIC_CONFERENCE");
+        }
+
         builder.append("]");
         return builder.toString();
     }
diff --git a/telephony/java/android/telephony/DisconnectCause.java b/telephony/java/android/telephony/DisconnectCause.java
index 1891976..674777e 100644
--- a/telephony/java/android/telephony/DisconnectCause.java
+++ b/telephony/java/android/telephony/DisconnectCause.java
@@ -165,6 +165,22 @@
      */
     public static final int IMS_MERGED_SUCCESSFULLY = 45;
 
+    /**
+     * Stk Call Control modified DIAL request to USSD request.
+     * {@hide}
+     */
+    public static final int DIAL_MODIFIED_TO_USSD          = 46;
+    /**
+     * Stk Call Control modified DIAL request to SS request.
+     * {@hide}
+     */
+    public static final int DIAL_MODIFIED_TO_SS            = 47;
+    /**
+     * Stk Call Control modified DIAL request to DIAL with modified data.
+     * {@hide}
+     */
+    public static final int DIAL_MODIFIED_TO_DIAL          = 48;
+
     //*********************************************************************************************
     // When adding a disconnect type:
     // 1) Please assign the new type the next id value below.
@@ -173,14 +189,14 @@
     // 4) Update toString() with the newly added disconnect type.
     // 5) Update android.telecom.DisconnectCauseUtil with any mappings to a telecom.DisconnectCause.
     //
-    // NextId: 46
+    // NextId: 49
     //*********************************************************************************************
 
     /** Smallest valid value for call disconnect codes. */
     public static final int MINIMUM_VALID_VALUE = NOT_DISCONNECTED;
 
     /** Largest valid value for call disconnect codes. */
-    public static final int MAXIMUM_VALID_VALUE = IMS_MERGED_SUCCESSFULLY;
+    public static final int MAXIMUM_VALID_VALUE = DIAL_MODIFIED_TO_DIAL;
 
     /** Private constructor to avoid class instantiation. */
     private DisconnectCause() {
@@ -272,6 +288,12 @@
             return "CDMA_CALL_LOST";
         case EXITED_ECM:
             return "EXITED_ECM";
+        case DIAL_MODIFIED_TO_USSD:
+            return "DIAL_MODIFIED_TO_USSD";
+        case DIAL_MODIFIED_TO_SS:
+            return "DIAL_MODIFIED_TO_SS";
+        case DIAL_MODIFIED_TO_DIAL:
+            return "DIAL_MODIFIED_TO_DIAL";
         case ERROR_UNSPECIFIED:
             return "ERROR_UNSPECIFIED";
         case OUTGOING_FAILURE:
diff --git a/telephony/java/com/android/internal/telephony/RILConstants.java b/telephony/java/com/android/internal/telephony/RILConstants.java
index b5e82e3..082e8bb 100644
--- a/telephony/java/com/android/internal/telephony/RILConstants.java
+++ b/telephony/java/com/android/internal/telephony/RILConstants.java
@@ -24,6 +24,8 @@
  * Also they should all probably be static final.
  */
 
+import android.os.SystemProperties;
+
 /**
  * {@hide}
  */
@@ -57,7 +59,17 @@
                                                  retries needed */
     int MISSING_RESOURCE = 16;                /* no logical channel available */
     int NO_SUCH_ELEMENT = 17;                 /* application not found on SIM */
+    int DIAL_MODIFIED_TO_USSD = 18;           /* DIAL request modified to USSD */
+    int DIAL_MODIFIED_TO_SS = 19;             /* DIAL request modified to SS */
+    int DIAL_MODIFIED_TO_DIAL = 20;           /* DIAL request modified to DIAL with different data*/
+    int USSD_MODIFIED_TO_DIAL = 21;           /* USSD request modified to DIAL */
+    int USSD_MODIFIED_TO_SS = 22;             /* USSD request modified to SS */
+    int USSD_MODIFIED_TO_USSD = 23;           /* USSD request modified to different USSD request */
+    int SS_MODIFIED_TO_DIAL = 24;             /* SS request modified to DIAL */
+    int SS_MODIFIED_TO_USSD = 25;             /* SS request modified to USSD */
     int SUBSCRIPTION_NOT_SUPPORTED = 26;      /* Subscription not supported */
+    int SS_MODIFIED_TO_SS = 27;               /* SS request modified to different SS request */
+
 
     /* NETWORK_MODE_* See ril.h RIL_REQUEST_SET_PREFERRED_NETWORK_TYPE */
     int NETWORK_MODE_WCDMA_PREF     = 0; /* GSM/WCDMA (WCDMA preferred) */
@@ -76,7 +88,8 @@
     int NETWORK_MODE_LTE_CDMA_EVDO_GSM_WCDMA = 10; /* LTE, CDMA, EvDo, GSM/WCDMA */
     int NETWORK_MODE_LTE_ONLY       = 11; /* LTE Only mode. */
     int NETWORK_MODE_LTE_WCDMA      = 12; /* LTE/WCDMA */
-    int PREFERRED_NETWORK_MODE      = NETWORK_MODE_WCDMA_PREF;
+    int PREFERRED_NETWORK_MODE      = SystemProperties.getInt("ro.telephony.default_network",
+            NETWORK_MODE_WCDMA_PREF);
 
     int CDMA_CELL_BROADCAST_SMS_DISABLED = 1;
     int CDMA_CELL_BROADCAST_SMS_ENABLED  = 0;
@@ -339,4 +352,6 @@
     int RIL_UNSOL_HARDWARE_CONFIG_CHANGED = 1040;
     int RIL_UNSOL_DC_RT_INFO_CHANGED = 1041;
     int RIL_UNSOL_RADIO_CAPABILITY = 1042;
+    int RIL_UNSOL_ON_SS = 1043;
+    int RIL_UNSOL_STK_CC_ALPHA_NOTIFY = 1044;
 }
diff --git a/wifi/java/android/net/wifi/WifiManager.java b/wifi/java/android/net/wifi/WifiManager.java
index 1393bce..6ddebde 100644
--- a/wifi/java/android/net/wifi/WifiManager.java
+++ b/wifi/java/android/net/wifi/WifiManager.java
@@ -1968,7 +1968,7 @@
     /**
      * Start Wi-fi Protected Setup
      *
-     * @param config WPS configuration
+     * @param config WPS configuration (does not support {@link WpsInfo#LABEL})
      * @param listener for callbacks on success or failure. Can be null.
      * @throws IllegalStateException if the WifiManager instance needs to be
      * initialized again